From b9dc71edb1734650b3eb8665e83931b15bfaeabd Mon Sep 17 00:00:00 2001 From: Jecelyn Yeen <5917927+jecfish@users.noreply.github.com> Date: Tue, 11 Apr 2023 10:49:23 +0200 Subject: [PATCH 001/982] Update What's New in DevTools video (#5967) --- site/en/blog/new-in-devtools-110/index.md | 2 +- site/en/blog/new-in-devtools-111/index.md | 3 +-- site/en/blog/new-in-devtools-112/index.md | 3 +-- site/es/blog/new-in-devtools-110/index.md | 1 + site/es/blog/new-in-devtools-111/index.md | 1 + site/es/blog/new-in-devtools-112/index.md | 1 + site/ja/blog/new-in-devtools-110/index.md | 1 + site/ja/blog/new-in-devtools-111/index.md | 1 + site/ja/blog/new-in-devtools-112/index.md | 1 + site/ko/blog/new-in-devtools-110/index.md | 1 + site/ko/blog/new-in-devtools-111/index.md | 1 + site/pt/blog/new-in-devtools-110/index.md | 1 + site/pt/blog/new-in-devtools-111/index.md | 1 + site/pt/blog/new-in-devtools-112/index.md | 1 + site/ru/blog/new-in-devtools-110/index.md | 1 + site/ru/blog/new-in-devtools-111/index.md | 1 + site/ru/blog/new-in-devtools-112/index.md | 1 + site/zh/blog/new-in-devtools-110/index.md | 1 + site/zh/blog/new-in-devtools-111/index.md | 1 + site/zh/blog/new-in-devtools-112/index.md | 1 + 20 files changed, 20 insertions(+), 5 deletions(-) diff --git a/site/en/blog/new-in-devtools-110/index.md b/site/en/blog/new-in-devtools-110/index.md index 22334523a..46b624ae4 100644 --- a/site/en/blog/new-in-devtools-110/index.md +++ b/site/en/blog/new-in-devtools-110/index.md @@ -15,7 +15,7 @@ tags: {% Partial 'devtools/banner.md' %} -*No video for this release.* +{% YouTube id='CrSmjooOEiE' %} diff --git a/site/en/blog/new-in-devtools-111/index.md b/site/en/blog/new-in-devtools-111/index.md index e97e09afb..efab6c85d 100644 --- a/site/en/blog/new-in-devtools-111/index.md +++ b/site/en/blog/new-in-devtools-111/index.md @@ -14,8 +14,7 @@ tags: --- {% Partial 'devtools/banner.md' %} - -*No video for this release.* +{% YouTube id='CrSmjooOEiE' %} diff --git a/site/en/blog/new-in-devtools-112/index.md b/site/en/blog/new-in-devtools-112/index.md index 61a05b666..d7e46fb38 100644 --- a/site/en/blog/new-in-devtools-112/index.md +++ b/site/en/blog/new-in-devtools-112/index.md @@ -15,8 +15,7 @@ tags: --- {% Partial 'devtools/banner.md' %} - -*No 'What's new in DevTools' video for this release. Check out the latest DevTools Tips video to learn [how to identify and fix CSS issues with the Styles pane](https://youtu.be/iuZx0kHS0Xs).* +{% YouTube id='CrSmjooOEiE' %} diff --git a/site/es/blog/new-in-devtools-110/index.md b/site/es/blog/new-in-devtools-110/index.md index b9e10bfac..c6fd50660 100644 --- a/site/es/blog/new-in-devtools-110/index.md +++ b/site/es/blog/new-in-devtools-110/index.md @@ -17,6 +17,7 @@ draft: true *Gracias por la traducción [Miguel Ángel](https://midu.dev) y por la revisión [Carlos Caballero](https://carloscaballero.io).* {% Partial 'devtools/banner.md' %} +{% YouTube id='CrSmjooOEiE' %} + +{% Partial 'devtools/banner.md' %} + +*No 'What's new in DevTools' video for this release. Check out the latest DevTools Tips video: [What are source maps?](https://youtu.be/FIYkjjFYvoI).* + + + +## Override network response headers {: #network } + +You can now override response headers in the **Network** panel. Previously, you needed access to the web server to experiment with HTTP response headers. + +With response header overrides, you can locally prototype fixes for various headers, including but not limited to: + +- [Cross-Origin Resource Sharing (CORS) Headers](https://developer.mozilla.org/docs/Web/HTTP/CORS) +- [Permissions-Policy Headers](https://developer.mozilla.org/docs/Web/HTTP/Headers/Permissions-Policy) +- [Cross-Origin Isolation Headers](https://web.dev/coop-coep/) + +To override a header, navigate to **Network** > **Headers** > **Response Headers**, hover over a header's value, click {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/k3WKQOAItcJ2pliOyD47.svg", alt="Edit.", width="24", height="24" %} and edit it. + +{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/N0GUECvGcvFad0JFs72l.png", alt="CORS error fixed by a header override.", width="800", height="504" %} + +You can also add custom headers. + +{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/dRPqQCkvX4GT3KiFonaW.png", alt="Adding a custom header.", width="800", height="506" %} + +To edit all overrides in a single place, edit the `.headers` file in **Sources** > **Overrides**. There, you can also click **Add override rule** to override multiple requests using wildcards (`*`). + +{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/XSgXk86kVgdJTlEBplTc.png", alt="Editing all overrides.", width="800", height="431" %} + +{# https://chromium.googlesource.com/devtools/devtools-frontend/+/102f7c4f25ffcdd66d800d8c4bf8dbcce7e29e79 #} + +Chromium issue: [1288023](https://crbug.com/1288023). + +## Nuxt, Vite, and Rollup debugging improvements {: #debug } + +To help you pinpoint issues quicker during debugging, the enhanced stack trace now hides frames that come from sources generated by [Nuxt 3.3](https://nuxt.com/blog/v3-3) or later. DevTools skips such frames: + +- In **Console** traces, under the **Show N more frames** link. +- In [**Sources** > **Call Stack**](/docs/devtools/javascript/reference/#show-ignore-listed-frames), under {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/hmp8j3HiLMCcqPArD9yt.svg", alt="Checkbox.", width="22", height="22" %} **Show ignore-listed frames**. + +{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/JbfA2QCj3YiZVgiycZ0q.png", alt="The stack trace before and after enabling third-party ignore-listing.", width="800", height="482" %} + +{% Aside %} +You can manually [disable ignore-listing](/docs/devtools/settings/ignore-list/#skip-third-party) in {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/9gzXiTYY0nZzBxGI6KrV.svg", alt="Settings.", width="24", height="24" %} [**Settings** > **Ignore List**](/docs/devtools/settings/ignore-list/). +{% endAside %} + +To bring you these improvements, the DevTools, Nuxt, Vite, and Rollup teams collaborated to adopt the [`x_google_ignoreList` source map extension](/articles/ignore-list): + +- [Nuxt 3.3 Release](https://nuxt.com/blog/v3-3#better-logging-in-browser-devtools) +- [Vite Server Options](https://vitejs.dev/config/server-options.html#server-sourcemapignorelist) +- [Rollup Configuration Options](https://rollupjs.org/configuration-options/#output-sourcemapignorelist) + +The DevTools team would like to express gratitude to the Nuxt, Vite, and Rollup teams for making this possible. We appreciate your efforts and collaboration, which were essential to the success of this implementation. Thank you again for your contributions! + +## Assertions in Recorder {: #recorder } + +The **Recorder** panel now lets you add assertions right during recording, with all the runtime data available to you. + +To add an assertion, start a new recording, interact with your page, and click **Add assertion**. The **Recorder** inserts a step with the [`waitForElement` type](/docs/devtools/recorder/reference/#step-properties) that you can customize on the fly. Watch the video to see assertions in action on the [coffee cart demo](https://coffee-cart.app/). + +{% Video src="video/NJdAV9UgKuN8AhoaPBquL7giZQo1/oSTbA1gmxW9EIzZjma1W.mp4", controls="true", muted="true", class="screenshot" %} + +This video shows you how to assert: + +- HTML attributes, for example, an element's `class` +- JavaScript properties, for example, `.innerText` + +Both are specified in JSON. You can also configure steps to assert, for example, conditional statements in JavaScript, number of node's children (`count`), element visibility, and more. For more information, see [Configure steps](/docs/devtools/recorder/reference/#configure-steps). + +Additionally, the **Recorder** now remembers your preferred script format in the [side-by-side code view](/docs/devtools/recorder/reference/#inspect-code) and right-click step menu. + +Chromium issue: [1423624](https://crbug.com/1423624). + +{# https://chrome-internal.googlesource.com/devtools/devtools-internal/+/67b9e72b50d50c5e959ccfebe202b486a3417736 #} + +## CSS improvements in Elements > Styles {: #css } + +### Invalid CSS properties and values {: #invalid-css } + +To help you diagnose [CSS issues](/docs/devtools/css/issues/) faster, the **Styles** pane now crosses out: + +- An entire CSS declaration (property *and* value) when the [CSS property is invalid](/docs/devtools/css/issues/#invalid). +- Just the value when the CSS property is valid but the value is invalid. + +{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/25gZlN9PjK8HosfW1ZGm.png", alt="Invalid property name and invalid property value.", width="800", height="582" %} + +The DevTools team would like to express gratitude to [Yisi](https://chromium.googlesource.com/devtools/devtools-frontend/+/b1e2495635a072b0eb814b0f683bb93b8f8d92e3) for landing this improvement. + +{# https://chromium.googlesource.com/devtools/devtools-frontend/+/b1e2495635a072b0eb814b0f683bb93b8f8d92e3 #} + +### Links to key frames in the animation shorthand property {: #animation-key-frames } + +The [`animation` shorthand CSS property](https://developer.mozilla.org/docs/Web/CSS/animation) now contains links to the corresponding [`@keyframes` at-rules](https://developer.mozilla.org/docs/Web/CSS/@keyframes), so you can navigate the **Styles** pane faster. + +{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/v4GiyX0dHEJiM8Qa4uRA.png", alt="Links to key frames in the animation shorthand property.", width="800", height="486" %} + +{# https://chromium.googlesource.com/devtools/devtools-frontend/+/a9047f3925842c12ab3f6c5ad55358aee4398649 #} +{# https://chromium.googlesource.com/devtools/devtools-frontend/+/aa93c8e723e832575437069f732a039b1331b56c #} + +Chromium issue: [1420656](https://crbug.com/1420656). + +## New Console setting: Autocomplete on Enter {: #console } + +Starting with the previous version (112), you can configure the DevTools **Console** to apply an autocomplete suggestion when you press `Enter`. + +By default, to accept an autocomplete suggestion, you can press `Tab` or `Arrow right`. To also autocomplete with `Enter`, enable {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/9gzXiTYY0nZzBxGI6KrV.svg", alt="Settings.", width="24", height="24" %} **Settings** > **Console** > {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/hmp8j3HiLMCcqPArD9yt.svg", alt="Checkbox.", width="22", height="22" %} **Accept autocomplete suggestion on Enter**. + +{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/cSd1G0KukIMfbeQZjbnk.png", alt="The corresponding checkbox in Settings.", width="800", height="621" %} + +Additionally, the text of [another setting](/docs/devtools/settings/preferences/#console) is now more user-friendly: {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/hmp8j3HiLMCcqPArD9yt.svg", alt="Checkbox.", width="22", height="22" %} **Treat code evaluation as user action**. + +{# https://chromium.googlesource.com/devtools/devtools-frontend/+/fa57e2c4429e60c47361383e3cf80b2c9022fab0 #} +{# https://chromium.googlesource.com/devtools/devtools-frontend/+/b35381df8e54d028accbd304f2edaa696a2c8218 #} + +Chromium issue: [1276960](https://crbug.com/1276960). + +## Command Menu emphasizes authored files {: #command-menu } + +The quick open dialog in the [**Command Menu**](/docs/devtools/command-menu/#open-files) now grays out the [ignore-listed](/docs/devtools/settings/ignore-list/) third-party files to put more emphasis on the files you authored. + +{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/3J6ZeS9oaG7yFXMDmMgR.png", alt="An ignore-listed script in the quick open dialog before and after the change.", width="800", height="368" %} + +{# https://chromium.googlesource.com/devtools/devtools-frontend/+/193652e716a06bc74dfab994a5888362bb0b1ee7 #} +{# https://chromium.googlesource.com/devtools/devtools-frontend/+/b53684f84a066382502e291a769f3732256ed180 #} + +Chromium issue: [1424345](https://crbug.com/1424345). + +## JavaScript Profiler deprecation: Stage two {: #js-profiler } + +As early as [Chrome 58](/blog/devtools-javascript-cpu-profile-migration-2/), the DevTools team planned to eventually deprecate the **JavaScript Profiler** and have Node.js and Deno developers use the **Performance** panel for profiling JavaScript CPU performance. + +DevTools version 113 starts *phase two* of the [four-phase **JavaScript Profiler** deprecation](https://github.com/ChromeDevTools/rfcs/discussions/2#discussioncomment-5189668). During this phase, you can still open the panel but its UI is no longer available. + +To profile CPU performance, click **Go to Performance panel**. + +{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/1HHtEbstCweUkTAK6eYH.png", alt="JavaScript Profiler deprecation.", width="800", height="393" %} + +{# https://chromium.googlesource.com/devtools/devtools-frontend/+/4f15b9fdb6b7f1932749813eb6e6f51fdef64e00 #} +{# https://chromium.googlesource.com/devtools/devtools-frontend/+/351e005d9e41f8310552cc84ab0ce9f9ab6e0b7d #} +{# https://chromium.googlesource.com/devtools/devtools-frontend/+/1dca54ab8016d2377885bd6146c89248ef81e24c #} + +Chromium issue: [1354548](https://crbug.com/1354548). + + +## Miscellaneous highlights {: #misc } + +These are some noteworthy fixes in this release: + +- Fixed a bug that caused pretty-printing in the **Sources** panel to handle variable names with Unicode characters incorrectly ([1425055](https://crbug.com/1425055)). +- The **Issues** tab added a new message for Autofill issues regarding non-standard HTML values ([1399414](https://crbug.com/1399414)). + + + +{% Partial 'devtools/reach-out.md' %} +{% Partial 'devtools/whats-new.md' %} From 09310cda6ffc4eb756409d624fb2d589fddb360d Mon Sep 17 00:00:00 2001 From: Sven May <39521568+Svenmay@users.noreply.github.com> Date: Tue, 11 Apr 2023 18:32:16 +0200 Subject: [PATCH 014/982] Adding Q&A for FLEDGE (#5664) * Adding Q&A for FLEDGE Adding specific question & answer for "How can a user block an ad when it's shown as a result of a FLEDGE auction?" * Update index.md * ad block move --------- Co-authored-by: Alexandra White --- site/en/docs/privacy-sandbox/faq/index.md | 6 ++++-- site/en/docs/privacy-sandbox/fledge/index.md | 12 +++++++++++- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/site/en/docs/privacy-sandbox/faq/index.md b/site/en/docs/privacy-sandbox/faq/index.md index b8db0c2b2..3f74c44bb 100644 --- a/site/en/docs/privacy-sandbox/faq/index.md +++ b/site/en/docs/privacy-sandbox/faq/index.md @@ -9,9 +9,11 @@ authors: - samdutton --- -If you have questions about any parts of the Privacy Sandbox, please see the relevant sections of the documentation. +If you have questions about any parts of the Privacy Sandbox, refer to the +relevant sections of the documentation. -Your questions are welcome. If you have a Privacy Sandbox question that is not answered in the documentation, you can: +Your questions are welcome. If you have a Privacy Sandbox question that is not +answered in the documentation, you can: - File an issue on the explainer repo for the proposal you're asking about. Links to these are provided below, and are available from the diff --git a/site/en/docs/privacy-sandbox/fledge/index.md b/site/en/docs/privacy-sandbox/fledge/index.md index 3591a3e4b..6e1aac724 100644 --- a/site/en/docs/privacy-sandbox/fledge/index.md +++ b/site/en/docs/privacy-sandbox/fledge/index.md @@ -194,10 +194,20 @@ and membership is removed when users clear their site data. Learn how you can [block access to the FLEDGE API](/docs/privacy-sandbox/fledge-api/opt-out), either as a site owner or as an individual user. -{: #glossary} +### Can users block an ad shown as the result of a FLEDGE auction? {: #ad-block } + +Users can [opt out of the Privacy Sandbox API](/docs/privacy-sandbox/fledge-api/opt-out/#opt-out-user). +To opt out of a specific ad or ad selection technique, the appropriate party to +provide those controls is the ad tech serving the ad. + +Developers can use multiple approaches to control which ads are eligible for +bidding and serving, as well as recording a user's ad preferences. One +technique is to call `leaveAdInterestGroup()` when a user asks to block a specific ad, for the winning interest group that provided the ad. This removes the user's browser from membership of the interest group and makes the group ineligible to bid in the future. ## Key concepts +{: #glossary} + Looking for more information on FLEDGE terminology? Refer to the [Privacy Sandbox glossary](/docs/privacy-sandbox/glossary/). {: #interest-group-detail} From a34729945b368d6f15bc539be7157ba54fc977da Mon Sep 17 00:00:00 2001 From: Samuel H Date: Tue, 11 Apr 2023 19:41:33 +0100 Subject: [PATCH 015/982] Update index.md (#5964) Fix typo in example code --- .../index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/en/blog/sqlite-wasm-in-the-browser-backed-by-the-origin-private-file-system/index.md b/site/en/blog/sqlite-wasm-in-the-browser-backed-by-the-origin-private-file-system/index.md index f91328d20..33600142b 100644 --- a/site/en/blog/sqlite-wasm-in-the-browser-backed-by-the-origin-private-file-system/index.md +++ b/site/en/blog/sqlite-wasm-in-the-browser-backed-by-the-origin-private-file-system/index.md @@ -186,7 +186,7 @@ const start = function (sqlite3) { let i; for (i = 20; i <= 25; ++i) { db.exec({ - sql: INSERT INTO t(a,b) VALUES (?,?)', + sql: 'INSERT INTO t(a,b) VALUES (?,?)', bind: [i, i * 2], }); } From 7fc92c8f2fe31efbabee172fa466fc9093d64166 Mon Sep 17 00:00:00 2001 From: Jecelyn Yeen <5917927+jecfish@users.noreply.github.com> Date: Tue, 11 Apr 2023 20:42:08 +0200 Subject: [PATCH 016/982] Update date (#5976) --- site/en/blog/new-in-devtools-113/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/en/blog/new-in-devtools-113/index.md b/site/en/blog/new-in-devtools-113/index.md index 5a2085d17..d376d42fc 100644 --- a/site/en/blog/new-in-devtools-113/index.md +++ b/site/en/blog/new-in-devtools-113/index.md @@ -4,7 +4,7 @@ title: "What's New in DevTools (Chrome 113)" authors: - sofiayem - jecelynyeen -date: 2023-04-28 +date: 2023-04-11 description: "" hero: 'image/NJdAV9UgKuN8AhoaPBquL7giZQo1/deVc0yGGerSjHtSI3Drw.jpg' alt: '' From ea8f06c0f06536ba9bbfa9affb66000cb7ebfd0f Mon Sep 17 00:00:00 2001 From: Nikolay Vitkov <34244704+Lightning00Blade@users.noreply.github.com> Date: Wed, 12 Apr 2023 12:01:06 +0200 Subject: [PATCH 017/982] Update broken Puppeteer links (#5691) * Update broken Puppeteer links * Update toc.yml * Update index.md --------- Co-authored-by: Aaron Forinton <89849359+AaronForinton@users.noreply.github.com> --- site/_data/docs/puppeteer/toc.yml | 4 ++-- site/en/articles/idle-detection/index.md | 2 +- site/en/blog/cvd/index.md | 2 +- site/en/docs/puppeteer/faq/index.md | 12 ++++++------ site/en/docs/puppeteer/get-started/index.md | 14 +++++++------- site/es/articles/idle-detection/index.md | 2 +- site/pt/articles/idle-detection/index.md | 2 +- 7 files changed, 19 insertions(+), 19 deletions(-) diff --git a/site/_data/docs/puppeteer/toc.yml b/site/_data/docs/puppeteer/toc.yml index 5292dc4f1..1d08efa9e 100644 --- a/site/_data/docs/puppeteer/toc.yml +++ b/site/_data/docs/puppeteer/toc.yml @@ -18,10 +18,10 @@ title: i18n.docs.puppeteer.project_npm - url: https://github.com/puppeteer/puppeteer title: i18n.docs.puppeteer.project_github - - url: https://github.com/puppeteer/puppeteer/issues/new + - url: https://github.com/puppeteer/puppeteer/issues/new/choose title: i18n.docs.puppeteer.project_issue - url: https://github.com/puppeteer/puppeteer/releases title: i18n.docs.puppeteer.project_releases - - url: https://github.com/puppeteer/puppeteer/blob/main/CONTRIBUTING.md + - url: https://pptr.dev/contributing title: i18n.docs.puppeteer.project_contribute - url: /docs/puppeteer/faq diff --git a/site/en/articles/idle-detection/index.md b/site/en/articles/idle-detection/index.md index 7bfa245dd..ed7dd3e14 100644 --- a/site/en/articles/idle-detection/index.md +++ b/site/en/articles/idle-detection/index.md @@ -171,7 +171,7 @@ You can see the various options in the video below. ### Puppeteer support As of Puppeteer version 5.3.1, you can -[emulate the various idle states](https://github.com/puppeteer/puppeteer/blob/main/docs/api.md#pageemulateidlestateoverrides) +[emulate the various idle states](https://pptr.dev/api/puppeteer.page.emulateidlestate/) to programmatically test how your web app's behavior changes. ### Demo diff --git a/site/en/blog/cvd/index.md b/site/en/blog/cvd/index.md index 8f84f5803..f007347df 100644 --- a/site/en/blog/cvd/index.md +++ b/site/en/blog/cvd/index.md @@ -49,7 +49,7 @@ We’ve recently added a new tool to this list, and it’s a bit different from {% YouTube id='mK_XmFb8E_w' %} -In Puppeteer, [the new `page.emulateVisionDeficiency(type)` API](https://github.com/puppeteer/puppeteer/blob/v5.4.1/docs/api.md#pageemulatevisiondeficiencytype) lets you programmatically enable these simulations. +In Puppeteer, [the new `page.emulateVisionDeficiency(type)` API](https://pptr.dev/api/puppeteer.page.emulatevisiondeficiency/) lets you programmatically enable these simulations. ## Color vision deficiencies {: #cvd } diff --git a/site/en/docs/puppeteer/faq/index.md b/site/en/docs/puppeteer/faq/index.md index d3f6aee2e..7d72b8145 100644 --- a/site/en/docs/puppeteer/faq/index.md +++ b/site/en/docs/puppeteer/faq/index.md @@ -10,13 +10,13 @@ updated: 2022-06-16 ## Q: Who maintains Puppeteer? The Chrome DevTools team maintains the library, but we'd love your help and expertise on the project! -See [Contributing](https://github.com/puppeteer/puppeteer/blob/main/CONTRIBUTING.md). +See [Contributing](https://pptr.dev/contributing). ## Q: What is the status of cross-browser support? Official Firefox support is currently experimental. The ongoing collaboration with Mozilla aims to support common end-to-end testing use cases, for which developers expect cross-browser coverage. The Puppeteer team needs input from users to stabilize Firefox support and to bring missing APIs to our attention. -From Puppeteer v2.1.0 onwards you can specify [`puppeteer.launch({product: 'firefox'})`](https://github.com/puppeteer/puppeteer/blob/main/docs/api.md#puppeteerlaunchoptions) to run your Puppeteer scripts in Firefox Nightly, without any additional custom patches. While [an older experiment](https://www.npmjs.com/package/puppeteer-firefox) required a patched version of Firefox, [the current approach](https://wiki.mozilla.org/Remote) works with “stock” Firefox. +From Puppeteer v2.1.0 onwards you can specify [`puppeteer.launch({product: 'firefox'})`](https://pptr.dev/api/puppeteer.puppeteerlaunchoptions) to run your Puppeteer scripts in Firefox Nightly, without any additional custom patches. While [an older experiment](https://www.npmjs.com/package/puppeteer-firefox) required a patched version of Firefox, [the current approach](https://wiki.mozilla.org/Remote) works with “stock” Firefox. We will continue to collaborate with other browser vendors to bring Puppeteer support to browsers such as Safari. This effort includes exploration of a standard for executing cross-browser commands (instead of relying on the non-standard DevTools Protocol used by Chrome). @@ -74,12 +74,12 @@ npm install puppeteer-core@chrome-71 Find the version using one of the following ways: -- Look for the `chromium` entry in [revisions.ts](https://github.com/puppeteer/puppeteer/blob/main/src/revisions.ts). To find the corresponding Chromium commit and version number, search for the revision prefixed by an `r` in [OmahaProxy](https://omahaproxy.appspot.com/)'s "Find Releases" section. +- Look for the `chromium` entry in [revisions.ts](https://github.com/puppeteer/puppeteer/blob/main/packages/puppeteer-core/src/revisions.ts). To find the corresponding Chromium commit and version number, search for the revision prefixed by an `r` in [OmahaProxy](https://omahaproxy.appspot.com/)'s "Find Releases" section. - Look for the `versionsPerRelease` map in [versions.js](https://github.com/puppeteer/puppeteer/blob/main/versions.js) which contains mapping between Chromium and Puppeteer versions. Note: The file contains only Puppeteer versions where Chromium is updated. Not all Puppeteer versions are listed. ## Q: Which Firefox version does Puppeteer use? -Since Firefox support is experimental, Puppeteer downloads the latest [Firefox Nightly](https://wiki.mozilla.org/Nightly) when the `PUPPETEER_PRODUCT` environment variable is set to `firefox`. That's also why the value of `firefox` in [revisions.ts](https://github.com/puppeteer/puppeteer/blob/main/src/revisions.ts) is `latest` -- Puppeteer isn't tied to a particular Firefox version. +Since Firefox support is experimental, Puppeteer downloads the latest [Firefox Nightly](https://wiki.mozilla.org/Nightly) when the `PUPPETEER_PRODUCT` environment variable is set to `firefox`. That's also why the value of `firefox` in [revisions.ts](https://github.com/puppeteer/puppeteer/blob/main/packages/puppeteer-core/src/revisions.ts) is `latest` -- Puppeteer isn't tied to a particular Firefox version. To fetch Firefox Nightly as part of Puppeteer installation: @@ -119,12 +119,12 @@ await page.evaluate(() => { You may find that Puppeteer does not behave as expected when controlling pages that incorporate audio and video. (For example, [video playback/screenshots is likely to fail](https://github.com/puppeteer/puppeteer/issues/291).) There are two reasons for this: -- Puppeteer is bundled with Chromium — not Chrome — and so by default, it inherits all of [Chromium's media-related limitations](https://www.chromium.org/audio-video). This means that Puppeteer does not support licensed formats such as AAC or H.264. (However, it is possible to force Puppeteer to use a separately-installed version Chrome instead of Chromium via the [`executablePath` option to `puppeteer.launch`](https://github.com/puppeteer/puppeteer/blob/main/docs/api.md#puppeteerlaunchoptions). You should only use this configuration if you need an official release of Chrome that supports these media formats.) +- Puppeteer is bundled with Chromium — not Chrome — and so by default, it inherits all of [Chromium's media-related limitations](https://www.chromium.org/audio-video). This means that Puppeteer does not support licensed formats such as AAC or H.264. (However, it is possible to force Puppeteer to use a separately-installed version Chrome instead of Chromium via the [`executablePath` option to `puppeteer.launch`](https://pptr.dev/api/puppeteer.puppeteerlaunchoptions). You should only use this configuration if you need an official release of Chrome that supports these media formats.) - Since Puppeteer (in all configurations) controls a desktop version of Chromium/Chrome, features that are only supported by the mobile version of Chrome are not supported. This means that Puppeteer [does not support HTTP Live Streaming (HLS)](https://caniuse.com/#feat=http-live-streaming). ## Q: I am having trouble installing / running Puppeteer in my test environment. Where should I look for help? -We have a [troubleshooting](https://github.com/puppeteer/puppeteer/blob/main/docs/troubleshooting.md) guide for various operating systems that lists the required dependencies. +We have a [troubleshooting](https://pptr.dev/troubleshooting) guide for various operating systems that lists the required dependencies. ## Q: Chromium gets downloaded on every `npm ci` run. How can I cache the download? diff --git a/site/en/docs/puppeteer/get-started/index.md b/site/en/docs/puppeteer/get-started/index.md index 8ee64b163..30ab3a06a 100644 --- a/site/en/docs/puppeteer/get-started/index.md +++ b/site/en/docs/puppeteer/get-started/index.md @@ -32,7 +32,7 @@ npm i puppeteer-core `puppeteer-core` is intended to be a lightweight version of Puppeteer for launching an existing browser installation or for connecting to a remote one. Be sure that the version of puppeteer-core you install is compatible with the browser you intend to connect to. -See [puppeteer vs puppeteer-core](https://github.com/puppeteer/puppeteer/blob/v14.3.0/docs/api.md#puppeteer-vs-puppeteer-core). +See [puppeteer vs puppeteer-core](https://pptr.dev/#puppeteer-core). ## Usage @@ -42,7 +42,7 @@ Puppeteer follows the latest [maintenance LTS](https://github.com/nodejs/Release Prior to v1.18.1, Puppeteer required at least Node v6.4.0. Versions from v1.18.1 to v2.1.0 rely on Node 8.9.0+. Starting from v3.0.0 Puppeteer starts to rely on Node 10.18.1+. All examples below use async/await which is only supported in Node v7.6.0 or greater. {% endAside %} -Puppeteer will be familiar to people using other browser testing frameworks. You create an instance of `Browser`, open pages, and then manipulate them with [Puppeteer's API](https://github.com/puppeteer/puppeteer/blob/v14.3.0/docs/api.md). +Puppeteer will be familiar to people using other browser testing frameworks. You create an instance of `Browser`, open pages, and then manipulate them with [Puppeteer's API](https://pptr.dev/api). **Example:** navigating to `https://example.com` and saving a screenshot as example.png: @@ -61,7 +61,7 @@ const puppeteer = require('puppeteer'); })(); ``` -Puppeteer sets an initial page size to 800×600px, which defines the screenshot size. The page size can be customized with [Page.setViewport()](https://github.com/puppeteer/puppeteer/blob/v14.3.0/docs/api.md#pagesetviewportviewport). +Puppeteer sets an initial page size to 800×600px, which defines the screenshot size. The page size can be customized with [Page.setViewport()](https://pptr.dev/api/puppeteer.page.setviewport/). **Example:** create a PDF. @@ -88,7 +88,7 @@ Execute script on the command line: node hn.js ``` -See [Page.pdf()](https://github.com/puppeteer/puppeteer/blob/v14.3.0/docs/api.md#pagepdfoptions) for more information about creating pdfs. +See [Page.pdf()](https://pptr.dev/api/puppeteer.pdfoptions) for more information about creating pdfs. **Example:** evaluate script in the context of the page @@ -123,13 +123,13 @@ Execute script on the command line: node get-dimensions.js ``` -See [Page.evaluate()](https://github.com/puppeteer/puppeteer/blob/v14.3.0/docs/api.md#pageevaluatepagefunction-args) for more information on evaluate and related methods such as `evaluateOnNewDocument` and `exposeFunction`. +See [Evaluate JavaScript](https://pptr.dev/guides/evaluate-javascript) for more information on evaluate and related methods such as `evaluateOnNewDocument` and `exposeFunction`. ## Default runtime settings ### Uses Headless mode -Puppeteer launches Chromium in [headless mode](/blog/headless-chrome/). To launch a full version of Chromium, set the [`headless`](https://github.com/puppeteer/puppeteer/blob/v14.3.0/docs/api.md#puppeteerlaunchoptions) option when launching a browser: +Puppeteer launches Chromium in [headless mode](/blog/headless-chrome/). To launch a full version of Chromium, set the [`headless`](https://pptr.dev/api/puppeteer.puppeteerlaunchoptions) option when launching a browser: ```shell const browser = await puppeteer.launch({ headless: false }); // default is true @@ -143,7 +143,7 @@ By default, Puppeteer downloads and uses a specific version of Chromium so its A const browser = await puppeteer.launch({ executablePath: '/path/to/Chrome' }); ``` -You can also use Puppeteer with Firefox Nightly (experimental support). See [`Puppeteer.launch()`](https://github.com/puppeteer/puppeteer/blob/v14.3.0/docs/api.md#puppeteerlaunchoptions) for more information. +You can also use Puppeteer with Firefox Nightly (experimental support). See [`Puppeteer.launch()`](https://pptr.dev/api/puppeteer.puppeteerlaunchoptions) for more information. See [this article](https://www.howtogeek.com/202825/what%E2%80%99s-the-difference-between-chromium-and-chrome/) for a description of the differences between Chromium and Chrome. [This article](https://chromium.googlesource.com/chromium/src/+/refs/heads/main/docs/chromium_browser_vs_google_chrome.md) describes some differences for Linux users. diff --git a/site/es/articles/idle-detection/index.md b/site/es/articles/idle-detection/index.md index 9fad1940a..8ed428b27 100644 --- a/site/es/articles/idle-detection/index.md +++ b/site/es/articles/idle-detection/index.md @@ -140,7 +140,7 @@ A partir de Chromium 94, puedes emular eventos inactivos en DevTools sin estar r ### Soporte de Puppeteer -A partir de la versión 5.3.1 de Puppeteer, puedes [emular los distintos estados inactivos](https://github.com/puppeteer/puppeteer/blob/main/docs/api.md#pageemulateidlestateoverrides) para probar mediante programación cómo cambia el comportamiento de tu aplicación web. +A partir de la versión 5.3.1 de Puppeteer, puedes [emular los distintos estados inactivos](https://pptr.dev/api/puppeteer.page.emulateidlestate/) para probar mediante programación cómo cambia el comportamiento de tu aplicación web. ### Demo diff --git a/site/pt/articles/idle-detection/index.md b/site/pt/articles/idle-detection/index.md index 94737b736..0fb574d5e 100644 --- a/site/pt/articles/idle-detection/index.md +++ b/site/pt/articles/idle-detection/index.md @@ -140,7 +140,7 @@ A partir do Chromium 94, você pode emular eventos ociosos no DevTools sem realm ### Suporte para Puppeteer -A partir da versão 5.3.1 do Puppeteer, você pode [emular os vários estados inativos](https://github.com/puppeteer/puppeteer/blob/main/docs/api.md#pageemulateidlestateoverrides) para testar programaticamente como o comportamento do seu aplicativo da web muda. +A partir da versão 5.3.1 do Puppeteer, você pode [emular os vários estados inativos](https://pptr.dev/api/puppeteer.page.emulateidlestate/) para testar programaticamente como o comportamento do seu aplicativo da web muda. ### Demo From 890215ba1983a83acdeed2041668840545c2c6a1 Mon Sep 17 00:00:00 2001 From: Sofia Emelianova <42939855+sofiayem@users.noreply.github.com> Date: Wed, 12 Apr 2023 12:41:57 +0100 Subject: [PATCH 018/982] fix link (#5984) --- site/en/blog/new-in-devtools-113/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/en/blog/new-in-devtools-113/index.md b/site/en/blog/new-in-devtools-113/index.md index d376d42fc..3c8725777 100644 --- a/site/en/blog/new-in-devtools-113/index.md +++ b/site/en/blog/new-in-devtools-113/index.md @@ -60,7 +60,7 @@ To help you pinpoint issues quicker during debugging, the enhanced stack trace n You can manually [disable ignore-listing](/docs/devtools/settings/ignore-list/#skip-third-party) in {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/9gzXiTYY0nZzBxGI6KrV.svg", alt="Settings.", width="24", height="24" %} [**Settings** > **Ignore List**](/docs/devtools/settings/ignore-list/). {% endAside %} -To bring you these improvements, the DevTools, Nuxt, Vite, and Rollup teams collaborated to adopt the [`x_google_ignoreList` source map extension](/articles/ignore-list): +To bring you these improvements, the DevTools, Nuxt, Vite, and Rollup teams collaborated to adopt the [`x_google_ignoreList` source map extension](/articles/x-google-ignore-list/): - [Nuxt 3.3 Release](https://nuxt.com/blog/v3-3#better-logging-in-browser-devtools) - [Vite Server Options](https://vitejs.dev/config/server-options.html#server-sourcemapignorelist) From 752cd1a35bccdf97efba6c45f78ca2dbc4e5dcf8 Mon Sep 17 00:00:00 2001 From: Rachel Andrew Date: Wed, 12 Apr 2023 13:22:29 +0100 Subject: [PATCH 019/982] Adding the reading-order post (#5895) * Adding the reading-order post * Apply suggestions from code review --- site/en/blog/reading-order/index.md | 158 ++++++++++++++++++++++++++++ 1 file changed, 158 insertions(+) create mode 100644 site/en/blog/reading-order/index.md diff --git a/site/en/blog/reading-order/index.md b/site/en/blog/reading-order/index.md new file mode 100644 index 000000000..2ac3e7e2d --- /dev/null +++ b/site/en/blog/reading-order/index.md @@ -0,0 +1,158 @@ +--- +title: Solving the CSS layout and source order disconnect +description: > + Your feedback is wanted on a proposed solution for the problem of layout methods arranging items in an order that is disconnected from the source of the document. +subhead: > + Your feedback is wanted on a proposed solution for the problem of layout methods arranging items in an order that is disconnected from the source of the document. +layout: 'layouts/blog-post.njk' +date: 2023-04-12 +thumbnail: 'image/kheDArv5csY6rvQUJDbWRscckLr1/ohpYeFraXHgCYHzmKKQ0.jpg' +alt: > + Books, some displayed out of order and alignment. +authors: + - rachelandrew +tags: + - accessibility + - css +--- + +The CSS Working Group is working on a solution to the situation where a layout method can arrange items in an order that is disconnected from the source, and therefore from the reading and focus order of the document. This article explains the problem and proposed solution, and we would love your feedback. + +## The problem + +The reading order of an HTML document follows the source order. This means that a screen reader will read the document as it is laid out in the source, and a person using the keyboard to tab around the document will also follow that source order. Usually this makes sense, and a sensible source order for the document is vital for reading mode presentations of content, screen readers, and any device with limited CSS. However, CSS, and flexbox and grid in particular, can create layouts where the layout defines a visual reading order that is different to the underlying source. + +For example, using the `order` property on flex items changes the layout order but not the order in the source. + +
+{% Codepen { + user: 'web-dot-dev', + id: 'mdjjmvG', + height: 300, + theme: 'dark', + tab: 'result' +} %} +
Click into the example and tab around to see how the tab order is disconnected from the layout order, using the `order` property.
+
+ +Using grid layout, it is possible for the chosen layout method to jumble up the tab order, for example when using `grid-auto-flow: dense`, which creates a randomized layout order of items. + +
+{% Codepen { + user: 'web-dot-dev', + id: 'RwBBgWq', + height: 600, + theme: 'dark', + tab: 'result' +} %} + +
Click into the example and tab around to see how the tab order is disconnected from the layout order, this time by grid arranging the items out of order.
+
+ +A developer can also cause this disconnect by placing items on the grid in a different order to that dictated in the source. + +
+{% Codepen { + user: 'web-dot-dev', + id: 'eYjjROB', + height: 600, + theme: 'dark', + tab: 'result' +} %} +
Click into the example and tab around to see how the tab order is disconnected from the layout order by use of grid placement properties.
+
+ +{% Aside %} +Learn more about the problem: + +- [Flexbox and the keyboard navigation disconnect](https://tink.uk/flexbox-the-keyboard-navigation-disconnect/) +- [HTML Source Order versus CSS Display Order](https://adrianroselli.com/2015/10/html-source-order-vs-css-display-order.html) +- [Video: Grid, Content Re-Ordering and Accessibility](https://www.youtube.com/watch?v=YXXvP3jtcCo) + +{% endAside %} + +## Proposed solution + +The CSS Working Group is proposing a solution for this problem, and would love feedback from developers and the accessibility community about this approach. + +{% Aside %} +Note that property and value names used in this post are likely to change. This post uses naming conventions that hopefully make things clear for the purpose of getting feedback. +{% endAside %} + +### Following randomized layouts with `reading-order: auto` + +In situations that create a randomized layout order, such as when using dense packing in grid layout, you probably want the browser to follow the layout, rather than the source order. To cause this to happen, the flex or grid items need to have a `reading-order` property, with a value of `auto`. + + The following CSS would cause the reading order to follow the placement of items that have been densely packed due to `grid-auto-flow: dense`. + +```css +.cards { + display: grid; + grid-auto-flow: dense; +} + +.cards li { + grid-column: auto / span 2; + reading-order: auto; +} +``` + +### Following non-randomized layouts with `reading-order-items` + +In some grid and flex layouts, the layout order is straightforward to understand. For example, in a flex layout that uses the `order` property to re-order items there is an obvious layout order dictated by the `order` property. In other layouts it is less clear what the ideal layout order is, there may be more than one possible choice. Therefore, when following non-randomized layouts, you will need to add the `grid-order-items` property to the container, with keyword values explaining your intention for the layout order. + +The following example shows a flex layout using `row-reverse`. The flex items have `reading-order: auto`, and the flex container `reading-order-items: flex flow` to indicate that we also want the reading order to follow the `flex-flow` direction too, rather than following a visual order (which we could indicate with `flex visual`). + +```css +.cards { + display: flex; + flex-flow: row-reverse; + reading-order-items: flex flow; +} + +.cards li { + reading-order: auto; +} +``` + +In this next example, a grid layout is created using `grid-template-areas` and the items are placed in a different layout order to the source order. The `reading-order-items` property is used to indicate we should follow the layout order, traversing each row before advancing to the next. (`grid column` would indicate the opposite direction). + +```css +.wrapper { + display: grid; + grid-template-columns: repeat(6, minmax(0, 1fr)); + grid-template-areas: + "a a b b b b" + "c c d d e e" + "f f g g h h"; + reading-order-items: grid rows; +} + +.a { + grid-area: a; + reading-order: auto; +} +``` + +## Does this mean that source order doesn't matter? + +No, source order still matters. This functionality should only be used in specific situations where the reading order might vary from the source. For example, when using layout methods that can cause this disconnect such as dense grid packing, or when a different layout order makes sense at a certain breakpoint. + +When using these properties, create a source document using an order that would make sense if the page was rendered with no CSS. Add these properties only in the places, and at the breakpoints, that require them. + +{% Aside %} +Reordering using CSS is compelling in cases such as the one described in [this tweet](https://twitter.com/jlengstorf/status/1531411993051090945), because it is easier and faster than manipulating the DOM. There is a companion issue [and proposal](https://github.com/whatwg/dom/issues/586#issuecomment-1414457981) raised against the DOM Standard to make this type of reordering more straightforward too. +{% endAside %} + +## Should authoring tools apply these properties? + +Authoring tools that allow people to create a grid layout by dragging and dropping elements, should still encourage people to create a sensible source document. Therefore in most cases it would be more appropriate to reorder the source based on the layout order, rather than use these properties as a lazy way of dealing with the disconnect. + +## Please share your feedback on this proposal + +We are very keen to gather feedback on this. In particular, if you have a use case that you feel this won't solve, or have an accessibility concern with the approach, please let the CSS Working Group know. + +[There is an ongoing thread](https://github.com/w3c/csswg-drafts/issues/7387), which contains many use cases and thoughts on the approach. That thread is a great place to add any comments, and highlight potential issues with this proposal. Note that the current proposal is very different from my initial one that started the thread. Interested people might enjoy all the conversation that led to where we are today, as it's a good example of how proposals are worked though in the CSS Working Group to become something that can be implemented in browsers. + +_Thumbnail image by [Patrick Tomasso](https://unsplash.com/@impatrickt?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText). Thanks to Chris Harrelson, Tab Atkins, and Ian Kilpatrick for feedback and review._ + \ No newline at end of file From f4f8da1e4aacfe64c5694d4e4049dc14306b8d68 Mon Sep 17 00:00:00 2001 From: Thomas Steiner Date: Wed, 12 Apr 2023 16:38:51 +0200 Subject: [PATCH 020/982] Add WordPress Playground article (#5986) * Add WordPress PHP article * Lint * Lint * Update site/en/blog/wordpress-playground/index.md * Apply suggestions from code review Co-authored-by: Adam Zielinski * Update site/en/blog/wordpress-playground/index.md * Update site/en/blog/wordpress-playground/index.md Co-authored-by: Adam Zielinski * Update site/en/blog/wordpress-playground/index.md --------- Co-authored-by: Rachel Andrew Co-authored-by: Adam Zielinski --- site/_data/authorsData.json | 11 + site/_data/i18n/authors.yaml | 10 + site/en/blog/wordpress-playground/index.md | 237 ++++ .../request-flow.excalidraw | 1182 +++++++++++++++++ 4 files changed, 1440 insertions(+) create mode 100644 site/en/blog/wordpress-playground/index.md create mode 100644 site/en/blog/wordpress-playground/request-flow.excalidraw diff --git a/site/_data/authorsData.json b/site/_data/authorsData.json index fae05d1ec..498f774a8 100644 --- a/site/_data/authorsData.json +++ b/site/_data/authorsData.json @@ -513,6 +513,17 @@ "github": "reillyeon", "image": "image/admin/C7kO2T8Q8jSZxU9xj3AC.jpg" }, + "nattestad": { + "twitter": "fractorious", + "country": "US", + "image": "image/admin/UyUsatSDE2wdnfy3KHzO.jpg" + }, + "adamzielinski": { + "twitter": "adamzielin", + "github": "adamziel", + "homepage": "https://adamadam.blog/", + "image": "image/8WbTDNrhLsU0El80frMBGE4eMCD3/qNsFHO1nZ3FxmYd3PwWL.webp" + }, "cwallez": { "country": "FR", "twitter": "DaKangz", diff --git a/site/_data/i18n/authors.yaml b/site/_data/i18n/authors.yaml index 56d03035c..e6480ddbe 100644 --- a/site/_data/i18n/authors.yaml +++ b/site/_data/i18n/authors.yaml @@ -571,6 +571,16 @@ reillyg: pt: Engenheiro de software no Google Chrome com foco em APIs de hardware ru: Инженер-программист в команде Google Chrome, специализирующийся на API для работы с устройствами zh: 专注于硬件 API 的 Google Chrome 软件工程师 +nattestad: + title: + en: Thomas Nattestad + description: + en: Product Manager at Google +adamzielinski: + title: + en: Adam Zieliński + description: + en: WordPress core committer at Automattic cwallez: title: en: Corentin Wallez diff --git a/site/en/blog/wordpress-playground/index.md b/site/en/blog/wordpress-playground/index.md new file mode 100644 index 000000000..9aef49f85 --- /dev/null +++ b/site/en/blog/wordpress-playground/index.md @@ -0,0 +1,237 @@ +--- +layout: 'layouts/blog-post.njk' +title: + Build in-browser WordPress experiences with WordPress Playground and + WebAssembly +description: > + The full WordPress powered by PHP running solely in the browser with + WebAssembly +authors: + - adamzielinski + - nattestad +date: 2023-04-12 +# updated: 2023-04-12 +hero: image/8WbTDNrhLsU0El80frMBGE4eMCD3/gaEAYfVaiHsMEz07wZSn.jpg +alt: A developer with a WordPress t-shirt sitting in front of a computer. +--- + +When you first see [WordPress Playground](http://wasm.wordpress.net/), it seems +like an ordinary site–maybe except for the colorful background. It's anything +but. What you're actually looking at is an entire WordPress tech stack, +including PHP and a database, running directly in your browser. + +In this post, Adam Zieliński (lead of WordPress Playground) and Thomas Nattestad +(Product Manager for V8) explore: + +- How WordPress Playground can help you as a WordPress developer. +- How it works under the hood. +- What it means for the future of WordPress. + +## Use WordPress without installation, embed it in your app, and even control it with JavaScript + +You can use and customize the WordPress embedded at +[playground.wordpress.net](http://playground.wordpress.net/) for free. There's +no cloud infrastructure and support to pay for, because that site lives entirely +in your browser–no one else can visit it. It's also temporary. As soon as you +refresh the page, it's gone. You can get as many of these sites as you want for +prototyping, trying out plugins, and quickly exploring ideas. + +You can even use them to test your code in different environments using the +built-in PHP and WordPress version switcher: + +{% Img src="image/8WbTDNrhLsU0El80frMBGE4eMCD3/tVA8iwBfR187eUUwCLAL.png", alt="phpinfo page.", width="800", height="699" %} + +WordPress Playground is an entirely new way of using WordPress. Its full power, +however, is only unlocked by including it in your app. The easy way is to embed +WordPress Playground in an `", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "", + "lineHeight": 1.25, + "baseline": 25 + }, + { + "type": "text", + "version": 695, + "versionNonce": 499914982, + "isDeleted": false, + "id": "m0ppO4zGoGdiczac1rtjq", + "fillStyle": "cross-hatch", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 17.467816065974034, + "y": 273.5009969810908, + "strokeColor": "#000000", + "backgroundColor": "#ced4da", + "width": 357.50384521484375, + "height": 35, + "seed": 1959136058, + "groupIds": [], + "roundness": null, + "boundElements": null, + "updated": 1681287917967, + "link": null, + "locked": false, + "fontSize": 28, + "fontFamily": 1, + "text": "an iframe with WordPress:", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "an iframe with WordPress:", + "lineHeight": 1.25, + "baseline": 25 + }, + { + "type": "text", + "version": 198, + "versionNonce": 122343546, + "isDeleted": false, + "id": "GzXz-vZtJsuUmmXzNUc2B", + "fillStyle": "cross-hatch", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": -404.0436057499726, + "y": 662.2340280946055, + "strokeColor": "#000000", + "backgroundColor": "#ced4da", + "width": 262.07989501953125, + "height": 70, + "seed": 719248742, + "groupIds": [], + "roundness": null, + "boundElements": [ + { + "id": "dVwaYw4OEATmX9w22A8E4", + "type": "arrow" + }, + { + "id": "u88zs7UXQNiVdfedzmuvQ", + "type": "arrow" + } + ], + "updated": 1681287917967, + "link": null, + "locked": false, + "fontSize": 28, + "fontFamily": 1, + "text": "Intercepted by the\nService Worker", + "textAlign": "center", + "verticalAlign": "top", + "containerId": null, + "originalText": "Intercepted by the\nService Worker", + "lineHeight": 1.25, + "baseline": 60 + }, + { + "type": "text", + "version": 363, + "versionNonce": 555456358, + "isDeleted": false, + "id": "e1rZuE8EC0qU3HJKGwFC4", + "fillStyle": "cross-hatch", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 109.64005416996633, + "y": 664.3904780686189, + "strokeColor": "#000000", + "backgroundColor": "#ced4da", + "width": 214.087890625, + "height": 70, + "seed": 487887866, + "groupIds": [], + "roundness": null, + "boundElements": [ + { + "id": "u88zs7UXQNiVdfedzmuvQ", + "type": "arrow" + }, + { + "id": "RqLRve-fQJe02Z7bCFKhs", + "type": "arrow" + } + ], + "updated": 1681287917967, + "link": null, + "locked": false, + "fontSize": 28, + "fontFamily": 1, + "text": "Rendered in the\nWorker Thread", + "textAlign": "center", + "verticalAlign": "top", + "containerId": null, + "originalText": "Rendered in the\nWorker Thread", + "lineHeight": 1.25, + "baseline": 60 + }, + { + "type": "text", + "version": 467, + "versionNonce": 1797991098, + "isDeleted": false, + "id": "RXyNgJQivCeHf5z55VRw0", + "fillStyle": "cross-hatch", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 548.0246754449877, + "y": 664.8082676755239, + "strokeColor": "#000000", + "backgroundColor": "#ced4da", + "width": 265.9998779296875, + "height": 70, + "seed": 1529495718, + "groupIds": [], + "roundness": null, + "boundElements": null, + "updated": 1681287917967, + "link": null, + "locked": false, + "fontSize": 28, + "fontFamily": 1, + "text": "...by the in-browser\nWordPress instance", + "textAlign": "center", + "verticalAlign": "top", + "containerId": null, + "originalText": "...by the in-browser\nWordPress instance", + "lineHeight": 1.25, + "baseline": 60 + }, + { + "type": "arrow", + "version": 548, + "versionNonce": 182235110, + "isDeleted": false, + "id": "dVwaYw4OEATmX9w22A8E4", + "fillStyle": "cross-hatch", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 2, + "opacity": 100, + "angle": 0, + "x": -45.38852413632435, + "y": 444.67800712473127, + "strokeColor": "#495057", + "backgroundColor": "#ced4da", + "width": 209.31589275623764, + "height": 207.43113956150046, + "seed": 1947468986, + "groupIds": [], + "roundness": { + "type": 2 + }, + "boundElements": null, + "updated": 1681287918018, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": { + "elementId": "GzXz-vZtJsuUmmXzNUc2B", + "focus": -0.09592636486162824, + "gap": 10.124881408373767 + }, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": "arrow", + "points": [ + [ + 0, + 0 + ], + [ + -119.25106087755307, + 85.57014355804313 + ], + [ + -209.31589275623764, + 207.43113956150046 + ] + ] + }, + { + "type": "text", + "version": 355, + "versionNonce": 1487520634, + "isDeleted": false, + "id": "RpIX1p85aBUMYhuE7YkVM", + "fillStyle": "cross-hatch", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 2, + "opacity": 70, + "angle": 0, + "x": -166.55596604964944, + "y": 534.7545262005287, + "strokeColor": "#495057", + "backgroundColor": "#ced4da", + "width": 243.17991638183594, + "height": 70, + "seed": 178732006, + "groupIds": [], + "roundness": null, + "boundElements": null, + "updated": 1681287917967, + "link": null, + "locked": false, + "fontSize": 28, + "fontFamily": 1, + "text": "HTTP request to\n/wp-admin", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "HTTP request to\n/wp-admin", + "lineHeight": 1.25, + "baseline": 60 + }, + { + "type": "arrow", + "version": 249, + "versionNonce": 1355399974, + "isDeleted": false, + "id": "u88zs7UXQNiVdfedzmuvQ", + "fillStyle": "cross-hatch", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 2, + "opacity": 100, + "angle": 0, + "x": -131.99745436348212, + "y": 691.8877300400327, + "strokeColor": "#495057", + "backgroundColor": "#ced4da", + "width": 236.7285738368414, + "height": 34.009861092194114, + "seed": 1130847610, + "groupIds": [], + "roundness": { + "type": 2 + }, + "boundElements": null, + "updated": 1681287918018, + "link": null, + "locked": false, + "startBinding": { + "elementId": "GzXz-vZtJsuUmmXzNUc2B", + "focus": 0.4635717927264672, + "gap": 9.966256366959215 + }, + "endBinding": { + "elementId": "e1rZuE8EC0qU3HJKGwFC4", + "focus": -0.41366093049067265, + "gap": 4.908934696607048 + }, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": "arrow", + "points": [ + [ + 0, + 0 + ], + [ + 115.2457931407489, + -30.974453294389605 + ], + [ + 236.7285738368414, + 3.0354077978045098 + ] + ] + }, + { + "type": "arrow", + "version": 338, + "versionNonce": 1275324986, + "isDeleted": false, + "id": "RqLRve-fQJe02Z7bCFKhs", + "fillStyle": "cross-hatch", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 2, + "opacity": 100, + "angle": 0, + "x": 330.43695331452227, + "y": 700.1128810834052, + "strokeColor": "#495057", + "backgroundColor": "#ced4da", + "width": 199.90870669883225, + "height": 25.224903487598567, + "seed": 258133798, + "groupIds": [], + "roundness": { + "type": 2 + }, + "boundElements": null, + "updated": 1681287918018, + "link": null, + "locked": false, + "startBinding": { + "elementId": "e1rZuE8EC0qU3HJKGwFC4", + "focus": 0.4621267913457183, + "gap": 6.709008519555937 + }, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": "arrow", + "points": [ + [ + 0, + 0 + ], + [ + 104.94313163725019, + -25.224903487598567 + ], + [ + 199.90870669883225, + -3.5719049540989545 + ] + ] + }, + { + "type": "rectangle", + "version": 1566, + "versionNonce": 316257382, + "isDeleted": false, + "id": "dv4xyRjxB1P6fa8bUHQ23", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 541.1914589846546, + "y": 847.5025500485262, + "strokeColor": "#ced4da", + "backgroundColor": "#ced4da", + "width": 281.0156618629228, + "height": 276.4817952203143, + "seed": 676437562, + "groupIds": [], + "roundness": null, + "boundElements": null, + "updated": 1681287917967, + "link": null, + "locked": false + }, + { + "type": "rectangle", + "version": 2669, + "versionNonce": 1746316538, + "isDeleted": false, + "id": "p3axPnqea6VunXFCHruYj", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 569.708555152364, + "y": 994.3258003612555, + "strokeColor": "#000000", + "backgroundColor": "#fff", + "width": 229, + "height": 46, + "seed": 1976171110, + "groupIds": [], + "roundness": null, + "boundElements": [ + { + "id": "GMTZNJkY3Hh74TPQl-_GP", + "type": "arrow" + }, + { + "type": "text", + "id": "6eIQUy6wZzdE9SazhSqHh" + } + ], + "updated": 1681287917967, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 2786, + "versionNonce": 1269970854, + "isDeleted": false, + "id": "6eIQUy6wZzdE9SazhSqHh", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 608.3986338877156, + "y": 1004.8258003612555, + "strokeColor": "#000000", + "backgroundColor": "#fff", + "width": 151.61984252929688, + "height": 25, + "seed": 532006650, + "groupIds": [], + "roundness": null, + "boundElements": null, + "updated": 1681287917967, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 1, + "text": "WordPress files", + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "p3axPnqea6VunXFCHruYj", + "originalText": "WordPress files", + "lineHeight": 1.25, + "baseline": 18 + }, + { + "type": "rectangle", + "version": 2747, + "versionNonce": 694877626, + "isDeleted": false, + "id": "ntye4r4LvjeVgMSB7rOA6", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 570.3362464789983, + "y": 1052.3295728787334, + "strokeColor": "#000000", + "backgroundColor": "#fff", + "width": 229, + "height": 46, + "seed": 883539366, + "groupIds": [], + "roundness": null, + "boundElements": [ + { + "id": "GMTZNJkY3Hh74TPQl-_GP", + "type": "arrow" + }, + { + "type": "text", + "id": "C0z70xHWicBus8vOAUg3s" + } + ], + "updated": 1681287917967, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 2869, + "versionNonce": 890786534, + "isDeleted": false, + "id": "C0z70xHWicBus8vOAUg3s", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 652.4062766914006, + "y": 1062.8295728787334, + "strokeColor": "#000000", + "backgroundColor": "#fff", + "width": 64.85993957519531, + "height": 25, + "seed": 303486906, + "groupIds": [], + "roundness": null, + "boundElements": null, + "updated": 1681287917967, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 1, + "text": "SQLite", + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "ntye4r4LvjeVgMSB7rOA6", + "originalText": "SQLite", + "lineHeight": 1.25, + "baseline": 18 + }, + { + "type": "rectangle", + "version": 2409, + "versionNonce": 91698810, + "isDeleted": false, + "id": "1n7kxdDmcbTC6y3_l9u0n", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 566.6396534631461, + "y": 943.224124132169, + "strokeColor": "#000000", + "backgroundColor": "#fff", + "width": 114, + "height": 40, + "seed": 1630476518, + "groupIds": [], + "roundness": null, + "boundElements": [ + { + "id": "GMTZNJkY3Hh74TPQl-_GP", + "type": "arrow" + }, + { + "type": "text", + "id": "nxENEqvhzdHNZ7CaLNEOR" + } + ], + "updated": 1681287917967, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 2525, + "versionNonce": 429458982, + "isDeleted": false, + "id": "nxENEqvhzdHNZ7CaLNEOR", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 592.3896839807243, + "y": 950.724124132169, + "strokeColor": "#000000", + "backgroundColor": "#fff", + "width": 62.49993896484375, + "height": 25, + "seed": 1603784826, + "groupIds": [], + "roundness": null, + "boundElements": null, + "updated": 1681287917967, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 1, + "text": "/php.js", + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "1n7kxdDmcbTC6y3_l9u0n", + "originalText": "/php.js", + "lineHeight": 1.25, + "baseline": 18 + }, + { + "type": "rectangle", + "version": 2539, + "versionNonce": 754865978, + "isDeleted": false, + "id": "dXFPGgFYsMyH1ZXChIimq", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 685.965203697478, + "y": 942.7841684630775, + "strokeColor": "#000000", + "backgroundColor": "#fff", + "width": 114, + "height": 40, + "seed": 1659309094, + "groupIds": [], + "roundness": null, + "boundElements": [ + { + "id": "GMTZNJkY3Hh74TPQl-_GP", + "type": "arrow" + }, + { + "type": "text", + "id": "o_nTEJCsh_FJ5ltOHBVLa" + } + ], + "updated": 1681287917967, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 2668, + "versionNonce": 1780568422, + "isDeleted": false, + "id": "o_nTEJCsh_FJ5ltOHBVLa", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 695.905244285857, + "y": 950.2841684630775, + "strokeColor": "#000000", + "backgroundColor": "#fff", + "width": 94.11991882324219, + "height": 25, + "seed": 1811657018, + "groupIds": [], + "roundness": null, + "boundElements": null, + "updated": 1681287917967, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 1, + "text": "/php.wasm", + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "dXFPGgFYsMyH1ZXChIimq", + "originalText": "/php.wasm", + "lineHeight": 1.25, + "baseline": 18 + }, + { + "type": "rectangle", + "version": 2735, + "versionNonce": 1080254458, + "isDeleted": false, + "id": "2tQE7lyNr0cK9YNGrCAil", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 570.9668662938317, + "y": 889.1233257041904, + "strokeColor": "#000000", + "backgroundColor": "#fff", + "width": 229, + "height": 46, + "seed": 666802022, + "groupIds": [], + "roundness": null, + "boundElements": [ + { + "id": "GMTZNJkY3Hh74TPQl-_GP", + "type": "arrow" + }, + { + "id": "DtRTJZeudobPamxju7HQj", + "type": "arrow" + }, + { + "type": "text", + "id": "Y8cFznNxoAT2f0p09ilj2" + } + ], + "updated": 1681287917967, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 2885, + "versionNonce": 1912485030, + "isDeleted": false, + "id": "Y8cFznNxoAT2f0p09ilj2", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 636.5569084080895, + "y": 899.6233257041904, + "strokeColor": "#000000", + "backgroundColor": "#fff", + "width": 97.81991577148438, + "height": 25, + "seed": 715487738, + "groupIds": [], + "roundness": null, + "boundElements": null, + "updated": 1681287917967, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 1, + "text": "PHP class", + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "2tQE7lyNr0cK9YNGrCAil", + "originalText": "PHP class", + "lineHeight": 1.25, + "baseline": 18 + }, + { + "type": "text", + "version": 936, + "versionNonce": 1537822906, + "isDeleted": false, + "id": "scJD9pCr_BWQ2zr3zvSKZ", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 628.2107428658089, + "y": 854.7483019705387, + "strokeColor": "#495057", + "backgroundColor": "#ccc", + "width": 104.0399169921875, + "height": 25, + "seed": 1476573862, + "groupIds": [], + "roundness": null, + "boundElements": null, + "updated": 1681287917967, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 1, + "text": "PHP Stack", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "PHP Stack", + "lineHeight": 1.25, + "baseline": 18 + } + ], + "appState": { + "gridSize": null, + "viewBackgroundColor": "#ffffff" + }, + "files": {} +} \ No newline at end of file From f57c7b3d4ffefd043fcdc6b1b08ada61a393ef5f Mon Sep 17 00:00:00 2001 From: Oliver Dunk Date: Wed, 12 Apr 2023 17:31:37 +0100 Subject: [PATCH 021/982] Document world key in manifest content_scripts declaration (#5987) --- site/en/docs/extensions/mv3/content_scripts/index.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/site/en/docs/extensions/mv3/content_scripts/index.md b/site/en/docs/extensions/mv3/content_scripts/index.md index 2a1830848..0b20bdc20 100644 --- a/site/en/docs/extensions/mv3/content_scripts/index.md +++ b/site/en/docs/extensions/mv3/content_scripts/index.md @@ -168,6 +168,14 @@ They can include JavaScript files, CSS files, or both. All auto-run content scri Injecting in related frames. + + world + ExecutionWorld + + Optional. The JavaScript world for a script to execute within. Defaults to ISOLATED. See also + Work in isolated worlds. + + From 107fe441f988910fcc09fb9a3f05c1018008049b Mon Sep 17 00:00:00 2001 From: Alexandra White Date: Wed, 12 Apr 2023 15:58:42 -0400 Subject: [PATCH 022/982] add rule (#5988) --- .../aggregation-service/index.md | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/site/en/docs/privacy-sandbox/aggregation-service/index.md b/site/en/docs/privacy-sandbox/aggregation-service/index.md index f164505e5..54f66a96e 100644 --- a/site/en/docs/privacy-sandbox/aggregation-service/index.md +++ b/site/en/docs/privacy-sandbox/aggregation-service/index.md @@ -79,6 +79,34 @@ If you are testing the Aggregation Service, see the [Coordinator Service Additional Terms of Service](/docs/privacy-sandbox/aggregation-service/tos/). {% endAside %} +### "No duplicates" rule {: #no-duplicates-rule } + +To gain insight into the contents of a specific aggregatable report, an +attacker might make multiple copies of the report and include those copies in a +single or multiple batches. Because of this, the Aggregation Service enforces a +"no duplicates" rule: + +* **In a batch**: An aggregatable report can only appear once within a batch. +* **Across batches**: Aggregatable reports cannot appear in more than one batch or contribute to more than one summary report. + +To accomplish this, the browser assigns each aggregatable report a shared ID. +The browser generates the shared ID from several data points, including: API +version, reporting origin, destination site, source registration time, and +scheduled report time. This data comes from the +[`shared_info`](https://github.com/WICG/attribution-reporting-api/blob/main/AGGREGATE.md#aggregatable-reports) field in the report. + +The Aggregation Service confirms that all aggregatable reports with the same +shared ID are in the same batch and reports to the coordinator that the shared +ID was processed. If multiple batches are created with the same ID, only one +batch can be accepted for aggregation, and other batches are rejected. + +When you perform a [debug run](https://github.com/privacysandbox/aggregation-service/blob/main/docs/DEBUGGING.md), +the "no duplicates" rule is not enforced across batches. In other words, +reports from previous batches may appear in a debug run. However, the rule is +still enforced within a batch. This allows you to experiment with the service +and various batching strategies, without limiting future processing in a +production environment. + ## Noise and scaling {: #noise-scale} To protect user privacy, the Aggregation Service applies an From bcdd6ced714b80ab7adfe78ed4b952da939b9b73 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 13 Apr 2023 11:15:53 +0200 Subject: [PATCH 023/982] Bump @mdn/browser-compat-data from 5.2.49 to 5.2.50 (#5979) Bumps [@mdn/browser-compat-data](https://github.com/mdn/browser-compat-data) from 5.2.49 to 5.2.50. - [Release notes](https://github.com/mdn/browser-compat-data/releases) - [Changelog](https://github.com/mdn/browser-compat-data/blob/main/RELEASE_NOTES.md) - [Commits](https://github.com/mdn/browser-compat-data/compare/v5.2.49...v5.2.50) --- updated-dependencies: - dependency-name: "@mdn/browser-compat-data" dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package-lock.json | 14 +++++++------- package.json | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index 04528993f..03d9d82cc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,7 +17,7 @@ "@google-cloud/error-reporting": "^2.0.4", "@google-cloud/storage": "^6.7.0", "@lhci/cli": "^0.7.2", - "@mdn/browser-compat-data": "5.2.49", + "@mdn/browser-compat-data": "5.2.50", "@rollup/plugin-node-resolve": "^8.4.0", "algoliasearch": "^4.6.0", "async-transforms": "1.0.6", @@ -1810,9 +1810,9 @@ } }, "node_modules/@mdn/browser-compat-data": { - "version": "5.2.49", - "resolved": "https://registry.npmjs.org/@mdn/browser-compat-data/-/browser-compat-data-5.2.49.tgz", - "integrity": "sha512-tXJUP9EFcfeTcn3hpn616qtcbaLMrhqfgsljRnIv/qYckL8ywLodk7Cj3oJlZed3zWLZLnE9LHHsfpO8w4yJuw==" + "version": "5.2.50", + "resolved": "https://registry.npmjs.org/@mdn/browser-compat-data/-/browser-compat-data-5.2.50.tgz", + "integrity": "sha512-3qGRdT2lrIloY8xotSRTW7k3oIRJAO7WSsJymTLN1sqeB1qiWPcbQdAiDG/IQWCA2QCVQewTeT2kfZf/you94w==" }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", @@ -26942,9 +26942,9 @@ } }, "@mdn/browser-compat-data": { - "version": "5.2.49", - "resolved": "https://registry.npmjs.org/@mdn/browser-compat-data/-/browser-compat-data-5.2.49.tgz", - "integrity": "sha512-tXJUP9EFcfeTcn3hpn616qtcbaLMrhqfgsljRnIv/qYckL8ywLodk7Cj3oJlZed3zWLZLnE9LHHsfpO8w4yJuw==" + "version": "5.2.50", + "resolved": "https://registry.npmjs.org/@mdn/browser-compat-data/-/browser-compat-data-5.2.50.tgz", + "integrity": "sha512-3qGRdT2lrIloY8xotSRTW7k3oIRJAO7WSsJymTLN1sqeB1qiWPcbQdAiDG/IQWCA2QCVQewTeT2kfZf/you94w==" }, "@nodelib/fs.scandir": { "version": "2.1.5", diff --git a/package.json b/package.json index 9fc9e94eb..83bd3156d 100644 --- a/package.json +++ b/package.json @@ -51,7 +51,7 @@ "@google-cloud/error-reporting": "^2.0.4", "@google-cloud/storage": "^6.7.0", "@lhci/cli": "^0.7.2", - "@mdn/browser-compat-data": "5.2.49", + "@mdn/browser-compat-data": "5.2.50", "@rollup/plugin-node-resolve": "^8.4.0", "algoliasearch": "^4.6.0", "async-transforms": "1.0.6", From 184c2c69f7c0eb59b0d7e99376d1733f61d1c745 Mon Sep 17 00:00:00 2001 From: ilyaspiridonov Date: Thu, 13 Apr 2023 15:16:30 +0300 Subject: [PATCH 024/982] [JA] March translations (#5980) * Translate index.md via GitLocalize * Translate index.md via GitLocalize * Translate index.md via GitLocalize * Translate index.md via GitLocalize * Translate index.md via GitLocalize * Translate index.md via GitLocalize * Translate index.md via GitLocalize * Translate index.md via GitLocalize * Update index.md * Update index.md * Update index.md * Update index.md * Update site/ja/blog/working-with-the-industry-to-evolve-chips/index.md Co-authored-by: Eiji Kitamura --------- Co-authored-by: Eiji Kitamura Co-authored-by: Nozomi Kugita Co-authored-by: mt-gitlocalize --- .../index.md | 176 ++++++++++++++++++ .../index.md | 66 +++++++ .../maximize-ad-relevance/index.md | 151 +++++++++++++++ 3 files changed, 393 insertions(+) create mode 100644 site/ja/blog/origin-trial-for-accept-language-reduction/index.md create mode 100644 site/ja/blog/working-with-the-industry-to-evolve-chips/index.md create mode 100644 site/ja/docs/privacy-sandbox/maximize-ad-relevance/index.md diff --git a/site/ja/blog/origin-trial-for-accept-language-reduction/index.md b/site/ja/blog/origin-trial-for-accept-language-reduction/index.md new file mode 100644 index 000000000..3a4ea6732 --- /dev/null +++ b/site/ja/blog/origin-trial-for-accept-language-reduction/index.md @@ -0,0 +1,176 @@ +--- +layout: layouts/blog-post.njk +title: Accept-Language の情報量削減のオリジントライアルに参加する +description: Accept-Language の情報量削減は、Chrome ブラウザにおけるパッシブフィンガープリンティングの攻撃サーフェスを削減するための取り組みです。 +date: 2022-12-01 +tags: + - privacy +authors: + - victortan +--- + +Accept-Language の情報量削減は、[`Accept-Language`](https://developer.mozilla.org/docs/Web/HTTP/Headers/Accept-Language) ヘッダーでユーザーの言語設定を減らし、ユーザーが最も優先する言語(1 つだけ)のみを送信することにより、パッシブフィンガープリンティングの攻撃サーフェスを減らす取り組みです。 + +[Chrome 109](https://chromiumdash.appspot.com/schedule) ベータ版より、Accept-Language の情報量削減の[オリジントライアル](/origintrials/#/view_trial/-7166352907053301759)を開始し、削減された `Accept-Language` ヘッダーをサイトが受け取ることを選択できるようにします。これにより、削減された `Accept-Language` が Chrome の将来のリリースでデフォルトの動作になる前に、サイトがイシューを発見して修正できるようになります。安定したユーザー数に対して公開される前に機能をテストするには、Chrome 109 のリリース日([現時点では 2023 年 1 月 10 日予定](https://chromiumdash.appspot.com/schedule))の前に必ずオプトインしてテストしてください。 + +以下は削減前後の`Accept-Language`ヘッダーの例です。 + +{% Compare 'worse', 'current' %} + +```text +Accept-Language: en-GB,en;q=0.9,de;q=0.8,fr;q=0.7 +``` + +{% endCompare %} + +{% Compare 'better', 'proposed' %} + +```text +Accept-Language: en-GB +``` + +{% endCompare %} + +以下は、オリジントライアルの概要と今後の予定です。[Accept-Language の情報量削減 GitHub リポジトリ](https://github.com/Tanych/accept-language)で、この変更またはオリジントライアル中に見つかったイシューに関するフィードバックを共有できます。 + +## Accept-Language とは? + +[Accept-Language](https://developer.mozilla.org/docs/Web/HTTP/Headers/Accept-Language) 文字列はすべての HTTP リクエストで共有され、ブラウザによって読み込まれたすべてのリソースに JavaScript で公開されます。現在、ユーザーの優先言語がすべて含まれています。 + +## Accept-Language が削減される理由 + +Accept-Language の情報量削減は、Chrome ブラウザにおけるパッシブフィンガープリンティングの攻撃サーフェスを削減する取り組みです。 + +現在、`Accept-Language` ヘッダーはデフォルトですべての HTTP リクエストで共有され、ブラウザによって読み込まれたすべてのリソースに JavaScript で公開されます。これには、ユーザーのすべての言語設定が含まれています。サイトが多言語コンテンツを提供する場合に、ブラウザがユーザー構成の完全な言語リストを送信するのではなく、サイトが多言語コンテンツを示し、ブラウザが言語ネゴシエーションを行って優先言語を表示するタスクを担当する、新しい手法を導入しています。 + +もう 1 つに、多くのサイトが言語ネゴシエーションに `Accept-Language` ヘッダーをまったく使用していない可能性があるという理由があります(たとえば、[ある調査](https://wonderproxy.com/blog/accept-language/)によると、上位 10,000 サイトの 7.2% のみが `Accept-Language` を使用していることがわかりました)。Chrome のシークレットモードでは、`Accept-Language` がすでに 1 つに減らされています。 + +## ウェブ開発者にとっての意味 + +言語ネゴシエーションを `Accept-Language` に任せているサイトは、削減された `Accept-Language` を受け取る準備をし、オリジントライアルへの参加を検討することをお勧めします。削減された `Accept-Language` 値は以下のの場所に表示されます。 + +- `Accept-Language` HTTP リクエストヘッダー。 +- `navigator.languages` JavaScript ゲッター。 + +サイトに送信するユーザーの優先言語を選択するための言語ネゴシエーションは、ブラウザが担当するようになります。これを実現するには、サイトはレスポンスヘッダーに `Accept-Language` と [`Content-Language`](https://datatracker.ietf.org/doc/html/rfc3282) の 2 つのヘッダー [`Variants`](https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-variants-06#section-2)(サイトがサポートする言語を示す新しいヘッダー)を追加する必要があります(詳細は以下の例をご覧ください)。 + +削減された `Accept-Language` の計画には現在、iOS と WebView が含まれていません。これらのプラットフォームでは、ユーザーの完全な `Accept-Language` リストが引き続き取得されます。これらのプラットフォームは後日サポートされる予定です。 + +## Accept-Language の情報量削減のオリジントライアル + +オリジントライアルでは、参加サイトがレスポンスでトークンを提供する必要があります。このトークンは、指定されたトライアルを有効にするようにブラウザに指示するものです。ただし、これは、サイトに対するブラウザの最初のリクエストにおいて、サイトがオリジントライアルに参加しているかどうかを確認する方法がないということになります。つまり、*セッションの最初のリクエストでは縮小された `Accept-Language header` は送信されません*。そのページのサブリソースのリクエストでは、同一オリジンやクロスオリジンに関係なく、縮小された `Accept-Language` ヘッダーが受け取られます。その後の同一オリジンの移動操作においても、縮小された `Accept-Language` ヘッダーが受け取られます。クロスオリジンの移動操作では完全なヘッダーの送信に戻りますが、ページ内のクロスオリジンリクエスト(サードパーティの iframe リクエストなど)では、トップレベルのフレームリクエストに有効なオリジントライアルトークンがある場合に、削減された `Accept-Language` ヘッダーが引き続き送信されます。 + +これは User-Agent の情報量削減のオリジントライアルに似ています。Chromium 内部の実装についての詳細は、[削減された Accept-Language HTTP ヘッダーの実装](https://docs.google.com/document/d/1RkPDf7DNtcOj4KXeW8wNCuYfto-drnGYST_NvZe3GoY/)をご覧ください。 + +## Accept-Language の情報量削減オリジントライアルに参加する + +[Chrome のオリジントライアルを開始する](/docs/web-platform/origin-trials/)で詳細なガイダンスを読むことができますが、基本的な手順を以下に示します。 + +### ステップ 1 + +オリジントライアルに登録してドメインのトークンを取得するには、 [Accept-Language の情報量削減のトライアル](/origintrials/#/view_trial/-7166352907053301759)ページにアクセスしてください。 + +### ステップ 2 + +HTTP レスポンスヘッダーを以下のように更新します。 + +1. `Origin-Trial: ` を HTTP レスポンスヘッダーに追加します。<`ORIGIN TRIAL TOKEN`> には、オリジントライアル登録時に取得したトークンが含まれています。 +2. `Content-Language` を HTTP レスポンスヘッダーに追加して、オーディエンス向けの言語を示します。 +3. `Variants` をHTTP レスポンスヘッダーに追加して、サイトがサポートする言語を示します。 +4. [オプション]`Vary: Accept-Language` を HTTP レスポンスに追加して、コンテンツネゴシエーション用のキャッシュキーを作成します。 +5. これらのヘッダーを設定すると、指定されたオリジンのブラウザ言語ネゴシエーション(最初のリクエストでは再起動の可能性)のみがトリガーされます。サイトがユーザーに対して正しい言語表現を表示するようにするには、ユーザーの Accept-Language ヘッダーに基づいてコンテンツを送信するサイトを更新する必要もあります(以下の例を参照)。 + +{% Aside %} レスポンスヘッダーに有効な `Origin-Trial` トークン、`Content-Language` ヘッダー、および有効な `Variants` ヘッダーが含まれている場合、すべてのサブリソースリクエスト(画像やスタイルシートなど)とサブナビゲーション(iframe など)は、これらのリクエストのオリジンがオリジントライアルに登録されていない場合でも、削減された Accept-Language 文字列を送信します。{% endAside %} + +### ステップ 3 + +ウェブサイトを Chrome M109 Beta(またはそれ以降)で読み込み、削減された Accept-Language 文字列の受信を開始します。 + +イシューやフィードバックについては、Accept-Language の情報量削減の [GitHub リポジトリ](https://github.com/Tanych/accept-language)に送信してください。 + +## デモ + +オリジントライアルにオプトインした多言語サイトのデモ(およびソースコード)については、[https://reduce-accept-language.glitch.me/](https://reduce-accept-language.glitch.me/) をご覧ください。 + +オリジントライアルのオプトインとオプトアウトのデモ(およびソースコード)については、[https://reduce-accept-language-ot.glitch.me/](https://reduce-accept-language-ot.glitch.me/) をご覧ください。 + +たとえば、`example.com` では、`ja`(日本語)と `en`(英語)がサポートされています。リクエストは以下のようになります。 + +```text +GET / HTTP/1.1 +Host: example.com +Accept-Language: en +``` + +サイトは、ユーザーの Accept-Language に基づいて、ユーザーが英語のコンテンツを優先することを認識しています。レスポンスヘッダーには以下が含まれる可能性があります。 + +```text +HTTP/1.1 200 OK +Content-Language: en +Variants: Accept-Language=(en ja) +Origin-Token: a-valid-token +``` + +ユーザーが日本語のコンテンツを優先する場合、リクエストは以下のようになります。 + +```text +GET / HTTP/1.1 +Host: example.com +Accept-Language: ja +``` + +この場合、サイトは日本語コンテンツのヘッダーで応答します。 + +```text +HTTP/1.1 200 OK +Content-Language: ja +Variants: Accept-Language=(en ja) +Origin-Token: a-valid-token +``` + +サーバー側では、サイトが特定の言語サポートを探しているにもかかわらず、サポートが検出されない場合は、デフォルトにフォールバックします。 + +```js +if(accept_language == 'ja') { + res.response('ja_page') +} +else { + res.response('en_page') +} +``` + +上記の例では、`example.com` は、`Accept-Language` 値に基づいて `en` または `ja` のいずれかを応答し、一致するものがなければデフォルトで `en` になります。この場合、サイトは、`Accept-Language` 値に基づいて、`/en` または `/ja` に対応する言語ページへのリダイレクトを提供することもできます。リダイレクトに関連する詳細な例については、[実装ドキュメント](https://docs.google.com/document/d/1RkPDf7DNtcOj4KXeW8wNCuYfto-drnGYST_NvZe3GoY/edit#bookmark=id.eml73ve0kywe)をご覧ください。 + +## サードパーティオリジントライアルのサポート + +現在、[トライアル用のサードパーティ](/docs/web-platform/third-party-origin-trials/)としてドメインを登録することはサポートされていません。オリジン間でサブリソースとして実装されているサービス(広告配信や分析など)を運用している場合、トップレベルサイトがオリジントライアルに参加している場合にのみ、削減された `Accept-Language` ヘッダーを受け取ります。 + +## オリジントライアルの動作状況の確認 + +[Chrome のオリジントライアルのトラブルシューティング](/docs/web-platform/origin-trial-troubleshooting/)ガイドでは、トークンが正しく構成されていることを確認するための完全なチェックリストを提供しています。 + +`chrome://settings/languages` または[設定]→[言語]から、複数の言語とその優先度を構成します。サイトで**サポートされていない**言語を選択し、それをリストの一番上に移動して、追加のネゴシエーションが確実にトリガーされるようにすることを検討してください。 + +origin-trial トークンを含む最初のレスポンスヘッダーは以下のようになります。 + +{% Img src="image/vgdbNJBYHma2o62ZqYmcnkq3j0o1/9vMsKcqCF2wEQ7K4dxKT.png", alt="削減された Accept-Language を含むリクエストヘッダーのスクリーンショット", width="800", height="228" %} + +削減された Accept-Language を含む後続のリクエストヘッダーは以下のようになります。 + +{% Img src="image/vgdbNJBYHma2o62ZqYmcnkq3j0o1/kdfphse1F4gscnY74UJi.png", alt="origin-trial トークンを含む最初のレスポンスのヘッダー。", width="800", height="257" %} + +## オリジントライアルへの参加を中止する + +トライアル期間中の任意の時点で参加を中止すると、ユーザーの Accept-Language の全リストを受け取ることができます。参加を中止するには、以下のようにします。 + +1. Accept-Language の情報量削減トライアルの `Origin-Trial` ヘッダーを HTTP レスポンスから削除します。 +2. [オプション]このヘッダーの送信に関心がない場合は、オリジントライアルにオプトインするために HTTP レスポンスに追加された `Variants` ヘッダーを削除します。また、`Variants` に空の値を使用しても、同じことを行えます。 +3. [オプション]このヘッダーの送信に関心がない場合は、オリジントライアルにオプトインするために HTTP レスポンスに追加された `Content-Language` ヘッダーを削除します。 + +## オリジントライアルの期間 + +Accept-Language の情報量削減オリジントライアルは、少なくとも 6 か月間実施されます。これは、約 6 つの Chrome マイルストーンに対応する期間です。オリジントライアルは M109 で開始され、M114 (トライアルを使用できる最後の Chrome リリース)で終了します。この時点で、オリジントライアルからのフィードバックが評価され、その後 Chrome は削減された Accept-Language 文字列を段階的にロールアウトします(まず、削減された Accept-Language HTTP ヘッダーをロールアウトしてから、JS インターフェースを削減します)。サイトがテスト期間の延長を必要とする場合は、その後のデプリケーショントライアルにオプトインできます。これにより、少なくともさらに 6 か月間、完全な Accept-Language 文字列にアクセスすることが可能です。デプリケーショントライアルの詳細については、準備が整い次第公開します。 + +## フィードバックを共有する + +イシューやフィードバックについては、Accept-Language の情報量削減の [GitHub リポジトリ](https://github.com/Tanych/accept-language)に送信してください。 diff --git a/site/ja/blog/working-with-the-industry-to-evolve-chips/index.md b/site/ja/blog/working-with-the-industry-to-evolve-chips/index.md new file mode 100644 index 000000000..7c98211ce --- /dev/null +++ b/site/ja/blog/working-with-the-industry-to-evolve-chips/index.md @@ -0,0 +1,66 @@ +--- +layout: layouts/blog-post.njk +title: CHIPS の進化に向けた業界との共同作業 +subhead: Chrome チームが CHIPS の実装で直面した 2 つの課題と、コミュニティからのフィードバックが提案デザインの進化にどのように重要な役割を果たしたかを探ります。 +description: Chrome チームが CHIPS の実装で直面した 2 つの課題と、コミュニティからのフィードバックが提案デザインの進化にどのように重要な役割を果たしたかを探ります。 +date: 2023-02-28 +authors: + - mihajlija + - jney +hero: image/udVScdcCFAdRjZwFdLk2jWAFQyr1/Rr2cBdWZprYKZQrJI8cw.png +alt: CHIPS の進化に向けた業界との共同作業。 +--- + +[Cookies having Independent Partitioned State(CHIPS)](/docs/privacy-sandbox/chips/)は、開発者がトップレベル サイトごとに個別の Cookie ジャーを使用して、Cookie を「パーティション化された」ストレージにオプトインできるようにするプライバシー サンドボックス テクノロジーです。
CHIPS のユースケースの例には、サードパーティのチャット ウィジェット、マップの埋め込み、サブリソース CDN の負荷分散、ヘッドレス CMS プロバイダーなど、単一のトップレベル サイトでのユーザーのアクティビティを対象とするセッションまたは永続的な状態の概念がクロスサイト サブリソースに必要となるシナリオが含まれます。 + +CHIPS は、オープンな Web 標準になることを目標に開発されています。これは PrivacyCG で議論されており、Chrome チームは 7 か月に渡るオリジン トライアルの期間中に有益なフィードバックを集めています。開発では、主要関係者との協力を通じてそのフィードバックを調査し、ウェブエコシステムにより良いサービスを提供するようにデザインを更新しました。 + +では、Chrome チームが CHIPS を実装する際に直面した 2 つの課題と、提案のデザインを進化させる上でコミュニティからのフィードバックがどれほど重要な役割を果たしたかについて探ってみましょう。 + +## host- プレフィックスと `Domain` 禁止要件の削除 + +適切なセキュリティ実践を促進するために、CHIPS の設計では、Cookie の設定と送信には安全なプロトコルのみを使用し、パーティション化された Cookie に `Secure` を設定することが要求されています。 + +最初の提案では、これらの要件のほかに、パーティション化された Cookie の `Domain` 属性を許可していませんでした。Cookie で `Domain` を省略すると、パーティション内の異なるサードパーティ サブドメイン間で Cookie を共有できなくなっていました。 + +オリジン トライアル中、Chrome チームはパートナーやその他の関係者から、[Domain 禁止要件により、サブドメインを持つサイトで CHIPS を実装するのが難しくなったとの報告](https://github.com/privacycg/CHIPS/issues/30)を受けました。たとえば、`shop.example.com` と `pay.example.com` では、パーティション化された Cookie ジャーの共有が困難になります。他には、[埋め込みのコンテキストでの認証フローが困難になったというケース](https://github.com/privacycg/CHIPS/issues/39)もありました。 + +{% Img src="image/vgdbNJBYHma2o62ZqYmcnkq3j0o1/P8OeJqoGqjW8oZLTWmr5.png", alt="pay.example.com と shop.example.com サイトを示す図", width="800", height="224" %} + +Chrome チームではこのフィードバックを評価し、Domain 禁止要件を削除してもプライバシーの問題は発生しないが、使いやすさが向上すると結論付けました。それに応じて、CHIPS プロダクトチームは [GitHub](https://github.com/privacycg/CHIPS/issues/43) でディスカッションを開始し、この要件の削除についてさらに多くのフィードバックを求めました。CHIPS をテストしていたいくつかの企業から、自社のユースケースにおけるこの変更の重要性についての回答と公式コメントをいただきました。 + +Chrome はこのフィードバックを W3C の Privacy Community Group に提出し、提案の更新を提示しました。Firefox と Edge は変更を承認し、Safari は何の懸念も提起しなかったため、翌日、Chrome チームは [Blink-Dev](https://groups.google.com/a/chromium.org/g/blink-dev/c/kZRtetS8jsY/m/ppK4kDbqAwAJ?utm_medium=email&utm_source=footer) を更新し、[CHIPS Github リポジトリ](https://github.com/privacycg/CHIPS/issues/47)でこの要件を削除する計画を提示しました。 + +CHIPS チームは当初、悪意のあるサブドメインや侵害されたサブドメインからサイトがクロスサイト Cookie を受信しないことを保証し、Domain Cookie をチャンネルとして使用してサブドメイン間でデータ漏洩の可能性を軽減するために、この要件を提案しました。 + +この提案によってセキュリティ上のメリットがさらにもたらされましたが、一部の現在のアプリケーション アーキテクチャがサブドメイン間で Cookie を共有することに依存しているため、CHIPS の採用には課題があることを [Tableau が強調](https://github.com/privacycg/CHIPS/issues/30)しました。 + +Chrome がこの変更を行った後、現在 Salesforce が所有するビジュアル分析プラットフォームを提供する Tableau は次のように [述べています](https://github.com/privacycg/CHIPS/issues/30#issuecomment-1104225686)。 + +{% Blockquote 'Lee Graber, Software Engineering Architect, Tableau' %} この命名変更の削除により、 `SameSite=None` 属性を追加し、より「既知の」数量を追加するという以前の変更と要件がより一致するようになります。Google がフィードバックを聞き入れ、潜在的な影響を検討し、より簡単な移行をサポートするために変更してくれたことに感謝します。 {% endBlockquote %} + +このプロセスを通じて、CHIPS は、ユーザーのプライバシーを保護しながら、関係者にとってより簡単に実装できるようになりました。 + +## 静的から動的への Cookie 制限の移行 + +CHIPS の実装におけるもう 1 つの課題は、静的 Cookie の制限でした。
Cookie のメモリ フットプリントが大きくなるのを防ぐために、最初の設計では、サイトごと、パーティションごとに 10 個の Cookie の数値制限が提案されていました。 + +Akamai は、顧客のコンテンツ(customer.cdn.xyz など)をホストするためのトップレベル ドメインを提供する CDN などのサービスには、提案されているパーティション化された Cookie の制限では不十分である可能性があるという[公開フィードバック](https://github.com/privacycg/CHIPS/issues/48)を提出しました。たとえば、customer1.cdn.xyz と customer2.cdn.xyz の両方はサードパーティコンテンツを配信し、それぞれが独自の Cookie を複数設定できます。このような複数の顧客サイトが別のウェブサイトに埋め込まれている場合、パーティションあたり 10 個の Cookie 数制限に達する可能性があります。 + +Chrome チームは、他のフォーラム、パートナー ミーティング、W3C ディスカッションから同様のフィードバックを受け取ったことから、これらのユースケースで Cookie の制限がもたらす課題を解決する最善の方法を検討しました。 + +
{% Img src="image/vgdbNJBYHma2o62ZqYmcnkq3j0o1/cLVE4czgWDZPY9lz1IcH.png", alt="単一のドメインがクライアントマシン上に持つ SameSite=None Cookie の最大数を示す図", width="800", height="457" %}
単一のドメインがクライアントのマシン上に持つ SameSite=None Cookie の最大数を示す図
+ +コミュニティのフィードバックを取り込む方法を検討した後、Chrome は [TPAC 2022](https://drive.google.com/file/d/1wSUfOb7BIjtmsO6TdxyBMmw3RUQqCtGa/view) で最新のアイデアを発表し、CHIPS が *静的*な 10 個の Cookie 制限からメモリに基づく _動的_ な 10 kb の制限に移行することを提案しました。分析では、この変更によってウェブ上のユースケースの 99% がカバーされるはずであり、主要な用途を維持したまま、Chrome が達成しようとしていたプライバシー原則(サイト間で共有されるユーザーに関する過度の情報を制限する)を支持するだろうということが分かりました。 + +他のブラウザ ベンダーは、PrivacyCG で CHIPS がクロスブラウザ サポートを維持するために重要な、最新のソリューションに同意したと[述べています](https://github.com/privacycg/CHIPS/issues/48#issuecomment-1271611177)。 + +その結果、Chrome は新しい制限を[採用](https://github.com/chromium/chromium/commit/8be338400e94964708796d2be6afe071233c0f6f)し、そのソリューションを CHIPS 設計に組み込むこととなりました。 + +## 業界との連携 + +ウェブ上のプライバシーを改善する取り組みでは、CHIPS の開発を通じて多くのパートナーから意見を聞き、協力し合うことが不可欠です。 + +{% Blockquote 'Martin Meyer, Senior Architect at Akamai Technologies' %} Akamai は、Google などの他の業界リーダーといくつかの面で協力関係を築いています。CHIPS プログラムについて提供したフィードバックは些細なことのように思えるかもしれませんが、この変更は、最終的な目標を達成しながら、優れたユースケースへの悪影響を最小限に抑えるのに大いに役立ちます。各組織が独自の方法でインターネットをより高速かつ安全にするために取り組んでいますが、共に協力することでインターネット全体をさらに良いものに作り上げることが可能です。 {% endBlockquote %} + +CHIPS は、プライバシー サンドボックスのテクノロジーを改善するには、エコシステムからのフィードバックが不可欠であることを示しました。GitHub でのオープンなウェブに関する対話、W3C ミーティング、および Chrome チームとの継続的なエンゲージメントが、現在 Chrome 安定版で展開されている変更に直接貢献しました。Chrome チームでは、さまざまな提案についてもこのようなフィードバックをお待ちしております。このフィードバックは、テクノロジーの開発方法とウェブ上での展開方法に大きく貢献します。 diff --git a/site/ja/docs/privacy-sandbox/maximize-ad-relevance/index.md b/site/ja/docs/privacy-sandbox/maximize-ad-relevance/index.md new file mode 100644 index 000000000..dc58f2f77 --- /dev/null +++ b/site/ja/docs/privacy-sandbox/maximize-ad-relevance/index.md @@ -0,0 +1,151 @@ +--- +layout: layouts/doc-post.njk +title: サードパーティ Cookie 後の広告の関連性を最大化する +subhead: 広告エコシステムの未来を詳しく見てみましょう +description: 広告エコシステムの未来を詳しく見てみましょう。 +date: 2022-12-13 +authors: + - joeytrotz +--- + +プライバシー サンドボックスは、公開されている無料のインターネット上での人々のアクティビティを非公開に保つことを目的としています。これを実現するために、Google は広告業界と協力して新しいプライベート広告技術に移行し、[2024 年後半](https://privacysandbox.com/open-web/#the-privacy-sandbox-timeline)には Chrome におけるサードパーティ Cookie のサポートを廃止できるように作業を進めています。 + +プロダクトリーダー、CTO、CMO、CEO など、その役割に関係なく、プライバシー意識が高まる世の中で広告のユースケースをサポートする方法を理解し、ビジネスの成果とユーザーのプライバシーの両方を最適化できるソリューションを採用することが不可欠です。 + +2023 年がサードパーティ Cookie のない世界に備えるための重要な年になることは間違いありません。このガイドでは、Cookie のない未来において、広告エコシステムが広告の関連性にどのようにアプローチできるかについて説明します。 + +- 関連する広告を表示するために使用されるデータについて、どのような変更がありますか? +- アドテックが、サードパーティ Cookie を使わずにインタレストベース広告を提供するにはどうすればよいでしょうか? +- 機械学習で、プライバシーに安全なシグナルを使用してパフォーマンスを最大化するにはどうすればよいでしょうか? + +## 関連する広告を表示するために使用されるデータについて、どのような変更がありますか? + +パーソナライズド広告とも呼ばれるインタレスト ベース広告は、個人の興味や好みに関する情報を使用して、より関連性の高い広告を表示する広告の一種です。このタイプの広告では、ユーザーが閲覧したコンテンツ、ユーザーが最近閲覧したサイトのパターン、以前にアクセスした特定のサイトなど、表示する広告を決定するためのシグナルとして幅広いデータを使用します。 + +現在、これらのシグナルは主に、個々のデバイスに固有のサードパーティ Cookie などのクロスサイト識別子によって強化されています。 + +サードパーティ Cookie が段階的に廃止されるにつれて、インタレストベース広告向けのアドテックソリューションは、プライバシーに配慮したシグナルを利用して関連性の高い広告を表示するように進化する必要があります。これらには、ファーストパーティ データ、コンテキスト シグナル、プラットフォーム提供のプライバシー保護 API([Topics API](/docs/privacy-sandbox/topics/overview/)、[FLEDGE API](/docs/privacy-sandbox/fledge/)、[Attribution Reporting API](/docs/privacy-sandbox/attribution-reporting/) など)が含まれており、これらはクロスサイト トラッキングから保護しながら、広告業界の重要なユース ケースをサポートするのに役立ちます。 + +インタレストベース広告は、エコシステム全体で開発された革新的なテクノロジーによって生かされ、繁栄することができます。これらのテクノロジーは、人々のデータがより適切に保護される世界に向けて前進するのに役立ちます、一方で広告は、ダイナミックでオープンなウェブをサポートするマーケティングの成果を引き続き推進できます。 + +## アドテックが、サードパーティ Cookie を使わずにインタレストベース広告を提供するにはどうすればよいでしょうか? + +現在、インタレストベース広告の広告主は通常、アドテックプロバイダを通じてキャンペーンに以下の設定を行っています。 + +1. **目標**: 広告主がこの広告キャンペーンで達成しようとしているビジネス上の成果は何ですか?これにより、広告プラットフォームは何を最適化すべきかがわかります。たとえば、子供服のウェブサイトで売り上げを伸ばしたいと考えている広告主がいるとします。多くの場合、これらの目標は、クロスサイトコンバージョンタグとアトリビューション レポートによって測定されます。 +2. **オーディエンス**: 広告主は誰にリーチしようと考えていますか?これにより、広告主がその広告に適していると考えているのが誰であるかが広告プラットフォームに伝えられます。たとえば、広告主は、現在子供服を購入している新規顧客にリーチしたいと考えているかもしれません。 +3. **プレースメント**: 広告主が広告を掲載したいウェブサイトは?これは、広告枠または広告枠のカテゴリに関して、広告の掲載が許可される場所を指定します。たとえば、広告主は幅広いウェブサイトに広告を掲載したり、目的のオーディエンスにリーチする可能性が高い特定のウェブサイトを選択したりできます。 +4. **予算と入札単価**: 広告主は、インプレッションの配信、広告のクリック、広告のコンバージョンなどの特定のアクションに対して、合計でどれくらい支払おうと考えていますか?これにより、キャンペーンが目標のコスト要件を満たしていることを保証できます。たとえば、広告主は最大 1,000 ドルを支出し、最大 2 ドルの CPM を支払って、ターゲットオーディエンスと特定のウェブサイトに 500,000 インプレッションを配信することを希望するかもしれません。 + +### オーディエンス作成の進化 + +ポストサードパーティ Cookie の世界では、アドテックプロバイダーは、自社のプラットフォームが関連性の高い広告を配信する方法を適応させたいと考えるでしょう。今日、広告の関連性は一般的に、広告主が自社の製品やサービスに関心を持つ可能性が最も高い人々にリーチするために使用できるオーディエンスを通じて達成されています。 + +広告主は通常、次のようなさまざまなオーディエンス タイプを使用しています。 + +1. [**アフィニティ**](#affinity): 習慣や関心事など、ユーザーが情熱を注いでいることに基づいてユーザーにリーチします。 +2. [**購買意向**](#in-market): 最近の購入意向に基づいてユーザーにリーチします。 +3. [**リマーケティング**](#remarketing): 以前に広告主のウェブサイトにアクセスしたことのあるユーザーにリーチします。 +4. [**オーディエンス拡張**](#audience-extension): 他のウェブサイトにおける特定のサイト運営者のユーザーにリーチします。 + +サードパーティ Cookie の廃止後も、アドテックプロバイダーは、プライバシー サンドボックス API などの新しいアプローチを使用して、これらのオーディエンス タイプの目標を引き続きサポートできます。 + +#### アフィニティ + +今日、広告主は、アフィニティ(インタレストとも呼ばれます)によって分類されたユーザーにリーチしています。最も一般的な方法は、サードパーティのデータ セグメントを活用することです。これらのオーディエンスは、多くのデータ マーケットプレイスによって提供されており、デマンドサイドプラットフォーム([DSP](/docs/privacy-sandbox/glossary/#dsp))やデータ管理プラットフォーム([DMP](/docs/privacy-sandbox/glossary/#dmp))などのチャンネルを通じてアドテックエコシステム全体に配布され、アクティベーションされます。 + +セグメントは通常、サード パーティ Cookie を使用して個人をトラッキングし、カテゴリの分類法と、ユーザーがカテゴリに該当するかどうかを判断するための独自の方法論に基づいてユーザーをグループ化することによって構築されます。 + +サードパーティ Cookie が廃止された後、アフィニティに基づくオーディエンスの選択は、さまざまなシグナルを使って特定のオーディエンスに含めるユーザーの適性を測るように進化します。プライバシー サンドボックスのプライバシー保護 API を使用してこれを行うには、次のようないくつかの方法があります。 + +- **Topics API** : この API では、標準化されたインタレスト分類法と、特定のユーザーの関心を最近アクセスしたウェブサイトの種類に基づいてオンデバイスで分類する一般的な方法論を使用します。アドテックは、Topics API を呼び出して、特定のユーザーの関心を取得できます。この API は、考慮されるブラウジング履歴の長さ、特定のトピックにアクセスできる関係者、返されるカテゴリの数などを制限することでプライバシーを保護します。この API は、サイト運営者との直接的な関係やコンテキスト最適化機能を持たないアドテックに特に有効です。 +- **コンテキスト データを使用した Topics API** : より高度な方法では、ユーザーのトピックとページのコンテキストを比較して、ユーザーの追加のアフィニティを推定します。たとえば、アドテックソリューションは、特定の一連のトピック(アウトドア活動など)に関心のあるユーザーが、特定のカテゴリのページ(グリルに関するサイトなど)にアクセスする際に過剰にインデックスを作成する可能性があることを知ることができます。アドテックは、「BBQ & グリル」がトピックとして返されなくても、「アウトドア活動」ウェブサイトの訪問者がグリルに興味がある可能性があると予測できるように、機械学習モデルをトレーニングすることができます。この方法は、コンテキスト最適化機能を備えている場合、バイサイドの広告技術に特に役立ちます。 +- **FLEDGE API** : この API を使用すると、アドテックは、ウェブページの訪問者を特定のセグメントのメンバーとしてラベル付けすることで、「家族旅行に興味がある」などのオーディエンス セグメントを作成できます。アドテックプロバイダーのパートナ ネットワークに「家族旅行」に関連する他のウェブサイトがある場合、それらのサイトの訪問者をこの同じセグメントに追加することもできます。 + +FLEDGE は、オーディエンス セグメントへの割り当てをオンデバイスで維持し、同じユーザーが複数のインタレストグループに属しているかどうかをアドテックに共有しないことで、ユーザーのプライバシーを保護します。これにより、クロスサイト トラッキングが制限されます。この API は、サイト パートナーシップのネットワークを持つアドテックにとって特に有用です。 + +これらの方法により、アドテックは、クロスサイトユーザー識別子に依存することなく、拡張されたアフィニティ オーディエンス セグメントを提供できます。アドテックは 1 つの方法に限定する必要はなく、サイト運営者との関係、広告主との関係、および機械学習機能に基づいて差別化することができます。 + +#### 購買意向 + +現在、広告主は、「アフィニティ」に基づいてオーディエンスにアクセスする方法と同様に、サードパーティ Cookie セグメントを使用して、「購買意向」がある(「購買意欲」があるとも呼ばれる)として分類されたユーザーにリーチしています。ユーザーが「調理器具」のような製品の購買意向で分類されるか、単に料理に興味があるで分類されるかどうかは、アドテックプロバイダーの独自の分類法と方法論に依存します。 + +サードパーティ Cookie の廃止後、プライバシーを保護する API は、「購買意向」のオーディエンスの作成を知らせる新しいシグナルを提供します。いくつかの代替方法は次のとおりです。 + +- **Topics API** : この API をアフィニティ オーディエンスに使用するのと同様に、これを購買意向に使用するには、オンデバイスで一般に知られている方法論と分類法に基づいて、特定のユーザーの購入意向を近似できるトピックを返す必要があります。 + +これらのトピックを生成するために使用されるルックバックウィンドウは、アドテックプロバイダーが利用できるデータの総量を制限することで、ユーザーのプライバシーを保護できるように3週間に標準化されています。ただし、商品やサービスのカテゴリが異なれば検討サイクルも数日から数か月に及ぶため、この API は、顧客の購入サイクルがトピックのルックバック ウィンドウと一致している広告主にとって便利です。 + +- **FLEDGE API** : アフィニティのユース ケースと同様に、この API を使用すると、アドテックプラットフォームは「購入意向のある自動車購入者」などの独自のセグメントを作成できます。アドテックプロバイダーのパートナーネットワークに、「購入意向のある自動車購入者」に関連する他のウェブサイトがある場合、クロスサイトユーザーのプライバシーを維持しながら、それらのサイトの訪問者をこの同じセグメントに追加することもできます。 FLEDGE は、アドテックプロバイダーに、データパートナーシップを可能にする直接的なサイト運営者/広告主の関係があり、トピックが許可する以上のカスタマイズが必要な場合に特に役立ちます。 +- **Topics API + Attribution Reporting API**: Topics と Attribution Reporting API を組み合わせることで、特定のコンバージョン(購入など)に対応するトピックのリストを拡張できます。これにより、購買意向のあるオーディエンスにリーチするための追加の方法が作成されます。 + +たとえば、分析または機械学習システムにより、スキューバ ダイビング用品の広告を見て購入したユーザーは、「ビーチと島」や「釣り」のトピックを関連付けられていることが非常に多いことがわかります。アドテックソリューションは、この 2 つのトピックを持つユーザーを選択することで、この洞察を「スキューバ用品の購入意向がある」ユーザーへのリーチの改善に変換できます。この場合、アトリビューション レポートは、トピックとコンバージョンの関連付けに関するノイズの多いコンバージョン データを提供することで、ユーザーのプライバシーを保護します。 + +このアプローチは、アドテックプロバイダーがコンテキストデータをあまり持っていないが、機械学習または堅牢なデータ サイエンスと分析機能を備えている場合に意味があります。 + +- **コンテキスト データを使用した Attribution Reporting API**: アドテックソリューションは、広告が表示されるページのコンテキスト分類、広告主と製品の分類、およびアトリビューション レポートからのデータを活用して、購入意向のある人々が特定の種類の製品やサービスを購入する場合に好むサイトの種類の傾向やパターンを明らかにします。このデータの組み合わせから、たとえば「家族レジャーに関するウェブページを閲覧している人は、アウトドア用品も購入する可能性が高い」ということを学習するなどのインサイトにつながる可能性があります。 + +これらの方法は、アドテックプロバイダーがクロスサイトユーザー識別子に依存することなく、創造性を活かしてオーディエンス セグメントを拡張およびカスタマイズできる多くの方法のほんの一部です。また、ファースト パーティ データやその他のプライバシー保護 API の組み合わせなど、より多くのシグナルを統合すれば、さらに優れた結果を得ることができます。したがって、アドテックプロバイダーは、オーディエンスの構築、独自のデータの保護、優れた機械学習機能の開発にさまざまなアプローチを採用することで、差別化を図ることができます。 + +#### リマーケティング + +広告主は、リマーケティングを通じて、以前にウェブサイトにアクセスしたことのあるユーザーに再度アプローチできます。現在、これには、ウェブサイトの訪問時にブラウザにサードパーティ Cookie を配置し、別のウェブサイトでその Cookie が観察されたときにそのブラウザに広告を表示するように入札するアプローチが含まれます。アドテックプロバイダーは、ウェブサイト全体で行われたユーザー アクティビティに基づいて、特定のウェブサイト用にさまざまなリマーケティング セグメントを作成できます。 + +サードパーティ Cookie がなければ、アドテックプロバイダーは FLEDGE API を使用してリマーケティングのユースケースをサポートできます。 + +- **FLEDGE API** : アドテックプロバイダーは、ユーザーの活動に応じてインタレストグループを作成することにより、サイト用にカスタマイズされたリマーケティング セグメントを作成できます。FLEDGE の以前のユースケースでは、アドテックプロバイダーは複数のウェブサイトから非常に多くのオーディエンスを構築していました。このユース ケースでは、1 つのウェブサイトのみが過去の訪問者にもう一度エンゲージしようとしており、FLEDGE に組み込まれたプライバシー保護がなければ、このユースケースではウェブサイトによる個人の特定に導かれる可能性があります。この API は、効果的なオーディエンス リマーケティングを可能にしながら、十分な数の個人が広告を見る資格があることを保証するために [k-匿名性](/docs/privacy-sandbox/glossary/#k-anonymity)のしきい値を設定して、個人のプライバシーを保護します。 + +サードパーティ Cookie がなくても、プライバシー サンドボックスを使用すると、広告主はファーストパーティのデータを使用して、サードパーティのウェブサイト全体で大規模なリマーケティングを行うことができます。 + +#### オーディエンス拡張 + +広告主は、特定のサイト運営者で見られる同じオーディエンスにより多くリーチしたい場合があります。ただし、それらのユーザーが他のウェブサイトにいる場合です。オーディエンス拡張は、サイト運営者の自社オーディエンスを他のサイトで見つけて拡張し、同じオーディエンスの頻度やリーチを増やすプロセスです。 + +オーディエンス拡張を使用することで、サイト運営者は、アフィニティ(ゴルファーなど)や人口統計(年齢層など)などのオーディエンス セグメントを広告主に提供し、広告主が他のサイトでそのオーディエンスを見つけられるようにすることができます。オーディエンス拡張は、小売業者のウェブサイトやウェブ上の他の場所で買い物をしている消費者にリーチして、広告主が商品の認知度を高めたい場合にも使用されます。 + +アドテックプロバイダーは、FLEDGE API を使用して、サードパーティ Cookie を使わずにサイト運営者のオーディエンスを拡張できます。 + +- **FLEDGE API**: アドテックプロバイダーは、ウェブサイトの特定のセクション(旅行セクションなど)を読むなどのユーザー アクティビティに応じてインタレストグループを作成することにより、サイトのカスタム オーディエンス拡張セグメントを作成できます。このプロセスはリマーケティングと事実上似ており、同じプライバシー保護を提供します。これは、サイト運営者の 1P オーディエンス データを重視していても、そのサイト運営者のウェブサイトでそのオーディエンスに十分な広告枠を取得できない広告主にとっては合理的と言えます。 + +## 機械学習で、プライバシーに安全なシグナルを使用してパフォーマンスを最大化するにはどうすればよいでしょうか? + +サードパーティ Cookie の廃止に伴い、広告主は、機械学習とプライバシーに安全なシグナルを使用して最良の結果を得る方法を検討する必要がある場合があります。 + +### 自動化によって広告主の成果を促進 + +ほとんどのアドテックプロバイダーは、多様な節度で手動および自動のキャンペーン最適化を提供しています。 + +ほとんどの手動ソリューションでは、広告主が目的のオーディエンス、プレースメント、および入札を指定し、それらの入力内にとどまる必要があります。手動設定は広告主に強力な制御を提供しますが、広告主がパフォーマンスの高いすべてのオーディエンスとプレースメントを知る必要がある場合、または関連するすべての変数を考慮して、各インプレッションの理論上の最適入札を予測できない場合は、最適ではない結果をもたらす可能性があります。 + +ほとんどの自動化されたソリューションでは、広告主に希望するビジネス成果(アクションあたりのコスト 2 ドルなど)を指定するよう求め、機械学習を使用して、その広告主にとって効果的なオーディエンスとプレースメント、および目的の目標を達成するための適切な入札を特定します。この設定では、予算と目標を除いて、アドテックソリューションに対する制約はほとんどまたはまったくありません。広告主によるオーディエンスの選択は、「提案」または「出発点」として扱われる場合がありますが、機械学習は、利用可能なすべてのデータの中から、人間には識別できない可能性のあるパターンを探します。 + +機械学習はこれらのパターンを使用して、より関連性の高いオーディエンスを追加し、それらのオーディエンスの予測パフォーマンスに基づいて入札単価を調整することで、パフォーマンスを最適化します。プライバシー サンドボックスは、サードパーティ Cookie の廃止後に機械学習に通知するために利用できるシグナルの多くのソースの 1 つです。 + +機械学習は、時間、キャンペーン、さらには広告主全体にわたって、すべての最適なオーディエンス、プレースメント、および入札を継続的にテストして学習することにより、広告のパフォーマンスを最大化できます。熟練したチームが実行する高度な分析でも、同様の相関関係を発見できることは注目すべきことでしょう。 + +広告主がオーディエンス、プレースメント、入札を管理する必要性を減らすことで、広告主のワークロードは簡素化され、機械学習システムにより可能な限り最高の結果をもたらすことができます。自動化されたソリューションへのアドテックへの投資は、広告主に利益をもたらすだけでなく、サードパーティ Cookie からの移行にも役立ちます。 + +### 機械学習用の追加シグナル + +アドテックプロバイダーは、広告を配信するために入札するかどうかを決定する際に、常に複数のシグナルを考慮してきました。クロスサイト Cookie トラッキングのない世界では、アドテックは、クリックやコンバージョンなどのビジネス成果を予測するために、機械学習で利用可能なすべてのプライバシー保護シグナルを使用して利益を得ることができます。 + +以下のプライバシー保護シグナルは過小評価されることがありますが、サードパーティ Cookie がなければ、将来的に広告の関連性に大きく貢献する可能性があります。 + +1. **広告クリエイティブの特徴**: コンポーネント レベル(テキスト、画像、デザインなど)で広告クリエイティブを分析すると、広告の主題やテキストが多く含まれているかどうかなど、特定のオーディエンスや特定のページでのパフォーマンスを予測するのに役立ちます。 +2. **ファーストパーティデータ**: サイト運営者、マーケティング担当者、小売ネットワークは、[販売者定義のオーディエンス](https://iabtechlab.com/sda)など、ファーストパーティの識別子とセグメントをますます構築しています。特定のサイトでの時間の経過に伴うユーザーの行動を知ることで、クロスサイト プロファイリングを行わなくても、そのサイトのそのユーザーまたはセグメントにとってどの広告が最も効果的かをより正確に予測できます。サイト運営者のファーストパーティデータは、すべてのサイトでの入札を改善するのに役立ちます。これらのサイト固有の入札単価の改善により、キャンペーン全体のパフォーマンスが累積的に向上します。 + +アドテックプロバイダーは、機械学習やプライバシー保護 API から得るプライバシー保護シグナルといった利用可能なすべてのツールを、コンテキスト データ、クリエイティブ データ、ファースト パーティ データと組み合わせることで、最高の結果を引き出すことができます。 + +## まとめ + +サードパーティ Cookie が段階的に廃止された後も、広告業界が関連性の高い広告を配信し続け、消費者が期待するプライバシー保護を提供できることが不可欠です。プライバシー サンドボックスのような新しいツールを使用して構築するには労力が伴うことを認識しており、この移行を通じて業界を引き続きサポートしていきます。 + +今後は、次のことをお勧めします。 + +1. Topics、FLEDGE、Attribution Reporting などのプライバシー保護 API をアドテックソリューションに統合することに投資して、サードパーティ Cookie が廃止された後の一般的なインタレストベース広告のユースケースをサポートできるようにする。 +2. プライバシー サンドボックス API を、ファースト パーティのサイト運営者データを含む他のプライバシー保護シグナルと組み合わせてテストし、将来のパフォーマンスを理解し、戦略に情報を提供する。 +3. 利用可能なすべてのプライバシー保護されたデータを機械学習に使用できるようにすることで、可能な限り自由に学習および最適化できるようにし、パフォーマンスを最大化する。 + +アドテック業界は、プライバシー サンドボックス API を使用して、ターゲティングや入札に関する多数の主な関数を実行できます。ただし、これらの API を超えて追加のプライバシー保護シグナルを組み込み、これらすべてのシグナルを一緒に展開すると、多くのメリットがもたらされます。 + +イノベーションは、デジタル広告業界の DNA に刻まれています。広告の関連性に対する既存のアプローチを進化させることで、サードパーティ Cookie から、よりプライベートでパフォーマンスの高いウェブへの移行を成功させられるでしょう。 From f4c9083f7da2a64670460c3c580167339687dac3 Mon Sep 17 00:00:00 2001 From: Adam Zielinski Date: Thu, 13 Apr 2023 17:11:22 +0200 Subject: [PATCH 025/982] [WordPress Playground] Update Pendant theme link to WordPress.org instead of WordPress.com (#5994) The Pendant theme exists in the open-source theme directory on WordPress.org and I've accidentally linked to the directory on WordPress.com. Let's update it to link to the .org site. --- site/en/blog/wordpress-playground/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/en/blog/wordpress-playground/index.md b/site/en/blog/wordpress-playground/index.md index 9aef49f85..d183fe389 100644 --- a/site/en/blog/wordpress-playground/index.md +++ b/site/en/blog/wordpress-playground/index.md @@ -47,7 +47,7 @@ WordPress Playground in an `", - "textAlign": "left", - "verticalAlign": "top", - "containerId": null, - "originalText": "", - "lineHeight": 1.25, - "baseline": 25 - }, - { - "type": "text", - "version": 695, - "versionNonce": 499914982, - "isDeleted": false, - "id": "m0ppO4zGoGdiczac1rtjq", - "fillStyle": "cross-hatch", - "strokeWidth": 1, - "strokeStyle": "solid", - "roughness": 1, - "opacity": 100, - "angle": 0, - "x": 17.467816065974034, - "y": 273.5009969810908, - "strokeColor": "#000000", - "backgroundColor": "#ced4da", - "width": 357.50384521484375, - "height": 35, - "seed": 1959136058, - "groupIds": [], - "roundness": null, - "boundElements": null, - "updated": 1681287917967, - "link": null, - "locked": false, - "fontSize": 28, - "fontFamily": 1, - "text": "an iframe with WordPress:", - "textAlign": "left", - "verticalAlign": "top", - "containerId": null, - "originalText": "an iframe with WordPress:", - "lineHeight": 1.25, - "baseline": 25 - }, - { - "type": "text", - "version": 198, - "versionNonce": 122343546, - "isDeleted": false, - "id": "GzXz-vZtJsuUmmXzNUc2B", - "fillStyle": "cross-hatch", - "strokeWidth": 1, - "strokeStyle": "solid", - "roughness": 1, - "opacity": 100, - "angle": 0, - "x": -404.0436057499726, - "y": 662.2340280946055, - "strokeColor": "#000000", - "backgroundColor": "#ced4da", - "width": 262.07989501953125, - "height": 70, - "seed": 719248742, - "groupIds": [], - "roundness": null, - "boundElements": [ - { - "id": "dVwaYw4OEATmX9w22A8E4", - "type": "arrow" - }, - { - "id": "u88zs7UXQNiVdfedzmuvQ", - "type": "arrow" - } - ], - "updated": 1681287917967, - "link": null, - "locked": false, - "fontSize": 28, - "fontFamily": 1, - "text": "Intercepted by the\nService Worker", - "textAlign": "center", - "verticalAlign": "top", - "containerId": null, - "originalText": "Intercepted by the\nService Worker", - "lineHeight": 1.25, - "baseline": 60 - }, - { - "type": "text", - "version": 363, - "versionNonce": 555456358, - "isDeleted": false, - "id": "e1rZuE8EC0qU3HJKGwFC4", - "fillStyle": "cross-hatch", - "strokeWidth": 1, - "strokeStyle": "solid", - "roughness": 1, - "opacity": 100, - "angle": 0, - "x": 109.64005416996633, - "y": 664.3904780686189, - "strokeColor": "#000000", - "backgroundColor": "#ced4da", - "width": 214.087890625, - "height": 70, - "seed": 487887866, - "groupIds": [], - "roundness": null, - "boundElements": [ - { - "id": "u88zs7UXQNiVdfedzmuvQ", - "type": "arrow" - }, - { - "id": "RqLRve-fQJe02Z7bCFKhs", - "type": "arrow" - } - ], - "updated": 1681287917967, - "link": null, - "locked": false, - "fontSize": 28, - "fontFamily": 1, - "text": "Rendered in the\nWorker Thread", - "textAlign": "center", - "verticalAlign": "top", - "containerId": null, - "originalText": "Rendered in the\nWorker Thread", - "lineHeight": 1.25, - "baseline": 60 - }, - { - "type": "text", - "version": 467, - "versionNonce": 1797991098, - "isDeleted": false, - "id": "RXyNgJQivCeHf5z55VRw0", - "fillStyle": "cross-hatch", - "strokeWidth": 1, - "strokeStyle": "solid", - "roughness": 1, - "opacity": 100, - "angle": 0, - "x": 548.0246754449877, - "y": 664.8082676755239, - "strokeColor": "#000000", - "backgroundColor": "#ced4da", - "width": 265.9998779296875, - "height": 70, - "seed": 1529495718, - "groupIds": [], - "roundness": null, - "boundElements": null, - "updated": 1681287917967, - "link": null, - "locked": false, - "fontSize": 28, - "fontFamily": 1, - "text": "...by the in-browser\nWordPress instance", - "textAlign": "center", - "verticalAlign": "top", - "containerId": null, - "originalText": "...by the in-browser\nWordPress instance", - "lineHeight": 1.25, - "baseline": 60 - }, - { - "type": "arrow", - "version": 548, - "versionNonce": 182235110, - "isDeleted": false, - "id": "dVwaYw4OEATmX9w22A8E4", - "fillStyle": "cross-hatch", - "strokeWidth": 1, - "strokeStyle": "solid", - "roughness": 2, - "opacity": 100, - "angle": 0, - "x": -45.38852413632435, - "y": 444.67800712473127, - "strokeColor": "#495057", - "backgroundColor": "#ced4da", - "width": 209.31589275623764, - "height": 207.43113956150046, - "seed": 1947468986, - "groupIds": [], - "roundness": { - "type": 2 - }, - "boundElements": null, - "updated": 1681287918018, - "link": null, - "locked": false, - "startBinding": null, - "endBinding": { - "elementId": "GzXz-vZtJsuUmmXzNUc2B", - "focus": -0.09592636486162824, - "gap": 10.124881408373767 - }, - "lastCommittedPoint": null, - "startArrowhead": null, - "endArrowhead": "arrow", - "points": [ - [ - 0, - 0 - ], - [ - -119.25106087755307, - 85.57014355804313 - ], - [ - -209.31589275623764, - 207.43113956150046 - ] - ] - }, - { - "type": "text", - "version": 355, - "versionNonce": 1487520634, - "isDeleted": false, - "id": "RpIX1p85aBUMYhuE7YkVM", - "fillStyle": "cross-hatch", - "strokeWidth": 1, - "strokeStyle": "solid", - "roughness": 2, - "opacity": 70, - "angle": 0, - "x": -166.55596604964944, - "y": 534.7545262005287, - "strokeColor": "#495057", - "backgroundColor": "#ced4da", - "width": 243.17991638183594, - "height": 70, - "seed": 178732006, - "groupIds": [], - "roundness": null, - "boundElements": null, - "updated": 1681287917967, - "link": null, - "locked": false, - "fontSize": 28, - "fontFamily": 1, - "text": "HTTP request to\n/wp-admin", - "textAlign": "left", - "verticalAlign": "top", - "containerId": null, - "originalText": "HTTP request to\n/wp-admin", - "lineHeight": 1.25, - "baseline": 60 - }, - { - "type": "arrow", - "version": 249, - "versionNonce": 1355399974, - "isDeleted": false, - "id": "u88zs7UXQNiVdfedzmuvQ", - "fillStyle": "cross-hatch", - "strokeWidth": 1, - "strokeStyle": "solid", - "roughness": 2, - "opacity": 100, - "angle": 0, - "x": -131.99745436348212, - "y": 691.8877300400327, - "strokeColor": "#495057", - "backgroundColor": "#ced4da", - "width": 236.7285738368414, - "height": 34.009861092194114, - "seed": 1130847610, - "groupIds": [], - "roundness": { - "type": 2 - }, - "boundElements": null, - "updated": 1681287918018, - "link": null, - "locked": false, - "startBinding": { - "elementId": "GzXz-vZtJsuUmmXzNUc2B", - "focus": 0.4635717927264672, - "gap": 9.966256366959215 - }, - "endBinding": { - "elementId": "e1rZuE8EC0qU3HJKGwFC4", - "focus": -0.41366093049067265, - "gap": 4.908934696607048 - }, - "lastCommittedPoint": null, - "startArrowhead": null, - "endArrowhead": "arrow", - "points": [ - [ - 0, - 0 - ], - [ - 115.2457931407489, - -30.974453294389605 - ], - [ - 236.7285738368414, - 3.0354077978045098 - ] - ] - }, - { - "type": "arrow", - "version": 338, - "versionNonce": 1275324986, - "isDeleted": false, - "id": "RqLRve-fQJe02Z7bCFKhs", - "fillStyle": "cross-hatch", - "strokeWidth": 1, - "strokeStyle": "solid", - "roughness": 2, - "opacity": 100, - "angle": 0, - "x": 330.43695331452227, - "y": 700.1128810834052, - "strokeColor": "#495057", - "backgroundColor": "#ced4da", - "width": 199.90870669883225, - "height": 25.224903487598567, - "seed": 258133798, - "groupIds": [], - "roundness": { - "type": 2 - }, - "boundElements": null, - "updated": 1681287918018, - "link": null, - "locked": false, - "startBinding": { - "elementId": "e1rZuE8EC0qU3HJKGwFC4", - "focus": 0.4621267913457183, - "gap": 6.709008519555937 - }, - "endBinding": null, - "lastCommittedPoint": null, - "startArrowhead": null, - "endArrowhead": "arrow", - "points": [ - [ - 0, - 0 - ], - [ - 104.94313163725019, - -25.224903487598567 - ], - [ - 199.90870669883225, - -3.5719049540989545 - ] - ] - }, - { - "type": "rectangle", - "version": 1566, - "versionNonce": 316257382, - "isDeleted": false, - "id": "dv4xyRjxB1P6fa8bUHQ23", - "fillStyle": "hachure", - "strokeWidth": 1, - "strokeStyle": "solid", - "roughness": 1, - "opacity": 100, - "angle": 0, - "x": 541.1914589846546, - "y": 847.5025500485262, - "strokeColor": "#ced4da", - "backgroundColor": "#ced4da", - "width": 281.0156618629228, - "height": 276.4817952203143, - "seed": 676437562, - "groupIds": [], - "roundness": null, - "boundElements": null, - "updated": 1681287917967, - "link": null, - "locked": false - }, - { - "type": "rectangle", - "version": 2669, - "versionNonce": 1746316538, - "isDeleted": false, - "id": "p3axPnqea6VunXFCHruYj", - "fillStyle": "solid", - "strokeWidth": 1, - "strokeStyle": "solid", - "roughness": 1, - "opacity": 100, - "angle": 0, - "x": 569.708555152364, - "y": 994.3258003612555, - "strokeColor": "#000000", - "backgroundColor": "#fff", - "width": 229, - "height": 46, - "seed": 1976171110, - "groupIds": [], - "roundness": null, - "boundElements": [ - { - "id": "GMTZNJkY3Hh74TPQl-_GP", - "type": "arrow" - }, - { - "type": "text", - "id": "6eIQUy6wZzdE9SazhSqHh" - } - ], - "updated": 1681287917967, - "link": null, - "locked": false - }, - { - "type": "text", - "version": 2786, - "versionNonce": 1269970854, - "isDeleted": false, - "id": "6eIQUy6wZzdE9SazhSqHh", - "fillStyle": "hachure", - "strokeWidth": 1, - "strokeStyle": "solid", - "roughness": 1, - "opacity": 100, - "angle": 0, - "x": 608.3986338877156, - "y": 1004.8258003612555, - "strokeColor": "#000000", - "backgroundColor": "#fff", - "width": 151.61984252929688, - "height": 25, - "seed": 532006650, - "groupIds": [], - "roundness": null, - "boundElements": null, - "updated": 1681287917967, - "link": null, - "locked": false, - "fontSize": 20, - "fontFamily": 1, - "text": "WordPress files", - "textAlign": "center", - "verticalAlign": "middle", - "containerId": "p3axPnqea6VunXFCHruYj", - "originalText": "WordPress files", - "lineHeight": 1.25, - "baseline": 18 - }, - { - "type": "rectangle", - "version": 2747, - "versionNonce": 694877626, - "isDeleted": false, - "id": "ntye4r4LvjeVgMSB7rOA6", - "fillStyle": "solid", - "strokeWidth": 1, - "strokeStyle": "solid", - "roughness": 1, - "opacity": 100, - "angle": 0, - "x": 570.3362464789983, - "y": 1052.3295728787334, - "strokeColor": "#000000", - "backgroundColor": "#fff", - "width": 229, - "height": 46, - "seed": 883539366, - "groupIds": [], - "roundness": null, - "boundElements": [ - { - "id": "GMTZNJkY3Hh74TPQl-_GP", - "type": "arrow" - }, - { - "type": "text", - "id": "C0z70xHWicBus8vOAUg3s" - } - ], - "updated": 1681287917967, - "link": null, - "locked": false - }, - { - "type": "text", - "version": 2869, - "versionNonce": 890786534, - "isDeleted": false, - "id": "C0z70xHWicBus8vOAUg3s", - "fillStyle": "hachure", - "strokeWidth": 1, - "strokeStyle": "solid", - "roughness": 1, - "opacity": 100, - "angle": 0, - "x": 652.4062766914006, - "y": 1062.8295728787334, - "strokeColor": "#000000", - "backgroundColor": "#fff", - "width": 64.85993957519531, - "height": 25, - "seed": 303486906, - "groupIds": [], - "roundness": null, - "boundElements": null, - "updated": 1681287917967, - "link": null, - "locked": false, - "fontSize": 20, - "fontFamily": 1, - "text": "SQLite", - "textAlign": "center", - "verticalAlign": "middle", - "containerId": "ntye4r4LvjeVgMSB7rOA6", - "originalText": "SQLite", - "lineHeight": 1.25, - "baseline": 18 - }, - { - "type": "rectangle", - "version": 2409, - "versionNonce": 91698810, - "isDeleted": false, - "id": "1n7kxdDmcbTC6y3_l9u0n", - "fillStyle": "solid", - "strokeWidth": 1, - "strokeStyle": "solid", - "roughness": 1, - "opacity": 100, - "angle": 0, - "x": 566.6396534631461, - "y": 943.224124132169, - "strokeColor": "#000000", - "backgroundColor": "#fff", - "width": 114, - "height": 40, - "seed": 1630476518, - "groupIds": [], - "roundness": null, - "boundElements": [ - { - "id": "GMTZNJkY3Hh74TPQl-_GP", - "type": "arrow" - }, - { - "type": "text", - "id": "nxENEqvhzdHNZ7CaLNEOR" - } - ], - "updated": 1681287917967, - "link": null, - "locked": false - }, - { - "type": "text", - "version": 2525, - "versionNonce": 429458982, - "isDeleted": false, - "id": "nxENEqvhzdHNZ7CaLNEOR", - "fillStyle": "hachure", - "strokeWidth": 1, - "strokeStyle": "solid", - "roughness": 1, - "opacity": 100, - "angle": 0, - "x": 592.3896839807243, - "y": 950.724124132169, - "strokeColor": "#000000", - "backgroundColor": "#fff", - "width": 62.49993896484375, - "height": 25, - "seed": 1603784826, - "groupIds": [], - "roundness": null, - "boundElements": null, - "updated": 1681287917967, - "link": null, - "locked": false, - "fontSize": 20, - "fontFamily": 1, - "text": "/php.js", - "textAlign": "center", - "verticalAlign": "middle", - "containerId": "1n7kxdDmcbTC6y3_l9u0n", - "originalText": "/php.js", - "lineHeight": 1.25, - "baseline": 18 - }, - { - "type": "rectangle", - "version": 2539, - "versionNonce": 754865978, - "isDeleted": false, - "id": "dXFPGgFYsMyH1ZXChIimq", - "fillStyle": "solid", - "strokeWidth": 1, - "strokeStyle": "solid", - "roughness": 1, - "opacity": 100, - "angle": 0, - "x": 685.965203697478, - "y": 942.7841684630775, - "strokeColor": "#000000", - "backgroundColor": "#fff", - "width": 114, - "height": 40, - "seed": 1659309094, - "groupIds": [], - "roundness": null, - "boundElements": [ - { - "id": "GMTZNJkY3Hh74TPQl-_GP", - "type": "arrow" - }, - { - "type": "text", - "id": "o_nTEJCsh_FJ5ltOHBVLa" - } - ], - "updated": 1681287917967, - "link": null, - "locked": false - }, - { - "type": "text", - "version": 2668, - "versionNonce": 1780568422, - "isDeleted": false, - "id": "o_nTEJCsh_FJ5ltOHBVLa", - "fillStyle": "hachure", - "strokeWidth": 1, - "strokeStyle": "solid", - "roughness": 1, - "opacity": 100, - "angle": 0, - "x": 695.905244285857, - "y": 950.2841684630775, - "strokeColor": "#000000", - "backgroundColor": "#fff", - "width": 94.11991882324219, - "height": 25, - "seed": 1811657018, - "groupIds": [], - "roundness": null, - "boundElements": null, - "updated": 1681287917967, - "link": null, - "locked": false, - "fontSize": 20, - "fontFamily": 1, - "text": "/php.wasm", - "textAlign": "center", - "verticalAlign": "middle", - "containerId": "dXFPGgFYsMyH1ZXChIimq", - "originalText": "/php.wasm", - "lineHeight": 1.25, - "baseline": 18 - }, - { - "type": "rectangle", - "version": 2735, - "versionNonce": 1080254458, - "isDeleted": false, - "id": "2tQE7lyNr0cK9YNGrCAil", - "fillStyle": "solid", - "strokeWidth": 1, - "strokeStyle": "solid", - "roughness": 1, - "opacity": 100, - "angle": 0, - "x": 570.9668662938317, - "y": 889.1233257041904, - "strokeColor": "#000000", - "backgroundColor": "#fff", - "width": 229, - "height": 46, - "seed": 666802022, - "groupIds": [], - "roundness": null, - "boundElements": [ - { - "id": "GMTZNJkY3Hh74TPQl-_GP", - "type": "arrow" - }, - { - "id": "DtRTJZeudobPamxju7HQj", - "type": "arrow" - }, - { - "type": "text", - "id": "Y8cFznNxoAT2f0p09ilj2" - } - ], - "updated": 1681287917967, - "link": null, - "locked": false - }, - { - "type": "text", - "version": 2885, - "versionNonce": 1912485030, - "isDeleted": false, - "id": "Y8cFznNxoAT2f0p09ilj2", - "fillStyle": "hachure", - "strokeWidth": 1, - "strokeStyle": "solid", - "roughness": 1, - "opacity": 100, - "angle": 0, - "x": 636.5569084080895, - "y": 899.6233257041904, - "strokeColor": "#000000", - "backgroundColor": "#fff", - "width": 97.81991577148438, - "height": 25, - "seed": 715487738, - "groupIds": [], - "roundness": null, - "boundElements": null, - "updated": 1681287917967, - "link": null, - "locked": false, - "fontSize": 20, - "fontFamily": 1, - "text": "PHP class", - "textAlign": "center", - "verticalAlign": "middle", - "containerId": "2tQE7lyNr0cK9YNGrCAil", - "originalText": "PHP class", - "lineHeight": 1.25, - "baseline": 18 - }, - { - "type": "text", - "version": 936, - "versionNonce": 1537822906, - "isDeleted": false, - "id": "scJD9pCr_BWQ2zr3zvSKZ", - "fillStyle": "hachure", - "strokeWidth": 1, - "strokeStyle": "solid", - "roughness": 1, - "opacity": 100, - "angle": 0, - "x": 628.2107428658089, - "y": 854.7483019705387, - "strokeColor": "#495057", - "backgroundColor": "#ccc", - "width": 104.0399169921875, - "height": 25, - "seed": 1476573862, - "groupIds": [], - "roundness": null, - "boundElements": null, - "updated": 1681287917967, - "link": null, - "locked": false, - "fontSize": 20, - "fontFamily": 1, - "text": "PHP Stack", - "textAlign": "left", - "verticalAlign": "top", - "containerId": null, - "originalText": "PHP Stack", - "lineHeight": 1.25, - "baseline": 18 - } - ], - "appState": { - "gridSize": null, - "viewBackgroundColor": "#ffffff" - }, - "files": {} -} \ No newline at end of file From f408ec82e9ad676af1a123fabafd55a9562a4710 Mon Sep 17 00:00:00 2001 From: Sofia Emelianova <42939855+sofiayem@users.noreply.github.com> Date: Fri, 14 Apr 2023 14:32:41 +0100 Subject: [PATCH 035/982] upd rec ext doc (#6008) --- .../devtools/recorder/extensions/index.md | 56 +++++++++++++++++-- .../docs/devtools/recorder/reference/index.md | 36 +----------- 2 files changed, 53 insertions(+), 39 deletions(-) diff --git a/site/en/docs/devtools/recorder/extensions/index.md b/site/en/docs/devtools/recorder/extensions/index.md index 91032161f..21c3bd1df 100644 --- a/site/en/docs/devtools/recorder/extensions/index.md +++ b/site/en/docs/devtools/recorder/extensions/index.md @@ -1,20 +1,46 @@ --- layout: "layouts/doc-post.njk" -title: "Extensions" +title: "Customize the Recorder with extensions" authors: - sofiayem - jecelynyeen date: 2023-02-22 updated: 2023-02-22 -description: "A list of known Recorder extensions." +description: "Customize and integrate the Recorder by installing extensions." tags: - test - performance --- -This page lists knows Chrome extensions for the DevTools **Recorder**. +You can customize the **Recorder** and integrate it into your workflow by installing third-party extensions that suit the tools you use. -## Export extensions +Check out the [list of known extensions](#extensions-list). + +{% Aside 'important' %} +If you can't find an extension that suits your tools, consider [building your own](#build-extension). +{% endAside %} + +## Install extensions {: #install-extensions } + +To integrate the **Recorder** with your tools, install extensions: + +1. Choose an extension from the [list of known ones](#extensions-list) and click its link. +1. In Chrome Web Store, click **Add extension**. +1. [Open DevTools](/docs/devtools/open/) in a new tab and find new custom options in the **Recorder**. + +{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/1yXSxuF798GRFI5Jmu9W.png", alt="Export and replay extensions.", width="800", height="406" %} + +This screenshot shows custom export and replay options provided by the extensions. + +{% Aside %} +You can get to the [list of known extensions](#extensions-list) from the **Recorder**. Select {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/4dU9UXvsinS4zbgjd8rK.svg", alt="File download.", width="20", height="20" %} **Export** > **Get extensions...** at the top of the **Recorder** panel. +{% endAside %} + +## List of known extensions {: #extensions-list } + +Currently, there are two types of extensions: [Export](/docs/devtools/recorder/extensions/#export-extensions) and [Replay](/docs/devtools/recorder/extensions/#replay-extensions). + +### Export extensions {: #export-extensions } {% Aside %} **Note**: This feature is available from Chrome version 104. @@ -52,7 +78,7 @@ Export extensions let you to customize the code generated by the **Recorder** pa : This extension lets you export user flows from the Recorder directly as [WebPageTest Custom scripts](https://docs.webpagetest.org/scripting/) to measure site's performance. See [Converting user flows to WebPageTest custom scripts](https://blog.webpagetest.org/posts/introducing-the-new-webpagetest-recorder-chrome-extension/) to learn more. -## Replay extensions +### Replay extensions {: #replay-extensions } {% Aside %} **Note**: This feature is available from Chrome version 112. @@ -65,3 +91,23 @@ Replay extensions let you run the recordings produced by **Recorder** using a th {% Aside %} **Note**: Currently, there are no known replay extensions. Check out an [example extension](https://github.com/puppeteer/replay/tree/main/examples/chrome-extension-replay). {% endAside %} + +## Troubleshooting {: #extension-troubleshooting } + +If you don't see export or replay options after installing an extension, check or do the following: + +- The extension only works on web pages. For example, the export option is not available for `chrome://` pages like `chrome://extensions`. +- Always open a new browser tab after installing the extension. + +Known issues: + +- [Issue 1351416](https://crbug.com/1351416) in Chrome 104 and 105 prevents the display of the export option if you open the **Recorder** as the [first DevTools panel](/docs/devtools/open/#last). As a workaround, open another panel first (for example, **Console**), then open the **Recorder**. The issue is fixed in Chrome 106. + +## Build your own extension {: #build-extension } + +To further customize the **Recorder** to your needs, you can build your own extension: + +1. Explore the [chrome.devtools.recorder](/docs/extensions/reference/devtools_recorder/) API. +1. Check out [example extensions](https://github.com/puppeteer/replay/tree/main/examples). +1. [Develop your extension](/docs/extensions/mv3/getstarted/) and publish it at [Chrome Web Store](/docs/webstore/about_webstore/). +1. Feel free to [add it to the list of extensions](https://github.com/GoogleChrome/developer.chrome.com/edit/main/site/en/docs/devtools/recorder/extensions/index.md) on this page. diff --git a/site/en/docs/devtools/recorder/reference/index.md b/site/en/docs/devtools/recorder/reference/index.md index bf402e5ae..d341e070c 100644 --- a/site/en/docs/devtools/recorder/reference/index.md +++ b/site/en/docs/devtools/recorder/reference/index.md @@ -71,7 +71,7 @@ To export a user flow: - **@puppeteer/replay**. Download the recording as a [Puppeteer Replay](https://github.com/puppeteer/replay) script. - **Puppeteer**. Download the recording as a [Puppeteer](/docs/puppeteer/) script. - **Puppeteer (including Lighthouse analysis)**. Download the recording as a [Puppeteer](/docs/puppeteer/) script with an embedded [Lighthouse](/docs/lighthouse/) analysis. - - One or more options provided by [Recorder Extensions](//docs/devtools/recorder/extensions/#export-extensions). + - One or more options provided by the Recorder's [Export extensions](/docs/devtools/recorder/extensions/#export-extensions). 1. Save the file. You can do the following with each default export option: @@ -92,39 +92,7 @@ You can do the following with each default export option: ### Export in a custom format by installing an extension {: #recorder-extension } -{% Aside %} -**Note**: This feature is available from Chrome version 104. -{% endAside %} - -To integrate the **Recorder** with your tools, install extensions: - -1. Select {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/4dU9UXvsinS4zbgjd8rK.svg", alt="File download.", width="20", height="20" %} **Export** > **Get extensions...** at the top of the **Recorder** panel or go to [Extensions](/docs/devtools/recorder/extensions/). -1. Choose an extension and click its link. -1. In Chrome Web Store, click **Add extension**. -1. [Open DevTools](/docs/devtools/open/) in a new tab and find new custom options in the **Recorder**. - -{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/1yXSxuF798GRFI5Jmu9W.png", alt="Export and replay extensions.", width="800", height="406" %} - -Currently, there are two types of extensions: [Export](/docs/devtools/recorder/extensions/#export-extensions) and [Replay](/docs/devtools/recorder/extensions/#replay-extensions). - -#### Troubleshooting {: #extension-troubleshooting } - -If you don't see the export option after installing the extension, do the following: - -- The extension only works on web pages. For example, the export option is not available for `chrome://` pages like `chrome://extensions`. -- Always open a new browser tab after installing the extension. -- There is an [issue](https://crbug.com/1351416) in Chrome 104 and 105 that prevents the export option showing if you open the **Recorder** as the first DevTools panel. As a workaround, open another panel (for example, **Console**) first before opening the **Recorder**. The issue is fixed in Chrome 106. - -{% Aside 'gotchas' %} -**Advanced use case: Build an extension** - -To further customize the **Recorder** to your needs, you can build your own extension: - -1. Explore the [chrome.devtools.recorder](/docs/extensions/reference/devtools_recorder/) API. -1. Check out [example extensions](https://github.com/puppeteer/replay/tree/main/examples). -1. [Develop your extension](/docs/extensions/mv3/getstarted/) and publish it at [Chrome Web Store](/docs/webstore/about_webstore/). -1. Feel free to [add it to the Extensions list](https://github.com/GoogleChrome/developer.chrome.com/edit/main/site/en/docs/devtools/recorder/extensions/index.md). -{% endAside %} +See [Recorder extensions](/docs/devtools/recorder/extensions). ### Import a user flow {: #import-flows } From cd7ee56989716dd0c3257eca176e2b57665bbede Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Beaufort?= Date: Fri, 14 Apr 2023 15:59:38 +0200 Subject: [PATCH 036/982] Add toji to authors (#6011) --- site/_data/authorsData.json | 8 ++++++++ site/_data/i18n/authors.yaml | 5 +++++ 2 files changed, 13 insertions(+) diff --git a/site/_data/authorsData.json b/site/_data/authorsData.json index 56d8d7d33..25f30c3ec 100644 --- a/site/_data/authorsData.json +++ b/site/_data/authorsData.json @@ -525,6 +525,14 @@ "mastodon": "https://mastodon.gamedev.place/@DaKangz", "image": "image/vvhSqZboQoZZN9wBvoXq72wzGAf1/mYkUaoNpythq50oIFiQh.jpeg" }, + "toji": { + "country": "US", + "twitter": "tojiro", + "github": "toji", + "mastodon": "https://mastodon.social/@tojiro", + "homepage": "https://toji.dev/", + "image": "image/vvhSqZboQoZZN9wBvoXq72wzGAf1/0OHajNUjLrRB7XsDWuFt.png" + }, "eladalon": { "country": "SE", "github": "eladalon1983", diff --git a/site/_data/i18n/authors.yaml b/site/_data/i18n/authors.yaml index 87f3b0bff..6cd66b5f9 100644 --- a/site/_data/i18n/authors.yaml +++ b/site/_data/i18n/authors.yaml @@ -581,6 +581,11 @@ cwallez: en: Corentin Wallez description: en: Graphics plumber at Google +toji: + title: + en: Brandon Jones + description: + en: WebGPU/WebXR/WebGL Dev at Google eladalon: title: en: 'Elad Alon' From 4e12efd9cadaea5bf8a2355f49d500957b4747e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Beaufort?= Date: Fri, 14 Apr 2023 16:55:45 +0200 Subject: [PATCH 037/982] Add WebGPU tag (#6012) --- site/_data/i18n/tags.yml | 3 +++ site/_data/supportedTags.json | 3 +++ site/en/articles/gpu-compute/index.md | 1 + site/en/blog/webgpu-release/index.md | 1 + site/en/docs/web-platform/webgpu/index.md | 2 ++ 5 files changed, 10 insertions(+) diff --git a/site/_data/i18n/tags.yml b/site/_data/i18n/tags.yml index 01a0a765b..23ac8d344 100644 --- a/site/_data/i18n/tags.yml +++ b/site/_data/i18n/tags.yml @@ -128,6 +128,9 @@ html: media: en: Media +webgpu: + en: WebGPU + new-in-chrome: en: New in Chrome es: Qué hay de nuevo en Chrome diff --git a/site/_data/supportedTags.json b/site/_data/supportedTags.json index 0c0ca9883..153df0dbb 100644 --- a/site/_data/supportedTags.json +++ b/site/_data/supportedTags.json @@ -71,6 +71,9 @@ "media": { "title": "i18n.tags.media" }, + "webgpu": { + "title": "i18n.tags.webgpu" + }, "new-in-chrome": { "title": "i18n.tags.new-in-chrome" }, diff --git a/site/en/articles/gpu-compute/index.md b/site/en/articles/gpu-compute/index.md index c32ed8c0c..f11a561bd 100644 --- a/site/en/articles/gpu-compute/index.md +++ b/site/en/articles/gpu-compute/index.md @@ -16,6 +16,7 @@ description: | you get started with performing data-parallel computations using the GPU. tags: - capabilities + - webgpu feedback: - api stack_overflow_tag: webgpu diff --git a/site/en/blog/webgpu-release/index.md b/site/en/blog/webgpu-release/index.md index 1384df820..6387d8103 100644 --- a/site/en/blog/webgpu-release/index.md +++ b/site/en/blog/webgpu-release/index.md @@ -13,6 +13,7 @@ hero: image/vvhSqZboQoZZN9wBvoXq72wzGAf1/DV3geEz9FsEc3JiFPSY2.png alt: Battle damaged Sci-fi helmet rendered with WebGPU. tags: - chrome-113 + - webgpu --- The Chrome team is thrilled to announce that WebGPU is now available by default in Chrome 113, which is currently in the Beta channel. WebGPU is a new web graphics API that offers significant benefits such as greatly reduced JavaScript workload for the same graphics and more than three times improvements in machine learning model inferences. This is possible due to more flexible GPU programming and access to advanced capabilities that WebGL does not provide. diff --git a/site/en/docs/web-platform/webgpu/index.md b/site/en/docs/web-platform/webgpu/index.md index 9254df8c8..58f66651b 100644 --- a/site/en/docs/web-platform/webgpu/index.md +++ b/site/en/docs/web-platform/webgpu/index.md @@ -8,6 +8,8 @@ authors: - cwallez date: 2021-08-26 updated: 2023-01-27 +tags: + - webgpu --- ## What is WebGPU? {: #what } From 619d7ce2070a2c8b12dcf6343f1f48fb9c7462ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Beaufort?= Date: Fri, 14 Apr 2023 17:08:04 +0200 Subject: [PATCH 038/982] Redirect webgpu doc to MDN (#6013) --- redirects.yaml | 5 + site/_data/docs/web-platform/toc.yml | 1 - site/en/docs/web-platform/webgpu/index.md | 241 ---------------------- site/es/docs/web-platform/webgpu/index.md | 156 -------------- site/pt/docs/web-platform/webgpu/index.md | 152 -------------- 5 files changed, 5 insertions(+), 550 deletions(-) delete mode 100644 site/en/docs/web-platform/webgpu/index.md delete mode 100644 site/es/docs/web-platform/webgpu/index.md delete mode 100644 site/pt/docs/web-platform/webgpu/index.md diff --git a/redirects.yaml b/redirects.yaml index dc6cffaa0..047183277 100644 --- a/redirects.yaml +++ b/redirects.yaml @@ -655,6 +655,11 @@ redirects: - from: /blog/fugu-showcase/ - to: /fugu-showcase/ +# Redirect old platform documentation to MDN + +- from: /docs/web-platform/webgpu/ + to: https://developer.mozilla.org/docs/Web/API/WebGPU_API + # Generic - from: /... diff --git a/site/_data/docs/web-platform/toc.yml b/site/_data/docs/web-platform/toc.yml index 96159caa4..09d3145ca 100644 --- a/site/_data/docs/web-platform/toc.yml +++ b/site/_data/docs/web-platform/toc.yml @@ -25,7 +25,6 @@ sections: - url: /docs/web-platform/document-picture-in-picture - url: /docs/web-platform/launch-handler - - url: /docs/web-platform/webgpu - url: /docs/web-platform/popup-api - url: /docs/web-platform/bfcache-notrestoredreasons - url: /blog/soft-navigations-experiment/ diff --git a/site/en/docs/web-platform/webgpu/index.md b/site/en/docs/web-platform/webgpu/index.md deleted file mode 100644 index 58f66651b..000000000 --- a/site/en/docs/web-platform/webgpu/index.md +++ /dev/null @@ -1,241 +0,0 @@ ---- -layout: 'layouts/doc-post.njk' -title: WebGPU -description: WebGPU enables high-performance 3D graphics and data-parallel computation on the web. -subhead: WebGPU enables high-performance 3D graphics and data-parallel computation on the web. -authors: - - beaufortfrancois - - cwallez -date: 2021-08-26 -updated: 2023-01-27 -tags: - - webgpu ---- - -## What is WebGPU? {: #what } - -[webgpu] is a new web API that exposes modern computer graphics capabilities, -specifically Direct3D 12, Metal, and Vulkan, for performing rendering and -computation operations on a graphics processing unit (GPU). - -
- {% Img src="image/vvhSqZboQoZZN9wBvoXq72wzGAf1/WHoJmX2IU7roV4iabH6M.png", alt="Architecture diagram showing WebGPUs connection between OS APIs and Direct3D 12, Metal, and Vulkan.", width="800", height="313" %} -
WebGPU architecture diagram
-
- -This goal is similar to the [WebGL][webgl] family of APIs, but WebGPU enables access to -more advanced features of GPUs. Whereas WebGL is mostly for drawing images but -can be repurposed with great effort for other kinds of computations, WebGPU -provides first-class support for performing general computations on the GPU. - -After four years of development in the [W3C's "GPU for the Web" Community -Group][w3c-gpu], WebGPU is now ready for developers to try in Chrome and give feedback on -the API and the shading language. - -{% Blockquote 'Mr.doob, Creator of Three.js' %} -"After a decade of WebGL bringing 3D graphics to the web and enabling all sorts -of new experiences, it's now time to upgrade the stack and help web developers -take full advantage of modern graphics cards. WebGPU arrives just in time!" -{% endBlockquote %} - -{% Blockquote 'David Catuhe, Creator of Babylon.js' %} -WebGPU gets us closer to the metal and it also unlocks the power of compute -shader for Web developers. New 3D experiences can be built today on [Babylon.js -Playground][babylon]. -{% endBlockquote %} - -
- {% Video src="video/vvhSqZboQoZZN9wBvoXq72wzGAf1/Xb7LvsJ5e8efTssp94c6.mov", autoplay=true, muted=true, playsinline=true, loop=true %} -
- A Babylon.js demo of a rough sea being simulated using WebGPU's compute shader capability. -
-
- -## Current status {: #status } - -
- -| Step | Status | -| ---------------------------------------- | ------------------------ | -| 1. Create explainer | [Complete][explainer] | -| 2. Create initial draft of specification | [In progress][spec] | -| 3. Gather feedback & iterate on design | [In progress](#feedback) | -| 4. **Origin trial** | **[In progress][ot]** | -| 5. Launch | Not started | - -
- -## How to use WebGPU {: #use } - -### Enabling via about://flags - -To experiment with WebGPU locally, without an origin trial token, enable the -`#enable-unsafe-webgpu` flag in `about://flags`. - -### Enabling support during the origin trial phase - -Starting in Chrome 94, WebGPU is available as an origin trial in Chrome. The -origin trial is expected to end in Chrome 109 (Feb 1, 2023). - -{% Aside 'caution' %} -The origin trial is expected to [pause for 2 weeks](https://groups.google.com/a/chromium.org/g/blink-dev/c/gBMsYQ1Aurw/m/xl1znc7fAAAJ) -starting in Chrome 106 (Sep 27, 2022). -{% endAside %} - -{% Partial 'origin-trials.njk' %} - -### Register for the origin trial {: #register-for-ot } - -{% Partial 'origin-trial-register.njk' %} - -### Feature detection {: #feature-detection } - -To check if WebGPU is supported, use: - -```js -if ("gpu" in navigator) { - // WebGPU is supported! 🎉 -} -``` - -{% Aside 'caution' %} -The GPU adapter returned by `navigator.gpu.requestAdapter()` may be `null`. -{% endAside %} - -### Get started {: #get-started } - -WebGPU is a low-level API, like WebGL. It is very powerful, quite verbose, and -requires understanding key concepts before diving into it. That's why I'll link -to existing high-quality content in this article for you to get started with -WebGPU. - -- [WebGPU — All of the cores, none of the canvas][webgpu-surma] -- [Get started with GPU Compute on the web][webgpu-started] -- [A Taste of WebGPU in Firefox][webgpu-firefox] -- [WebGPU for Metal Developers, Part One][webgpu-metal] -- [Learn what key data structures and types are needed to draw in WebGPU][webgpu-draw] -- [WebGPU Explainer][webgpu-explainer] -- [WebGPU Best Practices][webgpu-best-practices] - -## Browser support {: #browser-support } - -WebGPU is available on select devices on ChromeOS, macOS, and Windows 10 in -Chrome 94 with more devices being supported in the future. -Android support is available on Android in Chrome 111. Linux -experimental support is available by running Chrome with -`--enable-features=Vulkan`. More support for more platforms will -follow. - -The full list of known issues is available in the [ot-caveats]. - -At the time of writing, WebGPU support is in progress in [Safari][safari] and [Firefox][firefox]. - -## Platform support {: #platform-support } - -As in WebGL's world, some libraries implement WebGPU as well: - -- [Dawn][dawn] is a C++ implementation of WebGPU used in Chromium. It can be used to - target WebGPU in C and C++ applications that can then be ported to - [WebAssembly][webassembly] using [Emscripten][emscripten] and automatically take advantage of WebGPU in - the browser. -- [Wgpu][wgpu] is a Rust implementation of WebGPU used in Firefox. It is used by - various GPU applications in the Rust ecosystem, for example [Veloren][veloren], a - multiplayer voxel RPG. - -## Demos {: #demos } - -- [WebGPU Samples][samples] -- [Metaballs rendered in WebGPU][metaballs] -- [WebGPU Clustered Forward Shading][shading] - -## Security and privacy {: #security-privacy } - -To ensure a web page can only work with its own data, all the commands are -strictly validated before they reach the GPU. Check out the [Malicious use -considerations][malicious] section of the WebGPU spec to learn more about the security -tradeoffs regarding driver bugs for instance. - -## Feedback {: #feedback } - -The Chrome team wants to hear about your experiences with WebGPU. - -### Tell us about the API design - -Is there something about the API or the shading language that does not work like -you expected? Or are there missing methods or properties that you need to -implement your idea? Have a question or comment on the security model? File a -spec issue on the corresponding [gitHub-repo], or add your thoughts to an -existing issue. - -### Report a problem with the implementation - -Did you find a bug with Chrome's implementation? Or is the implementation -different from the spec? File a bug at [new.crbug.com](https://new.crbug.com). -Be sure to include as much detail as you can like the content of the internal -`about:gpu` page, simple instructions for reproducing, and enter `Blink>WebGPU` -in the **Components** box. [glitch](https://glitch.com/) works great for sharing -quick and easy repros. - -### Show support for WebGPU - -Are you planning to use WebGPU? Your public support helps the Chrome team -prioritize features and show other browser vendors how critical it is to support -them. - -Send a tweet to [@ChromiumDev][cr-dev-twitter] using the hashtag -[`#WebGPU`](https://twitter.com/search?q=%23WebGPU&src=recent_search_click&f=live) -and let us know where and how you are using it. Ask a question on StackOverflow -with the hashtag [`#webgpu`](https://stackoverflow.com/questions/tagged/webgpu). - -## Helpful links {: #helpful } - -- [Public explainer][explainer] -- [WebGPU API Spec][spec] -- [WebGPU Shading Language (WGSL)][wgsl-spec] -- [Chromium tracking bug][cr-bug] -- [ChromeStatus.com entry][cr-status] -- Blink Component: [`Blink>WebGPU`][blink-component] -- [TAG Review](https://github.com/w3ctag/design-reviews/issues/626) -- [Intent to Experiment](https://groups.google.com/a/chromium.org/g/blink-dev/c/K4_egTNAvTs/m/ApS804L_AQAJ) -- [WebGPU's matrix channel][matrix] - -## Acknowledgements {: #acknowledgements } - -Hero image via [Maxime Rossignol](https://unsplash.com/@maxoor) on -[Unsplash](https://unsplash.com/photos/ukOCJ09jpgc). - -[webgpu]: https://gpuweb.github.io/gpuweb/ -[webgl]: https://developer.mozilla.org/docs/Web/API/WebGL_API -[w3c-gpu]: https://www.w3.org/community/gpu/ -[babylon]: https://playground.babylonjs.com/#XCNL7Y -[webgpu-surma]: https://surma.dev/things/webgpu/ -[webgpu-started]: /gpu-compute/ -[webgpu-firefox]: https://hacks.mozilla.org/2020/04/experimental-webgpu-in-firefox/ -[webgpu-metal]: https://metalbyexample.com/webgpu-part-one/ -[webgpu-draw]: https://alain.xyz/blog/raw-webgpu -[webgpu-explainer]: https://gpuweb.github.io/gpuweb/explainer/ -[webgpu-best-practices]: https://toji.github.io/webgpu-best-practices/ -[ot-caveats]: https://hackmd.io/QcdsK_g7RVKRCIIBqgs5Hw -[safari]: https://webkit.org/blog/9528/webgpu-and-wsl-in-safari/ -[firefox]: https://hacks.mozilla.org/2020/04/experimental-webgpu-in-firefox/ -[dawn]: https://dawn.googlesource.com/dawn -[webassembly]: https://developer.mozilla.org/docs/WebAssembly -[emscripten]: https://emscripten.org/ -[wgpu]: https://sotrh.github.io/learn-wgpu/#what-is-wgpu -[veloren]: https://veloren.net/devblog-125/ -[samples]: https://austin-eng.com/webgpu-samples/ -[metaballs]: https://toji.github.io/webgpu-metaballs/ -[shading]: https://toji.github.io/webgpu-clustered-shading/ -[malicious]: https://gpuweb.github.io/gpuweb/#malicious-use -[github-repo]: https://github.com/gpuweb/gpuweb/issues/ -[spec]: https://gpuweb.github.io/gpuweb/ -[wgsl-spec]: https://gpuweb.github.io/gpuweb/wgsl/ -[issues]: https://github.com/gpuweb/gpuweb/issues -[explainer]: https://gpuweb.github.io/gpuweb/explainer/ -[cr-bug]: https://bugs.chromium.org/p/chromium/issues/detail?id=1156646 -[cr-status]: https://chromestatus.com/feature/6213121689518080 -[blink-component]: https://chromestatus.com/features#component%3ABlink%3EWebGPU -[cr-dev-twitter]: https://twitter.com/ChromiumDev -[ot]: https://developer.chrome.com/origintrials/#/view_trial/118219490218475521 -[matrix]: https://matrix.to/#/#WebGPU:matrix.org - diff --git a/site/es/docs/web-platform/webgpu/index.md b/site/es/docs/web-platform/webgpu/index.md deleted file mode 100644 index a31e1931f..000000000 --- a/site/es/docs/web-platform/webgpu/index.md +++ /dev/null @@ -1,156 +0,0 @@ ---- -layout: 'layouts/doc-post.njk' -title: WebGPU -description: WebGPU permite gráficos 3D de alto rendimiento y cálculo paralelo de datos en La web. -subhead: WebGPU permite gráficos 3D de alto rendimiento y cálculo paralelo de datos en La web. -date: 2021-08-26 -updated: 2022-03-23 ---- - -## ¿Qué es WebGPU? {: #what } - -[WebGPU](https://gpuweb.github.io/gpuweb/) es una nueva API web que expone las capacidades gráficas de sistemas modernos, específicamente Direct3D 12, Metal y Vulkan, para realizar operaciones de renderizado y cálculo en una unidad de procesamiento gráfico (GPU). - -
{% Img src="image/vvhSqZboQoZZN9wBvoXq72wzGAf1/WHoJmX2IU7roV4iabH6M.png", alt="Architecture diagram showing WebGPUs connection between OS APIs and Direct3D 12, Metal, and Vulkan.", width="800", height="313" %}
Diagrama de arquitectura WebGPU
- -Este objetivo es similar al de la familia de APIs [WebGL](https://developer.mozilla.org/docs/Web/API/WebGL_API), pero WebGPU permite el acceso a funciones más avanzadas de las GPUs. Mientras que WebGL es principalmente para dibujar imágenes, y también se puede utilizar con gran esfuerzo para otros tipos de cálculos, WebGPU proporciona soporte de primera clase para realizar cálculos generales en la GPU. - -Después de cuatro años de desarrollo en el [grupo comunitario "GPU para la Web" de W3C](https://www.w3.org/community/gpu/), WebGPU ya está lista para que los desarrolladores la prueben en Chrome y brinden comentarios sobre la API y el lenguaje de sombreado. - -{% Blockquote 'Mr.doob, Creator of Three.js' %} "Tras una década en la que WebGL ha llevado los gráficos 3D a la web y ha permitido todo tipo de nuevas experiencias, ha llegado el momento de actualizar la pila y ayudar a los desarrolladores web a aprovechar al máximo las tarjetas gráficas modernas. ¡WebGPU llega justo a tiempo!" {% endBlockquote %} - -{% Blockquote 'David Catuhe, Creator of Babylon.js' %} WebGPU nos acerca al metal y también desbloquea el poder del sombreador de cómputo para desarrolladores web. Hoy se pueden crear nuevas experiencias 3D en [Babylon.js Playground](https://playground.babylonjs.com/#XCNL7Y). {% endBlockquote %} - -
{% Video src="video/vvhSqZboQoZZN9wBvoXq72wzGAf1/Xb7LvsJ5e8efTssp94c6.mov", autoplay=true, muted=true, playsinline=true, loop=true %}
Una demostración en Babylon.js de la simulación de un mar embravecido utilizando la capacidad de sombreado de cómputo de WebGPU.
- -## Estado actual {: #status } - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - -
PasoEstado
1. Crear un explicadorCompleto
2. Crear borrador inicial de especificaciónEn curso
3. Recoger opiniones y repetir el diseñoEn curso
4. Prueba de origen -

En curso

5. IniciarSin comenzar
-
- -## Cómo usar WebGPU {: #use } - -### Habilitación a través de about: // flags - -Para experimentar con WebGPU localmente, sin un token de prueba de origen, habilita `#enable-unsafe-webgpu` en `about://flags`. - -### Soporte durante la fase de prueba de origen - -A partir de Chrome 94, WebGPU está disponible como prueba de origen en Chrome. Se espera que la prueba de origen finalice en Chrome 101 (18 de mayo de 2022). - -{% Partial 'origin-trials.njk' %} - -### Registrarse para la prueba de origen {: #register-for-ot } - -{% Partial 'origin-trial-register.njk' %} - -### Detección de características {: #feature-deployment } - -Para verificar si WebGPU es compatible, usa: - -```js -if ("gpu" in navigator) { - // WebGPU is supported! 🎉 -} -``` - -{% Aside 'caution' %} El adaptador de GPU devuelto por `navigator.gpu.requestAdapter()` puede ser `null`. {% endAside %} - -### Comenzar {: #get-started } - -WebGPU es una API de bajo nivel, como WebGL. Es muy potente, bastante detallada y requiere comprender conceptos claves antes de sumergirse en ella. Por eso, en este artículo te enlazaré a contenidos existentes de alta calidad para que te inicies en WebGPU. - -- [Empieza a utilizar GPU Compute en la web](/gpu-compute/) -- [Una muestra de WebGPU en Firefox](https://hacks.mozilla.org/2020/04/experimental-webgpu-in-firefox/) -- [WebGPU para desarrolladores de Metal, primera parte](https://metalbyexample.com/webgpu-part-one/) -- [Aprende qué tipos y estructuras de datos clave se necesitan para dibujar en WebGPU](https://alain.xyz/blog/raw-webgpu) -- [Explicador de WebGPU](https://gpuweb.github.io/gpuweb/explainer/) -- [Mejores prácticas de WebGPU](https://toji.github.io/webgpu-best-practices/) - -## Compatibilidad con navegadores {: #browser-support } - -WebGPU está disponible en determinados dispositivos de ChromeOS, macOS y Windows 10 en Chrome 94 y se admitirán más dispositivos en el futuro. La compatibilidad experimental con Linux está disponible ejecutando Chrome con `--enable-features=Vulkan`. Más adelante habrá más soporte para más plataformas. - -La lista completa de problemas conocidos está disponible en el [documento de Advertencias de la Prueba de Origin](https://hackmd.io/QcdsK_g7RVKRCIIBqgs5Hw). - -En el momento de redactar este artículo, la compatibilidad con WebGPU está en curso en [Safari](https://webkit.org/blog/9528/webgpu-and-wsl-in-safari/) y [Firefox](https://hacks.mozilla.org/2020/04/experimental-webgpu-in-firefox/). - -## Soporte de plataformas {: #platform-support } - -Al igual que en el mundo de WebGL, algunas bibliotecas también implementan WebGPU: - -- [Dawn](https://dawn.googlesource.com/dawn) es una implementación C++ de WebGPU utilizada en Chromium. Se puede usar para apuntar a WebGPU en aplicaciones C y C++ que luego se pueden portar a [WebAssembly](https://developer.mozilla.org/docs/WebAssembly) usando [Emscripten](https://emscripten.org/) y aprovechar automáticamente WebGPU en el navegador. -- [Wgpu](https://sotrh.github.io/learn-wgpu/#what-is-wgpu) es una implementación de Rust de WebGPU utilizada en Firefox. Es utilizado por varias aplicaciones de GPU en el ecosistema de Rust, por ejemplo [Veloren](https://veloren.net/devblog-125/), un juego de rol multijugador de voxel. - -## Demos {: #demos } - -- [Muestras de WebGPU](https://austin-eng.com/webgpu-samples/) -- [Metaballs renderizados en WebGPU](https://toji.github.io/webgpu-metaballs/) -- [Sombreado directo agrupado de WebGPU](https://toji.github.io/webgpu-clustered-shading/) - -## Seguridad y privacidad {: #security-privacy } - -Para garantizar que una página web solo pueda funcionar con sus propios datos, todos los comandos se validan estrictamente antes de que lleguen a la GPU. Consulta la sección [Consideraciones sobre el uso malicioso](https://gpuweb.github.io/gpuweb/#malicious-use) de la especificación de WebGPU para obtener más información sobre las compensaciones de seguridad relacionadas con los errores de los controladores, por ejemplo. - -## Comentarios {: #feedback } - -El equipo de Chrome desea conocer tus experiencias con WebGPU. - -### Contanos sobre el diseño de la API - -¿Hay algo sobre la API o el lenguaje de sombreado que no funciona como esperabas? ¿O faltan métodos o propiedades que necesitas para implementar tu idea? ¿Tienes alguna pregunta o comentario sobre el modelo de seguridad? Presenta un tema en el [repositorio de GitHub](https://github.com/gpuweb/gpuweb/issues/) correspondiente o agrega tus ideas a un tema existente. - -### Informar problemas sobre la implementación - -¿Encontraste un error con la implementación de Chrome? ¿O la implementación es diferente de la especificación? Presenta tu error en [new.crbug.com](https://new.crbug.com). Asegúrate de incluir tantos detalles como puedas, como el contenido de la página interna `about:gpu`, instrucciones simples para reproducirlo e ingresa `Blink>WebGPU` en la casilla **Componentes.** [Glitch](https://glitch.com/) funciona muy bien para compartir repros rápidos y fáciles. - -### Mostrar soporte para WebGPU - -¿Estás pensando en utilizar WebGPU? Su apoyo público ayuda al equipo de Chrome a priorizar funciones y mostrar a otros proveedores de navegadores lo importante que es brindarles soporte. - -Envía un tweet a [@ChromiumDev](https://twitter.com/ChromiumDev) usando el hashtag[`#WebGPU`](https://twitter.com/search?q=%23WebGPU&src=recent_search_click&f=live) y hacenos saber dónde y cómo lo estás usando. También puedes hacer una pregunta en StackOverflow con el hashtag [`#webgpu`](https://stackoverflow.com/questions/tagged/webgpu). - -## Enlaces útiles {: #helpful } - -- [Explicador público](https://gpuweb.github.io/gpuweb/explainer/) -- [Especificaciones de API de WebGPU](https://gpuweb.github.io/gpuweb/) -- [Lenguaje de sombreado de WebGPU (WGSL)](https://gpuweb.github.io/gpuweb/wgsl/) -- [Error de seguimiento de Cromium](https://bugs.chromium.org/p/chromium/issues/detail?id=1156646) -- [Entrada de ChromeStatus.com](https://chromestatus.com/feature/6213121689518080) -- Componente Blink: [`Blink>WebGPU`](https://chromestatus.com/features#component%3ABlink%3EWebGPU) -- [Revisión de TAG](https://github.com/w3ctag/design-reviews/issues/626) -- [Intención de experimentar](https://groups.google.com/a/chromium.org/g/blink-dev/c/K4_egTNAvTs/m/ApS804L_AQAJ) -- [Canal matriz de WebGPU](https://matrix.to/#/#WebGPU:matrix.org) - -## Agradecimientos {: #acknowledgements } - -Imagen de héroe a través de [Maxime Rossignol](https://unsplash.com/@maxoor) en [Unsplash](https://unsplash.com/photos/ukOCJ09jpgc). diff --git a/site/pt/docs/web-platform/webgpu/index.md b/site/pt/docs/web-platform/webgpu/index.md deleted file mode 100644 index 96107fabe..000000000 --- a/site/pt/docs/web-platform/webgpu/index.md +++ /dev/null @@ -1,152 +0,0 @@ ---- -layout: 'layouts/doc-post.njk' -title: WebGPU -description: WebGPU permite gráficos 3D de alto desempenho e computação paralela de dados. -subhead: WebGPU permite gráficos 3D de alto desempenho e computação paralela de dados. -date: 2021-08-26 -updated: 2022-03-23 ---- - -## O que é WebGPU? {: #what } - -[WebGPU](https://gpuweb.github.io/gpuweb/) é uma nova API da web que expõe recursos gráficos de computador modernos, especificamente Direct3D 12, Metal e Vulkan, para realizar operações de renderização e computação em uma unidade de processamento gráfico (GPU). - -
{% Img src = "image/vvhSqZboQoZZN9wBvoXq72wzGAf1/WHoJmX2IU7roV4iabH6M.png", alt = "Diagrama de arquitetura mostrando a conexão WebGPUs entre APIs do SO e Direct3D 12, Metal e Vulkan.", width="800", height="313" %}
Diagrama da arquitetura WebGPU
- -Esse objetivo é semelhante à [família WebGL](https://developer.mozilla.org/docs/Web/API/WebGL_API) de APIs, mas o WebGPU permite o acesso a recursos mais avançados de GPUs. Considerando que WebGL é principalmente para desenhar imagens, mas pode ser reaproveitado com grande esforço para outros tipos de cálculos, WebGPU fornece suporte de primeira classe para realizar cálculos gerais na GPU. - -Após quatro anos de desenvolvimento no [grupo da comunidade "GPU para a Web"](https://www.w3.org/community/gpu/) do W3C, o WebGPU está agora pronto para que os desenvolvedores experimentem o Chrome e forneçam feedback sobre a API e a linguagem de sombreamento. - -{% Blockquote 'Mr.doob, Creator of Three.js' %} "Após uma década de WebGL trazendo gráficos 3D para a web e permitindo todos os tipos de novas experiências, agora é hora de atualizar a pilha e ajudar os desenvolvedores da web a tirar o máximo proveito das placas gráficas modernas. WebGPU chega bem na hora!" {% endBlockquote %} - -{% Blockquote 'David Catuhe, Creator of Babylon.js' %} WebGPU nos deixa mais perto do metal e também revela o poder do sombreamento de computação para desenvolvedores da Web. Novas experiências 3D podem ser construídas hoje no [Babylon.js Playground](https://playground.babylonjs.com/#XCNL7Y). {% endBlockquote %} - -
{% Video src = "video/vvhSqZboQoZZN9wBvoXq72wzGAf1/Xb7LvsJ5e8efTssp94c6.mov", autoplay = true, muted = true, playsinline = true, loop = true%}
Uma demonstração do Babylon.js de um mar agitado sendo simulado usando o recurso de sombreamento de computação do WebGPU.
- -## Status atual {: #status } - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - -
DegrauStatus
1. Crie um explicadorCompleto
2. Crie o rascunho inicial das especificaçõesEm andamento
3. Reúna feedback e repita o designEm andamento
4. Teste de origem -

Em andamento

5. LançamentoNão foi iniciado
-
- -## Como usar o WebGPU {: #use } - -### Ativando via about://flags - -Para experimentar o WebGPU localmente, sem um token de teste de origem, habilite o sinalizador `#enable-unsafe-webgpu` `about://flags` . - -### Habilitando o suporte durante a fase de teste de origem - -A partir do Chrome 94, o WebGPU está disponível como um teste original no Chrome. Espera-se que o teste de origem termine no Chrome 101 (18 de maio de 2022). - -{% Partial 'origin-trials.njk' %} - -### Registre-se para o teste de origem {: #register-for-ot } - -{% Partial 'origin-trial-register.njk' %} - -### Detecção de recurso {: #feature-detection } - -Para verificar se WebGPU é compatível, use: - -```js -if ("gpu" in navigator) { - // WebGPU é suportado! 🎉 -} -``` - -{% Aside 'caution' %} O adaptador de GPU retornado por `navigator.gpu.requestAdapter()` pode ser `null` . {% endAside %} - -### Comece {: #get-started } - -WebGPU é uma API de baixo nível, como WebGL. É muito poderoso, bastante prolixo e requer a compreensão de conceitos-chave antes de mergulhar nele. É por isso que vou criar um link para conteúdo de alta qualidade existentes neste artigo para você começar a usar o WebGPU. - -- [Comece a usar GPU Compute na web](/gpu-compute/) -- [Um gostinho de WebGPU no Firefox](https://hacks.mozilla.org/2020/04/experimental-webgpu-in-firefox/) -- [WebGPU para Desenvolvedores de Metal, Parte Um](https://metalbyexample.com/webgpu-part-one/) -- [Aprenda quais tipos e estruturas de dados chave são necessários para desenhar no WebGPU](https://alain.xyz/blog/raw-webgpu) -- [Explicador WebGPU](https://gpuweb.github.io/gpuweb/explainer/) -- [Melhores Práticas WebGPU](https://toji.github.io/webgpu-best-practices/) - -## Suporte do navegador {: #browser-support } - -O WebGPU está disponível em dispositivos selecionados no ChromeOS, macOS e Windows 10 no Chrome 94, com mais dispositivos sendo suportados no futuro. O suporte experimental para Linux está disponível executando o Chrome com `--enable-features=Vulkan`. Mais suporte para mais plataformas virá em seguida. - -A lista completa de problemas conhecidos está disponível no [documento Origin Trial Caveats](https://hackmd.io/QcdsK_g7RVKRCIIBqgs5Hw) . - -No momento em que este artigo foi escrito, o suporte WebGPU estava em andamento no [Safari](https://webkit.org/blog/9528/webgpu-and-wsl-in-safari/) e no [Firefox](https://hacks.mozilla.org/2020/04/experimental-webgpu-in-firefox/) . - -## Suporte de plataforma {: #platform-support } - -Como no mundo do WebGL, algumas bibliotecas também implementam WebGPU: - -- [Dawn](https://dawn.googlesource.com/dawn) é uma implementação C++ de WebGPU usada no Chromium. Ele pode ser usado para direcionar WebGPU em aplicativos C e C++ que podem então ser transferidos para [WebAssembly](https://developer.mozilla.org/docs/WebAssembly) usando [Emscripten](https://emscripten.org/) e automaticamente tirar vantagem da WebGPU no navegador. -- [Wgpu](https://sotrh.github.io/learn-wgpu/#what-is-wgpu) é uma implementação Rust de WebGPU usada no Firefox. É usado por vários aplicativos de GPU no ecossistema Rust, por exemplo[, Veloren](https://veloren.net/devblog-125/), um RPG de voxel multijogador. - -## Demos {: #demos } - -- [Amostras WebGPU](https://austin-eng.com/webgpu-samples/) -- [Metaballs renderizados em WebGPU](https://toji.github.io/webgpu-metaballs/) -- [WebGPU Clustered Forward Shading](https://toji.github.io/webgpu-clustered-shading/) - -## Segurança e privacidade {: #security-privacy } - -Para garantir que uma página da web funcione apenas com seus próprios dados, todos os comandos são rigorosamente validados antes de chegarem à GPU. Verifique a seção de [considerações de uso malicioso](https://gpuweb.github.io/gpuweb/#malicious-use) da especificação WebGPU para aprender mais sobre as compensações de segurança relacionadas a bugs de driver, por exemplo. - -## Feedback {: #feedback } - -A equipe do Chrome quer ouvir sobre suas experiências com WebGPU. - -### Conte-nos sobre o design da API - -Há algo na API ou na linguagem de sombreamento que não funciona como você esperava? Ou faltam métodos ou propriedades de que você precisa para implementar sua ideia? Tem uma pergunta ou comentário sobre o modelo de segurança? Registre um problema de especificação no [repositório GitHub](https://github.com/gpuweb/gpuweb/issues/) correspondente ou adicione suas ideias a um problema existente. - -### Comunicar um problema com a implementação - -Você encontrou um bug com a implementação do Chrome? Ou a implementação é diferente da especificação? [Registre](https://new.crbug.com) um bug em new.crbug.com. Certifique-se de incluir o máximo de detalhes que puder sobre o conteúdo da página interna `about:gpu`, instruções simples para reproduzir e insira `Blink>WebGPU` na caixa **Componentes.** [Glitch](https://glitch.com/) funciona muito bem para compartilhar reproduções rápidas e fáceis. - -### Mostrar suporte para WebGPU - -Você está planejando usar o WebGPU? Seu apoio público ajuda a equipe do Chrome a priorizar os recursos e mostrar a outros fornecedores de navegadores como é fundamental apoiá-los. - -Envie um tweet para [@ChromiumDev](https://twitter.com/ChromiumDev) usando a hashtag [`#WebGPU`](https://twitter.com/search?q=%23WebGPU&src=recent_search_click&f=live) e diga-nos onde e como você está usando a API. Faça uma pergunta no StackOverflow com a hashtag [`#webgpu`](https://stackoverflow.com/questions/tagged/webgpu). - -## Links úteis {: #helpful } - -- [Explicador público](https://gpuweb.github.io/gpuweb/explainer/) -- [Especificação da API WebGPU](https://gpuweb.github.io/gpuweb/) -- [WebGPU Shading Language (WGSL)](https://gpuweb.github.io/gpuweb/wgsl/) -- [Bug de rastreamento do Chromium](https://bugs.chromium.org/p/chromium/issues/detail?id=1156646) -- [Entrada ChromeStatus.com](https://chromestatus.com/feature/6213121689518080) -- Componente Blink: [`Blink>WebGPU`](https://chromestatus.com/features#component%3ABlink%3EWebGPU) -- [Revisão de TAG](https://github.com/w3ctag/design-reviews/issues/626) -- [Intenção de Experimentar](https://groups.google.com/a/chromium.org/g/blink-dev/c/K4_egTNAvTs/m/ApS804L_AQAJ) -- [Canal de matriz da WebGPU](https://matrix.to/#/#WebGPU:matrix.org) From 223ff1a1ed945821db6a3118d072895c16c4b8c6 Mon Sep 17 00:00:00 2001 From: Joe Medley Date: Fri, 14 Apr 2023 10:59:55 -0700 Subject: [PATCH 039/982] Add link to MV3 conerter (#6016) --- site/en/docs/extensions/migrating/index.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/site/en/docs/extensions/migrating/index.md b/site/en/docs/extensions/migrating/index.md index b432b64fc..6a302f9da 100644 --- a/site/en/docs/extensions/migrating/index.md +++ b/site/en/docs/extensions/migrating/index.md @@ -4,6 +4,7 @@ title: Migrate to Manifest V3 subhead: A guide to converting Manifest V2 extensions to Manifest V3 extensions. description: A guide to converting Manifest V2 extensions to Manifest V3 extensions. date: 2023-03-09 +updated: 2023-04-14 --- This section helps you upgrade an extension from Manifest V2 to Manifest V3, the newest version of the Chrome Extensions platform. Migration work is broadly divided into the categories below. To help you track your work, we've provided a [checklist](/docs/extensions/migrating/checklist/) summarizing the contents of these documents. You can access the content via the checklist, or dive into the content. Both paths end with an upgraded extension. @@ -12,7 +13,9 @@ This section helps you upgrade an extension from Manifest V2 to Manifest V3, the * [Migrate to a service worker](/docs/extensions/migrating/to-service-workers/)—A service worker replaces the extension's background or event page to ensure that background code stays off the main thread where it can hurt performance. This change also requires moving DOM, window, and certain extension API calls into offscreen documents. * [Update API calls](/docs/extensions/migrating/api-calls)—Some API calls need to be replaced with more modern equivalents. * [Replace blocking web request listeners](/docs/extensions/migrating/blocking-web-requests)—Blocking or modifying network requests in Manifest V2 could significantly degrade performance and require excessive access to sensitive user data. The Declarative Net Request API allows extensions to block or modify web content with fewer permissions and without hindering performance. -* [Improve extension security](/docs/extensions/migrating/improve-security)—Manifest V3 improves extension security in several ways. Besides an enhanced content security policy, support is removed for remotely hosted code and execution of arbitrary strings. +* [Improve extension security](/docs/extensions/migrating/improve-security)—Manifest V3 improves extension security in several ways. Besides an enhanced content security policy, support is removed for remotely hosted code and execution of arbitrary strings. + +We also have an [Extension Manifest Converter](https://github.com/GoogleChromeLabs/extension-manifest-converter). It does not do everything for you, but it will get you started. The conver's README describes what the tool chanages. ## New extension features From 40ffaf701118bdc8570ace98fd6ab1ea9a0ef84b Mon Sep 17 00:00:00 2001 From: l3ra Date: Sun, 16 Apr 2023 17:35:35 +0100 Subject: [PATCH 040/982] Update index.md (#6019) Chrome App is no longer an option on the dropdown. It has been renamed to Chrome Extension --- site/en/docs/extensions/mv3/tut_oauth/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/en/docs/extensions/mv3/tut_oauth/index.md b/site/en/docs/extensions/mv3/tut_oauth/index.md index 8aaef325a..c8d41b487 100644 --- a/site/en/docs/extensions/mv3/tut_oauth/index.md +++ b/site/en/docs/extensions/mv3/tut_oauth/index.md @@ -89,7 +89,7 @@ Navigate to the [Google API console][google-console] and create a new project. O {% Img src="image/BrQidfK9jaQyIHwdw91aVpkPiib2/iC6LC1PYreTxndYmLEWN.png", alt="Create credentials for extension", height="478", width="800" %} -On the Create client ID page, select **Chrome App**. Fill out the name of the extension and place +On the Create client ID page, select **Chrome Extension**. Fill out the name of the extension and place the extension ID at the end of the URL in the Application ID field. {% Img src="image/BrQidfK9jaQyIHwdw91aVpkPiib2/CwgbnssSgeRtqHGxRbpd.png", From 95cd294e2e3cc6f8297f6ab65c6f02753afa9e64 Mon Sep 17 00:00:00 2001 From: Matthias Rohmer <12857772+matthiasrohmer@users.noreply.github.com> Date: Mon, 17 Apr 2023 11:03:16 +0200 Subject: [PATCH 041/982] Add clean-up task for staging environment (#4920) * feat: add task for clean up stale staging environments * fix: ignore default version when cleaning up versions * chore: remove accidentally created .netlify dir * fix: lint errors * refactor: adjust to github api client code changes * chore: regenerate package-lock.json * fix: update types to accept null instead of undefined * feat: add cloudbuild job to run gulp task * fix: finish comment stub * fix: actually return early if there is only 1 app engine version * chore: add note about pagination --- .cloudbuild/stagingCleanUp.yaml | 25 + gulp-tasks/stageGitHub/cleanUpGoogleCloud.js | 196 + gulp-tasks/stageGitHub/index.js | 2 + package-lock.json | 4083 ++++++++++++------ package.json | 1 + site/_filters/md.js | 4 +- 6 files changed, 2975 insertions(+), 1336 deletions(-) create mode 100644 .cloudbuild/stagingCleanUp.yaml create mode 100644 gulp-tasks/stageGitHub/cleanUpGoogleCloud.js diff --git a/.cloudbuild/stagingCleanUp.yaml b/.cloudbuild/stagingCleanUp.yaml new file mode 100644 index 000000000..2da27f429 --- /dev/null +++ b/.cloudbuild/stagingCleanUp.yaml @@ -0,0 +1,25 @@ +# Runs in dcc-staging and cleans up stale instances and bucket items by comparing open +# PRs to currently deployed instances/folders +timeout: 2700s +steps: + - id: 'install' + name: node:18 + entrypoint: npm + args: ['ci'] + + - id: 'clean' + name: node:18 + entrypoint: bash + args: + - '-c' + - | + npm run stage:github cleanUpGoogleCloud + +availableSecrets: + secretManager: + - versionName: projects/dcc-staging/secrets/GITHUB_APP_ID/versions/1 + env: 'GITHUB_APP_ID' + - versionName: projects/dcc-staging/secrets/GITHUB_APP_KEY/versions/1 + env: 'GITHUB_APP_KEY' + - versionName: projects/dcc-staging/secrets/GITHUB_APP_INSTALLATION_ID/versions/1 + env: 'GITHUB_APP_INSTALLATION_ID' \ No newline at end of file diff --git a/gulp-tasks/stageGitHub/cleanUpGoogleCloud.js b/gulp-tasks/stageGitHub/cleanUpGoogleCloud.js new file mode 100644 index 000000000..3033d7457 --- /dev/null +++ b/gulp-tasks/stageGitHub/cleanUpGoogleCloud.js @@ -0,0 +1,196 @@ +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @fileoverview Queries the Cloud Storage Bucket for currently deployed + * PRs, checks if there is a corresponding App Engine version (for full deploys) + * and then checks if the matching PR is still open on GitHub and otherwise + * removes the remains. + */ + +const {Storage} = require('@google-cloud/storage'); +const {VersionsClient} = require('@google-cloud/appengine-admin'); + +const {requestGitHubApi} = require('./lib/gitHubApi'); + +/** + * The bucket where static files are deployed + */ +const BUCKET_NAME = 'static-dcc-staging'; + +/** + * The project ID of the App Engine project + */ +const PROJECT_ID = 'dcc-staging'; + +/** This folder contains the base version of the site and should + * never be deleted. + */ +const FALLBACK_DIRECTORY = 'main/'; + +/** + * The version name of the default App Engine version, which should + * never be cleaned up (but also can't and would make the job fail it tried) + */ +const FALLBACK_VERSION = 'main'; + +const storage = new Storage(); +const versionsClient = new VersionsClient(); + +/** + * Reads all files from the root of a Google Cloud Storage bucket + * and returns the PR numbers of the deployed PRs. + * @returns {Promise>} [4124, 4125, 4126] for example + */ +async function getDeployedPullRequestsFromStorage() { + // eslint-disable-next-line no-unused-vars + const [files, nextQuery, apiResponse] = await storage + .bucket(BUCKET_NAME) + .getFiles({autoPaginate: false, delimiter: '/', prefix: ''}); + + const pullRequests = []; + // The prefixes (read: folder names) created by the Cloud Build job + // are in the form of pr-{number}, so they need to be cleaned up + for (const prefix of apiResponse.prefixes) { + if (prefix === FALLBACK_DIRECTORY) { + continue; + } + const prNumber = prefix.replace('pr-', '').replace('/', ''); + pullRequests.push(parseInt(prNumber)); + } + + return pullRequests; +} + +/** + * Fetches the open pull requests from GitHub and + * maps the API response to only get the pull request numbers. + * @returns {Promise>} [4124, 4125, 4126] for example + */ +async function getOpenPullRequestsFromGitHub() { + try { + // Note: this doesn't paginate, which should be okay as the job runs periodically + // and overflown items will be picked up with the next run and PRs will always be opened + // in a slower rate than the job runs. + const apiResponse = await requestGitHubApi( + 'GET', + 'pulls?state=open&per_page=100' + ); + const pullRequests = apiResponse.map(item => item.number); + return pullRequests; + } catch (e) { + console.error(e); + throw new Error('Could not fetch open pull requests from GitHub.'); + } +} + +/** + * Loops over a list of PRs and removes their remains from + * the Cloud Storage bucket. + * @param {Array} prNumbers A list of deployed PRs + */ +async function cleanUpCloudStorage(prNumbers) { + console.log('Starting to clean up Cloud Storage bucket ...'); + // Promise.all is intentionally not used here, as deleteFiles + // already internally batches HTTP requests and GCS actually requires + // a single request for every single object/file to be deleted + for (const prNumber of prNumbers) { + const prefix = `pr-${prNumber}/`; + console.log(`Removing files with prefix ${prefix} ...}`); + // Be patient: as of 01/2023, cleaning up one version can take up + // to 3 minutes following the constraints mentioned above. + await storage.bucket(BUCKET_NAME).deleteFiles({prefix}); + } + + console.log('Done cleaning up Cloud Storage bucket!'); +} + +/** + * Queries the App Engine API for all versions of the default service + * and maps their IDs to match PR numbers + * @returns {Promise>} [4124, 4125, 4126] for example + */ +async function getAppEngineVersions() { + console.log('Fetching App Engine versions ...'); + + const [apiResponse] = await versionsClient.listVersions({ + parent: `apps/${PROJECT_ID}/services/default`, + }); + + // IDs for AppEngine versions are in the format of pr-{number}-app. + // To be comparable to the raw PR numbers they need to be cleaned up + const prNumbers = []; + for (const version of apiResponse) { + if (version.id === FALLBACK_VERSION) { + continue; + } + prNumbers.push(parseInt(version.id.replace('pr-', '').replace('-app', ''))); + } + + return prNumbers; +} + +/** + * + * @param {Array} appEngineVersions [4124] for example + * @param {Array} staleDeployments [4124, 4125, 4126] for example + */ +async function cleanUpAppEngineVersions(appEngineVersions, staleDeployments) { + for (const prNumber of appEngineVersions) { + if (!staleDeployments.includes(prNumber)) { + continue; + } + + console.log(`Removing App Engine version for PR ${prNumber} ...`); + const [operation] = await versionsClient.deleteVersion({ + name: `apps/${PROJECT_ID}/services/default/versions/pr-${prNumber}-app`, + }); + await operation.promise(); + } +} + +async function cleanUpGoogleCloud() { + const deployedPullRequests = await getDeployedPullRequestsFromStorage(); + const openPullRequests = await getOpenPullRequestsFromGitHub(); + console.log( + `Currently ${deployedPullRequests.length} PRs are deployed, with ${openPullRequests.length} PRs open.` + ); + + // Holding the deployed PR numbers against the ones still open identifies + // the ones that have been closed and which remains can be cleaned up + const staleDeployments = deployedPullRequests.filter( + pr => !openPullRequests.includes(pr) + ); + console.log(`There are ${staleDeployments.length} stale deployments.`); + if (staleDeployments.length === 0) { + return; + } + + await cleanUpCloudStorage(staleDeployments); + const appEngineVersions = await getAppEngineVersions(); + // There is a posibility that there are only static deployments + // and no instances except the default one, then we can exit early + if (appEngineVersions.length === 1) { + console.log('No app deployments found.'); + return; + } + + await cleanUpAppEngineVersions(appEngineVersions, staleDeployments); +} + +module.exports = { + cleanUpGoogleCloud, +}; diff --git a/gulp-tasks/stageGitHub/index.js b/gulp-tasks/stageGitHub/index.js index f9a60e640..ae394d504 100644 --- a/gulp-tasks/stageGitHub/index.js +++ b/gulp-tasks/stageGitHub/index.js @@ -2,10 +2,12 @@ const {announceDeploymentStart} = require('./announceDeploymentStart'); const {determineDeploymentType} = require('./determineDeploymentType'); const {buildStaticSite} = require('./buildStaticSite'); const {announceDeploymentFinished} = require('./announceDeploymentFinished'); +const {cleanUpGoogleCloud} = require('./cleanUpGoogleCloud'); module.exports = { announceDeploymentStart, determineDeploymentType, buildStaticSite, announceDeploymentFinished, + cleanUpGoogleCloud, }; diff --git a/package-lock.json b/package-lock.json index b67aab7e7..1a801ba7a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,6 +13,7 @@ "@11ty/eleventy-cache-assets": "^2.3.0", "@11ty/eleventy-plugin-rss": "^1.1.2", "@11ty/eleventy-plugin-syntaxhighlight": "^4.0.0", + "@google-cloud/appengine-admin": "2.1.2", "@google-cloud/cloudbuild": "^2.6.0", "@google-cloud/error-reporting": "^2.0.4", "@google-cloud/storage": "^6.7.0", @@ -258,127 +259,127 @@ } }, "node_modules/@algolia/cache-browser-local-storage": { - "version": "4.16.0", - "resolved": "https://registry.npmjs.org/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.16.0.tgz", - "integrity": "sha512-jVrk0YB3tjOhD5/lhBtYCVCeLjZmVpf2kdi4puApofytf/R0scjWz0GdozlW4HhU+Prxmt/c9ge4QFjtv5OAzQ==", + "version": "4.17.0", + "resolved": "https://registry.npmjs.org/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.17.0.tgz", + "integrity": "sha512-myRSRZDIMYB8uCkO+lb40YKiYHi0fjpWRtJpR/dgkaiBlSD0plRyB6lLOh1XIfmMcSeBOqDE7y9m8xZMrXYfyQ==", "dependencies": { - "@algolia/cache-common": "4.16.0" + "@algolia/cache-common": "4.17.0" } }, "node_modules/@algolia/cache-common": { - "version": "4.16.0", - "resolved": "https://registry.npmjs.org/@algolia/cache-common/-/cache-common-4.16.0.tgz", - "integrity": "sha512-4iHjkSYQYw46pITrNQgXXhvUmcekI8INz1m+SzmqLX8jexSSy4Ky4zfGhZzhhhLHXUP3+x/PK/c0qPjxEvRwKQ==" + "version": "4.17.0", + "resolved": "https://registry.npmjs.org/@algolia/cache-common/-/cache-common-4.17.0.tgz", + "integrity": "sha512-g8mXzkrcUBIPZaulAuqE7xyHhLAYAcF2xSch7d9dABheybaU3U91LjBX6eJTEB7XVhEsgK4Smi27vWtAJRhIKQ==" }, "node_modules/@algolia/cache-in-memory": { - "version": "4.16.0", - "resolved": "https://registry.npmjs.org/@algolia/cache-in-memory/-/cache-in-memory-4.16.0.tgz", - "integrity": "sha512-p7RYykvA6Ip6QENxrh99nOD77otVh1sJRivcgcVpnjoZb5sIN3t33eUY1DpB9QSBizcrW+qk19rNkdnZ43a+PQ==", + "version": "4.17.0", + "resolved": "https://registry.npmjs.org/@algolia/cache-in-memory/-/cache-in-memory-4.17.0.tgz", + "integrity": "sha512-PT32ciC/xI8z919d0oknWVu3kMfTlhQn3MKxDln3pkn+yA7F7xrxSALysxquv+MhFfNAcrtQ/oVvQVBAQSHtdw==", "dependencies": { - "@algolia/cache-common": "4.16.0" + "@algolia/cache-common": "4.17.0" } }, "node_modules/@algolia/client-account": { - "version": "4.16.0", - "resolved": "https://registry.npmjs.org/@algolia/client-account/-/client-account-4.16.0.tgz", - "integrity": "sha512-eydcfpdIyuWoKgUSz5iZ/L0wE/Wl7958kACkvTHLDNXvK/b8Z1zypoJavh6/km1ZNQmFpeYS2jrmq0kUSFn02w==", + "version": "4.17.0", + "resolved": "https://registry.npmjs.org/@algolia/client-account/-/client-account-4.17.0.tgz", + "integrity": "sha512-sSEHx9GA6m7wrlsSMNBGfyzlIfDT2fkz2u7jqfCCd6JEEwmxt8emGmxAU/0qBfbhRSuGvzojoLJlr83BSZAKjA==", "dependencies": { - "@algolia/client-common": "4.16.0", - "@algolia/client-search": "4.16.0", - "@algolia/transporter": "4.16.0" + "@algolia/client-common": "4.17.0", + "@algolia/client-search": "4.17.0", + "@algolia/transporter": "4.17.0" } }, "node_modules/@algolia/client-analytics": { - "version": "4.16.0", - "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-4.16.0.tgz", - "integrity": "sha512-cONWXH3BfilgdlCofUm492bJRWtpBLVW/hsUlfoFtiX1u05xoBP7qeiDwh9RR+4pSLHLodYkHAf5U4honQ55Qg==", + "version": "4.17.0", + "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-4.17.0.tgz", + "integrity": "sha512-84ooP8QA3mQ958hQ9wozk7hFUbAO+81CX1CjAuerxBqjKIInh1fOhXKTaku05O/GHBvcfExpPLIQuSuLYziBXQ==", "dependencies": { - "@algolia/client-common": "4.16.0", - "@algolia/client-search": "4.16.0", - "@algolia/requester-common": "4.16.0", - "@algolia/transporter": "4.16.0" + "@algolia/client-common": "4.17.0", + "@algolia/client-search": "4.17.0", + "@algolia/requester-common": "4.17.0", + "@algolia/transporter": "4.17.0" } }, "node_modules/@algolia/client-common": { - "version": "4.16.0", - "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.16.0.tgz", - "integrity": "sha512-QVdR4019ukBH6f5lFr27W60trRxQF1SfS1qo0IP6gjsKhXhUVJuHxOCA6ArF87jrNkeuHEoRoDU+GlvaecNo8g==", + "version": "4.17.0", + "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.17.0.tgz", + "integrity": "sha512-jHMks0ZFicf8nRDn6ma8DNNsdwGgP/NKiAAL9z6rS7CymJ7L0+QqTJl3rYxRW7TmBhsUH40wqzmrG6aMIN/DrQ==", "dependencies": { - "@algolia/requester-common": "4.16.0", - "@algolia/transporter": "4.16.0" + "@algolia/requester-common": "4.17.0", + "@algolia/transporter": "4.17.0" } }, "node_modules/@algolia/client-personalization": { - "version": "4.16.0", - "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-4.16.0.tgz", - "integrity": "sha512-irtLafssDGPuhYqIwxqOxiWlVYvrsBD+EMA1P9VJtkKi3vSNBxiWeQ0f0Tn53cUNdSRNEssfoEH84JL97SV2SQ==", + "version": "4.17.0", + "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-4.17.0.tgz", + "integrity": "sha512-RMzN4dZLIta1YuwT7QC9o+OeGz2cU6eTOlGNE/6RcUBLOU3l9tkCOdln5dPE2jp8GZXPl2yk54b2nSs1+pAjqw==", "dependencies": { - "@algolia/client-common": "4.16.0", - "@algolia/requester-common": "4.16.0", - "@algolia/transporter": "4.16.0" + "@algolia/client-common": "4.17.0", + "@algolia/requester-common": "4.17.0", + "@algolia/transporter": "4.17.0" } }, "node_modules/@algolia/client-search": { - "version": "4.16.0", - "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-4.16.0.tgz", - "integrity": "sha512-xsfrAE1jO/JDh1wFrRz+alVyW+aA6qnkzmbWWWZWEgVF3EaFqzIf9r1l/aDtDdBtNTNhX9H3Lg31+BRtd5izQA==", + "version": "4.17.0", + "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-4.17.0.tgz", + "integrity": "sha512-x4P2wKrrRIXszT8gb7eWsMHNNHAJs0wE7/uqbufm4tZenAp+hwU/hq5KVsY50v+PfwM0LcDwwn/1DroujsTFoA==", "dependencies": { - "@algolia/client-common": "4.16.0", - "@algolia/requester-common": "4.16.0", - "@algolia/transporter": "4.16.0" + "@algolia/client-common": "4.17.0", + "@algolia/requester-common": "4.17.0", + "@algolia/transporter": "4.17.0" } }, "node_modules/@algolia/logger-common": { - "version": "4.16.0", - "resolved": "https://registry.npmjs.org/@algolia/logger-common/-/logger-common-4.16.0.tgz", - "integrity": "sha512-U9H8uCzSDuePJmbnjjTX21aPDRU6x74Tdq3dJmdYu2+pISx02UeBJm4kSgc9RW5jcR5j35G9gnjHY9Q3ngWbyQ==" + "version": "4.17.0", + "resolved": "https://registry.npmjs.org/@algolia/logger-common/-/logger-common-4.17.0.tgz", + "integrity": "sha512-DGuoZqpTmIKJFDeyAJ7M8E/LOenIjWiOsg1XJ1OqAU/eofp49JfqXxbfgctlVZVmDABIyOz8LqEoJ6ZP4DTyvw==" }, "node_modules/@algolia/logger-console": { - "version": "4.16.0", - "resolved": "https://registry.npmjs.org/@algolia/logger-console/-/logger-console-4.16.0.tgz", - "integrity": "sha512-+qymusiM+lPZKrkf0tDjCQA158eEJO2IU+Nr/sJ9TFyI/xkFPjNPzw/Qbc8Iy/xcOXGlc6eMgmyjtVQqAWq6UA==", + "version": "4.17.0", + "resolved": "https://registry.npmjs.org/@algolia/logger-console/-/logger-console-4.17.0.tgz", + "integrity": "sha512-zMPvugQV/gbXUvWBCzihw6m7oxIKp48w37QBIUu/XqQQfxhjoOE9xyfJr1KldUt5FrYOKZJVsJaEjTsu+bIgQg==", "dependencies": { - "@algolia/logger-common": "4.16.0" + "@algolia/logger-common": "4.17.0" } }, "node_modules/@algolia/requester-browser-xhr": { - "version": "4.16.0", - "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.16.0.tgz", - "integrity": "sha512-gK+kvs6LHl/PaOJfDuwjkopNbG1djzFLsVBklGBsSU6h6VjFkxIpo6Qq80IK14p9cplYZfhfaL12va6Q9p3KVQ==", + "version": "4.17.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.17.0.tgz", + "integrity": "sha512-aSOX/smauyTkP21Pf52pJ1O2LmNFJ5iHRIzEeTh0mwBeADO4GdG94cAWDILFA9rNblq/nK3EDh3+UyHHjplZ1A==", "dependencies": { - "@algolia/requester-common": "4.16.0" + "@algolia/requester-common": "4.17.0" } }, "node_modules/@algolia/requester-common": { - "version": "4.16.0", - "resolved": "https://registry.npmjs.org/@algolia/requester-common/-/requester-common-4.16.0.tgz", - "integrity": "sha512-3Zmcs/iMubcm4zqZ3vZG6Zum8t+hMWxGMzo0/uY2BD8o9q5vMxIYI0c4ocdgQjkXcix189WtZNkgjSOBzSbkdw==" + "version": "4.17.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-common/-/requester-common-4.17.0.tgz", + "integrity": "sha512-XJjmWFEUlHu0ijvcHBoixuXfEoiRUdyzQM6YwTuB8usJNIgShua8ouFlRWF8iCeag0vZZiUm4S2WCVBPkdxFgg==" }, "node_modules/@algolia/requester-node-http": { - "version": "4.16.0", - "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-4.16.0.tgz", - "integrity": "sha512-L8JxM2VwZzh8LJ1Zb8TFS6G3icYsCKZsdWW+ahcEs1rGWmyk9SybsOe1MLnjonGBaqPWJkn9NjS7mRdjEmBtKA==", + "version": "4.17.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-4.17.0.tgz", + "integrity": "sha512-bpb/wDA1aC6WxxM8v7TsFspB7yBN3nqCGs2H1OADolQR/hiAIjAxusbuMxVbRFOdaUvAIqioIIkWvZdpYNIn8w==", "dependencies": { - "@algolia/requester-common": "4.16.0" + "@algolia/requester-common": "4.17.0" } }, "node_modules/@algolia/transporter": { - "version": "4.16.0", - "resolved": "https://registry.npmjs.org/@algolia/transporter/-/transporter-4.16.0.tgz", - "integrity": "sha512-H9BVB2EAjT65w7XGBNf5drpsW39x2aSZ942j4boSAAJPPlLmjtj5IpAP7UAtsV8g9Beslonh0bLa1XGmE/P0BA==", + "version": "4.17.0", + "resolved": "https://registry.npmjs.org/@algolia/transporter/-/transporter-4.17.0.tgz", + "integrity": "sha512-6xL6H6fe+Fi0AEP3ziSgC+G04RK37iRb4uUUqVAH9WPYFI8g+LYFq6iv5HS8Cbuc5TTut+Bwj6G+dh/asdb9uA==", "dependencies": { - "@algolia/cache-common": "4.16.0", - "@algolia/logger-common": "4.16.0", - "@algolia/requester-common": "4.16.0" + "@algolia/cache-common": "4.17.0", + "@algolia/logger-common": "4.17.0", + "@algolia/requester-common": "4.17.0" } }, "node_modules/@ampproject/remapping": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", - "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", + "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", "dev": true, "dependencies": { - "@jridgewell/gen-mapping": "^0.1.0", + "@jridgewell/gen-mapping": "^0.3.0", "@jridgewell/trace-mapping": "^0.3.9" }, "engines": { @@ -441,9 +442,9 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", - "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.21.4.tgz", + "integrity": "sha512-LYvhNKfwWSPpocw8GI7gpK2nq3HSDuEPC/uSYaALSJu9xjsalaaYFOq0Pwt5KmVqwEbZlDu81aLXwBOmD/Fv9g==", "dev": true, "dependencies": { "@babel/highlight": "^7.18.6" @@ -453,30 +454,30 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.21.0.tgz", - "integrity": "sha512-gMuZsmsgxk/ENC3O/fRw5QY8A9/uxQbbCEypnLIiYYc/qVJtEV7ouxC3EllIIwNzMqAQee5tanFabWsUOutS7g==", + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.21.4.tgz", + "integrity": "sha512-/DYyDpeCfaVinT40FPGdkkb+lYSKvsVuMjDAG7jPOWWiM1ibOaB9CXJAlc4d1QpP/U2q2P9jbrSlClKSErd55g==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.21.3", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.21.3.tgz", - "integrity": "sha512-qIJONzoa/qiHghnm0l1n4i/6IIziDpzqc36FBs4pzMhDUraHqponwJLiAKm1hGLP3OSB/TVNz6rMwVGpwxxySw==", + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.21.4.tgz", + "integrity": "sha512-qt/YV149Jman/6AfmlxJ04LMIu8bMoyl3RB91yTFrxQmgbrSvQMy7cI8Q62FHx1t8wJ8B5fu0UDoLwHAhUo1QA==", "dev": true, "dependencies": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.21.3", - "@babel/helper-compilation-targets": "^7.20.7", + "@babel/code-frame": "^7.21.4", + "@babel/generator": "^7.21.4", + "@babel/helper-compilation-targets": "^7.21.4", "@babel/helper-module-transforms": "^7.21.2", "@babel/helpers": "^7.21.0", - "@babel/parser": "^7.21.3", + "@babel/parser": "^7.21.4", "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.3", - "@babel/types": "^7.21.3", + "@babel/traverse": "^7.21.4", + "@babel/types": "^7.21.4", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -501,12 +502,12 @@ } }, "node_modules/@babel/generator": { - "version": "7.21.3", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.21.3.tgz", - "integrity": "sha512-QS3iR1GYC/YGUnW7IdggFeN5c1poPUurnGttOV/bZgPGV+izC/D8HnD6DLwod0fsatNyVn1G3EVWMYIF0nHbeA==", + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.21.4.tgz", + "integrity": "sha512-NieM3pVIYW2SwGzKoqfPrQsf4xGs9M9AIG3ThppsSRmO+m7eQhmI6amajKMUeIO37wFfsvnvcxQFx6x6iqxDnA==", "dev": true, "dependencies": { - "@babel/types": "^7.21.3", + "@babel/types": "^7.21.4", "@jridgewell/gen-mapping": "^0.3.2", "@jridgewell/trace-mapping": "^0.3.17", "jsesc": "^2.5.1" @@ -515,28 +516,14 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/generator/node_modules/@jridgewell/gen-mapping": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", - "dev": true, - "dependencies": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.20.7.tgz", - "integrity": "sha512-4tGORmfQcrc+bvrjb5y3dG9Mx1IOZjsHqQVUz7XCNHO+iTmqxWnVg3KRygjGmpRLJGdQSKuvFinbIb0CnZwHAQ==", + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.21.4.tgz", + "integrity": "sha512-Fa0tTuOXZ1iL8IeDFUWCzjZcn+sJGd9RZdH9esYVjEejGmzf+FFYQpMi/kZUk2kPy/q1H3/GPw7np8qar/stfg==", "dev": true, "dependencies": { - "@babel/compat-data": "^7.20.5", - "@babel/helper-validator-option": "^7.18.6", + "@babel/compat-data": "^7.21.4", + "@babel/helper-validator-option": "^7.21.0", "browserslist": "^4.21.3", "lru-cache": "^5.1.1", "semver": "^6.3.0" @@ -592,12 +579,12 @@ } }, "node_modules/@babel/helper-module-imports": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", - "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.21.4.tgz", + "integrity": "sha512-orajc5T2PsRYUN3ZryCEFeMDYwyw09c/pZeaQEZPH0MpKzSvn3e0uXsDBu3k03VI+9DBiRo+l22BfKTpKwa/Wg==", "dev": true, "dependencies": { - "@babel/types": "^7.18.6" + "@babel/types": "^7.21.4" }, "engines": { "node": ">=6.9.0" @@ -777,9 +764,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.21.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.3.tgz", - "integrity": "sha512-lobG0d7aOfQRXh8AyklEAgZGvA4FShxo6xQbUrrT/cNBPUdIDojlokwJsQyCC/eKia7ifqM0yP+2DRZ4WKw2RQ==", + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.4.tgz", + "integrity": "sha512-alVJj7k7zIxqBZ7BTRhz0IqJFxW1VJbm6N8JbcYhQ186df9ZBPbZBmWSqAMXwHGsCJdYks7z/voa3ibiS5bCIw==", "bin": { "parser": "bin/babel-parser.js" }, @@ -904,19 +891,19 @@ } }, "node_modules/@babel/traverse": { - "version": "7.21.3", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.21.3.tgz", - "integrity": "sha512-XLyopNeaTancVitYZe2MlUEvgKb6YVVPXzofHgqHijCImG33b/uTurMS488ht/Hbsb2XK3U2BnSTxKVNGV3nGQ==", + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.21.4.tgz", + "integrity": "sha512-eyKrRHKdyZxqDm+fV1iqL9UAHMoIg0nDaGqfIOd8rKH17m5snv7Gn4qgjBoFfLz9APvjFU/ICT00NVCv1Epp8Q==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.21.3", + "@babel/code-frame": "^7.21.4", + "@babel/generator": "^7.21.4", "@babel/helper-environment-visitor": "^7.18.9", "@babel/helper-function-name": "^7.21.0", "@babel/helper-hoist-variables": "^7.18.6", "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/parser": "^7.21.3", - "@babel/types": "^7.21.3", + "@babel/parser": "^7.21.4", + "@babel/types": "^7.21.4", "debug": "^4.1.0", "globals": "^11.1.0" }, @@ -925,9 +912,9 @@ } }, "node_modules/@babel/types": { - "version": "7.21.3", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.21.3.tgz", - "integrity": "sha512-sBGdETxC+/M4o/zKC0sl6sjWv62WFR/uzxrJ6uYyMLZOUlPnwzw0tKgVHOXxaAd5l2g8pEDM5RZ495GPQI77kg==", + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.21.4.tgz", + "integrity": "sha512-rU2oY501qDxE8Pyo7i/Orqma4ziCOrby0/9mvbDUGEfvZjb279Nk9k19e2fiCxHbRRpY2ZyrgW1eq22mvmOIzA==", "dependencies": { "@babel/helper-string-parser": "^7.19.4", "@babel/helper-validator-identifier": "^7.19.1", @@ -978,6 +965,18 @@ "node": "^10.12.0 || >=12.0.0" } }, + "node_modules/@eslint/eslintrc/node_modules/acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/@eslint/eslintrc/node_modules/ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -1003,6 +1002,29 @@ "sprintf-js": "~1.0.2" } }, + "node_modules/@eslint/eslintrc/node_modules/eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@eslint/eslintrc/node_modules/espree": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", + "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", + "dev": true, + "dependencies": { + "acorn": "^7.4.0", + "acorn-jsx": "^5.3.1", + "eslint-visitor-keys": "^1.3.0" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, "node_modules/@eslint/eslintrc/node_modules/globals": { "version": "13.20.0", "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", @@ -1058,6 +1080,17 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/@google-cloud/appengine-admin": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@google-cloud/appengine-admin/-/appengine-admin-2.1.2.tgz", + "integrity": "sha512-ksR0Z64OhB5PDg9TgopWEUNt74hWP4Bs6IviFQGv3xAYQR43UqBWINPhYrxSkzIYol9L4PDyUoA1Dl1N4D0CXg==", + "dependencies": { + "google-gax": "^3.5.2" + }, + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/@google-cloud/cloudbuild": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/@google-cloud/cloudbuild/-/cloudbuild-2.6.0.tgz", @@ -1069,6 +1102,284 @@ "node": ">=10" } }, + "node_modules/@google-cloud/cloudbuild/node_modules/@grpc/grpc-js": { + "version": "1.6.12", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.6.12.tgz", + "integrity": "sha512-JmvQ03OTSpVd9JTlj/K3IWHSz4Gk/JMLUTtW7Zb0KvO1LcOYGATh5cNuRYzCAeDR3O8wq+q8FZe97eO9MBrkUw==", + "dependencies": { + "@grpc/proto-loader": "^0.7.0", + "@types/node": ">=12.12.47" + }, + "engines": { + "node": "^8.13.0 || >=10.10.0" + } + }, + "node_modules/@google-cloud/cloudbuild/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@google-cloud/cloudbuild/node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/@google-cloud/cloudbuild/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@google-cloud/cloudbuild/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/@google-cloud/cloudbuild/node_modules/gaxios": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-4.3.3.tgz", + "integrity": "sha512-gSaYYIO1Y3wUtdfHmjDUZ8LWaxJQpiavzbF5Kq53akSzvmVg0RfyOcFDbO1KJ/KCGRFz2qG+lS81F0nkr7cRJA==", + "dependencies": { + "abort-controller": "^3.0.0", + "extend": "^3.0.2", + "https-proxy-agent": "^5.0.0", + "is-stream": "^2.0.0", + "node-fetch": "^2.6.7" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@google-cloud/cloudbuild/node_modules/gcp-metadata": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-4.3.1.tgz", + "integrity": "sha512-x850LS5N7V1F3UcV7PoupzGsyD6iVwTVvsh3tbXfkctZnBnjW5yu5z1/3k3SehF7TyoTIe78rJs02GMMy+LF+A==", + "dependencies": { + "gaxios": "^4.0.0", + "json-bigint": "^1.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@google-cloud/cloudbuild/node_modules/google-auth-library": { + "version": "7.14.1", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-7.14.1.tgz", + "integrity": "sha512-5Rk7iLNDFhFeBYc3s8l1CqzbEBcdhwR193RlD4vSNFajIcINKI8W8P0JLmBpwymHqqWbX34pJDQu39cSy/6RsA==", + "dependencies": { + "arrify": "^2.0.0", + "base64-js": "^1.3.0", + "ecdsa-sig-formatter": "^1.0.11", + "fast-text-encoding": "^1.0.0", + "gaxios": "^4.0.0", + "gcp-metadata": "^4.2.0", + "gtoken": "^5.0.4", + "jws": "^4.0.0", + "lru-cache": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@google-cloud/cloudbuild/node_modules/google-gax": { + "version": "2.30.5", + "resolved": "https://registry.npmjs.org/google-gax/-/google-gax-2.30.5.tgz", + "integrity": "sha512-Jey13YrAN2hfpozHzbtrwEfEHdStJh1GwaQ2+Akh1k0Tv/EuNVSuBtHZoKSBm5wBMvNsxTsEIZ/152NrYyZgxQ==", + "dependencies": { + "@grpc/grpc-js": "~1.6.0", + "@grpc/proto-loader": "^0.6.12", + "@types/long": "^4.0.0", + "abort-controller": "^3.0.0", + "duplexify": "^4.0.0", + "fast-text-encoding": "^1.0.3", + "google-auth-library": "^7.14.0", + "is-stream-ended": "^0.1.4", + "node-fetch": "^2.6.1", + "object-hash": "^3.0.0", + "proto3-json-serializer": "^0.1.8", + "protobufjs": "6.11.3", + "retry-request": "^4.0.0" + }, + "bin": { + "compileProtos": "build/tools/compileProtos.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@google-cloud/cloudbuild/node_modules/google-gax/node_modules/@grpc/proto-loader": { + "version": "0.6.13", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.6.13.tgz", + "integrity": "sha512-FjxPYDRTn6Ec3V0arm1FtSpmP6V50wuph2yILpyvTKzjc76oDdoihXqM1DzOW5ubvCC8GivfCnNtfaRE8myJ7g==", + "dependencies": { + "@types/long": "^4.0.1", + "lodash.camelcase": "^4.3.0", + "long": "^4.0.0", + "protobufjs": "^6.11.3", + "yargs": "^16.2.0" + }, + "bin": { + "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@google-cloud/cloudbuild/node_modules/google-p12-pem": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-3.1.4.tgz", + "integrity": "sha512-HHuHmkLgwjdmVRngf5+gSmpkyaRI6QmOg77J8tkNBHhNEI62sGHyw4/+UkgyZEI7h84NbWprXDJ+sa3xOYFvTg==", + "dependencies": { + "node-forge": "^1.3.1" + }, + "bin": { + "gp12-pem": "build/src/bin/gp12-pem.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@google-cloud/cloudbuild/node_modules/gtoken": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-5.3.2.tgz", + "integrity": "sha512-gkvEKREW7dXWF8NV8pVrKfW7WqReAmjjkMBh6lNCCGOM4ucS0r0YyXXl0r/9Yj8wcW/32ISkfc8h5mPTDbtifQ==", + "dependencies": { + "gaxios": "^4.0.0", + "google-p12-pem": "^3.1.3", + "jws": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@google-cloud/cloudbuild/node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@google-cloud/cloudbuild/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@google-cloud/cloudbuild/node_modules/proto3-json-serializer": { + "version": "0.1.9", + "resolved": "https://registry.npmjs.org/proto3-json-serializer/-/proto3-json-serializer-0.1.9.tgz", + "integrity": "sha512-A60IisqvnuI45qNRygJjrnNjX2TMdQGMY+57tR3nul3ZgO2zXkR9OGR8AXxJhkqx84g0FTnrfi3D5fWMSdANdQ==", + "dependencies": { + "protobufjs": "^6.11.2" + } + }, + "node_modules/@google-cloud/cloudbuild/node_modules/protobufjs": { + "version": "6.11.3", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.3.tgz", + "integrity": "sha512-xL96WDdCZYdU7Slin569tFX712BxsxslWwAfAhCYjQKGTq7dAU91Lomy6nLLhh/dyGhk/YH4TwTSRxTzhuHyZg==", + "hasInstallScript": true, + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/long": "^4.0.1", + "@types/node": ">=13.7.0", + "long": "^4.0.0" + }, + "bin": { + "pbjs": "bin/pbjs", + "pbts": "bin/pbts" + } + }, + "node_modules/@google-cloud/cloudbuild/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/@google-cloud/cloudbuild/node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "engines": { + "node": ">=10" + } + }, + "node_modules/@google-cloud/cloudbuild/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/@google-cloud/cloudbuild/node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@google-cloud/cloudbuild/node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "engines": { + "node": ">=10" + } + }, "node_modules/@google-cloud/common": { "version": "3.10.0", "resolved": "https://registry.npmjs.org/@google-cloud/common/-/common-3.10.0.tgz", @@ -1240,105 +1551,149 @@ "node": ">=10" } }, - "node_modules/@google-cloud/storage": { - "version": "6.9.4", - "resolved": "https://registry.npmjs.org/@google-cloud/storage/-/storage-6.9.4.tgz", - "integrity": "sha512-5Li+0xRJ8wgc+vlf7Tgew8COKEJgRzRmC5ozdSYaBj7BK+X39aPPBP6ROsDTiCZ0MpAg7dxIc+HhKiCvQDplXQ==", + "node_modules/@google-cloud/secret-manager/node_modules/@grpc/grpc-js": { + "version": "1.6.12", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.6.12.tgz", + "integrity": "sha512-JmvQ03OTSpVd9JTlj/K3IWHSz4Gk/JMLUTtW7Zb0KvO1LcOYGATh5cNuRYzCAeDR3O8wq+q8FZe97eO9MBrkUw==", + "dev": true, "dependencies": { - "@google-cloud/paginator": "^3.0.7", - "@google-cloud/projectify": "^3.0.0", - "@google-cloud/promisify": "^3.0.0", - "abort-controller": "^3.0.0", - "async-retry": "^1.3.3", - "compressible": "^2.0.12", - "duplexify": "^4.0.0", - "ent": "^2.2.0", - "extend": "^3.0.2", - "gaxios": "^5.0.0", - "google-auth-library": "^8.0.1", - "mime": "^3.0.0", - "mime-types": "^2.0.8", - "p-limit": "^3.0.1", - "retry-request": "^5.0.0", - "teeny-request": "^8.0.0", - "uuid": "^8.0.0" + "@grpc/proto-loader": "^0.7.0", + "@types/node": ">=12.12.47" }, "engines": { - "node": ">=12" + "node": "^8.13.0 || >=10.10.0" } }, - "node_modules/@google-cloud/storage/node_modules/@google-cloud/projectify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@google-cloud/projectify/-/projectify-3.0.0.tgz", - "integrity": "sha512-HRkZsNmjScY6Li8/kb70wjGlDDyLkVk3KvoEo9uIoxSjYLJasGiCch9+PqRVDOCGUFvEIqyogl+BeqILL4OJHA==", + "node_modules/@google-cloud/secret-manager/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, "engines": { - "node": ">=12.0.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@google-cloud/storage/node_modules/@google-cloud/promisify": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@google-cloud/promisify/-/promisify-3.0.1.tgz", - "integrity": "sha512-z1CjRjtQyBOYL+5Qr9DdYIfrdLBe746jRTYfaYU6MeXkqp7UfYs/jX16lFFVzZ7PGEJvqZNqYUEtb1mvDww4pA==", - "engines": { - "node": ">=12" + "node_modules/@google-cloud/secret-manager/node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" } }, - "node_modules/@google-cloud/storage/node_modules/retry-request": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/retry-request/-/retry-request-5.0.2.tgz", - "integrity": "sha512-wfI3pk7EE80lCIXprqh7ym48IHYdwmAAzESdbU8Q9l7pnRCk9LEhpbOTNKjz6FARLm/Bl5m+4F0ABxOkYUujSQ==", + "node_modules/@google-cloud/secret-manager/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, "dependencies": { - "debug": "^4.1.1", - "extend": "^3.0.2" + "color-name": "~1.1.4" }, "engines": { - "node": ">=12" + "node": ">=7.0.0" } }, - "node_modules/@google-cloud/storage/node_modules/teeny-request": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/teeny-request/-/teeny-request-8.0.3.tgz", - "integrity": "sha512-jJZpA5He2y52yUhA7pyAGZlgQpcB+xLjcN0eUFxr9c8hP/H7uOXbBNVo/O0C/xVfJLJs680jvkFgVJEEvk9+ww==", + "node_modules/@google-cloud/secret-manager/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@google-cloud/secret-manager/node_modules/gaxios": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-4.3.3.tgz", + "integrity": "sha512-gSaYYIO1Y3wUtdfHmjDUZ8LWaxJQpiavzbF5Kq53akSzvmVg0RfyOcFDbO1KJ/KCGRFz2qG+lS81F0nkr7cRJA==", + "dev": true, "dependencies": { - "http-proxy-agent": "^5.0.0", + "abort-controller": "^3.0.0", + "extend": "^3.0.2", "https-proxy-agent": "^5.0.0", - "node-fetch": "^2.6.1", - "stream-events": "^1.0.5", - "uuid": "^9.0.0" + "is-stream": "^2.0.0", + "node-fetch": "^2.6.7" }, "engines": { - "node": ">=12" + "node": ">=10" } }, - "node_modules/@google-cloud/storage/node_modules/teeny-request/node_modules/uuid": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz", - "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==", - "bin": { - "uuid": "dist/bin/uuid" + "node_modules/@google-cloud/secret-manager/node_modules/gcp-metadata": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-4.3.1.tgz", + "integrity": "sha512-x850LS5N7V1F3UcV7PoupzGsyD6iVwTVvsh3tbXfkctZnBnjW5yu5z1/3k3SehF7TyoTIe78rJs02GMMy+LF+A==", + "dev": true, + "dependencies": { + "gaxios": "^4.0.0", + "json-bigint": "^1.0.0" + }, + "engines": { + "node": ">=10" } }, - "node_modules/@grpc/grpc-js": { - "version": "1.6.12", - "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.6.12.tgz", - "integrity": "sha512-JmvQ03OTSpVd9JTlj/K3IWHSz4Gk/JMLUTtW7Zb0KvO1LcOYGATh5cNuRYzCAeDR3O8wq+q8FZe97eO9MBrkUw==", + "node_modules/@google-cloud/secret-manager/node_modules/google-auth-library": { + "version": "7.14.1", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-7.14.1.tgz", + "integrity": "sha512-5Rk7iLNDFhFeBYc3s8l1CqzbEBcdhwR193RlD4vSNFajIcINKI8W8P0JLmBpwymHqqWbX34pJDQu39cSy/6RsA==", + "dev": true, "dependencies": { - "@grpc/proto-loader": "^0.7.0", - "@types/node": ">=12.12.47" + "arrify": "^2.0.0", + "base64-js": "^1.3.0", + "ecdsa-sig-formatter": "^1.0.11", + "fast-text-encoding": "^1.0.0", + "gaxios": "^4.0.0", + "gcp-metadata": "^4.2.0", + "gtoken": "^5.0.4", + "jws": "^4.0.0", + "lru-cache": "^6.0.0" }, "engines": { - "node": "^8.13.0 || >=10.10.0" + "node": ">=10" } }, - "node_modules/@grpc/grpc-js/node_modules/@grpc/proto-loader": { - "version": "0.7.6", - "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.6.tgz", - "integrity": "sha512-QyAXR8Hyh7uMDmveWxDSUcJr9NAWaZ2I6IXgAYvQmfflwouTM+rArE2eEaCtLlRqO81j7pRLCt81IefUei6Zbw==", + "node_modules/@google-cloud/secret-manager/node_modules/google-gax": { + "version": "2.30.5", + "resolved": "https://registry.npmjs.org/google-gax/-/google-gax-2.30.5.tgz", + "integrity": "sha512-Jey13YrAN2hfpozHzbtrwEfEHdStJh1GwaQ2+Akh1k0Tv/EuNVSuBtHZoKSBm5wBMvNsxTsEIZ/152NrYyZgxQ==", + "dev": true, + "dependencies": { + "@grpc/grpc-js": "~1.6.0", + "@grpc/proto-loader": "^0.6.12", + "@types/long": "^4.0.0", + "abort-controller": "^3.0.0", + "duplexify": "^4.0.0", + "fast-text-encoding": "^1.0.3", + "google-auth-library": "^7.14.0", + "is-stream-ended": "^0.1.4", + "node-fetch": "^2.6.1", + "object-hash": "^3.0.0", + "proto3-json-serializer": "^0.1.8", + "protobufjs": "6.11.3", + "retry-request": "^4.0.0" + }, + "bin": { + "compileProtos": "build/tools/compileProtos.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@google-cloud/secret-manager/node_modules/google-gax/node_modules/@grpc/proto-loader": { + "version": "0.6.13", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.6.13.tgz", + "integrity": "sha512-FjxPYDRTn6Ec3V0arm1FtSpmP6V50wuph2yILpyvTKzjc76oDdoihXqM1DzOW5ubvCC8GivfCnNtfaRE8myJ7g==", + "dev": true, "dependencies": { "@types/long": "^4.0.1", "lodash.camelcase": "^4.3.0", "long": "^4.0.0", - "protobufjs": "^7.0.0", + "protobufjs": "^6.11.3", "yargs": "^16.2.0" }, "bin": { @@ -1348,50 +1703,73 @@ "node": ">=6" } }, - "node_modules/@grpc/grpc-js/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/@google-cloud/secret-manager/node_modules/google-p12-pem": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-3.1.4.tgz", + "integrity": "sha512-HHuHmkLgwjdmVRngf5+gSmpkyaRI6QmOg77J8tkNBHhNEI62sGHyw4/+UkgyZEI7h84NbWprXDJ+sa3xOYFvTg==", + "dev": true, "dependencies": { - "color-convert": "^2.0.1" + "node-forge": "^1.3.1" }, - "engines": { - "node": ">=8" + "bin": { + "gp12-pem": "build/src/bin/gp12-pem.js" }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "engines": { + "node": ">=10" } }, - "node_modules/@grpc/grpc-js/node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "node_modules/@google-cloud/secret-manager/node_modules/gtoken": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-5.3.2.tgz", + "integrity": "sha512-gkvEKREW7dXWF8NV8pVrKfW7WqReAmjjkMBh6lNCCGOM4ucS0r0YyXXl0r/9Yj8wcW/32ISkfc8h5mPTDbtifQ==", + "dev": true, "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" + "gaxios": "^4.0.0", + "google-p12-pem": "^3.1.3", + "jws": "^4.0.0" + }, + "engines": { + "node": ">=10" } }, - "node_modules/@grpc/grpc-js/node_modules/color-convert": { + "node_modules/@google-cloud/secret-manager/node_modules/is-stream": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@google-cloud/secret-manager/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, "dependencies": { - "color-name": "~1.1.4" + "yallist": "^4.0.0" }, "engines": { - "node": ">=7.0.0" + "node": ">=10" } }, - "node_modules/@grpc/grpc-js/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + "node_modules/@google-cloud/secret-manager/node_modules/proto3-json-serializer": { + "version": "0.1.9", + "resolved": "https://registry.npmjs.org/proto3-json-serializer/-/proto3-json-serializer-0.1.9.tgz", + "integrity": "sha512-A60IisqvnuI45qNRygJjrnNjX2TMdQGMY+57tR3nul3ZgO2zXkR9OGR8AXxJhkqx84g0FTnrfi3D5fWMSdANdQ==", + "dev": true, + "dependencies": { + "protobufjs": "^6.11.2" + } }, - "node_modules/@grpc/grpc-js/node_modules/protobufjs": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.2.tgz", - "integrity": "sha512-++PrQIjrom+bFDPpfmqXfAGSQs40116JRrqqyf53dymUMvvb5d/LMRyicRoF1AUKoXVS1/IgJXlEgcpr4gTF3Q==", + "node_modules/@google-cloud/secret-manager/node_modules/protobufjs": { + "version": "6.11.3", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.3.tgz", + "integrity": "sha512-xL96WDdCZYdU7Slin569tFX712BxsxslWwAfAhCYjQKGTq7dAU91Lomy6nLLhh/dyGhk/YH4TwTSRxTzhuHyZg==", + "dev": true, "hasInstallScript": true, "dependencies": { "@protobufjs/aspromise": "^1.1.2", @@ -1404,22 +1782,20 @@ "@protobufjs/path": "^1.1.2", "@protobufjs/pool": "^1.1.0", "@protobufjs/utf8": "^1.1.0", + "@types/long": "^4.0.1", "@types/node": ">=13.7.0", - "long": "^5.0.0" + "long": "^4.0.0" }, - "engines": { - "node": ">=12.0.0" + "bin": { + "pbjs": "bin/pbjs", + "pbts": "bin/pbts" } }, - "node_modules/@grpc/grpc-js/node_modules/protobufjs/node_modules/long": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/long/-/long-5.2.1.tgz", - "integrity": "sha512-GKSNGeNAtw8IryjjkhZxuKB3JzlcLTwjtiQCHKvqQet81I93kXslhDQruGI/QsddO83mcDToBVy7GqGS/zYf/A==" - }, - "node_modules/@grpc/grpc-js/node_modules/wrap-ansi": { + "node_modules/@google-cloud/secret-manager/node_modules/wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -1432,18 +1808,26 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/@grpc/grpc-js/node_modules/y18n": { + "node_modules/@google-cloud/secret-manager/node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, "engines": { "node": ">=10" } }, - "node_modules/@grpc/grpc-js/node_modules/yargs": { + "node_modules/@google-cloud/secret-manager/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/@google-cloud/secret-manager/node_modules/yargs": { "version": "16.2.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, "dependencies": { "cliui": "^7.0.2", "escalade": "^3.1.1", @@ -1457,23 +1841,114 @@ "node": ">=10" } }, - "node_modules/@grpc/grpc-js/node_modules/yargs-parser": { + "node_modules/@google-cloud/secret-manager/node_modules/yargs-parser": { "version": "20.2.9", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, "engines": { "node": ">=10" } }, + "node_modules/@google-cloud/storage": { + "version": "6.9.5", + "resolved": "https://registry.npmjs.org/@google-cloud/storage/-/storage-6.9.5.tgz", + "integrity": "sha512-fcLsDA8YKcGuqvhk0XTjJGVpG9dzs5Em8IcUjSjspYvERuHYqMy9CMChWapSjv3Lyw//exa3mv4nUxPlV93BnA==", + "dependencies": { + "@google-cloud/paginator": "^3.0.7", + "@google-cloud/projectify": "^3.0.0", + "@google-cloud/promisify": "^3.0.0", + "abort-controller": "^3.0.0", + "async-retry": "^1.3.3", + "compressible": "^2.0.12", + "duplexify": "^4.0.0", + "ent": "^2.2.0", + "extend": "^3.0.2", + "gaxios": "^5.0.0", + "google-auth-library": "^8.0.1", + "mime": "^3.0.0", + "mime-types": "^2.0.8", + "p-limit": "^3.0.1", + "retry-request": "^5.0.0", + "teeny-request": "^8.0.0", + "uuid": "^8.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@google-cloud/storage/node_modules/@google-cloud/projectify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@google-cloud/projectify/-/projectify-3.0.0.tgz", + "integrity": "sha512-HRkZsNmjScY6Li8/kb70wjGlDDyLkVk3KvoEo9uIoxSjYLJasGiCch9+PqRVDOCGUFvEIqyogl+BeqILL4OJHA==", + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/@google-cloud/storage/node_modules/@google-cloud/promisify": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@google-cloud/promisify/-/promisify-3.0.1.tgz", + "integrity": "sha512-z1CjRjtQyBOYL+5Qr9DdYIfrdLBe746jRTYfaYU6MeXkqp7UfYs/jX16lFFVzZ7PGEJvqZNqYUEtb1mvDww4pA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/@google-cloud/storage/node_modules/retry-request": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/retry-request/-/retry-request-5.0.2.tgz", + "integrity": "sha512-wfI3pk7EE80lCIXprqh7ym48IHYdwmAAzESdbU8Q9l7pnRCk9LEhpbOTNKjz6FARLm/Bl5m+4F0ABxOkYUujSQ==", + "dependencies": { + "debug": "^4.1.1", + "extend": "^3.0.2" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@google-cloud/storage/node_modules/teeny-request": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/teeny-request/-/teeny-request-8.0.3.tgz", + "integrity": "sha512-jJZpA5He2y52yUhA7pyAGZlgQpcB+xLjcN0eUFxr9c8hP/H7uOXbBNVo/O0C/xVfJLJs680jvkFgVJEEvk9+ww==", + "dependencies": { + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "node-fetch": "^2.6.1", + "stream-events": "^1.0.5", + "uuid": "^9.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@google-cloud/storage/node_modules/teeny-request/node_modules/uuid": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz", + "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/@grpc/grpc-js": { + "version": "1.8.14", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.8.14.tgz", + "integrity": "sha512-w84maJ6CKl5aApCMzFll0hxtFNT6or9WwMslobKaqWUEf1K+zhlL43bSQhFreyYWIWR+Z0xnVFC1KtLm4ZpM/A==", + "dependencies": { + "@grpc/proto-loader": "^0.7.0", + "@types/node": ">=12.12.47" + }, + "engines": { + "node": "^8.13.0 || >=10.10.0" + } + }, "node_modules/@grpc/proto-loader": { - "version": "0.6.13", - "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.6.13.tgz", - "integrity": "sha512-FjxPYDRTn6Ec3V0arm1FtSpmP6V50wuph2yILpyvTKzjc76oDdoihXqM1DzOW5ubvCC8GivfCnNtfaRE8myJ7g==", + "version": "0.7.6", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.6.tgz", + "integrity": "sha512-QyAXR8Hyh7uMDmveWxDSUcJr9NAWaZ2I6IXgAYvQmfflwouTM+rArE2eEaCtLlRqO81j7pRLCt81IefUei6Zbw==", "dependencies": { "@types/long": "^4.0.1", "lodash.camelcase": "^4.3.0", "long": "^4.0.0", - "protobufjs": "^6.11.3", + "protobufjs": "^7.0.0", "yargs": "^16.2.0" }, "bin": { @@ -1655,13 +2130,14 @@ } }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", - "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", + "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", "dev": true, "dependencies": { - "@jridgewell/set-array": "^1.0.0", - "@jridgewell/sourcemap-codec": "^1.4.10" + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" }, "engines": { "node": ">=6.0.0" @@ -1686,43 +2162,46 @@ } }, "node_modules/@jridgewell/source-map": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", - "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.3.tgz", + "integrity": "sha512-b+fsZXeLYi9fEULmfBrhxn4IrPlINf8fiNarzTof004v3lFdntdwa9PF7vFJqm3mg7s+ScJMxXaE3Acp1irZcg==", "dev": true, "dependencies": { "@jridgewell/gen-mapping": "^0.3.0", "@jridgewell/trace-mapping": "^0.3.9" } }, - "node_modules/@jridgewell/source-map/node_modules/@jridgewell/gen-mapping": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.18", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz", + "integrity": "sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==", "dev": true, "dependencies": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "engines": { - "node": ">=6.0.0" + "@jridgewell/resolve-uri": "3.1.0", + "@jridgewell/sourcemap-codec": "1.4.14" } }, - "node_modules/@jridgewell/sourcemap-codec": { + "node_modules/@jridgewell/trace-mapping/node_modules/@jridgewell/sourcemap-codec": { "version": "1.4.14", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", "dev": true }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.17", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz", - "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", - "dev": true, + "node_modules/@jsdoc/salty": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/@jsdoc/salty/-/salty-0.2.5.tgz", + "integrity": "sha512-TfRP53RqunNe2HBobVBJ0VLhK1HbfvBYeTC1ahnN64PWvyYyGebmMiPkuwvD9fpw2ZbkoPb8Q7mwy0aR8Z9rvw==", "dependencies": { - "@jridgewell/resolve-uri": "3.1.0", - "@jridgewell/sourcemap-codec": "1.4.14" + "lodash": "^4.17.21" + }, + "engines": { + "node": ">=v12.0.0" } }, "node_modules/@justinribeiro/lite-youtube": { @@ -2446,14 +2925,14 @@ } }, "node_modules/@octokit/webhooks": { - "version": "10.7.0", - "resolved": "https://registry.npmjs.org/@octokit/webhooks/-/webhooks-10.7.0.tgz", - "integrity": "sha512-zZBbQMpXXnK/ki/utrFG/TuWv9545XCSLibfDTxrYqR1PmU6zel02ebTOrA7t5XIGHzlEOc/NgISUIBUe7pMFA==", + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/@octokit/webhooks/-/webhooks-10.9.1.tgz", + "integrity": "sha512-5NXU4VfsNOo2VSU/SrLrpPH2Z1ZVDOWFcET4EpnEBX1uh/v8Uz65UVuHIRx5TZiXhnWyRE9AO1PXHa+M/iWwZA==", "dev": true, "dependencies": { "@octokit/request-error": "^3.0.0", "@octokit/webhooks-methods": "^3.0.0", - "@octokit/webhooks-types": "6.10.0", + "@octokit/webhooks-types": "6.11.0", "aggregate-error": "^3.1.0" }, "engines": { @@ -2470,26 +2949,26 @@ } }, "node_modules/@octokit/webhooks-types": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/@octokit/webhooks-types/-/webhooks-types-6.10.0.tgz", - "integrity": "sha512-lDNv83BeEyxxukdQ0UttiUXawk9+6DkdjjFtm2GFED+24IQhTVaoSbwV9vWWKONyGLzRmCQqZmoEWkDhkEmPlw==", + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/@octokit/webhooks-types/-/webhooks-types-6.11.0.tgz", + "integrity": "sha512-AanzbulOHljrku1NGfafxdpTCfw2ENaWzH01N2vqQM+cUFbk868Cgh0xylz0JIM9BoKbfI++bdD6EYX0Q/UTEw==", "dev": true }, "node_modules/@percy/cli": { - "version": "1.21.0", - "resolved": "https://registry.npmjs.org/@percy/cli/-/cli-1.21.0.tgz", - "integrity": "sha512-capaTXkj/L0Itn8VpDY/ePkHM9InaqwTRTK+IHGTA2HsRlpiNotunDAv8cNJ/fBMoRBh1Bki7tEWIp6zB+KmBQ==", + "version": "1.23.0", + "resolved": "https://registry.npmjs.org/@percy/cli/-/cli-1.23.0.tgz", + "integrity": "sha512-3S+QUWdeJq6ZUWoRNLuX+wdJx8civJdrSmYG9WS2CP9auJNbuA+13xQnB5AkkWUvHEcC/yXzZpi5NAjoW86jgw==", "dev": true, "dependencies": { - "@percy/cli-app": "1.21.0", - "@percy/cli-build": "1.21.0", - "@percy/cli-command": "1.21.0", - "@percy/cli-config": "1.21.0", - "@percy/cli-exec": "1.21.0", - "@percy/cli-snapshot": "1.21.0", - "@percy/cli-upload": "1.21.0", - "@percy/client": "1.21.0", - "@percy/logger": "1.21.0" + "@percy/cli-app": "1.23.0", + "@percy/cli-build": "1.23.0", + "@percy/cli-command": "1.23.0", + "@percy/cli-config": "1.23.0", + "@percy/cli-exec": "1.23.0", + "@percy/cli-snapshot": "1.23.0", + "@percy/cli-upload": "1.23.0", + "@percy/client": "1.23.0", + "@percy/logger": "1.23.0" }, "bin": { "percy": "bin/run.cjs" @@ -2499,39 +2978,39 @@ } }, "node_modules/@percy/cli-app": { - "version": "1.21.0", - "resolved": "https://registry.npmjs.org/@percy/cli-app/-/cli-app-1.21.0.tgz", - "integrity": "sha512-kkYMTGEk33nsLIIKx57LzheK7WZK77Y52c+DAwnV1FDpzDvhpP4eLEpXwarTIapN76O4wZndFlX4zm07U9Cvfw==", + "version": "1.23.0", + "resolved": "https://registry.npmjs.org/@percy/cli-app/-/cli-app-1.23.0.tgz", + "integrity": "sha512-2L5chuBFp016LlkB7BihGtm0XJFCZEDNIcOFchsK7l2REBUkxVeM6hNQ89uuP2F9eKXwWKqtDEIYCzdzW0hfIQ==", "dev": true, "dependencies": { - "@percy/cli-command": "1.21.0", - "@percy/cli-exec": "1.21.0" + "@percy/cli-command": "1.23.0", + "@percy/cli-exec": "1.23.0" }, "engines": { "node": ">=14" } }, "node_modules/@percy/cli-build": { - "version": "1.21.0", - "resolved": "https://registry.npmjs.org/@percy/cli-build/-/cli-build-1.21.0.tgz", - "integrity": "sha512-LRvGsTl6bw6zNMOQ36emjdIdkvCEUAbRRp2nryBODMpJ8YUd1NcXw/qLVM2bzpJcTmeBXR76Yjgi1VhFZrNZlg==", + "version": "1.23.0", + "resolved": "https://registry.npmjs.org/@percy/cli-build/-/cli-build-1.23.0.tgz", + "integrity": "sha512-qIhfU/UtPl181Dw2kR8klEYLUlA5C8GE0M9781vz7D0W3LriccaLLLo1wBp4q4bo83uvUBvNJhq9/S4T38kPEQ==", "dev": true, "dependencies": { - "@percy/cli-command": "1.21.0" + "@percy/cli-command": "1.23.0" }, "engines": { "node": ">=14" } }, "node_modules/@percy/cli-command": { - "version": "1.21.0", - "resolved": "https://registry.npmjs.org/@percy/cli-command/-/cli-command-1.21.0.tgz", - "integrity": "sha512-ZfjDMgUQRQonJT106Y89NVDzVd2qDmwQ+4oC0AyGgE5h1cHAEaPoYV8LnMvpjbvFYni+jbeZvHNANMP7Ut2yOQ==", + "version": "1.23.0", + "resolved": "https://registry.npmjs.org/@percy/cli-command/-/cli-command-1.23.0.tgz", + "integrity": "sha512-tXj5vv2BQMBmn3ZL2YNqYYrmJLyYnBqwyJkecY2BwXQsKAIv3qBgTzr1d5+LxTOi5ArjFCHAgk2w4ohy6h6t4w==", "dev": true, "dependencies": { - "@percy/config": "1.21.0", - "@percy/core": "1.21.0", - "@percy/logger": "1.21.0" + "@percy/config": "1.23.0", + "@percy/core": "1.23.0", + "@percy/logger": "1.23.0" }, "bin": { "percy-cli-readme": "bin/readme.js" @@ -2541,24 +3020,24 @@ } }, "node_modules/@percy/cli-config": { - "version": "1.21.0", - "resolved": "https://registry.npmjs.org/@percy/cli-config/-/cli-config-1.21.0.tgz", - "integrity": "sha512-7Wn3L/XkKhVWixH4/oPJV66jD6LBCma6pT/bzbKuV5Hlpscel2xz3p8JSDOvxQJl1eSRtjwhI1HP/0OT6EX5dg==", + "version": "1.23.0", + "resolved": "https://registry.npmjs.org/@percy/cli-config/-/cli-config-1.23.0.tgz", + "integrity": "sha512-tI4c4MhU41rx9n7fYZrpn4gaOD9dA6PnefP397v7smqEWh7MJ+cxI/nyKU0/9G2wGjMhYACaLoR4BiCWOQZAkw==", "dev": true, "dependencies": { - "@percy/cli-command": "1.21.0" + "@percy/cli-command": "1.23.0" }, "engines": { "node": ">=14" } }, "node_modules/@percy/cli-exec": { - "version": "1.21.0", - "resolved": "https://registry.npmjs.org/@percy/cli-exec/-/cli-exec-1.21.0.tgz", - "integrity": "sha512-Uwqw1WqXzYXk4WQLyRWkQJ4Tdm7/bUOOa2HJU/J5kGLDmoSRNX/TesobFy8ii55mB0QV2hkZnMkAFPwzfxaCSw==", + "version": "1.23.0", + "resolved": "https://registry.npmjs.org/@percy/cli-exec/-/cli-exec-1.23.0.tgz", + "integrity": "sha512-ecxnMWxUlVx0EswGraHgN4LvWbXeUZQZUxJ9wYmMSgDEaKfEiEZ5WTLSKzQAxyfw2SjoQ3cHRZbKh4qMlCgbAg==", "dev": true, "dependencies": { - "@percy/cli-command": "1.21.0", + "@percy/cli-command": "1.23.0", "cross-spawn": "^7.0.3", "which": "^2.0.2" }, @@ -2567,12 +3046,12 @@ } }, "node_modules/@percy/cli-snapshot": { - "version": "1.21.0", - "resolved": "https://registry.npmjs.org/@percy/cli-snapshot/-/cli-snapshot-1.21.0.tgz", - "integrity": "sha512-DR0yPRCCRFGXrDwfAmC/26yF4CGMTAWNgIKFgeQcPGgjkdXOSmm04fhU36QBU5S66B2gmSjEG0mfh+2oOD68EQ==", + "version": "1.23.0", + "resolved": "https://registry.npmjs.org/@percy/cli-snapshot/-/cli-snapshot-1.23.0.tgz", + "integrity": "sha512-QOrUfyPCnjfIAcUBjNlO299NRPDxofcYQUCBYZE3CtemsNFtygFt0yPnZCwWmt0voSpnPl1Izc6/FA3wYUfuBQ==", "dev": true, "dependencies": { - "@percy/cli-command": "1.21.0", + "@percy/cli-command": "1.23.0", "yaml": "^2.0.0" }, "engines": { @@ -2580,12 +3059,12 @@ } }, "node_modules/@percy/cli-upload": { - "version": "1.21.0", - "resolved": "https://registry.npmjs.org/@percy/cli-upload/-/cli-upload-1.21.0.tgz", - "integrity": "sha512-NDh6NiirUgdnrNergiwtQceA0TjcT5vK6dzuE6pscwksvb9vzx+tvvbBcVBhpEQt+FmIoYDdqb8FVzMqxd5wEg==", + "version": "1.23.0", + "resolved": "https://registry.npmjs.org/@percy/cli-upload/-/cli-upload-1.23.0.tgz", + "integrity": "sha512-faRHjzaUf21RK9Ra051gKUl4HmMNPZxUKSZNmdG0yP+tc5KxU9cXkmEeCKGH7LOcVs0IfyRX0vv58YEZ6GsIRw==", "dev": true, "dependencies": { - "@percy/cli-command": "1.21.0", + "@percy/cli-command": "1.23.0", "fast-glob": "^3.2.11", "image-size": "^1.0.0" }, @@ -2594,25 +3073,25 @@ } }, "node_modules/@percy/client": { - "version": "1.21.0", - "resolved": "https://registry.npmjs.org/@percy/client/-/client-1.21.0.tgz", - "integrity": "sha512-IKFcMYcibWQjisjmS4K9HK7TbjPK4fnVeh/3Uq7Da0ejiu5qBvLn49aNcYfnrguPqaUcgIvLvpcgtHeH+srv/g==", + "version": "1.23.0", + "resolved": "https://registry.npmjs.org/@percy/client/-/client-1.23.0.tgz", + "integrity": "sha512-m0qNCrlfh6Pf0t2GfoeShuK7r2GeRk5rWVjIbdnDigvmtL0G+HJM1gvysLOxzKFHkZ1cLBfM1SnH1Yn6RM/6qQ==", "dev": true, "dependencies": { - "@percy/env": "1.21.0", - "@percy/logger": "1.21.0" + "@percy/env": "1.23.0", + "@percy/logger": "1.23.0" }, "engines": { "node": ">=14" } }, "node_modules/@percy/config": { - "version": "1.21.0", - "resolved": "https://registry.npmjs.org/@percy/config/-/config-1.21.0.tgz", - "integrity": "sha512-s6XFBhjP0fGVg8onapDwebGNIdwMgdidZW5q0HziBiQVqfwh/83NkDlCq+c6/JU5P0Y5DArxCIFDVUfiLkcs4A==", + "version": "1.23.0", + "resolved": "https://registry.npmjs.org/@percy/config/-/config-1.23.0.tgz", + "integrity": "sha512-giPIdNLcG1Qg0dkc/VDOkTzI4szzM4QAoJfMLEP0UYPkIU2Y0Xc8NH5GN3DEiudRJge72iGfeah6GugxmXmKXw==", "dev": true, "dependencies": { - "@percy/logger": "1.21.0", + "@percy/logger": "1.23.0", "ajv": "^8.6.2", "cosmiconfig": "^7.0.0", "yaml": "^2.0.0" @@ -2622,16 +3101,16 @@ } }, "node_modules/@percy/core": { - "version": "1.21.0", - "resolved": "https://registry.npmjs.org/@percy/core/-/core-1.21.0.tgz", - "integrity": "sha512-YFBTiRghq1m9t0/4ZUFWgS8LJ4DYugcMDoZ04yKWsIjRDcALwHAZahYpBZRcHkmfqB/kqLB5IYoyc6rel+PNeA==", + "version": "1.23.0", + "resolved": "https://registry.npmjs.org/@percy/core/-/core-1.23.0.tgz", + "integrity": "sha512-/BNHdvbD7r1p3k3HWgxYLBo2L2Ye9RDcmTuA6en2xUYaagf+0vfcAK8iyBvVm6ir2ZjAsMW0PGRa7OIfetvHHg==", "dev": true, "hasInstallScript": true, "dependencies": { - "@percy/client": "1.21.0", - "@percy/config": "1.21.0", - "@percy/dom": "1.21.0", - "@percy/logger": "1.21.0", + "@percy/client": "1.23.0", + "@percy/config": "1.23.0", + "@percy/dom": "1.23.0", + "@percy/logger": "1.23.0", "content-disposition": "^0.5.4", "cross-spawn": "^7.0.3", "extract-zip": "^2.0.1", @@ -2647,24 +3126,24 @@ } }, "node_modules/@percy/dom": { - "version": "1.21.0", - "resolved": "https://registry.npmjs.org/@percy/dom/-/dom-1.21.0.tgz", - "integrity": "sha512-OKpS9EPnUrMx3Mu9L7QiqEtc+yAUz3gbXrbRlrPAljyRAmmBe9p5vy0hKtP8wO1vxjumqmtxNABpz5bc70CJ2Q==", + "version": "1.23.0", + "resolved": "https://registry.npmjs.org/@percy/dom/-/dom-1.23.0.tgz", + "integrity": "sha512-68q3ceCWsWpUFyF/pnELSCTdbTAibGVyNwp+iZCFd/914sUhERYrrX8AqCgkCDerOzCwAQZQDe2Nv3jaB+d0ng==", "dev": true }, "node_modules/@percy/env": { - "version": "1.21.0", - "resolved": "https://registry.npmjs.org/@percy/env/-/env-1.21.0.tgz", - "integrity": "sha512-rqbACxivUTkpAJnjk/7IosFdh2vdz1SVGV0KXFf2xtEuUb7YhYrYixhf/6xE81o93C+pxrlXYWkgUSaMhZpP5A==", + "version": "1.23.0", + "resolved": "https://registry.npmjs.org/@percy/env/-/env-1.23.0.tgz", + "integrity": "sha512-oKvJBC/Zhfwp2QpFBpfHeAVuGhgaPeI7S4H2/68XT30pInfVJzaCjD/8ySAELGyMWmgHc51s+k09DZCo3C3Gyg==", "dev": true, "engines": { "node": ">=14" } }, "node_modules/@percy/logger": { - "version": "1.21.0", - "resolved": "https://registry.npmjs.org/@percy/logger/-/logger-1.21.0.tgz", - "integrity": "sha512-qKKSFP25X+a50vpjUSolI8WSQ2YAunS6K4brdTRemgvc48Wlkv3541SP8iMK5BAy3Nn4u0KRiwkstvyRr1tXlA==", + "version": "1.23.0", + "resolved": "https://registry.npmjs.org/@percy/logger/-/logger-1.23.0.tgz", + "integrity": "sha512-kNtdKQ9Kou/RcWgDoSK+ofOVqOzuzyHBNsK+I92XNh8HHO6ow08Cmw+LtZbDxmj3uq7nXG9Nhgj4ZqSgdk7J6Q==", "dev": true, "engines": { "node": ">=14" @@ -3247,12 +3726,11 @@ } }, "node_modules/@types/glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==", - "dev": true, + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-IO+MJPVhoqz+28h1qLAcBEH2+xHMK6MTyHJc7MTnnYb6wsoLR29POVGJ7LycmVXIqyy/4/2ShP5sUwTXuOwb/w==", "dependencies": { - "@types/minimatch": "*", + "@types/minimatch": "^5.1.2", "@types/node": "*" } }, @@ -3283,6 +3761,11 @@ "@types/node": "*" } }, + "node_modules/@types/linkify-it": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-3.0.2.tgz", + "integrity": "sha512-HZQYqbiFVWufzCwexrvh694SOim8z2d+xJl5UNamcvQFejLY/2YUtzXHYi3cHdI7PMlS8ejH2slRAOJQ32aNbA==" + }, "node_modules/@types/long": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.2.tgz", @@ -3294,6 +3777,15 @@ "integrity": "sha512-ssE3Vlrys7sdIzs5LOxCzTVMsU7i9oa/IaW92wF32JFb3CVczqOkru2xspuKczHEbG3nvmPY7IFqVmGGHdNbYw==", "dev": true }, + "node_modules/@types/markdown-it": { + "version": "12.2.3", + "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-12.2.3.tgz", + "integrity": "sha512-GKMHFfv3458yYy+v/N8gjufHO6MSZKCOXpZc5GXIWWy8uldwfmPn98vp81gZ5f9SVw8YYBctgfJ22a2d7AOMeQ==", + "dependencies": { + "@types/linkify-it": "*", + "@types/mdurl": "*" + } + }, "node_modules/@types/mdast": { "version": "3.0.11", "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.11.tgz", @@ -3303,6 +3795,11 @@ "@types/unist": "*" } }, + "node_modules/@types/mdurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-1.0.2.tgz", + "integrity": "sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA==" + }, "node_modules/@types/mime": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-3.0.1.tgz", @@ -3310,9 +3807,9 @@ "optional": true }, "node_modules/@types/minimatch": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz", - "integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==" + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz", + "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==" }, "node_modules/@types/minimist": { "version": "1.2.2", @@ -3326,9 +3823,9 @@ "integrity": "sha512-QB5D2sqfSjCmTuWcBWyJ+/44bcjO7VbjSbOE0ucoVbAsSNQc4Lt6QkgkVXkTDwkL4z/beecZNDvVX15D4P8Jbw==" }, "node_modules/@types/node-fetch": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.2.tgz", - "integrity": "sha512-DHqhlq5jeESLy19TYhLakJ07kNumXWjcDdxXsLUMJZ6ue8VZJj4kLPQVE/2mdHh3xZziNF1xppu5lwmS53HR+A==", + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.3.tgz", + "integrity": "sha512-ETTL1mOEdq/sxUtgtOhKjyB2Irra4cjxksvcMUR5Zr4n+PxVhsCD9WS46oPbHL3et9Zde7CNRr+WUNlcHvsX+w==", "optional": true, "dependencies": { "@types/node": "*", @@ -3373,6 +3870,15 @@ "@types/node": "*" } }, + "node_modules/@types/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-F3OznnSLAUxFrCEu/L5PY8+ny8DtcFRjx7fZZ9bycvXRi3KPTRS9HOitGZwvPg0juRhXFWIeKX58cnX5YqLohQ==", + "dependencies": { + "@types/glob": "*", + "@types/node": "*" + } + }, "node_modules/@types/serve-static": { "version": "1.15.1", "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.1.tgz", @@ -3479,6 +3985,15 @@ "eslint": ">=5" } }, + "node_modules/@typescript-eslint/experimental-utils/node_modules/eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, "node_modules/@typescript-eslint/parser": { "version": "4.33.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.33.0.tgz", @@ -3580,6 +4095,15 @@ "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, "node_modules/a-sync-waterfall": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/a-sync-waterfall/-/a-sync-waterfall-1.0.1.tgz", @@ -3617,7 +4141,6 @@ "version": "8.8.2", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", - "dev": true, "bin": { "acorn": "bin/acorn" }, @@ -3629,7 +4152,6 @@ "version": "5.3.2", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } @@ -3684,24 +4206,24 @@ } }, "node_modules/algoliasearch": { - "version": "4.16.0", - "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-4.16.0.tgz", - "integrity": "sha512-HAjKJ6bBblaXqO4dYygF4qx251GuJ6zCZt+qbJ+kU7sOC+yc84pawEjVpJByh+cGP2APFCsao2Giz50cDlKNPA==", - "dependencies": { - "@algolia/cache-browser-local-storage": "4.16.0", - "@algolia/cache-common": "4.16.0", - "@algolia/cache-in-memory": "4.16.0", - "@algolia/client-account": "4.16.0", - "@algolia/client-analytics": "4.16.0", - "@algolia/client-common": "4.16.0", - "@algolia/client-personalization": "4.16.0", - "@algolia/client-search": "4.16.0", - "@algolia/logger-common": "4.16.0", - "@algolia/logger-console": "4.16.0", - "@algolia/requester-browser-xhr": "4.16.0", - "@algolia/requester-common": "4.16.0", - "@algolia/requester-node-http": "4.16.0", - "@algolia/transporter": "4.16.0" + "version": "4.17.0", + "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-4.17.0.tgz", + "integrity": "sha512-JMRh2Mw6sEnVMiz6+APsi7lx9a2jiDFF+WUtANaUVCv6uSU9UOLdo5h9K3pdP6frRRybaM2fX8b1u0nqICS9aA==", + "dependencies": { + "@algolia/cache-browser-local-storage": "4.17.0", + "@algolia/cache-common": "4.17.0", + "@algolia/cache-in-memory": "4.17.0", + "@algolia/client-account": "4.17.0", + "@algolia/client-analytics": "4.17.0", + "@algolia/client-common": "4.17.0", + "@algolia/client-personalization": "4.17.0", + "@algolia/client-search": "4.17.0", + "@algolia/logger-common": "4.17.0", + "@algolia/logger-console": "4.17.0", + "@algolia/requester-browser-xhr": "4.17.0", + "@algolia/requester-common": "4.17.0", + "@algolia/requester-node-http": "4.17.0", + "@algolia/transporter": "4.17.0" } }, "node_modules/ansi-align": { @@ -4129,9 +4651,9 @@ } }, "node_modules/async-transforms/node_modules/@types/node": { - "version": "14.18.40", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.40.tgz", - "integrity": "sha512-pGteXO/JQX7wPxGR8lyT+doqjMa7XvlVowwrDwLfX92k5SdLkk4cwC7CYSLBxrenw/R5oQwKioVIak7ZgplM3g==", + "version": "14.18.42", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.42.tgz", + "integrity": "sha512-xefu+RBie4xWlK8hwAzGh3npDz/4VhF6icY/shU+zv/1fNn+ZVG7T7CRwe9LId9sAYRPxI+59QBPuKL3WpyGRg==", "optional": true }, "node_modules/asynckit": { @@ -4773,8 +5295,7 @@ "node_modules/bluebird": { "version": "3.7.2", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", - "dev": true + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" }, "node_modules/blueimp-md5": { "version": "2.19.0", @@ -5451,9 +5972,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001469", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001469.tgz", - "integrity": "sha512-Rcp7221ScNqQPP3W+lVOYDyjdR6dC+neEQCttoNr5bAyz54AboB4iwpnWgyi8P4YUsPybVzT4LgWiBbI3drL4g==", + "version": "1.0.30001478", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001478.tgz", + "integrity": "sha512-gMhDyXGItTHipJj2ApIvR+iVB5hd0KP3svMWWXDvZOmjzJJassGLMfxRkQCSYgGd2gtdL/ReeiyvMSFD1Ss6Mw==", "dev": true, "funding": [ { @@ -5463,6 +5984,10 @@ { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" } ] }, @@ -5476,6 +6001,17 @@ "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==" }, + "node_modules/catharsis": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.9.0.tgz", + "integrity": "sha512-prMTQVpcns/tzFgFVkVp6ak6RykZyWb3gu8ckUpd6YkTlacOd3DXGJjIpD4Q6zJirizvaiAjSSHlOsA+6sNh2A==", + "dependencies": { + "lodash": "^4.17.15" + }, + "engines": { + "node": ">= 10" + } + }, "node_modules/ccount": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/ccount/-/ccount-1.1.0.tgz", @@ -5831,9 +6367,9 @@ } }, "node_modules/chromium-bidi": { - "version": "0.4.5", - "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-0.4.5.tgz", - "integrity": "sha512-rkav9YzRfAshSTG3wNXF7P7yNiI29QAo1xBXElPoCoSQR5n20q3cOyVhDv6S7+GlF/CJ/emUxlQiR0xOPurkGg==", + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-0.4.6.tgz", + "integrity": "sha512-TQOkWRaLI/IWvoP8XC+7jO4uHTIiAUiklXU1T0qszlUFEai9LgKXIBXy3pOS3EnQZ3bQtMbKUPkug0fTAEHCSw==", "dev": true, "dependencies": { "mitt": "3.0.0" @@ -5996,9 +6532,9 @@ } }, "node_modules/cli-spinners": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.7.0.tgz", - "integrity": "sha512-qu3pN8Y3qHNgE2AFweciB1IfMnmZ/fsNTEE+NOFjmGB2F/7rLhnhzppvpCnN4FovtP26k8lHyy9ptEbNwWFLzw==", + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.8.0.tgz", + "integrity": "sha512-/eG5sJcvEIwxcdYM86k5tPwn0MUzkX5YY3eImTGpJOZgVe4SdTMY14vQpcxgBzJ0wXwAYrS8E+c3uHeK4JNyzQ==", "dev": true, "engines": { "node": ">=6" @@ -6914,8 +7450,7 @@ "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==" }, "node_modules/deep-strict-equal": { "version": "0.2.0", @@ -7118,9 +7653,9 @@ } }, "node_modules/devtools-protocol": { - "version": "0.0.1094867", - "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1094867.tgz", - "integrity": "sha512-pmMDBKiRVjh0uKK6CT1WqZmM3hBVSgD+N2MrgyV1uNizAZMw4tx6i/RTc+/uCsKSCmg0xXx7arCP/OFcIwTsiQ==", + "version": "0.0.1107588", + "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1107588.tgz", + "integrity": "sha512-yIR+pG9x65Xko7bErCUSQaDLrO/P1p3JUzEk7JCU4DowPcGHkTGUGQapcfcLc4qj0UaALwZ+cr0riFgiqpixcg==", "dev": true }, "node_modules/dir-glob": { @@ -7338,9 +7873,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.337", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.337.tgz", - "integrity": "sha512-W8gdzXG86mVPoc56eM8YA+QiLxaAxJ8cmDjxZgfhLLWVvZQxyA918w5tX2JEWApZta45T1/sYcmFHTsTOUE3nw==", + "version": "1.4.363", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.363.tgz", + "integrity": "sha512-ReX5qgmSU7ybhzMuMdlJAdYnRhT90UB3k9M05O5nF5WH3wR5wgdJjXw0uDeFyKNhmglmQiOxkAbzrP0hMKM59g==", "dev": true }, "node_modules/elegant-spinner": { @@ -7703,6 +8238,83 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/escodegen": { + "version": "1.14.3", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz", + "integrity": "sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==", + "dependencies": { + "esprima": "^4.0.1", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=4.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" + } + }, + "node_modules/escodegen/node_modules/levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", + "dependencies": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/escodegen/node_modules/optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "dependencies": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/escodegen/node_modules/prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/escodegen/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/escodegen/node_modules/type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", + "dependencies": { + "prelude-ls": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/eslint": { "version": "7.32.0", "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.32.0.tgz", @@ -7795,6 +8407,41 @@ "eslint": ">=7.22.0" } }, + "node_modules/eslint-plugin-ava/node_modules/acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/eslint-plugin-ava/node_modules/eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/eslint-plugin-ava/node_modules/espree": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", + "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", + "dev": true, + "dependencies": { + "acorn": "^7.4.0", + "acorn-jsx": "^5.3.1", + "eslint-visitor-keys": "^1.3.0" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, "node_modules/eslint-plugin-ava/node_modules/espurify": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/espurify/-/espurify-2.1.1.tgz", @@ -7908,12 +8555,14 @@ } }, "node_modules/eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true, + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.0.tgz", + "integrity": "sha512-HPpKPUBQcAsZOsHAFwTtIKcYlCje62XB7SEAcxjtmW6TD1WVpkS6i6/hOVtTZIl4zGj/mBqpFVGvaDneik+VoQ==", "engines": { - "node": ">=10" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, "node_modules/eslint/node_modules/@babel/code-frame": { @@ -7925,6 +8574,18 @@ "@babel/highlight": "^7.10.4" } }, + "node_modules/eslint/node_modules/acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/eslint/node_modules/ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -7950,6 +8611,38 @@ "sprintf-js": "~1.0.2" } }, + "node_modules/eslint/node_modules/eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/eslint/node_modules/espree": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", + "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", + "dev": true, + "dependencies": { + "acorn": "^7.4.0", + "acorn-jsx": "^5.3.1", + "eslint-visitor-keys": "^1.3.0" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/eslint/node_modules/espree/node_modules/eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, "node_modules/eslint/node_modules/globals": { "version": "13.20.0", "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", @@ -8018,38 +8711,19 @@ } }, "node_modules/espree": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", - "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", - "dev": true, + "version": "9.5.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.1.tgz", + "integrity": "sha512-5yxtHSZXRSW5pvv3hAlXM5+/Oswi1AUFqBmbibKb5s6bp3rGIDkyXU6xCoyuuLhijr4SFwPrXRoZjz0AZDN9tg==", "dependencies": { - "acorn": "^7.4.0", - "acorn-jsx": "^5.3.1", - "eslint-visitor-keys": "^1.3.0" + "acorn": "^8.8.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.0" }, "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/espree/node_modules/acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", - "dev": true, - "bin": { - "acorn": "bin/acorn" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/espree/node_modules/eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true, - "engines": { - "node": ">=4" + "funding": { + "url": "https://opencollective.com/eslint" } }, "node_modules/esprima": { @@ -8119,7 +8793,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, "engines": { "node": ">=4.0" } @@ -8134,7 +8807,6 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -8729,8 +9401,7 @@ "node_modules/fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==" }, "node_modules/fast-text-encoding": { "version": "1.0.6", @@ -10116,131 +10787,46 @@ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "node_modules/google-gax": { - "version": "2.30.5", - "resolved": "https://registry.npmjs.org/google-gax/-/google-gax-2.30.5.tgz", - "integrity": "sha512-Jey13YrAN2hfpozHzbtrwEfEHdStJh1GwaQ2+Akh1k0Tv/EuNVSuBtHZoKSBm5wBMvNsxTsEIZ/152NrYyZgxQ==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/google-gax/-/google-gax-3.6.0.tgz", + "integrity": "sha512-2fyb61vWxUonHiArRNJQmE4tx5oY1ni8VPo08fzII409vDSCWG7apDX4qNOQ2GXXT82gLBn3d3P1Dydh7pWjyw==", "dependencies": { - "@grpc/grpc-js": "~1.6.0", - "@grpc/proto-loader": "^0.6.12", + "@grpc/grpc-js": "~1.8.0", + "@grpc/proto-loader": "^0.7.0", "@types/long": "^4.0.0", + "@types/rimraf": "^3.0.2", "abort-controller": "^3.0.0", "duplexify": "^4.0.0", "fast-text-encoding": "^1.0.3", - "google-auth-library": "^7.14.0", + "google-auth-library": "^8.0.2", "is-stream-ended": "^0.1.4", "node-fetch": "^2.6.1", "object-hash": "^3.0.0", - "proto3-json-serializer": "^0.1.8", - "protobufjs": "6.11.3", - "retry-request": "^4.0.0" + "proto3-json-serializer": "^1.0.0", + "protobufjs": "7.2.3", + "protobufjs-cli": "1.1.1", + "retry-request": "^5.0.0" }, "bin": { - "compileProtos": "build/tools/compileProtos.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/google-gax/node_modules/gaxios": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-4.3.3.tgz", - "integrity": "sha512-gSaYYIO1Y3wUtdfHmjDUZ8LWaxJQpiavzbF5Kq53akSzvmVg0RfyOcFDbO1KJ/KCGRFz2qG+lS81F0nkr7cRJA==", - "dependencies": { - "abort-controller": "^3.0.0", - "extend": "^3.0.2", - "https-proxy-agent": "^5.0.0", - "is-stream": "^2.0.0", - "node-fetch": "^2.6.7" + "compileProtos": "build/tools/compileProtos.js", + "minifyProtoJson": "build/tools/minify.js" }, "engines": { - "node": ">=10" - } - }, - "node_modules/google-gax/node_modules/gcp-metadata": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-4.3.1.tgz", - "integrity": "sha512-x850LS5N7V1F3UcV7PoupzGsyD6iVwTVvsh3tbXfkctZnBnjW5yu5z1/3k3SehF7TyoTIe78rJs02GMMy+LF+A==", - "dependencies": { - "gaxios": "^4.0.0", - "json-bigint": "^1.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/google-gax/node_modules/google-auth-library": { - "version": "7.14.1", - "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-7.14.1.tgz", - "integrity": "sha512-5Rk7iLNDFhFeBYc3s8l1CqzbEBcdhwR193RlD4vSNFajIcINKI8W8P0JLmBpwymHqqWbX34pJDQu39cSy/6RsA==", - "dependencies": { - "arrify": "^2.0.0", - "base64-js": "^1.3.0", - "ecdsa-sig-formatter": "^1.0.11", - "fast-text-encoding": "^1.0.0", - "gaxios": "^4.0.0", - "gcp-metadata": "^4.2.0", - "gtoken": "^5.0.4", - "jws": "^4.0.0", - "lru-cache": "^6.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/google-gax/node_modules/google-p12-pem": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-3.1.4.tgz", - "integrity": "sha512-HHuHmkLgwjdmVRngf5+gSmpkyaRI6QmOg77J8tkNBHhNEI62sGHyw4/+UkgyZEI7h84NbWprXDJ+sa3xOYFvTg==", - "dependencies": { - "node-forge": "^1.3.1" - }, - "bin": { - "gp12-pem": "build/src/bin/gp12-pem.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/google-gax/node_modules/gtoken": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-5.3.2.tgz", - "integrity": "sha512-gkvEKREW7dXWF8NV8pVrKfW7WqReAmjjkMBh6lNCCGOM4ucS0r0YyXXl0r/9Yj8wcW/32ISkfc8h5mPTDbtifQ==", - "dependencies": { - "gaxios": "^4.0.0", - "google-p12-pem": "^3.1.3", - "jws": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/google-gax/node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=12" } }, - "node_modules/google-gax/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "node_modules/google-gax/node_modules/retry-request": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/retry-request/-/retry-request-5.0.2.tgz", + "integrity": "sha512-wfI3pk7EE80lCIXprqh7ym48IHYdwmAAzESdbU8Q9l7pnRCk9LEhpbOTNKjz6FARLm/Bl5m+4F0ABxOkYUujSQ==", "dependencies": { - "yallist": "^4.0.0" + "debug": "^4.1.1", + "extend": "^3.0.2" }, "engines": { - "node": ">=10" + "node": ">=12" } }, - "node_modules/google-gax/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, "node_modules/google-p12-pem": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-4.0.1.tgz", @@ -11261,9 +11847,9 @@ "dev": true }, "node_modules/html-tags": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.2.0.tgz", - "integrity": "sha512-vy7ClnArOZwCnqZgvv+ddgHgJiAFXe3Ge9ML5/mBctVJoUoYPCdxVucOywjDARn6CVoh3dRSFdPHy2sX80L0Wg==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.3.1.tgz", + "integrity": "sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==", "dev": true, "engines": { "node": ">=8" @@ -12008,9 +12594,9 @@ } }, "node_modules/is-core-module": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", - "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.0.tgz", + "integrity": "sha512-RECHCBCd/viahWmwj6enj19sKbHfJrddi/6cBDsNTKbNq0f7VeaUkBo60BqzvPqo/W54ChS62Z5qyun7cfOMqQ==", "dependencies": { "has": "^1.0.3" }, @@ -12863,11 +13449,98 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/js2xmlparser": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-4.0.2.tgz", + "integrity": "sha512-6n4D8gLlLf1n5mNLQPRfViYzu9RATblzPEtm1SthMX1Pjao0r9YI9nw7ZIfRxQMERS87mcswrg+r/OYrPRX6jA==", + "dependencies": { + "xmlcreate": "^2.0.4" + } + }, "node_modules/jsbn": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==" }, + "node_modules/jsdoc": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-4.0.2.tgz", + "integrity": "sha512-e8cIg2z62InH7azBBi3EsSEqrKx+nUtAS5bBcYTSpZFA+vhNPyhv8PTFZ0WsjOPDj04/dOLlm08EDcQJDqaGQg==", + "dependencies": { + "@babel/parser": "^7.20.15", + "@jsdoc/salty": "^0.2.1", + "@types/markdown-it": "^12.2.3", + "bluebird": "^3.7.2", + "catharsis": "^0.9.0", + "escape-string-regexp": "^2.0.0", + "js2xmlparser": "^4.0.2", + "klaw": "^3.0.0", + "markdown-it": "^12.3.2", + "markdown-it-anchor": "^8.4.1", + "marked": "^4.0.10", + "mkdirp": "^1.0.4", + "requizzle": "^0.2.3", + "strip-json-comments": "^3.1.0", + "underscore": "~1.13.2" + }, + "bin": { + "jsdoc": "jsdoc.js" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/jsdoc/node_modules/entities": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz", + "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==", + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/jsdoc/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/jsdoc/node_modules/markdown-it": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.3.2.tgz", + "integrity": "sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg==", + "dependencies": { + "argparse": "^2.0.1", + "entities": "~2.1.0", + "linkify-it": "^3.0.1", + "mdurl": "^1.0.1", + "uc.micro": "^1.0.5" + }, + "bin": { + "markdown-it": "bin/markdown-it.js" + } + }, + "node_modules/jsdoc/node_modules/markdown-it-anchor": { + "version": "8.6.7", + "resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-8.6.7.tgz", + "integrity": "sha512-FlCHFwNnutLgVTflOYHPW2pPcl2AACqVzExlkGQNsi4CJgqOHN7YTgDd4LuhgN1BFO3TS0vLAruV1Td6dwWPJA==", + "peerDependencies": { + "@types/markdown-it": "*", + "markdown-it": "*" + } + }, + "node_modules/jsdoc/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/jsesc": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", @@ -13162,6 +13835,14 @@ "node": ">=0.10.0" } }, + "node_modules/klaw": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-3.0.0.tgz", + "integrity": "sha512-0Fo5oir+O9jnXu5EefYbVK+mHMBeEVEy2cmctR1O1NECcCkPRreJKrS6Qt/j3KC2C148Dfo9i3pCmCMsdqGr0g==", + "dependencies": { + "graceful-fs": "^4.1.9" + } + }, "node_modules/kleur": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", @@ -13919,9 +14600,9 @@ } }, "node_modules/linkedom/node_modules/entities": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.4.0.tgz", - "integrity": "sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", "engines": { "node": ">=0.12" }, @@ -15186,15 +15867,6 @@ "node": ">=0.10.0" } }, - "node_modules/minipass": { - "version": "4.2.5", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.2.5.tgz", - "integrity": "sha512-+yQl7SX3bIT83Lhb4BVorMAHVuqsskxRdlmO9kTpyukp8vsm2Sn/fUOV9xlnG8/a5JsypJzap21lz/y3FBMJ8Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/mitt": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/mitt/-/mitt-1.2.0.tgz", @@ -15279,6 +15951,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/multimatch/node_modules/@types/minimatch": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz", + "integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==" + }, "node_modules/mustache": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz", @@ -15313,9 +15990,15 @@ "optional": true }, "node_modules/nanoid": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", - "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", + "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], "bin": { "nanoid": "bin/nanoid.cjs" }, @@ -16808,31 +17491,6 @@ "node": ">=0.10.0" } }, - "node_modules/path-scurry": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.6.3.tgz", - "integrity": "sha512-RAmB+n30SlN+HnNx6EbcpoDy9nwdpcGPnEKrJnu6GZoDWBdIjo1UQMVtW2ybtC7LC2oKLcMq8y5g8WnKLiod9g==", - "dev": true, - "dependencies": { - "lru-cache": "^7.14.1", - "minipass": "^4.0.2" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/path-scurry/node_modules/lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "dev": true, - "engines": { - "node": ">=12" - } - }, "node_modules/path-to-regexp": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.1.tgz", @@ -17420,9 +18078,9 @@ } }, "node_modules/prettier": { - "version": "2.8.6", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.6.tgz", - "integrity": "sha512-mtuzdiBbHwPEgl7NxWlqOkithPyp4VN93V7VeHVWBF+ad3I5avc0RVDT4oImXQy9H/AqxA2NSQH8pSxHW6FYbQ==", + "version": "2.8.7", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.7.tgz", + "integrity": "sha512-yPngTo3aXUUmyuTjeTUT75txrf+aMh9FiD7q9ZE/i6r0bPb22g4FsE6Y338PQX1bmfy08i9QQCB7/rcUAVntfw==", "dev": true, "bin": { "prettier": "bin-prettier.js" @@ -17538,17 +18196,20 @@ "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==" }, "node_modules/proto3-json-serializer": { - "version": "0.1.9", - "resolved": "https://registry.npmjs.org/proto3-json-serializer/-/proto3-json-serializer-0.1.9.tgz", - "integrity": "sha512-A60IisqvnuI45qNRygJjrnNjX2TMdQGMY+57tR3nul3ZgO2zXkR9OGR8AXxJhkqx84g0FTnrfi3D5fWMSdANdQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proto3-json-serializer/-/proto3-json-serializer-1.1.0.tgz", + "integrity": "sha512-SjXwUWe/vANGs/mJJTbw5++7U67nwsymg7qsoPtw6GiXqw3kUy8ByojrlEdVE2efxAdKreX8WkDafxvYW95ZQg==", "dependencies": { - "protobufjs": "^6.11.2" + "protobufjs": "^7.0.0" + }, + "engines": { + "node": ">=12.0.0" } }, "node_modules/protobufjs": { - "version": "6.11.3", - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.3.tgz", - "integrity": "sha512-xL96WDdCZYdU7Slin569tFX712BxsxslWwAfAhCYjQKGTq7dAU91Lomy6nLLhh/dyGhk/YH4TwTSRxTzhuHyZg==", + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.3.tgz", + "integrity": "sha512-TtpvOqwB5Gdz/PQmOjgsrGH1nHjAQVCN7JG4A6r1sXRWESL5rNMAiRcBQlCAdKxZcAbstExQePYG8xof/JVRgg==", "hasInstallScript": true, "dependencies": { "@protobufjs/aspromise": "^1.1.2", @@ -17561,15 +18222,90 @@ "@protobufjs/path": "^1.1.2", "@protobufjs/pool": "^1.1.0", "@protobufjs/utf8": "^1.1.0", - "@types/long": "^4.0.1", "@types/node": ">=13.7.0", - "long": "^4.0.0" + "long": "^5.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/protobufjs-cli": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/protobufjs-cli/-/protobufjs-cli-1.1.1.tgz", + "integrity": "sha512-VPWMgIcRNyQwWUv8OLPyGQ/0lQY/QTQAVN5fh+XzfDwsVw1FZ2L3DM/bcBf8WPiRz2tNpaov9lPZfNcmNo6LXA==", + "dependencies": { + "chalk": "^4.0.0", + "escodegen": "^1.13.0", + "espree": "^9.0.0", + "estraverse": "^5.1.0", + "glob": "^8.0.0", + "jsdoc": "^4.0.0", + "minimist": "^1.2.0", + "semver": "^7.1.2", + "tmp": "^0.2.1", + "uglify-js": "^3.7.7" }, "bin": { "pbjs": "bin/pbjs", "pbts": "bin/pbts" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "protobufjs": "^7.0.0" + } + }, + "node_modules/protobufjs-cli/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/protobufjs-cli/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/protobufjs-cli/node_modules/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/protobufjs-cli/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" } }, + "node_modules/protobufjs/node_modules/long": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/long/-/long-5.2.1.tgz", + "integrity": "sha512-GKSNGeNAtw8IryjjkhZxuKB3JzlcLTwjtiQCHKvqQet81I93kXslhDQruGI/QsddO83mcDToBVy7GqGS/zYf/A==" + }, "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -17798,96 +18534,132 @@ } }, "node_modules/puppeteer": { - "version": "19.7.5", - "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-19.7.5.tgz", - "integrity": "sha512-UqD8K+yaZa6/hwzP54AATCiHrEYGGxzQcse9cZzrtsVGd8wT0llCdYhsBp8n+zvnb1ofY0YFgI3TYZ/MiX5uXQ==", + "version": "19.9.0", + "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-19.9.0.tgz", + "integrity": "sha512-JDx8WwGlkdQYTaa3OMYDF+uFWimiwNnacg5FGEC5J6+VxDsLK30wHKU/Db2LqEhtAoIu4RwS+BRH4zRPlCsFpA==", "dev": true, "hasInstallScript": true, "dependencies": { - "cosmiconfig": "8.1.0", + "@puppeteer/browsers": "0.4.1", + "cosmiconfig": "8.1.3", "https-proxy-agent": "5.0.1", "progress": "2.0.3", "proxy-from-env": "1.1.0", - "puppeteer-core": "19.7.5" + "puppeteer-core": "19.9.0" } }, - "node_modules/puppeteer/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "node_modules/puppeteer/node_modules/@puppeteer/browsers": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-0.4.1.tgz", + "integrity": "sha512-4IICvy1McAkT/HyNZHIs7sp8ngBX1dmO0TPQ+FWq9ATQMqI8p+Ulm5A3kS2wYDh5HDHHkYrrETOu6rlj64VuTw==", "dev": true, "dependencies": { - "balanced-match": "^1.0.0" + "debug": "4.3.4", + "extract-zip": "2.0.1", + "https-proxy-agent": "5.0.1", + "progress": "2.0.3", + "proxy-from-env": "1.1.0", + "tar-fs": "2.1.1", + "unbzip2-stream": "1.4.3", + "yargs": "17.7.1" + }, + "bin": { + "browsers": "lib/cjs/main-cli.js" + }, + "engines": { + "node": ">=14.1.0" + }, + "peerDependencies": { + "typescript": ">= 4.7.4" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/puppeteer/node_modules/cosmiconfig": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.1.0.tgz", - "integrity": "sha512-0tLZ9URlPGU7JsKq0DQOQ3FoRsYX8xDZ7xMiATQfaiGMz7EHowNkbU9u1coAOmnh9p/1ySpm0RB3JNWRXM5GCg==", + "node_modules/puppeteer/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "dependencies": { - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "parse-json": "^5.0.0", - "path-type": "^4.0.0" + "color-convert": "^2.0.1" }, "engines": { - "node": ">=14" + "node": ">=8" }, "funding": { - "url": "https://github.com/sponsors/d-fischer" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/puppeteer/node_modules/glob": { - "version": "9.3.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-9.3.2.tgz", - "integrity": "sha512-BTv/JhKXFEHsErMte/AnfiSv8yYOLLiyH2lTg8vn02O21zWFgHPTfxtgn1QRe7NRgggUhC8hacR2Re94svHqeA==", + "node_modules/puppeteer/node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", "dev": true, "dependencies": { - "fs.realpath": "^1.0.0", - "minimatch": "^7.4.1", - "minipass": "^4.2.4", - "path-scurry": "^1.6.1" + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": ">=12" + } + }, + "node_modules/puppeteer/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "engines": { + "node": ">=7.0.0" } }, - "node_modules/puppeteer/node_modules/minimatch": { - "version": "7.4.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-7.4.3.tgz", - "integrity": "sha512-5UB4yYusDtkRPbRiy1cqZ1IpGNcJCGlEMG17RKzPddpyiPKoCdwohbED8g4QXT0ewCt8LTkQXuljsUfQ3FKM4A==", + "node_modules/puppeteer/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/puppeteer/node_modules/cosmiconfig": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.1.3.tgz", + "integrity": "sha512-/UkO2JKI18b5jVMJUp0lvKFMpa/Gye+ZgZjKD+DGEN9y7NRcf/nK1A0sp67ONmKtnDCNMS44E6jrk0Yc3bDuUw==", "dev": true, "dependencies": { - "brace-expansion": "^2.0.1" + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "parse-json": "^5.0.0", + "path-type": "^4.0.0" }, "engines": { - "node": ">=10" + "node": ">=14" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/sponsors/d-fischer" } }, "node_modules/puppeteer/node_modules/puppeteer-core": { - "version": "19.7.5", - "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-19.7.5.tgz", - "integrity": "sha512-EJuNha+SxPfaYFbkoWU80H3Wb1SiQH5fFyb2xdbWda0ziax5mhV63UMlqNfPeTDIWarwtR4OIcq/9VqY8HPOsg==", + "version": "19.9.0", + "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-19.9.0.tgz", + "integrity": "sha512-IJYfCE0oFpi5dTvNFqOwo8Dey6zzx7hANy7z6K2bjpCux9oPOSOIubq40awNhaHlfi8soYtgU4qabnzMXB7xBQ==", "dev": true, "dependencies": { - "chromium-bidi": "0.4.5", + "@puppeteer/browsers": "0.4.1", + "chromium-bidi": "0.4.6", "cross-fetch": "3.1.5", "debug": "4.3.4", - "devtools-protocol": "0.0.1094867", + "devtools-protocol": "0.0.1107588", "extract-zip": "2.0.1", "https-proxy-agent": "5.0.1", "proxy-from-env": "1.1.0", - "rimraf": "4.4.0", "tar-fs": "2.1.1", "unbzip2-stream": "1.4.3", - "ws": "8.12.1" + "ws": "8.13.0" }, "engines": { "node": ">=14.14.0" @@ -17901,28 +18673,10 @@ } } }, - "node_modules/puppeteer/node_modules/rimraf": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-4.4.0.tgz", - "integrity": "sha512-X36S+qpCUR0HjXlkDe4NAOhS//aHH0Z+h8Ckf2auGJk3PTnx5rLmrHkwNdbVQuCSUhOyFrlRvFEllZOYE+yZGQ==", - "dev": true, - "dependencies": { - "glob": "^9.2.0" - }, - "bin": { - "rimraf": "dist/cjs/src/bin.js" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/puppeteer/node_modules/typescript": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.2.tgz", - "integrity": "sha512-wVORMBGO/FAs/++blGNeAVdbNKtIh1rbBL2EyQ1+J9lClJ93KiiKe8PmFIVdXhHcyv44SL9oglmfeSsndo0jRw==", + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.4.tgz", + "integrity": "sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==", "dev": true, "optional": true, "peer": true, @@ -17934,25 +18688,57 @@ "node": ">=12.20" } }, - "node_modules/puppeteer/node_modules/ws": { - "version": "8.12.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.12.1.tgz", - "integrity": "sha512-1qo+M9Ba+xNhPB+YTWUlK6M17brTut5EXbcBaMRN5pH5dFrXz7lzz1ChFSUq3bOUl8yEvSenhHmYUNJxFzdJew==", + "node_modules/puppeteer/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, "engines": { - "node": ">=10.0.0" + "node": ">=10" }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/puppeteer/node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/puppeteer/node_modules/yargs": { + "version": "17.7.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.1.tgz", + "integrity": "sha512-cwiTb08Xuv5fqF4AovYacTFNxk62th7LKJ6BL9IGUpTJrWoU7/7WdQGTP2SjKf1dUNBGzDd28p/Yfs/GI6JrLw==", + "dev": true, + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } + "engines": { + "node": ">=12" + } + }, + "node_modules/puppeteer/node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "engines": { + "node": ">=12" } }, "node_modules/purgecss": { @@ -21089,12 +21875,20 @@ "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==" }, + "node_modules/requizzle": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.4.tgz", + "integrity": "sha512-JRrFk1D4OQ4SqovXOgdav+K8EAhSB/LJZqCz8tbX0KObcdeM15Ss59ozWMBWmmINMagCwmqn4ZNryUGpBsl6Jw==", + "dependencies": { + "lodash": "^4.17.21" + } + }, "node_modules/resolve": { - "version": "1.22.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", - "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "version": "1.22.2", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz", + "integrity": "sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==", "dependencies": { - "is-core-module": "^2.9.0", + "is-core-module": "^2.11.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, @@ -21308,6 +22102,16 @@ "node": ">=8.3" } }, + "node_modules/rollup-plugin-copy/node_modules/@types/glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==", + "dev": true, + "dependencies": { + "@types/minimatch": "*", + "@types/node": "*" + } + }, "node_modules/rollup-plugin-copy/node_modules/fs-extra": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", @@ -21495,9 +22299,9 @@ } }, "node_modules/semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.4.0.tgz", + "integrity": "sha512-RgOxM8Mw+7Zus0+zcLEUn8+JfoLpj/huFTItQy2hsM4khuC1HYRDp0cU482Ewn/Fcy6bCjufD8vAj7voC66KQw==", "dependencies": { "lru-cache": "^6.0.0" }, @@ -21856,9 +22660,9 @@ } }, "node_modules/shell-quote": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.0.tgz", - "integrity": "sha512-QHsz8GgQIGKlRi24yFc6a6lN69Idnx634w49ay6+jA5yFh7a1UY+4Rp6HPx/L/1zcEDPEij8cIsiqR6bQsE5VQ==", + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", + "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==", "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -21979,9 +22783,9 @@ "dev": true }, "node_modules/slugify": { - "version": "1.6.5", - "resolved": "https://registry.npmjs.org/slugify/-/slugify-1.6.5.tgz", - "integrity": "sha512-8mo9bslnBO3tr5PEVFzMPIWwWnipGS0xVbYf65zxDqfNwmzYn1LpiKNrR6DlClusuvo+hDHd1zKpmfAe83NQSQ==", + "version": "1.6.6", + "resolved": "https://registry.npmjs.org/slugify/-/slugify-1.6.6.tgz", + "integrity": "sha512-h+z7HKHYXj6wJU+AnS/+IH8Uh9fdcX1Lrhg1/VMdf9PwoBQXFcXiAdsy2tSK0P6gKwJLXp02r90ahUCqHk9rrw==", "engines": { "node": ">=8.0.0" } @@ -22780,7 +23584,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, "engines": { "node": ">=8" }, @@ -23290,9 +24093,9 @@ "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==" }, "node_modules/terser": { - "version": "5.16.6", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.6.tgz", - "integrity": "sha512-IBZ+ZQIA9sMaXmRZCUMDjNH0D5AQQfdn4WUjHL0+1lF4TP1IHRJbrhb6fNaXWikrYQTSkb7SLxkeXAiy1p7mbg==", + "version": "5.16.9", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.9.tgz", + "integrity": "sha512-HPa/FdTB9XGI2H1/keLFZHxl6WNvAI4YalHGtDQTlMnJcoqSab1UwL4l1hGEhs6/GmLHBZIg/YgB++jcbzoOEg==", "dev": true, "dependencies": { "@jridgewell/source-map": "^0.3.2", @@ -23418,7 +24221,6 @@ "version": "0.2.1", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", - "dev": true, "dependencies": { "rimraf": "^3.0.0" }, @@ -23840,9 +24642,9 @@ } }, "node_modules/ua-parser-js": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.34.tgz", - "integrity": "sha512-K9mwJm/DaB6mRLZfw6q8IMXipcrmuT6yfhYmwhAkuh+81sChuYstYA+znlgaflUPaYUa3odxKPKGw6Vw/lANew==", + "version": "1.0.35", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.35.tgz", + "integrity": "sha512-fKnGuqmTBnIE+/KXSzCn4db8RTigUzw1AN0DmdU6hJovUTbYJKyqj+8Mt1c4VfRDnOVJnENmfYkIPZ946UrSAA==", "funding": [ { "type": "opencollective", @@ -23871,7 +24673,6 @@ "version": "3.17.4", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz", "integrity": "sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==", - "optional": true, "bin": { "uglifyjs": "bin/uglifyjs" }, @@ -25114,9 +25915,9 @@ } }, "node_modules/web-vitals": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/web-vitals/-/web-vitals-3.3.0.tgz", - "integrity": "sha512-GZsEmJBNclIpViS/7QVOTr7Kbt4BgLeR7kQ5zCCtJVuiWsA+K6xTXaoEXssvl8yYFICEyNmA2Nr+vgBYTnS4bA==" + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/web-vitals/-/web-vitals-3.3.1.tgz", + "integrity": "sha512-LTfY5GjcY3ngFzNsYFSYL+AmVmlWrzPTUxSMDis2rZbf+SzT7HH3NH4Y/l45XOlrAIunOBeURN9qtBHkRskAiA==" }, "node_modules/webdev-infra": { "version": "1.0.53", @@ -25352,7 +26153,6 @@ "version": "1.2.3", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -25469,6 +26269,11 @@ "node": ">=8" } }, + "node_modules/xmlcreate": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-2.0.4.tgz", + "integrity": "sha512-nquOebG4sngPmGPICTS5EnxqhKbCmz5Ox5hsszI2T6U5qdrJizBc+0ilYSEjTSzU0yZcmvppztXe/5Al5fUwdg==" + }, "node_modules/xmlhttprequest-ssl": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.0.0.tgz", @@ -25704,127 +26509,127 @@ } }, "@algolia/cache-browser-local-storage": { - "version": "4.16.0", - "resolved": "https://registry.npmjs.org/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.16.0.tgz", - "integrity": "sha512-jVrk0YB3tjOhD5/lhBtYCVCeLjZmVpf2kdi4puApofytf/R0scjWz0GdozlW4HhU+Prxmt/c9ge4QFjtv5OAzQ==", + "version": "4.17.0", + "resolved": "https://registry.npmjs.org/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.17.0.tgz", + "integrity": "sha512-myRSRZDIMYB8uCkO+lb40YKiYHi0fjpWRtJpR/dgkaiBlSD0plRyB6lLOh1XIfmMcSeBOqDE7y9m8xZMrXYfyQ==", "requires": { - "@algolia/cache-common": "4.16.0" + "@algolia/cache-common": "4.17.0" } }, "@algolia/cache-common": { - "version": "4.16.0", - "resolved": "https://registry.npmjs.org/@algolia/cache-common/-/cache-common-4.16.0.tgz", - "integrity": "sha512-4iHjkSYQYw46pITrNQgXXhvUmcekI8INz1m+SzmqLX8jexSSy4Ky4zfGhZzhhhLHXUP3+x/PK/c0qPjxEvRwKQ==" + "version": "4.17.0", + "resolved": "https://registry.npmjs.org/@algolia/cache-common/-/cache-common-4.17.0.tgz", + "integrity": "sha512-g8mXzkrcUBIPZaulAuqE7xyHhLAYAcF2xSch7d9dABheybaU3U91LjBX6eJTEB7XVhEsgK4Smi27vWtAJRhIKQ==" }, "@algolia/cache-in-memory": { - "version": "4.16.0", - "resolved": "https://registry.npmjs.org/@algolia/cache-in-memory/-/cache-in-memory-4.16.0.tgz", - "integrity": "sha512-p7RYykvA6Ip6QENxrh99nOD77otVh1sJRivcgcVpnjoZb5sIN3t33eUY1DpB9QSBizcrW+qk19rNkdnZ43a+PQ==", + "version": "4.17.0", + "resolved": "https://registry.npmjs.org/@algolia/cache-in-memory/-/cache-in-memory-4.17.0.tgz", + "integrity": "sha512-PT32ciC/xI8z919d0oknWVu3kMfTlhQn3MKxDln3pkn+yA7F7xrxSALysxquv+MhFfNAcrtQ/oVvQVBAQSHtdw==", "requires": { - "@algolia/cache-common": "4.16.0" + "@algolia/cache-common": "4.17.0" } }, "@algolia/client-account": { - "version": "4.16.0", - "resolved": "https://registry.npmjs.org/@algolia/client-account/-/client-account-4.16.0.tgz", - "integrity": "sha512-eydcfpdIyuWoKgUSz5iZ/L0wE/Wl7958kACkvTHLDNXvK/b8Z1zypoJavh6/km1ZNQmFpeYS2jrmq0kUSFn02w==", + "version": "4.17.0", + "resolved": "https://registry.npmjs.org/@algolia/client-account/-/client-account-4.17.0.tgz", + "integrity": "sha512-sSEHx9GA6m7wrlsSMNBGfyzlIfDT2fkz2u7jqfCCd6JEEwmxt8emGmxAU/0qBfbhRSuGvzojoLJlr83BSZAKjA==", "requires": { - "@algolia/client-common": "4.16.0", - "@algolia/client-search": "4.16.0", - "@algolia/transporter": "4.16.0" + "@algolia/client-common": "4.17.0", + "@algolia/client-search": "4.17.0", + "@algolia/transporter": "4.17.0" } }, "@algolia/client-analytics": { - "version": "4.16.0", - "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-4.16.0.tgz", - "integrity": "sha512-cONWXH3BfilgdlCofUm492bJRWtpBLVW/hsUlfoFtiX1u05xoBP7qeiDwh9RR+4pSLHLodYkHAf5U4honQ55Qg==", + "version": "4.17.0", + "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-4.17.0.tgz", + "integrity": "sha512-84ooP8QA3mQ958hQ9wozk7hFUbAO+81CX1CjAuerxBqjKIInh1fOhXKTaku05O/GHBvcfExpPLIQuSuLYziBXQ==", "requires": { - "@algolia/client-common": "4.16.0", - "@algolia/client-search": "4.16.0", - "@algolia/requester-common": "4.16.0", - "@algolia/transporter": "4.16.0" + "@algolia/client-common": "4.17.0", + "@algolia/client-search": "4.17.0", + "@algolia/requester-common": "4.17.0", + "@algolia/transporter": "4.17.0" } }, "@algolia/client-common": { - "version": "4.16.0", - "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.16.0.tgz", - "integrity": "sha512-QVdR4019ukBH6f5lFr27W60trRxQF1SfS1qo0IP6gjsKhXhUVJuHxOCA6ArF87jrNkeuHEoRoDU+GlvaecNo8g==", + "version": "4.17.0", + "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.17.0.tgz", + "integrity": "sha512-jHMks0ZFicf8nRDn6ma8DNNsdwGgP/NKiAAL9z6rS7CymJ7L0+QqTJl3rYxRW7TmBhsUH40wqzmrG6aMIN/DrQ==", "requires": { - "@algolia/requester-common": "4.16.0", - "@algolia/transporter": "4.16.0" + "@algolia/requester-common": "4.17.0", + "@algolia/transporter": "4.17.0" } }, "@algolia/client-personalization": { - "version": "4.16.0", - "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-4.16.0.tgz", - "integrity": "sha512-irtLafssDGPuhYqIwxqOxiWlVYvrsBD+EMA1P9VJtkKi3vSNBxiWeQ0f0Tn53cUNdSRNEssfoEH84JL97SV2SQ==", + "version": "4.17.0", + "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-4.17.0.tgz", + "integrity": "sha512-RMzN4dZLIta1YuwT7QC9o+OeGz2cU6eTOlGNE/6RcUBLOU3l9tkCOdln5dPE2jp8GZXPl2yk54b2nSs1+pAjqw==", "requires": { - "@algolia/client-common": "4.16.0", - "@algolia/requester-common": "4.16.0", - "@algolia/transporter": "4.16.0" + "@algolia/client-common": "4.17.0", + "@algolia/requester-common": "4.17.0", + "@algolia/transporter": "4.17.0" } }, "@algolia/client-search": { - "version": "4.16.0", - "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-4.16.0.tgz", - "integrity": "sha512-xsfrAE1jO/JDh1wFrRz+alVyW+aA6qnkzmbWWWZWEgVF3EaFqzIf9r1l/aDtDdBtNTNhX9H3Lg31+BRtd5izQA==", + "version": "4.17.0", + "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-4.17.0.tgz", + "integrity": "sha512-x4P2wKrrRIXszT8gb7eWsMHNNHAJs0wE7/uqbufm4tZenAp+hwU/hq5KVsY50v+PfwM0LcDwwn/1DroujsTFoA==", "requires": { - "@algolia/client-common": "4.16.0", - "@algolia/requester-common": "4.16.0", - "@algolia/transporter": "4.16.0" + "@algolia/client-common": "4.17.0", + "@algolia/requester-common": "4.17.0", + "@algolia/transporter": "4.17.0" } }, "@algolia/logger-common": { - "version": "4.16.0", - "resolved": "https://registry.npmjs.org/@algolia/logger-common/-/logger-common-4.16.0.tgz", - "integrity": "sha512-U9H8uCzSDuePJmbnjjTX21aPDRU6x74Tdq3dJmdYu2+pISx02UeBJm4kSgc9RW5jcR5j35G9gnjHY9Q3ngWbyQ==" + "version": "4.17.0", + "resolved": "https://registry.npmjs.org/@algolia/logger-common/-/logger-common-4.17.0.tgz", + "integrity": "sha512-DGuoZqpTmIKJFDeyAJ7M8E/LOenIjWiOsg1XJ1OqAU/eofp49JfqXxbfgctlVZVmDABIyOz8LqEoJ6ZP4DTyvw==" }, "@algolia/logger-console": { - "version": "4.16.0", - "resolved": "https://registry.npmjs.org/@algolia/logger-console/-/logger-console-4.16.0.tgz", - "integrity": "sha512-+qymusiM+lPZKrkf0tDjCQA158eEJO2IU+Nr/sJ9TFyI/xkFPjNPzw/Qbc8Iy/xcOXGlc6eMgmyjtVQqAWq6UA==", + "version": "4.17.0", + "resolved": "https://registry.npmjs.org/@algolia/logger-console/-/logger-console-4.17.0.tgz", + "integrity": "sha512-zMPvugQV/gbXUvWBCzihw6m7oxIKp48w37QBIUu/XqQQfxhjoOE9xyfJr1KldUt5FrYOKZJVsJaEjTsu+bIgQg==", "requires": { - "@algolia/logger-common": "4.16.0" + "@algolia/logger-common": "4.17.0" } }, "@algolia/requester-browser-xhr": { - "version": "4.16.0", - "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.16.0.tgz", - "integrity": "sha512-gK+kvs6LHl/PaOJfDuwjkopNbG1djzFLsVBklGBsSU6h6VjFkxIpo6Qq80IK14p9cplYZfhfaL12va6Q9p3KVQ==", + "version": "4.17.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.17.0.tgz", + "integrity": "sha512-aSOX/smauyTkP21Pf52pJ1O2LmNFJ5iHRIzEeTh0mwBeADO4GdG94cAWDILFA9rNblq/nK3EDh3+UyHHjplZ1A==", "requires": { - "@algolia/requester-common": "4.16.0" + "@algolia/requester-common": "4.17.0" } }, "@algolia/requester-common": { - "version": "4.16.0", - "resolved": "https://registry.npmjs.org/@algolia/requester-common/-/requester-common-4.16.0.tgz", - "integrity": "sha512-3Zmcs/iMubcm4zqZ3vZG6Zum8t+hMWxGMzo0/uY2BD8o9q5vMxIYI0c4ocdgQjkXcix189WtZNkgjSOBzSbkdw==" + "version": "4.17.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-common/-/requester-common-4.17.0.tgz", + "integrity": "sha512-XJjmWFEUlHu0ijvcHBoixuXfEoiRUdyzQM6YwTuB8usJNIgShua8ouFlRWF8iCeag0vZZiUm4S2WCVBPkdxFgg==" }, "@algolia/requester-node-http": { - "version": "4.16.0", - "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-4.16.0.tgz", - "integrity": "sha512-L8JxM2VwZzh8LJ1Zb8TFS6G3icYsCKZsdWW+ahcEs1rGWmyk9SybsOe1MLnjonGBaqPWJkn9NjS7mRdjEmBtKA==", + "version": "4.17.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-4.17.0.tgz", + "integrity": "sha512-bpb/wDA1aC6WxxM8v7TsFspB7yBN3nqCGs2H1OADolQR/hiAIjAxusbuMxVbRFOdaUvAIqioIIkWvZdpYNIn8w==", "requires": { - "@algolia/requester-common": "4.16.0" + "@algolia/requester-common": "4.17.0" } }, "@algolia/transporter": { - "version": "4.16.0", - "resolved": "https://registry.npmjs.org/@algolia/transporter/-/transporter-4.16.0.tgz", - "integrity": "sha512-H9BVB2EAjT65w7XGBNf5drpsW39x2aSZ942j4boSAAJPPlLmjtj5IpAP7UAtsV8g9Beslonh0bLa1XGmE/P0BA==", + "version": "4.17.0", + "resolved": "https://registry.npmjs.org/@algolia/transporter/-/transporter-4.17.0.tgz", + "integrity": "sha512-6xL6H6fe+Fi0AEP3ziSgC+G04RK37iRb4uUUqVAH9WPYFI8g+LYFq6iv5HS8Cbuc5TTut+Bwj6G+dh/asdb9uA==", "requires": { - "@algolia/cache-common": "4.16.0", - "@algolia/logger-common": "4.16.0", - "@algolia/requester-common": "4.16.0" + "@algolia/cache-common": "4.17.0", + "@algolia/logger-common": "4.17.0", + "@algolia/requester-common": "4.17.0" } }, "@ampproject/remapping": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", - "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", + "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", "dev": true, "requires": { - "@jridgewell/gen-mapping": "^0.1.0", + "@jridgewell/gen-mapping": "^0.3.0", "@jridgewell/trace-mapping": "^0.3.9" } }, @@ -25877,36 +26682,36 @@ "dev": true }, "@babel/code-frame": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", - "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.21.4.tgz", + "integrity": "sha512-LYvhNKfwWSPpocw8GI7gpK2nq3HSDuEPC/uSYaALSJu9xjsalaaYFOq0Pwt5KmVqwEbZlDu81aLXwBOmD/Fv9g==", "dev": true, "requires": { "@babel/highlight": "^7.18.6" } }, "@babel/compat-data": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.21.0.tgz", - "integrity": "sha512-gMuZsmsgxk/ENC3O/fRw5QY8A9/uxQbbCEypnLIiYYc/qVJtEV7ouxC3EllIIwNzMqAQee5tanFabWsUOutS7g==", + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.21.4.tgz", + "integrity": "sha512-/DYyDpeCfaVinT40FPGdkkb+lYSKvsVuMjDAG7jPOWWiM1ibOaB9CXJAlc4d1QpP/U2q2P9jbrSlClKSErd55g==", "dev": true }, "@babel/core": { - "version": "7.21.3", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.21.3.tgz", - "integrity": "sha512-qIJONzoa/qiHghnm0l1n4i/6IIziDpzqc36FBs4pzMhDUraHqponwJLiAKm1hGLP3OSB/TVNz6rMwVGpwxxySw==", + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.21.4.tgz", + "integrity": "sha512-qt/YV149Jman/6AfmlxJ04LMIu8bMoyl3RB91yTFrxQmgbrSvQMy7cI8Q62FHx1t8wJ8B5fu0UDoLwHAhUo1QA==", "dev": true, "requires": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.21.3", - "@babel/helper-compilation-targets": "^7.20.7", + "@babel/code-frame": "^7.21.4", + "@babel/generator": "^7.21.4", + "@babel/helper-compilation-targets": "^7.21.4", "@babel/helper-module-transforms": "^7.21.2", "@babel/helpers": "^7.21.0", - "@babel/parser": "^7.21.3", + "@babel/parser": "^7.21.4", "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.3", - "@babel/types": "^7.21.3", + "@babel/traverse": "^7.21.4", + "@babel/types": "^7.21.4", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -25923,38 +26728,25 @@ } }, "@babel/generator": { - "version": "7.21.3", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.21.3.tgz", - "integrity": "sha512-QS3iR1GYC/YGUnW7IdggFeN5c1poPUurnGttOV/bZgPGV+izC/D8HnD6DLwod0fsatNyVn1G3EVWMYIF0nHbeA==", + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.21.4.tgz", + "integrity": "sha512-NieM3pVIYW2SwGzKoqfPrQsf4xGs9M9AIG3ThppsSRmO+m7eQhmI6amajKMUeIO37wFfsvnvcxQFx6x6iqxDnA==", "dev": true, "requires": { - "@babel/types": "^7.21.3", + "@babel/types": "^7.21.4", "@jridgewell/gen-mapping": "^0.3.2", "@jridgewell/trace-mapping": "^0.3.17", "jsesc": "^2.5.1" - }, - "dependencies": { - "@jridgewell/gen-mapping": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", - "dev": true, - "requires": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - } - } } }, "@babel/helper-compilation-targets": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.20.7.tgz", - "integrity": "sha512-4tGORmfQcrc+bvrjb5y3dG9Mx1IOZjsHqQVUz7XCNHO+iTmqxWnVg3KRygjGmpRLJGdQSKuvFinbIb0CnZwHAQ==", + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.21.4.tgz", + "integrity": "sha512-Fa0tTuOXZ1iL8IeDFUWCzjZcn+sJGd9RZdH9esYVjEejGmzf+FFYQpMi/kZUk2kPy/q1H3/GPw7np8qar/stfg==", "dev": true, "requires": { - "@babel/compat-data": "^7.20.5", - "@babel/helper-validator-option": "^7.18.6", + "@babel/compat-data": "^7.21.4", + "@babel/helper-validator-option": "^7.21.0", "browserslist": "^4.21.3", "lru-cache": "^5.1.1", "semver": "^6.3.0" @@ -25994,12 +26786,12 @@ } }, "@babel/helper-module-imports": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", - "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.21.4.tgz", + "integrity": "sha512-orajc5T2PsRYUN3ZryCEFeMDYwyw09c/pZeaQEZPH0MpKzSvn3e0uXsDBu3k03VI+9DBiRo+l22BfKTpKwa/Wg==", "dev": true, "requires": { - "@babel/types": "^7.18.6" + "@babel/types": "^7.21.4" } }, "@babel/helper-module-transforms": { @@ -26133,9 +26925,9 @@ } }, "@babel/parser": { - "version": "7.21.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.3.tgz", - "integrity": "sha512-lobG0d7aOfQRXh8AyklEAgZGvA4FShxo6xQbUrrT/cNBPUdIDojlokwJsQyCC/eKia7ifqM0yP+2DRZ4WKw2RQ==" + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.4.tgz", + "integrity": "sha512-alVJj7k7zIxqBZ7BTRhz0IqJFxW1VJbm6N8JbcYhQ186df9ZBPbZBmWSqAMXwHGsCJdYks7z/voa3ibiS5bCIw==" }, "@babel/plugin-proposal-dynamic-import": { "version": "7.18.6", @@ -26218,27 +27010,27 @@ } }, "@babel/traverse": { - "version": "7.21.3", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.21.3.tgz", - "integrity": "sha512-XLyopNeaTancVitYZe2MlUEvgKb6YVVPXzofHgqHijCImG33b/uTurMS488ht/Hbsb2XK3U2BnSTxKVNGV3nGQ==", + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.21.4.tgz", + "integrity": "sha512-eyKrRHKdyZxqDm+fV1iqL9UAHMoIg0nDaGqfIOd8rKH17m5snv7Gn4qgjBoFfLz9APvjFU/ICT00NVCv1Epp8Q==", "dev": true, "requires": { - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.21.3", + "@babel/code-frame": "^7.21.4", + "@babel/generator": "^7.21.4", "@babel/helper-environment-visitor": "^7.18.9", "@babel/helper-function-name": "^7.21.0", "@babel/helper-hoist-variables": "^7.18.6", "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/parser": "^7.21.3", - "@babel/types": "^7.21.3", + "@babel/parser": "^7.21.4", + "@babel/types": "^7.21.4", "debug": "^4.1.0", "globals": "^11.1.0" } }, "@babel/types": { - "version": "7.21.3", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.21.3.tgz", - "integrity": "sha512-sBGdETxC+/M4o/zKC0sl6sjWv62WFR/uzxrJ6uYyMLZOUlPnwzw0tKgVHOXxaAd5l2g8pEDM5RZ495GPQI77kg==", + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.21.4.tgz", + "integrity": "sha512-rU2oY501qDxE8Pyo7i/Orqma4ziCOrby0/9mvbDUGEfvZjb279Nk9k19e2fiCxHbRRpY2ZyrgW1eq22mvmOIzA==", "requires": { "@babel/helper-string-parser": "^7.19.4", "@babel/helper-validator-identifier": "^7.19.1", @@ -26279,6 +27071,12 @@ "strip-json-comments": "^3.1.1" }, "dependencies": { + "acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true + }, "ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -26300,6 +27098,23 @@ "sprintf-js": "~1.0.2" } }, + "eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true + }, + "espree": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", + "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", + "dev": true, + "requires": { + "acorn": "^7.4.0", + "acorn-jsx": "^5.3.1", + "eslint-visitor-keys": "^1.3.0" + } + }, "globals": { "version": "13.20.0", "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", @@ -26339,12 +27154,231 @@ } } }, + "@google-cloud/appengine-admin": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@google-cloud/appengine-admin/-/appengine-admin-2.1.2.tgz", + "integrity": "sha512-ksR0Z64OhB5PDg9TgopWEUNt74hWP4Bs6IviFQGv3xAYQR43UqBWINPhYrxSkzIYol9L4PDyUoA1Dl1N4D0CXg==", + "requires": { + "google-gax": "^3.5.2" + } + }, "@google-cloud/cloudbuild": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/@google-cloud/cloudbuild/-/cloudbuild-2.6.0.tgz", "integrity": "sha512-+MKgIJ6MEomk5KF14PYUXQzkW3BDY+eMzsoxExkwnAQEFdrgrfnDTuLEpBWdP37ywAmTi8DSrtCy4pNtwZBiqA==", "requires": { "google-gax": "^2.24.1" + }, + "dependencies": { + "@grpc/grpc-js": { + "version": "1.6.12", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.6.12.tgz", + "integrity": "sha512-JmvQ03OTSpVd9JTlj/K3IWHSz4Gk/JMLUTtW7Zb0KvO1LcOYGATh5cNuRYzCAeDR3O8wq+q8FZe97eO9MBrkUw==", + "requires": { + "@grpc/proto-loader": "^0.7.0", + "@types/node": ">=12.12.47" + } + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "gaxios": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-4.3.3.tgz", + "integrity": "sha512-gSaYYIO1Y3wUtdfHmjDUZ8LWaxJQpiavzbF5Kq53akSzvmVg0RfyOcFDbO1KJ/KCGRFz2qG+lS81F0nkr7cRJA==", + "requires": { + "abort-controller": "^3.0.0", + "extend": "^3.0.2", + "https-proxy-agent": "^5.0.0", + "is-stream": "^2.0.0", + "node-fetch": "^2.6.7" + } + }, + "gcp-metadata": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-4.3.1.tgz", + "integrity": "sha512-x850LS5N7V1F3UcV7PoupzGsyD6iVwTVvsh3tbXfkctZnBnjW5yu5z1/3k3SehF7TyoTIe78rJs02GMMy+LF+A==", + "requires": { + "gaxios": "^4.0.0", + "json-bigint": "^1.0.0" + } + }, + "google-auth-library": { + "version": "7.14.1", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-7.14.1.tgz", + "integrity": "sha512-5Rk7iLNDFhFeBYc3s8l1CqzbEBcdhwR193RlD4vSNFajIcINKI8W8P0JLmBpwymHqqWbX34pJDQu39cSy/6RsA==", + "requires": { + "arrify": "^2.0.0", + "base64-js": "^1.3.0", + "ecdsa-sig-formatter": "^1.0.11", + "fast-text-encoding": "^1.0.0", + "gaxios": "^4.0.0", + "gcp-metadata": "^4.2.0", + "gtoken": "^5.0.4", + "jws": "^4.0.0", + "lru-cache": "^6.0.0" + } + }, + "google-gax": { + "version": "2.30.5", + "resolved": "https://registry.npmjs.org/google-gax/-/google-gax-2.30.5.tgz", + "integrity": "sha512-Jey13YrAN2hfpozHzbtrwEfEHdStJh1GwaQ2+Akh1k0Tv/EuNVSuBtHZoKSBm5wBMvNsxTsEIZ/152NrYyZgxQ==", + "requires": { + "@grpc/grpc-js": "~1.6.0", + "@grpc/proto-loader": "^0.6.12", + "@types/long": "^4.0.0", + "abort-controller": "^3.0.0", + "duplexify": "^4.0.0", + "fast-text-encoding": "^1.0.3", + "google-auth-library": "^7.14.0", + "is-stream-ended": "^0.1.4", + "node-fetch": "^2.6.1", + "object-hash": "^3.0.0", + "proto3-json-serializer": "^0.1.8", + "protobufjs": "6.11.3", + "retry-request": "^4.0.0" + }, + "dependencies": { + "@grpc/proto-loader": { + "version": "0.6.13", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.6.13.tgz", + "integrity": "sha512-FjxPYDRTn6Ec3V0arm1FtSpmP6V50wuph2yILpyvTKzjc76oDdoihXqM1DzOW5ubvCC8GivfCnNtfaRE8myJ7g==", + "requires": { + "@types/long": "^4.0.1", + "lodash.camelcase": "^4.3.0", + "long": "^4.0.0", + "protobufjs": "^6.11.3", + "yargs": "^16.2.0" + } + } + } + }, + "google-p12-pem": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-3.1.4.tgz", + "integrity": "sha512-HHuHmkLgwjdmVRngf5+gSmpkyaRI6QmOg77J8tkNBHhNEI62sGHyw4/+UkgyZEI7h84NbWprXDJ+sa3xOYFvTg==", + "requires": { + "node-forge": "^1.3.1" + } + }, + "gtoken": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-5.3.2.tgz", + "integrity": "sha512-gkvEKREW7dXWF8NV8pVrKfW7WqReAmjjkMBh6lNCCGOM4ucS0r0YyXXl0r/9Yj8wcW/32ISkfc8h5mPTDbtifQ==", + "requires": { + "gaxios": "^4.0.0", + "google-p12-pem": "^3.1.3", + "jws": "^4.0.0" + } + }, + "is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==" + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "requires": { + "yallist": "^4.0.0" + } + }, + "proto3-json-serializer": { + "version": "0.1.9", + "resolved": "https://registry.npmjs.org/proto3-json-serializer/-/proto3-json-serializer-0.1.9.tgz", + "integrity": "sha512-A60IisqvnuI45qNRygJjrnNjX2TMdQGMY+57tR3nul3ZgO2zXkR9OGR8AXxJhkqx84g0FTnrfi3D5fWMSdANdQ==", + "requires": { + "protobufjs": "^6.11.2" + } + }, + "protobufjs": { + "version": "6.11.3", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.3.tgz", + "integrity": "sha512-xL96WDdCZYdU7Slin569tFX712BxsxslWwAfAhCYjQKGTq7dAU91Lomy6nLLhh/dyGhk/YH4TwTSRxTzhuHyZg==", + "requires": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/long": "^4.0.1", + "@types/node": ">=13.7.0", + "long": "^4.0.0" + } + }, + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==" + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "requires": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + } + }, + "yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==" + } } }, "@google-cloud/common": { @@ -26473,12 +27507,244 @@ "dev": true, "requires": { "google-gax": "^2.30.0" + }, + "dependencies": { + "@grpc/grpc-js": { + "version": "1.6.12", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.6.12.tgz", + "integrity": "sha512-JmvQ03OTSpVd9JTlj/K3IWHSz4Gk/JMLUTtW7Zb0KvO1LcOYGATh5cNuRYzCAeDR3O8wq+q8FZe97eO9MBrkUw==", + "dev": true, + "requires": { + "@grpc/proto-loader": "^0.7.0", + "@types/node": ">=12.12.47" + } + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "gaxios": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-4.3.3.tgz", + "integrity": "sha512-gSaYYIO1Y3wUtdfHmjDUZ8LWaxJQpiavzbF5Kq53akSzvmVg0RfyOcFDbO1KJ/KCGRFz2qG+lS81F0nkr7cRJA==", + "dev": true, + "requires": { + "abort-controller": "^3.0.0", + "extend": "^3.0.2", + "https-proxy-agent": "^5.0.0", + "is-stream": "^2.0.0", + "node-fetch": "^2.6.7" + } + }, + "gcp-metadata": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-4.3.1.tgz", + "integrity": "sha512-x850LS5N7V1F3UcV7PoupzGsyD6iVwTVvsh3tbXfkctZnBnjW5yu5z1/3k3SehF7TyoTIe78rJs02GMMy+LF+A==", + "dev": true, + "requires": { + "gaxios": "^4.0.0", + "json-bigint": "^1.0.0" + } + }, + "google-auth-library": { + "version": "7.14.1", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-7.14.1.tgz", + "integrity": "sha512-5Rk7iLNDFhFeBYc3s8l1CqzbEBcdhwR193RlD4vSNFajIcINKI8W8P0JLmBpwymHqqWbX34pJDQu39cSy/6RsA==", + "dev": true, + "requires": { + "arrify": "^2.0.0", + "base64-js": "^1.3.0", + "ecdsa-sig-formatter": "^1.0.11", + "fast-text-encoding": "^1.0.0", + "gaxios": "^4.0.0", + "gcp-metadata": "^4.2.0", + "gtoken": "^5.0.4", + "jws": "^4.0.0", + "lru-cache": "^6.0.0" + } + }, + "google-gax": { + "version": "2.30.5", + "resolved": "https://registry.npmjs.org/google-gax/-/google-gax-2.30.5.tgz", + "integrity": "sha512-Jey13YrAN2hfpozHzbtrwEfEHdStJh1GwaQ2+Akh1k0Tv/EuNVSuBtHZoKSBm5wBMvNsxTsEIZ/152NrYyZgxQ==", + "dev": true, + "requires": { + "@grpc/grpc-js": "~1.6.0", + "@grpc/proto-loader": "^0.6.12", + "@types/long": "^4.0.0", + "abort-controller": "^3.0.0", + "duplexify": "^4.0.0", + "fast-text-encoding": "^1.0.3", + "google-auth-library": "^7.14.0", + "is-stream-ended": "^0.1.4", + "node-fetch": "^2.6.1", + "object-hash": "^3.0.0", + "proto3-json-serializer": "^0.1.8", + "protobufjs": "6.11.3", + "retry-request": "^4.0.0" + }, + "dependencies": { + "@grpc/proto-loader": { + "version": "0.6.13", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.6.13.tgz", + "integrity": "sha512-FjxPYDRTn6Ec3V0arm1FtSpmP6V50wuph2yILpyvTKzjc76oDdoihXqM1DzOW5ubvCC8GivfCnNtfaRE8myJ7g==", + "dev": true, + "requires": { + "@types/long": "^4.0.1", + "lodash.camelcase": "^4.3.0", + "long": "^4.0.0", + "protobufjs": "^6.11.3", + "yargs": "^16.2.0" + } + } + } + }, + "google-p12-pem": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-3.1.4.tgz", + "integrity": "sha512-HHuHmkLgwjdmVRngf5+gSmpkyaRI6QmOg77J8tkNBHhNEI62sGHyw4/+UkgyZEI7h84NbWprXDJ+sa3xOYFvTg==", + "dev": true, + "requires": { + "node-forge": "^1.3.1" + } + }, + "gtoken": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-5.3.2.tgz", + "integrity": "sha512-gkvEKREW7dXWF8NV8pVrKfW7WqReAmjjkMBh6lNCCGOM4ucS0r0YyXXl0r/9Yj8wcW/32ISkfc8h5mPTDbtifQ==", + "dev": true, + "requires": { + "gaxios": "^4.0.0", + "google-p12-pem": "^3.1.3", + "jws": "^4.0.0" + } + }, + "is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "proto3-json-serializer": { + "version": "0.1.9", + "resolved": "https://registry.npmjs.org/proto3-json-serializer/-/proto3-json-serializer-0.1.9.tgz", + "integrity": "sha512-A60IisqvnuI45qNRygJjrnNjX2TMdQGMY+57tR3nul3ZgO2zXkR9OGR8AXxJhkqx84g0FTnrfi3D5fWMSdANdQ==", + "dev": true, + "requires": { + "protobufjs": "^6.11.2" + } + }, + "protobufjs": { + "version": "6.11.3", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.3.tgz", + "integrity": "sha512-xL96WDdCZYdU7Slin569tFX712BxsxslWwAfAhCYjQKGTq7dAU91Lomy6nLLhh/dyGhk/YH4TwTSRxTzhuHyZg==", + "dev": true, + "requires": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/long": "^4.0.1", + "@types/node": ">=13.7.0", + "long": "^4.0.0" + } + }, + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "requires": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + } + }, + "yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true + } } }, "@google-cloud/storage": { - "version": "6.9.4", - "resolved": "https://registry.npmjs.org/@google-cloud/storage/-/storage-6.9.4.tgz", - "integrity": "sha512-5Li+0xRJ8wgc+vlf7Tgew8COKEJgRzRmC5ozdSYaBj7BK+X39aPPBP6ROsDTiCZ0MpAg7dxIc+HhKiCvQDplXQ==", + "version": "6.9.5", + "resolved": "https://registry.npmjs.org/@google-cloud/storage/-/storage-6.9.5.tgz", + "integrity": "sha512-fcLsDA8YKcGuqvhk0XTjJGVpG9dzs5Em8IcUjSjspYvERuHYqMy9CMChWapSjv3Lyw//exa3mv4nUxPlV93BnA==", "requires": { "@google-cloud/paginator": "^3.0.7", "@google-cloud/projectify": "^3.0.0", @@ -26540,128 +27806,23 @@ } }, "@grpc/grpc-js": { - "version": "1.6.12", - "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.6.12.tgz", - "integrity": "sha512-JmvQ03OTSpVd9JTlj/K3IWHSz4Gk/JMLUTtW7Zb0KvO1LcOYGATh5cNuRYzCAeDR3O8wq+q8FZe97eO9MBrkUw==", + "version": "1.8.14", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.8.14.tgz", + "integrity": "sha512-w84maJ6CKl5aApCMzFll0hxtFNT6or9WwMslobKaqWUEf1K+zhlL43bSQhFreyYWIWR+Z0xnVFC1KtLm4ZpM/A==", "requires": { "@grpc/proto-loader": "^0.7.0", "@types/node": ">=12.12.47" - }, - "dependencies": { - "@grpc/proto-loader": { - "version": "0.7.6", - "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.6.tgz", - "integrity": "sha512-QyAXR8Hyh7uMDmveWxDSUcJr9NAWaZ2I6IXgAYvQmfflwouTM+rArE2eEaCtLlRqO81j7pRLCt81IefUei6Zbw==", - "requires": { - "@types/long": "^4.0.1", - "lodash.camelcase": "^4.3.0", - "long": "^4.0.0", - "protobufjs": "^7.0.0", - "yargs": "^16.2.0" - } - }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "requires": { - "color-convert": "^2.0.1" - } - }, - "cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "protobufjs": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.2.tgz", - "integrity": "sha512-++PrQIjrom+bFDPpfmqXfAGSQs40116JRrqqyf53dymUMvvb5d/LMRyicRoF1AUKoXVS1/IgJXlEgcpr4gTF3Q==", - "requires": { - "@protobufjs/aspromise": "^1.1.2", - "@protobufjs/base64": "^1.1.2", - "@protobufjs/codegen": "^2.0.4", - "@protobufjs/eventemitter": "^1.1.0", - "@protobufjs/fetch": "^1.1.0", - "@protobufjs/float": "^1.0.2", - "@protobufjs/inquire": "^1.1.0", - "@protobufjs/path": "^1.1.2", - "@protobufjs/pool": "^1.1.0", - "@protobufjs/utf8": "^1.1.0", - "@types/node": ">=13.7.0", - "long": "^5.0.0" - }, - "dependencies": { - "long": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/long/-/long-5.2.1.tgz", - "integrity": "sha512-GKSNGeNAtw8IryjjkhZxuKB3JzlcLTwjtiQCHKvqQet81I93kXslhDQruGI/QsddO83mcDToBVy7GqGS/zYf/A==" - } - } - }, - "wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - }, - "y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==" - }, - "yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "requires": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - } - }, - "yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==" - } } }, "@grpc/proto-loader": { - "version": "0.6.13", - "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.6.13.tgz", - "integrity": "sha512-FjxPYDRTn6Ec3V0arm1FtSpmP6V50wuph2yILpyvTKzjc76oDdoihXqM1DzOW5ubvCC8GivfCnNtfaRE8myJ7g==", + "version": "0.7.6", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.6.tgz", + "integrity": "sha512-QyAXR8Hyh7uMDmveWxDSUcJr9NAWaZ2I6IXgAYvQmfflwouTM+rArE2eEaCtLlRqO81j7pRLCt81IefUei6Zbw==", "requires": { "@types/long": "^4.0.1", "lodash.camelcase": "^4.3.0", "long": "^4.0.0", - "protobufjs": "^6.11.3", + "protobufjs": "^7.0.0", "yargs": "^16.2.0" }, "dependencies": { @@ -26805,13 +27966,14 @@ "dev": true }, "@jridgewell/gen-mapping": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", - "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", + "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", "dev": true, "requires": { - "@jridgewell/set-array": "^1.0.0", - "@jridgewell/sourcemap-codec": "^1.4.10" + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" } }, "@jridgewell/resolve-uri": { @@ -26827,42 +27989,45 @@ "dev": true }, "@jridgewell/source-map": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", - "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.3.tgz", + "integrity": "sha512-b+fsZXeLYi9fEULmfBrhxn4IrPlINf8fiNarzTof004v3lFdntdwa9PF7vFJqm3mg7s+ScJMxXaE3Acp1irZcg==", "dev": true, "requires": { "@jridgewell/gen-mapping": "^0.3.0", "@jridgewell/trace-mapping": "^0.3.9" - }, - "dependencies": { - "@jridgewell/gen-mapping": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", - "dev": true, - "requires": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - } - } } }, "@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", "dev": true }, "@jridgewell/trace-mapping": { - "version": "0.3.17", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz", - "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", + "version": "0.3.18", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz", + "integrity": "sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==", "dev": true, "requires": { "@jridgewell/resolve-uri": "3.1.0", "@jridgewell/sourcemap-codec": "1.4.14" + }, + "dependencies": { + "@jridgewell/sourcemap-codec": { + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", + "dev": true + } + } + }, + "@jsdoc/salty": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/@jsdoc/salty/-/salty-0.2.5.tgz", + "integrity": "sha512-TfRP53RqunNe2HBobVBJ0VLhK1HbfvBYeTC1ahnN64PWvyYyGebmMiPkuwvD9fpw2ZbkoPb8Q7mwy0aR8Z9rvw==", + "requires": { + "lodash": "^4.17.21" } }, "@justinribeiro/lite-youtube": { @@ -27523,14 +28688,14 @@ } }, "@octokit/webhooks": { - "version": "10.7.0", - "resolved": "https://registry.npmjs.org/@octokit/webhooks/-/webhooks-10.7.0.tgz", - "integrity": "sha512-zZBbQMpXXnK/ki/utrFG/TuWv9545XCSLibfDTxrYqR1PmU6zel02ebTOrA7t5XIGHzlEOc/NgISUIBUe7pMFA==", + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/@octokit/webhooks/-/webhooks-10.9.1.tgz", + "integrity": "sha512-5NXU4VfsNOo2VSU/SrLrpPH2Z1ZVDOWFcET4EpnEBX1uh/v8Uz65UVuHIRx5TZiXhnWyRE9AO1PXHa+M/iWwZA==", "dev": true, "requires": { "@octokit/request-error": "^3.0.0", "@octokit/webhooks-methods": "^3.0.0", - "@octokit/webhooks-types": "6.10.0", + "@octokit/webhooks-types": "6.11.0", "aggregate-error": "^3.1.0" } }, @@ -27541,131 +28706,131 @@ "dev": true }, "@octokit/webhooks-types": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/@octokit/webhooks-types/-/webhooks-types-6.10.0.tgz", - "integrity": "sha512-lDNv83BeEyxxukdQ0UttiUXawk9+6DkdjjFtm2GFED+24IQhTVaoSbwV9vWWKONyGLzRmCQqZmoEWkDhkEmPlw==", + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/@octokit/webhooks-types/-/webhooks-types-6.11.0.tgz", + "integrity": "sha512-AanzbulOHljrku1NGfafxdpTCfw2ENaWzH01N2vqQM+cUFbk868Cgh0xylz0JIM9BoKbfI++bdD6EYX0Q/UTEw==", "dev": true }, "@percy/cli": { - "version": "1.21.0", - "resolved": "https://registry.npmjs.org/@percy/cli/-/cli-1.21.0.tgz", - "integrity": "sha512-capaTXkj/L0Itn8VpDY/ePkHM9InaqwTRTK+IHGTA2HsRlpiNotunDAv8cNJ/fBMoRBh1Bki7tEWIp6zB+KmBQ==", + "version": "1.23.0", + "resolved": "https://registry.npmjs.org/@percy/cli/-/cli-1.23.0.tgz", + "integrity": "sha512-3S+QUWdeJq6ZUWoRNLuX+wdJx8civJdrSmYG9WS2CP9auJNbuA+13xQnB5AkkWUvHEcC/yXzZpi5NAjoW86jgw==", "dev": true, "requires": { - "@percy/cli-app": "1.21.0", - "@percy/cli-build": "1.21.0", - "@percy/cli-command": "1.21.0", - "@percy/cli-config": "1.21.0", - "@percy/cli-exec": "1.21.0", - "@percy/cli-snapshot": "1.21.0", - "@percy/cli-upload": "1.21.0", - "@percy/client": "1.21.0", - "@percy/logger": "1.21.0" + "@percy/cli-app": "1.23.0", + "@percy/cli-build": "1.23.0", + "@percy/cli-command": "1.23.0", + "@percy/cli-config": "1.23.0", + "@percy/cli-exec": "1.23.0", + "@percy/cli-snapshot": "1.23.0", + "@percy/cli-upload": "1.23.0", + "@percy/client": "1.23.0", + "@percy/logger": "1.23.0" } }, "@percy/cli-app": { - "version": "1.21.0", - "resolved": "https://registry.npmjs.org/@percy/cli-app/-/cli-app-1.21.0.tgz", - "integrity": "sha512-kkYMTGEk33nsLIIKx57LzheK7WZK77Y52c+DAwnV1FDpzDvhpP4eLEpXwarTIapN76O4wZndFlX4zm07U9Cvfw==", + "version": "1.23.0", + "resolved": "https://registry.npmjs.org/@percy/cli-app/-/cli-app-1.23.0.tgz", + "integrity": "sha512-2L5chuBFp016LlkB7BihGtm0XJFCZEDNIcOFchsK7l2REBUkxVeM6hNQ89uuP2F9eKXwWKqtDEIYCzdzW0hfIQ==", "dev": true, "requires": { - "@percy/cli-command": "1.21.0", - "@percy/cli-exec": "1.21.0" + "@percy/cli-command": "1.23.0", + "@percy/cli-exec": "1.23.0" } }, "@percy/cli-build": { - "version": "1.21.0", - "resolved": "https://registry.npmjs.org/@percy/cli-build/-/cli-build-1.21.0.tgz", - "integrity": "sha512-LRvGsTl6bw6zNMOQ36emjdIdkvCEUAbRRp2nryBODMpJ8YUd1NcXw/qLVM2bzpJcTmeBXR76Yjgi1VhFZrNZlg==", + "version": "1.23.0", + "resolved": "https://registry.npmjs.org/@percy/cli-build/-/cli-build-1.23.0.tgz", + "integrity": "sha512-qIhfU/UtPl181Dw2kR8klEYLUlA5C8GE0M9781vz7D0W3LriccaLLLo1wBp4q4bo83uvUBvNJhq9/S4T38kPEQ==", "dev": true, "requires": { - "@percy/cli-command": "1.21.0" + "@percy/cli-command": "1.23.0" } }, "@percy/cli-command": { - "version": "1.21.0", - "resolved": "https://registry.npmjs.org/@percy/cli-command/-/cli-command-1.21.0.tgz", - "integrity": "sha512-ZfjDMgUQRQonJT106Y89NVDzVd2qDmwQ+4oC0AyGgE5h1cHAEaPoYV8LnMvpjbvFYni+jbeZvHNANMP7Ut2yOQ==", + "version": "1.23.0", + "resolved": "https://registry.npmjs.org/@percy/cli-command/-/cli-command-1.23.0.tgz", + "integrity": "sha512-tXj5vv2BQMBmn3ZL2YNqYYrmJLyYnBqwyJkecY2BwXQsKAIv3qBgTzr1d5+LxTOi5ArjFCHAgk2w4ohy6h6t4w==", "dev": true, "requires": { - "@percy/config": "1.21.0", - "@percy/core": "1.21.0", - "@percy/logger": "1.21.0" + "@percy/config": "1.23.0", + "@percy/core": "1.23.0", + "@percy/logger": "1.23.0" } }, "@percy/cli-config": { - "version": "1.21.0", - "resolved": "https://registry.npmjs.org/@percy/cli-config/-/cli-config-1.21.0.tgz", - "integrity": "sha512-7Wn3L/XkKhVWixH4/oPJV66jD6LBCma6pT/bzbKuV5Hlpscel2xz3p8JSDOvxQJl1eSRtjwhI1HP/0OT6EX5dg==", + "version": "1.23.0", + "resolved": "https://registry.npmjs.org/@percy/cli-config/-/cli-config-1.23.0.tgz", + "integrity": "sha512-tI4c4MhU41rx9n7fYZrpn4gaOD9dA6PnefP397v7smqEWh7MJ+cxI/nyKU0/9G2wGjMhYACaLoR4BiCWOQZAkw==", "dev": true, "requires": { - "@percy/cli-command": "1.21.0" + "@percy/cli-command": "1.23.0" } }, "@percy/cli-exec": { - "version": "1.21.0", - "resolved": "https://registry.npmjs.org/@percy/cli-exec/-/cli-exec-1.21.0.tgz", - "integrity": "sha512-Uwqw1WqXzYXk4WQLyRWkQJ4Tdm7/bUOOa2HJU/J5kGLDmoSRNX/TesobFy8ii55mB0QV2hkZnMkAFPwzfxaCSw==", + "version": "1.23.0", + "resolved": "https://registry.npmjs.org/@percy/cli-exec/-/cli-exec-1.23.0.tgz", + "integrity": "sha512-ecxnMWxUlVx0EswGraHgN4LvWbXeUZQZUxJ9wYmMSgDEaKfEiEZ5WTLSKzQAxyfw2SjoQ3cHRZbKh4qMlCgbAg==", "dev": true, "requires": { - "@percy/cli-command": "1.21.0", + "@percy/cli-command": "1.23.0", "cross-spawn": "^7.0.3", "which": "^2.0.2" } }, "@percy/cli-snapshot": { - "version": "1.21.0", - "resolved": "https://registry.npmjs.org/@percy/cli-snapshot/-/cli-snapshot-1.21.0.tgz", - "integrity": "sha512-DR0yPRCCRFGXrDwfAmC/26yF4CGMTAWNgIKFgeQcPGgjkdXOSmm04fhU36QBU5S66B2gmSjEG0mfh+2oOD68EQ==", + "version": "1.23.0", + "resolved": "https://registry.npmjs.org/@percy/cli-snapshot/-/cli-snapshot-1.23.0.tgz", + "integrity": "sha512-QOrUfyPCnjfIAcUBjNlO299NRPDxofcYQUCBYZE3CtemsNFtygFt0yPnZCwWmt0voSpnPl1Izc6/FA3wYUfuBQ==", "dev": true, "requires": { - "@percy/cli-command": "1.21.0", + "@percy/cli-command": "1.23.0", "yaml": "^2.0.0" } }, "@percy/cli-upload": { - "version": "1.21.0", - "resolved": "https://registry.npmjs.org/@percy/cli-upload/-/cli-upload-1.21.0.tgz", - "integrity": "sha512-NDh6NiirUgdnrNergiwtQceA0TjcT5vK6dzuE6pscwksvb9vzx+tvvbBcVBhpEQt+FmIoYDdqb8FVzMqxd5wEg==", + "version": "1.23.0", + "resolved": "https://registry.npmjs.org/@percy/cli-upload/-/cli-upload-1.23.0.tgz", + "integrity": "sha512-faRHjzaUf21RK9Ra051gKUl4HmMNPZxUKSZNmdG0yP+tc5KxU9cXkmEeCKGH7LOcVs0IfyRX0vv58YEZ6GsIRw==", "dev": true, "requires": { - "@percy/cli-command": "1.21.0", + "@percy/cli-command": "1.23.0", "fast-glob": "^3.2.11", "image-size": "^1.0.0" } }, "@percy/client": { - "version": "1.21.0", - "resolved": "https://registry.npmjs.org/@percy/client/-/client-1.21.0.tgz", - "integrity": "sha512-IKFcMYcibWQjisjmS4K9HK7TbjPK4fnVeh/3Uq7Da0ejiu5qBvLn49aNcYfnrguPqaUcgIvLvpcgtHeH+srv/g==", + "version": "1.23.0", + "resolved": "https://registry.npmjs.org/@percy/client/-/client-1.23.0.tgz", + "integrity": "sha512-m0qNCrlfh6Pf0t2GfoeShuK7r2GeRk5rWVjIbdnDigvmtL0G+HJM1gvysLOxzKFHkZ1cLBfM1SnH1Yn6RM/6qQ==", "dev": true, "requires": { - "@percy/env": "1.21.0", - "@percy/logger": "1.21.0" + "@percy/env": "1.23.0", + "@percy/logger": "1.23.0" } }, "@percy/config": { - "version": "1.21.0", - "resolved": "https://registry.npmjs.org/@percy/config/-/config-1.21.0.tgz", - "integrity": "sha512-s6XFBhjP0fGVg8onapDwebGNIdwMgdidZW5q0HziBiQVqfwh/83NkDlCq+c6/JU5P0Y5DArxCIFDVUfiLkcs4A==", + "version": "1.23.0", + "resolved": "https://registry.npmjs.org/@percy/config/-/config-1.23.0.tgz", + "integrity": "sha512-giPIdNLcG1Qg0dkc/VDOkTzI4szzM4QAoJfMLEP0UYPkIU2Y0Xc8NH5GN3DEiudRJge72iGfeah6GugxmXmKXw==", "dev": true, "requires": { - "@percy/logger": "1.21.0", + "@percy/logger": "1.23.0", "ajv": "^8.6.2", "cosmiconfig": "^7.0.0", "yaml": "^2.0.0" } }, "@percy/core": { - "version": "1.21.0", - "resolved": "https://registry.npmjs.org/@percy/core/-/core-1.21.0.tgz", - "integrity": "sha512-YFBTiRghq1m9t0/4ZUFWgS8LJ4DYugcMDoZ04yKWsIjRDcALwHAZahYpBZRcHkmfqB/kqLB5IYoyc6rel+PNeA==", + "version": "1.23.0", + "resolved": "https://registry.npmjs.org/@percy/core/-/core-1.23.0.tgz", + "integrity": "sha512-/BNHdvbD7r1p3k3HWgxYLBo2L2Ye9RDcmTuA6en2xUYaagf+0vfcAK8iyBvVm6ir2ZjAsMW0PGRa7OIfetvHHg==", "dev": true, "requires": { - "@percy/client": "1.21.0", - "@percy/config": "1.21.0", - "@percy/dom": "1.21.0", - "@percy/logger": "1.21.0", + "@percy/client": "1.23.0", + "@percy/config": "1.23.0", + "@percy/dom": "1.23.0", + "@percy/logger": "1.23.0", "content-disposition": "^0.5.4", "cross-spawn": "^7.0.3", "extract-zip": "^2.0.1", @@ -27678,21 +28843,21 @@ } }, "@percy/dom": { - "version": "1.21.0", - "resolved": "https://registry.npmjs.org/@percy/dom/-/dom-1.21.0.tgz", - "integrity": "sha512-OKpS9EPnUrMx3Mu9L7QiqEtc+yAUz3gbXrbRlrPAljyRAmmBe9p5vy0hKtP8wO1vxjumqmtxNABpz5bc70CJ2Q==", + "version": "1.23.0", + "resolved": "https://registry.npmjs.org/@percy/dom/-/dom-1.23.0.tgz", + "integrity": "sha512-68q3ceCWsWpUFyF/pnELSCTdbTAibGVyNwp+iZCFd/914sUhERYrrX8AqCgkCDerOzCwAQZQDe2Nv3jaB+d0ng==", "dev": true }, "@percy/env": { - "version": "1.21.0", - "resolved": "https://registry.npmjs.org/@percy/env/-/env-1.21.0.tgz", - "integrity": "sha512-rqbACxivUTkpAJnjk/7IosFdh2vdz1SVGV0KXFf2xtEuUb7YhYrYixhf/6xE81o93C+pxrlXYWkgUSaMhZpP5A==", + "version": "1.23.0", + "resolved": "https://registry.npmjs.org/@percy/env/-/env-1.23.0.tgz", + "integrity": "sha512-oKvJBC/Zhfwp2QpFBpfHeAVuGhgaPeI7S4H2/68XT30pInfVJzaCjD/8ySAELGyMWmgHc51s+k09DZCo3C3Gyg==", "dev": true }, "@percy/logger": { - "version": "1.21.0", - "resolved": "https://registry.npmjs.org/@percy/logger/-/logger-1.21.0.tgz", - "integrity": "sha512-qKKSFP25X+a50vpjUSolI8WSQ2YAunS6K4brdTRemgvc48Wlkv3541SP8iMK5BAy3Nn4u0KRiwkstvyRr1tXlA==", + "version": "1.23.0", + "resolved": "https://registry.npmjs.org/@percy/logger/-/logger-1.23.0.tgz", + "integrity": "sha512-kNtdKQ9Kou/RcWgDoSK+ofOVqOzuzyHBNsK+I92XNh8HHO6ow08Cmw+LtZbDxmj3uq7nXG9Nhgj4ZqSgdk7J6Q==", "dev": true }, "@protobufjs/aspromise": { @@ -28091,12 +29256,11 @@ } }, "@types/glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==", - "dev": true, + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-IO+MJPVhoqz+28h1qLAcBEH2+xHMK6MTyHJc7MTnnYb6wsoLR29POVGJ7LycmVXIqyy/4/2ShP5sUwTXuOwb/w==", "requires": { - "@types/minimatch": "*", + "@types/minimatch": "^5.1.2", "@types/node": "*" } }, @@ -28127,6 +29291,11 @@ "@types/node": "*" } }, + "@types/linkify-it": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-3.0.2.tgz", + "integrity": "sha512-HZQYqbiFVWufzCwexrvh694SOim8z2d+xJl5UNamcvQFejLY/2YUtzXHYi3cHdI7PMlS8ejH2slRAOJQ32aNbA==" + }, "@types/long": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.2.tgz", @@ -28138,6 +29307,15 @@ "integrity": "sha512-ssE3Vlrys7sdIzs5LOxCzTVMsU7i9oa/IaW92wF32JFb3CVczqOkru2xspuKczHEbG3nvmPY7IFqVmGGHdNbYw==", "dev": true }, + "@types/markdown-it": { + "version": "12.2.3", + "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-12.2.3.tgz", + "integrity": "sha512-GKMHFfv3458yYy+v/N8gjufHO6MSZKCOXpZc5GXIWWy8uldwfmPn98vp81gZ5f9SVw8YYBctgfJ22a2d7AOMeQ==", + "requires": { + "@types/linkify-it": "*", + "@types/mdurl": "*" + } + }, "@types/mdast": { "version": "3.0.11", "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.11.tgz", @@ -28147,6 +29325,11 @@ "@types/unist": "*" } }, + "@types/mdurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-1.0.2.tgz", + "integrity": "sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA==" + }, "@types/mime": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-3.0.1.tgz", @@ -28154,9 +29337,9 @@ "optional": true }, "@types/minimatch": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz", - "integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==" + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz", + "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==" }, "@types/minimist": { "version": "1.2.2", @@ -28170,9 +29353,9 @@ "integrity": "sha512-QB5D2sqfSjCmTuWcBWyJ+/44bcjO7VbjSbOE0ucoVbAsSNQc4Lt6QkgkVXkTDwkL4z/beecZNDvVX15D4P8Jbw==" }, "@types/node-fetch": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.2.tgz", - "integrity": "sha512-DHqhlq5jeESLy19TYhLakJ07kNumXWjcDdxXsLUMJZ6ue8VZJj4kLPQVE/2mdHh3xZziNF1xppu5lwmS53HR+A==", + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.3.tgz", + "integrity": "sha512-ETTL1mOEdq/sxUtgtOhKjyB2Irra4cjxksvcMUR5Zr4n+PxVhsCD9WS46oPbHL3et9Zde7CNRr+WUNlcHvsX+w==", "optional": true, "requires": { "@types/node": "*", @@ -28217,6 +29400,15 @@ "@types/node": "*" } }, + "@types/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-F3OznnSLAUxFrCEu/L5PY8+ny8DtcFRjx7fZZ9bycvXRi3KPTRS9HOitGZwvPg0juRhXFWIeKX58cnX5YqLohQ==", + "requires": { + "@types/glob": "*", + "@types/node": "*" + } + }, "@types/serve-static": { "version": "1.15.1", "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.1.tgz", @@ -28287,6 +29479,12 @@ "requires": { "eslint-visitor-keys": "^2.0.0" } + }, + "eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true } } }, @@ -28341,6 +29539,14 @@ "requires": { "@typescript-eslint/types": "4.33.0", "eslint-visitor-keys": "^2.0.0" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true + } } }, "a-sync-waterfall": { @@ -28373,14 +29579,12 @@ "acorn": { "version": "8.8.2", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", - "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", - "dev": true + "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==" }, "acorn-jsx": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, "requires": {} }, "acorn-walk": { @@ -28420,24 +29624,24 @@ } }, "algoliasearch": { - "version": "4.16.0", - "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-4.16.0.tgz", - "integrity": "sha512-HAjKJ6bBblaXqO4dYygF4qx251GuJ6zCZt+qbJ+kU7sOC+yc84pawEjVpJByh+cGP2APFCsao2Giz50cDlKNPA==", - "requires": { - "@algolia/cache-browser-local-storage": "4.16.0", - "@algolia/cache-common": "4.16.0", - "@algolia/cache-in-memory": "4.16.0", - "@algolia/client-account": "4.16.0", - "@algolia/client-analytics": "4.16.0", - "@algolia/client-common": "4.16.0", - "@algolia/client-personalization": "4.16.0", - "@algolia/client-search": "4.16.0", - "@algolia/logger-common": "4.16.0", - "@algolia/logger-console": "4.16.0", - "@algolia/requester-browser-xhr": "4.16.0", - "@algolia/requester-common": "4.16.0", - "@algolia/requester-node-http": "4.16.0", - "@algolia/transporter": "4.16.0" + "version": "4.17.0", + "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-4.17.0.tgz", + "integrity": "sha512-JMRh2Mw6sEnVMiz6+APsi7lx9a2jiDFF+WUtANaUVCv6uSU9UOLdo5h9K3pdP6frRRybaM2fX8b1u0nqICS9aA==", + "requires": { + "@algolia/cache-browser-local-storage": "4.17.0", + "@algolia/cache-common": "4.17.0", + "@algolia/cache-in-memory": "4.17.0", + "@algolia/client-account": "4.17.0", + "@algolia/client-analytics": "4.17.0", + "@algolia/client-common": "4.17.0", + "@algolia/client-personalization": "4.17.0", + "@algolia/client-search": "4.17.0", + "@algolia/logger-common": "4.17.0", + "@algolia/logger-console": "4.17.0", + "@algolia/requester-browser-xhr": "4.17.0", + "@algolia/requester-common": "4.17.0", + "@algolia/requester-node-http": "4.17.0", + "@algolia/transporter": "4.17.0" } }, "ansi-align": { @@ -28754,9 +29958,9 @@ }, "dependencies": { "@types/node": { - "version": "14.18.40", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.40.tgz", - "integrity": "sha512-pGteXO/JQX7wPxGR8lyT+doqjMa7XvlVowwrDwLfX92k5SdLkk4cwC7CYSLBxrenw/R5oQwKioVIak7ZgplM3g==", + "version": "14.18.42", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.42.tgz", + "integrity": "sha512-xefu+RBie4xWlK8hwAzGh3npDz/4VhF6icY/shU+zv/1fNn+ZVG7T7CRwe9LId9sAYRPxI+59QBPuKL3WpyGRg==", "optional": true } } @@ -29244,8 +30448,7 @@ "bluebird": { "version": "3.7.2", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", - "dev": true + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" }, "blueimp-md5": { "version": "2.19.0", @@ -29755,9 +30958,9 @@ } }, "caniuse-lite": { - "version": "1.0.30001469", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001469.tgz", - "integrity": "sha512-Rcp7221ScNqQPP3W+lVOYDyjdR6dC+neEQCttoNr5bAyz54AboB4iwpnWgyi8P4YUsPybVzT4LgWiBbI3drL4g==", + "version": "1.0.30001478", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001478.tgz", + "integrity": "sha512-gMhDyXGItTHipJj2ApIvR+iVB5hd0KP3svMWWXDvZOmjzJJassGLMfxRkQCSYgGd2gtdL/ReeiyvMSFD1Ss6Mw==", "dev": true }, "canonicalize": { @@ -29770,6 +30973,14 @@ "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==" }, + "catharsis": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.9.0.tgz", + "integrity": "sha512-prMTQVpcns/tzFgFVkVp6ak6RykZyWb3gu8ckUpd6YkTlacOd3DXGJjIpD4Q6zJirizvaiAjSSHlOsA+6sNh2A==", + "requires": { + "lodash": "^4.17.15" + } + }, "ccount": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/ccount/-/ccount-1.1.0.tgz", @@ -30034,9 +31245,9 @@ } }, "chromium-bidi": { - "version": "0.4.5", - "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-0.4.5.tgz", - "integrity": "sha512-rkav9YzRfAshSTG3wNXF7P7yNiI29QAo1xBXElPoCoSQR5n20q3cOyVhDv6S7+GlF/CJ/emUxlQiR0xOPurkGg==", + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-0.4.6.tgz", + "integrity": "sha512-TQOkWRaLI/IWvoP8XC+7jO4uHTIiAUiklXU1T0qszlUFEai9LgKXIBXy3pOS3EnQZ3bQtMbKUPkug0fTAEHCSw==", "dev": true, "requires": { "mitt": "3.0.0" @@ -30165,9 +31376,9 @@ } }, "cli-spinners": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.7.0.tgz", - "integrity": "sha512-qu3pN8Y3qHNgE2AFweciB1IfMnmZ/fsNTEE+NOFjmGB2F/7rLhnhzppvpCnN4FovtP26k8lHyy9ptEbNwWFLzw==", + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.8.0.tgz", + "integrity": "sha512-/eG5sJcvEIwxcdYM86k5tPwn0MUzkX5YY3eImTGpJOZgVe4SdTMY14vQpcxgBzJ0wXwAYrS8E+c3uHeK4JNyzQ==", "dev": true }, "cli-truncate": { @@ -30898,8 +32109,7 @@ "deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==" }, "deep-strict-equal": { "version": "0.2.0", @@ -31042,9 +32252,9 @@ "integrity": "sha512-LmVkry/oDShEgSZPNgqCIp2/TlqtExeGmymru3uCELnfyjY11IzpAproLYs+1X88fXO6DBoYP3ul2Xo2yz2j6A==" }, "devtools-protocol": { - "version": "0.0.1094867", - "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1094867.tgz", - "integrity": "sha512-pmMDBKiRVjh0uKK6CT1WqZmM3hBVSgD+N2MrgyV1uNizAZMw4tx6i/RTc+/uCsKSCmg0xXx7arCP/OFcIwTsiQ==", + "version": "0.0.1107588", + "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1107588.tgz", + "integrity": "sha512-yIR+pG9x65Xko7bErCUSQaDLrO/P1p3JUzEk7JCU4DowPcGHkTGUGQapcfcLc4qj0UaALwZ+cr0riFgiqpixcg==", "dev": true }, "dir-glob": { @@ -31233,9 +32443,9 @@ } }, "electron-to-chromium": { - "version": "1.4.337", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.337.tgz", - "integrity": "sha512-W8gdzXG86mVPoc56eM8YA+QiLxaAxJ8cmDjxZgfhLLWVvZQxyA918w5tX2JEWApZta45T1/sYcmFHTsTOUE3nw==", + "version": "1.4.363", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.363.tgz", + "integrity": "sha512-ReX5qgmSU7ybhzMuMdlJAdYnRhT90UB3k9M05O5nF5WH3wR5wgdJjXw0uDeFyKNhmglmQiOxkAbzrP0hMKM59g==", "dev": true }, "elegant-spinner": { @@ -31510,6 +32720,61 @@ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==" }, + "escodegen": { + "version": "1.14.3", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz", + "integrity": "sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==", + "requires": { + "esprima": "^4.0.1", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.6.1" + }, + "dependencies": { + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, + "optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + } + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==" + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "optional": true + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", + "requires": { + "prelude-ls": "~1.1.2" + } + } + } + }, "eslint": { "version": "7.32.0", "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.32.0.tgz", @@ -31567,6 +32832,12 @@ "@babel/highlight": "^7.10.4" } }, + "acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true + }, "ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -31588,6 +32859,31 @@ "sprintf-js": "~1.0.2" } }, + "eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true + }, + "espree": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", + "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", + "dev": true, + "requires": { + "acorn": "^7.4.0", + "acorn-jsx": "^5.3.1", + "eslint-visitor-keys": "^1.3.0" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true + } + } + }, "globals": { "version": "13.20.0", "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", @@ -31651,6 +32947,29 @@ "resolve-from": "^5.0.0" }, "dependencies": { + "acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true + }, + "eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true + }, + "espree": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", + "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", + "dev": true, + "requires": { + "acorn": "^7.4.0", + "acorn-jsx": "^5.3.1", + "eslint-visitor-keys": "^1.3.0" + } + }, "espurify": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/espurify/-/espurify-2.1.1.tgz", @@ -31728,10 +33047,9 @@ } }, "eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.0.tgz", + "integrity": "sha512-HPpKPUBQcAsZOsHAFwTtIKcYlCje62XB7SEAcxjtmW6TD1WVpkS6i6/hOVtTZIl4zGj/mBqpFVGvaDneik+VoQ==" }, "espower-location-detector": { "version": "1.0.0", @@ -31746,28 +33064,13 @@ } }, "espree": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", - "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", - "dev": true, + "version": "9.5.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.1.tgz", + "integrity": "sha512-5yxtHSZXRSW5pvv3hAlXM5+/Oswi1AUFqBmbibKb5s6bp3rGIDkyXU6xCoyuuLhijr4SFwPrXRoZjz0AZDN9tg==", "requires": { - "acorn": "^7.4.0", - "acorn-jsx": "^5.3.1", - "eslint-visitor-keys": "^1.3.0" - }, - "dependencies": { - "acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", - "dev": true - }, - "eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true - } + "acorn": "^8.8.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.0" } }, "esprima": { @@ -31821,8 +33124,7 @@ "estraverse": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==" }, "estree-walker": { "version": "2.0.2", @@ -31833,8 +33135,7 @@ "esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==" }, "etag": { "version": "1.8.1", @@ -32310,8 +33611,7 @@ "fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==" }, "fast-text-encoding": { "version": "1.0.6", @@ -33397,97 +34697,35 @@ } }, "google-gax": { - "version": "2.30.5", - "resolved": "https://registry.npmjs.org/google-gax/-/google-gax-2.30.5.tgz", - "integrity": "sha512-Jey13YrAN2hfpozHzbtrwEfEHdStJh1GwaQ2+Akh1k0Tv/EuNVSuBtHZoKSBm5wBMvNsxTsEIZ/152NrYyZgxQ==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/google-gax/-/google-gax-3.6.0.tgz", + "integrity": "sha512-2fyb61vWxUonHiArRNJQmE4tx5oY1ni8VPo08fzII409vDSCWG7apDX4qNOQ2GXXT82gLBn3d3P1Dydh7pWjyw==", "requires": { - "@grpc/grpc-js": "~1.6.0", - "@grpc/proto-loader": "^0.6.12", + "@grpc/grpc-js": "~1.8.0", + "@grpc/proto-loader": "^0.7.0", "@types/long": "^4.0.0", + "@types/rimraf": "^3.0.2", "abort-controller": "^3.0.0", "duplexify": "^4.0.0", "fast-text-encoding": "^1.0.3", - "google-auth-library": "^7.14.0", + "google-auth-library": "^8.0.2", "is-stream-ended": "^0.1.4", "node-fetch": "^2.6.1", "object-hash": "^3.0.0", - "proto3-json-serializer": "^0.1.8", - "protobufjs": "6.11.3", - "retry-request": "^4.0.0" + "proto3-json-serializer": "^1.0.0", + "protobufjs": "7.2.3", + "protobufjs-cli": "1.1.1", + "retry-request": "^5.0.0" }, "dependencies": { - "gaxios": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-4.3.3.tgz", - "integrity": "sha512-gSaYYIO1Y3wUtdfHmjDUZ8LWaxJQpiavzbF5Kq53akSzvmVg0RfyOcFDbO1KJ/KCGRFz2qG+lS81F0nkr7cRJA==", - "requires": { - "abort-controller": "^3.0.0", - "extend": "^3.0.2", - "https-proxy-agent": "^5.0.0", - "is-stream": "^2.0.0", - "node-fetch": "^2.6.7" - } - }, - "gcp-metadata": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-4.3.1.tgz", - "integrity": "sha512-x850LS5N7V1F3UcV7PoupzGsyD6iVwTVvsh3tbXfkctZnBnjW5yu5z1/3k3SehF7TyoTIe78rJs02GMMy+LF+A==", - "requires": { - "gaxios": "^4.0.0", - "json-bigint": "^1.0.0" - } - }, - "google-auth-library": { - "version": "7.14.1", - "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-7.14.1.tgz", - "integrity": "sha512-5Rk7iLNDFhFeBYc3s8l1CqzbEBcdhwR193RlD4vSNFajIcINKI8W8P0JLmBpwymHqqWbX34pJDQu39cSy/6RsA==", - "requires": { - "arrify": "^2.0.0", - "base64-js": "^1.3.0", - "ecdsa-sig-formatter": "^1.0.11", - "fast-text-encoding": "^1.0.0", - "gaxios": "^4.0.0", - "gcp-metadata": "^4.2.0", - "gtoken": "^5.0.4", - "jws": "^4.0.0", - "lru-cache": "^6.0.0" - } - }, - "google-p12-pem": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-3.1.4.tgz", - "integrity": "sha512-HHuHmkLgwjdmVRngf5+gSmpkyaRI6QmOg77J8tkNBHhNEI62sGHyw4/+UkgyZEI7h84NbWprXDJ+sa3xOYFvTg==", - "requires": { - "node-forge": "^1.3.1" - } - }, - "gtoken": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-5.3.2.tgz", - "integrity": "sha512-gkvEKREW7dXWF8NV8pVrKfW7WqReAmjjkMBh6lNCCGOM4ucS0r0YyXXl0r/9Yj8wcW/32ISkfc8h5mPTDbtifQ==", - "requires": { - "gaxios": "^4.0.0", - "google-p12-pem": "^3.1.3", - "jws": "^4.0.0" - } - }, - "is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==" - }, - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "retry-request": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/retry-request/-/retry-request-5.0.2.tgz", + "integrity": "sha512-wfI3pk7EE80lCIXprqh7ym48IHYdwmAAzESdbU8Q9l7pnRCk9LEhpbOTNKjz6FARLm/Bl5m+4F0ABxOkYUujSQ==", "requires": { - "yallist": "^4.0.0" + "debug": "^4.1.1", + "extend": "^3.0.2" } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" } } }, @@ -34276,9 +35514,9 @@ "dev": true }, "html-tags": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.2.0.tgz", - "integrity": "sha512-vy7ClnArOZwCnqZgvv+ddgHgJiAFXe3Ge9ML5/mBctVJoUoYPCdxVucOywjDARn6CVoh3dRSFdPHy2sX80L0Wg==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.3.1.tgz", + "integrity": "sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==", "dev": true }, "htmlparser2": { @@ -34809,9 +36047,9 @@ } }, "is-core-module": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", - "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.0.tgz", + "integrity": "sha512-RECHCBCd/viahWmwj6enj19sKbHfJrddi/6cBDsNTKbNq0f7VeaUkBo60BqzvPqo/W54ChS62Z5qyun7cfOMqQ==", "requires": { "has": "^1.0.3" } @@ -35430,11 +36668,76 @@ "argparse": "^2.0.1" } }, + "js2xmlparser": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-4.0.2.tgz", + "integrity": "sha512-6n4D8gLlLf1n5mNLQPRfViYzu9RATblzPEtm1SthMX1Pjao0r9YI9nw7ZIfRxQMERS87mcswrg+r/OYrPRX6jA==", + "requires": { + "xmlcreate": "^2.0.4" + } + }, "jsbn": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==" }, + "jsdoc": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-4.0.2.tgz", + "integrity": "sha512-e8cIg2z62InH7azBBi3EsSEqrKx+nUtAS5bBcYTSpZFA+vhNPyhv8PTFZ0WsjOPDj04/dOLlm08EDcQJDqaGQg==", + "requires": { + "@babel/parser": "^7.20.15", + "@jsdoc/salty": "^0.2.1", + "@types/markdown-it": "^12.2.3", + "bluebird": "^3.7.2", + "catharsis": "^0.9.0", + "escape-string-regexp": "^2.0.0", + "js2xmlparser": "^4.0.2", + "klaw": "^3.0.0", + "markdown-it": "^12.3.2", + "markdown-it-anchor": "^8.4.1", + "marked": "^4.0.10", + "mkdirp": "^1.0.4", + "requizzle": "^0.2.3", + "strip-json-comments": "^3.1.0", + "underscore": "~1.13.2" + }, + "dependencies": { + "entities": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz", + "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==" + }, + "escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==" + }, + "markdown-it": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.3.2.tgz", + "integrity": "sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg==", + "requires": { + "argparse": "^2.0.1", + "entities": "~2.1.0", + "linkify-it": "^3.0.1", + "mdurl": "^1.0.1", + "uc.micro": "^1.0.5" + } + }, + "markdown-it-anchor": { + "version": "8.6.7", + "resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-8.6.7.tgz", + "integrity": "sha512-FlCHFwNnutLgVTflOYHPW2pPcl2AACqVzExlkGQNsi4CJgqOHN7YTgDd4LuhgN1BFO3TS0vLAruV1Td6dwWPJA==", + "requires": {} + }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" + } + } + }, "jsesc": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", @@ -35682,6 +36985,14 @@ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==" }, + "klaw": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-3.0.0.tgz", + "integrity": "sha512-0Fo5oir+O9jnXu5EefYbVK+mHMBeEVEy2cmctR1O1NECcCkPRreJKrS6Qt/j3KC2C148Dfo9i3pCmCMsdqGr0g==", + "requires": { + "graceful-fs": "^4.1.9" + } + }, "kleur": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", @@ -36267,9 +37578,9 @@ } }, "entities": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.4.0.tgz", - "integrity": "sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA==" + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==" }, "html-escaper": { "version": "3.0.3", @@ -37230,12 +38541,6 @@ } } }, - "minipass": { - "version": "4.2.5", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.2.5.tgz", - "integrity": "sha512-+yQl7SX3bIT83Lhb4BVorMAHVuqsskxRdlmO9kTpyukp8vsm2Sn/fUOV9xlnG8/a5JsypJzap21lz/y3FBMJ8Q==", - "dev": true - }, "mitt": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/mitt/-/mitt-1.2.0.tgz", @@ -37302,6 +38607,13 @@ "array-union": "^2.1.0", "arrify": "^2.0.1", "minimatch": "^3.0.4" + }, + "dependencies": { + "@types/minimatch": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz", + "integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==" + } } }, "mustache": { @@ -37332,9 +38644,9 @@ "optional": true }, "nanoid": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", - "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==" + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", + "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==" }, "nanomatch": { "version": "1.2.13", @@ -38434,24 +39746,6 @@ "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", "integrity": "sha512-4GlJ6rZDhQZFE0DPVKh0e9jmZ5egZfxTkp7bcRDuPlJXbAwhxcl2dINPUAsjLdejqaLsCeg8axcLjIbvBjN4pQ==" }, - "path-scurry": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.6.3.tgz", - "integrity": "sha512-RAmB+n30SlN+HnNx6EbcpoDy9nwdpcGPnEKrJnu6GZoDWBdIjo1UQMVtW2ybtC7LC2oKLcMq8y5g8WnKLiod9g==", - "dev": true, - "requires": { - "lru-cache": "^7.14.1", - "minipass": "^4.0.2" - }, - "dependencies": { - "lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "dev": true - } - } - }, "path-to-regexp": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.1.tgz", @@ -38881,9 +40175,9 @@ "dev": true }, "prettier": { - "version": "2.8.6", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.6.tgz", - "integrity": "sha512-mtuzdiBbHwPEgl7NxWlqOkithPyp4VN93V7VeHVWBF+ad3I5avc0RVDT4oImXQy9H/AqxA2NSQH8pSxHW6FYbQ==", + "version": "2.8.7", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.7.tgz", + "integrity": "sha512-yPngTo3aXUUmyuTjeTUT75txrf+aMh9FiD7q9ZE/i6r0bPb22g4FsE6Y338PQX1bmfy08i9QQCB7/rcUAVntfw==", "dev": true }, "prettier-linter-helpers": { @@ -38966,17 +40260,17 @@ "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==" }, "proto3-json-serializer": { - "version": "0.1.9", - "resolved": "https://registry.npmjs.org/proto3-json-serializer/-/proto3-json-serializer-0.1.9.tgz", - "integrity": "sha512-A60IisqvnuI45qNRygJjrnNjX2TMdQGMY+57tR3nul3ZgO2zXkR9OGR8AXxJhkqx84g0FTnrfi3D5fWMSdANdQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proto3-json-serializer/-/proto3-json-serializer-1.1.0.tgz", + "integrity": "sha512-SjXwUWe/vANGs/mJJTbw5++7U67nwsymg7qsoPtw6GiXqw3kUy8ByojrlEdVE2efxAdKreX8WkDafxvYW95ZQg==", "requires": { - "protobufjs": "^6.11.2" + "protobufjs": "^7.0.0" } }, "protobufjs": { - "version": "6.11.3", - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.3.tgz", - "integrity": "sha512-xL96WDdCZYdU7Slin569tFX712BxsxslWwAfAhCYjQKGTq7dAU91Lomy6nLLhh/dyGhk/YH4TwTSRxTzhuHyZg==", + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.3.tgz", + "integrity": "sha512-TtpvOqwB5Gdz/PQmOjgsrGH1nHjAQVCN7JG4A6r1sXRWESL5rNMAiRcBQlCAdKxZcAbstExQePYG8xof/JVRgg==", "requires": { "@protobufjs/aspromise": "^1.1.2", "@protobufjs/base64": "^1.1.2", @@ -38988,9 +40282,67 @@ "@protobufjs/path": "^1.1.2", "@protobufjs/pool": "^1.1.0", "@protobufjs/utf8": "^1.1.0", - "@types/long": "^4.0.1", "@types/node": ">=13.7.0", - "long": "^4.0.0" + "long": "^5.0.0" + }, + "dependencies": { + "long": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/long/-/long-5.2.1.tgz", + "integrity": "sha512-GKSNGeNAtw8IryjjkhZxuKB3JzlcLTwjtiQCHKvqQet81I93kXslhDQruGI/QsddO83mcDToBVy7GqGS/zYf/A==" + } + } + }, + "protobufjs-cli": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/protobufjs-cli/-/protobufjs-cli-1.1.1.tgz", + "integrity": "sha512-VPWMgIcRNyQwWUv8OLPyGQ/0lQY/QTQAVN5fh+XzfDwsVw1FZ2L3DM/bcBf8WPiRz2tNpaov9lPZfNcmNo6LXA==", + "requires": { + "chalk": "^4.0.0", + "escodegen": "^1.13.0", + "espree": "^9.0.0", + "estraverse": "^5.1.0", + "glob": "^8.0.0", + "jsdoc": "^4.0.0", + "minimist": "^1.2.0", + "semver": "^7.1.2", + "tmp": "^0.2.1", + "uglify-js": "^3.7.7" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "requires": { + "balanced-match": "^1.0.0" + } + }, + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==" + }, + "glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + } + }, + "minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "requires": { + "brace-expansion": "^2.0.1" + } + } } }, "proxy-addr": { @@ -39208,102 +40560,146 @@ } }, "puppeteer": { - "version": "19.7.5", - "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-19.7.5.tgz", - "integrity": "sha512-UqD8K+yaZa6/hwzP54AATCiHrEYGGxzQcse9cZzrtsVGd8wT0llCdYhsBp8n+zvnb1ofY0YFgI3TYZ/MiX5uXQ==", + "version": "19.9.0", + "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-19.9.0.tgz", + "integrity": "sha512-JDx8WwGlkdQYTaa3OMYDF+uFWimiwNnacg5FGEC5J6+VxDsLK30wHKU/Db2LqEhtAoIu4RwS+BRH4zRPlCsFpA==", "dev": true, "requires": { - "cosmiconfig": "8.1.0", + "@puppeteer/browsers": "0.4.1", + "cosmiconfig": "8.1.3", "https-proxy-agent": "5.0.1", "progress": "2.0.3", "proxy-from-env": "1.1.0", - "puppeteer-core": "19.7.5" + "puppeteer-core": "19.9.0" }, "dependencies": { - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "@puppeteer/browsers": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-0.4.1.tgz", + "integrity": "sha512-4IICvy1McAkT/HyNZHIs7sp8ngBX1dmO0TPQ+FWq9ATQMqI8p+Ulm5A3kS2wYDh5HDHHkYrrETOu6rlj64VuTw==", "dev": true, "requires": { - "balanced-match": "^1.0.0" + "debug": "4.3.4", + "extract-zip": "2.0.1", + "https-proxy-agent": "5.0.1", + "progress": "2.0.3", + "proxy-from-env": "1.1.0", + "tar-fs": "2.1.1", + "unbzip2-stream": "1.4.3", + "yargs": "17.7.1" } }, - "cosmiconfig": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.1.0.tgz", - "integrity": "sha512-0tLZ9URlPGU7JsKq0DQOQ3FoRsYX8xDZ7xMiATQfaiGMz7EHowNkbU9u1coAOmnh9p/1ySpm0RB3JNWRXM5GCg==", + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "parse-json": "^5.0.0", - "path-type": "^4.0.0" + "color-convert": "^2.0.1" } }, - "glob": { - "version": "9.3.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-9.3.2.tgz", - "integrity": "sha512-BTv/JhKXFEHsErMte/AnfiSv8yYOLLiyH2lTg8vn02O21zWFgHPTfxtgn1QRe7NRgggUhC8hacR2Re94svHqeA==", + "cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", "dev": true, "requires": { - "fs.realpath": "^1.0.0", - "minimatch": "^7.4.1", - "minipass": "^4.2.4", - "path-scurry": "^1.6.1" + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" } }, - "minimatch": { - "version": "7.4.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-7.4.3.tgz", - "integrity": "sha512-5UB4yYusDtkRPbRiy1cqZ1IpGNcJCGlEMG17RKzPddpyiPKoCdwohbED8g4QXT0ewCt8LTkQXuljsUfQ3FKM4A==", + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "requires": { - "brace-expansion": "^2.0.1" + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "cosmiconfig": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.1.3.tgz", + "integrity": "sha512-/UkO2JKI18b5jVMJUp0lvKFMpa/Gye+ZgZjKD+DGEN9y7NRcf/nK1A0sp67ONmKtnDCNMS44E6jrk0Yc3bDuUw==", + "dev": true, + "requires": { + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "parse-json": "^5.0.0", + "path-type": "^4.0.0" } }, "puppeteer-core": { - "version": "19.7.5", - "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-19.7.5.tgz", - "integrity": "sha512-EJuNha+SxPfaYFbkoWU80H3Wb1SiQH5fFyb2xdbWda0ziax5mhV63UMlqNfPeTDIWarwtR4OIcq/9VqY8HPOsg==", + "version": "19.9.0", + "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-19.9.0.tgz", + "integrity": "sha512-IJYfCE0oFpi5dTvNFqOwo8Dey6zzx7hANy7z6K2bjpCux9oPOSOIubq40awNhaHlfi8soYtgU4qabnzMXB7xBQ==", "dev": true, "requires": { - "chromium-bidi": "0.4.5", + "@puppeteer/browsers": "0.4.1", + "chromium-bidi": "0.4.6", "cross-fetch": "3.1.5", "debug": "4.3.4", - "devtools-protocol": "0.0.1094867", + "devtools-protocol": "0.0.1107588", "extract-zip": "2.0.1", "https-proxy-agent": "5.0.1", "proxy-from-env": "1.1.0", - "rimraf": "4.4.0", "tar-fs": "2.1.1", "unbzip2-stream": "1.4.3", - "ws": "8.12.1" - } - }, - "rimraf": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-4.4.0.tgz", - "integrity": "sha512-X36S+qpCUR0HjXlkDe4NAOhS//aHH0Z+h8Ckf2auGJk3PTnx5rLmrHkwNdbVQuCSUhOyFrlRvFEllZOYE+yZGQ==", - "dev": true, - "requires": { - "glob": "^9.2.0" + "ws": "8.13.0" } }, "typescript": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.2.tgz", - "integrity": "sha512-wVORMBGO/FAs/++blGNeAVdbNKtIh1rbBL2EyQ1+J9lClJ93KiiKe8PmFIVdXhHcyv44SL9oglmfeSsndo0jRw==", + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.4.tgz", + "integrity": "sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==", "dev": true, "optional": true, "peer": true }, - "ws": { - "version": "8.12.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.12.1.tgz", - "integrity": "sha512-1qo+M9Ba+xNhPB+YTWUlK6M17brTut5EXbcBaMRN5pH5dFrXz7lzz1ChFSUq3bOUl8yEvSenhHmYUNJxFzdJew==", + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, - "requires": {} + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true + }, + "yargs": { + "version": "17.7.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.1.tgz", + "integrity": "sha512-cwiTb08Xuv5fqF4AovYacTFNxk62th7LKJ6BL9IGUpTJrWoU7/7WdQGTP2SjKf1dUNBGzDd28p/Yfs/GI6JrLw==", + "dev": true, + "requires": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + } + }, + "yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true } } }, @@ -41755,12 +43151,20 @@ "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==" }, + "requizzle": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.4.tgz", + "integrity": "sha512-JRrFk1D4OQ4SqovXOgdav+K8EAhSB/LJZqCz8tbX0KObcdeM15Ss59ozWMBWmmINMagCwmqn4ZNryUGpBsl6Jw==", + "requires": { + "lodash": "^4.17.21" + } + }, "resolve": { - "version": "1.22.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", - "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "version": "1.22.2", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz", + "integrity": "sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==", "requires": { - "is-core-module": "^2.9.0", + "is-core-module": "^2.11.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" } @@ -41916,6 +43320,16 @@ "is-plain-object": "^3.0.0" }, "dependencies": { + "@types/glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==", + "dev": true, + "requires": { + "@types/minimatch": "*", + "@types/node": "*" + } + }, "fs-extra": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", @@ -42065,9 +43479,9 @@ } }, "semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.4.0.tgz", + "integrity": "sha512-RgOxM8Mw+7Zus0+zcLEUn8+JfoLpj/huFTItQy2hsM4khuC1HYRDp0cU482Ewn/Fcy6bCjufD8vAj7voC66KQw==", "requires": { "lru-cache": "^6.0.0" }, @@ -42357,9 +43771,9 @@ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" }, "shell-quote": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.0.tgz", - "integrity": "sha512-QHsz8GgQIGKlRi24yFc6a6lN69Idnx634w49ay6+jA5yFh7a1UY+4Rp6HPx/L/1zcEDPEij8cIsiqR6bQsE5VQ==" + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", + "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==" }, "shellsubstitute": { "version": "1.2.0", @@ -42461,9 +43875,9 @@ "dev": true }, "slugify": { - "version": "1.6.5", - "resolved": "https://registry.npmjs.org/slugify/-/slugify-1.6.5.tgz", - "integrity": "sha512-8mo9bslnBO3tr5PEVFzMPIWwWnipGS0xVbYf65zxDqfNwmzYn1LpiKNrR6DlClusuvo+hDHd1zKpmfAe83NQSQ==" + "version": "1.6.6", + "resolved": "https://registry.npmjs.org/slugify/-/slugify-1.6.6.tgz", + "integrity": "sha512-h+z7HKHYXj6wJU+AnS/+IH8Uh9fdcX1Lrhg1/VMdf9PwoBQXFcXiAdsy2tSK0P6gKwJLXp02r90ahUCqHk9rrw==" }, "snapdragon": { "version": "0.8.2", @@ -43074,8 +44488,7 @@ "strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==" }, "striptags": { "version": "3.2.0", @@ -43489,9 +44902,9 @@ } }, "terser": { - "version": "5.16.6", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.6.tgz", - "integrity": "sha512-IBZ+ZQIA9sMaXmRZCUMDjNH0D5AQQfdn4WUjHL0+1lF4TP1IHRJbrhb6fNaXWikrYQTSkb7SLxkeXAiy1p7mbg==", + "version": "5.16.9", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.9.tgz", + "integrity": "sha512-HPa/FdTB9XGI2H1/keLFZHxl6WNvAI4YalHGtDQTlMnJcoqSab1UwL4l1hGEhs6/GmLHBZIg/YgB++jcbzoOEg==", "dev": true, "requires": { "@jridgewell/source-map": "^0.3.2", @@ -43603,7 +45016,6 @@ "version": "0.2.1", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", - "dev": true, "requires": { "rimraf": "^3.0.0" } @@ -43903,9 +45315,9 @@ "integrity": "sha512-DqGhF5IKoBl8WNf8C1gu8q0xZSInh9j1kJJMqT3a94w1JzVaBU4EXOSMrz9yDqMT0xt3selp83fuFMQ0uzv6qA==" }, "ua-parser-js": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.34.tgz", - "integrity": "sha512-K9mwJm/DaB6mRLZfw6q8IMXipcrmuT6yfhYmwhAkuh+81sChuYstYA+znlgaflUPaYUa3odxKPKGw6Vw/lANew==" + "version": "1.0.35", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.35.tgz", + "integrity": "sha512-fKnGuqmTBnIE+/KXSzCn4db8RTigUzw1AN0DmdU6hJovUTbYJKyqj+8Mt1c4VfRDnOVJnENmfYkIPZ946UrSAA==" }, "uc.micro": { "version": "1.0.6", @@ -43920,8 +45332,7 @@ "uglify-js": { "version": "3.17.4", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz", - "integrity": "sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==", - "optional": true + "integrity": "sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==" }, "uhyphen": { "version": "0.2.0", @@ -44864,9 +46275,9 @@ } }, "web-vitals": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/web-vitals/-/web-vitals-3.3.0.tgz", - "integrity": "sha512-GZsEmJBNclIpViS/7QVOTr7Kbt4BgLeR7kQ5zCCtJVuiWsA+K6xTXaoEXssvl8yYFICEyNmA2Nr+vgBYTnS4bA==" + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/web-vitals/-/web-vitals-3.3.1.tgz", + "integrity": "sha512-LTfY5GjcY3ngFzNsYFSYL+AmVmlWrzPTUxSMDis2rZbf+SzT7HH3NH4Y/l45XOlrAIunOBeURN9qtBHkRskAiA==" }, "webdev-infra": { "version": "1.0.53", @@ -45049,8 +46460,7 @@ "word-wrap": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", - "dev": true + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==" }, "wordwrap": { "version": "1.0.0", @@ -45137,6 +46547,11 @@ "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==" }, + "xmlcreate": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-2.0.4.tgz", + "integrity": "sha512-nquOebG4sngPmGPICTS5EnxqhKbCmz5Ox5hsszI2T6U5qdrJizBc+0ilYSEjTSzU0yZcmvppztXe/5Al5fUwdg==" + }, "xmlhttprequest-ssl": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.0.0.tgz", diff --git a/package.json b/package.json index 5e7cecf5b..cf7f28302 100644 --- a/package.json +++ b/package.json @@ -47,6 +47,7 @@ "@11ty/eleventy-cache-assets": "^2.3.0", "@11ty/eleventy-plugin-rss": "^1.1.2", "@11ty/eleventy-plugin-syntaxhighlight": "^4.0.0", + "@google-cloud/appengine-admin": "2.1.2", "@google-cloud/cloudbuild": "^2.6.0", "@google-cloud/error-reporting": "^2.0.4", "@google-cloud/storage": "^6.7.0", diff --git a/site/_filters/md.js b/site/_filters/md.js index bff22fd7e..29adbb06b 100644 --- a/site/_filters/md.js +++ b/site/_filters/md.js @@ -24,7 +24,7 @@ const md = require('markdown-it')(); * Render content as markdown. * * @param {string?} content - * @return {string|undefined} + * @return {string|null} * @this {any} */ function render(content) { @@ -35,7 +35,7 @@ function render(content) { * Render content as inline markdown. * * @param {string?} content - * @return {string|undefined} + * @return {string|null} * @this {any} */ function renderInline(content) { From 2526f58305f0ebfd956ffbd474b21fb68398a82f Mon Sep 17 00:00:00 2001 From: Maya Janthong <45324326+mamieorine@users.noreply.github.com> Date: Mon, 17 Apr 2023 10:35:08 +0100 Subject: [PATCH 042/982] fix: project card are broken on the safari 16.4 (#5982) --- .../_includes/macros/cards/hero-card-wide.njk | 2 ++ site/_includes/macros/cards/hero-card.njk | 2 ++ site/_includes/macros/project-icon.njk | 2 ++ site/_scss/blocks/_project-icon.scss | 31 +++++++------------ 4 files changed, 18 insertions(+), 19 deletions(-) diff --git a/site/_includes/macros/cards/hero-card-wide.njk b/site/_includes/macros/cards/hero-card-wide.njk index 4cb854902..658e54c35 100644 --- a/site/_includes/macros/cards/hero-card-wide.njk +++ b/site/_includes/macros/cards/hero-card-wide.njk @@ -8,6 +8,8 @@

{% if titleIcon %}
+
+
{# image/jxu1OdD7LKOGIDU7jURMpSH2lyK2/TvE0fdJmcXI8fuPc8R7A.svg #} {% Img diff --git a/site/_includes/macros/cards/hero-card.njk b/site/_includes/macros/cards/hero-card.njk index 260e5bfa3..c8834e062 100644 --- a/site/_includes/macros/cards/hero-card.njk +++ b/site/_includes/macros/cards/hero-card.njk @@ -8,6 +8,8 @@

{% if titleIcon %}
+
+
{# image/jxu1OdD7LKOGIDU7jURMpSH2lyK2/TvE0fdJmcXI8fuPc8R7A.svg #} {% Img diff --git a/site/_includes/macros/project-icon.njk b/site/_includes/macros/project-icon.njk index a5c846ace..cda626102 100644 --- a/site/_includes/macros/project-icon.njk +++ b/site/_includes/macros/project-icon.njk @@ -4,6 +4,8 @@
{% set styles = (project_key | embededDoc(docs)).styles %} {% set color = styles.project_icon_color %} +
+
{# svg() looks in "_includes", so find the project image in the parent directory #} {{ svg('../_static/images/project/' + project_key | replace("/", "-") + '.svg', {hidden: true}) }} diff --git a/site/_scss/blocks/_project-icon.scss b/site/_scss/blocks/_project-icon.scss index 2a74bbb21..91b992742 100644 --- a/site/_scss/blocks/_project-icon.scss +++ b/site/_scss/blocks/_project-icon.scss @@ -27,42 +27,35 @@ justify-content: center; position: relative; transform-style: preserve-3d; // only needed for Firefox + transition: transform 0.4s; width: 128px; - &::before, - &::after { - background-color: inherit; - border-radius: 6px; - bottom: 0; - content: ''; - display: block; + &.cover-last, + &.cover-mid { + background-image: none; left: 0; position: absolute; - right: 0; top: 0; - transition: transform 0.4s; } - &::before { - filter: saturate(90%) contrast(0.9) brightness(1.4); - transform: translate3D(0, 0, -1rem) scale(0.95); - z-index: -1; - } - - &::after { + &.cover-last { filter: saturate(50%) contrast(0.7) brightness(2); transform: translate3D(0, 0, -2rem) scale(0.9); - z-index: -2; + } + + &.cover-mid { + filter: saturate(90%) contrast(0.9) brightness(1.4); + transform: translate3D(0, 0, -1rem) scale(0.95); } } .project-icon:hover { .project-icon__cover { - &::before { + &.cover-mid { transform: translate3D(0, 0, -0.25em) scale(1); } - &::after { + &.cover-last { transform: translate3D(0, 0, -0.5em) scale(1); } } From ec75df275ba66f1c1e3838ba14d9881f5fb05677 Mon Sep 17 00:00:00 2001 From: Suguru Inatomi Date: Mon, 17 Apr 2023 19:38:05 +0900 Subject: [PATCH 043/982] [devtools-translate] Japanese - What's New in DevTools (Chrome 112) (#5898) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * translate new-in-devtools-112 * translate whats-new * fix expression * Apply suggestions from code review Co-authored-by: Yoichiro Tanaka Co-authored-by: よしこ * Apply suggestions from code review Co-authored-by: ANDO Yasushi * fix --------- Co-authored-by: Yoichiro Tanaka Co-authored-by: よしこ Co-authored-by: ANDO Yasushi --- site/ja/_partials/devtools/whats-new.md | 26 +++---- site/ja/blog/new-in-devtools-112/index.md | 92 +++++++++++++++++++---- 2 files changed, 89 insertions(+), 29 deletions(-) diff --git a/site/ja/_partials/devtools/whats-new.md b/site/ja/_partials/devtools/whats-new.md index c42d37031..0b8d2a169 100644 --- a/site/ja/_partials/devtools/whats-new.md +++ b/site/ja/_partials/devtools/whats-new.md @@ -6,20 +6,20 @@ {# ### Chrome 112 {: #chrome112 } -* [Recorder updates](/ja/blog/new-in-devtools-112/#recorder) -* [Recorder replay extensions](/ja/blog/new-in-devtools-112/#replay-extensions) -* [Record with pierce selectors](/ja/blog/new-in-devtools-112/#pierce-selectors) -* [Export recordings as Puppeteer scripts with Lighthouse analysis](/ja/blog/new-in-devtools-112/#puppeteer-lighthouse) -* [Get extensions](/ja/blog/new-in-devtools-112/#get-extensions) -* [Elements > Styles updates](/ja/blog/new-in-devtools-112/#elements-styles) -* [CSS documentation in the Styles pane](/ja/blog/new-in-devtools-112/#css) -* [CSS nesting support](/ja/blog/new-in-devtools-112/#nesting) -* [Marking logpoints and conditional breakpoints in the Console](/ja/blog/new-in-devtools-112/#logpoint) -* [Ignore irrelevant scripts during debugging](/ja/blog/new-in-devtools-112/#ignore-list) -* [JavaScript Profiler deprecation started](/ja/blog/new-in-devtools-112/#js-profiler-deprecation) -* [Emulate reduced contrast](/ja/blog/new-in-devtools-112/#reduced-contrast) +* [Recorder のアップデート](/ja/blog/new-in-devtools-112/#recorder) +* [Recorder リプレイの拡張機能](/ja/blog/new-in-devtools-112/#replay-extensions) +* [ピアスセレクタを使用した記録](/ja/blog/new-in-devtools-112/#pierce-selectors) +* [Lighthouse の解析結果を Puppeteer のスクリプトとして書き出す](/ja/blog/new-in-devtools-112/#puppeteer-lighthouse) +* [拡張機能を手に入れる](/ja/blog/new-in-devtools-112/#get-extensions) +* [Elements > Styles のアップデート](/ja/blog/new-in-devtools-112/#elements-styles) +* [Styles ペインでの CSS ドキュメントの表示](/ja/blog/new-in-devtools-112/#css) +* [CSS ネスティングのサポート](/ja/blog/new-in-devtools-112/#nesting) +* [Console でログポイントや条件付きブレークポイントをマークする](/ja/blog/new-in-devtools-112/#logpoint) +* [デバッグ時に無関係なスクリプトを無視する](/ja/blog/new-in-devtools-112/#ignore-list) +* [JavaScript Profiler の非推奨化の開始](/ja/blog/new-in-devtools-112/#js-profiler-deprecation) +* [コントラスト低減をエミュレート](/ja/blog/new-in-devtools-112/#reduced-contrast) * [Lighthouse 10](/ja/blog/new-in-devtools-112/#lighthouse) -* [Miscellaneous highlights](/ja/blog/new-in-devtools-112/#misc) +* [その他のハイライト](/ja/blog/new-in-devtools-112/#misc) #} {# ### Chrome 111 {: #chrome111 } diff --git a/site/ja/blog/new-in-devtools-112/index.md b/site/ja/blog/new-in-devtools-112/index.md index fcdbeec6d..ee3068869 100644 --- a/site/ja/blog/new-in-devtools-112/index.md +++ b/site/ja/blog/new-in-devtools-112/index.md @@ -11,7 +11,6 @@ tags: - new-in-devtools - devtools - chrome-112 -draft: true --- *翻訳者の [technohippy](https://github.com/technohippy) さん、レビュアーの [yoichiro](https://github.com/yoichiro) さん、 [lacolaco](https://github.com/lacolaco) さん、 [yoshiko-pg](https://github.com/yoshiko-pg) さんに感謝いたします。* @@ -28,16 +27,21 @@ draft: true +## Recorder のアップデート {: #recorder } +### リプレイの拡張機能サポート {: #replay-extensions } +**Recorder**に、拡張機能を使ってDevToolsに組み込むことができるカスタムリプレイオプションがサポートされています。 +[拡張機能の例](https://github.com/puppeteer/replay/tree/main/examples/chrome-extension-replay)を試してみてください。新しいカスタムリプレイオプションを選択し、カスタムリプレイのUIを開きましょう。 -{% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/CAQFVtHyds7ByB0YMZht.png", alt="Custom replay UI.", width="800", height="563" %} +{% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/CAQFVtHyds7ByB0YMZht.png", alt="カスタムリプレイ UI", width="800", height="563" %} +あなたのニーズに合わせて**Recorder**をカスタマイズし、あなたのツールと統合するために、独自の拡張機能を開発することを検討してみましょう: [chrome.devtools.recorder API](/docs/extensions/reference/devtools_recorder/) を調べて、[拡張機能の例] (https://github.com/puppeteer/replay/tree/main/examples/) をチェックしてみてください。 {# https://chrome-internal.googlesource.com/devtools/devtools-internal/+/c2102177581f1c74d38502f469d99b20c1835b1c #} {# https://chrome-internal.googlesource.com/devtools/devtools-internal/+/e304e064dbead1d684b5c61f4fb308b101b4a66b #} @@ -45,38 +49,48 @@ draft: true Chromium issue: [1400243](https://crbug.com/1400243). +### ピアスセレクターを使用した記録 {: #pierce-selectors } +[カスタム、CSS、ARIA、テキスト、XPathセレクタ](/docs/devtools/recorder/reference/#selector)に加えて、[ピアスセレクタ](https://pptr.dev/guides/query-selectors#pierce-selectors-pierce)を使用して記録できるようになりました。これらのセレクタはCSSのセレクタと同じように振る舞いますが、シャドウルートを貫通することもできます。 +[Shadow DOM](https://web.dev/shadowdom-v1/)が含まれるページで新規レコードを開始し、**Selector types to record**で {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/hmp8j3HiLMCcqPArD9yt.svg", alt="Checkbox.", width="22", height="22" %} **Pierce** にチェックをつけます。Shadow DOMの中の要素とのインタラクションを記録し、対応するステップを検査します。 -{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/Spqbf2DG3Fr0D2sc1kgC.png", alt="Setting the Recorder to use pierce selectors; Pierce selector in action.", width="800", height="534" %} +{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/Spqbf2DG3Fr0D2sc1kgC.png", alt="ピアスセレクタを使った Recorder の設定; 作動中のピアスセレクタ", width="800", height="534" %} {# https://chrome-internal.googlesource.com/devtools/devtools-internal/+/a3968d1c01dd4d1a00b9aa13c50bfdc66995879e #} Chromium issue: [1411188](https://crbug.com/1411188). +### Lighthouse の解析結果を Puppeteer のスクリプトとして書き出す {: #puppeteer-lighthouse } +**Recorder** に新しいエクスポートオプション **Puppeteer (including Lighthouse analysis)** を導入しました。[Puppeteer](/docs/puppeteer/)を使用すると、Chromeを自動化し制御することができます。[Lighthouse](/docs/lighthouse/)を使用すると、ウェブサイトのパフォーマンスを把握し、改善することができます。 +記録を開き、{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/4dU9UXvsinS4zbgjd8rK.svg", alt="Export.", width="20", height="20" %} をクリックします。**Export**で新しいオプションを選択し、`.js`ファイルを保存してください。 -{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/ko6OD4tgGwUxqCJScYr9.png", alt="Export Puppeteer (including Lighthouse analysis).", width="800", height="584" %} +{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/ko6OD4tgGwUxqCJScYr9.png", alt="(Lighthouse 解析結果を含む) Puppeteer スクリプトのエクスポート", width="800", height="584" %} +[Puppeteerスクリプトを実行](/docs/puppeteer/get-started/)し、Lighthouseのレポートを`flow.report.html`ファイルから取得します。 -{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/pfvZ3QX0XhhbDBxpsyBF.png", alt="The Lighthouse report opened in Chrome.", width="800", height="690" %} +{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/pfvZ3QX0XhhbDBxpsyBF.png", alt="Chrome で開いた Lighthouse のレポート", width="800", height="690" %} {# https://chrome-internal.googlesource.com/devtools/devtools-internal/+/fcaf72d9134e54140cab41c011b7520dd168a340 #} +### 拡張機能を手に入れる {: #get-extensions } +カスタムエクスポートオプションなど、レコーダーの体験をカスタマイズする選択肢を探しましょう。**Recorder**の拡張機能を入手するには、{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/4dU9UXvsinS4zbgjd8rK.svg", alt="Export.", width="20", height="20" %} **Export** > **Get extensions** をクリックします。 -{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/vwgXoxR0FyArbCHvdvEY.png", alt="The Get extensions option in the Export drop-down menu.", width="800", height="649" %} +{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/vwgXoxR0FyArbCHvdvEY.png", alt="Export ドロップダウンメニュー内の Get extensions オプション", width="800", height="649" %} +気軽に[Recorder の拡張機能](/docs/devtools/recorder/extensions/)のリストに、[自身の拡張機能を追加](https://github.com/GoogleChrome/developer.chrome.com/edit/main/site/en/docs/devtools/recorder/extensions/index.md)してください。みなさんの拡張機能がリストに載るのを楽しみにしています! {# https://chrome-internal.googlesource.com/devtools/devtools-internal/+/21e3d3275c47df8b79c72d1a3e8f9d26cc11fc04 #} {# https://chrome-internal.googlesource.com/devtools/devtools-internal/+/b6d02827539eb54869cbb75d3705782bfd2c95ae #} @@ -84,21 +98,28 @@ Chromium issue: [1411188](https://crbug.com/1411188). Chromium issues: [1417104](https://crbug.com/1417104), [1413168](https://crbug.com/1413168). +## Elements > Styles のアップデート {: #elements-styles } +### CSS のドキュメンテーション {: #css } +CSSのプロパティについて、1日に何回ドキュメントを調べていますか? **Elements** > **Styles** ペインでプロパティにカーソルを合わせると、短い説明が表示されるようになりました。 -{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/v0joPkQg0NiMauy0bwwB.png", alt="The tooltip with documentation on a CSS property.", width="800", height="651" %} +{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/v0joPkQg0NiMauy0bwwB.png", alt="CSS プロパティ上でのドキュメントのツールチップ", width="800", height="651" %} +ツールチップには、このプロパティに関する[MDN の CSS リファレンス](https://developer.mozilla.org/docs/Web/CSS/Reference)を参照するための **Learn more** リンクも表示されます。 +CSSをよくご存知の方は、ツールチップを煩わしいと感じるかもしれません。これらをすべて消すには、{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/hmp8j3HiLMCcqPArD9yt.svg", alt="Checkbox.", width="22", height="22" %} **Don't show** にチェックをつけてください。 +機能をオンに戻すには、 {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/9gzXiTY0nZzBxGI6KrV.svg", alt="Settings.", width="24", height="24" %} [**Settings** > **Preferences** > **Elements**](/docs/devtools/settings/preferences/#elements) > {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/hmp8j3HiLMCcqPArD9yt.svg", alt="Checkbox.", width="22", height="22" %} **Show CSS documentation tooltip** にチェックをつけてください。 {% Aside %} +DevToolsは、ツールチップの説明を[VS Code Custom Data](https://github.com/microsoft/vscode-custom-data)から取得します。 {% endAside %} {# https://chromium.googlesource.com/devtools/devtools-frontend/+/f5266ee227449dbbc3bc599df1b38cdb36cae4cb #} @@ -107,8 +128,10 @@ Chromium issues: [1417104](https://crbug.com/1417104), [1413168](https://crbug.c Chromium issue: [1401107](https://crbug.com/1401107). +### CSS ネスティングのサポート {: #nesting } + **Elements** > **Styles** ペインで、[CSS ネスティング](/articles/css-nesting/) 構文を認識し、入れ子のスタイルを正しい要素に適用するようになりました。 {% Video src="video/NJdAV9UgKuN8AhoaPBquL7giZQo1/Wog2uOaJTV84OtXcHpYH.mp4", autoplay="true", muted="true", loop="true", controls="true", class="screenshot" %} @@ -117,19 +140,25 @@ Chromium issue: [1401107](https://crbug.com/1401107). Chromium issue: [1172985](https://crbug.com/1172985). +## Console でログポイントや条件付きブレークポイントをマークする {: #logpoint } +[ブレークポイントUXの強化](/blog/new-in-devtools-111/#breakpoint-redesign)をさらに改善し、 **Console** がブレークポイントによって引き起こされたメッセージをマークするようになりました: +- [条件付きブレークポイント](/docs/devtools/javascript/breakpoints/#conditional-loc) の中での `console.*` の呼び出しにはオレンジ色の疑問符 `?` +- [ログポイント](/docs/devtools/javascript/breakpoints/#log-loc) メッセージにはピンクの2つのドット `..` -{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/5udIX9W4LFcDb3H6DuDp.png", alt="Changes to how the Console now displays messages triggered by breakpoints: with icons and proper source link.", width="800", height="566" %} +{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/5udIX9W4LFcDb3H6DuDp.png", alt="Console がブレークポイントによってトリガーされたメッセージを表示する方法の変更: アイコンと適切なソースリンク", width="800", height="566" %} +**Console** では、 Chrome が [V8](https://v8.dev/) 上で任意の Javascript を実行するために作成する `VM` スクリプトではなく、ソースファイル内のブレークポイントへの適切なアンカーリンクが表示されるようになりました。 +ブレークポイントメッセージの横にあるリンクをクリックすると、ブレークポイントエディタに直接ジャンプします。 -{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/8lAz0lb168HXKvhscP2Q.png", alt="The anchor link next to a logpoint message that opens the breakpoint editor.", width="800", height="811" %} +{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/8lAz0lb168HXKvhscP2Q.png", alt="ブレークポイントエディタを開くログポイントメッセージの横にあるアンカーリンク。", width="800", height="811" %} {# https://chromium.googlesource.com/devtools/devtools-frontend/+/c845a441b0fe05c22f88cdb23463edee2b5985b7 #} {# https://chromium.googlesource.com/devtools/devtools-frontend/+/9762db476cd7414d3ce351f32a0564421f66901f #} @@ -140,19 +169,25 @@ Chromium issue: [1172985](https://crbug.com/1172985). Chromium issue: [1027458](https://crbug.com/1027458). +## デバッグ時に無関係なスクリプトを無視する {: #ignore-list } +コードの最も重要な部分に集中できるように、 **Sources** > **Page** ペインのファイルツリーから、無関係なスクリプトを **Ignore List** に追加できるようになりました。 +スクリプトまたはフォルダを右クリックし、無視関連のオプションのいずれかを選択します。スクリプトまたはフォルダーをリストに追加したり、リストから削除したりするオプションが表示される場合があります。デバッガーはリストに追加された[スクリプトを無視](/docs/devtools/javascript/reference/#show-ignore-listed-frames)し、コールスタックでそれらを省略します。 -{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/RrL7ZmzMjfhtH4gUW3ST.png", alt="Context menus of a folder and script with ignore-related options.", width="800", height="521" %} +{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/RrL7ZmzMjfhtH4gUW3ST.png", alt="無視に関連したオプションを持つフォルダやスクリプトのコンテキストメニュー", width="800", height="521" %} +無視リストに登録されたスクリプトやフォルダは、ファイルツリーですべてグレーアウトされます。 -{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/DRI11RoakrLnwLZPOJPO.png", alt="Ignore-listed scripts and folders are grayed out, you can hide them with an experimental option in the More options drop-down menu.", width="800", height="542" %} +{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/DRI11RoakrLnwLZPOJPO.png", alt="無視リストのスクリプトとフォルダはグレー表示されます。More オプションドロップダウンメニューの実験的なオプションを使用してそれらを非表示にすることができます。", width="800", height="542" %} -{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/9gzXiTYY0nZzBxGI6KrV.svg", alt="Settings.", width="24", height="24" %} [**Settings** > **Ignore List**](/docs/devtools/settings/ignore-list/). You can also hide ignored sources from the file tree with {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/N5Lkpdwpaz4YqRGFr2Ks.svg", alt="Three-dot menu.", width="24", height="24" %} > [**Hide ignore-listed sources**](/docs/devtools/javascript/reference/#hide-ignore-listed) {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/XfSWf04g2cwpnFcmp40m.svg", alt="Experimental.", width="20", height="20" %}. + +無視されたスクリプトを選択すると、 {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/9gzXiTYY0nZzBxGI6KrV.svg", alt="Settings.", width="24", height="24" %} [**Settings** > **Ignore List**](/docs/devtools/settings/ignore-list/) を開く **Configure** ボタンが表示されます。 +また、{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/N5Lkpdwpaz4YqRGFr2Ks.svg", alt="Three-dot menu.", width="24", height="24" %} > [**Hide ignore-listed sources**](/docs/devtools/javascript/reference/#hide-ignore-listed) {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/XfSWf04g2cwpnFcmp40m.svg", alt="Experimental.", width="20", height="20" %} で、無視されたソースをファイルツリーから隠すこともできます。 {# https://chromium.googlesource.com/devtools/devtools-frontend/+/e95d2f3fd27301945a1a095bae4bbcad57326cd8 #} {# https://chromium.googlesource.com/devtools/devtools-frontend/+/736762eda6a6f30d0e9c383998624e53ee04a6e2 #} @@ -161,30 +196,39 @@ Chromium issue: [1027458](https://crbug.com/1027458). Chromium issue: [883325](https://crbug.com/883325). +## JavaScript Profiler の非推奨化を開始 {: #js-profiler-deprecation } +[Chrome 58](/blog/devtools-javascript-cpu-profile-migration-2/) の時点で、DevToolsチームは、最終的に **JavaScript Profiler** を廃止し、Node.js および Deno 開発者には **Performance** パネルを使用して JavaScript CPU パフォーマンスのプロファイルをしてもらうことを計画していました。 +この DevTools バージョン(112)から、[4段階の **JavaScript Profiler** 非推奨化](https://github.com/ChromeDevTools/rfcs/discussions/2#discussioncomment-5189668)を開始します。 **JavaScript Profiler** パネルに対応する警告バナーが表示されるようになりました。 -{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/v4S5YWGdBV3nbc3OkGZ3.png", alt="Deprecation banner at the top of the Profiler.", width="800", height="712" %} +{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/v4S5YWGdBV3nbc3OkGZ3.png", alt="Profiler の上部にある非推奨を表示するバナー", width="800", height="712" %} +CPU のプロファイルは、 **Profiler** の代わりに [**Performance**](/docs/devtools/performance/reference/#main) パネルを使ってください。 +[RFC](https://github.com/ChromeDevTools/rfcs/discussions/2) および [crbug.com/1354548](https://crbug.com/1354548) で詳細を確認し、フィードバックしてください。 {# https://chromium.googlesource.com/devtools/devtools-frontend/+/71244f613a27289936b979fe515346137d0190f8 #} Chromium issue: [1417647](https://crbug.com/1417647). +## コントラスト低減をエミュレートする {: #reduced-contrast } +[**Rendering**](/docs/devtools/rendering/#open-rendering) タブでは、 [Emulate vision deficiencies](/docs/devtools/rendering/apply-effects/#emulate-vision-deficiencies) に新しいオプション **Reduced contrast** を追加しました。このオプションを使用すると、コントラスト感度が低下している人にあなたのウェブサイトがどのように見えるかを確認できます。 -{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/7qrlmuO7R47l5mytvoeQ.png", alt="The reduced contrast option on the Rendering > Emulate vision deficiencies.", width="800", height="574" %} +{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/7qrlmuO7R47l5mytvoeQ.png", alt="Rendering > Emulate vision deficiencies でのコントラストを下げるオプション", width="800", height="574" %} +なお、リストオプションが更新され、そのオプションがどのような色覚異常を表すかがわかるようになりました。 +DevTools を使えば、すべてのコントラストの問題を一度に見つけて修正することができます。詳しくは、 [Make your website more readable](/docs/devtools/accessibility/contrast/) を参照してください。 {# https://chromium.googlesource.com/devtools/devtools-frontend/+/0eaaa173c9e2cd357c99f7a275fe1819b86f0b9a #} {# https://chromium.googlesource.com/devtools/devtools-frontend/+/768af28f8cf64e10d23b10556b59dc0770cc14b6 #} @@ -192,16 +236,22 @@ Chromium issue: [1417647](https://crbug.com/1417647). Chromium issues: [1412719](https://crbug.com/1412719), [1412721](https://crbug.com/1412721). +## Lighthouse 10 {: #lighthouse } +**Lighthouse** パネルが [Lighthouse 10.0.1](/blog/lighthouse-10-0/) を実行するようになりました。詳しくは、 [Lighthouse 10.0.1の新機能](/blog/lighthouse-10-0/) をご覧ください。 +**Lighthouse** > {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/9gzXiTYY0nZzBxGI6KrV.svg", alt="Settings.", width="24", height="24" %} > {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/ZtDyFg7cjkxacORB3GQn.svg", alt="Empty checkbox.", width="24", height="24" %} **Legacy navigation** はデフォルトで無効になっています。このオプションは、ナビゲーションモードでレガシーな [Lighthouse 設定](https://github.com/GoogleChrome/lighthouse/blob/main/docs/configuration.md) を使用します。 -{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/mYuX9d2TFaJuWBOYGN5R.png", alt="Disabled legacy navigation.", width="800", height="548" %} + +{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/mYuX9d2TFaJuWBOYGN5R.png", alt="レガシーナビゲーションを無効化", width="800", height="548" %} +Lighthouse 10では、 Moto G Power を[デフォルトのエミュレーションデバイス](https://github.com/GoogleChrome/lighthouse/pull/14674)として使用するようになりました。 DevTools はこのデバイスを {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/9gzXiTYY0nZzBxGI6KrV.svg", alt="Settings.", width="24", height="24" %} [**Settings** > **Devices**](/docs/devtools/settings/devices/) に追加しました。 -{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/GpqmLAiuNasdRsfisVS7.png", alt="Moto G Power in the Devices list.", width="800", height="488" %} + +{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/GpqmLAiuNasdRsfisVS7.png", alt="デバイスリスト中の Moto G Power", width="800", height="488" %} {# https://chromium.googlesource.com/devtools/devtools-frontend/+/d5f9f7b395e2965356dfcaed026b5a1d141c19c6 #} {# https://chromium.googlesource.com/devtools/devtools-frontend/+/de6c4e5973980ad98d7d1699faa4e1059f102c4d #} @@ -211,8 +261,10 @@ Chromium issues: [1412719](https://crbug.com/1412719), [1412721](https://crbug.c Chromium issue: [772558](https://crbug.com/772558). +## その他のハイライト {: #misc } +今回のリリースでは、以下のような注目すべき修正が行われています: @@ -222,6 +274,14 @@ Chromium issue: [772558](https://crbug.com/772558). +- [**Sources** > **Breakpoints**](/docs/devtools/javascript/breakpoints/#manage-loc) ペインで、あいまいなファイル名の横に区別できるファイルパスを表示するようになりました([1403924](crbug.com/1403924)). +- **Performance** パネルのフレームチャートの [**Main** セクション](/docs/devtools/performance/reference/#main) で、 `CpuProfiler::StartProfiling` を `Profiler Overhead` ([1358602](https://crbug.com/1358602)) と指定するようにしました。 +- DevToolsのオートコンプリートを改善しました: + - **Sources**: 任意の単語の一貫した補完([1320204](https://crbug.com/1320204))。 + - **Console**: `Arrow down` で最初の候補が選択され、`Tab` で候補のヒントが得られます([1276960](https://crbug.com/1276960))。 +- DevTools に[イベントリスナーブレークポイント](/docs/devtools/javascript/breakpoints/#event-listeners)を追加し、[ドキュメントのピクチャーインピクチャーウィンドウ](https://wicg.github.io/document-picture-in-picture/#dom-documentpictureinpicture-onenter) ([1315352](https://crbug.com/1315352)) を開く際に一時停止できるようにしました。 +- DevToolsは、 Vue2 の webpack アーティファクトを JavaScript として適切に表示するワークアラウンドを設定しました([1416562](https://crbug.com/1416562))。 +- [**Console** の設定](/docs/devtools/settings/preferences/#console)が、より良い名前になりました: Automatically expand console.trace() messages ([1139616](https://crbug.com/1139616)). {% Partial 'devtools/reach-out.md' %} From 3da7442d4b8ccc073fae7ec98dc0982b704744d7 Mon Sep 17 00:00:00 2001 From: Maya Janthong <45324326+mamieorine@users.noreply.github.com> Date: Mon, 17 Apr 2023 13:58:46 +0100 Subject: [PATCH 044/982] feat: create rss feeds per author (#5975) * feat: add rss feeds per author * fix: unique the list of authors * fix: revert wrong guided code review changes --------- Co-authored-by: Matthias Rohmer --- site/_collections/authors.js | 1 + site/_collections/feeds.js | 20 +++++++++++++++++++- site/_includes/icons/rss-author.svg | 3 +++ site/_includes/layouts/author-individual.njk | 5 +++++ 4 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 site/_includes/icons/rss-author.svg diff --git a/site/_collections/authors.js b/site/_collections/authors.js index 56f86368b..5ccb89910 100644 --- a/site/_collections/authors.js +++ b/site/_collections/authors.js @@ -44,6 +44,7 @@ module.exports = collections => { authors[authorId].title = `i18n.authors.${authorId}.title`; authors[authorId].key = authorId; authors[authorId].url = `/authors/${authorId}/`; + authors[authorId].rss = `/authors/${authorId}/feed.xml`; authors[authorId].image = authorsData[authorId].image || site.defaultAvatarImg; diff --git a/site/_collections/feeds.js b/site/_collections/feeds.js index 8d728de8e..6df93008f 100644 --- a/site/_collections/feeds.js +++ b/site/_collections/feeds.js @@ -59,6 +59,9 @@ module.exports = collection => { /** @type FeedsCollection */ const tagsFeeds = {}; + /** @type FeedsCollection */ + const authorsFeeds = {}; + /** @type {EleventyCollectionItem[]} */ const all = []; @@ -106,6 +109,21 @@ module.exports = collection => { tagsFeeds[tag].items.push(post); } } + + const authors = post.data.authors ?? []; + for (const author of authors) { + // If author feed does not exist in feeds yet, create FeedsCollectionItem + if (!authorsFeeds[author]) { + authorsFeeds[author] = { + items: [], + permalink: `/authors/${author}/feed.xml`, + title: i18n(`i18n.authors.${author}.title`), + url: `/authors/${author}`, + }; + } + + authorsFeeds[author].items.push(post); + } } // We write these feeds out in their own object so it's obvious that they will "win" over any @@ -130,5 +148,5 @@ module.exports = collection => { }, }; - return {...tagsFeeds, ...specialFeeds}; + return {...tagsFeeds, ...authorsFeeds, ...specialFeeds}; }; diff --git a/site/_includes/icons/rss-author.svg b/site/_includes/icons/rss-author.svg new file mode 100644 index 000000000..5dc3a30e2 --- /dev/null +++ b/site/_includes/icons/rss-author.svg @@ -0,0 +1,3 @@ + + + diff --git a/site/_includes/layouts/author-individual.njk b/site/_includes/layouts/author-individual.njk index 6f3a9d3ee..9a7468ce4 100644 --- a/site/_includes/layouts/author-individual.njk +++ b/site/_includes/layouts/author-individual.njk @@ -56,6 +56,11 @@ {{ icon('linkedin', {hidden: true}) }} {% endif %} + {% if paged.rss %} + + {% endif %}
From b3d437672e628f20ce534844d34b10f22c8cb92c Mon Sep 17 00:00:00 2001 From: Joe Medley Date: Mon, 17 Apr 2023 08:19:51 -0700 Subject: [PATCH 045/982] Add notice about new conversion readme. (#6028) --- site/en/docs/extensions/whatsnew/index.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/site/en/docs/extensions/whatsnew/index.md b/site/en/docs/extensions/whatsnew/index.md index 2fc20fb94..75a1b4120 100644 --- a/site/en/docs/extensions/whatsnew/index.md +++ b/site/en/docs/extensions/whatsnew/index.md @@ -3,7 +3,7 @@ layout: 'layouts/doc-post.njk' title: What's new in Chrome extensions description: 'Recent changes to the Chrome extensions platform, documentation, and policy' date: 2021-02-25 -updated: 2023-04-07 +updated: 2023-04-14 tags: - extensions-news @@ -16,6 +16,12 @@ tags: Check this page often to learn about changes to the Chrome extensions platform, its documentation, and related policy or other changes. You'll find other notices posted on the [Extensions Google Group](https://groups.google.com/a/chromium.org/g/chromium-extensions). The [Extensions News](/tags/extensions-news/) tag lists articles about many of the topics listed here. (It even has [an RSS feed](/feeds/extensions-news.xml).) +### New instructions for the Extension Manifest Converter + +

Posted on

+ +We've rewritten the README for the [Extension Manifest Converter](https://github.com/GoogleChromeLabs/extension-manifest-converter) to make it easier to see what you need to do after running the tool. The converter helps helps migrate extensions built on Manifest V2 to Manifest V3. The new README describes what the tool does using words that closely match those in the [migration guide's checklist](/docs/extensions/migrating/checklist/). The converter doesn't do everything, but it does eliminate many tasks that don't require a human judgement call. + ### Chrome 113: New reasons for offscreen documents

Posted on

From 70154997ba16e299a1259b1c5d331e7cd876eb66 Mon Sep 17 00:00:00 2001 From: Joe Medley Date: Mon, 17 Apr 2023 12:41:39 -0700 Subject: [PATCH 046/982] Fix mistakes in API replacement list. (#6030) * Fix mistake in API replacement list. * Add missing methods to 'Unsupported APIs' --- site/en/docs/extensions/migrating/api-calls/index.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/site/en/docs/extensions/migrating/api-calls/index.md b/site/en/docs/extensions/migrating/api-calls/index.md index d3236d28e..1197fd421 100644 --- a/site/en/docs/extensions/migrating/api-calls/index.md +++ b/site/en/docs/extensions/migrating/api-calls/index.md @@ -4,6 +4,7 @@ title: Update your code subhead: 'Updates that are unrelated to other issues' description: 'The first of three sections describing changes needed for code that is not part of the extension service worker.' date: 2023-03-09 +updated: 2023-04-17 --- This is the first of three sections describing changes needed for code that is not part of the extension service worker. This section is for required code changes that are unrelated to other issues. The next two sections cover [replacing blocking web requests](/docs/extensions/migrating/blocking-web-requests) and [improving security](/docs/extensions/migrating/improve-security). @@ -181,15 +182,18 @@ The methods and properties listed below need to change in Manifest V3. | Manifest V2 method or property | Replace with | |---------------------------------------|------------------------------------------------------| -| `chrome.extension.connect()` | `chrome.extension.connect()` | +| `chrome.extension.connect()` | `chrome.runtime.connect()` | +| `chrome.extension.connectNative()` | `chrome.runtime.connectNative()` | | `chrome.extension.getExtensionTabs()` | `chrome.extension.getViews()` | | `chrome.extension.getURL()` | `chrome.runtime.getURL()` | | `chrome.extension.lastError` | Where methods return promises, use `promise.catch()` | | `chrome.extension.onConnect` | `chrome.runtime.onConnect` | +| `chrome.extension.onConnectExternal` | `chrome.runtime.onConnectExternal` | | `chrome.extension.onMessage` | `chrome.runtime.onMessage` | | `chrome.extension.onRequest` | `chrome.runtime.onRequest` | | `chrome.extension.onRequestExternal` | `chrome.runtime.onMessageExternal` | | `chrome.extension.sendMessage()` | `chrome.runtime.sendMessage()` | +| `chrome.extension.sendNativeMessage() | `chrome.runtime.sendNativeMessage() | | `chrome.extension.sendRequest()` | `chrome.runtime.sendMessage()` | | `chrome.runtime.onSuspend` (background scripts) | Not supported in extension service workers. Use the [`beforeunload`](https://developer.mozilla.org/docs/Web/API/Window/beforeunload_event) document event instead. | | `chrome.tabs.getAllInWindow()` | `chrome.tabs.query()` | From b7bec070d8e7696ed771af484bb061cce44ab9b5 Mon Sep 17 00:00:00 2001 From: "Kevin K. Lee" Date: Mon, 17 Apr 2023 16:17:13 -0400 Subject: [PATCH 047/982] Add Protected Audience API renaming banner (#6032) --- .../privacy-sandbox/protected-audience-rename-banner.md | 3 +++ .../blog/bidding-and-auction-services-availability/index.md | 4 +++- site/en/blog/fledge-service-overview/index.md | 2 ++ site/en/docs/privacy-sandbox/fledge-api/ad-auction/index.md | 2 ++ .../docs/privacy-sandbox/fledge-api/feature-status/index.md | 2 ++ site/en/docs/privacy-sandbox/fledge-api/index.md | 2 ++ .../docs/privacy-sandbox/fledge-api/interest-groups/index.md | 2 ++ site/en/docs/privacy-sandbox/fledge-api/latency/index.md | 2 ++ site/en/docs/privacy-sandbox/fledge-api/opt-out/index.md | 2 ++ site/en/docs/privacy-sandbox/fledge-api/reports/index.md | 2 ++ site/en/docs/privacy-sandbox/fledge-api/troubleshoot/index.md | 2 ++ site/en/docs/privacy-sandbox/fledge-experiment/index.md | 2 ++ site/en/docs/privacy-sandbox/fledge/index.md | 2 ++ 13 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 site/en/_partials/privacy-sandbox/protected-audience-rename-banner.md diff --git a/site/en/_partials/privacy-sandbox/protected-audience-rename-banner.md b/site/en/_partials/privacy-sandbox/protected-audience-rename-banner.md new file mode 100644 index 000000000..87ee2e443 --- /dev/null +++ b/site/en/_partials/privacy-sandbox/protected-audience-rename-banner.md @@ -0,0 +1,3 @@ +{% Aside 'update' %} +FLEDGE has been renamed to Protected Audience API. To learn more about the name change, see the [blog post](https://privacysandbox.com/intl/en_us/news/protected-audience-api-our-new-name-for-fledge). +{% endAside %} diff --git a/site/en/blog/bidding-and-auction-services-availability/index.md b/site/en/blog/bidding-and-auction-services-availability/index.md index b89cded3a..1ab05138d 100644 --- a/site/en/blog/bidding-and-auction-services-availability/index.md +++ b/site/en/blog/bidding-and-auction-services-availability/index.md @@ -12,6 +12,8 @@ tags: - privacy --- +{% Partial 'privacy-sandbox/protected-audience-rename-banner.njk' %} + As FLEDGE adoption continues to grow and scale, we recently launched a collection of new optimizations to help improve on-device auction latency. In addition to these improvements, we will be expanding support for the [Bidding and Auction services](https://github.com/privacysandbox/fledge-docs/blob/main/bidding_auction_services_api.md) to the web platform. The Bidding and Auction services integrate with existing FLEDGE designs and offload bid computation and scoring to a cloud-based trusted execution environment. This was proposed back in 2022 and, after careful consideration, both Chrome and Android plan to provide support for Bidding and Auction services. @@ -54,4 +56,4 @@ To learn more about these services and Privacy Sandbox proposals: * [Chrome's Privacy Sandbox Developer Support repository](https://github.com/GoogleChromeLabs/privacy-sandbox-dev-support) * [Privacy Sandbox on Android issue tracker](https://issuetracker.google.com/issues/new?component=1116743&template=1642575) * **Chrome:** Learn more about the [FLEDGE API on Chrome](/docs/privacy-sandbox/fledge/) and participate in the [origin trial](/docs/privacy-sandbox/unified-origin-trial/). -* **Android:** Read the [FLEDGE on Android design proposal](https://developer.android.com/design-for-safety/privacy-sandbox/fledge) and learn more about how to [build FLEDGE](https://developer.android.com/design-for-safety/privacy-sandbox/guides/fledge) in your Android projects. \ No newline at end of file +* **Android:** Read the [FLEDGE on Android design proposal](https://developer.android.com/design-for-safety/privacy-sandbox/fledge) and learn more about how to [build FLEDGE](https://developer.android.com/design-for-safety/privacy-sandbox/guides/fledge) in your Android projects. diff --git a/site/en/blog/fledge-service-overview/index.md b/site/en/blog/fledge-service-overview/index.md index c526e9059..0b8369ef6 100644 --- a/site/en/blog/fledge-service-overview/index.md +++ b/site/en/blog/fledge-service-overview/index.md @@ -18,6 +18,8 @@ tags: .type figcaption {text-align:left;} +{% Partial 'privacy-sandbox/protected-audience-rename-banner.njk' %} + FLEDGE ([Android](https://developer.android.com/design-for-safety/ads/fledge), [Chrome](/docs/privacy-sandbox/fledge/#overview)) is a Privacy Sandbox proposal to let marketers target ads to custom audiences, based on audience members' diff --git a/site/en/docs/privacy-sandbox/fledge-api/ad-auction/index.md b/site/en/docs/privacy-sandbox/fledge-api/ad-auction/index.md index cfda447dd..7ad91a83d 100644 --- a/site/en/docs/privacy-sandbox/fledge-api/ad-auction/index.md +++ b/site/en/docs/privacy-sandbox/fledge-api/ad-auction/index.md @@ -11,6 +11,8 @@ authors: - alexandrawhite --- +{% Partial 'privacy-sandbox/protected-audience-rename-banner.njk' %} + In this article, you'll find a technical reference for the ad auction, as used in the current iteration of the experimental FLEDGE API. Read the [developer guide](/docs/privacy-sandbox/fledge-api) for the full life diff --git a/site/en/docs/privacy-sandbox/fledge-api/feature-status/index.md b/site/en/docs/privacy-sandbox/fledge-api/feature-status/index.md index cf86b0f5c..3e79d802b 100644 --- a/site/en/docs/privacy-sandbox/fledge-api/feature-status/index.md +++ b/site/en/docs/privacy-sandbox/fledge-api/feature-status/index.md @@ -14,6 +14,8 @@ authors: - kevinkiklee --- +{% Partial 'privacy-sandbox/protected-audience-rename-banner.njk' %} + As we move [FLEDGE](/docs/privacy-sandbox/fledge/) closer to general availability and approach third-party cookie deprecation in Chrome, you may be wondering about the availability of FLEDGE services and features. Here you'll diff --git a/site/en/docs/privacy-sandbox/fledge-api/index.md b/site/en/docs/privacy-sandbox/fledge-api/index.md index 695d9e827..39dee9af0 100644 --- a/site/en/docs/privacy-sandbox/fledge-api/index.md +++ b/site/en/docs/privacy-sandbox/fledge-api/index.md @@ -15,6 +15,8 @@ authors: - kevinkiklee --- +{% Partial 'privacy-sandbox/protected-audience-rename-banner.njk' %} + For those new to FLEDGE, read the [FLEDGE overview](/docs/privacy-sandbox/fledge) for a high-level explanation of the proposal. diff --git a/site/en/docs/privacy-sandbox/fledge-api/interest-groups/index.md b/site/en/docs/privacy-sandbox/fledge-api/interest-groups/index.md index 88bd7a0fa..70afd9271 100644 --- a/site/en/docs/privacy-sandbox/fledge-api/interest-groups/index.md +++ b/site/en/docs/privacy-sandbox/fledge-api/interest-groups/index.md @@ -13,6 +13,8 @@ authors: - alexandrawhite --- +{% Partial 'privacy-sandbox/protected-audience-rename-banner.njk' %} + In this article, you'll find a technical reference for interest groups, as used in the current iteration of the experimental FLEDGE API. diff --git a/site/en/docs/privacy-sandbox/fledge-api/latency/index.md b/site/en/docs/privacy-sandbox/fledge-api/latency/index.md index e7128a256..e42937fd3 100644 --- a/site/en/docs/privacy-sandbox/fledge-api/latency/index.md +++ b/site/en/docs/privacy-sandbox/fledge-api/latency/index.md @@ -11,6 +11,8 @@ authors: - pauljensen --- +{% Partial 'privacy-sandbox/protected-audience-rename-banner.njk' %} + It's in everyone's best interest to make sure FLEDGE operates efficiently. * People browsing the web want sites to load quickly. This means developers diff --git a/site/en/docs/privacy-sandbox/fledge-api/opt-out/index.md b/site/en/docs/privacy-sandbox/fledge-api/opt-out/index.md index 1309e575f..e51dc008b 100644 --- a/site/en/docs/privacy-sandbox/fledge-api/opt-out/index.md +++ b/site/en/docs/privacy-sandbox/fledge-api/opt-out/index.md @@ -11,6 +11,8 @@ authors: - alexandrawhite --- +{% Partial 'privacy-sandbox/protected-audience-rename-banner.njk' %} + You can block access to the FLEDGE API, as a [site owner](#opt-out-site) or as an [individual user](#opt-out-user). ## Site owners {: #opt-out-site} diff --git a/site/en/docs/privacy-sandbox/fledge-api/reports/index.md b/site/en/docs/privacy-sandbox/fledge-api/reports/index.md index b6f9c4efc..876917f39 100644 --- a/site/en/docs/privacy-sandbox/fledge-api/reports/index.md +++ b/site/en/docs/privacy-sandbox/fledge-api/reports/index.md @@ -11,6 +11,8 @@ authors: - alexandrawhite --- +{% Partial 'privacy-sandbox/protected-audience-rename-banner.njk' %} + In this article, you'll find a technical reference for generating reports for FLEDGE auction wins, as used in the current iteration of the experimental FLEDGE API. diff --git a/site/en/docs/privacy-sandbox/fledge-api/troubleshoot/index.md b/site/en/docs/privacy-sandbox/fledge-api/troubleshoot/index.md index 737295341..ae140c961 100644 --- a/site/en/docs/privacy-sandbox/fledge-api/troubleshoot/index.md +++ b/site/en/docs/privacy-sandbox/fledge-api/troubleshoot/index.md @@ -11,6 +11,8 @@ authors: - alexandrawhite --- +{% Partial 'privacy-sandbox/protected-audience-rename-banner.njk' %} + From Chrome Canary 98.0.4718.0, it's possible to debug FLEDGE and FLEDGE worklets in Chrome DevTools. diff --git a/site/en/docs/privacy-sandbox/fledge-experiment/index.md b/site/en/docs/privacy-sandbox/fledge-experiment/index.md index 5683d5e64..08f798f49 100644 --- a/site/en/docs/privacy-sandbox/fledge-experiment/index.md +++ b/site/en/docs/privacy-sandbox/fledge-experiment/index.md @@ -11,6 +11,8 @@ authors: - samdutton --- +{% Partial 'privacy-sandbox/protected-audience-rename-banner.njk' %} + ## Learn the essentials * If you're a developer or software engineer, the [FLEDGE API Developer Guide](/blog/fledge-api) diff --git a/site/en/docs/privacy-sandbox/fledge/index.md b/site/en/docs/privacy-sandbox/fledge/index.md index 6e1aac724..86b473e11 100644 --- a/site/en/docs/privacy-sandbox/fledge/index.md +++ b/site/en/docs/privacy-sandbox/fledge/index.md @@ -15,6 +15,8 @@ authors: - kevinkiklee --- +{% Partial 'privacy-sandbox/protected-audience-rename-banner.njk' %} + {% YouTube id='HkvmYKqnytw' %} From 74db53f237963855fcb656d8290987b1715fd935 Mon Sep 17 00:00:00 2001 From: Maya Janthong <45324326+mamieorine@users.noreply.github.com> Date: Tue, 18 Apr 2023 11:19:44 +0100 Subject: [PATCH 048/982] fix: the alignment of the social media icons on the author page (#6036) --- site/_includes/icons/rss-author.svg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/_includes/icons/rss-author.svg b/site/_includes/icons/rss-author.svg index 5dc3a30e2..50fb51855 100644 --- a/site/_includes/icons/rss-author.svg +++ b/site/_includes/icons/rss-author.svg @@ -1,3 +1,3 @@ - + From 6309070ab675f783135ffb345797ecdad1235355 Mon Sep 17 00:00:00 2001 From: Jake Archibald Date: Tue, 18 Apr 2023 13:44:16 +0100 Subject: [PATCH 049/982] Reverting https://github.com/GoogleChrome/developer.chrome.com/pull/3503 (#6037) This change never happened. --- site/en/blog/timer-throttling-in-chrome-88/index.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/site/en/blog/timer-throttling-in-chrome-88/index.md b/site/en/blog/timer-throttling-in-chrome-88/index.md index 70b4c5496..f1018d0de 100644 --- a/site/en/blog/timer-throttling-in-chrome-88/index.md +++ b/site/en/blog/timer-throttling-in-chrome-88/index.md @@ -7,9 +7,9 @@ description: > Intensive throttling takes effect when the page has been hidden for more than 5 minutes, the page has been silent for at least 30 seconds, WebRTC is not in use, and the chain of timers is - 100 or greater. + 5 or greater. date: 2021-01-18 -updated: 2022-08-30 +updated: 2023-04-18 hero: image/CZmpGM8Eo1dFe0KNhEO9SGO8Ok23/5diIn5KBi44iwy3o6GRi.jpg alt: A collection of broken clocks --- @@ -82,7 +82,7 @@ This happens to timers that are scheduled when _any_ of the following is true: sound-making APIs, but a silent audio track doesn't count. The timer isn't throttled, unless the requested timeout is less than 4ms, and -the chain count is 100 or greater, in which case the timeout is set to 4ms. This +the chain count is 5 or greater, in which case the timeout is set to 4ms. This isn't new; browsers have done this for many years. ### Throttling @@ -90,7 +90,7 @@ isn't new; browsers have done this for many years. This happens to timers that are scheduled when _minimal throttling_ doesn't apply, and _any_ of the following is true: -- The _chain count_ is less than 100. +- The _chain count_ is less than 5. - The page has been _hidden_ for less than 5 minutes. - WebRTC is in use. Specifically, there's an `RTCPeerConnection` with an 'open' `RTCDataChannel` or a 'live' `MediaStreamTrack`. @@ -107,7 +107,7 @@ scheduled when none of the _minimal throttling_ or _throttling_ conditions apply, and _all_ of the following conditions are true: - The page has been _hidden_ for more than 5 minutes. -- The _chain count_ is 100 or greater. +- The _chain count_ is 5 or greater. - The page has been silent for at least 30 seconds. - WebRTC is not in use. From afa9970f782d6eb24d7df11bb5a00bc08610756f Mon Sep 17 00:00:00 2001 From: Barry Pollard Date: Tue, 18 Apr 2023 14:55:24 +0100 Subject: [PATCH 050/982] Misc updated to Prerender docs (#6004) * Misc updates to Prerender post * Linting * Typos * Review feedback * Add link to bug --- site/en/blog/prerender-pages/index.md | 63 +++++++++++++++++++++------ 1 file changed, 49 insertions(+), 14 deletions(-) diff --git a/site/en/blog/prerender-pages/index.md b/site/en/blog/prerender-pages/index.md index cf800fa0c..747997a32 100644 --- a/site/en/blog/prerender-pages/index.md +++ b/site/en/blog/prerender-pages/index.md @@ -7,7 +7,7 @@ description: | authors: - tunetheweb date: 2022-12-02 -updated: 2023-01-06 +updated: 2023-04-18 hero: image/W3z1f5ZkBJSgL1V1IfloTIctbIF3/eohdiqaZlxnWen7TT66M.jpg alt: City road at dusk with a long exposure of car lights giving impression of speed tags: @@ -86,7 +86,7 @@ Chrome will continually update its predictors based on your typing and selection - For a greater than 50% confidence level (shown in amber), Chrome proactively preconnects to the domain, but does not prerender the page. - For a greater than 80% confidence level (shown in green), Chrome will prerender the URL. -### Using the Speculation Rules API to prerender pages +## The Speculation Rules API For the third prerender option, web developers can insert JSON instructions onto their pages to inform the browser about which URLs to prerender: @@ -103,20 +103,35 @@ For the third prerender option, web developers can insert JSON instructions onto ``` -The Speculation Rules API is planned to be expanded beyond this simple example with the addition of prefetch, [scores](https://github.com/WICG/nav-speculation/blob/main/triggers.md#scores) (for example, the likelihood of a navigation), and syntax to implement [document rules](https://github.com/WICG/nav-speculation/blob/main/triggers.md#document-rules) instead of `list` rules (for example, matching `href` patterns on the page), which can be combined to only prerender links on mouse down, for example. +Speculation rules can also be used to just prefetch pages, without a full prerender. This can often be a good first step on the road to prerendering: -For now, only the above syntax is supported in Chrome, which is a simple list of urls to prerender. +```html + +``` + +{% Aside %} +Unlike the older `` resource hint which just prefetched to the HTTP cache, documents loaded via speculation rules are processed in the same way that navigations are (but then not rendered) and are held in memory so will be available quicker to the browser once needed. Using speculation rules for prefetches will also allow use of [future enhancements](#speculation-rules-restrictions-and-future-enhancements) as they are added to the API. -For the initial launch in Chrome 108, prerender is restricted to same-origin pages, opened within the same tab. Chrome 109 plans expand this to allow [prerendering same-site cross-origin pages](https://chromestatus.com/feature/4899735257743360) (for example, `https://a.example.com` could prerender a page on `https://b.example.com`, where the other site has opted in to same-site, cross-origin prerendering). Future versions may also [enable prerendering in new tabs](https://bugs.chromium.org/p/chromium/issues/detail?id=1350676). +[Only Chromium-based browsers support document prefetches](https://github.com/whatwg/html/issues/6723) via ``, and given the above, it is recommended to use speculation rules for these going forward, with `` only used for prefetching subresources. +{% endAside %} Speculation rules can be: * Statically included in the page's HTML. For example a news media site, or a blog may prerender the newest article, if that is often the next navigation for a large proportion of users. -* Dynamically inserted into the page by JavaScript. This could be based on application logic, personalized to the user, or on certain user actions such as hovering over, or clicking down on a link—as many libraries have done in the past with `preconnect`, `prefetch`, or the older NoState Prefetch `prerender`. Those favoring dynamic insertion, are recommended to keep an eye on Speculation Rules support, as the document rules may make allow the browser to handle many of your use cases as this is introduced in the future. +* Dynamically inserted into the page by JavaScript. This could be based on application logic, personalized to the user, or on certain user actions such as hovering over, or clicking down on a link—as many libraries have done in the past with `preconnect`, `prefetch`, or the older NoState Prefetch `prerender`. Those favoring dynamic insertion, are recommended to keep an eye on speculation rules support, as the document rules may make allow the browser to handle many of your use cases as this is introduced in the future. Speculation rules can be added in either the `` or the `` of in the main frame. Speculation rules in subframes are not acted upon, and speculation rules in prerendered pages are only acted upon once that page is activated. -#### Multiple Speculation Rules +### Multiple speculation rules Multiple speculation rules can also be added to the same page, and they append to the existing rules. Therefore, the following different ways all result in both `one.html` and `two.html` prerendering: @@ -179,7 +194,25 @@ Multiple speculation rules can also be added to the same page, and they append t ``` -#### Detecting of Speculation Rules API support +### Speculation rules restrictions and future enhancements + +At present, speculation rules are restricted to pages opened within the same tab, but we are working to reduce that restrictions. By default prerender is restricted to same-origin pages. + +{% Aside 'update' %} +[Prerendering same-site cross-origin pages](https://chromestatus.com/feature/4899735257743360) (for example, `https://a.example.com` could prerender a page on `https://b.example.com`) is supported from Chrome 109. + +To use this the prerendered page (`https://b.example.com` in this example) needs to opt-in by including a `Supports-Loading-Mode: credentialed-prerender` HTTP header or Chrome will cancel the prerender. +{% endAside %} + +Future versions may also [allow prerender for cross-origin pages](https://bugs.chromium.org/p/chromium/issues/detail?id=1176054) (where the site opts in with a similar `Supports-Loading-Mode: uncredentialed-prerender` HTTP header), and [enable prerendering in new tabs](https://bugs.chromium.org/p/chromium/issues/detail?id=1350676). + +The Speculation Rules API is planned to be expanded beyond this simple example with the addition of [scores](https://github.com/WICG/nav-speculation/blob/main/triggers.md#scores) (for example, the likelihood of a navigation), and syntax to implement [document rules](https://github.com/WICG/nav-speculation/blob/main/triggers.md#document-rules) instead of `list` rules (for example, matching `href` patterns on the page), which can be combined to only prerender links on mouse down, for example. + +{% Aside 'update' %} +A number of [experiments](https://github.com/WICG/nav-speculation/blob/main/chrome-2023q1-experiment-overview.md) are currently being run in Chrome for some of these additional features. Sites can opt-in to via an [origin trial](/origintrials/#/view_trial/705939241590325249) to try out—and give feedback—on these potential future additions. [Learn more about origin trials](/docs/web-platform/origin-trials/). +{% endAside %} + +### Detecting of Speculation Rules API support You can feature detect Speculation Rules API support with standard HTML checks: @@ -189,7 +222,7 @@ if (HTMLScriptElement.supports && HTMLScriptElement.supports('speculationrules') } ``` -#### Adding Speculation Rules dynamically through JavaScript +### Adding speculation rules dynamically through JavaScript Below is a simple example of adding a `prerender` speculation rule with JavaScript: @@ -214,13 +247,15 @@ if (HTMLScriptElement.supports && You can view a demo of Speculation Rules API prerendering, using JavaScript insertion, on [this demo page](https://prerender-demos.glitch.me/). -#### Cancelling Speculation Rules +### Cancelling speculation rules + +Removing speculation rules will result in the prerender being cancelled but, by the time this has happened, resources will likely have already been spent to initiate the prerender, so it is recommended not to prerender if there is a likelihood of needing to cancel the prerender. -Removing Speculation Rules will result in the prerender being cancelled but, by the time this has happened, resources will likely have already been spent to initiate the prerender, so it is recommended not to prerender if there is a likelihood of needing to cancel the prerender. +### Speculation rules and Content Security Policy -#### Speculation Rules and Content Security Policy +As speculation rules use a ` diff --git a/site/_includes/layouts/blog-landing.njk b/site/_includes/layouts/blog-landing.njk index 74de247ac..576462fa7 100644 --- a/site/_includes/layouts/blog-landing.njk +++ b/site/_includes/layouts/blog-landing.njk @@ -1,5 +1,10 @@ {% extends "layouts/base.njk" %} + +{% block css %} +{% InlineCss '/css/overview.css' %} +{% endblock %} + {% from 'macros/cards/blog-card.njk' import blogCard with context %} {% block title_bar %} diff --git a/site/_includes/layouts/blog-post.njk b/site/_includes/layouts/blog-post.njk index d30310456..3e8ce1a60 100644 --- a/site/_includes/layouts/blog-post.njk +++ b/site/_includes/layouts/blog-post.njk @@ -1,5 +1,9 @@ {% extends "layouts/base.njk" %} +{% block css %} +{% InlineCss '/css/single-post.css' %} +{% endblock %} + {% block title_bar %} {% set sharingEnabled = true %} {% include 'partials/breadcrumbs.njk' %} diff --git a/site/_includes/layouts/chrome-100.njk b/site/_includes/layouts/chrome-100.njk index 931f2d68c..f5e939cb0 100644 --- a/site/_includes/layouts/chrome-100.njk +++ b/site/_includes/layouts/chrome-100.njk @@ -1,6 +1,7 @@ {% extends "layouts/base.njk" %} {% block css %} +{% InlineCss '/css/single-post.css' %} {% InlineCss '/css/chrome-main.css' %} {% endblock %} diff --git a/site/_includes/layouts/collection-in-docs.njk b/site/_includes/layouts/collection-in-docs.njk index d4be02342..7a86de80f 100644 --- a/site/_includes/layouts/collection-in-docs.njk +++ b/site/_includes/layouts/collection-in-docs.njk @@ -1,5 +1,10 @@ {% extends "layouts/base.njk" %} + +{% block css %} +{% InlineCss '/css/single-post.css' %} +{% endblock %} + {% from 'macros/cards/hero-card.njk' import heroCard with context %} {% from 'macros/icon.njk' import icon with context %} {% from 'macros/cards/blog-card.njk' import blogCard with context %} diff --git a/site/_includes/layouts/collection-landing.njk b/site/_includes/layouts/collection-landing.njk index 049686d8d..a20c959bc 100644 --- a/site/_includes/layouts/collection-landing.njk +++ b/site/_includes/layouts/collection-landing.njk @@ -1,5 +1,10 @@ {% extends "layouts/base.njk" %} + +{% block css %} +{% InlineCss '/css/single-post.css' %} +{% endblock %} + {% from 'macros/cards/hero-card.njk' import heroCard with context %} {% from 'macros/icon.njk' import icon with context %} {% from 'macros/cards/blog-card.njk' import blogCard with context %} diff --git a/site/_includes/layouts/doc-post.njk b/site/_includes/layouts/doc-post.njk index c25eacc0b..08721ca0f 100644 --- a/site/_includes/layouts/doc-post.njk +++ b/site/_includes/layouts/doc-post.njk @@ -1,5 +1,10 @@ {% extends "layouts/base.njk" %} + +{% block css %} +{% InlineCss '/css/single-post.css' %} +{% endblock %} + {% block title_bar %} {% set sharingEnabled = true %} {% include 'partials/breadcrumbs.njk' %} diff --git a/site/_includes/layouts/docs-landing.njk b/site/_includes/layouts/docs-landing.njk index 5aaa89a55..63d582fd0 100644 --- a/site/_includes/layouts/docs-landing.njk +++ b/site/_includes/layouts/docs-landing.njk @@ -6,6 +6,10 @@ {% extends 'layouts/base.njk' %} +{% block css %} +{% InlineCss '/css/overview.css' %} +{% endblock %} + {% block title_bar %} {% set headingBreadcrumb = true %} {% include 'partials/breadcrumbs.njk' %} diff --git a/site/_includes/layouts/error.njk b/site/_includes/layouts/error.njk index bdc64a200..3e0f86212 100644 --- a/site/_includes/layouts/error.njk +++ b/site/_includes/layouts/error.njk @@ -1,5 +1,10 @@ {% extends "layouts/base.njk" %} + +{% block css %} +{% InlineCss '/css/single-post.css' %} +{% endblock %} + {% block content %}
{% Img diff --git a/site/_includes/layouts/events.njk b/site/_includes/layouts/events.njk index 4b40f7d53..8a0f77aa9 100644 --- a/site/_includes/layouts/events.njk +++ b/site/_includes/layouts/events.njk @@ -1,7 +1,7 @@ {% extends "layouts/base.njk" %} {% block css %} - {% InlineCss '/css/events-main.css' %} + {% InlineCss '/css/meet-the-team.css' %} {% endblock %} {% block content %} diff --git a/site/_includes/layouts/generic-reference-landing.njk b/site/_includes/layouts/generic-reference-landing.njk index 669a54f3d..f772d4287 100644 --- a/site/_includes/layouts/generic-reference-landing.njk +++ b/site/_includes/layouts/generic-reference-landing.njk @@ -1,5 +1,9 @@ {% extends "layouts/base.njk" %} +{% block css %} +{% InlineCss '/css/single-post.css' %} +{% endblock %} + {# Update "content" with additional headings and so forth, so we can pass it through the toc filter. #} {% set content %} diff --git a/site/_includes/layouts/home.njk b/site/_includes/layouts/home.njk index 336f9878b..c856afe68 100644 --- a/site/_includes/layouts/home.njk +++ b/site/_includes/layouts/home.njk @@ -1,5 +1,9 @@ {% extends "layouts/base.njk" %} +{% block css %} +{% InlineCss '/css/home.css' %} +{% endblock %} + {% from 'macros/cards/hero-card.njk' import heroCard with context %} {% from 'macros/cards/featured-post-card.njk' import featuredPostCard with context %} {% from 'macros/cards/featured-docs-card.njk' import featuredDocsCard with context %} diff --git a/site/_includes/layouts/landing.njk b/site/_includes/layouts/landing.njk index 389ca5e80..b0e89ddf7 100644 --- a/site/_includes/layouts/landing.njk +++ b/site/_includes/layouts/landing.njk @@ -1,5 +1,9 @@ {% extends "layouts/base.njk" %} +{% block css %} +{% InlineCss '/css/landing.css' %} +{% endblock %} + {% block content %}
{{ content | safe }} diff --git a/site/_includes/layouts/namespace-reference.njk b/site/_includes/layouts/namespace-reference.njk index 75f5a81ec..e46b683b8 100644 --- a/site/_includes/layouts/namespace-reference.njk +++ b/site/_includes/layouts/namespace-reference.njk @@ -4,6 +4,11 @@ {% extends "layouts/base.njk" %} + +{% block css %} +{% InlineCss '/css/main.css' %} +{% endblock %} + {% block title_bar %} {% include 'partials/breadcrumbs.njk' %} {% endblock %} diff --git a/site/_includes/layouts/native-client-post.njk b/site/_includes/layouts/native-client-post.njk index d1e6a7e0b..feab13d84 100644 --- a/site/_includes/layouts/native-client-post.njk +++ b/site/_includes/layouts/native-client-post.njk @@ -1,5 +1,6 @@ {% extends "layouts/doc-post.njk" %} + {# Native Client docs rely on the old prettify.js project for syntax highlighting. diff --git a/site/_includes/layouts/native-client-reference.njk b/site/_includes/layouts/native-client-reference.njk index eaf06457b..9207207e0 100644 --- a/site/_includes/layouts/native-client-reference.njk +++ b/site/_includes/layouts/native-client-reference.njk @@ -1,5 +1,10 @@ {% extends "layouts/base.njk" %} + +{% block css %} +{% InlineCss '/css/main.css' %} +{% endblock %} + {# Native Client docs rely on the old prettify.js project for syntax highlighting. diff --git a/site/_includes/layouts/project-landing.njk b/site/_includes/layouts/project-landing.njk index 20f55630a..db82d34fa 100644 --- a/site/_includes/layouts/project-landing.njk +++ b/site/_includes/layouts/project-landing.njk @@ -7,6 +7,11 @@ {% extends "layouts/base.njk" %} + +{% block css %} +{% InlineCss '/css/overview.css' %} +{% endblock %} + {% block title_bar %} {% include 'partials/breadcrumbs.njk' %} {% endblock %} diff --git a/site/_includes/layouts/reference-landing.njk b/site/_includes/layouts/reference-landing.njk index 933e1c34d..3c3f9f877 100644 --- a/site/_includes/layouts/reference-landing.njk +++ b/site/_includes/layouts/reference-landing.njk @@ -1,5 +1,10 @@ {% extends "layouts/base.njk" %} + +{% block css %} +{% InlineCss '/css/single-post.css' %} +{% endblock %} + {# Update "content" with additional headings and so forth, so we can pass it through the toc filter. #} {% set content %} diff --git a/site/_includes/layouts/releases-landing.njk b/site/_includes/layouts/releases-landing.njk deleted file mode 100644 index 3425f7eb2..000000000 --- a/site/_includes/layouts/releases-landing.njk +++ /dev/null @@ -1,20 +0,0 @@ -{% extends "layouts/base.njk" %} - -{% block content %} - {% for key, title in i18n.channels %} - - {% set release = chrome.channels[key] %} - {% if release %} - -

{{ title }}

- -
-
{{ i18n.release_title }}
-
{{ release.mstone }}
-
{{ i18n.stabledate_title }}
-
{{ release.stableDate.toLocaleDateString(locale, {day: 'numeric', month: 'long', year: 'numeric'}) }}
-
- - {% endif %} - {% endfor %} -{% endblock %} \ No newline at end of file diff --git a/site/_includes/layouts/tag-landing.njk b/site/_includes/layouts/tag-landing.njk index 148cf0b29..b66bf23e5 100644 --- a/site/_includes/layouts/tag-landing.njk +++ b/site/_includes/layouts/tag-landing.njk @@ -2,6 +2,11 @@ {% extends "layouts/base.njk" %} + +{% block css %} +{% InlineCss '/css/overview.css' %} +{% endblock %} + {% block title_bar %} {% set headingBreadcrumb = true %} {% include 'partials/breadcrumbs-tag.njk' %} diff --git a/site/_includes/layouts/tags-landing.njk b/site/_includes/layouts/tags-landing.njk index a030c877c..576831d6a 100644 --- a/site/_includes/layouts/tags-landing.njk +++ b/site/_includes/layouts/tags-landing.njk @@ -1,5 +1,10 @@ {% extends "layouts/base.njk" %} + +{% block css %} +{% InlineCss '/css/overview.css' %} +{% endblock %} + {% block title_bar %} {% set headingBreadcrumb = true %} {% include 'partials/breadcrumbs.njk' %} diff --git a/site/_scss/_global.scss b/site/_scss/_global.scss index 27d42f768..b07581cb8 100644 --- a/site/_scss/_global.scss +++ b/site/_scss/_global.scss @@ -1,4 +1,33 @@ // Global styles start +@import 'globals/functions'; +@import 'globals/colors'; +@import 'globals/vars'; +@import 'globals/mixins'; +@import 'globals/gorko'; +@import 'globals/extends'; +@import 'globals/fonts'; +@import 'globals/theme'; +@import 'globals/reset'; +@import 'globals/typography'; + +@import 'blocks/stack'; +@import 'blocks/search-box'; +@import 'blocks/logo'; +@import 'blocks/top-nav'; +@import 'blocks/footer'; +@import 'blocks/scaffold'; +@import 'blocks/navigation-rail'; +@import 'blocks/announcement-banner'; +@import 'blocks/cookie-banner'; +@import 'blocks/banner'; +@import 'blocks/button'; +@import 'blocks/link'; +@import 'blocks/icon'; +@import 'blocks/cluster'; +@import 'blocks/select'; +@import 'blocks/side-nav'; +@import 'blocks/skip-link'; + :root { --flow-space: #{get-size(500)}; } diff --git a/site/_scss/chrome-main.scss b/site/_scss/chrome-main.scss deleted file mode 100644 index f9f64833f..000000000 --- a/site/_scss/chrome-main.scss +++ /dev/null @@ -1,31 +0,0 @@ -// Globals -@import 'globals/functions'; -@import 'globals/colors'; -@import 'globals/vars'; -@import 'globals/mixins'; -@import 'globals/gorko'; -@import 'globals/extends'; - -@import 'fonts'; -@import 'theme'; -@import 'reset'; -@import 'global'; -@import 'typography'; - -//blocks -@import 'blocks/hero-section'; -@import 'blocks/card-section'; -@import 'blocks/footer-section'; -@import 'blocks/like-icon'; - -// Utilities -@import 'utilities/center-margin'; -@import 'utilities/center-images'; -@import 'utilities/floats'; -@import 'utilities/elevation'; -@import 'utilities/hairline'; -@import 'utilities/colors'; -@import 'utilities/scrollbars'; -@import 'utilities/surface'; -@import 'utilities/visually-hidden'; -@import 'utilities/wrapper'; diff --git a/site/_scss/_fonts.scss b/site/_scss/globals/_fonts.scss similarity index 100% rename from site/_scss/_fonts.scss rename to site/_scss/globals/_fonts.scss diff --git a/site/_scss/_reset.scss b/site/_scss/globals/_reset.scss similarity index 100% rename from site/_scss/_reset.scss rename to site/_scss/globals/_reset.scss diff --git a/site/_scss/_theme.scss b/site/_scss/globals/_theme.scss similarity index 100% rename from site/_scss/_theme.scss rename to site/_scss/globals/_theme.scss diff --git a/site/_scss/_typography.scss b/site/_scss/globals/_typography.scss similarity index 100% rename from site/_scss/_typography.scss rename to site/_scss/globals/_typography.scss diff --git a/site/_scss/layouts/chrome-100.scss b/site/_scss/layouts/chrome-100.scss new file mode 100644 index 000000000..ca6d5d2cd --- /dev/null +++ b/site/_scss/layouts/chrome-100.scss @@ -0,0 +1,20 @@ +// Globals +@import '../global'; + +//blocks +@import '../blocks/hero-section'; +@import '../blocks/card-section'; +@import '../blocks/footer-section'; +@import '../blocks/like-icon'; + +// Utilities +@import '../utilities/center-margin'; +@import '../utilities/center-images'; +@import '../utilities/floats'; +@import '../utilities/elevation'; +@import '../utilities/hairline'; +@import '../utilities/colors'; +@import '../utilities/scrollbars'; +@import '../utilities/surface'; +@import '../utilities/visually-hidden'; +@import '../utilities/wrapper'; diff --git a/site/_scss/layouts/fugu-showcase.scss b/site/_scss/layouts/fugu-showcase.scss new file mode 100644 index 000000000..6d4095dc5 --- /dev/null +++ b/site/_scss/layouts/fugu-showcase.scss @@ -0,0 +1,14 @@ +// Globals +@import '../global'; + +@import '../blocks/fugu-showcase'; +@import '../blocks/enhanced-select'; +@import '../blocks/hero-card'; +@import '../blocks/blog-card'; +@import '../blocks/blog-grid'; +@import '../blocks/tag-pill'; + +@import '../utilities/hairline'; +@import '../utilities/colors'; +@import '../utilities/surface'; +@import '../utilities/visually-hidden'; diff --git a/site/_scss/layouts/home.scss b/site/_scss/layouts/home.scss new file mode 100644 index 000000000..8f2ee5b3f --- /dev/null +++ b/site/_scss/layouts/home.scss @@ -0,0 +1,20 @@ +// Globals +@import '../global'; + +//Home Specific +@import '../blocks/hero-card'; +@import '../blocks/featured-card'; +@import '../blocks/home-container'; +@import '../blocks/card-authors'; +@import '../blocks/project-icon'; +@import '../blocks/project-card'; +@import '../blocks/card-title-bar'; +@import '../blocks/release-card'; +@import '../blocks/tweet-card'; + +// Utilities +@import '../utilities/center-margin'; +@import '../utilities/hairline'; +@import '../utilities/colors'; +@import '../utilities/surface'; +@import '../utilities/visually-hidden'; diff --git a/site/_scss/layouts/landing.scss b/site/_scss/layouts/landing.scss new file mode 100644 index 000000000..fb0024d3b --- /dev/null +++ b/site/_scss/layouts/landing.scss @@ -0,0 +1,17 @@ +// Globals +@import '../global'; + +@import '../blocks/heading-link'; +@import '../blocks/hero-card'; +@import '../blocks/project-icon'; +@import '../blocks/landing-container'; +@import '../blocks/landing-section'; +@import '../blocks/landing-section-expanded'; +@import '../blocks/landing-section-explore'; + +// Utilities +@import '../utilities/colors'; +@import '../utilities/hairline'; +@import '../utilities/surface'; +@import '../utilities/visually-hidden'; +@import '../utilities/wrapper'; diff --git a/site/_scss/layouts/main.scss b/site/_scss/layouts/main.scss new file mode 100644 index 000000000..49ffe7ee3 --- /dev/null +++ b/site/_scss/layouts/main.scss @@ -0,0 +1,87 @@ +// Globals +@import '../global'; + +// Blocks +@import '../blocks/details'; +@import '../blocks/link'; +@import '../blocks/button'; +@import '../blocks/banner'; +@import '../blocks/icon'; +@import '../blocks/like-icon'; +@import '../blocks/table'; +@import '../blocks/code'; +@import '../blocks/scaffold'; +@import '../blocks/stack'; +@import '../blocks/cluster'; +@import '../blocks/breadcrumbs'; +@import '../blocks/top-nav'; +@import '../blocks/navigation-rail'; +@import '../blocks/navigation-tree'; +@import '../blocks/side-nav'; +@import '../blocks/post-authors'; +@import '../blocks/card-authors'; +@import '../blocks/project-icon'; +@import '../blocks/project-hero'; +@import '../blocks/project-sections'; +@import '../blocks/project-grid'; +@import '../blocks/project-card'; +@import '../blocks/native-client'; +@import '../blocks/reference'; +@import '../blocks/code-sections'; +@import '../blocks/aside'; +@import '../blocks/post-banner'; +@import '../blocks/home-container'; +@import '../blocks/blog-grid'; +@import '../blocks/tags-grid'; +@import '../blocks/card-title-bar'; +@import '../blocks/hero-card'; +@import '../blocks/featured-card'; +@import '../blocks/blog-card'; +@import '../blocks/tweet-card'; +@import '../blocks/release-card'; +@import '../blocks/tag-pill'; +@import '../blocks/tag-card'; +@import '../blocks/footer'; +@import '../blocks/toc'; +@import '../blocks/search-box'; +@import '../blocks/youtube'; +@import '../blocks/hero-image'; +@import '../blocks/heading-link'; +@import '../blocks/announcement-banner'; +@import '../blocks/cookie-banner'; +@import '../blocks/columns'; +@import '../blocks/skip-link'; +@import '../blocks/compare'; +@import '../blocks/pagination'; +@import '../blocks/screenshot'; +@import '../blocks/share-button'; +@import '../blocks/stats'; +@import '../blocks/tabs'; +@import '../blocks/select'; +@import '../blocks/logo'; +@import '../blocks/devtools'; +@import '../blocks/select-loader'; +@import '../blocks/social-icon'; +@import '../blocks/figure'; +@import '../blocks/switcher'; +@import '../blocks/landing-section'; +@import '../blocks/landing-section-expanded'; +@import '../blocks/landing-section-explore'; +@import '../blocks/landing-container'; +@import '../blocks/featured-section'; +@import '../blocks/load-more'; +@import '../blocks/fugu-showcase'; +@import '../blocks/enhanced-select'; +@import 'node_modules/webdev-infra/shortcodes/BrowserCompat/styles'; + +// Utilities +@import '../utilities/center-margin'; +@import '../utilities/center-images'; +@import '../utilities/floats'; +@import '../utilities/elevation'; +@import '../utilities/hairline'; +@import '../utilities/colors'; +@import '../utilities/scrollbars'; +@import '../utilities/surface'; +@import '../utilities/visually-hidden'; +@import '../utilities/wrapper'; diff --git a/site/_scss/events-main.scss b/site/_scss/layouts/meet-the-team.scss similarity index 51% rename from site/_scss/events-main.scss rename to site/_scss/layouts/meet-the-team.scss index 45e58f28e..bc2277737 100644 --- a/site/_scss/events-main.scss +++ b/site/_scss/layouts/meet-the-team.scss @@ -1,37 +1,28 @@ // Globals -@import 'globals/functions'; -@import 'globals/colors'; -@import 'globals/vars'; -@import 'globals/mixins'; -@import 'globals/gorko'; -@import 'globals/extends'; - -@import 'fonts'; -@import 'theme'; -@import 'reset'; -@import 'global'; -@import 'typography'; +@import '../global'; //blocks -@import 'blocks/event-card'; -@import 'blocks/events-hero'; -@import 'blocks/events-list'; -@import 'blocks/checkbox-group'; -@import 'blocks/filter-sheet'; -@import 'blocks/enhanced-select'; -@import 'blocks/tag-pill-list'; +@import '../blocks/event-card'; +@import '../blocks/events-hero'; +@import '../blocks/events-list'; +@import '../blocks/checkbox-group'; +@import '../blocks/filter-sheet'; +@import '../blocks/enhanced-select'; +@import '../blocks/tag-pill'; +@import '../blocks/tag-pill-list'; +@import '../blocks/tabs'; // Utilities -@import 'utilities/center-margin'; -@import 'utilities/center-images'; -@import 'utilities/floats'; -@import 'utilities/elevation'; -@import 'utilities/hairline'; -@import 'utilities/colors'; -@import 'utilities/scrollbars'; -@import 'utilities/surface'; -@import 'utilities/visually-hidden'; -@import 'utilities/wrapper'; +@import '../utilities/center-margin'; +@import '../utilities/center-images'; +@import '../utilities/floats'; +@import '../utilities/elevation'; +@import '../utilities/hairline'; +@import '../utilities/colors'; +@import '../utilities/scrollbars'; +@import '../utilities/surface'; +@import '../utilities/visually-hidden'; +@import '../utilities/wrapper'; .events-container { max-width: calc(1290px + 3rem); diff --git a/site/_scss/layouts/overview.scss b/site/_scss/layouts/overview.scss new file mode 100644 index 000000000..589170f33 --- /dev/null +++ b/site/_scss/layouts/overview.scss @@ -0,0 +1,28 @@ +// Globals +@import '../global'; + +@import '../blocks/blog-card'; +@import '../blocks/blog-grid'; +@import '../blocks/breadcrumbs'; +@import '../blocks/card-authors'; +@import '../blocks/heading-link'; +@import '../blocks/pagination'; +@import '../blocks/project-card'; +@import '../blocks/project-grid'; +@import '../blocks/project-hero'; +@import '../blocks/project-icon'; +@import '../blocks/project-sections'; +@import '../blocks/select-loader'; +@import '../blocks/share-button'; +@import '../blocks/social-icon'; +@import '../blocks/tags-grid'; +@import '../blocks/tag-pill'; + +// Utilities +@import '../utilities/center-margin'; +@import '../utilities/center-images'; +@import '../utilities/hairline'; +@import '../utilities/colors'; +@import '../utilities/surface'; +@import '../utilities/visually-hidden'; +@import '../utilities/wrapper'; diff --git a/site/_scss/layouts/single-post.scss b/site/_scss/layouts/single-post.scss new file mode 100644 index 000000000..5b73e322d --- /dev/null +++ b/site/_scss/layouts/single-post.scss @@ -0,0 +1,41 @@ +// Globals +@import '../global'; + +@import '../blocks/aside'; +@import '../blocks/blog-card'; +@import '../blocks/blog-grid'; +@import '../blocks/card-authors'; +@import '../blocks/code'; +@import '../blocks/code-sections'; +@import '../blocks/columns'; +@import '../blocks/compare'; +@import '../blocks/details'; +@import '../blocks/devtools'; +@import '../blocks/figure'; +@import '../blocks/heading-link'; +@import '../blocks/hero-image'; +@import '../blocks/navigation-tree'; +@import '../blocks/pagination'; +@import '../blocks/post-authors'; +@import '../blocks/post-banner'; +@import '../blocks/screenshot'; +@import '../blocks/stats'; +@import '../blocks/switcher'; +@import '../blocks/table'; +@import '../blocks/tabs'; +@import '../blocks/tag-pill'; +@import '../blocks/toc'; +@import '../blocks/youtube'; + +@import 'node_modules/webdev-infra/shortcodes/BrowserCompat/styles'; + +@import '../utilities/center-margin'; +@import '../utilities/center-images'; +@import '../utilities/floats'; +@import '../utilities/elevation'; +@import '../utilities/hairline'; +@import '../utilities/colors'; +@import '../utilities/scrollbars'; +@import '../utilities/surface'; +@import '../utilities/visually-hidden'; +@import '../utilities/wrapper'; diff --git a/site/_scss/layouts/styleguide.scss b/site/_scss/layouts/styleguide.scss new file mode 100644 index 000000000..649474606 --- /dev/null +++ b/site/_scss/layouts/styleguide.scss @@ -0,0 +1,20 @@ +// Globals +@import '../global'; + +// Utilities +@import '../utilities/center-margin'; +@import '../utilities/center-images'; +@import '../utilities/floats'; +@import '../utilities/elevation'; +@import '../utilities/hairline'; +@import '../utilities/colors'; +@import '../utilities/scrollbars'; +@import '../utilities/surface'; +@import '../utilities/visually-hidden'; +@import '../utilities/wrapper'; + +//blocks +@import '../blocks/checkbox-group'; +@import '../blocks/filter-sheet'; +@import '../blocks/enhanced-select'; +@import '../blocks/tag-pill-list'; diff --git a/site/_scss/main.scss b/site/_scss/main.scss deleted file mode 100644 index de2979ee4..000000000 --- a/site/_scss/main.scss +++ /dev/null @@ -1,98 +0,0 @@ -// Globals -@import 'globals/functions'; -@import 'globals/colors'; -@import 'globals/vars'; -@import 'globals/mixins'; -@import 'globals/gorko'; -@import 'globals/extends'; - -@import 'fonts'; -@import 'theme'; -@import 'reset'; -@import 'global'; -@import 'typography'; - -// Blocks -@import 'blocks/details'; -@import 'blocks/link'; -@import 'blocks/button'; -@import 'blocks/banner'; -@import 'blocks/icon'; -@import 'blocks/like-icon'; -@import 'blocks/table'; -@import 'blocks/code'; -@import 'blocks/scaffold'; -@import 'blocks/stack'; -@import 'blocks/cluster'; -@import 'blocks/breadcrumbs'; -@import 'blocks/top-nav'; -@import 'blocks/navigation-rail'; -@import 'blocks/navigation-tree'; -@import 'blocks/side-nav'; -@import 'blocks/post-authors'; -@import 'blocks/card-authors'; -@import 'blocks/project-icon'; -@import 'blocks/project-hero'; -@import 'blocks/project-sections'; -@import 'blocks/project-grid'; -@import 'blocks/project-card'; -@import 'blocks/native-client'; -@import 'blocks/reference'; -@import 'blocks/code-sections'; -@import 'blocks/aside'; -@import 'blocks/post-banner'; -@import 'blocks/home-container'; -@import 'blocks/blog-grid'; -@import 'blocks/tags-grid'; -@import 'blocks/card-title-bar'; -@import 'blocks/hero-card'; -@import 'blocks/featured-card'; -@import 'blocks/blog-card'; -@import 'blocks/tweet-card'; -@import 'blocks/release-card'; -@import 'blocks/tag-pill'; -@import 'blocks/tag-card'; -@import 'blocks/footer'; -@import 'blocks/toc'; -@import 'blocks/search-box'; -@import 'blocks/youtube'; -@import 'blocks/hero-image'; -@import 'blocks/heading-link'; -@import 'blocks/announcement-banner'; -@import 'blocks/cookie-banner'; -@import 'blocks/columns'; -@import 'blocks/skip-link'; -@import 'blocks/compare'; -@import 'blocks/pagination'; -@import 'blocks/screenshot'; -@import 'blocks/share-button'; -@import 'blocks/stats'; -@import 'blocks/tabs'; -@import 'blocks/select'; -@import 'blocks/logo'; -@import 'blocks/devtools'; -@import 'blocks/select-loader'; -@import 'blocks/social-icon'; -@import 'blocks/figure'; -@import 'blocks/switcher'; -@import 'blocks/landing-section'; -@import 'blocks/landing-section-expanded'; -@import 'blocks/landing-section-explore'; -@import 'blocks/landing-container'; -@import 'blocks/featured-section'; -@import 'blocks/load-more'; -@import 'blocks/fugu-showcase'; -@import 'blocks/enhanced-select'; -@import 'node_modules/webdev-infra/shortcodes/BrowserCompat/styles'; - -// Utilities -@import 'utilities/center-margin'; -@import 'utilities/center-images'; -@import 'utilities/floats'; -@import 'utilities/elevation'; -@import 'utilities/hairline'; -@import 'utilities/colors'; -@import 'utilities/scrollbars'; -@import 'utilities/surface'; -@import 'utilities/visually-hidden'; -@import 'utilities/wrapper'; diff --git a/site/_scss/styleguide-main.scss b/site/_scss/styleguide-main.scss deleted file mode 100644 index f998b4f01..000000000 --- a/site/_scss/styleguide-main.scss +++ /dev/null @@ -1,31 +0,0 @@ -// Globals -@import 'globals/functions'; -@import 'globals/colors'; -@import 'globals/vars'; -@import 'globals/mixins'; -@import 'globals/gorko'; -@import 'globals/extends'; - -@import 'fonts'; -@import 'theme'; -@import 'reset'; -@import 'global'; -@import 'typography'; - -// Utilities -@import 'utilities/center-margin'; -@import 'utilities/center-images'; -@import 'utilities/floats'; -@import 'utilities/elevation'; -@import 'utilities/hairline'; -@import 'utilities/colors'; -@import 'utilities/scrollbars'; -@import 'utilities/surface'; -@import 'utilities/visually-hidden'; -@import 'utilities/wrapper'; - -//blocks -@import 'blocks/checkbox-group'; -@import 'blocks/filter-sheet'; -@import 'blocks/enhanced-select'; -@import 'blocks/tag-pill-list'; diff --git a/site/en/docs/handbook/style-guide/index.njk b/site/en/docs/handbook/style-guide/index.njk index 36eb8105c..49e782901 100644 --- a/site/en/docs/handbook/style-guide/index.njk +++ b/site/en/docs/handbook/style-guide/index.njk @@ -11,7 +11,8 @@ banner: {% from 'macros/icon.njk' import icon with context %} {% block css %} -{% InlineCss '/css/styleguide-main.css' %} +{% InlineCss '/css/single-post.css' %} +{% InlineCss '/css/styleguide.css' %} {% endblock %} {% block content %} diff --git a/site/en/fugu-showcase/index.njk b/site/en/fugu-showcase/index.njk index 74a4f7840..0be75b34e 100644 --- a/site/en/fugu-showcase/index.njk +++ b/site/en/fugu-showcase/index.njk @@ -9,6 +9,12 @@ alt: Blowfish swarm swimming in the ocean. --- {% extends "layouts/base.njk" %} + +{% block css %} +{% InlineCss '/css/fugu-showcase.css' %} +{% endblock %} + + {% from 'macros/cards/hero-card.njk' import heroCard with context %} {% from 'macros/icon.njk' import icon with context %} diff --git a/site/en/releases/index.md b/site/en/releases/index.md deleted file mode 100644 index 2b93172ba..000000000 --- a/site/en/releases/index.md +++ /dev/null @@ -1,15 +0,0 @@ ---- -# Remove the permalink when we launch this page -permalink: false -title: 'Releases' -description: '' -layout: 'layouts/releases-landing.njk' -type: landing -i18n: - channels: - stable: Stable - beta: Beta - channel_title: Channel - release_title: Release - stabledate_title: Stable Date ---- \ No newline at end of file diff --git a/site/en/releases/releases.11tydata.js b/site/en/releases/releases.11tydata.js deleted file mode 100644 index 0ce2bdf98..000000000 --- a/site/en/releases/releases.11tydata.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = { - type: 'release', -}; From b37969db3002da540cfef965f43dac411bcb47d5 Mon Sep 17 00:00:00 2001 From: James <42349493+Blazzike@users.noreply.github.com> Date: Thu, 4 May 2023 15:12:00 +0100 Subject: [PATCH 157/982] #3930 - Fix unique redirect handler (#6199) * fix: don't prevent uniqueHandler build due to insertRoot errors, instead print individual errors * feat: rewrite chromeX tags to chrome-x to automatically avoid unintentional tag archive generation * refactor: remove commented debug code --- server/handlers/redirects/uniqueRedirect.js | 7 ++++++- site/_collections/tags.js | 14 +++++++++++++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/server/handlers/redirects/uniqueRedirect.js b/server/handlers/redirects/uniqueRedirect.js index 78c064b8e..cdcd115c2 100644 --- a/server/handlers/redirects/uniqueRedirect.js +++ b/server/handlers/redirects/uniqueRedirect.js @@ -231,7 +231,12 @@ async function buildMatcher(source = 'dist/', avoidDirs = defaultAvoidDirs) { if (scope === path.dirname(p)) { force = true; } - insertRoot(scope, p, key, force); + + try { + insertRoot(scope, p, key, force); + } catch (e) { + console.error(`Error: Failed to insert '${p}' into '${scope}': ${e}`); + } } // Look at all redirs in avoided directories, and move them to the root only if possible. This basically diff --git a/site/_collections/tags.js b/site/_collections/tags.js index 1ba1b1a3b..b1a096395 100644 --- a/site/_collections/tags.js +++ b/site/_collections/tags.js @@ -67,12 +67,24 @@ module.exports = function (collections) { allSortedForLoop: for (const item of allSorted) { // If there are no tags or the tags isn't a string or array, skip the post. /** @type {string[]} */ - const allTags = [item.data.tags ?? []].flat(); + let allTags = [item.data.tags ?? []].flat(); if (!allTags.length) { delete item.data.tags; continue allSortedForLoop; } + // rewrite chromeX to chrome-X + const chromeXRegex = /^chrome(\d+)$/; + allTags = allTags.map(tag => { + chromeXRegex.lastIndex = 0; + const match = tag.match(chromeXRegex); + if (match) { + return `chrome-${match[1]}`; + } + + return tag; + }); + // Ensure that tags on the front matter is an array. item.data.tags = allTags; From 857228ca470586274155b2388f1475cd15354178 Mon Sep 17 00:00:00 2001 From: Matthias Rohmer Date: Thu, 4 May 2023 16:16:28 +0200 Subject: [PATCH 158/982] perf: disable warning in pretty-urls transform --- site/_transforms/dom-transformer.js | 2 +- site/_transforms/pretty-urls.js | 11 +---------- 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/site/_transforms/dom-transformer.js b/site/_transforms/dom-transformer.js index 8e1b1d6ed..eab29e085 100644 --- a/site/_transforms/dom-transformer.js +++ b/site/_transforms/dom-transformer.js @@ -30,7 +30,7 @@ const domTransformer = async (content, outputPath) => { // Pipe the page through transforms. // These transforms mutate the cheerio object. - prettyUrls($, outputPath, locale); + prettyUrls($, locale); tables($); // Return the final html. diff --git a/site/_transforms/pretty-urls.js b/site/_transforms/pretty-urls.js index a9faf16a2..c1f8e7ac0 100644 --- a/site/_transforms/pretty-urls.js +++ b/site/_transforms/pretty-urls.js @@ -9,10 +9,9 @@ const fakeOrigin = `https://fake-does-not-exist-${Math.random()}.localhost`; * Which url style to use is inferred from the outputPath's locale. * @param {cheerio.Selector} $ A cheerio representation of the page. This object will be * modified in place. - * @param {string} outputPath The destination for the file. * @param {string} locale The locale for the file. */ -const prettyUrls = ($, outputPath, locale) => { +const prettyUrls = ($, locale) => { /** @type {(href: string|undefined) => string|undefined} */ const prettyHref = href => { if (!href) { @@ -76,14 +75,6 @@ const prettyUrls = ($, outputPath, locale) => { const href = $link.attr('href'); if (!href && !$link.attr('id')) { - // Only warn in non-production builds, as this is a common occurrence and might - // be confusing when debugging build errors. - if (process.env.ELEVENTY_ENV !== 'production') { - console.warn( - `Found in ${outputPath} with no href/id (text=\`${$link.text()}\`)` - ); - } - return; } From 66bc0c18ab7c1e0f50d21a0064e19f1756d8adea Mon Sep 17 00:00:00 2001 From: Sebastian Benz Date: Thu, 4 May 2023 16:29:04 +0200 Subject: [PATCH 159/982] New Android Custom Tabs Guide (#6122) * New Android Custom Tabs Guide * Replaces existing implementation guide (redirects are set up), the existing implementation guide content is merged into the new guides. Except "Custom Tabs Connection Callback", which has been removed, instead a new engagement signals guide will be added as a follow up. * The guide is split up into multiple guides under the new "Guide" category. As part of this change, the existing guides (best practices, http headers, and low level api) are moved into a new "How to ..." category. The howtos will reworked in a follow up PR. * Add engagement signals guide * Included feedback from engineering * addressed andreban's comments * Apply suggestions from code review Co-authored-by: Joe Medley * Addressed Patrick's and Joe's feedback * Addressed feedback * new intro for engagement signals * cropped action image * small formatting/spelling fixes * Update site/en/docs/android/custom-tabs/guide-interactivity/index.md Co-authored-by: Joe Medley * Update site/en/docs/android/custom-tabs/guide-interactivity/index.md Co-authored-by: Joe Medley * Update site/en/docs/android/custom-tabs/guide-interactivity/index.md Co-authored-by: Joe Medley * fix typo --------- Co-authored-by: Joe Medley --- redirects.yaml | 3 + site/_data/authorsData.json | 15 +- site/_data/docs/android/toc.yml | 17 +- site/_data/i18n/authors.yaml | 5 + site/_data/i18n/docs/android.yml | 4 +- .../guide-engagement-signals/index.md | 161 +++++++ .../custom-tabs/guide-get-started/index.md | 43 ++ .../custom-tabs/guide-interactivity/index.md | 197 ++++++++ .../guide-partial-custom-tabs/index.md | 96 ++++ .../guide-ui-customization/index.md | 99 ++++ .../guide-warmup-prefetch/index.md | 109 +++++ .../custom-tabs/integration-guide/index.md | 448 ------------------ 12 files changed, 740 insertions(+), 457 deletions(-) create mode 100644 site/en/docs/android/custom-tabs/guide-engagement-signals/index.md create mode 100644 site/en/docs/android/custom-tabs/guide-get-started/index.md create mode 100644 site/en/docs/android/custom-tabs/guide-interactivity/index.md create mode 100644 site/en/docs/android/custom-tabs/guide-partial-custom-tabs/index.md create mode 100644 site/en/docs/android/custom-tabs/guide-ui-customization/index.md create mode 100644 site/en/docs/android/custom-tabs/guide-warmup-prefetch/index.md delete mode 100644 site/en/docs/android/custom-tabs/integration-guide/index.md diff --git a/redirects.yaml b/redirects.yaml index 31c317f63..fd5b844bd 100644 --- a/redirects.yaml +++ b/redirects.yaml @@ -711,6 +711,9 @@ redirects: - from: /docs/web-platform/pop-up-api/ to: https://developer.mozilla.org/docs/Web/API/Popover_API +- from: /docs/android/custom-tabs/integration-guide/ + to: /docs/android/custom-tabs/guide-get-started/ + # DO NOT REMOVE. This seems pointless but we rewrite "." to "_" inside our server's code, so if the # URL is fine for all but incorrect syntax, we'll fix it up. - from: /... diff --git a/site/_data/authorsData.json b/site/_data/authorsData.json index 9d3ec4e2e..1752ec0c7 100644 --- a/site/_data/authorsData.json +++ b/site/_data/authorsData.json @@ -1150,10 +1150,10 @@ "github": "arskama" }, "robertyang": { - "image": "image/RtQlPaM9wdhEJGVKR8boMPkWf443/In0YoXtpVY8pwm7Pcj33.jpeg", - "twitter": "yangrob", - "linkedin": "robertyanghk" -}, + "image": "image/RtQlPaM9wdhEJGVKR8boMPkWf443/In0YoXtpVY8pwm7Pcj33.jpeg", + "twitter": "yangrob", + "linkedin": "robertyanghk" + }, "vaatika": { "country": "DE", "twitter": "vaatika", @@ -1174,5 +1174,12 @@ }, "marcopaniconi": { "image": "image/kheDArv5csY6rvQUJDbWRscckLr1/sCdEdscRuD8KSRYpvTXI.png" + }, + "sebastianbenz": { + "country": "DE", + "twitter": "sebabenz", + "github": "sebastianbenz", + "mastodon": "https://mastodon.cloud/@sebabenz", + "image": "image/6hHqS5auVgWhN0cQNQztaJx5w4M2/aHVsNAzlN0L0oqVacct3.jpg" } } diff --git a/site/_data/docs/android/toc.yml b/site/_data/docs/android/toc.yml index 845fa2505..1985401a4 100644 --- a/site/_data/docs/android/toc.yml +++ b/site/_data/docs/android/toc.yml @@ -1,10 +1,19 @@ - title: i18n.docs.android.customtabs sections: - url: /docs/android/custom-tabs - - url: /docs/android/custom-tabs/integration-guide - - url: /docs/android/custom-tabs/best-practices - - url: /docs/android/custom-tabs/headers - - url: /docs/android/custom-tabs/low-level-api + - title: i18n.docs.android.guides + sections: + - url: /docs/android/custom-tabs/guide-get-started + - url: /docs/android/custom-tabs/guide-ui-customization + - url: /docs/android/custom-tabs/guide-interactivity + - url: /docs/android/custom-tabs/guide-warmup-prefetch + - url: /docs/android/custom-tabs/guide-partial-custom-tabs + - url: /docs/android/custom-tabs/guide-engagement-signals + - title: i18n.docs.android.howtos + sections: + - url: /docs/android/custom-tabs/best-practices + - url: /docs/android/custom-tabs/headers + - url: /docs/android/custom-tabs/low-level-api - title: i18n.docs.android.trustedwebactivity sections: - url: /docs/android/trusted-web-activity diff --git a/site/_data/i18n/authors.yaml b/site/_data/i18n/authors.yaml index 1c8c41167..9c8ed6a8e 100644 --- a/site/_data/i18n/authors.yaml +++ b/site/_data/i18n/authors.yaml @@ -1394,3 +1394,8 @@ yunqingwang: en: Yunqing Wang description: en: Senior Staff Software Engineer, Chrome Open Media +sebastianbenz: + title: + en: 'Sebastian Benz' + description: + en: 'Sebastian is a Developer Relations Engineer' diff --git a/site/_data/i18n/docs/android.yml b/site/_data/i18n/docs/android.yml index b478b9c39..42bb084dd 100644 --- a/site/_data/i18n/docs/android.yml +++ b/site/_data/i18n/docs/android.yml @@ -7,4 +7,6 @@ customtabs: trustedwebactivity: en: 'Trusted Web Activity' howtos: - en: 'How-Tos' + en: 'How-to ...' +guides: + en: 'Guides' diff --git a/site/en/docs/android/custom-tabs/guide-engagement-signals/index.md b/site/en/docs/android/custom-tabs/guide-engagement-signals/index.md new file mode 100644 index 000000000..8ff097739 --- /dev/null +++ b/site/en/docs/android/custom-tabs/guide-engagement-signals/index.md @@ -0,0 +1,161 @@ +--- +layout: "layouts/doc-post.njk" +title: Measuring user engagement +seoTitle: "Guide: measuring user engagement in Android Custom Tabs" +date: 2023-04-21 +description: How to measure user engagement in Custom Tabs. +authors: + - sebastianbenz +--- + +This guide explains how to measure engagement signals for Chrome Custom tabs. If your app regularly surfaces links to web content to its users, for example in a news feed, it can be important to know which links users find valuable and which not. In Custom Tabs, you can measure session specific user engagement via the number of navigations, scroll direction changes and scroll depth. + +
+ {% Video src="video/6hHqS5auVgWhN0cQNQztaJx5w4M2/m3WWGlZ2fFVZLgYjX9QV.mp4", controls="true", width="400", height="866", class="screenshot screenshot--filled" %} +
+ Custom Tab engagement signals demo. +
+
+ +{% Aside "caution" %} +This feature requires `androidx.browser:browser:1.6.0-alpha01` or higher. + +```groovy +dependencies { + … + implementation 'androidx.browser:browser:1.6.0-alpha01' +} +``` +{% endAside %} + +Custom Tabs provide two different callbacks for measuring user engagement: + +* [`CustomTabsCallback`](https://developer.android.com/reference/androidx/browser/customtabs/CustomTabsCallback) for tracking basic navigation events, such as `"NAVIGATION_STARTED"` or `"NAVIGATION_FINISHED"`. +* [`EngagementSignalsCallback`](https://developer.android.com/reference/androidx/browser/customtabs/CustomTabsCallback) for tracking page specific user engagement, such as scroll direction or scroll percentage. + +Both require an active [`CustomTabsServiceConnection`](https://developer.android.com/reference/androidx/browser/customtabs/CustomTabsServiceConnection). See the [previous `CustomTabsService` guide](/docs/android/custom-tabs/guide-warmup-prefetch/) for details on how to connect to a `CustomTabsService`. + +To measure user engagement, first create a `CustomTabsCallback` and an `EngagementSignalsCallback` instance. The `CustomTabsCallback` receives a `navigationEvent` constant describing which kind of navigation happened: + +```java +private CustomTabsCallback mCustomTabsCallback = new CustomTabsCallback() { + @Override + public void onNavigationEvent(int navigationEvent, @Nullable Bundle extras) { + String event; + switch (navigationEvent) { + case CustomTabsCallback.NAVIGATION_ABORTED: + event = "NAVIGATION_ABORTED"; + break; + case CustomTabsCallback.NAVIGATION_FAILED: + event = "NAVIGATION_FAILED"; + break; + case CustomTabsCallback.NAVIGATION_FINISHED: + event = "NAVIGATION_FINISHED"; + break; + case CustomTabsCallback.NAVIGATION_STARTED: + event = "NAVIGATION_STARTED"; + break; + case CustomTabsCallback.TAB_SHOWN: + event = "TAB_SHOWN"; + break; + case CustomTabsCallback.TAB_HIDDEN: + event = "TAB_HIDDEN"; + break; + default: + event = String.valueOf(navigationEvent); + } + Log.d(TAG, "onNavigationEvent (navigationEvent=" + event + ')'); + mTextNavigation.setText("onNavigationEvent " + event); + } +}; +``` + +The `EngagementSignalsCallback` supports three different callbacks: + +`onVerticalScrollEvent()` +: Called every time the user changes the scroll direction, where `isDirectionUp` (the first argument) indicates the direction. +1. `onGreatestScrollPercentageIncreased`: the Custom Tab signals scroll depth in 5% intervals up to 100% when the user has reached the bottom of the page. The callback is only invoked once the user stops scrolling. The value is reset to 0% with every new navigation. +1. `onSessionEnded`: the Custom Tab fires this event when it stops sending engagement signals (for example, after the user has closed the Custom Tab). `didUserInteract` will be true if the user interacted with the page in any way (scrolling, button click, etc.). + +```java +private EngagementSignalsCallback mEngagementSignalsCallback = new EngagementSignalsCallback() { + @Override + public void onVerticalScrollEvent(boolean isDirectionUp, @NonNull Bundle extras) { + Log.d(TAG, "onVerticalScrollEvent (isDirectionUp=" + isDirectionUp + ')'); + mTextVerticalScroll.setText("vertical scroll " + (isDirectionUp ? "UP️" : "DOWN")); + } + + @Override + public void onGreatestScrollPercentageIncreased(int scrollPercentage, @NonNull Bundle extras) { + Log.d(TAG, "scroll percentage: " + scrollPercentage + "%"); + mTextGreatestPercentage.setText("scroll percentage: " + scrollPercentage + "%"); + } + + @Override + public void onSessionEnded(boolean didUserInteract, @NonNull Bundle extras) { + Log.d(TAG, "onSessionEnded (didUserInteract=" + didUserInteract + ')'); + mTextSessionEnd.setText(didUserInteract ? "session ended with user interaction" : "session ended without user interaction"); + } +}; +``` + +{% Aside "important" %} +For the `onGreatestScrollPercentageIncreased` event to reset, a new navigation needs to happen on the main frame to a new document. In other words, scroll depth will **not** be reset for navigations inside a single page application or on navigation to an anchor. +{% endAside %} + +Both `CustomTabsCallback` and `EngagementSignalsCallback` require an active Custom Tab service connection. Once the service is connected, you can create a new `CustomTabsSession` by calling [`CustomTabsClient.newSession()`](https://developer.android.com/reference/androidx/browser/customtabs/CustomTabsClient#newSession(androidx.browser.customtabs.CustomTabsCallback)) and passing the `CustomTabsCallback`. + +Afterwards, you should call `isEngagementSignalsApiAvailable()` to check if engagement signals are supported by the current browser. If they are supported, you can register your `EngagementSignalsCallback` via `CustomTabsSession.setEngagementSignalsCallback()`. + +```java +private CustomTabsClient mCustomTabsClient; +private CustomTabsSession mCustomTabsSession; + +private final CustomTabsServiceConnection mServiceConnectionCallback = new CustomTabsServiceConnection() { + + @Override + public void onCustomTabsServiceConnected(@NonNull ComponentName name, @NonNull CustomTabsClient client) { + mCustomTabsClient = client; + mCustomTabsSession = mCustomTabsClient.newSession(mCustomTabsCallback); + try { + boolean engagementSignalsApiAvailable = mCustomTabsSession.isEngagementSignalsApiAvailable(Bundle.EMPTY); + if (!engagementSignalsApiAvailable) { + Log.d(TAG, "CustomTab Engagement signals not available, make sure to use the " + + "latest Chrome version and enable via chrome://flags/#cct-real-time-engagement-signals"); + return; + } + mCustomTabsSession.setEngagementSignalsCallback(mEngagementSignalsCallback, Bundle.EMPTY); + } catch (RemoteException e) { + Log.w(TAG, "The Service died while responding to the request.", e); + } catch (UnsupportedOperationException e) { + Log.w(TAG, "Engagement Signals API isn't supported by the browser.", e); + } + } + + @Override + public void onServiceDisconnected(ComponentName name) { + mCustomTabsClient = null; + mConnection = null; + mCustomTabsSession = null; + } +}; +``` + +The only thing left to do is binding the `CustomTabsService`: + + +```java +@Override +protected void onStart() { + super.onStart(); + bindCustomTabsService(); +} + +private void bindCustomTabsService() { + String packageName = CustomTabsHelper.getPackageNameToUse(this); + if (packageName == null) return; + CustomTabsClient.bindCustomTabsService(this, packageName, mConnection); +} +``` + + diff --git a/site/en/docs/android/custom-tabs/guide-get-started/index.md b/site/en/docs/android/custom-tabs/guide-get-started/index.md new file mode 100644 index 000000000..fd8192866 --- /dev/null +++ b/site/en/docs/android/custom-tabs/guide-get-started/index.md @@ -0,0 +1,43 @@ +--- +layout: "layouts/doc-post.njk" +title: Getting started +seoTitle: "Guide: getting started with Custom Tabs" +date: 2023-04-21 +description: How to launch a Custom Tab from your Android app. +authors: + - sebastianbenz +--- + +The first step for a Custom Tabs integration is adding the [AndroidX Browser Library](https://developer.android.com/jetpack/androidx/releases/browser#declaring_dependencies) to your project. Open the app/build.gradle file and add the browser library to the dependencies section. + +```java +dependencies { + … + implementation 'androidx.browser:browser:1.5.0' +} +``` + +{% Aside %} +Checkout the [Android Custom Tab Sample app on Github](https://github.com/GoogleChrome/android-browser-helper/tree/dc788207822576f6c867ff28d470ec51ad06d178/demos/custom-tabs-example-app) for a working example. +{% endAside %} + +## Open a link in a custom tab + +With the `androidx.browser/browser` library installed, you can use the [`CustomTabsIntent.Builder`](https://developer.android.com/reference/androidx/browser/customtabs/CustomTabsIntent.Builder) to create a [`CustomTabsIntent`](https://developer.android.com/reference/androidx/browser/customtabs/CustomTabsIntent) and launch the Custom Tab by calling [`launchUrl()`](https://developer.android.com/reference/androidx/browser/customtabs/CustomTabsIntent#launchUrl(android.content.Context,android.net.Uri)) and passing an [Uri](https://developer.android.com/reference/android/net/Uri): + +```java +String url = "https://developers.android.com"; +CustomTabsIntent intent = new CustomTabsIntent.Builder() + .build(); +intent.launchUrl(MainActivity.this, Uri.parse(url)); +``` + +This will open a fullscreen Custom Tab activity as seen on the following screenshot. + +{% Img src="image/6hHqS5auVgWhN0cQNQztaJx5w4M2/slw7FNNob6P1zwEkJMZa.png", alt="The default Custom Tabs experience.", width="400", height="866", class="screenshot screenshot--filled" %} + +{% Aside 'gotchas' %} +What happens if the user's default browser does not support Custom Tabs? Custom Tabs are supported by most Android browsers, but if no browser that supports Custom Tabs is installed, the `CustomTabIntent` will open the user's default browser instead. This works, as the `CustomTabsIntent` uses the [`ACTION\_VIEW` Intent](https://developer.android.com/reference/android/content/Intent#ACTION_VIEW) with `Extras` key to customize the UI. +{% endAside %} + +Next up: [learn how to customize the look and feel of your Custom Tab.](/docs/android/custom-tabs/guide-ui-customization/). diff --git a/site/en/docs/android/custom-tabs/guide-interactivity/index.md b/site/en/docs/android/custom-tabs/guide-interactivity/index.md new file mode 100644 index 000000000..9d7e3dc39 --- /dev/null +++ b/site/en/docs/android/custom-tabs/guide-interactivity/index.md @@ -0,0 +1,197 @@ +--- +layout: "layouts/doc-post.njk" +title: Adding custom interactivity +seoTitle: "Guide: Adding custom interactivity to a Custom Tab" +date: 2023-04-21 +description: How to add custom actions to a Custom Tabs. +authors: + - sebastianbenz +--- + +This guide explains how to add custom interactivity to Custom Tabs. + +## Enable the default share action + +If you don't provide a custom share action, it is a good idea to enable the browser's default share action in the overflow menu to make it easier for users to share a link to the content they are seeing: + +```java + CustomTabsIntent.Builder intentBuilder = new CustomTabsIntent.Builder(); + intentBuilder.setShareState(CustomTabsIntent.SHARE_STATE_ON); +``` + +## Add a custom action button + +For important actions, the Custom Tab toolbar lets you integrate a custom action button, which can either have a text label or a custom icon. The icon should be 24dp in height and 24-48 dp in width. + +{% Img src="image/6hHqS5auVgWhN0cQNQztaJx5w4M2/9eJW75CRW22UVx7FYnqs.png", alt="Custom Tab with a custom share action", width="800", height="460", class="screenshot screenshot--filled" %} + +For example, you can add a custom share action to the toolbar. To do this, create a [`BroadcastReceiver`](https://developer.android.com/guide/components/broadcasts#receiving-broadcasts) which gets called when the user clicks on the share action in the Custom Tab. + +Register the `BroadCastReceiver` in the `AndroidManifest.xml` file: + +```xml + + + +``` + +Then add a new class, `ShareBroadcastReceiver`. In the `onReceive()` method, extract the currently displayed URL from the intent and trigger a send intent. + +```java +public class ShareBroadcastReceiver extends BroadcastReceiver { + + @Override + public void onReceive(Context context, Intent intent) { + String url = intent.getDataString(); + Intent sendIntent = new Intent(); + sendIntent.setAction(Intent.ACTION_SEND); + sendIntent.putExtra(Intent.EXTRA_TEXT, url); + sendIntent.setType("text/plain"); + Intent shareIntent = Intent.createChooser(sendIntent, null); + context.startActivity(shareIntent); + } +} +``` + +Now, create a `PendingIntent` for `ShareBroadcast` and register it via [`setActionButton()`](https://developer.android.com/reference/androidx/browser/customtabs/CustomTabsIntent.Builder#setActionButton(android.graphics.Bitmap,java.lang.String,android.app.PendingIntent)). Pass the pending intent together with the icon and the description. + +```java +String shareDescription = getString(R.string.label_action_share); +Bitmap shareIcon = BitmapFactory.decodeResource(getResources(), +       android.R.drawable.ic_menu_share); + +// Create a PendingIntent to your BroadCastReceiver implementation +Intent actionIntent = new Intent( +       this.getApplicationContext(), ShareBroadcastReceiver.class); +PendingIntent pendingIntent = +       PendingIntent.getBroadcast(getApplicationContext(), 0 /* request code */, actionIntent, PendingIntent.FLAG_MUTABLE);           + +//Set the pendingIntent as the action to be performed when the button is clicked. +CustomTabsIntent intentBuilder = new CustomTabsIntent.Builder() + … + .setActionButton(shareIcon, shareDescription, pendingIntent) + .build(); +``` + +## Add custom menu items + +Custom tabs has as many as five default actions provided by the browser: "Forward", "Page Info", "Refresh", "Find in Page" and "Open in Browser". Additionally, you can add up to five more, which will be inserted between the icon row and the browser-provided items. (See the image below.) + +You can access your custom actions via the three dot menu in the top right corner: + +{% Img src="image/6hHqS5auVgWhN0cQNQztaJx5w4M2/3WXYfUUMRMqzNwgIT1Ao.png", alt="Custom Tab with five custom menu items.", width="320", height="693", class="screenshot screenshot--filled" %} + +To add a menu item, call [`CustomTabsIntent.Builder.addMenuItem()`](https://developer.android.com/reference/androidx/browser/customtabs/CustomTabsIntent.Builder#addMenuItem(java.lang.String,android.app.PendingIntent)) with title and a [`PendingIntent`](https://developer.android.com/reference/android/app/PendingIntent). When the user taps on a menu item, the browser will fire the `PendingIntent`. + + +```java +CustomTabsIntent intent = new CustomTabsIntent.Builder() + ... + .addMenuItem("Menu item 1", pendingIntent) + .addMenuItem("Menu item 2", pendingIntent) + .addMenuItem("Menu item 3", pendingIntent) + .addMenuItem("Menu item 4", pendingIntent) + .addMenuItem("Menu item 5", pendingIntent) + .build(); +``` + +## Customize the close button + +To better fit a Custom Tab into the flow of your app, customize the close button. If you want the user to feel like Custom Tabs is a modal dialog, use the default `“X”` button. If you want the user to feel the Custom Tab is part of the application flow, use the back arrow. + +```java +CustomTabsIntent.Builder intentBuilder = new CustomTabsIntent.Builder(); +intentBuilder.setCloseButtonIcon(BitmapFactory.decodeResource( + getResources(), R.drawable.ic_arrow_back)); +``` + +## Add a bottom toolbar + +The bottom toolbar is a very flexible way to add more functionality to a custom tab. + +{% Img src="image/6hHqS5auVgWhN0cQNQztaJx5w4M2/e0evUtBxkP0uI7kVj8PS.png", alt="Custom Tab with a bottom toolbar", width="320", height="693", class="screenshot screenshot--filled" %} + +By passing a [`RemoteViews`](https://developer.android.com/reference/android/widget/RemoteViews?cmdf=android+remoteviews) object to [CustomTabIntent.Builder.setSecondaryToolbarViews()](https://developer.android.com/reference/android/support/customtabs/CustomTabsIntent.Builder.html#setSecondaryToolbarViews(android.widget.RemoteViews,%20int[],%20android.app.PendingIntent)), the bottom toolbar can be fully customized and dynamically updated. + +First, declare a toolbar layout by creating a new layout file, `res/layout/custom_tab_toolbar.xml`: + +```xml + + +
+
+ {% include 'partials/post-navigation.njk' %} {% endblock %} diff --git a/site/_includes/partials/post-navigation.njk b/site/_includes/partials/post-navigation.njk new file mode 100644 index 000000000..22f6ca34c --- /dev/null +++ b/site/_includes/partials/post-navigation.njk @@ -0,0 +1,34 @@ +{% if type === 'article' %} + {% set collectionName = 'articles-' + locale %} +{% endif %} + +{% if type === 'blogPost' %} + {% set collectionName = 'blog-' + locale %} +{% endif %} + +{% if collections[collectionName] %} + {% set previousPost = collections[collectionName] | getPreviousCollectionItem(page) %} + {% set nextPost = collections[collectionName] | getNextCollectionItem(page) %} +{% endif %} + +
+ +
+ {% if previousPost %} + + {{ 'i18n.common.back' | i18n(locale) }} +

{{previousPost.data.title}}

+
+ {% endif %} +
+ +
+ {% if nextPost %} + + {{ 'i18n.common.next' | i18n(locale) }} +

{{nextPost.data.title}}

+
+ {% endif %} +
+ +
\ No newline at end of file diff --git a/site/_scss/blocks/_post-navigation.scss b/site/_scss/blocks/_post-navigation.scss new file mode 100644 index 000000000..46d6a6479 --- /dev/null +++ b/site/_scss/blocks/_post-navigation.scss @@ -0,0 +1,92 @@ +.post-navigation { + border-bottom: 1px solid var(--color-hairline); + border-top: 1px solid var(--color-hairline); + display: flex; + font-family: 'Google Sans'; + justify-content: space-between; + margin-bottom: px-to-rem(-72px); + margin-top: px-to-rem(80px); + width: 100%; + + @include media-query('md-max') { + flex-direction: column; + } + + &__link { + display: block; + font-size: px-to-rem(20px); + height: 100%; + line-height: px-to-rem(28px); + padding: px-to-rem(40px); + text-decoration: none; + + @include media-query('md-max') { + width: 100%; + } + + @include media-query('lg-max') { + padding: px-to-rem(40px) px-to-rem(24px); + } + } + + + &__link:hover { + background-color: var(--color-blue-lightest); + height: 100%; + } + + &__prev { + border-right: 1px solid var(--color-hairline); + + @include media-query('md-max') { + border-bottom: 1px solid var(--color-hairline); + border-top: unset; + } + } + + &__prev, + &__next { + width: 50%; + + @include media-query('md-max') { + width: 100%; + } + } + + + &__label { + color: var(--color-primary); + display: inline-block; + font-size: px-to-rem(14px); + line-height: px-to-rem(20px); + margin-bottom: px-to-rem(16px); + } + + &__label::before { + background-position: center center; + background-repeat: no-repeat no-repeat; + background-size: cover; + content: ''; + display: inline-block; + height: px-to-rem(16px); + margin-right: px-to-rem(20px); + margin-top: px-to-rem(-2px); + vertical-align: middle; + width: px-to-rem(16px); + } + + &__label::before { + background-image: url("data:image/svg+xml,%3Csvg width='16' height='16' viewBox='0 0 16 16' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M8 0L6.59 1.41L12.17 7H0V9H12.17L6.59 14.59L8 16L16 8L8 0Z' fill='%231A73E8'/%3E%3C/svg%3E%0A"); + } + + &__prev &__label::before { + transform: scaleX(-1); + } + + &__title { + color: var(--color-text); + display: block; + max-width: 70ch; + text-decoration: none; + } +} diff --git a/site/_scss/layouts/single-post.scss b/site/_scss/layouts/single-post.scss index 5b73e322d..4217b9f43 100644 --- a/site/_scss/layouts/single-post.scss +++ b/site/_scss/layouts/single-post.scss @@ -18,6 +18,7 @@ @import '../blocks/pagination'; @import '../blocks/post-authors'; @import '../blocks/post-banner'; +@import '../blocks/post-navigation'; @import '../blocks/screenshot'; @import '../blocks/stats'; @import '../blocks/switcher'; From 1edb09ac9cee0c1e1011ac8b09f0628ac5c315e9 Mon Sep 17 00:00:00 2001 From: Matthias Rohmer Date: Fri, 5 May 2023 15:14:01 +0200 Subject: [PATCH 163/982] fix: adapt pretty urls test --- tests/site/_transforms/pretty-urls.js | 49 +++++++++++---------------- 1 file changed, 20 insertions(+), 29 deletions(-) diff --git a/tests/site/_transforms/pretty-urls.js b/tests/site/_transforms/pretty-urls.js index 01e34a3a9..6bf84d7c6 100644 --- a/tests/site/_transforms/pretty-urls.js +++ b/tests/site/_transforms/pretty-urls.js @@ -9,8 +9,8 @@ const { * @param {string} outputPath * @param {string} locale */ -const prettyUrls = ($, outputPath, locale) => { - prettyUrlsRaw($, outputPath, locale); +const prettyUrls = ($, locale) => { + prettyUrlsRaw($, locale); return $; }; @@ -20,126 +20,117 @@ const template = markup => { test('removes the /en/ prefix from links', t => { const locale = 'en'; - const outputPath = '/en/bar/index.html'; let $ = template(''); let expected = template('').html(); - let actual = prettyUrls($, outputPath, locale).html(); + let actual = prettyUrls($, locale).html(); t.assert(actual === expected); $ = template(''); expected = template('').html(); - actual = prettyUrls($, outputPath, locale).html(); + actual = prettyUrls($, locale).html(); t.assert(actual === expected); $ = template(''); expected = template('').html(); - actual = prettyUrls($, outputPath, locale).html(); + actual = prettyUrls($, locale).html(); t.assert(actual === expected); $ = template(''); expected = template('').html(); - actual = prettyUrls($, outputPath, locale).html(); + actual = prettyUrls($, locale).html(); t.assert(actual === expected); }); test('adds the /${locale}/ prefix to links', t => { const locale = 'pl'; - const outputPath = '/pl/bar/index.html'; let $ = template(''); let expected = template('').html(); - let actual = prettyUrls($, outputPath, locale).html(); + let actual = prettyUrls($, locale).html(); t.assert(actual === expected); $ = template(''); expected = template('').html(); - actual = prettyUrls($, outputPath, locale).html(); + actual = prettyUrls($, locale).html(); t.assert(actual === expected); $ = template(''); expected = template('').html(); - actual = prettyUrls($, outputPath, locale).html(); + actual = prettyUrls($, locale).html(); t.assert(actual === expected); }); test('ignores external links', t => { const locale = 'en'; - const outputPath = '/en/foo/index.html'; let $ = template(''); let expected = template('').html(); - let actual = prettyUrls($, outputPath, locale).html(); + let actual = prettyUrls($, locale).html(); t.assert(actual === expected); $ = template(''); expected = template('').html(); - actual = prettyUrls($, outputPath, locale).html(); + actual = prettyUrls($, locale).html(); t.assert(actual === expected); $ = template(''); expected = template('').html(); - actual = prettyUrls($, outputPath, locale).html(); + actual = prettyUrls($, locale).html(); t.assert(actual === expected); }); test('ignores links without an href', t => { const locale = 'en'; - const outputPath = '/en/bar/index.html'; const $ = template(''); const expected = template('').html(); - const actual = prettyUrls($, outputPath, locale).html(); + const actual = prettyUrls($, locale).html(); t.assert(actual === expected); }); test('ignores internal links', t => { const locale = 'en'; - const outputPath = '/en/bar/index.html'; const $ = template(''); const expected = template('').html(); - const actual = prettyUrls($, outputPath, locale).html(); + const actual = prettyUrls($, locale).html(); t.assert(actual === expected); }); test('adds the locale prefix but does not add a trailing slash if there is a hash anchor', t => { const locale = 'pl'; - const outputPath = '/pl/docs/example/index.html'; const $ = template(''); const expected = template('').html(); - const actual = prettyUrls($, outputPath, locale).html(); + const actual = prettyUrls($, locale).html(); t.assert(actual === expected); }); test('removes the /en/ prefix but does not add a trailing slash if there is a hash anchor', t => { const locale = 'en'; - const outputPath = '/en/docs/example/index.html'; const $ = template(''); const expected = template('').html(); - const actual = prettyUrls($, outputPath, locale).html(); + const actual = prettyUrls($, locale).html(); t.assert(actual === expected); }); test('ignores mailto links', t => { const locale = 'en'; - const outputPath = '/en/bar/index.html'; const $ = template(''); const expected = template('').html(); - const actual = prettyUrls($, outputPath, locale).html(); + const actual = prettyUrls($, locale).html(); t.assert(actual === expected); }); test('ignores relative links', t => { const locale = 'en'; - const outputPath = '/en/bar/index.html'; let $ = template(''); let expected = template('').html(); - let actual = prettyUrls($, outputPath, locale).html(); + let actual = prettyUrls($, locale).html(); t.assert(actual === expected); $ = template(''); expected = template('').html(); - actual = prettyUrls($, outputPath, locale).html(); + actual = prettyUrls($, locale).html(); t.assert(actual === expected); $ = template(''); expected = template('').html(); - actual = prettyUrls($, outputPath, locale).html(); + actual = prettyUrls($, locale).html(); t.assert(actual === expected); }); From a92706b31a24cb11a7f048064954d94d10a20e43 Mon Sep 17 00:00:00 2001 From: James <42349493+Blazzike@users.noreply.github.com> Date: Fri, 5 May 2023 14:31:48 +0100 Subject: [PATCH 164/982] feat: replace pre-push hook with lintstaged pre-commit hook (#6198) * feat: replace pre-push hook with lintstaged package for pre-commit linting * refactor: replace lint-staged script with npx call in husky * fix: pin lint-staged version --- .huskyrc.js | 2 +- .lintstagedrc.json | 6 + package-lock.json | 695 ++++++++++++++++++++++++++++++++++++++++++++- package.json | 1 + 4 files changed, 697 insertions(+), 7 deletions(-) create mode 100644 .lintstagedrc.json diff --git a/.huskyrc.js b/.huskyrc.js index e1562f4c7..7b769a233 100644 --- a/.huskyrc.js +++ b/.huskyrc.js @@ -1,5 +1,5 @@ module.exports = { hooks: { - "pre-push": "npm run lint" + "pre-commit": "npx lint-staged" } }; \ No newline at end of file diff --git a/.lintstagedrc.json b/.lintstagedrc.json new file mode 100644 index 000000000..ee161c239 --- /dev/null +++ b/.lintstagedrc.json @@ -0,0 +1,6 @@ +{ + "*.scss": "npm run lint:scss", + "*.ts": "npm run lint:types", + "*.md": "npm run lint:md", + "*.js": "npm run lint:js" +} diff --git a/package-lock.json b/package-lock.json index d532dcf9e..bd116e904 100644 --- a/package-lock.json +++ b/package-lock.json @@ -75,6 +75,7 @@ "gts": "^3.1.0", "html-escaper": "^2.0.2", "husky": "^4.3.0", + "lint-staged": "^13.2.2", "micromatch": "4.0.5", "mvdir": "^1.0.21", "nyc": "^15.1.0", @@ -7773,6 +7774,12 @@ "node": ">=0.10.0" } }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, "node_modules/easy-extender": { "version": "2.3.4", "resolved": "https://registry.npmjs.org/easy-extender/-/easy-extender-2.3.4.tgz", @@ -14494,6 +14501,15 @@ "node": ">=10" } }, + "node_modules/lilconfig": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", + "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", + "dev": true, + "engines": { + "node": ">=10" + } + }, "node_modules/limiter": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/limiter/-/limiter-1.1.5.tgz", @@ -14652,6 +14668,207 @@ "uc.micro": "^1.0.1" } }, + "node_modules/lint-staged": { + "version": "13.2.2", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-13.2.2.tgz", + "integrity": "sha512-71gSwXKy649VrSU09s10uAT0rWCcY3aewhMaHyl2N84oBk4Xs9HgxvUp3AYu+bNsK4NrOYYxvSgg7FyGJ+jGcA==", + "dev": true, + "dependencies": { + "chalk": "5.2.0", + "cli-truncate": "^3.1.0", + "commander": "^10.0.0", + "debug": "^4.3.4", + "execa": "^7.0.0", + "lilconfig": "2.1.0", + "listr2": "^5.0.7", + "micromatch": "^4.0.5", + "normalize-path": "^3.0.0", + "object-inspect": "^1.12.3", + "pidtree": "^0.6.0", + "string-argv": "^0.3.1", + "yaml": "^2.2.2" + }, + "bin": { + "lint-staged": "bin/lint-staged.js" + }, + "engines": { + "node": "^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/lint-staged" + } + }, + "node_modules/lint-staged/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/lint-staged/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/lint-staged/node_modules/chalk": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.2.0.tgz", + "integrity": "sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA==", + "dev": true, + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/lint-staged/node_modules/cli-truncate": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-3.1.0.tgz", + "integrity": "sha512-wfOBkjXteqSnI59oPcJkcPl/ZmwvMMOj340qUIY1SKZCv0B9Cf4D4fAucRkIKQmsIuYK3x1rrgU7MeGRruiuiA==", + "dev": true, + "dependencies": { + "slice-ansi": "^5.0.0", + "string-width": "^5.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lint-staged/node_modules/commander": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", + "dev": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/lint-staged/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "node_modules/lint-staged/node_modules/execa": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-7.1.1.tgz", + "integrity": "sha512-wH0eMf/UXckdUYnO21+HDztteVv05rq2GXksxT4fCGeHkBhw1DROXh40wcjMcRqDOWE7iPJ4n3M7e2+YFP+76Q==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.1", + "human-signals": "^4.3.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^3.0.7", + "strip-final-newline": "^3.0.0" + }, + "engines": { + "node": "^14.18.0 || ^16.14.0 || >=18.0.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/lint-staged/node_modules/human-signals": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-4.3.1.tgz", + "integrity": "sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==", + "dev": true, + "engines": { + "node": ">=14.18.0" + } + }, + "node_modules/lint-staged/node_modules/is-fullwidth-code-point": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", + "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lint-staged/node_modules/pidtree": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.0.tgz", + "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==", + "dev": true, + "bin": { + "pidtree": "bin/pidtree.js" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/lint-staged/node_modules/slice-ansi": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", + "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.0.0", + "is-fullwidth-code-point": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/lint-staged/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lint-staged/node_modules/strip-ansi": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", + "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, "node_modules/liquidjs": { "version": "9.43.0", "resolved": "https://registry.npmjs.org/liquidjs/-/liquidjs-9.43.0.tgz", @@ -14673,6 +14890,180 @@ "resolved": "https://registry.npmjs.org/list-to-array/-/list-to-array-1.1.0.tgz", "integrity": "sha512-+dAZZ2mM+/m+vY9ezfoueVvrgnHIGi5FvgSymbIgJOFwiznWyA59mav95L+Mc6xPtL3s9gm5eNTlNtxJLbNM1g==" }, + "node_modules/listr2": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-5.0.8.tgz", + "integrity": "sha512-mC73LitKHj9w6v30nLNGPetZIlfpUniNSsxxrbaPcWOjDb92SHPzJPi/t+v1YC/lxKz/AJ9egOjww0qUuFxBpA==", + "dev": true, + "dependencies": { + "cli-truncate": "^2.1.0", + "colorette": "^2.0.19", + "log-update": "^4.0.0", + "p-map": "^4.0.0", + "rfdc": "^1.3.0", + "rxjs": "^7.8.0", + "through": "^2.3.8", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": "^14.13.1 || >=16.0.0" + }, + "peerDependencies": { + "enquirer": ">= 2.3.0 < 3" + }, + "peerDependenciesMeta": { + "enquirer": { + "optional": true + } + } + }, + "node_modules/listr2/node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/listr2/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/listr2/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/listr2/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/listr2/node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "dev": true + }, + "node_modules/listr2/node_modules/log-update": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-4.0.0.tgz", + "integrity": "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==", + "dev": true, + "dependencies": { + "ansi-escapes": "^4.3.0", + "cli-cursor": "^3.1.0", + "slice-ansi": "^4.0.0", + "wrap-ansi": "^6.2.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/listr2/node_modules/log-update/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/listr2/node_modules/rxjs": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "dev": true, + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/listr2/node_modules/slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/listr2/node_modules/tslib": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==", + "dev": true + }, + "node_modules/listr2/node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/listr2/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/lit-element": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/lit-element/-/lit-element-2.5.1.tgz", @@ -22053,6 +22444,12 @@ "node": ">=0.10.0" } }, + "node_modules/rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==", + "dev": true + }, "node_modules/rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", @@ -23423,6 +23820,15 @@ } ] }, + "node_modules/string-argv": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz", + "integrity": "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==", + "dev": true, + "engines": { + "node": ">=0.6.19" + } + }, "node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", @@ -26321,9 +26727,9 @@ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" }, "node_modules/yaml": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.2.1.tgz", - "integrity": "sha512-e0WHiYql7+9wr4cWMx3TVQrNwejKaEe7/rHNmQmqRjazfOP5W8PB6Jpebb5o6fIapbz9o9+2ipcaTM2ZwDI6lw==", + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.2.2.tgz", + "integrity": "sha512-CBKFWExMn46Foo4cldiChEzn7S7SRV+wqiluAb6xmueD/fGyRHIhX8m14vVGgeFWjN540nKCNVj6P21eQjgTuA==", "dev": true, "engines": { "node": ">= 14" @@ -32359,6 +32765,12 @@ } } }, + "eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, "easy-extender": { "version": "2.3.4", "resolved": "https://registry.npmjs.org/easy-extender/-/easy-extender-2.3.4.tgz", @@ -37499,6 +37911,12 @@ "resolved": "https://registry.npmjs.org/lighthouse-stack-packs/-/lighthouse-stack-packs-1.9.1.tgz", "integrity": "sha512-9prq6oMkVHz3GeCkphq4FHXXdj3M/WPiFWUvJAczLYV8j/oTxsgiHSPMqh1KVV11CP0VTxD40hFC0pDfXF+khQ==" }, + "lilconfig": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", + "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", + "dev": true + }, "limiter": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/limiter/-/limiter-1.1.5.tgz", @@ -37616,6 +38034,134 @@ "uc.micro": "^1.0.1" } }, + "lint-staged": { + "version": "13.2.2", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-13.2.2.tgz", + "integrity": "sha512-71gSwXKy649VrSU09s10uAT0rWCcY3aewhMaHyl2N84oBk4Xs9HgxvUp3AYu+bNsK4NrOYYxvSgg7FyGJ+jGcA==", + "dev": true, + "requires": { + "chalk": "5.2.0", + "cli-truncate": "^3.1.0", + "commander": "^10.0.0", + "debug": "^4.3.4", + "execa": "^7.0.0", + "lilconfig": "2.1.0", + "listr2": "^5.0.7", + "micromatch": "^4.0.5", + "normalize-path": "^3.0.0", + "object-inspect": "^1.12.3", + "pidtree": "^0.6.0", + "string-argv": "^0.3.1", + "yaml": "^2.2.2" + }, + "dependencies": { + "ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true + }, + "ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true + }, + "chalk": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.2.0.tgz", + "integrity": "sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA==", + "dev": true + }, + "cli-truncate": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-3.1.0.tgz", + "integrity": "sha512-wfOBkjXteqSnI59oPcJkcPl/ZmwvMMOj340qUIY1SKZCv0B9Cf4D4fAucRkIKQmsIuYK3x1rrgU7MeGRruiuiA==", + "dev": true, + "requires": { + "slice-ansi": "^5.0.0", + "string-width": "^5.0.0" + } + }, + "commander": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", + "dev": true + }, + "emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "execa": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-7.1.1.tgz", + "integrity": "sha512-wH0eMf/UXckdUYnO21+HDztteVv05rq2GXksxT4fCGeHkBhw1DROXh40wcjMcRqDOWE7iPJ4n3M7e2+YFP+76Q==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.1", + "human-signals": "^4.3.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^3.0.7", + "strip-final-newline": "^3.0.0" + } + }, + "human-signals": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-4.3.1.tgz", + "integrity": "sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", + "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", + "dev": true + }, + "pidtree": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.0.tgz", + "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==", + "dev": true + }, + "slice-ansi": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", + "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", + "dev": true, + "requires": { + "ansi-styles": "^6.0.0", + "is-fullwidth-code-point": "^4.0.0" + } + }, + "string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "requires": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + } + }, + "strip-ansi": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", + "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", + "dev": true, + "requires": { + "ansi-regex": "^6.0.1" + } + } + } + }, "liquidjs": { "version": "9.43.0", "resolved": "https://registry.npmjs.org/liquidjs/-/liquidjs-9.43.0.tgz", @@ -37626,6 +38172,131 @@ "resolved": "https://registry.npmjs.org/list-to-array/-/list-to-array-1.1.0.tgz", "integrity": "sha512-+dAZZ2mM+/m+vY9ezfoueVvrgnHIGi5FvgSymbIgJOFwiznWyA59mav95L+Mc6xPtL3s9gm5eNTlNtxJLbNM1g==" }, + "listr2": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-5.0.8.tgz", + "integrity": "sha512-mC73LitKHj9w6v30nLNGPetZIlfpUniNSsxxrbaPcWOjDb92SHPzJPi/t+v1YC/lxKz/AJ9egOjww0qUuFxBpA==", + "dev": true, + "requires": { + "cli-truncate": "^2.1.0", + "colorette": "^2.0.19", + "log-update": "^4.0.0", + "p-map": "^4.0.0", + "rfdc": "^1.3.0", + "rxjs": "^7.8.0", + "through": "^2.3.8", + "wrap-ansi": "^7.0.0" + }, + "dependencies": { + "ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "requires": { + "type-fest": "^0.21.3" + } + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "dev": true + }, + "log-update": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-4.0.0.tgz", + "integrity": "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==", + "dev": true, + "requires": { + "ansi-escapes": "^4.3.0", + "cli-cursor": "^3.1.0", + "slice-ansi": "^4.0.0", + "wrap-ansi": "^6.2.0" + }, + "dependencies": { + "wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + } + } + }, + "rxjs": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "dev": true, + "requires": { + "tslib": "^2.1.0" + } + }, + "slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + } + }, + "tslib": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==", + "dev": true + }, + "type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true + }, + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + } + } + }, "lit-element": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/lit-element/-/lit-element-2.5.1.tgz", @@ -43286,6 +43957,12 @@ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==" }, + "rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==", + "dev": true + }, "rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", @@ -44377,6 +45054,12 @@ } } }, + "string-argv": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz", + "integrity": "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==", + "dev": true + }, "string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", @@ -46589,9 +47272,9 @@ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" }, "yaml": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.2.1.tgz", - "integrity": "sha512-e0WHiYql7+9wr4cWMx3TVQrNwejKaEe7/rHNmQmqRjazfOP5W8PB6Jpebb5o6fIapbz9o9+2ipcaTM2ZwDI6lw==", + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.2.2.tgz", + "integrity": "sha512-CBKFWExMn46Foo4cldiChEzn7S7SRV+wqiluAb6xmueD/fGyRHIhX8m14vVGgeFWjN540nKCNVj6P21eQjgTuA==", "dev": true }, "yargs": { diff --git a/package.json b/package.json index 5643ef3f6..f4804f0e7 100644 --- a/package.json +++ b/package.json @@ -120,6 +120,7 @@ "gts": "^3.1.0", "html-escaper": "^2.0.2", "husky": "^4.3.0", + "lint-staged": "13.2.2", "micromatch": "4.0.5", "mvdir": "^1.0.21", "nyc": "^15.1.0", From e92f84e64838aba3075ef7cb8a183c2faa46225b Mon Sep 17 00:00:00 2001 From: Bramus! Date: Fri, 5 May 2023 16:35:09 +0200 Subject: [PATCH 165/982] Add scroll-driven animations article (#6147) --- .../scroll-driven-animations/index.md | 667 ++++++++++++++++++ 1 file changed, 667 insertions(+) create mode 100644 site/en/articles/scroll-driven-animations/index.md diff --git a/site/en/articles/scroll-driven-animations/index.md b/site/en/articles/scroll-driven-animations/index.md new file mode 100644 index 000000000..881b9fdb1 --- /dev/null +++ b/site/en/articles/scroll-driven-animations/index.md @@ -0,0 +1,667 @@ +--- +layout: 'layouts/blog-post.njk' +title: Animate elements on scroll with Scroll-driven animations +authors: + - bramus +subhead: > + Learn how to work with Scroll Timelines and View Timelines to create scroll-driven animations in a declarative way. +description: > + Learn how to work with Scroll Timelines and View Timelines to create scroll-driven animations in a declarative way. +date: 2023-05-05 +hero: image/AeNB0cHNDkYPUYzDuv8gInYA9rY2/iDNlcxHa6axrfgHi4aoU.png +alt: "A computer mouse and an arrow indicating scroll movement." +tags: + - css + - chrome-115 +--- + +{% Aside %} This feature is available in Chrome 115 with “Experimental Web Platform Features” enabled. {% endAside %} + +## Scroll-driven animations + +Scroll-driven animations are a common UX pattern on the web. A scroll-driven animation is linked to the scroll position of a scroll container. This means that as you scroll up or down, the linked animation scrubs forward or backward in direct response. Examples of this are effects such as parallax background images or reading indicators which move as you scroll. + +
+ {% Video src="video/AeNB0cHNDkYPUYzDuv8gInYA9rY2/HiTavHlNjHFrA3NLLDZq.mp4", width="800", height="800", controls="true", playsinline="true" %} +
A reading indicator atop a document, driven by scroll.
+
+ +A similar type of scroll-driven animation is an animation that is linked to an element's position within its scroll container. With it, for example, elements can fade-in as they come into view. + +
+ {% Video src="video/AeNB0cHNDkYPUYzDuv8gInYA9rY2/eV0R7BXHO7ieTFVBfTEE.mp4", width="800", height="800", controls="true", playsinline="true" %} +
The images on this page fade-in as they come into view.
+
+ +The classic way to achieve these kinds of effects is to respond to scroll events on [the main thread](https://developer.mozilla.org/docs/Glossary/Main_thread), which leads to two main problems: + +- Modern browsers perform scrolling on a separate process and therefore deliver scroll events asynchronously. +- Main thread animations are [subject to jank](/blog/inside-browser-part3/#updating-rendering-pipeline-is-costly). + +This makes creating performant scroll-driven animations that are in-sync with scrolling impossible or very difficult. + +Coming to Chrome is a new set of APIs and concepts that work in conjunction with the existing [Web Animations API (WAAPI)](https://drafts.csswg.org/web-animations-1/) and [CSS Animations API](https://drafts.csswg.org/css-animations-1/) to enable declarative scroll-driven animations. + +Integrating scroll-driven animations with two existing APIs, means that they benefit from the advantages of these APIs. That includes the ability to have these animations run off the main thread. Yes, read that correctly: you can now have silky smooth animations, driven by scroll, running off the main thread, with just a few lines of extra code. What's not to like?! + +{% Aside %} If you can’t wait to check out some demos go visit [https://scroll-driven-animations.style](https://scroll-driven-animations.style), a site packed with demos and tools to check out. {% endAside %} + +## Animations on the web, a small recap + +### Animations on the web with CSS + +To create an animation in CSS, define a set of keyframes using the `@keyframes` at-rule. Link it up to an element using the `animation-name` property while also setting an `animation-duration` to determine how long the animation should take. There are more `animation-*` longhand properties available–`animation-easing-function` and `animation-fill-mode` just to name a few–which can all be combined in the `animation` shorthand. + +For example, here’s an animation that scales up an element on the X-axis while also changing its background color: + +```css +@keyframes scale-up { + from { + background-color: red; + transform: scaleX(0); + } + to { + background-color: darkred; + transform: scaleX(1); + } +} + +#progressbar { + animation: 2.5s linear forwards scale-up; +} +``` + +{% Aside %} To learn more about CSS Animations, visit [Learn CSS Animations](https://web.dev/learn/css/animations/) {% endAside %} + +### Animations on the web with JavaScript + +In JavaScript, the Web Animations API can be used to achieve exactly the same. You can do this by either creating new `Animation` and `KeyFrameEffect` instances, or use the much shorter [`Element` `animate()` method](https://developer.mozilla.org/docs/Web/API/Element/animate). + +```js +document.querySelector('#progressbar').animate( + { + backgroundColor: ['red', 'darkred'], + transform: ['scaleX(0)', 'scaleX(1)'], + }, + { + duration: 2500, + fill: 'forwards', + easing: 'linear', + } +); +``` + +This visual result of the JavaScript snippet above is identical to the previous CSS version. + + +## Animation timelines + +By default, an animation attached to an element runs on the [document timeline](https://developer.mozilla.org/docs/Web/API/DocumentTimeline). Its origin time starts at 0 when the page loads, and starts ticking forwards as clock time progresses. This is the default animation timeline and, until now, was the only animation timeline you had access to. + +The [Scroll-driven Animations Specification](https://drafts.csswg.org/scroll-animations-1/) defines two new types of timelines that you can use: + + +- **Scroll Progress Timeline**: a timeline that is linked to the scroll position of a scroll container along a particular axis. +- **View Progress Timeline**: a timeline that is linked to the relative position of a particular element within its scroll container. + +### Scroll Progress Timeline + +A Scroll Progress Timeline is an animation timeline that is linked to progress in the scroll position of a scroll container–also called _scrollport_ or _scroller_–along a particular axis. It converts a position in a scroll range into a percentage of progress. + +The starting scroll position represents 0% progress and the ending scroll position represents 100% progress. In the following visualization, you can see that the progress counts up from 0% to 100% as you scroll the scroller from top to bottom. + +
+ {% Video src="video/AeNB0cHNDkYPUYzDuv8gInYA9rY2/xdU4YJ6cxjNYpec1XcE6.mp4", width="800", height="800", controls="true", playsinline="true" %} +
Visualization of a Scroll Progress Timeline. As you scroll down to the bottom of the scroller, the progress value counts up from 0% to 100%.
+
+ +{% Details %} +{% DetailsSummary %}✨ Try it for yourself{% endDetailsSummary %} + +{% endDetails %} + +A Scroll Progress Timeline is often abbreviated to simply “Scroll Timeline”. + +### View Progress Timeline + +This type of timeline is linked to the relative progress of a particular element within a scroll container. Just like a Scroll Progress Timeline, a scroller’s scroll offset is tracked. Unlike a Scroll Progress Timeline, it’s the relative position of a subject within that scroller that determines the progress. + +This is somewhat comparable to how [`IntersectionObserver`](https://developer.mozilla.org/docs/Web/API/Intersection_Observer_API) works, which can track how much an element is visible in the scroller. If the element is not visible in the scroller, it is not intersecting. If it is visible inside the scroller–even for the smallest part–it is intersecting. + +A View Progress Timeline begins from the moment a subject starts intersecting with the scroller and ends when the subject stops intersecting the scroller. In the following visualization, you can see that the progress starts counting up from 0% when the subject enters the scroll container and reaches 100% at the very moment the subject has left the scroll container. + +
+ {% Video src="video/AeNB0cHNDkYPUYzDuv8gInYA9rY2/rvPTFW2277KBTuWiZFj1.mp4", width="800", height="800", controls="true", playsinline="true" %} +
Visualization of a View Progress Timeline. The progress counts up from 0% to 100% as the subject (green box) crosses the scroller.
+
+ +{% Details %} +{% DetailsSummary %}✨ Try it for yourself{% endDetailsSummary %} + +{% endDetails %} + +A View Progress Timeline is often abbreviated to simply “View Timeline”. It is possible to target specific parts of a View Timeline based on the subject’s size, but more on that later. + + +## Getting practical with Scroll Progress Timelines + + +### Creating an anonymous Scroll Progress Timeline in CSS + +The easiest way to create a Scroll Timeline in CSS is to use the `scroll()` function. This creates an anonymous Scroll Timeline that you can set as the value for the new `animation-timeline` property. + +Example: + +```css +@keyframes animate-it { … } + +.subject { + animation: animate-it linear; + animation-timeline: scroll(root block); +} +``` + +The `scroll()` function accepts a `` and an `` argument. + +Accepted values for the `` argument are the following: +- `nearest`: Uses the nearest ancestor scroll container _(default)_. +- `root`: Uses the document viewport as the scroll container. +- `self`: Uses the element itself as the scroll container. + +Accepted values for the `` argument are the following: +- `block`: Uses the measure of progress along the block axis of the scroll container _(default)_. +- `inline`: Uses the measure of progress along the inline axis of the scroll container. +- `y`: Uses the measure of progress along the y axis of the scroll container. +- `x`: Uses the measure of progress along the x axis of the scroll container. + +For example, to bind an animation to the root scroller on the block axis, the values to pass into `scroll()` are `root` and `block`. Put together, the value is `scroll(root block)`. + +{% Aside 'important' %} Because an `animation-duration` set in seconds does not make sense when using a Scroll Progress Timeline, you must set `animation-duration` to `auto`. Alternatively, as done in the code snippet above, you can omit the `animation-duration` from the `animation` shorthand as it will then use its default value which is `auto`. {% endAside %} + +#### Demo: Reading progress indicator + +This demo has a reading progress indicator fixed to the top of the viewport. As you scroll down the page, the progress bar grows until it takes up the full viewport width upon reaching the end of the document. An anonymous Scroll Progress Timeline is used to drive the animation. + +
+ {% Video src="video/AeNB0cHNDkYPUYzDuv8gInYA9rY2/HiTavHlNjHFrA3NLLDZq.mp4", width="800", height="800", controls="true", playsinline="true" %} +
Demo: Reading progress indicator.
+
+ +{% Details %} +{% DetailsSummary %}✨ Try it for yourself{% endDetailsSummary %} + +{% endDetails %} + +The reading progress indicator is positioned at the top of the page using position fixed. To leverage composited animations, not the `width` is being animated but the element is scaled down on the x-axis using a `transform`. + +```html + +
+ … + +``` + +```css +@keyframes grow-progress { + from { transform: scaleX(0); } + to { transform: scaleX(1); } +} + +#progress { + position: fixed; + left: 0; top: 0; + width: 100%; height: 1em; + background: red; + + transform-origin: 0 50%; + animation: grow-progress auto linear; + animation-timeline: scroll(); +} +``` + +The timeline for the animation `grow-progress` on the `#progress` element is set to an anonymous timeline that’s created using `scroll()`. No arguments are given to `scroll()` so it will fall back to its default values. + +The default scroller to track is the `nearest` one, and the default axis is `block`. This effectively targets the root scroller as that is the nearest scroller of the `#progress` element, while tracking its block direction. + +### Creating a named Scroll Progress Timeline in CSS + +An alternative way to define a Scroll Progress Timeline is to use a named one. It’s a bit more verbose, but it can come in handy when you aren’t targeting a parent scroller or the root scroller, or when the page uses multiple timelines or when automatic lookups don’t work. This way, you can identify a Scroll Progress Timeline by the name that you give it. + +To create a named Scroll Progress Timeline on an element, set the `scroll-timeline-name` CSS property on the scroll container to an identifier of your liking. The value must start with `--`. + +To tweak which axis to track, also declare the `scroll-timeline-axis` property. Allowed values are the same as the `` argument of `scroll()`. + +Finally, to link the animation to the Scroll Progress Timeline, set the `animation-timeline` property on the element that needs to be animated to the same value as the identifier used for the `scroll-timeline-name`. + +Code Example: + +```css +@keyframes animate-it { … } + +.scroller { + scroll-timeline-name: --my-scroller; + scroll-timeline-axis: inline; +} + +.scroller .subject { + animation: animate-it linear; + animation-timeline: --my-scroller; +} +``` + +If wanted, you can combine `scroll-timeline-name` and `scroll-timeline-axis` in the `scroll-timeline` shorthand. For example: + +```css +scroll-timeline: --my-scroller inline; +``` + +{% Aside 'important' %} Note that even for named Scroll Timelines the lookup from the subject to the scroller happens across ancestors only. How to target a non-ancestor element, such as a sibling element, is covered further down this article in the [“Attaching to a non-ancestor Scroll Timeline”](#attaching-to-a-non-ancestor-scroll-timeline) section. {% endAside %} + +#### Demo: Horizontal carousel step indicator + +This demo features a step indicator shown above each image carousel. When a carousel contains three images, the indicator bar starts at 33% width to indicate you are currently looking at image one of three. When the last image is in view–determined by the scroller having scrolled to the end–the indicator takes up the full width of the scroller. A named Scroll Progress Timeline is used to drive the animation. + +
+ {% Video src="video/AeNB0cHNDkYPUYzDuv8gInYA9rY2/5ln4aDkZ625xlM9jZXPl.mp4", width="800", height="800", controls="true", playsinline="true" %} +
Demo: Horizontal carousel step indicator.
+
+ +{% Details %} +{% DetailsSummary %}✨ Try it for yourself{% endDetailsSummary %} + +{% endDetails %} + + +The base markup for a gallery is this: + +```html + +``` + +The `.gallery__progress` element is absolutely positioned within the `.gallery` wrapper element. Its initial size is determined by the `--num-images` custom property. + +```css +.gallery { + position: relative; +} + + +.gallery__progress { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 1em; + transform: scaleX(calc(1 / var(--num-images))); +} +``` + +The `.gallery__scrollcontainer` lays out the contained `.gallery__entry` elements horizontally and is the element that scrolls. By tracking its scroll position, the `.gallery__progress` gets animated. This is done by referring to the named Scroll Progress Timeline `--gallery__scrollcontainer`. + +```css +@keyframes grow-progress { + to { transform: scaleX(1); } +} + +.gallery__scrollcontainer { + overflow-x: scroll; + scroll-timeline: --gallery__scrollcontainer inline; +} +.gallery__progress { + animation: auto grow-progress linear forwards; + animation-timeline: --gallery__scrollcontainer; +} +``` + +{% Aside 'warning' %} For this specific demo, using an Anonymous Scroll Progress Timeline would not have worked. If you set `animation-timeline: scroll(nearest inline)` on `.gallery__progress` it would not find the scroller from the `.gallery__scrollcontainer` even if that element is its direct parent. + +The reason for this, is that lookups for `nearest` only considers the elements that can affect its position and size. Because `.gallery__progress` is absolutely positioned, the first parent element that will determine its size and position is the `.gallery` element as it has `position: relative` applied, thereby jumping over the `.gallery__scrollcontainer` element. + +Expressed in more technical terms, the lookup walks up [the containing block chain](https://drafts.csswg.org/css-display/#containing-block-chain) to find the nearest [scroll container](https://drafts.csswg.org/css-overflow-3/#scroll-container). {% endAside %} + +### Creating a Scroll Progress Timeline with JavaScript + +To create a Scroll Timeline in JavaScript, create a new instance of the `ScrollTimeline` class. Pass in a property bag with the `source` and `axis` that you want to track. + +- `source`: A reference to the element whose scroller that you want to track. Use `document.documentElement` to target the root scroller. +- `axis`: Determines which axis to track. Similar to the CSS variant, accepted values are `block`, `inline`, `x`, and `y`. + +```js +const tl = new ScrollTimeline({ + source: document.documentElement, +}); +```` + +To attach it to a Web Animation, pass it in as the `timeline` property and omit any `duration` if there was any. + +```js +$el.animate({ + opacity: [0, 1], +}, { + timeline: tl, +}); +``` + +#### Demo: Reading progress indicator, revisited + +To recreate the reading progress indicator with JavaScript, while using the same markup, use the following JavaScript code: + + +```js +const $progressbar = document.querySelector('#progress'); + +$progressbar.style.transformOrigin = '0% 50%'; +$progressbar.animate( + { + transform: ['scaleX(0)', 'scaleX(1)'], + }, + { + fill: 'forwards', + timeline: new ScrollTimeline({ + source: document.documentElement, + }), + } +); +``` + +The visual result is identical in the CSS version: the created `timeline` tracks the root scroller and scale the `#progress` up on the x-axis from 0% to 100% as you scroll the page. + + +{% Details %} +{% DetailsSummary %}✨ Try it for yourself{% endDetailsSummary %} + +{% endDetails %} + + +## Getting practical with View Progress Timeline + +### Creating an Anonymous View Progress Timeline in CSS + +To create a View Progress Timeline, use the `view()` function. Its accepted arguments are `` and ``. + +- The `` is the same as from the Scroll Progress Timeline and defines which axis to track. The default value is `block`. +- With ``, you can specify an offset _(positive or negative)_ to adjust the bounds when an element is considered to be in view or not. The value must be a percentage or `auto`, with `auto` being the default value. + +For example, to bind an animation to an element intersecting with its scroller on the block axis, use `view(block)`. Similar to `scroll()`, set this as the value for the `animation-timeline` property and don’t forget to set the `animation-duration` to `auto`. + +Using the following code, every `img` will fade-in as it crosses the viewport while you scroll. + +```css +@keyframes reveal { + from { opacity: 0; } + to { opacity: 1; } +} + +img { + animation: reveal linear; + animation-timeline: view(); +} +``` + +{% Aside 'important' %} It is not possible to determine the `` of a View Timeline, as it always tracks the subject within its nearest parent scroller. {% endAside %} + +### Intermezzo: View Timeline ranges + +By default, an animation linked to the View Timeline attaches to the entire timeline range. This starts from the moment the subject is about to enter the scrollport and ends when the subject has left the scrollport entirely. + +It is also possible to link it to a specific part of the View Timeline by specifying the range that it should attach to. This can be, for example, only when the subject is entering the scroller. In the following visualization, the progress starts counting up from 0% when the subject enters the scroll container but already reaches 100% from the moment it is entirely intersecting. + +
+ {% Video src="video/AeNB0cHNDkYPUYzDuv8gInYA9rY2/p952qt9FVzv2v3zP0o9Q.mp4", width="800", height="800", controls="true", playsinline="true" %} +
A View Timeline set to track the entry range of the subject. The animation only runs while the subject is entering the scrollport.
+
+ +The possible View Timeline ranges that you can target are the following: + +- `cover`: Represents the full range of the view progress timeline. +- `entry`: Represents the range during which the principal box is entering the view progress visibility range. +- `exit`: Represents the range during which the principal box is exiting the view progress visibility range. +- `entry-crossing`: Represents the range during which the principal box crosses the end border edge. +- `exit-crossing`: Represents the range during which the principal box crosses the start border edge. +- `contain`: Represents the range during which the principal box is either fully contained by, or fully covers, its view progress visibility range within the scrollport. This depends on whether the subject is taller or shorter than the scroller. + +To define a range, you must set a range-start and range-end. Each consists of range-name _(see list above)_ and a range-offset to determine the position within that range-name. The range-offset is typically a percentage ranging from `0%` to `100%` but you can also specify a fixed length such as `20em`. + +For example, if you want to run an animation from the moment a subject is entering, choose `entry 0%` as the range-start. To have it finished by the time the subject has entered, choose `entry 100%` as a value for the range-end. In CSS, you set this using the `animation-range` property. Example: + +```css +animation-range: entry 0% entry 100%; +``` + +Use the tool embedded below to see what each range-name represents and how the percentages affect the start and end positions. Try to set the range-start to `entry 0%` and the range-end to `cover 50%`, and then drag the scrollbar to see the animation result. + +
+ +
The View Timeline Ranges Visualizer, available at https://goo.gle/view-timeline-range-tool
+
+ +{% Details %} +{% DetailsSummary %}Watch a recording{% endDetailsSummary %} +{% Video src="video/AeNB0cHNDkYPUYzDuv8gInYA9rY2/x6SLvlnns26zNGeJOCuS.mp4", width="800", height="800", controls="true", playsinline="true" %} +{% endDetails %} + +As you might notice while playing around with this View Timeline Ranges tools, some ranges can be targeted by two different range-name + range-offset combinations. For example, `entry 0%`, `entry-crossing 0%`, and `cover 0%` all target the same area. + +When the range-start and range-end target the same range-name and span the entire range–from 0% up to 100%–you can shorten the value to simply the range name. For example, `animation-range: entry 0% entry 100%;` can be rewritten to the much shorter `animation-range: entry`. + +{% Aside 'important' %} Note that these ranges are derived from the untransformed _principal box_ of the subject. That means that transformations such as `scale` and `translate` are not taken into account when deriving the ranges. This is a good thing, as this allows you to scale a subject during scroll without affecting the available scroll estate. If the transformed box were used, attached animations would flicker because they would constantly need to be recalculated in response to a change in scroll estate. {% endAside %} + +#### Demo: Image reveal + +This demo fades in the images as they enter the scrollport. This is done using an Anonymous View Timeline. The animation range has been tweaked so that each image is at full opacity when it is halfway the scroller. + +
+ {% Video src="video/AeNB0cHNDkYPUYzDuv8gInYA9rY2/eV0R7BXHO7ieTFVBfTEE.mp4", width="800", height="800", controls="true", playsinline="true" %} +
Demo: Image reveal
+
+ +{% Details %} +{% DetailsSummary %}✨ Try it for yourself{% endDetailsSummary %} + +{% endDetails %} + +The expanding effect is achieved by using a clip-path that is animated. The CSS used for this effect is this: + +```css +@keyframes reveal { + from { opacity: 0; clip-path: inset(0% 60% 0% 50%); } + to { opacity: 1; clip-path: inset(0% 0% 0% 0%); } +} + +.revealing-image { + animation: auto linear reveal both; + animation-timeline: view(); + animation-range: entry 25% cover 50%; +} +``` + +### Creating a named View Progress Timeline in CSS + +Similar to how Scroll Timelines have named versions, you can also create named View Timelines. Instead of the `scroll-timeline-*` properties you use variants that carry the `view-timeline-` prefix, namely `view-timeline-name` and `view-timeline-axis`. + +The same type of values apply, and the same rules for looking up a named timeline apply. + +#### Demo: Image reveal, revisited + +Reworking the image reveal demo from earlier, the revised code looks like this: + +```css +.revealing-image { + view-timeline-name: --revealing-image; + view-timeline-axis: block; + + animation: auto linear reveal both; + animation-timeline: --revealing-image; + animation-range: entry 25% cover 50%; +} +``` + +Using `view-timeline-name: revealing-image`, the element will be tracked within its nearest scroller. The same value is then used as the value for the `animation-timeline` property. The visual output is exactly the same as before. + +{% Details %} +{% DetailsSummary %}✨ Try it for yourself{% endDetailsSummary %} + +{% endDetails %} + +### Creating a View Progress Timeline in JavaScript + +To create a View Timeline in JavaScript, create a new instance of the `ViewTimeline` class. Pass in a property bag with the `subject` that you want to track, `axis`, and `inset`. + +- `subject`: A reference to the element that you want to track within its own scroller. +- `axis`: The axis to track. Similar to the CSS variant, accepted values are `block`, `inline`, `x`, and `y`. +- `inset`: An inset _(positive)_ or outset _(negative)_ adjustment of the scrollport when determining whether the box is in view. + +```js +const tl = new ViewTimeline({ + subject: document.getElementById('subject'), +}); +```` + +To attach it to a Web Animation, pass it in as the `timeline` property and omit any `duration` if there was any. + +```js +$el.animate({ + opacity: [0, 1], +}, { + timeline: tl, +}); +``` + +{% Aside %} The animated element `$el` and the `subject` do not need to be the same element. This means that you can track an element in its scroller while animating a distant element somewhere else in the DOM tree. {% endAside %} + +## More things to try out + +### Attaching to multiple View Timeline ranges with one set of keyframes + +Let’s take a look at this contact list demo where the list entries are animated. As a list entry enters the scrollport from the bottom it slides+fades in, and as it exits the scrollport at the top it slides+fades out. + +
+ {% Video src="video/AeNB0cHNDkYPUYzDuv8gInYA9rY2/edztzaUNSuQsUVUzF9vr.mp4", width="800", height="800", controls="true", playsinline="true" %} +
Demo: Contact list
+
+ +{% Details %} +{% DetailsSummary %}✨ Try it for yourself{% endDetailsSummary %} + +{% endDetails %} + +For this demo, each element gets decorated with one View Timeline that tracks the element as it crosses its scrollport yet two scroll-driven animations are attached to it. The `animate-in` animation is attached to the `entry` range of the timeline, and the `animate-out` animation to the `exit` range of the timeline. + +```css +@keyframes animate-in { + 0% { opacity: 0; transform: translateY(100%); } + 100% { opacity: 1; transform: translateY(0); } +} +@keyframes animate-out { + 0% { opacity: 1; transform: translateY(0); } + 100% { opacity: 0; transform: translateY(-100%); } +} + +#list-view li { + animation: animate-in linear forwards, + animate-out linear forwards; + animation-timeline: view(); + animation-range: entry, exit; +} +``` + +Instead of running two different animations attached to two different ranges, it is also possible to create one set of keyframes that already contains the range information. + +```css +@keyframes animate-in-and-out { + entry 0% { + opacity: 0; transform: translateY(100%); + } + entry 100% { + opacity: 1; transform: translateY(0); + } + exit 0% { + opacity: 1; transform: translateY(0); + } + exit 100% { + opacity: 0; transform: translateY(-100%); + } +} + +#list-view li { + animation: linear animate-in-and-out; + animation-timeline: view(); +} +``` + +As the keyframes contain the range information, you don’t need to specify the `animation-range`. The result is exactly the same as it was before. + +{% Details %} +{% DetailsSummary %}✨ Try it for yourself{% endDetailsSummary %} + +{% endDetails %} + +### Attaching to a non-ancestor Scroll Timeline + +{% Aside %} The exact syntax for this feature is [still under discussion](https://github.com/w3c/csswg-drafts/issues/7759). The name of the properties might still change. {% endAside %} + +The lookup mechanism for named Scroll Timelines and named View Timelines is limited to scroll ancestors only. Very often though, the element that needs to be animated is not a child of the scroller that needs to be tracked. + +To make this work, the `scroll-timeline-root` and `view-timeline-root` properties come into play. You use these to declare a timeline with that name, giving it a broader scope. In practice, you do this on a shared parent element so that a child scroller’s timeline can attach to it. + +For example: + +```css +.parent { + scroll-timeline-root: --tl; +} +.parent .scroller { + scroll-timeline: --tl; +} +.parent .scroller ~ .subject { + animation: animate linear; + animation-timeline: --tl; +} +``` + +In this snippet: + +- The `.parent` element declares a Scroll Timeline with the name `--tl`. Any child of it can find and use it as a value for the `animation-timeline` property. +- The `.scroller` element actually defines a Scroll Timeline with the name `--tl`. By default it would only be visible to its children but because `.parent` has it set as the `scroll-timeline-root`, it attaches to it. +- The `.subject` element uses the `--tl` timeline. It walks up its ancestor tree and finds `--tl` on the `.parent`. With the `--tl` on the `.parent` pointing to the `--tl` of `.scroller`, the `.subject` will essentially track the `.scroller`’s Scroll Progress Timeline. + +Put differently, you can use `scroll-timeline-root` and `view-timeline-root` to move a Scroll Timeline up to an ancestor (aka _hoisting_), so that all children of the ancestor can access it. + +## More demos and resources + +All demos covered in this article on [the scroll-driven-animations.style mini-site](https://scroll-driven-animations.style/). The website includes many more demos to highlight what is possible with Scroll-driven animations. + +One of the additional demos is this list of album covers. Each cover rotates in 3D as it takes the center spotlight. + +
+ {% Video src="video/AeNB0cHNDkYPUYzDuv8gInYA9rY2/hiItR1vueBVTJbgOAwHp.mp4", width="800", height="800", controls="true", playsinline="true" %} +
Demo: Cover Flow
+
+ +{% Details %} +{% DetailsSummary %}✨ Try it for yourself{% endDetailsSummary %} + +{% endDetails %} + +Or this stacking cards demo that leverage `position: sticky`. As the cards stack, the already stuck cards scale down, creating a nice depth effect. In the end, the entire stack slides out of view as a group. + + +
+ {% Video src="video/AeNB0cHNDkYPUYzDuv8gInYA9rY2/dyy4rOs0WsWOAuxS9sBG.mp4", width="800", height="800", controls="true", playsinline="true" %} +
Demo: Stacking cards.
+
+ +{% Details %} +{% DetailsSummary %}✨ Try it for yourself{% endDetailsSummary %} + +{% endDetails %} + +Also featured on [scroll-driven-animations.style](https://scroll-driven-animations.style/) is a collection of tools such as the View Timeline Range Progress visualization that was included earlier in this post. + +Scroll-driven animations are also covered in [What’s new in Web Animations](https://io.google/2023/program/170b44dc-47f0-409f-92fe-b5c70aab4569/) at Google I/O ’23. From 45d927e8bf87c6f71ac5feb1252dc36c2c1e21a7 Mon Sep 17 00:00:00 2001 From: amysteamdev <37001393+AmySteam@users.noreply.github.com> Date: Fri, 5 May 2023 10:11:40 -0500 Subject: [PATCH 166/982] [ext-doc] New SidePanel API documentation (#6178) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Side panel first draft * Draft blurb ext arch * Draft blurb Design UI * Move global side panel instructions * Misc tweaks * Add dictionary side panel info * Final tweak * Match code & links in samples repo * Apply suggestions from tech review - part 1️⃣ Co-authored-by: Oliver Dunk * Tweak alt text Tweak intro * Add an aside for availability * Update aside content Co-authored-by: Oliver Dunk * catch error/async * Revert Arch and Design UI * Apply suggestions from David Li * Change aside * Update site/en/docs/extensions/reference/sidePanel/index.md --------- Co-authored-by: Oliver Dunk --- .../mv3/architecture-overview/index.md | 2 +- .../extensions/reference/sidePanel/index.md | 219 ++++++++++++++++++ 2 files changed, 220 insertions(+), 1 deletion(-) create mode 100644 site/en/docs/extensions/reference/sidePanel/index.md diff --git a/site/en/docs/extensions/mv3/architecture-overview/index.md b/site/en/docs/extensions/mv3/architecture-overview/index.md index 625c6c60d..2973b78eb 100644 --- a/site/en/docs/extensions/mv3/architecture-overview/index.md +++ b/site/en/docs/extensions/mv3/architecture-overview/index.md @@ -134,4 +134,4 @@ Now that you have completed the [Getting Started guides][doc-gs] and understand [doc-ui]: /docs/extensions/mv3/user_interface [manifest-icons]: /docs/extensions/mv3/manifest/icons/ [mdn-dom]: https://developer.mozilla.org/docs/Web/API/Document_Object_Model -[mdn-worker]: https://developer.mozilla.org/docs/Web/API/Worker +[mdn-worker]: https://developer.mozilla.org/docs/Web/API/Worker \ No newline at end of file diff --git a/site/en/docs/extensions/reference/sidePanel/index.md b/site/en/docs/extensions/reference/sidePanel/index.md new file mode 100644 index 000000000..c025e5b8a --- /dev/null +++ b/site/en/docs/extensions/reference/sidePanel/index.md @@ -0,0 +1,219 @@ +--- +api: sidePanel +--- + +{% Aside 'important' %} +The Side Panel API is currently available in [Chrome Canary](https://www.google.com/chrome/canary/). +{% endAside %} + +## Overview {: #overview } + +Chrome features a built-in side panel that enables users to view more information alongside the main content of a webpage. The Side Panel API allows extensions to display their own UI in the side panel, enabling persistent experiences that complement the user's browsing journey. + +
+ {% Img src="image/BhuKGJaIeLNPW9ehns59NfwqKxF2/2uFG8qxM7cqyMuXWlD9R.png", alt="Side panel drop-down menu", width="291", height="366" %} +
+ Chrome browser side panel UI. +
+
+ +Some features include: + +- The side panel remains open when navigating between tabs (if set to do so). +- It can be available only on specific websites. +- As an extension page, side panels have access to all Chrome APIs. +- Within Chrome's settings, users can specify which side the panel should be displayed on. + +## Manifest {: #manifest } + +To use the Side Panel API, add the `"sidePanel"` permission in the extension [manifest][doc-manifest] file: + +{% Label %}manifest.json:{% endLabel %} + +```json +{ + "name": "My side panel extension", + ... + "permissions": [ + "sidePanel" + ] +} +``` + +## Use cases {: #use-cases } + +The following sections demonstrate some common use cases for the Side Panel API. See [Extension samples](#examples) for complete extension examples. + +### Display the same side panel on every site {: #every-site } + +The side panel can be set initially from the `"default_path"` property in the `"side_panel"` key of the manifest to display the same side panel on every site. This should point to a relative path within the extension directory. + +{% Label %}manifest.json:{% endLabel %} + +```json +{ + "name": "My side panel extension", + ... + "side_panel": { + "default_path": "sidepanel.html" + } + ... +} +``` + +{% Label %}sidepanel.html:{% endLabel %} + +```html + + + + My Sidepanel + + +

All sites sidepanel extension

+

This side panel is enabled on all sites

+ + +``` + +### Enable a side panel on a specific site {: #by-site } + +An extension can use [`sidepanel.setOptions()`][sidepanel-setoptions] to enable a side panel on a specific tab. This example uses [`chrome.tabs.onUpdated()`][tabs-onupdated] to listen for any updates made to the tab. It checks if the URL is [www.google.com](https://www.google.com) and enables the side panel. Otherwise, it disables it. + +{% Label %}service-worker.js:{% endLabel %} + +```js +const GOOGLE_ORIGIN = 'https://www.google.com'; + +chrome.tabs.onUpdated.addListener(async (tabId, info, tab) => { + if (!tab.url) return; + const url = new URL(tab.url); + // Enables the side panel on google.com + if (url.origin === GOOGLE_ORIGIN) { + await chrome.sidePanel.setOptions({ + tabId, + path: 'sidepanel.html', + enabled: true + }); + } else { + // Disables the side panel on all other sites + await chrome.sidePanel.setOptions({ + tabId, + enabled: false + }); + } +}); +``` + +When a user temporarily switches to a tab where the side panel is not enabled, the side panel will be hidden. It will automatically show again when the user switches to a tab where it was previously open. + +When the user navigates to a site where the side panel is not enabled, the side panel will close and the extension will not show in the side panel drop-down menu. + +For a complete example, see the [Tab-specific side panel][sample-sp-google] sample. + +### Enable the action icon to open the side panel {: #open-action-icon } + +Developers can allow users to open the side panel when they click on the action toolbar icon with [`sidePanel.setPanelBehavior()`][sidepanel-set-behavior]. First, declare the `"action"` key in the manifest: + +{% Label %}manifest.json:{% endLabel %} + +```json/3-5 +{ + "name": "My side panel extension", + ... + "action": { + "default_title": "Click to open panel" + }, + ... +} +``` + +Now, let's add this functionality to the previous example: + +{% Label %}service-worker.js:{% endLabel %} + +```js +const GOOGLE_ORIGIN = 'https://www.google.com'; + +// Allows users to open the side panel by clicking on the action toolbar icon +chrome.sidePanel + .setPanelBehavior({ openPanelOnActionClick: true }) + .catch((error) => console.error(error)); +... +``` + +{% Aside 'success' %} +With `openPanelOnActionClick()` enabled, you can also open the side panel using a keyboard shortcut by specifying an [action command][action-commands] in the manifest as featured in the [Tab-specific side panel][sample-sp-google] sample. +{% endAside %} + +### Switch to a different panel {: #multi-panels } + +Extensions can use [`sidepanel.getOptions()`][sidepanel-getoptions] to retrieve the current side panel. The following example sets a welcome side panel on [`runtime.onInstalled()`][runtime-oninstalled]. Then when the user navigates to a different tab, it replaces it with the main side panel. + +{% Label %}service-worker.js:{% endLabel %} + +```js +const welcomePage = 'sidepanels/welcome-sp.html'; +const mainPage = 'sidepanels/main-sp.html'; + +chrome.runtime.onInstalled.addListener(() => { + chrome.sidePanel.setOptions({ path: welcomePage }); +}); + +chrome.tabs.onActivated.addListener(async ({ tabId }) => { + const { path } = await chrome.sidePanel.getOptions({ tabId }); + if (path === welcomePage) { + chrome.sidePanel.setOptions({ path: mainPage }); + } +}); +``` + +See the [Multiple side panels][sample-sp-multiple] for a complete sample. + +## Side panel user experience {: #user-experience } + +Users will see Chrome's built-in side panels first. Each side panel displays the extension's icon in the side panel menu. If no icons are included, it will show a placeholder icon with the first letter of the extension's name. + +### Opening the side panel {: #open } + +Navigating to the side panel menu +: Users can find available side panels on the side panel menu. Then, they can choose an extension from the drop-down menu. + +
+ {% Img src="image/BhuKGJaIeLNPW9ehns59NfwqKxF2/2uFG8qxM7cqyMuXWlD9R.png", alt="Side panel drop-down menu", width="291", height="366" %} +
+ Chrome browser side panel UI. +
+
+ +Using the action toolbar icon +: Users can open the side panel by clicking on [the action icon](#open-action-icon) if it's enabled. + +Using a keyboard shortcut +: Users can open the side panel by pressing a keyboard shortcut if the [action command][action-commands] and the [action icon](#open-action-icon) are enabled. + + +## Extension samples {: #examples } + +For more Side Panel API extensions demos, explore any of the following extensions: + +- [Site-specific side panel][sample-sp-google]. +- [Multiple side panels][sample-sp-multiple]. +- [Global side panel][sample-sp-global]. +- [Dictionary side panel][sample-sp-dictionary]. + +[action-commands]: /docs/extensions/reference/commands/#action-commands +[api-action]: /docs/extensions/reference/action/ +[doc-manifest]: /docs/extensions/mv3/manifest/ +[runtime-oninstalled]: /docs/extensions/reference/runtime/#event-onInstalled +[sample-sp-dictionary]: https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/functional-samples/sample.sidepanel-dictionary +[sample-sp-global]: https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/functional-samples/cookbook.sidepanel-global +[sample-sp-google]: https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/functional-samples/cookbook.sidepanel-site-specific +[sample-sp-multiple]: https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/functional-samples/cookbook.sidepanel-multiple +[sidepanel-getoptions]:#method-getOptions +[sidepanel-set-behavior]: #method-setPanelBehavior +[sidepanel-setoptions]: #method-setOptions +[tabs-onupdated]: /docs/extensions/reference/tabs/#event-onUpdated + + + From dc615e92f48ba7cb74c3914af1fdba5100b1ae22 Mon Sep 17 00:00:00 2001 From: Sofia Emelianova <42939855+sofiayem@users.noreply.github.com> Date: Fri, 5 May 2023 16:21:02 +0100 Subject: [PATCH 167/982] What's new in DevTools 114 (#6207) * draft 1: recorder assertions and lighthouse * perf: profile() and JS deprecation 3 * performance.mark() * perf: INP warning * minor edits * minor edit * autofill * misc * wasm * fix link * edits * edit * minor edit * add info on lighthouse * minor upds + hero * upd vide: attr assert now has editor * upd partials * Update site/en/blog/new-in-devtools-114/index.md Co-authored-by: Rachel Andrew * fix build --------- Co-authored-by: Rachel Andrew --- site/en/_partials/devtools/whats-new.md | 14 ++ site/en/blog/new-in-devtools-114/index.md | 170 ++++++++++++++++++++++ 2 files changed, 184 insertions(+) create mode 100644 site/en/blog/new-in-devtools-114/index.md diff --git a/site/en/_partials/devtools/whats-new.md b/site/en/_partials/devtools/whats-new.md index b64dba14b..cc3b68ab8 100644 --- a/site/en/_partials/devtools/whats-new.md +++ b/site/en/_partials/devtools/whats-new.md @@ -4,6 +4,20 @@ A list of everything that has been covered in the [What's New In DevTools](/tags {# $content #} +### Chrome 114 {: #chrome114 } + +* [WebAssembly debugging support](/blog/new-in-devtools-114/#wasm) +* [Improved stepping behavior in Wasm apps](/blog/new-in-devtools-114/#wasm-step) +* [Debug Autofill using the Elements panel and Issues tab](/blog/new-in-devtools-114/#autofill) +* [Assertions in Recorder](/blog/new-in-devtools-114/#recorder) +* [Lighthouse 10.1.1](/blog/new-in-devtools-114/#lighthouse) +* [Performance enhancements](/blog/new-in-devtools-114/#performance) +* [performance.mark() shows timing on hover in Performance > Timings](/blog/new-in-devtools-114/#mark) +* [profile() command populates Performance > Main](/blog/new-in-devtools-114/#profile) +* [Warning for slow user interactions](/blog/new-in-devtools-114/#slow-interaction-warning) +* [JavaScript Profiler deprecation: Phase three](/blog/new-in-devtools-114/#js-profiler) +* [Miscellaneous highlights](/blog/new-in-devtools-114/#misc) + ### Chrome 113 {: #chrome113 } * [Override network response headers](/blog/new-in-devtools-113/#network) diff --git a/site/en/blog/new-in-devtools-114/index.md b/site/en/blog/new-in-devtools-114/index.md new file mode 100644 index 000000000..3b25a1e58 --- /dev/null +++ b/site/en/blog/new-in-devtools-114/index.md @@ -0,0 +1,170 @@ +--- +layout: 'layouts/blog-post.njk' +title: "What's New in DevTools (Chrome 114)" +authors: + - sofiayem + - jecelynyeen +date: 2023-05-05 +description: "" +hero: 'image/NJdAV9UgKuN8AhoaPBquL7giZQo1/fy7JKyzJt0EPZd1g8hwl.jpg' +alt: 'WebAssembly debugging, Autofill debugging, better assertions in Recorder, Performance panel enhancements, Lighthouse 10.1.1, and more.' +tags: + - new-in-devtools + - devtools + - chrome-114 +--- + + +{% Partial 'devtools/banner.md' %} + +*There is no 'What's new in DevTools' video for this release, but you can watch this quick recap of the recent features.* + +{% YouTube id='CrSmjooOEiE' %} + + + +## WebAssembly debugging support {: #wasm } + +DevTools enables {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/9gzXiTYY0nZzBxGI6KrV.svg", alt="Settings.", width="24", height="24" %} **Settings** > **Experiments** > {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/hmp8j3HiLMCcqPArD9yt.svg", alt="Checkbox.", width="22", height="22" %} **WebAssembly Debugging: Enable DWARF support** by default. For more information, see [Debugging WebAssembly with modern tools](/blog/wasm-debugging-2020/). + +This experiment lets you pause execution and debug C and C++ code in Wasm apps, with all the debugging information available to you: + +- Your original source code, mapped using [DWARF](https://dwarfstd.org/) debugging information. +- Understandable function names in call stack. +- Breakpoints support, and more. + +{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/8COHSVU8nn1m9qjHH15z.png", alt="A Wasm application paused in the Debugger.", width="800", height="762" %} + +To test Wasm debugging, install the [C/C++ DevTools Support (DWARF) extension](goo.gle/wasm-debugging-extension) and step through the code in the [Mandelbrot demo](https://emscripten-dbg-stories.netlify.app/mandelbrot.html). + +{# https://chromium.googlesource.com/devtools/devtools-frontend/+/abb3f72ab0c637a1da69fd663c380333e5b6a003 #} + +Chromium issue: [1414289](https://crbug.com/1414289). + +### Improved stepping behavior in Wasm apps {: #wasm-step } + +{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/FBSJosXk2J6rXbRE0baL.svg", alt="Step over.", width="20", height="20" %} **Step over** in your original code now avoids pausing in disassembly (`.wasm` file). Previously, it would pause there. + +However, stepping ends when it lands outside of the function it started in, for example, after returning from the function. + +This behavior is enabled by default in {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/9gzXiTYY0nZzBxGI6KrV.svg", alt="Settings.", width="24", height="24" %} [**Settings** > **Preferences** > **Sources**](/docs/devtools/settings/preferences/#sources). + +{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/jhEckqLwOGILepWT8QRN.png", alt="The new setting in Preferences > Sources.", width="800", height="516" %} + +{# https://chromium.googlesource.com/devtools/devtools-frontend/+/87db8b89918cc2f7b18e2623a3c7df810e32da82 #} + +Chromium issue: [1418938](https://crbug.com/1418938). + +## Debug Autofill using the Elements panel and Issues tab {: #autofill } + +[Chrome Autofill](https://support.google.com/chrome/answer/142893) fills in forms automatically with saved information, like your addresses or payment information. To let you easily debug Autofill-related issues, the **Elements** panel can now highlight them with red curly underlines. + +To check out this feature, enable {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/9gzXiTYY0nZzBxGI6KrV.svg", alt="Settings.", width="24", height="24" %} **Settings** > **Experiments** > {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/hmp8j3HiLMCcqPArD9yt.svg", alt="Checkbox.", width="22", height="22" %} **Highlights a violating node or attribute in the Elements panel DOM tree** and inspect this [demo page](http://form-problems.glitch.me/). + +{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/VNEcEhKsc243YE218B7R.png", alt="Autofill issues highlighted in the Elements panel and reported by the Issues panel.", width="800", height="762" %} + +Hover over a highlighted issue in the DOM tree and click **View issue** to open the **Issues** tab that lists all detected issues and provides clues on what went wrong. + +{# https://chromium.googlesource.com/devtools/devtools-frontend/+/0461387468dc7258322216206391b925542b1207 #} +{# https://chromium.googlesource.com/devtools/devtools-frontend/+/7faa8cda6e13cd7bf4a7b199d90006dcab574b42 #} + +Chromium issue: [1399414](https://crbug.com/1399414). + +## Assertions in Recorder {: #recorder } + +The **Recorder** panel now lets you add assertions right during recording, with all the runtime data available to you. + +To add an assertion, start a new recording, interact with your page, and click **Add assertion**. The **Recorder** inserts a step with the [`waitForElement` type](/docs/devtools/recorder/reference/#step-properties) that you can customize on the fly. Watch the video to see assertions in action on the [coffee cart demo](https://coffee-cart.app/). + +{% Video src="video/NJdAV9UgKuN8AhoaPBquL7giZQo1/BNpFsEc4rzFsLVPE5EH2.mp4", controls="true", muted="true", class="screenshot" %} + +This video shows you how to assert: + +- HTML attributes, for example, an element's `class`. +- JavaScript properties in JSON, for example, `.innerText`. + +You can also configure steps to assert, for example, conditional statements in JavaScript, number of node's children (`count`), element visibility, and more. For more information, see [Configure steps](/docs/devtools/recorder/reference/#configure-steps). + +Additionally, the **Recorder** now remembers your preferred script format in the [side-by-side code view](/docs/devtools/recorder/reference/#inspect-code) and right-click step menu. + +{# https://chrome-internal.googlesource.com/devtools/devtools-internal/+/67b9e72b50d50c5e959ccfebe202b486a3417736 #} + +Chromium issue: [1423624](https://crbug.com/1423624). + +## Lighthouse 10.1.1 {: #lighthouse } + +The **Lighthouse** panel now runs Lighthouse 10.1.1, with a notable change introduced in [10.1.0](https://github.com/GoogleChrome/lighthouse/releases/tag/v10.1.0). All audits that deal with URLs are now grouped by entity and aggregate numerical statistics such as size or duration. Popular third parties are also tagged with their category so it's easier to identify their purpose on the page. + +{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/mKXh4UJb8OBM9rCNQv5M.png", alt="Grouped audits by entity.", width="800", height="736" %} + +To learn the basics of using the **Lighthouse** panel in DevTools, see [Lighthouse: Optimize website speed](/docs/devtools/lighthouse/). + +{# https://chromium.googlesource.com/devtools/devtools-frontend/+/9ba6ed7f9e83373c5395aa30c66dd6c81f0efec0 #} +{# https://chromium.googlesource.com/devtools/devtools-frontend/+/c2fc9fa0d279c8ed597688032a015063fa894b36 #} + +Chromium issue: [772558](https://crbug.com/772558). + +## Performance enhancements {: #performance } + +### `performance.mark()` shows timing on hover in Performance > Timings {: #mark } + +The [performance.mark() method](https://developer.mozilla.org/docs/Web/API/Performance/mark) now shows its timing when you hover over the corresponding mark in **Performance** > **Timings**. The timing here is a timestamp relative to the previous navigation event. + +{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/81B2NfenvYRiUK1uPiz8.png", alt="The pop-up with timing on hover in the Timings section.", width="800", height="782" %} + +{# https://chromium.googlesource.com/devtools/devtools-frontend/+/7b27d0a56548b9c5adc8bdae13751fae7f658515 #} + +Chromium issue: [1426762](https://crbug.com/1426762). + +### `profile()` command populates Performance > Main {: #profile } + +The [`profile()` and `profileEnd()` commands](/docs/devtools/console/utilities/#profile-function) in the **Console** now start and stop CPU profiling in the [**Main** thread](/docs/devtools/performance/reference/#main) of the **Performance** panel. + +{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/WPSIhGfU4uO1X2t71poK.png", alt="The console() command creates a profile in the Performance panel.", width="800", height="591" %} + +{# https://chromium.googlesource.com/devtools/devtools-frontend/+/f8fc1cc8b2c26c46e22b7af16b42122acccc13f6 #} + +Chromium issue: [1429191](https://crbug.com/1429191). + +### Warning for slow user interactions {: #slow-interaction-warning } + +User interactions longer than 200 milliseconds get an [Interaction to Next Paint (INP)](https://web.dev/inp/) warning in the **Performance** > **Summary** tab. + +{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/wrFaZ26nYCuprtCSNB5C.png", alt="The INP warning.", width="800", height="685" %} + +Additionally, the ID of the interaction has been moved from the tooltip to **Summary**. + +{# https://chromium.googlesource.com/devtools/devtools-frontend/+/e73984213b6dfdc2f858ed1edfe323d7755d757f #} +{# https://chromium.googlesource.com/devtools/devtools-frontend/+/7e33a26c738bcd848aacd140248d285b9db31704 #} + +Chromium issues: [1432512](https://crbug.com/1432512), [1432509](https://crbug.com/1432509). + +## JavaScript Profiler deprecation: Phase three {: #js-profiler } + +As early as [Chrome 58](/blog/devtools-javascript-cpu-profile-migration-2/), the DevTools team planned to eventually deprecate the **JavaScript Profiler** and have Node.js and Deno developers use the **Performance** panel for profiling JavaScript CPU performance. + +DevTools version 114 starts *phase three* of the [four-phase **JavaScript Profiler** deprecation](https://github.com/ChromeDevTools/rfcs/discussions/2#discussioncomment-5189668). During this phase, the **JavaScript Profiler** panel is removed from DevTools but you can still temporarily enable it via {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/9gzXiTYY0nZzBxGI6KrV.svg", alt="Settings.", width="24", height="24" %} [**Settings** > **Experiments**](/docs/devtools/settings/experiments/) and open it from the {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/N5Lkpdwpaz4YqRGFr2Ks.svg", alt="Three-dot menu.", width="24", height="24" %} three-dot menu. + +{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/iEkxGNsTwKYYMP2nCxfY.png", alt="JavaScript profiler checkbox in Settings > Experiments.", width="800", height="507" %} + +To profile CPU performance, use the **Performance** panel. + +{# https://chromium.googlesource.com/devtools/devtools-frontend/+/fecc2e9a652f3b4cb830555c9d991b66ecf3ddf0 #} + +Chromium issue: [1428026](https://crbug.com/1428026). + +## Miscellaneous highlights {: #misc } + +These are some noteworthy fixes in this release: + +- The [Color Picker](/docs/devtools/css/color/) now detects HWB values that are [out of gamut](/docs/devtools/css/color/#convert-colors) when clipped ([1429271](https://crbug.com/1429271)). +- The **Sources** panel: + - Enabled JSON syntax highlighting for source maps ([1385374](https://crbug.com/1385374)). + - Stopped showing "Source map detected" messages when you manually [disable source maps](/docs/devtools/javascript/source-maps/#enable_source_maps_in_settings) ([1423718](https://crbug.com/1423718)). +- The **Console** now lets you evaluate incomplete JavaScript expressions with Ctrl + Enter and outputs syntax errors ([1314700](https://crbug.com/1314700)). +- The [Breakpoint editing dialog](/docs/devtools/javascript/breakpoints/#edit-breakpoints) now has a close button. Previously, you had to press Enter or unfocus the dialog ([1412980](https://crbug.com/1412980)). + + + +{% Partial 'devtools/reach-out.md' %} +{% Partial 'devtools/whats-new.md' %} From bb4046dbda8e70cf6b61903a5ad6d241f0935672 Mon Sep 17 00:00:00 2001 From: Sebastian Benz Date: Fri, 5 May 2023 20:20:53 +0200 Subject: [PATCH 168/982] Rename Partial Custom Tab guide based on prod feedback (#6206) --- .../android/custom-tabs/guide-partial-custom-tabs/index.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/site/en/docs/android/custom-tabs/guide-partial-custom-tabs/index.md b/site/en/docs/android/custom-tabs/guide-partial-custom-tabs/index.md index 667b5a3ec..e7a3310fe 100644 --- a/site/en/docs/android/custom-tabs/guide-partial-custom-tabs/index.md +++ b/site/en/docs/android/custom-tabs/guide-partial-custom-tabs/index.md @@ -1,14 +1,14 @@ --- layout: "layouts/doc-post.njk" -title: Resizing with partial Custom Tabs -seoTitle: "Guide: resize a Custom Tab with Partial Custom Tabs" +title: Multi-tasking with Partial Custom Tabs +seoTitle: "Guide: Multi-tasking with Partial Custom Tabs" date: 2023-04-21 description: Learn how to you use partial Custom Tabs to let your users interact with your app while viewing web content. authors: - sebastianbenz --- -By default, Custom Tabs launch as a full-window activity. Starting in Chrome 107, you can use partial Custom Tabs to specify a different launch height in portrait mode such that users can interact with your app while viewing web content. Users can expand the Custom Tab to full-screen by dragging the toolbar handle up and restoring the initial launch height by dragging the handle down. +By default, Custom Tabs launch as a full-window activity. Starting in Chrome 107, you can use partial Custom Tabs to specify a different launch height in portrait mode such that users can multitask by interacting with your app while viewing web content. Users can expand the Custom Tab to full-screen by dragging the toolbar handle up and restoring the initial launch height by dragging the handle down. {% Img src="image/6AZNJBRnkpQUWTKPzig99lQY8jT2/iMTvWNK7aEqqxHEHEXuv.png", alt="Example Partial Tab", width="320", height="640", class="screenshot screenshot--filled" %} From a4b5638e412bdec955979b5d727bf71fc6d34e76 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 May 2023 09:16:43 +0200 Subject: [PATCH 169/982] Bump @mdn/browser-compat-data from 5.2.55 to 5.2.56 (#6219) Bumps [@mdn/browser-compat-data](https://github.com/mdn/browser-compat-data) from 5.2.55 to 5.2.56. - [Release notes](https://github.com/mdn/browser-compat-data/releases) - [Changelog](https://github.com/mdn/browser-compat-data/blob/main/RELEASE_NOTES.md) - [Commits](https://github.com/mdn/browser-compat-data/compare/v5.2.55...v5.2.56) --- updated-dependencies: - dependency-name: "@mdn/browser-compat-data" dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package-lock.json | 16 ++++++++-------- package.json | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/package-lock.json b/package-lock.json index bd116e904..1d8ec9729 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,7 +18,7 @@ "@google-cloud/error-reporting": "^2.0.4", "@google-cloud/storage": "^6.7.0", "@lhci/cli": "^0.7.2", - "@mdn/browser-compat-data": "5.2.55", + "@mdn/browser-compat-data": "5.2.56", "@rollup/plugin-node-resolve": "^8.4.0", "algoliasearch": "^4.6.0", "async-transforms": "1.0.6", @@ -75,7 +75,7 @@ "gts": "^3.1.0", "html-escaper": "^2.0.2", "husky": "^4.3.0", - "lint-staged": "^13.2.2", + "lint-staged": "13.2.2", "micromatch": "4.0.5", "mvdir": "^1.0.21", "nyc": "^15.1.0", @@ -2290,9 +2290,9 @@ } }, "node_modules/@mdn/browser-compat-data": { - "version": "5.2.55", - "resolved": "https://registry.npmjs.org/@mdn/browser-compat-data/-/browser-compat-data-5.2.55.tgz", - "integrity": "sha512-V5y5VhgXobwZl817zn+iAlCSTbXIXBMRHbL2WDyjJyMMgcHZoQTk6db1y3ZxBUo/H23MXgTKBo7bQ9S8aEfs2A==" + "version": "5.2.56", + "resolved": "https://registry.npmjs.org/@mdn/browser-compat-data/-/browser-compat-data-5.2.56.tgz", + "integrity": "sha512-1Pu6qcdJ1tQApjhWONtf8XtXH4bG9qnRyry+mYzNgZhfawoO2ODJWasvDf4pgEPlaHbxxFuZFL5l3UeKCdS3Xg==" }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", @@ -28513,9 +28513,9 @@ } }, "@mdn/browser-compat-data": { - "version": "5.2.55", - "resolved": "https://registry.npmjs.org/@mdn/browser-compat-data/-/browser-compat-data-5.2.55.tgz", - "integrity": "sha512-V5y5VhgXobwZl817zn+iAlCSTbXIXBMRHbL2WDyjJyMMgcHZoQTk6db1y3ZxBUo/H23MXgTKBo7bQ9S8aEfs2A==" + "version": "5.2.56", + "resolved": "https://registry.npmjs.org/@mdn/browser-compat-data/-/browser-compat-data-5.2.56.tgz", + "integrity": "sha512-1Pu6qcdJ1tQApjhWONtf8XtXH4bG9qnRyry+mYzNgZhfawoO2ODJWasvDf4pgEPlaHbxxFuZFL5l3UeKCdS3Xg==" }, "@nodelib/fs.scandir": { "version": "2.1.5", diff --git a/package.json b/package.json index f4804f0e7..75ca9d022 100644 --- a/package.json +++ b/package.json @@ -52,7 +52,7 @@ "@google-cloud/error-reporting": "^2.0.4", "@google-cloud/storage": "^6.7.0", "@lhci/cli": "^0.7.2", - "@mdn/browser-compat-data": "5.2.55", + "@mdn/browser-compat-data": "5.2.56", "@rollup/plugin-node-resolve": "^8.4.0", "algoliasearch": "^4.6.0", "async-transforms": "1.0.6", From 44acd5710733f670e32f416fb3fc357b37910c7d Mon Sep 17 00:00:00 2001 From: Shay Punter Date: Mon, 8 May 2023 08:45:16 +0100 Subject: [PATCH 170/982] Add multiple authors design (#6203) * feat: add multiple authors new design * feat: migrated postauthors macro into post author macro --- site/_includes/macros/post-author.njk | 160 ++++++++++++++++------- site/_includes/partials/post-authors.njk | 6 +- site/_scss/blocks/_post-authors.scss | 13 ++ 3 files changed, 124 insertions(+), 55 deletions(-) diff --git a/site/_includes/macros/post-author.njk b/site/_includes/macros/post-author.njk index aab703fd2..ea2b02204 100644 --- a/site/_includes/macros/post-author.njk +++ b/site/_includes/macros/post-author.njk @@ -1,59 +1,119 @@ {# - Renders an author info snippet. - If there's no data for the author, just renders their ID. This isn't ideal but is better than - crashing. +Renders an author info snippet. +If there's no data for the author, just renders their ID. This isn't ideal but is better than +crashing. +If there are more than 3 authors, it will render a condensed view #} -{% macro postAuthor(authorId, locale) %} +{% macro postAuthor(authors, locale) %} -{% set author = authorsData[authorId] %} -{% set authorTitle = 'i18n.authors.' + authorId + '.title' %} -{% set authorDescription = 'i18n.authors.' + authorId + '.description' %} -{% set authorImage = author.image or site.defaultAvatarImg %} + {# + Renders the default author view if there are less than three authors + #} + {% if authors.length < 3 %} +
``` ```css label { From 1792d5f1f0b0c57c1443dda953939a72c022a238 Mon Sep 17 00:00:00 2001 From: Johnny J Date: Mon, 31 Jul 2023 19:12:10 +0800 Subject: [PATCH 592/982] fix: link 404 (#6334) --- site/en/blog/whats-new-css-ui-2023/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/en/blog/whats-new-css-ui-2023/index.md b/site/en/blog/whats-new-css-ui-2023/index.md index aaf91ce61..cf955cb4b 100644 --- a/site/en/blog/whats-new-css-ui-2023/index.md +++ b/site/en/blog/whats-new-css-ui-2023/index.md @@ -213,7 +213,7 @@ The letter’s block-offset, or “sink”, for where the letter will sit. } %} -Learn more about using `intial-letter` [here](](/blog/control-your-drop-caps-with-css-initial-letter/)). +Learn more about using `intial-letter` [here](](/blog/control-your-drop-caps-with-css-initial-letter/). ### Dynamic viewport units From b650654b92f14a938e9ddc81dc58af42c2a107c0 Mon Sep 17 00:00:00 2001 From: SendBeesToMars <18416329+SendBeesToMars@users.noreply.github.com> Date: Mon, 31 Jul 2023 12:13:08 +0100 Subject: [PATCH 593/982] link fix (#6654) changed https://web.dev/javascript-async-functions/ to https://web.dev/async-functions/ former link 404's. It's the same article, checked wayback machine. --- site/en/blog/background-fetch/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/en/blog/background-fetch/index.md b/site/en/blog/background-fetch/index.md index accee720a..39b269d90 100644 --- a/site/en/blog/background-fetch/index.md +++ b/site/en/blog/background-fetch/index.md @@ -108,7 +108,7 @@ navigator.serviceWorker.ready.then(async (swReg) => { {% Aside %} Many examples in this article use async functions. If you aren't familiar with them, [check -out the guide](https://web.dev/javascript-async-functions/). +out the guide](https://web.dev/async-functions/). {% endAside %} `backgroundFetch.fetch` takes three arguments: From 2cfb932f41beed6a92376d1361cae36bc02e9216 Mon Sep 17 00:00:00 2001 From: Xavi Ivars Date: Mon, 31 Jul 2023 13:28:22 +0200 Subject: [PATCH 594/982] Fix History API link (#6930) --- site/en/docs/crux/methodology/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/en/docs/crux/methodology/index.md b/site/en/docs/crux/methodology/index.md index 3c6443814..59bdcadbf 100644 --- a/site/en/docs/crux/methodology/index.md +++ b/site/en/docs/crux/methodology/index.md @@ -234,7 +234,7 @@ The CrUX API returns more quickly than the [PageSpeed Insights API](#tool-psi-ap ### CrUX History API {: #tool-crux-history-api} -The [CrUX History API](/docs/crux/historical-api/) provides programmatic access to CrUX historical data by page or origin, and can be further filtered by form factor, effective connection type and metrics. +The [CrUX History API](/docs/crux/history-api/) provides programmatic access to CrUX historical data by page or origin, and can be further filtered by form factor, effective connection type and metrics. The API provides [Web Vitals](https://web.dev/vitals/) metrics both by origin and at page-level and the data is updated weekly. The only values provided for metrics are calculated from the past 25 weekly collection periods of 28 days as a rolling window. From d547be22a9bf95dfe18d883035fe4a164114548f Mon Sep 17 00:00:00 2001 From: mac <6609519+macplox@users.noreply.github.com> Date: Mon, 31 Jul 2023 04:29:09 -0700 Subject: [PATCH 595/982] Update index.md (remove broken links) (#6841) Broken link: Temporary* private USB host API This content has not been published and remains inaccessible. The API mentioned has been deprecated already. --- site/en/docs/apps/migration/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/en/docs/apps/migration/index.md b/site/en/docs/apps/migration/index.md index cd6b4a310..41302bee5 100644 --- a/site/en/docs/apps/migration/index.md +++ b/site/en/docs/apps/migration/index.md @@ -68,7 +68,7 @@ Chrome App API/Capability migration recommendations (current as of Nov. 2019): +chrome.serial
Chrome App feature/functionalityWeb platform migration recommendationsAndroid migration recommendationsExtension migration recommendations
chrome.accessibilityFeatureschrome.accessibilityFeatures
chrome.alarmsNotification TriggersWorkManagerchrome.alarms
chrome.app.runtimeLaunch EventActivity Lifecycle
chrome.app.runtime.onRestartedPage Life CycleActivity.onResume
chrome.app.windowWindow Placement / Screen Enumerationchrome.windows
chrome.audioAudio Device ClientSome Audio APIs
chrome.bluetoothWeb Bluetooth APIBluetooth API
chrome.bluetoothLowEnergyWeb Bluetooth APIBTLE
chrome.bluetoothSocketWeb Bluetooth APIBluetooth Socket
chrome.browserwindow.openIntent system
chrome.commandsUI EventsHard-code keyboard commandschrome.commands
chrome.contextMenus(HTML/script)Native, Android has its own contextmenus
chrome.documentScanchrome.documentScan
chrome.eventsAlarmschrome.events
chrome.extensionTypesN/Achrome.extensionTypes
chrome.fileSystem Native FileSystem API
chrome.fileSystemProviderFileSystemProviderchrome.fileSystemProvider
chrome.gcmWeb Push NotificationsN/Achrome.gcm
chrome.hidWeb HID API
chrome.i18n(HTML/script)Localizationchrome.i18n
chrome.identityOAuth API or Credential Management APINativechrome.identity
chrome.idleUser Idle Detection APIchrome.idle
chrome.instanceIDWeb pushPer-App ID needs to be self-generatedchrome.instanceID
chrome.mdnsNDS discovery
chrome.mediaGalleriesNative FileSystem API
chrome.networking.onc
chrome.notificationsNotifications APINotifications show in lower right of CrOS as system level notificationschrome.notifications
chrome.permissionsWeb Permissions APIN/Achrome.permissions
chrome.powerWakeLock APIIn discussionchrome.power
chrome.printerProviderTransition to Extensionandroid.printservicechrome.printerProvider
chrome.runtimeService Workers + Page Lifecycle APIchrome.runtime
chrome.runtime.connectChannel Messaging APIchrome.runtime.connect
chrome.runtime.sendMessagechrome.runtime.sendMessage
-chrome.serialWeb Serial API
chrome.sockets.tcpQuicTransport C/S (or WebSockets)android.net.ConnectivityManager and Java standard socket API
chrome.sockets.tcpServerandroid.net.ConnectivityManager and Java standard socket API
chrome.sockets.udpQuicTransport C/SDatagramSocket API for UDP
chrome.storageCache API
IndexedDB
chrome.storage
chrome.storage.managedManaged Configurationschrome.storage.managed
chrome.syncFileSystemJava - Drive REST API
chrome.system.cpunavigator.hardwareConcurrencychrome.system.cpu
chrome.system.displaywindow.screenDisplayMetrics, but high density displays are wonky
chrome.system.memorynavigator.deviceMemorychrome.system.memory
chrome.system.networkNetwork Information API
chrome.system.storagenavigator.storagechrome.system.storage
chrome.ttsWeb Speech API (Synthesis)Android TTS 2009chrome.tts
chrome.typeschrome.types
chrome.usbWeb USB APITemporary* private USB host API
chrome.virtualKeyboardSoft Input Method
chrome.vpnProviderVpnServiceWeb Serial API
chrome.sockets.tcpQuicTransport C/S (or WebSockets)android.net.ConnectivityManager and Java standard socket API
chrome.sockets.tcpServerandroid.net.ConnectivityManager and Java standard socket API
chrome.sockets.udpQuicTransport C/SDatagramSocket API for UDP
chrome.storageCache API
IndexedDB
chrome.storage
chrome.storage.managedManaged Configurationschrome.storage.managed
chrome.syncFileSystemJava - Drive REST API
chrome.system.cpunavigator.hardwareConcurrencychrome.system.cpu
chrome.system.displaywindow.screenDisplayMetrics, but high density displays are wonky
chrome.system.memorynavigator.deviceMemorychrome.system.memory
chrome.system.networkNetwork Information API
chrome.system.storagenavigator.storagechrome.system.storage
chrome.ttsWeb Speech API (Synthesis)Android TTS 2009chrome.tts
chrome.typeschrome.types
chrome.usbWeb USB API
chrome.virtualKeyboardSoft Input Method
chrome.vpnProviderVpnService chrome.vpnProvider
chrome.wallpaperWallpaperManagerchrome.wallpaper
externally_connectable
kiosk_enabled
minimum_chrome_versionTarget Android versionminimum_chrome_version
offline_enabledOffline via Service WorkersNative
NaClMigration Guide
<webview> tagNativeWebView
## FAQs {: #faqs } From 4555a19f8987aa975e6d940761220501c1c89f0b Mon Sep 17 00:00:00 2001 From: Joe Medley Date: Mon, 31 Jul 2023 08:24:44 -0700 Subject: [PATCH 596/982] Add a missing space. (#6950) --- site/en/docs/extensions/reference/printing/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/en/docs/extensions/reference/printing/index.md b/site/en/docs/extensions/reference/printing/index.md index 0741c76c6..2d49fdf28 100644 --- a/site/en/docs/extensions/reference/printing/index.md +++ b/site/en/docs/extensions/reference/printing/index.md @@ -69,7 +69,7 @@ The `submitJob()` method requires three things. Calling `submitJob()` triggers a dialog box asking the user to confirm printing. Use the [`PrintingAPIExtensionsAllowlist`](https://chromeenterprise.google/policies/#PrintingAPIExtensionsAllowlist") to bypass confirmation. -This is a simplified version of the printing example. Notice that the `ticket` is attached to the `SubmitJobRequest` structure (line 8) and that the data to print is converted to a blob (line 10). Getting the ID of the printer (line 1) is more complicated [in the sample](https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/api-samples/printing)than is shown here. +This is a simplified version of the printing example. Notice that the `ticket` is attached to the `SubmitJobRequest` structure (line 8) and that the data to print is converted to a blob (line 10). Getting the ID of the printer (line 1) is more complicated [in the sample](https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/api-samples/printing) than is shown here. ```javascript/0,7,9 const defaultPrinter = getDefaultPrinter(); From 8519e499afa78f484fa8b27a6f32f46b93c8c8e9 Mon Sep 17 00:00:00 2001 From: Joe Medley Date: Mon, 31 Jul 2023 08:25:55 -0700 Subject: [PATCH 597/982] Fix a broken link. (#6951) --- site/en/docs/extensions/reference/alarms/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/en/docs/extensions/reference/alarms/index.md b/site/en/docs/extensions/reference/alarms/index.md index 89c6630a0..c3bdaad40 100644 --- a/site/en/docs/extensions/reference/alarms/index.md +++ b/site/en/docs/extensions/reference/alarms/index.md @@ -43,4 +43,4 @@ chrome.alarms.onAlarm.addListener((alarm) => { ``` [repo-samples]: https://github.com/GoogleChrome/chrome-extensions-samples -[sample-example]; https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/api-samples/alarms \ No newline at end of file +[sample-example]: https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/api-samples/alarms From 3af760e3f0e2b7580a9908893fb7bac70ede8cfd Mon Sep 17 00:00:00 2001 From: Daniel <47279376+mdee5test@users.noreply.github.com> Date: Mon, 31 Jul 2023 16:27:33 +0100 Subject: [PATCH 598/982] Update index.md (#6832) There was a typo in the mSession variable inside the method, "onServiceDisconnected()". This led to errors. --- site/en/docs/android/custom-tabs/guide-warmup-prefetch/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/en/docs/android/custom-tabs/guide-warmup-prefetch/index.md b/site/en/docs/android/custom-tabs/guide-warmup-prefetch/index.md index 4554e3421..7bc90efe2 100644 --- a/site/en/docs/android/custom-tabs/guide-warmup-prefetch/index.md +++ b/site/en/docs/android/custom-tabs/guide-warmup-prefetch/index.md @@ -64,7 +64,7 @@ private CustomTabsServiceConnection mConnection = new CustomTabsServiceConnectio @Override public void onServiceDisconnected(ComponentName name) { mClient = null; - mSesssion = null; + mSession = null; } }; From 63b2feb669089163986624fea0d83d1d5c98b79d Mon Sep 17 00:00:00 2001 From: Joe Medley Date: Mon, 31 Jul 2023 09:16:37 -0700 Subject: [PATCH 599/982] Asides don't need 2 imperatives (#6952) * Asides don't need 2 imperatives * Update site/en/docs/extensions/reference/devtools_inspectedWindow/index.md Co-authored-by: amysteamdev <37001393+AmySteam@users.noreply.github.com> --------- Co-authored-by: amysteamdev <37001393+AmySteam@users.noreply.github.com> --- .../docs/extensions/reference/devtools_inspectedWindow/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/en/docs/extensions/reference/devtools_inspectedWindow/index.md b/site/en/docs/extensions/reference/devtools_inspectedWindow/index.md index 25d8faaf7..4e42e4e7c 100644 --- a/site/en/docs/extensions/reference/devtools_inspectedWindow/index.md +++ b/site/en/docs/extensions/reference/devtools_inspectedWindow/index.md @@ -46,7 +46,7 @@ Here are the main differences between the `eval` and `tabs.executeScript` method {% Aside 'caution' %} -**Important:** Due to the security considerations explained above, the [`tabs.executeScript`][4] +Due to the security considerations explained above, the [`scripting.executeScript`](/docs/extensions/reference/scripting#method-executeScript) method is the preferred way for an extension to access DOM data of the inspected page in cases where the access to JavaScript state of the inspected page is not required. From fcf65b778d33b82f39b47f80031c2203e0ebb014 Mon Sep 17 00:00:00 2001 From: Daniel <47279376+mdee5test@users.noreply.github.com> Date: Mon, 31 Jul 2023 17:17:27 +0100 Subject: [PATCH 600/982] Update index.md (#6831) Added "Uri.parse()" to the mSession.mayLaunchUrl() method. Required parameter is of type "Uri", but supplied parameter is of type "String". --- site/en/docs/android/custom-tabs/guide-warmup-prefetch/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/en/docs/android/custom-tabs/guide-warmup-prefetch/index.md b/site/en/docs/android/custom-tabs/guide-warmup-prefetch/index.md index 7bc90efe2..fbf2b108b 100644 --- a/site/en/docs/android/custom-tabs/guide-warmup-prefetch/index.md +++ b/site/en/docs/android/custom-tabs/guide-warmup-prefetch/index.md @@ -58,7 +58,7 @@ private CustomTabsServiceConnection mConnection = new CustomTabsServiceConnectio mSession = mClient.newSession(new CustomTabsCallback()); // Pre-render pages the user is likely to visit // you can do this any time while the service is connected - mSession.mayLaunchUrl("https://developers.android.com", null, null); + mSession.mayLaunchUrl(Uri.parse("https://developers.android.com"), null, null); } @Override From 99377949be4330336198de290dcecd3476ea85ca Mon Sep 17 00:00:00 2001 From: Anusmita Date: Mon, 31 Jul 2023 18:21:55 +0100 Subject: [PATCH 601/982] Update images (#6962) --- site/en/blog/bounce-tracking-mitigations-dev-trial/index.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/site/en/blog/bounce-tracking-mitigations-dev-trial/index.md b/site/en/blog/bounce-tracking-mitigations-dev-trial/index.md index 6e38418c2..250272322 100644 --- a/site/en/blog/bounce-tracking-mitigations-dev-trial/index.md +++ b/site/en/blog/bounce-tracking-mitigations-dev-trial/index.md @@ -71,7 +71,7 @@ Bounce tracking mitigations are available to test with feature flags from Chrome For example, if in step (4) you visit [this demo page](https://bounce-tracking-demo.glitch.me/) and select the "bounce me" link, then you can expect to see a DevTools issue:
-{% Img src="image/udVScdcCFAdRjZwFdLk2jWAFQyr1/YtP70APBL2ZSbBVa2EYX.png", alt="A screenshot of the DevTools issue indicating bounce-tracking-demo-tracker.glitch.me is at risk of being deleted.", width="800", height="218" %} +{% Img src="image/udVScdcCFAdRjZwFdLk2jWAFQyr1/6QPd7ZS0s5F1uDXZberP.png", alt="A screenshot of the DevTools issue indicating bounce-tracking-demo-tracker.glitch.me is at risk of being deleted.", width="800", height="218" %}

Screenshot of the DevTools issue.

@@ -79,7 +79,7 @@ For example, if in step (4) you visit [this demo page](https://bounce-tracking-d Then, in step 6 you can force the deletion to occur immediately by using the DevTools Application Panel:
-{% Img src="image/udVScdcCFAdRjZwFdLk2jWAFQyr1/6QPd7ZS0s5F1uDXZberP.png", alt="A screenshot of the devtools application tab with the bounce tracking mitigations panel selected. The panel shows that the force run operation has been used and storage has been deleted for the demo site.", width="800", height="273" %} +{% Img src="image/udVScdcCFAdRjZwFdLk2jWAFQyr1/YtP70APBL2ZSbBVa2EYX.png", alt="A screenshot of the devtools application tab with the bounce tracking mitigations panel selected. The panel shows that the force run operation has been used and storage has been deleted for the demo site.", width="800", height="273" %}

DevTools bounce tracking mitigations panel.

From 3120e399f202159845faf0f6b24c0a1fa09d3654 Mon Sep 17 00:00:00 2001 From: Joe Medley Date: Mon, 31 Jul 2023 20:12:53 -0700 Subject: [PATCH 602/982] Remove link to old content. (#6963) --- site/en/docs/extensions/mv3/linux_hosting/index.md | 7 ------- 1 file changed, 7 deletions(-) diff --git a/site/en/docs/extensions/mv3/linux_hosting/index.md b/site/en/docs/extensions/mv3/linux_hosting/index.md index 69f06aaf0..fdcf5803e 100644 --- a/site/en/docs/extensions/mv3/linux_hosting/index.md +++ b/site/en/docs/extensions/mv3/linux_hosting/index.md @@ -36,12 +36,6 @@ The downloaded file can be hosted on a personal server. This is the most secure extension locally as the contents of the extension will be signed by the Chrome Web Store. This helps detect potential attacks and tampering. -{% Aside %} - -Read more about the [hosting policy][hosting-changes]. - -{% endAside %} - ### Create .crx locally {: #create } Extension directories are converted to `.crx` files at the Extensions Management Page. Navigate to @@ -274,7 +268,6 @@ This would ensure that users would autoupdate to version 2 only if they are runn [chromium-with-flags]: https://www.chromium.org/developers/how-tos/run-chromium-with-flags [developer-dashboard]: https://chrome.google.com/webstore/developer/dashboard [header-updating]: #update -[hosting-changes]: /docs/extensions/mv2/hosting_changes/ [hosting-options]: /docs/extensions/mv3/hosting [load-locally]: #create [manifest]: /docs/extensions/mv3/manifest/ From 890a8721fd547eefeae050d2635f700b143c4b8d Mon Sep 17 00:00:00 2001 From: Md Rakib Miah Date: Tue, 1 Aug 2023 09:00:40 +0200 Subject: [PATCH 603/982] Update index.md (#6446) --- site/en/blog/introducing-popover-api/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/en/blog/introducing-popover-api/index.md b/site/en/blog/introducing-popover-api/index.md index 95f3c6068..cc5888d1c 100644 --- a/site/en/blog/introducing-popover-api/index.md +++ b/site/en/blog/introducing-popover-api/index.md @@ -40,7 +40,7 @@ You can now build popovers with all of these features without using JavaScript.
-

I am a popover with more information.

+

I am a popover with more information.

``` From 73a26fc3396558d279741194b7595b9e5fbec697 Mon Sep 17 00:00:00 2001 From: Weston Ruter Date: Tue, 1 Aug 2023 00:01:52 -0700 Subject: [PATCH 604/982] Replace curly double quotes with straight double quotes for attribute values (#6411) --- site/en/blog/introducing-popover-api/index.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/site/en/blog/introducing-popover-api/index.md b/site/en/blog/introducing-popover-api/index.md index cc5888d1c..b262db70f 100644 --- a/site/en/blog/introducing-popover-api/index.md +++ b/site/en/blog/introducing-popover-api/index.md @@ -75,7 +75,7 @@ Using `popovertargetaction="hide"`, you can create a “close” button within a ```html ``` @@ -146,7 +146,7 @@ By default, popovers get a 2px border and are positioned in the center of the UI ## The difference between a `popover` and a `dialog` -It's important to note that the `popover` attribute does not provide semantics on its own. And while you can now build modal dialog-like experiences using `popover=”auto”`, there are a few key differences between the two: +It's important to note that the `popover` attribute does not provide semantics on its own. And while you can now build modal dialog-like experiences using `popover="auto"`, there are a few key differences between the two: A `dialog` element opened with `dialog.showModal` (a modal dialog), is an experience which requires explicit user interaction to close the modal. A `popover` supports light-dismiss. A modal `dialog` does not. From 440fb4256c80287a15ea45a7d326cc0147030c20 Mon Sep 17 00:00:00 2001 From: materialknight <95397606+materialknight@users.noreply.github.com> Date: Tue, 1 Aug 2023 01:04:41 -0600 Subject: [PATCH 605/982] Changed casing in 2 words (#4702) * Changed casing in 2 words In line 197, I changed 'InsertAdjacentElement()' to 'insertAdjacentElement()' and in line 198, 'Classlist ' to 'classList', so that the text matches the title of the linked articles and the proper name of the function and the property. * chore: try to force checks to run --------- Co-authored-by: Matthias Rohmer --- .../docs/extensions/mv3/getstarted/tut-reading-time/index.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/site/en/docs/extensions/mv3/getstarted/tut-reading-time/index.md b/site/en/docs/extensions/mv3/getstarted/tut-reading-time/index.md index 9d929068c..d7881f467 100644 --- a/site/en/docs/extensions/mv3/getstarted/tut-reading-time/index.md +++ b/site/en/docs/extensions/mv3/getstarted/tut-reading-time/index.md @@ -194,8 +194,8 @@ if (article) { - [Regular expressions][mdn-regular-expressions] used to count only the words inside the `
` element. -- [InsertAdjacentElement()][mdn-insert-adjacent] used to insert the reading time node after the element. -- The [Classlist][mdn-classlist] property used to add CSS class names to the element class attribute. +- [insertAdjacentElement()][mdn-insert-adjacent] used to insert the reading time node after the element. +- The [classList][mdn-classlist] property used to add CSS class names to the element class attribute. - [Optional chaining][mdn-optional-chaining] used to access an object property that may be undefined or null. - [Nullish coalescing][mdn-nullish-coalescing] returns the `` if the `` is null or undefined. From ea9fc26a47e7e2b5674da598bacb94de3e23fe20 Mon Sep 17 00:00:00 2001 From: Thomas Steiner Date: Tue, 1 Aug 2023 11:19:07 +0200 Subject: [PATCH 606/982] Reflect `.connection` now being called `opened` (#6965) --- site/en/articles/websocketstream/index.md | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/site/en/articles/websocketstream/index.md b/site/en/articles/websocketstream/index.md index 3a1e8a054..21d5f55be 100644 --- a/site/en/articles/websocketstream/index.md +++ b/site/en/articles/websocketstream/index.md @@ -130,7 +130,7 @@ Examples of sites that can use this API include: The WebSocketStream API is promise-based, which makes dealing with it feel natural in a modern JavaScript world. You start by constructing a new `WebSocketStream` and passing it the URL of the WebSocket server. -Next, you wait for the `connection` to be established, +Next, you wait for the connection to be `opened`, which results in a [`ReadableStream`](https://developer.mozilla.org/docs/Web/API/ReadableStream/ReadableStream) and/or a @@ -153,7 +153,7 @@ data to. ```js const wss = new WebSocketStream(WSS_URL); - const {readable, writable} = await wss.connection; + const {readable, writable} = await wss.opened; const reader = readable.getReader(); const writer = writable.getWriter(); @@ -184,18 +184,22 @@ which behaves the same as the ```js const chatWSS = new WebSocketStream(CHAT_URL, {protocols: ['chat', 'chatv2']}); -const {protocol} = await chatWSS.connection; +const {protocol} = await chatWSS.opened; ``` The selected `protocol` as well as potential `extensions` are part of the dictionary -available via the `WebSocketStream.connection` promise. +available via the `WebSocketStream.opened` promise. All the information about the live connection is provided by this promise, since it is not relevant if the connection fails. ```js -const {readable, writable, protocol, extensions} = await chatWSS.connection; +const {readable, writable, protocol, extensions} = await chatWSS.opened; ``` +{% Aside %} +In an earlier version of the API, `WebSocketStream.opened` was called `WebSocketStream.connection`. +{% endAside %} + ### Information about closed WebSocketStream connection The information that was available from the From eaab7bda90128d8fe504bd527a6f7b17cb0adce2 Mon Sep 17 00:00:00 2001 From: Maud Date: Tue, 1 Aug 2023 11:40:08 +0200 Subject: [PATCH 607/982] Added one-time permissions article (#6948) * Added one-time permissions article * Tweaked text * Added tag * Added tags * Apply suggestions from code review Co-authored-by: Rachel Andrew * Removed duplicate sentence * Fixed code reference * Updated publication date --------- Co-authored-by: Rachel Andrew --- site/en/blog/one-time-permissions/index.md | 234 +++++++++++++++++++++ 1 file changed, 234 insertions(+) create mode 100644 site/en/blog/one-time-permissions/index.md diff --git a/site/en/blog/one-time-permissions/index.md b/site/en/blog/one-time-permissions/index.md new file mode 100644 index 000000000..a437bbc57 --- /dev/null +++ b/site/en/blog/one-time-permissions/index.md @@ -0,0 +1,234 @@ +--- +layout: 'layouts/blog-post.njk' +title: 'One-time permissions in Chrome' +description: > + "Allow this time" is a one-time option for permission grants in Chrome. It will initially be available on desktop only for geolocation, camera, and microphone. +authors: + - maudn +date: 2023-08-01 +updated: 2023-08-01 +hero: image/O2RNUyVSLubjvENAT3e7JSdqSOx1/FRytD8YVBZi9P3hAcOXv.jpeg +alt: Permission prompt in Chrome, with the Allow this time option. +tags: + - capabilities + - privacy +--- + + +With a gradual rollout from [Chrome 116](https://chromiumdash.appspot.com/schedule), we will be adding the **Allow this time** option to permission prompts. Our goal is to make it easier for people to use powerful web capabilities on their own terms. **Allow this time** will initially be available on desktop for some of the most common permissions: geolocation, camera, and microphone. Permission prompts for other capabilities and on the mobile web are unchanged for now, but may change in the future. + +**If you're a site owner, review [Impact and Recommendations](#impact-and-recommendations), and try the [demo](#demo).** + +## A new UX for permissions + +### Permissions UX before Chrome 116 + +
+{% Img src="image/O2RNUyVSLubjvENAT3e7JSdqSOx1/TcL9YukUHlkdn1bLbZTv.png", alt="Permission prompt showing only block and allow.", width="800", height="427" %} +
+ Permission prompt before Chrome 116. +
+
+ +Users are presented with three options: + +- **Allow**: Persistent allow. +- **Block**: Persistent block. +- Clicking the **x** button: Temporary block. The site can prompt the user again later, at most three times. + +Permissions can be managed via the **Site controls** in the address bar or via the **Site settings**. + +{% Aside 'key-term' %} +*Site controls*: User-facing information and controls for a site, accessible after clicking the icon in the address bar. + +
+{% Img src="image/O2RNUyVSLubjvENAT3e7JSdqSOx1/UD9Don3Ks7ZYL0cF2c2c.png", alt="The site controls menu in Chrome.", width="483", height="370" %} +
+ Site controls in Chrome. +
+
+{% endAside %} + +{% Aside 'key-term' %} +*Site settings*: User-facing information and controls for a site. Site settings can be accessed by clicking **Site settings** in the **Site controls** menu, or via Chrome's **Settings** page (`chrome://settings` or the **Settings** entry in the [three-dot-menu](https://support.google.com/chrome/answer/114662?hl=en)). +{% endAside %} + +### New permissions UX from Chrome 116 + +
+{% Img src="image/O2RNUyVSLubjvENAT3e7JSdqSOx1/7aSSSclHdEj33k5ifeQv.png", alt="Permission prompt with the new one-time option.", width="800", height="560" %} +
+ Permission prompt with the new one-time option. This is the new permission prompt on desktop for geolocation, camera, and microphone. +
+
+ +Users are presented with four options: + +- **Allow this time**: Temporary allow. +- **Allow on every visit**: Persistent allow. +- **Don't allow**: Persistent block. +- Clicking the **x** button: Temporary block. + +When users select **Allow this time**, the granted permission is temporary, also referred to as _one-time permission_. Its duration is limited to the current ongoing interaction with a web application. + +
+{% Video src="video/O2RNUyVSLubjvENAT3e7JSdqSOx1/EqRZdDpv30X1x7FdOGFP.mov", width="800", height="547", autoplay=true, muted=true, playsinline=true, loop=true%} +
+ One-time permissions can be managed like other permissions, via the Site controls or Site settings. +
+
+ + +### User benefits and UX design of "Allow this time" + +**Allow this time** provides users with: + +- **Increased control.** Chrome user research has shown that users often are not ready to make a persistent decision for website permissions, trying to assess if they get value in return for granting permissions. Offering a one-time Allow option accommodates this need and makes allowing access less risky. +- **More clarity.** Explicit **Allow this time** and **Allow on every visit** options make it clear that one of the options is temporary, while the other one is persistent. + +{% Aside %} +Chrome UX teams tested multiple layout and string variations before settling on the vertical three-button layout. User feedback indicated that a layout similar to mobile UIs provides safer outcomes and better expectation match. We think that this is partly due to users being already familiar with this pattern. + +
+{% Img src="image/O2RNUyVSLubjvENAT3e7JSdqSOx1/wthfyv9PF4DUz5XnBbgk.jpg", alt="Permission prompt for an Android app.", width="336", height="674" %} +
+ Permission prompt for an Android app, with three options presented in vertically-stacked buttons, including a one-time permission. Source: https://developer.android.com/training/location/permissions. +
+
+ +{% endAside %} + +## One-time permissions in other browsers + +On the web, one-time permissions are supported in a number of browsers, including Safari and Firefox. To see how they work on your device, experiment with [https://permission.site/one-time](https://permission.site/one-time). Make sure to try out geolocation, camera, and microphone permissions, as they may have specific behaviors. + +For example: +* In Safari 16 on desktop, geolocation is one-time by default (until next navigation). The user can opt into access being persisted for 24 hours via a checkbox. +* In Firefox 115 on desktop, geolocation, camera and microphone permissions are one-time by default. The user can opt into persistent access via a checkbox. + +{% Aside %} +One-time permissions are also built into several mobile operating systems. +{% endAside %} + + +## Impact and recommendations + +Impact of one-time permissions: +- The introduction of one-time permissions does not impact permissions that users have previously granted persistently. +- Once a user makes a decision on a permission prompt, then for the duration of their visit, the permission state is either granted or denied. One-time permissions make no difference in this regard. +- However, if the user selects **Allow this time**, they will see a permission prompt again on their next visit. + +To accommodate for one-time permissions, we recommend that site owners do the following: + +- Ensure your implementation follows best practices around permissions. Review [Best practices](#best-practices). +- Understand when one-time permissions expire. See details in [Expiration of one-time permissions](#expiration). +- Understand how the [Permissions API](https://developer.mozilla.org/docs/Web/API/Permissions_API) behaves for one-time permissions, and **how to observe expiration.** Review details in [Permissions API](#permissions-api). + +{% Aside %} +Chrome [removes permissions](https://blog.google/products/chrome/5-tips-to-stay-safer-online-with-chrome/#:~:text=A%20more%20proactive%20Safety%20Check) from sites users haven't recently visited. This is independent from one-time permissions. +{% endAside %} + +### Best practices {: #best-practices } + +**Allow this time** may make people more likely to grant permissions to try out capabilities, but it may also reduce their willingness to grant permanent access. This makes it even more important to follow best practices. + +- Provide the necessary context before requesting permissions. Explain to your users why they'll benefit from a capability. +- Requests permissions at an appropriate and expected moment. Ideally, let your users express their intention to use a certain capability at their own pace. +- For the duration of the user’s visit, provide the same experience regardless of whether the user selected the one-time or persistent option. + +Review additional guidance in [Permission UX](https://developers.google.com/web/fundamentals/push-notifications/permission-ux). + +### Expiration of one-time permissions {: #expiration } + +By default, all web permissions are bound to an [origin](https://web.dev/same-site-same-origin/#origin), which can be thought of as an app of its own. With **Allow this time**, the user gives a one-time permission to an origin. In essence, one-time permissions expire when the user stops actively interacting with that origin for some time. This means the site can continue to use the capability if the user briefly switches to another web page in a different tab but then comes back. + +In more detail, one-time permission grants expire as soon as any of the following conditions are met: + +* The page has been closed, was navigated away from, or was [discarded](/blog/page-lifecycle-api/#states:~:text=next%20states%3A%0ANONE-,Discarded,-A%20page%20is). This includes closing Chrome. +* 16 hours have passed since granting permission. +* The user manually revokes the permission (for example, in **Site controls**), or the permission is overridden through an enterprise policy. +* The page has been in the [background](#background-tab) for at least 5 minutes—except if the capability is allowed to run in the background, like camera or microphone. In this case, as long as the site uses the capability, Chrome shows a [tab strip indicator](#tab-strip-indicator) and doesn't start the 5-minute timer until the page stops using the capability. Note that the 16-hour timer is still running. + +{% Aside %} +A user may have several tabs of the same origin open simultaneously. In that case, the expiration conditions are unchanged—you only need to replace the term "page" with "all pages from that origin". +{% endAside %} + +#### Background tab {: #background-tab } +A browser tab is in the _background_ when it's not in the foreground. A tab is in the foreground when it's the visible tab in a browser window that is not minimized. + +In Chrome, some capabilities, like geolocation, can only run in the foreground tab. They're not allowed to run in a background tab. Others, like camera and microphone, are allowed to run in a background tab. + +{% Img src="image/O2RNUyVSLubjvENAT3e7JSdqSOx1/Cjc8Tj8lnks8eB6Ntx7k.jpg", alt="A screenshot of the browser window highlight an active foreground tab and inactive background tab.", width="800", height="579" %} + +#### Tab strip indicator {: #tab-strip-indicator } + +Capabilities that continue to run when the tab is in the background have a *tab strip indicator*. +For example, camera has a tab strip indicator. + +
+{% Img src="image/O2RNUyVSLubjvENAT3e7JSdqSOx1/RE7sxBJLNpuvD7wUcOJW.jpg", alt="A tab with a red dot.", width="515", height="111" %} +
+ The tab indicator for camera access is a red dot. +
+
+ + + +Geolocation doesn't need a tab strip indicator, because geolocation access is paused as soon as the page is in the background. + +{% Aside 'gotchas' %} +Geolocation has an address bar indicator, but no tab strip indicator. +{% endAside %} + +#### Examples + +* **Geolocation**: The user is on `example.com` and grants one-time geolocation access. The user switches to another tab. This makes `example.com` a background tab. Geolocation access is paused immediately because Chrome doesn't allow background geolocation access, but the one-time permission grant is still valid. If the user comes back to `example.com` within five minutes, the page can resume geolocation access (and the 5-minute expiry timer is reset). If they don't, the one-time permission expires. +* **Camera/Microphone**: The user is on `example.com` and grants one-time camera access. The user switches to another tab. This makes `example.com` a background tab. Camera access can continue because Chrome allows camera access to continue in the background. Chrome keeps displaying the tab strip indicator for camera as long as it's in use to keep the user informed. At some point, the site may decide to stop camera access, in which case the 5-minute expiry timer starts. After 5 minutes without camera access, the one-time permission expires. + + +### Permissions API {: #permissions-api } + +{% Aside 'caution' %} + +At the time of this writing, the [Permissions API](https://developer.mozilla.org/docs/Web/API/Permissions_API) is only available for some capabilities, depending on the browser. Review the list of capabilities that are permissions-aware [here](https://developer.mozilla.org/docs/Web/API/Permissions_API#permission-aware_apis), and detailed browser support [here](https://developer.mozilla.org/docs/Web/API/Permissions_API#browser_compatibility). +{% BrowserCompat 'api.Permissions' %} + +{% endAside %} + +To query the status of API permissions, you can use the [Permissions API](https://developer.mozilla.org/docs/Web/API/Permissions_API): + +- If the user picks **Allow this time**, the Permission API status is set to `granted`. This means that an unexpired one-time permission and a persistent permission are indistinguishable and have the same status: `granted`. +- Once the one-time permission expires, the status will be set back to `prompt`. +- To observe the expiration of a one-time permission, register a [`PermissionStatus.onchange`](https://developer.mozilla.org/docs/Web/API/PermissionStatus) event handler. + +{% Aside 'objective' %} +Review example code [here](https://github.com/chromium/permission.site/blob/master/one-time.js#L103), and try the [demo](https://permission.site/one-time) to observe these behaviors. +{% endAside %} + +{% Aside 'gotchas' %} +Do not use the `prompt` state as a signal that a user is a first-time user. This has never been a reliable signal. With one-time permissions, it becomes even less reliable because `prompt` may now be the status of a permission that the user has previously chosen to **Allow this time** but has since expired. For example, because all tabs from that origin were in the background for 5 minutes. +{% endAside %} + +## Demo + +1. Open [Chrome 116](https://chromiumdash.appspot.com/schedule) or newer, on a desktop computer. +2. Open `chrome://flags/#one-time-permission` and select **Enable**. Restart Chrome. This step force-enables one-time permissions in case they aren't yet rolled out in your Chrome browser. +3. Open [https://permission.site/one-time](https://permission.site/one-time). +4. Click the **Geolocation** button. +5. Observe the new one-time permission prompt. +6. Pick **Allow this time**. +7. Open the **Site controls**. Observe that you can manage the one-time permission. +8. Close the tab for [https://permission.site/one-time](https://permission.site/one-time). Make sure that no other tab for that origin is open. +9. Open [https://permission.site/one-time](https://permission.site/one-time) in a new tab. +10. Open the **Site controls**. Navigate to the **Site settings**. +11. Observe that the Geolocation permission is now back to its initial state: **Ask (default)**. + +## Conclusion and feedback + +One-time permissions offer users more choice, and Chrome's new permission UI brings a more consistent permission user experience across browsers and platforms. + +If you encounter any issues with one-time permissions, [file a new crbug issue for permission prompts](https://bugs.chromium.org/p/chromium/issues/entry?components=UI%3EBrowser%3EPermissions%3EPrompts). + +### Acknowledgements + +Thanks to [Rachel Andrew](/authors/rachelandrew), Balazs Engedy, Marian Harbach, Florian Jacky and [Thomas Steiner](/authors/thomassteiner/) for reviewing this article. From e4da293ad6ae8138e4237d8a8cad9859fcb44662 Mon Sep 17 00:00:00 2001 From: Maud Date: Tue, 1 Aug 2023 12:59:11 +0200 Subject: [PATCH 608/982] Added reviewer (#6966) --- site/en/blog/one-time-permissions/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/en/blog/one-time-permissions/index.md b/site/en/blog/one-time-permissions/index.md index a437bbc57..e821adbf1 100644 --- a/site/en/blog/one-time-permissions/index.md +++ b/site/en/blog/one-time-permissions/index.md @@ -231,4 +231,4 @@ If you encounter any issues with one-time permissions, [file a new crbug issue f ### Acknowledgements -Thanks to [Rachel Andrew](/authors/rachelandrew), Balazs Engedy, Marian Harbach, Florian Jacky and [Thomas Steiner](/authors/thomassteiner/) for reviewing this article. +Thanks to [Rachel Andrew](/authors/rachelandrew), Serena Chen, Balazs Engedy, Marian Harbach, Florian Jacky and [Thomas Steiner](/authors/thomassteiner/) for reviewing this article. From e03558e8eef93b65ebee13fd952005f3562eadf1 Mon Sep 17 00:00:00 2001 From: Nancymic2 Date: Tue, 1 Aug 2023 07:46:45 -0400 Subject: [PATCH 609/982] Add use case to ARA debugging (#6914) * Update index.md * Update site/en/docs/privacy-sandbox/attribution-reporting-debugging/part-1/index.md Co-authored-by: Anusmita --------- Co-authored-by: Anusmita --- .../attribution-reporting-debugging/part-1/index.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/site/en/docs/privacy-sandbox/attribution-reporting-debugging/part-1/index.md b/site/en/docs/privacy-sandbox/attribution-reporting-debugging/part-1/index.md index 2cb701aba..aafcb4e8b 100644 --- a/site/en/docs/privacy-sandbox/attribution-reporting-debugging/part-1/index.md +++ b/site/en/docs/privacy-sandbox/attribution-reporting-debugging/part-1/index.md @@ -164,6 +164,10 @@ include the unencrypted payload. Use aggregatable debug reports to validate the contents of aggregatable reports, and to generate summary reports with the local [aggregation tool](https://github.com/privacysandbox/aggregation-service#set-up-local-testing) for testing. +### Reprocessing reports + +Another advantage of using debug mode is that it allows you to process reports again. Therefore, to process reports more than once, make sure to have debug reports enabled. + ## Up next [Part 2: Set up debug reports](/docs/privacy-sandbox/attribution-reporting-debugging/part-2/) From 35afefd2ea5f50551e9aa70b1dc870b28812ac3d Mon Sep 17 00:00:00 2001 From: Maud Date: Tue, 1 Aug 2023 14:42:46 +0200 Subject: [PATCH 610/982] Fixed title level (#6967) * Added reviewer * Fixed title level --- site/en/blog/one-time-permissions/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/en/blog/one-time-permissions/index.md b/site/en/blog/one-time-permissions/index.md index e821adbf1..be9869bb0 100644 --- a/site/en/blog/one-time-permissions/index.md +++ b/site/en/blog/one-time-permissions/index.md @@ -229,6 +229,6 @@ One-time permissions offer users more choice, and Chrome's new permission UI bri If you encounter any issues with one-time permissions, [file a new crbug issue for permission prompts](https://bugs.chromium.org/p/chromium/issues/entry?components=UI%3EBrowser%3EPermissions%3EPrompts). -### Acknowledgements +## Acknowledgements Thanks to [Rachel Andrew](/authors/rachelandrew), Serena Chen, Balazs Engedy, Marian Harbach, Florian Jacky and [Thomas Steiner](/authors/thomassteiner/) for reviewing this article. From 2f20b61d076f461a140b06b6240c4382ec136053 Mon Sep 17 00:00:00 2001 From: Barry Pollard Date: Tue, 1 Aug 2023 17:35:38 +0100 Subject: [PATCH 611/982] Update Page Lifecycle API diagram to add some missing states (#6953) * Update Page Lifecycle API diagram to add some missing states * Review feedback * Fix brefore unload handler example * Update state diagram --------- Co-authored-by: Philip Walton --- .../memory-and-energy-saver-mode/index.md | 4 ++-- site/en/blog/page-lifecycle-api/index.md | 23 +++++++++++++------ 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/site/en/blog/memory-and-energy-saver-mode/index.md b/site/en/blog/memory-and-energy-saver-mode/index.md index 2160bfb65..a4160cddc 100644 --- a/site/en/blog/memory-and-energy-saver-mode/index.md +++ b/site/en/blog/memory-and-energy-saver-mode/index.md @@ -51,9 +51,9 @@ These are the worst times to store state because these events are completely unr You can refer to the [Page Lifecycle event diagram](/blog/page-lifecycle-api/#overview-of-page-lifecycle-states-and-events) to see what events are expected to fire as a page is being discarded. As you can see from that diagram, a tab can get from the "hidden" state to the "discarded" state without any events firing.
- + {% Img - src="image/eqprBhZUGfb8WYnumQ9ljAxRrA72/KCIeOsJ0lCWMthBSSBrn.svg", + src="image/W3z1f5ZkBJSgL1V1IfloTIctbIF3/vHuB6kURi4lvu8oBaUT9.svg", alt="Page Lifecycle API state and event flow. A visual representation of the state and event flow described throughout this document.", width="800", height="400" diff --git a/site/en/blog/page-lifecycle-api/index.md b/site/en/blog/page-lifecycle-api/index.md index bf19a8041..be66f5f42 100644 --- a/site/en/blog/page-lifecycle-api/index.md +++ b/site/en/blog/page-lifecycle-api/index.md @@ -2,7 +2,7 @@ layout: 'layouts/blog-post.njk' title: Page Lifecycle API date: 2018-07-24 -updated: 2022-11-18 +updated: 2023-07-31 authors: - philipwalton description: The Page Lifecycle API brings app lifecycle features common on mobile operating systems to the web. Browsers are now able to safely freeze and discard background pages to conserve resources, and developers can safely handle these interventions without affecting the user experience. @@ -83,12 +83,12 @@ Perhaps the easiest way to explain the Page Lifecycle states — as well as the events that signal transitions between them — is with a diagram:
- + {% Img - src="image/eqprBhZUGfb8WYnumQ9ljAxRrA72/KCIeOsJ0lCWMthBSSBrn.svg", + src="image/eqprBhZUGfb8WYnumQ9ljAxRrA72/wgyY9jyBaPTlVZIrJfoD.svg", alt="Page Lifecycle API state and event flow. A visual representation of the state and event flow described throughout this document.", width="800", - height="400" + height="390" %}
@@ -116,6 +116,9 @@ use to observe changes. Possible previous states:
passive (via the focus event)
+ frozen + (via the resume event, then the + pageshow event)

Possible next states:
@@ -135,7 +138,10 @@ use to observe changes. (via the blur event)
hidden (via the - visibilitychange event) + visibilitychange event)
+ frozen + (via the resume event, then the + pageshow event)

Possible next states:
@@ -157,6 +163,9 @@ use to observe changes. passive (via the visibilitychange event)
+ frozen + (via the resume event, then the + pageshow event)

Possible next states:
@@ -854,7 +863,7 @@ addEventListener('beforeunload', (event) => { // A function that returns `true` if the page has unsaved changes. if (pageHasUnsavedChanges()) { event.preventDefault(); - return (event.returnValue = 'Are you sure you want to exit?'); + return (event.returnValue = ''); } }); ``` @@ -865,7 +874,7 @@ needed, and removes it when it's not): ```js const beforeUnloadListener = (event) => { event.preventDefault(); - return (event.returnValue = 'Are you sure you want to exit?'); + return (event.returnValue = ''); }; // A function that invokes a callback when the page has unsaved changes. From ec033c2ebc1aeb93aee5288cdae4e68618a099a8 Mon Sep 17 00:00:00 2001 From: Milica Date: Tue, 1 Aug 2023 19:07:49 +0200 Subject: [PATCH 612/982] Update deprecation trial status (#6970) * Update deprecation trial status * Update date --- site/en/_partials/privacy-sandbox/timeline/ua-ch.md | 2 +- site/en/blog/user-agent-reduction-deprecation-trial/index.md | 2 +- site/en/docs/privacy-sandbox/user-agent/index.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/site/en/_partials/privacy-sandbox/timeline/ua-ch.md b/site/en/_partials/privacy-sandbox/timeline/ua-ch.md index 6f8cd92d0..520ef9fa8 100644 --- a/site/en/_partials/privacy-sandbox/timeline/ua-ch.md +++ b/site/en/_partials/privacy-sandbox/timeline/ua-ch.md @@ -1,5 +1,5 @@ * [Origin trial](/blog/user-agent-reduction-origin-trial/) Chrome 95 to 103 -* [Deprecation trial](/blog/user-agent-reduction-deprecation-trial/) Chrome 103 to Chrome 112 +* [Deprecation trial](/blog/user-agent-reduction-deprecation-trial/) Chrome 103 to Chrome 116 * [Chrome DevTools integration](/blog/new-in-devtools-89/#ua-ch) * Review the [UA-CH Chrome platform status](https://chromestatus.com/feature/5995832180473856) diff --git a/site/en/blog/user-agent-reduction-deprecation-trial/index.md b/site/en/blog/user-agent-reduction-deprecation-trial/index.md index 7527ba930..cf74329f6 100644 --- a/site/en/blog/user-agent-reduction-deprecation-trial/index.md +++ b/site/en/blog/user-agent-reduction-deprecation-trial/index.md @@ -95,7 +95,7 @@ The second, referenced here, is a deprecation trial intended for sites that need ## How long will the deprecation trial last? -The User-Agent Reduction deprecation trial will run from Chrome 100 to Chrome 112. Chrome 113 will be the first release where only the completely reduced User-Agent string is sent. +The User-Agent Reduction deprecation trial will run from Chrome 100 to Chrome 115. Chrome 116 will be the first release where only the completely reduced User-Agent string is sent. ## How do I share feedback for the User-Agent Reduction depreciation trial? diff --git a/site/en/docs/privacy-sandbox/user-agent/index.md b/site/en/docs/privacy-sandbox/user-agent/index.md index fc72cca2c..d671d6922 100644 --- a/site/en/docs/privacy-sandbox/user-agent/index.md +++ b/site/en/docs/privacy-sandbox/user-agent/index.md @@ -6,7 +6,7 @@ subhead: > description: > Limit passively shared browser data to reduce the volume of sensitive information which leads to fingerprinting. date: 2021-11-09 -updated: 2023-03-14 +updated: 2023-08-01 authors: - alexandrawhite --- From bd1dd88e02b6aaf9177e308f1d09b42eb39665ac Mon Sep 17 00:00:00 2001 From: Eric Bidelman Date: Tue, 1 Aug 2023 20:48:58 -0700 Subject: [PATCH 613/982] Update index.md (#6973) typo --- site/en/articles/declarative-shadow-dom/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/en/articles/declarative-shadow-dom/index.md b/site/en/articles/declarative-shadow-dom/index.md index a2c99de25..19e9e89b2 100644 --- a/site/en/articles/declarative-shadow-dom/index.md +++ b/site/en/articles/declarative-shadow-dom/index.md @@ -148,7 +148,7 @@ Declarative Shadow DOM to continue working, since declarative roots are preserve For newly-created Custom Elements, a new [`ElementInternals.shadowRoot`](https://github.com/WICG/webcomponents/issues/871) property provides an explicit way to get a reference to an element's existing Declarative Shadow Root, both open and closed. This -can be used to check for and use any Declarative Shadow Root, while still falling back `toattachShadow()` in cases where one was +can be used to check for and use any Declarative Shadow Root, while still falling back to `attachShadow()` in cases where one was not provided. ```javascript From 8acaa7ec9fa152b4c66dcf93396e24d17aed5036 Mon Sep 17 00:00:00 2001 From: Jecelyn Yeen <5917927+jecfish@users.noreply.github.com> Date: Wed, 2 Aug 2023 11:39:11 +0200 Subject: [PATCH 614/982] Add video to workspace (#6971) --- site/en/docs/devtools/workspaces/index.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/site/en/docs/devtools/workspaces/index.md b/site/en/docs/devtools/workspaces/index.md index f7d42d561..32d102277 100644 --- a/site/en/docs/devtools/workspaces/index.md +++ b/site/en/docs/devtools/workspaces/index.md @@ -14,6 +14,8 @@ tags: - javascript --- +{% YouTube id='Zu9CdbnS5ps' %} + **Goal**: This tutorial provides hands-on practice in setting up and using Workspaces so that you can use Workspaces in your own projects. Workspaces enable you to save changes that you make within DevTools to source code that's stored on your computer. From d886e2ac270f0117cea4dbbf0c9e152de2323c02 Mon Sep 17 00:00:00 2001 From: Oliver Dunk Date: Wed, 2 Aug 2023 12:41:42 +0100 Subject: [PATCH 615/982] Add documentation for using Google Analytics with Chrome Web Store (#6799) * Add documentation for using Google Analytics with Chrome Web Store * Add header IDs * Add note about Looker Studio * Update site/en/docs/webstore/google-analytics/index.md Co-authored-by: Sebastian Benz * Apply suggestions from code review Co-authored-by: Joe Medley * Clarify when install event is sent * Formatting tweak * Clarify limits * Re-arrange sections based on feedback * Remove mention of track_install URL * Add link to related item --------- Co-authored-by: Sebastian Benz Co-authored-by: Joe Medley --- site/_data/docs/webstore/toc.yml | 1 + .../docs/webstore/google-analytics/index.md | 118 ++++++++++++++++++ site/en/docs/webstore/manage/index.md | 3 + 3 files changed, 122 insertions(+) create mode 100644 site/en/docs/webstore/google-analytics/index.md diff --git a/site/_data/docs/webstore/toc.yml b/site/_data/docs/webstore/toc.yml index f7a020f93..7f6ee0b24 100644 --- a/site/_data/docs/webstore/toc.yml +++ b/site/_data/docs/webstore/toc.yml @@ -16,6 +16,7 @@ - url: /docs/webstore/manage/ - url: /docs/webstore/update/ - url: /docs/webstore/review-process/ + - url: /docs/webstore/google-analytics/ - url: /docs/webstore/troubleshooting/ - url: /docs/webstore/branding/ - url: /docs/webstore/rating/ diff --git a/site/en/docs/webstore/google-analytics/index.md b/site/en/docs/webstore/google-analytics/index.md new file mode 100644 index 000000000..3ded408f1 --- /dev/null +++ b/site/en/docs/webstore/google-analytics/index.md @@ -0,0 +1,118 @@ +--- +layout: "layouts/doc-post.njk" +title: "Using your Google Analytics account with the Chrome Web Store" +seoTitle: "Using your Google Analytics account with the Chrome Web Store" +date: 2023-07-11 +description: The Chrome Web Store offers integration with Google Analytics, which allows you to see analytics for your Chrome Web Store listing in addition to the view offered in the Developer Dashboard. +--- + +The Chrome Web Store offers integration with Google Analytics. This allows you to see analytics for +your Chrome Web Store listing in addition to the view offered in the Developer Dashboard. + +If you’re instead looking to track usage of your extension, see +[Using Google Analytics 4][extensions-ga4]. + +## Opt-in to Google Analytics {: #opt-in } + +When viewing your item in the [Developer Dashboard][developer-dashboard], find the Additional +metrics section on the Store listing page. Click "Opt in to Google Analytics". + +

+ {% Img src="image/wVNVUJS8Z8O04i1tJKSdsp6nkRQ2/AVqhwuRqmI00g7AVkIDc.png", alt="Opt in UI for Google Analytics in Developer Dashboard", width="800", height="161" %} +
Opt in UI for Google Analytics in Developer Dashboard.
+
+ +Then, head to [https://analytics.google.com/][ga]. You should have access to a new property which +has been named with your extension ID. + +## Limits {: #limits } + +Some limits apply in your Google Analytics property. These include: + +- Data retention is set to two months. +- Data de-identification is enabled, which limits access to non aggregated data to prevent tracking +an individual user. For example, data may be withheld if it does not meet system-defined +[thresholds][ga-thresholds]. +- Additional users can only be added by syncing with a Group Publisher (see +[below](#group-publisher)). + +## Page views {: #page-views } + +Each time a user visits your extension listing, you will see a page view for the following URL: `/webstore/detail/ext/free/EXTENSION_ID/EXTENSION_NAME` + +## Events {: #events } + +The Chrome Web Store also sends a number of events to your property: + +- [`page_view`][ga-pageview], [`session_start`][ga-sessionstart], [`first_visit`][ga-firstvisit] and +[`user_engagement`][ga-userengagement] +- `install`: A [custom event][ga-custom-events] sent when a user installs your extension. This is +only sent if a user accepts the permission prompt to complete the install. + +## Monitoring ad performance {: #monitor-performance } + +### Using UTM parameters {: #utm-params } + +A common use case for developers is monitoring advertising performance. In these cases, it is useful +to know which ads led to views of your item’s store listing or which resulted in conversions. + +You can use the `utm_source`, `utm_medium`, and `utm_campaign` parameters for this which are all +forwarded to Google Analytics. For example, an ad could direct users to the following URL: + +[https://chrome.google.com/webstore/detail/action-api-demo/ljjhjaakmncibonnjpaoglbhcjeolhkk?utm_source=ad&utm_medium=cpc&utm_campaign=summer-ad-campaign](https://chrome.google.com/webstore/detail/action-api-demo/ljjhjaakmncibonnjpaoglbhcjeolhkk?utm_source=ad&utm_medium=cpc&utm_campaign=summer-ad-campaign) + +You will see the following for the corresponding `page_view` and `install` events: + +- Session source: `ad` +- Session medium: `cpc` +- Session campaign: `summer-ad-campaign` + +If this is the first time the user has visited your extension listing the "first user +medium", "first user campaign", and "first user source" fields will also be set. + +{% Aside %} +It can take between 24 and 48 hours for data to be finalized. Before then, you may see events +reported with a blank entry for these fields. This will be corrected as the data is finalized. +{% endAside %} + +### Connecting to Google Ads or other services {: #connect-other-services } + +It is not currently possible to link your Google Analytics property to other services like Google +Ads. We recommend periodically checking the data in Google Analytics to understand ad performance +and make decisions about how to optimize campaigns. + +## Tracking conversions {: #track-conversions } + +The install event generated when a user installs your extension can be marked as a conversion event. +Go to **Admin**, then **Conversions** and choose **New Conversion Event**. Enter "install" and click **Save**. The +event will now appear as a Conversion across your Google Analytics dashboard. + +## Giving other accounts access to Google Analytics {: #grant-access } + +### Using a Group Publisher {: #group-publisher } + +To give other Google accounts access to your Google Analytics property, set up a +[Group Publisher][group-publisher]. Members of this group will be automatically granted access to +the Google Analytics property. Note that granting access to the linked group means those users can +act on behalf of the publisher account. This means they can access the Developer Dashboard and edit +and publish updates to your extensions. Consequently, access should be shared sparingly. + +### With Looker Studio {: #looker-studio } + +Alternatively, you can use [Looker Studio][looker-studio] to create a report based on your +Google Analytics data. This can be easily shared with any Google account. + +Simple choose "Create" and choose the type of file you would like to create. Use the Google +Analytics connector and add your property under the "Chrome Web Store developer properties" account. + +[developer-dashboard]: https://chrome.google.com/webstore/devconsole/ +[ga]: https://analytics.google.com/ +[ga-thresholds]: https://support.google.com/analytics/answer/9383630 +[ga-pageview]: https://support.google.com/analytics/answer/9234069#page_view +[ga-sessionstart]: https://support.google.com/analytics/answer/9234069#session_start +[ga-firstvisit]: https://support.google.com/analytics/answer/9234069#first_visit +[ga-userengagement]: https://support.google.com/analytics/answer/9234069#user_engagement +[ga-custom-events]: https://support.google.com/analytics/answer/12229021 +[extensions-ga4]: /docs/extensions/mv3/tut_analytics/ +[group-publisher]: /docs/webstore/group-publishers/ +[looker-studio]: https://lookerstudio.google.com/ diff --git a/site/en/docs/webstore/manage/index.md b/site/en/docs/webstore/manage/index.md index 3ff10b1c8..fa0382bb0 100644 --- a/site/en/docs/webstore/manage/index.md +++ b/site/en/docs/webstore/manage/index.md @@ -211,6 +211,8 @@ To track store item metrics, you can opt in to Google Analytics 4 by clicking ** The Chrome Web Store manages the account for you and makes the data available in Google Analytics. Chrome Web Store grants you access only to non user-level data. For group publishers, all developers within the group, regardless of their role within the group, are granted access to data for items owned by the group. {% Img src="image/sQ51XsLqKMgSQMCZjIN0B7hlBO02/etCDPbAFMIeOcKvAW4rN.png", alt="Where to opt in to Google Analytics", width="713", height="123" %} +Learn more [here][analytics]. + [cws-review]: /docs/webstore/review-process/ [cws-support]: https://support.google.com/chrome_webstore/contact/dev_account_transfer [dev-dashboard]: https://chrome.google.com/webstore/devconsole @@ -219,3 +221,4 @@ The Chrome Web Store manages the account for you and makes the data available in [support-tab]: #user-support-tab [troubleshooting]: /docs/webstore/troubleshooting/ [whats-new]: /docs/extensions/whatsnew/ +[analytics]: /docs/webstore/google-analytics/ From 9de66047a305460594cf78089f85fe4cd0c570f1 Mon Sep 17 00:00:00 2001 From: "Kevin K. Lee" Date: Wed, 2 Aug 2023 10:00:14 -0400 Subject: [PATCH 616/982] Add first-party data usage info to the PAAPI FAQ (#6972) * Add first-party data usage info to the PAAPI FAQ * Update site/en/docs/privacy-sandbox/fledge/index.md Co-authored-by: Anusmita * Describe how the advertiser passes in 1p data --------- Co-authored-by: Anusmita --- site/en/docs/privacy-sandbox/fledge/index.md | 57 ++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/site/en/docs/privacy-sandbox/fledge/index.md b/site/en/docs/privacy-sandbox/fledge/index.md index da547d9af..d5180015e 100644 --- a/site/en/docs/privacy-sandbox/fledge/index.md +++ b/site/en/docs/privacy-sandbox/fledge/index.md @@ -471,6 +471,63 @@ To ensure that the ecosystem has sufficient time to test, we don’t expect to r {% endDetails %} +{% Details %} +{% DetailsSummary %} +### How is first-party data used in a Protected Audience auction? +{% endDetailsSummary %} + +First-party data is data owned by the site on their users. For example, if a user has specified their favorite color on the advertiser’s or publisher’s site, that color is considered first-party data. + +In a Protected Audience auction, the advertiser can use their first-party data to determine the [ad interest group membership](https://github.com/WICG/turtledove/blob/main/FLEDGE.md#11-joining-interest-groups), and can also pass data into the interest group as [`userBiddingSignals`](https://github.com/WICG/turtledove/blob/main/FLEDGE.md#12-interest-group-attributes). The first-party data from the advertiser will be available only for the buyers during the bid generation step, and is not available for the sellers. + +For example, if the advertiser knows the user’s favorite color, the value can be set in the interest group config as `userBiddingSignals` when the user is added to an interest group: + +```js +const interestGroup = { + owner: 'https://example-buyer.com', + name: 'running-shoes', + userBiddingSignals: { + favoriteColor: 'blue' // First-party data + }, + // ...other interest group settings +}; + +navigator.joinAdInterestGroup(interestGroup, 3600); +``` + +The publisher can also pass in their first-party data by setting the signals in the [auction config](https://github.com/WICG/turtledove/blob/main/FLEDGE.md#21-initiating-an-on-device-auction) when initiating the auction, and can control who receives the first-party data. When a publisher passes the first-party data in as `auctionSignals`, it is available to both buyers and sellers. When the data is passed in as `sellerSignals`, it is available only to the seller, and when passed in as `perBuyerSignals`, it is available only to the specified buyers. The publisher can also pass in first-party data to component auctions. The publisher and the auction participants should agree before on what first-party data needs to be shared, and how the data needs to be formatted. + +The following example describes how the first-party data can be passed in by the publisher to various auction participants: + +```js +const auctionConfig = { + seller: 'https://example-seller.com', + auctionSignals: { + favoriteColor: 'blue', // Both buyer and seller will receive this signal + }, + sellerSignals: { + favoriteIceCreamFlavor: 'chocolate', // Only the seller will receive this signal + }, + perBuyerSignals: { + 'https://example-buyer.com': { + favoriteDrink: 'tea', // Only a specific buyer will receive this signal + }, + }, + // The same pattern applies to the component auction + componentAuctions: [{ + seller: 'https://example-component-seller.com', + auctionSignals: { ... }, + sellerSignals: { ... }, + perBuyerSignals { ... } + }], + // ...other auction settings +}; + +navigator.runAdAuction(auctionConfig); +``` + +{% endDetails %} + {: #engage} ## Find out more From 57470536c5feb0379b390c53fda4138c9c5346a7 Mon Sep 17 00:00:00 2001 From: patrick kettner Date: Wed, 2 Aug 2023 12:37:06 -0400 Subject: [PATCH 617/982] fix links for chrome custom tab comparison page (#6785) --- .../android/custom-tabs/browser-support/index.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/site/en/docs/android/custom-tabs/browser-support/index.md b/site/en/docs/android/custom-tabs/browser-support/index.md index 4d9b40464..7875656ec 100644 --- a/site/en/docs/android/custom-tabs/browser-support/index.md +++ b/site/en/docs/android/custom-tabs/browser-support/index.md @@ -116,7 +116,7 @@ It is currently not possible to programmatically check on an Android device, if ### addDefaultShareMenuItem() {% Aside 'warning' %} -This method is deprecated. Instead, you should use [`setShareState`](#setShareState). +This method is deprecated. Instead, you should use [`setShareState`](https://developer.android.com/reference/androidx/browser/customtabs/CustomTabsIntent.Builder#setShareState(int)). {% endAside %} [addDefaultShareMenuItem()](https://developer.android.com/reference/androidx/browser/customtabs/CustomTabsIntent.Builder#addDefaultShareMenuItem()) adds a default share button to the Custom Tabs toolbar, allowing the user to share the current web page via various apps on their device. @@ -157,7 +157,7 @@ Adds a menu item. ### addToolbarItem() {% Aside 'warning' %} -This method is deprecated. Instead, you should use [`setSecondaryToolbarViews`](#setSecondaryToolbarViews). +This method is deprecated. Instead, you should use [`setSecondaryToolbarViews`](https://developer.android.com/reference/androidx/browser/customtabs/CustomTabsIntent.Builder#setSecondaryToolbarViews(android.widget.RemoteViews,int[],android.app.PendingIntent)). {% endAside %} Adds an action button to the custom tab. Multiple buttons can be added via this method. @@ -178,7 +178,7 @@ Adds an action button to the custom tab. Multiple buttons can be added via this ### enableUrlBarHiding() {% Aside 'warning' %} -This method is deprecated. Instead, you should use [`setUrlBarHidingEnabled`](#setUrlBarHidingEnabled). +This method is deprecated. Instead, you should use [`setUrlBarHidingEnabled`](https://developer.android.com/reference/androidx/browser/customtabs/CustomTabsIntent.Builder#setUrlBarHidingEnabled(boolean)). {% endAside %} Enables the url bar to hide as the user scrolls down on the page. @@ -312,7 +312,7 @@ Sets [`CustomTabColorSchemeParams()`](https://developer.android.com/reference/an ### setDefaultShareMenuItemEnabled() {% Aside 'warning' %} -This method is deprecated. Instead, you should use [`setShareState`](#setShareState). +This method is deprecated. Instead, you should use [`setShareState`](https://developer.android.com/reference/androidx/browser/customtabs/CustomTabsIntent.Builder#setShareState(int)). {% endAside %} Set whether a default share item is added to the menu. @@ -367,7 +367,7 @@ Sets the Custom Tab Activity's initial height in pixels with default resize beha ### setNavigationBarColor() {% Aside 'warning' %} -This method is deprecated. Instead, you should use [`setDefaultColorSchemeParams`](#setDefaultColorSchemeParams). +This method is deprecated. Instead, you should use [`setDefaultColorSchemeParams`](https://developer.android.com/reference/androidx/browser/customtabs/CustomTabsIntent.Builder#setDefaultColorSchemeParams(androidx.browser.customtabs.CustomTabColorSchemeParams)). {% endAside %} Sets the navigation bar color. Has no effect on API versions below L. @@ -387,7 +387,7 @@ Sets the navigation bar color. Has no effect on API versions below L. ### setNavigationBarDividerColor() {% Aside 'warning' %} -This method is deprecated. Instead, you should use [`setDefaultColorSchemeParams`](#setDefaultColorSchemeParams). +This method is deprecated. Instead, you should use [`setDefaultColorSchemeParams`](https://developer.android.com/reference/androidx/browser/customtabs/CustomTabsIntent.Builder#setDefaultColorSchemeParams(androidx.browser.customtabs.CustomTabColorSchemeParams)). {% endAside %} {% AndroidBrowserSupportTable @@ -405,7 +405,7 @@ This method is deprecated. Instead, you should use [`setDefaultColorSchemeParams ### setSecondaryToolbarColor() {% Aside 'warning' %} -This method is deprecated. Instead, you should use [`setDefaultColorSchemeParams`](#setDefaultColorSchemeParams). +This method is deprecated. Instead, you should use [`setDefaultColorSchemeParams`](https://developer.android.com/reference/androidx/browser/customtabs/CustomTabsIntent.Builder#setDefaultColorSchemeParams(androidx.browser.customtabs.CustomTabColorSchemeParams)). {% endAside %} Sets the color of the secondary toolbar. @@ -478,7 +478,7 @@ Sets the start animations. ### setToolbarColor() {% Aside 'warning' %} -This method is deprecated. Instead, you should use [`setDefaultColorSchemeParams`](#setDefaultColorSchemeParams). +This method is deprecated. Instead, you should use [`setDefaultColorSchemeParams`](https://developer.android.com/reference/androidx/browser/customtabs/CustomTabsIntent.Builder#setDefaultColorSchemeParams(androidx.browser.customtabs.CustomTabColorSchemeParams)). {% endAside %} Sets the toolbar color. On Android L and above, this color is also applied to the status bar. From d451b2bc2557a902c352408a8d55ea4667a49fe9 Mon Sep 17 00:00:00 2001 From: Barry Pollard Date: Wed, 2 Aug 2023 19:05:44 +0100 Subject: [PATCH 618/982] Add BrowserComnpat widget to 103 Early Hints article (#6976) --- site/en/blog/early-hints/index.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/site/en/blog/early-hints/index.md b/site/en/blog/early-hints/index.md index 6c7f0be1b..68d6155f7 100644 --- a/site/en/blog/early-hints/index.md +++ b/site/en/blog/early-hints/index.md @@ -7,7 +7,7 @@ description: > subhead: > Find out how your server can send hints to the browser about critical sub-resources. date: 2022-06-23 -updated: 2023-06-10 +updated: 2023-08-02 authors: - kenjibaheux - tunetheweb @@ -50,7 +50,9 @@ In some cases, the performance improvement to the [Largest Contentful Paint](htt ## Implementing Early Hints -Early Hints is available from Chrome version 103, as a response to navigation requests, or user interactions that change the url in the status bar, with support for both preconnect and preload hints. +{% BrowserCompat 'http.status.103' %} + +Early Hints is available from Chrome version 103, as a response to navigation requests, or user interactions that change the url in the status bar, with support for both preconnect and preload hints. Other browsers are adding support for preconnect. Before going deep into the topic, please note that Early Hints are not useful if your server can send a 200 (or other final responses) right away. Instead, consider using the regular `link rel=preload` or `link rel=preconnect` on the main response ([Link rel HTTP header](https://developer.mozilla.org/docs/Web/HTTP/Headers/Link)), or in the main response (`` elements), in such situations. For the cases where your server needs a little time to generate the main response, read on! From a203e831f6e94c000015ced50f388d8b8ca21ca1 Mon Sep 17 00:00:00 2001 From: Alex Loskutov <599181+aloskutov@users.noreply.github.com> Date: Thu, 3 Aug 2023 05:39:51 +0700 Subject: [PATCH 619/982] Update index.md (#6651) Typo in CSS --- site/en/articles/css-nesting/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/en/articles/css-nesting/index.md b/site/en/articles/css-nesting/index.md index 2e495faca..c5e578a27 100644 --- a/site/en/articles/css-nesting/index.md +++ b/site/en/articles/css-nesting/index.md @@ -349,7 +349,7 @@ selectors. Consider the following example: ```css .demo { .lg { - .triange, + .triangle, .circle { opacity: .25; filter: blur(25px); From 7651f1c233b49b28e6506c17887bd236a8b19286 Mon Sep 17 00:00:00 2001 From: Thomas Steiner Date: Thu, 3 Aug 2023 11:44:11 +0200 Subject: [PATCH 620/982] Remove wrong hero image (#6984) --- site/en/blog/webar-chacmool/index.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/site/en/blog/webar-chacmool/index.md b/site/en/blog/webar-chacmool/index.md index be2f554ec..9af1c97d1 100644 --- a/site/en/blog/webar-chacmool/index.md +++ b/site/en/blog/webar-chacmool/index.md @@ -6,8 +6,6 @@ authors: - chriswilson date: 2018-06-14 updated: 2019-06-14 -hero: 'image/dPDCek3EhZgLQPGtEG3y0fTn4v82/59E79cYprjy3EuTSq0u6.jpg' -alt: 'Webar chacmool' description: > Chacmool, an educational web demo, shows how easily web based AR can build an engaging experience. --- From 0c77664413a20e7b8768259f203573c444d5eaa7 Mon Sep 17 00:00:00 2001 From: Maud Date: Thu, 3 Aug 2023 15:43:45 +0200 Subject: [PATCH 621/982] Added screenshot and fixed link (#6986) --- .../summary-reports/design-decisions/index.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/site/en/docs/privacy-sandbox/summary-reports/design-decisions/index.md b/site/en/docs/privacy-sandbox/summary-reports/design-decisions/index.md index 1311280e7..cadbaf97d 100644 --- a/site/en/docs/privacy-sandbox/summary-reports/design-decisions/index.md +++ b/site/en/docs/privacy-sandbox/summary-reports/design-decisions/index.md @@ -22,7 +22,14 @@ tags: When you read this article, you will: - Understand what strategies to create before generating summary reports in the origin trial. -- Be introduced to [Noise Lab](#quick-tour), a tool that helps grasp the effects of various noise parameters, and that enables quick exploration and assessment of various noise management strategies. +- Be introduced to [Noise Lab](https://goo.gle/noise-lab), a tool that helps grasp the effects of various noise parameters, and that enables quick exploration and assessment of various noise management strategies. + +
+{% Img src="image/O2RNUyVSLubjvENAT3e7JSdqSOx1/0vow72qj9OD9NBZuQ0ej.png", alt="Screenshot of Noise Lab", width="800", height="561" %} +
+ Noise Lab +
+
### Share your feedback From d40552f9dcedc4092f4203d5ef7f9b84bb81a149 Mon Sep 17 00:00:00 2001 From: Nancymic2 Date: Thu, 3 Aug 2023 12:12:19 -0400 Subject: [PATCH 622/982] Update attribution-reporting-features.md (#6975) --- .../timeline/attribution-reporting-features.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/site/en/_partials/privacy-sandbox/timeline/attribution-reporting-features.md b/site/en/_partials/privacy-sandbox/timeline/attribution-reporting-features.md index 4b4aa4598..899bc6468 100644 --- a/site/en/_partials/privacy-sandbox/timeline/attribution-reporting-features.md +++ b/site/en/_partials/privacy-sandbox/timeline/attribution-reporting-features.md @@ -45,6 +45,14 @@ Reducing delays for aggregatable reports
Github issue | Updated Explainer Available in Chrome for origin trial in Q2 2023 + + Phase 1 Lite Flexible Event-Level
Flexible event-level configurations explainer + Expected in Chrome in Q4 2023 + + + Phase 2 Full Flexible Event-Level
Flexible event-level configurations explainer + Expected in Chrome in Q1 2024 + Support for Attribution Reporting debugging after third-party cookie deprecation
Seeking feedback on GitHub Expected in Chrome in H2 2023 From 239d190ca0d19dc1b2feff92def78382984cb5e8 Mon Sep 17 00:00:00 2001 From: Joe Medley Date: Fri, 4 Aug 2023 07:35:28 -0700 Subject: [PATCH 623/982] Remove mv2 links from chrome.experimental. (#6980) --- site/en/docs/extensions/reference/experimental/index.md | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/site/en/docs/extensions/reference/experimental/index.md b/site/en/docs/extensions/reference/experimental/index.md index 5c8b9c61a..993634826 100644 --- a/site/en/docs/extensions/reference/experimental/index.md +++ b/site/en/docs/extensions/reference/experimental/index.md @@ -12,9 +12,6 @@ We'd like your [feedback][1] on the following experimental APIs:
NameDescription
-Pay special attention to the following APIs, which we expect to finalize soon: **devtools**, -**permissions**, For examples of using the experimental APIs, see [Samples][2]. -
Caution: Don't depend on these experimental APIs. They might disappear, and they will change. Also, the Chrome Web Store doesn't allow you to upload items that use experimental APIs.
## How to use experimental APIs {: #using } @@ -53,10 +50,9 @@ Pay special attention to the following APIs, which we expect to finalize soon: * For information on the standard APIs, see [chrome.\* APIs][7] and [Other APIs][8]. [1]: https://groups.google.com/a/chromium.org/group/chromium-extensions/topics -[2]: /docs/extensions/mv2/samples#search:experimental [3]: https://tools.google.com/dlpage/chromesxs [4]: https://www.chromium.org/getting-involved/dev-channel -[5]: /docs/extensions/mv2/declare_permissions +[5]: /docs/extensions/mv3/declare_permissions [6]: https://groups.google.com/a/chromium.org/group/chromium-extensions/topics [7]: /docs/extensions/reference [8]: https://developer.mozilla.org/docs/Web/API From d2d7d6c1c29bbe5441c6d823cf7382be263b7c87 Mon Sep 17 00:00:00 2001 From: Rick Viscomi Date: Fri, 4 Aug 2023 10:50:14 -0400 Subject: [PATCH 624/982] Update framework INP values (Feb 2023) (#5867) * Update index.md * Update index.md * Create index.md * Delete index.md * Update index.md * Update index.md * Update redirects.yaml * updated conclusion * update CWV Tech Report data --- redirects.yaml | 3 ++ .../inp-in-frameworks/index.md | 33 ++++++++++--------- 2 files changed, 20 insertions(+), 16 deletions(-) rename site/en/{blog => articles}/inp-in-frameworks/index.md (96%) diff --git a/redirects.yaml b/redirects.yaml index a4ec91c14..101eb7e67 100644 --- a/redirects.yaml +++ b/redirects.yaml @@ -568,6 +568,9 @@ redirects: - from: /blog/inside-oct-2022/... to: /blog/insider-oct-2022/... + +- from: /blog/inp-in-frameworks/... + to: /articles/inp-in-frameworks/... - from: /blog/webdriver-bidi/ to: /articles/webdriver-bidi/ diff --git a/site/en/blog/inp-in-frameworks/index.md b/site/en/articles/inp-in-frameworks/index.md similarity index 96% rename from site/en/blog/inp-in-frameworks/index.md rename to site/en/articles/inp-in-frameworks/index.md index b24eb6e6b..dc8f5e296 100644 --- a/site/en/blog/inp-in-frameworks/index.md +++ b/site/en/articles/inp-in-frameworks/index.md @@ -3,7 +3,7 @@ layout: 'layouts/blog-post.njk' title: How do modern frameworks perform on the new INP metric subhead: Understand how the new INP metric affects the experience of sites built using JavaScript frameworks and libraries. date: 2022-05-16 -updated: 2022-07-18 +updated: 2023-03-31 authors: - leenasohoni - addyosmani @@ -14,6 +14,7 @@ hero: image/1L2RBhCLSnXjCnSlevaDjy3vba73/EK3nTunaRZbP96S2zwM2.jpeg alt: Person about to touch the calm water. tags: - aurora-project + - performance --- Chrome recently introduced a new [experimental responsiveness metric](https://groups.google.com/a/chromium.org/g/chrome-ux-report-announce/c/F7S4_emZkcw) in the [Chrome UX Report](/docs/crux/) report. This metric, which we now know as [Interaction to Next Paint (INP)](https://web.dev/inp/) measures overall responsiveness to user interactions on the page. Today we want to share insights on where websites built using modern JavaScript frameworks stand in relation to this metric. We want to discuss why INP is relevant to frameworks and how [Aurora](/blog/introducing-aurora/) and frameworks are working to optimize responsiveness. @@ -86,7 +87,7 @@ The [Aurora](/blog/introducing-aurora/) team in Chrome works with open-source we ## Experimental responsiveness metric data -An INP below or equal to 200 milliseconds indicates good responsiveness. The CrUX report data and the [CWV Technology Report](https://www.google.com/url?q=https://datastudio.google.com/s/gPxRJmoivLA&sa=D&source=docs&ust=1652475737927418&usg=AOvVaw3ZQ0WOZu2ZGjCuJb23dQYg) for April 2022 give us the following information about responsiveness for popular JavaScript frameworks. +An INP below or equal to 200 milliseconds indicates good responsiveness. The CrUX report data and the [CWV Technology Report](https://lookerstudio.google.com/s/uwsf2UWxr6k) for February 2023 give us the following information about responsiveness for popular JavaScript frameworks. {% Aside %} This measurement includes data from all versions of the frameworks listed. For more mature frameworks, this can include data from versions many years out-of-date. @@ -112,53 +113,53 @@ This measurement includes data from all versions of the frameworks listed. For m Angular (v2.0.0+) - 19.0 + 28.6 - 65.5 + 83.6 Next.js - 20.2 + 28.5 - 73.4 + 87.3 Nuxt.js - 25.4 + 32.0 - 84.5 + 91.2 Preact - 36.6 + 48.6 - 90.6 + 92.8 Vue (v2.0.0+) - 41.7 + 50.3 - 90.0 + 94.1 Lit - 36.4 + 50.0 - 75.7 + 88.3 - CWV technology report - INP data for April 2022 + CWV technology report - INP data for June 2023
@@ -230,7 +231,7 @@ Through these enhancements, we can address different issues that lead to poor re ## Conclusion -We expect the INP score to provide a better compass for websites to improve responsiveness and performance in the future. We will take steps to provide more actionable guidance on the metric in 2022-23. We hope to achieve this by: +We expect the INP score to provide a better compass for websites to improve responsiveness and performance in the future. We will build on our [existing INP guide](https://web.dev/optimize-inp/) to provide more actionable tips for framework developers in 2023. We hope to achieve this by: * Creating channels for easy access to field data on INP for frameworks and web developers. * Work with frameworks to build features that will improve INP by default. From 0dbe33a5bea46d0186e8e2a229d0e0c4c1af3a52 Mon Sep 17 00:00:00 2001 From: Joe Medley Date: Fri, 4 Aug 2023 10:51:45 -0700 Subject: [PATCH 625/982] Overhaul documentation for declarative net request (#6921) * Convert dNR article to markdown. * Tidy up a few things. * Additional cleanup. * Consolidate examples and clean up anchors. * Additional cleanup. * Update site/en/docs/extensions/reference/declarativeNetRequest/index.md Co-authored-by: Oliver Dunk * Update site/en/docs/extensions/reference/declarativeNetRequest/index.md Co-authored-by: Oliver Dunk * Fix permissions and manifest keys. * Add item to rule definition. * Add service worker information to replace CacheStorage advice. * Update site/en/docs/extensions/reference/declarativeNetRequest/index.md Co-authored-by: Oliver Dunk * Add text resolving cache-sw issue. * New text about service workers. * Add regex information. * Fix list of ruleset types. * Preemptive copy edit. * Fix a few more formatting issues. * Remove unneeded bolding. * Update site/en/docs/extensions/reference/declarativeNetRequest/index.md Co-authored-by: Oliver Dunk * Update site/en/docs/extensions/reference/declarativeNetRequest/index.md Co-authored-by: amysteamdev <37001393+AmySteam@users.noreply.github.com> * Update site/en/docs/extensions/reference/declarativeNetRequest/index.md Co-authored-by: amysteamdev <37001393+AmySteam@users.noreply.github.com> * Update site/en/docs/extensions/reference/declarativeNetRequest/index.md Co-authored-by: amysteamdev <37001393+AmySteam@users.noreply.github.com> * Update site/en/docs/extensions/reference/declarativeNetRequest/index.md Co-authored-by: amysteamdev <37001393+AmySteam@users.noreply.github.com> * Update site/en/docs/extensions/reference/declarativeNetRequest/index.md Co-authored-by: amysteamdev <37001393+AmySteam@users.noreply.github.com> * Update site/en/docs/extensions/reference/declarativeNetRequest/index.md Co-authored-by: amysteamdev <37001393+AmySteam@users.noreply.github.com> * Update site/en/docs/extensions/reference/declarativeNetRequest/index.md Co-authored-by: amysteamdev <37001393+AmySteam@users.noreply.github.com> * Update site/en/docs/extensions/reference/declarativeNetRequest/index.md Co-authored-by: amysteamdev <37001393+AmySteam@users.noreply.github.com> * Update site/en/docs/extensions/reference/declarativeNetRequest/index.md Co-authored-by: amysteamdev <37001393+AmySteam@users.noreply.github.com> * Update site/en/docs/extensions/reference/declarativeNetRequest/index.md Co-authored-by: amysteamdev <37001393+AmySteam@users.noreply.github.com> * Update site/en/docs/extensions/reference/declarativeNetRequest/index.md Co-authored-by: amysteamdev <37001393+AmySteam@users.noreply.github.com> * Update site/en/docs/extensions/reference/declarativeNetRequest/index.md Co-authored-by: amysteamdev <37001393+AmySteam@users.noreply.github.com> * Update site/en/docs/extensions/reference/declarativeNetRequest/index.md Co-authored-by: amysteamdev <37001393+AmySteam@users.noreply.github.com> * Update site/en/docs/extensions/reference/declarativeNetRequest/index.md Co-authored-by: amysteamdev <37001393+AmySteam@users.noreply.github.com> * Update site/en/docs/extensions/reference/declarativeNetRequest/index.md Co-authored-by: amysteamdev <37001393+AmySteam@users.noreply.github.com> * Update site/en/docs/extensions/reference/declarativeNetRequest/index.md Co-authored-by: amysteamdev <37001393+AmySteam@users.noreply.github.com> * Feedback from Amy. --------- Co-authored-by: Oliver Dunk Co-authored-by: amysteamdev <37001393+AmySteam@users.noreply.github.com> --- .../reference/declarativeNetRequest/index.md | 503 +++++++++--------- 1 file changed, 245 insertions(+), 258 deletions(-) diff --git a/site/en/docs/extensions/reference/declarativeNetRequest/index.md b/site/en/docs/extensions/reference/declarativeNetRequest/index.md index 5f08c8a2a..8d98d6fb5 100644 --- a/site/en/docs/extensions/reference/declarativeNetRequest/index.md +++ b/site/en/docs/extensions/reference/declarativeNetRequest/index.md @@ -2,26 +2,14 @@ api: declarativeNetRequest extra_permissions_html: declarativeNetRequestFeedback
- host permissions
-has_warning: One or more of these permissions triggers a warning. - + host_permissions
+has_warning: +

One or more of these permissions triggers a warning. The declarativeNetRequest and declarativeNetRequestWithHostAccess permissions provide the same capabilities, and both require host permissions; however, the latter prevents host permission warnings.

--- ## Manifest {: #manifest } -Extensions must declare either the `declarativeNetRequest` or the -`declarativeNetRequestWithHostAccess` (available since **Chrome 96**) permission in the extension -[manifest][1] to use this API. The former allows extensions to block and upgrade requests without -any [host permissions][2]. Host permissions are still required if the extension wants to redirect a -request or modify headers on it. The `declarativeNetRequestWithHostAccess` permission always -requires host permissions to the request URL and initiator to act on a request. - -The `declarativeNetRequestFeedback` permission is required to access functions and events which -return information on declarative rules matched. - -To specify static [Rulesets][3], extensions must also declare the `"declarative_net_request"` -manifest key, which should be a dictionary with a single key called `"rule_resources"`. It should be -a list containing dictionaries of type [Ruleset][3], as shown below. +In addition to the permissions described above, certain types of rulesets, static rulesets specifically, require declaring the `"declarative_net_request"` manifest key, which should be a dictionary with a single key called `"rule_resources"`. This key is an array containing dictionaries of type `Ruleset`, as shown below. (Note that the name 'Ruleset' does not appear in the manifest's JSON since it is merely an array.) [Static rulesets](#rules) are explained later in this document. ```json { @@ -51,57 +39,71 @@ a list containing dictionaries of type [Ruleset][3], as shown below. } ``` -### Rule Resources {: #manifest-rule-resources } +## Concepts and usage {: #concepts-and-usage } -Rules are specified in JSON files referenced under the `"rule_resources"` manifest key. +To use this API, specify one or more rulesets. A ruleset contains an array of rules. A single rule does one of the following: -Each file should contain an array of [rules](#rules) as in the [example](#example). +- Block a network request. +- Upgrade the schema (http to https). +- Prevent a request from getting blocked by negating any matching blocked rules. +- Redirect a network request. +- Modify request or response headers. -**Note:** Errors and warnings about invalid static rules are only displayed for unpacked extensions. -Invalid static rules in packed extensions are ignored. It's therefore important to verify that your -static rulesets are valid by testing with an unpacked version of your extension. +There are three types of rulesets, managed in slightly different ways. -## Limits {: #limits } +Dynamic +: Persist across browser sessions and extension upgrades and are managed using JavaScript while an extension is in use. -There is a performance overhead to loading and evaluating rules in the browser, -and so a number of limits apply when using the API. Limits depend on the type of -rule you're using. +Session +: Cleared when the browser shuts down and when a new version of the extension is installed. Session rules are managed using JavaScript while an extension is in use. + +Static +: Packaged, installed, and updated when an extension is installed or upgraded. Static rules are stored in JSON-formatted rule files and listed in the manifest file. + +The next few sections explain ruleset types in detail. + +### Dynamic and session-scoped rulesets {: #dynamic-and-session-rules } -### Static rules {: #static-rules } +Dynamic and session rulesets are managed using JavaScript while an extension is in use. -Static rules are those specified in rule files (which are specified in the manifest file). +- Dynamic rules persist across browser sessions and extension upgrades. +- Session rules are cleared when the browser shuts down and when a new version of the extension is installed. -An extension can specify up to **50** static [rulesets][3] as part of the -`"rule_resources"` manifest key, but only **10** of these rulesets can be -enabled at a time. The latter is called the -[`MAX_NUMBER_OF_ENABLED_STATIC_RULESETS`][14]. Collectively, those rulesets are -guaranteed at least **30,000** rules. This is called the -[`GUARANTEED_MINIMUM_STATIC_RULES`][5]. The number of rules available after that -depend on how many rules are enabled by all the extensions installed on a user's -browser. You can find this number at runtime by calling -[`getAvailableStaticRuleCount()`][7]. +There is only one each of these ruleset types. An extension can add or remove rules to them dynamically by calling [`updateDynamicRules()`](/docs/extensions/reference/declarativeNetRequest/#method-updateDynamicRules) and [`updateSessionRules()`](/docs/extensions/reference/declarativeNetRequest/#method-updateSessionRules), provided the rule limits aren't exceeded. For information on rule limits, see [Rule limits](#limits). You can see [an example of this](#update-dynamic-rule-examples) under [code examples](#code-examples). -### Dynamic and session rules {: #dynamic-session-rules } +### Static rulesets {: #rules } + +Unlike dynamic and session rules, static rules are packaged, installed, and updated when an extension is installed or upgraded. They're stored in rule files in JSON format, which are indicated to the extension using the `"declarative_net_request"` and `"rule_resources"` keys [as described above](#manifest), as well as one or more [`Ruleset`](/docs/extensions/reference/declarativeNetRequest/#type-Ruleset) dictionaries. A `Ruleset` dictionary contains a path to the rule file, an ID for the ruleset contained in the file, and whether the ruleset is enabled or disabled. The last two are important when you enable or disable a ruleset programmatically. + +```json +{ + ... + "declarative_net_request" : { + "rule_resources" : [{ + "id": "ruleset_1", + "enabled": true, + "path": "rules_1.json" + }, + ... + ] + } + ... +} +``` -The limits applied to dynamic and session rules are simpler than static rules. The total number of -both cannot exceed **5000**. This is called the -[`MAX_NUMBER_OF_DYNAMIC_AND_SESSION_RULES`][10]. +To test rule files, [load your extension unpacked](/docs/extensions/mv3/getstarted/development-basics/#load-unpacked). Errors and warnings about invalid static rules are only displayed for unpacked extensions. Invalid static rules in packed extensions are ignored. -### Rules that use regex {: #regex-rules } +### Enable and disable static rulesets {: #update-enabled-rulesets } -All types of rules can use regular expressions; however the total number of regex rules, of each type cannot exceed **1000**. This is called the [MAX_NUMBER_OF_REGEX_RULES][15]. +To enable or disable static rulesets, call [`updateEnabledRulesets()`](#method-updateEnabledRulesets). This method takes an [`UpdateRulesetOptions`](#type-UpdateRulesetOptions) object, which contains arrays of IDs of rules to enable or disable. The IDs are defined using the `"id"` key of the `Ruleset` dictionary. -## Rules {: #rules } +The set of enabled static rulesets is persisted across browser sessions. Static rules are not persisted across exension updates, meaning that only rules you chose to leave in your rule files are available after an update. -A single declarative [Rule][8] consists of four fields: `id`, `priority`, `condition`, and -`action`. There are the following kinds of rules: +For performance reasons there are also limits to the number of rules and rulesets that may be enabled at one time. Call [`getAvailableStaticRuleCount()`](#method-getAvailableStaticRuleCount) to check the number of additional rules that may be enabled. For information on rule limits, see [Rule limits](#limits). -- Rules that block a network request. -- Rules that prevent a request from getting blocked by negating any matching blocked rules. -- Rules that redirect a network request. -- Rules that modify headers from a network request. +### Build rules {: #build-rules } -An example rule: +Regardless of type, a rule starts with four fields as shown below. While the `"id"` and `"number"` keys take a number, the [`"action"`](#property-Rule-action) and [`"condition"`](#property-Rule-condition) keys may provide several blocking and redirecting conditions. The following rule blocks all script requests originating from `"foo.com"` to any URL with `"abc"` as a substring. ```json { @@ -116,12 +118,9 @@ An example rule: } ``` -The above rule will block all script requests originating from `"foo.com"` to any URL with `"abc"` -as a substring. +### urlFilter matching characters {: #filter-matching-charactgers } -The `urlFilter` field of a rule condition is used to specify the pattern which is matched against -the request URL. It is documented on the [`RuleCondition`](#type-RuleCondition) type below. Some -examples of URL filters: +A rule's `"condition"` key allows a `"urlFilter"` key for acting on URLs under a specified domain. You create patterns using [pattern matching tokens](/docs/extensions/reference/declarativeNetRequest/#property-RuleCondition-urlFilter). A few examples are shown below. @@ -158,102 +157,142 @@ examples of URL filters:
-## Dynamic and session-scoped rules {: #dynamic-and-session-rules } +### Rule prioritization {: #implementation-matching-algorithm } -An extension can add or remove rules dynamically using the [`updateDynamicRules()`][9] and the [`updateSessionRules()`][13] API methods. -- Rules added using the [`updateDynamicRules()`][9] API method are persisted across both sessions and extension updates. -- Rules added using the [`updateSessionRules()`][13] API method are not persisted across Chrome sessions. These rules are backed in memory by Chrome. -- The number of dynamic and session-scoped rules that an an extension can add is bounded by the [`MAX_NUMBER_OF_DYNAMIC_AND_SESSION_RULES`][10] constant. +Rules are triggered by requests sent from web pages. If multiple rules match a particular request, then the rules must be prioritized. This section explains how they're prioritized. Prioritization happens in two stages. -## Updating enabled rulesets {: #update-enabled-rulesets } +1. Priority is determined for rules within an extension. +1. If more than one extension can apply a rule to a request, priority is determined for all extensions that match a particular request. -An extension can update the set of enabled static rulesets using the [`updateEnabledRulesets()`][11] -method. +Thinking of matching this way: whatever rule a particular extension prioritizes will then be prioritized against rules from other extensions. -- The number of static rulesets which are enabled at one time must not exceed - [`MAX_NUMBER_OF_ENABLED_STATIC_RULESETS`][14]. -- The number of rules across enabled static rulesets across all extensions must not exceed the - [global limit][6]. Calling [`getAvailableStaticRuleCount()`][7] is recommended to check the number - of rules an extension can still enable before the global limit is reached. -- The set of enabled static rulesets is persisted across sessions but not across extension updates. - The `"rule_resources"` manifest key will determine the set of enabled static rulesets on initial - extension install and on each subsequent extension update. +{% Aside 'caution' %} +Avoid building rulesets that depend on rules with the same priority running in a particular order. Rules with the same priority in the same set (e.g., static rules with priority 1) are executed in an arbitrary order which is not defined and can change between runs or browser versions. This is the case across browsers. +{% endAside %} -## Implementation details {: #implementation } +#### Rule prioritization within an extension {: #rule-prioritization-within-an-extension } -### web_accessible_resources {: #implementation-web-accessible-resources } +Within a single extension, prioritization is worked out using the following process: -When an extension uses declarativeNetRequest APIs to redirect a public resource request to a resource that is not web accessible, it is blocked and will result in an error. The above holds true even if the resource that is not web accessible is owned by the redirecting extension. To declare resources for use with declarativeNetRequest APIs, populate the [`"web_accessible_resources"`](/docs/extensions/mv3/manifest/web_accessible_resources/) array. +1. The rule with the highest developer-defined priority (in other words, the `"priority"` field) is returned. +1. If there is more than one rule with the highest developer-defined priority, rules are prioritized using the `"action"` field, in the following order: + 1. `allow` + 1. `allowAllRequests` + 1. `block` + 1. `upgradeScheme` + 1. `redirect` -### Matching algorithm {: #implementation-matching-algorithm } +1. If the action type is not `block` or `redirect`, any matching `modifyHeaders` rules are evaluated. Be aware that if there are any rules with a developer-defined priority lower than the priority specified for `allow` and `allowAllRequests`, such rules are ignored. +1. If multiple rules modify the same header, modification is determined by the developer-defined `"priority"` field and by the specified operations. + - If a rule appends to a header, then lower priority rules can only append to that header. Set and remove operations are not allowed. + - If a rule sets a header, then lower priority rules can only append to that header. No other modifications are allowed. + - If a rule removes a header, then lower priority rules cannot further modify the header. -Before the request is sent, each extension is queried for an action to take. The following actions -are considered at this stage: +#### Rule prioritization between extensions {: #rule-prioritization-between-extensions } -- Actions which block requests of type `block` -- Actions which redirect requests of type `redirect` or `upgradeScheme` -- Actions which allow requests of type `allow` or `allowAllRequests` +If only one extension has a rule that matches a request, that rule is applied. But if more than one extension matches a request, the following process is used: -If more than one extension returns an action, the extension whose action type comes first in the -list above gets priority. If more than one extension returns an action with the same priority -(position in the list), the most recently installed extension gets priority. +1. Rules are prioritized using the `"action"` field, in the following order: + 1. `block` + 1. `redirect` or `upgradeScheme` + 1. `allow` or `allowAllRequests` -When an extension is queried for how to handle a request, the highest priority matching rule is returned. If more than one matching rule has the highest priority, the tie is broken -based on the action type, in the following order of decreasing precedence: +1. If more than one rule matches, the most recently installed extension gets priority. -- `allow` -- `allowAllRequests` -- `block` -- `upgradeScheme` -- `redirect` +### Rule limits {: #limits } -If the request was not blocked or redirected, the matching `modifyHeaders` rules are evaluated with -the most recently installed extensions getting priority. Within each extension, all `modifyHeaders` -rules with a priority lower than matching `allow` or `allowAllRequests` rules are ignored. +There is a performance overhead to loading and evaluating rules in the browser, +so some limits apply when using the API. Limits depend on the type of +rule you're using. -If multiple `modifyHeaders` rules specify the same header, the resulting modification for the header -is determined based on the priority of each rule and the operations specified. +#### Static rules {: #static-rules } -- If a rule has appended to a header, then lower priority rules can only append to that header. - `set` and `remove` operations are not permitted. -- If a rule has set a header, then lower priority rules cannot further modify the header, except for - `append` rules from the same extension. -- If a rule has removed a header, then lower priority rules cannot further modify the header. +Static rules are those specified in rule files declared in the manifest file. An extension can specify up to 50 static [rulesets](#type-Ruleset) as part of the `"rule_resources"` manifest key, but only 10 of these rulesets can be enabled at a time. The latter is called the [`MAX_NUMBER_OF_ENABLED_STATIC_RULESETS`](#property-MAX_NUMBER_OF_ENABLED_STATIC_RULESETS). Collectively, those rulesets are guaranteed at least 30,000 rules. This is called the [`GUARANTEED_MINIMUM_STATIC_RULES`](#property-GUARANTEED_MINIMUM_STATIC_RULES). -### Interaction with cached pages {: #implementation-cached-pages } +The number of rules available after that depends on how many rules are enabled by all the extensions installed on a user's browser. You can find this number at runtime by calling [`getAvailableStaticRuleCount()`](#method-getAvailableStaticRuleCount). You can see [an example of this](#update-static-rulesets) under [code examples](#code-examples). -When rules are applied to browsers with pages in the service worker's cached storage, the browser may ignore the set rule for those specific pages until the cached storage is cleared. This is because cached storage is intended to be persistent, and many features like offline use do not expect the cache to be cleared without also clearing a service worker's registration as well. For cases when extensions utilizing declarativeNetRequest must be enabled and disabled repeatedly, the [`chrome.browsingData`](/docs/extensions/reference/browsingData/) API may be used to clear the cache to guarantee proper functionality. +#### Dynamic and session rules {: #dynamic-session-rules } -## Example {: #example } +The limits applied to dynamic and session rules are simpler than static rules. The total number of both cannot exceed 5000. This is called the [`MAX_NUMBER_OF_DYNAMIC_AND_SESSION_RULES`](#property-MAX_NUMBER_OF_DYNAMIC_AND_SESSION_RULES). -{% Label %}manifest.json:{% endLabel %} +#### Rules that use regex {: #regex-rules } -```json -{ - "name": "declarativeNetRequest extension", - "version": "1", - "declarative_net_request": { - "rule_resources": [{ - "id": "ruleset_1", - "enabled": true, - "path": "rules.json" - }] - }, - "permissions": [ - "declarativeNetRequest" - ], - "host_permissions": [ - "*://*.google.com/*", - "*://*.abcd.com/*", - "*://*.example.com/*", - "https://*.xyz.com/*", - "*://*.headers.com/*", - ], - "manifest_version": 3 +All types of rules can use regular expressions; however, the total number of regex rules of each type cannot exceed 1000. This is called the [MAX_NUMBER_OF_REGEX_RULES](#property-MAX_NUMBER_OF_REGEX_RULES). + +Additionally, each rule must be less than 2KB once compiled. This roughly correlates with the complexity of the rule. If you try to load a rule that exceeds this limit, you will see a warning like the one below and the rule will be ignored. + +```bash +rules_1.json: Rule with id 1 specified a more complext regex than allowed +as part of the "regexFilter" key. +``` + +### Interactions with service workers {: #interact-w-service-workers } + +A declarativeNetRequest only applies to requests that reach the network stack. This includes responses from the HTTP cache, but may not include responses that go through a service worker's `onfetch` handler. declarativeNetRequest won't affect responses generated by the service worker or retrieved from `CacheStorage`, but it will affect calls to `fetch()` made in a service worker. + +### Web accessible resources {: #implementation-web-accessible-resources } + +A declarativeNetRequest rule cannot redirect from a public resource request to a resource that is not web accessible. Doing so triggers an error. This is true even if the specified web accessible resource is owned by the redirecting extension. To declare resources for declarativeNetRequest, use the manifest's [`"web_accessible_resources"`](/docs/extensions/mv3/manifest/web_accessible_resources/) array. + +## Examples {: #example } + +### Code examples {: #code-examples } + +#### Update dynamic rules {: #update-dynamic-rule-examples } + +The following example shows how to call `updateDynamicRules()`. The procedure for `updateSessionRules()` is the same. + +```js +// Get arrays containing new and old rules +const newRules = await getNewRules(); +const oldRules = await chrome.declarativeNetRequest.getDynamicRules(); +const oldRuleIds = oldRules.map(rule => rule.id); + +// Use the arrays to update the dynamic rules +await chrome.declarativeNetRequest.updateDynamicRules({ + removeRuleIds: oldRuleIds, + addRules: newRules +}); +``` + +#### Update static rulesets {: #update-static-rulesets } + +The following example shows how to enable and disable rulesets while considering the number of available and the maximum number of enabled static rulesets. You would do this when the number of static rules you need exceeds the number allowed. For this to work, some of your rulesets should be installed with some of your rulesets disabled (setting `"Enabled"` to `false` within the manifest file). + +```js +async function updateStaticRules(enableRulesetIds, disableCandidateIds) { + // Create the options structure for the call to updateEnabledRulesets() + let options = { enableRulesetIds: enableRulesetIds } + // Get the number of enabled static rules + const enabledStaticCount = await chrome.declarativeNetRequest.getEnabledRulesets(); + // Compare rule counts to determine if anything needs to be disabled so that + // new rules can be enabled + const proposedCount = enableRulesetIds.length; + if (enabledStaticCount + proposedCount > chrome.declarativeNetRequest.MAX_NUMBER_OF_ENABLED_STATIC_RULESETS) { + options.disableRulesetIds = disableCandidateIds + } + // Update the enabled static rules + await chrome.declarativeNetRequest.updateEnabledRulesets(options); } ``` -{% Label %}rules.json:{% endLabel %} +### Rule examples {: #rule-examples } +The examples below illustrate how Chrome prioritizes rules in an extension. When reviewing them, you may want to open the [prioritization](#implementation-matching-algorithm) rules in a separate window. + +#### The "priority" key {: #priority-key } + +These examples require [host permission](/docs/extensions/mv3/declare_permissions/) to `*://*.example.com/*`. + +To work out the priority of a particular URL, look at the (developer-defined) `"priority"` key, the `"action"` key and the `"urlFilter"` key. These examples refer to the example rule file shown below them. + +Navigation to https://google.com +: Two rules cover this URL: the rules with IDs 1 and 4. The rule with ID 1 applies because `"block"` actions have a higher priority than `"redirect"` actions. The remaining rules do not apply because they are for longer URLs. + +Navigation to https://google.com/1234 +: Because of the longer URL, the rule with ID 2 now matches in addition to the rules with IDs 1 and 4. The rule with ID 2 applies because `"allow"` has a higher priority than `"block"` and `"redirect"`. + +Navigation to https://google.com/12345 +: All four rules match this URL. The rule with ID 3 applies because its developer-defined priority is the highest of the group. ```json [ @@ -281,140 +320,88 @@ When rules are applied to browsers with pages in the service worker's cached sto "action": { "type": "redirect", "redirect": { "url": "https://example.com" } }, "condition": { "urlFilter": "google.com", "resourceTypes": ["main_frame"] } }, - { - "id": 5, - "priority": 1, - "action": { "type": "redirect", "redirect": { "extensionPath": "/a.jpg" } }, - "condition": { "urlFilter": "abcd.com", "resourceTypes": ["main_frame"] } - }, - { - "id": 6, - "priority": 1, - "action": { - "type": "redirect", - "redirect": { - "transform": { "scheme": "https", "host": "new.example.com" } - } - }, - "condition": { "urlFilter": "||example.com", "resourceTypes": ["main_frame"] } - }, - { - "id": 7, - "priority": 1, - "action": { - "type": "redirect", - "redirect": { - "regexSubstitution": "https://\\1.xyz.com/" - } - }, - "condition": { - "regexFilter": "^https://www\\.(abc|def)\\.xyz\\.com/", - "resourceTypes": [ - "main_frame" - ] - } - }, - { - "id" : 8, - "priority": 2, - "action" : { - "type" : "allowAllRequests" - }, - "condition" : { - "urlFilter" : "||b.com/path", - "resourceTypes" : ["sub_frame"] +] +``` + +#### Redirects {: #redirects } + +The example below requires [host permission](/docs/extensions/mv3/declare_permissions/) to `*://*.example.com/*`. + +The following example shows how to redirect a request from example.com to a page within the extension itself. The extension path `/a.jpg` resolves to `chrome-extension://EXTENSION_ID/a.jpg`, where `EXTENSION_ID` is the ID of your extension. For this to work the manifest should declare `/a.jpg` as a [web accessible resource](/docs/extensions/mv3/manifest/web_accessible_resources/). + +```json +{ + "id": 1, + "priority": 1, + "action": { "type": "redirect", "redirect": { "extensionPath": "/a.jpg" } }, + "condition": { + "urlFilter": "https://www.example.com", + "resourceTypes": ["main_frame"] + } +} +``` + +The following uses the `"transform"` key to redirect to a subdomain of example.com. It uses a domain name anchor ("||") to intercept requests with any scheme from example.com. The `"scheme"` key in `"transform"` specifies that redirects to the subdomain will always use "https". + +```json +{ + "id": 1, + "priority": 1, + "action": { + "type": "redirect", + "redirect": { + "transform": { "scheme": "https", "host": "new.example.com" } } }, - { - "id" : 9, - "priority": 1, - "action" : { - "type" : "block" - }, - "condition" : { - "urlFilter" : "script.js", - "resourceTypes" : ["script"] + "condition": { + "urlFilter": "||example.com", + "resourceTypes": ["main_frame"] + } +} +``` + +The following example uses regular expressions to redirect from `https://www.abc.xyz.com/path` to `https://abc.xyz.com/path`. In the `"regexFilter"` key, notice how periods are escaped and that the capturing group selects either "abc" or "def". The `"regexSubstitution"` key specifies the first returned match of the regular expression using "\\1". In this case, "abc" is captured from the redirected URL and placed in the substitution. + +```json +{ + "id": 1, + "priority": 1, + "action": { + "type": "redirect", + "redirect": { + "regexSubstitution": "https://\\1.xyz.com/" } }, - { - "id": 10, - "priority": 2, - "action": { - "type": "modifyHeaders", - "responseHeaders": [ - { "header": "h1", "operation": "remove" }, - { "header": "h2", "operation": "set", "value": "v2" }, - { "header": "h3", "operation": "append", "value": "v3" } - ] - }, - "condition": { "urlFilter": "headers.com/123", "resourceTypes": ["main_frame"] } - }, - { - "id": 11, - "priority": 1, - "action": { - "type": "modifyHeaders", - "responseHeaders": [ - { "header": "h1", "operation": "set", "value": "v4" }, - { "header": "h2", "operation": "append", "value": "v5" }, - { "header": "h3", "operation": "append", "value": "v6" } - ] - }, - "condition": { "urlFilter": "headers.com/12345", "resourceTypes": ["main_frame"] } + "condition": { + "regexFilter": "^https://www\\.(abc|def)\\.xyz\\.com/", + "resourceTypes": [ + "main_frame" + ] + } +} +``` + +#### Headers {: #headers } + +The following example removes all cookies from both a main frame and any sub frames. + +```json +{ + "id": 1, + "priority": 1, + "action": { + "type": "modifyHeaders", + "requestHeaders": [{ "header": "cookie", "operation": "remove" }] }, -] + "condition": { "resourceTypes": ["main_frame", "sub_frame"] } +} ``` -- Consider a navigation to `"https://google.com"`. Rules with id (1) and (4) match. The request will - be blocked because blocking rules have higher priority than redirect rules when the `"priority"` - is the same. -- Consider a navigation to `"https://google.com/1234"`. Rules with id (1), (2), and (4) match. - Because the request has a matching `allow` rule and no higher priority rules, the request is not - blocked nor redirected and continues to `"https://google.com/1234"`. -- Consider a navigation to `"https://google.com/12345"` Rules with id (1), (2), (3), and (4) match. - The request will be blocked because rule (3) has the highest priority, overriding all other - matching rules. -- Consider a navigation to `"https://abcd.com"`. The rule with id (5) matches. Since rule (5) - specifies an extension path, the request is redirected to - `"chrome-extension://EXTENSION_ID/a.jpg"`. -- Consider a navigation to `"http://example.com/path"`. The rule with id (6) matches. Since rule (6) - specifies a url transform, the request is redirected to `"https://new.example.com/path"`. -- Consider a navigation to `"https://www.abc.xyz.com/path"`. The rule with id (7) matches. The - request will be redirected to `"https://abc.xyz.com/path"`. -- Consider the following request hierarchy: - - https://a.com/path (main-frame request) - - https://b.com/path (sub-frame request, matches rule with id (8)) - - https://c.com/path (sub-frame request, matches rule with id (8)) - - https://c.com/script.js (script request, matches rules with ids (8, 9) but (8) has higher - priority) - - https://b.com/script.js (script request, matches rules with ids (8, 9) but (8) has higher - priority) - - https://d.com/path (sub-frame request) - - https://d.com/script.js (script request, matches rule with ids (9))All requests in green - will be allow-listed due to rule with id (8) and not be evaluated by the extensions' - ruleset. Requests in red will be blocked due to rule with id (9). -- Consider a navigation to `"https://headers.com/12345"` with response headers - `{ "h1": "initial_1", "h2": "initial_2" }`. Rules with id (10) and (11) match. The request will - have its response headers modified to `{ "h2": "v2", "h2": "v5", "h3": "v3", "h3": "v6" }`. Header - `h1` was removed by (10), `h2` was set by (10) then appended by (11), and `h3` was appended by - (10) and (11). - -To try the `chrome.declarativeNetRequest` API, -install the [declarativeNetRequest samples](https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/api-samples/declarativeNetRequest) from the [chrome-extension-samples](https://github.com/GoogleChrome/chrome-extensions-samples) -repository. - -[1]: /docs/extensions/mv3/manifest -[2]: /docs/extensions/mv3/declare_permissions -[3]: #type-Ruleset -[4]: #property-MAX_NUMBER_OF_STATIC_RULESETS -[5]: #property-GUARANTEED_MINIMUM_STATIC_RULES -[6]: #limits-global-static-rule-limit -[7]: #method-getAvailableStaticRuleCount -[8]: #type-Rule -[9]: #method-updateDynamicRules -[10]: #property-MAX_NUMBER_OF_DYNAMIC_AND_SESSION_RULES -[11]: #method-updateEnabledRulesets -[12]: /docs/extensions/webRequest -[13]: #method-updateSessionRules -[14]: #property-MAX_NUMBER_OF_ENABLED_STATIC_RULESETS -[15]: #property-MAX_NUMBER_OF_REGEX_RULES + + + + + + + + From becbddf2af28fb7ac0a43645b30499f84e033a6c Mon Sep 17 00:00:00 2001 From: Joe Medley Date: Fri, 4 Aug 2023 12:06:40 -0700 Subject: [PATCH 626/982] Update index.md (#6995) --- site/en/docs/webstore/api_index/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/en/docs/webstore/api_index/index.md b/site/en/docs/webstore/api_index/index.md index b7440a219..c35fef3f6 100644 --- a/site/en/docs/webstore/api_index/index.md +++ b/site/en/docs/webstore/api_index/index.md @@ -8,7 +8,7 @@ title: "Chrome Web Store API Reference" {% Aside 'warning' %} -The Licensing API used by the Chrome Web Store payments system is now deprecated. See [Payment +The Payments API used by the Chrome Web Store payments system is now deprecated. See [Payment deprecation](/docs/webstore/cws-payments-deprecation/) to learn about migration and official timelines. From 3ec6e7f67f78f437bb7dbeec259b7c5153b53a0e Mon Sep 17 00:00:00 2001 From: Sebastian Benz Date: Fri, 4 Aug 2023 21:18:18 +0200 Subject: [PATCH 627/982] Custom Tabs: document Chrome's increase in supported menu items (#6997) * Custom Tabs: document Chrome's increase in supported menu items * fix spelling * Update site/en/docs/android/custom-tabs/guide-interactivity/index.md Co-authored-by: Joe Medley --------- Co-authored-by: Joe Medley --- site/en/docs/android/custom-tabs/guide-interactivity/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/en/docs/android/custom-tabs/guide-interactivity/index.md b/site/en/docs/android/custom-tabs/guide-interactivity/index.md index 5d3312939..3d0aee7f7 100644 --- a/site/en/docs/android/custom-tabs/guide-interactivity/index.md +++ b/site/en/docs/android/custom-tabs/guide-interactivity/index.md @@ -75,7 +75,7 @@ CustomTabsIntent intentBuilder = new CustomTabsIntent.Builder() ## Add custom menu items -Custom tabs has as many as five default actions provided by the browser: "Forward", "Page Info", "Refresh", "Find in Page" and "Open in Browser". Additionally, you can add up to five more, which will be inserted between the icon row and the browser-provided items. (See the image below.) +A Custom Tab has as many as five default actions provided by the browser: "Forward", "Page Info", "Refresh", "Find in Page" and "Open in Browser". Additionally, you can add up to seven more. These menu items will be inserted between the icon row and the browser-provided items. (See the image below.) The actual number depends on the underlying browser implementation. (For example, with version 117 Chrome increased the number of menu items from five to seven.) So it is best to add the most important items first. You can access your custom actions via the three dot menu in the top right corner: From a2081a1a754610247175ab7caefa233050cffc17 Mon Sep 17 00:00:00 2001 From: Joe Medley Date: Fri, 4 Aug 2023 12:34:56 -0700 Subject: [PATCH 628/982] Update to MV3 language (#6996) --- site/en/docs/extensions/reference/windows/index.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/site/en/docs/extensions/reference/windows/index.md b/site/en/docs/extensions/reference/windows/index.md index a81d712c0..778876630 100644 --- a/site/en/docs/extensions/reference/windows/index.md +++ b/site/en/docs/extensions/reference/windows/index.md @@ -28,7 +28,7 @@ For example, say an extension creates a few tabs or windows from a single HTML f HTML file contains a call to [tabs.query][9]. The current window is the window that contains the page that made the call, no matter what the topmost window is. -In the case of the [event page][10], the value of the current window falls back to the last active +In the case of [service workers][10], the value of the current window falls back to the last active window. Under some circumstances, there may be no current window for background pages. ## Examples @@ -47,7 +47,7 @@ repository. [7]: /docs/extensions/reference/tabs#property-Tab-favIconUrl [8]: /docs/extensions/reference/tabs#type-Tab [9]: /docs/extensions/reference/tabs#method-query -[10]: /docs/extensions/mv2/event_pages +[10]: /docs/extensions/mv3/service_workers/ [11]: https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/mv2/api/windows/ [12]: https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/mv2/api/tabs/inspector/tabs_api.html [13]: https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/mv2/api/tabs/inspector/ From 756db0cb08badaa0651780be7786b3b593a30f2b Mon Sep 17 00:00:00 2001 From: Sebastian Benz Date: Fri, 4 Aug 2023 22:07:17 +0200 Subject: [PATCH 629/982] fix link formatting (#6985) * fix link formatting * Update site/en/articles/post-message-twa/index.md Co-authored-by: Joe Medley --------- Co-authored-by: Joe Medley --- site/en/articles/post-message-twa/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/en/articles/post-message-twa/index.md b/site/en/articles/post-message-twa/index.md index 77a22ffbc..fe542354b 100644 --- a/site/en/articles/post-message-twa/index.md +++ b/site/en/articles/post-message-twa/index.md @@ -53,7 +53,7 @@ Note that setup on the origin associated with the TWA, it is required to provide ## Add the PostMessageService to your manifest -To receive `postMessage` communication you need to setup the service, you do so by adding the `[PostMessageService]`(https://developer.android.com/reference/androidx/browser/customtabs/PostMessageService) in your Android manifest: +To receive `postMessage` communication you need to setup the service, you do so by adding the [`PostMessageService`](https://developer.android.com/reference/androidx/browser/customtabs/PostMessageService) in your Android manifest: ```xml Date: Mon, 7 Aug 2023 10:03:01 -0400 Subject: [PATCH 630/982] Add aggregation key generation steps for Private Aggregation (#6977) * Add aggregation key generation steps for Private Aggregation * Update MDN links * Apply suggestions from code review Co-authored-by: Anusmita --------- Co-authored-by: Anusmita --- .../private-aggregation-fundamentals/index.md | 32 +++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/site/en/docs/privacy-sandbox/private-aggregation-fundamentals/index.md b/site/en/docs/privacy-sandbox/private-aggregation-fundamentals/index.md index d73b93665..018a0282a 100644 --- a/site/en/docs/privacy-sandbox/private-aggregation-fundamentals/index.md +++ b/site/en/docs/privacy-sandbox/private-aggregation-fundamentals/index.md @@ -80,9 +80,37 @@ Let's say the key represents the count of users from France (country ID `061`) w If a dimension has available key space for multiple digits, but the value has fewer, add leading zeros. For example, if country ID allows 3 digits, the country ID for Algeria is `003`. {% endAside %} -The aggregation key can also be generated with a hashing mechanism, such as SHA-256. For example, the string `“WidgetID=3276;CountryID=67”` can be converted to a hex string `c002f0033c108abf3ae0ec654fe38a1792186bfd582380b24ea93ebdeb6395be` which is equivalent to the BigInt `86849257128445315549261263548129498923703362729078813106545648910309959898558n`. +The aggregation key can be also generated with a hashing mechanism, such as [SHA-256](https://en.wikipedia.org/wiki/SHA-2). For example, the string `{"WidgetId":3276,"CountryID":67}` can be hashed and then converted to a `BigInt` value of `42943797454801331377966796057547478208888578253058197330928948081739249096287n`. If the hash value has more than 128 bits, you can truncate it to ensure it won’t exceed the maximum allowed bucket value of `2^128−1`. -Some important web APIs that are required to generate a hash, like [`crypto`](https://developer.mozilla.org/docs/Web/API/Web_Crypto_API), are not currently available within Shared Storage worklets or Protected Audience API worklets. As these worklets cannot communicate outside of itself, if you want to create hashes, you need to pre-generate one or more hashes outside the worklet then pass it in. +Within a Shared Storage worklet, you can access the [`crypto`](https://developer.mozilla.org/docs/Web/API/Crypto) and [`TextEncoder`](https://developer.mozilla.org/docs/Web/API/TextEncoder) modules that can help you generate a hash. To learn more on generating a hash, check out [`SubtleCrypto.digest()` on MDN](https://developer.mozilla.org/docs/Web/API/SubtleCrypto/digest). + +The following example describes how you can generate a bucket key from a hashed value: + +```js +async function convertToBucket(data) { + // Encode as UTF-8 Uint8Array + const encodedData = new TextEncoder().encode(data); + + // Generate SHA-256 hash + const hashBuffer = await crypto.subtle.digest('SHA-256', encodedData); + + // Truncate the hash + const truncatedHash = Array.from(new Uint8Array(hashBuffer, 0, 16)); + + // Convert the byte sequence to a decimal + return truncatedHash.reduce((acc, curr) => acc * 256n + BigInt(curr), 0n); +} + +const data = { + WidgetId: 3276, + CountryID: 67 +}; + +const dataString = JSON.stringify(data); +const bucket = await convertToBucket(dataString); + +console.log(bucket); // 126200478277438733997751102134640640264n +``` {% Aside %} Although the concepts are similar, the key is constructed differently for the Private Aggregation API than the Attribution Reporting API. For Private Aggregation, the complete key is specified at the one time, in the JavaScript call. From af69540ade435b8a090158eda143c22c66cf91ca Mon Sep 17 00:00:00 2001 From: Joe Medley Date: Mon, 7 Aug 2023 13:58:58 -0700 Subject: [PATCH 631/982] Add new item to CWS troubleshooting. (#7010) * Add new item to CWS troubleshooting. * Fix date. * Update site/en/docs/webstore/troubleshooting/index.md Co-authored-by: amysteamdev <37001393+AmySteam@users.noreply.github.com> --------- Co-authored-by: amysteamdev <37001393+AmySteam@users.noreply.github.com> --- .../en/docs/webstore/troubleshooting/index.md | 36 +++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/site/en/docs/webstore/troubleshooting/index.md b/site/en/docs/webstore/troubleshooting/index.md index 76e42c0bd..fc2e803de 100644 --- a/site/en/docs/webstore/troubleshooting/index.md +++ b/site/en/docs/webstore/troubleshooting/index.md @@ -2,7 +2,7 @@ layout: "layouts/doc-post.njk" title: "Troubleshooting Chrome Web Store violations" date: 2020-11-16 -updated: 2023-04-21 +updated: 2023-08-08 description: > Guidelines for understanding why an item was rejected or removed from the Chrome Web Store and how to fix the problem. @@ -17,6 +17,38 @@ each violation a human-readable ID. These IDs are composed of two words: a color example, Yellow Magnesium corresponds to the general class of errors where the extension does not behave as expected. +## Additional requirements for Manifest V3 {: #additional-requirements-for-manifest-v3 } + +Corresponds to notification ID: `Blue Argon` + +The intent of this policy is to ensure that Manifest V3 extensions are not including remotely hosted code. + +### Common reasons for rejection + +* Including a ` + +{% endblock %} diff --git a/types/site/_collections/extensionSamples.d.ts b/types/site/_collections/extensionSamples.d.ts new file mode 100644 index 000000000..fa875480d --- /dev/null +++ b/types/site/_collections/extensionSamples.d.ts @@ -0,0 +1,31 @@ +declare global { + export interface SampleElement extends HTMLElement { + data: extensionSample; + } + + export interface extensionSample { + type: 'API_SAMPLE' | 'FUNCTIONAL_SAMPLE'; + name: string; + repo_link: string; + apis: extensionApiItem[]; + title: string; + description: string; + permissions: string[]; + } + + export interface extensionApiItem { + type: extensionApiTypeResult; + namespace: string; + propertyName: string; + } + + export type extensionApiTypeResult = + | 'event' + | 'method' + | 'property' + | 'type' + | 'unknown'; +} + +// empty export to keep file a module +export {}; From 811da5a37214986c3879440416d3c8c23a5d7769 Mon Sep 17 00:00:00 2001 From: Matthias Rohmer Date: Thu, 17 Aug 2023 16:37:22 +0200 Subject: [PATCH 685/982] fix: configure environment before fetching samples --- external/build/extension-samples.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/external/build/extension-samples.js b/external/build/extension-samples.js index 5f3391b99..1743b5e80 100644 --- a/external/build/extension-samples.js +++ b/external/build/extension-samples.js @@ -4,6 +4,8 @@ * https://github.com/GoogleChrome/chrome-extensions-samples */ +require('dotenv').config(); + const { getGitHubApiClient, } = require('../../gulp-tasks/stageGitHub/lib/gitHubApi.js'); From d47a76ba524a80e71b5468120311ab5fbea0590e Mon Sep 17 00:00:00 2001 From: Matthias Rohmer Date: Thu, 17 Aug 2023 17:09:41 +0200 Subject: [PATCH 686/982] perf: use built in gcp secret managing for cloud build --- .cloudbuild/external.yaml | 17 ++++++++++++----- external/build/extension-samples.js | 2 -- external/build/youtube-playlist.js | 4 +--- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/.cloudbuild/external.yaml b/.cloudbuild/external.yaml index 5f8d862eb..5eb0c5a75 100644 --- a/.cloudbuild/external.yaml +++ b/.cloudbuild/external.yaml @@ -9,11 +9,6 @@ steps: entrypoint: npm args: ['ci'] - - name: node:16.14.2 - id: 'Configure secrets' - entrypoint: npm - args: ['run', 'cloud-secrets'] - - name: node:16.14.2 id: 'Build external data' entrypoint: npm @@ -49,3 +44,15 @@ options: env: - 'PROJECT_ID=$PROJECT_ID' - 'NODE_OPTIONS=--unhandled-rejections=strict' + secretEnv: ['GITHUB_APP_ID', 'GITHUB_APP_KEY', 'GITHUB_APP_INSTALLATION_ID', 'TWITTER_BEARER', 'YOUTUBE_API_KEY'] + +availableSecrets: + secretManager: + - versionName: projects/dcc-staging/secrets/GITHUB_APP_ID/versions/1 + env: 'GITHUB_APP_ID' + - versionName: projects/dcc-staging/secrets/GITHUB_APP_KEY/versions/4 + env: 'GITHUB_APP_KEY' + - versionName: projects/dcc-staging/secrets/GITHUB_APP_INSTALLATION_ID/versions/1 + env: 'GITHUB_APP_INSTALLATION_ID' + - versionName: projects/dcc-staging/secrets/YOUTUBE_API_KEY/versions/1 + env: 'YOUTUBE_API_KEY' \ No newline at end of file diff --git a/external/build/extension-samples.js b/external/build/extension-samples.js index 1743b5e80..5f3391b99 100644 --- a/external/build/extension-samples.js +++ b/external/build/extension-samples.js @@ -4,8 +4,6 @@ * https://github.com/GoogleChrome/chrome-extensions-samples */ -require('dotenv').config(); - const { getGitHubApiClient, } = require('../../gulp-tasks/stageGitHub/lib/gitHubApi.js'); diff --git a/external/build/youtube-playlist.js b/external/build/youtube-playlist.js index d1312eaef..c24f01481 100644 --- a/external/build/youtube-playlist.js +++ b/external/build/youtube-playlist.js @@ -17,8 +17,6 @@ * @fileoverview Fetches the most recent playlists by specified channels from YouTube */ -require('dotenv').config(); - const fs = require('fs').promises; const path = require('path'); const ms = require('ms'); @@ -189,7 +187,7 @@ async function checkDataTimestamp() { * specified in the config. */ async function run() { - if (!process.env.YOUTUBE_API_KEY) { + if (!API_KEY) { throw new Error('No `YOUTUBE_API_KEY` environment var for production'); } From 287772450603c83a54dc7e621b56ed4472e18ce7 Mon Sep 17 00:00:00 2001 From: Matthias Rohmer Date: Thu, 17 Aug 2023 17:10:35 +0200 Subject: [PATCH 687/982] fix: remove unused twitter bearer secret --- .cloudbuild/external.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.cloudbuild/external.yaml b/.cloudbuild/external.yaml index 5eb0c5a75..35717d81d 100644 --- a/.cloudbuild/external.yaml +++ b/.cloudbuild/external.yaml @@ -44,7 +44,7 @@ options: env: - 'PROJECT_ID=$PROJECT_ID' - 'NODE_OPTIONS=--unhandled-rejections=strict' - secretEnv: ['GITHUB_APP_ID', 'GITHUB_APP_KEY', 'GITHUB_APP_INSTALLATION_ID', 'TWITTER_BEARER', 'YOUTUBE_API_KEY'] + secretEnv: ['GITHUB_APP_ID', 'GITHUB_APP_KEY', 'GITHUB_APP_INSTALLATION_ID', 'YOUTUBE_API_KEY'] availableSecrets: secretManager: From ee01e72a1b906ee59304b4b56a9271678723c3e3 Mon Sep 17 00:00:00 2001 From: Matthias Rohmer Date: Thu, 17 Aug 2023 17:11:16 +0200 Subject: [PATCH 688/982] fix: use correct gcp project for secrets --- .cloudbuild/external.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.cloudbuild/external.yaml b/.cloudbuild/external.yaml index 35717d81d..85bdb99d2 100644 --- a/.cloudbuild/external.yaml +++ b/.cloudbuild/external.yaml @@ -48,11 +48,11 @@ options: availableSecrets: secretManager: - - versionName: projects/dcc-staging/secrets/GITHUB_APP_ID/versions/1 + - versionName: projects/chrome-apps-doc/secrets/GITHUB_APP_ID/versions/1 env: 'GITHUB_APP_ID' - - versionName: projects/dcc-staging/secrets/GITHUB_APP_KEY/versions/4 + - versionName: projects/chrome-apps-doc/secrets/GITHUB_APP_KEY/versions/4 env: 'GITHUB_APP_KEY' - - versionName: projects/dcc-staging/secrets/GITHUB_APP_INSTALLATION_ID/versions/1 + - versionName: projects/chrome-apps-doc/secrets/GITHUB_APP_INSTALLATION_ID/versions/1 env: 'GITHUB_APP_INSTALLATION_ID' - - versionName: projects/dcc-staging/secrets/YOUTUBE_API_KEY/versions/1 + - versionName: projects/chrome-apps-doc/secrets/YOUTUBE_API_KEY/versions/1 env: 'YOUTUBE_API_KEY' \ No newline at end of file From 9bdf1aced580e37ba0d1046d4507d47e0bf56c75 Mon Sep 17 00:00:00 2001 From: Nancymic2 Date: Thu, 17 Aug 2023 16:35:18 -0400 Subject: [PATCH 689/982] PS demo library (#6287) * demos * demos * demos * demos * demos * demos * demos * demos * edit * Update index.md * Update index.md * Update index.md * Update index.md * Update index.md * Update site/en/docs/privacy-sandbox/demos/index.md Co-authored-by: Anusmita * Update site/en/docs/privacy-sandbox/demos/index.md Co-authored-by: Anusmita * Update index.md * partials * partials * partials * space * partials * fix link * remove fedCM newly missing demo * better links (to new docs) --------- Co-authored-by: Anusmita --- site/_data/docs/privacy-sandbox/toc.yml | 1 + .../en/_partials/privacy-sandbox/demos/ara.md | 45 +++++++++++++++++++ .../_partials/privacy-sandbox/demos/fedcm.md | 18 ++++++++ .../en/_partials/privacy-sandbox/demos/fps.md | 18 ++++++++ .../_partials/privacy-sandbox/demos/paapi.md | 22 +++++++++ .../demos/permissions-policy.md | 18 ++++++++ .../privacy-sandbox/demos/private-state.md | 18 ++++++++ .../privacy-sandbox/demos/shared-storage.md | 21 +++++++++ .../_partials/privacy-sandbox/demos/topics.md | 45 +++++++++++++++++++ .../privacy-sandbox/demos/ua-reduction.md | 42 +++++++++++++++++ site/en/docs/privacy-sandbox/demos/index.md | 35 +++++++++++++++ 11 files changed, 283 insertions(+) create mode 100644 site/en/_partials/privacy-sandbox/demos/ara.md create mode 100644 site/en/_partials/privacy-sandbox/demos/fedcm.md create mode 100644 site/en/_partials/privacy-sandbox/demos/fps.md create mode 100644 site/en/_partials/privacy-sandbox/demos/paapi.md create mode 100644 site/en/_partials/privacy-sandbox/demos/permissions-policy.md create mode 100644 site/en/_partials/privacy-sandbox/demos/private-state.md create mode 100644 site/en/_partials/privacy-sandbox/demos/shared-storage.md create mode 100644 site/en/_partials/privacy-sandbox/demos/topics.md create mode 100644 site/en/_partials/privacy-sandbox/demos/ua-reduction.md create mode 100644 site/en/docs/privacy-sandbox/demos/index.md diff --git a/site/_data/docs/privacy-sandbox/toc.yml b/site/_data/docs/privacy-sandbox/toc.yml index 0ab31cf66..1bd464257 100644 --- a/site/_data/docs/privacy-sandbox/toc.yml +++ b/site/_data/docs/privacy-sandbox/toc.yml @@ -9,6 +9,7 @@ - url: /docs/privacy-sandbox/glossary title: i18n.docs.privacy-sandbox.glossary - url: /docs/privacy-sandbox/events + - url: /docs/privacy-sandbox/demos - url: /tags/privacy title: i18n.docs.privacy-sandbox.blog - url: /docs/privacy-sandbox/videos diff --git a/site/en/_partials/privacy-sandbox/demos/ara.md b/site/en/_partials/privacy-sandbox/demos/ara.md new file mode 100644 index 000000000..318430b8e --- /dev/null +++ b/site/en/_partials/privacy-sandbox/demos/ara.md @@ -0,0 +1,45 @@ +{% Details %} +{% DetailsSummary %} +**Attribution Reporting** +{% endDetailsSummary %} + +**Demo** + +{% Columns %} +{% Column %} +The Attribution Reporting API enables advertisers and ad tech providers to measure conversions for ad clicks and views, +ads in a third-party iframe, and ads in a first-party context. In this demo an advertiser uses an ad tech provider to run their ads on a publisher site. + +[Demo](https://arapi-home.web.app/) + +[Docs](/docs/privacy-sandbox/attribution-reporting/) + +[Summary reports walkthrough video](https://drive.google.com/file/d/18RGEx_mrhDJuMsLUK1BZ0cK5FSZRAAqh/view) + +{% endColumn %} +{% Column %} + +{% Img src="image/RtQlPaM9wdhEJGVKR8boMPkWf443/cQABHch0L68I92idOgcN.png", alt="Attribution Reporting API demo.", width="707", height="512" %} + +{% endColumn %} +{% endColumns %} + + +**Noiselab** + +{% Columns %} +{% Column %} +When aggregatable reports are batched by a collector and processed by the aggregation service, random data is added to the resulting summary reports in order to protect user privacy. Use Noiselab to experiment with different values to see the impact of noise. + +[Noise Lab](https://noise-lab.uc.r.appspot.com/?mode=simple) + +[Docs](/docs/privacy-sandbox/attribution-reporting/understanding-noise/) + +{% endColumn %} +{% Column %} + +{% Img src="image/RtQlPaM9wdhEJGVKR8boMPkWf443/9pln3PilOb2Hh5zrLdhz.png", alt="Noise Lab.", width="686", height="448" %} + +{% endColumn %} +{% endColumns %} +{% endDetails %} diff --git a/site/en/_partials/privacy-sandbox/demos/fedcm.md b/site/en/_partials/privacy-sandbox/demos/fedcm.md new file mode 100644 index 000000000..c122f0a15 --- /dev/null +++ b/site/en/_partials/privacy-sandbox/demos/fedcm.md @@ -0,0 +1,18 @@ +{% Details %} +{% DetailsSummary %} +**FedCM** +{% endDetailsSummary %} +{% Columns %} +{% Column %} +FedCM is a privacy-preserving approach to federated identity services where users can log into sites without sharing their personal information with the identity service or the site. This demo illustrates how it works. + +[Demo](https://fedcm-rp-demo.glitch.me) + +[Docs](/docs/privacy-sandbox/fedcm/) + +{% endColumn %} +{% Column %} +{% Img src="image/RtQlPaM9wdhEJGVKR8boMPkWf443/r9RNu995n1Toyp9ysI5d.png", alt="FedCM demo.", width="514", height="380" %} +{% endColumn %} +{% endColumns %} +{% endDetails %} \ No newline at end of file diff --git a/site/en/_partials/privacy-sandbox/demos/fps.md b/site/en/_partials/privacy-sandbox/demos/fps.md new file mode 100644 index 000000000..f2b3b66aa --- /dev/null +++ b/site/en/_partials/privacy-sandbox/demos/fps.md @@ -0,0 +1,18 @@ +{% Details %} +{% DetailsSummary %} +**First-party Sets** +{% endDetailsSummary %} +{% Columns %} +{% Column %} +First-Party Sets (FPS) is a way for a company to declare relationships among sites, so that browsers allow limited third-party cookie access for specific purposes. Chrome will use these declared relationships to decide when to allow or deny a site access to their cookies when in a third-party context. + +[Demo](https://first-party-sets.glitch.me/) + +[Docs](/docs/privacy-sandbox/first-party-sets/) + +{% endColumn %} +{% Column %} +{% Img src="image/RtQlPaM9wdhEJGVKR8boMPkWf443/xQbEZnwQ7Fjw8MOYuddS.png", alt="First-Party Sets demo.", width="600", height="400" %} +{% endColumn %} +{% endColumns %} +{% endDetails %} \ No newline at end of file diff --git a/site/en/_partials/privacy-sandbox/demos/paapi.md b/site/en/_partials/privacy-sandbox/demos/paapi.md new file mode 100644 index 000000000..dbcb6c595 --- /dev/null +++ b/site/en/_partials/privacy-sandbox/demos/paapi.md @@ -0,0 +1,22 @@ +{% Details %} +{% DetailsSummary %} +**Protected Audience API** +{% endDetailsSummary %} +{% Columns %} +{% Column %} + +The demo uses the Protected Audience API to join ad interest groups on two advertiser sites, +and then initiates an on-device auction to select an ad for display on a publisher site. + +[Demo](https://protected-audience-demo.web.app/) + +[Docs](/docs/privacy-sandbox/fledge-api/) + +{% endColumn %} +{% Column %} + +{% Img src="image/RtQlPaM9wdhEJGVKR8boMPkWf443/pi7cN0x6j7OAJXoog0zo.png", alt="Protected Audience API demo.", width="800", height="708" %} + +{% endColumn %} +{% endColumns %} +{% endDetails %} diff --git a/site/en/_partials/privacy-sandbox/demos/permissions-policy.md b/site/en/_partials/privacy-sandbox/demos/permissions-policy.md new file mode 100644 index 000000000..7e8d95982 --- /dev/null +++ b/site/en/_partials/privacy-sandbox/demos/permissions-policy.md @@ -0,0 +1,18 @@ +{% Details %} +{% DetailsSummary %} +**Permissions Policy** +{% endDetailsSummary %} +{% Columns %} +{% Column %} +Permissions Policy allows the developer to control the browser features available to a page, its iframes, and subresources, by declaring a set of policies for the browser to enforce. This demo lets you try out the available policies. + +[Demo](https://permissions-policy-demo.glitch.me/demo/) + +[Docs](/docs/privacy-sandbox/permissions-policy/) + +{% endColumn %} +{% Column %} +{% Img src="image/RtQlPaM9wdhEJGVKR8boMPkWf443/qaZFVmYVbQmEGhl004VT.png", alt="Permissions Policy demo.", width="676", height="458" %} +{% endColumn %} +{% endColumns %} +{% endDetails %} \ No newline at end of file diff --git a/site/en/_partials/privacy-sandbox/demos/private-state.md b/site/en/_partials/privacy-sandbox/demos/private-state.md new file mode 100644 index 000000000..ea4dedc8a --- /dev/null +++ b/site/en/_partials/privacy-sandbox/demos/private-state.md @@ -0,0 +1,18 @@ +{% Details %} +{% DetailsSummary %} +**Private State Token API** +{% endDetailsSummary %} +{% Columns %} +{% Column %} +With the Private State Token API, a website can issue cryptographic tokens to a user it trusts, which can later be used elsewhere. The tokens are stored securely by the user's browser, and can then be redeemed in other contexts to confirm the user's authenticity. Check out the API in this demo. + +[Demo](https://private-state-token-demo.glitch.me/) + +[Docs](/docs/privacy-sandbox/trust-tokens/) +{% endColumn %} + +{% Column %} +{% Img src="image/RtQlPaM9wdhEJGVKR8boMPkWf443/OVudOoLOz1BKNEmfY1pc.png", alt="Private State Token API demo.", width="620", height="519" %} +{% endColumn %} +{% endColumns %} +{% endDetails %} diff --git a/site/en/_partials/privacy-sandbox/demos/shared-storage.md b/site/en/_partials/privacy-sandbox/demos/shared-storage.md new file mode 100644 index 000000000..288ec4d1a --- /dev/null +++ b/site/en/_partials/privacy-sandbox/demos/shared-storage.md @@ -0,0 +1,21 @@ +{% Details %} +{% DetailsSummary %} +**Shared Storage** +{% endDetailsSummary %} + +{% Columns %} +{% Column %} +The Shared Storage API provides storage that can be used cross-site, meaning you store a value at one domain, then read the value from another domain. You can set data freely, but are restricted in how you get data out of storage. This demo illustrates how it works. + +[Demo](https://shared-storage-demo.web.app/) + +[Docs](/docs/privacy-sandbox/shared-storage/) + +{% endColumn %} +{% Column %} + +{% Img src="image/RtQlPaM9wdhEJGVKR8boMPkWf443/dOFtwOaI8ldFfwgmG5El.png", alt="Shared Storage API demo.", width="751", height="521" %} + +{% endColumn %} +{% endColumns %} +{% endDetails %} diff --git a/site/en/_partials/privacy-sandbox/demos/topics.md b/site/en/_partials/privacy-sandbox/demos/topics.md new file mode 100644 index 000000000..7a7c9f5ca --- /dev/null +++ b/site/en/_partials/privacy-sandbox/demos/topics.md @@ -0,0 +1,45 @@ +{% Details %} +{% DetailsSummary %} +**Topics API** +{% endDetailsSummary %} + +**Demo** + +{% Columns %} +{% Column %} +The Topics API allows a browser to share information about a user's interests with third parties without the use of third-party cookies. It enables interest-based advertising (IBA) without tracking the sites a user visits. This demo shows an example of the API in action. + +[Demo](https://topics-demo.glitch.me/) + +[Walkthrough video](https://www.youtube.com/watch?v=hEBzWuXjeTQ) + +[Docs](/docs/privacy-sandbox/topics/overview/) + +{% endColumn %} +{% Column %} + +{% Img src="image/RtQlPaM9wdhEJGVKR8boMPkWf443/3YDJBguZVeVorWT4BdkA.png", alt="The Topics API demo.", width="469", height="386" %} + +{% endColumn %} +{% endColumns %} + +**Colab** + +{% Columns %} +{% Column %} +This colab makes it easy to load the TensorFlow Lite model used by Chrome to infer topics from hostnames. + +[Colab](https://colab.research.google.com/drive/1hIVoz8bRCTpllYvads51MV7YS3zi3prn) + +[Colab doc](/docs/privacy-sandbox/topics/colab/) + +[Walkthrough video](https://www.youtube.com/watch?v=hEBzWuXjeTQ) + +{% endColumn %} +{% Column %} + +{% Img src="image/RtQlPaM9wdhEJGVKR8boMPkWf443/Au0wqVDHINuCmWxN0lOR.png", alt="Topics API colab.", width="503", height="269" %} + +{% endColumn %} +{% endColumns %} +{% endDetails %} \ No newline at end of file diff --git a/site/en/_partials/privacy-sandbox/demos/ua-reduction.md b/site/en/_partials/privacy-sandbox/demos/ua-reduction.md new file mode 100644 index 000000000..27fb36cb8 --- /dev/null +++ b/site/en/_partials/privacy-sandbox/demos/ua-reduction.md @@ -0,0 +1,42 @@ +{% Details %} +{% DetailsSummary %} +**User Agent Reduction** +{% endDetailsSummary %} +{% Columns %} +{% Column %} +User-Agent reduction minimizes the identifying information shared in the User-Agent string, which may be used for passive fingerprinting. Resource requests have a reduced User-Agent header now and the return values from certain Navigator interfaces are reduced. This demo lets you experiment with the new UA string values. + +[Demo](https://uar-ot.glitch.me/) + +[Docs](/docs/privacy-sandbox/user-agent/) + +{% endColumn %} +{% Column %} +{% Img src="image/RtQlPaM9wdhEJGVKR8boMPkWf443/S5ALrfmMdD2xDkIpsnS0.png", alt="User Agent Reduction demo.", width="800", height="627" %} +{% endColumn %} +{% endColumns %} +{% Columns %} +{% Column %} +JavaScript reduced user-agent + +[Demo](https://reduced-ua.glitch.me/javascript.html) + +[Docs](/docs/privacy-sandbox/user-agent/) +{% endColumn %} +{% Column %} +{% Img src="image/RtQlPaM9wdhEJGVKR8boMPkWf443/rQpRviM9Xv2tYAxDg0Bc.png", alt="JavaScript reduced user-agent demo.", width="694", height="396" %} +{% endColumn %} +{% endColumns %} +{% Columns %} +{% Column %} +Server-side reduced user-agent + +[Demo](https://reduced-ua.glitch.me/server-side) + +[Docs](/docs/privacy-sandbox/user-agent/) +{% endColumn %} +{% Column %} +{% Img src="image/RtQlPaM9wdhEJGVKR8boMPkWf443/pon9P8soEiUNb4gTfluf.png", alt="Server-side reduced user-agent demo.", width="592", height="544" %} +{% endColumn %} +{% endColumns %} +{% endDetails %} \ No newline at end of file diff --git a/site/en/docs/privacy-sandbox/demos/index.md b/site/en/docs/privacy-sandbox/demos/index.md new file mode 100644 index 000000000..1503a1603 --- /dev/null +++ b/site/en/docs/privacy-sandbox/demos/index.md @@ -0,0 +1,35 @@ +--- +layout: 'layouts/doc-post.njk' +title: 'Privacy Sandbox demos' +subhead: > + Demos and colabs walk you through the Privacy Sandbox APIs. +description: > + Demos and colabs walk you through the Privacy Sandbox APIs. +date: 2023-08-18 +authors: + - alexandrawhite +--- + +There are a number of demos available for the Privacy Sandbox APIs. Most of them will require you to be familiar with the APIs, so if you haven't read the docs, check out the links we've listed along with the demos. + +

+

+ +## Demos and colabs + +{% Partial 'privacy-sandbox/demos/paapi.njk' %} + +{% Partial 'privacy-sandbox/demos/topics.njk' %} + +{% Partial 'privacy-sandbox/demos/ara.njk' %} + +{% Partial 'privacy-sandbox/demos/shared-storage.njk' %} + +{% Partial 'privacy-sandbox/demos/fps.njk' %} + +{% Partial 'privacy-sandbox/demos/permissions-policy.njk' %} + +{% Partial 'privacy-sandbox/demos/ua-reduction.njk' %} + +{% Partial 'privacy-sandbox/demos/private-state.njk' %} + From 890241571f12787fb32b4a48c99699980a1d8a61 Mon Sep 17 00:00:00 2001 From: Joe Medley Date: Fri, 18 Aug 2023 07:14:43 -0700 Subject: [PATCH 690/982] Add en_AU to locales list (#7110) Source is here: https://source.corp.google.com/piper///depot/google3/java/com/google/chrome/webstore/common/LanguageInfo.java There is no ticket for this. --- site/en/docs/webstore/i18n/index.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/site/en/docs/webstore/i18n/index.md b/site/en/docs/webstore/i18n/index.md index c53f26393..b493e17e2 100644 --- a/site/en/docs/webstore/i18n/index.md +++ b/site/en/docs/webstore/i18n/index.md @@ -2,7 +2,7 @@ layout: "layouts/doc-post.njk" title: Internationalize your extension date: 2017-08-30 -updated: 2023-05-01 +updated: 2023-08-17 description: How to internationalize your Chrome Web Store extension. --- @@ -57,6 +57,7 @@ You can localize your extension to any of the following locales. | de | German | | el | Greek | | en | English | +| en_AU | English (Australia) | | en_GB | English (Great Britain) | | en_US | English (USA) | | es | Spanish | From 963dd1d162975ea111cde62163dac990d2f62c3d Mon Sep 17 00:00:00 2001 From: Thomas Steiner Date: Fri, 18 Aug 2023 16:27:31 +0200 Subject: [PATCH 691/982] Add tabbed application mode article (#7107) --- .../articles/tabbed-application-mode/index.md | 230 ++++++++++++++++++ 1 file changed, 230 insertions(+) create mode 100644 site/en/articles/tabbed-application-mode/index.md diff --git a/site/en/articles/tabbed-application-mode/index.md b/site/en/articles/tabbed-application-mode/index.md new file mode 100644 index 000000000..3f6008e4a --- /dev/null +++ b/site/en/articles/tabbed-application-mode/index.md @@ -0,0 +1,230 @@ +--- +layout: 'layouts/blog-post.njk' +title: Tabbed application mode for PWAs +subhead: Work on more than one document at a time with tabs in your Progressive Web App +authors: + - thomassteiner +date: 2021-02-25 +updated: 2023-08-17 +description: | + Tabbed application mode allows Progressive Web App developers to add a tabbed document interface + to their standalone PWAs. +hero: image/8WbTDNrhLsU0El80frMBGE4eMCD3/N08W5skJmcYgS7346DBS.jpg +alt: Dictionary thumb index. +tags: + - progressive-web-apps + - capabilities +--- + +{% Aside %} Tabbed application mode is part of the +[capabilities project](/blog/fugu-status/) and is currently in +development. This post will be updated as the implementation progresses. Tabbed application mode is +an early-stage exploration of the Chrome team. It is not ready for production yet. {% endAside %} + +In the world of computing, the [desktop metaphor](https://en.wikipedia.org/wiki/Desktop_metaphor) is +an interface metaphor that is a set of unifying concepts used by graphical user interfaces (GUI) to +help users interact more easily with the computer. In keeping with the desktop metaphor, GUI tabs +are modeled after traditional card tabs inserted in books, paper files, or card indexes. A _tabbed +document interface_ (TDI) or tab is a graphical control element that allows multiple documents or +panels to be contained within a single window, using tabs as a navigational widget for switching +between sets of documents. + +Progressive Web Apps can run in [various display modes](/add-manifest/#display) determined by the +`display` property in the web app manifest. Examples are `fullscreen`, `standalone`, `minimal-ui`, +and `browser`. These display modes follow a +[well-defined fallback chain](https://w3c.github.io/manifest/#dfn-fallback-display-mode) +(`"fullscreen"` → `"standalone"` → `"minimal-ui"` → `"browser"`). If a browser does not support a +given mode, it falls back to the next display mode in the chain. Via the +[`"display_override"`](/display-override/) property, developers can specify their own fallback chain +if they need to. + +## What is tabbed application mode + +Something that has been missing from the platform so far is a way to let PWA developers offer their +users a tabbed document interface, for example, to enable editing different files in the same PWA +window. Tabbed application mode closes this gap. + +{% Aside %} This feature is about having a standalone app window with multiple tabs (containing +separate documents inside the app scope) inside it. It is not to be confused with the existing +`"display": "browser"`, which has a separate meaning (specifically, that the app is opened in a +regular browser tab). {% endAside %} + +### Suggested use cases for tabbed application mode + +Examples of sites that may use tabbed application mode include: + +- Productivity apps that let the user edit more than one document (or file) at the same time. +- Communication apps that let the user have conversations in different rooms per tab. +- Reading apps that open article links in new in-app tabs. + +### Differences to developer-built tabs + +Having documents in separate browser tabs comes with resource isolation for free, which is not +possible using the web today. Developer-built tabs would not scale acceptably to hundreds of tabs +like browser tabs do. Browser affordances such as navigation history, "Copy this page URL", "Cast +this tab" or "Open this page in a web browser" would be applied to the developer-built tabbed +interface page, but not the currently selected document page. + +### Differences to `"display": "browser"` + +The current `"display": "browser"` already has a +[specific meaning](https://w3c.github.io/manifest/#dom-displaymodetype-browser): + +> Opens the web application using the platform-specific convention for opening hyperlinks in the +> user agent (e.g., in a browser tab or a new window). + +While browsers can do whatever they want regarding UI, it would clearly be a pretty big subversion +of developer expectations if `"display": "browser"` suddenly meant "run in a separate +application-specific window with no browser affordances, but a tabbed document interface". + +Setting `"display": "browser"` is effectively the way you _opt out_ of being put into an application +window. + +## Current status + +
+ +| Step | Status | +| ---------------------------------------- | ------------------------ | +| 1. Create explainer | [Completed][explainer] | +| 2. Create initial draft of specification | Not started | +| 3. Gather feedback & iterate on design | [In progress](#feedback) | +| 4. Origin trial | Not started | +| 5. Launch | Not started | + +
+ +## Using tabbed application mode + +To use tabbed application mode, developers need to opt their apps in by setting a specific +[`"display_override"`](/display-override/) mode value in the web app manifest. + +```json +{ + "display": "standalone", + "display_override": ["tabbed"] +} +``` + +Next, the property `"tab_strip"` can optionally be used to fine-tune the tab behavior. It has two +allowed sub-properties, `"home_tab"` and `"new_tab_button"`. If the `"tab_strip"` property is not +present, the particular properties' `"auto"` values are used. The browser determines what values to +use for `"auto"`. + +### Home tab + +The home tab is a pinned tab that, if enabled for an app, should always be present when the app is +open. This tab should never navigate. Links clicked from this tab should open in a new app tab. Apps +can choose to customize the URL this tab is locked to and the icon displayed on the tab. + +The allowed values for `"home_tab"` are: + +- `"auto"` to let the browser determine what to do. +- `"absent"` to tell the browser to not show a home tab. +- An object with two sub-properties: + - `"url"` with the allowed values of `"auto"` or a URL to lock the home tab to. + - `"icons"` with the allowed values of `"auto"` or an array of icons as in the main + [`"icons"` property](/add-manifest/#icons). + +### New tab button + +The new tab button, if present, should open a new tab at a URL that is within the scope of the app. +The app may choose to set a custom URL and icon for this button. Browsers can decide how to handle +dragging these tabs around to create new windows or combine with browser tabs. + +The allowed values for `"new_tab_button"` are: + +- `"auto"` to let the browser determine what to do. +- `"absent"` to tell the browser to not show a new tab button. +- An object with two sub-properties: + - `"url"` with the allowed values of `"auto"` or an in-scope URL to open new tabs on. + - `"icons"` with the allowed values of `"auto"` or an array of icons as in the main + [`"icons"` property](/add-manifest/#icons). + +### Complete example + +A complete example to configure the behavior of an app with a tabbed interface may look as follows: + +```json +{ + "display_override": ["tabbed"], + "tab_strip": { + "home_tab": { + "url": "./home/", + "icons": [ + { + "src": "./home.svg", + "sizes": "any", + "type": "image/svg+xml" + } + ] + }, + "new_tab_button": { + "url": "./new-tab/", + "icons": [ + { + "src": "./new-tab.svg", + "sizes": "any", + "type": "image/svg+xml" + } + ] + } + } +} +``` + +### Demo + +You can try tabbed application mode by setting a browser flag: + +1. Set the `#enable-desktop-pwas-tab-strip` flag. +1. Install the app [tabbed-application-mode.glitch.me](https://tabbed-application-mode.glitch.me/) + ([source code](https://glitch.com/edit/#!/tabbed-application-mode?path=manifest.json)). +1. Click the different links on the different tabs. + +{% Img src="image/8WbTDNrhLsU0El80frMBGE4eMCD3/piz5g2gsqkkQMNmgJ1db.png", alt="Screenshot of the tabbed application mode demo at tabbed-application-mode.glitch.me.", width="800", height="706" %} + +## Feedback + +The Chrome team wants to hear about your experiences with tabbed application mode. + +### Tell us about the API design + +Is there something about tabbed application mode that does not work like you expected? Comment on +the [web app manifest Issue][issue] that we have created. + +### Report a problem with the implementation + +Did you find a bug with Chrome's implementation? File a bug at +[new.crbug.com](https://new.crbug.com). Be sure to include as much detail as you can, simple +instructions for reproducing, and enter `UI>Browser>WebAppInstalls` in the **Components** box. +[Glitch](https://glitch.com/) works great for sharing quick and easy reproduction cases. + +### Show support for the API + +Are you planning to use tabbed application mode? Your public support helps the Chrome team +prioritize features and shows other browser vendors how critical it is to support them. + +Send a tweet to [@ChromiumDev][cr-dev-twitter] using the hashtag +[`#TabbedApplicationMode`](https://twitter.com/search?q=%23TabbedApplicationMode&src=typed_query&f=live) +and let us know where and how you are using it. + +## Useful links + +- [Explainer][explainer] +- [Web app manifest spec issue][issue] +- [Chromium bug](https://crbug.com/897314) +- Blink Component: [`UI>Browser>WebAppInstalls`][blink-component] + +## Acknowledgements + +Tabbed application mode was explored by [Matt Giuca](https://github.com/mgiuca). The experimental +implementation in Chrome was the work of [Alan Cutter](https://github.com/alancutter). This article +was reviewed by [Joe Medley](https://github.com/jpmedley). Hero image by +[Till Niermann](https://commons.wikimedia.org/wiki/User:Till.niermann) on +[Wikimedia Commons](https://commons.wikimedia.org/wiki/File:Dictionary_indents_headon.jpg). + +[blink-component]: https://chromestatus.com/features#component%3ABlink%3EUI>Browser>WebAppInstalls +[cr-dev-twitter]: https://twitter.com/ChromiumDev +[issue]: https://github.com/w3c/manifest/issues/737 +[explainer]: https://github.com/WICG/manifest-incubations/blob/gh-pages/tabbed-mode-explainer.md From 239cec4203242bb68ceea5e611915b6ce9490eb4 Mon Sep 17 00:00:00 2001 From: Thomas Steiner Date: Fri, 18 Aug 2023 16:37:21 +0200 Subject: [PATCH 692/982] Fix code sample (#7097) --- .../index.md | 190 ++++++++++-------- 1 file changed, 108 insertions(+), 82 deletions(-) diff --git a/site/en/blog/sqlite-wasm-in-the-browser-backed-by-the-origin-private-file-system/index.md b/site/en/blog/sqlite-wasm-in-the-browser-backed-by-the-origin-private-file-system/index.md index fc7dfb711..78100e466 100644 --- a/site/en/blog/sqlite-wasm-in-the-browser-backed-by-the-origin-private-file-system/index.md +++ b/site/en/blog/sqlite-wasm-in-the-browser-backed-by-the-origin-private-file-system/index.md @@ -4,7 +4,7 @@ title: SQLite Wasm in the browser backed by the Origin Private File System subhead: > Use SQLite to handle all your storage needs performantly on the web. date: 2023-01-11 -updated: 2023-04-29 +updated: 2023-08-16 hero: image/8WbTDNrhLsU0El80frMBGE4eMCD3/l5kRHOrUI9mQmwOTJKr7.jpg alt: Library symbolizing a database. authors: @@ -14,50 +14,60 @@ tags: --- {% Aside 'success' %} In our blog post -[Deprecating and removing Web SQL](/blog/deprecating-web-sql/), we promised a replacement for Web -SQL based on SQLite. The SQLite Wasm library with the Origin Private File System persistence backend -is our fulfillment of this promise. {% endAside %} +[Deprecating and removing Web SQL](/blog/deprecating-web-sql/), we promised a +replacement for Web SQL based on SQLite. The SQLite Wasm library with the Origin +Private File System persistence backend is our fulfillment of this promise. +{% endAside %} ## About SQLite -[SQLite](https://sqlite.org/) is a popular, [open-source](https://sqlite.org/src/tree), lightweight, -embedded relational database management system. Many developers use it to store data in a -structured, easy-to-use manner. Because of its small size and low memory requirements, SQLite is -often leveraged as a database engine in mobile devices, desktop applications, and web browsers. +[SQLite](https://sqlite.org/) is a popular, +[open-source](https://sqlite.org/src/tree), lightweight, embedded relational +database management system. Many developers use it to store data in a +structured, easy-to-use manner. Because of its small size and low memory +requirements, SQLite is often leveraged as a database engine in mobile devices, +desktop applications, and web browsers. -One of the key features of SQLite is that it is a serverless database, which means that it does not -require a separate server process to operate. Instead, the database is stored in a single file on -the user's device, making it easy to integrate into applications. +One of the key features of SQLite is that it is a serverless database, which +means that it does not require a separate server process to operate. Instead, +the database is stored in a single file on the user's device, making it easy to +integrate into applications. {% Img src="image/8WbTDNrhLsU0El80frMBGE4eMCD3/eDfwxFJirAZ6hqdt6Z8Y.png", alt="SQLite logo.", width="220", height="101" %} ## SQLite based on Web Assembly -There are a number of unofficial SQLite versions based on Web Assembly (Wasm), allowing it to be -used in web browsers, for example, [sql.js](https://github.com/sql-js/sql.js). The -[sqlite3 WASM/JS subproject](https://sqlite.org/wasm/doc/tip/about.md) is the first effort that is -officially associated with the [SQLite project](https://sqlite.org/) making Wasm builds of the -library established members of the family of supported SQLite deliverables. The concrete goals of -this project include: - -- Binding a low-level sqlite3 API which is as close to the C one as feasible in terms of usage. -- A higher-level object-oriented API, more akin to [sql.js](https://github.com/sql-js/sql.js/) and - [Node.js-style implementations](https://www.npmjs.com/package/sqlite3), that speaks directly to - the low-level API. This API must be used from the same thread as the low-level API. -- A Worker-based API which speaks to the previous APIs via Worker messages. This one is intended for - use in the main thread, with the lower-level APIs installed in a Worker thread, and talking to - them via Worker messages. -- A Promise-based variant of the Worker API which entirely hides the cross-thread communication - aspects from the user. -- Support for persistent client-side storage using available JavaScript APIs, including the Origin - Private File System (OPFS). +There are a number of unofficial SQLite versions based on Web Assembly (Wasm), +allowing it to be used in web browsers, for example, +[sql.js](https://github.com/sql-js/sql.js). The +[sqlite3 WASM/JS subproject](https://sqlite.org/wasm/doc/tip/about.md) is the +first effort that is officially associated with the +[SQLite project](https://sqlite.org/) making Wasm builds of the library +established members of the family of supported SQLite deliverables. The concrete +goals of this project include: + +- Binding a low-level sqlite3 API which is as close to the C one as feasible in + terms of usage. +- A higher-level object-oriented API, more akin to + [sql.js](https://github.com/sql-js/sql.js/) and + [Node.js-style implementations](https://www.npmjs.com/package/sqlite3), that + speaks directly to the low-level API. This API must be used from the same + thread as the low-level API. +- A Worker-based API which speaks to the previous APIs via Worker messages. This + one is intended for use in the main thread, with the lower-level APIs + installed in a Worker thread, and talking to them via Worker messages. +- A Promise-based variant of the Worker API which entirely hides the + cross-thread communication aspects from the user. +- Support for persistent client-side storage using available JavaScript APIs, + including the Origin Private File System (OPFS). ## Using SQLite Wasm with the Origin Private File System persistence backend ### Installing the library from npm -Install the [@sqlite.org/sqlite-wasm](https://www.npmjs.com/package/@sqlite.org/sqlite-wasm) package -from npm with the following command: +Install the +[@sqlite.org/sqlite-wasm](https://www.npmjs.com/package/@sqlite.org/sqlite-wasm) +package from npm with the following command: ```bash npm install @sqlite.org/sqlite-wasm @@ -66,65 +76,76 @@ npm install @sqlite.org/sqlite-wasm ### The Origin Private File System The Origin Private File System (OPFS, part of the -[File System Access API](/articles/file-system-access/)) is augmented with a special surface that -brings very performant access to data. This new surface differs from existing ones by offering -in-place and exclusive write access to a file's content. This change, along with the ability to -consistently read unflushed modifications and the availability of a synchronous variant on dedicated -workers, significantly improves performance and unblocks new use cases. - -As you can imagine, the last point of the project's goals, Support for persistent client-side -storage using available JavaScript APIs, comes with strict performance requirements -regarding persisting data to the database file. This is where the Origin Private File System, and, -more specifically, the +[File System Access API](/articles/file-system-access/)) is augmented with a +special surface that brings very performant access to data. This new surface +differs from existing ones by offering in-place and exclusive write access to a +file's content. This change, along with the ability to consistently read +unflushed modifications and the availability of a synchronous variant on +dedicated workers, significantly improves performance and unblocks new use +cases. + +As you can imagine, the last point of the project's goals, Support for +persistent client-side storage using available JavaScript APIs, comes with +strict performance requirements regarding persisting data to the database file. +This is where the Origin Private File System, and, more specifically, the [`createSyncAccessHandle()`](https://developer.mozilla.org/docs/Web/API/FileSystemFileHandle/createSyncAccessHandle) -method of [`FileSystemFileHandle`](https://developer.mozilla.org/docs/Web/API/FileSystemFileHandle) +method of +[`FileSystemFileHandle`](https://developer.mozilla.org/docs/Web/API/FileSystemFileHandle) objects comes into play. This method returns a Promise which resolves to a [`FileSystemSyncAccessHandle`](https://developer.mozilla.org/docs/Web/API/FileSystemSyncAccessHandle) -object that can be used to synchronously read from and write to a file. The synchronous nature of -this method brings performance advantages, but therefore it is only usable inside dedicated -[Web Workers](https://developer.mozilla.org/docs/Web/API/Web_Workers_API) for files within the -Origin Private File System so the main thread can't be blocked. +object that can be used to synchronously read from and write to a file. The +synchronous nature of this method brings performance advantages, but therefore +it is only usable inside dedicated +[Web Workers](https://developer.mozilla.org/docs/Web/API/Web_Workers_API) for +files within the Origin Private File System so the main thread can't be blocked. ### Setting the required headers -{% Aside 'warning' %} Setting these headers is a required step for the Origin Private File System -persistence backend to work. {% endAside %} +{% Aside 'warning' %} Setting these headers is a required step for the Origin +Private File System persistence backend to work. {% endAside %} -Among other files, the downloaded SQLite Wasm archive contains the `sqlite3.js` and `sqlite3.wasm` -files, which make up the sqlite3 WASM/JS build. The `jswasm` directory contains the core sqlite3 -deliverables and the top-level directory contains demonstration and test apps. Browsers will not -serve Wasm files from `file://` URLs, so any apps you build with this require a web server and that -server must include the following headers in its response when serving the files: +Among other files, the downloaded SQLite Wasm archive contains the `sqlite3.js` +and `sqlite3.wasm` files, which make up the sqlite3 WASM/JS build. The `jswasm` +directory contains the core sqlite3 deliverables and the top-level directory +contains demonstration and test apps. Browsers will not serve Wasm files from +`file://` URLs, so any apps you build with this require a web server and that +server must include the following headers in its response when serving the +files: - [`Cross-Origin-Opener-Policy`](https://developer.mozilla.org/docs/Web/HTTP/Headers/Cross-Origin-Opener-Policy) set to the [`same-origin` directive](https://developer.mozilla.org/docs/Web/HTTP/Headers/Cross-Origin-Opener-Policy#directives), - which isolates the browsing context exclusively to same-origin documents. Cross-origin documents - are not loaded in the same browsing context. + which isolates the browsing context exclusively to same-origin documents. + Cross-origin documents are not loaded in the same browsing context. - [`Cross-Origin-Embedder-Policy`](https://developer.mozilla.org/docs/Web/HTTP/Headers/Cross-Origin-Embedder-Policy) set to the [`require-corp` directive](https://developer.mozilla.org/docs/Web/HTTP/Headers/Cross-Origin-Embedder-Policy#directives), - so a document can only load resources from the same origin, or resources explicitly marked as - loadable from another origin. + so a document can only load resources from the same origin, or resources + explicitly marked as loadable from another origin. The reason for these headers is that SQLite Wasm depends on [`SharedArrayBuffer`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer), and setting these headers is part of its [security requirements](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer#security_requirements). -If you inspect the traffic with DevTools, you should find the following information: +If you inspect the traffic with DevTools, you should find the following +information: {% Img src="image/8WbTDNrhLsU0El80frMBGE4eMCD3/5IwU6G8KyFjV3SP3f0lX.png", alt="The two headers mentioned above, Cross-Origin-Embedder-Policy and Cross-Origin-Opener-Policy, highlighted in Chrome DevTools.", width="377", height="249" %} ### Speedtest -The SQLite team have run some benchmarks on their WebAssembly implementation compared to the deprecated Web SQL. These benchmarks show that SQLite Wasm is generally about as fast as Web SQL. Sometimes it's a little slower, sometimes it's a little faster. See all details on the [results page](https://sqlite-wasm-opfs.glitch.me/speedtest.html). +The SQLite team have run some benchmarks on their WebAssembly implementation +compared to the deprecated Web SQL. These benchmarks show that SQLite Wasm is +generally about as fast as Web SQL. Sometimes it's a little slower, sometimes +it's a little faster. See all details on the +[results page](https://sqlite-wasm-opfs.glitch.me/speedtest.html). ### Getting started code sample -As mentioned previously, SQLite Wasm with the Origin Private File System persistence backend needs -to run from a Worker context. So to use it, in the main thread, you need to create the worker and -listen to messages from it. +As mentioned previously, SQLite Wasm with the Origin Private File System +persistence backend needs to run from a Worker context. So to use it, in the +main thread, you need to create the worker and listen to messages from it. ```js const logHtml = function (cssClass, ...args) { @@ -148,8 +169,9 @@ worker.onmessage = function ({ data }) { }; ``` -After that, in the worker thread, you can then set up the communication with the main thread, -initialize the Wasm module, and finally start working with SQLite and execute queries. +After that, in the worker thread, you can then set up the communication with the +main thread, initialize the Wasm module, and finally start working with SQLite +and execute queries. ```js import sqlite3InitModule from '@sqlite.org/sqlite-wasm'; @@ -165,18 +187,19 @@ const log = (...args) => logHtml('', ...args); const error = (...args) => logHtml('error', ...args); const start = function (sqlite3) { - const capi = sqlite3.capi; /*C-style API*/ - const oo = sqlite3.oo1; /*high-level OO API*/ - log('sqlite3 version', capi.sqlite3_libversion(), capi.sqlite3_sourceid()); + const capi = sqlite3.capi; // C-style API + const oo = sqlite3.oo1; // High-level OO API + log('SQLite3 version', capi.sqlite3_libversion(), capi.sqlite3_sourceid()); let db; - if (sqlite3.opfs) { - db = new sqlite3.opfs.OpfsDb('/mydb.sqlite3'); + if ('OpfsDb' in oo) { + db = new oo.OpfsDb('/mydb.sqlite3'); log('The OPFS is available.'); + log('Persisted db =', db.filename); } else { db = new oo.DB('/mydb.sqlite3', 'ct'); log('The OPFS is not available.'); + log('transient db =', db.filename); } - log('transient db =', db.filename); try { log('Create a table...'); @@ -206,8 +229,7 @@ log('Loading and initializing sqlite3 module...'); sqlite3InitModule({ print: log, printErr: error, -}) -.then(function (sqlite3) { +}).then(function (sqlite3) { log('Done initializing. Running demo...'); try { start(sqlite3); @@ -221,9 +243,10 @@ sqlite3InitModule({ See the above code in action in the [demo](https://sqlite-wasm-opfs.glitch.me/). Be sure to check out the -[source code](https://glitch.com/edit/#!/sqlite-wasm-opfs?path=index.js%3A1%3A0) on Glitch. -Note how the embedded version below does not use the OPFS backend, but when you open the demo -in a [separate tab](https://sqlite-wasm-opfs.glitch.me/) it does. +[source code](https://glitch.com/edit/#!/sqlite-wasm-opfs?path=index.js%3A1%3A0) +on Glitch. Note how the embedded version below does not use the OPFS backend, +but when you open the demo in a +[separate tab](https://sqlite-wasm-opfs.glitch.me/) it does. {% Glitch { id: 'sqlite-wasm-opfs' @@ -237,21 +260,24 @@ Chrome extension. {% Img src="image/8WbTDNrhLsU0El80frMBGE4eMCD3/jT2SFMpWzPuPKjcphLlR.png", alt="OPFS Explorer in the Chrome Web Store.", width="800", height="612" %} -After installing the extension, open the Chrome DevTools, select the **OPFS Explorer** tab, and -you're then ready to inspect what SQLite Wasm writes to the Origin Private File System. +After installing the extension, open the Chrome DevTools, select the **OPFS +Explorer** tab, and you're then ready to inspect what SQLite Wasm writes to the +Origin Private File System. {% Img src="image/8WbTDNrhLsU0El80frMBGE4eMCD3/vIjB6Gnl879OySnYuueJ.png", alt="OPFS Explorer Chrome extension showing the Origin Private File System structure of the demo app.", width="800", height="416" %} -If you click on any of the files in the OPFS Explorer window in DevTools, you can save it to the -local disk. You can then use an app like [SQLite Viewer](https://sqliteviewer.app/) to inspect the -database, so you can assure yourself that SQLite Wasm actually works as promised. +If you click on any of the files in the OPFS Explorer window in DevTools, you +can save it to the local disk. You can then use an app like +[SQLite Viewer](https://sqliteviewer.app/) to inspect the database, so you can +assure yourself that SQLite Wasm actually works as promised. {% Img src="image/8WbTDNrhLsU0El80frMBGE4eMCD3/fKoJyNfsmFWI5oC4kEJA.png", alt="SQLite Viewer app used to open a database file from the SQLite Wasm demo.", width="800", height="329" %} ## Getting help and providing feedback -SQLite Wasm is developed and maintained by the SQLite community. Get help and provide feedback by -searching in and posting to the [support forum](https://sqlite.org/forum/forum). The full +SQLite Wasm is developed and maintained by the SQLite community. Get help and +provide feedback by searching in and posting to the +[support forum](https://sqlite.org/forum/forum). The full [documentation](https://sqlite.org/docs.html) is available on the SQLite site. ## Acknowledgements From 02cafdedb07781cf07908e11019724040980dd23 Mon Sep 17 00:00:00 2001 From: Joe Medley Date: Fri, 18 Aug 2023 07:48:54 -0700 Subject: [PATCH 693/982] Add explanation of locales (#7114) @oliverdunk, apologies. I should have included this information in yesterday's PR. --- site/en/docs/webstore/i18n/index.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/site/en/docs/webstore/i18n/index.md b/site/en/docs/webstore/i18n/index.md index b493e17e2..779e35fba 100644 --- a/site/en/docs/webstore/i18n/index.md +++ b/site/en/docs/webstore/i18n/index.md @@ -2,7 +2,7 @@ layout: "layouts/doc-post.njk" title: Internationalize your extension date: 2017-08-30 -updated: 2023-08-17 +updated: 2023-08-18 description: How to internationalize your Chrome Web Store extension. --- @@ -43,7 +43,7 @@ localizing the name, description, and detailed description. ## Choose locales to support {: #choosing-locales-to-support } -You can localize your extension to any of the following locales. +You can localize your extension to any of the following locales. Note that Chrome Web Store does not support all of the locals supported by Chrome. If your locale is not listed here, choose the closest alternative. For example, if the default locale of your extension is "de_CH", choose "de" in the Chrome Web Store. | Locale code | Language (region) | | :---------- | :------------------------------------ | From e010285f22983005a9d6d9ed95f82b3e6eb793ee Mon Sep 17 00:00:00 2001 From: Barry Pollard Date: Fri, 18 Aug 2023 17:48:08 +0100 Subject: [PATCH 694/982] Bfcache notRestoredReasons API did not ship in 116 (#7103) * Bfcache notRestoredReasons API not ship in 116 * Add an aside to note the feature was delayed --- site/en/blog/new-in-chrome-116/index.md | 34 +++++-------------------- 1 file changed, 7 insertions(+), 27 deletions(-) diff --git a/site/en/blog/new-in-chrome-116/index.md b/site/en/blog/new-in-chrome-116/index.md index 70472e4a6..9f1b031f4 100644 --- a/site/en/blog/new-in-chrome-116/index.md +++ b/site/en/blog/new-in-chrome-116/index.md @@ -1,9 +1,10 @@ --- title: New in Chrome 116 description: > - Chrome 116 is rolling out now! Use the document picture in picture API to increase user productivity, improve performance by checking the notRestoredReasons property to optimize bfcache use, it is now easier to debug missing stylesheets in DevTools, and there’s plenty more. + Chrome 116 is rolling out now! Use the document picture in picture API to increase user productivity, it is now easier to debug missing stylesheets in DevTools, and there’s plenty more. layout: 'layouts/blog-post.njk' date: 2023-08-15 +updated: 2023-08-18 authors: - ajara hero: 'image/SeARmcA1EicLXagFnVOe0ou9cqK2/D40mYqd8kvfXSy2IxbVv.png' @@ -19,7 +20,6 @@ tags: Here's what you need to know: * Use the [Document Picture in Picture API](#document-picture-in-picture) to increase user productivity. -* Improve performance by checking the [notRestoredReasons](#not-restored-reasons) property to optimize bfcache use. * It is now easier to [debug missing stylesheets](#missing-stylesheets-debug) in DevTools * And there’s plenty [more](#more). @@ -67,30 +67,6 @@ pipButton.addEventListener('click', async () => { Check out [Picture-in-picture for any element](/docs/web-platform/document-picture-in-picture/) for more details and examples. -## `notRestoredReasons` property. {: #not-restored-reasons } - -Modern browsers provide an optimization feature for history navigation called the [back/forward cache](https://web.dev/bfcache/), or bfcache. It enables an instant loading experience when users go back to a page they have already visited. - -Check out this video of bfcache in action to understand the speed up it can bring to navigations: - -{% YouTube 'cuPsdRckkF0' %} - -Pages can be blocked from entering the bfcache or be evicted while in bfcache for different reasons, some required by a specification and some specific to browser implementations. - -Previously, there was no way for developers to find out why their pages were blocked from using the bfcache in the field, though there was a test in Chrome DevTools. - -To enable monitoring in the field, the `PerformanceNavigationTiming` class has been extended to include a `notRestoredReasons` property. - -This returns an object containing related information on all frames present in the document: - -* Details such as frame ID and name, to help identify them in the HTML. -* Whether they were blocked from using the bfcache. -* Reasons why they were blocked from using the bfcache. - -This allows developers to take action to make those pages bfcache-compatible, thereby improving site performance. - -Check out [not restored reasons API](/docs/web-platform/bfcache-notrestoredreasons/) for the code sample to find out the reasons your site might not be using bfcache, so you don’t miss out on a performance boost. - ## DevTools missing stylesheets debugging improvements. {: #missing-stylesheets-debug } DevTools got a number of improvements to identify and debug issues with missing stylesheets. @@ -121,6 +97,10 @@ Of course there’s plenty more. * The `display` and `content-visibility` properties are now supported in keyframe animations, which allows exit animations to be added purely in CSS. * The fetch API can now be used with [Bring Your Own Buffer readers](https://developer.mozilla.org/docs/Web/API/ReadableStreamBYOBReader), reducing garbage collection overhead and copies, and improving responsiveness for users. +{% Aside 'update' %} +A previous version of this post stated that the [Back/forward cache `notRestoredReasons` API](/docs/web-platform/bfcache-notrestoredreasons/) was included in Chrome 116 but this feature has been delayed until a future release. +{% endAside %} + ## Further reading This covers only some key highlights. Check the links below for @@ -139,4 +119,4 @@ To stay up to date, [subscribe](https://goo.gl/6FP1a5) to the and you'll get an email notification whenever we launch a new video. Yo soy Adriana Jara, and as soon as Chrome 117 is released, I'll be right here to -tell you what's new in Chrome! \ No newline at end of file +tell you what's new in Chrome! From 6d06ba1e34eaf8e3c4b74f72089610db69588977 Mon Sep 17 00:00:00 2001 From: Joe Medley Date: Fri, 18 Aug 2023 10:07:44 -0700 Subject: [PATCH 695/982] Fix link (#7117) --- site/en/docs/extensions/whatsnew/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/en/docs/extensions/whatsnew/index.md b/site/en/docs/extensions/whatsnew/index.md index 58108b2f3..7497efe27 100644 --- a/site/en/docs/extensions/whatsnew/index.md +++ b/site/en/docs/extensions/whatsnew/index.md @@ -37,7 +37,7 @@ Injected content scripts are now in the DevTools ignore list by default. This do

Posted on

-Chrome 116 is a big release for extensions. You can now open side panels programmatically. A new method lets you learn if there's an active offscreen document. Service workers got serveral improvements. There's enough improvements in 116 that we've written [a blog post to cover them](/blog/chrome-116-beta-whats-new-for-extensions/#runtime-get-contexts). Chrome 116 is in beta as of July 19. +Chrome 116 is a big release for extensions. You can now open side panels programmatically. A new method lets you learn if there's an active offscreen document. Service workers got serveral improvements. There's enough improvements in 116 that we've written [a blog post to cover them](/blog/chrome-116-beta-whats-new-for-extensions/). Chrome 116 is in beta as of July 19. ### Blog post: What's happening in Chrome Extensions {: #whats-happening-7-23 } From 5c5ae7bd7d42e840c8aa247e402c88e2b8d81137 Mon Sep 17 00:00:00 2001 From: Alexandra White Date: Fri, 18 Aug 2023 15:18:24 -0400 Subject: [PATCH 696/982] fix link (#7035) --- .../docs/privacy-sandbox/third-party-cookie-phase-out/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/en/docs/privacy-sandbox/third-party-cookie-phase-out/index.md b/site/en/docs/privacy-sandbox/third-party-cookie-phase-out/index.md index f91747647..97fb93ebd 100644 --- a/site/en/docs/privacy-sandbox/third-party-cookie-phase-out/index.md +++ b/site/en/docs/privacy-sandbox/third-party-cookie-phase-out/index.md @@ -94,7 +94,7 @@ To learn more about DevTools features you can use to investigate third-party coo In Chrome version 115 or higher, you can test the browser behavior after third-party cookie phase out by [running Chrome from the command line](https://www.chromium.org/developers/how-tos/run-chromium-with-flags/) with the flag `--test-third-party-cookies-phaseout`. This will block third-party cookies, enable [third-party storage partitioning](/docs/privacy-sandbox/storage-partitioning) and [FedCM](/docs/privacy-sandbox/fedcm), and enable Chrome UI settings for [First-Party Sets](docs/privacy-sandbox/first-party-sets-integration) (["Allow related sites to see your activity in the group"](https://support.google.com/chrome/answer/95647?hl=EN#zippy=%2Callow-related-sites-to-access-your-activity)). -If your site breaks when third-party cookies are blocked, you can report the issue to [Chrome's cookie breakage tracker](goo.gle/report-3pc-broken). +If your site breaks when third-party cookies are blocked, you can report the issue to [Chrome's cookie breakage tracker](https://goo.gle/report-3pc-broken). ## Partitioned cookies From a22309d40659335ff4c7b33ee61e4c6ca56b147c Mon Sep 17 00:00:00 2001 From: Alexandra White Date: Fri, 18 Aug 2023 15:32:25 -0400 Subject: [PATCH 697/982] FLEDGE overview reduce complexity (#5693) * fewer words * link to OT * clean dev guide links * add k/v service ref * nits * synonyms * allow -> enable --- .../fledge-experiment/index.md | 107 +++++----- site/en/docs/privacy-sandbox/fledge/index.md | 189 ++++++++---------- 2 files changed, 141 insertions(+), 155 deletions(-) diff --git a/site/en/docs/privacy-sandbox/fledge-experiment/index.md b/site/en/docs/privacy-sandbox/fledge-experiment/index.md index a96cf3476..548d45845 100644 --- a/site/en/docs/privacy-sandbox/fledge-experiment/index.md +++ b/site/en/docs/privacy-sandbox/fledge-experiment/index.md @@ -15,53 +15,55 @@ authors: ## Learn the essentials -* If you're a developer or software engineer, the [Protected Audience API Developer Guide](/blog/fledge-api) -provides an in-depth technical reference to the proposal. - -* [The Protected Audience API](/docs/privacy-sandbox/fledge) is a less technical overview, and also has a -[glossary](/docs/privacy-sandbox/fledge#glossary). - +* If you're a developer or software engineer, the + [Protected Audience API Developer Guide](/docs/privacy-sandbox/fledge-api/) provides an + in-depth technical reference for the proposal. +* The [Protected Audience API overview](/docs/privacy-sandbox/fledge) offers a higher level + explanation for those who work in advertiser and ad tech, who are new to the Privacy + Sandbox. ## Try the API {% Aside 'caution' %} -Not all users may be eligible for the Privacy Sandbox Relevance and Measurement origin trial, even -on pages that provide a valid trial token. +Not all users may be eligible to experience features from the Privacy Sandbox +Relevance and Measurement origin trial, even on pages that provide a valid +trial token. -[Testing the Privacy Sandbox ads relevance and measurement APIs](/blog/privacy-sandbox-unified-origin-trial#eligible-users) -explains why this is so, and shows how you can (and should) detect if an origin trial feature is -available before attempting to use it. +Read about [feature detection](/docs/privacy-sandbox/unified-origin-trial/#feature-detection) +to learn how to determine if a feature is available before attempting to use it. {% endAside %} -1. Try the [demo](https://fledge-demo.glitch.me). This provides a walkthrough of a basic Protected Audience API -implementation. [The Protected Audience API demo video](https://www.youtube.com/watch?v=znDD0gkdJyM&list=PLNYkxOF6rcICntazGfSVKSj5EwuR9w5Nv) -explains how the demo code works, and shows how to use Chrome DevTools for Protected Audience API debugging. -2. Check the Privacy Sandbox [status page](/docs/privacy-sandbox/status/#fledge) for updates on the -implementation status of the Protected Audience API. -3. Experiment with the API: - * [Protected Audience API developer guide](/blog/fledge-api#try-fledge) explains how to take part in the - Privacy Sandbox Relevance and Measurement origin trial. - * Try out Protected Audience API for a single user by enabling `chrome://flags/#privacy-sandbox-ads-apis` - or by running Chrome from the command line with [Protected Audience API feature flags](/blog/fledge-api#flags). - * The [developer guide](/blog/fledge-api) also provides a reference guide to API methods - and parameters. - * The [source code](https://github.com/JackJey/fledge-demo) for the [Protected Audience API demo](https://fledge-demo.glitch.me) - provides a starting point for your own experimentation. - * [Debug Protected Audience API worklets](/blog/fledge-api/#debugging) - explains how to use Chrome DevTools to help debug Protected Audience API bidding and auction code. - * The [developer guide](/blog/fledge-api) details the features supported in the latest version of Chrome. - [The API explainer provides more detail](https://github.com/WICG/turtledove/blob/main/FLEDGE.md#summary)about feature - support and constraints. +1. Learn how to use the Protected Audience API. + * Review the [Protected Audience API Developer Guide](/docs/privacy-sandbox/fledge-api/). + This guide offers a reference for API methods and parameters. + * Read about [Protected Audience services](/blog/fledge-service-overview/). For example, + the Key/Value service offers real-time information to buyers and sellers + during the ad auction. +2. Try the [demo](https://fledge-demo.glitch.me). + * Review the [source code](https://github.com/JackJey/fledge-demo). + * Watch the [Protected Audience demo video](https://www.youtube.com/watch?v=znDD0gkdJyM&list=PLNYkxOF6rcICntazGfSVKSj5EwuR9w5Nv) to learn how the demo code works and how to use Chrome DevTools for FLEDGE debugging. +3. Experiment with the API. + * Sign up for the [origin trial](/docs/privacy-sandbox/fledge-api/#origin-trial) + * Try out FLEDGE for a single user by enabling + `chrome://flags/#privacy-sandbox-ads-apis` or by running Chrome from the + command line with [Protected Audience feature flags](/docs/privacy-sandbox/fledge-api/#flags). + * [Troubleshoot Protected Audience worklets](/docs/privacy-sandbox/fledge-api/troubleshoot/) with Chrome DevTools. Learn how to debug FLEDGE bidding and auction code. +4. Review the [Protected Audience status](/docs/privacy-sandbox/status/#fledge) for updates + on the implementation of the FLEDGE API. Review the + [pending Protected Audience capabilities](/docs/privacy-sandbox/fledge-api/feature-status/) + for more details. + +The [Protected Audience API explainer](https://github.com/WICG/turtledove/blob/main/FLEDGE.md#summary) +provides more detail about feature support and constraints. ## Get support Is anything blocking you from experimenting with the API? Ask a question -about **your implementation**, about the **demo**, or about the -**documentation**: +about **your implementation**, the **demo**, or the **documentation**: -* [Open a new issue](https://github.com/GoogleChromeLabs/privacy-sandbox-dev-support/issues/new/choose) +* [Open a new Issue](https://github.com/GoogleChromeLabs/privacy-sandbox-dev-support/issues/new/choose) on the Privacy Sandbox Dev Support repository. Make sure to select the Issue template for the Protected Audience API. * Raise an issue on the [demo code repo on @@ -84,32 +86,33 @@ particular, if you're experimenting with the API, your feedback is essential. Like other Privacy Sandbox proposals, this API is documented and discussed publicly. -* [Read the proposal explainer on GitHub](https://github.com/WICG/turtledove/blob/main/FLEDGE.md). +* Read the [FLEDGE explainer on GitHub](https://github.com/WICG/turtledove/blob/main/FLEDGE.md). * Join the conversation about [existing issues](https://github.com/WICG/turtledove/issues). -* [Open a new issue](https://github.com/WICG/turtledove/issues/new) to ask a question, propose a -feature, or discuss a use case. -* [Join the scheduled calls for the Protected Audience API](https://github.com/WICG/turtledove/issues/88) (every - second week). Everyone is welcome to join—to participate, first make sure to [join the - WICG](https://www.w3.org/community/wicg/). You can actively participate or just listen in! +* [Open a new issue](https://github.com/WICG/turtledove/issues/new) to ask a + question, propose a feature, or discuss a use case. +* [Join the scheduled calls for Protected Audience](https://github.com/WICG/turtledove/issues/88) + (every second week). Everyone is welcome to join—to participate, + first make sure to [join the WICG](https://www.w3.org/community/wicg/). + You can actively participate or just listen in! ### Discuss related topics -- Discuss industry use cases in the [Improving Web Advertising Business Group](https://www.w3.org/community/web-adv/participants). +Discuss industry use cases in the +[Improving Web Advertising Business Group](https://www.w3.org/community/web-adv/participants). ### Give feedback -* Use the Privacy Sandbox [feedback form](/docs/privacy-sandbox/feedback/#feedback-form) -to share feedback privately with the Chrome team outside of public forums. -* [Privacy Sandbox Feedback](/docs/privacy-sandbox/feedback/#fledge-api) explains how to provide -other types of feedback, and how to engage in discussion of Privacy Sandbox proposals. - +[Privacy Sandbox feedback](/docs/privacy-sandbox/feedback/#fledge-api) +explains how to provide other types of feedback, and how to engage in +discussion of Privacy Sandbox proposals. ## Get updates -- To be notified of status changes in the API, join the [mailing list for - developers](https://groups.google.com/u/3/a/chromium.org/g/fledge-api-announce). -- To closely follow all ongoing discussions on the API, click the **Watch** button on the [proposal page on - GitHub](https://github.com/WICG/turtledove/blob/main/FLEDGE.md). This requires you have or [create a GitHub - account](https://docs.github.com/en/get-started/signing-up-for-github/signing-up-for-a-new-github-account). -- To get overall updates on the Privacy Sandbox, subscribe to the RSS feed [Progress in the Privacy - Sandbox](/tags/progress-in-the-privacy-sandbox/). +* To be notified of status changes in the API, join the + [mailing list for developers](https://groups.google.com/u/3/a/chromium.org/g/fledge-api-announce). +* To closely follow all ongoing discussions on the API, click the **Watch** + button on the [proposal page on GitHub](https://github.com/WICG/turtledove/blob/main/FLEDGE.md). + This requires you have or + [create a GitHub account](https://docs.github.com/get-started/signing-up-for-github/signing-up-for-a-new-github-account). +* To get overall updates on the Privacy Sandbox, subscribe to the RSS feed + [Progress in the Privacy Sandbox](/tags/progress-in-the-privacy-sandbox/). diff --git a/site/en/docs/privacy-sandbox/fledge/index.md b/site/en/docs/privacy-sandbox/fledge/index.md index d5180015e..7162c5759 100644 --- a/site/en/docs/privacy-sandbox/fledge/index.md +++ b/site/en/docs/privacy-sandbox/fledge/index.md @@ -26,35 +26,31 @@ authors: This article covers the basics of the Protected Audience API and explains some underlying concepts, but doesn't go into much technical detail. -* If you work in **advertising or ad tech**, you'll get an overview of [how the Protected Audience API works](#overview). -* If you're a **developer or software engineer**, the [Protected Audience API Developer Guide](/docs/privacy-sandbox/fledge-api) provides more in-depth technical detail about the proposal and the [Intent to prototype](https://groups.google.com/a/chromium.org/g/blink-dev/c/w9hm8eQCmNI) - offers the latest conversation about Protected Audience API status in the browser. -* [The Protected Audience API demo](/docs/privacy-sandbox/fledge-api#demo) provides a walkthrough of a basic Protected Audience API deployment. +* If you work in **advertising or ad tech**, you'll get an overview of + [how Protected Audience works](#overview). +* If you're a **developer or software engineer**, the + [Protected Audience API Developer Guide](/docs/privacy-sandbox/fledge-api) provides more + in-depth technical detail about the proposal. Read the + [latest status of pending Protected Audience capabilities](/docs/privacy-sandbox/fledge-api/feature-status/). -{% Aside %} -Refer to the [glossary](/docs/privacy-sandbox/glossary/) for terms used across Protected Audience API documentation. -{% endAside %} - -At the end of this article is a link to [engage and share feedback](#engage). +Refer to the [glossary](/docs/privacy-sandbox/glossary/) for terms used across +Protected Audience documentation. At the end of this article, you can learn how to +[engage and share feedback](#engage). ## What is the Protected Audience API? {: #what} -The Protected Audience API is a [Privacy Sandbox](/docs/privacy-sandbox/overview) proposal to serve -[remarketing](/docs/privacy-sandbox/glossary/#remarketing) and custom audience -use cases, designed so third parties cannot track user browsing behavior across sites. +The Protected Audience API is a [Privacy Sandbox](/docs/privacy-sandbox/overview) +technology to serve remarketing and custom audience use cases, designed so +third parties cannot track user browsing behavior across sites. -The API enables on-device auctions by the browser, to choose relevant ads from +FLEDGE enables on-device auctions by the browser, to choose relevant ads from websites the user has previously visited. The Protected Audience API is the first experiment to be implemented in Chromium within the [TURTLEDOVE](https://github.com/WICG/turtledove) family of proposals. The -[Privacy Sandbox timeline](https://privacysandbox.com/timeline) provides implementation timing -information for the Protected Audience API and other Privacy Sandbox proposals. - -### How does the Protected Audience API differ from Turtledove? - -The differences between the Protected Audience API and Turtledove pertain mostly to separation of the on-device role -of the ad buyer and seller. The sections below explain how the Protected Audience API works. +difference between Protected Audience and TURTLEDOVE primarily pertain to separation of +the on-device role of the ad buyer and seller. The sections below explain how +FLEDGE works. ### Protected Audience API in one minute {: #overview} @@ -72,19 +68,15 @@ For a more in-depth overview of the Protected Audience API, read the The Protected Audience API uses [interest groups](#interest-group-detail) to enable sites to display ads that are relevant to their users. -For example, when a user visits a website that wants to advertise its products, +For example, when a user visits a site that wants to advertise its products, an interest group [owner](#interest-group-detail) (such as a -[demand side platform or DSP](/docs/privacy-sandbox/glossary/#dsp) working for the site) can ask the user's -browser to add membership for the interest group. The group owner (in this example, the DSP) does -this by calling the JavaScript function `navigator.joinAdInterestGroup()`. If the call is -successful, the browser records: +[demand-side platform (DSP)](/docs/privacy-sandbox/glossary/#dsp)) can ask the user's browser to add membership for the interest group. If the request is successful, the browser records: * The **name** of the interest group: for example, 'custom-bikes'. * The **owner** of the interest group: for example, 'https://dsp.example'. -* Interest group **configuration information** to enable the browser to access +* Interest group **configuration information** to allow the browser to access bidding code, ad code, and real-time data, if the group's owner is invited to - bid in an online ad auction. This information can be updated later by the - interest group owner. + bid in an ad auction. {% Aside %} @@ -92,78 +84,74 @@ There are other use cases for interest groups; see the [examples of owners and t {% endAside %} -Later, when the user visits a site that sells ad space, the ad space seller -(most likely the site's -[SSP](/docs/privacy-sandbox/glossary/#ssp), or the site itself) can use -the Protected Audience API to run an ad auction to select the most appropriate ads to display to the user. The seller -calls the `navigator.runAdAuction()` function, which provides a list of interest group owners who are invited to bid. +Later, when the user visits a site with available ad space, the ad space seller +(a [sell-side provider (SSP)](/docs/privacy-sandbox/glossary/#ssp), or the site +itself) can use Protected Audience to run an ad auction to select the most appropriate ads +to display to the user. The seller calls the `navigator.runAdAuction()` +function, which provides a list of interest group owners who are invited to bid. -Bidding code is only run for interest groups that the browser is a member of, -and whose owners have been invited to bid. +Bids can only be provided by interest groups that the browser is a member of, whose owners have been invited to bid. -Bidding code is retrieved from the URL provided in the configuration -information for the interest group. This code is passed data about the interest -group and information from the seller, along with contextual data about the -page and from the browser. +Bidding code is retrieved from a URL provided in the interest group's +configuration. This code provides data about the interest group and +information from the seller, along with contextual data about the +page and from the browser. -Each bidder is also known as a buyer. +Each interest group providing a bid is known as a buyer. -When the browser calls the function to run the ad auction, each buyer's code generates -a bid with the help of real-time data provided by their -[Protected Audience API Key/Value service](#key-value-service-detail). Then, the seller receives these -bids as well as seller-owned real-time data, and scores each bid. The bid with the -highest score wins the auction. +When the browser calls the function to run the ad auction, each buyer's code +generates a bid with the help of real-time data provided by their +[Protected Audience Key/Value service](#key-value-service-detail). Then, the seller +receives these bids as well as seller-owned real-time data and scores each +bid. The bid with the highest score wins the auction. -The winning ad is displayed in a [fenced frame](/docs/privacy-sandbox/fenced-frame). +The winning ad is displayed in a +[fenced frame](/docs/privacy-sandbox/fenced-frame). The ad creative's URL is specified in the bid, and the origin must match one in the list provided by the interest group's configuration. The seller can report the auction outcome (`reportResult()`), and buyers can report their wins (`reportWin()`). -Learn how to [generate reports of the Protected Audience API auction results](/docs/privacy-sandbox/fledge-api/reports/). +Learn about [Protected Audience auction reports](/docs/privacy-sandbox/fledge-api/reports/). ## Why do we need the Protected Audience API? {: #why} -Understanding user interests can enable more relevant ads than simply choosing -ads based on site content (contextual targeting) or by using information that -the user provided to the site on which the ad appears (first-party data targeting). +Understanding user interests can enable more relevant ads than just choosing +ads based on site content (contextual targeting) or by using information +provided by a user to the site on which the ad appears (first-party data targeting). Traditionally, ad platforms have learned about user interests by tracking their behavior across sites. Browsers need a way to enable ad platforms to select relevant ads, so content publishers can get ad revenue without cross-site tracking. -The Protected Audience API experiment aims to move the web platform closer to a state where the -user's browser, on their device, not the advertiser or ad tech platforms, holds +The Protected Audience API aims to move the web platform closer to a state where the +user's browser on their device—not the advertiser or ad tech platforms—holds information about what that person is interested in. -{% Aside 'warning' %} +{% Aside 'caution' %} -Not all features described here have been implemented (in part or in full) in -the version of the Protected Audience API currently being tested in Chrome. The -[Protected Audience API developer guide](/docs/privacy-sandbox/fledge-api#try-fledge) explains which Protected Audience API -features are currently available for testing in Chrome run from the command line -using [feature flags](https://www.chromium.org/developers/how-tos/run-chromium-with-flags). +Read the [developer guide](/docs/privacy-sandbox/fledge-api/) and +[status of pending Protected Audience capabilities](/docs/privacy-sandbox/fledge-api/feature-status/) +to understand what features are currently available for testing in Chrome. -Features of the Protected Audience API will be added over time. While the [origin trial](/docs/privacy-sandbox/unified-origin-trial/) -is active, we'll regularly update a list of which features are already -implemented and what's still in progress. +Protected Audience features will be added over time, and we'll regularly update a list of +which features are already implemented and what's still in progress. The Protected Audience API is +currently in an [origin trial](/docs/privacy-sandbox/unified-origin-trial/). {% endAside %} ## How can I try the Protected Audience API? {: #try-fledge} -* The [Protected Audience API developer guide](/docs/privacy-sandbox/fledge-api#try-fledge) describes how to - take part in the Privacy Sandbox Relevance and Measurement origin trial and - how to try out the Protected Audience API for a single user by setting Chrome flags. +* The [Protected Audience API developer guide](/docs/privacy-sandbox/fledge-api) describes + how to use the API, how to test locally and how to participate in the + [relevence and measurement origin trial](/docs/privacy-sandbox/unified-origin-trial/). * [fledge-demo.glitch.me](https://fledge-demo.glitch.me/) provides a - walkthrough of a basic Protected Audience API deployment across advertiser and publisher - sites. - * [Watch the Protected Audience API demo video](https://www.youtube.com/watch?v=znDD0gkdJyM&list=PLNYkxOF6rcICntazGfSVKSj5EwuR9w5Nv) - to understand how the demo code works. The video also previews how to use - Chrome DevTools for Protected Audience API debugging. + walkthrough of a basic Protected Audience deployment across advertiser and publisher + sites. The Protected Audience demo video explains how this code works and previews + how to use Chrome DevTools for debugging. {% YouTube id='znDD0gkdJyM' @@ -181,9 +169,9 @@ they've been added to across the sites they've visited. As with the Privacy Sandbox technologies, user settings may evolve with feedback from users, regulators, and others. -We'll update the available settings in Chrome as the Protected Audience API proposal -progresses, [based on tests and feedback](/docs/privacy-sandbox/proposal-lifecycle/#testing). -In the future, we'll offer more granular settings to manage the Protected Audience API and +We'll update the available settings in Chrome as the Protected Audience API progresses, +[based on tests and feedback](/docs/privacy-sandbox/proposal-lifecycle/#testing). +In the future, we'll offer more granular settings to manage Protected Audience and associated data. API callers can't access group membership when users browse in Incognito mode, @@ -196,21 +184,10 @@ and membership is removed when users clear their site data. Learn how you can [block access to the Protected Audience API](/docs/privacy-sandbox/fledge-api/opt-out), either as a site owner or as an individual user. -### Can users block an ad shown as the result of a Protected Audience API auction? {: #ad-block } - -Users can [opt out of the Privacy Sandbox API](/docs/privacy-sandbox/fledge-api/opt-out/#opt-out-user). -To opt out of a specific ad or ad selection technique, the appropriate party to -provide those controls is the ad tech serving the ad. - -Developers can use multiple approaches to control which ads are eligible for -bidding and serving and record a user's ad preferences. One -technique is to call `leaveAdInterestGroup()` when a user asks to block a specific ad, for the winning interest group that provided the ad. This removes the user's browser from membership in the interest group and makes the group ineligible to bid in the future. - ## Key concepts -{: #glossary} - -Looking for more information on Protected Audience API terminology? Refer to the [Privacy Sandbox glossary](/docs/privacy-sandbox/glossary/). +Looking for more information on Protected Audience terminology? Refer to the +[Privacy Sandbox glossary](/docs/privacy-sandbox/glossary/). {: #interest-group-detail} @@ -220,16 +197,17 @@ Looking for more information on Protected Audience API terminology? Refer to the ### What is an interest group? {% endDetailsSummary %} -A Protected Audience API interest group represents a group of people with a common interest, corresponding to a -[remarketing](/docs/privacy-sandbox/glossary/#remarketing) list. +A Protected Audience API interest group represents a group of people with a common interest, +corresponding to a [remarketing](/docs/privacy-sandbox/glossary/#remarketing) list. -Every Protected Audience API interest group has an owner. Different types of owners will create different types of -interest groups with different use cases. +Every Protected Audience API interest group has an owner. Different types of owners will create +different types of interest groups with different use cases. -The owner asks the user's browser to add membership of their interest group by calling the -JavaScript function `navigator.joinAdInterestGroup()`, providing information such as data about ads -relevant to the interest group, and a URL for JavaScript used in bidding. Interest group data -(such as the ads) can be updated, and an interest group can be enabled for up to 30 days. +The owner asks the user's browser to add membership of their interest group by +calling the JavaScript function `navigator.joinAdInterestGroup()`, providing +information such as data about ads relevant to the interest group, and a URL +for JavaScript used in bidding. Interest group data (such as the ads) can be +updated, and an interest group can be enabled for up to 30 days. {% Aside %} @@ -269,18 +247,23 @@ The table below provides examples of different types of Protected Audience API i News website Content People who read about cycling. - Publishers can use first-party data to enable advertisers - to buy ads that are relevant to readers on their site. A publisher-owned interest group - could let publishers do the same even when those people are browsing other sites. - Publishers may be able to charge for the ability to show ads to specific segments of their + + Publishers can use first-party data to enable advertisers + to buy ads that are relevant to readers on their site. A + publisher-owned interest group could let publishers do the same even + when those people are browsing other sites. Publishers may be able to + charge for the ability to show ads to specific segments of their audience. Ad tech DSP Category of products - People who showed an interest in cycling gear. - An ad tech company might create and manage an interest group + + People who showed an interest in cycling gear. + + + An ad tech company might create and manage an interest group of people they believe are in the market for some category of item. This interest group could then be used to advertise products on sites that sell things in that category (and who work with the ad tech company). @@ -311,7 +294,7 @@ In the Protected Audience API, a buyer is a party that owns an [interest group]( For example: * **[Advertiser](/docs/privacy-sandbox/glossary/#advertiser)**: acting for itself. -* **[Demand-Side Platform](/docs/privacy-sandbox/glossary/#dsp)** (DSP): acting for advertisers. +* **[Demand-side platform](/docs/privacy-sandbox/glossary/#dsp)** (DSP): acting for advertisers. * **Interest group owner**: working for multiple advertisers. Buyers have three jobs: @@ -402,7 +385,7 @@ The seller provides the browser with code to score bids, which includes each bid code from buyers and bid-scoring code from the seller can receive data from their [Key/Value services](#key-value-service-detail). Once an ad is chosen and displayed (in a [fenced frame](/docs/privacy-sandbox/fenced-frame/) to preserve -privacy), the seller and the winning bidder can report the auction result. +privacy) the seller and the winning buyer can report the auction result. 1. A user visits a site which displays ads. 2. The seller's code starts an auction. The seller specifies which ad space is @@ -459,8 +442,8 @@ and the [trust model explainer](https://github.com/privacysandbox/fledge-docs/bl ### How is real-time data incorporated into auctions? {% endDetailsSummary %} -The [buyers](#buyer-detail) or [seller](#seller-detail) in an ad auction may need access to real-time -data. For example, bidders may want to calculate the remaining budget in an ad campaign, or the +The [buyers](#buyer-detail) or [seller](#seller-detail) in an ad auction may need access to realtime +data. For example, buyers may want to calculate the remaining budget in an ad campaign, or the seller may be required to check ad creatives against publisher policies. To meet the privacy requirements of the Protected Audience API, real-time data required during an ad auction is provided by the [Key/Value service](#key-value-service-detail). When each buyer calls `navigator.joinAdInterestGroup()`, the buyer specifies a Key/Value service URL and specifies the keys to be queried to the service during an auction. Likewise, when the seller runs an ad auction by calling `navigator.runAdAuction()`, the seller provides a URL for its Key/Value service. The seller's Key/Value service will be queried with the render URL of the creative. From 8786ffeb12e984a6df5d2b6d7b2c58954f22c621 Mon Sep 17 00:00:00 2001 From: Sam Dutton Date: Fri, 18 Aug 2023 20:37:34 +0100 Subject: [PATCH 698/982] Shared Storage: fixed broken link (#7109) /docs/privacy-sandbox/shared-storage/content-selection/ --- site/en/docs/privacy-sandbox/shared-storage/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/en/docs/privacy-sandbox/shared-storage/index.md b/site/en/docs/privacy-sandbox/shared-storage/index.md index 58a09497d..5f21bfb82 100644 --- a/site/en/docs/privacy-sandbox/shared-storage/index.md +++ b/site/en/docs/privacy-sandbox/shared-storage/index.md @@ -133,7 +133,7 @@ gates available, but more may be added in the future. The available Shared Storage API output gates are: -* **[Cross-site content selection](/docs/privacy-sandbox/shared-storage/url-selection/)**: You can run a worklet script to select a URL from a provided list, based on the stored data, and then render that content in a fenced frame. +* **[Cross-site content selection](/docs/privacy-sandbox/shared-storage/content-selection/)**: You can run a worklet script to select a URL from a provided list, based on the stored data, and then render that content in a fenced frame. * **Noisy aggregation with the [Private Aggregation API](/docs/privacy-sandbox/private-aggregation/)**: You can run a worklet to send cross-site data through the Private Aggregation API and return a [summary report](/docs/privacy-sandbox/attribution-reporting/summary-reports/). ## Try the Shared Storage API From 90dd379813bc767daf18e9f034e101b8482f8536 Mon Sep 17 00:00:00 2001 From: Colin <38937291+espresso@users.noreply.github.com> Date: Fri, 18 Aug 2023 15:38:17 -0400 Subject: [PATCH 699/982] Fix #6922 - Minor Typo in the "Format and style messages in the Console" Page (#6923) Fixes #6922 Minor Typo in the "Format and style messages in the Console" Page. --- site/en/docs/devtools/console/format-style/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/en/docs/devtools/console/format-style/index.md b/site/en/docs/devtools/console/format-style/index.md index 5b2f5dc81..d9f3f7f29 100644 --- a/site/en/docs/devtools/console/format-style/index.md +++ b/site/en/docs/devtools/console/format-style/index.md @@ -301,7 +301,7 @@ Here is a list of styling code supported in DevTools. 9 - Add line-through to text-decoration propertyh + Add line-through to text-decoration property 22 From 6fc60ed471ba860ec9220680bd93656bf11a8344 Mon Sep 17 00:00:00 2001 From: Sam Dutton Date: Mon, 21 Aug 2023 17:24:35 +0100 Subject: [PATCH 700/982] Shared Storage article: fixed typo, and one minor wording tweak (#7104) --- site/en/docs/privacy-sandbox/shared-storage/index.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/site/en/docs/privacy-sandbox/shared-storage/index.md b/site/en/docs/privacy-sandbox/shared-storage/index.md index 5f21bfb82..696394ecf 100644 --- a/site/en/docs/privacy-sandbox/shared-storage/index.md +++ b/site/en/docs/privacy-sandbox/shared-storage/index.md @@ -65,7 +65,7 @@ existing uses for third-party cookies. This includes: Creative rotation - You can store data, such as creative ID, view counts, and user interaction, to determine which creative users' see across different sites. This allows you to balance views and avoid oversaturation of ceratin content, which can help you avoid a negative user experience. + You can store data, such as creative ID, view counts, and user interaction, to determine which creative users' see across different sites. This allows you to balance views and avoid oversaturation of certain content, which can help you avoid a negative user experience. Content selection @@ -114,7 +114,7 @@ Shared Storage allows you to make informed decisions based on cross-site data, without sharing user information (such as browser history or other personal details) with an embedding site or exfiltrating data to your own servers. -You can write to shared storage at any time, like other JavaScript storage APIs (like localStorage or indexedDB). Unlike the other storage APIs, you can only read the shared storage values in a secure environment, known as a shared storage worklet. +You can write to shared storage at any time, like other JavaScript storage APIs such as localStorage or indexedDB. Unlike the other storage APIs, you can only read the shared storage values in a secure environment, known as a shared storage worklet. {% Aside 'key-term' %} From ec3a5fa89ebca0e80df4cc040da58f1f4454bfa8 Mon Sep 17 00:00:00 2001 From: Alexandra White Date: Mon, 21 Aug 2023 12:25:08 -0400 Subject: [PATCH 701/982] update old URL and other nits (#7119) * update old URL and other nits * nit --- site/en/blog/removing-document-write/index.md | 33 +++++++++---------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/site/en/blog/removing-document-write/index.md b/site/en/blog/removing-document-write/index.md index 95b1909cd..99bbf7921 100644 --- a/site/en/blog/removing-document-write/index.md +++ b/site/en/blog/removing-document-write/index.md @@ -29,7 +29,7 @@ specifically those uses that inject scripts. As innocuous as the following looks can cause real issues for users. ```js -document.write(''); +document.write(''); ``` Before the browser can render a page, it has to build the DOM tree by parsing the HTML markup. @@ -38,12 +38,12 @@ parsing the HTML. If the script dynamically injects another script, the parser i even longer for the resource to download, which can incur one or more network roundtrips and delay the time to first render of the page -**For users on slow connections, such as 2G, external scripts dynamically injected via -`document.write()` can delay the display of main page content for tens of seconds**, -or cause pages to either fail to load or take so long that the user just gives -up. Based on instrumentation in Chrome, we've learned that pages featuring -third-party scripts inserted via `document.write()` are typically twice as slow to -load than other pages on 2G. +For users on slow connections, such as 2G, external scripts dynamically +injected via `document.write()` can delay the display of main page content for +tens of seconds, or cause pages to either fail to load or take so long that the +user just gives up. Based on instrumentation in Chrome, we've learned that +pages featuring third-party scripts inserted via `document.write()` are +typically twice as slow to load than other pages on 2G. We collected data from a 28 day field trial on 1% of Chrome stable users, restricted to users on 2G connections. We saw that 7.6% of all page loads @@ -89,29 +89,28 @@ Specifically Chrome will not execute the ` +``` + +{% Aside 'important' %} +Prefetch speculation rules only prefetch the document, not its subresources. This uses fewer resources than a full prerender of a potential next navigation, but also means the subresources need to be fetched and rendered upon navigation. +{% endAside %} + +Speculation rules are used for navigation prefetches have some advantages over the older `` syntax, such as a more expressive API and the results being stored in memory cache rather than the HTTP disk cache. + +### Debugging `prefetch` speculation rules + +Prefetches triggered by speculation rules can be seen in the **Network** panel in the same way as other fetches: + +
+ {% Img src="image/W3z1f5ZkBJSgL1V1IfloTIctbIF3/k0SqZ4VcyVAnUq4y5lvC.png", alt="Network panel in Chrome DevTools showing prefetched documents", width="800", height="571" %} +
+ +The two requests highlighted in red are the prefetched resources, as can be seen by the **Type** column. These are fetched at `Lowest` priority as they are for future navigations and Chrome prioritizes the current page's resources. + +Clicking on one of the rows also shows the `Sec-Purpose: prefetch` HTTP header, which is how these requests can be identified on the server side: + +
+ {% Img src="image/W3z1f5ZkBJSgL1V1IfloTIctbIF3/ox90RIbGNpYXn05A1e37.png", alt="Chrome DevTools prefetch headers with Sec-Purpose set to prefetch", width="800", height="686" %} +
+ +### Debugging `prefetch` with the Preloading panes + +A new **Preloading** section has been added in the **Application** panel of Chrome DevTools to help aid in debugging speculation rules: + +
+ {% Img src="image/W3z1f5ZkBJSgL1V1IfloTIctbIF3/2HuCiXo0UN2FfchwaPtg.png", alt="Chrome DevTools Speculation Rules pane showing prefetch rule", width="800", height="587" %} +
+ +{% Aside 'important' %} +The **Preloading** panes are for working with speculation rules prefetching and prerendering (collectively known as "preloading"). These panes cannot be used to debug subresource _preloading_ using `` and subresource _prefetching_ using ``. +{% endAside %} + +There are three panes available in this section: + +- **Speculation Rules** which lists all the rule sets found on the current page. +- **Preloads** which lists all the prefetched and prerendered URLs from the rule sets. +- **This Page** which lists the prerendered status of the current page. + +The **Speculation Rules** pane is shown above, and we can see this example page has a single set of speculation rules for prefetching 3 pages. Two of those prefetches succeeded and one failed. The icon besides the **Rule set** can be clicked to take you to the source of the rule set in the **Elements** panel. Alternatively, the **Status** link can be clicked to take you to the **Preloads** pane filtered to that ruleset. + +The **Preloads** pane lists all the target URLs, along with the action (prefetch or prerender), which rule set they came from (as there may be multiple on a page), and the status of each preload: + +
+ {% Img src="image/W3z1f5ZkBJSgL1V1IfloTIctbIF3/m5cy4LilaIbGF7vthZl5.png", alt="Chrome DevTools Preloads pane showing prefetched URLs along with their status", width="800", height="593" %} +
+ +Above the URLs, a drop down can be used to show URLs from all the rule sets, or only URLs from a particular rule set. Below that, all the URLs are listed. Clicking on a URL gives you more detailed information. + +In this screenshot, we can see the failure reason for the `next3.html` page (which does not exist and therefore returns a 404, which is a non-2xx HTTP status code). + +The final pane, **This Page**, shows a **Preloading status** report to show whether a prefetch or prerender was used for this page or not. + +For a prefetched page, you should see a successful message when that page is navigated to: + +
+ {% Img src="image/W3z1f5ZkBJSgL1V1IfloTIctbIF3/5q9aRZuYclNB8jG7VB1h.png", alt="Chrome DevTools This Page pane showing a successful prefetch", width="800", height="326" %} +
+ +#### Unmatched preloads + +When a navigation happens from a page with speculation rules that does not result in a preload, an additional section of the pane will show more details of why the URL did not match any of the preloaded URLs. This is useful for spotting typos in your speculation rules. + +
+ {% Img src="image/W3z1f5ZkBJSgL1V1IfloTIctbIF3/suepp8Pn5xNr9oNYeEkX.png", alt="Chrome DevTools This Page pane, showing how the current URL did not match any of the URLs in the previous page's speculation rules", width="800", height="364" %} +
+ +For example, here we navigated to `next4.html`, but only `next.html`, `next2.html`, or `next3.html` are prefetches, so we can see this doesn't quite match any of those three rules. + +{% Aside %} + As this feedback is primarily intended for debugging speculation rules, this URL matching can look a little confusing when navigating to a completely different page that is not included in speculation rules, and is therefore not expected to be preloaded: + +
+ {% Img src="image/W3z1f5ZkBJSgL1V1IfloTIctbIF3/u8qawIQeCNv8KFsoDxaO.png", alt="Chrome DevTools showing an unmatched URL in the This Page Preloading pane", width="800", height="364" %} +
+ + The Chrome team is [continuing to iterate on this feature](https://bugs.chromium.org/p/chromium/issues/detail?id=1473861) to improve the user interface in these cases. +{% endAside %} + +The **Preloading** panes are very useful for debugging the speculation rules themselves, and finding any syntax errors in the JSON. + +As for the prefetches themselves, the **Network** panel is likely a more familiar place. For the prefetch failure example, you can see the 404 for the prefetch here: + +
+ {% Img src="image/W3z1f5ZkBJSgL1V1IfloTIctbIF3/kHIghY1mr64PNnvowgrR.png", alt="Chrome DevTools Network panel showing a failed prefetch", width="800", height="296" %} +
+ +However, the **Preloading** panes become much more useful for prerendering speculation rules, which are covered next. + +## Speculation rules for `prerender` + +Prerender speculation rules follow the same syntax as prefetch speculation rules. For example: + +```html + +``` + +This rule set triggers a full load and render of the specified pages (subject to certain restrictions). This can provide an instant loading experience—albeit with extra resource costs. + +Unlike prefetches however, these are not available to be seen in the **Network** panel, as these are fetched and rendered in a separate rendering process in Chrome. This makes the **Preloading** panes more important to debug prerender speculation rules. + +### Debugging `prerender` with the Preloading panes + +The same **Preloading** section introduced above can be used for prerender speculation rules as demonstrated with a similar demo page that attempts to prerender, instead of prefetching the three pages: + +
+ {% Img src="image/W3z1f5ZkBJSgL1V1IfloTIctbIF3/9mlMrC7ekXP67BWozsaD.png", alt="Chrome DevTools Preloading panes for a page with prerender speculation rules", width="800", height="436" %} +
+ +Here we see again that one of the 3 preloads failed to prerender, and developers can get the details per URL in the **Preloads** pane by clicking on the **2 Ready, 1 Failure** link. + +We are currently experimenting with [document speculation rules](https://github.com/WICG/nav-speculation/blob/main/chrome-2023q1-experiment-overview.md#automatic-link-finding) (available as [an origin trial](/origintrials/#/view_trial/705939241590325249)), which—rather than listing a specific set of URLs—allows the browser to pick these up from same origin links on the page: + +```html + +``` + +The above example selects all same origin links (including those with URL params or fragments—that is what the `\\?*#*` part means), except those beginning with `/not-safe-to-prerender `as prerender candidates. + +It also sets the prerender `eagerness` to `moderate` which means the navigations are prerendered when the link is hovered, or clicked. + +There are similar rules like this on [developer.chrome.com](/) itself, and using the new **Preloading** section on this site shows the usefulness of this new pane as all the eligible URLs the browser found on the page are listed: + +
+ {% Img src="image/W3z1f5ZkBJSgL1V1IfloTIctbIF3/w9iL4IYKM1gXL1S5lIap.png", alt="Chrome DevTools Preloads pane with a number of Not triggered URLs", width="800", height="528" %} +
+ +The **Status** is **Not triggered** as the prerender process for these has not started. However, as we hover over the links, we see the status change as each URL is prerendered: + +
+ {% Img src="image/W3z1f5ZkBJSgL1V1IfloTIctbIF3/srL61CA90M1IB2u9IYFH.png", alt="Chrome DevTools Preloads pane with prerendered pages triggered", width="800", height="528" %} +
+ +Chrome currently [limits a page to 10 prerenders](https://bugs.chromium.org/p/chromium/issues/detail?id=1464021), so after hovering over the 11th link, we see the failure reason for that URL: + +
+ {% Img src="image/W3z1f5ZkBJSgL1V1IfloTIctbIF3/hNWZE6yNtYWtjfkffUjL.png", alt="Chrome DevTools Preloads pane with failed preloads showing", width="800", height="465" %} +
+ +### Debugging `prerender` with the other DevTools panels + +Unlike prefetches, pages that have been prerendered will not show up in the current rendering processes in DevTools panels like the **Network** panel, because they are rendered in their own behind-the-scenes renderer. + +However, it is now possible to switch the renderer used by the DevTools panels with the drop down menu in the top right drop down, or by selecting a URL in the top part of the panel and selecting **Inspect**: + +
+ {% Img src="image/W3z1f5ZkBJSgL1V1IfloTIctbIF3/Pxu2F91J3FTk7090DrvD.png", alt="Chrome DevTools now allows you to switch renderers that information is displayed for", width="800", height="599" %} +
+ +This drop down (and the value selected) is shared across all the other panels too, such as the **Network** panel, where you can see the page being requested is the prerendered one: + +
+ {% Img src="image/W3z1f5ZkBJSgL1V1IfloTIctbIF3/YZwZCcZ0a6sJtmafEdS6.png", alt="Chrome DevTools Network panel showing the network requests for the prerendered page", width="800", height="465" %} +
+ +Looking at the HTTP headers for these resources we can see they will all be set with the `Sec-Purpose: prefetch;prerender` header: + +
+ {% Img src="image/W3z1f5ZkBJSgL1V1IfloTIctbIF3/sChO1hRSxqB8o4n2v7Ya.png", alt="Chrome DevTools Network panel showing Sec-Purpose header for a prerendered page", width="800", height="487" %} +
+ +Or the **Elements** panel, where you can see the page contents, like in below screenshot where we see the `

` element is for the prerendered page: + +
+ {% Img src="image/W3z1f5ZkBJSgL1V1IfloTIctbIF3/wTF5aocvUFFnnZnMRomH.png", alt="Chrome DevTools Elements panel for the prerendered page", width="800", height="465" %} +
+ +Or the **Console panel**, where you can see console logs emitted by the prerendered page: + +
+ {% Img src="image/W3z1f5ZkBJSgL1V1IfloTIctbIF3/u1QnilcFwOmbjmgQWQEe.png", alt="Chrome DevTools Console panel showing the console output from a prerendered page", width="800", height="226" %} +
+ +It's even possible to see the **Preload** pane for a prerendered frame to see if it had speculation rules: + +
+ {% Img src="image/W3z1f5ZkBJSgL1V1IfloTIctbIF3/rBbT9ZOTqKWtZ5G3rxeJ.png", alt="Chrome DevTools Preloads pane for a preloaded page 🤯", width="800", height="487" %} +
+ +Note that speculation rules themselves are not actioned until the prerendered page is activated. These pages will always be in the `Not triggered` status. + +### Debugging speculation rules on the prerendered page + +The previous sections discuss how to debug prerendered pages on the page which initiates the prerendering. However, it's also possible for the prerendered pages themselves to provide debugging information, either by making analytics calls or logging to the console (which is viewable as described above). + +Additionally, once a prerendered page is activated by the user navigating to it, the **This Page** pane will show this status, and whether it was successfully prerendered or not. If it could not be prerender an explanation as to why that was the case is provided: + +
+ {% Img src="image/W3z1f5ZkBJSgL1V1IfloTIctbIF3/7ksJhB9WgTxSn4y0qBdX.png", alt="Chrome DevTools Preloading This Page pane showing both a successful and failed prerendered page", width="800", height="413" %} +
+ +Additionally—[as is the case for prefetches](#unmatched-preloads)—navigating from a page with speculation rules that did not match the current page will attempt to show you why the URLs did not match those covered in the previous page's speculation rules in the **This Page** pane: + +
+ {% Img src="image/W3z1f5ZkBJSgL1V1IfloTIctbIF3/ZfJXbAYqt2BMvmDyvlmy.png", alt="Chrome DevTools This Page pane showing the URL mismatch of the current URL and those covered by the previous page", width="800", height="400" %} +
+ +## Conclusion + +In this post, we have shown the various ways developers can debug prefetch and prerender speculation rules. The team is continuing to work on tooling for speculation rules, and we would love to hear suggestions from the developers as to what other ways would be helpful for debugging this exciting new API. We encourage developers to raise an issue on the [Chrome issue tracker](https://bugs.chromium.org/p/chromium/issues/entry?template=Defect&components=Internals-Preload) for any feature requests or bugs spotted. + +## Acknowledgements + +_Hero image by [Nubelson Fernandes](https://unsplash.com/@nublson) on [Unsplash](https://unsplash.com/photos/CO6r5hbt1jg)._ diff --git a/site/en/blog/new-in-devtools-117/index.md b/site/en/blog/new-in-devtools-117/index.md index ccc6174ac..0a3e0cdb1 100644 --- a/site/en/blog/new-in-devtools-117/index.md +++ b/site/en/blog/new-in-devtools-117/index.md @@ -3,7 +3,7 @@ layout: 'layouts/blog-post.njk' title: "What's New in DevTools (Chrome 117)" authors: - sofiayem -date: 2023-08-15 +date: 2023-08-22 description: "Override XHR/fetch requests and hide extension requests from the Network panel, see changes in fetch priority in the Performance panel, experience multiple UI improvements, check out new colors and experimental features, and more." hero: 'image/NJdAV9UgKuN8AhoaPBquL7giZQo1/oM7ywmnxgVDuegxueVbK.png' alt: 'Override XHR/fetch requests and hide extension requests from the Network panel, see changes in fetch priority in the Performance panel, experience multiple UI improvements, check out new colors and experimental features, and more.' @@ -94,7 +94,7 @@ Chromium issue: [1153956](https://crbug.com/1153956). ### Pretty-print responses for JSON subtypes {: #pretty-json-response } The **Response** tab of for a request with a `application/[subtype]+json` [MIME subtype](https://www.iana.org/assignments/media-types/media-types.xhtml#application) (for example, `ld+json`, `hal+json`, and others) now parses the response correctly and lets you prettify it. - + {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/Na2g2Ba9ihx4P5BH9ZYW.png", alt="The before and after parsing an application/json subtype in a network response preview.", width="800", height="446" %} {# https://chromium.googlesource.com/devtools/devtools-frontend/+/2d0a199d6b50cc3cb6b8ca6539859045b52fb5e1 #} @@ -144,9 +144,9 @@ You can already test how Chrome behaves *after* the third-party cookie phaseout. Regardless of the way you run Chrome (with or without the flag), the **Issues** tab now has the {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/hmp8j3HiLMCcqPArD9yt.svg", alt="Checkbox.", width="22", height="22" %} **Include third-party cookie issues** checkbox enabled by default and, as a result, reports: - A breaking change warning about the upcoming phaseout. -- Issues related to third-party cookies. +- Issues related to third-party cookies. -To test this, inspect cookies at [this demo page](https://samesite-sandbox.glitch.me/). +To test this, inspect cookies at [this demo page](https://samesite-sandbox.glitch.me/). {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/WlT6ntQm5iEGujg8P32c.png", alt="Third-party cookie issues reported in the Issues tab.", width="800", height="439" %} @@ -162,7 +162,7 @@ Chromium issues: [1458839](https://crbug.com/1458839), [1462693](https://crbug.c ## Debug preloading in the Application panel {: #preloading } -The Chrome team is [bringing back full prerendering](/blog/prerender-pages/) of future pages that a user is likely to navigate to. To let you debug this, DevTools adds the **Preloading** section to the **Application** panel. The new prefetching and prerendering (collectively known as preloading) uses Speculation Rules is unrelated to the [legacy link-based resource hint versions](/blog/prerender-pages/#a-brief-history-of-prerender). +The Chrome team is [bringing back full prerendering](/blog/prerender-pages/) of future pages that a user is likely to navigate to. To let you debug this, DevTools adds the **Preloading** section to the **Application** panel. The new prefetching and prerendering (collectively known as "navigational preloading") uses the Speculation Rules API rather than to the [link-based resource hints](/blog/prerender-pages/#a-brief-history-of-prerender). On [this demo page](https://prerender-demos.glitch.me/), in the **Application** > **Preloading** section, you can inspect: @@ -172,6 +172,8 @@ On [this demo page](https://prerender-demos.glitch.me/), in the **Application** {% Video src="video/NJdAV9UgKuN8AhoaPBquL7giZQo1/YyxptgchqoTk8BQmXKO3.mp4", autoplay="false", loop="true", muted="true", controls="true", class="screenshot", width="800", height="592" %} +For more information, refer to the [dedicated post on debugging speculation rules](/blog/debugging-speculation-rules/). + {# https://chromium.googlesource.com/devtools/devtools-frontend/+/4e07e2023f0c99a2c2b31c87024d94dc820193de #} Chromium issue: [1410709](https://crbug.com/1410709). diff --git a/site/en/blog/prerender-pages/index.md b/site/en/blog/prerender-pages/index.md index 747997a32..f33cd274f 100644 --- a/site/en/blog/prerender-pages/index.md +++ b/site/en/blog/prerender-pages/index.md @@ -7,7 +7,7 @@ description: | authors: - tunetheweb date: 2022-12-02 -updated: 2023-04-18 +updated: 2023-08-22 hero: image/W3z1f5ZkBJSgL1V1IfloTIctbIF3/eohdiqaZlxnWen7TT66M.jpg alt: City road at dusk with a long exposure of car lights giving impression of speed tags: @@ -131,6 +131,10 @@ Speculation rules can be: Speculation rules can be added in either the `` or the `` of in the main frame. Speculation rules in subframes are not acted upon, and speculation rules in prerendered pages are only acted upon once that page is activated. +### Debugging speculation rules + +Please see the [dedicated post on debugging speculation rules](/blog/debugging-speculation-rules/), for new Chrome DevTools features to assist with viewing and debugging this new API. + ### Multiple speculation rules Multiple speculation rules can also be added to the same page, and they append to the existing rules. Therefore, the following different ways all result in both `one.html` and `two.html` prerendering: @@ -302,6 +306,10 @@ The easiest way to see if a page was prerendered is to open DevTools after the p {% Img src="image/W3z1f5ZkBJSgL1V1IfloTIctbIF3/C3pNnuCo3i4zHgbLWEo0.png", alt="Console in Chrome DevTools showing a positive activationStart indicating the page was prerendered", width="400", height="98.5" %} +{% Aside 'update' %} +From Chrome 117, additional Chrome DevTools debugging features are available for debugging prerendered pages. Please see the [Debugging speculation rules post](/blog/debugging-speculation-rules/) for more details. +{% endAside %} + When the page is activated by the user viewing the page, the `prerenderingchange` event will be dispatched on the `document`, which can then be used to enable activities that previously would be started by default on page load but which you wish to delay until the page is actually viewed by the user. Using these APIs, front-end JavaScript can detect and act upon prerendered pages appropriately. @@ -388,6 +396,7 @@ Prerendering is in active development by the Chrome team, and there are plenty o ## Related links +- [Debugging speculation rules](/blog/debugging-speculation-rules/) - [Introducing NoState Prefetch](/blog/nostate-prefetch/) - [Speculation Rules API](https://github.com/jeremyroman/alternate-loading-modes/blob/main/triggers.md#speculation-rules) - [The Navigational speculation GitHub repo](https://github.com/WICG/nav-speculation/) From a5a18b2e6bb21332eaed0601a48035ed154bd019 Mon Sep 17 00:00:00 2001 From: amysteamdev <37001393+AmySteam@users.noreply.github.com> Date: Tue, 22 Aug 2023 13:14:14 -0600 Subject: [PATCH 705/982] Update chrome.storage.local size in permissions article (#7145) Fixes #7101 --- site/en/docs/extensions/mv3/declare_permissions/index.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/site/en/docs/extensions/mv3/declare_permissions/index.md b/site/en/docs/extensions/mv3/declare_permissions/index.md index 03912b386..e6027b296 100644 --- a/site/en/docs/extensions/mv3/declare_permissions/index.md +++ b/site/en/docs/extensions/mv3/declare_permissions/index.md @@ -445,7 +445,7 @@ The following table lists the currently available permissions. For a list of per "unlimitedStorage" Provides an unlimited quota for storing client-side data, such as databases and local storage files. - Without this permission, the extension is limited to 5 MB of local storage.
Note: This permission applies only to Web SQL Database and application cache (see issue 58985). Also, it doesn't currently work with wildcard subdomains such as http://*.example.com.
@@ -497,4 +497,4 @@ The following table lists the currently available permissions. For a list of per [perm-update]: /docs/extensions/mv3/permission_warnings/#update_permissions [vision-optperms]: /docs/extensions/mv3/intro/platform-vision/#improved-user-visibility-and-control [file-scheme-allow]: /docs/extensions/reference/extension/#method-isAllowedFileSchemeAccess -[incognito-allow]: /docs/extensions/reference/extension/#method-isAllowedIncognitoAccess \ No newline at end of file +[incognito-allow]: /docs/extensions/reference/extension/#method-isAllowedIncognitoAccess From 5bf21896f6bb5cb8b7753366c9c62151d7738de8 Mon Sep 17 00:00:00 2001 From: Barry Pollard Date: Tue, 22 Aug 2023 20:40:22 +0100 Subject: [PATCH 706/982] Long animation frames (LoAF) article (#7078) * Long animation frames (LoAF) article * Better JS * Even more better JS * Tweaks * Add Noam as co-author * Update date * Smart quote * Brendan's initial feedback * Re-export to get latest changes * More INP tweaks * Rexport with latest changes * Latest export * Linkify PerformanceObserver * Add look up to Performance Timeline * let -> const * Link to INP linkage issues * Update dates * Tweaks * Rename variable --- site/_data/authorsData.json | 7 + site/_data/i18n/authors.yaml | 7 +- .../articles/long-animation-frames/index.md | 409 ++++++++++++++++++ 3 files changed, 422 insertions(+), 1 deletion(-) create mode 100644 site/en/articles/long-animation-frames/index.md diff --git a/site/_data/authorsData.json b/site/_data/authorsData.json index 4e8cf5c5c..8777d7b92 100644 --- a/site/_data/authorsData.json +++ b/site/_data/authorsData.json @@ -1866,6 +1866,13 @@ "country": "FR", "github": "hemeryar" }, + "nrosenthal": { + "country": "IL", + "github": "noamr", + "twitter": "nomsternom", + "mastodon": "https://indieweb.social/@nomster", + "image": "image/W3z1f5ZkBJSgL1V1IfloTIctbIF3/WvcwHjz1DNHSx2n7qCeM.jpg" + }, "samrichard": { "country": "US", "twitter": "snugug", diff --git a/site/_data/i18n/authors.yaml b/site/_data/i18n/authors.yaml index 00f074e2f..8cbcc8001 100644 --- a/site/_data/i18n/authors.yaml +++ b/site/_data/i18n/authors.yaml @@ -1521,8 +1521,13 @@ hemeryar: en: 'Arthur Hemery' description: en: 'Software Engineer, Google' +nrosenthal: + title: + en: 'Noam Rosenthal' + description: + en: 'Software engineer at Google working on web performance.' samrichard: title: en: 'Sam Richard' description: - en: 'Developer Advocate, Google ChromeOS' \ No newline at end of file + en: 'Developer Advocate, Google ChromeOS' diff --git a/site/en/articles/long-animation-frames/index.md b/site/en/articles/long-animation-frames/index.md new file mode 100644 index 000000000..ff4da378b --- /dev/null +++ b/site/en/articles/long-animation-frames/index.md @@ -0,0 +1,409 @@ +--- +# Required +layout: 'layouts/blog-post.njk' +title: Long Animation Frames API +description: | + Learn about the Long Animation Frames API (LoAF) proposal which is the next iteration of the Long Tasks API and allows measuring frame update delays with attribution +authors: + - tunetheweb + - nrosenthal +date: 2023-08-22 +#updated: 2023-08-22 +hero: image/W3z1f5ZkBJSgL1V1IfloTIctbIF3/bQjxz9V8QoQMnP2tpczn.jpg +alt: A clock on the frame of St Pancras station +tags: + - performance + - origin-trials + - chrome-116 +--- + +The [Long Animation Frames API](https://github.com/w3c/longtasks/blob/main/loaf-explainer.md) (LoAF - pronounced Lo-Af) is a new proposal from the Chrome team to update the [Long Tasks API](https://w3c.github.io/longtasks/) to provide a better understanding of slow user interface (UI) updates. This can be useful to identify slow animation frames which are likely to affect the pending [Interaction to Next Paint (INP)](https://web.dev/inp/) Core Web Vital metric which measures responsiveness, or to identify other UI jank which affects [smoothness](https://web.dev/smoothness/). + +The LoAF API is available as [an origin trial from Chrome 116](/origintrials/#/view_trial/3935020174414970881) for developers to experiment with and provide feedback on. + +## The Long Tasks API + +The Long Animation Frames API is an alternative to the Long Tasks API which has been available in Chrome for some time now (since Chrome 58). As its name suggests, the Long Task API allows you to monitor for long tasks, which are tasks that occupy the main thread for 50 milliseconds or longer. Long tasks can be monitored using the [`PerformanceLongTaskTiming`](https://developer.mozilla.org/docs/Web/API/PerformanceLongTaskTiming) interface, with a [`PeformanceObserver`](https://developer.mozilla.org/docs/Web/API/PerformanceObserver): + +```js +const observer = new PerformanceObserver((list) => { + console.log(list.getEntries()); +}); + +observer.observe({ type: 'longtask', buffered: true }); +``` + +Long tasks are likely to cause responsiveness issues. If a user tries to interact with a page—for example, click a button, or open a menu—but the main thread is already dealing with a long task, then the [user's interaction is delayed](https://web.dev/optimize-input-delay/#what-is-input-delay) waiting for that task to be completed. + +To improve responsiveness, it is often advised to [break up long tasks](https://web.dev/optimize-long-tasks/). If each long task is instead broken up into a series of multiple, smaller tasks, it may allow more important tasks to be executed in between them to avoid significant delays in responding to interactions. + +So when trying to improve responsiveness, the first effort is often to run a performance trace and look at long tasks. This could be through a lab-based auditing tool like Lighthouse (which has an **Avoid long main-thread tasks** audit), or by [looking at long tasks in Chrome DevTools](https://web.dev/long-tasks-devtools/). + +Lab-based testing is [often a poor starting place for identifying responsiveness issues](https://web.dev/diagnose-slow-interactions-in-the-lab/), as these tools may not include interactions—when they do, they are a small subset of likely interactions. Ideally, you would measure causes of slow interactions in the field. + +### Shortcomings of the Long Tasks API + +Measuring long tasks in the field using the Performance Observer above is only somewhat useful. In reality, it doesn't give that much information beyond the fact that a long task happened, and how long it took. + +Real User Monitoring (RUM) tools often use this to trend the number or duration of long tasks or identifying which pages they happen on—but without the underlying details of what caused the long task, this is only of limited use. The Long Tasks API only has a [basic attribution model](https://developer.mozilla.org/docs/Web/API/TaskAttributionTiming), which at best only tells you the container the long task happened in (the top-level document or an ` ``` -The [Proposed First FLEDGE Origin Trial Permissions-Policy](https://github.com/WICG/turtledove/blob/main/Proposed_First_FLEDGE_OT_Details.md#permissions-policy) section provides more detail. +The [Proposed First Protected Audience Origin Trial Permissions-Policy](https://github.com/WICG/turtledove/blob/main/Proposed_First_FLEDGE_OT_Details.md#permissions-policy) section provides more detail. ### User opt-out {: #opt-out-user} -A user can block access to the FLEDGE API and other Privacy Sandbox features by using any of the +A user can block access to the Protected Audience API and other Privacy Sandbox features by using any of the following mechanisms: * **Disable the Privacy Sandbox trials** in Chrome Settings: **Settings** > @@ -273,12 +278,12 @@ following mechanisms: from `chrome://settings/cookies`. * Use Incognito mode. -The FLEDGE explainer provides [more detail about API design elements](https://github.com/WICG/turtledove/blob/main/FLEDGE.md#design-elements) and describes how the API seeks to meet [privacy goals](https://github.com/WICG/turtledove/blob/main/FLEDGE.md#:~:text=privacy%20goal). +The Protected Audience explainer provides [more detail about API design elements](https://github.com/WICG/turtledove/blob/main/FLEDGE.md#design-elements) and describes how the API seeks to meet [privacy goals](https://github.com/WICG/turtledove/blob/main/FLEDGE.md#:~:text=privacy%20goal). -## Debug FLEDGE worklets {: #debugging } +## Debug Protected Audience worklets {: #debugging } -From Chrome Canary 98.0.4718.0, it's possible to debug FLEDGE worklets within Chrome DevTools. +From Chrome Canary 98.0.4718.0, it's possible to debug Protected Audience worklets within Chrome DevTools. The first step is to set breakpoints via a new category in the **Event Listener Breakpoints** pane in the **Sources** panel. @@ -301,33 +306,33 @@ Since some worklets may run in parallel, multiple threads may end up in the "pau you can use the thread list to switch between threads, and resume or inspect them more closely as appropriate. -### Observe FLEDGE events +### Observe Protected Audience events -From the Application panel in Chrome DevTools, you can observe FLEDGE interest group and auction +From the Application panel in Chrome DevTools, you can observe Protected Audience interest group and auction events. -If you visit the [FLEDGE demo shopping site](https://shopping-fledge-demo.glitch.me/advertiser/shopping.html) -in a browser with FLEDGE enabled, DevTools will display information about the `join` event. +If you visit the [Protected Audience demo shopping site](https://protected-audience-demo-advertiser.web.app/) +in a browser with Protected Audience enabled, DevTools will display information about the `join` event. {% Img src="image/80mq7dk16vVEg8BBhsVe42n6zn82/3jI5bJh8XKiZP5WHMBYl.png", alt="The - DevTools Application panel in Chrome Canary, showing information about a FLEDGE interest group + DevTools Application panel in Chrome Canary, showing information about a Protected Audience interest group join event.", width="800", height="402" %} -Now, if you visit the [FLEDGE demo publisher site](https://publisher-fledge-demo.glitch.me/publisher/index.html?fencedframe) - in a browser with FLEDGE enabled, DevTools displays information about the `bid` and `win` events. +Now, if you visit the [Protected Audience demo publisher site](https://protected-audience-demo-publisher.web.app/) + in a browser with Protected Audience enabled, DevTools displays information about the `bid` and `win` events. {% Img src="image/80mq7dk16vVEg8BBhsVe42n6zn82/wMvNrY9GrcD2p3Q6wTsw.png", alt="The - DevTools Application panel in Chrome Canary, showing information about FLEDGE auction bid and + DevTools Application panel in Chrome Canary, showing information about Protected Audience auction bid and win events.", width="800", height="482" %} {% Aside %} -You'll need to refresh the page to see FLEDGE events if DevTools wasn't open when you navigated to +You'll need to refresh the page to see Protected Audience events if DevTools wasn't open when you navigated to the site. {% endAside %} -## How does the FLEDGE API work? {: #how} +## How does the Protected Audience API work? {: #how} In this example, a user browses the website of a custom bike maker, then later visits a news website and is shown an ad for a new bike from the bike maker. @@ -335,11 +340,11 @@ and is shown an ad for a new bike from the bike maker. {% Aside 'warning' %} Not all features described in this post have been implemented (or fully implemented) in the version -of the FLEDGE API currently being tested in Chrome. [Test with feature flags](#flags) -explains what FLEDGE features are currently available for testing in Chrome run from the command line +of the Protected Audience API currently being tested in Chrome. [Test with feature flags](#flags) +explains what Protected Audience features are currently available for testing in Chrome run from the command line using [feature flags](https://www.chromium.org/developers/how-tos/run-chromium-with-flags). -We expect the features of FLEDGE will be added over time as work on implementation continues. Once +We expect the features of Protected Audience will be added over time as work on implementation continues. Once the API reaches the origin trial stage, we'll provide a regularly-updated list of which parts are already implemented and what's still in progress. @@ -351,14 +356,14 @@ already implemented and what's still in progress. a person visiting a custom bike manufacturer site in a browser on their laptop.", width="400", height="190" %} -Imagine that a user visits the website of a custom bike maker (the [advertiser](/docs/privacy-sandbox/fledge#advertiser) in +Imagine that a user visits the website of a custom bike maker (the [advertiser](/docs/privacy-sandbox/protected-audience#advertiser) in this example) and spends some time on the product page for a handmade steel bike. This provides the -bike maker with a [remarketing](/docs/privacy-sandbox/fledge#remarketing) opportunity. +bike maker with a [remarketing](/docs/privacy-sandbox/protected-audience#remarketing) opportunity. {% Aside 'key-term' %} A _demand-side platform_ (DSP) is an adtech service used to automate ad purchasing. DSPs are used by advertisers to buy [ad impressions](https://en.wikipedia.org/wiki/Impression_(online_media)) -across a range of publisher sites. Publishers put their [ad inventory](/docs/privacy-sandbox/fledge#ad-inventory) up for sale +across a range of publisher sites. Publishers put their [ad inventory](/docs/privacy-sandbox/protected-audience#ad-inventory) up for sale through marketplaces called ad exchanges, and DSPs decide programmatically which available ad impression makes most sense for an advertiser to buy. @@ -377,11 +382,11 @@ exchanges, DSPs, and networks. This enables a wide range of potential buyers to **Explainer section:** [Browsers Record Interest Groups](https://github.com/WICG/turtledove/blob/main/FLEDGE.md#1-browsers-record-interest-groups) -The advertiser's [demand-side platform](/docs/privacy-sandbox/fledge/#dsp) (DSP) (or the advertiser +The advertiser's [demand-side platform](/docs/privacy-sandbox/protected-audience#dsp) (DSP) (or the advertiser itself) calls `navigator.joinAdInterestGroup()` to ask the browser to add an interest group to the list of groups the browser is a member of. In this example, the group is named `custom-bikes`, and the owner is `dsp.example`. The interest group owner (in this case, the DSP) will be a -[buyer](/docs/privacy-sandbox/fledge/#buyer) in the ad auction described in [step 4](#ad-auction). +[buyer](/docs/privacy-sandbox/protected-audience#buyer) in the ad auction described in [step 4](#ad-auction). Interest group membership is stored by the browser, on the user's device, and is not shared with the browser vendor or anyone else. @@ -407,7 +412,7 @@ For example: it must not be possible for `malicious.example` to call **Same origin**: By default, permission is implicitly granted for `joinAdInterestGroup()` calls from the same origin as the site being visited, i.e. from the same origin as the top-level frame of the -current page. Sites can use a FLEDGE [permissions policy header](/docs/privacy-sandbox/permissions-policy/) +current page. Sites can use a Protected Audience [permissions policy header](/docs/privacy-sandbox/permissions-policy/) `join-ad-interest-group` directive to disable `joinAdInterestGroup()` calls. **Cross origin**: Calling `joinAdInterestGroup()` from origins that are different from the current @@ -415,10 +420,10 @@ page can only succeed if the site being visited has set a permissions policy tha `joinAdInterestGroup()` from cross-origin iframes. {% Aside %} -The default in the current implementation of FLEDGE is to allow calls to `joinAdInterestGroup()` +The default in the current implementation of Protected Audience is to allow calls to `joinAdInterestGroup()` from anywhere in a page, even from cross-origin iframes. In the future, once site owners have had time to adjust their permissions policies, the plan is by default to disallow calls from -cross-origin iframes, as described in the FLEDGE explainer. +cross-origin iframes, as described in the Protected Audience explainer. {% endAside %} #### Permission from the interest group owner @@ -459,9 +464,9 @@ days. Successive calls overwrite previously stored values. {% Aside 'gotchas' %} -All URLs used as parameters for FLEDGE API methods must be from secure origins: all resources must +All URLs used as parameters for Protected Audience API methods must be from secure origins: all resources must be served over HTTPS URLs. [How to use HTTPS for local development](https://web.dev/how-to-use-local-https/) -explains how to do this when running FLEDGE locally. +explains how to do this when running Protected Audience locally. In addition, `biddingLogicUrl`, `decisionLogicUrl`, and `trustedBiddingSignals` all require an `X-Allow-FLEDGE: true` HTTP response header. @@ -663,7 +668,7 @@ metadata. * `perBuyerSignals`
As with `auctionSignals`, a property of the [auction configuration](#ad-auction) argument passed to `navigator.runAdAuction()` by the seller. This can provide contextual -signals from the buyer's server about the page, if the seller is an [SSP](/docs/privacy-sandbox/fledge#ssp) which +signals from the buyer's server about the page, if the seller is an [SSP](/docs/privacy-sandbox/protected-audience#ssp) which performs a real-time bidding call to buyer servers and pipes the response back, or if the publisher page contacts the buyer's server directly. If so, the buyer may wish to check a cryptographic signature of those signals inside generateBid() as protection against tampering. @@ -758,19 +763,19 @@ Code for an ad can also call this function for its interest group. has an empty ad slot.", width="400", height="182" %} Later, the user visits a site that sells ads space, in this example a news website. The site has -[ad inventory](/docs/privacy-sandbox/fledge/#ad-inventory), which it sells programmatically using -[real-time bidding](/docs/privacy-sandbox/fledge/#rtb). +[ad inventory](/docs/privacy-sandbox/protected-audience#ad-inventory), which it sells programmatically using +[real-time bidding](/docs/privacy-sandbox/protected-audience#rtb). {% Aside %} -There are three main roles described in the FLEDGE proposal explainer: +There are three main roles described in the Protected Audience proposal explainer: * **Advertiser**: a site that pays to advertise its products. In the example here, a custom bike maker. * **Publisher**: sites that sell ad space, such as the online news website referred to in the examples here. Many (but not all) sites selling ad space are content publishers. * **Seller**: the party running the ad auction (in the next step). Most publishers use an adtech - service such as an [SSP](/docs/privacy-sandbox/fledge#ssp) to optimize selling ad inventory. + service such as an [SSP](/docs/privacy-sandbox/protected-audience#ssp) to optimize selling ad inventory. {% endAside %} @@ -780,11 +785,11 @@ There are three main roles described in the FLEDGE proposal explainer: {% Img src="image/80mq7dk16vVEg8BBhsVe42n6zn82/fP9qHtCjfk8IwrJLtOpo.png", alt="Illustration showing a person viewing a news website in a browser on their laptop. An ad - auction using the FLEDGE API is taking place.", width="400", height="182" %} + auction using the Protected Audience API is taking place.", width="400", height="182" %} **Explainer section:** [Sellers Run On-Device Auctions](https://github.com/WICG/turtledove/blob/main/FLEDGE.md#2-sellers-run-on-device-auctions) -The ad auction is likely to be run by the publisher's [SSP](/docs/privacy-sandbox/fledge#ssp), or +The ad auction is likely to be run by the publisher's [SSP](/docs/privacy-sandbox/protected-audience#ssp), or the publisher itself. The purpose of the auction is to select the most appropriate ad for a single available ad slot on the current page. The auction takes into account the interest groups the browser is a member of, along with data from ad-space buyers and the sellers from the [Key/Value services](#keyvalue-service). @@ -828,7 +833,7 @@ const auctionResultPromise = navigator.runAdAuction(auctionConfig); ``` `runAdAuction()` returns a promise that resolves to a [URN](https://developer.mozilla.org/docs/Web/HTTP/Basics_of_HTTP/Identifying_resources_on_the_Web#urns) (`urn:uuid:`) that represents the -ad auction outcome. This can only be decoded by the browser when passed to a [fenced frame](/docs/privacy-sandbox/fledge#fenced-frame) +ad auction outcome. This can only be decoded by the browser when passed to a [fenced frame](/docs/privacy-sandbox/protected-audience#fenced-frame) for rendering: the publisher page cannot inspect the winning ad. {% Aside %} As explained earlier, the origin of the calling context for @@ -929,9 +934,9 @@ metadata, one at a time, and then assigns it a numerical desirability score. Ads are then accepted or rejected based on criteria other than inclusion of the interest group owner. For example, the seller may review ad creatives to confirm compliance with their policies. -\*\* `additionalBids` is not supported in the current implementation of FLEDGE. Read the [Auction +\*\* `additionalBids` is not supported in the current implementation of Protected Audience. Read the [Auction Participants](https://github.com/WICG/turtledove/blob/main/FLEDGE.md#22-auction-participants) section in the -FLEDGE explainer for more information. +Protected Audience explainer for more information. #### How are ads selected? @@ -980,9 +985,9 @@ its `scoreAd()` logic is to reject any ad that can't beat the contextual winner. {% Img src="image/80mq7dk16vVEg8BBhsVe42n6zn82/rn0slzXLZNSzGHMm6w7Y.png", alt="Illustration showing a person viewing a news website in a browser on their laptop. An ad - auction using the FLEDGE API is taking place, with a participant getting data from the Key/Value service.", width="400", height="126" %} + auction using the Protected Audience API is taking place, with a participant getting data from the Key/Value service.", width="400", height="126" %} -**Explainer section:** [Fetching Real-Time Data from the FLEDGE Key/Value service](https://github.com/WICG/turtledove/blob/main/FLEDGE.md#31-fetching-real-time-data-from-a-trusted-server). +**Explainer section:** [Fetching Real-Time Data from the Protected Audience Key/Value service](https://github.com/WICG/turtledove/blob/main/FLEDGE.md#31-fetching-real-time-data-from-a-trusted-server). During an ad auction, the ad-space **seller** can get realtime data about specific ad creatives by making a request to a [Key/Value service](#keyvalue-service) using the `trustedScoringSignalsUrl` property of @@ -1008,7 +1013,7 @@ https://kv-service.example/getvalues?hostname=publisher.example&keys=key1,key2 The response to this request is a JSON object providing values for each of the keys. {% Aside 'gotchas' %} -In the current initial experimental phase for testing FLEDGE, `trustedBiddingSignalsUrl` must have +In the current initial experimental phase for testing Protected Audience, `trustedBiddingSignalsUrl` must have the same origin as the interest group owner: see [Interest group properties](#interest-group-properties) and [Bring Your Own Server](https://github.com/WICG/turtledove/blob/main/FLEDGE.md#:~:text=bring%20your%20own%20server). {% endAside %} @@ -1025,7 +1030,7 @@ the same origin as the interest group owner: see [Interest group properties](#in **Explainer section:** [Browsers Render the Winning Ad](https://github.com/WICG/turtledove/blob/main/FLEDGE.md#4-browsers-render-the-winning-ad) As described earlier: the promise returned by [`runAdAuction()`](#ad-auction) resolves to an [URN](https://developer.mozilla.org/docs/Web/HTTP/Basics_of_HTTP/Identifying_resources_on_the_Web#urns) -which is passed to a [fenced frame](/docs/privacy-sandbox/fledge#fenced-frame) for rendering, and the site displays +which is passed to a [fenced frame](/docs/privacy-sandbox/protected-audience#fenced-frame) for rendering, and the site displays the winning ad. @@ -1098,7 +1103,7 @@ reportWin(auctionSignals, perBuyerSignals, sellerSignals, browserSignals) { {% Aside %} -The current implementation of FLEDGE in Chrome will warn if `reportWin()` is not defined. +The current implementation of Protected Audience in Chrome will warn if `reportWin()` is not defined. {% endAside %} @@ -1138,7 +1143,7 @@ Chrome only sends debug loss/win reports when an auction runs to completion. If canceled (for example, due to a new navigation) no reports will be generated. These methods are available by default in Chrome if `chrome://flags/#privacy-sandbox-ads-apis` is -enabled. But, if you're running Chrome with command line flags to enable FLEDGE, you'll need to +enabled. But, if you're running Chrome with command line flags to enable Protected Audience, you'll need to explicitly enable the methods by including the `BiddingAndScoringDebugReportingAPI` flag. If the flag is not enabled, the methods will still be available but do nothing. @@ -1160,13 +1165,13 @@ see [Fenced Frames Ads Reporting](https://github.com/WICG/turtledove/blob/main/F {: #auction-diagram} -The diagram below outlines each stage of a FLEDGE [ad auction](#ad-auction): +The diagram below outlines each stage of a Protected Audience [ad auction](#ad-auction): view a larger version.
{% Img src="image/hVf1flv5Jdag8OQKYqOcJgWUvtz1/M8lyXt6JbwFncB16mTb0.png", alt="Illustration providing - an overview of each stage of a FLEDGE ad auction", + an overview of each stage of a Protected Audience ad auction", width="800", height="481" %}
@@ -1177,13 +1182,13 @@ The diagram below outlines each stage of a FLEDGE [ad auction](#ad-auction): {% Details %} {% DetailsSummary %} -### What is the difference between FLEDGE and TURTLEDOVE? +### What is the difference between Protected Audience and TURTLEDOVE? {% endDetailsSummary %} -FLEDGE is the first experiment to be implemented in Chromium within the TURTLEDOVE family of proposals. +Protected Audience is the first experiment to be implemented in Chromium within the TURTLEDOVE family of proposals. -FLEDGE follows TURTLEDOVE's high-level principles. Some online advertising has been based on showing an ad to a potentially-interested person who has previously interacted with the advertiser or ad network. Historically this has worked by the advertiser recognizing a specific person as they browse across web sites, a core privacy concern with today's web. +Protected Audience follows TURTLEDOVE's high-level principles. Some online advertising has been based on showing an ad to a potentially-interested person who has previously interacted with the advertiser or ad network. Historically this has worked by the advertiser recognizing a specific person as they browse across web sites, a core privacy concern with today's web. The TURTLEDOVE effort is about offering a new API to address this use case while offering some key privacy advances: @@ -1192,26 +1197,26 @@ The TURTLEDOVE effort is about offering a new API to address this use case while - Advertisers can serve ads based on an interest, but cannot combine that interest with other information about a person — in particular, who they are or what page they are visiting. -FLEDGE grew out of TURTLEDOVE and a collection of related proposals for modifications to better served the developers who would be using the API: +Protected Audience grew out of TURTLEDOVE and a collection of related proposals for modifications to better served the developers who would be using the API: - In [SPARROW](https://github.com/WICG/sparrow): [Criteo](https://www.admonsters.com/what-is-sparrow/) proposed the addition of a - ("Gatekeeper") service model running in a [trusted execution environment (TEE)](https://github.com/privacysandbox/fledge-docs/blob/main/trusted_services_overview.md#trusted-execution-environment). FLEDGE includes a more limited use of TEEs, for real-time data lookup and aggregated reporting. + ("Gatekeeper") service model running in a [trusted execution environment (TEE)](https://github.com/privacysandbox/fledge-docs/blob/main/trusted_services_overview.md#trusted-execution-environment). Protected Audience includes a more limited use of TEEs, for real-time data lookup and aggregated reporting. - NextRoll's [TERN](https://github.com/WICG/turtledove/blob/main/TERN.md) and Magnite's [PARRROT](https://github.com/prebid/identity-gatekeeper/blob/master/proposals/PARRROT.md) proposals described the different roles that buyers and sellers had in the on-device auction. - FLEDGE's ad bidding/scoring flow is based on this work. + Protected Audience's ad bidding/scoring flow is based on this work. - RTB House's [Outcome-based](https://github.com/WICG/turtledove/blob/main/OUTCOME_BASED.md) and [Product-level](https://github.com/WICG/turtledove/blob/main/PRODUCT_LEVEL.md) TURTLEDOVE modifications improved the anonymity model and personalization capabilities of the on-device auction - [PARAKEET](https://github.com/WICG/privacy-preserving-ads/blob/main/Parakeet.md) is Microsoft's proposal for a TURTLEDOVE-like ad service that relies on a proxy server running in a TEE between the browser and the adtech providers, to anonymize ad requests and enforce privacy - properties. FLEDGE has not adopted this proxying model. We are bringing the JavaScript APIs - for PARAKEET and FLEDGE into alignment, in support of future work to further combine the best + properties. Protected Audience has not adopted this proxying model. We are bringing the JavaScript APIs + for PARAKEET and Protected Audience into alignment, in support of future work to further combine the best features of both proposals. -FLEDGE does not yet prevent a website's ad network from learning which ads a person sees. We expect +Protected Audience does not yet prevent a website's ad network from learning which ads a person sees. We expect to modify the API to become more private over time. {% endDetails %} @@ -1228,14 +1233,14 @@ to modify the API to become more private over time. Users can adjust their participation for Privacy Sandbox trials in Chrome by enabling or disabling the top-level setting in chrome://settings/privacySandbox. During initial testing, people will be -able to use this high-level Privacy Sandbox setting to opt out of FLEDGE. Chrome plans to allow +able to use this high-level Privacy Sandbox setting to opt out of Protected Audience. Chrome plans to allow users to see and manage the list of interest groups that they have been added to across the web sites they have visited. As with the Privacy Sandbox technologies themselves, user settings may evolve with feedback from users, regulators and others. -We'll continue to update the available settings in Chrome as the FLEDGE proposal progresses, [based +We'll continue to update the available settings in Chrome as the Protected Audience proposal progresses, [based on tests and feedback](/docs/privacy-sandbox/cds21-update/#collaborate). -In the future, we plan to offer more granular settings to manage FLEDGE and associated data. +In the future, we plan to offer more granular settings to manage Protected Audience and associated data. API callers can't access group membership when users browse in Incognito mode, and membership is removed when users clear their site data. @@ -1256,7 +1261,7 @@ removed when users clear their site data. [Privacy Sandbox Developer Support repo](https://github.com/GoogleChromeLabs/privacy-sandbox-dev-support). - **FLEDGE mailing list**: [fledge-api-announce](https://groups.google.com/u/1/a/chromium.org/g/fledge-api-announce) provides announcements and updates about the API. -- [Join the scheduled calls for FLEDGE](https://github.com/WICG/turtledove/issues/88) (every +- [Join the scheduled calls for Protected Audience](https://github.com/WICG/turtledove/issues/88) (every second week). Everyone is welcome to join—to participate, first make sure to [join the WICG](https://www.w3.org/community/wicg/). You can actively participate or just listen in! - Use the Privacy Sandbox [feedback form](/docs/privacy-sandbox/feedback/#feedback-form) @@ -1266,12 +1271,12 @@ to share feedback privately with the Chrome team outside of public forums. To ask a question about **your implementation**, about the **demo**, or about the **documentation**: * [Open a new issue](https://github.com/GoogleChromeLabs/privacy-sandbox-dev-support/issues/new/choose) -on the privacy-sandbox-dev-support repository. Make sure to select the issue template for FLEDGE. +on the privacy-sandbox-dev-support repository. Make sure to select the issue template for Protected Audience. * Raise an issue on the [demo code repo on GitHub](https://github.com/JackJey/fledge-demo). * For more general questions about how to meet your **use cases** with the API, [file an issue on the proposal repository](https://github.com/WICG/turtledove/issues/new). -For bugs and issues with the implementation of the FLEDGE API in Chrome: +For bugs and issues with the implementation of the Protected Audience API in Chrome: * [View existing issues](https://bugs.chromium.org/p/chromium/issues/list?q=component:Blink%3EInterestGroups) reported for the API. * Raise a new issue at [crbug.com/new](https://crbug.com/new). @@ -1289,11 +1294,11 @@ reported for the API. ## Find out more -- [The FLEDGE API](/docs/privacy-sandbox/fledge): less technical overview of the proposal. -- [FLEDGE demo](https://fledge-demo.glitch.me): walkthrough of a basic FLEDGE deployment. -- [The FLEDGE demo video](https://www.youtube.com/watch?v=znDD0gkdJyM&list=PLNYkxOF6rcICntazGfSVKSj5EwuR9w5Nv): -explains the demo code, and shows how to use Chrome DevTools for FLEDGE debugging. -- [FLEDGE API technical explainer](https://github.com/WICG/turtledove/blob/master/FLEDGE.md) +- [The Protected Audience API](/docs/privacy-sandbox/protected-audience): less technical overview of the proposal. +- [Protected Audience demo](https://protected-audience-demo.web.app/): walkthrough of a basic Protected Audience deployment. +- [The Protected Audience demo video](https://www.youtube.com/watch?v=znDD0gkdJyM&list=PLNYkxOF6rcICntazGfSVKSj5EwuR9w5Nv): +explains the demo code, and shows how to use Chrome DevTools for Protected Audience debugging. +- [Protected Audience API technical explainer](https://github.com/WICG/turtledove/blob/master/FLEDGE.md) - [Digging into the Privacy Sandbox](https://web.dev/digging-into-the-privacy-sandbox) - [Intent to prototype](https://groups.google.com/a/chromium.org/g/blink-dev/c/w9hm8eQCmNI) diff --git a/site/en/docs/privacy-sandbox/attribution-reporting/index.md b/site/en/docs/privacy-sandbox/attribution-reporting/index.md index 206b21467..3a2bcdd53 100644 --- a/site/en/docs/privacy-sandbox/attribution-reporting/index.md +++ b/site/en/docs/privacy-sandbox/attribution-reporting/index.md @@ -180,7 +180,7 @@ Other features proposed for this API include: In a future without third-party cookies, this API would be combined with other privacy-preserving ads APIs to cover end-to-end use cases: -- Remarketing: see [Protected Audience API](/docs/privacy-sandbox/fledge/) +- Remarketing: see [Protected Audience API](/docs/privacy-sandbox/protected-audience/) - Interest-based ad selection: see [Topics](/docs/privacy-sandbox/topics/) {% endAside %} diff --git a/site/en/docs/privacy-sandbox/cds21-update/index.md b/site/en/docs/privacy-sandbox/cds21-update/index.md index 97140c16f..b7116764d 100644 --- a/site/en/docs/privacy-sandbox/cds21-update/index.md +++ b/site/en/docs/privacy-sandbox/cds21-update/index.md @@ -131,7 +131,7 @@ There have also been more than half a dozen other proposals offered by other companies, in the same solution space. Through continued collaboration, we hope to define a path forward. -At the same time, we're starting [developer testing](/docs/privacy-sandbox/fledge/) for the +At the same time, we're starting [developer testing](/docs/privacy-sandbox/protected-audience/) for the initial version of the Protected Audience API behind a flag in Chrome so developers can get their hands on it. diff --git a/site/en/docs/privacy-sandbox/chrome-testing/index.md b/site/en/docs/privacy-sandbox/chrome-testing/index.md index 668df0c89..e85999993 100644 --- a/site/en/docs/privacy-sandbox/chrome-testing/index.md +++ b/site/en/docs/privacy-sandbox/chrome-testing/index.md @@ -38,7 +38,7 @@ as we progress in Q3 2023. The current proposals are as follows. Ad techs will be able to receive experiment labels for a portion of Chrome traffic. An ad tech can choose to coordinate with other ad techs, for example, -to run [Protected Audience](/docs/privacy-sandbox/fledge/) auctions without +to run [Protected Audience](/docs/privacy-sandbox/protected-audience/) auctions without third-party cookies for a consistent experiment group. Ad techs can also use these labels for their own independent experiments and testing. diff --git a/site/en/docs/privacy-sandbox/feedback/report-2023-q1.md b/site/en/docs/privacy-sandbox/feedback/report-2023-q1.md index 726f8331d..886035151 100644 --- a/site/en/docs/privacy-sandbox/feedback/report-2023-q1.md +++ b/site/en/docs/privacy-sandbox/feedback/report-2023-q1.md @@ -330,7 +330,7 @@ requests. Clarification on timelines for testing and implementation for FLEDGE features such as Fenced Frame enforcement, K-Anonymity, and so forth. We have shared a blog post on various scoped FLEDGE features and when they will +href="https://developer.chrome.com/docs/privacy-sandbox/protected-audience-api/feature-status/">shared a blog post on various scoped FLEDGE features and when they will be supported. We welcome additional feedback on the announcement as we continue to develop FLEDGE. @@ -338,7 +338,7 @@ we continue to develop FLEDGE. Product rendering restrictions Request to loosen Ads Composed of Multiple Pieces restrictions for FLEDGE Fenced Frames As we announced in February, usage of Fenced Frames will remain optional until at +href="https://developer.chrome.com/docs/privacy-sandbox/protected-audience-api/feature-status/">announced in February, usage of Fenced Frames will remain optional until at least 2026, and iframes behavior will be supported by urn-iframes. We welcome further discussion on this topic. @@ -495,7 +495,7 @@ additional feedback here. Interest in keeping certain data such as highestScoringOtherBid available even after third-party cookie deprecation As we shared in the February +href="/docs/privacy-sandbox/protected-audience-api/feature-status/">February blog post, event-level auction win reporting will be supported until "at least 2026." We do not have further details to share at the moment, but we welcome additional feedback on why it is important to diff --git a/site/en/docs/privacy-sandbox/fenced-frame/index.md b/site/en/docs/privacy-sandbox/fenced-frame/index.md index 69f50187f..b65ef0999 100644 --- a/site/en/docs/privacy-sandbox/fenced-frame/index.md +++ b/site/en/docs/privacy-sandbox/fenced-frame/index.md @@ -71,15 +71,15 @@ which suggests top-level sites should partition data. Many Privacy Sandbox proposals aim to satisfy cross-site use cases without third-party cookies or other tracking mechanisms. For example: -* [Protected Audience API](/docs/privacy-sandbox/fledge/) allows for interest-based ad serving +* [Protected Audience API](/docs/privacy-sandbox/protected-audience/) allows for interest-based ad serving in a privacy-preserving manner. * [Shared Storage](https://github.com/pythagoraskitty/shared-storage) allows access to unpartitioned cross-site data in a secure environment. Let's consider how fenced frames could work with the -[Protected Audience API](/docs/privacy-sandbox/fledge/) proposal. With the Protected Audience API, a user's interests +[Protected Audience API](/docs/privacy-sandbox/protected-audience/) proposal. With the Protected Audience API, a user's interests are registered on an advertiser's site in [interest -groups](/docs/privacy-sandbox/fledge/#interest-group-detail), along with ads that +groups](/docs/privacy-sandbox/protected-audience/#interest-group-detail), along with ads that may be of interest to the user. Then, on a separate site (known as a "publisher"), the ads registered in relevant interest groups are auctioned and the winning ad is displayed in a fenced frame. diff --git a/site/en/docs/privacy-sandbox/overview/index.md b/site/en/docs/privacy-sandbox/overview/index.md index 60bce47b1..a4d8b1a05 100644 --- a/site/en/docs/privacy-sandbox/overview/index.md +++ b/site/en/docs/privacy-sandbox/overview/index.md @@ -81,7 +81,7 @@ Several key proposals are listed below. * [**Topics API**](/docs/privacy-sandbox/topics): Enable interest-based advertising without use of third-party cookies or tracking user behavior across sites. -* [**Protected Audience API**](/docs/privacy-sandbox/fledge): Ad selection to serve remarketing +* [**Protected Audience API**](/docs/privacy-sandbox/protected-audience): Ad selection to serve remarketing and custom audience use cases, designed so that it cannot be used by third parties to track user browsing behavior across sites. The Protected Audience API is the first experiment to be implemented in Chromium from the diff --git a/site/en/docs/privacy-sandbox/private-aggregation/index.md b/site/en/docs/privacy-sandbox/private-aggregation/index.md index 46caafeee..fe12c9388 100644 --- a/site/en/docs/privacy-sandbox/private-aggregation/index.md +++ b/site/en/docs/privacy-sandbox/private-aggregation/index.md @@ -24,7 +24,7 @@ privacy-preserving manner. ## What is the Private Aggregation API The Private Aggregation API allows developers to generate aggregate data reports -with data from the [Protected Audience API](/docs/privacy-sandbox/fledge/) and +with data from the [Protected Audience API](/docs/privacy-sandbox/protected-audience/) and cross-site data from [Shared Storage](/docs/privacy-sandbox/shared-storage/). This API currently provides one operation, `sendHistogramReport()`, but more may be @@ -78,7 +78,7 @@ A demo of Private Aggregation API for the Protected Audience API will be publish ## Use cases -Private Aggregation is a general purpose API for cross-site measurement, and it’s available to be used in [Shared Storage](/docs/privacy-sandbox/shared-storage/) and [Protected Audience API](/docs/privacy-sandbox/fledge/) worklets. The first step is to decide specifically what information you want to collect. Those data points are the basis of your aggregation keys. +Private Aggregation is a general purpose API for cross-site measurement, and it’s available to be used in [Shared Storage](/docs/privacy-sandbox/shared-storage/) and [Protected Audience API](/docs/privacy-sandbox/protected-audience/) worklets. The first step is to decide specifically what information you want to collect. Those data points are the basis of your aggregation keys. ### With Shared storage diff --git a/site/en/docs/privacy-sandbox/trust-tokens/index.md b/site/en/docs/privacy-sandbox/private-state-tokens/index.md similarity index 99% rename from site/en/docs/privacy-sandbox/trust-tokens/index.md rename to site/en/docs/privacy-sandbox/private-state-tokens/index.md index 9946a2f25..0d3763fad 100644 --- a/site/en/docs/privacy-sandbox/trust-tokens/index.md +++ b/site/en/docs/privacy-sandbox/private-state-tokens/index.md @@ -111,7 +111,7 @@ For more detail about the JavaScript calls in this example, see [Sample API usag ## Is tooling available for Privacy State Tokens? -Chrome DevTools turns on inspection from the Network and Application tabs. Read more about this [DevTools integration](/blog/new-in-devtools-89/#trust-token) and about [Private State Tokens](/docs/privacy-sandbox/trust-tokens/). +Chrome DevTools turns on inspection from the Network and Application tabs. Read more about this [DevTools integration](/blog/new-in-devtools-89/#trust-token) and about [Private State Tokens](/docs/privacy-sandbox/private-state-tokens/). ## How do publishers handle tokens from multiple trusted issuers? diff --git a/site/en/docs/privacy-sandbox/proposal-lifecycle/index.md b/site/en/docs/privacy-sandbox/proposal-lifecycle/index.md index 1cfca43f5..5bacc15bf 100644 --- a/site/en/docs/privacy-sandbox/proposal-lifecycle/index.md +++ b/site/en/docs/privacy-sandbox/proposal-lifecycle/index.md @@ -92,7 +92,7 @@ There have also been more than half a dozen other proposals offered by other companies, in the same solution space. Through continued collaboration, we hope to define a path forward. -[Testing for Protected Audience](/docs/privacy-sandbox/fledge-experiment/) and +[Testing for Protected Audience](/docs/privacy-sandbox/protected-audience-experiment/) and other APIs is available behind a Chrome flag, so developers can access them early. diff --git a/site/en/docs/privacy-sandbox/fledge-api/ad-auction/index.md b/site/en/docs/privacy-sandbox/protected-audience-api/ad-auction/index.md similarity index 97% rename from site/en/docs/privacy-sandbox/fledge-api/ad-auction/index.md rename to site/en/docs/privacy-sandbox/protected-audience-api/ad-auction/index.md index 17f705b81..6ff3a014c 100644 --- a/site/en/docs/privacy-sandbox/fledge-api/ad-auction/index.md +++ b/site/en/docs/privacy-sandbox/protected-audience-api/ad-auction/index.md @@ -15,11 +15,11 @@ authors: In this article, you'll find a technical reference for the ad auction, as used in the current iteration of the experimental Protected Audience API. -Read the [developer guide](/docs/privacy-sandbox/fledge-api) for the full life +Read the [developer guide](/docs/privacy-sandbox/protected-audience-api) for the full life cycle of Protected Audience API, and refer to the Protected Audience API explainer for an in-depth proposal of how [sellers run on-device auctions](https://github.com/WICG/turtledove/blob/main/FLEDGE.md#2-sellers-run-on-device-auctions). -Not a developer? Refer to the [Protected Audience API overview](/docs/privacy-sandbox/fledge). +Not a developer? Refer to the [Protected Audience API overview](/docs/privacy-sandbox/protected-audience). ## What is the Protected Audience API ad auction? @@ -54,11 +54,11 @@ title="View a larger version of image." target="_blank">view a larger version {% YouTube @@ -184,7 +184,7 @@ Read more about feature support and constraints in the ### Interest group permissions The default for the current implementation of the Protected Audience API is to allow calling -[`joinAdInterestGroup()`](/docs/privacy-sandbox/fledge-api/interest-groups) +[`joinAdInterestGroup()`](/docs/privacy-sandbox/protected-audience-api/interest-groups) from anywhere in a page, even from cross-domain iframes. In the future, once site owners have had time to update their cross-domain @@ -284,13 +284,13 @@ on the user's device, and is not shared with the browser vendor or anyone else. * **Read the Protected Audience API explainer**: [Browsers Record Interest Groups](https://github.com/WICG/turtledove/blob/main/FLEDGE.md#1-browsers-record-interest-groups). * **Read the API guide**: buyers and DSPs, learn how to - [`joinAdInterestGroup()`](/docs/privacy-sandbox/fledge-api/interest-groups) and generate bids. + [`joinAdInterestGroup()`](/docs/privacy-sandbox/protected-audience-api/interest-groups) and generate bids. {% Aside %} The origin of the calling context for `joinAdInterestGroup()` must match the interest group owner's origin. -[`joinAdInterestGroup()`](/docs/privacy-sandbox/fledge-api/interest-groups) must be called from an iframe owned by the interest group owner (for example, from a DSP). If the origin of the current document is the same as the interest group owner (for example, a website with its own interest groups), no iframe is needed. +[`joinAdInterestGroup()`](/docs/privacy-sandbox/protected-audience-api/interest-groups) must be called from an iframe owned by the interest group owner (for example, from a DSP). If the origin of the current document is the same as the interest group owner (for example, a website with its own interest groups), no iframe is needed. {% endAside %} #### Specify ads for an interest group @@ -310,7 +310,7 @@ optionally, arbitrary metadata that can be used at bidding time. For example: `generateBid()` is called for each interest group that the browser is a member of—if the interest group's owner is invited to bid. -Read the [`generatedBid()` developer documentation](/docs/privacy-sandbox/fledge-api/interest-groups#generatebid). +Read the [`generatedBid()` developer documentation](/docs/privacy-sandbox/protected-audience-api/interest-groups#generatebid). ### 3. The user visits a site that sells ad space @@ -340,7 +340,7 @@ along with data from ad-space buyers and the sellers from the * **Read the Protected Audience API explainer**: [Sellers Run On-Device Auctions](https://github.com/WICG/turtledove/blob/main/FLEDGE.md#2-sellers-run-on-device-auctions) * **Read the API guide**: sellers can learn more about - [`runAdAuction()`](/docs/privacy-sandbox/fledge-api/ad-auction/) and the [ad auction latency best practices](/docs/privacy-sandbox/fledge-api/latency). + [`runAdAuction()`](/docs/privacy-sandbox/protected-audience-api/ad-auction/) and the [ad auction latency best practices](/docs/privacy-sandbox/protected-audience-api/latency). ### 5. The seller and participating buyers request real-time data from the Key/Value service @@ -353,7 +353,7 @@ along with data from ad-space buyers and the sellers from the During an ad auction, the seller can request real-time data about specific ad creatives by making a request to their [Key/Value service](#keyvalue-service). The seller can request this information during -[`runAdAuction()`](/docs/privacy-sandbox/fledge-api/ad-auction/) by the `trustedScoringSignalsUrl` property, +[`runAdAuction()`](/docs/privacy-sandbox/protected-audience-api/ad-auction/) by the `trustedScoringSignalsUrl` property, along with the keys from the `renderUrl` properties of all entries in the `ads` and `adComponents` fields of all interest groups in the auction. @@ -394,7 +394,7 @@ owner. Learn more in [Bring Your Own Server](https://github.com/WICG/turtledove/ %} -The promise returned by [runAdAuction()](/docs/privacy-sandbox/fledge-api/ad-auction/) resolves to a fenced frame config object (`FencedFrameConfig`) when the`resolveToConfig` flag is set to `true` in the auction config. The frame config is used by a fenced frame to navigate the frame to the winning ad, but the URL of the ad is not visible to the frame embedder. +The promise returned by [runAdAuction()](/docs/privacy-sandbox/protected-audience-api/ad-auction/) resolves to a fenced frame config object (`FencedFrameConfig`) when the`resolveToConfig` flag is set to `true` in the auction config. The frame config is used by a fenced frame to navigate the frame to the winning ad, but the URL of the ad is not visible to the frame embedder. {% Aside ‘important’ %} The `FencedFrameConfig` object is returned only when the flag `resolveToConfig` is set to `true` in the auction config. If the flag is not set, or is `false`, an opaque [URN](https://en.wikipedia.org/wiki/Uniform_Resource_Name) will be returned which can only be rendered in an iframe. @@ -415,7 +415,7 @@ call the `sendReportTo()` function. This takes a single argument: a string representing a URL that is fetched after the auction completes, which encodes event-level information to be reported. -* **Read the API guide**: learn about [seller and buyer reporting](/docs/privacy-sandbox/fledge-api/reports) +* **Read the API guide**: learn about [seller and buyer reporting](/docs/privacy-sandbox/protected-audience-api/reports) ### 8. An ad click is reported @@ -570,7 +570,7 @@ to share feedback privately with the Chrome team outside of public forums. #### Opt-out {: #opt-out} Want to opt-out of the Protected Audience API? Learn how to -[block access to the Protected Audience API](/docs/privacy-sandbox/fledge-api/opt-out/), +[block access to the Protected Audience API](/docs/privacy-sandbox/protected-audience-api/opt-out/), as a site owner or an individual user. ### Get updates diff --git a/site/en/docs/privacy-sandbox/fledge-api/interest-groups/index.md b/site/en/docs/privacy-sandbox/protected-audience-api/interest-groups/index.md similarity index 98% rename from site/en/docs/privacy-sandbox/fledge-api/interest-groups/index.md rename to site/en/docs/privacy-sandbox/protected-audience-api/interest-groups/index.md index 3171a9d22..9e7af9f80 100644 --- a/site/en/docs/privacy-sandbox/fledge-api/interest-groups/index.md +++ b/site/en/docs/privacy-sandbox/protected-audience-api/interest-groups/index.md @@ -18,19 +18,19 @@ authors: In this article, you'll find a technical reference for interest groups, as used in the current iteration of the experimental Protected Audience API. -Read the [developer guide](/docs/privacy-sandbox/fledge-api) for the full life +Read the [developer guide](/docs/privacy-sandbox/protected-audience-api) for the full life cycle of the Protected Audience API, and refer to the Protected Audience API explainer for an in-depth proposal of how [browsers record interest groups](https://github.com/WICG/turtledove/blob/main/FLEDGE.md#1-browsers-record-interest-groups). Not a developer? Refer to the -[Protected Audience API overview](/docs/privacy-sandbox/fledge). +[Protected Audience API overview](/docs/privacy-sandbox/protected-audience). ## Protected Audience API interest groups A Protected Audience API interest group represents a group of people with a common interest, corresponding to a [remarketing](/docs/privacy-sandbox/glossary/#remarketing) list. Every Protected Audience API interest group has an -[owner](/docs/privacy-sandbox/fledge#interest-group-types). +[owner](/docs/privacy-sandbox/protected-audience#interest-group-types). Interest group owners act as the buyer in the Protected Audience API ad auction. Interest group membership is stored by the browser, on the user's device, and is not shared @@ -282,7 +282,7 @@ For example: The interest group owner's script at `biddingLogicUrl` must include a `generateBid()` function. -When a [seller calls `navigator.runAdAuction()`](/docs/privacy-sandbox/fledge-api/ad-auction), +When a [seller calls `navigator.runAdAuction()`](/docs/privacy-sandbox/protected-audience-api/ad-auction), the `generateBid()` function is called once for each candidate ad. In other words, it's called for each interest group that the browser is a member of—if the interest group's owner is invited to bid. @@ -309,7 +309,7 @@ function. The script at `biddingLogicUrl` provided by a buyer must include a `generateBid()` function. This function is called once for each candidate ad. -[`runAdAuction()`](/docs/privacy-sandbox/fledge-api/ad-auction/) +[`runAdAuction()`](/docs/privacy-sandbox/protected-audience-api/ad-auction/) individually checks each ad, along with its associated bid and metadata, then assigns the ad a numerical desirability score. diff --git a/site/en/docs/privacy-sandbox/fledge-api/latency/index.md b/site/en/docs/privacy-sandbox/protected-audience-api/latency/index.md similarity index 100% rename from site/en/docs/privacy-sandbox/fledge-api/latency/index.md rename to site/en/docs/privacy-sandbox/protected-audience-api/latency/index.md diff --git a/site/en/docs/privacy-sandbox/fledge-api/opt-out/index.md b/site/en/docs/privacy-sandbox/protected-audience-api/opt-out/index.md similarity index 100% rename from site/en/docs/privacy-sandbox/fledge-api/opt-out/index.md rename to site/en/docs/privacy-sandbox/protected-audience-api/opt-out/index.md diff --git a/site/en/docs/privacy-sandbox/fledge-api/reports/index.md b/site/en/docs/privacy-sandbox/protected-audience-api/reports/index.md similarity index 97% rename from site/en/docs/privacy-sandbox/fledge-api/reports/index.md rename to site/en/docs/privacy-sandbox/protected-audience-api/reports/index.md index 1c569717b..088f13863 100644 --- a/site/en/docs/privacy-sandbox/fledge-api/reports/index.md +++ b/site/en/docs/privacy-sandbox/protected-audience-api/reports/index.md @@ -17,11 +17,11 @@ This article is a technical reference for generating reports for Protected Audience API auction wins, as used in the current iteration of the experimental Protected Audience API. -Read the [developer guide](/docs/privacy-sandbox/fledge-api) for the full life +Read the [developer guide](/docs/privacy-sandbox/protected-audience-api) for the full life cycle of the Protected Audience API, and refer to the Protected Audience API explainer for an in-depth proposal of [event-level reporting (temporary)](https://github.com/WICG/turtledove/blob/main/FLEDGE.md#5-event-level-reporting-for-now). -Not a developer? Refer to the [Protected Audience API API overview](/docs/privacy-sandbox/fledge). +Not a developer? Refer to the [Protected Audience API API overview](/docs/privacy-sandbox/protected-audience). ## What does the Protected Audience API report? diff --git a/site/en/docs/privacy-sandbox/fledge-api/troubleshoot/index.md b/site/en/docs/privacy-sandbox/protected-audience-api/troubleshoot/index.md similarity index 87% rename from site/en/docs/privacy-sandbox/fledge-api/troubleshoot/index.md rename to site/en/docs/privacy-sandbox/protected-audience-api/troubleshoot/index.md index 2a601a306..9224cc990 100644 --- a/site/en/docs/privacy-sandbox/fledge-api/troubleshoot/index.md +++ b/site/en/docs/privacy-sandbox/protected-audience-api/troubleshoot/index.md @@ -16,9 +16,9 @@ authors: From Chrome Canary 98.0.4718.0, it's possible to debug the Protected Audience API and Protected Audience API worklets in Chrome DevTools. -Read the [developer guide](/blog/fledge-api) for the full life cycle of the Protected Audience API. +Read the [developer guide](/docs/privacy-sandbox/protected-audience-api/) for the full life cycle of the Protected Audience API. Not a developer? Refer to the -[Protected Audience API overview](/docs/privacy-sandbox/fledge). +[Protected Audience API overview](/docs/privacy-sandbox/protected-audience). ## Protected Audience API worklets {: #debugging } @@ -51,7 +51,7 @@ resume or inspect them more closely as appropriate. From the Application panel in Chrome DevTools, you can observe Protected Audience API interest group and auction events. -If you visit the [Protected Audience API demo shopping site](https://shopping-fledge-demo.glitch.me/advertiser/shopping.html) +If you visit the [Protected Audience API demo advertiser site](https://protected-audience-demo-advertiser.web.app/) in a browser with the Protected Audience API enabled, DevTools will display information about the `join` event.
@@ -62,7 +62,7 @@ in a browser with the Protected Audience API enabled, DevTools will display info
Now, if you visit the -[Protected Audience API demo publisher site](https://publisher-fledge-demo.glitch.me/publisher/index.html?fencedframe) +[Protected Audience API demo publisher site](https://protected-audience-demo-publisher.web.app/) in a browser with the Protected Audience API enabled, DevTools displays information about the `bid` and `win` events. diff --git a/site/en/docs/privacy-sandbox/fledge-experiment/index.md b/site/en/docs/privacy-sandbox/protected-audience-experiment/index.md similarity index 89% rename from site/en/docs/privacy-sandbox/fledge-experiment/index.md rename to site/en/docs/privacy-sandbox/protected-audience-experiment/index.md index 548d45845..fef41838c 100644 --- a/site/en/docs/privacy-sandbox/fledge-experiment/index.md +++ b/site/en/docs/privacy-sandbox/protected-audience-experiment/index.md @@ -16,9 +16,9 @@ authors: ## Learn the essentials * If you're a developer or software engineer, the - [Protected Audience API Developer Guide](/docs/privacy-sandbox/fledge-api/) provides an + [Protected Audience API Developer Guide](/docs/privacy-sandbox/protected-audience-api/) provides an in-depth technical reference for the proposal. -* The [Protected Audience API overview](/docs/privacy-sandbox/fledge) offers a higher level +* The [Protected Audience API overview](/docs/privacy-sandbox/protected-audience) offers a higher level explanation for those who work in advertiser and ad tech, who are new to the Privacy Sandbox. @@ -36,23 +36,23 @@ to learn how to determine if a feature is available before attempting to use it. {% endAside %} 1. Learn how to use the Protected Audience API. - * Review the [Protected Audience API Developer Guide](/docs/privacy-sandbox/fledge-api/). + * Review the [Protected Audience API Developer Guide](/docs/privacy-sandbox/protected-audience-api/). This guide offers a reference for API methods and parameters. * Read about [Protected Audience services](/blog/fledge-service-overview/). For example, the Key/Value service offers real-time information to buyers and sellers during the ad auction. -2. Try the [demo](https://fledge-demo.glitch.me). - * Review the [source code](https://github.com/JackJey/fledge-demo). +2. Try the [demo](https://protected-audience-demo.web.app/). + * Review the [source code](https://github.com/GoogleChromeLabs/protected-audience-demo). * Watch the [Protected Audience demo video](https://www.youtube.com/watch?v=znDD0gkdJyM&list=PLNYkxOF6rcICntazGfSVKSj5EwuR9w5Nv) to learn how the demo code works and how to use Chrome DevTools for FLEDGE debugging. 3. Experiment with the API. - * Sign up for the [origin trial](/docs/privacy-sandbox/fledge-api/#origin-trial) + * Sign up for the [origin trial](/docs/privacy-sandbox/protected-audience-api/#origin-trial) * Try out FLEDGE for a single user by enabling `chrome://flags/#privacy-sandbox-ads-apis` or by running Chrome from the - command line with [Protected Audience feature flags](/docs/privacy-sandbox/fledge-api/#flags). - * [Troubleshoot Protected Audience worklets](/docs/privacy-sandbox/fledge-api/troubleshoot/) with Chrome DevTools. Learn how to debug FLEDGE bidding and auction code. + command line with [Protected Audience feature flags](/docs/privacy-sandbox/protected-audience-api/#flags). + * [Troubleshoot Protected Audience worklets](/docs/privacy-sandbox/protected-audience-api/troubleshoot/) with Chrome DevTools. Learn how to debug FLEDGE bidding and auction code. 4. Review the [Protected Audience status](/docs/privacy-sandbox/status/#fledge) for updates on the implementation of the FLEDGE API. Review the - [pending Protected Audience capabilities](/docs/privacy-sandbox/fledge-api/feature-status/) + [pending Protected Audience capabilities](/docs/privacy-sandbox/protected-audience-api/feature-status/) for more details. The [Protected Audience API explainer](https://github.com/WICG/turtledove/blob/main/FLEDGE.md#summary) diff --git a/site/en/docs/privacy-sandbox/fledge/index.md b/site/en/docs/privacy-sandbox/protected-audience/index.md similarity index 95% rename from site/en/docs/privacy-sandbox/fledge/index.md rename to site/en/docs/privacy-sandbox/protected-audience/index.md index 7162c5759..1959bad2d 100644 --- a/site/en/docs/privacy-sandbox/fledge/index.md +++ b/site/en/docs/privacy-sandbox/protected-audience/index.md @@ -29,9 +29,9 @@ concepts, but doesn't go into much technical detail. * If you work in **advertising or ad tech**, you'll get an overview of [how Protected Audience works](#overview). * If you're a **developer or software engineer**, the - [Protected Audience API Developer Guide](/docs/privacy-sandbox/fledge-api) provides more + [Protected Audience API Developer Guide](/docs/privacy-sandbox/protected-audience-api) provides more in-depth technical detail about the proposal. Read the - [latest status of pending Protected Audience capabilities](/docs/privacy-sandbox/fledge-api/feature-status/). + [latest status of pending Protected Audience capabilities](/docs/privacy-sandbox/protected-audience-api/feature-status/). Refer to the [glossary](/docs/privacy-sandbox/glossary/) for terms used across Protected Audience documentation. At the end of this article, you can learn how to @@ -55,7 +55,7 @@ FLEDGE works. ### Protected Audience API in one minute {: #overview} For a more in-depth overview of the Protected Audience API, read the -[Protected Audience API developer guide](/docs/privacy-sandbox/fledge-api/). +[Protected Audience API developer guide](/docs/privacy-sandbox/protected-audience-api/).
{% Img src="image/hVf1flv5Jdag8OQKYqOcJgWUvtz1/zXKEk8OymLJp6KpOwwbk.png", alt="An overview of each stage of the Protected Audience API lifecycle", @@ -113,7 +113,7 @@ the list provided by the interest group's configuration. The seller can report the auction outcome (`reportResult()`), and buyers can report their wins (`reportWin()`). -Learn about [Protected Audience auction reports](/docs/privacy-sandbox/fledge-api/reports/). +Learn about [Protected Audience auction reports](/docs/privacy-sandbox/protected-audience-api/reports/). ## Why do we need the Protected Audience API? {: #why} @@ -132,8 +132,8 @@ information about what that person is interested in. {% Aside 'caution' %} -Read the [developer guide](/docs/privacy-sandbox/fledge-api/) and -[status of pending Protected Audience capabilities](/docs/privacy-sandbox/fledge-api/feature-status/) +Read the [developer guide](/docs/privacy-sandbox/protected-audience-api/) and +[status of pending Protected Audience capabilities](/docs/privacy-sandbox/protected-audience-api/feature-status/) to understand what features are currently available for testing in Chrome. Protected Audience features will be added over time, and we'll regularly update a list of @@ -144,11 +144,11 @@ currently in an [origin trial](/docs/privacy-sandbox/unified-origin-trial/). ## How can I try the Protected Audience API? {: #try-fledge} -* The [Protected Audience API developer guide](/docs/privacy-sandbox/fledge-api) describes +* The [Protected Audience API developer guide](/docs/privacy-sandbox/protected-audience-api) describes how to use the API, how to test locally and how to participate in the [relevence and measurement origin trial](/docs/privacy-sandbox/unified-origin-trial/). -* [fledge-demo.glitch.me](https://fledge-demo.glitch.me/) provides a +* [protected-audience-demo.web.app](https://protected-audience-demo.web.app/) provides a walkthrough of a basic Protected Audience deployment across advertiser and publisher sites. The Protected Audience demo video explains how this code works and previews how to use Chrome DevTools for debugging. @@ -181,7 +181,7 @@ and membership is removed when users clear their site data. ### Can I opt out of the Protected Audience API? {: #opt-out} -Learn how you can [block access to the Protected Audience API](/docs/privacy-sandbox/fledge-api/opt-out), +Learn how you can [block access to the Protected Audience API](/docs/privacy-sandbox/protected-audience-api/opt-out), either as a site owner or as an individual user. ## Key concepts @@ -516,14 +516,14 @@ navigator.runAdAuction(auctionConfig); ## Find out more For a more in-depth overview of the Protected Audience API, read the -[Protected Audience API developer guide](/docs/privacy-sandbox/fledge-api/). +[Protected Audience API developer guide](/docs/privacy-sandbox/protected-audience-api/). ### Developers If you're ready to start working with the Protected Audience API, read -[experiment and participate](/docs/privacy-sandbox/fledge-experiment/). +[experiment and participate](/docs/privacy-sandbox/protected-audience-experiment/). -We've written an [API developer guide](/docs/privacy-sandbox/fledge-api) and built a [Protected Audience API demo](https://fledge-demo.glitch.me), which offers a walkthrough of a basic Protected Audience API deployment. The [Protected Audience API demo video](https://www.youtube.com/watch?v=znDD0gkdJyM&list=PLNYkxOF6rcICntazGfSVKSj5EwuR9w5Nv) explains how the demo code works, and shows how to use Chrome DevTools for Protected Audience API debugging. +We've written an [API developer guide](/docs/privacy-sandbox/protected-audience-api) and built a [Protected Audience API demo](https://protected-audience-demo.web.app/), which offers a walkthrough of a basic Protected Audience API deployment. The [Protected Audience API demo video](https://www.youtube.com/watch?v=znDD0gkdJyM&list=PLNYkxOF6rcICntazGfSVKSj5EwuR9w5Nv) explains how the demo code works, and shows how to use Chrome DevTools for Protected Audience API debugging. ## Engage and share feedback diff --git a/site/en/docs/privacy-sandbox/third-party-cookie-phase-out/index.md b/site/en/docs/privacy-sandbox/third-party-cookie-phase-out/index.md index 97fb93ebd..b67a4cecc 100644 --- a/site/en/docs/privacy-sandbox/third-party-cookie-phase-out/index.md +++ b/site/en/docs/privacy-sandbox/third-party-cookie-phase-out/index.md @@ -156,7 +156,7 @@ If neither meets your needs, there is a wider set of Privacy Sandbox proposals f [Federated Credential Management (FedCM)](/docs/privacy-sandbox/fedcm/) enables privacy-preserving approach to federated identity services so users can log into sites without sharing their personal information with a third-party service or website. -[Private State Tokens](/docs/privacy-sandbox/trust-tokens/) convey a limited amount of information from one browsing context to another (for example, across sites) to help combat fraud, without passive tracking. +[Private State Tokens](/docs/privacy-sandbox/private-state-tokens/) convey a limited amount of information from one browsing context to another (for example, across sites) to help combat fraud, without passive tracking. A suite of APIs is available to cover [ad relevance](/docs/privacy-sandbox/#show-relevant-content) and [measurement](/docs/privacy-sandbox/#measure-digital-ads) use cases such as interest-based advertising, on-device auctions for custom audiences, cross-site content selection, ad conversion measurement and attribution, and more. diff --git a/site/en/docs/privacy-sandbox/topics/index.md b/site/en/docs/privacy-sandbox/topics/index.md index 600b3d0d5..655a40d3c 100644 --- a/site/en/docs/privacy-sandbox/topics/index.md +++ b/site/en/docs/privacy-sandbox/topics/index.md @@ -30,7 +30,7 @@ You can also run the Topics [colab](/docs/privacy-sandbox/topics/colab/) to try ### Test Topics in an origin trial {: #origin-trial} -A Privacy Sandbox Relevance and Measurement [origin trial](/docs/privacy-sandbox/unified-origin-trial/) has been made available in Chrome Beta 101.0.4951.26 and above on desktop for the Topics, [Protected Audience](/docs/privacy-sandbox/fledge/), and [Attribution Reporting](/docs/privacy-sandbox/attribution-reporting/) APIs. +A Privacy Sandbox Relevance and Measurement [origin trial](/docs/privacy-sandbox/unified-origin-trial/) has been made available in Chrome Beta 101.0.4951.26 and above on desktop for the Topics, [Protected Audience](/docs/privacy-sandbox/protected-audience/), and [Attribution Reporting](/docs/privacy-sandbox/attribution-reporting/) APIs. #### Provide an origin trial token diff --git a/site/en/docs/privacy-sandbox/unified-origin-trial/index.md b/site/en/docs/privacy-sandbox/unified-origin-trial/index.md index 2dc7d8782..2e336e8d6 100644 --- a/site/en/docs/privacy-sandbox/unified-origin-trial/index.md +++ b/site/en/docs/privacy-sandbox/unified-origin-trial/index.md @@ -143,7 +143,7 @@ Check out previous updates on the origin trial. {% endDetailsSummary %} ##### Private Aggregation 1% ramp-up in Stable -[Private Aggregation API](/docs/privacy-sandbox/private-aggregation/) origin trial will be available at 1% of Chrome Stable unified experiment traffic from Monday April 17. The [sendHistogramReport()](/docs/privacy-sandbox/private-aggregation/#sendhistogramreport) function of Private Aggregation is available to be used in [Protected Audience API](/docs/privacy-sandbox/fledge/) and [Shared Storage](/docs/privacy-sandbox/shared-storage/) worklets. +[Private Aggregation API](/docs/privacy-sandbox/private-aggregation/) origin trial will be available at 1% of Chrome Stable unified experiment traffic from Monday April 17. The [sendHistogramReport()](/docs/privacy-sandbox/private-aggregation/#sendhistogramreport) function of Private Aggregation is available to be used in [Protected Audience API](/docs/privacy-sandbox/protected-audience/) and [Shared Storage](/docs/privacy-sandbox/shared-storage/) worklets. The traffic allocation will look like the following starting on Monday, April 17: @@ -440,7 +440,7 @@ Also, Shared Storage’s URL Selection API origin trial will be increasing to 5% - Protected Audience API + Protected Audience API Available in Stable, temporarily decreasing to 4% from January 26th 2023. @@ -490,7 +490,7 @@ on November 9th. - Protected Audience API + Protected Audience API Available in Stable, increasing to 5% from November 9th. @@ -539,7 +539,7 @@ Protected Audience API and Fenced Frames will increase from November 9th. Read m - Protected Audience API + Protected Audience API Available in Stable, increasing to 5% from November 9th. @@ -598,10 +598,10 @@ guide for the origin trial. Protected Audience API +href="/docs/privacy-sandbox/protected-audience/">Protected Audience API Developer +href="/docs/privacy-sandbox/protected-audience-experiment/">Developer guide for the origin trial. @@ -671,10 +671,10 @@ guide for the origin trial. Protected Audience API +href="/docs/privacy-sandbox/protected-audience-experiment/">Protected Audience API Developer +href="/docs/privacy-sandbox/protected-audience-experiment/">Developer guide for the origin trial. @@ -729,7 +729,7 @@ an individual origin trial. Protected Audience API +href="/docs/privacy-sandbox/protected-audience-experiment/">Protected Audience API Individual Intent @@ -971,7 +971,7 @@ in the origin trial over that period. For specific guidance on local developer testing, see: - [Topics](/docs/privacy-sandbox/topics-experiment/) -- [Protected Audience API](/docs/privacy-sandbox/fledge-experiment/) +- [Protected Audience API](/docs/privacy-sandbox/protected-audience-experiment/) - [Attribution Reporting](/docs/privacy-sandbox/attribution-reporting-experiment/) diff --git a/site/en/docs/privacy-sandbox/videos/index.md b/site/en/docs/privacy-sandbox/videos/index.md index f5bc41415..4f8ec9f95 100644 --- a/site/en/docs/privacy-sandbox/videos/index.md +++ b/site/en/docs/privacy-sandbox/videos/index.md @@ -77,13 +77,13 @@ At Google I/O 2022, [Rowan Merewood](/authors/rowan_m/) from the Chrome team spo %} Refer to the documentation for the latest details: Topics API, -Protected Audience API, +Protected Audience API, Attribution Reporting {% endColumn %} {% Column %} February 2023. Run time: 11:08 -[Danny Rojas](/authors/darojas/) of the Products Partnerships team provides a high-level view of the Privacy Sandbox ads APIs. He briefly describes the [Topics API](/docs/privacy-sandbox/topics/), the [Protected Audience API](/docs/privacy-sandbox/fledge/) (formerly FLEDGE), and [Attribution Reporting](/docs/privacy-sandbox/attribution-reporting/), along with some common use cases. +[Danny Rojas](/authors/darojas/) of the Products Partnerships team provides a high-level view of the Privacy Sandbox ads APIs. He briefly describes the [Topics API](/docs/privacy-sandbox/topics/), the [Protected Audience API](/docs/privacy-sandbox/protected-audience/) (formerly FLEDGE), and [Attribution Reporting](/docs/privacy-sandbox/attribution-reporting/), along with some common use cases. {% endColumn %} {% endColumns %} @@ -191,7 +191,7 @@ The Chrome team presents a high-level overview of the Attribution Reporting API {% YouTube id='HkvmYKqnytw' %} -Refer to the documentation for the latest details: Protected Audience API. +Refer to the documentation for the latest details: Protected Audience API. {% endColumn %} {% Column %} Sep 8, 2021. Run time: 5:51 @@ -205,7 +205,7 @@ Refer to the documentation for the latest details: Protected Audience API. +Refer to the documentation for the latest details: Protected Audience API. {% endColumn %} {% Column %} @@ -323,7 +323,7 @@ Origin trials are a way to test a new or experimental web platform feature. A th id='bXB1Iwq6Eq4' %} Refer to the documentation for the latest details: -Private State Tokens +Private State Tokens {% endColumn %} {% Column %} Jul 28, 2021. Run time: 8:17 diff --git a/site/en/privacy-sandbox/index.njk b/site/en/privacy-sandbox/index.njk index 43fde7980..4527a56ac 100644 --- a/site/en/privacy-sandbox/index.njk +++ b/site/en/privacy-sandbox/index.njk @@ -33,13 +33,13 @@ sections: - url: /docs/privacy-sandbox/topics-experiment - url: /docs/privacy-sandbox/topics/latest/ show_relevant_content_fledge: - - url: /docs/privacy-sandbox/fledge + - url: /docs/privacy-sandbox/protected-audience title: Overview description: A proposal for on-device auctions to serve custom audiences. Choose relevant ads from websites the user has previously visited without third-party tracking. - url: /docs/privacy-sandbox/fledge-best-practices title: Best practices description: Improve FLEDGE auction latency with these best practices. - - url: /docs/privacy-sandbox/fledge-experiment + - url: /docs/privacy-sandbox/protected-audience-experiment title: Experiment and participate description: Quick guide to implement and test the API. Play with demo code and share your feedback. measure_ads: diff --git a/site/ja/privacy-sandbox/index.njk b/site/ja/privacy-sandbox/index.njk index b697791b8..5ebe9826a 100644 --- a/site/ja/privacy-sandbox/index.njk +++ b/site/ja/privacy-sandbox/index.njk @@ -23,9 +23,9 @@ sections: - url: /docs/privacy-sandbox/topics - url: /docs/privacy-sandbox/topics-experiment show_relevant_content_fledge: - - url: /docs/privacy-sandbox/fledge - - url: /docs/privacy-sandbox/fledge-best-practices - - url: /docs/privacy-sandbox/fledge-experiment + - url: /docs/privacy-sandbox/protected-audience + - url: /docs/privacy-sandbox/protected-audience-best-practices + - url: /docs/privacy-sandbox/protected-audience-experiment measure_ads: - url: /docs/privacy-sandbox/attribution-reporting - url: /docs/privacy-sandbox/attribution-reporting/system-overview From 7581a8a72644c8a3f2bc4e016cc58a85d04b9c83 Mon Sep 17 00:00:00 2001 From: Joe Medley Date: Fri, 25 Aug 2023 11:56:15 -0700 Subject: [PATCH 720/982] Add a more reasonable link for colors. (#7176) (We should define these in the documentation instead of sending people to source code. I can't prioritize the time right now. --- site/en/docs/extensions/mv3/themes/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/en/docs/extensions/mv3/themes/index.md b/site/en/docs/extensions/mv3/themes/index.md index 604215a9b..16aa99eaa 100644 --- a/site/en/docs/extensions/mv3/themes/index.md +++ b/site/en/docs/extensions/mv3/themes/index.md @@ -93,7 +93,7 @@ You can alternatively use `-1.0` for any of the HSL values to specify _no change [1]: /docs/extensions/mv3/linux_hosting/#packaging [2]: https://chrome.google.com/webstore/category/themes [3]: /docs/extensions/mv3/manifest/ -[4]: https://source.chromium.org/search/?q=file:chrome/browser/themes%20symbol:kOverwritableColorTable +[4]: https://source.chromium.org/chromium/chromium/src/+/main:chrome/browser/themes/browser_theme_pack.cc;l=222 [5]: https://source.chromium.org/search/?q=file:chrome/browser/themes%20symbol:kPersistingImages$ [6]: https://source.chromium.org/search/?q=file:chrome/browser/themes%20symbol:kDisplayProperties$ [7]: https://source.chromium.org/search/?q=file:chrome/browser/themes%20symbol:kTintTable$ From 95083c0e42377c6e4ace73ad41f190d047fe6976 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Beaufort?= Date: Mon, 28 Aug 2023 11:30:15 +0200 Subject: [PATCH 721/982] Mark Document Picture-in-Picture API as shipped (#6864) * Mark Document Picture-in-Picture API as shipped * Update index.md --- site/_data/docs/web-platform/toc.yml | 2 +- .../document-picture-in-picture/index.md | 27 +++++++------------ 2 files changed, 10 insertions(+), 19 deletions(-) diff --git a/site/_data/docs/web-platform/toc.yml b/site/_data/docs/web-platform/toc.yml index 22c323f95..89e903274 100644 --- a/site/_data/docs/web-platform/toc.yml +++ b/site/_data/docs/web-platform/toc.yml @@ -9,6 +9,7 @@ - title: i18n.docs.web-platform.shipped sections: + - url: /docs/web-platform/document-picture-in-picture - url: /docs/web-platform/conditional-focus - url: /docs/web-platform/screen-sharing-controls - url: /docs/web-platform/capture-handle @@ -23,7 +24,6 @@ - title: i18n.docs.web-platform.origin-trials sections: - - url: /docs/web-platform/document-picture-in-picture - url: /docs/web-platform/launch-handler - url: /docs/web-platform/popup-api - url: /docs/web-platform/bfcache-notrestoredreasons diff --git a/site/en/docs/web-platform/document-picture-in-picture/index.md b/site/en/docs/web-platform/document-picture-in-picture/index.md index c385526d4..2da964bc2 100644 --- a/site/en/docs/web-platform/document-picture-in-picture/index.md +++ b/site/en/docs/web-platform/document-picture-in-picture/index.md @@ -6,11 +6,12 @@ description: > authors: - beaufortfrancois date: 2023-02-02 -updated: 2023-07-07 +updated: 2023-08-28 hero: image/vvhSqZboQoZZN9wBvoXq72wzGAf1/l8xW8V85N60e4dmwUwmE.jpg alt: Person holding outdoor lounge chairs. tags: - chrome-111 + - chrome-116 --- The [Document Picture-in-Picture API][spec] makes it possible to open an always-on-top window that can be populated with arbitrary HTML content. It extends the existing [Picture-in-Picture API for `

-## Try out the API on desktop - -During the trial phase you can test the API on desktop by one of two methods. - -### Local testing - -To experiment with the Document Picture-in-Picture API locally, without an origin trial token, enable the `chrome://flags/#document-picture-in-picture-api` flag. - -### Register for the origin trial - -Starting in Chrome 111, the Document Picture-in-Picture API is available as an [origin trial](/docs/web-platform/origin-trials/). It is expected to end in Chrome 115 (September 8, 2023). [Register here][ot]. - ## Use cases ### Custom video player @@ -283,7 +272,7 @@ You can play with the Document Picture-in-Picture API [VideoJS player demo]. Be ## Feedback -Developer feedback is really important at this stage, so please [file issues on GitHub][issues] with suggestions and questions. +Please [file issues on GitHub][issues] with suggestions and questions. ## Useful links @@ -293,7 +282,8 @@ Developer feedback is really important at this stage, so please [file issues on - [ChromeStatus.com entry][cr-status] - Blink Component: [`Blink>Media>PictureInPicture`][blink-component] - [TAG Review][tag] -- [Intent to Experiment][intent] +- [Intent to Experiment][intent-experiment] +- [Intent to Ship][intent-ship] ## Acknowledgements @@ -317,5 +307,6 @@ Hero image by [Jakob Owens]. [cr-status]: https://chromestatus.com/feature/5755179560337408 [blink-component]: https://bugs.chromium.org/p/chromium/issues/list?q=component:Blink%3EMedia%3EPictureInPicture [tag]: https://github.com/w3ctag/design-reviews/issues/798 -[intent]: https://groups.google.com/a/chromium.org/g/blink-dev/c/Tz1gUh92dXs +[intent-experiment]: https://groups.google.com/a/chromium.org/g/blink-dev/c/Tz1gUh92dXs +[intent-ship]: https://groups.google.com/a/chromium.org/g/blink-dev/c/JTPl7fM64Lc [jakob owens]: https://unsplash.com/photos/TqnpKA_elIU From 35ed842632038e5917325507894a66f793575990 Mon Sep 17 00:00:00 2001 From: Pankaj <101002817+letsbuildanything@users.noreply.github.com> Date: Mon, 28 Aug 2023 21:55:15 +0530 Subject: [PATCH 722/982] corrected 'https' to 'http' in valid patterns example of 'http://*/*' (#7183) --- site/en/docs/extensions/mv3/match_patterns/index.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/site/en/docs/extensions/mv3/match_patterns/index.md b/site/en/docs/extensions/mv3/match_patterns/index.md index 0e1868ca6..90f5e2476 100644 --- a/site/en/docs/extensions/mv3/match_patterns/index.md +++ b/site/en/docs/extensions/mv3/match_patterns/index.md @@ -62,7 +62,7 @@ Top Level domain match patterns http://*/* - Matches any URL that uses the https scheme + Matches any URL that uses the http scheme http://74.125.127.100/search
http://example.com/ @@ -158,4 +158,4 @@ Content scripts can be injected into related frames like `about:`, `data:`, etc [host-permissions]: /docs/extensions/mv3/declare_permissions/#host-permissions [mdn-tld]: https://developer.mozilla.org/docs/Glossary/TLD [permissions]: /docs/extensions/mv3/declare_permissions/ -[war]: /docs/extensions/mv3/manifest/web_accessible_resources/#manifest-declaration \ No newline at end of file +[war]: /docs/extensions/mv3/manifest/web_accessible_resources/#manifest-declaration From 8114dd6f112d022127f01cf420a638dedf3224f7 Mon Sep 17 00:00:00 2001 From: Joe Medley Date: Mon, 28 Aug 2023 10:11:53 -0700 Subject: [PATCH 723/982] Quick formatting fixes (#7175) * Quick formatting fixes - Uses the proper widget for a note. (I think the DevSite conversion script assumes the presence of the widget.) - Remove bullets where existing run-in headings serve just as well. * Update site/en/docs/extensions/mv3/override/index.md * Update site/en/docs/extensions/mv3/override/index.md * Update site/en/docs/extensions/mv3/override/index.md * Update site/en/docs/extensions/mv3/override/index.md * Update site/en/docs/extensions/mv3/override/index.md * Update site/en/docs/extensions/mv3/override/index.md * Update site/en/docs/extensions/mv3/override/index.md * Update site/en/docs/extensions/mv3/override/index.md * Update site/en/docs/extensions/mv3/override/index.md * Update site/en/docs/extensions/mv3/override/index.md --- site/en/docs/extensions/mv3/override/index.md | 56 +++++++++++-------- 1 file changed, 34 insertions(+), 22 deletions(-) diff --git a/site/en/docs/extensions/mv3/override/index.md b/site/en/docs/extensions/mv3/override/index.md index e3bbe88b7..da5f08c93 100644 --- a/site/en/docs/extensions/mv3/override/index.md +++ b/site/en/docs/extensions/mv3/override/index.md @@ -14,16 +14,23 @@ Chrome normally provides like New Tab page. In addition to HTML, an override pag An extension can replace any one of the following pages: -- **Bookmark Manager:** The page that appears when the user chooses the Bookmark Manager menu item - from the Chrome menu or, on Mac, the Bookmark Manager item from the Bookmarks menu. You can also - get to this page by entering the URL **chrome://bookmarks**. -- **History:** The page that appears when the user chooses the History menu item from the Chrome - menu or, on Mac, the Show Full History item from the History menu. You can also get to this page - by entering the URL **chrome://history**. -- **New Tab:** The page that appears when the user creates a new tab or window. You can also get to - this page by entering the URL **chrome://newtab**. +Bookmark Manager +: The page that appears when the user chooses the Bookmark Manager menu item +from the Chrome menu or, on Mac, the Bookmark Manager item from the Bookmarks menu. You can also +get to this page by entering the URL **chrome://bookmarks**. -
Note: A single extension can override only one page. For example, an extension can't override both the Bookmark Manager and History pages.
+History +: The page that appears when the user chooses the History menu item from the Chrome +menu or, on Mac, the Show Full History item from the History menu. You can also get to this page +by entering the URL **chrome://history**. + +New Tab +: The page that appears when the user creates a new tab or window. You can also get to +this page by entering the URL **chrome://newtab**. + +{% Aside %} +A single extension can override only one page. For example, an extension can't override both the Bookmark Manager and History pages. +{% endAside %} Incognito windows are treated specially. New Tab pages cannot be overridden in incognito windows. Other override pages work in incognito windows as long as the [incognito][1] manifest property is @@ -31,11 +38,17 @@ set to "spanning" (which is the default value). See [Saving data and incognito m The following screenshots show the default New Tab page and then a custom New Tab page. -{% Img src="image/BrQidfK9jaQyIHwdw91aVpkPiib2/LbjiI23vPdf5z8jjttwN.png", +
+ {% Img src="image/BrQidfK9jaQyIHwdw91aVpkPiib2/LbjiI23vPdf5z8jjttwN.png", alt="The default new tab page", height="173", width="200" %} +
The default new tab page.
+
-{% Img src="image/BrQidfK9jaQyIHwdw91aVpkPiib2/OvYbqxEERBMXwIQsxkm7.png", +
+ {% Img src="image/BrQidfK9jaQyIHwdw91aVpkPiib2/OvYbqxEERBMXwIQsxkm7.png", alt="A custom new tab page", height="173", width="200" %} +
A custom new tab page.
+
## Manifest {: #manifest } @@ -64,17 +77,16 @@ For `PAGE_TO_OVERRIDE`, substitute one of the following: For an effective override page, follow these guidelines: -- **Make your page quick and small.** - Users expect built-in browser pages to open instantly. Avoid doing things that might take a long - time. For example, avoid synchronous fetches of network or database resources. -- **Include a title in your page.** - Otherwise people might see the URL of the page, which could be confusing. Here's an example of - specifying the title: `New Tab` -- **Don't rely on the page having the keyboard focus.** - The address bar always gets the focus first when the user creates a new tab. -- **Don't try to emulate the default New Tab page.** - The APIs necessary to create a slightly modified version of the default New Tab page—with top - pages, recently closed pages, tips, a theme background image, and so on—don't exist. +**Make your page quick and small.**
Users expect built-in browser pages to open instantly. Avoid doing things that might take a long +time. For example, avoid synchronous fetches of network or database resources. + +**Include a title in your page.**
Otherwise people might see the URL of the page, which could be confusing. Here's an example of +specifying the title: `New Tab` + +**Don't rely on the page having the keyboard focus.**
The address bar always gets the focus first when the user creates a new tab. + +**Don't try to emulate the default New Tab page.**
The APIs necessary to create a slightly modified version of the default New Tab page—with top +pages, recently closed pages, tips, a theme background image, and so on—don't exist. ## Examples {: #examples } From 35e90930f94245bcaa5ca53a7a5dae8e0fc0f2e6 Mon Sep 17 00:00:00 2001 From: Adam Raine <6752989+adamraine@users.noreply.github.com> Date: Mon, 28 Aug 2023 12:26:13 -0700 Subject: [PATCH 724/982] Add Lighthouse 11 release post (#7166) * Add Lighthouse 11 release post * backticks * relative * author data * nits * psi done * Update site/en/blog/lighthouse-11-0/index.md Co-authored-by: Jeremy Wagner --------- Co-authored-by: Jeremy Wagner --- site/_data/authorsData.json | 5 ++ site/_data/i18n/authors.yaml | 5 ++ site/en/blog/lighthouse-11-0/index.md | 105 ++++++++++++++++++++++++++ 3 files changed, 115 insertions(+) create mode 100644 site/en/blog/lighthouse-11-0/index.md diff --git a/site/_data/authorsData.json b/site/_data/authorsData.json index 291f72999..c26cf494e 100644 --- a/site/_data/authorsData.json +++ b/site/_data/authorsData.json @@ -1887,5 +1887,10 @@ "homepage": "https://jlwagner.net/", "country": "US", "image": "image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/YROiiX412sAFeV58NStI.jpg" + }, + "adamraine": { + "country": "US", + "image": "image/9B7J9oWjgsWbuE84mmxDaY37Wpw2/gra2tr5xbhH5c8Zz9d3k.jpeg", + "github": "adamraine" } } diff --git a/site/_data/i18n/authors.yaml b/site/_data/i18n/authors.yaml index c6d32c577..97a259735 100644 --- a/site/_data/i18n/authors.yaml +++ b/site/_data/i18n/authors.yaml @@ -1536,3 +1536,8 @@ jlwagner: en: 'Jeremy Wagner' description: en: 'Tech writin'', doc slingin'' reprobate.' +adamraine: + title: + en: 'Adam Raine' + description: + en: 'Software Engineer, Google' diff --git a/site/en/blog/lighthouse-11-0/index.md b/site/en/blog/lighthouse-11-0/index.md new file mode 100644 index 000000000..b906ddb7e --- /dev/null +++ b/site/en/blog/lighthouse-11-0/index.md @@ -0,0 +1,105 @@ +--- +layout: 'layouts/blog-post.njk' +title: What's new in Lighthouse 11 +authors: + - adamraine + - jasmineyan +date: 2023-08-24 +description: > + Lighthouse 11 is here with new accessibility changes and audit updates +hero: 'image/MtjnObpuceYe3ijODN3a79WrxLU2/SM05YIr19Ucx2cUCx5lR.png' +alt: 'Lighthouse category scores, all 100' +tags: + - new-in-lighthouse + - lighthouse + - chrome-118 +--- + +[Lighthouse is a website auditing tool](/docs/lighthouse/overview/) that helps developers with opportunities and diagnostics to improve the user experience of their sites. + +Lighthouse 11 is available immediately on the [command line through npm](https://www.npmjs.com/package/lighthouse), in [Chrome Canary](https://www.google.com/chrome/canary/), and in [PageSpeed Insights](https://pagespeed.web.dev/). It will land in Chrome stable in Chrome 118. + +See the full list of changes in the [11.0 changelog](https://github.com/GoogleChrome/lighthouse/releases/tag/v11.0.0). + +## Accessibility category updates + +Category updates include new automated audits, improved weighting, and prioritized manual audits to help developers make their sites more accessible. + +### New audits and weighting + +Since Lighthouse 10.0, 13 new accessibility audits have been added: + +- `aria-allowed-role` +- `aria-dialog-name` +- `aria-text` +- `html-xml-lang-mismatch` +- `image-redundant-alt` +- `input-button-name` +- `label-content-name-mismatch` +- `link-in-text-block` +- `select-name` +- `skip-link` +- `table–duplicate-name` +- `table-fake-caption` +- `td-has-header` + +In addition to the new audits, the weights of all the audits have been updated to better match the corresponding [aXe rule impact levels](https://docs.deque.com/devtools-mobile/2023.4.19/en/impact). See the [Lighthouse accessibility scoring](/docs/lighthouse/accessibility/scoring/) documentation for exact details about the new audits and weights. + +### Manual audit visibility + +Lighthouse has always included some manual audits that cannot be tested automatically, but are still included as a checklist to verify important functionality. The manual audit section is now automatically expanded when all the automated audits have passed. + +{% Img src="image/9B7J9oWjgsWbuE84mmxDaY37Wpw2/Gm3aRnJOiWahqTQZKPty.png", alt="A Lighthouse report showing the manual audits in the accessibility category expanded", width="800", height="874" %} + +This emphasizes that passing all the automated audits and scoring a 100 in accessibility does not guarantee that the audited page is accessible; manual testing is still important. The manual audits have also been reordered to start with the most approachable checks. + +## Changes to existing audits + +### Interaction to Next Paint (INP) + +INP is [no longer experimental](https://web.dev/inp-cwv/), so the metric has been moved from `experimental-interaction-to-next-paint` to `interaction-to-next-paint`. + +### Service workers + +A service worker is no longer required for a page to be installable as a PWA in Chrome, so the `service-worker` check has been removed from the Lighthouse PWA category. + +### Resource summary + +The `resource-summary` audit has been removed from the Lighthouse report. Network request stats can still be compiled using the hidden `network-requests` audit: + +```js +const {lhr} = await lighthouse('https://example.com'); +const networkRequests = lhr.audits['network-requests'].details.items; +const resourceSummary = {}; + +for (const request of networkRequests) { + let total = resourceSummary[request.resourceType] || 0; + total += request.resourceSize; + resourceSummary[request.resourceType] = total; +} + +console.log(resourceSummary); +``` + +## Legacy navigation + +The `--legacy-navigation` flag for the CLI, the `legacyNavigation()` function in the Node API, and the "Legacy navigation" checkbox in the DevTools panel have all been removed. This completes a years-long transition in Lighthouse’s infrastructure to support [user flows](https://github.com/GoogleChrome/lighthouse/blob/main/docs/user-flows.md). + +## Running Lighthouse {: #running-lighthouse } + +Lighthouse is available in [Chrome DevTools](/docs/devtools/overview/), [npm](https://www.npmjs.com/package/lighthouse) (as a Node module and a CLI tool), and as a browser extension (in [Chrome](https://chrome.google.com/webstore/detail/lighthouse/blipmdconlkpinefehnmjammfjpmpbjk) and [Firefox](https://addons.mozilla.org/en-US/firefox/addon/google-lighthouse/)). It also powers several Google services, including [PageSpeed Insights](https://pagespeed.web.dev/). + +To try the Lighthouse Node CLI, use the following commands: + +```text +npm install -g lighthouse +lighthouse https://www.example.com --view +``` + +## Get in touch with the Lighthouse team {: #contact-us } + +To discuss the new features, changes in the Lighthouse 11 release, or anything else related to Lighthouse: + +- Report an issue or submit feedback in the [Lighthouse GitHub issue tracker](https://github.com/GoogleChrome/lighthouse/issues). +- Ask questions in the [Lighthouse GitHub discussion forums](https://github.com/GoogleChrome/lighthouse/discussions). +- Reach out to the Lighthouse team on Twitter @____lighthouse. From fb5e33c236e0b11d86de45311ecd7a3a40a084da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Beaufort?= Date: Tue, 29 Aug 2023 07:32:20 +0200 Subject: [PATCH 725/982] Add missing WebUSB exclusionFilters feature (#7185) --- site/en/blog/chrome-117-beta/index.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/site/en/blog/chrome-117-beta/index.md b/site/en/blog/chrome-117-beta/index.md index c4cd2a129..7ea15c92a 100644 --- a/site/en/blog/chrome-117-beta/index.md +++ b/site/en/blog/chrome-117-beta/index.md @@ -6,6 +6,7 @@ subhead: > CSS grid subgrid, entry and exit animation support for CSS, array grouping, iterator helpers, and more. layout: 'layouts/blog-post.njk' date: 2023-08-16 +updated: 2023-08-28 hero: 'image/kheDArv5csY6rvQUJDbWRscckLr1/JEQ1ZvdVbdKX9jO3iTXd.png' alt: > Chrome 117 beta hero logo @@ -133,6 +134,10 @@ Extend the WebRTC `RTCRtpTransceiver` API to offer control over which RTP header Adds "quantizer" `VideoEncoderBitrateMode` for VideoEncoder. This provides the ability to specify a quantizer parameter for each frame for AV1, VP9, and AVC video codecs. +### WebUSB `exclusionFilters` option in `requestDevice()` + +The [`exclusionFilters`](https://wicg.github.io/webusb/#dom-usbdevicerequestoptions-exclusionfilters) option in `navigator.usb.requestDevice()` allows web developers to exclude some devices from the browser picker. It can be used to exclude devices that match a broader filter but are unsupported. + ## Origin trials in progress In Chrome 117 you can opt into the following new [origin trials](/docs/web-platform/origin-trials/). From c5c77325b459dd582a5df4a060d40d4c96dfc3e8 Mon Sep 17 00:00:00 2001 From: Thomas Steiner Date: Tue, 29 Aug 2023 09:41:38 +0200 Subject: [PATCH 726/982] Add origin trial link (#7186) --- site/en/articles/tabbed-application-mode/index.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/site/en/articles/tabbed-application-mode/index.md b/site/en/articles/tabbed-application-mode/index.md index 3f6008e4a..243aff3e0 100644 --- a/site/en/articles/tabbed-application-mode/index.md +++ b/site/en/articles/tabbed-application-mode/index.md @@ -5,7 +5,7 @@ subhead: Work on more than one document at a time with tabs in your Progressive authors: - thomassteiner date: 2021-02-25 -updated: 2023-08-17 +updated: 2023-08-28 description: | Tabbed application mode allows Progressive Web App developers to add a tabbed document interface to their standalone PWAs. @@ -89,7 +89,7 @@ window. | 1. Create explainer | [Completed][explainer] | | 2. Create initial draft of specification | Not started | | 3. Gather feedback & iterate on design | [In progress](#feedback) | -| 4. Origin trial | Not started | +| 4. Origin trial | [In progress][ot] | | 5. Launch | Not started |
@@ -228,3 +228,4 @@ was reviewed by [Joe Medley](https://github.com/jpmedley). Hero image by [cr-dev-twitter]: https://twitter.com/ChromiumDev [issue]: https://github.com/w3c/manifest/issues/737 [explainer]: https://github.com/WICG/manifest-incubations/blob/gh-pages/tabbed-mode-explainer.md +[ot]: https://developer.chrome.com/origintrials/#/view_trial/3547710606461108225 From f9c3ce711739ea71370f04fa9e254fe5d616a391 Mon Sep 17 00:00:00 2001 From: Matthias Rohmer <12857772+matthiasrohmer@users.noreply.github.com> Date: Tue, 29 Aug 2023 13:54:30 +0200 Subject: [PATCH 727/982] fix: clean up approvers (#7191) --- .github/chrome-devrel-bot.json | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/.github/chrome-devrel-bot.json b/.github/chrome-devrel-bot.json index 6665c7fbe..61b1180af 100644 --- a/.github/chrome-devrel-bot.json +++ b/.github/chrome-devrel-bot.json @@ -5,6 +5,7 @@ "check_name" : "Content team approval", "teams" : [], "users" : [ + "PaulKinlan", "malchata", "rachelandrew", "heyawhite", @@ -13,7 +14,6 @@ "sofiayem", "nancymic2", "anusmitaray", - "IanStanion-google", "AmySteam" ], "paths" : [ @@ -46,16 +46,18 @@ "teams" : [], "users" : [ "PaulKinlan", - "jeffposnick", - "devnook", "malchata", "rachelandrew", "heyawhite", "jpmedley", "mihajlija", "sofiayem", - "AaronForinton", - "matthiasrohmer" + "nancymic2", + "anusmitaray", + "AmySteam", + "matthiasrohmer", + "devnook", + "tunetheweb" ], "paths" : [ "site/_data/**.yml", @@ -65,9 +67,18 @@ ] }, { - "check_name" : "Content (es) team approval", + "check_name" : "Content team or Spanish reader approval", "teams" : [], "users" : [ + "malchata", + "rachelandrew", + "heyawhite", + "jpmedley", + "mihajlija", + "sofiayem", + "nancymic2", + "anusmitaray", + "AmySteam", "tropicadri" ], "paths" : [ From ebdaf2a411b8b8fe80486e309d2323c6ce2e5675 Mon Sep 17 00:00:00 2001 From: "Kevin K. Lee" Date: Tue, 29 Aug 2023 11:51:07 -0400 Subject: [PATCH 728/982] Update FLEDGE->PA redirect (#7193) --- redirects.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/redirects.yaml b/redirects.yaml index 300e27190..361e86e11 100644 --- a/redirects.yaml +++ b/redirects.yaml @@ -758,8 +758,8 @@ redirects: - from: /docs/extensions/reference/declarativeNetRequest/#limits-global-static-rule-limit to: /docs/extensions/reference/declarativeNetRequest/#static-rules -- from: /fledge/... - to: /protected-audience/... +- from: /docs/privacy-sandbox/fledge/... + to: /docs/privacy-sandbox/protected-audience/... # DO NOT REMOVE. This seems pointless but we rewrite "." to "_" inside our server's code, so if the # URL is fine for all but incorrect syntax, we'll fix it up. From 891a19b322fa4ad309acbfbf5b26dd9b5cef348b Mon Sep 17 00:00:00 2001 From: Sam Dutton Date: Tue, 29 Aug 2023 19:58:42 +0200 Subject: [PATCH 729/982] Updated Topics classification information (#7192) * Updated Topics classification information * Update Topics epoch information Added "per user" explanation. * Update site/en/docs/privacy-sandbox/topics/topic-classification/index.md Co-authored-by: Nancymic2 --------- Co-authored-by: Nancymic2 --- site/en/docs/privacy-sandbox/topics/overview/index.md | 4 ++-- .../docs/privacy-sandbox/topics/topic-classification/index.md | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/site/en/docs/privacy-sandbox/topics/overview/index.md b/site/en/docs/privacy-sandbox/topics/overview/index.md index 1f9937974..7cbe19e5c 100644 --- a/site/en/docs/privacy-sandbox/topics/overview/index.md +++ b/site/en/docs/privacy-sandbox/topics/overview/index.md @@ -6,7 +6,7 @@ subhead: > description: > The Topics API enables interest-based advertising (IBA) without having to resort to tracking the sites a user visits. date: 2022-01-25 -updated: 2023-06-26 +updated: 2023-08-29 authors: - samdutton --- @@ -44,7 +44,7 @@ Previously, in order for a caller to be regarded by the browser as having observ ### Epochs {: #epoch} -Of course the Topics API must ensure that the topics of interest it provides are kept up to date. The browser infers topics for a user based on their browsing activity during a period of time known as an *epoch*, currently one week. The topic selected for each epoch is randomly selected from the user's top five topics for that time period. To further enhance privacy and ensure that all topics may be represented, there is a 5% chance the topic is randomly selected from all possible topics in a [taxonomy](https://github.com/jkarlin/topics/blob/main/taxonomy_v1.md) of interests. +Of course the Topics API must ensure that the topics of interest it provides are kept up to date. The browser infers topics for a user based on their browsing activity during a period of time known as an *epoch*, currently one week. Each user has their own epochs (epochs are "per user") and the initial start time is randomized. The topic selected for each epoch is randomly selected from the user's top five topics for that time period. To further enhance privacy and ensure that all topics may be represented, there is a 5% chance the topic is randomly selected from all possible topics in a [taxonomy](https://github.com/jkarlin/topics/blob/main/taxonomy_v1.md) of interests. The Topics API has three main tasks: diff --git a/site/en/docs/privacy-sandbox/topics/topic-classification/index.md b/site/en/docs/privacy-sandbox/topics/topic-classification/index.md index f0d5c1e93..1f7b904a5 100644 --- a/site/en/docs/privacy-sandbox/topics/topic-classification/index.md +++ b/site/en/docs/privacy-sandbox/topics/topic-classification/index.md @@ -7,7 +7,7 @@ description: > More in-depth information about the topics themselves and how they are chosen. date: 2022-01-25 -updated: 2023-06-26 +updated: 2023-08-29 authors: - samdutton --- @@ -73,6 +73,8 @@ A caller can also access topics from the [`Sec-Browsing-Topics` header](docs/pri {% endAside %} +Topics returned for a user are recalculated for a caller depending on the top-level site. For example, if `adtech.example` requests the user's topics on `news-a.example`, then on `news-b.example`, and then on `news-c.example`, topics returned to them will be recalculated on each site. This means a caller is likely to get different topics for a user on different top-level sites, since the (maximum) three topics returned for a user are chosen at random from the top five for the past three [epochs](/docs/privacy-sandbox/topics/overview/#epoch) (with a 5% chance of getting a random topic). That makes it harder for a caller to identify a user by their topics, since these are likely to be different across different top-level sites (even for the same user, caller, and epoch). + ## The classifier model {: #classifier-model} Topics are manually curated for 10,000 top domains, and this curation is used to train the classifier. This list can be found in `override_list.pb.gz`, which is available at `chrome://topics-internals/` under the current model in the **Classifier** tab. The domain-to-topics associations in the list are used by the API in lieu of the output of the model itself. From 9342518d83575f69692da51653e9674c9ced3e87 Mon Sep 17 00:00:00 2001 From: Jeremy Wagner Date: Tue, 29 Aug 2023 15:16:20 -0500 Subject: [PATCH 730/982] Fixes link to scheduler.yield demo source code. (#7196) --- .../en/blog/introducing-scheduler-yield-origin-trial/index.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/site/en/blog/introducing-scheduler-yield-origin-trial/index.md b/site/en/blog/introducing-scheduler-yield-origin-trial/index.md index 3becf29c8..ae4ac4664 100644 --- a/site/en/blog/introducing-scheduler-yield-origin-trial/index.md +++ b/site/en/blog/introducing-scheduler-yield-origin-trial/index.md @@ -5,7 +5,7 @@ description: | `scheduler.yield` is a proposed new addition to the scheduler API currently in origin trial, and is a novel approach to breaking up tasks for more responsive user experiences. Understand the benefits of this proposed addition to the scheduling API, and sign up for the origin trial to help us gain insights and feedback. authors: - jlwagner -date: 2023-08-25 +date: 2023-08-29 hero: image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/8vKzdbeRT4L2rBBcYxpM.jpg thumbnail: image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/da1Vdzrrs8xViNRf3NTt.jpg alt: A greyscale aerial photograph of a roundabout. @@ -57,7 +57,7 @@ To see this in action, try out [this Glitch demo](https://task-chunking-demo.gli {% Glitch { id: 'scheduler-yield-demo' } %} {% Aside %} -[The source code for this demo is available](https://task-chunking-demo.glitch.me/interact.js) if you want to dig further into what's going on. +[The source code for this demo is available](https://scheduler-yield-demo.glitch.me/js/scripts.js) if you want to dig further into what's going on. {% endAside %} You'll notice that the box at the bottom of the demo will read something like this: From e93db1798b1aa7e469d08d099b10c15ef1590662 Mon Sep 17 00:00:00 2001 From: Sofia Emelianova <42939855+sofiayem@users.noreply.github.com> Date: Wed, 30 Aug 2023 09:29:06 +0100 Subject: [PATCH 731/982] DevTools > Protocol monitor: New command editor, engineering post (#7163) * post * fix link * fix json --- site/_data/authorsData.json | 6 ++ site/_data/i18n/authors.yaml | 5 + site/en/blog/cdp-command-editor/index.md | 122 +++++++++++++++++++++++ 3 files changed, 133 insertions(+) create mode 100644 site/en/blog/cdp-command-editor/index.md diff --git a/site/_data/authorsData.json b/site/_data/authorsData.json index c26cf494e..ad1c020ac 100644 --- a/site/_data/authorsData.json +++ b/site/_data/authorsData.json @@ -1881,6 +1881,12 @@ "homepage": "https://snugug.com", "image": "image/admin/5kuER6QRWs54zbYIJ4zS.jpg" }, + "hadrijau": { + "country": "DE", + "github": "hadrijau", + "homepage": "https://www.hadrienjaubert.com", + "image": "image/NJdAV9UgKuN8AhoaPBquL7giZQo1/wawuvrG5lPYcSKABrMgq.png" + }, "jlwagner": { "github": "malchata", "linkedin": "malchata", diff --git a/site/_data/i18n/authors.yaml b/site/_data/i18n/authors.yaml index 97a259735..e46732e7d 100644 --- a/site/_data/i18n/authors.yaml +++ b/site/_data/i18n/authors.yaml @@ -1531,6 +1531,11 @@ samrichard: en: 'Sam Richard' description: en: 'Developer Advocate, Google ChromeOS' +hadrijau: + title: + en: 'Hadrien Jaubert' + description: + en: 'Software Engineering Intern, Google Chrome DevTools' jlwagner: title: en: 'Jeremy Wagner' diff --git a/site/en/blog/cdp-command-editor/index.md b/site/en/blog/cdp-command-editor/index.md new file mode 100644 index 000000000..f9f2431b2 --- /dev/null +++ b/site/en/blog/cdp-command-editor/index.md @@ -0,0 +1,122 @@ +--- +layout: "layouts/blog-post.njk" +title: Craft your Chrome Devtools Protocol (CDP) commands efficiently with the new command editor +authors: + - hadrijau +description: > + To make it easier to type Chrome Devtools Protocol (CDP) commands, DevTools introduced a new user-friendly editor so that you don't have to use JSON. +date: 2023-08-24 +hero: 'image/NJdAV9UgKuN8AhoaPBquL7giZQo1/rdTsT4xLywawzS9aVQdR.jpg' +alt: 'Craft your CDP commands with the new editor.' +tags: + - devtools-engineering + - devtools +--- + + +{% Partial 'devtools/banner.md' %} + +[Chrome DevTools Protocol (CDP)](https://chromedevtools.github.io/devtools-protocol/) is a remote debugging protocol (API) that lets developers communicate with a running Chrome browser. Chrome DevTools uses CDP to help you inspect the browser's state, control its behavior, and collect debugging information. You can also build Chrome extensions that use CDP. + +For example, this is a CDP command that inserts a new rule with the given `ruleText` in a stylesheet with given `styleSheetId`, at the position specified by `location`. + + +```js +{ + command: 'CSS.addRule', + parameters: { + styleSheetId: '2', + ruleText:'Example', + location: { + startLine: 1, + startColumn: 1, + endLine: 1, + endColumn: 1 + } + } +} +``` + +The [Protocol monitor](/blog/new-in-devtools-92/#protocol-monitor) drawer tab provides you with a way to send CDP requests and view all the CDP requests and responses DevTools sends and receives. + +{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/eRbncSjMieLuViSCDUwq.png", alt="The command line bar at the bottom of Protocol monitor.", width="800", height="504" %} + +Previously it was difficult to craft the command by hand, especially a command with many parameters. Not only did you need to be mindful of opening and closing brackets and quotation marks, you also had to remember the command's parameters which, in turn, makes you look up the [CDP documentation](https://chromedevtools.github.io/devtools-protocol/). + +To solve this problem, DevTools introduced a new CDP editor whose main goals are to: + +- **Auto-complete commands**. Simplify your CDP command input by providing you with the list of available commands via an auto completion feature. +- **Auto-populate command parameters**. Reduce the need to check the CDP documentation for the list of available command parameters. +- **Simplify the typing of parameter**. You just have to fill in the values of the parameters you want to send. +- **Edit and resend**. Improve prototyping speed by making it quicker to modify a CDP command. + +Now, let's have a look at what this new editor offers, and how you can make use of it! + +## Autocompletion feature + +{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/EuJUlPz9xkUJvAqBzshK.png", alt="The autocompletion drop-down menu.", width="800", height="535" %} + +An auto completion feature now powers the command input bar. It helps you write the names of the CDP commands you have access to. This can be very handy for commands that don't accept parameters. + +## String and number parameters + +With this new editor, you can now easily edit the values of primitive parameters. To open the editor, click the {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/H4duJWlMkdd1903sC0Bw.svg", alt="Open left panel.", width="20", height="20" %} icon next to the command input. + +Once you enter the command name, the editor shows you the corresponding parameters automatically. You don't have to look up documentation to know what parameters go with what commands. Furthermore, the editor displays the parameters in a given order: the mandatory one first (in red) and the optional ones next (in blue). + +To add a value to an optional parameter, hover over its name and click the `+` button. To reset the parameter to undefined, click the **Reset to default value** button. + +{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/G41qHOdmuIQf96Ogsldv.png", alt="The + and 'Reset to default value' buttons.", width="800", height="535" %} + +## Enum and boolean parameters + +When editing enum or boolean parameters, you'll see a drop-down menu that provides a selection of potential values (for enums) or the straightforward true or false option for booleans. This feature reduces the possibility of typing the wrong value for enum parameters and maintains accuracy and simplicity. + +{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/1Othh7taZZ4MlbQ7KBZd.png", alt="The boolean and enum drop-down menus.", width="800", height="457" %} + +## Array parameters + +For array parameters, you can manually add values to the array. Hover over the parameter's row and click the `+` button. + +{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/KmPRLFeC3crtueTne40S.png", alt="The + button that adds an array item.", width="800", height="535" %} + +To delete array items one by one, click the bin button next to the items. You can also clear all the parameters from the array with the block button. In this case, the array parameter is reset to `[]`. + +{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/WVdAIEPFTqwH9jnUSAFE.png", alt="The 'Delete parameter' and 'Reset to default' buttons.", width="800", height="535" %} + +## Object parameters + +When you enter a command that accepts object parameters, the editor lists the keys of this object and you can edit their values directly. This works for every type of nested parameters. + +{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/O9VSKDH9ENYv9aWW1igP.png", alt="Nested parameters.", width="800", height="564" %} + +## Discover what the command and parameters do in the editor + +Were you ever uncertain about the purpose of a parameter or command? Now, you can hover over a command or parameter, and a descriptive tooltip will pop up, complete with a link to the online documentation. + +{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/1aIyonSFctdZrbdSrpES.png", alt="The descriptive tooltip that appears when you hover over a command.", width="800", height="468" %} + +## Be warned before sending incorrect parameters + +Previously, if you didn't know if a parameter's value was of the correct type and had to wait to read the error response, this new editor is for you. It shows you real-time errors if the parameter can't accept the value you entered. + +{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/xUAwWfx2v1On7mxgfqCn.png", alt="An error icon next to a parameter with an incorrect value.", width="800", height="468" %} + +## Resend a command + +If you need to tweak a parameter of the command you just sent, you don't have to type it again. To edit and resend the command, right-click an item in the datagrid and select **Edit and resend** from the drop-down menu. This will automatically reopen the CDP editor and prefill it with the command you selected. + +{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/XTmr9IHseehMDsq3Ts2K.png", alt="The drop-down menu of a command in the datagrid with the 'Edit and resend' option.", width="800", height="468" %} + +## Copy a command to JSON format + +To copy the CDP command in JSON format to your clipboard, click the {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/ZYotGnpXcKxDQmRQRq59.svg", alt="Copy.", width="24", height="24" %} copy icon at the leftmost end of the toolbar. Additionally, keep in mind that if you input a command directly into the input bar, it will seamlessly populate the editor, and the other way around. + +## Conclusion + +The DevTools team's goal behind the design of this new CDP editor was to simplify the typing of CDP commands. The new editor can also be used to view parameters alongside the documentation and to provide you with an easier way to send your CDP commands. + + + +{% Partial 'devtools/reach-out.md' %} +{% Partial 'devtools/engineering-blog.md' %} From e13f0c8bbb5f9100b098ff6737954783c02093be Mon Sep 17 00:00:00 2001 From: kaslee <55968165+kaslee@users.noreply.github.com> Date: Wed, 30 Aug 2023 17:29:19 +0800 Subject: [PATCH 732/982] New post for astro view transitions (#7200) * New post for astro view tranitions New file and author entries added * Update index.md updated based on feedback * Update site/en/blog/astro-view-transitions/index.md Co-authored-by: Rachel Andrew * Update site/en/blog/astro-view-transitions/index.md Co-authored-by: Rachel Andrew * Update index.md Removed indentation for top level code * Update index.md Change to inline code --------- Co-authored-by: Addy Osmani Co-authored-by: Rachel Andrew --- site/_data/authorsData.json | 12 ++ site/_data/i18n/authors.yaml | 15 ++ site/en/blog/astro-view-transitions/index.md | 165 +++++++++++++++++++ 3 files changed, 192 insertions(+) create mode 100644 site/en/blog/astro-view-transitions/index.md diff --git a/site/_data/authorsData.json b/site/_data/authorsData.json index ad1c020ac..cc5fb8470 100644 --- a/site/_data/authorsData.json +++ b/site/_data/authorsData.json @@ -1898,5 +1898,17 @@ "country": "US", "image": "image/9B7J9oWjgsWbuE84mmxDaY37Wpw2/gra2tr5xbhH5c8Zz9d3k.jpeg", "github": "adamraine" + }, + "schottfk": { + "twitter": "FredKSchott", + "image": "image/1L2RBhCLSnXjCnSlevaDjy3vba73/2jqKQUkysDpGKMudG0g8.jpg" + }, + "phillipsm": { + "twitter": "matthewcp", + "image": "image/1L2RBhCLSnXjCnSlevaDjy3vba73/lu5YmuyoVJqP0flKUfKg.jpg" + }, + "ferreiram": { + "twitter": "charca", + "image": "image/1L2RBhCLSnXjCnSlevaDjy3vba73/2nczWyIuJperJ2qSEpA3.jpg" } } diff --git a/site/_data/i18n/authors.yaml b/site/_data/i18n/authors.yaml index e46732e7d..91a830f95 100644 --- a/site/_data/i18n/authors.yaml +++ b/site/_data/i18n/authors.yaml @@ -1546,3 +1546,18 @@ adamraine: en: 'Adam Raine' description: en: 'Software Engineer, Google' +schottfk: + title: + en: 'Fred K Schott' + description: + en: 'Co-creator, Astro' +phillipsm: + title: + en: 'Matthew Phillips' + description: + en: 'Co-creator, Astro' +ferreiram: + title: + en: 'Maxi Ferreira' + description: + en: 'Creator, FrontendAtScale' \ No newline at end of file diff --git a/site/en/blog/astro-view-transitions/index.md b/site/en/blog/astro-view-transitions/index.md new file mode 100644 index 000000000..c5bd95efa --- /dev/null +++ b/site/en/blog/astro-view-transitions/index.md @@ -0,0 +1,165 @@ +--- +layout: 'layouts/blog-post.njk' +title: Astro View Transitions +description: + Highlight how the Astro community embraced View Transitions when Chrome was shaping up the API and the journey towards landing first-class support for it in Astro + persistent islands. +date: 2023-08-30 +authors: + - schottfk + - phillipsm + - ferreiram + - karaerickson + - addyosmani +hero: 'image/1L2RBhCLSnXjCnSlevaDjy3vba73/EncUMvDPYDCZHMbJt3Kg.png' +alt: > + Logos of Chrome and Astro +tags: + - aurora-project +--- + +Today we would like to share more about Chrome and [Astro](https://astro.build/)’s journey with the [View Transitions API](/docs/web-platform/view-transitions/). This includes how the Astro community embraced and experimented with the API early, highlighting the possibilities to the broader community. We’re also excited to share more about the new built-in support for View Transitions in Astro 3.0! + +## Background + +Seamless transitions between different states of a page, known as _state transitions,_ have always been a complex aspect of building seamless, animated experiences on the web. Despite the availability of tools like CSS transitions, CSS animations, and the Web Animation API, creating state transitions has remained a daunting task. One of the challenges is handling interaction on outgoing elements, which can make the transitions more complex. + +In addition, maintaining reading position and focus for assistive devices is difficult. And, dealing with scroll position differences makes state transitions a cumbersome process. All these factors contribute to the complexity of implementing smooth transitions between various elements on a webpage + +**The View Transitions API** emerged as the browser’s solution to these challenges. This new API provides an easier way to change the DOM in a single step while creating an animated transition between two states. + +The [launch of the View Transitions API in Chrome 111](/blog/spa-view-transitions-land/) marked the beginning of a broader vision for transition support for all websites, not just JavaScript-based web applications. Future enhancements are also on their way. Chrome may explore exciting additions like transitions across documents, compositor-driven animations, scoped transitions, and nested transition groups in the future. + +
+ {% Video src="video/1L2RBhCLSnXjCnSlevaDjy3vba73/0o0qMJfjMfQqaldl4N4G.mp4", width="800", height="624", controls=true, autoplay=true, loop=false, muted=true, playsinline=true %} +
+ With the View Transitions API, navigating traditional multi-page applications feels as seamless as using a native app. +
+
+ +Visit demo: [Live](https://astro-movies.pages.dev/), [Source](https://github.com/Charca/astro-movies) + +## Early explorations with view transitions + +Chrome's journey with the View Transitions API was not a solitary one. Feedback and collaboration from developers, framework authors, and the CSS Working Group all played a crucial role in shaping the feature over the course of several years. + +Developer experimentation played a critical role early on. The earliest versions of the API didn't support CSS animations, and transitions were restricted to a few restrictive presets. Early feedback made it clear that developers wanted transitions to be fully customizable and expressive. This back-and-forth collaboration ensured that the API was designed with a balance of good defaults, extensibility, and customization. + +Astro was one of those frameworks that leaned into View Transitions early. The rest of this article is from the point of view of the Astro team, and shares their experience finding, adopting, and bringing View Transitions front-and-center to the web development experience. + +## Why Astro bet on view transitions + +Astro had been looking for something like View Transitions for a long time. Astro is a JavaScript web framework that server-renders your UI components to lightweight HTML for faster page load performance. Astro intentionally moves as much work off the client device as possible. Astro websites use native browser page navigation, where other web frameworks might hijack browser navigation with JavaScript client-side routing instead. + +This tradeoff created a challenge for the Astro team: How could Astro animate page transitions and provide app-like UI persistence across pages without adopting client-side routing? + +
+{% Img src="image/1L2RBhCLSnXjCnSlevaDjy3vba73/SIBoP8VgOkV2bBWTWmwE.png", alt="ALT_TEXT_HERE", width="800", height="678" %} +
+ Challenges of animating page transitions with Astro +
+
+ + +View Transitions were the answer. With View Transitions, Astro could provide the same routing features that JavaScript-heavy SPA web frameworks offered, but without the performance and complexity overhead of client-side routing. Other frameworks approached View Transitions as an optional implementation detail, but for Astro it was something much bigger. + +
+{% Img src="image/1L2RBhCLSnXjCnSlevaDjy3vba73/cG7Evh8rZRMB2q0wObHx.png", alt="ALT_TEXT_HERE", width="800", height="455" %} +
+ View Transitions as the answer +
+
+ + +The next question the Astro team had to answer was, “how?” The team looked to projects like Turbo, Swup, and Livewire for inspiration and even prototyped a few similar approaches inside of Astro. + +One of the earliest attempts involved a full-page “smart transition” that would automatically compare every new page of HTML to the current HTML and then attempt to replace every element at once using JavaScript. It was clever, but error-prone. + +```javascript +// An early API design for enabling view transitions +// in Astro via top-level config. Never implemented. + +export default defineConfig({ + router: 'spa' +}) +``` + +Thankfully, the Astro community showed that the View Transitions API was already powerful without the product over-complicating things. After seeing some early demos, the Astro team were sold on the idea of a simple Astro API that could match the browser APIs as closely as possible. Instead of seeing View Transitions as an invisible implementation detail hidden inside of Astro, they could be directly exposed to the developer. Aligning Astro directly with the web platform and reducing overall complexity on the frontend. + +```jsx +--- +// Add a simple fade transition with 2 lines of code! +// 1. Import the component +// 2. Add it to your common/base head component, or individual pages. + +import { ViewTransitions } from 'astro:transitions'; +--- + + My View Transitions Demo + + + +``` + +The work became simple: bring the new View Transitions API into Astro and provide automatic fallbacks that would bring to as many websites and browsers as possible. Fallback support is essential, because most browsers (outside of Chrome) haven’t shipped full support for native View Transitions yet. + +## Launching official support in Astro + +Astro released experimental View Transitions support in Astro 2.9. The response was positive immediately. Developers began sharing incredible demos of so many different use-cases, and in some cases even shipping it all to production. + +
+ {% Video src="video/1L2RBhCLSnXjCnSlevaDjy3vba73/UomZ1Je8dO4WbD6tR5FP.mp4", width="800", height="593", controls=true, autoplay=true, loop=false, muted=true, playsinline=true + %} +
+ Videos and animations continue to play while View Transitions are taking place. Thanks to Astro 3.0 built-in support, transitions can include shared elements across different routes. +
+
+ +Visit demo: [Live](https://live-transitions.pages.dev/), [Source](https://github.com/Charca/view-transitions-live) + +Astro 3.0, finalizes support and unflags the new View Transitions API for everyone. These new APIs are now ready for you to adopt experimentally, or all-at-once. + +```html +
+

Slide animation as you navigate to and from the page!

+
+ +``` +An unexpected benefit of aligning Astro with the platform APIs is the ability to to experiment with building new features on top of the native View Transitions API. For example, the new Astro `transition:persist` directive lets any element persist itself across a full-page navigation. This powers long-lived elements like persistent audio and video players, something that used to only be possible in heavy-weight JavaScript SPAs. + +```html + +``` + +
+ {% Video src="video/1L2RBhCLSnXjCnSlevaDjy3vba73/90DVznqvAEye95LiZPED.mp4", width="800", height="692", controls=true, autoplay=true, loop=false, muted=true, playsinline=true + %} +
+ Astro 3.0 supports persisting HTML elements across page navigations. When persisting interactive UI components, their state is also maintained. +
+
+ +Visit demo: [Live](https://astro-records.pages.dev/), [Source](https://github.com/Charca/astro-records) + +Astro is also free to make View Transitions more ergonomic to the developer. For instance, the team has already added support for custom forward/backward animations and animations for dynamic HTML. Both of these features are difficult to do with the lower-level APIs alone, but in Astro they are practically effortless. + +These features are only in Astro for now, but the Astro team hopes to feed their experience back to the specification authors and working groups for potential browser enhancements down the road. For example, by closely monitoring [a proposal](https://github.com/w3c/csswg-drafts/issues/8319) to make it easier to share animations in CSS. + + +## What comes next? + +The future for View Transitions on the web is bright. Astro, Nuxt, and HTMX have all shipped some degree of support, and many others have expressed interest. + +The Chrome team is thrilled about Astro's native View Transitions support. It's a big step for web development, enabling more fluid and dynamic user experiences. Developers, we encourage you to dive into View Transitions in Astro 3.0. Whether you're creating new landing pages or upgrading existing sites, these enhancements are game-changers. View Transitions helped to fill a gap between what was possible with SPAs and MPAs. Chrome would love to hear from you on whether there are additional gaps in support for SPA and/or MPA. Feel free to comment on the [View Transitions WICG GitHub repo](https://github.com/WICG/view-transitions/) to discuss this further. + +We're already inspired by the innovative demos and applications we've seen, and we're eager to see more. Your work with View Transitions is shaping the future of the web. Give View Transitions a try in Astro, share your work, and let's continue this journey together. + +## Additional references + +* [Experiments with Astro and the Shared Element Transition API](https://www.maxiferreira.com/blog/astro-page-transitions/) +* [View Transitions (Experimental) - Astro Docs](https://docs.astro.build/en/guides/view-transitions/) +* [Astro 2.9: View Transitions (experimental)](https://astro.build/blog/astro-290/) +* [Seamless Page Navigation With the View Transitions API](https://www.youtube.com/watch?v=5K5wNqCUrL8) \ No newline at end of file From a7008f46483c87723c74159007e503b0e815c301 Mon Sep 17 00:00:00 2001 From: Milica Date: Wed, 30 Aug 2023 15:20:47 +0200 Subject: [PATCH 733/982] Fix typo and add a note (#7206) --- .../privacy-sandbox/third-party-cookie-phase-out/index.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/site/en/docs/privacy-sandbox/third-party-cookie-phase-out/index.md b/site/en/docs/privacy-sandbox/third-party-cookie-phase-out/index.md index b67a4cecc..c20491e85 100644 --- a/site/en/docs/privacy-sandbox/third-party-cookie-phase-out/index.md +++ b/site/en/docs/privacy-sandbox/third-party-cookie-phase-out/index.md @@ -6,7 +6,7 @@ subhead: > description: > Learn how to audit your code to look for third-party cookies and what action you can take to ensure you're all set for the end of third-party cookies. date: 2023-05-17 -updated: 2023-07-27 +updated: 2023-08-30 authors: - mihajlija --- @@ -92,10 +92,14 @@ Another option is to browse through your site with third-party cookies blocked o To learn more about DevTools features you can use to investigate third-party cookies check out [the instructions on chromium.org](https://www.chromium.org/Home/chromium-privacy/privacy-sandbox/third-party-cookie-phaseout/). -In Chrome version 115 or higher, you can test the browser behavior after third-party cookie phase out by [running Chrome from the command line](https://www.chromium.org/developers/how-tos/run-chromium-with-flags/) with the flag `--test-third-party-cookies-phaseout`. This will block third-party cookies, enable [third-party storage partitioning](/docs/privacy-sandbox/storage-partitioning) and [FedCM](/docs/privacy-sandbox/fedcm), and enable Chrome UI settings for [First-Party Sets](docs/privacy-sandbox/first-party-sets-integration) (["Allow related sites to see your activity in the group"](https://support.google.com/chrome/answer/95647?hl=EN#zippy=%2Callow-related-sites-to-access-your-activity)). +In Chrome version 115 or higher, you can test the browser behavior after third-party cookie phase out by [running Chrome from the command line](https://www.chromium.org/developers/how-tos/run-chromium-with-flags/) with the flag `--test-third-party-cookie-phaseout`. This will block third-party cookies, enable [third-party storage partitioning](/docs/privacy-sandbox/storage-partitioning) and [FedCM](/docs/privacy-sandbox/fedcm), and enable Chrome UI settings for [First-Party Sets](docs/privacy-sandbox/first-party-sets-integration) (["Allow related sites to see your activity in the group"](https://support.google.com/chrome/answer/95647?hl=EN#zippy=%2Callow-related-sites-to-access-your-activity)). If your site breaks when third-party cookies are blocked, you can report the issue to [Chrome's cookie breakage tracker](https://goo.gle/report-3pc-broken). +{% Aside %} +This article was updated on 30 August 2023 to correct a typing mistake in the testing flag `--test-third-party-cookie-phaseout`. +{% endAside %} + ## Partitioned cookies [CHIPS (Cookies Having Independent Partitioned State)](/docs/privacy-sandbox/chips/) is a web platform mechanism that enables opting-in to having third-party cookies partitioned by top-level site using a new cookie attribute `Partitioned`. From 38dd47be1b1797836f0e282083b2b80a692b0b40 Mon Sep 17 00:00:00 2001 From: Nancymic2 Date: Wed, 30 Aug 2023 09:24:24 -0400 Subject: [PATCH 734/982] Add demo for CHIPS (#7194) * Create chips.md * Update index.md * Update chips.md * Update chips.md link * Update chips.md * Update index.md * Update chips.md --- .../_partials/privacy-sandbox/demos/chips.md | 19 +++++++++++++++++++ site/en/docs/privacy-sandbox/demos/index.md | 5 ++++- 2 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 site/en/_partials/privacy-sandbox/demos/chips.md diff --git a/site/en/_partials/privacy-sandbox/demos/chips.md b/site/en/_partials/privacy-sandbox/demos/chips.md new file mode 100644 index 000000000..42df35a4f --- /dev/null +++ b/site/en/_partials/privacy-sandbox/demos/chips.md @@ -0,0 +1,19 @@ +{% Details %} +{% DetailsSummary %} +**CHIPS** +{% endDetailsSummary %} +{% Columns %} +{% Column %} +Cookies Having Independent Partitioned State (CHIPS) allows developers to opt a cookie into partitioned storage, with separate cookie jars per top-level site, improving user privacy and security. This demo illustrates how it works. + +[Demo](https://chips-site-a.glitch.me/) + +[Docs](/docs/privacy-sandbox/chips/) + +{% endColumn %} +{% Column %} +{% Img src="image/RtQlPaM9wdhEJGVKR8boMPkWf443/Un7OFSJTQHhly3twuEHw.png", alt="CHIPS demo.", width="597", height="417" %} +{% endColumn %} +{% endColumns %} +{% endDetails %} + diff --git a/site/en/docs/privacy-sandbox/demos/index.md b/site/en/docs/privacy-sandbox/demos/index.md index 1503a1603..2e6acbdf4 100644 --- a/site/en/docs/privacy-sandbox/demos/index.md +++ b/site/en/docs/privacy-sandbox/demos/index.md @@ -6,8 +6,9 @@ subhead: > description: > Demos and colabs walk you through the Privacy Sandbox APIs. date: 2023-08-18 +updated: 2023-08-29 authors: - - alexandrawhite + - nmichell --- There are a number of demos available for the Privacy Sandbox APIs. Most of them will require you to be familiar with the APIs, so if you haven't read the docs, check out the links we've listed along with the demos. @@ -25,6 +26,8 @@ There are a number of demos available for the Privacy Sandbox APIs. Most of them {% Partial 'privacy-sandbox/demos/shared-storage.njk' %} +{% Partial 'privacy-sandbox/demos/chips.njk' %} + {% Partial 'privacy-sandbox/demos/fps.njk' %} {% Partial 'privacy-sandbox/demos/permissions-policy.njk' %} From e3d253eef8d706ba1242abd62e0cc42a8d81422d Mon Sep 17 00:00:00 2001 From: Thomas Steiner Date: Wed, 30 Aug 2023 15:52:28 +0200 Subject: [PATCH 735/982] Add more detail (#7208) --- .../articles/tabbed-application-mode/index.md | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/site/en/articles/tabbed-application-mode/index.md b/site/en/articles/tabbed-application-mode/index.md index 243aff3e0..183e20d83 100644 --- a/site/en/articles/tabbed-application-mode/index.md +++ b/site/en/articles/tabbed-application-mode/index.md @@ -173,6 +173,29 @@ A complete example to configure the behavior of an app with a tabbed interface m } ``` +### Detecting tabbed application mode + +Apps can detect whether they are running in tabbed application mode by checking the +[`display-mode`](https://developer.mozilla.org/docs/Web/CSS/@media/display-mode) CSS media feature +in either CSS or JavaScript: + +```css +@media (display-mode: tabbed) { + /* Styles to apply in tabbed application mode. */ +} +``` + +```js +const tabbedApplicationModeEnabled = window.matchMedia('(display-mode: tabbed)').matches; +``` + +### Interaction with the Launch Handler API + +The [Launch Handler API](/docs/web-platform/launch-handler/) lets sites redirect app +launches into existing app windows to prevent duplicate windows from being opened. When a +tabbed app sets `"client_mode": "navigate-new"`, app launches will open a new tab in an +existing app window. + ### Demo You can try tabbed application mode by setting a browser flag: From 3f0d7832ad5aa6f77c8ba9fdfdb566b67701bf08 Mon Sep 17 00:00:00 2001 From: Nancymic2 Date: Wed, 30 Aug 2023 10:13:24 -0400 Subject: [PATCH 736/982] aggregation keys doc (#7116) * agg keys doc * better error messages * better error messages * better error messages * better error messages * better error messages * creating page * content * content * content * content * content * edits * edits * title * edits * Update site/en/docs/privacy-sandbox/attribution-reporting/aggregation-keys/index.md Co-authored-by: Anusmita * Update site/en/docs/privacy-sandbox/attribution-reporting/aggregation-keys/index.md Co-authored-by: Anusmita * edits * typo * typo * Update site/en/docs/privacy-sandbox/attribution-reporting/aggregation-keys/index.md Co-authored-by: Anusmita --------- Co-authored-by: Anusmita --- site/_data/docs/privacy-sandbox/toc.yml | 1 + .../aggregation-keys/index.md | 1000 +++++++++++++++++ 2 files changed, 1001 insertions(+) create mode 100644 site/en/docs/privacy-sandbox/attribution-reporting/aggregation-keys/index.md diff --git a/site/_data/docs/privacy-sandbox/toc.yml b/site/_data/docs/privacy-sandbox/toc.yml index bf8267762..b5397600b 100644 --- a/site/_data/docs/privacy-sandbox/toc.yml +++ b/site/_data/docs/privacy-sandbox/toc.yml @@ -121,6 +121,7 @@ - url: /docs/privacy-sandbox/attribution-reporting/multiple-reporters/ - url: /docs/privacy-sandbox/attribution-reporting/report-schedules/ - url: /docs/privacy-sandbox/attribution-reporting/constraints/ + - url: /docs/privacy-sandbox/attribution-reporting/aggregation-keys/ - url: /docs/privacy-sandbox/attribution-reporting/understanding-noise/ - url: /docs/privacy-sandbox/attribution-reporting/working-with-noise/ - url: /docs/privacy-sandbox/attribution-reporting/contribution-budget/ diff --git a/site/en/docs/privacy-sandbox/attribution-reporting/aggregation-keys/index.md b/site/en/docs/privacy-sandbox/attribution-reporting/aggregation-keys/index.md new file mode 100644 index 000000000..592d9aa70 --- /dev/null +++ b/site/en/docs/privacy-sandbox/attribution-reporting/aggregation-keys/index.md @@ -0,0 +1,1000 @@ +--- +layout: 'layouts/doc-post.njk' +title: 'Understanding aggregation keys' +subhead: > + What aggregation keys are, how they're used, and how you can translate goals into keys. +description: > + What aggregation keys are, how they're used, and how you can translate goals into keys. +date: 2022-12-15 +updated: 2023-08-25 +authors: + - maudn +--- + +As an ad tech company running campaigns in multiple locations for various product categories, you want to help advertisers answer the following questions: + +1. How many **purchases** of each product category did each of my campaigns in each geographic region generate? +1. How much **revenue** for each product category did each of my campaigns in each geographic region generate? + +While many ad tech companies encourage advertisers to configure a variety of conversion types, focusing on the most important conversions such as purchases is a good way to ensure that summary results are detailed and accurate for these important events. + +To do so, you'll need to think of what questions you want to answer before data is collected. + +## Dimensions, keys, and values + +To answer these questions, let's take a look at dimensions, keys, and values. + +### Dimensions + +To understand how your campaigns are generating revenue, as described here, you'll want to track the following dimensions: + +- Ad campaign ID: the identifier for the specific campaign. +- Geography ID: the geographic region where the ad was served. +- Product category: the type of product as you've defined it. + +While the Campaign ID and the Geography ID dimensions are known when the ad is served (ad-serving time), the Product category will be known from a trigger event, when the user completes a conversion (conversion time). + +{% Aside %} +For the diagram in this document, we'll display dimensions as follows: +- Dimensions known at ad-serving time on a green background. +- Dimensions known at conversion time on a yellow background and underlined. +{% endAside %} + +The dimensions you want to track for this example are as shown in the following image: +{% Img src="image/RtQlPaM9wdhEJGVKR8boMPkWf443/7H0FNCjZM9zr3VE48Q2G.png", alt="Campaign ID, Geography ID, and product category.", width="498", height="55" %} + +### What are aggregation keys (buckets)? + +The terms aggregation key and bucket refer to the same thing. _Aggregation key_ is used in the browser APIs used to configure reports. The term _bucket_ is used in the aggregatable and summary reports, and in the [aggregation service APIs](/docs/privacy-sandbox/aggregation-service/). + +An aggregation key (key for short) is a piece of data that represents the values of the dimensions being tracked. Data is later aggregated along each aggregation key. + +For example, let's assume you're tracking the dimensions Product category, Geography ID, and Campaign ID. + +When a user located in Geography ID 7 sees an ad for Campaign ID 12, and later converts by purchasing a product in Product category 25, you may set an aggregation key that looks like the one in the following image: + +{% Img src="image/RtQlPaM9wdhEJGVKR8boMPkWf443/dmpyjw7KIcunQemDqs8i.png", alt="Aggregation key for a conversion.", width="495", height="125" %} + +You'll see later that an aggregation key does not look exactly like this in practice, but for now let's focus on the information contained in the key. + +### What are aggregatable values? + +To answer your questions for the dimensions we've outlined, you want to know: + +- The number of purchases (the purchase count). Once aggregated and made available in a summary report, this will be the total purchase count (summary value). +- The revenue for each purchase (the purchase value). Once aggregated and made available in a summary report, this will be the total revenue (summary value). + +Each of these—the purchase count for one conversion and the purchase value for one conversion—is an aggregatable value. You can think of aggregatable values as the values of your measurement goals. + + + + + + + + + + + + + + + + + +
QuestionAggregatable value = Measurement goal +
How many purchasesPurchase count
How much revenuePurchase value
+ +When a user located in Geography ID 7 sees an ad for Campaign ID 12, and later converts by purchasing a product of Product category 25 for $120 (assuming your currency is USD), you may set an aggregation key and aggregatable values that look like these: + +{% Img src="image/RtQlPaM9wdhEJGVKR8boMPkWf443/b5Mu1k7bH5wg3aAFrAGs.png", alt="Aggregation keys and values.", width="658", height="251" %} +
Aggregation key and aggregatable values. Note, aggregatable values are bold on a blue background.
+ + +Aggregatable values are summed per key across many users to generate aggregated insights, in the form of summary values in summary reports. + +{% Img src="image/RtQlPaM9wdhEJGVKR8boMPkWf443/H6qwvsRbrEDaxsKyV7Vz.png", alt="Generating aggregated insights.", width="800", height="446" %} + +Aggregatable values are summed to generate aggregated insights for your measurement goals. + +Note that this diagram omits decryption and represents a simplified example without noise applied. In the next section, we will outline this example with noise. + +## From keys and values to reports + +Now let's discuss how aggregatable keys and values relate to reports. + +### Aggregatable reports + +When a user clicks or views an ad and later converts, you instruct the browser to store an {aggregation key, aggregatable value} pair. + +{% Aside %} +In the explainer, an {aggregation key, aggregatable value} pair is also called a **histogram contribution**: it represents how this conversion—and the dimensions and values associated with it—**contribute** to the summary report. +{% endAside %} + +In our example, when a user clicks or views an ad and later converts, you instruct the browser to generate two contributions (one per measurement goal). + +{% Img src="image/RtQlPaM9wdhEJGVKR8boMPkWf443/rTwVxMnjMAexdZEXkX1P.png", alt="Generating two contributions.", width="800", height="422" %} + +You'll see later that an {aggregation key, aggregatable value} aggregatable report does not look exactly like this—but for now let's focus on the information contained in the report. + +When you instruct the browser to generate two contributions, the browser generates an aggregatable report (if it can [match](/docs/privacy-sandbox/attribution-reporting/system-overview/#match-sources-to-triggers) the conversion with a previous view or click). + +An aggregatable report contains: + +- The contribution(s) you've configured. +- Metadata about the click or view event and the conversion event: the site where the conversion occurred, and more. [See all the fields in an aggregatable report](https://github.com/WICG/conversion-measurement-api/blob/main/AGGREGATE.md#aggregatable-reports). + +{% Img src="image/RtQlPaM9wdhEJGVKR8boMPkWf443/LXNjMwwFx9h1AzgbcedI.png", alt="The resulting aggregatable report.", width="700", height="524" %} + +Aggregatable reports are JSON-formatted and include among other things, a payload field that will be used as a data input for the final summary report. + +The payload contains a list of contributions, each one being an {aggregation key, aggregatable value} pair: + +- bucket: the aggregation key, encoded as a bytestring. +- value: the aggregatable value for that measurement goal, encoded as a bytestring. + +Here's an example: + +```json +{ + "data": [ + { + "bucket": "111001001", + "value": "11111010000", + } + ], + "operation": "histogram" +} +``` + +In practice, aggregatable reports are encoded in a way that will make buckets and values look different than in the previous example (that is, a bucket may look like `\u0000\u0000\x80\u0000`). **Bucket** and **value** are both bytestrings. + +### Summary reports + +Aggregatable reports are aggregated across many browsers and devices (users) as follows: + +- An ad tech requests summary reports for a given set of keys, and a given set of aggregatable reports that come from many different browsers (users). +- Aggregatable reports are decrypted by the [aggregation service](/docs/privacy-sandbox/aggregation-service/). +- For each key, the aggregatable values from the aggregatable reports are summed. +- Noise is added to the summary value. + +{% Img src="image/RtQlPaM9wdhEJGVKR8boMPkWf443/LRQV3b1jgEYdYO49FMyz.png", alt="Aggregatable reports plus aggregation, decryption, and noise results in a summary report.", width="800", height="536" %} + +The result is a summary report that contains a set of {aggregation key, summary value} pairs. + +A summary report contains a JSON dictionary-style set of key-value pairs. Each pair contains: + +- bucket: the aggregation key, encoded as a bytestring. +- value: the summary value in decimal for a given measurement goal, summed up from all available aggregatable reports, with an added level of noise. + +Example: + +```json +[ + {"bucket": "111001001", "value": "2558500"}, + {"bucket": "111101001", "value": "3256211"}, + {...} +] +``` + +In practice, summary reports are encoded in a way that will make buckets and values look different than stated in the example (that is, a bucket may look like `\u0000\u0000\x80\u0000`). **Bucket** and **value** are both bytestrings. + +## Aggregation keys in practice + +Aggregation keys (buckets) are defined by an ad tech company, typically in two steps: when an ad is clicked or viewed, and when a user converts. + +### Key structure {: #key-structure} + +We'll use the term **key structure** to designate the set of dimensions encoded into a key. + +For example, Campaign ID x GeoID x Product category is a key structure. + +{% Img src="image/RtQlPaM9wdhEJGVKR8boMPkWf443/6xi8Qd9BrECKS4eGBTxI.png", alt="Key structure.", width="539", height="57" %} + +### Key types + +Aggregatable values are summed for a given key across multiple users/browsers. But we've seen that aggregatable values can track different measurement goals, such as a purchase value or a purchase count. You want to ensure that the aggregation service will sum aggregatable values of the same type. + +To do so, within each key, encode a piece of data that tells you what the summary value represents—the measurement goal this key is referring to. One way to do that is to create an additional dimension for your key that represents the measurement goal type. + +Using our earlier example, this measurement goal type would have two different possible values: + +- **Purchase count** is the first type of measurement goal. +- **Purchase value** is the second type of measurement goal. + +{% Img src="image/RtQlPaM9wdhEJGVKR8boMPkWf443/XRPniBSgCLLe0UEDB9Yt.png", alt="Measurement goals and measurement goal types.", width="465", height="331" %} + +If you had _n_ measurement goals, the measurement goal type would have _n_ different types of values. + +You can think of a key's dimensions as a metric. For example, "the number of **purchases** of a certain product per campaign per geography". + +### Key size, dimension size + +The maximum key size is defined in bits—the number of zeros and ones in binary to create the full key. The API allows for a key length of **128 bits**. + +This size allows for very granular keys, but more granular keys are more likely to lead to more noisy values. You can read more about noise in [Understand noise](/docs/privacy-sandbox/attribution-reporting/understanding-noise/). + +As introduced earlier, dimensions are encoded into the aggregation key. Each dimension has a certain cardinality—that is, the number of distinct values the dimension can take. Depending on its cardinality, each dimension needs to be represented by a certain number of bits. With _n_ bits, it is possible to express 2n distinct options. + +For example, a Country dimension may have a cardinality of 200, as there are about 200 countries in the world. How many bits are needed to encode this dimension? + +7 bits would only store **27** =128 distinct options, which is less than the necessary 200. + +8 bits would store **28** =256 distinct options which is more than the necessary 200, so you can use n=8 bits to encode this dimension. + +### Key encoding + +When you set keys in the browser, they should be encoded in hexadecimal. In summary reports, keys will appear in binary (and be named buckets). + +{% Aside %} +Hexadecimal data is typically prefixed with 0x ("x" for hexadecimal). For example, 0x19 is 19 in hexadecimal; that's 25 in decimal, not 19. + +Binary numbers are typically prefixed with 0b ("b" for binary). For example, 0b11001 is 11001 in binary; that's 25 in decimal, not 11,001. +{% endAside %} + +### Set two key pieces for a full key {: #full-key} + +Let's assume you use a key to track the following dimensions: + +- Campaign ID +- Geography ID +- Product category + +While the Campaign ID and the Geography ID dimensions are known when the ad is served (ad-serving time), the product category will be known from a trigger event, when the user completes a conversion (conversion time). + +In practice, this means you'll set a key in two steps: + +1. You'll set one part of the key—Campaign ID x Geography ID—at click or view time. +1. You'll set the second part of the key—Product category—at conversion time. + +These different parts of the keys are called key pieces. + +A key is calculated by taking the XOR (^) of its key pieces. + +{% Img src="image/RtQlPaM9wdhEJGVKR8boMPkWf443/CVeB1l6DHo0TZzxlueMn.png", alt="XORing key pieces.", width="800", height="161" %} + +Example: + +- Source-side key piece = `0x159` +- Trigger-side key piece = `0x400` +- Key = `0x159 ^ 0x400 = 0x559` + +### Aligning key pieces + +With two 64-bit key pieces extended to 128 bits using carefully placed 64-bits fillers/offsets (the sixteen zeros), XOR-ing key pieces is equivalent to concatenating them, which is easier to reason with and verify: + +- Source-side key piece = `0xa7e297e7c8c8d0540000000000000000` +- Trigger-side key piece = `0x0000000000000000674fbe308a597271` +- Key = + - 0xa7e297e7c8c8d0540000000000000000 ^ 0x0000000000000000674fbe308a597271 = + - 0xa7e297e7c8c8d054674fbe308a597271 + +### Multiple keys per ad click or view + +In practice, you may set multiple keys per attribution source event (ad click or view). For example, you may set: + +- A key that tracks Geography ID x Campaign ID. +- Another key that tracks Creative Type x Campaign ID. + +Take a look at [Strategy B](#strategy-b) for another example. + +### Encoding dimensions into keys + +When requesting summary reports, you need to tell the aggregation service what metrics you want to access, by requesting summary reports for a certain set of aggregation keys. + +Summary reports contain raw {key, summary value} pairs, and no additional information about the key. This means that: + +- When setting keys as the user views or clicks an ad and later converts, you need to reliably set keys based on the values of the dimensions they represent. +- When defining the keys you want to request summary reports for, you need to reliably generate or access on the fly the same keys as the keys set when the user viewed or clicked an ad and converted, based on the values of the dimensions you want to see aggregated data for. + +### Encoding dimensions using key structure maps {: #encoding-1} + +To encode dimensions into keys, you can create and maintain a key structure map ahead of time, upon defining your keys (before ad-serving time). + +A key structure map represents each of your dimensions and their position in the key. + +In practice, creating and maintaining key structure maps means you have to implement and maintain decoder logic. If you're looking for a method that doesn't require you to do that, consider using a [hash-based approach](#encoding) instead. + +Here's an example: + +Let's assume that you plan to track both purchases and purchase values for specific campaigns, geographic regions, and products. + +The product category, geography ID, and campaign ID need to be dimensions in your keys. Additionally, because you want to track two different measurement goals—purchase count and purchase value—you need to add one dimension within your key that keeps track of the [key type](#key-types). This will allow you to define what the aggregatable value actually represents upon receiving {key, aggregatable value} pairs in summary reports. + +With these measurement goals, your key has the following dimensions: + +- Product category +- Measurement goal type +- Geography ID +- Campaign ID + +Now, looking at each dimension, let's assume for your use case that you need to track the following: + +- 29 different products categories. +- 8 different geographic regions: North America, Central America, South America, Europe, Africa, Asia, Caribbean, and Oceania. +- 16 different campaigns. + +Here's the number of bits you would need to encode each dimension in your key: + +- Product category: 5 bits (2**5** = 32 > 29). +- Measurement goal type: 1 bit. The measurement goal is either purchase count or purchase value, that means two distinct possibilities; therefore, one bit is sufficient to store this. +- Geography ID: 3 bits (2**3** = 8). You would also define a dimension map for the Geography ID in order to know what geographic region each binary value represents. Your dimension map for your Geography ID dimension might look like this: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Binary value in the keyGeography
000North America
001Central America
010South America
011Europe
100Africa
101Asia
110Caribbean
111Oceania
+ +- Campaign ID: 4 bits (2**4** = 16) + +Keys following this structure would be 13 bits long (5 + 1 + 3 + 4). + +For this example, the key structure map for these keys would look like this: + +{% Img src="image/RtQlPaM9wdhEJGVKR8boMPkWf443/rja74M29VmZIaii9epxl.png", alt="Key structure map.", width="709", height="261" %} + +The order of the dimensions within the key is up to you. + +To illustrate how dimensions make up a key structure, we'll be using a binary representation, which is why the Campaign ID (first bits) is the right-most one, and the product category (last bits) is the left-most one. + +Within each dimension, the most significant bit—the one that carries the greatest numerical value—is the left-most bit. The least significant bit—the one that carries the smallest numerical value—is the right-most bit. + +Let's see how you would use a key structure map to decode a key. + +Let's take 0b1100100111100 as an arbitrary example key, and let's assume you have a way to know that this key follows the key structure map in the previous illustration. + +According to the key structure map, this key would decode into: + +```text +11001 0 011 1100 +``` + +{% Img src="image/RtQlPaM9wdhEJGVKR8boMPkWf443/JUR7V2S3MZTC3M5QZTwP.png", alt="ALT_TEXT_HERE", width="656", height="362" %} + +So the key 0b1100100111100 represents the number of purchases of Product category 25, for the Campaign ID 12 launched in Europe. + +### Encoding dimensions using a hash function {: #encoding-2} + +Rather than using a key structure map, you can use a hashing function to dynamically generate keys in a consistent and reliable way. + +This works as follows: + +
    +
  1. Select a hashing algorithm.
  2. +
  3. At ad-serving time, generate a string that includes all the dimensions you want to track, and their values. To generate the source-side key piece, +hash this string and consider adding a 64-bit suffix of zeros to align +it with the trigger-side key piece and make XOR easier to reason about. +
      +
    • Source-side key piece
      + = <64-bit hex hash("COUNT, campaignID=12, geoID=7"))><64-bit 00000000…> +
    • +
    • Note that COUNT encodes the same thing as measurementGoalType=0 in the key structure map approach. COUNT is a bit leaner and more explicit.
    • +
    +
  4. +
  5. At conversion time, generate a string that includes all the dimensions you want to track, and +their values. To generate a trigger-side key piece, hash this string and add a 64-bit prefix of zeros: +
    • Trigger-side key piece + + = <64-bit 00000000…><64-bit hex hash("productCategory=25")> +
    + +
  6. +
  7. The browser XORs these key pieces to generate a key. +
      +
    • 128-bit aggregation key
      + = <64-bit hex source-side key piece hash><64-bit hex source-side key piece hash> +
    • +
    +
  8. +
  9. Later, when you're ready to request a summary report for this key, generate it on the fly: +
      +
    • Based on the dimensions you're interested in, generate a source-side and trigger-side key piece as you did earlier. +
        +
      • Source-side key piece
        + = <64-bit hex hash("COUNT, campaignID=12, geoID=7"))><64-bit 00000000…> +
      • +
      • Trigger-side key piece
        + = <64-bit 00000000…><64-bit hex hash("productCategory=25")> +
      • +
      • trigger-side key piece = toHex(hash("productCategory=25"))
      • +
      +
    • +
    • Just like the browser, XOR these key pieces to generate the same key the browser has generated earlier. +
        +
      • 128-bit aggregation key
        + = <64-bit source-side key piece hash><64-bit source-side key piece hash> +
      • +
      +
    • +
    +
  10. +
+ + +A few practical tips if you're using this hash-based approach: + +- Always use the same ordering of the dimensions. This ensures that your hashes can be reliably regenerated. ("COUNT, CampaignID=12, GeoID=7" will not generate the same hash as "COUNT, GeoID=7, CampaignID=12"). One straightforward way to achieve this is to sort dimensions alphanumerically. This is what we'll be doing in the [example](#main-example), except for the fact that we'll always make COUNT or VALUE the first item in the dimension—this is a choice for readability, as COUNT or VALUE encodes information that's slightly different conceptually than all other dimensions. +- Keep track of the set of dimensions you're using in keys. You want to avoid generating keys based on a set of dimensions that you've never used. +- Hash collisions are rare if a suitable hash function is used, but checking against previously used hashes (which should be stored to interpret the results from the aggregation service) can avoid introducing new keys that collide with older keys. + +See how to use hash-based keys in practice in the [one conversion per click or view example](#main-example). + +## Aggregatable values in practice + +The ad tech company sets aggregatable values when a user converts. + +To protect user privacy, contributions from each user has an upper limit. Across all aggregatable values associated with a single source (ad click or view), no value can be higher than a certain contribution limit. + +We'll refer to this limit as the `CONTRIBUTION_BUDGET`. In the explainer, this limit is called the **L1 budget**, but it's the same as the `CONTRIBUTION_BUDGET`. + +For an in-depth discussion of the contribution budget, refer to [Contribution budget for summary reports](/docs/privacy-sandbox/attribution-reporting/contribution-budget/). + +## Example: one conversion per click or view {: #main-example} + +For this example, let's assume that you're looking to answer the following questions: + +- Which product categories are the most valuable in each region? +- Which campaign strategies are the most effective in each region? + +Let's also assume that for your use case, you need weekly insights. + +You also need to track the following: + +- 16 different campaigns. +- 8 different geographic regions: North America, Central America, South America, Europe, Africa, Asia, Caribbean, and Oceania. +- 29 different product categories. + +### What to measure + +While many ad tech companies encourage advertisers to configure a variety of conversion types, focusing on the most important conversions such as purchases is a good way to ensure that aggregate results are detailed and accurate for these important conversion events. +Indeed, the more metrics you measure, the smaller your contribution budget per metric, and hence the more noisy each value is likely to be. Therefore, you need to carefully select what to measure. + +In this example, we'll focus on campaign setups that measure only one conversion per click or view: a purchase. + +You'll still measure both the purchase count and the purchase value, and access a variety of important aggregate statistics such as total purchase value and geographic breakdowns. +This keeps noise reasonable and ensures a simple scaling approach for your contribution budget. + +### What about currencies? + +Running campaigns in different regions implies that currencies should be taken into account. +You could: + +- Make currency a dedicated dimension in the aggregation keys. +- Or infer the currency from a campaign ID, and convert all currencies to a reference currencies. + +In this example, we'll assume that you can infer the currency from a campaign ID. This allows you to convert any given purchase value from the user's local currency to a reference currency of your choice. You can also perform that conversion on the fly, when the user purchases an item. + +With this technique, all aggregatable values are in the same reference currency, and can therefore be summed to generate a total aggregated purchase value—a summary purchase value. + +### Translate goals into keys + +With your measurement goals and metrics, you have a number of options for your +key strategy. Let's focus on two of these strategies: + +- Strategy A: one granular key structure. +- Strategy B: two coarse key structures. + +#### Strategy A: one deep tree (one granular key structure) {: #strategy-a} + +In strategy A, you use one granular key structure, that includes all the +dimensions you need: + +{% Img src="image/RtQlPaM9wdhEJGVKR8boMPkWf443/L0ToNPnSf4W1hR2jQDpq.png", alt="One granular key structure", width="674", height="65" %} + +All your keys use this structure. + +You split this key structure into two key types to support two measurement +goals. + +- Key type 0: measurement goal type = 0, which you decide to define as a + **purchase count**. +- Key type 1: measurement goal type = 1, which you decide to define as a + **purchase value**. + +Summary reports look as follows: + +{% Img src="image/RtQlPaM9wdhEJGVKR8boMPkWf443/6C0IpYscwSrnxfEVQa4t.png", alt="Strategy A summary report.", width="360", height="621" %} + +You can think of strategy A as a "one deep tree" strategy: + +- Each summary value in summary reports is associated to all of the + dimensions you're tracking. +- You can roll up these summary values alongside each of these dimensions, + so these rollups can go as deep as the numbers of dimensions you have. + +With strategy A, you would answer your questions as follows: + + + + + + + + + + + + + + + + + + +
QuestionAnswer
Which product categories are the most valuable in each region?Sum the summary purchase counts and values that are in the summary +reports, across all campaigns.
+This gives you the purchase count and value per Geo ID x Product +category.
+For each region, compare the purchase value and count of different +product categories.
Which campaign strategies are the most effective in each region?Sum the summary purchase counts and values that are in the summary +reports, across all product categories.
+This gives you the purchase count and value per Campaign ID x Geo ID. +
+For each region, compare the purchase value and count for different +campaigns.
+ +With strategy A, you can also directly answer this third question: + +"How much revenue for each product did each of my campaigns in each geographic +region generate?" + +Even though the summary values will be noisy, you can determine when +differences in the value measured between each campaign are not due to noise +alone. Learn how to accomplish this in [Understanding noise](/docs/privacy-sandbox/attribution-reporting/understanding-noise/#evaluating-noise). + +#### Strategy B: two shallow trees (two coarse key structures) {: #strategy-b} + +In strategy B, you use two coarse key structures, each including a subset of +the dimensions you need: + +{% Img src="image/RtQlPaM9wdhEJGVKR8boMPkWf443/kEqEHcELeAnAikMbWj2Y.png", alt="Key structure 1 and key structure 2.", width="556", height="202" %} + +You split each of these key structures into two key types to support two +measurement goals. + +- Measurement goal type = 0, which you decide to define as a **purchase + count**. +- Measurement goal type = 1, which you decide to define as a **purchase + value**. + +You end up with four key types: + +- Key type I-0: Key structure I, purchase count. +- Key type I-1: Key structure I, purchase value. +- Key type II-0: Key structure II, purchase count. +- Key type II-1: Key structure II, purchase value. + +Summary reports look as follows: + +{% Img src="image/RtQlPaM9wdhEJGVKR8boMPkWf443/fRtRU43Udj1ZIq2Gkl8p.png", alt="Summary report strategy B.", width="800", height="680" %} + +You can think of strategy B as a "two shallow trees" strategy: + +- The summary values in summary reports map to one of two small sets of + dimensions. +- You can roll up these summary values alongside each of the dimensions in + these sets—this means that these rollups aren't as deep as in option A, + since there are less dimensions to roll up against. + +With strategy B, you would answer your questions as follows: + + + + + + + + + + + + + + + + + + +
QuestionAnswer
Which product categories are the most valuable in each region?Directly access the summary purchase counts and values that are in +the summary reports.
Which campaign strategies are the most effective in each region?Directly access the summary purchase counts and values that are in +the summary reports.
+ +#### Decision: Strategy A + +Strategy A is simpler; all data follows the same key structure, which also +means you only have one key structure to maintain. + +However, with strategy A, you need to sum the summary values you receive in +summary reports to answer some of your questions. Each of these summary values +is noisy. By summing up that data, you're also +[summing the noise](/docs/privacy-sandbox/attribution-reporting/working-with-noise/#summing-up-summary-values-rollups-also-sums-their-noise). + +This isn't the case with strategy B, where summary values exposed in the summary +reports already give you the information you need. This means that strategy B +will likely lead to a lesser impact from noise than strategy A. + +How should you determine which strategy to use? For existing advertisers or +campaigns, you might rely on historical data to determine whether the volume of +conversions is more suitable for strategy A or strategy B. However, for new +advertisers or campaigns, you may decide to: + +- Collect a month's worth of data with the granular keys (Strategy A). + Because you're extending the duration of data collection, summary values + will be higher and noise will be relatively lower. +- Assess with reasonable accuracy the weekly conversion count and + purchase value. + +{% Aside %} +Do not rely on report counts or data available only via debug reports +as a source of truth in your designs. In the future, the data +available in debug reports will change and noisy reports will be +generated alongside real reports, so these signals should be used +only to validate your implementation and testing strategy. +{% endAside %} + +In this example, let's assume that the weekly purchase count and purchase value +are high enough that strategy A would lead to a noise percentage that you deem +acceptable for your use case. + +Because strategy A is simpler and leads to a noise impact that doesn't +affect your ability to make decisions, you decide to go with strategy A. + +### Select a hashing algorithm + +You decide to adopt a [hash-based approach](#encoding-2) +to generate your keys. To do so, you need to select a hashing algorithm to +support that approach. + +Let's assume that you've selected SHA-256. You could also use a simpler, less +secure algorithm, such as MD5. + +### In the browser: set keys and values + +Now that you've decided on a key structure and a hashing algorithm, you're +ready to register keys and values when users click or view ads and subsequently +convert. + +Next is an overview of the headers you'll set to register keys and values in +the browser: + +{% Img src="image/RtQlPaM9wdhEJGVKR8boMPkWf443/hBdxStaGCFnzLKc2CDlh.png", alt="Register keys and values for a view or click.", width="512", height="302" %} + +{% Img src="image/RtQlPaM9wdhEJGVKR8boMPkWf443/jhcNyq6FRUD1SpO7iUoP.png", alt="Register keys and values for a conversion.", width="512", height="369" %} + +#### Set source-side key pieces + +When a user clicks or views an ad, set the aggregation keys in the +`Attribution-Reporting-Register-Aggregatable-Source` header. +At this stage, for each key, you can only set the part of the key, or +[key piece](#full-key), that's known at ad-serving time. + +Let's generate the key pieces: + + + + + + + + + + + + + + + + + + + + + + + + +
Source-side key piece for the key ID…String containing the dimension values you want to setHash of this string as hex, trimmed to the first 64 bits (64/4 += 16 characters1)Hex hash with appended zeros to simplify + XOR-ing. This is the source-side key piece.
key_purchaseCountCOUNT, CampaignID=12, GeoID=70x3cf867903fbb73ec0x3cf867903fbb73ec0000000000000000
key_purchaseValueVALUE, CampaignID=12, GeoID=70x245265f432f16e730x245265f432f16e730000000000000000
+ +
+1Each hexadecimal digit represents four bits (binary digits). +
+ +Let's now set the key pieces: + +```javascript +// Upon receiving the request from the publisher site +res.set( + "Attribution-Reporting-Register-Aggregatable-Source", + JSON.stringify( + [{ + "id": "key_purchaseCount", + "key_piece": "0x3cf867903fbb73ec0000000000000000" + }, { + "id": "key_purchaseValue", + "key_piece": "0x245265f432f16e730000000000000000" + }] +)) +``` + +Note that key IDs will **not** appear in the final reports. They're only used +when setting keys in the browser, so that source-side and trigger-side key +pieces can be mapped with each other and combined into a full key. + +#### Optional: event-level reports + +If you need to use event-level reports alongside aggregatable reports ensure that for a given source, the event-level data (source event ID and trigger data) and the +aggregation key can be matched. + +You might use both reports if, for example, you plan to use event-level reports to run models on which types of ads tend to lead to the greatest number of purchases. + +#### A user converts + +When a user converts, a pixel request is typically sent to the ad tech server. +Upon receiving this request: + +- Set the conversion-side (trigger-side) key pieces to complete the key. + You'll set these key pieces via the header + `Attribution-Reporting-Register-Aggregatable-Trigger-Data`. +- Set the aggregatable value for that conversion, via the header + `Attribution-Reporting-Register-Aggregatable-Values`. + +#### Set trigger-side key pieces to complete the key {: #trigger-side} + +Let's generate the key pieces: + + + + + + + + + + + + + + + + + + + + + + + + +
Trigger-side key piece for the key ID…String containing the dimension values you want to setHash of this string as hex, trimmed to the first 64 bits (64/4 += 16 characters1)Hex hash with appended zeros to simplify XOR-ing. +This is the source-side key piece.
key_purchaseCountProductCategory=250x1c7ce88c4904bbe20x0000000000000000f9e491fe37e55a0c
key_purchaseValue(same)(same)(same)
+
+1Each hexadecimal digit represents four bits (binary digits). +
+ +Let's now set the key pieces: + +```javascript +// Upon receiving the pixel request from the advertiser site +res.set( + "Attribution-Reporting-Register-Aggregatable-Trigger-Data", + JSON.stringify( + [ + // Each dictionary independently adds pieces to multiple source keys + { "key_piece": "0x0000000000000000f9e491fe37e55a0c", + "source_keys": ["key_purchaseCount", "key_purchaseValue"]}, + ] +)) +``` + +Note how you're adding the same key piece to several keys, by listing several +key IDs in `source_keys`—the key piece will be added to both keys. + +#### Set aggregatable values + +Before you set the aggregatable values, you need to scale them up in order to +reduce noise. + +Let's assume one purchase was made for product type 25 for $52. + +You won't set these directly as aggregatable values: + +- ~~`key_purchaseCount`: 1 conversion~~ +- ~~`key_purchaseValue`: $52~~ + +Instead, before you register these aggregatable values, you need to +[scale](/docs/privacy-sandbox/attribution-reporting/working-with-noise/#scale-up-to-contribution-budget) +them in order to minimize noise. + +You have two goals to spend your contribution budget against, so you might +decide to split the contribution budget in two. + +In this case, each goal is allocated a maximum of `CONTRIBUTION_BUDGET/2` +(=65,536/2=32,768). + +Let's assume the maximum purchase value for a single user, based on purchase +history across all users of the site, is $1,500. There may be outliers, for +example very few users who spent over that sum, but you may decide to ignore +these outliers. + +Your scaling factor for the purchase value should be: + +((`CONTRIBUTION_BUDGET`/2) / 1,500) = 32,768/1,500 = 21.8~ 22 + +Your scaling factor for purchase count is 32,768/1 = 32,768, since you +decided to track at most one purchase per ad click or view (source event). + +You can now set these values: + +- `key_purchaseCount`: 1*32,768 = 32,768 +- `key_purchaseValue`: 52*22 = 1,144 + +In practice, you would set them as follows, using the dedicated header +`Attribution-Reporting-Register-Aggregatable-Values`: + +```javascript +// Instruct the browser to schedule-send a report +res.set( + "Attribution-Reporting-Register-Aggregatable-Values", + JSON.stringify( + { + "key_purchaseCount": 32768, + "key_purchaseValue": 1144, + } +)) +``` + +### The aggregatable report is generated + +The browser matches the conversion to a previous view or click and generates an +aggregatable report, which includes the encrypted payload next to report +metadata. + +The following is an example of the data that could be found within the payload of the +aggregatable report, if it was readable in cleartext: + +```javascript +[ { + key: 0x3cf867903fbb73ecf9e491fe37e55a0c, // = source-side key piece XOR conversion-side key piece for the key key_purchaseCount + value: 32768 // the scaled value for 1 conversion, in the context of [CONTRIBUTION_BUDGET/2] +}, { + key: 0x245265f432f16e73f9e491fe37e55a0c, // source-side key piece XOR conversion-side key piece for the key key_purchaseValue + value: 1144 // the scaled value for $52, in the context of [CONTRIBUTION_BUDGET/2] +}] +``` + +Here, you can see two separate contributions within one single aggregatable +report. + +### Request a summary report + +- Batch aggregatable reports. Follow the advice offered in + [Batching](/docs/privacy-sandbox/attribution-reporting/system-overview/#batched-aggregatable-reports). +- Generate the keys you want to see data for. For example, to see summary + data for COUNT (total number of purchases) and VALUE (total purchase value) + for the Campaign ID 12 x Geography ID 7 x Product category 25: + - Generate the source-side key piece, as you did when [setting it + in the browser](#set-source-side-key-pieces). + - Generate the trigger-side key piece, as you did when [setting it in the browser](#trigger-side). + + + + + + + + + + + + + + + + + + + + + + + + +
Metric you want to request1Source-side key pieceTrigger-side key pieceKey to request to the aggregation service2
Total purchase count (COUNT)0x3cf867903fbb73ec
0000000000000000
0x00000000000000
00f9e491fe37e55a0c
0x3cf867903fbb73
ecf9e491fe37e55a0c
Total purchase value (VALUE)0x245265f432f16e73
0000000000000000
0x0000000000000000
f9e491fe37e55a0c
0x245265f432f16e73
f9e491fe37e55a0c
+
+1Metric you are looking to request (for Campaign ID 12 x Geography ID 7 x Product category 25). + +2Key to request to the aggregation service = Source-side key piece XOR Trigger-side key piece. +
+ +- Request summary data to the aggregation service for these keys. + +### Handle the summary report + +Ultimately, you receive a summary report that may look like this: + +```json +[ + {"bucket": "00111100111110000110011110010000001111111011101101110011111011001111100111100100100100011111111000110111111001010101101000001100", + "value": "2558500"}, + {"bucket": "00100100010100100110010111110100001100101111000101101110011100111111100111100100100100011111111000110111111001010101101000001100", + "value": "687060"}, +… +] +``` + +The first bucket is the COUNT key in binary. The second bucket is the VALUE key +in binary. +Note that while the keys are heterogeneous (COUNT vs VALUE), they're contained +in the same report. + +{% Aside %} +In practice, summary reports are encoded in a way that will make +buckets and values look different than you just saw (that is, a bucket +may look like \u0000\u0000\x80\u0000). **Bucket** and +**value** are both bytestrings. [An example](https://github.com/google/trusted-execution-aggregation-service/blob/main/COLLECTING.md#produce-a-summary-report-locally) can be found here. +{% endAside %} + +#### Scale down the values + +- 2,558,500 refers to the number of purchases for this key, scaled up by + your previously calculated scaling factor. The scaling factor for the + purchase count was 32,768. Divide 2,558,500 by the goal's contribution + budget: 2,558,500/32,768 = 156.15 purchases. +- 687,060 → 687,060/22 = $31,230 total purchase value. + +As a result, the summary reports give you the following insights: + +```text +Within the reporting time period, campaign #12 +run in Europe drove about 156 purchases (± noise) +for the product category #25. +``` + +```text +Within the reporting time period, campaign #12 +run in Europe drove $31,230 of purchases (± noise) +for the product category #25. +``` + From cc5baf749518f6b0a9d346fcce48e94614e6b324 Mon Sep 17 00:00:00 2001 From: Barry Pollard Date: Wed, 30 Aug 2023 15:29:58 +0100 Subject: [PATCH 737/982] Fix a couple of nits in Debugging Speculation Rules post (#7202) --- site/en/blog/debugging-speculation-rules/index.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/site/en/blog/debugging-speculation-rules/index.md b/site/en/blog/debugging-speculation-rules/index.md index 86e1bf516..93b212767 100644 --- a/site/en/blog/debugging-speculation-rules/index.md +++ b/site/en/blog/debugging-speculation-rules/index.md @@ -7,7 +7,7 @@ description: | authors: - tunetheweb date: 2023-08-22 -#updated: 2023-08-22 +updated: 2023-08-30 hero: image/W3z1f5ZkBJSgL1V1IfloTIctbIF3/ALZTuy3IA4jUdOpjjm2j.jpg alt: A picture of developer hunched over a computer screen with code on it tags: @@ -56,7 +56,7 @@ Speculation rules can be used to prefetch the next navigation's document. For ex Prefetch speculation rules only prefetch the document, not its subresources. This uses fewer resources than a full prerender of a potential next navigation, but also means the subresources need to be fetched and rendered upon navigation. {% endAside %} -Speculation rules are used for navigation prefetches have some advantages over the older `` syntax, such as a more expressive API and the results being stored in memory cache rather than the HTTP disk cache. +Using speculation rules for navigation prefetches has some advantages over the older `` syntax, such as a more expressive API and the results being stored in memory cache rather than the HTTP disk cache. ### Debugging `prefetch` speculation rules @@ -262,7 +262,7 @@ Note that speculation rules themselves are not actioned until the prerendered pa The previous sections discuss how to debug prerendered pages on the page which initiates the prerendering. However, it's also possible for the prerendered pages themselves to provide debugging information, either by making analytics calls or logging to the console (which is viewable as described above). -Additionally, once a prerendered page is activated by the user navigating to it, the **This Page** pane will show this status, and whether it was successfully prerendered or not. If it could not be prerender an explanation as to why that was the case is provided: +Additionally, once a prerendered page is activated by the user navigating to it, the **This Page** pane will show this status, and whether it was successfully prerendered or not. If it could not be prerendered an explanation as to why that was the case is provided:
{% Img src="image/W3z1f5ZkBJSgL1V1IfloTIctbIF3/7ksJhB9WgTxSn4y0qBdX.png", alt="Chrome DevTools Preloading This Page pane showing both a successful and failed prerendered page", width="800", height="413" %} From 6cbfbfe2d506f4a5dafda80283940236632a2fbf Mon Sep 17 00:00:00 2001 From: Adriana Jara <32825533+tropicadri@users.noreply.github.com> Date: Wed, 30 Aug 2023 08:37:00 -0700 Subject: [PATCH 738/982] Adding post message docs to TWA set (#7195) --- site/_data/docs/android/toc.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/site/_data/docs/android/toc.yml b/site/_data/docs/android/toc.yml index c2c5792f9..36d3e4fea 100644 --- a/site/_data/docs/android/toc.yml +++ b/site/_data/docs/android/toc.yml @@ -34,3 +34,4 @@ - url: /docs/android/trusted-web-activity/play-billing/ - url: /docs/android/trusted-web-activity/receive-payments-play-billing/ - url: /docs/android/trusted-web-activity/offline-first/ + - url: /articles/post-message-twa/ From 9a8d44fbde94331a9950d016aecc1ca976d5e354 Mon Sep 17 00:00:00 2001 From: Rachel Andrew Date: Wed, 30 Aug 2023 21:20:30 +0200 Subject: [PATCH 739/982] faster releases 2 post (#7207) --- .../faster-chrome-releases-round2/index.md | 66 +++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 site/en/blog/faster-chrome-releases-round2/index.md diff --git a/site/en/blog/faster-chrome-releases-round2/index.md b/site/en/blog/faster-chrome-releases-round2/index.md new file mode 100644 index 000000000..aee5a616b --- /dev/null +++ b/site/en/blog/faster-chrome-releases-round2/index.md @@ -0,0 +1,66 @@ +--- +# Required +layout: 'layouts/blog-post.njk' +title: Faster Chrome releases (round two!) +description: > + From Chrome 119 we will shorten the time between the branch for a release and release to stable. +subhead: > + From Chrome 119 we will shorten the time between the branch for a release and release to stable. +date: 2023-08-30 +authors: + - rachelandrew +tags: + - chrome-119 +thumbnail: 'image/kheDArv5csY6rvQUJDbWRscckLr1/xg1bTUKc9fy03fpMsJ7W.jpg' +alt: > + Light trails from fast cars. +--- + +Starting with Chrome 119, the Chrome team is again reducing the time between the branch for a release, and the actual release to stable. This change builds on the success of the [previous time reduction](/blog/faster-chrome-releases/), and continues our efforts to shorten the time it takes to launch. + +This will change the release date for Chrome stable and [early stable](/blog/early-stable/). + +The following table shows how this change affects the 119 release. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
StageChrome 119 (Old)Chrome 119 (Revised)
Branch Tue, Oct 3Mon, Oct 2
Beta PromotionWed, Oct 11Wed, Oct 4
Stable CutTue, Oct 31Tue, Oct 24
Early Stable ReleaseWed, Nov 1Wed, Oct 25
Stable ReleaseTue, Nov 7Tue, Oct 31
+ +Note that Chrome 120 stable will release on December 6 due to this change, and all dates after this have been adjusted to account for this. + +You can keep track of upcoming releases on the [Chrome Status Roadmap](https://chromestatus.com/roadmap), and see the schedule in detail on the [Chromium Dashboard](https://chromiumdash.appspot.com/schedule). We publish a post on this site for each [beta release](/tags/beta/), so you can keep track of upcoming changes to Chrome. + +_Hero image by [Caleb George](https://unsplash.com/@seemoris)._ From af5ac512b468dfc9807e736b1198d482f3faf8d9 Mon Sep 17 00:00:00 2001 From: amysteamdev <37001393+AmySteam@users.noreply.github.com> Date: Wed, 30 Aug 2023 15:59:36 -0500 Subject: [PATCH 740/982] Change samples link (#7212) --- site/en/docs/extensions/mv3/devtools/index.md | 4 +--- site/en/docs/extensions/mv3/index.md | 2 +- site/en/docs/extensions/mv3/override/index.md | 2 +- site/en/docs/extensions/reference/cookies/index.md | 2 +- site/en/docs/extensions/reference/debugger/index.md | 3 +-- site/en/docs/extensions/reference/devtools_network/index.md | 1 - site/en/docs/extensions/reference/i18n/index.md | 2 +- 7 files changed, 6 insertions(+), 10 deletions(-) diff --git a/site/en/docs/extensions/mv3/devtools/index.md b/site/en/docs/extensions/mv3/devtools/index.md index fc765cc53..373144e4d 100644 --- a/site/en/docs/extensions/mv3/devtools/index.md +++ b/site/en/docs/extensions/mv3/devtools/index.md @@ -438,8 +438,6 @@ var backgroundPageConnection = chrome.runtime.connect({ }); ``` - - ## DevTools extension examples Browse the source of these DevTools extension examples: @@ -484,7 +482,7 @@ You can find examples that use DevTools APIs in [Samples][doc-samples]. [api-scripting-executescript]: /docs/extensions/reference/scripting#method-executeScript [api-scripting-sendmessage]: /docs/extensions/reference/scripting#method-sendMessage [doc-message-passing]: /docs/extensions/mv3/messaging -[doc-samples]: /docs/extensions/mv3/samples#devtools +[doc-samples]: /docs/extensions/samples/ [doc-utilities]: /docs/devtools/console/utilities/ [gh-coquette]: https://github.com/thomasboyt/coquette-inspect [gh-devtools-messaging]: https://github.com/GoogleChrome/devtools-docs/issues/143 diff --git a/site/en/docs/extensions/mv3/index.md b/site/en/docs/extensions/mv3/index.md index b61b8b915..e5bbbb327 100644 --- a/site/en/docs/extensions/mv3/index.md +++ b/site/en/docs/extensions/mv3/index.md @@ -41,7 +41,7 @@ Thank you for being a member of the extension developer community. We're glad yo [doc-mv2-sunset]: /docs/extensions/mv3/mv2-sunset [doc-whats-new]: /docs/extensions/whatsnew [doc-get-help]: /docs/extensions/gethelp -[gh-ext-samples]: https://github.com/GoogleChrome/chrome-extensions-samples +[gh-ext-samples]: /docs/extensions/samples/ [github-ext-doc]: https://github.com/GoogleChrome/developer.chrome.com [gs-tuts]: /docs/extensions/mv3/getstarted/#tutorial [migrate-to-mv3]: /docs/extensions/migrating/ diff --git a/site/en/docs/extensions/mv3/override/index.md b/site/en/docs/extensions/mv3/override/index.md index da5f08c93..45a392440 100644 --- a/site/en/docs/extensions/mv3/override/index.md +++ b/site/en/docs/extensions/mv3/override/index.md @@ -95,4 +95,4 @@ See the [override samples][4]. [1]: /docs/extensions/mv3/manifest/incognito [2]: /docs/extensions/mv3/user_privacy#data-incognito [3]: /docs/extensions/mv3/manifest/ -[4]: /docs/extensions/mv3/samples#search:chrome_url_overrides +[4]: /docs/extensions/samples/ diff --git a/site/en/docs/extensions/reference/cookies/index.md b/site/en/docs/extensions/reference/cookies/index.md index 9a1cdb19f..c4c0942d2 100644 --- a/site/en/docs/extensions/reference/cookies/index.md +++ b/site/en/docs/extensions/reference/cookies/index.md @@ -30,4 +30,4 @@ the source code, see [Samples][3]. [1]: /docs/extensions/mv3/declare_permissions [2]: https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/api-samples/cookies/cookie-clearer -[3]: /docs/extensions/mv3/samples +[3]: /docs/extensions/samples/ diff --git a/site/en/docs/extensions/reference/debugger/index.md b/site/en/docs/extensions/reference/debugger/index.md index c63f8dee3..64379ce83 100644 --- a/site/en/docs/extensions/reference/debugger/index.md +++ b/site/en/docs/extensions/reference/debugger/index.md @@ -18,7 +18,7 @@ Protocol Domains. The available domains are: [Accessibility][accessibility], ## Manifest -You must declare the "debugger" permission in your extension's manifest to use this API. +You must declare the `"debugger"`` permission in your extension's manifest to use this API. ```json { @@ -52,7 +52,6 @@ repository. [target]: https://chromedevtools.github.io/devtools-protocol/tot/Target [tracing]: https://chromedevtools.github.io/devtools-protocol/tot/Tracing [webauthn]: https://chromedevtools.github.io/devtools-protocol/tot/WebAuthn -[debugger-samples]: /docs/extensions/mv3/samples#search:debugger [css]: https://chromedevtools.github.io/devtools-protocol/tot/css [cache-storage]: https://chromedevtools.github.io/devtools-protocol/tot/CacheStorage [dom-debugger]: https://chromedevtools.github.io/devtools-protocol/tot/DOMDebugger diff --git a/site/en/docs/extensions/reference/devtools_network/index.md b/site/en/docs/extensions/reference/devtools_network/index.md index 48f6e9319..8f2d6b032 100644 --- a/site/en/docs/extensions/reference/devtools_network/index.md +++ b/site/en/docs/extensions/reference/devtools_network/index.md @@ -42,4 +42,3 @@ repository. [1]: /docs/extensions/mv3/devtools [2]: https://www.softwareishard.com/blog/har-12-spec/ -[3]: /docs/extensions/mv3/samples#search:devtools.network diff --git a/site/en/docs/extensions/reference/i18n/index.md b/site/en/docs/extensions/reference/i18n/index.md index e623e2924..443affde2 100644 --- a/site/en/docs/extensions/reference/i18n/index.md +++ b/site/en/docs/extensions/reference/i18n/index.md @@ -354,7 +354,7 @@ For more details on calling `detectLanguage(inputText)`, see the [API reference] [13]: https://www.chromium.org/developers/creating-and-using-profiles [14]: https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/mv2/api/i18n/ [15]: https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/mv2/extensions/news/ -[16]: /docs/extensions/mv3/samples +[16]: /docs/extensions/samples/ [17]: /docs/extensions/mv3/i18n-messages/#placeholders [18]: #method-getMessage [19]: #method-getAcceptLanguages From 34bdcf3ede0fa007ed5e8ec65961e34af8ecda3c Mon Sep 17 00:00:00 2001 From: Rowan Merewood Date: Thu, 31 Aug 2023 13:26:01 +0100 Subject: [PATCH 741/982] RWS blog (#7213) Blog announcing the Related Website Sets rename from First-Party Sets. Co-authored-by: Anusmita --- site/en/blog/related-website-sets/index.md | 61 ++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 site/en/blog/related-website-sets/index.md diff --git a/site/en/blog/related-website-sets/index.md b/site/en/blog/related-website-sets/index.md new file mode 100644 index 000000000..0155e24d4 --- /dev/null +++ b/site/en/blog/related-website-sets/index.md @@ -0,0 +1,61 @@ +--- +layout: 'layouts/blog-post.njk' +title: Related Website Sets - the new name for First-Party Sets in Chrome 117 +description: > + Related Website Sets (RWS) is the new name for First-Party Sets. It also brings increased flexibility in defining sets. +date: 2023-08-31 +thumbnail: 'image/80mq7dk16vVEg8BBhsVe42n6zn82/s3iDQJUgLZV25YbtYxs1.png' +alt: Privacy Sandbox logo +tags: + - privacy +authors: + - helencho +--- + +Many Privacy Sandbox APIs are ramping up to General Availability (GA) in Chrome Stable in preparation for third-party cookie deprecation beginning in 2024. Some of these APIs will help preserve crucial cross-site cookie use cases, like [CHIPS](/docs/privacy-sandbox/chips/), and the API currently known as [First-Party Sets (FPS)](/docs/privacy-sandbox/first-party-sets/). In this post, we introduce Related Website Sets (RWS)—our new name for FPS that better reflects its purpose—and provide a refresher on key use cases along with an update on the associated subset domain limit. + + +## Preserving critical user journeys + +RWS is designed to minimize disruptions to specific user-facing features once Chrome starts limiting access to third-party cookies by default. Our goal is to allow users to browse the web with minimal disruption while still upholding the privacy goals of the Privacy Sandbox. To strike this balance, RWS targets specific use cases related to website functionality: + +* The [ccTLD use case](https://github.com/WICG/first-party-sets/tree/main#defining-a-set-through-use-case-based-subsets) addresses breakages like the [login example](https://issuetracker.google.com/268390722) filed in our public tracker. Such cases are often addressed in the ecosystem through heuristic-based exceptions (See [ref 1](#ref-1)). +* The [service domain use case](https://github.com/WICG/first-party-sets/tree/main#defining-a-set-through-use-case-based-subsets) addresses a common developer practice to isolate sensitive functions (like supporting an authentication flow) from user-facing domains. Such cases may be addressed in the ecosystem through targeted [exceptions](https://searchfox.org/mozilla-central/rev/3002762e41363de8ee9ca80196d55e79651bcb6b/browser/extensions/webcompat/data/shims.js#686) (See [ref 2](#ref-2)). +* The [associated domain use case](https://github.com/WICG/first-party-sets/tree/main#defining-a-set-through-use-case-based-subsets) provides more flexibility for the types of domains that may require third-party cookie access for critical user journeys (See [ref 3](#ref-3)). While the ccTLD and service domain use cases employ strict technical checks based on domain characteristics to minimize abuse, the associated domain uses a numeric limit. Read more about this in the next section. + + +## Associated domain limit increased to five domains + +Chrome previously proposed a numeric limit of three domains for the Associated Subset (plus one primary domain), in alignment with our objective to prevent widespread tracking abuse. We have heard feedback from web standards participants that the limit was too low for different types of use cases. + +We have decided to increase the associated domain limit to five domains (plus one primary domain) which best matches the most comparable implementation offered by another major browser (See [ref 4](#ref-4)). This will take effect beginning in Chrome 117. + +Since RWS is not intended as an ads solution, we are not taking into consideration feedback on how to improve RWS to better serve ads use cases. For ads use cases, developers should explore using the Topics, Protected Audience, and Attribution Reporting APIs and provide feedback on them accordingly. + + +## Users have a choice for extended use cases, beyond five associated domains + +For user-impacting experiences that are not supported by this limit, Chrome is [working on a user prompting flow](https://github.com/cfredric/chrome-storage-access-api) that also leverages the Storage Access API (SAA), a standard adopted by other browsers. For use cases that need more than five associated domains, we encourage developers to evaluate how SAA may be supported in non-RWS contexts. We are following the Blink launch process separately for [this feature](https://groups.google.com/a/chromium.org/g/blink-dev/c/JHf7CWXDZUc/m/Dy2EElgvAgAJ), which will be rolling out in Chrome Desktop beginning in Chrome 117. + + +## Next steps + +We're grateful for the ecosystem feedback that has helped shape the API so far. We have invested in RWS as a method of providing developers predictability, control, and agency in preserving the end user experience of the websites they build. We are excited to see how developers adopt and use RWS as we ramp up. The [submission process](https://github.com/GoogleChrome/first-party-sets/blob/main/FPS-Submission_Guidelines.md) is currently live, and the [RWS JSON generator tool](https://goo.gle/rws-json-generator) is a great starting point to help with submissions. + +Follow the [Intent to Ship thread](https://groups.google.com/a/chromium.org/g/blink-dev/c/7_6JDIfE1as/m/wModmpcaAgAJ) to track progress, and check out [these materials](/docs/privacy-sandbox/first-party-sets-integration/) for implementation guidance. + + +{% Details %} + +{% DetailsSummary %} + +References + +{% endDetailsSummary %} + +1. There is general agreement across browsers that these cross-site cookie use-cases are necessary, but they have taken different approaches in enabling them. [Firefox](https://developer.mozilla.org/docs/Web/Privacy/Storage_Access_Policy#automatic_storage_access_upon_interaction) ([code](https://searchfox.org/mozilla-central/rev/3002762e41363de8ee9ca80196d55e79651bcb6b/dom/base/Document.cpp#16328)) and [Safari](https://webkit.org/blog/8311/intelligent-tracking-prevention-2-0/#:~:text=Temporary%20Compatibility%20Fix%3A%20Automatic%20Storage%20Access%20for%20Popups) ([code](https://searchfox.org/wubkat/rev/5b368793a8c0a3d99c6991fcd3ef96e3dbd2cf2a/Source/WebKit/NetworkProcess/Classifier/ResourceLoadStatisticsDatabaseStore.cpp#1266)) have both implemented the pop-up heuristic that addresses the breakage observed, for example in the [Nintendo login flow](https://issuetracker.google.com/268390722). +2. There are also multiple examples where browsers hard code exceptions to minimize disruption for users. Firefox grants [storage access on redirect flows between Microsoft Teams and login.microsoftonline.us](https://searchfox.org/mozilla-central/rev/3002762e41363de8ee9ca80196d55e79651bcb6b/browser/extensions/webcompat/data/shims.js#686). +3. Firefox provides a ["shim" that will call requestStorageAccessForOrigin on behalf of facebook.com](https://searchfox.org/mozilla-central/source/browser/extensions/webcompat/shims/instagram.js) when the user logs in on instagram.com. An example of site grouping can also be seen in Safari's [hard coded exceptions](https://github.com/WebKit/WebKit/blob/a2db53cd97dc8136ac5c2a22d4cd2b53d0d717d6/Source/WebCore/platform/network/NetworkStorageSession.cpp#L395) to group storage access prompts for multiple domains. +4. Firefox [autogrants the first 5 requestStorageAccess calls made by a third-party site](https://developer.mozilla.org/docs/Web/API/Storage_Access_API#:~:text=Firefox%20only%20prompts%20users%20after%20an%20origin%20has%20requested%20storage%20access%20on%20more%20than%20a%20threshold%20number%20of%20sites) ([code](https://searchfox.org/mozilla-central/rev/c615dc4db129ece5cce6c96eb8cab8c5a3e26ac3/modules/libpref/init/StaticPrefList.yaml#4035)) that the user has visited before. In Chrome, the first five domains listed in the associated subset in addition to the same set's primary domain will have autogranted third-party cookie access through RWS. + +{% endDetails %} From 3097e869fde56fabc351d3682304b0c9b4add4d7 Mon Sep 17 00:00:00 2001 From: Sofia Emelianova <42939855+sofiayem@users.noreply.github.com> Date: Thu, 31 Aug 2023 19:21:13 +0100 Subject: [PATCH 742/982] dtt26 promo post (#7209) --- site/en/blog/devtools-tips-26/index.md | 52 +++++++++++++++++++ .../console/live-expressions/index.md | 4 +- 2 files changed, 54 insertions(+), 2 deletions(-) create mode 100644 site/en/blog/devtools-tips-26/index.md diff --git a/site/en/blog/devtools-tips-26/index.md b/site/en/blog/devtools-tips-26/index.md new file mode 100644 index 000000000..c3b8c3559 --- /dev/null +++ b/site/en/blog/devtools-tips-26/index.md @@ -0,0 +1,52 @@ +--- +title: > + DevTools Tips: Snippets and live expressions +description: > + Use Snippets to run code you frequently use and live expressions to watch values in real time. +layout: 'layouts/blog-post.njk' +date: 2023-08-31 +authors: + - sofiayem +hero: 'image/NJdAV9UgKuN8AhoaPBquL7giZQo1/XLtGnF6v8O8YXwQGPjwJ.png' +alt: > + DevTools Tips hero logo +tags: + - devtools + - devtools-tips +--- + +Use **Snippets** in DevTools to run code you frequently use and live expression to watch JavaScript values in real time. + +{% YouTube id='zW9ibQbYJNE' %} + +Watch the video to learn how to: + +- Create a snippet or open the **Snippets** pane: + + - With the [Command Menu](/docs/devtools/command-menu/) + - In [**Sources** > **Snippets**](/docs/devtools/javascript/snippets/#open). + +- Run your new snippet: + + - With the Command / Control + Enter shortcut in **Sources** + - From the [Command Menu](/docs/devtools/command-menu/#help) using `!`. + +- Pass values to your snippet: + + 1. Pause it with a [breakpoint](/docs/devtools/javascript/breakpoints/#loc). + 1. Set values in the [**Sources** > **Scope**](/docs/devtools/javascript/reference/#scope) pane. + 1. Resume execution. + +- Execute snippets from the **Console**: load them as global functions and run once. +- Use [Console Utilities API](/docs/devtools/console/utilities/) in your snippets. +- Use [**Console** > **Live Expressions**](/docs/devtools/console/live-expressions/): + + - To execute a piece of code you want to run repeatedly, for example, during a debugging session. + - Watch how the values change during execution in real time. + +To learn more, see: + +- [Run commands in the Command Menu](/docs/devtools/command-menu/) +- [Run snippets of JavaScript](/docs/devtools/javascript/snippets/) +- [Console Utilities API reference](/docs/devtools/console/utilities/) +- [Watch JavaScript values in real time with Live Expressions](/docs/devtools/console/live-expressions/) diff --git a/site/en/docs/devtools/console/live-expressions/index.md b/site/en/docs/devtools/console/live-expressions/index.md index ca2056631..e06d8e91c 100644 --- a/site/en/docs/devtools/console/live-expressions/index.md +++ b/site/en/docs/devtools/console/live-expressions/index.md @@ -1,6 +1,6 @@ --- layout: "layouts/doc-post.njk" -title: "Watch JavaScript values in real-time with Live Expressions" +title: "Watch JavaScript values in real time with Live Expressions" authors: - kaycebasques - sofiayem @@ -15,7 +15,7 @@ tags: If you find yourself typing the same JavaScript expression in the Console repeatedly, you might find it easier to create a **Live Expression**. With **Live Expressions**, you type an expression once and -then pin it to the top of your Console. The value of the expression updates in near real-time. +then pin it to the top of your Console. The value of the expression updates in near real time. ## Create a live expression {: #create } From 36c63a23f0a22602ac2641a35051ab9283006b26 Mon Sep 17 00:00:00 2001 From: wizardofdocs <83661258+wizardofdocs@users.noreply.github.com> Date: Thu, 31 Aug 2023 13:31:19 -0700 Subject: [PATCH 743/982] Update 'Welcome to Manifest V3' (#7178) * Copyedits to index.md * Update site/en/docs/extensions/mv3/intro/index.md Updated News section and blog link Co-authored-by: Joe Medley * Update site/en/docs/extensions/mv3/intro/index.md Futureproofed mv2-sunset info Co-authored-by: Joe Medley * Updated update date for Welcome to Manifest V3 --------- Co-authored-by: Joe Medley --- site/en/docs/extensions/mv3/intro/index.md | 40 +++++++--------------- 1 file changed, 13 insertions(+), 27 deletions(-) diff --git a/site/en/docs/extensions/mv3/intro/index.md b/site/en/docs/extensions/mv3/intro/index.md index 57f05a515..20bc4414d 100644 --- a/site/en/docs/extensions/mv3/intro/index.md +++ b/site/en/docs/extensions/mv3/intro/index.md @@ -5,48 +5,34 @@ seoTitle: Welcome to the Chrome Extension Manifest V3 subhead: 'A step in the direction of security, privacy, and performance.' description: 'An introduction to Manifest V3' date: 2020-11-09 -updated: 2022-09-28 +updated: 2023-08-31 --- {% Partial 'extensions/mv3-support.md' %} -This site introduces Manifest V3, short for Manifest Version 3, which is the latest iteration of the Chrome extension platform. It shares the background and reasons for introducing Manifest V3 and the vision for the platform's future, along with resources on how to migrate. +Manifest Version 3 (Manifest V3) is the latest iteration of the Chrome extension platform. This page outlines the changes in Manifest V3 and provides migration resources. -## What is a manifest? {: #what-is-a-manifest } +An extension [manifest][doc-manifest] gives the browser information about an extension's capabilities and the files it uses. The features available for extensions to use are defined by the current [manifest version][manifest-version]. Manifest V3 introduces enhancements to extension security, privacy, and performance, and allows extensions to use open web technologies such as service workers and promises. -An extension [manifest][doc-manifest] gives the browser information about the extension, such as the most important files and the capabilities the extension might use. The extension platform features change when there's a new [manifest version][manifest-version]. +The Chrome Web Store no longer accepts new Manifest V2 extensions. Watch the [Manifest V2 support timeline][mv2-sunset] for details. We strongly recommend migrating your extensions to Manifest V3 as soon as possible. -## Introducing Manifest V3 {: #introducing-manifest-v3 } +## Resources {: #manifest-v3-resources } -Manifest V3 represents one of the most significant shifts in the extensions platform since it launched a decade ago. Manifest V3 extensions enjoy enhancements in security, privacy, and performance; they can also use more contemporary open web technologies such as service workers and promises. +Manifest V3 is part of a shift in Chrome's user security and privacy philosophy. The following articles provide an overview of Manifest V3, the reasons for the update, and how to +implement it: -## Manifest V3 resources {: #manifest-v3-resources } +* [Platform vision][mv3-platform] explains how the Manifest V3 changes fit into the big picture. -Manifest V3 is part of a shift in the philosophy behind user security and privacy. The following articles provide an overview of Manifest V3, the reasons behind it, and how to -approach it: +* [Overview of Manifest V3][mv3-overview] summarizes the technical changes introduced in Manifest V3. -[Platform vision][mv3-platform] -: Explains how the Manifest V3 changes fit into the big picture of where the platform is going. +* [Migration guide][mv3-migration] explains how to update Manifest V2 extensions to use Manifest V3. For a quick reference, see [Migration checklist][mv3-checklist]. -[Overview of Manifest V3][mv3-overview] -: Summarizes the technical changes introduced with Manifest V3. +## Manifest V3 news {: #keep-up-with-the-latest-news } -[Migration guide][mv3-migration] -: Describes how to get started updating Manifest V2 extensions so they work in Manifest V3. +For more information and updates on Manifest V3, see [What's new in Chrome Extensions][doc-new] and the [Chrome Developer Blog][devs-blog]. -[Migration checklist][mv3-checklist] -: Provides a quick checklist to help adapt your extension to Manifest V3. -## Start the conversion {: #start-the-conversion } - -As of January 17, 2022 the Chrome Web Store has stopped accepting new Manifest V2 extensions. We strongly recommend migrating your extensions to Manifest V3 as soon as possible; this will become mandatory after [Manifest V2 is phased out][mv2-sunset] in 2024. - -## Keep up with the latest news {: #keep-up-with-the-latest-news } - -We're excited about the improvements that Manifest V3 brings to the platform. Look for new announcements in [What's new in Chrome Extensions][doc-new] and the [Chrome Developer Blog][devs-blog]. - - -[devs-blog]: https://developer.chrome.com/tags/extensions/ +[devs-blog]: https://developer.chrome.com/tags/extensions-news/ [doc-manifest]: /docs/extensions/mv3/manifest/ [doc-new]: /docs/extensions/whatsnew/ [manifest-version]: /docs/extensions/mv3/manifest/manifest_version/ From 83771b896fb337294d976e90e14e356a95461be6 Mon Sep 17 00:00:00 2001 From: Sofia Emelianova <42939855+sofiayem@users.noreply.github.com> Date: Fri, 1 Sep 2023 10:57:09 +0100 Subject: [PATCH 744/982] add vid (#7221) --- site/en/docs/devtools/console/live-expressions/index.md | 2 ++ site/en/docs/devtools/javascript/snippets/index.md | 2 ++ 2 files changed, 4 insertions(+) diff --git a/site/en/docs/devtools/console/live-expressions/index.md b/site/en/docs/devtools/console/live-expressions/index.md index e06d8e91c..109b16cf5 100644 --- a/site/en/docs/devtools/console/live-expressions/index.md +++ b/site/en/docs/devtools/console/live-expressions/index.md @@ -13,6 +13,8 @@ tags: - javascript --- +{% YouTube id='zW9ibQbYJNE' %} + If you find yourself typing the same JavaScript expression in the Console repeatedly, you might find it easier to create a **Live Expression**. With **Live Expressions**, you type an expression once and then pin it to the top of your Console. The value of the expression updates in near real time. diff --git a/site/en/docs/devtools/javascript/snippets/index.md b/site/en/docs/devtools/javascript/snippets/index.md index d007ec9b3..333d33989 100644 --- a/site/en/docs/devtools/javascript/snippets/index.md +++ b/site/en/docs/devtools/javascript/snippets/index.md @@ -15,6 +15,8 @@ tags: - prototype-fixes --- +{% YouTube id='zW9ibQbYJNE' %} + If you find yourself running the same code in the [**Console**][1] repeatedly, consider saving the code as a snippet instead. Snippets have access to the page's JavaScript context. They are an alternative to [bookmarklets][3]. You can author snippets in the [**Sources** panel][2] and run them on any page and in incognito mode. From 778df9fd836f3adf18d3efee45caeee61b9d40c8 Mon Sep 17 00:00:00 2001 From: Anusmita Date: Fri, 1 Sep 2023 17:34:08 +0100 Subject: [PATCH 745/982] Update chrome testing page (#7224) --- .../privacy-sandbox/chrome-testing/index.md | 103 ++++++++++++++---- 1 file changed, 82 insertions(+), 21 deletions(-) diff --git a/site/en/docs/privacy-sandbox/chrome-testing/index.md b/site/en/docs/privacy-sandbox/chrome-testing/index.md index e85999993..645db6184 100644 --- a/site/en/docs/privacy-sandbox/chrome-testing/index.md +++ b/site/en/docs/privacy-sandbox/chrome-testing/index.md @@ -6,21 +6,23 @@ subhead: > description: > Test your sites with third-party cookies disabled. date: 2023-05-18 +updated: 2023-09-01 authors: - alexandrawhite - rowan_m --- -As we start [general availability](/blog/privacy-sandbox-launch/) for the -relevance and measurement APIs, we intend to provide Chrome-facilitated testing -that allows sites to meaningfully preview what it's like to operate in a world -without third-party cookies. APIs will be gradually enabled over the course of the 115 milestone while monitoring for issues, aiming for 99% availability by mid-August. This will allow us to perform more effective API -testing and grow confidence within the ecosystem as to its readiness for -third-party cookie phase out. +To prepare for third-party cookie deprecation, we will be providing Chrome-facilitated testing modes that allow sites to preview how site behavior and functionality works without third-party cookies. This post provides an overview of the testing modes Chrome plans to provide and how to access experiment group labels. + +{% Aside %} + +This testing focuses on measuring the performance of the Privacy Sandbox relevance and measurement APIs (PS R&M APIs): Attribution Reporting, Protected Audience, Topics, Private Aggregation, Shared Storage, and Fenced Frames. + +{% endAside %} We have worked with the CMA to ensure these testing modes align with the -testing framework (and timeline) for third parties laid out in its note on -_[Quantitative testing of Google's Privacy Sandbox technologies](https://assets.publishing.service.gov.uk/media/6363b00de90e0705a8c3544d/CMA_Experiments_note.pdf)_. +testing framework (and timeline) for third parties laid out in its +[guidance on industry testing](https://www.gov.uk/cma-cases/investigation-into-googles-privacy-sandbox-browser-changes#industry-testing). As a result, the CMA anticipates that the results from testing in these modes can be used in its assessment of the Privacy Sandbox. @@ -31,12 +33,17 @@ We plan to have two modes of Chrome-facilitated testing: * **Mode B**: Chrome globally disables third-party cookies for some portion of all Chrome users. -These details are not final, and we'll publish further implementation guidance -as we progress in Q3 2023. The current proposals are as follows. +{% Aside %} + +Labels will be available via the temporary cookie-deprecation value which can be accessed via an HTTP header or JavaScript API. See the later section [Accessing labels via the cookie-deprecation value](#cookie-deprecation-value) for implementation details. + +{% endAside %} + +Some of the precise details of the composition and size of the groups within the modes are not final, however they will be in line with the treatment and control groups defined in the CMA’s testing guidance and we will publish further implementation guidance in Q3 2023. The current proposals are as follows. ## Mode A: Opt-in testing {: #mode-a } -Ad techs will be able to receive experiment labels for a portion of Chrome +Ad techs will be able to receive labels for experimental treatment and control groups for a portion of Chrome traffic. An ad tech can choose to coordinate with other ad techs, for example, to run [Protected Audience](/docs/privacy-sandbox/protected-audience/) auctions without third-party cookies for a consistent experiment group. Ad techs can also use @@ -50,8 +57,8 @@ if their ad tech partners are participating in the experiment. We expect this to allow for meaningful experimentation, where all involved sites and services can coordinate to ensure third-party cookies are not used at -any point within the process. We anticipate providing labels for up to 10% of -Chrome browsers via a new request header and low-entropy client hint. We +any point within the process. We anticipate providing labels for up to 9% of +Chrome browsers. We encourage anyone interested in testing to provide [feedback](https://github.com/GoogleChromeLabs/privacy-sandbox-dev-support/issues) from the ecosystem on the method for accessing labels and the granularity of @@ -82,7 +89,7 @@ can report site issues resulting from third-party cookie deprecation. We're working on mitigations to detect, address, and proactively alert site owners of issues that impact user experience during this phase. -Additionally, we plan to provide a small fraction of traffic within Mode B that +Additionally, we plan to provide a small fraction of traffic within Mode B that also has Privacy Sandbox relevance and measurement APIs disabled. Other APIs, like First-Party Sets, CHIPS, FedCM, and so on, will not be disabled. We anticipate that this combination will be helpful to establish a baseline of @@ -93,21 +100,75 @@ an appropriate fraction of traffic to devote to this subset of testing. We plan to deprecate 1% of third party cookies in Q1 2024, and we'll work closely with the CMA before taking further steps to expand deprecation. -## Engage and share feedback +## Accessing labels via the `Cookie-Deprecation` value {: #cookie-deprecation-value} + +For the duration of Mode A and Mode B we will be introducing a temporary `Cookie-Deprecation` value accessible via an opt-in HTTP header and JavaScript API provide the label for the browser's applicable Mode A or B experiment group (as defined by the percentages above), if it falls into one. We will remove this value when the experiment ends. + +Accessing labels involves accessing information stored on the user’s device. In some jurisdictions (for example, the EU and UK), we understand that this activity is analogous to the use of cookies and thus accessing labels likely requires end user consent. Before you begin requesting labels, we recommend that you seek legal advice as to whether this consent obligation applies to you. + +{% Aside %} + +As with all features we ship in Chromium, we will send an [Intent to Prototype as part of the Blink development process](/docs/privacy-sandbox/proposal-lifecycle/). The implementation details below are what we are proposing, but these **may change before we ship the feature** in Chrome Stable. We will continue to update this documentation and you can also follow the public discussion when the Intents are posted to the [blink-dev mailing list](https://groups.google.com/a/chromium.org/g/blink-dev). + +{% endAside %} + +### Accessing the `Sec-Cookie-Deprecation` HTTP header + +To receive the `Sec-Cookie-Deprecation` request header, the site must first set the `receive-cookie-deprecation` cookie. This cookie must use the [Partitioned attribute](/docs/privacy-sandbox/chips/), which means that opt-in for receiving the header must be done per top-level site. + +For example, if `3p-example.site` wants to receive the `Sec-Cookie-Deprecation` header on its resources embedded on `example.com`, then `3p-example.site` must set the following cookie in that context. + +```text +Set-Cookie: receive-cookie-deprecation=1; Secure; HttpOnly; Path=/; SameSite=None; Partitioned; +``` + +The `Secure`, `HttpOnly`, `Path`, `SameSite`, and `Partitioned` cookie attributes are mandatory. The other attributes: `Domain`, `Expires`, and `Max-Age` may be set as best suits your needs. + +Assuming the browser was in the `example_label_1 group`, subsequent requests which include this cookie would also include the `Sec-Cookie-Deprecation` header. + +```text +Sec-Cookie-Deprecation: example_label_1 +``` + +If the browser is not part of a group, no header will be sent. + +As labels are tied to the presence of the cookie, if the cookie is deleted, labels will also no longer be sent. As the `Partitioned` attribute is intended for continued use after third-party cookies are fully deprecated, this means `Partitioned` cookies may be set when third-party cookies are blocked. + + +### Accessing the cookieDeprecationLabel JavaScript API + +The `Cookie-Deprecation` value can also be accessed via the `navigator.cookieDeprecationLabel.getValue()` JavaScript API. This will return a promise which resolves to a string containing the applicable group label. For example, if the browser was in the `example_label_1`: + +```js +// Feature detect temporary API first +if ('cookieDeprecationLabel' in navigator) { + // Request value and resolve promise + navigator.cookieDeprecationLabel.getValue().then((label) => { + console.log(label); + // Expected output: "example_label_1" + }); +} +``` + +If the browser is not part of a group, then the value will be `null`. + +The JavaScript API may be called regardless of the presence of the `receive-cookie-deprecation` cookie. + +## Feedback Feedback from a diverse set of stakeholders across the web ecosystem is critical to the Privacy Sandbox initiative. The dedicated [feedback section](/docs/privacy-sandbox/feedback/) provides an overview of the existing public channels, where you can follow or contribute to discussion, along with a feedback form to ensure you can always reach the Chrome team directly. -You can provide your feedback on the following issues: +We use the ["chrome-testing"](https://github.com/GoogleChromeLabs/privacy-sandbox-dev-support/labels/chrome-testing) label in the developer support repo on GitHub to manage questions. We welcome your feedback and discussion on the initial questions: -- [Are you planning to test using Mode A, Mode B, or both?](https://github.com/GoogleChromeLabs/privacy-sandbox-dev-support/issues/112) -- [Picking label sizes for Chrome-facilitated testing](https://github.com/GoogleChromeLabs/privacy-sandbox-dev-support/issues/113) -- [Use of Client Hints for Chrome-facilitated testing](https://github.com/GoogleChromeLabs/privacy-sandbox-dev-support/issues/114) +* [Are you planning to test using Mode A, Mode B, or both?](https://github.com/GoogleChromeLabs/privacy-sandbox-dev-support/issues/112) +* [Picking label sizes for Chrome-facilitated testing](https://github.com/GoogleChromeLabs/privacy-sandbox-dev-support/issues/113) +* [Use of Client Hints for Chrome-facilitated testing](https://github.com/GoogleChromeLabs/privacy-sandbox-dev-support/issues/114) -Or you can also [raise a new issue](https://github.com/GoogleChromeLabs/privacy-sandbox-dev-support/issues) for additional questions or discussion. +You can also [raise new questions or discussions](https://github.com/GoogleChromeLabs/privacy-sandbox-dev-support/issues/new/choose) in the repo using the "Chrome-facilitated testing" template. {% Aside %} -The [Competition and Markets Authority (CMA)](https://www.gov.uk/government/organisations/competition-and-markets-authority) has published their [guidance on testing Privacy Sandbox APIs](https://assets.publishing.service.gov.uk/media/649d6a5f45b6a2000c3d455f/20230629_CMA_industry_testing_update_B.pdf) with relevant information on timelines, approaches to testing, and next steps. +The [Competition and Markets Authority (CMA)](https://www.gov.uk/government/organisations/competition-and-markets-authority) has published their [guidance on testing Privacy Sandbox APIs](https://www.gov.uk/cma-cases/investigation-into-googles-privacy-sandbox-browser-changes#industry-testing) with relevant information on timelines, approaches to testing, and next steps. {% endAside %} From 0c833c5fadffa29d374a934cc65f9b1bc74b0b7d Mon Sep 17 00:00:00 2001 From: Sam Dutton Date: Fri, 1 Sep 2023 18:57:39 +0100 Subject: [PATCH 746/982] Minor fixes to testing post (#7225) --- site/en/docs/privacy-sandbox/chrome-testing/index.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/site/en/docs/privacy-sandbox/chrome-testing/index.md b/site/en/docs/privacy-sandbox/chrome-testing/index.md index 645db6184..c337acf54 100644 --- a/site/en/docs/privacy-sandbox/chrome-testing/index.md +++ b/site/en/docs/privacy-sandbox/chrome-testing/index.md @@ -102,7 +102,7 @@ closely with the CMA before taking further steps to expand deprecation. ## Accessing labels via the `Cookie-Deprecation` value {: #cookie-deprecation-value} -For the duration of Mode A and Mode B we will be introducing a temporary `Cookie-Deprecation` value accessible via an opt-in HTTP header and JavaScript API provide the label for the browser's applicable Mode A or B experiment group (as defined by the percentages above), if it falls into one. We will remove this value when the experiment ends. +For the duration of Mode A and Mode B we will be introducing a temporary `Cookie-Deprecation` value accessible via an opt-in HTTP header and JavaScript API, which will provide the label for the browser's applicable Mode A or B experiment group (as defined by the percentages above), if it falls into one. We will remove this value when the experiment ends. Accessing labels involves accessing information stored on the user’s device. In some jurisdictions (for example, the EU and UK), we understand that this activity is analogous to the use of cookies and thus accessing labels likely requires end user consent. Before you begin requesting labels, we recommend that you seek legal advice as to whether this consent obligation applies to you. @@ -137,7 +137,7 @@ As labels are tied to the presence of the cookie, if the cookie is deleted, labe ### Accessing the cookieDeprecationLabel JavaScript API -The `Cookie-Deprecation` value can also be accessed via the `navigator.cookieDeprecationLabel.getValue()` JavaScript API. This will return a promise which resolves to a string containing the applicable group label. For example, if the browser was in the `example_label_1`: +The `Cookie-Deprecation` value can also be accessed via the `navigator.cookieDeprecationLabel.getValue()` JavaScript API. This will return a promise which resolves to a string containing the applicable group label. For example, if the browser was in the `example_label_1` group: ```js // Feature detect temporary API first From a35c9a3a72d29db034c11466602d70118849f41c Mon Sep 17 00:00:00 2001 From: Adam Argyle Date: Sat, 2 Sep 2023 07:52:00 -0700 Subject: [PATCH 747/982] removes canary with flags comments and specifies chrome version (#7214) --- site/en/blog/css-text-wrap-balance/index.md | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/site/en/blog/css-text-wrap-balance/index.md b/site/en/blog/css-text-wrap-balance/index.md index 310fbe70a..a400150be 100644 --- a/site/en/blog/css-text-wrap-balance/index.md +++ b/site/en/blog/css-text-wrap-balance/index.md @@ -16,11 +16,11 @@ alt: > A cairn of rocks balanced. --- -[Chrome Canary](https://www.google.com/chrome/canary/) includes a new feature—`text-wrap: balance` from [CSS Text Level -4](https://www.w3.org/TR/css-text-4/#text-wrap). To check it out, enable -[chrome://flags/#enable-experimental-web-platform-features](chrome://flags/#enable-experimental-web-platform-features), -and then take a look at the examples in this post to learn how this one line of -CSS can massively improve your text layouts. +[Chrome Canary](https://www.google.com/chrome/canary/) includes a new +feature—`text-wrap: balance` from [CSS Text Level +4](https://www.w3.org/TR/css-text-4/#text-wrap). In Chrome +114 or newer, take a look at the examples in this post to learn how +this one line of CSS can massively improve your text layouts.
{% Video @@ -70,10 +70,7 @@ With `text-wrap: balance` from [CSS Text 4](https://www.w3.org/TR/css-text-4/#text-wrap), you can request the browser to figure out the best balanced line wrapping solution for the text. The browser **does know** all the factors, like font size, language, and allocated area. -Results of browser balanced text wrapping looks like this today in [Chrome -Canary](https://www.google.com/chrome/canary/) with -[chrome://flags/#enable-experimental-web-platform-features](chrome://flags/#enable-experimental-web-platform-features) -enabled: +Results of browser balanced text wrapping looks like this today:
{% Img src="image/vS06HQ1YTsbMKSFTIPl2iogUQP73/49XR6eV5QLBiiZg0jr5P.png", alt="Headline is highlighted like the previous DevTools, this time is not spanning the full width. It started a new line before the end and as such is a balanced block of text.", width="800", height="210" %} From 67354a2316b8f79ae0776ab83423ba1e85baeb43 Mon Sep 17 00:00:00 2001 From: Xuezhou Dai Date: Mon, 4 Sep 2023 18:06:59 +0800 Subject: [PATCH 748/982] Add a blog post about GSoC & Chrome Extensions (#7190) * Add a blog post about GSoC & Chrome Extensions * Add a line break * Update author description * Fix post mistakes * Apply suggestions from code review Co-authored-by: Joe Medley * Update site/en/blog/google-summer-of-code-and-chrome-extensions/index.md Co-authored-by: Oliver Dunk * Update site/en/blog/google-summer-of-code-and-chrome-extensions/index.md Co-authored-by: Oliver Dunk * Update site/en/blog/google-summer-of-code-and-chrome-extensions/index.md --------- Co-authored-by: Joe Medley Co-authored-by: Oliver Dunk --- site/_data/authorsData.json | 7 ++ site/_data/i18n/authors.yaml | 6 + .../index.md | 103 ++++++++++++++++++ 3 files changed, 116 insertions(+) create mode 100644 site/en/blog/google-summer-of-code-and-chrome-extensions/index.md diff --git a/site/_data/authorsData.json b/site/_data/authorsData.json index cc5fb8470..a0f691e92 100644 --- a/site/_data/authorsData.json +++ b/site/_data/authorsData.json @@ -1881,6 +1881,13 @@ "homepage": "https://snugug.com", "image": "image/admin/5kuER6QRWs54zbYIJ4zS.jpg" }, + "xuezhoudai": { + "country": "CN", + "twitter": "imdaidr", + "github": "daidr", + "homepage": "https://im.daidr.me", + "image": "image/wVNVUJS8Z8O04i1tJKSdsp6nkRQ2/40TNtORm0BtUUR2IeF8Z.jpg" + }, "hadrijau": { "country": "DE", "github": "hadrijau", diff --git a/site/_data/i18n/authors.yaml b/site/_data/i18n/authors.yaml index 91a830f95..8676e163e 100644 --- a/site/_data/i18n/authors.yaml +++ b/site/_data/i18n/authors.yaml @@ -1531,6 +1531,12 @@ samrichard: en: 'Sam Richard' description: en: 'Developer Advocate, Google ChromeOS' +xuezhoudai: + title: + en: 'Xuezhou Dai' + zh: '戴学舟' + description: + en: 'Summer of Code ''23 Contributor' hadrijau: title: en: 'Hadrien Jaubert' diff --git a/site/en/blog/google-summer-of-code-and-chrome-extensions/index.md b/site/en/blog/google-summer-of-code-and-chrome-extensions/index.md new file mode 100644 index 000000000..905abce64 --- /dev/null +++ b/site/en/blog/google-summer-of-code-and-chrome-extensions/index.md @@ -0,0 +1,103 @@ +--- +layout: 'layouts/blog-post.njk' +title: Google Summer of Code and Chrome Extensions +description: > + Experience and advice on participating in Google Summer of Code. +date: 2023-09-04 +authors: + - xuezhoudai + +hero: 'image/wVNVUJS8Z8O04i1tJKSdsp6nkRQ2/8ZNtuWAIcc7NBdS3AQEv.jpg' +alt: > + Google Summer of Code and Chrome Extensions + +sharing_image: 'image/wVNVUJS8Z8O04i1tJKSdsp6nkRQ2/8ZNtuWAIcc7NBdS3AQEv.jpg' +--- + +I'm a sophomore from China passionate about web development. In my first year, I joined a technical club at our college. This club was my introduction to coding and open source. In the club, I met a group of like-minded partners who love coding. And it was from them that I learned about Google Summer of Code at the beginning of 2023. This Google-organized global program connects students with open-source organizations and guides them in making good use of their summer by participating in open-source activities. + +Giving it a try, I submitted my application. Fortunately, I was accepted. The summer I spent contributing to the Chrome Extension Samples repo has been memorable and precious. Of course, I've also learned a lot: effective communication, coding skills, and planning abilities, among other things. + +As GSoC 2023 is drawing to a close, it's worth sharing some of my experiences in GSoC. This post will briefly introduce the general process of GSoC through my own participation, hoping to be helpful to you! + +## The story of how I contributed to GSoC + +I applied for the Chromium GSoC 2023 Project, where my main task would be upgrading existing Chrome extension samples to work in Manifest V3, including some related scripts and documents. + +### At the Very Beginning + +I first learned of GSoC in February 2023 but was not yet sure I wanted to apply. I had a few concerns back then: + +* I'm introverted, and English is not my native language, so communication with mentors might be challenging. +* GSoC communities come from all over the world, and dealing with time zone differences could be difficult. +* GSoC is such a renowned program that it can be competitive, making my chances seem slim. + +However, I can confidently say none of these were an issue. + +Before I tell my story, I'd like to talk about something that happened to me at the beginning of 2022. This incident was also an opportunity for me to participate in GSoC. I had wanted to migrate a browser extension based on Manifest V2 to Manifest V3. To complete the migration, I had to refer to the documentation and understand every API change. I also had to search for whether there were relevant samples for reference. Comprehending the new API and transferring the code is quite challenging for me. + +That's why I was highly excited when browsing the GSoC project list and catching the idea related to MV3. I was eager to contribute to improving the Manifest V3 extension samples and provide an amenity for future developers. + +In March, I emailed Oliver, one of the mentors in charge, a brief email about my intention: + +{% Details 'open' %} +{% DetailsSummary %} +The application to participate in the GSoC project +{% endDetailsSummary %} + +Hi, + +I am a CS undergraduate student from China. I learned about the Chrome Extensions Samples related project at GSoC and I was interested in improving the Manifest V3 Samples. I don't have much prior experience in working on API Samples, however, I have experience in web development and MV3 extension development (https://github.com/daidr/paimon-webext), which has made me realize the importance of MV3 api samples, so I would like both to learn and to contribute to it. Can I still apply for this project? + +Thanks. + +{% endDetails %} + +Not long after, I received a reply from Oliver and Ali (Oliver's boss). They answered my questions and provided detailed information about the specific rules and timeline of GSoC. They also shared many valuable reference materials with me. + +It was like a shot in the arm, strengthening my determination to move forward. Taking the first step is paramount if you are interested in participating in upcoming open-source events, whether GSoC 2024 or anything else; never hesitate and bravely try it. + +Before applying, I checked the project's code and skimmed the documentation. Although GSoC provides a community bonding period of nearly one month for participants to familiarize themselves with the community, prior knowledge alleviated pressure and allowed me to write a more targeted proposal. + +I tried solving starter bugs provided by the project. These issues were relatively simple and helped me quickly understand the project. I'm grateful for my mentor Oliver (although he wasn't my mentor then). He promptly replied to my emails whenever I needed clarification and patiently resolved my problems. When encountering issues while writing a proposal, you can also send it to your mentor to see if any areas need improvement. + +### Getting accepted + +Writing a proposal is the last thing to do before applying. The proposal should include ideas, goals, and a schedule in addition to the application form. Depending on the +project you're hoping to work on, you may be provided with an additional template for the proposal. Many ready-made proposal examples are available online for reference. + +After completing the draft, I sent it to my mentor for feedback. Once the application is submitted, there's a long wait. And in early May, I received a notification that I was accepted. + +### Code Work + +During the initial bonding period, I first dealt with the remaining starter bugs and checked if there were any new skills I had to learn. And I spend the rest of the time reading documentation. + +After a discussion with my mentor, we adjusted some goals to make the time allocated to tasks more reasonable. We also discussed an idea for creating a new developer.chrome.com page listing all API samples and providing basic filters to help developers locate the needed samples quickly. It was a rather complex task for me, and it took my mentor and me quite some time to define the project and write a [product requirements doc](https://en.wikipedia.org/wiki/Product_requirements_document) (PRD). + +For this larger task, we decided that we needed an automated script in the samples repo to traverse the repository and generate a JSON file containing a list of extension samples and the APIs they use. The developer.chrome.com documentation repo now uses this file to build a page. + +I first considered using Babel to analyze the sample code's [Abstract Syntax Tree](https://en.wikipedia.org/wiki/Abstract_syntax_tree) and identify the APIs it used. After sharing this idea with my mentor, I discovered they had previously worked on something similar, confirming this approach's feasibility. After I completed the code, my mentor and other members of his team provided valuable suggestions including paying attention to code segmentation, standardizing code style, and documenting functions properly. + +After several big and small reviews, the code was successfully merged. You can find the whole thread on [GitHub](https://github.com/GoogleChrome/developer.chrome.com/pull/7029), or [view the live page](/docs/extensions/samples). + +## Wrapping Up + +If you ask me what GSoC has brought me: first of all, of course, is understanding the knowledge related to browser extension APIs. By reading the documentation and writing new samples, I gained a detailed understanding of various browser extension APIs. + +Additionally, I have acquired many skills I had little exposure to before being accepted for GSoC, such as following a comprehensive code review process and creating a PRD. I've also started using GitHub actions to automate workflows and learned how to use Babel to traverse all extension samples and track the APIs used. Moreover, I had my first experience with the Nunjucks template engine. These abilities are essential for programming, and I am delighted that I learned them. Participating in open-source communities brings me joy. + +This summer has given me many indelible memories. Coding makes me highly content. I have encountered patient mentors who guided me and taught me interesting knowledge, enriching my experience. + +The knowledge in the field of computer science is endless. When I compared myself with others, I realized my understanding of open source was only the tip of the iceberg. However, every little bit helps. I believe GSoC is a great starting point for participating in open source. + +I also hope my experience can provide some reference for future participation in open-source activities. + +Here are some of my suggestions for anyone wanting to participate in Google Summer of Code: + +1. Choose an idea that suits you: In my opinion, when looking for ideas, interest should be your priority, followed by skills. This strategy will allow you to maintain enthusiasm throughout the contribution process. +2. Quality over quantity: You can submit many proposals to increase the chances of being accepted for GSoC. However, I believe that quality is probably more critical because human energy is limited. Focusing on two or three ideas may be more helpful in the end. +3. Don't be afraid of new things: Don't hesitate to try technologies you haven't worked with in a project. You have nearly a month of community bonding to familiarize yourself with unfamiliar technologies and a whole summer to implement them. Just go for it! +4. Get acquainted with the project in advance: For example, read through development documentation, look at previous commit history and issues, and skim through past pull requests. Getting an overall understanding of the project in advance will help you write a more comprehensive proposal. +5. Maintain communication: Regularly communicate with your mentor, and don't hesitate to ask questions when confronting problems, whether before applying or after being accepted. Most mentors are willing to help you solve problems; this way, they can also keep track of your progress. + +Thank you for reading. From 1ef0f94e9237ab014d6b8596df7c631da8e023f4 Mon Sep 17 00:00:00 2001 From: Barry Pollard Date: Mon, 4 Sep 2023 15:34:13 +0100 Subject: [PATCH 749/982] Fix prerender analytics (#7238) * Move Origin Trial token to top of page * Only initialise after activation * Clean up speculation rules --- site/_includes/layouts/base.njk | 18 ++++++------------ site/_js/analytics.js | 3 ++- 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/site/_includes/layouts/base.njk b/site/_includes/layouts/base.njk index 9edaedf04..3e1c9daf1 100644 --- a/site/_includes/layouts/base.njk +++ b/site/_includes/layouts/base.njk @@ -7,6 +7,10 @@ {%- endif %} + {# Dogfood document speculation rules origin trial #} + + + {% include 'partials/meta.njk' %} {% block feed %} @@ -40,9 +44,6 @@ {% endfor %} {% endif %} - {# Dogfood document speculation rules origin trial #} - - {# Exclude the /articles/ section as a control #} - -``` +Bundle third-party libraries +: If you are using a popular framework like React or Bootstrap which you were previously loading from an external server, you can download the minified files, add them to your project and import them locally. For example: + ```html + + + ``` + In some cases, libraries, such as Firebase, will fetch additional code on a by need basis at runtime. In this case, you have to download all possible dynamic imports at build time. Here is an [example script that bundles Firebase using Rollup.js][firebase]. -To include a library in a service worker set the `"background.type"` to `"module"` in the manifest and use an `import` statement. +Look for other workarounds +: If the previous approaches don’t help with your use case you might have to either find an alternative solution (i.e. migrate to a different library) or find other ways to use the library's functionality. For example, in the case of Google Analytics, you can switch to the Google measurement protocol instead of using the official remote hosted JavaScript version as described in our [Google Analytics 4 guide][google-analytics]. ### Use external libraries in tab-injected scripts {: #use-external-libraries } @@ -151,5 +162,11 @@ Manifest V3 disallows certain content security policy values in the `"extension_ Content security policy values for `sandbox` have no such new restrictions. - [mdn-cdn]: https://developer.mozilla.org/docs/Glossary/CDN +[sandbox-eval]: /docs/extensions/mv3/sandboxingEval/ +[insert-css]: /docs/extensions/reference/scripting/#method-insertCSS +[inspect-window-eval]: /docs/extensions/reference/devtools_inspectedWindow/ +[send-command]: /docs/extensions/reference/debugger/#method-sendCommand +[firebase]: https://gist.github.com/patrickkettner/8c1a91b1b8f9502b3b67d874e7024a7b +[google-analytics]: /docs/extensions/mv3/tut_analytics/ + From 3f3b0a11dfa0884e82375e3bc136b2f3fe51f841 Mon Sep 17 00:00:00 2001 From: wizardofdocs <83661258+wizardofdocs@users.noreply.github.com> Date: Wed, 6 Sep 2023 06:27:49 -0700 Subject: [PATCH 755/982] Reformatted argument table in Settings Override to definition list (#7244) I've left a couple of clarification questions in comments. --- .../extensions/mv3/settings_override/index.md | 153 +++++------------- 1 file changed, 43 insertions(+), 110 deletions(-) diff --git a/site/en/docs/extensions/mv3/settings_override/index.md b/site/en/docs/extensions/mv3/settings_override/index.md index 96d2ca60a..819626233 100644 --- a/site/en/docs/extensions/mv3/settings_override/index.md +++ b/site/en/docs/extensions/mv3/settings_override/index.md @@ -82,121 +82,54 @@ Values in the manifest can be customized in the following ways: An extension can override one or more of the following properties in the manifest: +`alternate_urls` (array of strings, optional) +: A list of URL patterns that can be used in addition to `search_url.` + +`encoding` (string, optional) +: The encoding used for search terms. This is required if you don't set `prepopulated_id`. + +`favicon_url` (string, optional) +: An icon URL for the search engine. This is required if you don't set `prepopulated_id`. + `homepage` (string, optional) -: New value for the homepage. +: The new value for the homepage. + +`image_url` (string, optional) +: The URL the search engine uses for image search. If this isn't used, the engine doesn't support image search. + +`image_url_post_params` (string, optional) +: The post parameters for `image_url`. + +`is_default` (boolean, required) +: Specifies whether the search provider should be default. + +`keyword` (string, optional) +: An omnibox keyword for the search engine. This is required if you don't set `prepopulated_id`. + +`name` (string, optional) +: Name of the search engine displayed to user. This is required if you don't set `prepopulated_id`. + +`prepopulated_id` (integer, optional) +: An ID for Chrome's built-in search engine. `search_provider` (object, optional) -: A search engine - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
TypeAttributeDescription
string(optional) name -

Name of the search engine displayed to user. This may only be omitted if - prepopulated_id is set.

-
string(optional) keyword -

Omnibox keyword for the search engine. This may only be omitted if - prepopulated_id is set.

-
string(optional) favicon_url -

An icon URL for the search engine. This may only be omitted if prepopulated_id - is set.

-
stringsearch_url -

A search URL used by the search engine.

-
string(optional) encoding -

Encoding of the search term. This may only be omitted if prepopulated_id is - set.

-
string(optional) suggest_url -

If omitted, this engine does not support suggestions.

-
string(optional) image_url -

If omitted, this engine does not support image search.

-
string(optional) search_url_post_params -

The string of post parameters to search_url

-
string(optional) suggest_url_post_params -

The string of post parameters to suggest_url

-
string(optional) image_url_post_params -

The string of post parameters to image_url

-
array of string(optional) alternate_urls -

A list of URL patterns that can be used, in addition to search_url.

-
integer(optional) prepopulated_id -

An ID of the built-in search engine in Chrome.

-
booleanis_default -

Specifies if the search provider should be default.

-
- -`startup_pages` (array of string, optional) +: A search engine. + +`search_url` (string, required) +: The search URL the search engine uses. + +`search_url_post_params` (string, optional) +: The post parameters for `search_url`. + +`startup_pages` (array of strings, optional) : An array of length one containing a URL to be used as the startup page. +`suggest_url` (string, optional) +: The URL the search engine uses for suggestions. If this isn't used, the engine doesn't support suggestions. + +`suggest_url_post_params` (string, optional) +: The post parameters for `suggest_url`. + [1]: #homepage [2]: #search_provider [3]: #startup_pages From 67f4c6373e48f1a79b3c7c2d9612d77cb702f278 Mon Sep 17 00:00:00 2001 From: Nancymic2 Date: Wed, 6 Sep 2023 09:31:01 -0400 Subject: [PATCH 756/982] Nits (#7241) * Nits * link --- .../shared-storage/content-selection/index.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/site/en/docs/privacy-sandbox/shared-storage/content-selection/index.md b/site/en/docs/privacy-sandbox/shared-storage/content-selection/index.md index 8c564a5b7..5aef89d8c 100644 --- a/site/en/docs/privacy-sandbox/shared-storage/content-selection/index.md +++ b/site/en/docs/privacy-sandbox/shared-storage/content-selection/index.md @@ -2,10 +2,10 @@ layout: 'layouts/doc-post.njk' title: 'Content selection with Shared Storage' subhead: > - Select a URL based on data collected in Shared Storage render the + Select a URL based on data collected in Shared Storage, and render the content in a fenced frame. description: > - Select a URL based on data collected in Shared Storage render the + Select a URL based on data collected in Shared Storage, and render the content in a fenced frame. date: 2023-04-14 authors: @@ -43,11 +43,11 @@ When a user first observes a winning ad space, you can store an ID and click sta width="800", height="354" %}
-Your JavaScript runs in a worklet to retrieve this information, but your code +Your JavaScript runs in a [worklet](/docs/privacy-sandbox/glossary/#worklet) to retrieve this information, but your code cannot interact with or communicate outside of the iframe or fenced frame on the parent page. -Let's take another example. Let's say you're interested in testing what article +Let's take another example. Let's say you're interested in testing which article would perform better in an embedded context. You can assign a user to an experiment group when you see that user on your site, then store that group ID in Shared Storage to be accessed in a cross-site context. On another site, your @@ -97,7 +97,7 @@ To test, you must enable the **Privacy Sandbox Ads APIs experiment** flag at A [demo is available](https://shared-storage-demo.web.app/), and you can review the code on [GitHub](https://github.com/GoogleChromeLabs/shared-storage-demo). -This demo is constructed from the perspective of an advertiser, adtech, content +This demo is constructed from the perspective of an advertiser, ad tech, content distributor or other third-party service that wants to store information across different publishers' sites. In the demo, the same third-party code runs on both Publisher A and Publisher B sites for each use case. Visit each From 26ac332b9dcbc81008dcde5ec31214eb48bba3fb Mon Sep 17 00:00:00 2001 From: Nancymic2 Date: Wed, 6 Sep 2023 09:54:41 -0400 Subject: [PATCH 757/982] Add ARA note (#7226) --- .../attribution-reporting/aggregation-keys/index.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/site/en/docs/privacy-sandbox/attribution-reporting/aggregation-keys/index.md b/site/en/docs/privacy-sandbox/attribution-reporting/aggregation-keys/index.md index 592d9aa70..6cdb12223 100644 --- a/site/en/docs/privacy-sandbox/attribution-reporting/aggregation-keys/index.md +++ b/site/en/docs/privacy-sandbox/attribution-reporting/aggregation-keys/index.md @@ -2,9 +2,9 @@ layout: 'layouts/doc-post.njk' title: 'Understanding aggregation keys' subhead: > - What aggregation keys are, how they're used, and how you can translate goals into keys. + What aggregation keys are, how they're used in the Attribution Reporting API, and how you can translate goals into keys. description: > - What aggregation keys are, how they're used, and how you can translate goals into keys. + What aggregation keys are, how they're used in the Attribution Reporting API, and how you can translate goals into keys. date: 2022-12-15 updated: 2023-08-25 authors: @@ -24,6 +24,10 @@ To do so, you'll need to think of what questions you want to answer before data To answer these questions, let's take a look at dimensions, keys, and values. +{% Aside %} +The aggregation keys discussed in this document are specific to the Attribuion Reporting API. +{% endAside %} + ### Dimensions To understand how your campaigns are generating revenue, as described here, you'll want to track the following dimensions: From 06203da3c0ab5192533dab031639669fb8452ef4 Mon Sep 17 00:00:00 2001 From: Nancymic2 Date: Wed, 6 Sep 2023 11:24:53 -0400 Subject: [PATCH 758/982] Nancy appweb (#6978) * web to app * app to web * web to app * web to app * Update index.md * edit * Update site/en/docs/privacy-sandbox/attribution-reporting/web-to-app-attribution/index.md Co-authored-by: Anusmita * Update index.md * add author * Update site/en/docs/privacy-sandbox/attribution-reporting/web-to-app-attribution/index.md Co-authored-by: Anusmita * Update date * Update date * essentially a noop to rerun stuck tests --------- Co-authored-by: Anusmita --- site/_data/docs/privacy-sandbox/toc.yml | 1 + .../web-to-app-attribution/index.md | 45 +++++++++++++++++++ 2 files changed, 46 insertions(+) create mode 100644 site/en/docs/privacy-sandbox/attribution-reporting/web-to-app-attribution/index.md diff --git a/site/_data/docs/privacy-sandbox/toc.yml b/site/_data/docs/privacy-sandbox/toc.yml index f6b52e465..ad6a07754 100644 --- a/site/_data/docs/privacy-sandbox/toc.yml +++ b/site/_data/docs/privacy-sandbox/toc.yml @@ -122,6 +122,7 @@ - url: /docs/privacy-sandbox/attribution-reporting/multiple-reporters/ - url: /docs/privacy-sandbox/attribution-reporting/report-schedules/ - url: /docs/privacy-sandbox/attribution-reporting/constraints/ + - url: /docs/privacy-sandbox/attribution-reporting/web-to-app-attribution/ - url: /docs/privacy-sandbox/attribution-reporting/aggregation-keys/ - url: /docs/privacy-sandbox/attribution-reporting/understanding-noise/ - url: /docs/privacy-sandbox/attribution-reporting/working-with-noise/ diff --git a/site/en/docs/privacy-sandbox/attribution-reporting/web-to-app-attribution/index.md b/site/en/docs/privacy-sandbox/attribution-reporting/web-to-app-attribution/index.md new file mode 100644 index 000000000..4a73cbd1b --- /dev/null +++ b/site/en/docs/privacy-sandbox/attribution-reporting/web-to-app-attribution/index.md @@ -0,0 +1,45 @@ +--- +layout: 'layouts/doc-post.njk' +title: 'Web-to-app and app-to-web measurement' +subhead: > + Learn how your Chrome web app can pass attributions to your Android app. +description: > + Learn how your Chrome web app can pass attributions to your Android app. +date: 2023-09-06 +authors: + - maudn + - nmichell +--- + +The Privacy Sandbox natively supports web-to-app and app-to-web attribution, and the Attribution Reporting API allows measurement across mobile browsers and Android apps. + +## What is web-to-app attribution? + +If a user clicks an ad in a Chrome mobile browser, then goes on to later make a purchase in an Android app, the Attribution Reporting API can directly attribute that conversion performed in the Android app to the ads shown in the Chrome mobile browser. That's web-to-app attribution. + +Similarly, if a user clicks an ad in an Android app, and then goes on to later make a purchase in a Chrome mobile browser, the Attribution Reporting API can directly attribute that conversion. That's app-to-web attribution. + +The API records web-to-app attributions when they occur on the same device. + +## How is web-to-app attribution implemented? + +To implement web-to-app attribution, first make sure that web-to-app and app-to-web measurement is available in your web code base. +To do this, when you register an event, include the `Attribution-Reporting-Eligible` header +in your request to the reporting origin. + +The browser will broadcast if OS-level support is available to the reporting origin server with a dictionary-structured request header. + +Then continue to register that the ad was clicked by [registering a source](/docs/privacy-sandbox-attribution-reporting/register-source/). + +If OS support is available, the reporting origin should send back a response with the string structured header, `Attribution-Reporting-Register-OS-Source`, which includes the URL indicating where to register the source. + +The response is similar to how the reporting origin would respond when performing web-to-web measurement, but in this case, it indicates that the Android OS should handle the reporting instead of the Chrome browser. + +The response metadata includes both web and app destinations. These destination fields specify the website and app package where attribution will be triggered for the source. + +Under the hood, the `Attribution-Reporting-Register-OS-Source` header signals the Android OS to call register web source, which takes the metadata from the header and packages it up to send to the ad-tech URL specified in `Attribution-Reporting-Register-OS-Source`. You don't need to call `registerWebSource()` directly. + +## Next steps + +- Read more about web-to-app attribution in [Cross App and Web Attribution Measurement](https://github.com/WICG/attribution-reporting-api/blob/main/app_to_web.md). +- Also check out [Attribution reporting: cross app and web measurement](https://developer.android.com/design-for-safety/privacy-sandbox/attribution-app-to-web). From 6198d7e947158bc29b909755627cc1e0112351f4 Mon Sep 17 00:00:00 2001 From: Kara Date: Wed, 6 Sep 2023 14:16:06 -0700 Subject: [PATCH 759/982] Updated "recent projects" to become "recent blog posts" (#7189) --- site/en/aurora/index.njk | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/site/en/aurora/index.njk b/site/en/aurora/index.njk index 43fd9332f..ff7b8575f 100644 --- a/site/en/aurora/index.njk +++ b/site/en/aurora/index.njk @@ -13,10 +13,19 @@ sections: - url: /blog/aurora-update-2023 title: What is Aurora focusing on now? description: In 2023, the Aurora team is focusing on improving Core Web Vitals for applications using web frameworks. We are currently partnering with Next.js, Angular, and Nuxt to ship performance features. - projects: + blogs: + - url: /blog/aurora-update-2023/ + title: "What's New with Aurora?" + description: "Check out our recent project releases, as well as a roadmap for 2023 and beyond." - url: /blog/framework-tools-font-fallback/ title: "Framework tools for font fallbacks" description: "Master how to adjust the size of your font fallbacks to prevent Cumulative Layout Shift (CLS), using tools in Next.js, Nuxt, Vite, and Capsize." + - url: /blog/font-fallbacks + title: "Improved font fallbacks" + description: "Dive deep into the methodology behind generating font fallbacks and the size-adjust, ascent-override, descent-override, and line-gap-override APIs. " + - url: /blog/inside-the-container-query-polyfill/ + title: "Inside the container query polyfill" + description: "Take a peek inside how the polyfill works, the challenges it overcomes, and the best practices when using it to provide a great user experience." - url: /blog/angular-image-directive/ title: "Optimizing Images with the Angular Image Directive" description: "Learn how the Angular image directive can improve Largest Contentful Paint (LCP), now available from version 14." @@ -84,9 +93,9 @@ sections: }} {{ landingSection( - 'Recent Projects', + 'Recent Blog Posts', 'Read about our 2022-2023 focus areas in more detail.', - sections.projects, + sections.blogs, 'green', 'top-3', true, From 7319cc6ba5b6b39625ca7966724605d096e0b064 Mon Sep 17 00:00:00 2001 From: Joe Medley Date: Thu, 7 Sep 2023 11:13:20 -0700 Subject: [PATCH 760/982] Small edit (#7252) --- site/en/docs/extensions/reference/action/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/en/docs/extensions/reference/action/index.md b/site/en/docs/extensions/reference/action/index.md index 85ca883be..ec34516ea 100644 --- a/site/en/docs/extensions/reference/action/index.md +++ b/site/en/docs/extensions/reference/action/index.md @@ -12,7 +12,7 @@ not specified. ## Manifest -In order to use the `chrome.action` API, you need to specify a `"manifest_version"` of `3` or higher +To use the `chrome.action` API, you need to specify a `"manifest_version"` of `3` or higher and include the `action` key in your [manifest file][doc-manifest]. ```json From 655b3b9669b96cf8c359cc641ee017a5a9abdfda Mon Sep 17 00:00:00 2001 From: Demian Renzulli Date: Fri, 8 Sep 2023 02:20:04 -0300 Subject: [PATCH 761/982] Updating "Transitioning from Chrome Apps" article (#7076) * Updating Transitioning from Chrome Apps article. * Adding line break * Google photos update * Apply suggestions from code review Co-authored-by: Rachel Andrew * Discord channel link. * Update site/en/docs/apps/migration/index.md --------- Co-authored-by: Rachel Andrew --- site/_data/authorsData.json | 4 + site/_data/i18n/authors.yaml | 7 +- site/en/docs/apps/migration/index.md | 464 ++++++--------------------- 3 files changed, 111 insertions(+), 364 deletions(-) diff --git a/site/_data/authorsData.json b/site/_data/authorsData.json index a0f691e92..a69bd7519 100644 --- a/site/_data/authorsData.json +++ b/site/_data/authorsData.json @@ -1865,6 +1865,10 @@ "hemeryar": { "country": "FR", "github": "hemeryar" + }, + "paulrossman": { + "country": "US", + "github": "paulrossman" }, "nrosenthal": { "country": "IL", diff --git a/site/_data/i18n/authors.yaml b/site/_data/i18n/authors.yaml index 8676e163e..655cc6d7b 100644 --- a/site/_data/i18n/authors.yaml +++ b/site/_data/i18n/authors.yaml @@ -1521,6 +1521,11 @@ hemeryar: en: 'Arthur Hemery' description: en: 'Software Engineer, Google' +paulrossman: + title: + en: 'Paul Rossman' + description: + en: 'Paul is a Technical Program Manager at Google' nrosenthal: title: en: 'Noam Rosenthal' @@ -1566,4 +1571,4 @@ ferreiram: title: en: 'Maxi Ferreira' description: - en: 'Creator, FrontendAtScale' \ No newline at end of file + en: 'Creator, FrontendAtScale' diff --git a/site/en/docs/apps/migration/index.md b/site/en/docs/apps/migration/index.md index 840fae4cb..68a7fecb2 100644 --- a/site/en/docs/apps/migration/index.md +++ b/site/en/docs/apps/migration/index.md @@ -2,415 +2,153 @@ layout: "layouts/doc-post.njk" title: "Transitioning from Chrome Apps" date: 2016-08-18 -updated: 2019-12-02 +updated: 2023-09-08 description: How to migrate your Chrome packaged or hosted app. +authors: + - demianrenzulli + - paulrossman --- {% Aside 'caution' %} -**Important:** Chrome will be removing support for Chrome Apps on all platforms. Chrome browser and -the Chrome Web Store will continue to support extensions. [**Read the announcement**][1] and learn -more about [**migrating your app**][2]. +**Important:** As [previously announced on the Chromium Blog][1], we are phasing out support for Chrome Apps in favor of web applications. From Chrome 112, Chrome Apps on Windows, Mac, and Linux no longer work. Based on feedback from ChromeOS Enterprise and Education customers and developers, Chrome App support for those users on ChromeOS is extended until at least January 2025. {% endAside %} -To transition away from a Chrome packaged or hosted app, the following options are available. +## Migration options {: #migration-options } -## Chrome packaged apps {: #chrome-packaged-apps } +There are two primary options to migrate from Chrome Apps: web applications and Chrome Extensions: -Recommended migration options for packaged apps are listed in order from simplest to most -complicated. +{% Img src="image/26V1DWN36MZr3mUo8ChSBlCpzp43/DG9uvmotUXImXRu1Yhge.png", alt="Chrome app migration options. Web Applications or Chrome Extensions.", width="800", height="421" %} -### Build a Progressive Web App {: #build-pwa } +Web applications are the preferred path in most cases. Chrome Extensions can be used in some scenarios for use cases that the web doesn’t support, like running in the background without a user interface. -Building a [Progressive Web App][3] (PWA) is the ideal way to reach users across all operating -systems. -As part of our [Web Capabilities][4] (codename: [Fugu][5]) efforts, we are investigating ways to -improve the migration path to the web for developers that depend on exclusive Chrome App APIs—in -particular the Sockets, HID, File System, and Serial APIs. If there are web platform features you -need that are [only available in select browsers][6], you can use feature detection to gracefully -degrade or include explanatory text when your app is run in a browser that doesn't support a -particular API. If there are gaps in the web platform for your application, **[let us -know][7]**. +### Web applications {: #web-applications } -PWAs are installable on both [desktop][8] and [mobile][9] platforms. Users who choose to install -your PWA can launch it via icons and shortcuts, similar to the way that Chrome Apps can be installed -today. +The preferred alternative for migrating from Chrome Apps is to build a web application. By doing so you can use advanced features, like those of the [web capabilities project][2]. The APIs that are part of the Capabilities project now cover most of the use cases that were previously achievable with Chrome App APIs. However, it is not mandatory to use any of these features: the flexibility of the web allows developers to choose the level of complexity that best suits their needs. -### Build an extension-enhanced web page {: #build-extension-web-page } +#### Advantages of web applications {: #advantages-web-applications } -If there is a capability that your Chrome App has that the regular web platform can't provide, it -might be available as an **[extension API][10]**. In this case, you use a **[progressive web app -together with an externally connectable extension your web app can send messages to][11]**. Building -a web app is typically preferable to this, because this approach forces users to install an -extension that is only useful on your site and can cause increased friction. +Web applications have some advantages over Chrome Apps: -As Chrome extensions can't be run on other browsers, you should detect when required functionality -isn't available and provide explanatory text for users on these other browsers. +- **Portability:** Chrome Apps only run in Chrome. Web applications run on most browsers and operating systems, although support for different APIs varies among them. +- **Developer experience:** Chrome Apps use the same technologies as web applications (HTML, JavaScript, and CSS), but some of Chrome Apps advanced capabilities (for example, background pages) are not standard, therefore requiring additional knowledge. +- **Feature set:** Chrome Apps rely on APIs that are no longer maintained or updated with new features. Web applications rely on the open web, which evolves continuously and has access to all the up-to-date APIs. +- **Installation and updates:** Chrome Apps require manual installation and updating, and sometimes require store reviews. Web applications can be accessed directly from a browser and can optionally be installed. Updates for web applications are instant upon deployment, as soon as the browser fetches the new files. +- **Support:** While both Chrome Apps and web applications have sizable communities, the web platform has a much larger presence and offers a broader range of development tools, such as frameworks and libraries, to support developers. -### Build an extension {: #build-extension } +#### Progressive Web Apps {: #progressive-web-apps } -Depending on the user experience you want to provide, it might make sense to convert your entire app -into an extension. For example you could provide a **[browser action][12]** button which shows a -small popup window for your user interface, or navigates to a page your extension provides. For some -apps, this might be a good enough user experience to be a viable solution. +Progressive Web Apps, or PWAs, are just web applications that are built and optimized with modern APIs to deliver enhanced capabilities, installability, and reliability. Implementing these functionalities allows you to achieve app-like experiences on the web. -Note there are significant costs to this approach. [While some browsers][13] support the same -extensions API as Chrome, this support is not universal. This can significant friction for your -users who would prefer a cross-browser alternative. +##### Installability {: #installability } -### Build for ChromeOS via Android {: #build-chromeos-android } +PWAs are [installable][4] on both desktop and mobile platforms, but this is optional, as they can still be accessed directly from the browser. Users who choose to install a PWA can launch it via icons and shortcuts. You can provide metadata in your PWA's [web manifest file][5] indicating that, when launched after installation, it will open in its own window. -If you are an Android developer interested in building for ChromeOS, you can optimize your Android -application for a better experience. +##### Reliability {: #reliability } -Chrome App API/Capability migration recommendations (current as of Nov. 2019): +PWAs have the ability to function consistently even under challenging network conditions. This is made possible by a core component of PWAs, known as [service workers][6]. Service workers allow you to intercept network requests and serve cached content to ensure that the app works offline or in scenarios of poor connectivity. Libraries like [Workbox][7], provide a set of out of the box strategies to let you implement common offline functionalities, greatly simplifying development. - - -
Chrome App feature/functionalityWeb platform migration recommendationsAndroid migration recommendationsExtension migration recommendations
chrome.accessibilityFeatureschrome.accessibilityFeatures
chrome.alarmsNotification TriggersWorkManagerchrome.alarms
chrome.app.runtimeLaunch EventActivity Lifecycle
chrome.app.runtime.onRestartedPage Life CycleActivity.onResume
chrome.app.windowWindow Placement / Screen Enumerationchrome.windows
chrome.audioAudio Device ClientSome Audio APIs
chrome.bluetoothWeb Bluetooth APIBluetooth API
chrome.bluetoothLowEnergyWeb Bluetooth APIBTLE
chrome.bluetoothSocketWeb Bluetooth APIBluetooth Socket
chrome.browserwindow.openIntent system
chrome.commandsUI EventsHard-code keyboard commandschrome.commands
chrome.contextMenus(HTML/script)Native, Android has its own contextmenus
chrome.documentScanchrome.documentScan
chrome.eventsAlarmschrome.events
chrome.extensionTypesN/Achrome.extensionTypes
chrome.fileSystemNative FileSystem API
chrome.fileSystemProviderFileSystemProviderchrome.fileSystemProvider
chrome.gcmWeb Push NotificationsN/Achrome.gcm
chrome.hidWeb HID API
chrome.i18n(HTML/script)Localizationchrome.i18n
chrome.identityOAuth API or Credential Management APINativechrome.identity
chrome.idleUser Idle Detection APIchrome.idle
chrome.instanceIDWeb pushPer-App ID needs to be self-generatedchrome.instanceID
chrome.mdnsNDS discovery
chrome.mediaGalleriesNative FileSystem API
chrome.networking.onc
chrome.notificationsNotifications APINotifications show in lower right of CrOS as system level notificationschrome.notifications
chrome.permissionsWeb Permissions APIN/Achrome.permissions
chrome.powerWakeLock APIIn discussionchrome.power
chrome.printerProviderTransition to Extensionandroid.printservicechrome.printerProvider
chrome.runtimeService Workers + Page Lifecycle APIchrome.runtime
chrome.runtime.connectChannel Messaging APIchrome.runtime.connect
chrome.runtime.sendMessagechrome.runtime.sendMessage
-chrome.serialWeb Serial API
chrome.sockets.tcpQuicTransport C/S (or WebSockets)android.net.ConnectivityManager and Java standard socket API
chrome.sockets.tcpServerandroid.net.ConnectivityManager and Java standard socket API
chrome.sockets.udpQuicTransport C/SDatagramSocket API for UDP
chrome.storageCache API
IndexedDB
chrome.storage
chrome.storage.managedManaged Configurationschrome.storage.managed
chrome.syncFileSystemJava - Drive REST API
chrome.system.cpunavigator.hardwareConcurrencychrome.system.cpu
chrome.system.displaywindow.screenDisplayMetrics, but high density displays are wonky
chrome.system.memorynavigator.deviceMemorychrome.system.memory
chrome.system.networkNetwork Information API
chrome.system.storagenavigator.storagechrome.system.storage
chrome.ttsWeb Speech API (Synthesis)Android TTS 2009chrome.tts
chrome.typeschrome.types
chrome.usbWeb USB API
chrome.virtualKeyboardSoft Input Method
chrome.vpnProviderVpnServicechrome.vpnProvider
chrome.wallpaperWallpaperManagerchrome.wallpaper
externally_connectable
kiosk_enabled
minimum_chrome_versionTarget Android versionminimum_chrome_version
offline_enabledOffline via Service WorkersNative
NaClMigration Guide
<webview> tagNativeWebView
+##### Enhanced capabilities {: #enhanced-capabilities } -## FAQs {: #faqs } +The [Web Capabilities project][8] enables web applications to achieve many use cases that Chrome Apps can implement. However, the web's security model imposes certain limitations. Here are some examples of advanced web capabilities that you can use instead of existing Chrome App APIs: -### Q: What if the Chrome App migration recommendations do not meet my use case requirements? {: #use-case-requirements } +- **Bluetooth and USB access:** [Web Bluetooth][9] and [Web USB][10] provide an alternative to [`chrome.bluetooth`][11] and [`chrome.usb`][12] respectively. +- **File System management:** The [File System Access API][13] is the alternative to [`chrome.fileSystem`][14] API. +- **Shortcuts:** Web apps can support keyboard shortcuts by listening to the various key events (e.g. [keydown][15]), but the shortcuts you can support are limited. When your web app is used in fullscreen mode, you are able to intercept these system shortcuts with the [Keyboard Lock API][16]. +- **Persistent Storage:** Requesting [Persistent Storage][17] permission within your web application can offer similar capabilities as the `unlimitedStorage` permission in Chrome Apps. +- **Geolocation:** The [Geolocation API][18] can be used in web apps to locate a user's position, as an alternative to the geolocation permission. +- **Background processing:** Alternatives to the `background` permission include the [Background Sync API][19] and the [Periodic Background Sync API][20]. +- **Copy to clipboard:** The [Async Clipboard API][21] allows you to copy and paste both text and images programmatically. -We'd like your feedback! [Fill out this form][167] with as much detail as possible. +### Chrome extensions {: #chrome-extensions } -### Q: My Chrome App has many users. What's the best way to migrate them to my new web app and deprecate my Chrome App? {: #best-migration-path } +Web applications are the best alternative to migrate from Chrome Apps, but Chrome extensions can be an option in some cases. Extensions are also built with web technologies (HTML, CSS, and JavaScript) and can be used to add or modify the browser's functionality and customize other web applications for better user experience. -You will still be able to publish updates to your Chrome App until the runtime is removed. We -recommend updating your app to include a message indicating that your app has been discontinued, and -that users should visit your website going forward (see example below). You can also include an -"uninstall" button that calls the [`uninstallSelf()`][168] method. +#### Build a standalone extension {: #build-standalone-extension } -Starting with Chrome 75, the [`installReplacementWebApp()`][169] method can be used inside of a -Chrome App, in response to a button click or other user gesture, to automatically trigger the -installation flow for your replacement PWA. +Depending on the user experience you want to provide, it might make sense to convert your Chrome App into an extension. For example, you could provide a [browser action][22] button which shows a small popup window for your user interface, or navigates to a page your extension provides. This UI model may be more suitable for apps that do most of their work in the background. -{% Img src="image/BrQidfK9jaQyIHwdw91aVpkPiib2/Qw8PhA0V122tSWZTRyw9.png", alt="Shows button that can link to install PWA", height="468", width="598" %} +#### Connect a Chrome extension from a web application {: #connect-extension-web-application } -### Q: I want to continue to have a UI affordance that enables users to launch my app from the taskbar/dock/homescreen. What should I do? {: #app-launcher } +If your Chrome App offers capabilities that are not available on the web platform, it may be possible to [connect a Chrome extension with a web application][23] and give it access to [extension APIs][24].The disadvantage of this approach is that users / IT admins have to manage two different parts (web application and companion extensions). It’s important to note that Chrome extensions can't be run on some browsers, you should detect when required functionality isn't available and provide explanatory text for users on these other browsers. -[Progressive Web Apps][170] are installable on both [desktop][171] and [mobile][172] platforms. -Users who choose to install your PWA can launch it via icons and shortcuts, similar to the way that -Chrome Apps can be installed today. +### Should I create a web application or a Chrome extension? {: #web-application-or-chrome-extension } -### Q: I want my app to run in its own window, not in a tab. Is this something I can do with a web app? {: #run-in-window } +A web application is the preferred technology to migrate to from Chrome Apps. There are a few use cases where Chrome extensions might be a better choice. Before deciding, analyze which option is better according to different factors: -You can provide [metadata][173] in your Progressive Web App's [manifest file][174] indicating that, -when launched after installation, it will open in its own window. +- **Purpose:** Chrome extensions are primarily used to extend the functionality of the browser. Common use cases include: productivity tools, web page content enrichment, and information aggregation. Web applications can have a much wider range of use cases by using the full power of the web. +- **User Experience:** Chrome extensions typically have a more limited user interface and are designed to integrate with the browser. Web applications can have a rich user interface that looks and feels like a native app and it’s highly customizable. +- **Portability:** Chrome Extensions are Chrome-specific. Some browsers (for example, [Firefox][25] and [Edge][26]) support the same extension APIs as Chrome, but this support is not universal. Web applications are supported by all the browsers (although not all the APIs might be). +- **Discoverability:** Chrome Extensions need to be installed (for example, from the Chrome Web Store or via self hosting) and accessed via the browser toolbar. Web applications can be instantly loaded via a URL and accessed from all the browsers. They can optionally be installed but this is not mandatory. +- **Feature set:** Chrome Extensions have a deep integration with Chrome, through Chrome APIs. Web applications might be more limited in low-level or system-level tasks. As discussed, it's possible to [call an extension from a web application][27] to have access to extension-only APIs. +- **Background work:** Chrome extensions can perform background work and run even when the browser window is closed. Web applications, on the other hand, are typically designed to run in the foreground and have more limited background capabilities, mostly used for performance and reliability. -### Q: My app supports keyboard shortcuts. Can the web support this also? {: #keyboard-shortcuts } +## Migration steps -Web apps can support keyboard shortcuts by listening to the various key events (e.g. -**[keydown][175]**), but the shortcuts you can support are limited. For example, you cannot -intercept Ctrl+N, Ctrl+T etc. as these are used by the browser. Or, these might be shortcuts that -are handled by the operating system (e.g. Alt+Tab on Windows). +### Migrating your Chrome Apps -When your web app is used in [fullscreen][176] mode, you are able to [intercept][177] these system -shortcuts. +Follow these steps to migrate from a Chrome App to web applications or Chrome extensions: -The **[Extension Commands API][178]** supports richer keyboard shortcuts which operate across the -entire browser, which may enable new capabilities if transitioning to an extension is possible. +1. **Scope your app functionality:** In some cases your app will dictate if you must go for a web application or if your only choice is to build a Chrome Extension. In cases where both can suit your needs you have a choice. Check out the [Web Capabilities site][28] and [Chrome Extension API reference][29] to learn more about what each technology has to offer. +1. **Learn and build:** Follow the learning resources to know about technologies and get your app up and running. The [PWA training][30] and the [Getting Started Chrome Extension][31] guides are great resources to get started on each of these technologies. +1. **Test and distribute:** Offer your new app to a smaller percentage of users before a broader rollout to make sure it works well. To distribute them more widely, web applications can be accessed and installed from the browser. Chrome extensions are usually distributed via the Chrome Web Store or self-hosted. Both can be forced installed by admins in managed scenarios. -### Q: My app needs to run when the user is offline. Can I do that with a web app? {: #offline-app } +### Migrating your users -Yes, you can **[use service workers to make your site run offline][179]**. The [Workbox][180] -project can simplify developing a full-featured caching strategy for your service worker. +Regardless of the technology you have chosen to migrate from Chrome Apps, you need to tell your users to uninstall the current app and guide them to the new experience. +We recommend updating your app to include a message indicating that it has been discontinued, and that users should visit your website or the Chrome Web Store going forward (see the following example). You can also include an "uninstall" button that calls the [`uninstallSelf()`][32] method. +From Chrome 75, the [`installReplacementWebApp()`][33] method can be used inside of a Chrome App, in response to a button click or other user gesture, to automatically trigger the installation flow for your replacement web application. -### Q: My app uses the chrome.gcm API to receive push messages from the cloud. Can the open web do that? {: #push-messages } +{% Img src="image/26V1DWN36MZr3mUo8ChSBlCpzp43/Ci5PDjsTJmh0hp1E5DBr.png", alt="Google Photos Chrome App replacement.", width="598", height="468" %} -Yes, assuming the user has granted permission, the **[Push API and Notifications API][181]** can -allow your web app to show your user push notifications. +An additional consideration is to inform Chrome Enterprise browser and ChromeOS Enterprise admins to update their app policies for their organizations. It is common for Enterprise and Education managed users to have their apps and extensions [force-installed via management policy][34]. +Developers should inform admins to update their [ExtensionInstallForcelist policy][35] (used to install Chrome Apps) and replace it with the [WebAppInstallForceList policy][36] with your web app’s URL: -### Q: My app needs to be able to show notifications to the user even when it has no windows open. Can I do that with the open web? {: #show-notifications } +{% Img src="image/26V1DWN36MZr3mUo8ChSBlCpzp43/Dw3v8JgKRxeEQwy9HikV.png", alt="Admin Console Extension and Web App force install policy.", width="598", height="468" %} -Yes, the **[Push API and Notifications API][182]** can allow your web app to show your user push -notifications even when your web app is closed, as long as an instance of the browser is running. +## Support -### Q: My app uses chrome.bluetooth/chrome.usb to talk to a Bluetooth/USB device. Can this be done on the open web? {: #bluetooth } +If you have any technical questions here are some resources you can use to get support: -Both [Web Bluetooth][183] and [Web USB][184] are available in certain browsers, and can be used -(along with feature detection) in a Progressive Web App. - -### Q: My app uses the chrome.fileSystem API to read and write user-specified files and / or directories. Can this be done on the open web? {: #fileSystem } - -The open web can read single files that the user opens, but cannot retain access to those files, -write to those files, or have any access to directories. - -There are plans to [implement direct filesystem access][185], and an experimental implementation is -available in Chrome, but that functionality has not yet been fully standardized. - -### Q: My app uses the chrome sockets API to do networking. Can this be done with the open web? {: #sockets } - -You might be able to do what you need with **[WebSockets][186]**. However, to use this, you will -likely need to change the remote end of your connection. - -If that isn't possible, we'd like to hear more about your use case—let us know about what -you're trying to accomplish [via the Chromium issue tracker][187]. - -### Q: What resources are available to help with a Progressive Web App migration? {: #migration-resources } - -The Chrome team maintains the following sites and tools with information that can help during your -migration: - -- [Web Capabilities][188] overview -- [Progressive Web Apps Training][189] -- [Workbox][190], for generating a service worker - -If you have a specific question not addressed via those resources, we recommend asking a question on -[Stack Overflow][191]. This [template][192] can be used to create a question tagged with both -[`google-chrome-app`][193] and [`progressive-web-apps`][194], to ensure maximum visibility. - -### Q: I'd like to use a capability not mentioned already that lacks a web alternative. How do I make a feature request? {: #missing-capability } - -We'd like to hear more about what you're trying to accomplish— let us know [via the Chromium issue -tracker][195]. - -## Chrome hosted apps {: #hosted-apps } - -## FAQs {: #hosted-apps-faqs } - -### Q: My hosted app uses the notifications permission. How do I do that on the web? {: #hosted-apps-notifications-permission } - -Yes, assuming the user has granted permission, the **[Push API and Notifications API][196]** can -allow your web app to show your user push notifications. - -### Q: My hosted app uses the unlimitedStorage permission. How do I do that on the web? {: #unlimitedStorage } - -The unlimitedStorage permission ensured that data you store was 'Persistent', which means it can -only be cleared manually by the user. - -The recommended alternative is to request **[Persistent Storage][197]** permission within your web -app. - -### Q: My hosted app uses the geolocation permission. How do I do that on the web? {: #geolocation } - -The **[Geolocation API][198]** can be used in web apps to locate a user's position. - -### Q: My hosted app uses the background permission. How do I do that on the web? {: #background } - -To ensure minimal power consumption we have been careful about introducing a generic method for -sites to run in the background on user's devices. - -Sites that have deployed a [service worker][199] can ensure actions taken by the user while offline -are synced to the server using the **[Background Sync API][200]**. This API allows sites to run some -limited code in the background when the device re-connects to the internet, even if the tab has -since been closed. Note that this API doesn't allow for the service worker to be woken up -periodically. - -A separate feature, [Periodic Background Sync][201], is being implemented as an experimental feature -in Chrome. It allows developers to request periodic updates via a special event exposed on the -service worker, with controls over the frequency of those updates. - -### Q: My hosted app uses the clipboardRead and/or clipboardWrite permission. How do I do that on the web? {: #clipboard } - -Web apps can use a standard platform API to copy and paste both [text][202] and [images -programmatically.][203] +- For questions related to migrating from Chrome Apps to Web Applications or Chrome Extensions join the [ChromeOS developer community on Discord][37]. +- For missing web app capabilities, request a new capability under [Capabilities, aka. Project Fugu][38]. [1]: https://blog.chromium.org/2021/10/extending-chrome-app-support-on-chrome.html -[2]: /apps/migration +[2]: https://developer.chrome.com/blog/capabilities/ [3]: https://web.dev/progressive-web-apps/ -[4]: /blog/capabilities -[5]: https://www.chromium.org/teams/web-capabilities-fugu -[6]: https://caniuse.com/ -[7]: - https://bugs.chromium.org/p/chromium/issues/entry?summary=Fugu+Request:++Add+your+feature+title&comment&labels=Type-Feature,Pri-3,Proj-Fugu -[8]: https://web.dev/learn/pwa/app-design/#optimizing-design-for-desktop/ -[9]: https://web.dev/customize-install/ -[10]: /docs/extensions/reference -[11]: /extensions/messaging#external-webpage -[12]: /extensions/browserAction -[13]: - https://developer.mozilla.org/docs/Mozilla/Add-ons/WebExtensions/Porting_a_Google_Chrome_extension -[14]: /apps/accessibilityFeatures -[15]: /extensions/accessibilityFeatures -[16]: /apps/alarms -[17]: http://crbug.com/891339 -[18]: https://developer.android.com/topic/libraries/architecture/workmanager -[19]: /extensions/alarms -[20]: /apps/app_runtime -[21]: https://bugs.chromium.org/p/chromium/issues/detail?id=844279 -[22]: https://developer.android.com/guide/components/activities/activity-lifecycle -[23]: /apps/app_runtime#event-onRestarted -[24]: /articles/page-lifecycle-api/ -[25]: https://developer.android.com/guide/components/activities/activity-lifecycle#onresume -[26]: /apps/app_window -[27]: https://crbug.com/897300 -[28]: /extensions/windows -[29]: /apps/audio -[30]: http://crbug.com/897326 -[31]: https://developer.android.com/guide/topics/media/mediaplayer -[32]: /apps/app_bluetooth -[33]: https://www.chromestatus.com/feature/5264933985976320 -[34]: https://developer.android.com/guide/topics/connectivity/bluetooth -[35]: /apps/bluetoothLowEnergy -[36]: https://www.chromestatus.com/feature/5264933985976320 -[37]: https://developer.android.com/guide/topics/connectivity/bluetooth-le -[38]: /apps/bluetoothSocket -[39]: https://www.chromestatus.com/feature/5264933985976320 -[40]: https://developer.android.com/reference/android/bluetooth/BluetoothSocket -[41]: /apps/browser -[42]: https://developer.mozilla.org/docs/Web/API/Window/open -[43]: https://developer.android.com/reference/android/content/Intent -[44]: /apps/commands -[45]: https://w3c.github.io/uievents/ -[46]: https://developer.android.com/training/keyboard-input/commands -[47]: /extensions/commands -[48]: /apps/contextMenus -[49]: https://developer.android.com/reference/android/view/ContextMenu -[50]: /apps/documentScan -[51]: /extensions/documentScan -[52]: /apps/events -[53]: https://bugs.chromium.org/p/chromium/issues/detail?id=891339 -[54]: /extensions/events -[55]: /apps/extensionTypes -[56]: /extensions/extensionTypes -[57]: /apps/fileSystem -[58]: http://crbug.com/853326 -[59]: /apps/fileSystemProvider -[60]: https://developer.android.com/reference/java/nio/file/spi/FileSystemProvider.html -[61]: /extensions/fileSystemProvider -[62]: /apps/gcm -[63]: https://web.dev/notifications/ -[64]: /extensions/gcm -[65]: /apps/hid -[66]: https://www.chromestatus.com/feature/5172464636133376 -[67]: /apps/i18n -[68]: https://developer.android.com/guide/topics/resources/localization -[69]: /extensions/i18n -[70]: /apps/identity -[71]: https://www.chromestatus.com/feature/5669923372138496 -[72]: https://developer.android.com/training/id-auth/authenticate -[73]: /extensions/identity -[74]: /apps/idle -[75]: http://crbug.com/878979 -[76]: /extensions/idle -[77]: /apps/instanceID -[78]: https://web.dev/notifications/ -[79]: /extensions/instanceID -[80]: /apps/mdns -[81]: https://developer.android.com/training/connect-devices-wirelessly/nsd -[82]: /apps/mediaGalleries -[83]: http://crbug.com/853326 -[84]: /apps/networking_onc -[85]: /apps/notifications -[86]: https://www.chromestatus.com/feature/5064350557536256 -[87]: /extensions/notifications -[88]: /apps/permissions -[89]: https://developer.mozilla.org/docs/Web/API/Permissions_API -[90]: /extensions/permissions -[91]: /apps/power -[92]: https://www.chromestatus.com/feature/4636879949398016 -[93]: http://b/133417350 -[94]: /extensions/power -[95]: /apps/printerProvider -[96]: /extensions/printerProvider -[97]: https://developer.android.com/reference/android/printservice/package-summary -[98]: /extensions/printerProvider -[99]: /apps/runtime -[100]: /articles/page-lifecycle-api/ -[101]: /extensions/runtime -[102]: /apps/messaging#connect -[103]: https://www.chromestatus.com/feature/6710044586409984 -[104]: /extensions/runtime#method-connect -[105]: /apps/messaging#simple -[106]: /extensions/runtime#method-sendMessage -[107]: /apps/app_serial -[108]: https://www.chromestatus.com/feature/6577673212002304 -[109]: /apps/app_network -[110]: https://w3c.github.io/webrtc-quic/cs.html -[111]: https://developer.android.com/reference/java/net/Socket -[112]: /apps/sockets_tcpServer -[113]: https://developer.android.com/reference/java/net/Socket -[114]: /apps/sockets_udp -[115]: https://w3c.github.io/webrtc-quic/cs.html -[116]: https://developer.android.com/reference/java/net/DatagramSocket -[117]: /apps/storage -[118]: https://www.chromestatus.com/feature/5072127703121920 -[119]: https://www.chromestatus.com/feature/6507459568992256 -[120]: /extensions/storage -[121]: /extensions/manifest/storage -[122]: https://developer.android.com/work/managed-configurations -[123]: /extensions/storage#property-managed -[124]: /apps/syncFileSystem -[125]: https://developers.google.com/drive/api/quickstart/java/ -[126]: /apps/system.cpu -[127]: https://www.chromestatus.com/feature/6248386202173440 -[128]: /extensions/system_cpu -[129]: /apps/system.display -[130]: https://drafts.csswg.org/cssom-view/#the-screen-interface -[131]: https://developer.android.com/reference/android/util/DisplayMetrics -[132]: /apps/system.memory -[133]: https://www.chromestatus.com/feature/5119701235531776 -[134]: /extensions/system_memory -[135]: /apps/system.network -[136]: https://www.chromestatus.com/feature/6338383617982464 -[137]: /apps/system.storage -[138]: https://www.chromestatus.com/feature/5630353511284736 -[139]: /extensions/system_storage -[140]: /apps/tts -[141]: https://www.chromestatus.com/feature/4782875580825600 -[142]: https://android-developers.googleblog.com/2009/09/introduction-to-text-to-speech-in.html -[143]: /extensions/tts -[144]: /apps/types -[145]: /extensions/types -[146]: /apps/app_usb -[147]: https://www.chromestatus.com/feature/5651917954875392 -[148]: http://go/arc++usb -[149]: /apps/virtualKeyboard -[150]: https://developer.android.com/training/keyboard-input -[151]: /apps/vpnProvider -[152]: https://developer.android.com/reference/android/net/VpnService -[153]: /extensions/vpnProvider -[154]: /apps/wallpaper -[155]: https://developer.android.com/reference/android/app/WallpaperManager -[156]: /extensions/wallpaper -[157]: /apps/manifest/externally_connectable -[158]: /apps/manifest/kiosk_enabled -[159]: /apps/manifest/minimum_chrome_version -[160]: /apps/manifest/minimum_chrome_version -[161]: /apps/offline_apps -[162]: https://developers.google.com/web/fundamentals/codelabs/offline/ -[163]: /native-client -[164]: /native-client/migration -[165]: /docs/extensions/reference/webviewTag/ -[166]: https://developer.android.com/reference/android/webkit/WebView -[167]: https://forms.gle/cNiZJbSutFbnFUdv8 -[168]: /extensions/management#method-uninstallSelf -[169]: /extensions/management#method-installReplacementWebApp -[170]: https://web.dev/progressive-web-apps -[171]: https://web.dev/learn/pwa/app-design/#optimizing-design-for-desktop -[172]: https://web.dev/customize-install/ -[173]: https://web.dev/add-manifest/#display -[174]: https://web.dev/add-manifest/ -[175]: https://developer.mozilla.org/docs/Web/Events/keydown -[176]: https://web.dev/add-manifest/#display -[177]: https://chromestatus.com/feature/5642959835889664 -[178]: /extensions/commands -[179]: https://web.dev/learn/pwa/service-workers -[180]: /docs/workbox -[181]: https://web.dev/notifications/ -[182]: https://web.dev/notifications/ -[183]: /articles/bluetooth/ -[184]: /articles/usb -[185]: /articles/file-system-access -[186]: https://developer.mozilla.org/docs/Web/API/WebSockets_API -[187]: https://bit.ly/new-fugu-request -[188]: /blog/capabilities -[189]: https://web.dev/learn/pwa/ -[190]: /docs/workbox/ -[191]: https://stackoverflow.com/ -[192]: https://stackoverflow.com/questions/ask?tags=progressive-web-apps,google-chrome-app -[193]: https://stackoverflow.com/questions/tagged/google-chrome-app -[194]: https://stackoverflow.com/questions/tagged/progressive-web-apps -[195]: https://bit.ly/new-fugu-request -[196]: https://web.dev/notifications -[197]: https://web.dev/persistent-storage/ -[198]: https://developer.mozilla.org/docs/Web/API/Geolocation_API -[199]: https://web.dev/learn/pwa/service-workers/ -[200]: /blog/background-sync -[201]: /articles/periodic-background-sync -[202]: https://web.dev/async-clipboard/ -[203]: https://web.dev/async-clipboard/ +[4]: https://web.dev/customize-install/ +[5]: https://web.dev/add-manifest/ +[6]: https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API +[7]: https://developer.chrome.com/docs/workbox/ +[8]: https://www.chromium.org/teams/web-capabilities-fugu/ +[9]: https://developer.chrome.com/articles/bluetooth/ +[10]: https://developer.chrome.com/articles/usb/ +[11]: https://developer.chrome.com/docs/extensions/reference/bluetooth/ +[12]: https://developer.chrome.com/docs/extensions/reference/usb/ +[13]: https://developer.chrome.com/articles/file-system-access/ +[14]: https://developer.chrome.com/docs/extensions/reference/fileSystem/ +[15]: https://developer.mozilla.org/en-US/docs/Web/API/Element/keydown_event +[16]: https://developer.chrome.com/articles/keyboard-lock/ +[17]: https://web.dev/persistent-storage/ +[18]: https://developer.mozilla.org/en-US/docs/Web/API/Geolocation_API +[19]: https://developer.chrome.com/blog/background-sync/ +[20]: https://developer.chrome.com/articles/periodic-background-sync/ +[21]: https://web.dev/async-clipboard/ +[22]: https://developer.chrome.com/docs/extensions/reference/browserAction/ +[23]: https://chromeos.dev/en/kiosk/connecting-an-extension-from-a-kiosk-pwa +[24]: https://developer.chrome.com/docs/extensions/reference/ +[25]: https://extensionworkshop.com/documentation/develop/porting-a-google-chrome-extension/ +[26]: https://learn.microsoft.com/en-us/microsoft-edge/extensions-chromium/developer-guide/port-chrome-extension +[27]: https://chromeos.dev/en/kiosk/connecting-an-extension-from-a-kiosk-pwa +[28]: https://developer.chrome.com/capabilities/ +[29]: https://developer.chrome.com/docs/extensions/reference/ +[30]: https://web.dev/learn/pwa/ +[31]: https://developer.chrome.com/docs/extensions/#getting-started-guides +[32]: https://developer.chrome.com/docs/extensions/reference/management/#method-uninstallSelf +[33]: https://developer.chrome.com/docs/extensions/reference/management/#method-installReplacementWebApp +[34]: https://support.google.com/chrome/a/answer/6306504 +[35]: https://chromeenterprise.google/policies/#ExtensionInstallForcelist +[36]: https://chromeenterprise.google/policies/#WebAppInstallForceList +[37]: https://chromeos.dev/en/posts/join-us-in-the-chromeos-developer-community-on-discord +[38]: https://developer.chrome.com/capabilities/ \ No newline at end of file From 21eb4a67f84f9813ef59faa3d560c42d8871524c Mon Sep 17 00:00:00 2001 From: Nancymic2 Date: Fri, 8 Sep 2023 11:29:00 -0400 Subject: [PATCH 762/982] Add use case to debugging part 1 (#7211) * Add use case * Update date --- .../attribution-reporting-debugging/part-1/index.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/site/en/docs/privacy-sandbox/attribution-reporting-debugging/part-1/index.md b/site/en/docs/privacy-sandbox/attribution-reporting-debugging/part-1/index.md index 5fc6b92b2..dca3b8106 100644 --- a/site/en/docs/privacy-sandbox/attribution-reporting-debugging/part-1/index.md +++ b/site/en/docs/privacy-sandbox/attribution-reporting-debugging/part-1/index.md @@ -4,7 +4,7 @@ title: 'Introduction to debug reports' subhead: Part 1 of 3 on debugging Attribution Reporting. Learn why debugging matters and when to use debug reports in testing. description: Part 1 of 3 on debugging Attribution Reporting. Learn why debugging matters and when to use debug reports in testing. date: 2022-12-13 -updated: 2023-03-02 +updated: 2023-09-06 authors: - maudn - alexandrawhite @@ -173,6 +173,10 @@ You may want to reprocess reports when you're: - experimenting with different batching strategies. - experimenting with different epsilon values. +### Data recovery + +Ad techs should enable debug mode for the Aggregation Service to be able to recover data in the event of a disaster such as unavailable or non-responsive services. + ## Up next [Part 2: Set up debug reports](/docs/privacy-sandbox/attribution-reporting-debugging/part-2/) From 3f3ad9c43bb4f7306bab54140ad776ed336e316d Mon Sep 17 00:00:00 2001 From: Joe Medley Date: Fri, 8 Sep 2023 13:54:32 -0700 Subject: [PATCH 763/982] Add platform APIs to the list of supported technologies. (#7264) --- .../en/docs/extensions/mv3/getstarted/extensions-101/index.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/site/en/docs/extensions/mv3/getstarted/extensions-101/index.md b/site/en/docs/extensions/mv3/getstarted/extensions-101/index.md index 32f9d8c20..e374d9dfb 100644 --- a/site/en/docs/extensions/mv3/getstarted/extensions-101/index.md +++ b/site/en/docs/extensions/mv3/getstarted/extensions-101/index.md @@ -5,7 +5,7 @@ seoTitle: 'Chrome Extensions 101' subhead: 'Explore basic concepts of Chrome extension development.' description: 'Explore basic concepts of Chrome extension development.' date: 2022-10-04 -# updated: 2022-06-13 +updated: 2023-09-08 --- This page describes what an extension is and provides a brief introduction to Chrome extension development. It also includes links to [beginner tutorials][section-tutorials]. @@ -29,6 +29,7 @@ Extensions are written with the same web technologies used to create web applica - [HTML][web-dev-html] is used as a content markup language. - [CSS][web-dev-css] is used for styling. - [JavaScript][mdn-js] is used for scripting and logic. +- [Web platform APIs][web-apis] let you use virtually any feature available to a standard web page. Before moving forward, we recommend that you become familiar with these technologies. @@ -185,6 +186,7 @@ extension and Chrome Web store documentation: [tut-focus-mode]: /docs/extensions/mv3/getstarted/tut-focus-mode [tut-reading-time]: /docs/extensions/mv3/getstarted/tut-reading-time [tut-tabs-manager]: /docs/extensions/mv3/getstarted/tut-tabs-manager +[web-apis]: https://developer.mozilla.org/docs/Web/API [web-dev-css]: https://web.dev/learn/css/ [web-dev-html]: https://web.dev/learn/html/ From 5091807b9a2b5c61cadc4a692a14f04938d3775e Mon Sep 17 00:00:00 2001 From: Nancymic2 Date: Mon, 11 Sep 2023 09:11:51 -0400 Subject: [PATCH 764/982] ARA get started Akash's feedback incorporated (#7256) * Akash's feedback incorporated * Update link * details about the explainer link --- .../glossary-entries/event-level.md | 2 +- .../glossary-entries/summary-report.md | 7 +----- .../getting-started/index.md | 23 +++++++------------ 3 files changed, 10 insertions(+), 22 deletions(-) diff --git a/site/en/_partials/privacy-sandbox/glossary-entries/event-level.md b/site/en/_partials/privacy-sandbox/glossary-entries/event-level.md index 6ef8d2936..b3ec0c340 100644 --- a/site/en/_partials/privacy-sandbox/glossary-entries/event-level.md +++ b/site/en/_partials/privacy-sandbox/glossary-entries/event-level.md @@ -1 +1 @@ -[Event-level reports](/docs/privacy-sandbox/attribution-reporting/#event-level-reports) associate a particular ad click or view (on the ad side) with data on the conversion side. To preserve user privacy by limiting the joining of user identity across sites, conversion-side data is very limited, and the data is noisy. An event-level report represents one action rather than many user actions. \ No newline at end of file +[Event-level reports](/docs/privacy-sandbox/attribution-reporting/#event-level-reports) associate a particular ad click or view (on the ad side) with data on the conversion side. To preserve user privacy by limiting the joining of user identity across sites, conversion-side data is very limited, and the data is noisy. \ No newline at end of file diff --git a/site/en/_partials/privacy-sandbox/glossary-entries/summary-report.md b/site/en/_partials/privacy-sandbox/glossary-entries/summary-report.md index 750b739fd..4e78080c6 100644 --- a/site/en/_partials/privacy-sandbox/glossary-entries/summary-report.md +++ b/site/en/_partials/privacy-sandbox/glossary-entries/summary-report.md @@ -1,7 +1,2 @@ A summary report is an Attribution Reporting API and Private Aggregation API report type. A [summary -report](/docs/privacy-sandbox/attribution-reporting/summary-reports/) includes -aggregated user data and detailed conversion data, resulting from noisy -aggregation applied to aggregatable reports. The summary -includes aggregated user data and detailed conversion data. - -Summary reports were formerly known as aggregate reports. \ No newline at end of file +report](/docs/privacy-sandbox/attribution-reporting/summary-reports/) includes aggregated user data and can contain detailed conversion data, with noise added.Summary reports are made up of aggregate reports. \ No newline at end of file diff --git a/site/en/docs/privacy-sandbox/attribution-reporting/getting-started/index.md b/site/en/docs/privacy-sandbox/attribution-reporting/getting-started/index.md index 4e8e72e6d..381902177 100644 --- a/site/en/docs/privacy-sandbox/attribution-reporting/getting-started/index.md +++ b/site/en/docs/privacy-sandbox/attribution-reporting/getting-started/index.md @@ -62,17 +62,13 @@ Here are the minimum steps to follow to generate event-level reports: Refer to the [example code in adtech.js](https://github.com/GoogleChromeLabs/trust-safety-demo/blob/8f3d874b79ab0c8a15822fbcd09e94042aee7dcd/conversion-measurement/functions/apps/adtech.js#L309) to see the `post` method. More information on [.well-known](https://en.wikipedia.org/wiki/Well-known_URI) is here. -1. **Complete the source registration**. Upon receiving the request, respond with the header [`Attribution-Reporting-Register-Source`](/docs/privacy-sandbox/attribution-reporting/register-attribution-source/#step-2-respond-with-header-clicks-and-views). In that header, specify the desired Attribution Reporting configuration. This step is the same for both clicks and views. - - Refer to [Register attribution sources](/docs/privacy-sandbox/attribution-reporting/register-attribution-source/#step-2-respond-with-header-clicks-and-views) for the instructions. - More details on [event-level reports](https://github.com/WICG/attribution-reporting-api/blob/main/EVENT.md) here. ### Summary report generation -To generate reports, follow these high-level steps: +To generate summary reports, follow these high-level steps: -1. **Register a source**. Refer to [Register attribution sources](/docs/privacy-sandbox/attribution-reporting/register-attribution-source) for the instructions. Note that [the steps](/docs/privacy-sandbox/attribution-reporting/register-attribution-source/#step-1-initiate-source-registration) are different for clicks and views. +1. **Register a source**. Refer to [Register attribution sources](/docs/privacy-sandbox/attribution-reporting/register-attribution-source) for the instructions. Note that [the steps](/docs/privacy-sandbox/attribution-reporting/register-attribution-source/#step-1-initiate-source-registration) are different for clicks and views. Additional details can be found in [Attribution source registration](https://github.com/WICG/attribution-reporting-api/blob/main/AGGREGATE.md#attribution-source-registration). 1. **Register a trigger**. Refer to [Register attribution triggers](/docs/privacy-sandbox/attribution-reporting/register-attribution-trigger) for the instructions. {: #summary-endpoint } @@ -81,16 +77,13 @@ To generate reports, follow these high-level steps: Refer to the [example code in adtech.js](https://github.com/GoogleChromeLabs/trust-safety-demo/blob/8f3d874b79ab0c8a15822fbcd09e94042aee7dcd/conversion-measurement/functions/apps/adtech.js#L334) to see the `post` method. More information on [.well-known](https://en.wikipedia.org/wiki/Well-known_URI) is here. -1. **Complete the source registration**: Upon receiving the request, respond with the header [`Attribution-Reporting-Register-Source`](/docs/privacy-sandbox/attribution-reporting/register-attribution-source/#step-2-respond-with-header-clicks-and-views). In that header, specify the desired Attribution Reporting configuration. This step is the same for both clicks and views. - - Refer to [Register attribution sources](/docs/privacy-sandbox/attribution-reporting/register-attribution-source/#step-2-respond-with-header-clicks-and-views) for the instructions. - -1. **Set up debug reports**: Learn how in the [Attribution reporting debugging series](/docs/privacy-sandbox/attribution-reporting-debugging/). - + 1. **Batch and send the reports** for further processing by the [Aggregation Service](/docs/privacy-sandbox/aggregation-service/) which will produce summary reports. Refer to [batched aggregatable reports](/docs/privacy-sandbox/attribution-reporting/system-overview/#batched-aggregatable-reports). More details on [summary reports](https://github.com/WICG/attribution-reporting-api/blob/main/AGGREGATE.md) here. +Learn how to set up debug reports in the [Attribution reporting debugging series](/docs/privacy-sandbox/attribution-reporting-debugging/). + #### Summary reports additional concepts In addition to understanding the implementation steps here, the following concepts will help you plan your summary reporting strategy: @@ -105,8 +98,8 @@ In addition to understanding the implementation steps here, the following concep 1. Follow the instructions in [Define custom rules using filters](/docs/privacy-sandbox/attribution-reporting/define-filters/). 1. Review details specific to filters for aggregatable reports in - the - [explainer](https://github.com/WICG/attribution-reporting-api/blob/main/AGGREGATE.md). + the triggers section of the + [explainer](https://github.com/WICG/attribution-reporting-api/blob/main/AGGREGATE.md#attribution-trigger-registration). ### Don't forget feature detection @@ -127,8 +120,8 @@ Note that this check alone isn't a guarantee that the API is usable on that page If you're ready to begin implementation, check out these docs: - Setup: - - [Register an attribution trigger](/docs/privacy-sandbox/attribution-reporting/register-attribution-trigger) - [Register an attribution source](/docs/privacy-sandbox/attribution-reporting/register-attribution-source) + - [Register an attribution trigger](/docs/privacy-sandbox/attribution-reporting/register-attribution-trigger) - [Prioritize specific clicks, views, or conversions](/docs/privacy-sandbox/attribution-reporting/change-attribution-logic/) - [Debugging Attribution Reporting](/docs/privacy-sandbox/attribution-reporting-debugging/) - [Aggregation keys](/docs/privacy-sandbox/attribution-reporting/aggregation-keys) From ce234db7c895186f7a14b3752c4f1ad3d4dccfdb Mon Sep 17 00:00:00 2001 From: Nancymic2 Date: Mon, 11 Sep 2023 09:47:25 -0400 Subject: [PATCH 765/982] Revert "Add use case to debugging part 1 (#7211)" (#7261) This reverts commit 21eb4a67f84f9813ef59faa3d560c42d8871524c. --- .../attribution-reporting-debugging/part-1/index.md | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/site/en/docs/privacy-sandbox/attribution-reporting-debugging/part-1/index.md b/site/en/docs/privacy-sandbox/attribution-reporting-debugging/part-1/index.md index dca3b8106..5fc6b92b2 100644 --- a/site/en/docs/privacy-sandbox/attribution-reporting-debugging/part-1/index.md +++ b/site/en/docs/privacy-sandbox/attribution-reporting-debugging/part-1/index.md @@ -4,7 +4,7 @@ title: 'Introduction to debug reports' subhead: Part 1 of 3 on debugging Attribution Reporting. Learn why debugging matters and when to use debug reports in testing. description: Part 1 of 3 on debugging Attribution Reporting. Learn why debugging matters and when to use debug reports in testing. date: 2022-12-13 -updated: 2023-09-06 +updated: 2023-03-02 authors: - maudn - alexandrawhite @@ -173,10 +173,6 @@ You may want to reprocess reports when you're: - experimenting with different batching strategies. - experimenting with different epsilon values. -### Data recovery - -Ad techs should enable debug mode for the Aggregation Service to be able to recover data in the event of a disaster such as unavailable or non-responsive services. - ## Up next [Part 2: Set up debug reports](/docs/privacy-sandbox/attribution-reporting-debugging/part-2/) From 611fe01780207eb7b35c54e4806d8a2997ae957f Mon Sep 17 00:00:00 2001 From: Barry Pollard Date: Mon, 11 Sep 2023 15:49:03 +0200 Subject: [PATCH 766/982] Tweak LoAF example to make it more obvious it's two code snippets (#7259) * Tweak LoAF example to make it more obvious it's two code snippets * Fix spacing issue --- site/en/articles/long-animation-frames/index.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/site/en/articles/long-animation-frames/index.md b/site/en/articles/long-animation-frames/index.md index ff4da378b..ac46e3716 100644 --- a/site/en/articles/long-animation-frames/index.md +++ b/site/en/articles/long-animation-frames/index.md @@ -277,9 +277,11 @@ const observer = new PerformanceObserver(list => { ).slice(0, MAX_LOAFS_TO_CONSIDER); }); observer.observe({ type: 'long-animation-frame', buffered: true }); +``` + +At the appropriate time ([ideally on the `visibilitychange` event](/articles/page-lifecycle-api/#:~:text=it%27s%20always%20better%20to%20rely%20on%20the%20visibilitychange%20event%20to%20determine%20when%20a%20session%20ends)) beacon back to analytics. For local testing you can use `console.table` periodically: -// At the appropriate time, beacon back to analytics. -// Example here logs to console +```js console.table(longestBlockingLoAFs); ``` @@ -303,7 +305,7 @@ const observer = new PerformanceObserver(list => { if (entry.duration > REPORTING_THRESHOLD_MS && entry.firstUIEventTimestamp > 0 ) { - // Example here logs to console, but could also report back to analytics + // Example here logs to console, but could also report back to analytics console.log(entry); } } From 099604a88e7ddf3f33f90824e0ed06f21fe281c8 Mon Sep 17 00:00:00 2001 From: Barry Pollard Date: Mon, 11 Sep 2023 16:15:45 +0200 Subject: [PATCH 767/982] Add note about GA and prerender support (#7262) * Add note about GA and prerender support * Update site/en/blog/prerender-pages/index.md Co-authored-by: Jeremy Wagner --------- Co-authored-by: Jeremy Wagner --- site/en/blog/prerender-pages/index.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/site/en/blog/prerender-pages/index.md b/site/en/blog/prerender-pages/index.md index f33cd274f..59851241c 100644 --- a/site/en/blog/prerender-pages/index.md +++ b/site/en/blog/prerender-pages/index.md @@ -7,7 +7,7 @@ description: | authors: - tunetheweb date: 2022-12-02 -updated: 2023-08-22 +updated: 2023-09-08 hero: image/W3z1f5ZkBJSgL1V1IfloTIctbIF3/eohdiqaZlxnWen7TT66M.jpg alt: City road at dusk with a long exposure of car lights giving impression of speed tags: @@ -324,7 +324,11 @@ Analytics are used to measure website usage, for example using Google Analytics Pages should only be prerendered when there is a high probability the page will be loaded by the user. This is why the Chrome address bar prerendering options only happen when there is such a high probability (greater than 80% of the time). -However—particularly when using the Speculation Rules API—prerendered pages may have an impact on analytics and site owners may wish to add extra code to only enable analytics for prerendered pages on activation. +However—particularly when using the Speculation Rules API—prerendered pages may have an impact on analytics and site owners may wish to add extra code to only enable analytics for prerendered pages on activation, as not all analytics providers may do this by default. + +{% Aside 'update' %} +Google Analytics handles prerender by default as of September 2023. +{% endAside %} This could be achieved by using a `Promise` which waits for the `prerenderingchange` event if a document is prerendering, or resolves immediately if it is now: From 6db82c0082d13db2a430035f89c7ddd1293913d6 Mon Sep 17 00:00:00 2001 From: Barry Pollard Date: Mon, 11 Sep 2023 16:59:57 +0200 Subject: [PATCH 768/982] Update Soft Navigations post to note new Origin Trial (#7245) * Update Soft Navigations post to note new Origin Trial * Tweaks * Improved navid lookups * Cannot pass two types to getEntriesByType * Update site/en/blog/soft-navigations-experiment/index.md Co-authored-by: Jeremy Wagner * Update site/en/blog/soft-navigations-experiment/index.md Co-authored-by: Jeremy Wagner * Update site/en/blog/soft-navigations-experiment/index.md --------- Co-authored-by: Jeremy Wagner --- .../blog/soft-navigations-experiment/index.md | 84 ++++++++++--------- 1 file changed, 44 insertions(+), 40 deletions(-) diff --git a/site/en/blog/soft-navigations-experiment/index.md b/site/en/blog/soft-navigations-experiment/index.md index dfdd529ca..b2bcde583 100644 --- a/site/en/blog/soft-navigations-experiment/index.md +++ b/site/en/blog/soft-navigations-experiment/index.md @@ -8,7 +8,7 @@ authors: - tunetheweb - yoavweiss date: 2023-02-01 -updated: 2023-07-04 +updated: 2023-09-04 hero: image/W3z1f5ZkBJSgL1V1IfloTIctbIF3/ZJLD5QJvoFcWXkqF8m5P.jpg alt: A compass on top of some booklets labeled Field Notes tags: @@ -17,13 +17,17 @@ tags: - origin-trials --- +{% Aside 'update' %} +The Soft Navigations origin trial has entered a [second origin trial from Chrome 117](/origintrials/#/view_trial/21392098230009857) after taking feedback on board from the initial trial. +{% endAside %} + Since its launch, the [Core Web Vitals initiative](https://web.dev/vitals/) has sought to measure the actual user experience of a website, rather than technical details behind how a website is created or loaded. The three Core Web Vitals metrics were created as [user-centric metrics](https://web.dev/user-centric-performance-metrics/)—an evolution over existing technical metrics such as[`DOMContentLoaded`](https://developer.mozilla.org/docs/Web/API/Document/DOMContentLoaded_event) or [`load`](https://developer.mozilla.org/docs/Web/API/Window/load_event) that measured timings that were often unrelated to how users perceived the performance of the page. Because of this, the technology used to build the site should not impact the scoring providing the site performs well. -The reality is always a little trickier than the ideal, and the popular Single Page Application architecture has [never been fully supported by the Core Web Vitals metrics](https://web.dev/vitals-spa-faq/). Rather than loading distinct, individual web pages as the user navigates about the site, these web applications use so-called “soft navigations”, where the page content is instead changed by JavaScript. In these applications, the illusion of a traditional webpage architecture is maintained by altering the URL and pushing previous URLs in the browser’s history to allow the back and forward buttons to work as the user would expect. +The reality is always a little trickier than the ideal, and the popular Single Page Application architecture has [never been fully supported by the Core Web Vitals metrics](https://web.dev/vitals-spa-faq/). Rather than loading distinct, individual web pages as the user navigates about the site, these web applications use so-called "soft navigations", where the page content is instead changed by JavaScript. In these applications, the illusion of a traditional webpage architecture is maintained by altering the URL and pushing previous URLs in the browser's history to allow the back and forward buttons to work as the user would expect. -Many JavaScript frameworks use this model, but each in a different way. Since this is outside of what the browser traditionally understands as a “page”, measuring this has always been difficult: where is the line to be drawn between an interaction on the _current_ page, versus considering this as a _new_ page? +Many JavaScript frameworks use this model, but each in a different way. Since this is outside of what the browser traditionally understands as a "page", measuring this has always been difficult: where is the line to be drawn between an interaction on the _current_ page, versus considering this as a _new_ page? -The Chrome team has been been considering this challenge for some time now, and is looking to standardize a definition of what is a “soft-navigation”, and how the Core Web Vitals can be measured for this—in a similar way that websites implemented in the traditional multi-page architecture (MPA) is currently measured. While still in early stages, the team is now ready to make what has already been implemented more widely available for sites to experiment with. This will allow sites to provide feedback on the approach so far. +The Chrome team has been been considering this challenge for some time now, and is looking to standardize a definition of what is a "soft-navigation", and how the Core Web Vitals can be measured for this—in a similar way that websites implemented in the traditional multi-page architecture (MPA) is currently measured. While still in early stages, the team is now ready to make what has already been implemented more widely available for sites to experiment with. This will allow sites to provide feedback on the approach so far. ## What is a soft navigation? @@ -33,7 +37,7 @@ We have come up with the following definition of a _soft navigation_: - The navigation results in a visible URL change to the user, and a history change. - The navigation results in a DOM change. -For some sites, these heuristics may lead to false positives (that users would not really consider a "navigation" to have happened) or false negatives (where the user does consider a “navigation” to have happened despite not meeting the above criteria). We welcome feedback at [the soft navigation specification repository](https://github.com/WICG/soft-navigations/issues) on the heuristics. +For some sites, these heuristics may lead to false positives (that users would not really consider a "navigation" to have happened) or false negatives (where the user does consider a "navigation" to have happened despite not meeting the above criteria). We welcome feedback at [the soft navigation specification repository](https://github.com/WICG/soft-navigations/issues) on the heuristics. ### How does Chrome implement soft navigations? @@ -41,9 +45,9 @@ Once the soft navigation heuristics are enabled (more on this in the next sectio - A `soft-navigation` [`PerformanceTiming`](https://developer.mozilla.org/docs/Web/API/PerformanceTiming) event will be emitted after each soft navigation is detected. - The performance API will provide access to a `soft-navigation` timing entry, as emitted by the above `PerformanceTiming` event. -- The [First Paint (FP)](https://developer.mozilla.org/docs/Glossary/First_paint), [First Contentful Paint (FCP)](https://web.dev/fcp/), [Largest Contentful Paint (LCP)](https://web.dev/lcp/) metrics will be reset, and re-emitted on the next appropriate occurrences of these. +- The [First Paint (FP)](https://developer.mozilla.org/docs/Glossary/First_paint), [First Contentful Paint (FCP)](https://web.dev/fcp/), [Largest Contentful Paint (LCP)](https://web.dev/lcp/) metrics will be reset, and re-emitted on the next appropriate occurrences of these. (Note: FP, and FCP are not yet implemented.) - The [First Input Delay (FID)](https://web.dev/fcp/) will be reset, and re-emitted on the first input (note: this is not yet implemented). -- A `navigationId` attribute will be added to each of performance timings (`first-paint`, `first-contentful-paint`, `largest-contentful-paint`, `first-input-delay`, `event`, `layout-shift`) corresponding to the navigation entry the event was related to, allowing [Cumulative Layout Shift (CLS)](https://web.dev/cls/) and [Interaction to Next Paint (INP)](https://web.dev/inp/) to be calculated. _Note: this is [subject to change](#reporting-the-metrics-against-the-appropriate-url)._ +- A `navigationId` attribute will be added to each of performance timings (`first-paint`, `first-contentful-paint`, `largest-contentful-paint`, `first-input-delay`, `event`, and `layout-shift`) corresponding to the navigation entry the event was related to, allowing [Cumulative Layout Shift (CLS)](https://web.dev/cls/) and [Interaction to Next Paint (INP)](https://web.dev/inp/) to be calculated. These changes will allow the Core Web Vitals—and some of the associated diagnostic metrics—to be measured per page navigation, though there are some nuances that need to be considered. @@ -64,17 +68,13 @@ Soft navigations are not enabled by default in Chrome, but are available for exp For developers, this can be enabled by turning on the _Experimental Web Platform features_ flag at `chrome://flags/#enable-experimental-web-platform-features` or by using the `--enable-experimental-web-platform-features` command line argument when launching Chrome. -For a website that wishes to enable this for all their visitors to see the impact, there is an origin trial running from Chrome 110 to Chrome 114 which can be enabled by signing up for the trial and including a meta element with the origin trial token in the HTML or HTTP header. See the [Get started with origin trials](/docs/web-platform/origin-trials/) post for more information. +For a website that wishes to enable this for all their visitors to see the impact, there is an origin trial running from Chrome 117 which can be enabled by signing up for the trial and including a meta element with the origin trial token in the HTML or HTTP header. See the [Get started with origin trials](/docs/web-platform/origin-trials/) post for more information. Site owners can choose to include the origin trial on their pages for all, or for just a subset of users. Be aware of the [implications section](#what-are-the-implications-of-enabling-soft-navigations-in-chrome) above as to how this changes how your metrics may be reported, especially if enabling this origin trial for a large proportion of your users. Note that CrUX will continue to report the metrics in the existing manner regardless of this soft navigation setting so is not impacted by those implications. It should also be noted that origin trials are also limited to enabling experimental features on a maximum of 0.5% of all Chrome page loads as a median over 14 days, but this should only be an issue for very large sites. -{% Aside 'important' %} -The Soft Navigations origin trial has now ended. The Chrome team are taking onboard the feedback received and will be making some adjustments and are aiming to relaunch a second origin trial from Chrome 117 (due for release in September 2023) for further feedback. -{% endAside %} - ## How can I measure Core Web Vitals per soft navigation? -To includes soft navigations you need to include `includeSoftNavigationObservations: true` in your performance observer's `observe` call: +To include soft navigation metric entries, you need to include `includeSoftNavigationObservations: true` in your performance observer's `observe` call: ```js new PerformanceObserver((entryList) => { @@ -84,27 +84,27 @@ new PerformanceObserver((entryList) => { }).observe({type: 'largest-contentful-paint', buffered: true, includeSoftNavigationObservations: true}); ``` -This extra flag on the `observe` method is needed in addition to [enabling the soft navigation functionality in Chrome](#how-do-i-enable-soft-navigations-in-chrome). This explicit opt-in at the performance observer level is to [ensure existing performance observers aren't surprised by these extra entries](https://github.com/WICG/soft-navigations/issues/11) as some considerations need to be taken into account when attempting to measure Core Web Vitals for soft navigations. +This extra flag on the `observe` method is needed in addition to [enabling the soft navigation functionality in Chrome](#how-do-i-enable-soft-navigations-in-chrome). This explicit opt-in at the performance observer level is to [ensure existing performance observers aren't surprised by these extra entries](https://github.com/WICG/soft-navigations/issues/11) as some additional considerations need to be taken into account when attempting to measure Core Web Vitals for soft navigations. -Some metrics have traditionally been measured throughout the life of the page: LCP, for example, can change until an interaction occurs. CLS, FID and INP can be updated until the page is navigated away from. Therefore each “navigation” (including the original navigation) will need to finalize these metrics as each new soft navigation occurs. +Some metrics have traditionally been measured throughout the life of the page: LCP, for example, can change until an interaction occurs. CLS, FID and INP can be updated until the page is navigated away from. Therefore each "navigation" (including the original navigation) will need to finalize these metrics as each new soft navigation occurs, meaning the initial "hard" navigation metrics may be finalised earlier that usual. -Similarly, when starting to measure the metrics for the new soft navigation of these long-lived metrics, metrics will need to be “reset” or “reinitialized” and treated as new metrics, with no memory of the values that were set for previous “pages”. +Similarly, when starting to measure the metrics for the new soft navigation of these long-lived metrics, metrics will need to be "reset" or "reinitialized" and treated as new metrics, with no memory of the values that were set for previous "pages". -Timings will still be returned in respect of the original “hard” navigation start time. So to calculate LCP for a soft navigation for example, you will need to take the LCP timing and subtract the appropriate soft navigation start time to get a timing relative to the soft navigation. This has been done to keep all timings consistent so other performance timings (such as event timings) that are not measured from the “navigation” time can be treated the same. +Timings will still be returned in respect of the original "hard" navigation start time. So to calculate LCP for a soft navigation for example, you will need to take the LCP timing and subtract the appropriate soft navigation start time to get a timing relative to the soft navigation. This has been done to keep all timings consistent so other performance timings (such as event timings) that are not measured from the "navigation" time can be treated the same. ### Reporting soft navigations Once the soft navigations experiment is enabled, the metrics will be reporting via the [`PerformanceObserver`](https://developer.mozilla.org/docs/Web/API/PerformanceObserver) API as usual, but with an additional `navigationId` added to each metric, corresponding to the navigation entry the metric was emitted for. {% Aside 'note' %} -Note: [FID is not currently reported](https://bugs.chromium.org/p/chromium/issues/detail?id=1407656) for soft navigations. +Note: [FP and FCP are currently not reported for soft navigations](https://bugs.chromium.org/p/chromium/issues/detail?id=1479350), and [neither is FID](https://bugs.chromium.org/p/chromium/issues/detail?id=1407656). {% endAside %} You can use a `PerformanceObserver` to observe soft navigations. Below is an example code snippet that logs soft navigation entries to the console—including previous soft navigations on this page via the `buffered` option: ```js const observer = new PerformanceObserver(console.log); -observer.observe({ type: "soft-navigation", buffered: true, includeSoftNavigationObservations: true }); +observer.observe({ type: "soft-navigation", buffered: true }); ``` This can be used to finalize full-life page metrics for the previous navigation. @@ -116,17 +116,15 @@ As soft navigations can only be seen after they have occurred, some metrics will The `navigationID` attribute of the appropriate `PerformanceEntry` can be used to tie the event back to the correct URL. This can be looked up with the [`PerformanceEntry` API](https://developer.mozilla.org/docs/Web/API/PerformanceEntry): ```js -pageUrl = - performance.getEntriesByType('soft-navigation')[navigationId - 2]?.name - || performance.getEntriesByType('navigation')[0]?.name +const softNavEntry = + performance.getEntriesByType('soft-navigation').filter( + (entry) => entry.navigationId === navigationId + )[0]; +const hardNavEntry = performance.getEntriesByType('navigation')[0]; +const navEntry = softNavEntry || hardNavEntry; +const pageUrl = navEntry?.name; ``` -Here we are subtracting `2` as the first soft navigation is `2` and `getEntriesByType` returns an array, which like all JavaScript arrays, is zero-indexed. - -{% Aside 'warning' %} -There are discussions on [whether there are better ways to link event entries to the navigation entries](https://github.com/WICG/soft-navigations/issues/12), so this may change. -{% endAside %} - This `pageUrl` should be used to report the metrics against the correct URL, rather than the current URL that they may have used in the past. ### Getting the `startTime` of soft navigations @@ -134,12 +132,18 @@ This `pageUrl` should be used to report the metrics against the correct URL, rat The navigation start time can be obtained in a similar manner: ```js -startTime = - performance.getEntriesByType('soft-navigation')[navigationId - 2]?.startTime - || performance.getEntriesByType('navigation')[0]?.startTime +const softNavEntry = + performance.getEntriesByType('soft-navigation').filter( + (entry) => entry.navigationId === navigationId + )[0]; +const hardNavEntry = performance.getEntriesByType('navigation')[0]; +const navEntry = softNavEntry || hardNavEntry; +const startTime = navEntry?.startTime; ``` -The `startTime` is the time of the initial interaction (for example, a button click) that initiated the soft navigation. Again, this is subject to change as noted above. +The `startTime` is the time of the initial interaction (for example, a button click) that initiated the soft navigation. + +All performance timings, including those for soft navigations, are reported as a time from the initial "hard" page navigation time. Therefore, the soft navigation start time is needed to baseline the soft navigation loading metric times (for example LCP), relative to this soft navigation time instead. ### How should content that remains the same between navigations be treated? @@ -153,15 +157,15 @@ As this example shows, the LCP element for the soft navigation can be reported d [Time to First Byte (TTFB)](https://web.dev/ttfb/) for a traditional page load represents the time that the first bytes of the original request are returned. -For a soft navigation this is a more tricky question. Should we measure the first request made for the new page? What if all the content already exists in the app and there are no additional requests? What if that request is made in advance with a prefetch? What if a request unrelated to the soft navigation from a user perspective (for example, it’s an analytics request)? +For a soft navigation this is a more tricky question. Should we measure the first request made for the new page? What if all the content already exists in the app and there are no additional requests? What if that request is made in advance with a prefetch? What if a request unrelated to the soft navigation from a user perspective (for example, it's an analytics request)? A simpler method is to report TTFB of 0 for soft navigations—in a similar manner as we recommend for [back/forward cache](https://web.dev/bfcache/) restores. This is the method the [`web-vitals` library](#using-the-web-vitals-library-to-measure-core-web-vitals-for-soft-navigations) currently uses for soft navigations. -In the future, we may support more precise ways of knowing which request is the soft navigation’s “navigation request” and will be able to have more precise TTFB measurements. But that’s not part of the current experiment. +In the future, we may support more precise ways of knowing which request is the soft navigation's "navigation request" and will be able to have more precise TTFB measurements. But that's not part of the current experiment. ### How to measure both old and new? -During this experiment, it is recommended to continue to measure your Core Web Vitals in the current manner, based on “hard” page navigations to match what CrUX will measure and report on as the official dataset of the Core Web Vitals initiative. +During this experiment, it is recommended to continue to measure your Core Web Vitals in the current manner, based on "hard" page navigations to match what CrUX will measure and report on as the official dataset of the Core Web Vitals initiative. Soft navigations should be measured in addition to these to allow you to see how these might be measured in the future, and to give you the opportunity to provide feedback to the Chrome team about how this implementation works in practice. This will help you and the Chrome team to shape the API going forward. @@ -214,7 +218,7 @@ The `web-vitals` library currently reports the following metrics for soft naviga FCP - The time of the next contentful paint, relative to the soft navigation start time. Existing paints present from the previous navigation are not considered. Therefore, the FCP will be >= 0. + Currently only the first FCP for the page is reported by the web-vitals library. LCP @@ -236,7 +240,7 @@ The `web-vitals` library currently reports the following metrics for soft naviga {% Aside 'warning' %} -The `web-vitals` implementation is under active development and is subject to change with new changes being published to that branch. At present, it does not support FID on soft navigations, as that requires [more underlying work in Chrome](https://bugs.chromium.org/p/chromium/issues/detail?id=1407656) or polyfilling FID-based on events. +The `web-vitals` implementation is under active development and is subject to change with new changes being published to that branch. At present, it does not support FCP and FID on soft navigations, as that requires [more underlying work in Chrome for FCP](https://bugs.chromium.org/p/chromium/issues/detail?id=1479350) and [for FID](https://bugs.chromium.org/p/chromium/issues/detail?id=1407656). Those using the `web-vitals` JavaScript library should be aware of this if looking to use this library on production sites, and should take a local copy and test that version, and monitor the branch for changes. {% endAside %} @@ -245,11 +249,11 @@ Those using the `web-vitals` JavaScript library should be aware of this if looki At present, this soft navigation experiment is exactly that—an experiment. We wish to evaluate the heuristics and see if they more accurately reflect the user experience before we make any decision on whether this will be integrated in the Core Web Vitals initiative. We are very excited at the possibility of this experiment, but cannot offer guarantees on whether or when this will replace the current measurements. -We value web developers' feedback on the experiment, the heuristics used, and whether you feel it more accurately reflects the experience. The [soft navigation GitHub repository](https://github.com/WICG/soft-navigations/issues) is the best place to provide that feedback, though individual bugs with Chrome’s implementation of that should be raised in the [Chrome issue tracker](https://bugs.chromium.org/p/chromium/issues/list). +We value web developers' feedback on the experiment, the heuristics used, and whether you feel it more accurately reflects the experience. The [soft navigation GitHub repository](https://github.com/WICG/soft-navigations/issues) is the best place to provide that feedback, though individual bugs with Chrome's implementation of that should be raised in the [Chrome issue tracker](https://bugs.chromium.org/p/chromium/issues/list). ### How will soft navigations be reported in CrUX? -How exactly soft navigations will be reported in CrUX, should this experiment be successful, is also still to be determined. It is not necessarily a given that they will be treated the same as current “hard” navigations are treated. +How exactly soft navigations will be reported in CrUX, should this experiment be successful, is also still to be determined. It is not necessarily a given that they will be treated the same as current "hard" navigations are treated. In some web pages, soft navigations are almost identical to full page loads as far as the user is concerned and the use of Single Page Application technology is just an implementation detail. In others, they may be more akin to a partial load of additional content. @@ -262,7 +266,7 @@ At present, the team is concentrating on the heuristic and technical implementat We are actively seeking feedback on this experiment at the following places: - [The soft navigations heuristics and standardization](https://github.com/WICG/soft-navigations/issues). -- [Chrome implementation issues](https://bugs.chromium.org/p/chromium/issues/list) of those heuristics. +- [Chrome implementation issues](https://bugs.chromium.org/p/chromium/issues/entry?template=Defect&components=Blink%3EPerformanceAPIs) of those heuristics. - General web vitals feedback at [web-vitals-feedback@googlegrouops.com](mailto:web-vitals-feedback@googlegrouops.com). ## Conclusion From b0c7cc4e1135a322be3e5700a476a01867284922 Mon Sep 17 00:00:00 2001 From: Jack J Date: Tue, 12 Sep 2023 17:09:09 +0900 Subject: [PATCH 769/982] Add FedCM Updates Link to Roadmap (#7267) * Add FedCM Updates Link to Roadmap fix #501 * fix internal link to relative * move to section top and add more links. * adding update link to existing list --- site/en/docs/privacy-sandbox/fedcm/index.md | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/site/en/docs/privacy-sandbox/fedcm/index.md b/site/en/docs/privacy-sandbox/fedcm/index.md index 121ee9835..57379a9d3 100644 --- a/site/en/docs/privacy-sandbox/fedcm/index.md +++ b/site/en/docs/privacy-sandbox/fedcm/index.md @@ -237,14 +237,20 @@ They can do the same for Chrome on desktop by going to We are working on landing a number of changes on the FedCM. +Several updates have already been applied based on feedback. And also it's +expected to continue evolving until Q4 2023 at least to stabilize. Please see +Updates for more details. + +* **Change Log**: Federated Credential Management API [updates](/docs/privacy-sandbox/fedcm-updates/). + There are a few things we know that still need to be done, including issues we heard about from IdPs, RPs and browser vendors. We believe we know how to resolve these issues: * **Cross-origin iframe support**: IdPs can call FedCM from within a - cross-origin iframe. + cross-origin iframe ([update](/docs/privacy-sandbox/fedcm-developer-guide/#call-fedcm-from-within-a-cross-origin-iframe)). * **Personalized button**: IdPs can display a returning user's identity on the - sign-in button from within an IdP owned cross-origin iframe. + sign-in button from within an IdP owned cross-origin iframe ([update](/blog/fedcm-chrome-116-updates/#user-info)). * **Metrics endpoint**: Provides performance metrics to IdPs. Additionally, there are unresolved issues we are actively exploring including @@ -264,7 +270,7 @@ specific proposals that we are evaluating or prototyping: * **Sign in to IdP API**: To support [various scenarios](https://github.com/fedidcg/FedCM/issues/348), when a user is not signed in to the IdP, the browser provides a UI for the user to sign in - without leaving the RP. + without leaving the RP ([update](/blog/fedcm-chrome-116-updates/#idp-signin-status)). Finally, there are things we believe still need to be done, based on feedback from From 363d3b6728c91f684bb3aecabee62b71df748ceb Mon Sep 17 00:00:00 2001 From: ilyaspiridonov Date: Tue, 12 Sep 2023 11:49:41 +0300 Subject: [PATCH 770/982] [JA] Privacy Sandbox Translations (#7281) * Translate index.md via GitLocalize * Translate index.md via GitLocalize * Translate index.md via GitLocalize * Fixes --------- Co-authored-by: Nozomi Kugita --- site/ja/blog/privacy-sandbox-demos/index.md | 99 +++++++++++++ site/ja/blog/privacy-sandbox-launch/index.md | 140 +++++++++++++++++++ site/ja/blog/related-website-sets/index.md | 55 ++++++++ 3 files changed, 294 insertions(+) create mode 100644 site/ja/blog/privacy-sandbox-demos/index.md create mode 100644 site/ja/blog/privacy-sandbox-launch/index.md create mode 100644 site/ja/blog/related-website-sets/index.md diff --git a/site/ja/blog/privacy-sandbox-demos/index.md b/site/ja/blog/privacy-sandbox-demos/index.md new file mode 100644 index 000000000..61f7ee86c --- /dev/null +++ b/site/ja/blog/privacy-sandbox-demos/index.md @@ -0,0 +1,99 @@ +--- +layout: layouts/blog-post.njk +title: プライバシーサンドボックスのデモの紹介 +description: プライバシーサンドボックスのデモでは、プライバシーサンドボックス API に基づくクックブックレシピ、サンプルコード、およびデモアプリケーションを提供しています。 +authors: + - seburan +tags: + - privacy +date: 2023-06-29 +--- + +プライバシーサンドボックスイニシアチブでは、ユーザーのオンラインプライバシーを保護する一方で、企業や開発者にデジタルビジネスの繁栄を築くためのツールを提供する [20 個以上の API](/docs/privacy-sandbox/) を提供しています。サイト運営者、広告主、およびテックプロバイダーは評価し始めており、ユーザーのプライバシーを保護しながら自由でオープンなインターネットを提供し続けられるように計画しています。 + +開発者リソースの拡大は段階的に進められており、[Chrome デベロッパーサイト](/docs/privacy-sandbox/)では、現在利用可能なドキュメントとデモが API ごとに提供されています。また、アドテック企業とウェブエコシステム開発者が現在サードパーティ Cookie によってサポートされている典型的なユースケースに対する新しいアプローチを求めていることも理解しています。これらのユースケースでは通常、新しいプライバシーサンドボックス API を組み合わせて製品に投入することが必要となっています。そのため、その計画とこれらの API の仕組みを十分に理解することが求められています。 + +プライバシーサンドボックスのデモでは、プライバシーサンドボックス API に基づくクックブックレシピ、サンプルコード、およびデモアプリケーションが提供されています。ビジネスと開発者が、サポートしているアプリケーションとビジネスを、サードパーティ Cookie を使用せずにウェブエコシステムに適合させる際に、その助力となるように設計されています。 + +## プライバシーサンドボックスのデモに期待できること + +プライバシーサンドボックスのデモは、オープンソースのコードとして提供されており、コンテナイメージスクリプトとして軽量のインフラストラクチャがバンドルされています。リポジトリには、Docker を使ってローカル環境でデモをデプロイして実行するための手順や、Google Cloud Platform にデプロイするための手順が含まれています。また、単に興味があるユーザーも含めたあらゆるユーザーが学習と実験を迅速に行えるように、[Google でホストされているインスタンス](https://privacy-sandbox-demos.dev/)も用意しています。 + +現在、[多くの組織](https://www.google.com/url?q=https://privacysandbox.com/%23ecosystem&sa=D&source=docs&ust=1687308560959323&usg=AOvVaw33TZoXl39m4LkRaevo66Z0)がプライバシーサンドボックス API の[評価とテスト](/docs/privacy-sandbox/unified-origin-trial/)を実施しています。それらの組織からのフィードバックは、ウェブの新しい標準を開発していく上で非常に重要です。典型的なアドテックのユースケースのソリューションを公開することで、追加のフィードバックを受け取り、提案を洗練させられると期待しています。皆さんの貢献も歓迎しています。 + +プライバシーサンドボックス API の採用パスにおいては、プライバシーサンドボックスのデモがウェブ開発者の貴重なリソースとなると考えています。参考資料(レシピ、サンプルコード、デモ)は、最も一般的なユースケースに対応できるように拡大され、これによって移行が加速されることを期待しています。 + +## 最初のリリースが公開されました + +プライバシーサンドボックスデモの初回リリースが、[GitHub で公開されました](https://github.com/privacysandbox/privacy-sandbox-demos)。以降のデプロイ手順は、リポジトリの [README](https://github.com/privacysandbox/privacy-sandbox-demos/blob/main/README.md) ファイルに記載されています。
初回リリースでは、以下のユースケースのデモを用意しました。 + + + + + + + + + + + + + + + + + + + + + +
ユースケース説明API
リマーケティングブランドまたは製品をオンラインで調べたことのあるユーザーに関連性のある広告を表示します。Protected Audience API
Fenced Frame
シングルタッチコンバージョンのアトリビューションニュースサイトで広告を表示し、オンラインショッピングサイトで商品を購入した後のコンバージョンを測定します。Attribution Reporting API
+ +これらのユースケースは、デジタル広告エコシステムのアクターをシミュレーションするために、プロジェクトで開発した一連のデモアプリとサービスを通じて実装されます。 + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
デモアプリ
+
説明
+
eコマースサイト
+
広告主ショッピングサイト
+
ニュースサイト
+
広告が表示されるサイト運営者サイト
+
SSP サービス(サプライサイドプラットフォーム)
+
デモ SSP サービス:
  • Topics, Protected Audience オークション、およびその他のコンテキストまたはファーストパーティのシグナルに基づいて、表示する広告を選択します。
  • iframe または Fenced Frame に広告を表示します。
  • Attribution Reporting API でビュー/クリックインプレッション数を登録します。
+
+
DSP サービス(デマンドサイドプラットフォーム)
+
デモ DSP サービス:
  • Protected Audience API でユーザーをインタレストグループに参加させます。
  • Attribution Reporting API でコンバージョンを登録します。
+
+ +今後のリリースには、プライバシーを保護するテクノロジーの最新の進化をサポートする新しいユースケース、デモシナリオ、新しいサービスが含まれる予定です。また、開発者がこれらのy-スケースをビジネスに実装できるように、より多くのドキュメントとクックブックレシピを追加していきます。 + +## 貢献とフィードバックの共有 + +包括的なドキュメントとデモを提供する取り組みは継続して行われており、今後のリリースでどのユースケースをご覧になりたいかについての皆さんのご意見をお待ちしております。アイデアやフィードバックを[イシュートラッカー](https://github.com/privacysandbox/privacy-sandbox-demos/issues)でお知らせください。 + +プライバシーサンドボックスのデモとプライバシーサンドボックス API の詳細については、[GitHub](https://github.com/privacysandbox/privacy-sandbox-demos) をご覧ください。 diff --git a/site/ja/blog/privacy-sandbox-launch/index.md b/site/ja/blog/privacy-sandbox-launch/index.md new file mode 100644 index 000000000..61a874f0c --- /dev/null +++ b/site/ja/blog/privacy-sandbox-launch/index.md @@ -0,0 +1,140 @@ +--- +layout: layouts/blog-post.njk +title: プライバシーサンドボックス広告関連 API のリリース +authors: + - rowan_m + - anusmitaray +description: + Chrome 115 でプライバシーサンドボックス広告関連 API を段階的に有効にするための計画とタイムライン、オリジントライアルの終了、および登録に関する更新情報。 +subhead: + Chrome 115 でプライバシーサンドボックス広告関連 API を段階的に有効にするための計画とタイムライン、オリジントライアルの終了、および登録に関する更新情報。 +date: 2023-07-20 +thumbnail: image/80mq7dk16vVEg8BBhsVe42n6zn82/s3iDQJUgLZV25YbtYxs1.png +alt: + プライバシーサンドボックス広告関連 API のリリース +tags: + - privacy +--- + +5 月に、Chrome 115 における[プライバシーサンドボックス広告関連 API のリリース計画](/blog/shipping-privacy-sandbox/)を発表しましたが、遂にその時期がやってきました。Chrome 115 は安定版としてリリースされ、今後数日のうちに、API の段階的な有効化が開始されます。 + +この記事では、今回のリリースに関わる次の内容について確認します。 + +- **リリース内容:** 広告関連 API のリリースプロセス: Topics、Protected Audience、アトリビューション レポート、プライベート集計、共有ストレージ、および Fenced Frames。 +- **API の段階的有効化:** API は、イシューを監視しながら、8 月中旬までに 99% の可用性を得ることを目標に、115 マイルストーンに沿って段階的に有効化されます。 +- **総合オリジントライアルの終了:** プライバシーサンドボックス広告関連オリジントライアルは 2023 年 9 月 20 日に終了し、同時に一般提供への移行を開始します。 +- **ユーザーコントロールの更新:** ユーザーは、API を管理するための広告プライバシーコントロールを利用できるようになります。 +- **登録:** 広告関連 API を使用する開発者に必須の登録プロセスが更新されています。 +- **Chrome を使用したテストモード:** 開発者がサードパーティ Cookie データを使用せずに API を使用できるオプションに関する詳細が更新されます。 + +## リリース内容 + +[前回の記事](/blog/shipping-privacy-sandbox/)では、Chrome 115 でリリースされる広告関連 API のリストを照会しました。[通常のプロセス](/docs/privacy-sandbox/proposal-lifecycle/)の一環として、各機能の blink-dev メーリングリストに "Intent to Ship"(I2S)メッセージを送信しました。I2S メッセージには、115 リリースに特化した API 機能の詳細、提案に関するエンジニアリングディスカッション、および重要な、[Blink API オーナーからの](https://www.chromium.org/blink/guidelines/api-owners/#:~:text=The%20Blink%20API%20owners%20oversee,APIs%20to%20Chromium%2Dbased%20browsers.)機能のリリースに関する承認(LGTM)が含まれます。 + +{% Aside %} + +[Attribution Reporting API](https://groups.google.com/a/chromium.org/g/blink-dev/c/2Rmj5V6FSaY)、[Protected Audience](https://groups.google.com/a/chromium.org/g/blink-dev/c/igFixT5n7Bs)、[Topics API](https://groups.google.com/a/chromium.org/g/blink-dev/c/PN_aE-X-f9U)、[Private Aggregation API](https://groups.google.com/a/chromium.org/g/blink-dev/c/8cKaLstq2QQ)、[Shared Storage API](https://groups.google.com/a/chromium.org/g/blink-dev/c/dZ0NRwh7cvs)、および [Fenced Frames](https://groups.google.com/a/chromium.org/g/blink-dev/c/tpw8wW0VenQ) の I2S メッセージをご覧ください。 + +{% endAside %} + +ウェブプラットフォーム API と共に、アトリビューション レポートとプライベート集計の[集計サービス](/docs/privacy-sandbox/aggregation-service)も一般公開となります。また、[First-Party Sets](/docs/privacy-sandbox/first-party-sets/)([I2S](https://groups.google.com/a/chromium.org/g/blink-dev/c/7_6JDIfE1as))と[プライベートステートトークン](/docs/privacy-sandbox/trust-tokens/)([I2S](https://groups.google.com/a/chromium.org/g/blink-dev/c/vKCYxKqw8k0/m/ohKLGrM5AQAJ))を段階的に有効化するプロセスも開始されており、[ストレージ パーティション](/docs/privacy-sandbox/storage-partitioning/)([I2S](https://groups.google.com/a/chromium.org/g/blink-dev/c/24hK6DKJnqY/m/ChL2WWx5CgAJ))もリリースされる予定です。 + +## API の段階的有効化 + +いかなる潜在的なイシューも監視して対応できるように、前回の一部のプライバシーサンドボックス機能と同様に、ブラウザインスタンスの割合を増やしながら、広告関連 API を段階的に有効化していきます。このプロセスを、2023 年 7 月 18 日の 115 安定版リリースから数日後に開始することを目標としているため、7 月 24 日の週にはほぼ開始される可能性があります。その後 1 週間かけて、API の提供を約 35% のブラウザに拡大する意向です。[統合オリジントライアル](/docs/privacy-sandbox/unified-origin-trial/#status)と同様に、この拡大には、すべての API が有効化されたメインのグループと API のサブセットが有効化された小規模の隔離されたグループが含まれます。API の潜在的なイシューを特定するには、隔離されたグループを使用するのが近道です。 + +{% Aside %} + +ユーザーは、バージョンアップデートまたは API の増分アップデートが適用される前に、Chrome を再起動する必要があります。つまり、ターゲットとするレベルに達するには、拡大までにさらに時間がかかることになります。示されているすべての割合はおおよその数であり、レベルを調整してイシューに対応する可能性もあるため、開発者はこの期間が変動することも予期しておくことをお勧めします。Chrome ブラウザの全体的な割合も個々のサイトのトラフィックの割合に一致しない可能性もあるため、この数値を期待されるトラフィックの指標として捉えることをお勧めします。 + +{% endAside %} + +次に、8 月の始めに、提供を約 60% のブラウザに増やすことを考えています。これにも実験グループが含まれたままになるため、API ごとに異なるレベルの提供状況が確認される可能性があります。すべてがうまくいった場合、8 月中旬の 116 安定版リリースの頃までには約 99% のブラウザまで最終拡大が適用されます。この時点で、個々の実験グループもマージされ、潜在的なイシューの検出を補助するために、すべての API を有効にしていない隔離された小規模のグループのみが維持されるようになります。このレベルを維持して監視を続け、Chrome 対応テストモードの準備を開始する予定です。 + +{% Img src="image/udVScdcCFAdRjZwFdLk2jWAFQyr1/oPELU4sAmYTdAsahyFQy.png", alt="Chrome 安定版におけるバージョンごとのおおよその提供率。", width="800", height="339" %} + +このタイムラインは、過程での監視結果によって変更される可能性があります。これまでと同様に、各ステージを通過するたびにこちらでドキュメントを更新し、blink-dev スレッドに更新情報を投稿します。 + +## 登録 + +Chrome と Android でプライバシーサンドボックス広告関連 API にアクセスするには、開発者は[登録とアテステーションプロセス](https://goo.gle/privacy-sandbox-enroll)を完了する必要があります。これは間もなく API にアクセスするための必須要件となる予定ですので、できるだけ早期にプロセスを開始することをお勧めします。
ローカルでテストする場合には、Chrome 116 から Chrome フラグと CLI スイッチによるオーバーライドを開発者に提供しています。 + +- フラグ: `chrome://flags/#privacy-sandbox-enrollment-overrides` +- CLI: `--privacy-sandbox-enrollment-overrides=https://example.com,https://example.co.uk,...` + +## 統合オリジントライアルの終了 + +[プライバシーサンドボックス広告関連のオリジントライアル](/docs/privacy-sandbox/unified-origin-trial/)では、サイトは、広告関連 API で統一された実験を実行できます。オリジントライアルで有効になっているのと同じグループから API の拡大を開始し、既存のデータを継続できるようにしています。トークンとオリジントライアルは 2023 年 9 月 20 日まで有効となりますが、7 月末にはそれらを提供する必要はなくなります。また全体的なトラフィックの増加を開始するに当たり、今週は、安定版より前のチャンネル(ベータ、カナリアなど)におけるオリジントライアルトークンの要件の削除を開始する予定です。ただし、円滑に移行できるように、失効日前に API への登録を済ませておくことをお勧めします。オリジントライアルの終了が近づくにつれ、ガイダンスと手順の追加により[ドキュメント](/docs/privacy-sandbox/unified-origin-trial/)を更新します。 + +## ユーザーコントロールの更新 + +プライバシーサンドボックスコントロールのトライアルバージョンに代わる更新済みの広告プライバシーコントロールを徐々にロールアウトしています。8 月中旬の完了を目標に、API と同じようなタイミングで新しい UX を有効化しています。
開発者は、`chrome://flags/#privacy-sandbox-settings-4` でフラグを有効にすることで、テスト用に新しい設定を有効化できます。以下の表には、関連する Chrome 設定とそれが制御する API を示しています。 + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
Chrome の設定 +
+
設定の場所 +
+
プライバシーサンドボックス API +
+
広告トピック
+

+
chrome://settings/adPrivacy/interests
+
+
+
Topics
+
サイトが提案する広告
+

+
chrome://settings/adPrivacy/sites
+
+
+
Protected Audience
+
広告の測定
+

+
chrome://settings/adPrivacy/measurement
+
+
+
Attribution Reporting
+ +## Chrome が提供するテストモード + +[Chrome が提供するテストモード](/docs/privacy-sandbox/chrome-testing/)については、初期の情報を以前に提供済みであり、こちらでは [developer support GitHub リポジトリ](https://github.com/GoogleChromeLabs/privacy-sandbox-dev-support/labels/chrome-testing)に寄せられたフィードバックへの対応も行っています。8 月中旬には技術的な詳細をさらに共有することを検討しています。それ以降は、開発者向けのオフィスアワーセッションを開催し、GitHub のテストモードイシューへの対応作業を引き続き行います。
以下のイシューに関するフィードバックをお寄せください。 + +- [テストにはモード A とモード B のいずれか、または両方を使用していますか?](https://github.com/GoogleChromeLabs/privacy-sandbox-dev-support/issues/112) +- [Chrome が提供するテストのラベルサイズの選択](https://github.com/GoogleChromeLabs/privacy-sandbox-dev-support/issues/113) +- [Chrome が提供するテストでのクライアントヒントの使用](https://github.com/GoogleChromeLabs/privacy-sandbox-dev-support/issues/114) + +その他の質問やディスカッションについては、[新しいイシューを提出](https://github.com/GoogleChromeLabs/privacy-sandbox-dev-support/issues)することもできます。 + +{% Aside %} + +英国の [Competition and Markets Authority](https://www.gov.uk/government/organisations/competition-and-markets-authority)(CMA)は、タイムライン、テスト方法、および次のステップに関する関連情報を記載した[プライバシーサンドボックス API のテストに関するガイダンス](https://assets.publishing.service.gov.uk/media/649d6a5f45b6a2000c3d455f/20230629_CMA_industry_testing_update_B.pdf)を公開しました。 + +{% endAside %} + +進行中の[プライバシーサンドボックスのタイムライン](https://privacysandbox.com/open-web/#the-privacy-sandbox-timeline)では、これらの API のリリースも重要なマイルストーンとなっています。このマイルストーンより、オリジントライアルでサイトがテストしている段階から、本番環境でこれらの API を統合する段階への移行が開始されることになります。API の有効化のフェーズを経て、2023 年の第 4 四半期でのラベルを使ったオプトインテスト、2024 年第 1 四半期のサードパーティ Cookie の1% 廃止、2024 年第 3 四半期のサードパーティ Cookie の完全撤廃に至るまで、更新情報を案内し続ける予定です。弊社は廃止の拡大に対するさらなる対応を行う前に、コミットメントに従って CMA と緊密に連携作業を進めていく予定です。 diff --git a/site/ja/blog/related-website-sets/index.md b/site/ja/blog/related-website-sets/index.md new file mode 100644 index 000000000..4a1cd1554 --- /dev/null +++ b/site/ja/blog/related-website-sets/index.md @@ -0,0 +1,55 @@ +--- +layout: layouts/blog-post.njk +title: Related Website Sets - Chrome 117 で First-Party Sets の名前を変更 +description: Related Website Sets(RWS)は、First-Party Sets の新しい名前です。セットをさらに柔軟に定義できるように改善されています。 +date: 2023-08-31 +thumbnail: image/80mq7dk16vVEg8BBhsVe42n6zn82/s3iDQJUgLZV25YbtYxs1.png +alt: プライバシーサンドボックスのロゴ +tags: + - privacy +authors: + - helencho +--- + +2024 年に開始されるサードパーティ Cookie の廃止に向け、Chrome 安定版では多数のプライバシーサンドボックス API が正式版(GA)へと強化されています。これらの API の中には、重要なクロスサイト Cookie のユースケースを保持する [CHIPS](/docs/privacy-sandbox/chips/) や、現在 [First-Party Sets(FPS)](/docs/privacy-sandbox/first-party-sets/)として知られている API も含まれています。この記事では、FPS の用途をさらによく反映して名前が変更された Related Website Sets(RWS)を紹介し、重要なユースケースと関連サブセットドメイン制限に関するアップデートについて説明します。 + +## 重要なユーザージャーニーの保持 + +RWS は、Chrome がデフォルトでサードパーティ Cookie へのアクセスを制限し始めた際にユーザー向けの機能が停止するのを最小限に抑えるように設計されています。プライバシーサンドボックスのプライバシーの目標を支持しながら、中断を最小限に抑えてユーザーがウェブを閲覧できるようにすることが目標です。この均衡を取るために、RWS はウェブサイトの機能に関連する特定のユースケースをターゲットとしています。 + +- [ccTLD のユースケース](https://github.com/WICG/first-party-sets/tree/main#defining-a-set-through-use-case-based-subsets)は、公開トラッカーに記録されている[ログイン例](https://issuetracker.google.com/268390722)などの破損に対処します。このようなケースは、通常ヒューリスティックベースの例外によってエコシステムで対処されます([参照 1](#ref-1) を参照)。 +- [サービスドメインのユースケース](https://github.com/WICG/first-party-sets/tree/main#defining-a-set-through-use-case-based-subsets)は、機密性を伴う機能(認証フローのサポートなど)をユーザー向けのドメインから分離する開発者の一般的な実践に対処します。このようなケースは、ターゲット[例外](https://searchfox.org/mozilla-central/rev/3002762e41363de8ee9ca80196d55e79651bcb6b/browser/extensions/webcompat/data/shims.js#686)によってエコシステムで対処されます([参照 2](#ref-2) を参照)。 +- [関連ドメインのユースケース](https://github.com/WICG/first-party-sets/tree/main#defining-a-set-through-use-case-based-subsets)は、重要なユーザージャーニーに関するサードパーティ Cookie アクセスが必要となるドメインのタイプにより高い柔軟性を提供します([参照 3](#ref-3) を参照)。ccTLD とサービスドメインのユースケースでは、ドメインの特徴に基づいて乱用を最小限に抑えるための厳しい技術チェックが採用されますが、関連ドメインでは、ドメイン数制限が使用されます。この詳細については、次のセクションをお読みください。 + +## 関連ドメインの制限が 5 ドメインに増加 + +Chrome は以前、Associated Subset(と 1 プライマリードメイン)に対して 3 ドメインの数制限を提案しました。これは、蔓延するトラッキングの乱用を防止することを目的に提案されたものでしたが、様々なユースケースに対応するにはこの数が少なすぎるというウェブ標準参加団体からのフィードバックを聞きいれることとしました。 + +他の主要ブラウザが提供する最も比較可能な実装に最も一致するように、関連ドメインの数制限を 5 に引き上げることに決定shしました([参照 4](#ref-4) を参照)。これは、Chrome 117 より適用されます。 + +RWS は広告ソリューションとしての機能を意図としていないため、広告ユースケースに役立つように RWS を改善する方法についてのフィードバックは考慮されていません。広告ユースケースにおいては、開発者は Topics、Protected Audience、および Attribution Reporting API の使用を詳しく調べ、それらに関するフィードバックを適宜提供してください。 + +## 5 関連ドメインの枠を超えた拡張ユースケースのオプション + +ユーザーに影響する、この制限でサポートされないエクスペリエンスについて、Chrome は、Storage Access API(SAA)という他のブラウザが採用した標準も利用する[ユーザープロンプトフローに取り組んでいます](https://github.com/cfredric/chrome-storage-access-api)。5 関連ドメイン以上の数が必要なユースケースについては、RWS 以外のコンテキストで SAA がどのようにサポートできるかを評価するように開発者に勧めています。[この機能](https://groups.google.com/a/chromium.org/g/blink-dev/c/JHf7CWXDZUc/m/Dy2EElgvAgAJ)については、別途 Blink のリリースプロセスに従っています。Blink は Chrome 117 よりデスクトップ版 Chrome で公開される予定です。 + +## 次のステップ + +これまでこの API の形成に貢献していただいたエコシステムからのフィードバックに感謝しています。開発者が構築するウェブサイトのエンドユーザーエクスペリエンスを維持するための予測可能性、制御性、および主体性を提供する方法として RWS に取り組んできました。RWS をリリースするに当たり、開発者がそれを採用して使用する要するを目の当たりにし、感激しています。[提出プロセス](https://github.com/GoogleChrome/first-party-sets/blob/main/FPS-Submission_Guidelines.md)は現在公開中であり、提出を支援するための出発点としては [RWS JSON ジェネレーターツール](https://goo.gle/rws-json-generator)を使用するのが最適です。 + +進捗は、[Intent to Ship スレッド](https://groups.google.com/a/chromium.org/g/blink-dev/c/7_6JDIfE1as/m/wModmpcaAgAJ)で追跡できます。また、実装ガイドについては、[こちらの資料](/docs/privacy-sandbox/first-party-sets-integration/)をご覧ください。 + +{% Details %} + +{% DetailsSummary %} + +リファレンス + +{% endDetailsSummary %} + +1. ブラウザ間で、これらのクロスサイト Cookie のユースケースは必要であるという一般的な合意がありますが、それぞれに異なる方法で有効にされます。[Firefox](https://developer.mozilla.org/docs/Web/Privacy/Storage_Access_Policy#automatic_storage_access_upon_interaction)([コード](https://searchfox.org/mozilla-central/rev/3002762e41363de8ee9ca80196d55e79651bcb6b/dom/base/Document.cpp#16328))と [Safari](https://webkit.org/blog/8311/intelligent-tracking-prevention-2-0/#:~:text=Temporary%20Compatibility%20Fix%3A%20Automatic%20Storage%20Access%20for%20Popups)([コード](https://searchfox.org/wubkat/rev/5b368793a8c0a3d99c6991fcd3ef96e3dbd2cf2a/Source/WebKit/NetworkProcess/Classifier/ResourceLoadStatisticsDatabaseStore.cpp#1266))はいずれもポップアップヒューリスティックの実装によって、[Nintendo ログインフロー](https://issuetracker.google.com/268390722)などで観察された破損に対処しています。 +2. また、ブラウザが例外をハードコーディングしてユーザーの中断を最小限に抑えた例も複数あります。Firefox は [Microsoft Teams と login.microsoftonline.us の間のリダイレクトフローでのストレージアクセス](https://searchfox.org/mozilla-central/rev/3002762e41363de8ee9ca80196d55e79651bcb6b/browser/extensions/webcompat/data/shims.js#686)を許可しています。 +3. Firefox は、ユーザーが instagram.com でログインすると [facebook.com に代わって requestStorageAccessForOrigin を呼び出す「shim」](https://searchfox.org/mozilla-central/source/browser/extensions/webcompat/shims/instagram.js)を提供しています。サイトのグループ化の例は、複数のドメインに対してストレージアクセスのプロンプトをグループ化する Safari の[ハードコーディングされた例外](https://github.com/WebKit/WebKit/blob/a2db53cd97dc8136ac5c2a22d4cd2b53d0d717d6/Source/WebCore/platform/network/NetworkStorageSession.cpp#L395)でも見られます。 +4. Firefox は、ユーザーが過去にアクセスしたことのある[サードパーティサイトが発行する最初の 5 つの requestStorageAccess 呼び出しを自動許可](https://developer.mozilla.org/docs/Web/API/Storage_Access_API#:~:text=Firefox%20only%20prompts%20users%20after%20an%20origin%20has%20requested%20storage%20access%20on%20more%20than%20a%20threshold%20number%20of%20sites)([コード](https://searchfox.org/mozilla-central/rev/c615dc4db129ece5cce6c96eb8cab8c5a3e26ac3/modules/libpref/init/StaticPrefList.yaml#4035))します。 Chrome では、同一サイトのプライマリードメインのほかに、関連サブセットにリストされている最初の 5 ドメインに、RWS を介して自動付与されたサードパーティ Cookie アクセスが与えられます。 + +{% endDetails %} From b60ef430a69444cc91ecd8125f273c709817a756 Mon Sep 17 00:00:00 2001 From: Nancymic2 Date: Tue, 12 Sep 2023 08:36:15 -0400 Subject: [PATCH 771/982] protected audience demo code links (#7260) --- site/en/_partials/privacy-sandbox/demos/paapi.md | 4 ++++ site/en/blog/fledge-api/index.md | 2 +- site/en/docs/privacy-sandbox/protected-audience-api/index.md | 2 +- .../privacy-sandbox/protected-audience-experiment/index.md | 2 +- 4 files changed, 7 insertions(+), 3 deletions(-) diff --git a/site/en/_partials/privacy-sandbox/demos/paapi.md b/site/en/_partials/privacy-sandbox/demos/paapi.md index b3dad753f..b65db4d16 100644 --- a/site/en/_partials/privacy-sandbox/demos/paapi.md +++ b/site/en/_partials/privacy-sandbox/demos/paapi.md @@ -10,8 +10,12 @@ and then initiates an on-device auction to select an ad for display on a publish [Demo](https://protected-audience-demo.web.app/) +[Demo code](https://github.com/GoogleChromeLabs/protected-audience-demo) + [Docs](/docs/privacy-sandbox/protected-audience-api/) + + {% endColumn %} {% Column %} diff --git a/site/en/blog/fledge-api/index.md b/site/en/blog/fledge-api/index.md index 8fcaf9856..aa3560655 100644 --- a/site/en/blog/fledge-api/index.md +++ b/site/en/blog/fledge-api/index.md @@ -1272,7 +1272,7 @@ to share feedback privately with the Chrome team outside of public forums. To ask a question about **your implementation**, about the **demo**, or about the **documentation**: * [Open a new issue](https://github.com/GoogleChromeLabs/privacy-sandbox-dev-support/issues/new/choose) on the privacy-sandbox-dev-support repository. Make sure to select the issue template for Protected Audience. -* Raise an issue on the [demo code repo on GitHub](https://github.com/JackJey/fledge-demo). +* Raise an issue on the [demo code repo on GitHub](https://github.com/GoogleChromeLabs/protected-audience-demo). * For more general questions about how to meet your **use cases** with the API, [file an issue on the proposal repository](https://github.com/WICG/turtledove/issues/new). diff --git a/site/en/docs/privacy-sandbox/protected-audience-api/index.md b/site/en/docs/privacy-sandbox/protected-audience-api/index.md index 8da049815..2aad7d18b 100644 --- a/site/en/docs/privacy-sandbox/protected-audience-api/index.md +++ b/site/en/docs/privacy-sandbox/protected-audience-api/index.md @@ -550,7 +550,7 @@ documentation: * **GitHub**: Read the [proposal](https://github.com/WICG/turtledove/blob/main/FLEDGE.md), [raise questions, and follow discussion](https://github.com/WICG/turtledove/issues). -* **Demo**: Raise an issue on the [demo code repository](https://github.com/JackJey/fledge-demo). +* **Demo**: Raise an issue on the [demo code repository](https://github.com/GoogleChromeLabs/protected-audience-demo). * **Developer support**: Ask questions and join discussions on the [Privacy Sandbox Developer Support repo](https://github.com/GoogleChromeLabs/privacy-sandbox-dev-support). diff --git a/site/en/docs/privacy-sandbox/protected-audience-experiment/index.md b/site/en/docs/privacy-sandbox/protected-audience-experiment/index.md index fef41838c..16f41b8cb 100644 --- a/site/en/docs/privacy-sandbox/protected-audience-experiment/index.md +++ b/site/en/docs/privacy-sandbox/protected-audience-experiment/index.md @@ -67,7 +67,7 @@ about **your implementation**, the **demo**, or the **documentation**: on the Privacy Sandbox Dev Support repository. Make sure to select the Issue template for the Protected Audience API. * Raise an issue on the [demo code repo on - GitHub](https://github.com/JackJey/fledge-demo). + GitHub](https://github.com/GoogleChromeLabs/protected-audience-demo). * For more general questions about how to meet your **use cases** with the API, [file an issue on the proposal repository](https://github.com/WICG/turtledove/issues/new). From 79a1ecb1944bb55115a6393cf02452422efae2c6 Mon Sep 17 00:00:00 2001 From: wizardofdocs <83661258+wizardofdocs@users.noreply.github.com> Date: Tue, 12 Sep 2023 07:29:27 -0700 Subject: [PATCH 772/982] Update "Override Chrome pages" (#7197) * Update index.md * Reworded examples link Co-authored-by: Joe Medley * Update site/en/docs/extensions/mv3/override/index.md Fixed HTML in inline code Co-authored-by: Joe Medley * Updated Overrides Fixed inline code. Updated Update date. * Update site/en/docs/extensions/mv3/override/index.md Changed negative phrasing to positive phrasing Co-authored-by: Oliver Dunk * Updated phrasing in Overrides * Update site/en/docs/extensions/mv3/override/index.md Clarified fetch context Co-authored-by: Joe Medley * Update site/en/docs/extensions/mv3/override/index.md Corrected typo Co-authored-by: Joe Medley --------- Co-authored-by: Joe Medley Co-authored-by: Oliver Dunk --- site/en/docs/extensions/mv3/override/index.md | 60 ++++++++----------- 1 file changed, 26 insertions(+), 34 deletions(-) diff --git a/site/en/docs/extensions/mv3/override/index.md b/site/en/docs/extensions/mv3/override/index.md index 45a392440..fbf659b6a 100644 --- a/site/en/docs/extensions/mv3/override/index.md +++ b/site/en/docs/extensions/mv3/override/index.md @@ -1,18 +1,15 @@ --- layout: "layouts/doc-post.njk" -title: "Overriding Chrome pages" -seoTitle: "Chrome Extensions: Overriding Chrome pages" +title: "Override Chrome pages" +seoTitle: "Chrome Extensions: Override Chrome pages" date: 2012-09-18 -updated: 2023-02-06 +updated: 2023-08-31 description: > How to override the Chrome bookmark manager, history, and new tab pages from your Chrome Extension. --- -Override pages are a way to substitute an HTML file from your extension for a page that Google -Chrome normally provides like New Tab page. In addition to HTML, an override page usually has CSS and JavaScript code. - -An extension can replace any one of the following pages: +Extensions can use HTML override pages to replace a page Google Chrome normally provides. An extension can contain an override for any of the following pages, but each extension can only override one page: Bookmark Manager : The page that appears when the user chooses the Bookmark Manager menu item @@ -28,14 +25,6 @@ New Tab : The page that appears when the user creates a new tab or window. You can also get to this page by entering the URL **chrome://newtab**. -{% Aside %} -A single extension can override only one page. For example, an extension can't override both the Bookmark Manager and History pages. -{% endAside %} - -Incognito windows are treated specially. New Tab pages cannot be overridden in incognito windows. -Other override pages work in incognito windows as long as the [incognito][1] manifest property is -set to "spanning" (which is the default value). See [Saving data and incognito mode][2] in Protect User Privacy for more details on how you should treat incognito windows. - The following screenshots show the default New Tab page and then a custom New Tab page.
@@ -50,9 +39,16 @@ The following screenshots show the default New Tab page and then a custom New Ta
A custom new tab page.
+To try this out, see our [override samples][4]. + +## Incognito window behavior {: #incognito } + +In incognito windows, extensions can't override New Tab pages. Other pages still work if the [incognito][2] manifest property is +set to "spanning" (the default value). For details on how to handle incognito windows, see [Saving data and incognito mode][3]. + ## Manifest {: #manifest } -Register an override page in the [extension manifest][3] like this: +Use the following code to register an override page in the [extension manifest][4]: ```json/4-6 { @@ -69,30 +65,26 @@ Register an override page in the [extension manifest][3] like this: For `PAGE_TO_OVERRIDE`, substitute one of the following: -- `bookmarks` -- `history` -- `newtab` - -## Tips {: #tips } +- `"bookmarks"` +- `"history"` +- `"newtab"` -For an effective override page, follow these guidelines: +## Best practices {: #tips } -**Make your page quick and small.**
Users expect built-in browser pages to open instantly. Avoid doing things that might take a long -time. For example, avoid synchronous fetches of network or database resources. +* **Make your page quick and small.**
Users expect built-in browser pages to open instantly. Avoid doing things that might take a long +time. Specifically, avoid accessing database resources synchronously. When making network requests, prefer [`fetch()`](https://developer.mozilla.org/docs/Web/API/fetch) over `XMLHttpRequest()`. -**Include a title in your page.**
Otherwise people might see the URL of the page, which could be confusing. Here's an example of -specifying the title: `New Tab` +* **To avoid user confusion, give your page a title.**
Without a title, the page title defaults to the URL. Specify the title using the `` tag in your HTML file. -**Don't rely on the page having the keyboard focus.**<br/>The address bar always gets the focus first when the user creates a new tab. +* **Remember that new tabs give keyboard focus to the address bar first.** Don't rely on keyboard focus defaulting to other parts of the page. -**Don't try to emulate the default New Tab page.**<br/>The APIs necessary to create a slightly modified version of the default New Tab page—with top -pages, recently closed pages, tips, a theme background image, and so on—don't exist. +* **Make the new tab page your own.** <br/>Avoid creating a new tab page which users may confuse with Chrome's default new tab page. ## Examples {: #examples } -See the [override samples][4]. +See the [override samples][1]. -[1]: /docs/extensions/mv3/manifest/incognito -[2]: /docs/extensions/mv3/user_privacy#data-incognito -[3]: /docs/extensions/mv3/manifest/ -[4]: /docs/extensions/samples/ +[1]: /docs/extensions/mv3/samples#search:chrome_url_overrides +[2]: /docs/extensions/mv3/manifest/incognito +[3]: /docs/extensions/mv3/user_privacy#data-incognito +[4]: /docs/extensions/mv3/manifest/ From 0734724c8ba88005aa3b966c8ee0756690c10502 Mon Sep 17 00:00:00 2001 From: Barry Pollard <barrypollard@google.com> Date: Tue, 12 Sep 2023 16:36:10 +0200 Subject: [PATCH 773/982] September 2023 CrUX Release (for August data) (#7284) * September 2023 CrUX Release (for August data) * Link updates * Apply suggestions from code review Co-authored-by: Jeremy Wagner <malchata@users.noreply.github.com> --------- Co-authored-by: Jeremy Wagner <malchata@users.noreply.github.com> --- site/en/docs/crux/release-notes/index.md | 50 ++++++++++++++---------- 1 file changed, 30 insertions(+), 20 deletions(-) diff --git a/site/en/docs/crux/release-notes/index.md b/site/en/docs/crux/release-notes/index.md index 2edfd547c..46c8e083d 100644 --- a/site/en/docs/crux/release-notes/index.md +++ b/site/en/docs/crux/release-notes/index.md @@ -21,7 +21,7 @@ date: 2017-10-01 # Optional # Include an updated date when you update your post -updated: 2023-08-03 +updated: 2023-09-12 # Optional # How to add a new author @@ -43,6 +43,26 @@ The CrUX dataset on BigQuery is generally updated on the second Tuesday of every In the list below, we've curated some release notes for each monthly dataset. Subscribe to our [CrUX Announce](https://groups.google.com/a/chromium.org/forum/#!forum/chrome-ux-report-announce) mailing list or follow [@ChromeUXReport](https://twitter.com/ChromeUXReport) on Twitter for release Announcements. +## 202308 + +[Announcement](https://groups.google.com/a/chromium.org/g/chrome-ux-report-announce/c/CJT8_DbO9DU) + +Publication date + : September 12, 2023 + +What's new + : We're seeing continual improvements across most of the metrics which seem to be driven by the following changes: + : - Chrome [started rolling out a change to increase image priority from low to medium for the first 5 images](https://chromium.googlesource.com/chromium/src/+/refs/heads/main/docs/speed/metrics_changelog/2023_08_image_loading.md) which may have improved LCP and CLS (testing showed less impact on LCP, and more on CLS). + : - Chrome made a change for LCP for animated image formats (for example, GIFs) which now measure [the first frame rather than the full image load time as the LCP time](https://chromium.googlesource.com/chromium/src/+/refs/heads/main/docs/speed/metrics_changelog/2023_08_lcp.md#animated-images). This is expected to improve the LCP for the small number of sites that have animated images as LCP elements. + : - Chrome made another change for LCP whereby [video elements are now considered as LCP element candidates](https://chromium.googlesource.com/chromium/src/+/refs/heads/main/docs/speed/metrics_changelog/2023_08_lcp.md#videos). Previously they were only considered with a poster image. As videos are typically larger resources to download, this is expected to deteriorate the LCP for the small number of sites that have videos as LCP elements. + : Note that all of these changes are still rolling out so the full effect of all these changes has not been seen yet and hopefully we will see further improvements next month too. + : On a less positive note, INP pass rates remained static, showing it's a more tricky metric to optimize for. + +Notable stats + : - 18,263,523 origins + : - 45.3% of origins have good [Core Web Vitals](https://web.dev/vitals/#core-web-vitals) + : - 41.6% of origins have good Core Web Vitals when [using INP in place of FID as will happen from March 2024](https://web.dev/inp-cwv/). + ## 202307 [Announcement](https://groups.google.com/a/chromium.org/g/chrome-ux-report-announce/c/76V2bzaidBk) @@ -51,16 +71,13 @@ Publication date : August 8, 2023 What's new - -As noted last month, we made progress on origins with redirects on their root page not showing in CrUX and since then we resolved the last of the known issues and this month no origins should be excluded for this reason. - -As warned in the last few releases, we have now removed the experimental prefixed Interaction to Next Paint metric from CrUX BigQuery, API, and History API. Users need to use the non-prefixed field to access this metric. + : - As noted last month, we made progress on origins with redirects on their root page not showing in CrUX and since then we resolved the last of the known issues, and this month, no origins should be excluded for this reason. + : - As warned in the last few releases, we have now removed the experimental prefixed Interaction to Next Paint metric from CrUX BigQuery, API, and History API. Users need to use the non-prefixed field to access this metric. Notable stats : - 17,976,663 origins : - 44.6% of origins have good [Core Web Vitals](https://web.dev/vitals/#core-web-vitals) - ## 202306 [Announcement](https://groups.google.com/a/chromium.org/g/chrome-ux-report-announce/c/AaW8rohYfHk) @@ -69,10 +86,8 @@ Publication date : July 11, 2023 What's new - -I am pleased to say that we have finally made progress on the long-standing root page redirect issue [mentioned last month](https://groups.google.com/a/chromium.org/g/chrome-ux-report-announce/c/13hl37E28RE). Some origins which redirect their root page, and were therefore excluded from CrUX due to our lack of handling this properly, should now start to be included again from this month. Please note that some origins are still being resolved so not all origins are in this month's dataset. However, it is great that we have made some good progress on this now and we hope to have the issue fully resolved in the near future. - -This is the last month that the INP metric is guaranteed to be available in the CrUX BigQuery, API, and History API both with and without the experimental prefix. We encourage users to move to the non-prefixed field as the experimental prefix fields should now be considered deprecated and will be removed in 30 days. + : - We are pleased to announce that we have finally made progress on the long-standing root page redirect issue [mentioned last month](https://groups.google.com/a/chromium.org/g/chrome-ux-report-announce/c/13hl37E28RE). Some origins which redirect their root page, and were therefore excluded from CrUX due to our lack of handling this properly, should now start to be included again from this month. Please note that some origins are still being resolved, so not all origins are in this month's dataset. However, it is great that we have made some good progress on this now and we hope to have the issue fully resolved in the near future. + : - This is the last month that the INP metric is guaranteed to be available in the CrUX BigQuery, API, and History API both with and without the experimental prefix. We encourage users to move to the non-prefixed field, as the experimental prefix fields should now be considered deprecated and will be removed in 30 days. Notable stats : - 18,065,718 origins @@ -86,10 +101,8 @@ Publication date : June 13, 2023 What's new - -We're seeing a slight decrease again this month for LCP and FCP due to the final roll outs of the [change in LCP to ignore low-entropy images](https://chromium.googlesource.com/chromium/src/+/refs/heads/main/docs/speed/metrics_changelog/2023_04_lcp.md) and [correction in paint timing](https://chromium.googlesource.com/chromium/src/+/refs/heads/main/docs/speed/metrics_changelog/2023_03_lcp_fcp.md) discussed last month. However, despite this, the overall good LCP, FID, and CLS rates are up slightly from last month. - -We are aware that some origins that redirect their root page (for example, https://www.example.com that automatically redirects to https://www.example.com/en/) are not showing origin-level data in CrUX, and so are also not appearing in the BigQuery dataset. We're also aware that this has been going on for some time. Unfortunately, this is proving a difficult issue to resolve and so we still do not have an estimated time of when this will be resolved. + : - We're seeing a slight decrease again this month for LCP and FCP due to the final roll outs of the [change in LCP to ignore low-entropy images](https://chromium.googlesource.com/chromium/src/+/refs/heads/main/docs/speed/metrics_changelog/2023_04_lcp.md) and [correction in paint timing](https://chromium.googlesource.com/chromium/src/+/refs/heads/main/docs/speed/metrics_changelog/2023_03_lcp_fcp.md) discussed last month. However, despite this, the overall good LCP, FID, and CLS rates are up slightly from last month. + : - We are aware that some origins that redirect their root page (for example, https://www.example.com that automatically redirects to https://www.example.com/en/) are not showing origin-level data in CrUX, and so are also not appearing in the BigQuery dataset. We're also aware that this has been going on for some time. Unfortunately, this is proving a difficult issue to resolve, and so we still do not have an estimated time of when this will be fixed. Notable stats : - 18,377,791 origins @@ -103,12 +116,9 @@ Publication date : May 10, 2023 What's new - -We’re seeing a slight decrease in pass rates for the Core Web Vitals, especially for LCP due in part to [a change in LCP to ignore low-entropy images](https://chromium.googlesource.com/chromium/src/+/refs/heads/main/docs/speed/metrics_changelog/2023_04_lcp.md). We also see a decrease in FCP pass rates [due to correction in paint timing](https://chromium.googlesource.com/chromium/src/+/refs/heads/main/docs/speed/metrics_changelog/2023_03_lcp_fcp.md) (which also affects LCP but to a lesser extent). - -On a more positive note [INP](https://web.dev/inp/) continues to improve with a further improvement of 0.2%. This is especially important as we are [moving this metric from an Experimental metric to a Pending metric](https://web.dev/inp-cwv/), and it will join the reset of the Core Web Vitals next year. - -From this release, the INP metric is available in the [CrUX BigQuery](/docs/crux/bigquery/), [API](/docs/crux/api/), and [History API](/docs/crux/history-api/) both with and without the experimental prefix. We encourage users to move to the non-prefixed field as the experimental prefix fields should now be considered deprecated and will be removed in 90 days. + : - We're seeing a slight decrease in pass rates for the Core Web Vitals, especially for LCP due in part to [a change in LCP to ignore low-entropy images](https://chromium.googlesource.com/chromium/src/+/refs/heads/main/docs/speed/metrics_changelog/2023_04_lcp.md). We also see a decrease in FCP pass rates [due to correction in paint timing](https://chromium.googlesource.com/chromium/src/+/refs/heads/main/docs/speed/metrics_changelog/2023_03_lcp_fcp.md) (which also affects LCP but to a lesser extent). + : - On a more positive note, the [INP](https://web.dev/inp/) pass rate continues to improve with a further increase of 0.2%. This is especially important, as we are [moving this metric from an Experimental metric to a Pending metric](https://web.dev/inp-cwv/), and it will join the reset of the Core Web Vitals next year. + : - From this release, the INP metric is available in the [CrUX BigQuery](/docs/crux/bigquery/), [API](/docs/crux/api/), and [History API](/docs/crux/history-api/), both with and without the experimental prefix. We encourage users to move to the non-prefixed field, as the experimental prefix fields should now be considered deprecated and will be removed in 90 days. Notable stats : - 18,406,973 origins From 4cbc6fa2906467e14c2fc477ebd6860ede946b90 Mon Sep 17 00:00:00 2001 From: Sofia Emelianova <42939855+sofiayem@users.noreply.github.com> Date: Tue, 12 Sep 2023 15:50:25 +0100 Subject: [PATCH 774/982] network upds (#7144) --- .../docs/devtools/network/reference/index.md | 55 ++++++++++++++++--- 1 file changed, 47 insertions(+), 8 deletions(-) diff --git a/site/en/docs/devtools/network/reference/index.md b/site/en/docs/devtools/network/reference/index.md index 76795bdf8..53b2ceda0 100644 --- a/site/en/docs/devtools/network/reference/index.md +++ b/site/en/docs/devtools/network/reference/index.md @@ -255,9 +255,45 @@ shown. [Data URLs][12] are small files embedded into other documents. Any request that you see in the **Requests** table that starts with `data:` is a data URL. -Check the **Hide data URLs** checkbox to hide these requests. +To hide these requests, check {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/hmp8j3HiLMCcqPArD9yt.svg", alt="Checkbox.", width="22", height="22" %} **Hide data URLs**. -{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/Y3TDa8EhT6gARFcLFwKf.png", alt="The Hide Data URLs checkbox.", width="800", height="514" %} +{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/y3wTmRMS9Y5JlM0Z9wBF.png", alt="Data URLs hidden from the Requests table.", width="800", height="567" %} + +The status bar at the bottom displays the number of the shown requests out of the total. + +### Hide extension URLs {: #hide-extension-urls } + +To focus on the code you author, you can filter out irrelevant requests sent by extensions you may have installed in Chrome. Extension requests have URLs that start with `chrome-extension://`. + +To hide extension requests, check {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/hmp8j3HiLMCcqPArD9yt.svg", alt="Checkbox.", width="22", height="22" %} **Hide extension URLs**. + +{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/07CwNEuofVPa8jp3LFfm.png", alt="Extension URLs hidden from the Requests table.", width="800", height="478" %} + +The status bar at the bottom displays the number of the shown requests out of the total. + +### Show only the requests with blocked response cookies {: #show-blocked-cookies } + +To filter out everything except the requests with response cookies blocked for any reason, check {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/hmp8j3HiLMCcqPArD9yt.svg", alt="Checkbox.", width="22", height="22" %} **Blocked response cookies**. Try it on this [demo page](https://samesite-sandbox.glitch.me/). + +{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/owWZhGDXayLxFQdo20vO.png", alt="The Requests table shows only the requests with blocked response cookies.", width="800", height="550" %} + +The status bar at the bottom displays the number of the shown requests out of the total. + +To find out the reason why a response cookie was blocked, select the request, open its **Cookies** tab, and hover over the {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/qruVplg26sPV7Ryl8fHg.svg", alt="", width="24", height="24" %} information icon. + +### Show only blocked requests {: #show-blocked } + +To filter out everything except blocked requests, check {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/hmp8j3HiLMCcqPArD9yt.svg", alt="Checkbox.", width="22", height="22" %} **Blocked requests**. To test this, you can use the [**Network request blocking**](/docs/devtools/network/#block) drawer tab. + +{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/MWJci8DFgTzlOI18Wlqz.png", alt="The Requests table shows only blocked requests.", width="800", height="517" %} + +The **Requests** table highlights blocked requests in red. The status bar at the bottom displays the number of the shown requests out of the total. + +### Show only third-party requests {: #third-party } + +To filter out everything except the requests with with origin that differs from page origin, check {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/hmp8j3HiLMCcqPArD9yt.svg", alt="Checkbox.", width="22", height="22" %} **3rd-party requests**. Try it on this [demo page](https://samesite-sandbox.glitch.me/). + +{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/K6waxv6tB2anAbECE4pK.png", alt="The Requests table shows only the third-party requests.", width="800", height="455" %} The status bar at the bottom displays the number of the shown requests out of the total. @@ -340,7 +376,7 @@ To add a custom column to the **Requests** table: ### Group requests by inline frames {: #group-by-frames } -If inline frames on a page initiate a lot of requests, you can make the request log frendlier by grouping them. +If inline frames on a page initiate a lot of requests, you can make the request log friendlier by grouping them. To group requests by iframes, open **Settings** {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/9gzXiTYY0nZzBxGI6KrV.svg", alt="Settings.", width="24", height="24" %} inside the **Network** panel and check {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/hmp8j3HiLMCcqPArD9yt.svg", alt="Checkbox.", width="22", height="22" %} **Group by frame**. @@ -407,12 +443,16 @@ To view the response body to a request: ### View HTTP headers {: #headers } -To view HTTP header data about a request: +To view HTTP header data of a request: -1. Click on the URL of the request, under the **Name** column of the Requests table. -2. Click the **Headers** tab. +1. Click a request in the **Requests** table. +1. Open the **Headers** tab and scroll down to **General**, **Response Headers**, or **Request Headers** sections. -{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/0l9iRxK3yvrnha53NiKH.png", alt="The Headers tab.", width="800", height="469" %} +{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/j67jfFC4iJveVZhMVFwg.png", alt="The Headers tab of a request selected from the Requests table.", width="800", height="683" %} + +In the **General** section, DevTools shows you human-readable status message next to the received HTTP status code. + +In the **Response Headers** section, you can hover over a header value and click the {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/k3WKQOAItcJ2pliOyD47.svg", alt="Edit.", width="24", height="24" %} **Edit** button to [override the response header locally](/docs/devtools/overrides/#override-headers). #### View HTTP header source {: #header-source } @@ -422,7 +462,6 @@ order they were received: 1. Open the **Headers** tab for the request you're interested in. See [View HTTP headers][15]. 2. Click **view source**, next to the **Request Header** or **Response Header** section. - #### Provisional headers warning {: #provisional-headers } Sometimes the **Headers** tab shows the `Provisional headers are shown...` warning message. This may be due to the following reasons: From 5e78e1eaf32d86f6b35344171e4ca823ac99b246 Mon Sep 17 00:00:00 2001 From: Ian Kerins <git@isk.haus> Date: Tue, 12 Sep 2023 11:00:07 -0400 Subject: [PATCH 775/982] Fix typo in crux API doc (#6728) Co-authored-by: Barry Pollard <barrypollard@google.com> --- site/en/docs/crux/api/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/en/docs/crux/api/index.md b/site/en/docs/crux/api/index.md index aecc1d366..57454edb8 100644 --- a/site/en/docs/crux/api/index.md +++ b/site/en/docs/crux/api/index.md @@ -692,7 +692,7 @@ A bin's start and end values are given in the value type of the metric it repres #### UrlNormalization {: #api-response-urlnormalization } -Object representing the normalization actions taken to normalize a url to achieve a higher chance of successful lookup. These are simple automated changes that are taken when looking up the provided `url_patten` would be known to fail. Complex actions like following redirects are not handled. +Object representing the normalization actions taken to normalize a url to achieve a higher chance of successful lookup. These are simple automated changes that are taken when looking up the provided `url_pattern` would be known to fail. Complex actions like following redirects are not handled. ```json { From 988a0779b5a26664e12addb790be58b62a92d032 Mon Sep 17 00:00:00 2001 From: Nancymic2 <nmichell@google.com> Date: Tue, 12 Sep 2023 11:03:39 -0400 Subject: [PATCH 776/982] remove use-shared-storage and the one link to it (#6716) * remove use-shared-storage and the one link to it * Remove link --- .../private-aggregation/index.md | 2 +- .../use-shared-storage/index.md | 99 ------------------- 2 files changed, 1 insertion(+), 100 deletions(-) delete mode 100644 site/en/docs/privacy-sandbox/use-shared-storage/index.md diff --git a/site/en/docs/privacy-sandbox/private-aggregation/index.md b/site/en/docs/privacy-sandbox/private-aggregation/index.md index fe12c9388..998e970da 100644 --- a/site/en/docs/privacy-sandbox/private-aggregation/index.md +++ b/site/en/docs/privacy-sandbox/private-aggregation/index.md @@ -110,7 +110,7 @@ From a Protected Audience API worklet, you can aggregate your data directly usin ## Available functions -The following functions are available in the `privateAggregation` object available in Shared Storage and Protected Audience API worklets. To learn how to run your code in a worklet, refer to the [Shared Storage code samples](/docs/privacy-sandbox/use-shared-storage/). +The following functions are available in the `privateAggregation` object available in Shared Storage and Protected Audience API worklets. ### contributeToHistogram() diff --git a/site/en/docs/privacy-sandbox/use-shared-storage/index.md b/site/en/docs/privacy-sandbox/use-shared-storage/index.md deleted file mode 100644 index e71b34522..000000000 --- a/site/en/docs/privacy-sandbox/use-shared-storage/index.md +++ /dev/null @@ -1,99 +0,0 @@ ---- -layout: 'layouts/doc-post.njk' -title: 'Use Shared Storage' -subhead: > - Examine use cases and code samples for Shared Storage. -description: > - Examine use cases and code samples for Shared Storage. -date: 2022-06-28 -updated: 2022-10-14 -authors: - - alexandrawhite - - kevinkiklee ---- - -The Shared Storage proposal intends to create a general purpose cross-site -storage API which supports many possible use cases. In this document, you'll -find code samples to help you get started. - -The following features are available to test in Chrome 104: - -* [**Creative selection by frequency**](/docs/privacy-sandbox/shared-storage/creative-selection-by-frequency): - run a worklet script to select a URL from a provided list, based on the - stored data, and then render that URL in a fenced frame. This has many - possible uses, such as selecting new content when a frequency cap is reached. -* [**A/B testing**](/docs/privacy-sandbox/shared-storage/ab-testing): You can assign a user to an experiment - group, then store that group in Shared Storage to be accessed cross-site. -* [**Creative rotation**](/docs/privacy-sandbox/shared-storage/creative-rotation): You can store the creative - rotation mode, and other metadata, to rotate the creatives across different sites. -* [**Known customer for payment provider**](/docs/privacy-sandbox/shared-storage/known-customer): You can store - whether the user has registered on your site into Shared Storage, then - render a different element based on that stored status. - -The following use case isn't available for testing in Chrome Beta, but we -intend to support it in the future: - -* [**Noisy aggregation of cross-site data**](#aggregated-data): you will be - able to run a worklet script to aggregate your data with the - [Private Aggregation API](/docs/privacy-sandbox/private-aggregation) - which returns a privacy-preserving report. - -These are only some of the possible use cases for Shared Storage. We'll -continue to add examples as we -[receive feedback](/docs/privacy-sandbox/shared-storage/#engage-and-share-feedback) -and discover new use cases. - -## Try the Shared Storage API - -Shared Storage API with Fenced Frames can be tested in Chrome 104 (version -104.0.5086.0 or later) by enabling the **Privacy Sandbox Ads APIs experiment** -flag at `chrome://flags/#privacy-sandbox-ads-apis`. - -{% Img - src="image/hVf1flv5Jdag8OQKYqOcJgWUvtz1/CWfgCMJQ5cYPOfjttF3k.png", - alt="Set Privacy Sandbox Ads APIs experiment to enabled to use these APIs", - width="744", height="124" -%} - -You can also enable Shared Storage with the `--enable-features=PrivacySandboxAdsAPIsOverride,OverridePrivacySandboxSettingsLocalTesting,SharedStorageAPI,FencedFrames` flag in the command line. - -### Use the demo - -The demo can be accessed at [goo.gle/shared-storage-demo](http://goo.gle/shared-storage-demo), -and the code is available on -[GitHub](https://github.com/GoogleChromeLabs/shared-storage-demo). - -The demo is constructed from the perspective of an advertiser/DSP that wants to -store information across different publishers. Think of the advertiser as a -shoe company, and the publishers as news companies. In the demo, the same -advertiser code will run on both **Publisher A** and **Publisher B** sites for -each use case. Visit both publishers to see how the data is shared between two -sites. - -The demo contains frequency capping, creative rotation, known customer, and A/B -testing use cases. - -### Not recommended: user consent status {: #user-content-status } - -Ad tech companies often have cross-site consent statuses that they need to keep -track of. For example, an ad tech company may want to store if a user consents -to an ad tech's terms or service or policies related to regulations, such as -GDPR. - -**Shared storage is not recommended for this use case**. This is because: - -1. A user might opt-out of using the privacy sandbox apis, which would prevent - organizations from using shared storage at all. -1. The current output gates will require k-anonymity or additional noise - sometime after the Origin Trial, which would mean there is a non-zero chance - the consent status would not be 100% accurately represented in all cases. - -## Engage and share feedback - -The Shared Storage proposal is under active discussion and subject to change -in the future. If you try this API and have feedback, we'd love to hear it. - -* **GitHub**: Read the - [proposal](https://github.com/pythagoraskitty/shared-storage), [raise questions and participate in discussion](https://github.com/pythagoraskitty/shared-storage/issues). -* **Developer support**: Ask questions and join discussions on the - [Privacy Sandbox Developer Support repo](https://github.com/GoogleChromeLabs/privacy-sandbox-dev-support). From c8228f00d2bce26a26dd348065f56bb0db061e8f Mon Sep 17 00:00:00 2001 From: Noah van der Aa <ndvdaa@gmail.com> Date: Tue, 12 Sep 2023 17:09:05 +0200 Subject: [PATCH 777/982] Fix typo in CrUX Dashboard docs (#4749) Co-authored-by: Barry Pollard <barrypollard@google.com> --- site/en/docs/crux/dashboard/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/en/docs/crux/dashboard/index.md b/site/en/docs/crux/dashboard/index.md index 3a678ed46..b00c3e0ae 100644 --- a/site/en/docs/crux/dashboard/index.md +++ b/site/en/docs/crux/dashboard/index.md @@ -37,7 +37,7 @@ tags: - crux --- -The CrUX Dashboard is a [Looker Studio](https://cloud.google.com/looker-studio) (formerly Data Studio) dashboard that links to the raw origin-level CrUX data on [BigQuery](/docs/crux/bigquery/) and the visualizes the data for you. It eliminates the need for users of the dashboard to write any queries or generate any charts. Everything is built for you; all you need is to provide an origin and the dashboard will be generated for you. +The CrUX Dashboard is a [Looker Studio](https://cloud.google.com/looker-studio) (formerly Data Studio) dashboard that links to the raw origin-level CrUX data on [BigQuery](/docs/crux/bigquery/) and then visualizes the data for you. It eliminates the need for users of the dashboard to write any queries or generate any charts. Everything is built for you; all you need is to provide an origin and the dashboard will be generated for you. ## Accessing the CrUX Dashboard From 153d8ba28ae904860b9763fc8ab13085b615e4f9 Mon Sep 17 00:00:00 2001 From: Nancymic2 <nmichell@google.com> Date: Tue, 12 Sep 2023 12:15:31 -0400 Subject: [PATCH 778/982] Update use cases for ARA debug reports (#7276) * Update use cases * Update index.md * Update index.md * Update index.md --- .../attribution-reporting-debugging/part-1/index.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/site/en/docs/privacy-sandbox/attribution-reporting-debugging/part-1/index.md b/site/en/docs/privacy-sandbox/attribution-reporting-debugging/part-1/index.md index 5fc6b92b2..6509fb204 100644 --- a/site/en/docs/privacy-sandbox/attribution-reporting-debugging/part-1/index.md +++ b/site/en/docs/privacy-sandbox/attribution-reporting-debugging/part-1/index.md @@ -4,7 +4,7 @@ title: 'Introduction to debug reports' subhead: Part 1 of 3 on debugging Attribution Reporting. Learn why debugging matters and when to use debug reports in testing. description: Part 1 of 3 on debugging Attribution Reporting. Learn why debugging matters and when to use debug reports in testing. date: 2022-12-13 -updated: 2023-03-02 +updated: 2023-09-11 authors: - maudn - alexandrawhite @@ -173,6 +173,10 @@ You may want to reprocess reports when you're: - experimenting with different batching strategies. - experimenting with different epsilon values. +### Data recovery + +We recommend ad techs enable debug mode to receive debug reports so they can recover their reporting data. This is useful in cases of Aggregation Service issues such as unavailable or non-responsive services that may cause summary report generation to fail. + ## Up next [Part 2: Set up debug reports](/docs/privacy-sandbox/attribution-reporting-debugging/part-2/) From 24e18e3cd2101a39f9e3ab884c46ff6b75d872bb Mon Sep 17 00:00:00 2001 From: Adriana Jara <32825533+tropicadri@users.noreply.github.com> Date: Tue, 12 Sep 2023 09:16:23 -0700 Subject: [PATCH 779/982] New in Chrome 1117 (#7279) New in chrome article 117 --- site/en/blog/new-in-chrome-117/index.md | 207 +++++++++++++++++++++++ site/es/blog/new-in-chrome-117/index.md | 208 ++++++++++++++++++++++++ 2 files changed, 415 insertions(+) create mode 100644 site/en/blog/new-in-chrome-117/index.md create mode 100644 site/es/blog/new-in-chrome-117/index.md diff --git a/site/en/blog/new-in-chrome-117/index.md b/site/en/blog/new-in-chrome-117/index.md new file mode 100644 index 000000000..385e03399 --- /dev/null +++ b/site/en/blog/new-in-chrome-117/index.md @@ -0,0 +1,207 @@ +--- +title: New in Chrome 117 +description: > + Chrome 117 is rolling out now! With three new CSS features that make it easy to add smooth entry and exit animations, array grouping to compute higher order datasets, devtools makes local overrides easier and there’s plenty more. +layout: 'layouts/blog-post.njk' +date: 2023-09-12 +authors: + - ajara +hero: 'image/SeARmcA1EicLXagFnVOe0ou9cqK2/msCTpRahj6qrF4R4m5y3.png' +alt: > + New in Chrome hero logo +tags: + - new-in-chrome + - chrome-117 +--- + +{% YouTube id='MOQpPiyoolM' %} + +Here's what you need to know: + +* [Three new CSS features](#exit-entry-animations) make it easy to add smooth entry and exit animations. +* Compute higher order datasets with [array grouping](#array-grouping). +* DevTools makes [local overrides easier](#local-overrides). +* And there’s plenty [more](#more). + +I’m Adriana Jara. Let’s dive in and see what’s new for developers in Chrome 117. + +## New CSS features for entry and exit animations. {: #exit-entry-animations} + +These three new CSS features complete the set to easily add entry and exit animations, +and smoothly animate to and from the top layer dismissible elements such as dialogs and popovers. + +The first feature is `transition-behavior`. To transition discrete properties, like `display`, use the `allow-discrete` value for `transition-behavior`. + +```css +.card { + transition: opacity 0.25s, display 0.25s; + transition-behavior: allow-discrete; /* Note: be sure to write this after the shorthand */ +} + +.card.fade-out { + opacity: 0; + display: none; +} +``` + +Then the `@starting-style` rule is used to animate entry effects from `display: none` and into the top-layer. Use `@starting-style` to apply a style that the browser can look up before the element is open on the page. + +```css +/* 0. BEFORE-OPEN STATE */ +/* Starting point for the transition */ +@starting-style { + .item { + opacity: 0; + height: 0; + } +} + +/* 1. IS-OPEN STATE */ +/* The state at which the element is open + transition logic */ +.item { + height: 3rem; + display: grid; + overflow: hidden; + transition: opacity 0.5s, transform 0.5s, height 0.5s, display 0.5s allow-discrete; +} + +/* 2. EXITING STATE */ +/* While it is deleting, before DOM removal in JS, apply this + transformation for height, opacity, and a transform which + skews the element and moves it to the left before setting + it to display: none */ +.is-deleting { + opacity: 0; + height: 0; + display: none; + transform: skewX(50deg) translateX(-25vw); +} +``` + +Finally, to fade out a `popover` or `dialog` from the top layer, add the `overlay` property to your list of transitions. Include overlay in the transition or animation to animate overlay along with the rest of the features and ensure it stays in the top layer when animating. This will look much smoother. + +```css +[open] { + transition: opacity 1s, display 1s allow-discrete; +} +``` + +<figure> + {% Video + src="video/HodOHWjMnbNw56hvNASHWSgZyAf2/kPZ5Ds1LJQ72ZAiMcaJX.mp4", + autoplay="true", + loop="true", + muted="true", + controls="true" + %} +</figure> + +```css +[open] { + transition: opacity 1s, display 1s allow-discrete, overlay 1s allow-discrete; +} +``` + +<figure> + {% Video + src="video/HodOHWjMnbNw56hvNASHWSgZyAf2/6kjtLdvlpz8ObkcbG2jV.mp4", + autoplay="true", + loop="true", + muted="true", + controls="true" + %} +</figure> + +Checkout [Four new CSS features for smooth entry and exit animations](/blog/entry-exit-animations/) for details on how to use these features for improving your user experience with motion. + +## Array grouping {: #array-grouping } + +In programming, array grouping is an extremely common operation, seen most often when we use SQL's GROUP BY clause and MapReduce programming (which is better thought of as map-group-reduce). + + The ability to combine data into groups allows developers to compute higher order datasets. +For example, the average age of a cohort, or daily LCP values for a webpage. + + Array grouping enables these scenarios by adding the `Object.groupBy` and `Map.groupBy` static methods. + +`groupBy` calls a provided callback function once for each element in an iterable. The callback function should return a string or symbol that indicates the group of the associated element. + +In the following example, from the [MDN documentation](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/groupBy), there is an array of products with the `groupBy` method used to return them grouped by their type. + +```js +const inventory = [ + { name: "asparagus", type: "vegetables", quantity: 5 }, + { name: "bananas", type: "fruit", quantity: 0 }, + { name: "goat", type: "meat", quantity: 23 }, + { name: "cherries", type: "fruit", quantity: 5 }, + { name: "fish", type: "meat", quantity: 22 }, +]; + +const result = Object.groupBy(inventory, ({ type }) => type); + +/* Result is: +{ + vegetables: [ + { name: 'asparagus', type: 'vegetables', quantity: 5 }, + ], + fruit: [ + { name: "bananas", type: "fruit", quantity: 0 }, + { name: "cherries", type: "fruit", quantity: 5 } + ], + meat: [ + { name: "goat", type: "meat", quantity: 23 }, + { name: "fish", type: "meat", quantity: 22 } + ] +} +*/ + +``` +For more details check out the [`groupBy` documentation](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/groupBy). + +## Local overrides streamlined in DevTools. {: #local-overrides } + +The [local overrides](/docs/devtools/overrides/) feature is now streamlined, so you can easily mock response headers and web content of remote resources from the **Network** panel without access to them. + +To override web content, open the **Network** panel, right-click a request, and select **Override content**. + +{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/BRExqF6iUJioa9YkiUeV.png", alt="The override options in the drop-down menu of a request.", width="800", height="685" %} + +If you have local overrides set up but disabled, DevTools enables them. If you haven't set them up yet, DevTools prompts you in the action bar at the top. Select a folder to store the overrides in and allow DevTools access to it. + +{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/cuNvCVUAVtICozqgThQi.png", alt="Select a folder and allow access to it in the action bar at the top.", width="800", height="507" %} + +Once the overrides are set up, DevTools then takes you to **Sources** > **Overrides** > **Editor** to let you [override web content](/docs/devtools/overrides/#make-changes). + +Note that the overridden resources are indicated with {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/s81rU6SgdmbseeBDGbPl.png", alt="Saved.", width="17", height="20" %} in the **Network** panel. Hover over the icon to see what's overridden. + +{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/hekOD6lUKKXipZ6qFT3D.png", alt="An override icon next to a request in the Network panel.", width="800", height="493" %} + +Check out [what’s new in DevTools](/blog/new-in-devtools-117/) for all the details and more information on DevTools in Chrome 117. + +## And more! {: #more } + +Of course there’s plenty more. + +* The much anticipated [`subgrid`](https://developer.mozilla.org/docs/Web/CSS/CSS_grid_layout/Subgrid) value for `grid-template-columns` and `grid-template-rows` is now implemented in Chrome. + +* There is a [`WebSQL` deprecation trial](/blog/deprecating-web-sql/) and a developer trial for the [`unload` event deprecation](/blog/deprecating-unload/). + +* The [`notRestoredReasons` API](/docs/web-platform/bfcache-notrestoredreasons/) for bfcache, mentioned in the [video for Chrome 116](https://youtu.be/JHwWUsMKYdk?si=sAzRp5hb5n9fQHxf&t=105), should be launching in this version. + +## Further reading + +This covers only some key highlights. Check the links below for +additional changes in Chrome 117. + +* [What's new in Chrome DevTools (117)](/blog/new-in-devtools-117/) +* [Chrome 117 deprecations and removals](/blog/deps-rems-117/) +* [ChromeStatus.com updates for Chrome 117](https://chromestatus.com/features#milestone%3D117) +* [Chromium source repository change list](https://chromium.googlesource.com/chromium/src/+log/116.0.5845.171..117.0.5938.57) +* [Chrome release calendar](https://chromiumdash.appspot.com/schedule) + +## Subscribe + +To stay up to date, [subscribe](https://goo.gl/6FP1a5) to the +[Chrome Developers YouTube channel](https://www.youtube.com/user/ChromeDevelopers/), +and you'll get an email notification whenever we launch a new video. + +Yo soy Adriana Jara, and as soon as Chrome 117 is released, I'll be right here to tell you what's new in Chrome! diff --git a/site/es/blog/new-in-chrome-117/index.md b/site/es/blog/new-in-chrome-117/index.md new file mode 100644 index 000000000..de3849c23 --- /dev/null +++ b/site/es/blog/new-in-chrome-117/index.md @@ -0,0 +1,208 @@ +--- +title: Nuevo en Chrome 117 +description: > + Chrome 117 ya está disponible! Con tres nuevas funciones de CSS que facilitan la creación de animaciones fluidas de entrada y salida, agrupación de arreglos para calcular conjuntos de datos de orden superior, DevTools facilita las alternativas locales y mucho más. +layout: 'layouts/blog-post.njk' +date: 2023-09-12 +authors: + - ajara +hero: 'image/SeARmcA1EicLXagFnVOe0ou9cqK2/msCTpRahj6qrF4R4m5y3.png' +alt: > + New in Chrome hero logo +tags: + - new-in-chrome + - chrome-117 +--- + +{% YouTube id='MOQpPiyoolM' %} + +Esto es lo que necesitas saber: + +* [Tres nuevas funciones CSS](#exit-entry-animations) facilitan la creación de animaciones fluidas de entrada y salida. +*Calcule conjuntos de datos de orden superior con [agrupación de matrices] (#array-grouping). +*DevTools facilita las [alternativas locales](#local-overrides). +* Y hay mucho [más](#más). + +Yo soy Adriana Jara. Profundicemos y veamos las novedades para los desarrolladores en Chrome 117. + +## Nuevas funciones de CSS para animaciones de entrada y salida. {: #exit-entry-animations} + +Estas tres nuevas características de CSS completan el conjunto para agregar fácilmente animaciones de entrada y salida. +Y animar de manera fluida desde y hacia la capa superior elementos descartables, como `<dialog>` y `<popover>` + +La primera característica es "transition-behavior". Para transicionar propiedades discretas , como `display` ,utilice el valor `allow-discrete` para `transition-behavior` + +```css +.card { + transition: opacity 0.25s, display 0.25s; + transition-behavior: allow-discrete; /* Note: be sure to write this after the shorthand */ +} + +.card.fade-out { + opacity: 0; + display: none; +} +``` + + +Luego, la regla `@starting-style` se usa para animar los efectos de entrada desde `display: none` y hasta la capa superior. Utilice `@starting-style` para aplicar un estilo que el navegador pueda buscar antes de que el elemento se abra en la página. + +```css +/* 0. BEFORE-OPEN STATE */ +/* Starting point for the transition */ +@starting-style { + .item { + opacity: 0; + height: 0; + } +} + +/* 1. IS-OPEN STATE */ +/* The state at which the element is open + transition logic */ +.item { + height: 3rem; + display: grid; + overflow: hidden; + transition: opacity 0.5s, transform 0.5s, height 0.5s, display 0.5s allow-discrete; +} + +/* 2. EXITING STATE */ +/* While it is deleting, before DOM removal in JS, apply this + transformation for height, opacity, and a transform which + skews the element and moves it to the left before setting + it to display: none */ +.is-deleting { + opacity: 0; + height: 0; + display: none; + transform: skewX(50deg) translateX(-25vw); +} +``` + +Finalmente, para desvanecer un `<popover>` o un `<dialog>` de la capa superior, agregue la propiedad `overlay` a su lista de transiciones. Incluya `overlay` en la transición o animación para animar la superposición junto con el resto de las funciones y asegúrese de que permanezca en la capa superior al animar. Esto se verá mucho más suave. + +```css +[open] { + transition: opacity 1s, display 1s allow-discrete; +} +``` + +<figure> + {% Video + src="video/HodOHWjMnbNw56hvNASHWSgZyAf2/kPZ5Ds1LJQ72ZAiMcaJX.mp4", + autoplay="true", + loop="true", + muted="true", + controls="true" + %} +</figure> + +```css +[open] { + transition: opacity 1s, display 1s allow-discrete, overlay 1s allow-discrete; +} +``` + +<figure> + {% Video + src="video/HodOHWjMnbNw56hvNASHWSgZyAf2/6kjtLdvlpz8ObkcbG2jV.mp4", + autoplay="true", + loop="true", + muted="true", + controls="true" + %} +</figure> + +Consulte [Cuatro nuevas funciones CSS para animaciones de entrada y salida fluidas](/blog/entry-exit-animations/) para obtener detalles sobre cómo utilizar estas funciones para mejorar su experiencia de usuario con movimiento. + +## Array grouping {: #array-grouping } + +En programación, la agrupación de matrices es una operación extremadamente común, la vemos con mayor frecuencia cuando usamos la cláusula `GROUP BY` de SQL y la programación MapReduce (que se considera mejor como map-group-reduce). + + La capacidad de combinar datos en grupos permite a los desarrolladores calcular conjuntos de datos de orden superior. +Por ejemplo, la edad promedio de una cohorte,o valores LCP diarios para una página web. + + La agrupación de matrices permite estos escenarios agregando los métodos estáticos `Object.groupBy` y `Map.groupBy`. + +`groupBy` llama una función de devolución de llamada proporcionada una vez para cada elemento en un iterable. La función de devolución de llamada debe devolver una cadena o símbolo que indique el grupo del elemento asociado. + +En el siguienteejemplo, de la [documentación de MDN](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/groupBy), hay una gama de productos con el `grupoPor` método utilizadoregresar ellos agrupados por su tipo. + +```js +const inventario = [ + { nombre: "espárragos", tipo: "verduras", cantidad: 5 }, + { nombre: "plátanos", tipo: "fruta", cantidad: 0 }, + { nombre: "cabra", tipo: "carne", cantidad: 23 }, + { nombre: "cerezas", tipo: "fruta", cantidad: 5 }, + { nombre: "pescado", tipo: "carne", cantidad: 22 }, +]; + +const result = Object.groupBy(inventario, ({ tipo }) => tipo); + +/* El resultado es: +{ + verduras: [ + { nombre: 'espárragos', tipo: 'verduras', cantidad: 5 }, + ], + fruta: [ + { nombre: "plátanos", tipo: "fruta", cantidad: 0 }, + { nombre: "cerezas", tipo: "fruta", cantidad: 5 } + ], + carne: [ + { nombre: "cabra", tipo: "carne", cantidad: 23 }, + { nombre: "pescado", tipo: "carne", cantidad: 22 } + ] +} +*/ + +``` +Para obtener más detalles, consulte la [documentación `groupBy`] (https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/groupBy). + +## Cambios locales optimizadas en DevTools. {: #local-overrides } + +La función [cambios locales](/docs/devtools/overrides/) ahora está optimizada, por lo que puede simular fácilmente encabezados de respuesta y contenido web de recursos remotos desde el panel **Red** sin acceso a ellos. + +Para anular el contenido web, abra el panel **Red**, haga clic con el botón derecho en una solicitud y seleccione **Anular contenido**. + +{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/BRExqF6iUJioa9YkiUeV.png", alt="Las opciones de anulación en el menú desplegable de una solicitud.", width="800", height="685" %} + +Si tiene cambios locales configuradas pero deshabilitadas, DevTools las habilita. Si aún no los ha configurado, DevTools se lo indica en la barra de acciones en la parte superior. Seleccione una carpeta para almacenar los cambios y permita que DevTools acceda a ella. + +{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/cuNvCVUAVtICozqgThQi.png", alt="Seleccione una carpeta y permita el acceso a ella en la barra de acciones en la parte superior.", width="800", height="507" %} + +Una vez configuradas las anulaciones, DevTools lo lleva a **Fuentes** > **Anulaciones** > **Editor** para permitirle [anular contenido web](/docs/devtools/overrides/#make-changes) . + +Tenga en cuenta que los recursos alternativos se indican con {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/s81rU6SgdmbseeBDGbPl.png", alt="Saved.", width="17", height="20" %} en el panel de **Red**. Pase el cursor sobre el ícono para ver qué se anula. + +{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/hekOD6lUKKXipZ6qFT3D.png", alt="Un ícono de cambios al lado de una solicitud en el panel Red.", width="800", height="493" %} + +Consulte [las novedades de DevTools](/blog/new-in-devtools-117/) para obtener todos los detalles y más información sobre DevTools en Chrome 117. + +## ¡Y más! {: #más } + +Por supuesto que hay mucho más. + +* El tan esperado valor [`subgrid`](https://developer.mozilla.org/docs/Web/CSS/CSS_grid_layout/Subgrid) para `grid-template-columns` y `grid-template-rows` ya está implementado en Chrome. + +* Hay una [deprecation trial `WebSQL`](/blog/deprecating-web-sql/) y una prueba de desarrollador para el [deprecation del evento `unload`](/blog/deprecating-unload/). + +* La [API `notRestoredReasons`](/docs/web-platform/bfcache-notRestoredreasons/) para bfcache, mencionado en el [vídeo para Chrome 116](https://youtu.be/JHwWUsMKYdk?si=sAzRp5hb5n9fQHxf&t=105), debería lanzarse en esta versión. + +## Otras lecturas + +Esto cubre sólo algunos aspectos destacados clave. Consulte los enlaces a continuación para +cambios adicionales en Chrome 117. + +* [Novedades de Chrome DevTools (117)](/blog/new-in-devtools-117/) +* [Desuso y eliminaciones de Chrome 117](/blog/deps-rems-117/) +* [Actualizaciones de ChromeStatus.com para Chrome 117](https://chromestatus.com/features#milestone%3D117) +* [Lista de cambios del repositorio fuente de Chromium](https://chromium.googlesource.com/chromium/src/+log/116.0.5845.171..117.0.5938.57) +* [Calendario de lanzamientos de Chrome](https://chromiumdash.appspot.com/schedule) + +## Suscríbete + +Para mantenerse actualizado, [suscríbase](https://goo.gl/6FP1a5) al +[Canal de YouTube para desarrolladores de Chrome](https://www.youtube.com/user/ChromeDevelopers/), +y recibirás una notificación por correo electrónico cada vez que lancemos un nuevo vídeo. + +Yo soy Adriana Jara, y tan pronto como se lance Chrome 117, estaré aquí para contarles que hay de nuevo en Chrome. From ba18753850b7dea46140cacee3c2ebe0d7495d69 Mon Sep 17 00:00:00 2001 From: Adriana Jara <32825533+tropicadri@users.noreply.github.com> Date: Tue, 12 Sep 2023 10:02:00 -0700 Subject: [PATCH 780/982] Updated new in chrome video (#7287) --- site/en/blog/new-in-chrome-117/index.md | 2 +- site/es/blog/new-in-chrome-117/index.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/site/en/blog/new-in-chrome-117/index.md b/site/en/blog/new-in-chrome-117/index.md index 385e03399..3c740b0af 100644 --- a/site/en/blog/new-in-chrome-117/index.md +++ b/site/en/blog/new-in-chrome-117/index.md @@ -14,7 +14,7 @@ tags: - chrome-117 --- -{% YouTube id='MOQpPiyoolM' %} +{% YouTube id='coidqLlYgoo' %} Here's what you need to know: diff --git a/site/es/blog/new-in-chrome-117/index.md b/site/es/blog/new-in-chrome-117/index.md index de3849c23..fd88f877f 100644 --- a/site/es/blog/new-in-chrome-117/index.md +++ b/site/es/blog/new-in-chrome-117/index.md @@ -14,7 +14,7 @@ tags: - chrome-117 --- -{% YouTube id='MOQpPiyoolM' %} +{% YouTube id='coidqLlYgoo' %} Esto es lo que necesitas saber: From f68e22ff8d0cb19d166065b831a8e8373bd4d51d Mon Sep 17 00:00:00 2001 From: Joe Medley <jmedley@google.com> Date: Tue, 12 Sep 2023 10:49:53 -0700 Subject: [PATCH 781/982] Fix FAQ's low-hanging fruit (#7265) * Fix FAQ's low-hanging fruit I know that we're trying to disperse this content and get rid of it. Since that is taking longer than expected, we need to fix its most egregious errors. * Update site/en/docs/extensions/mv3/faq/index.md Co-authored-by: amysteamdev <37001393+AmySteam@users.noreply.github.com> * Update site/en/docs/extensions/mv3/faq/index.md * Update site/en/docs/extensions/mv3/faq/index.md Co-authored-by: amysteamdev <37001393+AmySteam@users.noreply.github.com> * Update site/en/docs/extensions/mv3/faq/index.md Co-authored-by: amysteamdev <37001393+AmySteam@users.noreply.github.com> * Update site/en/docs/extensions/mv3/faq/index.md * Fix answer about storage. * Add link for local storage. * Update site/en/docs/extensions/mv3/faq/index.md Co-authored-by: amysteamdev <37001393+AmySteam@users.noreply.github.com> --------- Co-authored-by: amysteamdev <37001393+AmySteam@users.noreply.github.com> --- site/en/docs/extensions/mv3/faq/index.md | 105 +++++++++-------------- 1 file changed, 40 insertions(+), 65 deletions(-) diff --git a/site/en/docs/extensions/mv3/faq/index.md b/site/en/docs/extensions/mv3/faq/index.md index 3dc3bbf6f..18151182a 100644 --- a/site/en/docs/extensions/mv3/faq/index.md +++ b/site/en/docs/extensions/mv3/faq/index.md @@ -3,7 +3,7 @@ layout: "layouts/doc-post.njk" title: "Frequently asked questions" seoTitle: "Chrome Extensions: Frequently asked questions" date: 2014-02-28 -updated: 2020-11-20 +updated: 2023-09-12 description: Frequently asked questions about Chrome Extensions. --- @@ -40,66 +40,38 @@ the browser. ### Are extensions fetched from the web every time the browser is loaded? {: #faq-gen-03 } -Extensions are downloaded by the Chrome browser upon install, and are subsequently run off of the -local disk in order to speed up performance. However, if a new version of the extension is pushed -online, it will be automatically downloaded in the background to any users who have the extension -installed. Extensions may also make requests for remote content at any time, in order to interact -with a web service or pull new content from the web. +Extensions are downloaded by the Chrome browser upon install, and are subsequently run off of +local disk to speed up performance. However, if a new version of the extension is uploaded to +the Chrome Web Store, it will be automatically downloaded in the background for any users who have +the extension installed. Extensions may also make requests for remote data at any time, but not +remotely-hosted code. ### How do I determine which version of Chrome is deployed to which channel? {: #faq-dev-14 } To determine which version of Chrome is currently available on each of the different platforms, -visit [omahaproxy.appspot.com][34]. On that site you will see data in a format similar to: - -```text -cf,dev,#.#.###.#,#.#.###.#,mm/dd/yy,mm/dd/yy,#####,#####,##### -cf,beta,#.#.###.#,#.#.###.#,mm/dd/yy,mm/dd/yy,#####,#####,##### -cf,stable,#.#.###.#,#.#.###.#,mm/dd/yy,mm/dd/yy,#####,#####,##### -linux,dev,#.#.###.#,#.#.###.#,mm/dd/yy,mm/dd/yy,#####,#####,##### -linux,beta,#.#.###.#,#.#.###.#,mm/dd/yy,mm/dd/yy,#####,#####,##### -linux,stable,#.#.###.#,#.#.###.#,mm/dd/yy,mm/dd/yy,#####,#####,##### -mac,dev,#.#.###.#,#.#.###.#,mm/dd/yy,mm/dd/yy,#####,#####,##### -mac,beta,#.#.###.#,#.#.###.#,mm/dd/yy,mm/dd/yy,#####,#####,##### -mac,stable,#.#.###.#,#.#.###.#,mm/dd/yy,mm/dd/yy,#####,#####,##### -win,canary,#.#.###.#,#.#.###.#,mm/dd/yy,mm/dd/yy,#####,#####,##### -win,dev,#.#.###.#,#.#.###.#,mm/dd/yy,mm/dd/yy,#####,#####,##### -win,beta,#.#.###.#,#.#.###.#,mm/dd/yy,mm/dd/yy,#####,#####,##### -win,stable,#.#.###.#,#.#.###.#,mm/dd/yy,mm/dd/yy,#####,#####,##### -cros,dev,#.#.###.#,#.#.###.#,mm/dd/yy,mm/dd/yy,#####,#####,##### -cros,beta,#.#.###.#,#.#.###.#,mm/dd/yy,mm/dd/yy,#####,#####,##### -``` - -Each line represents information about a different platform and channel combination. The listed -platforms are `cf` (Google Chrome Frame), `linux`, `mac`, `win`, and `cros` (Google ChromeOS). The -listed channels are `canary`, `dev`, `beta`, and `stable`. The two four-part numbers after the -channel represent the current and previous versions of Chrome deployed to that platform-channel -combination. The rest of the information is metadata about when the releases were first pushed, as -well as revision numbers associated with each build. +visit [chrome releases][34], which lists the current Chrome releases for each channel and platform. ## Capabilities {: #capabilities2 } -### Can extensions make cross-domain Ajax requests? {: #faq-dev-02 } +### Can extensions make cross-origin network requests? {: #faq-dev-02 } -Yes. Extensions can make cross-domain requests. See [this page][35] for more information. +Yes. Extensions can make cross-origin network requests. See [this page][35] for more information. ### Can extensions use 3rd party web services? {: #faq-dev-03 } -Yes. Extensions are capable of making cross-domain Ajax requests, so they can call remote APIs +Yes. Extensions are capable of making cross-origin network requests, so they can call remote APIs directly. APIs that provide data in JSON format are particularly easy to use. ### Can extensions encode/decode JSON data? {: #faq-dev-07 } -Yes, modern JavaScript engines like Chrome's V8 have built-in support for +Yes. Chrome's JavaScript engine, called "V8", has built-in support for [JSON.stringify][stringify] and [JSON.parse][parse] so you can use these functions in your extensions without including JSON libraries in your code. ### Can extensions store data locally? {: #faq-dev-08 } -Yes, extensions can use [localStorage][37] to store string data permanently. Using Chrome's built-in -JSON functions, you can store complex data structures in localStorage. For extensions that need to -execute SQL queries on their stored data, Chrome implements [client side SQL databases][38], which -may be used as well. +Yes. Extensions provide a [storage API][63] designed specifically for extensions. An extension service worker can als0 use [CacheStorage][65], and [IndexedDB][38]. Additionally, contexts outside the extension service worker can use the [Web Storage API][37]. ### Can extensions use OAuth? {: #faq-dev-04 } @@ -109,11 +81,11 @@ requests. ### Can extensions create UI outside of the rendered web page? {: #faq-dev-05 } -Yes, your extension may add buttons to the Chrome browser's user interface. See [browser -actions][40] and [page actions][41] for more information. +Yes, your extension may add buttons to the Chrome browser's user interface using the +[action API][40]. An extension may also create popup notifications, which exist outside of the browser window. See the -[Rich notifications][42] documentation for more details. +[Rich notifications][42] documentation for details. ### Can extensions listen to clicks on Chrome tabs and navigation buttons? {: #faq-interact-chrome } @@ -121,21 +93,20 @@ No. Extensions are limited to listening to the events described in the [API docu ### Can two extensions communicate with each other? {: #faq-dev-11 } -Yes, extensions may pass messages to other extensions. See the [message passing documentation][44] +Yes, extensions may pass messages to other extensions. See [Cross-extension messaging][44] for more information. ### Can extensions use Google Analytics? {: #faq-dev-13 } Yes, since extensions are built just like websites, they can use [Google Analytics][45] to track -usage. However, you must modify the tracking code to pull an HTTPS version of the Google Analytics -library. See [this tutorial][46] for more information on doing this. +usage. See [Using Google Analytics 4][46] for more information. ### Can extensions modify chrome:// URLs? {: #faq-dev-15 } No. The extensions APIs have been designed to minimize backwards compatibility issues that can arise when new versions of the browser are pushed. Allowing content scripts on `chrome://` URLs would mean that developers would begin to rely on the DOM, CSS, and JavaScript of these pages to stay the same. -In the best case, these pages could not be updated as quickly as they are being updated right now. +In the best case, these pages could not be updated as quickly as they are currently. In the worst case, it could mean that an update to one of these pages could cause an extension to break, causing key parts of the browser to stop working for users of that extension. @@ -143,19 +114,19 @@ The reason that [replacing the content][47] hosted at these URLs entirely is all forces an extension developer to implement all of the functionality they want without depending on the browser's internal implementation to stay the same. -### Can extensions open browser/page action popups without user interaction? {: #faq-open-popups } +### Can extensions open action popups without a user interaction? {: #faq-open-popups } -No, popups can only be opened if the user clicks on the corresponding page or browser action. An +No. Popups can only be opened if the user clicks the corresponding action. An extension cannot open its popup programmatically. ### Can extensions keep popups open after the user clicks away from them? {: #faq-persist-popups } -No, popups automatically close when the user focuses on some portion of the browser outside of the +No. Popups automatically close when the user focuses on some portion of the browser outside of the popup. There is no way to keep the popup open after the user has clicked away. ### Can extensions be notified when they are installed/uninstalled? {: #faq-lifecycle-events } -You can listen to the [runtime.onInstalled][48] event to be notified when your +You can listen to the [`runtime.onInstalled`][48] event to be notified when your extension is installed or updated, or when Chrome itself is updated. While there is no event listener for uninstalling an extension, a URL can be set by calling [`runtime.setUninstallUrl()`](/docs/extensions/reference/runtime/#method-setUninstallURL) @@ -169,12 +140,13 @@ implementing surveys without access to any extension APIs. ### How do I build a UI for my extension? {: #faq-building-ui } Extensions use HTML and CSS to define their user interfaces, so you can use standard form controls -to build your UI, or style the interface with CSS, as you would a web page. Additionally, extensions +to build your UI, or style the interface with CSS, as you would a web page. You can also create rich +interactions using JavaScript and the web platform's many APIs. Additionally, extensions can add [some limited UI elements to Chrome itself.][49] ### How much data can I store in localStorage? {: #faq-dev-09 } -Extensions can store up to 5MB of data in localStorage. +Extensions can store up to 10MB of data in [`storage.local`][local-storage]. ### How do I create an options menu for my extension? {: #faq-dev-10 } @@ -185,23 +157,23 @@ they can be persisted across browsers. ### What debugging tools are available to extension developers? {: #faq-dev-12 } -Chrome's built-in developer tools can be used to debug extensions as well as web pages. See this -[tutorial on debugging extensions][51] for more information. +Chrome's built-in developer tools can be used to debug extensions as well as web pages. See +[Debugging extensions][51] for more information. -### Why do wildcard matches not work for top level domains (TLDs)? {: #faq-dev-16 } +### Why do wildcard matches not work for top level domains? {: #faq-dev-16 } -You cannot use wildcard match patterns like `https://google.*/*` to match TLDs (like +You cannot use wildcard match patterns like `https://google.*/*` to match top level domains (like `https://google.es` and `https://google.fr`) due to the complexity of actually restricting such a match to only the desired domains. For the example of `https://google.*/*`, the Google domains would be matched, but so would -`https://google.someotherdomain.com`. Additionally, many sites do not own all of the TLDs for their +`https://google.someotherdomain.com`. Additionally, many sites do not own all of the top level domains for their domain. For an example, assume you want to use `https://example.*/*` to match `https://example.com` and `https://example.es`, but `https://example.net` is a hostile site. If your extension has a bug, the hostile site could potentially attack your extension in order to get access to your extension's increased privileges. -You should explicitly enumerate the TLDs that you wish to run your extension on. +You should explicitly enumerate the top level domains that you wish to run your extension on. ### How can an extension determine whether it is running for the first time? {: #faq-firstrun } @@ -305,14 +277,13 @@ The steps you should follow to ensure this are: [31]: #faq-fea-02 [32]: /docs/extensions/mv3/getstarted [33]: https://developer.mozilla.org/docs/Web/API -[34]: https://omahaproxy.appspot.com +[34]: https://chromiumdash.appspot.com/releases [35]: /docs/extensions/mv3/xhr [36]: https://json.org/js.html -[37]: https://dev.w3.org/html5/webstorage/ -[38]: https://dev.w3.org/html5/webdatabase/ -[39]: https://unitedheroes.net/OAuthSimple/js/OAuthSimple.js -[40]: /docs/extensions/reference/browserAction -[41]: /docs/extensions/reference/pageAction +[37]: https://developer.mozilla.org/docs/Web/API/Web_Storage_API +[38]: https://developer.mozilla.org/docs/Web/API/IDBDatabase +[39]: /docs/extensions/mv3/tut_oauth/ +[40]: /docs/extensions/reference/action/ [42]: /docs/extensions/mv3/richNotifications [43]: /docs/extensions/reference [44]: /docs/extensions/mv3/messaging#external @@ -335,5 +306,9 @@ The steps you should follow to ensure this are: https://bugs.chromium.org/p/chromium/issues/list?can=2&q=component%3DPlatform>Extensions+Type%3DFeature+shortcuts [61]: https://crbug.com/new [62]: https://groups.google.com/a/chromium.org/group/chromium-extensions/topics +[63]: /docs/extensions/reference/storage/ +[64]: /docs/extensions/mv3/service_workers/ +[65]: https://developer.mozilla.org/docs/Web/API/CacheStorage +[local-storage]: /docs/extensions/reference/storage/#property-local [stringify]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify [parse]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse From 3db7b6d2a6ee8414ee8db1e28ca1005a06a7ce93 Mon Sep 17 00:00:00 2001 From: Sofia Emelianova <42939855+sofiayem@users.noreply.github.com> Date: Wed, 13 Sep 2023 12:49:28 +0100 Subject: [PATCH 782/982] DevTools 117: Local overrides. New workflow and xhr/fetch support (#7135) * local overrides: new workflow and xhr/fetch * mention show all overrides --- site/en/docs/devtools/overrides/index.md | 76 +++++++++++++++--------- 1 file changed, 49 insertions(+), 27 deletions(-) diff --git a/site/en/docs/devtools/overrides/index.md b/site/en/docs/devtools/overrides/index.md index 4390b169d..23f786695 100644 --- a/site/en/docs/devtools/overrides/index.md +++ b/site/en/docs/devtools/overrides/index.md @@ -1,11 +1,11 @@ --- layout: "layouts/doc-post.njk" -title: "Override files and HTTP response headers locally" +title: "Override web content and HTTP response headers locally" authors: - sofiayem date: 2023-04-12 -#updated: YYYY-MM-DD -description: "Use local overrides to keep changes you make in DevTools across page loads." +updated: 2023-08-21 +description: "Use local overrides to mock remote resources and keep the changes you make in DevTools across page loads." tags: - prototype-fixes - javascript @@ -13,7 +13,7 @@ tags: - network --- -With local overrides, you can keep the changes you make in DevTools across page loads. You can also [override HTTP response headers](#override-headers). +With local overrides, you can [override HTTP response headers](#override-headers) and [web content](#make-changes), including [XHR and fetch requests](#override-xhr-fetch), to mock remote resources even if you don't have access to them. This lets you prototype changes without waiting for the backend to support them. Local overrides also lets you keep the changes you make in DevTools across page loads. How it works: @@ -26,45 +26,66 @@ You can also save your changes directly to source files. See [Edit and save file ## Limitations {: #limitations } -Local overrides work for network response headers and for most file types, with a couple of exceptions: +Local overrides work for network response headers and for most file types, including XHR and fetch requests, with a couple of exceptions: - DevTools doesn't save changes made in the DOM tree of the [**Elements**](/docs/devtools/dom/) panel. - If you edit CSS in the **Styles** pane, and the source of that CSS is an HTML file, DevTools won't save the change. Instead, you can edit HTML files in the [**Sources**](/docs/devtools/sources/) panel. -## Enable or disable local overrides {: #enable-overrides } +## Set up local overrides {: #set-up } -Specify a folder where DevTools will keep your changes: +You can override web content or response headers right away in the **Network** panel: -1. [Open DevTools](/docs/devtools/open) on a page. -1. Go to [**Sources**](/docs/devtools/sources/) > **Overrides** and click {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/eY8MaTQqlXF3oiT6STmy.svg", alt="Add.", width="20", height="20" %} **Select folder for overrides**. +1. [Open DevTools](/docs/devtools/open), navigate to the **Network** panel, right-click a request you want to override, choose **Override headers** or **Override content** from the drop-down menu. + {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/qOixESNMKApJdBaw0Kcy.png", alt="Choosing override content from the right-click menu of a request.", width="800", height="425" %} +1. If you haven't set up local overrides yet, in the action bar at the top, DevTools prompts you to: + 1. **Select a folder** to store the override files in. + {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/oEWmbPqoEmv7uOF1KwAg.png", alt="DevTools prompts you to select a folder.", width="800", height="515" %} + 1. Click **Allow** to grant DevTools access rights to it. + {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/RkMW3bOZAroc83TujxBq.png", alt="DevTools requests access.", width="800", height="515" %} +1. If you have local overrides set up but disabled, DevTools automatically enables them. +1. Once local overrides are set up and enabled, depending on what you are about to override, DevTools takes you to: - {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/Mcwf0iY9MPSBTsbm3MWH.png", alt="The 'Select folder for overrides' button.", width="800", height="425" %} + - The **Sources** panel to let you make changes to [web content](#make-changes). + - The editor in **Network** > **Headers** > **Response Headers** to let you make changes to [response headers](#override-headers). -1. Pick a folder and, when prompted, allow DevTools access to it. +To temporarily disable local overrides or delete all the override files, navigate to **Sources** > **Overrides** and clear the {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/ZtDyFg7cjkxacORB3GQn.svg", alt="Empty checkbox.", width="24", height="24" %} **Enable Local Overrides** checkbox or click {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/mMGdymtMmpYX2j3PRSfa.svg", alt="Clear.", width="24", height="24" %} **Clear** respectively. -{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/Uq6nmriJ6PMGAWqRzTtq.png", alt="Local overrides enabled in a specified folder.", width="800", height="404" %} +To quickly see all overrides, in the **Network** panel, right-click a request and select **Show all overrides**. DevTools will take you to **Sources** > **Overrides**. -To view the files served by the server again, clear {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/ZtDyFg7cjkxacORB3GQn.svg", alt="Cleared checkbox.", width="24", height="24" %} **Enable local overrides** at any time. +## Override web content {: #make-changes } -To delete all the files with changes, click {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/MadqZsIZpo1sj3qQ3GsZ.svg", alt="Clear.", width="24", height="24" %}. +To override web content: +1. [Set up local overrides](#set-up). +1. Make changes to files and save them in DevTools. -## Make changes {: #make-changes } +For example, you can edit [files in **Sources**](/docs/devtools/javascript/reference/#edit) or [CSS in **Elements** > **Styles**](/docs/devtools/css/reference/#change-declaration), unless the CSS lives in [HTML files](#limitations). -Make changes to your code, for example, edit [CSS in the **Elements** panel](/docs/devtools/css/reference/#change-declaration), or [JavaScript in **Sources**](/docs/devtools/javascript/reference/#edit). +DevTools saves the modified files, lists them in **Sources** > **Overrides**, and shows you the {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/s81rU6SgdmbseeBDGbPl.png", alt="Saved.", width="17", height="20" %} icon next to the overridden files in the relevant panels and panes: **Elements** > **Styles**, **Network**, and **Sources** > **Overrides**. -DevTools saves the modified files, lists them in **Sources** > **Overrides**, and shows you the {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/s81rU6SgdmbseeBDGbPl.png", alt="Saved.", width="17", height="20" %} icon next to the overridden files. +{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/fpsd3XU6dnDWVhHJa2ID.png", alt="The corresponding icons next to overridden files in Sources, Network, and Elements > Styles", width="800", height="649" %} -{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/FPuaWwuQ3HFlgOuc4ZP4.png", alt="Overridden files listed in the Sources > Overrides and icons next to these files.", width="800", height="540" %} +### Override XHR or fetch requests to mock remote resources {: #override-xhr-fetch } -## Track your local changes {: #track-changes } +With local overrides, you don't need access to the backend and don't have to wait for it to support your changes. Mock and experiment on the fly: -You can keep track of all the changes you make in one place—the [**Changes**](/docs/devtools/changes/) drawer tab. +1. [Set up local overrides](#set-up). +1. In **Network**, [filter for **XHR/fetch** requests](/docs/devtools/network/reference/#filter-by-type), find the one you need, right-click it, and select **Override content**. +1. Make your changes to the fetched data and save the file. +1. {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/sX65QEDYhwBFHCM24BtV.svg", alt="Refresh.", width="24", height="24" %} **Refresh** the page and observe your changes applied. + +To learn this workflow, watch the following video: + +{% Video src="video/NJdAV9UgKuN8AhoaPBquL7giZQo1/TNcd8DCxoK6OmHQqJjKT.mp4", autoplay="false", loop="true", muted="true", controls="true", width="800", height="704", class="screenshot" %} + +### Track your local changes {: #track-changes } + +You can keep track of all the changes you make to web content in one place—the [**Changes**](/docs/devtools/changes/) drawer tab. ## Override HTTP response headers {: #override-headers } -From the **Network** panel, you can override HTTP response headers without the access to the web server. +From the **Network** panel, you can override HTTP response headers without access to the web server. With response header overrides, you can locally prototype fixes for various headers, including but not limited to: @@ -74,14 +95,15 @@ With response header overrides, you can locally prototype fixes for various head To override a response header: -1. [Open DevTools](/docs/devtools/open), for example, on [this demo page](https://cors-demo-devtools.glitch.me/). -1. Go to **Network**, select a request from the table, open **Headers** > **Response Headers**. -1. Hover over a response header value and click {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/JJEyylF1sToNKTtoFm4Q.svg", alt="Edit.", width="22", height="22" %}. +1. [Set up local overrides](#set-up) and inspect, for example, [this demo page](https://cors-demo-devtools.glitch.me/). +1. Go to **Network**, find a request, right-click it, and select **Override headers**. DevTools takes you to the **Headers** > **Response Headers** editor. +1. Hover over a response header value and place a cursor there. + + {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/6u5U79XxwBavyHX8nEOc.png", alt="The Response Headers editor.", width="800", height="608" %} - {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/U9f8IhtBACotmtYUNjtO.png", alt="The edit button next to a response header.", width="800", height="552" %} + Alternatively, to enable the **Response Headers** editor, hover over a response header value and click {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/JJEyylF1sToNKTtoFm4Q.svg", alt="Edit.", width="22", height="22" %}. -1. If prompted, pick a folder for DevTools to save changes to and allow access. -1. Modify a header. +1. Modify or add a new header. {% Aside %} This example adds the `Access-Control-Allow-Origin: *` header to get rid of a [CORS error](https://web.dev/cross-origin-resource-sharing/). From a1b841f966f6dbf13f6157852173fc633a5afa11 Mon Sep 17 00:00:00 2001 From: Nancymic2 <nmichell@google.com> Date: Wed, 13 Sep 2023 08:16:19 -0400 Subject: [PATCH 783/982] change remaining links to ARA tips doc (#7290) --- .../en/_partials/privacy-sandbox/ar-engage.md | 2 +- .../aggregation-service/index.md | 2 +- .../attribution-reporting-experiment/index.md | 8 +++---- .../contribution-budget/index.md | 2 +- .../working-with-noise/index.md | 2 +- .../private-aggregation-fundamentals/index.md | 6 +++--- .../summary-reports/design-decisions/index.md | 21 ++++++++----------- 7 files changed, 20 insertions(+), 23 deletions(-) diff --git a/site/en/_partials/privacy-sandbox/ar-engage.md b/site/en/_partials/privacy-sandbox/ar-engage.md index 89b14823c..a7d84cfc3 100644 --- a/site/en/_partials/privacy-sandbox/ar-engage.md +++ b/site/en/_partials/privacy-sandbox/ar-engage.md @@ -3,6 +3,6 @@ You can [participate and experiment with this API](/docs/privacy-sandbox/attribution-reporting-experiment/). * Read the [client-side proposal](https://github.com/WICG/conversion-measurement-api/blob/main/AGGREGATE.md) and [aggregation service proposal](https://github.com/WICG/conversion-measurement-api/blob/main/AGGREGATION_SERVICE_TEE.md), ask questions, and suggest feedback. -* Read the [Strategy and tips for summary reports](https://docs.google.com/document/d/1bU0a_njpDcRd9vDR0AJjwJjrf3Or8vAzyfuK8JZDEfo/edit?usp=sharing). +* Read the [Attribution reporting guides](/docs/privacy-sandbox/attribution-reporting/). * Ask questions and join discussions on the [Privacy Sandbox Developer Support repo](https://github.com/GoogleChromeLabs/privacy-sandbox-dev-support). \ No newline at end of file diff --git a/site/en/docs/privacy-sandbox/aggregation-service/index.md b/site/en/docs/privacy-sandbox/aggregation-service/index.md index b582ffc7d..d2eb69af3 100644 --- a/site/en/docs/privacy-sandbox/aggregation-service/index.md +++ b/site/en/docs/privacy-sandbox/aggregation-service/index.md @@ -135,7 +135,7 @@ data by a scaling factor to reduce the impact of noise. To understand how noise is added, your controls, and the impact on your reports, refer to the -[Contribution section of the Attribution Reporting strategy guide](https://docs.google.com/document/d/1bU0a_njpDcRd9vDR0AJjwJjrf3Or8vAzyfuK8JZDEfo/edit#heading=h.683u7t2q1xk2). +[Contribution budget](/docs/privacy-sandbox/attribution-reporting/contribution-budget/) and [Scale up to contribution budget](/docs/privacy-sandbox/attribution-reporting/working-with-noise/#scale-up-to-contribution-budget) in [Working with noise](/docs/privacy-sandbox/attribution-reporting/working-with-noise/). ## Generate summary reports diff --git a/site/en/docs/privacy-sandbox/attribution-reporting-experiment/index.md b/site/en/docs/privacy-sandbox/attribution-reporting-experiment/index.md index 05722b5ed..8eb4dd423 100644 --- a/site/en/docs/privacy-sandbox/attribution-reporting-experiment/index.md +++ b/site/en/docs/privacy-sandbox/attribution-reporting-experiment/index.md @@ -24,10 +24,10 @@ in the first half of 2023. guide](https://docs.google.com/document/d/1NY7SScCYcPc9v5wtf_fVAikFxGQTAFvwldhExN1P03Y/edit#) to participate in the latest origin trial. * To experiment with the API, follow these guides: - * [What you should know about the Attribution Reporting - API](https://docs.google.com/document/d/1lvrKd5Vv7SYLMGZb0Fz7bpGNEl0LOx9i1waAHw2sUg8/) + * [Getting started with the Attribution Reporting + API](/docs/privacy-sandbox/attribution-reporting/getting-started/) 4. Experiment with [summary - reports](/docs/privacy-sandbox/summary-reports). + reports](/docs/privacy-sandbox/summary-reports/). * Ad techs can generate summary reports with the [aggregation service](/docs/privacy-sandbox/aggregation-service). Set up [local testing](https://github.com/google/trusted-execution-aggregation-service/#set-up-local-testing) or [test in production with Amazon Web Services](https://github.com/google/trusted-execution-aggregation-service/#test-on-aws-with-support-for-encrypted-reports) (AWS) : @@ -37,7 +37,7 @@ in the first half of 2023. * Complete the aggregation service [onboarding form](https://forms.gle/EHoecersGKhpcLPNA). After you've submitted this form, we'll send a verification email and instructions. - * Refer to the [strategy and tips for summary reports](https://docs.google.com/document/d/1bU0a_njpDcRd9vDR0AJjwJjrf3Or8vAzyfuK8JZDEfo/edit?usp=sharing). + * Refer to the [Getting started guide](/docs/privacy-sandbox/attribution-reporting/getting-started/). ## Get support diff --git a/site/en/docs/privacy-sandbox/attribution-reporting/contribution-budget/index.md b/site/en/docs/privacy-sandbox/attribution-reporting/contribution-budget/index.md index 026110447..7dadd4379 100644 --- a/site/en/docs/privacy-sandbox/attribution-reporting/contribution-budget/index.md +++ b/site/en/docs/privacy-sandbox/attribution-reporting/contribution-budget/index.md @@ -41,7 +41,7 @@ These tips will help you work successfully with the contribution budget. - Ensure your values are strictly within the contribution budget to not lose any information, since the budget is a hard cap. - Allocate the contribution budget across metrics. Because the budget is common to all metrics for a given source, if more than one metric is tracked, you should share the budget across these metrics. -- If you're tracking two metrics—for example, the purchase value and the purchase count—you would split the contribution budget across these two metrics. More details can be found [in the example](https://docs.google.com/document/d/1bU0a_njpDcRd9vDR0AJjwJjrf3Or8vAzyfuK8JZDEfo/view#heading=h.i6ovl4dm1npa). +- If you're tracking two metrics—for example, the purchase value and the purchase count—you would split the contribution budget across these two metrics. More details can be found [in this example](/docs/privacy-sandbox/attribution-reporting/aggregation-keys/#main-example). - Adjust aggregatable values to minimize the impact of noise. Because the contribution budget impacts noise, adjusting the aggregatable values to this budget will allow you to improve signal-to-noise ratio. Read the details in [Scale up to contribution budget](/docs/privacy-sandbox/attribution-reporting/working-with-noise/#scale-up-to-contribution-budget). <!-- working with noise --> diff --git a/site/en/docs/privacy-sandbox/attribution-reporting/working-with-noise/index.md b/site/en/docs/privacy-sandbox/attribution-reporting/working-with-noise/index.md index 0a1596738..d575da6fa 100644 --- a/site/en/docs/privacy-sandbox/attribution-reporting/working-with-noise/index.md +++ b/site/en/docs/privacy-sandbox/attribution-reporting/working-with-noise/index.md @@ -52,7 +52,7 @@ If you have several measurement goals—for example, purchase count and purc In this case, your scaling factors will be different for different aggregatable values, depending on the expected maximum of a given aggregatable value. -Read details in the [complete example](https://docs.google.com/document/d/1bU0a_njpDcRd9vDR0AJjwJjrf3Or8vAzyfuK8JZDEfo/view#heading=h.duini3m1xb4y). +Read details in the [Understanding aggregation keys](/docs/privacy-sandbox/attribution-reporting/aggregation-keys/). {% Aside %} You may decide to allocate the budget equally between two measurement goals, or you can choose to prioritize different measurement goals by allocating more budget to certain goals and less to others. diff --git a/site/en/docs/privacy-sandbox/private-aggregation-fundamentals/index.md b/site/en/docs/privacy-sandbox/private-aggregation-fundamentals/index.md index 018a0282a..3fe4fb674 100644 --- a/site/en/docs/privacy-sandbox/private-aggregation-fundamentals/index.md +++ b/site/en/docs/privacy-sandbox/private-aggregation-fundamentals/index.md @@ -12,7 +12,7 @@ authors: ## Who is this article for? -The [Private Aggregation API]( /docs/privacy-sandbox/private-aggregation) enables aggregate data collection from worklets with access to cross-site data. The concepts shared here are important for developers building reporting functions within Shared Storage and Protected Audience API. +The [Private Aggregation API](/docs/privacy-sandbox/private-aggregation) enables aggregate data collection from worklets with access to cross-site data. The concepts shared here are important for developers building reporting functions within Shared Storage and Protected Audience API. * If you're a **developer** building a reporting system for cross-site measurement. * If you're a **marketer**, **data scientist**, or other **summary report consumer**, understanding these mechanisms will help you make design decisions to retrieve an optimized summary report. @@ -44,7 +44,7 @@ When you call the Private Aggregation API with an aggregation key and an aggrega A _trusted execution environment_ is a special configuration of computer hardware and software that allows external parties to verify the exact versions of software running on the computer. TEEs allow external parties to verify that the software does exactly what the software manufacturer claims it does—nothing more or less. {% endAside %} -The workflow described in this section is similar to the [Attribution Reporting API](https://docs.google.com/document/d/1bU0a_njpDcRd9vDR0AJjwJjrf3Or8vAzyfuK8JZDEfo/edit#). However, Attribution Reporting associates data gathered from an impression event and a conversion event, which happen at different times. Private Aggregation measures a single, cross-site event. +The workflow described in this section is similar to the [Attribution Reporting API](/docs/privacy-sandbox/attribution-reporting/). However, Attribution Reporting associates data gathered from an impression event and a conversion event, which happen at different times. Private Aggregation measures a single, cross-site event. ## Aggregation key @@ -157,7 +157,7 @@ When you sum all aggregatable values across all aggregation keys, the sum must b The _contribution budget_ is represented by the parameter `L<sub>1</sub>`, and for the current Privacy Sandbox Origin Trial, the contribution budget has been set to 2<sup>16</sup> = 65,536. The value of the contribution budget is arbitrary where noise is scaled to it, and you can use this budget to maximize signal-to-noise ratio on the summary values (discussed more below in the [Noise and scaling](#noise-and-scaling) section below). -To learn more about contribution budgets, see the [explainer](https://github.com/patcg-individual-drafts/private-aggregation-api#contribution-bounding-and-budgeting). Also, refer to the [Contribution Budget section of the Attribution Reporting strategy guide](https://docs.google.com/document/d/1bU0a_njpDcRd9vDR0AJjwJjrf3Or8vAzyfuK8JZDEfo/edit#) for more guidance. +To learn more about contribution budgets, see the [explainer](https://github.com/patcg-individual-drafts/private-aggregation-api#contribution-bounding-and-budgeting). Also, refer to [Contribution Budget](/docs/privacy-sandbox/attribution-reporting/contribution-budget/) for more guidance. ## Aggregatable reports diff --git a/site/en/docs/privacy-sandbox/summary-reports/design-decisions/index.md b/site/en/docs/privacy-sandbox/summary-reports/design-decisions/index.md index cadbaf97d..2392462b6 100644 --- a/site/en/docs/privacy-sandbox/summary-reports/design-decisions/index.md +++ b/site/en/docs/privacy-sandbox/summary-reports/design-decisions/index.md @@ -49,17 +49,15 @@ here. Your suggestions, additions, and questions are welcome! ### Before you start -1. Read [Attribution Reporting: summary reports](/docs/privacy-sandbox/attribution-reporting/summary-reports/) and [What you should know about the Attribution Reporting API](https://docs.google.com/document/d/1lvrKd5Vv7SYLMGZb0Fz7bpGNEl0LOx9i1waAHw2sUg8/edit) for an introduction. -2. Scan [Strategy and tips for summary reports](https://docs.google.com/document/d/1bU0a_njpDcRd9vDR0AJjwJjrf3Or8vAzyfuK8JZDEfo/edit#heading=h.j8m326urvgnt)⏤in particular the [essential notions](https://docs.google.com/document/d/1bU0a_njpDcRd9vDR0AJjwJjrf3Or8vAzyfuK8JZDEfo/edit#heading=h.kizul7z2av3y) required for you to make best use of this guide. +1. Read [Attribution Reporting: summary reports](/docs/privacy-sandbox/attribution-reporting/summary-reports/) and [Attribution Reporting full system overview](/docs/privacy-sandbox/attribution-reporting/system-overview/) for an introduction. +2. Scan [Understanding noise](/docs/privacy-sandbox/attribution-reporting/understanding-noise/) and [Understanding aggregation keys](/docs/privacy-sandbox/attribution-reporting/aggregation-keys/) to make best use of this guide. ## Design decisions ### Core design principle {: #core} -There are -[foundational differences](https://docs.google.com/document/d/1lvrKd5Vv7SYLMGZb0Fz7bpGNEl0LOx9i1waAHw2sUg8/edit#heading=h.ktl1cq7bdlk) -between how third-party cookies and summary reports operate. One key difference is the -[noise](/docs/privacy-sandbox/attribution-reporting/understanding-noise/) added to measurement data in summary reports. +There are foundational differences between how third-party cookies and summary reports operate. One key difference is the +[noise](/docs/privacy-sandbox/attribution-reporting/understanding-noise/) added to measurement data in summary reports. Another is how reports are [scheduled](/docs/privacy-sandbox/attribution-reporting/report-schedules/). **To access summary report measurement data with higher signal-to-noise ratios, demand-side platforms (DSPs) and ad measurement providers will need to @@ -176,7 +174,7 @@ are included; you can also modify these. Another design decision that will impact the number of attributed conversion events within a single bucket is the -[key structures](https://docs.google.com/document/d/1bU0a_njpDcRd9vDR0AJjwJjrf3Or8vAzyfuK8JZDEfo/edit#heading=h.81usg7c4jnsg) +[key structures](/docs/privacy-sandbox/attribution-reporting/aggregation-keys/#aggregation-keys-in-practice) you decide to use. Consider the following examples of aggregation keys: - One key structure with all dimensions; let's call this Key Strategy A. @@ -191,7 +189,7 @@ reports may already give you the information you need. This means that Strategy will likely lead to better signal-to-noise ratios than Strategy A. However, the noise may already be acceptable with Strategy A, so you may still decide to favor Strategy A for simplicity. -[Learn more in the detailed example outlining these two strategies](https://docs.google.com/document/d/1bU0a_njpDcRd9vDR0AJjwJjrf3Or8vAzyfuK8JZDEfo/edit#heading=h.i6ovl4dm1npa). +[Learn more in the detailed example outlining these two strategies](/docs/privacy-sandbox/attribution-reporting/aggregation-keys/#translate-goals-into-keys). Key management is a deep topic. A number of elaborate techniques can be considered to improve signal-to-noise ratios. One is described in [Advanced key @@ -234,12 +232,11 @@ batching frequency is how often you process aggregatable reports. A report that is scheduled for aggregation more frequently (e.g. each hour) will have fewer conversion events included than the same report with a less frequent aggregation schedule (e.g. each week). As a result, the hourly report will have -a higher signal-to-noise ratio than the weekly report, all else being equal. **Experiment with reporting requirements at various frequencies, and assess -signal-to-noise ratios for each.** +a higher signal-to-noise ratio than the weekly report, all else being equal. **Experiment with reporting requirements at various frequencies, and assess signal-to-noise ratios for each.** Learn more in -[Batching](https://docs.google.com/document/d/1bU0a_njpDcRd9vDR0AJjwJjrf3Or8vAzyfuK8JZDEfo/edit#heading=h.pef51jskrx06) -and [Aggregating over longer time periods](https://docs.google.com/document/d/1bU0a_njpDcRd9vDR0AJjwJjrf3Or8vAzyfuK8JZDEfo/edit#heading=h.pef51jskrx06). +[Batching](/docs/privacy-sandbox/summary-reports/#batching) +and [Aggregating over longer time periods](/docs/privacy-sandbox/attribution-reporting/working-with-noise/#aggregating-over-longer-time-periods-increases-signal-to-noise-ratio). ### Decision: Campaign variables that affect attributable conversions {: #campaign-variables} From 6a57e6a0c88b5f2ab04f50df5f75c9ed979562d2 Mon Sep 17 00:00:00 2001 From: "Kevin K. Lee" <kevinkiklee@google.com> Date: Wed, 13 Sep 2023 09:07:32 -0400 Subject: [PATCH 784/982] Update PA status table links (#7288) * Update PA status table links * Update site/en/docs/privacy-sandbox/protected-audience-api/feature-status/index.md * Update links to point to anchors Co-authored-by: Anusmita <anusmitaray@google.com> --------- Co-authored-by: Anusmita <anusmitaray@google.com> --- .../protected-audience-api/feature-status/index.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/site/en/docs/privacy-sandbox/protected-audience-api/feature-status/index.md b/site/en/docs/privacy-sandbox/protected-audience-api/feature-status/index.md index ba7d365be..21c0e9b50 100644 --- a/site/en/docs/privacy-sandbox/protected-audience-api/feature-status/index.md +++ b/site/en/docs/privacy-sandbox/protected-audience-api/feature-status/index.md @@ -32,7 +32,7 @@ find a list of the scoped Protected Audience API features and when they'll be su </tr> </thead> <tr> - <td><a href="https://github.com/WICG/turtledove/blob/main/FLEDGE.md#5-event-level-reporting-for-now">Event-level auction win reporting</a> + <td><a href="#event-level-auction-win-reporting">Event-level auction win reporting</a> </td> <td>Now</td> <td><p>Supported until at least 2026.</p> @@ -40,31 +40,31 @@ find a list of the scoped Protected Audience API features and when they'll be su </td> </tr> <tr> - <td><a href="/docs/privacy-sandbox/private-aggregation/#contributetohistogramonevent">Trigger-based aggregation</a> + <td><a href="#trigger-based-aggregate-reporting">Trigger-based aggregation</a> </td> <td>Now</td> <td><p>Available for testing in Chrome Canary/Dev M113+ and Beta/Stable M115+.</p> </td> </tr> <tr> - <td><a href="https://github.com/privacysandbox/fledge-docs/blob/main/trusted_services_overview.md#trusted-execution-environment">Trusted Execution Environment (TEE)</a> usage for Key/Value service</td> + <td><a href="#trusted-execution-environment-usage-for-keyvalue-service">Trusted Execution Environment (TEE)</a> usage for Key/Value service</td> <td>Now</td> <td>Required no sooner than Q3 2025.</td> </tr> <tr> - <td><a href="/docs/privacy-sandbox/fenced-frame/">Fenced frames</a> + <td><a href="#fenced-frames">Fenced frames</a> </td> <td>Now </td> <td>Required no sooner than 2026.</td> </tr> <tr> - <td>Improved Protected Audience API + <a href="/docs/privacy-sandbox/attribution-reporting/">Attribution Reporting</a> integration.</td> + <td><a href="#improved-protected-audience-api-and-attribution-reporting-integration">Improved Protected Audience API + Attribution Reporting integration</a></td> <td>2023 Q2</td> <td>Available for testing in Chrome Stable M112+.</td> </tr> <tr> - <td><a href="https://github.com/WICG/turtledove/blob/main/FLEDGE_k_anonymity_server.md">K-anonymity</a> + <td><a href="#k-anonymity">K-anonymity</a> </td> <td>Later in 2023 Q3 </td> @@ -72,7 +72,7 @@ find a list of the scoped Protected Audience API features and when they'll be su </td> </tr> <tr> - <td><a href="/blog/fledge-service-overview/#bidding-auction-service">Bidding and Auction services</a> + <td><a href="#bidding-and-auction-services">Bidding and Auction services</a> </td> <td>Targeted for testing in H2 2023.</td> <td>In development.</td> From 7bc88ab25c52610f7e47658a40ae6f97a4420971 Mon Sep 17 00:00:00 2001 From: Nancymic2 <nmichell@google.com> Date: Wed, 13 Sep 2023 09:56:09 -0400 Subject: [PATCH 785/982] add a use shared storage redirect (#7286) * add a use shared storage redirect * fix a typo --- redirects.yaml | 3 +++ .../privacy-sandbox/glossary-entries/summary-report.md | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/redirects.yaml b/redirects.yaml index 361e86e11..116cda086 100644 --- a/redirects.yaml +++ b/redirects.yaml @@ -81,6 +81,9 @@ redirects: - from: /docs/privacy-sandbox/status to: https://privacysandbox.com/open-web/#the-privacy-sandbox-timeline +- from: /docs/privacy-sandbox/use-shared-storage/ + to: /docs/privacy-sandbox/shared-storage/ + - from: /android to: /docs/android diff --git a/site/en/_partials/privacy-sandbox/glossary-entries/summary-report.md b/site/en/_partials/privacy-sandbox/glossary-entries/summary-report.md index 4e78080c6..d36c6366d 100644 --- a/site/en/_partials/privacy-sandbox/glossary-entries/summary-report.md +++ b/site/en/_partials/privacy-sandbox/glossary-entries/summary-report.md @@ -1,2 +1,3 @@ A summary report is an Attribution Reporting API and Private Aggregation API report type. A [summary -report](/docs/privacy-sandbox/attribution-reporting/summary-reports/) includes aggregated user data and can contain detailed conversion data, with noise added.Summary reports are made up of aggregate reports. \ No newline at end of file +report](/docs/privacy-sandbox/attribution-reporting/summary-reports/) includes aggregated user data and can contain detailed conversion data, with noise added. +Summary reports are made up of aggregate reports. \ No newline at end of file From e6f721c6d6b3fb43de96681bfed5b074832d6bb0 Mon Sep 17 00:00:00 2001 From: Rachel Andrew <rachelandrew@google.com> Date: Wed, 13 Sep 2023 20:16:09 +0200 Subject: [PATCH 786/982] Beta 118 post (#7293) * Beta 118 post * fixes --- site/en/blog/chrome-118-beta/index.md | 173 ++++++++++++++++++++++++++ 1 file changed, 173 insertions(+) create mode 100644 site/en/blog/chrome-118-beta/index.md diff --git a/site/en/blog/chrome-118-beta/index.md b/site/en/blog/chrome-118-beta/index.md new file mode 100644 index 000000000..ebb7a340c --- /dev/null +++ b/site/en/blog/chrome-118-beta/index.md @@ -0,0 +1,173 @@ +--- +title: Chrome 118 beta +description: > + Scoped styles for CSS, additional media features, keyboard-focusable scroll containers, and more. +subhead: > + Scoped styles for CSS, additional media features, keyboard-focusable scroll containers, and more. +layout: 'layouts/blog-post.njk' +date: 2023-09-13 +hero: 'image/kheDArv5csY6rvQUJDbWRscckLr1/UXMAh3Kiswqs91x97YYG.png' +alt: > + Chrome 118 beta hero logo +tags: + - beta + - chrome-118 +--- + +Unless otherwise noted, changes described below apply to the newest Chrome beta channel release for Android, ChromeOS, Linux, macOS, and Windows. Learn more about the features listed here through the provided links or from the list on ChromeStatus.com. Chrome 118 is beta as of September 13, 2023. You can download the latest on [Google.com](https://www.google.com/chrome/beta/) for desktop or on Google Play Store on Android. + +## CSS + +This release adds five new CSS features. + +### Scoped styles + +The `@scope` rule allows developers to [scope style rules](https://drafts.csswg.org/css-cascade-6/#scoped-styles) to a given scoping root, and style elements according to the proximity of that scoping root. + +### CSS logical flow-relative values + +Adds the following new values to existing CSS properties: + +`float: inline-start` +`float: inline-end` +`clear: inline-start` +`clear: inline-end` +`resize: block` +`resize: inline` + +These flow-relative directional keywords resolve to a physical value depending on the writing mode or direction of the element or its containing block. + +### Media Queries: prefers-reduced-transparency feature + +Adds the [`prefers-reduced-transparency` media feature](https://developer.mozilla.org/docs/Web/CSS/@media/prefers-reduced-transparency), which lets developers adapt web content to user-selected preference for reduced transparency in the OS, such as the **Reduce transparency** setting on macOS. Valid options are `reduce` or `no-preference`. + +### Media Queries: scripting feature + +The [`scripting` media feature](https://developer.mozilla.org/docs/Web/CSS/@media/scripting) is used to query whether scripting languages, such as JavaScript, are supported on the current document. Valid options are `enabled`, `initial-only`, or `none`. However, `initial-only` never matches inside a browser. + +### Support stroke-box, content-box, and border-box in the transform-box CSS property + +Adding this support enables changing how the reference box for the [`transform`](https://developer.mozilla.org/docs/Web/CSS/transform) property is computed. This enables additional transforms or graphical effects. For example, rotation around a point in the content box, where the width of the border of an element does not influence the result. Or, where the stroke of an (SVG) element should influence the result, for example, when rotating a stroked shape around its center—including the stroke. + +## HTML + +### Keyboard-focusable scroll containers + +Improves accessibility by making scroll containers focusable using sequential focus navigation. Before this change, the tab key doesn't focus scrollers unless `tabIndex` is explicitly set to `0` or greater. By making scrollers focusable by default, users who can't (or don't want to) use a mouse will be able to access clipped content using a keyboard's tab and arrow keys. This behavior does not apply to scrollers that contain keyboard focusable elements, since those are already accessible via the keyboard. + +### Remove quirks mode behavior for option label attribute + +Option elements support a [`label` attribute](https://developer.mozilla.org/docs/Web/HTML/Element/option#label) which causes the option to render with the text inside the attribute rather than the child text of the option element itself. This functionality is disabled in quirks mode, where the label attribute is ignored and the child text is always rendered. This change will always use the label attribute in both standards mode and quirks mode. + + +## Web APIs + +### Enrollment for Privacy Sandbox (PSB) + +As the [Privacy Sandbox](https://privacysandbox.com/) relevance and measurement APIs start ramping up for general availability, we want to make sure these technologies are used as intended and with transparency. The APIs include [Attribution Reporting](/docs/privacy-sandbox/attribution-reporting/), the [Protected Audience API](/docs/privacy-sandbox/protected-audience/), the [Topics API](/docs/privacy-sandbox/topics/overview/), the [Private Aggregation API](/docs/privacy-sandbox/private-aggregation/) and the [Shared Storage API](/docs/privacy-sandbox/shared-storage/). PSB is introducing a new Developer Enrollment process for Privacy Sandbox relevance and measurement APIs. Chrome will fetch the enrolled-sites list from the enrollment server (via component updater) and use it to gate access to the Privacy Sandbox APIs. + +### Block all cookies set via JavaScript that contain control characters + +Updates how control characters in cookies set via JavaScript are handled. Specifically, all control characters cause the entire cookie to be rejected. Previously, a NULL character, a carriage return character, or a line feed character in a cookie line caused it to be truncated instead of rejected entirely, which could have enabled malicious behavior in certain circumstances. This behavior aligns Chrome with the behavior indicated by the latest drafts of RFC6265bis. This change can be disabled using the `--disable-features=BlockTruncatedCookies` or the BlockTruncatedCookies enterprise policy, which will exist for several milestones in case this change causes any breakage. + +### Consistent minimum font size across languages + +Changes the default setting for the ***Minimum font size*** to be off by default for seven languages (Arabic, Farsi, Japanese, Korean, Thai, Simplified and Traditional Chinese) to improve interoperability and accessibility. Before this change, this setting was off by default for all languages except the seven languages listed. This change makes these languages consistent with other languages. Note, this is not about changing the minimum font size feature itself. It will be available without any changes for accessibility and readability. + +### Detect UA transitions on same-document navigations + +Smooth visual transitions as users navigate on the web can lower cognitive load by helping users stay in context. However, the user experience is bad if both the site author and the UA add these transitions: the transitions may conflict and cause confusion for the user. This API avoids such cases to ensure only one visual transition is executed at a time. The API adds a boolean on `PopStateEvent` and `NavigateEvent` to indicate whether the UA has executed a visual transition for this navigation. Developers can use this to skip their custom transition. + +### URL parser will not decode percent-encoded ASCII characters in URL's path + +This changes makes the URL parser not decode percent-encoded ASCII characters in the URL's path, such as "%41" ('A'). Before this change: + +```js +const url = new URL("http://example.com/%41"); +url.href "http://example.com/A" +``` + +After this change: + +```js +const url = new URL("http://example.com/%41"); +url.href "http://example.com/%41" +``` + +### Protected Audiences negative targeting + +In online ad auctions for ad space, it's sometimes useful to prevent showing an ad to certain audiences, a concept known as _negative targeting_. For example, you might not want to show a new customer advertisement to existing customers. New customer acquisition campaigns most often have this as a critical requirement. Protected Audience currently enables ads to target users that have been joined to a given interest group through some past activity on the web. This feature extends Protected Audience to enable negative targeting by allowing new ads to target only those users who have not been joined to a given interest group. In this way, we're enabling advertisers to target new groups of users using the existing privacy-preserving concepts of the Protected Audience API. + +### Remove payment user activation requirement + +To help developers reduce friction in Payment Request flows, we are removing the user activation requirement in Payment Request and Secure Payment Confirmation. Spam and clickjacking mitigations are put in place to mitigate security and privacy risks with this change. + +### WebUSB in Extension Service Workers + +Allows web developers to use the [WebUSB API](https://developer.mozilla.org/docs/Web/API/WebUSB_API) when responding to extension events by exposing the WebUSB API to Service Workers registered by browser extensions. This API is not currently exposed to Service Workers registered by sites. + +### XML documents merge consecutive CDATA sections into single node + +Due to a bug in libxml, CDATA sections in an XHTML document can sometimes erroneously produce multiple nodes, depending on the size of the document and the position of the CDATA section in the document. When a single CDATA section spans multiple input parser chunks, libxml buffers and emits the CDATA input into 300 byte runs. This unexpectedly turns a single CDATA section into multiple nodes (if the length of the input chunk is greater than 300 bytes). This change causes sibling CDATA section nodes to be merged into a single CDATA section during parsing. This fixes the libxml bug during parsing but will also merge authored separate nodes, for example: `<![CDATA[foo]]><!CDATA[bar]]>` Will produce a single CDATA DOM node with content `"foobar": CDATA "foobar"`. + +### Change beforeunload handler dialog condition + +There are two new changes on how the cancel dialog gets prompted for the `beforeunload` event. + +If `event.preventDefault()` is called, prompt cancel dialog. +If `event.returnValue` is the empty string, do not prompt cancel dialog. + +## Origin trials in progress + +In Chrome 118 you can opt into the following new [origin trial](/docs/web-platform/origin-trials/). + +### WebRTC encoded transform: modify metadata functions + +Adds features to the WebRTC Encoded Transform API that allow manipulating audio and video frame metadata. A number of use cases have been identified that require the manipulation of WebRTC encoded media without decoding them first. These include: + +- Sending data that has been encoded previously. +- Sending data that has been received in encoded form. +- Receiving data in encoded form and forwarding it. + +In particular, we want to support the use case of glitch-free forwarding of media coming from multiple redundant peer connections that provide the same media payloads but with different metadata. + +Register for the [RTCEncodedFrameSetMetadata origin trial](/origintrials/#/register_trial/1097752409171558401). + +## Deprecations and removals + +This version of Chrome introduces the deprecations and removals listed below. Visit ChromeStatus.com for lists of planned deprecations, current deprecations and previous removals. + +This release of Chrome removes the following feature. + +### Removal of some non-standard appearance keywords + +In Chrome 118, the non-standard [`appearance`](https://developer.mozilla.org/docs/Web/CSS/appearance) keywords with the lowest usage will be deactivated. Once the feature is deactivated, the appearance property will be ignored if it uses that keyword as a value. The keywords being deactivated in Chrome 118 are those with less than 0.001% usage: + +* `media-slider` +* `media-sliderthumb` +* `media-volume-slider` +* `media-volume-sliderthumb` +* `sliderthumb-horizontal` +* `sliderthumb-vertical` + +#### Background + +Since only standard [`appearance`](https://developer.mozilla.org/docs/Web/CSS/appearance) keywords should be supported, we are removing the `appearance` (and `-webkit-appearance`) keywords that are non-standard. The full list is as follows: + +* `inner-spin-button` +* `media-slider` +* `media-sliderthumb` +* `media-volume-slider` +* `media-volume-sliderthumb` +* `push-button` +* `searchfield-cancel-button` +* `slider-horizontal` +* `sliderthumb-horizontal` +* `sliderthumb-vertical` +* `square-button` + +Note that value `slider-vertical` will not be removed as part of this +patch it is used for allowing `<input type=range>` vertical. It will be +removed once [form controls vertical writing mode](https://chromestatus.com/feature/5602118873907200) is fully adopted. + +Prior to being deactivated, if using any of the above keywords, a console warning will be shown, but the keyword will be recognized as a valid value. From 2dea80ccb8f3c898bc76e84e2bf840e0fbe1daf6 Mon Sep 17 00:00:00 2001 From: ilyaspiridonov <spiridonov.ilya@gmail.com> Date: Fri, 15 Sep 2023 10:00:04 +0300 Subject: [PATCH 787/982] [JA] Privacy Sandbox Translations (#7303) * Translate index.md via GitLocalize * Translate index.md via GitLocalize * Translate index.md via GitLocalize * Update index.md --------- Co-authored-by: Eiji Kitamura <agektmr@google.com> Co-authored-by: Nozomi Kugita <nozomi@nozygatos.com> Co-authored-by: mt-gitlocalize <mt@gitlocalize.com> --- site/ja/docs/privacy-sandbox/enroll/index.md | 61 ++------------------ 1 file changed, 5 insertions(+), 56 deletions(-) diff --git a/site/ja/docs/privacy-sandbox/enroll/index.md b/site/ja/docs/privacy-sandbox/enroll/index.md index eebb07d8f..e1d61becf 100644 --- a/site/ja/docs/privacy-sandbox/enroll/index.md +++ b/site/ja/docs/privacy-sandbox/enroll/index.md @@ -1,64 +1,13 @@ --- layout: layouts/doc-post.njk title: プライバシー サンドボックスに登録する -subhead: Chrome と Android におけるプライバシーサンドボックスの広告関連 API の新しいプロセス。 -description: アイデンティティの検証と、プライバシーサンドボックスの広告関連 API について構成情報の詳細を共有してください。Chrome と Android で共通です。 -date: 2023-04-13 +subhead: あなたのアイデンティティを検証し、Chrome と Android を跨いだプライバシーサンドボックス広告関連 API の構成情報を共有してください。 +description: あなたのアイデンティティを検証し、Chrome と Android を跨いだプライバシーサンドボックス広告関連 API の構成情報を共有してください。 +date: 2023-06-13 authors: - georgiafranklin --- -{% Aside %} +開発者登録は、これらの API を呼び出すエンティティを検証し、プライバシーサンドボックス API を適切に構成して使用するために必要な開発者のデータを収集するメカニズムを提供します。[Chrome](/docs/privacy-sandbox/) と [Android](https://developer.android.com/design-for-safety/privacy-sandbox) でプライバシーサンドボックス広告関連 API にアクセスするには、開発者はプライバシーサンドボックスに登録する必要があります。これには、アトリビューション レポート、Protected Audience、Topics、Fenced Frames、共有ストレージが含まれます。 -このページは登録手順によって更新される予定です。この時点では、[登録に関するお知らせ](/blog/announce-enrollment-privacy-sandbox/)を記載しています。 - -{% endAside %} - -API を呼び出すすべてのエンティティを検証し、これらの API を適切に構成して使用するために必要なデータを収集するために、新しいプライバシーサンドボックス登録を開始します。 - -ここでは、登録が必要となる前にその方法についての手順ガイドを提供しています。このプロセスが完成次第、このページが更新されます。 - -## 登録を要求する理由について - -ユーザーのプライバシーを保護することは、プライバシーサンドボックスにとって最も重要です。この登録プロセスでは、誰がデータを収集しているかということに透明性を与え、API の悪用により意図した以上のデータを収集しようとする試みを抑制することにより、各 API 内に適用される構造上の制限の上にさらに追加の保護レイヤーが追加されます。 - -監査可能な透明性を提供するために、会社に関する登録情報は公開されます。この情報の公開アクセスの仕組みについては、今後の更新で詳細をお知らせします。 - -API 呼び出し元が受け取ることができるデータの量を制限するために、広告関連 API に各開発者のレート制限をすでに組み込んでいます。登録により、独立したサードパーティの検証サービスを使用して、これらのレート制限をより適切に適用できます。 企業のアイデンティティと潜在的な企業関係の確認には、Dun & Bradstreet を起用します。 - -この確認プロセスは、ある開発者が別の開発者になりすまして API の使用を制限できないようにするのにも役立ちます。最後に、この取り組みにより、プライバシー サンドボックスの Chrome と Android のエコシステムに共通の登録プロセスが採用されるため、プラットフォーム間で確認作業を繰り返す必要がなくなります。 - -## 登録方法は? - -{% Aside %} 新たに統一されたプライバシーサンドボックス開発者登録プロセスは 2023 年 6 月に開始され、2023 年 8 月に必須となります。8 月には、API へのアクセスは、登録を正常に完了したエンティティのみに制限されます。 {% endAside %} - -登録するには、以下の情報をご提供ください。 - -- 連絡先情報 -- 組織の [DUNS 番号](https://www.dnb.com/duns-number.html)を含む事業 ID -- API またはサーバーの構成に必要なその他の情報(API の呼び出しに使用されるサイトや SDK など) -- リクエストされる API のリスト - -開発者がプライバシー サンドボックス API を簡単にセットアップしてテストを開始できるように、このプロセスを軽量化する予定です。現在登録されている Android テスターには、新しい登録プロセスへの移行に関する特別な支援が提供されます。また、登録関連の質問に対応するための Google サポートチャンネルが用意されます。 - -### サイト単位の登録 - -すべての API 呼び出し元は、[サイト](https://web.dev/same-site-same-origin/#public-suffix-list-and-etld)を登録する必要があります。サイトは、プライバシーサンドボックス API のプライバシー保護を通知する境界を提供します。 - -{% Aside %} この登録は、1 つ以上のプライバシーサンドボックスの広告関連 API を呼び出す企業にのみ適用されます。アドテックの顧客であるサイト運営者やその他の企業は、登録する必要はありません。 {% endAside %} - -登録は、独立した事業部門または製品に合わせて行う必要があります。レート制限を共有しないエンティティが複数ある場合は、独立したサイトごとに登録を申し込むことができます。API の呼び出しに使用されるオリジンは、登録のサイト境界内にある必要があります。 - -Chrome または Android で [Attribution Reporting API](/docs/privacy-sandbox/attribution-reporting/) を使用する場合は、既存の統合に影響する可能性があることに注意してください。登録に関連するレート制限については、現在議論中です。[GitHub イシュー 661](https://github.com/WICG/attribution-reporting-api/issues/661) および [GitHub イシュー 725](https://github.com/WICG/attribution-reporting-api/issues/725) の会話にご参加ください。 - -### 構成証明 - -登録するには、開発者は、登録済みのプライバシー サンドボックス API の使用に関する特定のステートメント(構成証明とも呼ばれます)に同意する必要があります。これにより、クロスサイト トラッキングを制限しながら主要なビジネス ユースケースを有効にするという意図された目的を超えて、これらの API が不適切に使用されるリスクを軽減できます。 - -さらに、構成証明は、プライバシーサンドボックス API で収集および使用されるデータの公開透明性の向上に役立ちます。構成証明は、実装の詳細ではなく結果に焦点を当て、ユーザーが理解できるように作成されます。 - -開発者が全プロセスをレビューできるように、統一された登録期間が開始する前に、構成証明に関する詳細を提供します。開発者は、2023 年 8 月までに、登録プロセスの一環として構成証明を完了し、検証できるように公開する必要があります。 - -## 次のステップ - -登録手順が利用可能になり次第、このドキュメントを更新します。 +プライバシーサンドボックスへの登録は、[goo.gle/privacy-sandbox-enroll](https://goo.gle/privacy-sandbox-enroll) で行います。 From 4c1e2f4fe94054beff6144fd4563cbc2a2a125ee Mon Sep 17 00:00:00 2001 From: "Richard D. Worth" <rdworth@gmail.com> Date: Fri, 15 Sep 2023 14:12:02 +0200 Subject: [PATCH 788/982] mv3 promises - changed 'many apis' to 'most apis' (#7308) --- site/en/docs/extensions/mv3/intro/mv3-overview/index.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/site/en/docs/extensions/mv3/intro/mv3-overview/index.md b/site/en/docs/extensions/mv3/intro/mv3-overview/index.md index 8cf2fcdf9..cac4f3924 100644 --- a/site/en/docs/extensions/mv3/intro/mv3-overview/index.md +++ b/site/en/docs/extensions/mv3/intro/mv3-overview/index.md @@ -35,7 +35,7 @@ There are a number of new features and functional changes for extensions using M * [Service workers](#service-workers) replace background pages. * [Network request modification](#network-request-modification) is now handled with the new [declarativeNetRequest](/docs/extensions/reference/declarativeNetRequest) API. * [Remotely hosted code](#remotely-hosted-code) is no longer allowed; an extension can only execute JavaScript that is included within its package. -* [Promise](#promises) support has been added to many methods, though callbacks are still supported as an alternative. (We will eventually support promises on all appropriate methods.) +* [Promise](#promises) support has been added to most methods, though callbacks are still supported as an alternative. (We will eventually support promises on all appropriate methods.) * A number of other, relatively [minor feature changes](#other-features) are also introduced in Manifest V3. @@ -111,7 +111,7 @@ for more information. ### Promises {: #promises } -Manifest V3 provides first-class support for promises. Many popular APIs support +Manifest V3 provides first-class support for promises. Most APIs support promises now, and we will eventually support promises on all appropriate methods. Promise chains, async, and await are also supported. Some API features, such as event listeners, continue to require callbacks. From 06d42d3fc2abd7a7fe9730843d1981cd801a90ed Mon Sep 17 00:00:00 2001 From: Sofia Emelianova <42939855+sofiayem@users.noreply.github.com> Date: Fri, 15 Sep 2023 13:37:34 +0100 Subject: [PATCH 789/982] What's new in DevTools 118 (#7304) * skeleton and search * lighthouse * fix typos * at property * workspaces * edits * edits * reorder sources panes * sources highlight, pretty-print more script types * a11y * overrides * typo * exp: storage buckets * misc * typos * typos * edits * reorder sections * add reduced transparency * 117 hero upd + edit * 118 hero and edits * edits * edit * remove a premature experimental feature * upd date --- site/en/blog/new-in-devtools-117/index.md | 6 +- site/en/blog/new-in-devtools-118/index.md | 192 ++++++++++++++++++++++ site/en/docs/devtools/workspaces/index.md | 22 +-- 3 files changed, 207 insertions(+), 13 deletions(-) create mode 100644 site/en/blog/new-in-devtools-118/index.md diff --git a/site/en/blog/new-in-devtools-117/index.md b/site/en/blog/new-in-devtools-117/index.md index 0a3e0cdb1..309f55a8e 100644 --- a/site/en/blog/new-in-devtools-117/index.md +++ b/site/en/blog/new-in-devtools-117/index.md @@ -5,7 +5,7 @@ authors: - sofiayem date: 2023-08-22 description: "Override XHR/fetch requests and hide extension requests from the Network panel, see changes in fetch priority in the Performance panel, experience multiple UI improvements, check out new colors and experimental features, and more." -hero: 'image/NJdAV9UgKuN8AhoaPBquL7giZQo1/oM7ywmnxgVDuegxueVbK.png' +hero: 'image/NJdAV9UgKuN8AhoaPBquL7giZQo1/aUS2cyTsoXaIdbnbpSe1.png' alt: 'Override XHR/fetch requests and hide extension requests from the Network panel, see changes in fetch priority in the Performance panel, experience multiple UI improvements, check out new colors and experimental features, and more.' tags: - new-in-devtools @@ -141,11 +141,13 @@ In an effort to help build a [more private web](https://blog.google/products/chr You can already test how Chrome behaves *after* the third-party cookie phaseout. To do this, run [Chrome from the command line](https://www.chromium.org/developers/how-tos/run-chromium-with-flags/) with the `--test-third-party-cookies-phaseout` flag. To learn what this flag does, see [Debugging cookies](/docs/privacy-sandbox/third-party-cookie-phase-out/#debugging-cookies). -Regardless of the way you run Chrome (with or without the flag), the **Issues** tab now has the {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/hmp8j3HiLMCcqPArD9yt.svg", alt="Checkbox.", width="22", height="22" %} **Include third-party cookie issues** checkbox enabled by default and, as a result, reports: +Regardless of the way you run Chrome (with or without the flag), the **Issues** tab now has the {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/hmp8j3HiLMCcqPArD9yt.svg", alt="Checkbox.", width="22", height="22" %} **Include third-party cookie issues** checkbox enabled by default for all new Chrome users and, as a result, reports: - A breaking change warning about the upcoming phaseout. - Issues related to third-party cookies. +If want to see cookie warnings about the upcoming phaseout as an existing Chrome user, make sure to check this checkbox. + To test this, inspect cookies at [this demo page](https://samesite-sandbox.glitch.me/). {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/WlT6ntQm5iEGujg8P32c.png", alt="Third-party cookie issues reported in the Issues tab.", width="800", height="439" %} diff --git a/site/en/blog/new-in-devtools-118/index.md b/site/en/blog/new-in-devtools-118/index.md new file mode 100644 index 000000000..54093fc31 --- /dev/null +++ b/site/en/blog/new-in-devtools-118/index.md @@ -0,0 +1,192 @@ +--- +layout: 'layouts/blog-post.njk' +title: "What's New in DevTools (Chrome 118)" +authors: + - sofiayem +date: 2023-09-15 +description: "New section for custom properties in Elements > Styles, more local overrides improvements, enhanced search, streamlined workspace in Sources, and more." +hero: 'image/NJdAV9UgKuN8AhoaPBquL7giZQo1/r8TZKv9wtqFJvjYbyBeb.png' +alt: 'New section for custom properties in Elements > Styles, more local overrides improvements, enhanced search, streamlined workspace in Sources, and more.' +tags: + - new-in-devtools + - devtools + - chrome-118 +--- +<!--image/dPDCek3EhZgLQPGtEG3y0fTn4v82/gctGASDKBFTUtOQqVq2H.png --> + +{% Partial 'devtools/banner.md' %} + +*There is no 'What's new in DevTools' video for this release, but you can watch this quick recap of the recent features.* + +{% YouTube id='e8tl_yp5BQg' %} + +<!-- $contentStart --> + +## New section for custom properties in Elements > Styles {: #css } + +The **Elements** panel now supports the [@property CSS at-rule](https://web.dev/at-property/). It lets you define [CSS custom properties](https://developer.mozilla.org/docs/Web/CSS/--*) explicitly and register them in a stylesheet without running any JavaScript. + +To inspect your registered custom properties, in **Elements** > **Styles**, hover over the property name and see its descriptors in a tooltip. In the tooltip, click the link to view the registered property in the collapsible `@property` section. + +{% Video src="video/NJdAV9UgKuN8AhoaPBquL7giZQo1/vDfXTULIyNIJXVw6lKvf.mp4", width="800", height="511", autoplay="false", loop="true", muted="true", controls="true", class="screenshot" %} + +{# https://chromium.googlesource.com/devtools/devtools-frontend/+/b98b663cb79d1cd341efe824d1bc1995d917e385 #} +{# https://chromium.googlesource.com/devtools/devtools-frontend/+/69d1f4a605113e436deb6fa5f2f7dc4316819f57 #} +{# https://chromium.googlesource.com/devtools/devtools-frontend/+/1cfe38799440fe5d58d9387a4009cfdae2deced2 #} + +Chromium issues: [1471102](https://crbug.com/1471102), [1471103](https://crbug.com/1471103), [1471105](https://crbug.com/1471105). + + +## More local overrides improvements {: #overrides } + +Continuing the stream of improvements in the [previous version](/blog/new-in-devtools-117/#overrides), [local overrides](/docs/devtools/overrides/) now do the following: + +- In **Sources** > **Page**, when you right-click a source mapped file and select **Override content**, DevTools will show a dialog that takes to the original source instead. Content overrides of source mapped files can't be overridden. + + {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/7pgnWI5CLcNBnv2H7aWT.png", alt="The dialog that takes you to the original code instead of the source mapped file.", width="800", height="458" %} + +- The **Network** panel get a new **Has overrides** column and a corresponding `has-overrides:[content|headers|yes|no]` filter. To see the **Has overrides** column, [right-click](/docs/devtools/network/reference/#columns) the table header and select it. + + {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/8YIC3pobJEwjA6xCdE4I.png", alt="Filtering for 'has-overrides:yes' value in the 'Has overrides' column.", width="800", height="512" %} + +- In **Sources** > **Overrides**, the **Delete all overrides** menu option has been replaced with the **Delete** option with precise behavior. + + {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/GiuilKK9SD0duIIYK1Ig.png", alt="Before and after replacing 'Delete all overrides' with 'Delete'.", width="800", height="443" %} + +The previous **Delete all overrides** was confusing because it deleted only the overrides active in the current session, marked by the {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/s81rU6SgdmbseeBDGbPl.png", alt="Saved.", width="17", height="20" %} purple dot icon. + +The new **Delete** option, first shows a warning message and prompts confirmation, then deletes the folder you clicked with all its contents. + +To bring back the previous option, check {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/hmp8j3HiLMCcqPArD9yt.svg", alt="Checkbox.", width="22", height="22" %} **Enable "Delete all overrides temporarily"** in {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/9gzXiTYY0nZzBxGI6KrV.svg", alt="Settings.", width="24", height="24" %} **Settings** > **Experiments**. + +{# https://chromium.googlesource.com/devtools/devtools-frontend/+/77c8346f9025d1430c418bf596ff88f93f6ff2a9 #} +{# https://chromium.googlesource.com/devtools/devtools-frontend/+/fca7018689c03a74041741baee510fd2758b55d3 #} +{# https://chromium.googlesource.com/devtools/devtools-frontend/+/2b9c9f9d07db75e8b4dda600718384039083f0e5 #} + +Chromium issues: [1472952](https://crbug.com/1472952), [1416338](https://crbug.com/1416338), [1472580](https://crbug.com/1472580), [1473681](https://crbug.com/1473681) [1475668](https://crbug.com/1475668). + +## Enhanced search {: #search } + +[**Search**](/docs/devtools/search/) results now show an entry per all the matches it found in a line of code. Previously, it showed only the first match per line of code. The new behavior is especially useful when you search across minified files. When you click a search result, it opens the file in the editor and now scrolls the match into view not only vertically but also horizontally. + +{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/f5Yu4fSECIVDllWkpEZs.png", alt="The before and after making search show all the matches per line.", width="800", height="424" %} + +Additionally, **Search** got a speed boost. See the before (left) and after (right) comparison in the next video. + +{% Video src="video/NJdAV9UgKuN8AhoaPBquL7giZQo1/FyExrp5BLiGRHAT3OK4C.mp4", width="800", height="481", autoplay="false", loop="true", muted="true", controls="true", class="screenshot" %} + +Finally, **Search** now supports [ignore listing](/docs/devtools/settings/ignore-list/) and won't show you results from ignored files. + +{# https://chromium.googlesource.com/devtools/devtools-frontend/+/8bede301d455d921e66ba4052e8d3512e01d34bf #} +{# https://chromium.googlesource.com/devtools/devtools-frontend/+/2da188c6a7b519a30f2f43e114e78ac4c818e0cb #} +{# https://chromium.googlesource.com/devtools/devtools-frontend/+/1cfe38799440fe5d58d9387a4009cfdae2deced2 #} + +Chromium issues: [1468875](https://crbug.com/1468875), [1472019](https://crbug.com/1472019). + +## Improved Sources panel {: #sources } + +### Streamlined workspace in the Sources panel {: #workspace } + +The [workspace](/docs/devtools/workspaces/) feature in the **Sources** panel is new streamlined: + +- **Consistent naming**. Most notably, the **Sources** > **Filesystem** pane was renamed into **Workspace**. Various UI texts in this pane are now clearer and free of redundancy. +- **Improved setup**. See better cues for dragging and dropping folders or click a link to select a folder. + +[**Sources** > **Workspace**](/docs/devtools/workspaces/) lets you sync changes you make in DevTools directly to your source files. + +See the new setup and workflow in action: + +{% Video src="video/NJdAV9UgKuN8AhoaPBquL7giZQo1/1T78X6ldgLhiH6iJgAMk.mp4", width="800", height="436", autoplay="false", loop="true", muted="true", controls="true", class="screenshot" %} + +{# https://chromium.googlesource.com/devtools/devtools-frontend/+/9e9dd3ac6799946946e5442d5ab52acef6f53746 #} +{# https://chromium.googlesource.com/devtools/devtools-frontend/+/f9a46dfec696a73efb8824e1a794155d50a14e7e #} +{# https://chromium.googlesource.com/devtools/devtools-frontend/+/9d4f22fb8fb50085dd0a908c4099e0d275143886 #} +{# https://chromium.googlesource.com/devtools/devtools-frontend/+/49b05f57392ec6294c96ed385f2e91b2900224eb #} + +Chromium issues: [1473771](https://crbug.com/1473771), [1473880](https://crbug.com/1473880), [1473963](https://crbug.com/1473963), [1474686](https://crbug.com/1474686), [1474687](https://crbug.com/1474687). + +### Reorder panes in Sources {: #reorder-panes } + +You can now reorder panes on the left side of the **Sources** panel by dragging and dropping, similar to how you can [reorder other panels, tabs, and panes](/docs/devtools/customize/#reorder). + +{% Video src="video/NJdAV9UgKuN8AhoaPBquL7giZQo1/bHYhk8yS881OvomklbjW.mp4", width="800", height="375", autoplay="false", loop="true", muted="true", controls="true", class="screenshot" %} + +{# https://chromium.googlesource.com/devtools/devtools-frontend/+/49160d253ecbbcea84586457014947c1fa7e7876 #} + +Chromium issues: [1473758](https://crbug.com/1473758). + +### Syntax highlighting and pretty-printing for more script types {: #syntax } + +The **Sources** panel can now: + +- Pretty-print inline JavaScript within the following script types: [`module`](https://developer.mozilla.org/docs/Web/JavaScript/Guide/Modules), [`importmap`](https://developer.mozilla.org/docs/Web/HTML/Element/script/type/importmap), [`speculationrules`](/blog/debugging-speculation-rules/). +- Highlight the syntax of `importmap` and `speculationrules` script types, both of which hold JSON. + +{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/yZYe1CF5ObuLu7zVjcot.png", alt="Before and after pretty-printing and syntax highlighting of speculation rules script type.", width="800", height="395" %} + +For more information on speculation rules, see [Prerender pages in Chrome for instant page navigations](/blog/prerender-pages/). + +{# https://chromium.googlesource.com/devtools/devtools-frontend/+/d9f69138dae7d7042d5a964de4a91799029ba63e #} +{# https://chromium.googlesource.com/devtools/devtools-frontend/+/a49a95dd95a964a380334ddfba99b395d645f51a #} + +Chromium issue: [1473875](https://crbug.com/1473875). + +## Emulate prefers-reduced-transparency media feature {: #reduced-transparency } + +[Chrome 118 now supports](/blog/chrome-118-beta/#media-queries-prefers-reduced-transparency-feature) the [`prefers-reduced-transparency` media feature](https://developer.mozilla.org/docs/Web/CSS/@media/prefers-reduced-transparency). This feature lets developers adapt web content to user-selected preference for reduced transparency in the OS, such as the **Reduce transparency** setting on macOS. + +To emulate this media feature, open the **Rendering** tab and scroll down to it. + +{% Video src="video/NJdAV9UgKuN8AhoaPBquL7giZQo1/Xh60t9y0KnAIdwoUnbX5.mp4", autoplay="false", loop="true", muted="true", controls="true", class="screenshot", width="800", height="533" %} + +{# https://chromium.googlesource.com/devtools/devtools-frontend/+/8f2118f91bab0707949706421727ca423d53e111 #} + +Chromium issue: [1424879](https://crbug.com/1424879). + +## Lighthouse 11 {: #lighthouse } + +The **Lighthouse** panel now runs [Lighthouse 11](/blog/lighthouse-11-0/). Most notably, this version removes legacy navigation and adds new accessibility audits and changes how the accessibility category is scored. + +See also the [full list of changes](https://github.com/GoogleChrome/lighthouse/releases/tag/v11.0.0). To learn the basics of using the **Lighthouse** panel in DevTools, see [Lighthouse: Optimize website speed](/docs/devtools/lighthouse/). + +{# https://chromium.googlesource.com/devtools/devtools-frontend/+/8b7d433f10fd854784121020b76e29295bf51f84 #} + +Chromium issue: [772558](https://crbug.com/772558). + +## Accessibility improvements {: #accessibility } + +DevTools now supports more navigation keystrokes: + +- **CSS Overview**: Use the up and down arrows to navigate sections in the left sidebar. +- **Memory**: In the left sidebar, focus the **Save** button next to snapshots with <kbd>Tab</kbd> and press <kbd>Enter</kbd> to select folder. + +Additionally, several screen reader announcement issues have been fixed. + +{# https://chromium.googlesource.com/devtools/devtools-frontend/+/b16ef33f36c694dd67fe07a24b0ff5da98ab9307 #} +{# https://chromium.googlesource.com/devtools/devtools-frontend/+/bd7b236205de8c3e7cb3e67d83e8c4f1ada44ad4 #} +{# https://chromium.googlesource.com/devtools/devtools-frontend/+/11ca806035cccb4af046583e8b8d7aa7dc1af0f1 #} +{# https://chromium.googlesource.com/devtools/devtools-frontend/+/33964c8dfa442b928c5320a8f82d14287ab06a8e #} +{# https://chromium.googlesource.com/devtools/devtools-frontend/+/c4a2a6833828f4425e5e5add1b7aec6aafb3a451 #} + +Chromium issues: [1470401](https://crbug.com/1470401), [1471301](https://crbug.com/1471301), [1474108](https://crbug.com/1474108), [1468631](https://crbug.com/1468631). + +## Miscellaneous highlights {: #misc } + +These are some noteworthy fixes and improvements in this release: + +- **Network**: New icons for popular resources types: `media`, `wasm`, `websocket`, `manifest`, `fetch/xhr`, `json` ([1466298](https://crbug.com/1466298)). +- Color updates to material 3 colors in many UI elements, most notably in the **Elements** and **Performance** panels ([1456690](https://crbug.com/1456690), [1472243](https://crbug.com/1472243)). +- **Issues** now preserves cookie issues across navigations ([1466601](https://crbug.com/1466601)). +- Various [**Application** > **Preloading**](/blog/new-in-devtools-117/#preloading) improvements, most notably sortable grids and revised rule set details ([1410709](https://crbug.com/1410709)). +- Various improvements of the command editor in [**Protocol monitor**](/blog/new-in-devtools-117/#protocol-monitor), most notably warnings on wrong input, editing a sent command, editor for object parameters without predefined keys, support for enums undefined by references, objects without type reference, filter commands by substring matches, and more ([1448050](https://crbug.com/1448050)). +- **Performance** flame chart gets a border around the total box on the pie chart ([1470147](https://crbug.com/1470147)). +- **Sources** now doesn't treat dashes as word characters in CSS ([1471354](https://crbug.com/1471354)). +- Autocomplete now always sorts CSS-wise keywords at the end. +- RegEx filters now support spaces ([1346936](https://crbug.com/1346936)). +- **Elements** fixed media query feature detection ([1472693](https://crbug.com/1472693)). + +<!-- $contentEnd --> + +{% Partial 'devtools/reach-out.md' %} +{% Partial 'devtools/whats-new.md' %} + diff --git a/site/en/docs/devtools/workspaces/index.md b/site/en/docs/devtools/workspaces/index.md index 32d102277..2f94e07ff 100644 --- a/site/en/docs/devtools/workspaces/index.md +++ b/site/en/docs/devtools/workspaces/index.md @@ -1,12 +1,12 @@ --- layout: "layouts/doc-post.njk" -title: "Edit and save files with Workspaces" +title: "Edit and save files in a workspace" authors: - kaycebasques - sofiayem date: 2018-04-10 updated: 2022-10-31 -description: "Learn how to save changes made within DevTools to disk." +description: "Learn how to save changes made within DevTools to your source files." tags: - prototype-fixes - html @@ -16,8 +16,8 @@ tags: {% YouTube id='Zu9CdbnS5ps' %} -**Goal**: This tutorial provides hands-on practice in setting up and using Workspaces so that you -can use Workspaces in your own projects. Workspaces enable you to save changes that you make within +**Goal**: This tutorial provides hands-on practice in setting up a workspace so that you +can use it in your own projects. Workspace lets you to save changes that you make within DevTools to source code that's stored on your computer. {% Aside "caution" %} @@ -32,7 +32,7 @@ DevTools to source code that's stored on your computer. ## Overview {: #overview } -Workspaces enable you to save a change that you make in Devtools to a local copy of the same file on +Workspace lets you save a change that you make in DevTools to a local copy of the same file on your computer. For example, suppose: - You have the source code for your site on your desktop. @@ -41,30 +41,30 @@ your computer. For example, suppose: - You've got `localhost:8080` open in Google Chrome, and you're using DevTools to change the site's CSS. -With Workspaces enabled, the CSS changes that you make within DevTools are saved to the source code +With workspace enabled, the CSS changes that you make within DevTools are saved to the source code on your desktop. ## Limitations {: #limitations } If you're using a modern framework, it probably transforms your source code from a format that's -easy for you to maintain into a format that's optimized to run as quickly as possible. Workspaces is +easy for you to maintain into a format that's optimized to run as quickly as possible. Workspace is usually able to map the optimized code back to your original source code with the help of [source maps][4]. The DevTools community works to support the capabilities provided by source maps across a [variety of frameworks and tools](/docs/devtools/javascript/source-maps/#use_a_supported_preprocessor). -If you run into issues while using Workspaces with your framework of choice, or you get it working +If you run into issues while using a workspace with your framework of choice, or you get it working after some custom configuration, please [start a thread in the mailing list][5] or [ask a question on Stack Overflow][6] to share your knowledge with the rest of the DevTools community. ## Related feature: Local Overrides {: #overrides } -[Local overrides][7] is another DevTools feature that is similar to Workspaces. Use local overrides +[Local overrides][7] is another DevTools feature that is similar to workspace. Use local overrides when you want to experiment with changes to a page, and you need to see those changes across page loads, but you don't care about mapping your changes to the page's source code. ## Step 1: Setup {: #setup } -Complete this tutorial to get hands-on experience with Workspaces. +Complete this tutorial to get hands-on experience with a workspace. ### Set up the demo {: #demo } @@ -229,7 +229,7 @@ to your site. There's a way to have the **Sources** panel open alongside other p Congratulations! You now know how to save to sources the changes you make in DevTools to your locally hosted website. {% endAside %} -You can set up multiple folders as **Workspaces**. All such folders are listed in {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/9gzXiTYY0nZzBxGI6KrV.svg", alt="Settings.", width="24", height="24" %} [**Settings** > **Workspace**](/docs/devtools/settings/#workspace). +You can set up multiple folders in a workspace. All such folders are listed in {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/9gzXiTYY0nZzBxGI6KrV.svg", alt="Settings.", width="24", height="24" %} [**Settings** > **Workspace**](/docs/devtools/settings/#workspace). Next, learn how to use DevTools to [change CSS](/docs/devtools/css/) and [debug JavaScript](/docs/devtools/javascript/). From bf8e4ebb6a8426f09f2352c108d4d42cd1865eeb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Beaufort?= <beaufort.francois@gmail.com> Date: Fri, 15 Sep 2023 17:18:08 +0200 Subject: [PATCH 790/982] Add monitorTypeSurfaces option (#7310) --- .../screen-sharing-controls/index.md | 32 +++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/site/en/docs/web-platform/screen-sharing-controls/index.md b/site/en/docs/web-platform/screen-sharing-controls/index.md index 5109b596a..bcfd6c256 100644 --- a/site/en/docs/web-platform/screen-sharing-controls/index.md +++ b/site/en/docs/web-platform/screen-sharing-controls/index.md @@ -7,17 +7,19 @@ authors: - beaufortfrancois - eladalon date: 2022-09-29 -updated: 2023-03-14 +updated: 2023-09-15 hero: image/vvhSqZboQoZZN9wBvoXq72wzGAf1/5VpvNzrvEM3qSxasqP1j.jpeg alt: toddler holding her lips photo tags: - chrome-107 + - chrome-119 --- Sharing tabs, windows, and screens is already possible on the web platform with the [Screen Capture API]. In short, [`getDisplayMedia()`] allows the user to select a screen or portion of a screen (such as a window) to capture as a media stream. This stream can then be recorded or shared with others over the network. This article introduces some recent changes to the API to better preserve privacy, and prevent accidental sharing of personal information. Here’s a list of controls you can use for privacy preserving screen sharing: - The `displaySurface` option can indicate that the web app prefers to offer a specific display surface type (tabs, windows, or screens). +- The `monitorTypeSurfaces` option can be used to prevent the user from sharing an entire screen. - The `surfaceSwitching` option indicates whether Chrome should allow the user to dynamically switch between shared tabs. - The `selfBrowserSurface` option can be used to prevent the user from sharing the current tab. This avoids the "hall of mirrors" effect. - The `systemAudio` option ensures Chrome only offers relevant audio-capture to the user. @@ -51,6 +53,27 @@ const stream = await navigator.mediaDevices.getDisplayMedia({ Note that we don’t offer the option to pre-select a specific window or screen. This is by design, as that would give the web app too much power over the user. +### The `monitorTypeSurfaces` option {: #monitorTypeSurfaces } + +To protect companies from leakage of private information through employee-error, video conferencing web apps can now set [`monitorTypeSurfaces`] to `"exclude"`. Chrome will then exclude screens in the media picker. To include it, set it to `"include"`. Presently, the default value for `monitorTypeSurfaces` is `"include"`, but web apps are encouraged to set it explicitly, as the default may change in the future. + +```js +const stream = await navigator.mediaDevices.getDisplayMedia({ + video: true, + // Remove the "Entire Screen" pane in the media picker. + monitorTypeSurfaces: "exclude", +}); +``` + +<figure> + {% Img src="image/vvhSqZboQoZZN9wBvoXq72wzGAf1/HA2gYMmPpJzVcDqM4o8J.png", alt="Screenshot of the media picker with no \"Entire Screen\" pane.", width="800", height="519" %} + <figcaption> + The "Entire Screen" pane is not visible in the media picker. + </figcaption> +</figure> + +Note that an explicit `monitorTypeSurfaces: "exclude"` is mutually exclusive with `displaySurface: "monitor"`. + ### The `surfaceSwitching` option {: #surfaceSwitching } One of the top-cited reasons for sharing the entire screen, is the desire to seamlessly switch between sharing different surfaces during a session. To address this, Chrome now exposes a button that lets a user dynamically switch between sharing different tabs. This "Share this tab instead" button has previously been available to Chrome extensions, and can now be used by any web app which calls [`getDisplayMedia()`]. @@ -132,7 +155,9 @@ You can play with these screen sharing controls by running the [demo] on Glitch. ## Browser support {: #browser-support } -`displaySurface`, `surfaceSwitching`, and `selfBrowserSurface` are available in Chrome 107 on desktop. `systemAudio` is available in Chrome 105 on desktop. +- `displaySurface`, `surfaceSwitching`, and `selfBrowserSurface` are available in Chrome 107 on desktop. +- `systemAudio` is available in Chrome 105 on desktop. +- `monitorTypeSurfaces` is available in Chrome 119 on desktop. ## Feedback {: #feedback } @@ -160,6 +185,7 @@ Send a tweet to [@ChromiumDev] and let us know where and how you are using it. - [Specification][spec] - [`displaySurface` explainer] +- [`monitorTypeSurfaces` explainer] - [`surfaceSwitching` explainer] - [`selfBrowserSurface` explainer] - [`systemAudio` explainer] @@ -174,6 +200,7 @@ Thanks to [Rachel Andrew] for reviewing this article. [screen capture api]: https://w3c.github.io/mediacapture-screen-share/ [`getdisplaymedia()`]: https://developer.mozilla.org/docs/web/api/mediadevices/getdisplaymedia [`displaysurface`]: https://w3c.github.io/mediacapture-screen-share/#dfn-displaysurface +[`monitortypesurfaces`]: https://w3c.github.io/mediacapture-screen-share/#dom-displaymediastreamoptions-monitortypesurfaces [`surfaceswitching`]: https://w3c.github.io/mediacapture-screen-share/#dom-displaymediastreamoptions-surfaceswitching [`selfbrowsersurface`]: https://w3c.github.io/mediacapture-screen-share/#dom-displaymediastreamoptions-selfbrowsersurface [`prefercurrenttab: true`]: https://wicg.github.io/prefer-current-tab/ @@ -185,6 +212,7 @@ Thanks to [Rachel Andrew] for reviewing this article. [@chromiumdev]: https://twitter.com/chromiumdev [spec]: https://w3c.github.io/mediacapture-screen-share/ [`displaysurface` explainer]: https://github.com/eladalon1983/screen-share-explainers/blob/main/displaySurface_Constraint_Explainer.md +[`monitortypesurfaces` explainer]: https://github.com/eladalon1983/screen-share-explainers/blob/main/monitorTypeSurfaces_Explainer.md [`surfaceswitching` explainer]: https://github.com/eladalon1983/screen-share-explainers/blob/main/surfaceSwitching_Explainer.md [`selfbrowsersurface` explainer]: https://github.com/eladalon1983/screen-share-explainers/blob/main/selfBrowserSurface_Explainer.md [`systemaudio` explainer]: https://github.com/eladalon1983/screen-share-explainers/blob/main/systemAudio_Explainer.md From d3a240601dd27f1a8f3124b81ea7a58e2daec6b5 Mon Sep 17 00:00:00 2001 From: amysteamdev <37001393+AmySteam@users.noreply.github.com> Date: Fri, 15 Sep 2023 13:04:47 -0500 Subject: [PATCH 791/982] Fix code sample in GA4 tutorial (#7311) Fixes #7295 --- site/en/docs/extensions/mv3/tut_analytics/index.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/site/en/docs/extensions/mv3/tut_analytics/index.md b/site/en/docs/extensions/mv3/tut_analytics/index.md index 08b949ada..b39372454 100644 --- a/site/en/docs/extensions/mv3/tut_analytics/index.md +++ b/site/en/docs/extensions/mv3/tut_analytics/index.md @@ -166,15 +166,15 @@ The event will be displayed as follows in the Google Analytics Realtime report. {% Img src="image/6hHqS5auVgWhN0cQNQztaJx5w4M2/AQqSJb9VqalWfrQ6xSXM.png", alt="Realtime events in Google Analytics. ", width="396", height="414" %} -## Tracking page views in popup, side panel and extension pages {: #toc-tracking-pageviews } +## Tracking page views in popup, side panel, and extension pages {: #toc-tracking-pageviews } The Google Analytics Measurement Protocol supports a special `page_view` event for tracking page views. Use this to track users visiting your popup pages, side panel or an extension page in a new tab. The `page_view` event also requires the `page_title` and `page_location` parameters. The following example fires a page view event at the document [`load`][13] event for an extension popup.: {% Label %}popup.js:{% endLabel %} ```js -window.addEventListener("load", () => { - ${GA_ENDPOINT}?measurement_id=${MEASUREMENT_ID}&api_secret=${API_SECRET}`, +window.addEventListener("load", async () => { + fetch(`${GA_ENDPOINT}?measurement_id=${MEASUREMENT_ID}&api_secret=${API_SECRET}`, { method: "POST", body: JSON.stringify({ @@ -183,7 +183,7 @@ window.addEventListener("load", () => { { name: "page_view", params: { - session_id: await this.getOrCreateSessionId(), + session_id: await getOrCreateSessionId(), engagement_time_msec: DEFAULT_ENGAGEMENT_TIME_IN_MSEC, page_title: document.title, page_location: document.location.href @@ -191,7 +191,7 @@ window.addEventListener("load", () => { }, ], }), - } + }); }); ``` From 130d07673224da704acc7df275893598aa3266ee Mon Sep 17 00:00:00 2001 From: Joe Medley <jmedley@google.com> Date: Fri, 15 Sep 2023 11:57:24 -0700 Subject: [PATCH 792/982] Add file scheme changes to 'What's new'. (#7313) * Add file scheme changes to 'What's new'. * Update site/en/docs/extensions/whatsnew/index.md Co-authored-by: amysteamdev <37001393+AmySteam@users.noreply.github.com> --------- Co-authored-by: amysteamdev <37001393+AmySteam@users.noreply.github.com> --- site/en/docs/extensions/whatsnew/index.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/site/en/docs/extensions/whatsnew/index.md b/site/en/docs/extensions/whatsnew/index.md index 55216c2f9..523468b9e 100644 --- a/site/en/docs/extensions/whatsnew/index.md +++ b/site/en/docs/extensions/whatsnew/index.md @@ -3,7 +3,7 @@ layout: 'layouts/doc-post.njk' title: What's new in Chrome extensions description: 'Recent changes to the Chrome extensions platform, documentation, and policy' date: 2021-02-25 -updated: 2023-08-23 +updated: 2023-09-15 tags: - extensions-news @@ -15,6 +15,10 @@ tags: Check this page often to learn about changes to Chrome extensions, extensions documentation, or related policy or other changes. You'll find other notices posted on the [Extensions Google Group](https://groups.google.com/a/chromium.org/g/chromium-extensions). The [Extensions News](/tags/extensions-news/) tag lists articles about some of the topics listed here. (It even has [an RSS feed](/feeds/extensions-news.xml).) The [Chrome schedule](https://chromiumdash.appspot.com/schedule) lists stable and beta release dates. +### Chrome 118: Changes to opening file: scheme URLs {: #changes-to-file-scheme } + +Beginning in Chrome 118, extensions will need the "Allow access to file URLs" setting enabled from the `chrome://extensions` page to open file:// scheme URLs using the [Tabs](/docs/extensions/reference/tabs/) or [Windows](/docs/extensions/reference/windows/) APIs. You can programmatically check for this access by calling [`chrome.extension.isAllowedFileSchemeAccess()`](/docs/extensions/reference/extension/#method-isAllowedFileSchemeAccess). Firefox already restricts file URLs, and Safari supports the change. For more information, read the [post in the extensions Google Group](https://groups.google.com/a/chromium.org/g/chromium-extensions/c/ZtCvVISQU54/m/tOjjlzkfAgAJ). + ### Chrome 117: Expanded URL protections on extension API navigations {: #expanded-kill-url } <p class="color-secondary-text type--caption">Posted on <time>August 23, 2023</time></p> From d77afde1a2c0141f5728c82dace0775e356db15f Mon Sep 17 00:00:00 2001 From: Sofia Emelianova <42939855+sofiayem@users.noreply.github.com> Date: Mon, 18 Sep 2023 12:26:41 +0100 Subject: [PATCH 793/982] DevTools 117: Performance and Sources upds (#7203) * perf: fetch priority * edits * fold code blocks * 3pc enabled in issues panel * edit * edit * edits * reorg editor nav section --- site/en/docs/devtools/issues/index.md | 6 ++-- .../devtools/javascript/reference/index.md | 31 ++++++++++++++----- .../devtools/performance/reference/index.md | 12 +++---- 3 files changed, 34 insertions(+), 15 deletions(-) diff --git a/site/en/docs/devtools/issues/index.md b/site/en/docs/devtools/issues/index.md index a06ab5d76..19c8763f9 100644 --- a/site/en/docs/devtools/issues/index.md +++ b/site/en/docs/devtools/issues/index.md @@ -93,12 +93,14 @@ To group issues, check {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/hmp8j3HiLM ### Include third-party issues {: #include-third-party } -Third-party cookie issues are hidden by default. +The Issues tab shows third-party cookies issues by default. -To view such issues, check {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/hmp8j3HiLMCcqPArD9yt.svg", alt="Checkbox.", width="22", height="22" %} **Include third-party cookie issues** in the action bar at the top of the **Issues** tab. You can find third-party cookie issues in the **AFFECTED RESOURCES** section missing a link. +You can find third-party cookie issues in the **AFFECTED RESOURCES** section missing a link. {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/hPAEUH4LTwDFyPoQoPQ0.png", alt="Third-party cookie without a linked resource in the Affected Resources section.", width="800", height="654" %} +To hide such issues, clear {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/ZtDyFg7cjkxacORB3GQn.svg", alt="Clear.", width="24", height="24" %} **Include third-party cookie issues** in the action bar at the top of the **Issues** tab. + ### Hide issues {: #hide-issues } To hide an issue, select **Hide issues like this** from the {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/N5Lkpdwpaz4YqRGFr2Ks.svg", alt="Three-dot menu.", width="24", height="24" %} three-dot menu next to the issue. diff --git a/site/en/docs/devtools/javascript/reference/index.md b/site/en/docs/devtools/javascript/reference/index.md index b441e3010..82c899de9 100644 --- a/site/en/docs/devtools/javascript/reference/index.md +++ b/site/en/docs/devtools/javascript/reference/index.md @@ -468,14 +468,31 @@ expression. {% Img src="image/BrQidfK9jaQyIHwdw91aVpkPiib2/iWsdoHnowdltMpnOfSJG.png", alt="Delete expression", width="20", height="11" %} to delete it. -## Make a minified file readable {: #format } +## Inspect and edit scripts {: #editor } -Click **Format** {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/JCyivmZxQVqpI4tj7Sil.svg", alt="Format.", width="20", height="20" %} to make a minified -file human-readable. +When you open a script in the [**Page**](/docs/devtools/javascript/reference/#file-tree) pane, DevTools shows you its contents in the **Editor** pane. In the **Editor** pane, you can browse and edit your code. -{% Img src="image/admin/cttlkengXdMrdvwjh5S3.svg", alt="The Format button.", width="800", height="609" %} +Additionally, you can [override](/docs/devtools/overrides/) the contents locally or create a [workspace](/docs/devtools/workspaces/) and save the changes you make in DevTools directly to your local sources. -## Edit a script {: #edit } +### Make a minified file readable {: #format } + +By default, the **Sources** panel pretty-prints minified files. When pretty-printed, the **Editor** may show a single long code line in multiple lines, with `-` to indicate that it's the line continuation. + +{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/vqpCILSqkHx4mJlliMf5.png", alt="A pretty-printed long code line shown in multiple lines, with '-' to indicate line continuation.", width="800", height="557" %} + +To see the minified filed as it was loaded, click `{ }` in the bottom left corner of the **Editor**. + +### Fold code blocks {: #fold-code-blocks } + +To fold a code block, hover over the line number in the left column and click {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/TGwMBZWZWJlVmQhR2cHx.svg", alt="Collapse.", width="20", height="20" %} **Collapse**. + +To unfold the code block, click `{...}` next to it. + +{% Video src="video/NJdAV9UgKuN8AhoaPBquL7giZQo1/A99gci0l8aXMmv0IHAGH.mp4", width="800", height="456", autoplay="false", controls="true", muted="true", class="screenshot" %} + +To configure this behavior, see {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/9gzXiTYY0nZzBxGI6KrV.svg", alt="Settings.", width="24", height="24" %} [**Settings** > **Preferences** > **Sources**](/docs/devtools/settings/preferences/#sources). + +### Edit a script {: #edit } When fixing a bug, you often want to test out some changes to your JavaScript code. You don't need to make the changes in an external browser and then reload the page. You can edit your script in @@ -492,7 +509,7 @@ To edit a script: The **Editor** pane on the screenshot above is outlined in blue. -## Edit a paused function live {: #live-edit} +### Edit a paused function live {: #live-edit} {% Aside %} **Note:** This feature is available from Chrome version 105. @@ -520,7 +537,7 @@ Watch the video below to learn this workflow. In this example, the `addend1` and `addend2` variables initially have an incorrect `string` type. So, instead of adding numbers, the strings are concatenated. To fix it, the `parseInt()` functions are added during live editing. -## Search and replace text in a script {: #search } +### Search and replace text in a script {: #search } To search for text in a script: diff --git a/site/en/docs/devtools/performance/reference/index.md b/site/en/docs/devtools/performance/reference/index.md index 9e88e36ac..cf3653713 100644 --- a/site/en/docs/devtools/performance/reference/index.md +++ b/site/en/docs/devtools/performance/reference/index.md @@ -476,7 +476,7 @@ outlines the selected frame in blue. Expand the **Network** section to view a waterfall of network requests that occurred during the recording. -{% Img src="image/admin/ZkpNSWGs2csexM9Mo7GO.svg", alt="The Network section.", width="800", height="950" %} +{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/o92Wkwgu306BlRGTXuGJ.png", alt="A request selected in the Network sections, with the Summary tab open.", width="800", height="722" %} Requests are color-coded as follows: @@ -485,13 +485,13 @@ Requests are color-coded as follows: - JS: Yellow - Images: Green -Click on a request to view more information about it in the **Summary** tab. In the example above, -the **Summary** tab is displaying more information about the blue request that's selected in the -**Network** section. +Click a request to view more information about it in the **Summary** tab. In the example above, the **Summary** tab is displaying information about the selected green request. A darker-blue square in the top-left of a request means it's a higher-priority request. A -lighter-blue square means lower-priority. In the example above, the selected request is -higher-priority, and the green one above it is lower-priority. +lighter-blue square means lower-priority. In the example above, the selected request is of +high priority, and the blue one above it is highest-priority. + +The **Summary** section includes **Initial Priority** and (final) **Priority** fields. If their values differ, the fetch priority of the request has changed during the recording. For more information, see [Optimizing resource loading with the Fetch Priority API](https://web.dev/fetch-priority/). In the example above, the request for `www.google.com` is represented by a line on the left, a bar in the middle with a dark portion and a light portion, and a line on the right. The screenshot below shows the From fd63f693b41e33766b42db2034eb1a813a254247 Mon Sep 17 00:00:00 2001 From: Nancymic2 <nmichell@google.com> Date: Mon, 18 Sep 2023 10:08:54 -0400 Subject: [PATCH 794/982] Publish Privacy Regulation FAQs to developer.chrome.com website (#7273) * FAQ partners page * FAQ partners page * Capitalization * date --- site/_data/docs/privacy-sandbox/toc.yml | 1 + .../privacy-compliance-faq/index.md | 135 ++++++++++++++++++ 2 files changed, 136 insertions(+) create mode 100644 site/en/docs/privacy-sandbox/privacy-compliance-faq/index.md diff --git a/site/_data/docs/privacy-sandbox/toc.yml b/site/_data/docs/privacy-sandbox/toc.yml index ad6a07754..3ecca82b4 100644 --- a/site/_data/docs/privacy-sandbox/toc.yml +++ b/site/_data/docs/privacy-sandbox/toc.yml @@ -21,6 +21,7 @@ - url: /docs/privacy-sandbox/enroll title: i18n.docs.privacy-sandbox.enroll - url: /docs/privacy-sandbox/status + - url: /docs/privacy-sandbox/privacy-compliance-faq - url: /docs/privacy-sandbox/feedback - title: i18n.docs.privacy-sandbox.strengthen-boundaries sections: diff --git a/site/en/docs/privacy-sandbox/privacy-compliance-faq/index.md b/site/en/docs/privacy-sandbox/privacy-compliance-faq/index.md new file mode 100644 index 000000000..e6ade403d --- /dev/null +++ b/site/en/docs/privacy-sandbox/privacy-compliance-faq/index.md @@ -0,0 +1,135 @@ +--- +layout: 'layouts/doc-post.njk' +title: 'Privacy-related compliance FAQs' +subhead: > + Answers to frequently asked questions about obligations, consent, and user controls. +description: > + Answers to frequently asked questions about obligations, consent, and user controls. +date: 2023-09-18 +--- + +## Privacy-related compliance FAQs for Privacy Sandbox Relevance and Measurement APIs + +Privacy Sandbox relevance and measurement APIs and updated user controls are +now +[generally available in Chrome](https://privacysandbox.com/intl/en_us/news/privacy-sandbox-for-the-web-reaches-general-availability). +Ecosystem participants have asked about Chrome's approach to privacy-related +compliance with Privacy Sandbox as well as their own responsibilities. While we +cannot provide legal advice, we can share our responses to frequently asked +questions and provide information about the APIs that can help those responsible +for privacy-related compliance decisions. + +### Questions and answers + +**Do sites and other Privacy Sandbox relevance and measurement API callers have ePrivacy obligations?** + +Laws like ePrivacy require consent to store or access data on and from a user's +browser unless strictly necessary and do not differentiate between legacy +technologies such as third-party cookies, and emerging Privacy Enhancing +Technologies (PET) such as the Privacy Sandbox APIs. + +Use of each of the Privacy Sandbox APIs involves accessing data that is stored +on the user's device. + +For reference, companies can see how Google's own ads services, which operate +independently from Chrome, are incorporating Privacy Sandbox technologies as +part of their +[EU User Consent Policies](https://www.google.com/about/company/user-consent-policy-help/#:~:text=Do%20I%20need%20to%20follow%20this%20policy%20if%20I%20participate,and%20the%20UK.). +As the landscape evolves, we are hopeful that the privacy benefits of PETs may +be reflected in user consent regulations in the future. We encourage companies +to monitor privacy regulations and DPA guidance, and assess their own +obligations. + +**Can users withdraw consent or otherwise control Privacy Sandbox relevance and measurement APIs?** + +Yes. Users can access `chrome://settings/adPrivacy`, which provides individual, +granular controls for turning off Privacy Sandbox APIs, blocking individual +topics and specific sites from setting Interest Groups. Users can delete +ad-measurement data by deleting browsing data. + +Sites will need to determine what choices they offer to users, how those +preferences are stored, how a user's preference is signaled to the site's +ad-tech vendors who may call the Privacy Sandbox APIs, and how those vendors are +held accountable. Sites and their vendors will need to decide what a user's +choice means in terms of whether and how a given Privacy Sandbox API is used. + +Some opt-out based, self-regulatory programs such as AdChoices rely on third-party +cookies. We encourage you to ask those programs how they are preparing for +third-party cookie deprecation. + +**Can user choices related to Privacy Sandbox be persisted across sites?** + +Users can access `chrome://settings/adPrivacy`, which provides controls for turning +off Privacy Sandbox APIs altogether or blocking individual topics. Users can +delete ad-measurement data by deleting browsing data. + +Sites will need to determine whether they take responsibility for extending +user choices expressed on their own sites to the rest of the web. Some opt-out +based, self-regulatory programs such as AdChoices are meant to offer users choices +about how ad tech companies process user data across sites (such as +[Interest-based Advertising](https://youradchoices.com/learn#learn-icon)). +Traditionally those programs are specific to ad tech companies who choose to +participate, and not to sites. We encourage you to ask those programs how they +are preparing for third-party cookie deprecation. + +**Can users delete data related to Privacy Sandbox relevance and measurement APIs?** + +Users can access `chrome://settings/adPrivacy`, which provides individual, granular +controls for turning off Privacy Sandbox APIs, blocking individual topics and +specific sites from setting Interest Groups. Users can delete ad-measurement +data by deleting browsing data. Additionally, Chrome will automatically delete +users' topics of interest, Interest Groups and reporting events after a set +period of time. + +For sites and other Privacy Sandbox relevance and measurement API callers, the +following technical functions are available: + +- For Protected Audience, a site or its ad tech that can add Interest + Groups from this site can also call the `leaveAdInterestGroup` function. +- For Shared Storage, a site or its ad tech can call the `delete` method + on a key or the `clear` method to clear all keys. +- For the Attribution Reporting API, a site or its ad tech can use + the + [`Clear-Site-Data` header](https://developer.mozilla.org/docs/Web/HTTP/Headers/Clear-Site-Data). + +Sites and other API callers will need to determine if their current mechanisms +for deletion rights are suitable if and when they have chosen to store data +retrieved from Privacy Sandbox APIs or data related to calling the APIs. + +**How is Privacy Sandbox approaching privacy-related compliance in Chrome?** + +In the case of Topics, this is a new experience for Chrome users and Chrome +wanted to provide a separate moment for users to learn and choose what's best +for them. Topics marks a new way for Chrome to enable relevant experiences based +on a user's browsing history, and Chrome has taken the decision to ask for +consent from users in the UK/EEA and Switzerland before enabling the API. + +The Protected Audience and measurement APIs represent more private versions of +existing processing behaviors both within the browser and in protected, trusted +environments. Overall, all users will have robust controls, and can opt out of +the Privacy Sandbox experience at any point. + +You can learn more about Privacy Sandbox ad controls in our +[Help Center](https://support.google.com/chrome/answer/13355898#zippy=%2Cmanage-ad-topics). + +## More API information + +Learn more about the Privacy Sandbox relevance and measurement APIs: + +- [Topics](/docs/privacy-sandbox/topics/): + Generate signals for interest-based advertising without third-party cookies + or other user identifiers that track individuals across sites. +- [Protected Audience](/docs/privacy-sandbox/protected-audience/): + Select ads to serve remarketing and custom audience use cases, designed to + mitigate third-party tracking across sites. +- [Attribution Reporting](/docs/privacy-sandbox/attribution-reporting/): + Correlate ad clicks or ad views with conversions. Ad techs can generate + event-level or summary reports. +- [Private Aggregation](/docs/privacy-sandbox/private-aggregation/): + Generate aggregate data reports using data from Protected Audience and + cross-site data from Shared Storage. +- [Shared Storage](/docs/privacy-sandbox/shared-storage/): + Allow unlimited, cross-site storage write access with privacy-preserving + read access. +- [Fenced Frames](/docs/privacy-sandbox/fenced-frame/): + Securely embed content onto a page without sharing cross-site data. From 77562208838a03f26adb6d7e19af9ca3b5ceb854 Mon Sep 17 00:00:00 2001 From: Anusmita <anusmitaray@google.com> Date: Mon, 18 Sep 2023 23:01:54 +0100 Subject: [PATCH 795/982] Fix link (#7329) --- .../attribution-reporting/register-attribution-trigger/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/en/docs/privacy-sandbox/attribution-reporting/register-attribution-trigger/index.md b/site/en/docs/privacy-sandbox/attribution-reporting/register-attribution-trigger/index.md index 9ad192f79..e8862ac4f 100644 --- a/site/en/docs/privacy-sandbox/attribution-reporting/register-attribution-trigger/index.md +++ b/site/en/docs/privacy-sandbox/attribution-reporting/register-attribution-trigger/index.md @@ -31,7 +31,7 @@ This generates network requests that you then respond to with a trigger registra ## Register a trigger to attribute a conversion Registering a trigger is similar to -[registering an attribution source event](http://localhost:8080/docs/privacy-sandbox/attribution-reporting/register-attribution-source/). The [complete steps](#step-1-initiate-the-trigger-registration) are described later. Here's the summary: +[registering an attribution source event](/docs/privacy-sandbox/attribution-reporting/register-attribution-source/). The [complete steps](#step-1-initiate-the-trigger-registration) are described later. Here's the summary: 1. **Initiate the trigger registration.** Use a pixel or a `fetch()` call to make a request. From 84dcfdaf794a18fdd39fe1eab4d5a670a67c971e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Beaufort?= <beaufort.francois@gmail.com> Date: Tue, 19 Sep 2023 09:41:35 +0200 Subject: [PATCH 796/982] Add From WebGL to WebGPU blog post (#7324) --- site/en/blog/from-webgl-to-webgpu/index.md | 150 +++++++++++++++++++++ 1 file changed, 150 insertions(+) create mode 100644 site/en/blog/from-webgl-to-webgpu/index.md diff --git a/site/en/blog/from-webgl-to-webgpu/index.md b/site/en/blog/from-webgl-to-webgpu/index.md new file mode 100644 index 000000000..33c618687 --- /dev/null +++ b/site/en/blog/from-webgl-to-webgpu/index.md @@ -0,0 +1,150 @@ +--- +layout: "layouts/blog-post.njk" +title: "From WebGL to WebGPU" +description: "Learn some tips for WebGL developers who are migrating to WebGPU." +hero: "image/vvhSqZboQoZZN9wBvoXq72wzGAf1/zgz7uZNkCxByGrzpKGq1.png" +alt: "WebGL and WebGPU logos" +date: 2023-09-19 +#updated: YYYY-MM-DD +authors: + - beaufortfrancois +tags: + - webgpu + - media + - video +--- + +As a WebGL developer, you may be both intimidated and excited to start using WebGPU, the successor to WebGL that brings the advancements of modern graphics APIs to the web. + +It’s reassuring to know that WebGL and WebGPU share many core concepts. Both APIs allow you to run small programs called shaders on the GPU. WebGL supports vertex and fragment shaders, while WebGPU also supports compute shaders. WebGL uses the OpenGL Shading Language (GLSL) while WebGPU uses the WebGPU Shading Language (WGSL). Although the two languages are different, the underlying concepts are mostly the same. + +With that in mind, this article highlights some differences between WebGL and WebGPU, to help you get started. + +## Global state + +WebGL has a [lot of global state](https://webglfundamentals.org/webgl/lessons/resources/webgl-state-diagram.html). Some settings apply to all rendering operations, such as which textures and buffers are bound. You set this global state by calling various API functions, and it remains in effect until you change it. The global state in WebGL is a [major source of errors](https://kangz.net/posts/2016/07/11/lets-do-opengl-archeology/), as it is easy to forget to change a global setting. Additionally, global state makes code sharing difficult, as developers need to be careful not to accidentally change the global state in a way that affects other parts of the code. + +WebGPU is a stateless API, and does not maintain a global state. Instead, it uses the concept of a [pipeline](https://gpuweb.github.io/gpuweb/#pipelines) to encapsulate all of the rendering state that was global in WebGL. A pipeline contains information such as which blending, topology, and attributes to use. A pipeline is immutable. If you want to change some settings, you need to create another pipeline. WebGPU also uses [command encoders](https://gpuweb.github.io/gpuweb/#command-encoding) to batch commands together and execute them in the order that they were recorded. This is useful in shadow mapping for example, where, in a single pass over the objects, the application can record multiple command streams, one for each light's shadow map. + +To summarize, as WebGL’s global state model made creating robust, composable libraries and applications difficult and fragile, WebGPU significantly reduced the amount of state that developers needed to keep track of while sending commands to the GPU. + +## Sync no more + +On GPUs, it is typically inefficient to send commands and wait for them synchronously, as this can flush the pipeline and cause [bubbles](https://en.wikipedia.org/wiki/Pipeline_stall). This is especially true in WebGPU and WebGL, which use a multi-process architecture with the GPU driver running in a separate process from JavaScript. + +In WebGL, for example, calling `gl.getError()` requires a synchronous [IPC](/blog/inside-browser-part1/#executing-program-on-process-and-thread) from the JavaScript process to the GPU process and back. This can cause a bubble on the CPU side as the two processes communicate. + +To avoid these bubbles, WebGPU is designed to be completely [asynchronous](https://gpuweb.github.io/gpuweb/#asynchrony). The [error model](https://toji.dev/webgpu-best-practices/error-handling) and all other operations happen asynchronously. For example, when you create a texture, the operation appears to succeed immediately, even if the texture is actually an error. You can only discover the error asynchronously. This design keeps the cross-process communication bubble-free and gives applications reliable performance. + +## Compute shaders + +Compute shaders are programs that run on the GPU to perform general-purpose computations. They are available only in WebGPU, not WebGL. + +Unlike vertex and fragment shaders, they are not limited to graphics processing, and can be used for a wide variety of tasks, such as machine learning, physics simulation, and scientific computing. Compute shaders are executed in parallel by hundreds or even thousands of threads, which makes them very efficient for processing large datasets. Learn about [GPU compute](/articles/gpu-compute) and more detail [in this extensive article about WebGPU](https://surma.dev/things/webgpu/index.html). + +## Video frame processing + +Processing video frames using JavaScript and WebAssembly has some drawbacks: the cost of copying the data from GPU memory to CPU memory, and the limited parallelism that can be achieved with workers and CPU threads. WebGPU does not have those limitations, making it a great fit for processing video frames thanks to its tight integration with the [WebCodecs](https://developer.mozilla.org/docs/Web/API/WebCodecs_API) API. + +The following code snippet shows how to import a VideoFrame as an external texture in WebGPU and process it. You can try out this [demo](https://webgpu-video-processing.glitch.me/). + +```js +// Init WebGPU device and pipeline... +// Configure canvas context... +// Feed camera stream to video... + +(function render() { + const videoFrame = new VideoFrame(video); + applyFilter(videoFrame); + requestAnimationFrame(render); +})(); + +function applyFilter(videoFrame) { + const texture = device.importExternalTexture({ source: videoFrame }); + const bindgroup = device.createBindGroup({ + layout: pipeline.getBindGroupLayout(0), + entries: [{ binding: 0, resource: texture }], + }); + // Finally, submit commands to GPU +} +``` + +{% Glitch { id: 'webgpu-video-processing', path: 'script.js' } %} + +## Application portability by default + +WebGPU forces you to request [`limits`](https://developer.mozilla.org/docs/Web/API/GPUAdapter/limits). By default, [`requestDevice()`](https://developer.mozilla.org/docs/Web/API/GPUAdapter/requestDevice) returns a GPUDevice that may not match the physical device’s hardware capabilities, but rather a reasonable and lowest common denominator of all GPUs. By requiring developers to request device limits, WebGPU ensures that applications will run on as many devices as possible. + +## Canvas handling + +WebGL automatically manages the canvas after you create a WebGL context and supply [context attributes](https://developer.mozilla.org/docs/Web/API/HTMLCanvasElement/getContext) such as alpha, antialias, colorSpace, depth, preserveDrawingBuffer, or stencil. + +On the other hand, WebGPU requires you to manage the canvas yourself. For example, to achieve antialiasing in WebGPU, you would create a multisample texture and render to it. Then, you would resolve the multisample texture to a regular texture and draw that texture to the canvas. This manual management allows you to output to as many canvases as you want from a single [GPUDevice](https://developer.mozilla.org/docs/Web/API/GPUDevice) object. In contrast, WebGL can only create one context per canvas. + +Check out the [WebGPU Multiple Canvases demo](https://jsgist.org/?src=bcb94d8b67b19f71a9792966da827af7). + +On a side note, browsers currently have a limit on the number of WebGL canvases per page. At the time of writing, Chrome and Safari can only use up to 16 WebGL canvases simultaneously; Firefox can create up to 200 of them. On the other hand, there is no limit on the number of WebGPU canvases per page. + +<figure> + {% Img src="image/vvhSqZboQoZZN9wBvoXq72wzGAf1/xxUCC7nuUT35G5mafrIT.png", alt="Screenshot featuring maximum number of WebGL canvases in Safari, Chrome, and Firefox browsers", width="800", height="517" %} + <figcaption> + The maximum number of WebGL canvases in Safari, Chrome, and Firefox (from left to right) - <a target="_blank" href="https://max-gl-contexts.glitch.me/">demo</a>. + </figcaption> +</figure> + +## Helpful error messages + +WebGPU provides a call stack for every message that is returned from the API. This means that you can quickly see where the error occurred in your code, which is [helpful](https://twitter.com/DasSurma/status/1486312385996640262) for debugging and fixing errors. + +Besides providing a call stack, WebGPU error messages are also easy to understand and actionable. The error messages typically include a description of the error and suggestions for how to fix the error. + +WebGPU also allows you to provide a custom [`label`](https://gpuweb.github.io/gpuweb/#dom-gpuobjectbase-label) for each WebGPU object. This label is then used by the browser in GPUError messages, console warnings, and browser developer tools. + +## From names to indexes + +In WebGL, many things are connected by names. For example, you can declare a uniform variable called `myUniform` in GLSL and get its location using `gl.getUniformLocation(program, 'myUniform')`. This comes handy as you get an error if you mistype the name of the uniform variable. + +On the other hand, in WebGPU, everything is entirely connected by byte offset or index (often called [location](https://gpuweb.github.io/gpuweb/wgsl/#input-output-locations)). It is your responsibility to keep the locations for the code in WGSL and JavaScript in sync. + +## Mipmap generation + +In WebGL, you can create a texture's level 0 mip and then call `gl.generateMipmap()`. WebGL will then generate all the other mip levels for you. + +In WebGPU, you must generate mipmaps yourself. There is no built-in function to do this. See the [spec discussion](https://github.com/gpuweb/gpuweb/issues/386) to learn more about the decision. You can use handy libraries such as [webgpu-utils](https://github.com/greggman/webgpu-utils) to generate mipmaps or learn how to do it [yourself](https://webgpufundamentals.org/webgpu/lessons/webgpu-importing-textures.html). + +## Storage buffers and storage textures + +Uniform buffers are supported by both WebGL and WebGPU and allow you to pass constant parameters of limited size to shaders. Storage buffers, which look a lot like uniform buffers, are only supported by WebGPU and are more powerful and flexible than uniform buffers. + +- Storage buffers data passed to shaders can be much larger than uniform buffers. While the spec says uniform buffers bindings can be up to 64KB in size (see [`maxUniformBufferBindingSize`](https://gpuweb.github.io/gpuweb/#dom-supported-limits-maxuniformbufferbindingsize)) , the maximum size of a storage buffer binding is at least 128MB in WebGPU (see [`maxStorageBufferBindingSize`](https://gpuweb.github.io/gpuweb/#dom-supported-limits-maxstoragebufferbindingsize)). + +- Storage buffers are writable, and support some atomic operations while uniform buffers are just read-only. This allows new classes of algorithms to be implemented. + +- Storage buffers bindings support runtime-sized arrays for more flexible algorithms, while uniform buffer array sizes have to be provided in the shader. + +Storage textures are only supported in WebGPU, and are to textures what storage buffers are to uniform buffers. They are more flexible than regular textures, supporting random access writes (and reads as well in the future). + +## Buffer and texture changes + +In WebGL, you can create a buffer or texture and then change its size at any time with `gl.bufferData()` and `gl.texImage2D()` respectively for instance. + +In WebGPU, buffers and textures are immutable. This means that you cannot change their size, usage, or format after they have been created. You can only change their contents. + +## Space convention differences + +In WebGL, the Z [clip space](https://developer.mozilla.org/docs/Web/API/WebGL_API/WebGL_model_view_projection#clip_space) range is from -1 to 1. In WebGPU, the Z clip space range is from 0 to 1. This means that objects with a z value of 0 are the closest to the camera, while objects with a z value of 1 are the furthest away. + +<figure> + {% Img src="image/vvhSqZboQoZZN9wBvoXq72wzGAf1/8Y8w4tqvwQlKyTjld2Si.svg", alt="Illustration of Z clip space ranges in WebGL and WebGPU.", width="800", height="414" %} + <figcaption> + Z clip space ranges in WebGL and WebGPU. + </figcaption> +</figure> + +WebGL uses the OpenGL convention, where the Y axis is up and the Z axis is towards the viewer. WebGPU uses the Metal convention, where the Y axis is down and the Z axis is out of the screen. Note that the Y axis direction is down in framebuffer coordinate, viewport coordinate and fragment/pixel coordinate. In clip space, the Y axis direction is still up as in WebGL. + +## Acknowledgements + +Thanks to Corentin Wallez, Gregg Tavares, Stephen White, Ken Russell, and Rachel Andrew for reviewing this article. + +I also recommend [WebGPUFundamentals.org](https://webgpufundamentals.org/webgpu/lessons/webgpu-from-webgl.html) for a deep dive of differences between WebGPU and WebGL. From f4be9853b6968e5f50872e14fd8822d957605a14 Mon Sep 17 00:00:00 2001 From: Sofia Emelianova <42939855+sofiayem@users.noreply.github.com> Date: Tue, 19 Sep 2023 14:35:11 +0100 Subject: [PATCH 797/982] typos (#7336) --- site/en/blog/new-in-devtools-118/index.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/site/en/blog/new-in-devtools-118/index.md b/site/en/blog/new-in-devtools-118/index.md index 54093fc31..c1b43b409 100644 --- a/site/en/blog/new-in-devtools-118/index.md +++ b/site/en/blog/new-in-devtools-118/index.md @@ -41,11 +41,11 @@ Chromium issues: [1471102](https://crbug.com/1471102), [1471103](https://crbug.c Continuing the stream of improvements in the [previous version](/blog/new-in-devtools-117/#overrides), [local overrides](/docs/devtools/overrides/) now do the following: -- In **Sources** > **Page**, when you right-click a source mapped file and select **Override content**, DevTools will show a dialog that takes to the original source instead. Content overrides of source mapped files can't be overridden. +- In **Sources** > **Page**, when you right-click a source-mapped file and select **Override content**, DevTools will show a dialog that takes you to the original source instead. Contents of source-mapped files can't be overridden. - {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/7pgnWI5CLcNBnv2H7aWT.png", alt="The dialog that takes you to the original code instead of the source mapped file.", width="800", height="458" %} + {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/7pgnWI5CLcNBnv2H7aWT.png", alt="The dialog that takes you to the original code instead of the source-mapped file.", width="800", height="458" %} -- The **Network** panel get a new **Has overrides** column and a corresponding `has-overrides:[content|headers|yes|no]` filter. To see the **Has overrides** column, [right-click](/docs/devtools/network/reference/#columns) the table header and select it. +- The **Network** panel gets a new **Has overrides** column and a corresponding `has-overrides:[content|headers|yes|no]` filter. To see the **Has overrides** column, [right-click](/docs/devtools/network/reference/#columns) the table header and select it. {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/8YIC3pobJEwjA6xCdE4I.png", alt="Filtering for 'has-overrides:yes' value in the 'Has overrides' column.", width="800", height="512" %} From 62e3ff47b1780d0c3d279f4e0240e3e8f1b2a7a3 Mon Sep 17 00:00:00 2001 From: Ewa <devnook@gmail.com> Date: Wed, 20 Sep 2023 05:05:31 +0200 Subject: [PATCH 798/982] Homepage refresh (#7302) --- gulp-tasks/sass.js | 8 + site/_data/banner.yml | 6 - site/_data/i18n/nav/side_nav.yml | 4 + site/_data/nav/rail.yml | 10 +- site/_includes/icons/devsite-logo.svg | 37 + site/_includes/icons/getInspired-active.svg | 3 + site/_includes/icons/getInspired.svg | 3 + site/_includes/layouts/base.njk | 4 - site/_includes/layouts/devsite-home.njk | 565 +++++++++++++ site/_includes/layouts/devsite.njk | 131 +++ site/_includes/partials/footer.njk | 50 +- site/_includes/partials/navigation-rail.njk | 10 +- site/_includes/partials/top-nav.njk | 17 +- site/_scss/_global.scss | 6 + site/_scss/blocks/_announcement-banner.scss | 13 +- site/_scss/blocks/_banner.scss | 9 +- site/_scss/blocks/_cookie-banner.scss | 4 +- site/_scss/blocks/_scaffold.scss | 8 +- site/_scss/blocks/_search-box.scss | 34 +- site/_scss/blocks/_side-nav.scss | 35 + site/_scss/blocks/_top-nav.scss | 196 ++++- site/_scss/globals/_vars.scss | 4 +- site/_scss/layouts/devsite-theme.scss | 754 ++++++++++++++++++ site/_scss/layouts/devsite.scss | 30 + .../static/dcc/bringing-safety-thumb.jpg | Bin 0 -> 8255 bytes site/_static/static/dcc/case-study-thumb.jpg | Bin 0 -> 10708 bytes site/_static/static/dcc/chrome-117-beta.jpg | Bin 0 -> 11959 bytes .../_static/static/dcc/chrome-at-io-thumb.jpg | Bin 0 -> 6941 bytes .../static/dcc/chrome-devtools-thumb.svg | 17 + .../static/dcc/chrome-extensions-thumb.svg | 13 + site/_static/static/dcc/chrome-twitter.svg | 11 + .../static/dcc/chrome-web-store-thumb.svg | 22 + site/_static/static/dcc/chrome-youtube.svg | 12 + site/_static/static/dcc/get-inspired-icon.svg | 11 + site/_static/static/dcc/hero.webp | Bin 0 -> 106046 bytes site/_static/static/dcc/new-in-chrome-116.jpg | Bin 0 -> 11570 bytes .../static/dcc/new-in-devtools-118-thumb.webp | Bin 0 -> 33714 bytes site/_static/static/dcc/open-icon.webp | Bin 0 -> 33334 bytes site/_static/static/dcc/powerful-icon.webp | Bin 0 -> 38934 bytes .../_static/static/dcc/productivity-icon.webp | Bin 0 -> 34092 bytes site/_static/static/dcc/solutions-icon.webp | Bin 0 -> 27966 bytes .../static/dcc/web-on-android-thumb.svg | 15 + site/en/index.md | 4 +- 43 files changed, 1981 insertions(+), 65 deletions(-) delete mode 100644 site/_data/banner.yml create mode 100644 site/_includes/icons/devsite-logo.svg create mode 100644 site/_includes/icons/getInspired-active.svg create mode 100644 site/_includes/icons/getInspired.svg create mode 100644 site/_includes/layouts/devsite-home.njk create mode 100644 site/_includes/layouts/devsite.njk create mode 100644 site/_scss/layouts/devsite-theme.scss create mode 100644 site/_scss/layouts/devsite.scss create mode 100644 site/_static/static/dcc/bringing-safety-thumb.jpg create mode 100644 site/_static/static/dcc/case-study-thumb.jpg create mode 100644 site/_static/static/dcc/chrome-117-beta.jpg create mode 100644 site/_static/static/dcc/chrome-at-io-thumb.jpg create mode 100644 site/_static/static/dcc/chrome-devtools-thumb.svg create mode 100644 site/_static/static/dcc/chrome-extensions-thumb.svg create mode 100644 site/_static/static/dcc/chrome-twitter.svg create mode 100644 site/_static/static/dcc/chrome-web-store-thumb.svg create mode 100644 site/_static/static/dcc/chrome-youtube.svg create mode 100644 site/_static/static/dcc/get-inspired-icon.svg create mode 100644 site/_static/static/dcc/hero.webp create mode 100644 site/_static/static/dcc/new-in-chrome-116.jpg create mode 100644 site/_static/static/dcc/new-in-devtools-118-thumb.webp create mode 100644 site/_static/static/dcc/open-icon.webp create mode 100644 site/_static/static/dcc/powerful-icon.webp create mode 100644 site/_static/static/dcc/productivity-icon.webp create mode 100644 site/_static/static/dcc/solutions-icon.webp create mode 100644 site/_static/static/dcc/web-on-android-thumb.svg diff --git a/gulp-tasks/sass.js b/gulp-tasks/sass.js index 5ea109b71..c2c32108b 100644 --- a/gulp-tasks/sass.js +++ b/gulp-tasks/sass.js @@ -23,6 +23,14 @@ const entrypoints = [ src: './site/_scss/layouts/home.scss', dest: './dist/css/home.css', }, + { + src: './site/_scss/layouts/devsite.scss', + dest: './dist/css/devsite.css', + }, + { + src: './site/_scss/layouts/devsite-theme.scss', + dest: './dist/css/devsite-theme.css', + }, { src: './site/_scss/layouts/fugu-showcase.scss', dest: './dist/css/fugu-showcase.css', diff --git a/site/_data/banner.yml b/site/_data/banner.yml deleted file mode 100644 index 8eb9f4039..000000000 --- a/site/_data/banner.yml +++ /dev/null @@ -1,6 +0,0 @@ -type: info -text: Thanks for tuning in to Google I/O. Watch the Chrome content on-demand. -actions: - - text: Watch now. - href: https://io.google/2023/?utm_source=chrome&utm_medium=embedded_marketing&utm_campaign=hpp_ondemand_banner&utm_content= - - text: Dismiss \ No newline at end of file diff --git a/site/_data/i18n/nav/side_nav.yml b/site/_data/i18n/nav/side_nav.yml index 4eabdd9b5..b3ac9b94c 100644 --- a/site/_data/i18n/nav/side_nav.yml +++ b/site/_data/i18n/nav/side_nav.yml @@ -20,3 +20,7 @@ releases: articles: en: 'Articles' es: 'Artículos' + +getInspired: + en: 'Get Inspired' + es: 'Inspírate' diff --git a/site/_data/nav/rail.yml b/site/_data/nav/rail.yml index aa2077595..c70a40021 100644 --- a/site/_data/nav/rail.yml +++ b/site/_data/nav/rail.yml @@ -1,6 +1,6 @@ -home: - text: i18n.nav.side_nav.home - url: / +getInspired: + text: i18n.nav.side_nav.getInspired + url: /tags/case-study/ docs: text: i18n.nav.side_nav.docs @@ -13,7 +13,3 @@ blog: articles: text: i18n.nav.side_nav.articles url: /articles/ - -# releases: -# text: i18n.nav.side_nav.releases -# url: /releases/ diff --git a/site/_includes/icons/devsite-logo.svg b/site/_includes/icons/devsite-logo.svg new file mode 100644 index 000000000..4ed96bccd --- /dev/null +++ b/site/_includes/icons/devsite-logo.svg @@ -0,0 +1,37 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="200" height="36" viewBox="0 0 184 26" fill="none"> + <g clip-path="url(#clip0_399_8764)"> + <path d="M36.0427 16.8959C35.2246 16.4198 34.5814 15.7644 34.1155 14.9319C33.6496 14.0994 33.4155 13.1726 33.4155 12.1493C33.4155 11.1259 33.6496 10.1991 34.1155 9.36665C34.5814 8.53416 35.2246 7.87874 36.0427 7.40271C36.8609 6.92667 37.77 6.6875 38.7723 6.6875C39.5427 6.6875 40.2472 6.83698 40.8881 7.13364C41.529 7.4303 42.0836 7.85115 42.5563 8.39617L41.6768 9.25856C41.2813 8.78252 40.8518 8.43067 40.3836 8.2076C39.9177 7.98453 39.3813 7.87184 38.7745 7.87184C38.0245 7.87184 37.3359 8.04892 36.7109 8.40537C36.0859 8.76183 35.5882 9.26316 35.2177 9.90937C34.8473 10.5579 34.6609 11.3053 34.6609 12.1516C34.6609 12.9979 34.8473 13.7453 35.2177 14.3938C35.5882 15.0423 36.0859 15.5436 36.7109 15.8978C37.3359 16.2542 38.0245 16.4313 38.7745 16.4313C40.0245 16.4313 41.0881 15.9093 41.9654 14.8675L42.8608 15.7437C42.379 16.3186 41.7881 16.774 41.0859 17.1097C40.3836 17.4455 39.6131 17.6134 38.7768 17.6134C37.7745 17.6134 36.8655 17.3742 36.0473 16.8982L36.0427 16.8959Z" fill="#606367"/> + <path d="M44.229 6.91699H45.4563V9.99859L45.3994 11.022H45.4563C45.6585 10.6425 45.979 10.3251 46.4153 10.0722C46.854 9.81921 47.3312 9.69273 47.8517 9.69273C48.7471 9.69273 49.4289 9.95719 49.9017 10.4884C50.3721 11.0197 50.6085 11.7234 50.6085 12.5995V17.376H49.3812V12.7881C49.3812 12.1166 49.213 11.6199 48.8767 11.2979C48.5403 10.976 48.1017 10.815 47.5631 10.815C47.179 10.815 46.8244 10.9323 46.5017 11.1645C46.179 11.3968 45.9244 11.7004 45.7358 12.0706C45.5472 12.4409 45.454 12.8249 45.454 13.2251V17.3737H44.2267V6.91699H44.229Z" fill="#606367"/> + <path d="M52.3698 9.92745H53.5403V11.1256H53.5971C53.7403 10.7163 54.0198 10.3782 54.4334 10.1114C54.8471 9.84467 55.2811 9.70898 55.7334 9.70898C56.0698 9.70898 56.3584 9.75728 56.5993 9.85616V11.1992C56.2902 11.0428 55.9448 10.9646 55.5607 10.9646C55.2039 10.9646 54.8766 11.0658 54.5789 11.2705C54.2812 11.4752 54.0425 11.7511 53.8652 12.0961C53.688 12.441 53.5971 12.8136 53.5971 13.2137V17.3762H52.3698V9.92516V9.92745Z" fill="#606367"/> + <path d="M58.7947 17.0842C58.2175 16.7347 57.7675 16.2563 57.4447 15.6538C57.122 15.049 56.9607 14.3821 56.9607 13.6531C56.9607 12.9241 57.122 12.2549 57.4447 11.6524C57.7675 11.0475 58.2175 10.5715 58.7947 10.2219C59.372 9.87239 60.022 9.69531 60.7447 9.69531C61.4674 9.69531 62.1151 9.87009 62.6924 10.2219C63.2697 10.5715 63.7197 11.0498 64.0424 11.6524C64.3651 12.2572 64.5265 12.9241 64.5265 13.6531C64.5265 14.3821 64.3651 15.0513 64.0424 15.6538C63.7197 16.2586 63.2697 16.7347 62.6924 17.0842C62.1151 17.4338 61.4652 17.6109 60.7447 17.6109C60.0243 17.6109 59.3743 17.4361 58.7947 17.0842ZM62.0061 16.1414C62.3947 15.9137 62.7083 15.5848 62.9447 15.1548C63.181 14.727 63.2992 14.2257 63.2992 13.6508C63.2992 13.0759 63.181 12.5745 62.9447 12.1468C62.7083 11.719 62.397 11.3902 62.0061 11.1602C61.6151 10.9325 61.1947 10.8176 60.7424 10.8176C60.2902 10.8176 59.8674 10.9325 59.472 11.1602C59.0765 11.3902 58.7629 11.719 58.5265 12.1468C58.2902 12.5745 58.172 13.0759 58.172 13.6508C58.172 14.2257 58.2902 14.727 58.5265 15.1548C58.7629 15.5825 59.0765 15.9114 59.472 16.1414C59.8674 16.3713 60.2902 16.484 60.7424 16.484C61.1947 16.484 61.6151 16.369 62.0061 16.1414Z" fill="#606367"/> + <path d="M65.8105 9.92793H66.981V11.0226H67.0378C67.2492 10.6431 67.5673 10.3258 67.9901 10.0728C68.4128 9.81984 68.8605 9.69336 69.3332 9.69336C69.8719 9.69336 70.3423 9.82444 70.74 10.0866C71.14 10.3488 71.4264 10.7006 71.5991 11.1376C71.8582 10.6983 72.2036 10.3488 72.6309 10.0866C73.0582 9.82444 73.5559 9.69336 74.1241 9.69336C74.9718 9.69336 75.6082 9.95322 76.0377 10.4753C76.465 10.9973 76.6809 11.7056 76.6809 12.6002V17.3766H75.4672V12.7888C75.4672 12.0965 75.3263 11.5952 75.0491 11.2847C74.7695 10.9743 74.3559 10.8179 73.8082 10.8179C73.4423 10.8179 73.1105 10.926 72.8127 11.1399C72.515 11.3537 72.2809 11.6412 72.1127 12.0023C71.9446 12.3633 71.8605 12.752 71.8605 13.1705V17.3766H70.6332V12.8048C70.6332 12.1034 70.4946 11.5975 70.215 11.2847C69.9355 10.9743 69.5264 10.8179 68.9878 10.8179C68.6219 10.8179 68.2901 10.9283 67.9923 11.1468C67.6946 11.3652 67.4605 11.6573 67.2923 12.023C67.1242 12.3886 67.0401 12.7796 67.0401 13.1981V17.3766H65.8128V9.92563L65.8105 9.92793Z" fill="#606367"/> + <path d="M79.8286 17.1007C79.2695 16.7603 78.8354 16.2889 78.5218 15.691C78.2081 15.093 78.0536 14.4169 78.0536 13.6672C78.0536 12.9175 78.2013 12.2851 78.4945 11.6803C78.7877 11.0755 79.2036 10.5948 79.7422 10.2338C80.2808 9.87274 80.9058 9.69336 81.6195 9.69336C82.3331 9.69336 82.9672 9.85664 83.4967 10.1832C84.0262 10.5098 84.4331 10.9605 84.7171 11.5354C85.0012 12.1103 85.1421 12.7681 85.1421 13.5086C85.1421 13.6534 85.1285 13.7822 85.099 13.888H79.2808C79.3104 14.4537 79.4445 14.9298 79.6854 15.3184C79.9263 15.7071 80.2308 15.9991 80.6013 16.1946C80.9717 16.3901 81.3581 16.4867 81.7626 16.4867C82.7058 16.4867 83.4331 16.0382 83.9422 15.1436L84.9808 15.6542C84.6626 16.259 84.2331 16.735 83.6899 17.0846C83.1467 17.4341 82.4899 17.6112 81.7195 17.6112C81.0172 17.6112 80.3854 17.441 79.8286 17.1007ZM83.8422 12.8646C83.8217 12.5542 83.7353 12.2414 83.5831 11.9287C83.4285 11.6182 83.1853 11.3537 82.8535 11.1399C82.5217 10.926 82.1058 10.8179 81.6058 10.8179C81.0286 10.8179 80.5399 11.0065 80.1399 11.3813C79.7399 11.7562 79.4786 12.2506 79.3536 12.8646H83.8422Z" fill="#606367"/> + <path d="M90.483 11.0519H89.1262V9.92739H90.483V9.1248C90.483 8.65796 90.5898 8.24861 90.8012 7.89676C91.0125 7.54721 91.2966 7.27584 91.6534 7.08497C92.0102 6.89409 92.4034 6.7998 92.8375 6.7998C93.2716 6.7998 93.6125 6.8573 93.9193 6.97458V8.18652C93.7466 8.11753 93.5829 8.06234 93.4284 8.01864C93.2738 7.97495 93.092 7.95195 92.8807 7.95195C92.5625 7.95195 92.2898 8.06694 92.058 8.29461C91.8261 8.52458 91.7125 8.84194 91.7125 9.25128V9.92279H93.6034V11.0473H91.7125V17.3715H90.4853V11.0473L90.483 11.0519Z" fill="#606367"/> + <path d="M96.0988 17.0842C95.5215 16.7347 95.0715 16.2563 94.7488 15.6538C94.4261 15.049 94.2647 14.3821 94.2647 13.6531C94.2647 12.9241 94.4261 12.2549 94.7488 11.6524C95.0715 11.0475 95.5215 10.5715 96.0988 10.2219C96.6761 9.87239 97.3261 9.69531 98.0488 9.69531C98.7715 9.69531 99.4192 9.87009 99.9965 10.2219C100.574 10.5715 101.024 11.0498 101.346 11.6524C101.669 12.2572 101.831 12.9241 101.831 13.6531C101.831 14.3821 101.669 15.0513 101.346 15.6538C101.024 16.2586 100.574 16.7347 99.9965 17.0842C99.4192 17.4338 98.7692 17.6109 98.0488 17.6109C97.3283 17.6109 96.6783 17.4361 96.0988 17.0842ZM99.3101 16.1414C99.6988 15.9137 100.012 15.5848 100.249 15.1548C100.485 14.727 100.603 14.2257 100.603 13.6508C100.603 13.0759 100.485 12.5745 100.249 12.1468C100.012 11.719 99.701 11.3902 99.3101 11.1602C98.9192 10.9325 98.4988 10.8176 98.0465 10.8176C97.5942 10.8176 97.1715 10.9325 96.7761 11.1602C96.3806 11.3902 96.067 11.719 95.8306 12.1468C95.5943 12.5745 95.4761 13.0759 95.4761 13.6508C95.4761 14.2257 95.5943 14.727 95.8306 15.1548C96.067 15.5825 96.3806 15.9114 96.7761 16.1414C97.1715 16.3713 97.5942 16.484 98.0465 16.484C98.4988 16.484 98.9192 16.369 99.3101 16.1414Z" fill="#606367"/> + <path d="M103.115 9.92745H104.285V11.1256H104.342C104.485 10.7163 104.765 10.3782 105.178 10.1114C105.592 9.84467 106.026 9.70898 106.478 9.70898C106.815 9.70898 107.103 9.75728 107.344 9.85616V11.1992C107.035 11.0428 106.69 10.9646 106.305 10.9646C105.949 10.9646 105.621 11.0658 105.324 11.2705C105.026 11.4752 104.787 11.7511 104.61 12.0961C104.433 12.441 104.342 12.8136 104.342 13.2137V17.3762H103.115V9.92516V9.92745Z" fill="#606367"/> + <path d="M112.124 6.91699H115.242C116.301 6.91699 117.224 7.13776 118.014 7.5816C118.803 8.02545 119.41 8.64176 119.833 9.43056C120.255 10.2194 120.467 11.1254 120.467 12.1465C120.467 13.1676 120.255 14.0736 119.833 14.8624C119.41 15.6512 118.803 16.2676 118.014 16.7114C117.226 17.1552 116.301 17.376 115.242 17.376H112.124V6.91699ZM115.242 16.194C116.464 16.194 117.433 15.8375 118.151 15.1269C118.867 14.4163 119.226 13.4228 119.226 12.1465C119.226 10.8702 118.867 9.8767 118.151 9.1661C117.433 8.45549 116.464 8.09904 115.242 8.09904H113.337V16.1917H115.242V16.194Z" fill="#606367"/> + <path d="M123.196 17.1007C122.637 16.7603 122.203 16.2889 121.889 15.691C121.576 15.093 121.421 14.4169 121.421 13.6672C121.421 12.9175 121.569 12.2851 121.862 11.6803C122.155 11.0755 122.571 10.5948 123.11 10.2338C123.648 9.87274 124.273 9.69336 124.987 9.69336C125.701 9.69336 126.335 9.85664 126.864 10.1832C127.394 10.5098 127.801 10.9605 128.085 11.5354C128.369 12.1103 128.51 12.7681 128.51 13.5086C128.51 13.6534 128.496 13.7822 128.467 13.888H122.648C122.678 14.4537 122.812 14.9298 123.053 15.3184C123.294 15.7071 123.598 15.9991 123.969 16.1946C124.339 16.3901 124.726 16.4867 125.13 16.4867C126.073 16.4867 126.801 16.0382 127.31 15.1436L128.348 15.6542C128.03 16.259 127.601 16.735 127.058 17.0846C126.514 17.4341 125.858 17.6112 125.087 17.6112C124.385 17.6112 123.753 17.441 123.196 17.1007ZM127.21 12.8646C127.189 12.5542 127.103 12.2414 126.951 11.9287C126.796 11.6182 126.553 11.3537 126.221 11.1399C125.889 10.926 125.473 10.8179 124.973 10.8179C124.396 10.8179 123.908 11.0065 123.508 11.3813C123.108 11.7562 122.846 12.2506 122.721 12.8646H127.21Z" fill="#606367"/> + <path d="M128.985 9.92773H130.298L132.58 15.9161H132.61L134.919 9.92773H136.203L133.201 17.3788H131.96L128.985 9.92773Z" fill="#606367"/> + <path d="M138.382 17.1007C137.823 16.7603 137.389 16.2889 137.076 15.691C136.762 15.093 136.607 14.4169 136.607 13.6672C136.607 12.9175 136.755 12.2851 137.048 11.6803C137.342 11.0755 137.757 10.5948 138.296 10.2338C138.835 9.87274 139.46 9.69336 140.173 9.69336C140.887 9.69336 141.521 9.85664 142.051 10.1832C142.58 10.5098 142.987 10.9605 143.271 11.5354C143.555 12.1103 143.696 12.7681 143.696 13.5086C143.696 13.6534 143.682 13.7822 143.653 13.888H137.835C137.864 14.4537 137.998 14.9298 138.239 15.3184C138.48 15.7071 138.785 15.9991 139.155 16.1946C139.526 16.3901 139.912 16.4867 140.316 16.4867C141.26 16.4867 141.987 16.0382 142.496 15.1436L143.535 15.6542C143.216 16.259 142.787 16.735 142.244 17.0846C141.701 17.4341 141.044 17.6112 140.273 17.6112C139.571 17.6112 138.939 17.441 138.382 17.1007ZM142.396 12.8646C142.376 12.5542 142.289 12.2414 142.137 11.9287C141.982 11.6182 141.739 11.3537 141.407 11.1399C141.076 10.926 140.66 10.8179 140.16 10.8179C139.582 10.8179 139.094 11.0065 138.694 11.3813C138.294 11.7562 138.032 12.2506 137.907 12.8646H142.396Z" fill="#606367"/> + <path d="M145.123 6.91699H146.35V17.376H145.123V6.91699Z" fill="#606367"/> + <path d="M149.541 17.0842C148.964 16.7347 148.514 16.2563 148.191 15.6538C147.869 15.049 147.707 14.3821 147.707 13.6531C147.707 12.9241 147.869 12.2549 148.191 11.6524C148.514 11.0475 148.964 10.5715 149.541 10.2219C150.119 9.87239 150.769 9.69531 151.491 9.69531C152.214 9.69531 152.862 9.87009 153.439 10.2219C154.016 10.5715 154.466 11.0498 154.789 11.6524C155.112 12.2572 155.273 12.9241 155.273 13.6531C155.273 14.3821 155.112 15.0513 154.789 15.6538C154.466 16.2586 154.016 16.7347 153.439 17.0842C152.862 17.4338 152.212 17.6109 151.491 17.6109C150.771 17.6109 150.121 17.4361 149.541 17.0842ZM152.753 16.1414C153.141 15.9137 153.455 15.5848 153.691 15.1548C153.928 14.727 154.046 14.2257 154.046 13.6508C154.046 13.0759 153.928 12.5745 153.691 12.1468C153.455 11.719 153.144 11.3902 152.753 11.1602C152.362 10.9325 151.941 10.8176 151.489 10.8176C151.037 10.8176 150.614 10.9325 150.219 11.1602C149.823 11.3902 149.51 11.719 149.273 12.1468C149.037 12.5745 148.919 13.0759 148.919 13.6508C148.919 14.2257 149.037 14.727 149.273 15.1548C149.51 15.5825 149.823 15.9114 150.219 16.1414C150.614 16.3713 151.037 16.484 151.489 16.484C151.941 16.484 152.362 16.369 152.753 16.1414Z" fill="#606367"/> + <path d="M156.571 9.92758H157.741V11.0383H157.798C158.019 10.6589 158.355 10.3392 158.8 10.0817C159.248 9.8241 159.75 9.69531 160.309 9.69531C160.964 9.69531 161.559 9.86549 162.1 10.2058C162.639 10.5462 163.062 11.0199 163.371 11.6225C163.678 12.2273 163.832 12.9034 163.832 13.6531C163.832 14.4028 163.678 15.0927 163.371 15.6906C163.062 16.2885 162.639 16.76 162.1 17.1003C161.562 17.4407 160.964 17.6109 160.309 17.6109C159.75 17.6109 159.248 17.4821 158.8 17.2245C158.353 16.967 158.019 16.6519 157.798 16.2816H157.741L157.798 17.305V20.5338H156.571V9.92758ZM161.364 16.1368C161.739 15.9022 162.039 15.5687 162.266 15.1364C162.491 14.7041 162.605 14.2096 162.605 13.6531C162.605 13.0966 162.491 12.6044 162.266 12.1698C162.039 11.7374 161.739 11.404 161.364 11.1694C160.989 10.9348 160.589 10.8199 160.166 10.8199C159.743 10.8199 159.343 10.9371 158.968 11.1694C158.594 11.4017 158.296 11.7351 158.073 12.1629C157.853 12.5906 157.741 13.0874 157.741 13.6531C157.741 14.2188 157.853 14.7155 158.073 15.1433C158.294 15.571 158.594 15.9022 158.968 16.1368C159.343 16.3713 159.743 16.4863 160.166 16.4863C160.589 16.4863 160.989 16.369 161.364 16.1368Z" fill="#606367"/> + <path d="M166.648 17.1007C166.089 16.7603 165.655 16.2889 165.341 15.691C165.028 15.093 164.873 14.4169 164.873 13.6672C164.873 12.9175 165.021 12.2851 165.314 11.6803C165.607 11.0755 166.023 10.5948 166.562 10.2338C167.1 9.87274 167.725 9.69336 168.439 9.69336C169.152 9.69336 169.787 9.85664 170.316 10.1832C170.846 10.5098 171.252 10.9605 171.537 11.5354C171.821 12.1103 171.962 12.7681 171.962 13.5086C171.962 13.6534 171.948 13.7822 171.918 13.888H166.1C166.13 14.4537 166.264 14.9298 166.505 15.3184C166.746 15.7071 167.05 15.9991 167.421 16.1946C167.791 16.3901 168.177 16.4867 168.582 16.4867C169.525 16.4867 170.252 16.0382 170.762 15.1436L171.8 15.6542C171.482 16.259 171.052 16.735 170.509 17.0846C169.966 17.4341 169.309 17.6112 168.539 17.6112C167.837 17.6112 167.205 17.441 166.648 17.1007ZM170.662 12.8646C170.641 12.5542 170.555 12.2414 170.402 11.9287C170.248 11.6182 170.005 11.3537 169.673 11.1399C169.341 10.926 168.925 10.8179 168.425 10.8179C167.848 10.8179 167.359 11.0065 166.959 11.3813C166.559 11.7562 166.298 12.2506 166.173 12.8646H170.662Z" fill="#606367"/> + <path d="M173.389 9.92745H174.559V11.1256H174.616C174.759 10.7163 175.039 10.3782 175.452 10.1114C175.866 9.84467 176.3 9.70898 176.752 9.70898C177.089 9.70898 177.377 9.75728 177.618 9.85616V11.1992C177.309 11.0428 176.964 10.9646 176.58 10.9646C176.223 10.9646 175.896 11.0658 175.598 11.2705C175.3 11.4752 175.061 11.7511 174.884 12.0961C174.707 12.441 174.616 12.8136 174.616 13.2137V17.3762H173.389V9.92516V9.92745Z" fill="#606367"/> + <path d="M179.107 17.0501C178.577 16.6752 178.202 16.1946 177.982 15.6105L179.08 15.1137C179.261 15.5622 179.534 15.9071 179.895 16.1509C180.257 16.3947 180.652 16.5166 181.086 16.5166C181.548 16.5166 181.943 16.4223 182.27 16.2314C182.598 16.0405 182.761 15.7715 182.761 15.4196C182.761 15.1091 182.632 14.8562 182.37 14.6676C182.111 14.4767 181.702 14.3157 181.143 14.1778L180.248 13.9432C179.661 13.7983 179.18 13.5499 178.805 13.1981C178.43 12.8485 178.241 12.3955 178.241 11.839C178.241 11.4112 178.368 11.0341 178.623 10.7075C178.877 10.381 179.218 10.1303 179.641 9.95552C180.064 9.78075 180.52 9.69336 181.011 9.69336C181.657 9.69336 182.232 9.83364 182.736 10.1165C183.241 10.3994 183.6 10.7926 183.811 11.3008L182.743 11.7976C182.416 11.1353 181.834 10.8041 180.995 10.8041C180.591 10.8041 180.239 10.8984 179.934 11.0893C179.632 11.2801 179.48 11.5193 179.48 11.8114C179.48 12.085 179.586 12.3058 179.798 12.476C180.009 12.6462 180.327 12.7842 180.75 12.8922L181.818 13.1705C182.541 13.3568 183.084 13.6304 183.45 13.9961C183.816 14.3617 183.998 14.8079 183.998 15.3322C183.998 15.7899 183.868 16.1923 183.609 16.5373C183.35 16.8822 182.998 17.149 182.555 17.333C182.111 17.5169 181.62 17.6112 181.082 17.6112C180.293 17.6112 179.634 17.4226 179.105 17.0478L179.107 17.0501Z" fill="#606367"/> + <path d="M23.0475 6.25082C19.6361 0.273913 12.0817 -1.77512 6.17494 1.67673C4.29769 2.77368 2.73862 4.35127 1.65454 6.25082L2.39544 19.75L23.0475 6.25082Z" fill="#E84436"/> + <path d="M7.00446 15.6245L1.6568 6.25098C-1.75452 12.2302 0.270453 19.8744 6.1772 23.3239C8.05445 24.4209 10.184 24.9981 12.3521 24.9981L24.4565 12.4993L7.00219 15.6245H7.00446Z" fill="#34A653"/> + <path d="M17.7021 15.6245L12.3544 24.9981C19.177 24.9981 24.7042 19.3983 24.7042 12.497C24.7042 10.303 24.1338 8.15053 23.0497 6.25098H12.3544L17.7021 15.6245Z" fill="url(#paint0_linear_399_8764)"/> + <path d="M12.3544 18.7495C15.7657 18.7495 18.5293 15.9507 18.5293 12.5012C18.5293 9.05166 15.7634 6.25293 12.3544 6.25293C8.94535 6.25293 6.17947 9.05166 6.17947 12.5012C6.17947 15.9507 8.94535 18.7495 12.3544 18.7495Z" fill="white"/> + <path d="M12.3544 17.45C15.0566 17.45 17.2452 15.2354 17.2475 12.5011C17.2475 9.76671 15.0589 7.5521 12.3567 7.5498C9.65443 7.5498 7.46582 9.76671 7.46582 12.5011C7.46582 15.2331 9.6567 17.45 12.3567 17.45H12.3544Z" fill="#4383F2"/> + </g> + <defs> + <linearGradient id="paint0_linear_399_8764" x1="10.5567" y1="25.0027" x2="21.4447" y2="6.39923" gradientUnits="userSpaceOnUse"> + <stop stop-color="#FAC735"/> + <stop offset="1" stop-color="#F8BA07"/> + </linearGradient> + <clipPath id="clip0_399_8764"> + <rect width="184" height="25" fill="white"/> + </clipPath> + </defs> +</svg> \ No newline at end of file diff --git a/site/_includes/icons/getInspired-active.svg b/site/_includes/icons/getInspired-active.svg new file mode 100644 index 000000000..a41c29e3b --- /dev/null +++ b/site/_includes/icons/getInspired-active.svg @@ -0,0 +1,3 @@ +<svg width="24" height="23" viewBox="0 0 22 23" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path fill-rule="evenodd" clip-rule="evenodd" d="M1.67939 1.6707V9.8293V9.74576V20.6053V1.6707ZM4.45038 12.8087H9.6285C9.83562 12.4913 10.0595 12.1961 10.3003 11.9177C10.541 11.6392 10.8153 11.3775 11.112 11.138H4.45038V12.8087ZM4.45038 17.5424H8.81679C8.76081 17.2639 8.71603 16.9855 8.68804 16.707C8.66005 16.4286 8.65445 16.1501 8.67125 15.8717H4.44478V17.5424H4.45038ZM1.67939 22.276C1.23155 22.276 0.839695 22.109 0.503817 21.7748C0.167939 21.4407 0 21.0508 0 20.6053V1.6707C0 1.22518 0.167939 0.835351 0.503817 0.501211C0.839695 0.16707 1.23155 0 1.67939 0H11.7837L17.9135 6.09806V10.3862C17.6504 10.2581 17.3817 10.1467 17.1018 10.0521C16.8219 9.95739 16.5308 9.88499 16.2341 9.8293V6.84988H10.944V1.6707H1.67939V20.6053H10.4962C10.8712 20.9952 11.2855 21.3293 11.7445 21.6077C12.2036 21.8862 12.7018 22.109 13.2448 22.276H1.67939ZM15.1145 19.2131C15.9934 19.2131 16.7267 18.9179 17.3145 18.3332C17.9023 17.7484 18.199 17.0189 18.199 16.1446C18.199 15.2702 17.9023 14.5407 17.3145 13.9559C16.7267 13.3712 15.9934 13.076 15.1145 13.076C14.2356 13.076 13.5023 13.3712 12.9145 13.9559C12.3267 14.5407 12.03 15.2702 12.03 16.1446C12.03 17.0189 12.3267 17.7484 12.9145 18.3332C13.5023 18.9179 14.2356 19.2131 15.1145 19.2131ZM20.8244 23L17.8239 20.0206C17.4377 20.2823 17.0122 20.4884 16.5532 20.6499C16.0941 20.8114 15.6127 20.8893 15.1089 20.8893C13.7878 20.8893 12.6626 20.4271 11.7389 19.5082C10.8153 18.5893 10.3506 17.47 10.3506 16.1501C10.3506 14.8303 10.8153 13.7165 11.7389 12.7976C12.6626 11.8787 13.7878 11.4165 15.1145 11.4165C16.4412 11.4165 17.5608 11.8787 18.4845 12.7976C19.4081 13.7165 19.8728 14.8358 19.8728 16.1501C19.8728 16.6513 19.7944 17.1303 19.6321 17.5869C19.4753 18.0436 19.2626 18.4613 18.9995 18.8511L21.9944 21.8361L20.8188 23.0056L20.8244 23Z" /> +</svg> diff --git a/site/_includes/icons/getInspired.svg b/site/_includes/icons/getInspired.svg new file mode 100644 index 000000000..a41c29e3b --- /dev/null +++ b/site/_includes/icons/getInspired.svg @@ -0,0 +1,3 @@ +<svg width="24" height="23" viewBox="0 0 22 23" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path fill-rule="evenodd" clip-rule="evenodd" d="M1.67939 1.6707V9.8293V9.74576V20.6053V1.6707ZM4.45038 12.8087H9.6285C9.83562 12.4913 10.0595 12.1961 10.3003 11.9177C10.541 11.6392 10.8153 11.3775 11.112 11.138H4.45038V12.8087ZM4.45038 17.5424H8.81679C8.76081 17.2639 8.71603 16.9855 8.68804 16.707C8.66005 16.4286 8.65445 16.1501 8.67125 15.8717H4.44478V17.5424H4.45038ZM1.67939 22.276C1.23155 22.276 0.839695 22.109 0.503817 21.7748C0.167939 21.4407 0 21.0508 0 20.6053V1.6707C0 1.22518 0.167939 0.835351 0.503817 0.501211C0.839695 0.16707 1.23155 0 1.67939 0H11.7837L17.9135 6.09806V10.3862C17.6504 10.2581 17.3817 10.1467 17.1018 10.0521C16.8219 9.95739 16.5308 9.88499 16.2341 9.8293V6.84988H10.944V1.6707H1.67939V20.6053H10.4962C10.8712 20.9952 11.2855 21.3293 11.7445 21.6077C12.2036 21.8862 12.7018 22.109 13.2448 22.276H1.67939ZM15.1145 19.2131C15.9934 19.2131 16.7267 18.9179 17.3145 18.3332C17.9023 17.7484 18.199 17.0189 18.199 16.1446C18.199 15.2702 17.9023 14.5407 17.3145 13.9559C16.7267 13.3712 15.9934 13.076 15.1145 13.076C14.2356 13.076 13.5023 13.3712 12.9145 13.9559C12.3267 14.5407 12.03 15.2702 12.03 16.1446C12.03 17.0189 12.3267 17.7484 12.9145 18.3332C13.5023 18.9179 14.2356 19.2131 15.1145 19.2131ZM20.8244 23L17.8239 20.0206C17.4377 20.2823 17.0122 20.4884 16.5532 20.6499C16.0941 20.8114 15.6127 20.8893 15.1089 20.8893C13.7878 20.8893 12.6626 20.4271 11.7389 19.5082C10.8153 18.5893 10.3506 17.47 10.3506 16.1501C10.3506 14.8303 10.8153 13.7165 11.7389 12.7976C12.6626 11.8787 13.7878 11.4165 15.1145 11.4165C16.4412 11.4165 17.5608 11.8787 18.4845 12.7976C19.4081 13.7165 19.8728 14.8358 19.8728 16.1501C19.8728 16.6513 19.7944 17.1303 19.6321 17.5869C19.4753 18.0436 19.2626 18.4613 18.9995 18.8511L21.9944 21.8361L20.8188 23.0056L20.8244 23Z" /> +</svg> diff --git a/site/_includes/layouts/base.njk b/site/_includes/layouts/base.njk index 3e1c9daf1..5d0437554 100644 --- a/site/_includes/layouts/base.njk +++ b/site/_includes/layouts/base.njk @@ -98,10 +98,6 @@ {% include 'partials/top-nav.njk' %} {% endblock %} - {% block navigation_rail %} - {% include 'partials/navigation-rail.njk' %} - {% endblock %} - {% block sidebar %} {% include 'partials/side-nav.njk' %} {% endblock %} diff --git a/site/_includes/layouts/devsite-home.njk b/site/_includes/layouts/devsite-home.njk new file mode 100644 index 000000000..7e8620dab --- /dev/null +++ b/site/_includes/layouts/devsite-home.njk @@ -0,0 +1,565 @@ +{% extends "layouts/devsite.njk" %} +{% block devsite_main %} +<main role="main" class="devsite-content"> + {% include 'partials/banner.njk' %} + <devsite-content> + <article class="devsite-article"> + <div class="devsite-article-body clearfix + "> + <section class="devsite-landing-row devsite-landing-row-1-up devsite-landing-row-100 dcc-hero" header-position="top"> + <div class="devsite-landing-row-inner"> + <div class="devsite-landing-row-group"> + <div class="devsite-landing-row-item" description-position="bottom"> + <div class="devsite-landing-row-item-media + "> + <figure class="devsite-landing-row-item-image"> + <img + alt="A cartoon-style rendering of a diverse set of people building a website on a whiteboard" + src="/static/dcc/hero.webp" + loading="lazy" + width="1160" + height="608" + fetchpriority="high"> + </figure> + </div> + <div class="devsite-landing-row-item-description"> + <div class="devsite-landing-row-item-body"> + <h3 id="a-powerful-web-spanmade-easierspan" data-text="A Powerful Web. Made Easier." class="hide-from-toc no-link"> + A Powerful Web. + <span>Made Easier.</span> + </h3> + <div class="devsite-landing-row-item-description-content"> + Helping you build, grow and innovate on the web. + </div> + <div class="devsite-landing-row-item-buttons"> + <a href="/#features-tools-and-programs-to-make-developers-successful-on-the-web" class="button + " aria-label="Get started with documentation for web features, tools and programs.">Get Started</a> + </div> + </div> + </div> + </div> + </div> + </div> + </section> + <section + class="devsite-landing-row devsite-landing-row-2-up devsite-landing-row-cards devsite-landing-row-no-image-background + dcc-featured" + header-position="top"> + <div class="devsite-landing-row-inner"> + <div class="devsite-landing-row-group"> + <div class="devsite-landing-row-item dcc-blog-card" description-position="left"> + <div class="devsite-landing-row-item-media + "> + <figure class="devsite-landing-row-item-image"> + <a href="/blog/chrome-at-io23"> + <img alt="" src="/static/dcc/chrome-at-io-thumb.jpg" loading="lazy" width="534" height="685"> + </a> + </figure> + </div> + <div class="devsite-landing-row-item-description"> + <div class="devsite-landing-row-item-body"> + <div class="devsite-landing-row-item-labels"> + <span class=" + + ">FEATURED</span> + </div> + <h3 id="10-updates-at-google-io" data-text="10 updates at Google I/O" class="hide-from-toc no-link"> + <a href="/blog/chrome-at-io23"> + 10 updates at Google I/O + </a> + </h3> + <div class="devsite-landing-row-item-description-content"> + We're wrapping things up on this year's Google I/O, with more than 100 new APIs, components, and tools discussed on the + keynote stage, and in Chrome's on-demand sessions. + </div> + <div class="devsite-landing-row-item-buttons"> + <a href="/blog/chrome-at-io23" class="button + " aria-label="Read the Google I/O recap blog.">Explore Now</a> + </div> + </div> + </div> + </div> + <div class="devsite-landing-row-item dcc-blog-card" description-position="bottom"> + <div class="devsite-landing-row-item-media + "> + <figure class="devsite-landing-row-item-image"> + <a href="/blog/new-in-devtools-118/"> + <img alt="" src="/static/dcc/new-in-devtools-118-thumb.webp" loading="lazy" width="565" height="178"> + </a> + </figure> + </div> + <div class="devsite-landing-row-item-description"> + <div class="devsite-landing-row-item-body"> + <div class="devsite-landing-row-item-labels"> + <span class="dcc-label-top + ">LATEST NEWS</span> + </div> + <h3 + id="bringing-safety-check-to-the-chromeextensions-page" + data-text="What's New in DevTools (Chrome 118)" + class="hide-from-toc no-link"> + <a href="/blog/new-in-devtools-118/"> + What's New in DevTools (Chrome 118) + </a> + </h3> + <div class="devsite-landing-row-item-description-content"> + Check out the latest set of features and updates landing in the next release. + </div> + <div class="devsite-landing-row-item-buttons"> + <a href="/blog/new-in-devtools-118/" class="button + " aria-label="Read more about new features in Chrome 118 DevTools.">Explore Now</a> + </div> + </div> + </div> + </div> + </div> + </div> + </section> + <section + class="devsite-landing-row devsite-landing-row-3-up devsite-landing-row-cards devsite-landing-row-no-image-background + dcc-case-studies" + header-position="top"> + <div class="devsite-landing-row-inner"> + <div class="devsite-landing-row-group"> + <div class="devsite-landing-row-item" description-position="bottom"> + <div class="devsite-landing-row-item-media + "> + <figure class="devsite-landing-row-item-image"> + <img alt="" src="/static/dcc/get-inspired-icon.svg" loading="lazy" width="40" height="40"> + </figure> + </div> + <div class="devsite-landing-row-item-description"> + <div class="devsite-landing-row-item-body"> + <h3 id="get-inspired" data-text="Get Inspired" class="hide-from-toc no-link"> + Get Inspired + </h3> + <div class="devsite-landing-row-item-description-content"> + Extend your product’s reach through the browser, increase engagement by improving quality and make the most of the web’s + capabilities. See how businesses are succeeding on the web. + </div> + <div class="devsite-landing-row-item-buttons"> + <a href="/tags/case-study" class="button + ">All stories</a> + </div> + </div> + </div> + </div> + <div class="devsite-landing-row-item dcc-blog-card" description-position="top"> + <div class="devsite-landing-row-item-media + "> + <figure class="devsite-landing-row-item-image"> + <a href="/blog/how-photoshop-solved-working-with-files-larger-than-can-fit-into-memory"> + <img alt="" src="/static/dcc/case-study-thumb.jpg" loading="lazy" width="395" height="222"> + </a> + </figure> + </div> + <div class="devsite-landing-row-item-description"> + <div class="devsite-landing-row-item-body"> + <div class="devsite-landing-row-item-labels"> + <span class=" + + ">CASE STUDY</span> + <span class="dcc-label-top + "></span> + </div> + <div class="devsite-landing-row-item-description-content"> + case study + </div> + </div> + </div> + </div> + <div class="devsite-landing-row-item devsite-landing-row-item-no-media" description-position="bottom"> + <div class="devsite-landing-row-item-description"> + <div class="devsite-landing-row-item-body"> + <h3 + id="how-photoshop-solved-working-with-files-larger-than-can-fit-into-memory" + data-text="How Photoshop solved working with files larger than can fit into memory" + class="hide-from-toc no-link"> + <a href="/blog/how-photoshop-solved-working-with-files-larger-than-can-fit-into-memory"> + How Photoshop solved working with files larger than can fit into memory + </a> + </h3> + <div class="devsite-landing-row-item-description-content"> + Learn how Adobe managed to let users edit even the biggest files on the web version of its iconic Photoshop app. + </div> + <div class="devsite-landing-row-item-buttons"> + <a + href="/blog/how-photoshop-solved-working-with-files-larger-than-can-fit-into-memory" + class="button + button-white + ">Read more</a> + </div> + </div> + </div> + </div> + </div> + </div> + </section> + <section + class="devsite-landing-row devsite-landing-row-4-up devsite-landing-row-cards devsite-landing-row-no-image-background + dcc-pillars" + background="pale-blue" + header-position="top"> + <div class="devsite-landing-row-inner"> + <header class="devsite-landing-row-header"> + <div class="devsite-landing-row-header-text"> + <h2 + id="features-tools-and-programs-to-make-developers-successful-on-the-web" + data-text="Features, tools and programs to make developers successful on the web."> + Features, tools and programs to make developers successful on the web. + </h2> + </div> + </header> + <div class="devsite-landing-row-group"> + <div class="devsite-landing-row-item dcc-services-card" description-position="bottom"> + <div class="devsite-landing-row-item-media + "> + <figure class="devsite-landing-row-item-image"> + <img alt="" src="/static/dcc/powerful-icon.webp" loading="lazy" width="176" height="176"> + </figure> + </div> + <div class="devsite-landing-row-item-description"> + <div class="devsite-landing-row-item-body"> + <h3 id="powerful-platform-capabilities" data-text="Powerful platform capabilities" class="hide-from-toc no-link"> + Powerful platform capabilities + </h3> + <div class="devsite-landing-row-item-buttons"> + <a href="/capabilities" class="button dcc-web-app-features-link dcc-icon-button + ">Web App Features</a> + <a href="/docs/android" class="button dcc-web-on-android-link dcc-icon-button + ">Web on Android</a> + <a href="/docs/extensions" class="button dcc-chrome-extensions-link dcc-icon-button + ">Chrome Extensions</a> + </div> + </div> + </div> + </div> + <div class="devsite-landing-row-item dcc-services-card" description-position="bottom"> + <div class="devsite-landing-row-item-media + "> + <figure class="devsite-landing-row-item-image"> + <img alt="" src="/static/dcc/solutions-icon.webp" loading="lazy" width="176" height="176"> + </figure> + </div> + <div class="devsite-landing-row-item-description"> + <div class="devsite-landing-row-item-body"> + <h3 id="solutions-for-quality-experiences" data-text="Solutions for quality experiences" class="hide-from-toc no-link"> + Solutions for quality experiences + </h3> + <div class="devsite-landing-row-item-buttons"> + <a href="https://web.dev/vitals/" class="button dcc-cwv-link dcc-icon-button + ">Core Web Vitals</a> + <a href="/tags/css" class="button dcc-design-link dcc-icon-button + ">Design and UI</a> + <a href="/tags/identity" class="button dcc-identity-link dcc-icon-button + ">Identity</a> + </div> + </div> + </div> + </div> + <div class="devsite-landing-row-item dcc-services-card" description-position="bottom"> + <div class="devsite-landing-row-item-media + "> + <figure class="devsite-landing-row-item-image"> + <img alt="" src="/static/dcc/productivity-icon.webp" loading="lazy" width="176" height="176"> + </figure> + </div> + <div class="devsite-landing-row-item-description"> + <div class="devsite-landing-row-item-body"> + <h3 id="productivity-made-easier" data-text="Productivity made easier" class="hide-from-toc no-link"> + Productivity made easier + </h3> + <div class="devsite-landing-row-item-buttons"> + <a href="/docs/devtools" class="button dcc-dev-tools-link dcc-icon-button + ">Chrome DevTools</a> + <a href="https://developers.google.com/speed/" class="button dcc-performance-link dcc-icon-button + ">Performance + Tools</a> + <a href="/docs/puppeteer" class="button dcc-puppeteer-link dcc-icon-button + ">Puppeteer</a> + <a href="/blog/chrome-for-testing" class="button dcc-chrome-testing-link dcc-icon-button + ">Chrome for Testing</a> + </div> + </div> + </div> + </div> + <div class="devsite-landing-row-item dcc-services-card" description-position="bottom"> + <div class="devsite-landing-row-item-media + "> + <figure class="devsite-landing-row-item-image"> + <img alt="" src="/static/dcc/open-icon.webp" loading="lazy" width="176" height="176"> + </figure> + </div> + <div class="devsite-landing-row-item-description"> + <div class="devsite-landing-row-item-body"> + <h3 id="open-by-design" data-text="Open by design" class="hide-from-toc no-link"> + Open by design + </h3> + <div class="devsite-landing-row-item-buttons"> + <a href="https://web.dev/baseline/" class="button dcc-baseline-link dcc-icon-button + ">Baseline</a> + <a href="/aurora" class="button dcc-aurora-link dcc-icon-button + ">Project Aurora</a> + <a href="https://web.dev/" class="button dcc-webdev-link dcc-icon-button + ">web.dev</a> + </div> + </div> + </div> + </div> + </div> + </div> + </section> + <section class="devsite-landing-row devsite-landing-row-2-up dcc-chrome-releases" header-position="left"> + <div class="devsite-landing-row-inner"> + <header class="devsite-landing-row-header" icon-position="top"> + <div class="devsite-landing-row-header-icon-container" size="medium"> + <div class="devsite-landing-row-header-icon material-icons" aria-hidden="true"> + verified + </div> + </div> + <div class="devsite-landing-row-header-text"> + <h2 id="always-updating" data-text="Always updating"> + Always updating + </h2> + <div class="devsite-landing-row-description"> + See what's included in Chrome's latest stable and beta releases + </div> + </div> + </header> + <div class="devsite-landing-row-group"> + <div class="devsite-landing-row-item dcc-blog-card" description-position="bottom"> + <div class="devsite-landing-row-item-media + "> + <figure class="devsite-landing-row-item-image"> + <a href="/blog/chrome-117-beta"> + <img alt="" src="/static/dcc/chrome-117-beta.jpg" loading="lazy" width="371" height="200"> + </a> + </figure> + </div> + <div class="devsite-landing-row-item-description"> + <div class="devsite-landing-row-item-body"> + <h3 id="chrome-117-beta" data-text="Chrome 117 beta" class="hide-from-toc no-link"> + <a href="/blog/chrome-117-beta"> + Chrome 117 beta + </a> + </h3> + <div class="devsite-landing-row-item-description-content"> + Chrome 117 beta brings you subgrid for CSS grid layout, entry and exit animation support in CSS, array grouping, + iterator helpers, and more. You can also register for several new origin trials, including tabbed web apps. + </div> + <div class="devsite-landing-row-item-buttons"> + <a href="/tags/beta" class="button + ">All beta blog posts</a> + </div> + </div> + </div> + </div> + <div class="devsite-landing-row-item dcc-blog-card" description-position="bottom"> + <div class="devsite-landing-row-item-media + "> + <figure class="devsite-landing-row-item-image"> + <a href="/blog/new-in-chrome-116"> + <img alt="" src="/static/dcc/new-in-chrome-116.jpg" loading="lazy" width="371" height="200"> + </a> + </figure> + </div> + <div class="devsite-landing-row-item-description"> + <div class="devsite-landing-row-item-body"> + <h3 id="new-in-chrome-116" data-text="New in Chrome 116" class="hide-from-toc no-link"> + <a href="/blog/new-in-chrome-116"> + New in Chrome 116 + </a> + </h3> + <div class="devsite-landing-row-item-description-content"> + The latest stable Chrome includes the Document Picture-in-Picture API—open an always-on-top window populated with any + HTML content. You’ll also discover new features that make debugging missing stylesheets much easier in Chrome DevTools. + </div> + <div class="devsite-landing-row-item-buttons"> + <a href="/tags/new-in-chrome" class="button + ">All stable blog posts</a> + </div> + </div> + </div> + </div> + </div> + </div> + </section> + <section class="devsite-landing-row devsite-landing-row-4-up dcc-docs" header-position="left"> + <div class="devsite-landing-row-inner"> + <header class="devsite-landing-row-header" icon-position="top"> + <div class="devsite-landing-row-header-icon-container" size="medium"> + <div class="devsite-landing-row-header-icon material-icons" aria-hidden="true"> + description + </div> + </div> + <div class="devsite-landing-row-header-text"> + <h2 id="docs" data-text="Docs"> + Docs + </h2> + <div class="devsite-landing-row-description"> + All the resources you need to start building + </div> + </div> + <div class="devsite-landing-row-header-buttons"> + <a href="/docs" class="button + ">See all docs</a> + </div> + </header> + <div class="devsite-landing-row-group"> + <div class="devsite-landing-row-item dcc-docs-card" description-position="bottom"> + <div class="devsite-landing-row-item-media + "> + <figure class="devsite-landing-row-item-image"> + <img alt="" src="/static/dcc/chrome-devtools-thumb.svg" loading="lazy" width="128" height="128"> + </figure> + </div> + <div class="devsite-landing-row-item-description"> + <div class="devsite-landing-row-item-body"> + <h3 id="chrome-devtools" data-text="Chrome DevTools" class="hide-from-toc no-link"> + Chrome DevTools + </h3> + <div class="devsite-landing-row-item-description-content"> + Diagnose problems and edit source files quickly to build better, faster websites, directly in the Chrome browser. + </div> + <div class="devsite-landing-row-item-buttons"> + <a href="/docs/devtools" class="button + ">See all documentation</a> + </div> + </div> + </div> + </div> + <div class="devsite-landing-row-item dcc-docs-card" description-position="bottom"> + <div class="devsite-landing-row-item-media + "> + <figure class="devsite-landing-row-item-image"> + <img alt="" src="/static/dcc/chrome-extensions-thumb.svg" loading="lazy" width="128" height="128"> + </figure> + </div> + <div class="devsite-landing-row-item-description"> + <div class="devsite-landing-row-item-body"> + <h3 id="extensions" data-text="Extensions" class="hide-from-toc no-link"> + Extensions + </h3> + <div class="devsite-landing-row-item-description-content"> + Customize the Chrome browsing experience using on web technologies, such as HTML, CSS, and JavaScript. + </div> + <div class="devsite-landing-row-item-buttons"> + <a href="/docs/extensions" class="button + ">See all documentation</a> + </div> + </div> + </div> + </div> + <div class="devsite-landing-row-item dcc-docs-card" description-position="bottom"> + <div class="devsite-landing-row-item-media + "> + <figure class="devsite-landing-row-item-image"> + <img alt="" src="/static/dcc/chrome-web-store-thumb.svg" loading="lazy" width="128" height="128"> + </figure> + </div> + <div class="devsite-landing-row-item-description"> + <div class="devsite-landing-row-item-body"> + <h3 id="chrome-web-store" data-text="Chrome Web Store" class="hide-from-toc no-link"> + Chrome Web Store + </h3> + <div class="devsite-landing-row-item-description-content"> + Publish your extensions and themes to Chrome’s online marketplace. + </div> + <div class="devsite-landing-row-item-buttons"> + <a href="/docs/webstore" class="button + ">See all documentation</a> + </div> + </div> + </div> + </div> + <div class="devsite-landing-row-item dcc-docs-card" description-position="bottom"> + <div class="devsite-landing-row-item-media + "> + <figure class="devsite-landing-row-item-image"> + <img alt="" src="/static/dcc/web-on-android-thumb.svg" loading="lazy" width="128" height="128"> + </figure> + </div> + <div class="devsite-landing-row-item-description"> + <div class="devsite-landing-row-item-body"> + <h3 id="web-platform" data-text="Web Platform" class="hide-from-toc no-link"> + Web Platform + </h3> + <div class="devsite-landing-row-item-description-content"> + Learn key Chrome concepts, discover Chrome web APIs, and experiment with origin trials + </div> + <div class="devsite-landing-row-item-buttons"> + <a href="/docs/web-platform" class="button + ">See all documentation</a> + </div> + </div> + </div> + </div> + </div> + </div> + </section> + <section + class="devsite-landing-row devsite-landing-row-2-up devsite-landing-row-cards devsite-landing-row-no-image-background + dcc-social" + background="pale-blue" + header-position="top"> + <div class="devsite-landing-row-inner"> + <header class="devsite-landing-row-header"> + <div class="devsite-landing-row-header-text"> + <h2 id="connect-with-the-team" data-text="Connect with the team"> + Connect with the team + </h2> + </div> + </header> + <div class="devsite-landing-row-group"> + <div class="devsite-landing-row-item dcc-social-card" description-position="bottom"> + <div class="devsite-landing-row-item-media + "> + <figure class="devsite-landing-row-item-image"> + <img alt="" src="/static/dcc/chrome-twitter.svg" loading="lazy" width="57" height="57"> + </figure> + </div> + <div class="devsite-landing-row-item-description"> + <div class="devsite-landing-row-item-body"> + <h3 id="chrome-for-developers-on-x" data-text="Chrome for Developers on X" class="hide-from-toc no-link"> + Chrome for Developers on X + </h3> + <div class="devsite-landing-row-item-description-content"> + Follow us to get real time updates and announcements about Chrome and the web. + </div> + <div class="devsite-landing-row-item-buttons"> + <a href="https://twitter.com/ChromiumDev" class="button + ">Follow</a> + </div> + </div> + </div> + </div> + <div class="devsite-landing-row-item dcc-social-card" description-position="bottom"> + <div class="devsite-landing-row-item-media + "> + <figure class="devsite-landing-row-item-image"> + <img alt="" src="/static/dcc/chrome-youtube.svg" loading="lazy" width="57" height="57"> + </figure> + </div> + <div class="devsite-landing-row-item-description"> + <div class="devsite-landing-row-item-body"> + <h3 id="chrome-for-developers-on-youtube" data-text="Chrome for Developers on YouTube" class="hide-from-toc no-link"> + Chrome for Developers on YouTube + </h3> + <div class="devsite-landing-row-item-description-content"> + Subscribe to stay up to speed with Chrome and web updates, tutorials, case studies and more. + </div> + <div class="devsite-landing-row-item-buttons"> + <a href="https://www.youtube.com/@ChromeDevs" class="button + ">Learn more</a> + </div> + </div> + </div> + </div> + </div> + </div> + </section> + </div> + </article> + </devsite-content> +</main> +{% endblock %} \ No newline at end of file diff --git a/site/_includes/layouts/devsite.njk b/site/_includes/layouts/devsite.njk new file mode 100644 index 000000000..0f2ebb0d6 --- /dev/null +++ b/site/_includes/layouts/devsite.njk @@ -0,0 +1,131 @@ +<!DOCTYPE html> +<html lang="{{ locale }}"> + <head> + <meta charset="UTF-8" /> + <meta name="viewport" content="width=device-width, initial-scale=1.0" /> + {% if noindex -%} + <meta name="robots" content="noindex"> + {%- endif %} + + {% include 'partials/meta.njk' %} + {% block feed %} + <link rel="alternate" type="application/rss+xml" title="{{ site.title }}" href="{{ site.url }}/feeds/all.xml"> + <link rel="alternate" type="application/rss+xml" title="{{ site.title }} - {{ 'i18n.common.blog' | i18n(locale) }}" href="{{ site.url }}/feeds/blog.xml"> + <link rel="alternate" type="application/rss+xml" title="{{ site.title }} - {{ 'i18n.common.articles' | i18n(locale) }}" href="{{ site.url }}/feeds/articles.xml"> + {% endblock %} + + <link rel="preload" as="font" crossorigin href="/fonts/google-sans-v2003/regular/latin.woff2"> + <link rel="preload" as="font" crossorigin href="/fonts/google-sans-v2003/medium/latin.woff2"> + <link rel="preconnect" href="https://fonts.googleapis.com"> + <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> + <link href="https://fonts.googleapis.com/icon?family=Material+Icons|Material+Icons+Outlined" rel="stylesheet"> + + {% block css %} + {% InlineCss '/css/home.css' %} + {% InlineCss '/css/devsite.css' %} + {% InlineCss '/css/devsite-theme.css' %} + {% endblock %} + + <script type="module" src="{{ helpers.hashForProd('/js/main.js') }}"></script> + {% if process.env.NODE_ENV === 'production' %} + <script async src="https://www.googletagmanager.com/gtm.js?id=GTM-5QF3RT2"></script> + {% endif %} + + {# Private Aggregation API testing script #} + {# The test will run until mid-April #} + {% if process.env.NODE_ENV === 'production' %} + <script type="module" defer src="https://shared-storage-demo-content-producer.web.app/paa/scripts/private-aggregation-test.js"></script> + {% endif %} + + {# Add a facility for pages to declare an array of script paths. #} + {# Note: We could also use this approach to load module/nomodule scripts #} + {# https://philipwalton.com/articles/deploying-es2015-code-in-production-today/ #} + {% if pageScripts %} + {% for item in pageScripts %} + <script type="module" src="{{ helpers.hashForProd(item) }}"></script> + {% endfor %} + {% endif %} + + {# Dogfood document speculation rules origin trial #} + <!-- developer.chrome.com origin trial token - valid until 23 Mar 2023 --> + <meta http-equiv="origin-trial" content="AhaT7AdLUbVk3M0VorYLzXSY8Km9PJZlzg3Xkv6KT2QMZ4zyqA5BfdTJLCj1TVnGhryWtQH66HWQEsIbZDUrsAwAAABseyJvcmlnaW4iOiJodHRwczovL2RldmVsb3Blci5jaHJvbWUuY29tOjQ0MyIsImZlYXR1cmUiOiJTcGVjdWxhdGlvblJ1bGVzUHJlZmV0Y2hGdXR1cmUiLCJleHBpcnkiOjE2OTQxMzExOTl9"> + {# Exclude the /articles/ section as a control #} + <script type="speculationrules"> + { + "prerender": [ + { + "source": "document", + "where": { + "and": [ + { + "href_matches": "/*\\?*", "relative_to": "document" + }, + { + "not": { + "href_matches": "/articles/*\\?*", + "relative_to": "document" + } + } + ] + }, + "eagerness": "moderate" + } + ] + } + </script> + + {# This needs to be include'd, because it expands 11ty variables #} + <script>{% include 'partials/script.js' %}</script> + + {# Some articles may have previously used lists with anchors for their + content (like FAQs) which may have evolved into their own articles by now. + Such anchors should be able to link to those new articles #} + {% if anchorRedirects %} + <script> + (() => { + let anchorRedirects = {{ anchorRedirects|dump|safe }}; + + function redirect(targetURL) { + let {hash} = new URL(targetURL); + if (!hash) { + return; + } + + hash = hash.substring(1); + + if (anchorRedirects[hash]) { + window.location.replace(anchorRedirects[hash]); + } + } + redirect(window.location.href); + window.addEventListener('hashchange', (event) => redirect(event.newURL)); + })(); + </script> + {% endif %} + + {% set isDevsite = true %} + + </head> + <body class="" template="landing" theme="web-theme" type="article" layout="full" ready="" style="--devsite-js-header-height: 49px; --devsite-panel-height: 0px;"> + <div class="scaffold"> + {% block header %} + {% include 'partials/top-nav.njk' %} + {% endblock %} + + {% block sidebar %} + {% include 'partials/side-nav.njk' %} + {% endblock %} + + <section class="dcc-devsite-wrapper" theme="web-theme"> + {% block devsite_main %}{% endblock %} + </section> + + {% block footer %} + {% include 'partials/footer.njk' %} + {% endblock %} + </div> + {% include 'partials/cookie-banner.njk' %} + + {% block scripts %}{% endblock %} + </body> +</html> diff --git a/site/_includes/partials/footer.njk b/site/_includes/partials/footer.njk index ba901a175..06790ca58 100644 --- a/site/_includes/partials/footer.njk +++ b/site/_includes/partials/footer.njk @@ -2,19 +2,21 @@ <footer class="type--footer gap-top-1000 lg:pad-left-600 lg:pad-right-600" data-side-nav-inert data-search-inert> - <div class="pad-top-600 pad-bottom-600 pad-left-400 pad-right-400 hairline-bottom lg:pad-left-0 lg:pad-right-0"> - <div class="display-flex direction-column lg:direction-row lg:align-center"> - <div class="footer__heading">{{ 'i18n.footer.follow_us' | i18n(locale) }}</div> - <div class="display-flex color-secondary-text gap-top-300 lg:gap-top-0"> - <a href="https://www.youtube.com/user/ChromeDevelopers" class="display-inline-flex color-secondary-text lg:gap-left-400" aria-label="{{ 'i18n.footer.youtube' | i18n(locale) }}"> - {{ icon('youtube', {hidden: true}) }} - </a> - <a href="https://twitter.com/ChromiumDev" class="display-inline-flex color-secondary-text gap-left-400" aria-label="{{ 'i18n.footer.twitter' | i18n(locale) }}"> - {{ icon('twitter', {hidden: true}) }} - </a> + {% if not isDevsite %} + <div class="pad-top-600 pad-bottom-600 pad-left-400 pad-right-400 hairline-bottom lg:pad-left-0 lg:pad-right-0"> + <div class="display-flex direction-column lg:direction-row lg:align-center"> + <div class="footer__heading">{{ 'i18n.footer.follow_us' | i18n(locale) }}</div> + <div class="display-flex color-secondary-text gap-top-300 lg:gap-top-0"> + <a href="https://www.youtube.com/user/ChromeDevelopers" class="display-inline-flex color-secondary-text lg:gap-left-400" aria-label="{{ 'i18n.footer.youtube' | i18n(locale) }}"> + {{ icon('youtube', {hidden: true}) }} + </a> + <a href="https://twitter.com/ChromiumDev" class="display-inline-flex color-secondary-text gap-left-400" aria-label="{{ 'i18n.footer.twitter' | i18n(locale) }}"> + {{ icon('twitter', {hidden: true}) }} + </a> + </div> </div> </div> - </div> + {% endif %} <div class="pad-top-600 pad-bottom-600 pad-left-400 pad-right-400 hairline-bottom lg:pad-left-0 lg:pad-right-0"> <div class="display-flex direction-column lg:direction-row justify-content-between"> @@ -80,16 +82,24 @@ <div class="pad-top-600 pad-bottom-600 pad-left-400 pad-right-400 lg:pad-left-0 lg:pad-right-0"> <div class="display-flex direction-column lg:direction-row align-start lg:align-center"> - <svg aria-label="Google Developers" width="180" height="20" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M8.36 15.32a7.465 7.465 0 01-3.76-.98 7.287 7.287 0 01-2.72-2.68c-.667-1.147-1-2.42-1-3.82s.333-2.667 1-3.8a7.243 7.243 0 012.72-2.7A7.464 7.464 0 018.36.36c1.08 0 2.087.193 3.02.58.933.387 1.713.927 2.34 1.62l-1.56 1.56a4.78 4.78 0 00-1.66-1.2c-.64-.28-1.353-.42-2.14-.42-.933 0-1.8.22-2.6.66-.8.44-1.44 1.067-1.92 1.88-.467.813-.7 1.747-.7 2.8 0 1.053.24 1.987.72 2.8.48.813 1.12 1.44 1.92 1.88.8.44 1.667.66 2.6.66.84 0 1.547-.127 2.12-.38a5.434 5.434 0 001.54-1.02c.293-.28.54-.64.74-1.08.213-.453.36-.94.44-1.46H8.34v-2h6.98c.08.453.12.84.12 1.16a7.89 7.89 0 01-.44 2.62 5.63 5.63 0 01-1.32 2.16c-1.36 1.427-3.133 2.14-5.32 2.14zm14.05 0c-.987 0-1.873-.227-2.66-.68a5.087 5.087 0 01-1.86-1.9c-.44-.8-.66-1.7-.66-2.7 0-1 .22-1.9.66-2.7a4.939 4.939 0 011.86-1.88c.787-.467 1.673-.7 2.66-.7 1 0 1.893.233 2.68.7.787.453 1.4 1.08 1.84 1.88.44.8.66 1.7.66 2.7 0 1-.22 1.9-.66 2.7a4.939 4.939 0 01-1.84 1.9c-.787.453-1.68.68-2.68.68zm0-2.02c.533 0 1.027-.133 1.48-.4.453-.267.82-.647 1.1-1.14.28-.493.42-1.067.42-1.72 0-.667-.14-1.247-.42-1.74a2.868 2.868 0 00-1.1-1.12 2.867 2.867 0 00-1.48-.4c-.52 0-1.013.133-1.48.4-.453.253-.82.627-1.1 1.12-.267.493-.4 1.073-.4 1.74 0 .653.14 1.227.42 1.72.28.493.647.873 1.1 1.14.453.267.94.4 1.46.4zm12.019 2.02c-.987 0-1.874-.227-2.66-.68a5.087 5.087 0 01-1.86-1.9c-.44-.8-.66-1.7-.66-2.7 0-1 .22-1.9.66-2.7a4.939 4.939 0 011.86-1.88c.786-.467 1.673-.7 2.66-.7 1 0 1.893.233 2.68.7.786.453 1.4 1.08 1.84 1.88.44.8.66 1.7.66 2.7 0 1-.22 1.9-.66 2.7a4.94 4.94 0 01-1.84 1.9c-.787.453-1.68.68-2.68.68zm0-2.02c.533 0 1.026-.133 1.48-.4.453-.267.82-.647 1.1-1.14.28-.493.42-1.067.42-1.72 0-.667-.14-1.247-.42-1.74a2.868 2.868 0 00-1.1-1.12 2.868 2.868 0 00-1.48-.4c-.52 0-1.014.133-1.48.4-.454.253-.82.627-1.1 1.12-.267.493-.4 1.073-.4 1.74 0 .653.14 1.227.42 1.72.28.493.646.873 1.1 1.14.453.267.94.4 1.46.4zm11.878 6.34c-1.24 0-2.266-.293-3.08-.88-.8-.573-1.34-1.247-1.62-2.02l2.08-.86c.2.547.534.98 1 1.3.467.32 1.007.48 1.62.48.92 0 1.64-.28 2.16-.84.534-.56.8-1.333.8-2.32v-.86h-.12c-.32.467-.76.84-1.32 1.12-.546.28-1.173.42-1.88.42-.826 0-1.6-.22-2.32-.66-.706-.44-1.28-1.053-1.72-1.84-.426-.8-.64-1.7-.64-2.7 0-1 .214-1.893.64-2.68.44-.8 1.014-1.42 1.72-1.86a4.276 4.276 0 012.32-.68c.707 0 1.334.14 1.88.42.56.28 1 .653 1.32 1.12h.12V5.08h2.1v9.36c0 1.093-.22 2.033-.66 2.82a4.215 4.215 0 01-1.8 1.78c-.76.4-1.626.6-2.6.6zm.06-6.46c.52 0 1-.127 1.44-.38a2.81 2.81 0 001.06-1.1c.267-.493.4-1.067.4-1.72 0-.667-.133-1.24-.4-1.72-.266-.493-.62-.867-1.06-1.12-.44-.253-.92-.38-1.44-.38-.52 0-1 .133-1.44.4-.44.253-.793.627-1.06 1.12-.266.48-.4 1.047-.4 1.7s.134 1.227.4 1.72c.267.48.62.847 1.06 1.1.44.253.92.38 1.44.38zM54.14.68h2.2V15h-2.2V.68zm9.45 14.64c-.973 0-1.853-.227-2.64-.68a4.838 4.838 0 01-1.82-1.88c-.44-.813-.66-1.72-.66-2.72 0-.96.207-1.84.62-2.64a4.848 4.848 0 011.78-1.92c.76-.48 1.627-.72 2.6-.72 1 0 1.867.22 2.6.66a4.28 4.28 0 011.7 1.84c.387.773.58 1.667.58 2.68 0 .12-.007.24-.02.36a4.16 4.16 0 00-.02.2h-7.64c.067.907.393 1.607.98 2.1.587.493 1.253.74 2 .74 1.147 0 2.027-.533 2.64-1.6l1.88.9a5.195 5.195 0 01-1.84 1.96c-.773.48-1.687.72-2.74.72zm2.52-6.5a2.419 2.419 0 00-.32-.98c-.187-.333-.48-.613-.88-.84-.387-.24-.873-.36-1.46-.36-.653 0-1.22.2-1.7.6-.467.4-.787.927-.96 1.58h5.32zm9.7-8.14h4.6c1.48 0 2.767.3 3.86.9a6.137 6.137 0 012.54 2.54c.6 1.08.9 2.32.9 3.72 0 1.4-.3 2.647-.9 3.74a6.168 6.168 0 01-2.54 2.52c-1.093.6-2.38.9-3.86.9h-4.6V.68zm4.54 12.18c1.6 0 2.847-.44 3.74-1.32.907-.893 1.36-2.127 1.36-3.7 0-1.56-.453-2.787-1.36-3.68-.893-.893-2.14-1.34-3.74-1.34h-2.3v10.04h2.3zm14.042 2.46c-.973 0-1.853-.227-2.64-.68a4.839 4.839 0 01-1.82-1.88c-.44-.813-.66-1.72-.66-2.72 0-.96.207-1.84.62-2.64a4.849 4.849 0 011.78-1.92c.76-.48 1.627-.72 2.6-.72 1 0 1.867.22 2.6.66a4.28 4.28 0 011.7 1.84c.387.773.58 1.667.58 2.68 0 .12-.006.24-.02.36-.013.12-.02.187-.02.2h-7.64c.067.907.394 1.607.98 2.1.587.493 1.254.74 2 .74 1.147 0 2.027-.533 2.64-1.6l1.88.9a5.195 5.195 0 01-1.84 1.96c-.773.48-1.686.72-2.74.72zm2.52-6.5a2.417 2.417 0 00-.32-.98c-.186-.333-.48-.613-.88-.84-.386-.24-.873-.36-1.46-.36-.653 0-1.22.2-1.7.6-.466.4-.786.927-.96 1.58h5.32zm3.136-3.74h2.46l2.72 7.08h.08l2.76-7.08h2.42l-4.14 9.92h-2.2l-4.1-9.92zm16.37 10.24c-.973 0-1.853-.227-2.64-.68a4.84 4.84 0 01-1.82-1.88c-.44-.813-.66-1.72-.66-2.72 0-.96.207-1.84.62-2.64a4.851 4.851 0 011.78-1.92c.76-.48 1.627-.72 2.6-.72 1 0 1.867.22 2.6.66a4.274 4.274 0 011.7 1.84c.387.773.58 1.667.58 2.68 0 .12-.006.24-.02.36-.013.12-.02.187-.02.2h-7.64c.067.907.394 1.607.98 2.1.587.493 1.254.74 2 .74 1.147 0 2.027-.533 2.64-1.6l1.88.9a5.192 5.192 0 01-1.84 1.96c-.773.48-1.686.72-2.74.72zm2.52-6.5a2.402 2.402 0 00-.32-.98c-.186-.333-.48-.613-.88-.84-.386-.24-.873-.36-1.46-.36-.653 0-1.22.2-1.7.6-.466.4-.786.927-.96 1.58h5.32zm4.451-8.14h2.2V15h-2.2V.68zm9.509 14.64c-.986 0-1.873-.227-2.66-.68a5.098 5.098 0 01-1.86-1.9c-.44-.8-.66-1.7-.66-2.7 0-1 .22-1.9.66-2.7a4.949 4.949 0 011.86-1.88c.787-.467 1.674-.7 2.66-.7 1 0 1.894.233 2.68.7.787.453 1.4 1.08 1.84 1.88.44.8.66 1.7.66 2.7 0 1-.22 1.9-.66 2.7a4.937 4.937 0 01-1.84 1.9c-.786.453-1.68.68-2.68.68zm0-2.02c.534 0 1.027-.133 1.48-.4.454-.267.82-.647 1.1-1.14.28-.493.42-1.067.42-1.72 0-.667-.14-1.247-.42-1.74a2.864 2.864 0 00-1.1-1.12 2.865 2.865 0 00-1.48-.4c-.52 0-1.013.133-1.48.4a2.87 2.87 0 00-1.1 1.12c-.266.493-.4 1.073-.4 1.74 0 .653.14 1.227.42 1.72.28.493.647.873 1.1 1.14.454.267.94.4 1.46.4zm7.222-8.22h2.08v1.28h.12c.28-.453.7-.833 1.26-1.14.573-.307 1.22-.46 1.94-.46.853 0 1.64.227 2.36.68.733.453 1.313 1.087 1.74 1.9.44.8.66 1.7.66 2.7 0 1-.22 1.9-.66 2.7a4.992 4.992 0 01-1.74 1.9c-.72.453-1.507.68-2.36.68-.72 0-1.367-.153-1.94-.46-.56-.307-.98-.693-1.26-1.16h-.12l.12 1.4v4.22h-2.2V5.08zm5.02 8.22c.52 0 1-.133 1.44-.4a2.88 2.88 0 001.08-1.14c.28-.507.42-1.08.42-1.72 0-.64-.14-1.207-.42-1.7a2.849 2.849 0 00-1.08-1.16c-.44-.267-.92-.4-1.44-.4a2.83 2.83 0 00-1.46.4c-.44.267-.8.647-1.08 1.14-.267.493-.4 1.067-.4 1.72s.133 1.227.4 1.72c.28.493.64.873 1.08 1.14.453.267.94.4 1.46.4zm11.912 2.02c-.974 0-1.854-.227-2.64-.68a4.834 4.834 0 01-1.82-1.88c-.44-.813-.66-1.72-.66-2.72 0-.96.206-1.84.62-2.64a4.844 4.844 0 011.78-1.92c.76-.48 1.626-.72 2.6-.72 1 0 1.866.22 2.6.66a4.286 4.286 0 011.7 1.84c.386.773.58 1.667.58 2.68 0 .12-.007.24-.02.36a3.41 3.41 0 00-.02.2h-7.64c.066.907.393 1.607.98 2.1a3.02 3.02 0 002 .74c1.146 0 2.026-.533 2.64-1.6l1.88.9a5.2 5.2 0 01-1.84 1.96c-.774.48-1.687.72-2.74.72zm2.52-6.5a2.433 2.433 0 00-.32-.98c-.187-.333-.48-.613-.88-.84-.387-.24-.874-.36-1.46-.36-.654 0-1.22.2-1.7.6-.467.4-.787.927-.96 1.58h5.32zm4.45-3.74h2.08v1.48h.12c.214-.507.6-.927 1.16-1.26.56-.347 1.134-.52 1.72-.52.48 0 .874.067 1.18.2v2.3a3.35 3.35 0 00-1.52-.34c-.72 0-1.326.28-1.82.84-.48.547-.72 1.22-.72 2.02V15h-2.2V5.08zm11.441 10.24c-1.134 0-2.074-.26-2.82-.78-.734-.533-1.254-1.2-1.56-2l1.96-.84c.226.547.553.96.98 1.24.44.28.92.42 1.44.42.546 0 .993-.1 1.34-.3.346-.213.52-.487.52-.82 0-.32-.14-.58-.42-.78-.28-.213-.74-.4-1.38-.56l-1.36-.32a4.5 4.5 0 01-1.94-.96c-.534-.48-.8-1.1-.8-1.86 0-.92.38-1.647 1.14-2.18.76-.547 1.693-.82 2.8-.82.92 0 1.733.193 2.44.58.72.387 1.24.947 1.56 1.68l-1.94.82a1.87 1.87 0 00-.86-.92c-.387-.2-.807-.3-1.26-.3-.44 0-.827.1-1.16.3-.334.187-.5.44-.5.76 0 .28.113.507.34.68.24.173.613.32 1.12.44l1.48.36c1 .253 1.746.64 2.24 1.16.493.507.74 1.12.74 1.84 0 .587-.18 1.12-.54 1.6-.347.48-.834.86-1.46 1.14-.614.28-1.314.42-2.1.42z" fill="#5F6368"/></svg> + <svg aria-label="Google for Developers" width="180" height="20" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 886 96"> + <path fill="#5f6368" d="M342.32 6.41c3.07 0 5.58.52 7.54 1.56l-2.3 7.45a10.9 10.9 0 0 0-4.97-1.1c-2.09 0-3.79.72-5.11 2.16-1.32 1.44-1.98 3.36-1.98 5.75v5.7h11.78v7.73H335.5v37.35h-8.46V35.66h-8.46v-7.73h8.46V21.4c0-4.48 1.43-8.1 4.28-10.86 2.85-2.76 6.52-4.14 10.99-4.14ZM349.29 50.48c0-6.93 2.18-12.66 6.53-17.2 4.42-4.54 9.97-6.81 16.65-6.81s12.21 2.27 16.56 6.81c4.42 4.54 6.62 10.27 6.62 17.2s-2.21 12.73-6.62 17.2c-4.36 4.54-9.88 6.81-16.56 6.81s-12.24-2.27-16.65-6.81c-4.36-4.54-6.53-10.27-6.53-17.2Zm8.46 0c0 4.85 1.41 8.77 4.23 11.78 2.82 3.01 6.32 4.51 10.49 4.51s7.67-1.5 10.49-4.51c2.82-3 4.23-6.93 4.23-11.78s-1.41-8.68-4.23-11.68c-2.88-3.07-6.38-4.6-10.49-4.6s-7.61 1.53-10.49 4.6c-2.82 3.01-4.23 6.9-4.23 11.68ZM410.13 73.02h-8.46V27.94h8.1v7.36h.37c.86-2.39 2.62-4.43 5.29-6.12 2.67-1.69 5.29-2.53 7.87-2.53s4.54.37 6.26 1.1l-2.58 8.19c-1.04-.43-2.7-.64-4.97-.64-3.19 0-5.97 1.29-8.33 3.86a12.93 12.93 0 0 0-3.54 9.02v24.84ZM456.77 73.02V7.15h20.15c10.06 0 18.14 3.04 24.24 9.11 6.1 6.07 9.15 14.02 9.15 23.83s-3.05 17.83-9.15 23.87c-6.1 6.04-14.18 9.06-24.24 9.06h-20.15Zm8.46-57.78v49.68h11.68c7.67 0 13.71-2.19 18.12-6.58 4.42-4.38 6.62-10.47 6.62-18.26s-2.21-13.8-6.62-18.22c-4.42-4.42-10.46-6.62-18.12-6.62h-11.68ZM537.78 74.49c-6.62 0-12.08-2.27-16.38-6.81-4.29-4.54-6.44-10.27-6.44-17.2s2.08-12.59 6.26-17.16c4.17-4.57 9.51-6.85 16.01-6.85s12.01 2.16 15.96 6.49c3.96 4.32 5.93 10.38 5.93 18.17l-.09.92h-35.42c.12 4.42 1.59 7.97 4.42 10.67a14.11 14.11 0 0 0 10.12 4.05c5.4 0 9.63-2.7 12.7-8.1l7.54 3.68c-2.02 3.8-4.83 6.78-8.42 8.92s-7.65 3.22-12.19 3.22Zm-13.52-29.44h25.85a11.22 11.22 0 0 0-3.82-7.77c-2.3-2.05-5.38-3.08-9.25-3.08-3.19 0-5.93.98-8.23 2.94a14.01 14.01 0 0 0-4.55 7.91ZM585.33 73.02h-8.46l-18.22-45.08h9.2L581.1 62.9h.18l13.43-34.96h9.02l-18.4 45.08ZM625.96 74.49c-6.62 0-12.08-2.27-16.38-6.81-4.29-4.54-6.44-10.27-6.44-17.2s2.08-12.59 6.26-17.16c4.17-4.57 9.51-6.85 16.01-6.85s12.01 2.16 15.96 6.49c3.96 4.32 5.93 10.38 5.93 18.17l-.09.92h-35.42c.12 4.42 1.59 7.97 4.42 10.67a14.11 14.11 0 0 0 10.12 4.05c5.4 0 9.63-2.7 12.7-8.1l7.54 3.68c-2.02 3.8-4.83 6.78-8.42 8.92s-7.65 3.22-12.19 3.22Zm-13.52-29.44h25.85a11.22 11.22 0 0 0-3.82-7.77c-2.3-2.05-5.38-3.08-9.25-3.08-3.19 0-5.93.98-8.23 2.94a14.01 14.01 0 0 0-4.55 7.91ZM661.78 7.15v65.87h-8.46V7.15h8.46ZM667.9 50.48c0-6.93 2.18-12.66 6.53-17.2 4.42-4.54 9.97-6.81 16.65-6.81s12.21 2.27 16.56 6.81c4.42 4.54 6.62 10.27 6.62 17.2s-2.21 12.73-6.62 17.2c-4.36 4.54-9.88 6.81-16.56 6.81s-12.24-2.27-16.65-6.81c-4.36-4.54-6.53-10.27-6.53-17.2Zm8.46 0c0 4.85 1.41 8.77 4.23 11.78 2.82 3.01 6.32 4.51 10.49 4.51s7.67-1.5 10.49-4.51c2.82-3 4.23-6.93 4.23-11.78s-1.41-8.68-4.23-11.68c-2.88-3.07-6.38-4.6-10.49-4.6s-7.61 1.53-10.49 4.6c-2.82 3.01-4.23 6.9-4.23 11.68ZM743.93 74.49c-3.31 0-6.33-.71-9.06-2.12a15.83 15.83 0 0 1-6.3-5.61h-.37l.37 6.26v19.87h-8.46V27.94h8.1v6.26h.37a15.83 15.83 0 0 1 6.3-5.61 19.45 19.45 0 0 1 9.06-2.12c5.95 0 10.98 2.33 15.09 6.99 4.23 4.72 6.35 10.4 6.35 17.02s-2.12 12.36-6.35 17.02c-4.11 4.66-9.14 6.99-15.09 6.99Zm-1.38-7.73c4.05 0 7.45-1.53 10.21-4.6 2.76-3 4.14-6.9 4.14-11.68s-1.38-8.62-4.14-11.68c-2.76-3.07-6.16-4.6-10.21-4.6s-7.54 1.53-10.3 4.6c-2.7 3.07-4.05 6.96-4.05 11.68s1.35 8.71 4.05 11.78a13.4 13.4 0 0 0 10.3 4.51ZM791.88 74.49c-6.62 0-12.08-2.27-16.38-6.81-4.29-4.54-6.44-10.27-6.44-17.2s2.08-12.59 6.26-17.16c4.17-4.57 9.51-6.85 16.01-6.85s12.01 2.16 15.96 6.49c3.96 4.32 5.93 10.38 5.93 18.17l-.09.92h-35.42c.12 4.42 1.59 7.97 4.42 10.67a14.11 14.11 0 0 0 10.12 4.05c5.4 0 9.63-2.7 12.7-8.1l7.54 3.68c-2.02 3.8-4.83 6.78-8.42 8.92s-7.65 3.22-12.19 3.22Zm-13.52-29.44h25.85a11.22 11.22 0 0 0-3.82-7.77c-2.3-2.05-5.38-3.08-9.25-3.08-3.19 0-5.93.98-8.23 2.94a14.01 14.01 0 0 0-4.55 7.91ZM827.75 73.02h-8.46V27.94h8.1v7.36h.37c.86-2.39 2.62-4.43 5.29-6.12 2.67-1.69 5.29-2.53 7.87-2.53s4.54.37 6.26 1.1l-2.58 8.19c-1.04-.43-2.7-.64-4.97-.64-3.19 0-5.97 1.29-8.33 3.86a12.93 12.93 0 0 0-3.54 9.02v24.84ZM885.03 60.51c0 3.93-1.72 7.24-5.15 9.94-3.44 2.7-7.76 4.05-12.97 4.05-4.54 0-8.53-1.18-11.96-3.54a19.46 19.46 0 0 1-7.36-9.34l7.54-3.22c1.1 2.7 2.71 4.8 4.83 6.3a11.76 11.76 0 0 0 6.95 2.25c2.7 0 4.95-.58 6.76-1.75 1.81-1.16 2.71-2.54 2.71-4.14 0-2.88-2.21-5-6.62-6.35l-7.73-1.93c-8.77-2.21-13.16-6.44-13.16-12.7 0-4.11 1.67-7.41 5.01-9.89 3.34-2.48 7.62-3.73 12.83-3.73 3.99 0 7.59.95 10.81 2.85a15.5 15.5 0 0 1 6.76 7.64l-7.54 3.13a9.46 9.46 0 0 0-4.19-4.46 13.15 13.15 0 0 0-6.49-1.61c-2.21 0-4.19.55-5.93 1.66s-2.62 2.45-2.62 4.05c0 2.58 2.42 4.42 7.27 5.52l6.81 1.75c8.95 2.21 13.43 6.72 13.43 13.52Z"/> + <path fill="#4285f4" d="M37.76 74.48C17.24 74.48 0 57.76 0 37.24S17.24 0 37.76 0c11.35 0 19.42 4.45 25.5 10.26l-7.17 7.17a25.91 25.91 0 0 0-18.33-7.27c-14.97 0-26.68 12.08-26.68 27.07s11.71 27.06 26.68 27.06c9.71 0 15.25-3.9 18.79-7.45 2.9-2.91 4.81-7.08 5.54-12.81H37.5V33.86h34.48c.36 1.82.54 4 .54 6.36 0 7.63-2.09 17.08-8.8 23.8-6.53 6.81-14.88 10.44-25.96 10.44Z"/> + <path fill="#ea4335" d="M124.16 50.5c0 13.81-10.79 23.98-24.02 23.98S76.12 64.31 76.12 50.5s10.79-23.98 24.02-23.98 24.02 10.08 24.02 23.98Zm-10.52 0c0-8.63-6.26-14.53-13.51-14.53s-13.51 5.9-13.51 14.53 6.26 14.53 13.51 14.53 13.51-5.99 13.51-14.53Z"/> + <path fill="#fbbc04" d="M176.45 50.5c0 13.81-10.79 23.98-24.02 23.98s-24.02-10.17-24.02-23.98 10.79-23.98 24.02-23.98 24.02 10.08 24.02 23.98Zm-10.52 0c0-8.63-6.26-14.53-13.51-14.53s-13.51 5.9-13.51 14.53 6.26 14.53 13.51 14.53 13.51-5.99 13.51-14.53Z"/> + <path fill="#4285f4" d="M226.47 27.97v43.05c0 17.71-10.44 24.98-22.78 24.98-11.62 0-18.61-7.81-21.24-14.17l9.17-3.81c1.63 3.91 5.63 8.54 12.07 8.54 7.9 0 12.8-4.9 12.8-14.08v-3.45h-.36c-2.36 2.91-6.9 5.45-12.62 5.45-11.98 0-22.96-10.44-22.96-23.89s10.98-24.07 22.96-24.07c5.72 0 10.26 2.54 12.62 5.36h.36v-3.91h9.98Zm-9.26 22.62c0-8.45-5.63-14.62-12.8-14.62s-13.34 6.18-13.34 14.62 6.08 14.44 13.34 14.44 12.8-6.09 12.8-14.44Z"/> + <path fill="#34a853" d="M244.57 2.54v70.48h-10.53V2.54h10.53Z"/> + <path fill="#ea4335" d="m285.38 58.4 8.17 5.45a23.83 23.83 0 0 1-19.97 10.63c-13.61 0-23.78-10.54-23.78-23.98 0-14.26 10.26-23.98 22.6-23.98s18.51 9.9 20.51 15.26L294 44.5l-32.04 13.26c2.45 4.81 6.26 7.27 11.62 7.27s9.08-2.63 11.8-6.63Zm-25.14-8.63 21.42-8.9c-1.18-3-4.72-5.09-8.89-5.09-5.35 0-12.8 4.72-12.52 13.99Z"/> + </svg> <div class="footer__cluster cluster flex-1 gap-top-300 flow-space-300 lg:gap-top-0 lg:gap-left-500 lg:flow-space-500"> - <div role="list"> - {# Google Developer logo #} - <a role="listitem" class="footer__link" href="https://www.google.com/chrome/">Chrome</a> - <a role="listitem" class="footer__link" href="https://firebase.google.com">Firebase</a> - <a role="listitem" class="footer__link" href="https://developers.google.com/products">{{ 'i18n.footer.all_products' | i18n(locale) }}</a> - <a role="listitem" class="footer__link" href="https://policies.google.com/privacy">{{ 'i18n.footer.privacy' | i18n(locale) }}</a> - <a role="listitem" class="footer__link" href="https://policies.google.com/terms">{{ 'i18n.footer.terms' | i18n(locale) }}</a> - </div> + <ul role="list"> + <li role="listitem"><a class="footer__link" href="https://www.google.com/chrome/">Chrome</a></li> + <li role="listitem"><a class="footer__link" href="https://firebase.google.com">Firebase</a></li> + <li role="listitem"><a class="footer__link" href="https://developers.generativeai.google/">Generative AI</a></li> + <li role="listitem"><a class="footer__link" href="https://developers.google.com/products">{{ 'i18n.footer.all_products' | i18n(locale) }}</a></li> + <li role="listitem"><a class="footer__link" href="https://policies.google.com/privacy">{{ 'i18n.footer.privacy' | i18n(locale) }}</a></li> + <li role="listitem"><a class="footer__link" href="https://policies.google.com/terms">{{ 'i18n.footer.terms' | i18n(locale) }}</a></li> + </ul> </div> <language-select current="{{ locale }}" supported="{{ site.locales }}"></language-select> </div> diff --git a/site/_includes/partials/navigation-rail.njk b/site/_includes/partials/navigation-rail.njk index 79bdcb99e..9940b7b1b 100644 --- a/site/_includes/partials/navigation-rail.njk +++ b/site/_includes/partials/navigation-rail.njk @@ -6,17 +6,13 @@ {{ icon('close', {hidden: true}) }} </button> <div class="display-flex pad-left-200 pad-right-200"> - <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" width="36" height="36"> - <use href="#chromeLogo" /> + <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" width="220" height="36"> + <use href="#devsiteChromeLogo" /> </svg> - <div class="logo__text logo__text-small"> - <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" width="190" height="36"> - <use href="#chromeDevelopersText" /> - </svg> - </div> </div> </div> <div class="navigation-rail__links display-flex direction-column pad-top-300 pad-right-200 lg:pad-right-0"> + {% for name, item in nav.rail %} {# Because the item url comes from the _data directory, it doesn't have a locale prefix. diff --git a/site/_includes/partials/top-nav.njk b/site/_includes/partials/top-nav.njk index bccb0dbf6..4701c13ec 100644 --- a/site/_includes/partials/top-nav.njk +++ b/site/_includes/partials/top-nav.njk @@ -3,9 +3,9 @@ <top-nav role="banner" class="display-block hairline-bottom" data-side-nav-inert> <a href="#main-content" class="color-primary visually-hidden skip-link">{{ 'i18n.common.skip_to_content' | i18n(locale) }}</a> - <nav class="display-grid align-center" aria-label="{{ 'i18n.common.chrome_developers' | i18n(locale) }}" role="search"> + <nav class="align-center display-grid" aria-label="{{ 'i18n.common.chrome_developers' | i18n(locale) }}" role="navigation"> {# Hamburger button #} - <button class="top-nav__hamburger button display-flex lg:display-none align-center justify-content-center width-700 height-700" aria-label="{{ 'i18n.common.menu' | i18n(locale) }}"> + <button class="dcc-hamburger top-nav__hamburger button display-flex lg:display-none align-center justify-content-center width-700 height-700" aria-label="{{ 'i18n.common.menu' | i18n(locale) }}"> {{ icon('hamburger', {hidden: true}) }} </button> @@ -14,10 +14,7 @@ without also updating there #} <div class="top-nav__logo display-flex justify-content-start"> <a class="display-inline-flex" href="/" aria-label="developer.chrome.com"> - {{ icon('logo', {id: 'chromeLogo', hidden: true}) }} - <div class="logo__text"> - {{ icon('logo-lockup', {id: 'chromeDevelopersText', hidden: true}) }} - </div> + {{ icon('devsite-logo', {id: 'devsiteChromeLogo', hidden: true}) }} </a> </div> @@ -25,11 +22,19 @@ <search-box class="display-grid align-center" locale="{{locale}}" + role="search" buttonLabel="{{ 'i18n.common.open_search' | i18n(locale) }}" docsLabel="{{ 'i18n.common.documentation' | i18n(locale) }}" articlesLabel="{{ 'i18n.common.articles' | i18n(locale) }}" blogLabel="{{ 'i18n.common.blog' | i18n(locale) }}" placeholder="{{'i18n.common.search_placeholder' | i18n(locale)}}" ></search-box> + + <nav class='dcc-top-menu'> + <a href='/tags/case-study' class='no-visited'>{{ 'i18n.nav.side_nav.getInspired' | i18n(locale) }}</a> + <a href='/docs' class='no-visited'>{{ 'i18n.nav.side_nav.docs' | i18n(locale) }}</a> + <a href='/blog' class='no-visited'>{{ 'i18n.nav.side_nav.blog' | i18n(locale) }}</a> + <a href='/articles' class='no-visited'>{{ 'i18n.nav.side_nav.articles' | i18n(locale) }}</a> + </nav> </nav> </top-nav> diff --git a/site/_scss/_global.scss b/site/_scss/_global.scss index ae9201e7c..a09191291 100644 --- a/site/_scss/_global.scss +++ b/site/_scss/_global.scss @@ -32,9 +32,15 @@ --flow-space: #{get-size(500)}; } +html { + scroll-behavior: smooth; +} + body { background-color: var(--color-bg); color: var(--color-text); + -moz-osx-font-smoothing: grayscale; + -webkit-font-smoothing: antialiased; // Allow normally unbreakable words to be broken at arbitrary points if // there are no otherwise acceptable break points in the line. // Soft wrap opportunities introduced by the word break are NOT considered diff --git a/site/_scss/blocks/_announcement-banner.scss b/site/_scss/blocks/_announcement-banner.scss index e30d0d80f..fb8911650 100644 --- a/site/_scss/blocks/_announcement-banner.scss +++ b/site/_scss/blocks/_announcement-banner.scss @@ -7,8 +7,11 @@ announcement-banner[hidden] { } announcement-banner { - [data-banner-close-btn] { + &:not(.cookie-banner) [data-banner-close-btn] { + line-height: 1.125rem; + margin: -0.5rem 1rem -0.4rem 0; opacity: 0; + padding: 0 0.5rem; pointer-events: none; } @@ -17,5 +20,13 @@ announcement-banner { opacity: 1; pointer-events: auto; } + + [data-banner-close-btn]:hover { + border: 0; + } + } + + p { + margin: 0; } } diff --git a/site/_scss/blocks/_banner.scss b/site/_scss/blocks/_banner.scss index d11a45cdc..474624022 100644 --- a/site/_scss/blocks/_banner.scss +++ b/site/_scss/blocks/_banner.scss @@ -29,17 +29,24 @@ } &__text { + margin: auto; max-width: 65ch; + text-align: center; + + @include media-query('lg') { + text-align: left; + } } &__actions { display: flex; - justify-content: flex-end; + justify-content: center; margin-top: get-size(300); white-space: nowrap; @include media-query('lg') { align-items: flex-end; + justify-content: flex-end; margin-left: get-size(300); margin-top: 0; } diff --git a/site/_scss/blocks/_cookie-banner.scss b/site/_scss/blocks/_cookie-banner.scss index 141c24c13..b0b8662e2 100644 --- a/site/_scss/blocks/_cookie-banner.scss +++ b/site/_scss/blocks/_cookie-banner.scss @@ -22,12 +22,12 @@ margin-top: get-size(300); @include media-query('md') { - margin-left: get-size(400); + margin-left: get-size(300); margin-top: 0; } > button { - margin-bottom: get-size(300); + margin: get-size(100) 1rem get-size(100) 0; min-width: 8rem; } } diff --git a/site/_scss/blocks/_scaffold.scss b/site/_scss/blocks/_scaffold.scss index 44e0e85d1..2011bbedb 100644 --- a/site/_scss/blocks/_scaffold.scss +++ b/site/_scss/blocks/_scaffold.scss @@ -5,12 +5,12 @@ .scaffold { display: grid; height: 100vh; - grid-template-columns: auto 1fr; grid-template-rows: auto 1fr auto; + grid-template-columns: 1fr; grid-template-areas: - 'header header' - 'sidebar main' - 'sidebar footer'; + 'header' + 'main' + 'footer'; } .scaffold > * { diff --git a/site/_scss/blocks/_search-box.scss b/site/_scss/blocks/_search-box.scss index 5a23412d0..be91dc99b 100644 --- a/site/_scss/blocks/_search-box.scss +++ b/site/_scss/blocks/_search-box.scss @@ -1,6 +1,17 @@ search-box { min-height: $search-box-height; position: relative; + + input[type='text'] { + background-color: get-color('grey-100'); + border: 1px solid get-color('grey-200'); + border-radius: 0; + color: get-color('grey-700'); + font-family: 'Google Sans', sans-serif; + font-size: 1rem; + height: 40px; + padding-left: 3rem; + } } search-box[active] { @@ -29,14 +40,35 @@ search-box[active] { @extend %button; @include apply-utility('stack', '400'); align-items: center; - display: flex; + color: get-color('grey-700'); + display: inline-block; + font-family: 'Google Sans', sans-serif; height: 100%; justify-content: center; + line-height: get-size(400); + margin-top: 0; + padding: 0; width: get-size(700); > svg { fill: currentColor; } + + &:hover { + border: 0; + color: get-color('grey-700'); + } + + &:focus, + &:active { + background-color: transparent; + border: 0; + box-shadow: none; + } + + @media (max-width: 1280px) { + width: 3.5rem; + } } .search-box__input { diff --git a/site/_scss/blocks/_side-nav.scss b/site/_scss/blocks/_side-nav.scss index eed3d6f78..9e5b09c56 100644 --- a/site/_scss/blocks/_side-nav.scss +++ b/site/_scss/blocks/_side-nav.scss @@ -1,5 +1,6 @@ $side-nav-transition-speed: 0.2s; $side-nav-transition-ease: cubic-bezier(0.4, 0, 0.2, 1); +$devsite-text-link: #3982f7; // We always want the entirety of the side-nav.scss to be inlined in the page // so we tell purgecss to "ignore" it—in other words "don't purge it". @@ -96,6 +97,24 @@ side-nav[animating] { } } +side-nav .navigation-rail { + &__close { + border: 0; + color: var(--color-secondary-text); + margin: 0; + padding: 0; + } + + &__link { + color: var(--color-secondary-text); + font-weight: 500; + + &[data-state='active'] { + color: $devsite-text-link; + } + } +} + side-nav[view='project'] { navigation-rail { opacity: 0; @@ -113,6 +132,22 @@ side-nav[view='site'] { navigation-rail { opacity: 1; transform: translate(0, 0); + + &__close { + border: 0; + color: var(--color-secondary-text); + margin: 0; + padding: 0; + } + + &__link { + color: var(--color-secondary-text); + font-weight: 500; + } + + &__link[data-state='active'] { + color: $devsite-text-link; + } } navigation-tree { diff --git a/site/_scss/blocks/_top-nav.scss b/site/_scss/blocks/_top-nav.scss index 7286403fe..c4e231fd3 100644 --- a/site/_scss/blocks/_top-nav.scss +++ b/site/_scss/blocks/_top-nav.scss @@ -1,3 +1,5 @@ +$devsite-text-link: #3982f7; + top-nav { padding: map-get($top-nav-padding, 'sm'); @@ -10,11 +12,34 @@ top-nav { grid-template-columns: min-content auto min-content; position: relative; + @media (max-width: 1280px) { + gap: get-size(300); + } + @include media-query('lg') { gap: get-size(800); - grid-template-columns: 1fr 2fr 1fr; } } + + > nav[role='search'] { + gap: 4.5rem; + grid-template-columns: 1fr 6fr 2fr; + position: relative; + + @media (max-width: 1280px) { + gap: 2.5rem; + } + + @media (max-width: 991px) { + gap: 0; + grid-template-columns: 1fr 1fr; + } + } + + .top-nav__logo { + align-items: center; + height: 44px; + } } top-nav[data-search-active] { @@ -23,7 +48,6 @@ top-nav[data-search-active] { // so the search can take the full width of the top-nav. @include media-query('lg-max') { nav { - grid-template-columns: 1fr; padding: 0 get-size(400); } @@ -33,6 +57,26 @@ top-nav[data-search-active] { } } + > nav[role='search'] { + gap: 4.5rem; + grid-template-columns: 1fr 2fr 1fr; + + @media (max-width: 1280px) { + grid-template-columns: 1fr 3fr 1fr; + } + + @media (max-width: 991px) { + grid-template-columns: 1fr; + } + } + + .top-nav__hamburger, + .top-nav__logo, + .dcc-top-menu { + height: 0; + opacity: 0; + } + // Recreate the hairline that appears at the bottom of the top-nav. // This will appear above the overlay, in between the search box and the // search results. @@ -60,4 +104,152 @@ top-nav[data-search-active] { position: absolute; top: 0; } + + search-box[active] { + order: 0; + + + .dcc-top-menu::before { + display: none; + } + + .search-box__inner { + margin: 0; + } + } + + .search-box__btn input[type='text'] { + padding-left: 1.5rem; + } + + @media (max-width: 992px) { + search-box[active] .search-box__inner { + margin-top: 0.3125rem; + } + } +} + +search-box { + min-width: 20rem; + order: 1; + + .search-box__btn { + color: get-color('grey-700'); + display: inline-block; + margin-top: 0; + padding: 0; + + &:hover { + border: 0; + color: get-color('grey-700'); + } + + &:focus, + &:active { + background-color: transparent; + border: 0; + box-shadow: none; + } + } + + @media (max-width: 840px) { + font-size: 1.125rem; + font-weight: 400; + line-height: 1.875rem; + min-width: auto; + } + + @media (max-width: 991px) { + &:not([active]) .search-box__btn { + position: absolute; + right: 0; + } + } + + @media (max-width: 480px) { + min-width: auto; + } +} + +.dcc-hamburger.button { + border: 0; + color: get-color('grey-700'); + display: none; + line-height: 1; + margin: 0 1.375rem 0 0; + padding: 0; + width: 2.325rem; + + &:hover, + &:active, + &:focus { + border: 0; + color: get-color('grey-700'); + } + + @media (max-width: 840px) { + display: block; + } +} + +.dcc-top-menu { + display: flex; + flex: 1; + justify-content: flex-start; + margin-top: 0.05rem; + + a { + color: get-color('grey-700'); + font-family: 'Google Sans', sans-serif; + font-size: 0.9375em; + font-weight: 500; + letter-spacing: 0.25px; + line-height: 1.25rem; + text-decoration: none; + + &:hover, + &:active, + &:focus { + color: $devsite-text-link; + text-decoration: none; + } + } +} + +@media (max-width: 1280px) { + top-nav nav { + gap: 2.5rem; + } +} + +@media (max-width: 991px) { + top-nav { + padding: 0.125rem 0.75rem; + + .dcc-hamburger.button { + display: block; + position: absolute; + } + + .top-nav__logo { + margin-left: 3.5rem; + + @media (max-width: 480px) { + margin-left: 3rem; + } + } + + .dcc-top-menu { + display: none; + } + } + + .scaffold { + display: block; + } +} + +@media (max-width: 840px) { + top-nav nav { + gap: 0; + } } diff --git a/site/_scss/globals/_vars.scss b/site/_scss/globals/_vars.scss index 39f161428..816178569 100644 --- a/site/_scss/globals/_vars.scss +++ b/site/_scss/globals/_vars.scss @@ -13,8 +13,8 @@ $blog-card-size: #{px-to-rem(378px)}; // The padding for the top-nav is shared by the search-box when it goes // full screen. $top-nav-padding: ( - 'sm': (#{px-to-rem(8px)}), - 'lg': (#{px-to-rem(10px)} #{px-to-rem(24px)}), + 'sm': 0.5rem 1rem, + 'lg': 0.5rem 1.5rem, ); $search-box-height: #{px-to-rem(44px)}; diff --git a/site/_scss/layouts/devsite-theme.scss b/site/_scss/layouts/devsite-theme.scss new file mode 100644 index 000000000..e232e0d90 --- /dev/null +++ b/site/_scss/layouts/devsite-theme.scss @@ -0,0 +1,754 @@ +/* stylelint-disable */ + +$CHROME_BLUE: #006bee; +$CHROME_GREEN: #4da949; +$CHROME_RED: #ea3323; +$CHROME_YELLOW: #f5b840; + +$BG_PRIMARY: #f6f9ff; + +$TEXT_PRIMARY_FONT_FAMILY: '"Google Sans", sans-serif'; +$TEXT_PRIMARY: #000; +$TEXT_PRIMARY_PALEBLUE: #3a3a3a; +$TEXT_SECONDARY: #5f6368; +$TEXT_LINK: #006bee; +$TEXT_BOLD_WEIGHT: 600; +$TEXT_WEIGHT: 500; +$TEXT_LETTER_SPACING: -0.03125rem; + +$H1_FONT: #{$TEXT_BOLD_WEIGHT} 2.5rem #{$TEXT_PRIMARY_FONT_FAMILY}; +$H2_FONT: #{$TEXT_WEIGHT} 2.25rem/2.75rem #{$TEXT_PRIMARY_FONT_FAMILY}; +$H2_LETTER_SPACING: -0.5px; +$H2_MARGIN: 0 0 1.3rem 0; +$H3_FONT: #{$TEXT_WEIGHT} 2rem #{$TEXT_PRIMARY_FONT_FAMILY}; + +$BUTTON_BG: transparent; +$BUTTON_BORDER: 2px solid #{$TEXT_LINK}; +$BUTTON_BORDER_RADIUS: 2.75rem; +$BUTTON_FONT: 500 1rem/1.3125rem #{$TEXT_PRIMARY_FONT_FAMILY}; +$BUTTON_LETTER_SPACING: 0.5px; +$BUTTON_LINE_HEIGHT: 1.3125rem; +$BUTTON_MARGIN: 1rem 0 0 0; +$BUTTON_MARGIN_MOBILE: 1.5rem 0 0; +$BUTTON_PADDING: 0.8125rem 2.5rem; +$BUTTON_PADDING_MOBILE: 0.8125rem 1rem; +$BUTTONS_MARGIN: 1.5rem 0 0 -0.75rem; + +$CARD_BORDER_RADIUS: 1.5rem; +$CARD_GAP: 1.5rem; +$CARD_BORDER: 2px solid #eef4ff; + +$DESCRIPTION_FONT: 1.125rem/1.875rem #{$TEXT_PRIMARY_FONT_FAMILY}; +$DESCRIPTION_MARGIN: 1.325rem 0 0 0; + +$HEADER_ICON_SIZE: 2rem; + +$LABEL_FONT: 700 0.875rem/1.719rem #{$TEXT_PRIMARY_FONT_FAMILY}; +$LABEL_LETTER_SPACING: 0.1rem; + +$ROW_PADDING: 3.5rem 0; +$ROW_PADDING_MOBILE: 0 1.875rem; + +/* fallback Material Icons */ +@font-face { + font-display: swap; + font-family: 'Material Icons'; + font-style: normal; + font-weight: 400; + src: url('https://fonts.gstatic.com/s/materialicons/v140/flUhRq6tzZclQEJ-Vdg-IuiaDsNcIhQ8tQ.woff2') format('woff2'); +} +/* fallback Material Icons Outlined */ +@font-face { + font-display: swap; + font-family: 'Material Icons Outlined'; + font-style: normal; + font-weight: 400; + src: url('https://fonts.gstatic.com/s/materialiconsoutlined/v109/gok-H7zzDkdnRel8-DQ6KAXJ69wP1tGnf4ZGhUcel5euIg.woff2') format('woff2'); +} + +.material-icons { + direction: ltr; + display: inline-block; + font-family: 'Material Icons'; + font-size: 24px; + -webkit-font-smoothing: antialiased; + font-style: normal; + font-weight: normal; + letter-spacing: normal; + line-height: 1; + text-transform: none; + white-space: nowrap; + word-wrap: normal; +} + +.material-icons-outlined { + direction: ltr; + display: inline-block; + font-family: 'Material Icons Outlined'; + font-size: 24px; + -webkit-font-smoothing: antialiased; + font-style: normal; + font-weight: normal; + letter-spacing: normal; + line-height: 1; + text-transform: none; + white-space: nowrap; + word-wrap: normal; +} + +[theme="web-theme"] { + --devsite-background-4: #fff; + --devsite-background-color: #{$BG_PRIMARY}; + --devsite-button-background: #{$BUTTON_BG}; + --devsite-button-background-hover: #{$BUTTON_BG}; + --devsite-button-border: #{$BUTTON_BORDER}; + --devsite-button-border-hover: #{$BUTTON_BORDER}; + --devsite-button-border-radius: #{$BUTTON_BORDER_RADIUS}; + --devsite-button-color: #{$TEXT_LINK}; + --devsite-button-font: #{$BUTTON_FONT}; + --devsite-button-height: auto; + --devsite-button-letter-spacing: #{$BUTTON_LETTER_SPACING}; + --devsite-button-line-height: #{$BUTTON_LINE_HEIGHT}; + --devsite-button-margin: #{$BUTTON_MARGIN}; + --devsite-button-padding: #{$BUTTON_PADDING}; + --devsite-button-primary-background: #{$CHROME_BLUE}; + --devsite-button-text-transform: none; + --devsite-buttons-margin: #{$BUTTONS_MARGIN}; + --devsite-card-background: #{$BG_PRIMARY}; + --devsite-card-border: none; + --devsite-card-border-radius: #{$CARD_BORDER_RADIUS}; + --devsite-description-content-font: #{$DESCRIPTION_FONT}; + --devsite-heading-color: #{$TEXT_PRIMARY}; + --devsite-h1-font: #{$H1_FONT}; + --devsite-h1-letter-spacing: #{$TEXT_LETTER_SPACING}; + --devsite-h2-font: #{$H2_FONT}; + --devsite-h2-letter-spacing: #{$H2_LETTER_SPACING}; + --devsite-h2-margin: #{$H2_MARGIN}; + --devsite-h3-font: #{H3_FONT}; + --devsite-header-icon-size: #{$HEADER_ICON_SIZE}; + --devsite-heading-color: #{$TEXT_PRIMARY}; + --devsite-landing-row-group-margin: 0; + --devsite-landing-row-header-text-margin: 0 auto; + --devsite-landing-row-header-text-max-width: 57.8125rem; + --devsite-landing-row-padding: #{$ROW_PADDING}; + --devsite-item-body-display: block; + --devsite-item-description-margin: #{$DESCRIPTION_MARGIN}; + --devsite-item-gap: #{$CARD_GAP}; + --devsite-item-text-padding: 0; + --devsite-label-font: #{$LABEL_FONT}; + --devsite-label-letter-spacing: #{$LABEL_LETTER_SPACING}; + --devsite-primary-font-family: #{$TEXT_PRIMARY_FONT_FAMILY}; + --devsite-primary-text-color: #{$TEXT_PRIMARY}; + --devsite-text-color: #{$TEXT_PRIMARY}; + --link-color: #{$TEXT_PRIMARY}; + --link-rgb-background: #{$BUTTON_BG}; + --link-visited-color: #{$TEXT_PRIMARY}; + --rgb-button-overlay: #{$TEXT_LINK}; + --devsite-link-color: #{$TEXT_LINK};; + --devsite-landing-row-max-width: 1280px; + + + @media (max-width: 591px) { + --devsite-button-padding: #{$BUTTON_PADDING_MOBILE}; + --devsite-buttons-margin: #{$BUTTON_MARGIN_MOBILE}; + --devsite-landing-group-padding: 0; + --devsite-landing-row-padding: #{$ROW_PADDING_MOBILE}; + } + + a:not([class]){ + text-decoration: none; + + &:hover { + text-decoration: underline; + } + } + + .material-icons { + background-color: $CHROME_BLUE; + border-radius: 100%; + color: #fff; + display: inline; + padding: 0.46875rem; + position: relative; + top: 0.5rem; + } + + .dcc-icon-button::before { + font-family: "Material Icons Outlined"; + font-size: 1.3rem; + margin-top: -0.325rem; + padding-right: 0.5rem; + vertical-align: middle; + } + + .dcc-web-app-features-link::before { + content: "widgets"; + } + .dcc-web-on-android-link::before { + content: "android"; + } + + .dcc-chrome-extensions-link::before { + content: "extension"; + } + + .dcc-cwv-link::before { + content: "display_settings"; + } + + .dcc-design-link::before { + content: "toggle_on"; + } + + .dcc-privacy-link::before { + content: "lock"; + } + + .dcc-identity-link::before { + content: "badge"; + } + + .dcc-dev-tools-link::before { + content: "build"; + } + + .dcc-performance-link::before { + content: "construction"; + } + + .dcc-puppeteer-link::before { + content: "data_object"; + } + + .dcc-chrome-testing-link::before { + content: "science"; + } + + .dcc-baseline-link::before { + content: url("data:image/svg+xml, %3Csvg width='20' height='11' viewBox='0 0 20 11' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cg id='Layer_1' clip-path='url(%23clip0_399_7980)'%3E%3Cpath id='Vector' d='M14.3855 11L11.258 7.93623L12.4894 6.72949L14.3855 8.587L17.5368 5.5L14.3855 2.413L10.3634 6.35315H10.358L5.61448 11L0 5.5L5.61448 0L8.72363 3.04576L7.49226 4.25203L5.61448 2.413L2.46323 5.5L5.61448 8.587L9.63664 4.64685H9.64196L14.3855 0L20 5.5L14.3855 11Z' fill='%233982F7'/%3E%3C/g%3E%3Cdefs%3E%3CclipPath id='clip0_399_7980'%3E%3Crect width='20' height='11' fill='white'/%3E%3C/clipPath%3E%3C/defs%3E%3C/svg%3E%0A"); + vertical-align: baseline; + } + + .dcc-aurora-link::before { + content: "offline_bolt"; + } + + .dcc-webdev-link::before { + content: url("data:image/svg+xml, %3Csvg xmlns='http://www.w3.org/2000/svg' height='20' viewBox='0 -960 960 960' fill='%233982F7' width='22'%3E%3Cpath d='M146.666-160q-27 0-46.833-19.833T80-226.666v-506.668q0-27 19.833-46.833T146.666-800h666.668q27 0 46.833 19.833T880-733.334v506.668q0 27-19.833 46.833T813.334-160H146.666Zm0-66.666h666.668v-424.001H146.666v424.001ZM300-288l-46.666-46.667 103-104-104-104L300-589.333l150.666 150.666L300-288Zm186.667 2.667V-352h226.666v66.667H486.667Z'/%3E%3C/svg%3E"); + margin-top: 0; + } + + .dcc-blog-card { + --devsite-buttons-margin: 0.5rem 0 0 -0.75rem; + --devsite-item-gap: 0; + + padding: 5rem 2.125rem 3rem; + + .devsite-landing-row-item-labels span { + position: absolute; + top: 2.25rem; + } + + img { + border-radius: #{$CARD_BORDER_RADIUS}; + } + + &[description-position=left] { + align-items: flex-start; + } + + &[description-position=bottom] { + padding: 5rem 1.125rem 3rem; + + figure{ + margin-bottom: 1rem; + padding: 0 1rem; + } + } + + @media (max-width: 1280px) { + &[description-position=left] { + flex-direction: row-reverse; + } + } + + @media (max-width: 840px) { + padding-left: 1rem; + + figure { + margin-bottom: 1.5rem; + } + + &[description-position=left], + &[description-position=right] { + align-items: center; + justify-content: space-between; + flex-direction: row; + } + } + + @media (max-width: 591px) { + &[description-position=left] figure img, + &[description-position=right] figure img, + figure img { + height: 13.75rem; + object-fit: cover; + object-position: center; + } + } + } + + .dcc-services-card { + --devsite-button-border-radius: 0; + --devsite-button-padding: 0; + --devsite-buttons-margin: auto; + --devsite-buttons-padding: 1rem 0 0 0; + --devsite-h2-font: 500 1.8rem #{$TEXT_PRIMARY_FONT_FAMILY}; + --devsite-h2-margin: 1.6875rem auto auto; + --devsite-item-gap: 0; + --devsite-item-media-container-width: 11rem; + --devsite-item-media-margin: 0 auto; + + margin-bottom: 2rem; + padding: 2.8rem 2.5rem; + + h3 { + max-width: 90%; + min-height: 8.75rem; + text-align: center; + + @media (max-width: 840px) { + min-height: 6rem; + } + + @media (max-width: 591px) { + min-height: auto; + } + } + + h3 + div { + align-items: start; + flex-direction: column; + max-width: 12.5rem; + } + + @media (max-width: 1440px) and (min-width: 1280px) { + --devsite-h2-font: 500 1.875rem #{$TEXT_PRIMARY_FONT_FAMILY}; + } + + @media (max-width: 840px) { + --devsite-button-font: 1.125rem #{$TEXT_PRIMARY_FONT_FAMILY}; + --devsite-h2-font: 500 1.75rem #{$TEXT_PRIMARY_FONT_FAMILY}; + margin-bottom: 0; + } + } + + .dcc-docs-card { + --devsite-item-border-radius: #{$CARD_BORDER_RADIUS}; + --devsite-item-gap: 0; + --devsite-item-image-width: 8rem; + --devsite-buttons-margin: 0.5rem 0 0 -0.75rem; + + border: #{$CARD_BORDER}; + max-width: 24.75rem; + padding: 2.125rem; + margin-bottom: 1.3rem; + + @media (max-width: 840px) { + --devsite-h2-font: 500 1.5rem #{$TEXT_PRIMARY_FONT_FAMILY}; + } + + @media (max-width: 591px) { + max-width: 100%; + margin-bottom: 0; + } + } + + .dcc-social-card { + --devsite-buttons-margin: 1rem 0; + --devsite-h2-font: 500 2rem #{$TEXT_PRIMARY_FONT_FAMILY}; + --devsite-item-gap: 0rem; + --devsite-item-image-width: 3rem; + --devsite-item-media-margin: 0 0 0.875rem 0; + --devsite-item-media-padding: 0 1rem; + --devsite-item-text-padding: 0; + + padding: 2.5rem 1.5rem 1.5rem; + + h3 { + text-align: left; + } + + .button { + margin: 0; + padding:0; + } + + @media (max-width: 840px) { + --devsite-h2-font: 500 1.5rem #{$TEXT_PRIMARY_FONT_FAMILY}; + } + } + + .dcc-hero { + --devsite-button-background: #{$TEXT_LINK}; + --devsite-button-background-hover: #{$TEXT_LINK}; + --devsite-button-color: #fff; + --devsite-button-padding: 0.75rem 1.5rem; + --devsite-description-content-font: 1.3rem/1.875rem #{$TEXT_PRIMARY_FONT_FAMILY}; + --devsite-h2-font: 700 4rem/4.5rem #{$TEXT_PRIMARY_FONT_FAMILY}; + --devsite-landing-row-padding: 3rem 0 0; + --devsite-item-gap: 0; + + + text-align: center; + + + h3 span { + color: #{$TEXT_LINK}; + } + + .button { + margin: 0 auto; + z-index: 1; + } + + figure { + margin: -3rem auto 6rem; + } + + @media (max-width: 840px) { + --devsite-description-content-font: 400 1.125rem/1.875rem #{$TEXT_PRIMARY_FONT_FAMILY}; + --devsite-h2-font: 700 3.125rem #{$TEXT_PRIMARY_FONT_FAMILY}; + --devsite-item-display: flex; + + [description-position]{ + flex-direction: column-reverse; + } + + figure { + margin: -1rem auto 4rem; + } + + h3 span { + display: block; + } + } + + @media (max-width: 591px) { + --devsite-h2-font: 700 2.25rem #{$TEXT_PRIMARY_FONT_FAMILY}; + --devsite-item-description-margin: 0; + --devsite-buttons-padding: 2.5rem 0 0; + + .button { + font-size: 1rem; + margin-bottom: 3rem; + } + } + } + + .dcc-featured { + --devsite-h2-font: 700 1.875rem/2.365rem #{$TEXT_PRIMARY_FONT_FAMILY}; + + @media (max-width: 1280px) { + --devsite-landing-row-group-grid: 2 1; + --devsite-h2-font: 500 1.5rem #{$TEXT_PRIMARY_FONT_FAMILY}; + + .dcc-blog-card { + margin-bottom: 2rem; + + &[description-position=left] { + @media (max-width: 591px) { + figure { + padding: 0 1rem; + } + } + } + } + } + + @media (max-width: 591px) { + --devsite-card-border-radius: 0; + --devsite-landing-group-padding: 0; + } + } + + .dcc-case-studies { + --devsite-landing-row-group-background: #{$BG_PRIMARY}; + --devsite-landing-row-group-border-radius: #{$CARD_BORDER_RADIUS}; + --devsite-landing-row-group-max-width: 90rem; + --devsite-landing-row-group-padding: 2rem 1rem 1rem; + --devsite-item-gap: 0; + + [description-position=bottom] { + --devsite-item-gap: 0; + --devsite-item-media-margin: 0 0 0 1rem; + --devsite-buttons-margin: 0.5rem 0 0 -0.75rem; + padding: 2.125rem; + + &:first-child { + --devsite-item-image-width: 2.5rem; + --devsite-item-media-container-width: 2.5rem; + --devsite-item-text-align: left; + --devsite-h2-font: 700 2.5rem/3rem #{$TEXT_PRIMARY_FONT_FAMILY}; + + padding-right: 0; + padding-top: 1rem; + + figure { + margin-bottom: 0.25rem; + } + + @media (max-width: 1290px) { + grid-column: 1 / span 3; + } + + @media (max-width: 840px) { + --devsite-h2-font: 700 1.75rem #{$TEXT_PRIMARY_FONT_FAMILY}; + padding: 1.125rem 0; + } + } + + &:last-child { + --devsite-h2-font: 500 2rem/2.375rem #{$TEXT_PRIMARY_FONT_FAMILY}; + padding-left: 0; + padding-top:4rem; + + @media (max-width: 1290px) { + grid-column: 2 / span 2; + padding-top: 0; + + --devsite-h2-font: 500 1.5rem #{$TEXT_PRIMARY_FONT_FAMILY}; + } + + @media (max-width: 840px) { + padding: 0; + grid-column: 1/span2; + } + } + + @media (max-width: 840px) { + padding: 1.125rem; + grid-column: 1 / span 3; + } + + } + + [description-position=top] { + --devsite-description-content-font: 0 #{$TEXT_PRIMARY_FONT_FAMILY}; + + display: block; + padding: 5rem 1rem 0rem; + + figure { + padding: 0 0 0 1rem; + } + + @media (max-width: 1290px) { + padding-top: 2.5rem; + + .devsite-landing-row-item-labels span { + top: 0; + } + } + + @media (max-width: 840px) { + padding: 2.5rem 1.125rem 0; + grid-column: 1 / span 3; + + > div:last-child { + padding: 0; + } + + figure { + margin-bottom: 0; + padding: 0 0 1rem 0; + } + } + } + + @media (max-width: 591px) { + --devsite-landing-group-margin: 0 0 2rem 0; + --devsite-landing-group-padding: 0; + --devsite-landing-row-group-border-radius: 0; + padding: 0; + } + + } + + .dcc-chrome-releases { + --devsite-landing-row-header-max-width: 17.5625rem; + --devsite-landing-row-header-padding: 0.5rem 0; + + position: relative; + + .dcc-blog-card { + max-width: 24.75rem; + padding: 0; + + figure{ + margin-bottom: 0; + padding: 0; + } + + img{ + height: 12.5rem; + object-fit: cover; + } + } + + @media (max-width: 992px) { + &[header-position=left] > div { + display: block; + + header + div { + margin-top: 32px; + } + + .dcc-blog-card { + max-width: 100%; + } + } + } + + @media (max-width: 840px) { + --devsite-h1-font: 700 1.75rem #{$TEXT_PRIMARY_FONT_FAMILY}; + --devsite-h2-font: #{$TEXT_WEIGHT} 1.5rem #{$TEXT_PRIMARY_FONT_FAMILY}; + --devsite-landing-row-group-grid-column: 1 / span 3; + --devsite-landing-row-header-grid-column: 1 / span 3; + --devsite-landing-row-header-max-width: 100%; + } + + @media (max-width: 591px) { + --devsite-h1-font: 700 1.5625rem #{$TEXT_PRIMARY_FONT_FAMILY}; + + .dcc-blog-card { + max-width: 100%; + margin-bottom: 2rem; + } + } + } + + .dcc-docs { + --devsite-landing-group-padding: 4.6875rem 1.5rem 0; + --devsite-landing-group-margin: 1.5rem auto; + --devsite-landing-row-header-padding: 0.5rem 0; + --devsite-buttons-margin: 0.5rem 0 0 0; + --devsite-item-gap: 2.5rem; + + position: relative; + + &::before { + background: linear-gradient( + 92deg, + #fb0301 0%, + #fb0301 10.94%, + #fbbb06 19.79%, + #fbbb06 37.5%, + #34a653 60.42%, + #34a653 76.56%, + #206ace 100% + ); + content: ""; + height: 3px; + left: 0; + position: absolute; + top: 0; + width: 100%; + } + + @media (max-width: 992px) { + &[header-position=left] > div { + display: block; + + header + div { + margin-top: 32px; + } + + .dcc-docs-card { + max-width: 100%; + } + } + } + + @media (max-width: 840px) { + --devsite-h1-font: 700 1.75rem #{$TEXT_PRIMARY_FONT_FAMILY}; + } + } + + [background="pale-blue"] { + --devsite-background-color: #{$BG_PRIMARY}; + --devsite-button-border: none; + --devsite-button-border-hover: none; + --devsite-card-background: white; + --devsite-heading-color: #{$TEXT_PRIMARY_PALEBLUE}; + --devsite-h1-font: 500 3rem #{$TEXT_PRIMARY_FONT_FAMILY}; + --devsite-landing-row-group-margin: 0; + --devsite-landing-row-header-text-margin: 0 auto 3.75rem auto; + --devsite-landing-row-header-text-max-width: 57.8125rem; + --devsite-landing-row-padding: 3.5rem 0; + + margin: 3rem 0 2.1875rem; + + h2{ + text-align: center; + } + + @media (max-width: 1280px) { + --devsite-h1-font: 500 2.25rem #{$TEXT_PRIMARY_FONT_FAMILY}; + + header + div { + grid-template-columns: 1fr 1fr; + } + } + + @media (max-width: 591px) { + --devsite-h1-font: 500 1.75rem #{$TEXT_PRIMARY_FONT_FAMILY}; + + header + div { + grid-template-columns: 1fr; + } + } + } + + .dcc-social { + --devsite-item-gap: 3.125rem; + --devsite-landing-row-header-text-margin: 0 0 2.875rem 0; + --devsite-landing-row-padding: 3.438rem 0 6.25rem; + --devsite-h1-font: 700 3rem #{$TEXT_PRIMARY_FONT_FAMILY}; + + margin: 0; + + h2 { + text-align: left; + } + + h3 + div { + color: #606367; + } + + .button { + border-radius: 0; + } + + img { + --devsite-item-image-width: 3.563rem; + } + + @media (max-width: 1280px) { + --devsite-h1-font: 700 2.5rem #{$TEXT_PRIMARY_FONT_FAMILY}; + } + + @media (max-width: 840px) { + --devsite-h1-font: 700 1.75rem #{$TEXT_PRIMARY_FONT_FAMILY}; + } + } + + footer { + margin-top: 0; + } + + .dcc-devsite-wrapper { + width: 100%; + } +} +/* stylelint-enable */ \ No newline at end of file diff --git a/site/_scss/layouts/devsite.scss b/site/_scss/layouts/devsite.scss new file mode 100644 index 000000000..84649d7dc --- /dev/null +++ b/site/_scss/layouts/devsite.scss @@ -0,0 +1,30 @@ +/* stylelint-disable */ +[theme=web-theme]{--devsite-primary-color:#3740ff;--devsite-secondary-color:#e51661}[foreground=web-theme],[theme=web-theme] [foreground=theme]{--devsite-foreground-color:#3740ff;--devsite-foreground-button-background-hover:#ebecff;--devsite-foreground-button-border-color:#dadce0;--devsite-foreground-button-border-color-hover:#cdcfff;--devsite-foreground-button-border-color-active:#ebecff;--devsite-foreground-button-color:#3740ff;--devsite-foreground-button-primary-background:#3740ff;--devsite-foreground-button-primary-background-hover:#e51661;--devsite-foreground-button-primary-color:#fff}body,dd,div,dl,figure,form,img,input,menu{margin:0;padding:0}body[no-overflow]{overflow:hidden}iframe{border:0}iframe:not([src]){display:none}.beta>:first-child,.caution>:first-child,.deprecated>:first-child,.dogfood>:first-child,.experimental>:first-child,.key-point>:first-child,.key-term>:first-child,.note>:first-child,.objective>:first-child,.preview>:first-child,.quickstart-left>:first-child,.quickstart-wide>:first-child,.special>:first-child,.success>:first-child,.warning>:first-child,aside>:first-child,blockquote>:first-child,dd>:first-child,li>p:first-child,td>.devsite-table-wrapper:first-child>table,td>.expandable:first-child>:nth-child(2),td>:first-child,td>:first-child:empty+devsite-code,td>:first-child>li:first-child{margin-top:0}.beta>:last-child,.caution>:last-child,.deprecated>:last-child,.dogfood>:last-child,.experimental>:last-child,.key-point>:last-child,.key-term>:last-child,.note>:last-child,.objective>:last-child,.preview>:last-child,.quickstart-left>:last-child,.quickstart-wide>:last-child,.special>:last-child,.success>:last-child,.warning>:last-child,aside>:last-child,blockquote>:last-child,dd>:last-child,li>p:last-child,td>.devsite-table-wrapper:last-child>table,td>.expandable:last-child>:last-child,td>:last-child,td>:last-child>li:last-child{margin-bottom:0}html{-moz-box-sizing:border-box;box-sizing:border-box}*,:after,:before{-moz-box-sizing:inherit;box-sizing:inherit}.clearfix:after,.quickstart-step:after{clear:both;content:"";display:table;height:0;visibility:hidden}:root{--devsite-code-font-family:Roboto Mono,monospace;--devsite-primary-font-family:Roboto,Noto Sans,Noto Sans JP,Noto Sans KR,Noto Naskh Arabic,Noto Sans Thai,Noto Sans Hebrew,Noto Sans Bengali,sans-serif;--devsite-h1-margin:40px 0 20px;--devsite-h2-margin:40px 0 20px;--devsite-h3-margin:32px 0 16px;--devsite-h4-font:500 16px/24px var(--devsite-primary-font-family);--devsite-h5-font:700 14px/24px var(--devsite-primary-font-family);--devsite-h6-font:500 14px/24px var(--devsite-primary-font-family);--devsite-background-0:#e8eaed;--devsite-background-1:#fff;--devsite-background-2:#f8f9fa;--devsite-background-3:#f1f3f4;--devsite-background-4:#e8eaed;--devsite-background-5:#dadce0;--devsite-primary-text-color:#202124;--devsite-primary-text-rgba:rgba(0,0,0,.87);--devsite-secondary-text-color:#5f6368;--devsite-secondary-text-rgba:rgba(0,0,0,.65);--devsite-tertiary-text-color:#bdc1c6;--devsite-tertiary-text-rgba:rgba(0,0,0,.26);--devsite-inverted-text-color:#fff;--devsite-inverted-text-color-hover:hsla(0,0%,100%,.7);--devsite-inverted-text-rgba:hsla(0,0%,100%,.7);--devsite-primary-border:1px solid #dadce0;--devsite-secondary-border:1px solid #e8eaed;--devsite-elevation-key-shadow-color:rgba(60,64,67,.3);--devsite-elevation-ambient-shadow-color:rgba(60,64,67,.15);--devsite-elevation-inset-shadow-color:hsla(210,6%,63%,.5);--tenant-background-1:#fff;--tenant-background-2:#f8f9fa;--tenant-background-3:#f1f3f4;--tenant-primary-text-color:#202124;--tenant-secondary-text-color:#5f6368;--tenant-inverted-text-color:#fff;--tenant-primary-border:1px solid #dadce0;--tenant-secondary-border:1px solid #e8eaed;--devsite-link-background:#d2e3fc;--devsite-link-background-active:#e8f0fe;--devsite-link-color:#1a73e8;--devsite-contrast-link-color:#185abc;--devsite-button-background-hover:#e4eefc;--devsite-button-background-active:#c8ddf9;--devsite-button-color:#1a73e8;--devsite-button-primary-background:#1a73e8;--devsite-button-primary-background-hover:#1765cc;--devsite-button-primary-background-active:#185abc;--devsite-button-primary-color:#fff;--devsite-caution-notice-background:#feefe3;--devsite-caution-notice-border-color:transparent;--devsite-caution-notice-color:#bf360c;--devsite-key-point-notice-background:#e8eaf6;--devsite-key-point-notice-border-color:transparent;--devsite-key-point-notice-color:#3f51b5;--devsite-key-term-notice-background:#f3e8fd;--devsite-key-term-notice-border-color:transparent;--devsite-key-term-notice-color:#9334e6;--devsite-note-notice-background:#e1f5fe;--devsite-note-notice-border-color:transparent;--devsite-note-notice-color:#01579b;--devsite-status-notice-background:#eceff1;--devsite-status-notice-border-color:transparent;--devsite-status-notice-color:#546e7a;--devsite-success-notice-background:#e0f2f1;--devsite-success-notice-border-color:transparent;--devsite-success-notice-color:#00796b;--devsite-warning-notice-background:#fce8e6;--devsite-warning-notice-border-color:transparent;--devsite-warning-notice-color:#d50000;--devsite-notice-margin:16px 0;--devsite-notice-padding-block:15px;--devsite-notice-padding-inline:60px 24px;--devsite-book-nav-background:var(--devsite-background-1);--devsite-concierge-top:48px;--devsite-concierge-width-closed:54px;--devsite-concierge-width-open:387px;--devsite-concierge-width:0px;--devsite-card-background:var(--devsite-background-1);--devsite-card-header-background:var(--devsite-background-3);--devsite-checkbox-border-radius:2px;--devsite-checkbox-icon-canvas-border-radius:50%;--devsite-checkbox-icon-canvas-offset-x:-9px;--devsite-checkbox-icon-canvas-offset-y:-9px;--devsite-checkbox-icon-canvas-size:36px;--devsite-checkbox-margin-block:-2px 2px;--devsite-checkbox-margin-inline:0 8px;--devsite-checkbox-offset-x:3px;--devsite-checkbox-offset-y:-3px;--devsite-checkbox-size:18px;--devsite-feature-tooltip-background-color:#1a73e8;--devsite-feature-tooltip-offset-y:3px;--devsite-input-background:var(--devsite-background-1);--devsite-input-border:var(--devsite-secondary-border);--devsite-item-gap:24px;--devsite-mdc-line-height:56px;--devsite-scrollbar-thumb-background:hsla(207,5%,52%,.26);--devsite-select-background-image:url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="20" height="4" viewBox="0 0 20 4"><path d="M0,0l4,4l4-4H0z" fill="%23202124"/></svg>');--devsite-select-border-radius:2px}[lang=ar],[lang=fa]{--devsite-nav-item-line-height:18px}devsite-appearance-selector{--devsite-appearance-selector-menu-transform:translate3d(-10px,0,0)}[dir=rtl] devsite-appearance-selector{--devsite-appearance-selector-menu-transform:translate3d(calc(46px - 100%),0,0)}devsite-bookmark{--devsite-bookmark-background:0;--devsite-bookmark-background-focus-legacy:var(--devsite-background-4);--devsite-bookmark-background-hover-legacy:var(--devsite-background-3);--devsite-bookmark-icon-color:var(--devsite-secondary-text-color);--devsite-bookmark-icon-color-saved:var(--devsite-link-color);--devsite-bookmark-icon-color-saved-hover:#174ea6;--devsite-dropdown-list-toggle-background-hover:var(--devsite-background-3);--devsite-dropdown-list-toggle-border:var(--devsite-primary-border,0);--devsite-dropdown-list-toggle-border-hover:var(--devsite-primary-border);--devsite-dropdown-list-toggle-height:36px}devsite-book-nav{--devsite-book-nav-input-height:32px;--devsite-nav-divider-background:#eceff1}.devsite-book-nav-toggle[aria-expanded]{--devsite-book-nav-toggle-background:var(--devsite-background-3);--devsite-book-nav-toggle-background-hover:var(--devsite-background-4)}.devsite-book-nav-toggle:not([aria-expanded]){--devsite-book-nav-toggle-background:var(--devsite-background-1);--devsite-book-nav-toggle-background-hover:var(--devsite-background-3)}devsite-carousel{--devsite-carousel-gap:16px 24px;--devsite-carousel-grid:1fr 40px/40px 1fr 40px;--devsite-carousel-item-flex:0 0 var(--devsite-carousel-item-width,auto);--devsite-carousel-marker-margin-inline:-18px 0;--devsite-carousel-marker-size:12px;--devsite-carousel-markers-gap:0 4px;--devsite-carousel-markers-grid-column:2;--devsite-carousel-markers-grid-row:2;--devsite-carousel-next-grid-column:3;--devsite-carousel-prev-grid-column:1;--devsite-carousel-prev-next-grid-row:2;--devsite-carousel-slideshow-grid-column:1/-1;--devsite-carousel-slideshow-grid-row:1}devsite-carousel[data-items-per-slide]{--devsite-carousel-item-gap:0 24px}devsite-carousel[data-items-per-slide=auto]{--devsite-carousel-item-gap:0 8px}[template=page] devsite-carousel[data-full-width],[template=page] devsite-carousel[data-items-per-slide=auto]{--devsite-carousel-gap:16px 40px;--devsite-carousel-grid:1fr 40px/0 40px 1fr 40px 0;--devsite-carousel-margin-inline:-40px;--devsite-carousel-markers-grid-column:3;--devsite-carousel-next-grid-column:4;--devsite-carousel-prev-grid-column:2;--devsite-carousel-slideshow-grid-column:1/-1;--devsite-carousel-slideshow-padding-inline:40px}[template=page] devsite-carousel[data-items-per-slide=auto]{--devsite-carousel-ghost-item-width:32px;--devsite-carousel-slideshow-scroll-padding:0 40px}devsite-catalog{--devsite-button-icon-content:"cancel";--devsite-button-icon-margin-x-end:8px;--devsite-button-icon-margin-x-start:8px;--devsite-catalog-grid:"sidebar main" 1fr/1fr 3fr;--devsite-chips-gap:8px;--devsite-dynamic-content-margin:0;--devsite-catalog-sidebar-button-display:none!important;--devsite-input-border-radius:var(--devsite-card-border-radius);--devsite-input-height:40px;--devsite-input-padding:7px 16px;--devsite-input-width:100%;--devsite-notice-margin:16px 0;--devsite-notice-padding-block:15px;--devsite-notice-padding-inline:60px 24px}[layout=docs] devsite-catalog{--devsite-catalog-grid:"sidebar main" 1fr/1fr 2fr}[layout=docs] devsite-catalog:not([items-across]),devsite-catalog[template=activity]:not([items-across]){--devsite-columns:2}devsite-catalog .catalog-filter-chip{--devsite-button-sibling-gap-x:0}[dir=ltr] devsite-catalog .catalog-filter-chip{--devsite-button-padding:0 0 0 12px}[dir=rtl] devsite-catalog .catalog-filter-chip{--devsite-button-padding:0 12px 0 0}devsite-code,devsite-content{--devsite-code-background:#f1f3f4;--devsite-code-color:#37474f;--devsite-var-color:#d01884}devsite-code{--devsite-code-buttons-toggle-dark-display:inline;--devsite-code-buttons-toggle-light-display:none;--devsite-code-comments-color:#b80672;--devsite-code-keywords-color:#1967d2;--devsite-code-numbers-color:#c5221f;--devsite-code-strings-color:#188038;--devsite-code-types-color:#9334e6;--devsite-github-link-icon:url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 18 18"><path d="M9-.06A9,9,0,0,0,6.16,17.48c.44.09.59-.19.59-.43V15.38c-2.5.54-3-1.07-3-1.07a2.35,2.35,0,0,0-1-1.31c-.82-.56.06-.55.06-.55a1.89,1.89,0,0,1,1.38.93,1.92,1.92,0,0,0,2.62.75,1.91,1.91,0,0,1,.57-1.21c-2-.23-4.1-1-4.1-4.45a3.49,3.49,0,0,1,.92-2.41,3.25,3.25,0,0,1,.09-2.38S5,3.43,6.75,4.6a8.59,8.59,0,0,1,4.5,0c1.72-1.17,2.48-.92,2.48-.92a3.25,3.25,0,0,1,.09,2.38,3.49,3.49,0,0,1,.92,2.41c0,3.46-2.1,4.22-4.11,4.44a2.14,2.14,0,0,1,.62,1.67v2.47c0,.24.14.52.6.43A9,9,0,0,0,9-.06Z" fill="%231a73e8"/></svg>')}devsite-code[dark-code]{--devsite-code-background:#283142;--devsite-code-buttons-color:hsla(0,0%,100%,.7);--devsite-code-buttons-hover:#fff;--devsite-code-buttons-toggle-dark-display:none;--devsite-code-buttons-toggle-light-display:inline;--devsite-code-color:#eceff1;--devsite-code-comments-color:#ff8bcb;--devsite-code-keywords-color:#78d9ec;--devsite-code-numbers-color:#fbc02d;--devsite-code-strings-color:#9ccc65;--devsite-code-types-color:#d7aefb;--devsite-github-link-icon:url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 18 18"><path d="M9-.06A9,9,0,0,0,6.16,17.48c.44.09.59-.19.59-.43V15.38c-2.5.54-3-1.07-3-1.07a2.35,2.35,0,0,0-1-1.31c-.82-.56.06-.55.06-.55a1.89,1.89,0,0,1,1.38.93,1.92,1.92,0,0,0,2.62.75,1.91,1.91,0,0,1,.57-1.21c-2-.23-4.1-1-4.1-4.45a3.49,3.49,0,0,1,.92-2.41,3.25,3.25,0,0,1,.09-2.38S5,3.43,6.75,4.6a8.59,8.59,0,0,1,4.5,0c1.72-1.17,2.48-.92,2.48-.92a3.25,3.25,0,0,1,.09,2.38,3.49,3.49,0,0,1,.92,2.41c0,3.46-2.1,4.22-4.11,4.44a2.14,2.14,0,0,1,.62,1.67v2.47c0,.24.14.52.6.43A9,9,0,0,0,9-.06Z" fill="%23669df6"/></svg>');--devsite-scrollbar-thumb-background:hsla(0,0%,100%,.7);--devsite-var-color:#ff8bcb}devsite-content{--devsite-compare-yes-color:#34a853;--devsite-compare-no-color:#dd2c00;--devsite-confidential-results-background:hsla(27,93%,94%,.5);--devsite-search-results-breadcrumb-color:#1e8e3e;--devsite-select-sibling-gap-x:16px;--devsite-steps-title-border-focus:1px solid #174ea6;--devsite-steps-title-color:#174ea6;--devsite-dropdown-list-border-radius:var( + --devsite-dropdown-list-toggle-border-radius + );--devsite-dropdown-list-min-width:194px;--devsite-dropdown-list-toggle-background-hover:var(--devsite-background-2);--devsite-dropdown-list-toggle-border-radius:4px;--devsite-dropdown-list-toggle-color:var(--devsite-secondary-text-color);--devsite-dropdown-list-toggle-color-hover:var(--devsite-primary-text-color);--devsite-dropdown-list-toggle-button-padding:0 3px;--devsite-dropdown-list-toogle-button-justify-content:center}devsite-device{--devsite-device-border-color:#ddd}devsite-dynamic-content{--devsite-progress-background:#dadce0;--devsite-progress-background-2:#dadce0;--devsite-progress-background-4:#dadce0;--devsite-progress-bar-color:#f9ab00}devsite-dynamic-content .completed{--devsite-progress-bar-color:#1e8e3e}devsite-dynamic-hero{--devsite-background-text-decoration:none}devsite-footer-linkboxes{--devsite-footer-linkboxes-grid-template-columns:repeat(auto-fit,minmax(85.4px,1fr));--devsite-footer-linkboxes-padding:0 24px}devsite-footer-utility devsite-language-selector{--devsite-language-selector-menu-inset-inline:auto 0;--devsite-language-selector-menu-transform:translate3d(0,calc(-100% - 36px),0)}devsite-header devsite-language-selector{--devsite-select-color:#3c4043}devsite-multiple-choice{--devsite-multiple-choice-answer-border-bottom:var(--devsite-primary-border);--devsite-multiple-choice-answer-border-top:0;--devsite-multiple-choice-background:var(--devsite-background-2);--devsite-multiple-choice-border:0;--devsite-multiple-choice-border-radius:0;--devsite-multiple-choice-correct-background:#f8fbf9;--devsite-multiple-choice-correct-color:#137333;--devsite-multiple-choice-incorrect-background:#fef9f9;--devsite-multiple-choice-incorrect-color:#d32f2f;--devsite-multiple-choice-overflow:visible;--devsite-multiple-choice-question-background:var( + --devsite-secondary-text-color + );--devsite-multiple-choice-question-color:var(--devsite-inverted-text-color)}devsite-nav-buttons{--devsite-button-primary-background-selected:#174ea6}devsite-playlist{--devsite-playlist-icon-color:#0d652d;--devsite-playlist-max-width:936px;--devsite-playlist-padding-x:40px}[type=playlist]{--devsite-card-image-object-fit:contain}devsite-playlist devsite-bookmark{--devsite-bookmark-background-focus-legacy:rgba(138,180,248,.12);--devsite-bookmark-background-hover-legacy:rgba(138,180,248,.12);--devsite-bookmark-icon-arrow-color:#dadce0;--devsite-bookmark-icon-color:#dadce0;--devsite-bookmark-icon-color-saved:#8ab4f8;--devsite-bookmark-icon-color-saved-hover:#d2e3fc;--devsite-dropdown-list-toggle-background-hover:hsla(220,9%,87%,.24);--devsite-dropdown-list-toggle-border:1px solid #5f6368;--devsite-dropdown-list-toggle-border-hover:1px solid #5f6368;--devsite-dropdown-list-toggle-color-hover:#dadce0}devsite-quiz{--devsite-quiz-correct-background:#e6f4ea;--devsite-quiz-correct-border-color:#e6f4ea;--devsite-quiz-correct-border-color-focus:#1e8e3e;--devsite-quiz-correct-color:#1e8e3e;--devsite-quiz-error-background:#fce8e6;--devsite-quiz-error-border-color:#fce8e6;--devsite-quiz-error-border-color-focus:#d93025;--devsite-quiz-error-color:#d93025;--devsite-quiz-partially-correct-background:#feefe3;--devsite-quiz-partially-correct-color:#e8710a;--devsite-quiz-partially-correct-indicator-background:orange;--devsite-quiz-secondary-text-color:#5f6368}devsite-recommendations-sidebar,devsite-recommended-content{--devsite-recommendations-accent:#01579b}devsite-recommended-content{--devsite-background-text-decoration:none;--devsite-checkbox-margin-block:0;--devsite-checkbox-margin-inline:0;--devsite-checkbox-size:0;--devsite-h1-margin:0;--devsite-h3-margin:0;--devsite-recommended-content-filters-overflow:scroll hidden;--devsite-recommended-content-grid:"list-header" 24px "content"/1fr;--devsite-recommended-content-item-show-all-display:flex;--devsite-recommended-content-toggle-display:none}devsite-recommended-content[filters]{--devsite-recommended-content-grid:"filters-header" 24px "filters" minmax(40px,auto) "list-header" 24px "content" /1fr}[template=landing] devsite-carousel[data-markers-size=small]{--devsite-carousel-marker-size:8px;--devsite-carousel-markers-gap:0}[template=landing] devsite-carousel[data-markers-background=secondary],devsite-recommended-content devsite-carousel{--devsite-carousel-button-color:var(--devsite-secondary-text-color);--devsite-carousel-button-color-hover:var(--devsite-primary-text-color);--devsite-carousel-marker-margin-inline:-16px 0;--devsite-carousel-marker-size:8px;--devsite-carousel-markers-background-focus:var( + --devsite-secondary-text-color + );--devsite-carousel-markers-background-hover:var( + --devsite-secondary-text-color + );--devsite-carousel-markers-gap:0;--devsite-carousel-prev-next-box-shadow:0 1px 2px 0 var(--devsite-elevation-key-shadow-color),0 2px 6px 2px var(--devsite-elevation-ambient-shadow-color);--devsite-recommended-content-filters-overflow:initial}[template=landing] devsite-carousel[data-controls-position=center],[template=landing] devsite-recommended-content devsite-carousel{--devsite-carousel-gap:0;--devsite-carousel-grid:1fr auto/24px 24px 1fr 24px 24px;--devsite-carousel-margin-inline:-24px;--devsite-carousel-markers-grid-column:2/-2;--devsite-carousel-markers-grid-row:2;--devsite-carousel-next-grid-column:-1/-3;--devsite-carousel-prev-grid-column:1/3;--devsite-carousel-prev-next-grid-row:1;--devsite-carousel-slideshow-grid-column:2/-2;--devsite-carousel-slideshow-grid-row:1;--devsite-carousel-slideshow-padding-inline:24px}devsite-recommended-content devsite-carousel[data-items-per-slide=auto]{--devsite-carousel-gradient-background:var(--devsite-background-3);--devsite-carousel-gradient-display:block;--devsite-carousel-gradient-end-grid-column:5;--devsite-carousel-gradient-grid-row:1;--devsite-carousel-gradient-start-grid-column:1;--devsite-carousel-markers-display:none;--devsite-carousel-slideshow-margin-block:-8px;--devsite-carousel-slideshow-padding-block:8px}devsite-book-nav,devsite-search{--devsite-searchbox-hover:#e8eaed;--devsite-searchbox-inactive:var(--devsite-background-3);--devsite-search-border-radius:2px;--devsite-search-form-background-active:var(--devsite-background-3);--devsite-search-height:36px;--devsite-search-image-top:6px;--devsite-search-image-x:8px;--devsite-search-field-border:0;--devsite-search-field-height:36px;--devsite-search-field-padding-x-start:40px}devsite-select{--devsite-select-display:inline-block}devsite-user{--devsite-notification-background:#1967d2}google-codelab-about{--google-codelab-about-active-border-color:#1a73e8}table{--devsite-alt-table-cell-background:rgba(241,243,244,.75);--devsite-h2-border:0;--devsite-responsive-table-first-column-background:#f1f3f4;--devsite-table-cell-background:hsla(0,0%,100%,.95);--devsite-table-heading-background:#e8eaed}table.blue{--devsite-alt-table-cell-background:#f6f7fb;--devsite-table-heading-background:0;--devsite-responsive-table-first-column-background:#f6f7fb;--devsite-table-row-background:#e8eaf6;--devsite-table-row-border:1px solid #c5cae9}table.blue table{--devsite-table-heading-background:inherit}table.cyan{--devsite-alt-table-cell-background:#f4fcfd;--devsite-table-heading-background:0;--devsite-responsive-table-first-column-background:#f4fcfd;--devsite-table-row-background:#e4f7fb;--devsite-table-row-border:1px solid #a1e4f2}table.cyan table{--devsite-table-heading-background:inherit}table.green{--devsite-alt-table-cell-background:#f3faf9;--devsite-table-heading-background:0;--devsite-responsive-table-first-column-background:#f3faf9;--devsite-table-row-background:#e0f2f1;--devsite-table-row-border:1px solid #b2dfdb}table.green table{--devsite-table-heading-background:inherit}table.orange{--devsite-alt-table-cell-background:#fff9f4;--devsite-table-heading-background:0;--devsite-responsive-table-first-column-background:#fff9f4;--devsite-table-row-background:#feefe3;--devsite-table-row-border:1px solid #fedfc8}table.orange table{--devsite-table-heading-background:inherit}table.pink{--devsite-alt-table-cell-background:#fef5fa;--devsite-table-heading-background:0;--devsite-responsive-table-first-column-background:#fef5fa;--devsite-table-row-background:#fde7f3;--devsite-table-row-border:1px solid #fdcfe8}table.pink table{--devsite-table-heading-background:inherit}table.purple{--devsite-alt-table-cell-background:#faf6fe;--devsite-table-heading-background:0;--devsite-responsive-table-first-column-background:#faf6fe;--devsite-table-row-background:#f3e8fd;--devsite-table-row-border:1px solid #e9d2fd}table.purple table{--devsite-table-heading-background:inherit}.devsite-header-billboard{--devsite-h1-margin:14px 0}[background]{--devsite-background-button-border-color:transparent;--devsite-background-button-color:var(--devsite-button-color);--devsite-background-button-color-hover:var(--devsite-button-color);--devsite-background-button-primary-background:var(--devsite-background-1);--devsite-background-button-primary-background-hover:var( + --devsite-link-background-active + );--devsite-background-button-primary-color:var(--devsite-button-color);--devsite-background-button-primary-color-hover:var(--devsite-button-color);--devsite-background-button-white-background-hover:hsla(210,6%,63%,.3);--devsite-background-button-white-background-focus:hsla(210,6%,63%,.5);--devsite-background-button-white-color:var(--devsite-inverted-text-color);--devsite-heading-color:var(--devsite-inverted-text-color);--devsite-icon-color:var(--devsite-inverted-text-color);--devsite-icon-color-hover:var(--devsite-inverted-text-color-hover);--devsite-link-color:var(--devsite-inverted-text-color)}.devsite-landing-row-cta{--devsite-button-border:1px solid transparent;--devsite-button-border-active:1px solid transparent;--devsite-button-border-hover:1px solid transparent;--devsite-button-primary-background:var(--devsite-background-1);--devsite-button-primary-background-hover:var( + --devsite-link-background-active + );--devsite-button-primary-color:var(--devsite-button-color);--devsite-button-primary-color-hover:var(--devsite-button-color);--devsite-button-raised-background:var(--devsite-background-1);--devsite-button-raised-background-active:var( + --devsite-link-background-active + );--devsite-button-raised-background-hover:var( + --devsite-link-background-active + );--devsite-button-white-background-focus:hsla(210,6%,63%,.5);--devsite-button-white-background-hover:hsla(210,6%,63%,.3);--devsite-button-white-color:var(--devsite-inverted-text-color)}[theme=cyan] .devsite-landing-row-cta,[theme=google-yellow] .devsite-landing-row-cta,[theme=orange] .devsite-landing-row-cta,[theme=pale-blue] .devsite-landing-row-cta{--devsite-button-white-color:#202124;--devsite-text-color:#202124}[background=theme]{--devsite-background-color:var(--devsite-primary-color)}[background=grey],[background=white]{--devsite-background-button-border-color:#dadce0;--devsite-background-button-color:var(--devsite-button-color);--devsite-background-button-color-hover:var(--devsite-button-color);--devsite-background-button-primary-background:var( + --devsite-button-primary-background + );--devsite-background-button-primary-background-hover:var( + --devsite-button-primary-background-hover + );--devsite-background-button-primary-color:var( + --devsite-button-primary-color + );--devsite-background-button-primary-color-hover:var( + --devsite-button-primary-color-hover + );--devsite-background-button-white-color:var(--devsite-button-color);--devsite-icon-color:var(--devsite-secondary-text-color);--devsite-icon-color-hover:var(--devsite-link-color)}[background=blue-grey]{--devsite-background-color:#607d8b}[foreground=blue-grey],[theme=blue-grey] [foreground=theme]{--devsite-foreground-color:#607d8b;--devsite-foreground-button-background-hover:#eff2f3;--devsite-foreground-button-border-color:#dadce0;--devsite-foreground-button-border-color-hover:#d7dfe2;--devsite-foreground-button-border-color-active:#eff2f3;--devsite-foreground-button-color:#607d8b;--devsite-foreground-button-primary-background:#607d8b;--devsite-foreground-button-primary-background-hover:#455a64;--devsite-foreground-button-primary-color:#fff}[background=blue-grey-dark]{--devsite-background-color:#455a64}[foreground=blue-grey-dark],[theme=blue-grey-dark] [foreground=theme]{--devsite-foreground-color:#455a64;--devsite-foreground-button-background-hover:#eceff0;--devsite-foreground-button-border-color:#dadce0;--devsite-foreground-button-border-color-hover:#d1d6d8;--devsite-foreground-button-border-color-active:#eceff0;--devsite-foreground-button-color:#455a64;--devsite-foreground-button-primary-background:#455a64;--devsite-foreground-button-primary-background-hover:#37474f;--devsite-foreground-button-primary-color:#fff}[background=cyan]{--devsite-background-color:#12b5cb}[foreground=cyan],[theme=cyan] [foreground=theme]{--devsite-foreground-color:#12b5cb;--devsite-foreground-button-background-hover:#e7f8fa;--devsite-foreground-button-border-color:#dadce0;--devsite-foreground-button-border-color-hover:#c4edf2;--devsite-foreground-button-border-color-active:#e7f8fa;--devsite-foreground-button-color:#12b5cb;--devsite-foreground-button-primary-background:#12b5cb;--devsite-foreground-button-primary-background-hover:#098591;--devsite-foreground-button-primary-color:#fff}[background=deep-orange]{--devsite-background-color:#ff5722}[foreground=deep-orange],[theme=deep-orange] [foreground=theme]{--devsite-foreground-color:#ff5722;--devsite-foreground-button-background-hover:#ffeee9;--devsite-foreground-button-border-color:#dadce0;--devsite-foreground-button-border-color-hover:#ffd5c8;--devsite-foreground-button-border-color-active:#ffeee9;--devsite-foreground-button-color:#ff5722;--devsite-foreground-button-primary-background:#ff5722;--devsite-foreground-button-primary-background-hover:#e64a19;--devsite-foreground-button-primary-color:#fff}[background=deep-purple]{--devsite-background-color:#673ab7}[foreground=deep-purple],[theme=deep-purple] [foreground=theme]{--devsite-foreground-color:#673ab7;--devsite-foreground-button-background-hover:#f0ebf8;--devsite-foreground-button-border-color:#dadce0;--devsite-foreground-button-border-color-hover:#d9ceed;--devsite-foreground-button-border-color-active:#f0ebf8;--devsite-foreground-button-color:#673ab7;--devsite-foreground-button-primary-background:#673ab7;--devsite-foreground-button-primary-background-hover:#512da8;--devsite-foreground-button-primary-color:#fff}[background=google-blue]{--devsite-background-color:#1a73e8}[foreground=google-blue],[theme=google-blue] [foreground=theme]{--devsite-foreground-color:#1a73e8;--devsite-foreground-button-background-hover:#e8f1fd;--devsite-foreground-button-border-color:#dadce0;--devsite-foreground-button-border-color-hover:#c6dcf9;--devsite-foreground-button-border-color-active:#e8f1fd;--devsite-foreground-button-color:#1a73e8;--devsite-foreground-button-primary-background:#1a73e8;--devsite-foreground-button-primary-background-hover:#185abc;--devsite-foreground-button-primary-color:#fff}[background=google-green]{--devsite-background-color:#1e8e3e}[foreground=google-green],[theme=google-green] [foreground=theme]{--devsite-foreground-color:#1e8e3e;--devsite-foreground-button-background-hover:#e9f4ec;--devsite-foreground-button-border-color:#dadce0;--devsite-foreground-button-border-color-hover:#c7e3cf;--devsite-foreground-button-border-color-active:#e9f4ec;--devsite-foreground-button-color:#1e8e3e;--devsite-foreground-button-primary-background:#1e8e3e;--devsite-foreground-button-primary-background-hover:#137333;--devsite-foreground-button-primary-color:#fff}[background=google-red]{--devsite-background-color:#d93025}[foreground=google-red],[theme=google-red] [foreground=theme]{--devsite-foreground-color:#d93025;--devsite-foreground-button-background-hover:#fbeae9;--devsite-foreground-button-border-color:#dadce0;--devsite-foreground-button-border-color-hover:#f6cbc9;--devsite-foreground-button-border-color-active:#fbeae9;--devsite-foreground-button-color:#d93025;--devsite-foreground-button-primary-background:#d93025;--devsite-foreground-button-primary-background-hover:#b31412;--devsite-foreground-button-primary-color:#fff}[background=google-yellow]{--devsite-background-color:#f9ab00}[foreground=google-yellow],[theme=google-yellow] [foreground=theme]{--devsite-foreground-color:#f9ab00;--devsite-foreground-button-background-hover:#fef7e6;--devsite-foreground-button-border-color:#dadce0;--devsite-foreground-button-border-color-hover:#feeabf;--devsite-foreground-button-border-color-active:#fef7e6;--devsite-foreground-button-color:#f9ab00;--devsite-foreground-button-primary-background:#f9ab00;--devsite-foreground-button-primary-background-hover:#ea8600;--devsite-foreground-button-primary-color:#fff}[background=indigo]{--devsite-background-color:#3f51b5}[foreground=indigo],[theme=indigo] [foreground=theme]{--devsite-foreground-color:#3f51b5;--devsite-foreground-button-background-hover:#eceef8;--devsite-foreground-button-border-color:#dadce0;--devsite-foreground-button-border-color-hover:#cfd4ed;--devsite-foreground-button-border-color-active:#eceef8;--devsite-foreground-button-color:#3f51b5;--devsite-foreground-button-primary-background:#3f51b5;--devsite-foreground-button-primary-background-hover:#303f9f;--devsite-foreground-button-primary-color:#fff}[background=orange]{--devsite-background-color:#e8710a}[foreground=orange],[theme=orange] [foreground=theme]{--devsite-foreground-color:#e8710a;--devsite-foreground-button-background-hover:#fdf1e7;--devsite-foreground-button-border-color:#dadce0;--devsite-foreground-button-border-color-hover:#f9dcc2;--devsite-foreground-button-border-color-active:#fdf1e7;--devsite-foreground-button-color:#e8710a;--devsite-foreground-button-primary-background:#e8710a;--devsite-foreground-button-primary-background-hover:#c26401;--devsite-foreground-button-primary-color:#fff}[background=pink]{--devsite-background-color:#e52592}[foreground=pink],[theme=pink] [foreground=theme]{--devsite-foreground-color:#e52592;--devsite-foreground-button-background-hover:#fce9f4;--devsite-foreground-button-border-color:#dadce0;--devsite-foreground-button-border-color-hover:#f9c9e4;--devsite-foreground-button-border-color-active:#fce9f4;--devsite-foreground-button-color:#e52592;--devsite-foreground-button-primary-background:#e52592;--devsite-foreground-button-primary-background-hover:#b80672;--devsite-foreground-button-primary-color:#fff}[background=purple]{--devsite-background-color:#9334e6}[foreground=purple],[theme=purple] [foreground=theme]{--devsite-foreground-color:#9334e6;--devsite-foreground-button-background-hover:#f4ebfd;--devsite-foreground-button-border-color:#dadce0;--devsite-foreground-button-border-color-hover:#e4ccf9;--devsite-foreground-button-border-color-active:#f4ebfd;--devsite-foreground-button-color:#9334e6;--devsite-foreground-button-primary-background:#9334e6;--devsite-foreground-button-primary-background-hover:#7627bb;--devsite-foreground-button-primary-color:#fff}[background=teal]{--devsite-background-color:#009688}[foreground=teal],[theme=teal] [foreground=theme]{--devsite-foreground-color:#009688;--devsite-foreground-button-background-hover:#e6f5f3;--devsite-foreground-button-border-color:#dadce0;--devsite-foreground-button-border-color-hover:#bfe5e1;--devsite-foreground-button-border-color-active:#e6f5f3;--devsite-foreground-button-color:#009688;--devsite-foreground-button-primary-background:#009688;--devsite-foreground-button-primary-background-hover:#00796b;--devsite-foreground-button-primary-color:#fff}[background=blue]{--devsite-background-color:#1a73e8}[foreground=blue],[theme=blue] [foreground=theme]{--devsite-foreground-color:#1a73e8;--devsite-foreground-button-background-hover:#e8f1fd;--devsite-foreground-button-border-color:#dadce0;--devsite-foreground-button-border-color-hover:#c6dcf9;--devsite-foreground-button-border-color-active:#e8f1fd;--devsite-foreground-button-color:#1a73e8;--devsite-foreground-button-primary-background:#1a73e8;--devsite-foreground-button-primary-background-hover:#185abc;--devsite-foreground-button-primary-color:#fff}[background=green]{--devsite-background-color:#1e8e3e}[foreground=green],[theme=green] [foreground=theme]{--devsite-foreground-color:#1e8e3e;--devsite-foreground-button-background-hover:#e9f4ec;--devsite-foreground-button-border-color:#dadce0;--devsite-foreground-button-border-color-hover:#c7e3cf;--devsite-foreground-button-border-color-active:#e9f4ec;--devsite-foreground-button-color:#1e8e3e;--devsite-foreground-button-primary-background:#1e8e3e;--devsite-foreground-button-primary-background-hover:#137333;--devsite-foreground-button-primary-color:#fff}[background=light-blue]{--devsite-background-color:#0288d1}[foreground=light-blue],[theme=light-blue] [foreground=theme]{--devsite-foreground-color:#0288d1;--devsite-foreground-button-background-hover:#e6f3fa;--devsite-foreground-button-border-color:#dadce0;--devsite-foreground-button-border-color-hover:#c0e1f4;--devsite-foreground-button-border-color-active:#e6f3fa;--devsite-foreground-button-color:#0288d1;--devsite-foreground-button-primary-background:#0288d1;--devsite-foreground-button-primary-background-hover:#01579b;--devsite-foreground-button-primary-color:#fff}[background=light-green]{--devsite-background-color:#8bc34a}[foreground=light-green],[theme=light-green] [foreground=theme]{--devsite-foreground-color:#8bc34a;--devsite-foreground-button-background-hover:#f3f9ed;--devsite-foreground-button-border-color:#dadce0;--devsite-foreground-button-border-color-hover:#e2f0d2;--devsite-foreground-button-border-color-active:#f3f9ed;--devsite-foreground-button-color:#8bc34a;--devsite-foreground-button-primary-background:#8bc34a;--devsite-foreground-button-primary-background-hover:#689f38;--devsite-foreground-button-primary-color:#fff}[background=navy]{--devsite-background-color:#3f51b5}[foreground=navy],[theme=navy] [foreground=theme]{--devsite-foreground-color:#3f51b5;--devsite-foreground-button-background-hover:#eceef8;--devsite-foreground-button-border-color:#dadce0;--devsite-foreground-button-border-color-hover:#cfd4ed;--devsite-foreground-button-border-color-active:#eceef8;--devsite-foreground-button-color:#3f51b5;--devsite-foreground-button-primary-background:#3f51b5;--devsite-foreground-button-primary-background-hover:#303f9f;--devsite-foreground-button-primary-color:#fff}[background=pale-blue]{--devsite-background-color:#12b5cb}[foreground=pale-blue],[theme=pale-blue] [foreground=theme]{--devsite-foreground-color:#12b5cb;--devsite-foreground-button-background-hover:#e7f8fa;--devsite-foreground-button-border-color:#dadce0;--devsite-foreground-button-border-color-hover:#c4edf2;--devsite-foreground-button-border-color-active:#e7f8fa;--devsite-foreground-button-color:#12b5cb;--devsite-foreground-button-primary-background:#12b5cb;--devsite-foreground-button-primary-background-hover:#098591;--devsite-foreground-button-primary-color:#fff}[background=cyan]{--devsite-background-color:#43cde6}[background=google-yellow]{--devsite-background-color:#fcc934}[background=light-green]{--devsite-background-color:#aed581}[background=orange]{--devsite-background-color:#fcad70}[background=grey],[background=light-green]{--devsite-link-color:unset}[background=grey]{--devsite-background-color:var(--devsite-background-3);--devsite-heading-color:var(--devsite-primary-text-color);--devsite-text-color:var(--devsite-primary-text-color);--devsite-text-color-hover:var(--devsite-secondary-text-color)}[background=light-green]{--devsite-background-button-white-color:#202124;--devsite-icon-color:#202124;--devsite-icon-color-hover:#5f6368;--devsite-text-color:#202124;--devsite-text-color-hover:#5f6368}[foreground=light-green]{--devsite-foreground-button-primary-color:#202124}.devsite-landing-row-item-labels [background=light-green]:not([foreground]){--devsite-text-color:#202124}[background=cyan],[background=google-yellow],[background=orange],[background=pale-blue],[theme=cyan] [background=theme],[theme=google-yellow] [background=theme],[theme=orange] [background=theme],[theme=pale-blue] [background=theme]{--devsite-background-button-white-color:#202124;--devsite-heading-color:#202124;--devsite-icon-color:#202124;--devsite-icon-color-hover:#5f6368;--devsite-link-color:#202124;--devsite-text-color:#202124;--devsite-text-color-hover:#5f6368}[background=white]{--devsite-background-color:var(--devsite-background-1);--devsite-heading-color:var(--devsite-primary-text-color);--devsite-link-color:unset;--devsite-text-color:var(--devsite-primary-text-color);--devsite-text-color-hover:var(--devsite-secondary-text-color)}[foreground=cyan],[foreground=google-yellow],[foreground=orange],[foreground=pale-blue]{--devsite-foreground-button-primary-color:#202124}[foreground=theme]{--devsite-icon-color:var(--devsite-primary-color)}[foreground=theme] .devsite-heading-link{--devsite-icon-color:var(--devsite-secondary-text-color);--devsite-icon-color-hover:var(--devsite-link-color)}[foreground=white]{--devsite-icon-color:var(--devsite-inverted-text-color);--devsite-text-color:var(--devsite-inverted-text-color)}.devsite-landing-row-item-labels [background]:not([foreground]){--devsite-text-color:#fff}.devsite-landing-row-item-labels [background=cyan]:not([foreground]),.devsite-landing-row-item-labels [background=google-yellow]:not([foreground]),.devsite-landing-row-item-labels [background=orange]:not([foreground]),.devsite-landing-row-item-labels [background=pale-blue]:not([foreground]){--devsite-text-color:#202124}[layout=docs]{--devsite-banner-margin:-40px -40px 40px}[layout=docs],[layout=docs][template=landing]{--devsite-banner-message-padding:20px 40px 19px}[layout=full],[template=landing]{--devsite-banner-message-padding:20px 24px 19px}[layout=full]{--devsite-banner-margin:-40px calc(50% - 50vw) 40px;--devsite-main-content-max-width:1600px;--devsite-main-content-padding:40px 80px}[template="404"],[template=offline]{--devsite-404-links-columns:4;--devsite-404-search-margin:0 0 160px;--devsite-main-content-padding:0 80px}[layout][template=badge],[layout][template=landing],[layout][template=playlist],[layout][template=profile],[layout][template=quiz],[layout][template=topic]{--devsite-banner-margin:0;--devsite-main-content-max-width:none;--devsite-main-content-padding:0}[layout][concierge=closed],[layout][concierge]{--devsite-concierge-width:var(--devsite-concierge-width-closed,0)}[layout][concierge=open]{--devsite-concierge-width:var(--devsite-concierge-width-open,0)}[layout][concierge=modal]{--devsite-concierge-width:0}[layout=full]:not([template=landing]){--devsite-notice-margin:16px calc(50% - 50vw);--devsite-notice-padding-block:15px;--devsite-notice-padding-inline:calc(50vw - 50% + 36px) calc(50vw - 50%)}[layout=full] devsite-content,[template=landing] devsite-content{--devsite-breadcrumb-list-display:none;--devsite-breadcrumb-list-padding:20px 24px}[layout=full][template=search] devsite-content{--devsite-breadcrumb-list-padding:inherit}.devsite-landing-row{--devsite-landing-group-padding:0 24px;--devsite-landing-row-padding:40px 0}[layout=docs] .devsite-landing-row{--devsite-landing-group-padding:0 40px}.devsite-landing-row-padding-small{--devsite-landing-row-padding:32px 0}.devsite-landing-row-padding-medium{--devsite-landing-row-padding:64px 0}.devsite-landing-row-padding-large{--devsite-landing-row-padding:96px 0}.devsite-landing-row-padding-xlarge{--devsite-landing-row-padding:128px 0}.devsite-landing-row-1-up{--devsite-1-up-grid-template-columns:repeat(12,1fr);--devsite-1-up-no-media-description-grid-column:1/span 8;--devsite-custom-image-icon-font-size:256px;--devsite-custom-image-icon-max-height:256px;--devsite-custom-image-icon-width:256px}.devsite-landing-row-2-up,.devsite-landing-row-50{--devsite-custom-image-icon-font-size:192px;--devsite-custom-image-icon-max-height:192px;--devsite-custom-image-icon-width:192px}.devsite-landing-row-3-up,.devsite-landing-row-67{--devsite-custom-image-icon-font-size:128px;--devsite-custom-image-icon-max-height:128px;--devsite-custom-image-icon-width:128px}.devsite-landing-row-4-up,.devsite-landing-row-75,[layout=docs] .devsite-landing-row-2-up{--devsite-custom-image-icon-font-size:96px;--devsite-custom-image-icon-max-height:96px;--devsite-custom-image-icon-width:96px}.devsite-landing-row-2-up{--devsite-landing-row-group-grid:auto-flow/repeat(2,1fr)}.devsite-landing-row-3-up{--devsite-landing-row-group-grid:auto-flow/repeat(3,1fr)}.devsite-landing-row-4-up{--devsite-landing-row-group-grid:auto-flow/repeat(4,1fr)}[header-position=left],[header-position=right]{--devsite-landing-row-group-grid:auto-flow/repeat(2,1fr)}[size=small]{--devsite-icon-size:24px}[size=medium]{--devsite-icon-size:48px}[size=large]{--devsite-icon-size:96px}[size=xlarge]{--devsite-icon-size:144px}.devsite-landing-row-logos [size]{--devsite-custom-image-icon-font-size:96px;--devsite-custom-image-icon-max-height:96px;--devsite-custom-image-icon-width:96px;--devsite-icon-size:96px}[background][size]{--devsite-icon-margin-block:0;--devsite-icon-margin-inline:0}[background][size=small]{--devsite-icon-canvas-size:28px;--devsite-icon-size:18px}[background][size=medium],[size=medium]{--devsite-icon-canvas-size:56px}[background][size=medium]{--devsite-icon-size:36px}[background][size=large]{--devsite-icon-canvas-size:112px;--devsite-icon-size:72px}[background][size=xlarge]{--devsite-icon-canvas-size:168px;--devsite-icon-size:108px}[icon-position^=bottom]{--devsite-icon-canvas-margin-block:8px 0}[icon-position=bottom]{--devsite-icon-canvas-margin-inline:0;--devsite-icon-margin-inline:0}[icon-position=bottom-right]{--devsite-icon-canvas-margin-inline:20px 0;--devsite-icon-margin-inline:0 4px}[icon-position=right]{--devsite-icon-canvas-margin-block:0;--devsite-icon-canvas-margin-inline:20px 0;--devsite-icon-margin-block:0;--devsite-icon-margin-inline:0}[icon-position=top]{--devsite-header-icon-canvas-margin-block:0 20px;--devsite-header-icon-canvas-margin-inline:0}[icon-position=top] [size=small]{--devsite-icon-canvas-margin-block:0 12px}[icon-position=top] [size=medium]{--devsite-icon-canvas-margin-block:0 16px}[icon-position=top] [size=large]{--devsite-icon-canvas-margin-block:0 24px}[icon-position=top] [size=xlarge]{--devsite-icon-canvas-margin-block:0 32px}.devsite-landing-row-header-centered,.devsite-landing-row-header-centered [icon-position=top]{--devsite-header-icon-canvas-margin-inline:auto}.devsite-landing-row-item-centered{--devsite-icon-margin-inline:auto}@media screen and (max-width:1253px){[layout] devsite-catalog{--devsite-catalog-grid:"main"/1fr;--devsite-catalog-sidebar-button-display:inline-block!important;--devsite-catalog-sidebar-button-margin:0 0 16px;--devsite-columns:2}devsite-recommended-content{--devsite-columns:3}}@media screen and (max-width:1440px){[template] devsite-recommended-content devsite-carousel[data-items-per-slide=auto]{--devsite-carousel-gap:0;--devsite-carousel-ghost-item-width:16px;--devsite-carousel-gradient-start-grid-column:2;--devsite-carousel-gradient-end-grid-column:-2;--devsite-carousel-gradient-width:80px;--devsite-carousel-grid:minmax(40px,auto) /0 48px 1fr 48px 0;--devsite-carousel-slideshow-scroll-padding:0 24px}}@media screen and (max-width:840px){[template=page] devsite-carousel[data-full-width],[template=page] devsite-carousel[data-items-per-slide=auto]{--devsite-carousel-gap:16px 24px;--devsite-carousel-grid:1fr 40px/0 40px 1fr 40px 0;--devsite-carousel-margin-inline:-24px;--devsite-carousel-markers-grid-column:3;--devsite-carousel-next-grid-column:4;--devsite-carousel-prev-grid-column:2;--devsite-carousel-slideshow-grid-column:1/-1;--devsite-carousel-slideshow-padding-inline:24px}[template=page] devsite-carousel[data-items-per-slide=auto]{--devsite-carousel-ghost-item-width:16px;--devsite-carousel-slideshow-scroll-padding:0 24px}devsite-footer-utility devsite-language-selector{--devsite-language-selector-menu-inset-inline:0 auto}devsite-playlist{--devsite-playlist-max-width:768px;--devsite-playlist-padding-x:40px}devsite-recommended-content{--devsite-columns:2;--devsite-recommended-content-filters-margin-inline:-24px;--devsite-recommended-content-filters-padding-inline:24px;--devsite-recommended-content-filters-width:calc(100% + 48px)}[layout]{--devsite-banner-margin:-24px -24px 24px}[layout][template]{--devsite-banner-message-padding:20px 24px 19px}[layout=full]{--devsite-main-content-padding:24px}[template="404"],[template=offline]{--devsite-404-links-columns:2;--devsite-404-search-margin:0 0 80px;--devsite-main-content-padding:0 24px}.devsite-landing-row,[class^=devsite-landing-row-padding-]{--devsite-landing-row-padding:24px 0}[layout=docs] .devsite-landing-row{--devsite-landing-group-padding:0 24px}.devsite-landing-row-1-up{--devsite-1-up-grid-template-columns:repeat(2,1fr);--devsite-1-up-no-media-description-grid-column:1/span 2}.devsite-landing-row-1-up,.devsite-landing-row-2-up,.devsite-landing-row-3-up,.devsite-landing-row-4-up{--devsite-custom-image-icon-font-size:128px;--devsite-custom-image-icon-max-height:128px;--devsite-custom-image-icon-width:128px}.devsite-landing-row-3-up,.devsite-landing-row-4-up{--devsite-landing-row-group-grid:auto-flow/repeat(2,1fr)}[icon-position^=bottom]{--devsite-icon-canvas-margin-block:0;--devsite-icon-canvas-margin-inline:20px 0;--devsite-icon-margin-inline:0 4px}}@media screen and (max-width:600px){:root{--devsite-item-gap:16px}[layout]{--devsite-banner-margin:-16px -16px 16px}[layout][template]{--devsite-banner-message-padding:16px 16px 15px}[layout=full]{--devsite-main-content-padding:16px;--devsite-notice-margin:16px -40px;--devsite-notice-padding-block:15px;--devsite-notice-padding-inline:76px 40px}[layout=full] devsite-content,[template=landing] devsite-content{--devsite-breadcrumb-list-padding:20px 16px}[template="404"],[template=offline]{--devsite-404-search-margin:0 0 40px;--devsite-main-content-padding:0 16px}[template] devsite-carousel[data-full-width],[template] devsite-carousel[data-items-per-slide=auto]{--devsite-carousel-gap:16px 16px;--devsite-carousel-grid:1fr 40px/0 40px 1fr 40px 0;--devsite-carousel-margin-inline:-16px;--devsite-carousel-markers-grid-column:3;--devsite-carousel-next-grid-column:4;--devsite-carousel-prev-grid-column:2;--devsite-carousel-slideshow-grid-column:1/-1;--devsite-carousel-slideshow-padding-inline:16px}[template] devsite-carousel[data-items-per-slide=auto]{--devsite-carousel-ghost-item-width:8px;--devsite-carousel-slideshow-scroll-padding:0 16px}devsite-content{--devsite-select-sibling-gap-x:0;--devsite-select-sibling-gap-y:16px}devsite-footer-linkboxes{--devsite-footer-linkboxes-grid-template-columns:1fr;--devsite-footer-linkboxes-padding:0 16px}devsite-playlist{--devsite-playlist-max-width:100%;--devsite-playlist-padding-x:24px}[template=landing] devsite-carousel[data-hide-mobile-controls]{--devsite-carousel-markers-display:none;--devsite-carousel-prev-next-display:none}[template] devsite-recommended-content devsite-carousel{--devsite-carousel-item-width:70vw!important;--devsite-carousel-margin-inline:-16px;--devsite-carousel-markers-display:none;--devsite-carousel-prev-next-display:none;--devsite-carousel-slideshow-grid-column:1/-1;--devsite-carousel-slideshow-padding-inline:16px;--devsite-carousel-slideshow-scroll-padding:0 16px}devsite-recommended-content devsite-carousel[data-items-per-slide=auto]{--devsite-carousel-gradient-display:none;--devsite-carousel-item-flex:initial}devsite-select{--devsite-select-display:block}.devsite-landing-row,[class^=devsite-landing-row-padding-]{--devsite-landing-group-padding:0 16px;--devsite-landing-row-padding:16px 0}[layout=docs] .devsite-landing-row{--devsite-landing-group-padding:0 16px}.devsite-landing-row-1-up,.devsite-landing-row-2-up,.devsite-landing-row-3-up{--devsite-item-display:block}.devsite-landing-row-2-up,.devsite-landing-row-3-up,.devsite-landing-row-4-up,.devsite-landing-row[header-position]{--devsite-landing-row-group-grid:auto-flow/1fr}}:root{--devsite-headline-font-family:Roboto,Noto Sans,Noto Sans JP,Noto Sans KR,Noto Naskh Arabic,Noto Sans Thai,Noto Sans Hebrew,Noto Sans Bengali,sans-serif;--devsite-display-font:300 48px/56px var(--devsite-primary-font-family);--devsite-h1-font:300 34px/40px var(--devsite-primary-font-family);--devsite-h1-letter-spacing:-0.01em;--devsite-h2-font:300 24px/32px var(--devsite-primary-font-family);--devsite-h2-letter-spacing:-0.01em;--devsite-h2-padding:0 0 3px;--devsite-h3-font:400 20px/32px var(--devsite-primary-font-family);--devsite-card-border:0;--devsite-card-border-radius:2px;--devsite-card-box-shadow:0 1px 2px 0 var(--devsite-elevation-key-shadow-color),0 1px 3px 1px var(--devsite-elevation-ambient-shadow-color);--devsite-feature-tooltip-border-radius:2px}devsite-header{--devsite-button-box-shadow:none;--devsite-button-box-shadow-focus:none;--devsite-button-box-shadow-active:none;--devsite-upper-tab-marker-color-inactive:transparent;--devsite-lower-tab-marker-color-inactive:transparent}devsite-catalog,devsite-nav-buttons{--devsite-button-background:var(--devsite-background-1);--devsite-button-background-hover:var(--devsite-background-3);--devsite-button-background-selected:var(--devsite-background-3);--devsite-button-border:1px solid #bdc1c6;--devsite-button-border-hover:1px solid #bdc1c6;--devsite-button-border-selected:1px solid #bdc1c6;--devsite-button-color:var(--devsite-primary-text-color)}.devsite-header-billboard{--devsite-h1-font:300 24px/32px var(--devsite-primary-font-family);--devsite-h1-letter-spacing:0}[foreground]{--devsite-foreground-button-border-color:transparent;--devsite-foreground-button-border-color-hover:transparent;--devsite-foreground-button-border-color-active:transparent}@media screen and (max-width:600px){:root{--devsite-display-font:300 24px/32px var(--devsite-primary-font-family);--devsite-h1-font:300 24px/32px var(--devsite-primary-font-family)}}html{-ms-touch-action:manipulation;touch-action:manipulation}body,html{color:var(--devsite-primary-text-color);font:400 16px/24px var(--devsite-primary-font-family);-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;height:100%;margin:0;-webkit-text-size-adjust:100%;-moz-text-size-adjust:100%;-ms-text-size-adjust:100%;text-size-adjust:100%}body{background-color:var(--devsite-background-1)}.devsite-book-nav-bg:after,body[layout=docs]{background-color:var(--devsite-body-background,var(--devsite-background-0))}body[sitemask--active]{overflow:hidden}p{margin:16px 0;padding:0}img,video{border:0;height:auto;max-width:100%}table img{max-width:272px}table :link,table :visited{word-break:normal}.devsite-toast-content :link,.devsite-toast-content :visited{color:#fff;text-decoration:underline}.devsite-toast-content a:focus{background:hsla(0,0%,100%,.3);border-radius:2px;margin:-4px;padding:4px;text-decoration:none}sup{line-height:1}dd,ol,ul{margin:0;padding-left:40px}td>dl>dd,td>ol,td>ul{padding-left:20px}ol{list-style:decimal outside}ol ol{list-style-type:lower-alpha}ol ol ol{list-style-type:lower-roman}ol.upper-alpha{list-style-type:upper-alpha}ul{list-style:disc outside}li,li p{margin:12px 0;padding:0}dt{font:700 16px/24px var(--devsite-primary-font-family)}dd,dt{margin:16px 0}blockquote{background:var(--devsite-blockquote-background,var(--devsite-background-3));border-left:var(--devsite-blockquote-border-left,0);border-radius:var(--devsite-blockquote-border-radius,0);margin:var(--devsite-blockquote-margin,16px 0);padding:var(--devsite-blockquote-padding,8px);quotes:none}hr{border:0;border-top:var(--devsite-primary-border);height:0;margin:var(--devsite-hr-margin,16px 0);width:100%}.devsite-page-title~.devsite-article-body>p:first-child{margin-top:28px}.devsite-article-body>hr.full-width{margin:16px -40px;width:calc(100% + 80px)}@media screen and (max-width:840px){.devsite-article-body>hr.full-width{margin:16px -24px;width:calc(100% + 48px)}}@media screen and (max-width:600px){.devsite-article-body>hr.full-width{margin:16px -16px;width:calc(100% + 32px)}}abbr,acronym{border-bottom:1px dotted var(--devsite-secondary-text-color);cursor:help}address,cite,dfn,em{font-style:italic}strong{font-weight:700}[visually-hidden]{opacity:0!important;pointer-events:none!important;visibility:hidden!important}.hidden,[hidden]{display:none!important}[render-hidden]{display:inline!important;position:absolute!important;visibility:hidden!important}[no-scroll]{overflow:hidden}#app-progress{left:0;position:fixed;right:0;top:0;z-index:1011}#app-progress .devsite-progress--indeterminate .devsite-progress--indeterminate-1,#app-progress .devsite-progress--indeterminate .devsite-progress--indeterminate-3{background-color:var(--devsite-progress-background-color,var(--devsite-primary-color,var(--devsite-secondary-text-color)))}.devsite-article .material-icons{vertical-align:bottom}.devsite-article-body .material-icons:not(:link):not(button),[template=landing] .devsite-article .material-icons:not(:link):not(button){cursor:default;pointer-events:none}.footnotes ol{padding-left:16px}.footnotes li{font:400 13px/20px var(--devsite-primary-font-family)}#qv-wrapper,#table-of-contents,#tb-wrapper,.inline-toc,div.toc:not(.class):not(.group):not(.type):not(.interface),h2#contents,h2.toc,h3#contents,h3.toc,ol.toc,section.toc,ul.toc{display:none}@media screen and (max-width:840px){#app-progress{z-index:1014}}:link,:visited{color:var(--devsite-link-color);outline:0;-webkit-text-decoration:var(--devsite-link-text-decoration,none);-moz-text-decoration:var(--devsite-link-text-decoration,none);text-decoration:var(--devsite-link-text-decoration,none);word-break:break-word}a:hover{-webkit-text-decoration:var(--devsite-link-text-decoration-hover);-moz-text-decoration:var(--devsite-link-text-decoration-hover);text-decoration:var(--devsite-link-text-decoration-hover)}a:focus{text-decoration:underline}a:focus img{-webkit-filter:brightness(75%);filter:brightness(75%)}.no-feedback devsite-feedback{display:none!important}.preserve-case{text-transform:none}a.external:after,a[href*="man7.org"]:after,a[href*="oracle.com"]:after{font:normal normal normal 24px/1 Material Icons;-webkit-font-feature-settings:"liga";-moz-font-feature-settings:"liga";font-feature-settings:"liga";-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;text-transform:none;word-wrap:normal;content:"open_in_new";font-size:18px;margin-block:0;margin-inline:4px 0;vertical-align:text-bottom}[dir=rtl] a.external:after,[dir=rtl] a[href*="man7.org"]:after,[dir=rtl] a[href*="oracle.com"]:after{-webkit-transform:scaleX(-1);transform:scaleX(-1)}a.download:before{font:normal normal normal 24px/1 Material Icons;-webkit-font-feature-settings:"liga";-moz-font-feature-settings:"liga";font-feature-settings:"liga";-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;text-transform:none;word-wrap:normal;content:"file_download";display:inline-block;font-size:18px;margin-block:0;margin-inline:0 4px;vertical-align:text-bottom}devsite-content{counter-reset:numbered-h2 numbered-h3}h2.numbered{line-height:48px;margin-top:60px;padding-bottom:19px}h2.numbered~h3.numbered{line-height:40px}h2.numbered:before,h2.numbered~h3.numbered:before{background:var(--devsite-tertiary-text-color);color:var(--devsite-inverted-text-color);display:inline-block;margin-block:0;text-align:center}h2.numbered:before{border-radius:24px;content:counter(numbered-h2);counter-increment:numbered-h2;counter-set:numbered-h3 0;height:48px;line-height:48px;margin-inline:0 20px;width:48px}h2.numbered~h3.numbered:before{border-radius:20px;content:counter(numbered-h2) "." counter(numbered-h3);counter-increment:numbered-h3;height:40px;line-height:40px;margin-inline:0 16px;min-width:40px;padding-inline:4px}.compare-better,.compare-no,.compare-worse,.compare-yes{font-weight:700}.compare-better:before,.compare-blank:before,.compare-no:before,.compare-worse:before,.compare-yes:before{content:"";display:inline-block;font:normal normal normal 24px/1 Material Icons;-webkit-font-feature-settings:"liga";-moz-font-feature-settings:"liga";font-feature-settings:"liga";-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;word-wrap:normal;margin-block:-4px 0;margin-inline:0 4px;text-transform:none;vertical-align:middle;width:24px}.compare-better:before,.compare-yes:before{color:var(--devsite-compare-yes-color)}.compare-no:before,.compare-worse:before{color:var(--devsite-compare-no-color)}.compare-better:before{content:"thumb_up"}.compare-no:before{content:"not_interested"}.compare-worse:before{content:"thumb_down"}.compare-yes:before{content:"check"}.align-center{text-align:center}.align-right{text-align:right}.hanging-indent,.members.function td:first-child{-webkit-padding-start:25px;-moz-padding-start:25px;padding-inline-start:25px;text-indent:-17px}.bad-table{table-layout:fixed}.bad-table td,.bad-table tr{word-wrap:break-word}.bad-table pre{word-wrap:normal}.screenshot{border:var(--devsite-secondary-border);padding:3px}.columns td,.columns th,.columns tr{background:0;border:0;font:16px/24px var(--devsite-primary-font-family);padding-block:0}.columns tr{padding-inline:0}.columns td,.columns th{padding-inline:0 20px}.columns th{color:var(--devsite-primary-text-color);font-weight:500}.columns code,.columns pre{background:var(--devsite-background-3)}.inline:not(.expandable){display:inline}.inline-block{display:inline-block}.block{display:block}img.inline-icon{height:1.2em;vertical-align:sub}.no-select{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.wrap-code{white-space:normal}.attempt-left,.attempt-right,aside.attempt-left,aside.attempt-right{max-width:calc(50% - 20px)}.attempt-left,.video-wrapper-left,aside.attempt-left{margin-block:0 40px;margin-inline:0 40px}[dir=ltr] .attempt-left,[dir=ltr] .video-wrapper-left,[dir=ltr] aside.attempt-left{float:left}[dir=rtl] .attempt-left,[dir=rtl] .video-wrapper-left,[dir=rtl] aside.attempt-left{float:right}.attempt-right,.video-wrapper,aside.attempt-right{margin-block:0 40px;margin-inline:40px 0}[dir=ltr] .attempt-right,[dir=ltr] .video-wrapper,[dir=ltr] aside.attempt-right{float:right}[dir=rtl] .attempt-right,[dir=rtl] .video-wrapper,[dir=rtl] aside.attempt-right{float:left}.clear{clear:both}.attempt-left+.attempt-right,.attempt-left+.video-wrapper,.video-wrapper-left+.attempt-right,.video-wrapper-left+.video-wrapper{margin-inline:0}.video-wrapper,.video-wrapper-full-width{overflow:hidden;position:relative}.video-wrapper,.video-wrapper-left{width:calc(50% - 20px)}.video-wrapper-full-width{margin:16px 0;width:100%}.video-wrapper embed,.video-wrapper iframe,.video-wrapper object,.video-wrapper-full-width embed,.video-wrapper-full-width iframe,.video-wrapper-full-width object,.video-wrapper-left embed,.video-wrapper-left iframe,.video-wrapper-left object{height:101%;left:-.5%;position:absolute;top:-.5%;width:101%}@media screen and (max-width:840px){.attempt-left,.attempt-right,aside.attempt-left,aside.attempt-right{display:block;max-width:100%}.attempt-left,.attempt-right,.video-wrapper,.video-wrapper-left,aside.attempt-left,aside.attempt-right{float:none;margin:16px 0;width:100%}}body[pending] #gc-wrapper{margin-top:0!important}body[ready] #gc-wrapper{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-flex:1;-webkit-flex:1 0;-moz-box-flex:1;-ms-flex:1 0;flex:1 0;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-moz-box-orient:vertical;-moz-box-direction:normal;-ms-flex-direction:column;flex-direction:column}[dir=ltr] body[ready][concierge] #gc-wrapper{margin-right:var(--devsite-concierge-width,0)}[dir=rtl] body[ready][concierge] #gc-wrapper{margin-left:var(--devsite-concierge-width,0)}.devsite-wrapper{min-height:100vh}body[ready] .devsite-wrapper{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-moz-box-orient:vertical;-moz-box-direction:normal;-ms-flex-direction:column;flex-direction:column;min-height:100%;overflow:hidden}.full-bleed{margin:0;padding:0}.devsite-book-nav-bg,devsite-book-nav{width:269px}body[pending] devsite-book-nav{position:absolute}@media screen and (max-width:840px){body[devsite-book-nav--open]{overflow:hidden}body[devsite-book-nav--open] devsite-book-nav[fixed]{-webkit-transform:translateX(0)!important;transform:translateX(0)!important}}.devsite-sidebar{grid-column:3;grid-row:1;min-width:0;width:auto}[has-sidebar] .devsite-sidebar{margin:24px 0 0;-webkit-margin-end:24px;-moz-margin-end:24px;margin-inline-end:24px;-webkit-margin-start:-8px;-moz-margin-start:-8px;margin-inline-start:-8px}.devsite-sidebar[fixed] .devsite-sidebar-content{background-color:var(--devsite-body-background,var(--devsite-background-0));contain:content;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-moz-box-orient:vertical;-moz-box-direction:normal;-ms-flex-direction:column;flex-direction:column;max-height:var(--devsite-js-sidebar-max-height);max-width:var(--devsite-js-sidebar-max-width);-webkit-padding-start:8px;-moz-padding-start:8px;padding-inline-start:8px;position:fixed;-webkit-transform:translate3d(0,var(--devsite-js-sidebar-offset),0);transform:translate3d(0,var(--devsite-js-sidebar-offset),0)}.devsite-sidebar devsite-toc.devsite-toc,.devsite-sidebar devsite-toc>.devsite-nav-list{width:auto}devsite-recommendations-sidebar.recommendations-rendered{margin-top:20px}body devsite-toc>.devsite-nav-list{width:auto}.devsite-main-content{margin:0 auto;max-width:var(--devsite-main-content-max-width);padding:var(--devsite-main-content-padding);position:relative;width:100%}#contain-402{z-index:1004!important}body[pending] .devsite-main-content{min-height:calc(100vh - 456px)}body[ready] .devsite-main-content{-webkit-box-flex:1;-webkit-flex-grow:1;-moz-box-flex:1;-ms-flex-positive:1;flex-grow:1;min-height:auto}body[layout=docs] .devsite-main-content{display:grid;grid-gap:24px;grid-template-columns:1fr minmax(752px,936px) 1fr;grid-template-rows:1fr}body[layout=docs] .devsite-main-content[has-sidebar]{grid-template-columns:1fr minmax(752px,936px) minmax(160px,1fr)}body[layout=docs] .devsite-main-content[has-book-nav]{grid-template-columns:minmax(269px,1fr) minmax(752px,936px) 1fr}body[layout=docs][concierge] .devsite-main-content[has-book-nav]{grid-template-columns:minmax(269px,1fr) minmax(365px,936px) 1fr}body[layout=docs] .devsite-main-content[has-book-nav][has-sidebar]{grid-template-columns:minmax(269px,1fr) minmax(752px,936px) minmax(160px,1fr)}.devsite-main-content[has-book-nav]~.devsite-footer,.devsite-main-content[has-book-nav]~devsite-footer-promos,.devsite-main-content[has-book-nav]~devsite-footer-utility{margin-block:0;margin-inline:269px 0}@media screen and (max-width:1253px){body[layout=docs] .devsite-main-content[has-sidebar]{grid-template-columns:1fr minmax(752px,936px) 1fr}body[layout=docs] .devsite-main-content[has-book-nav],body[layout=docs] .devsite-main-content[has-book-nav][has-sidebar]{grid-template-columns:269px 1fr 0}[layout][concierge=closed],[layout][concierge=open],[layout][concierge]{--devsite-concierge-width:var(--devsite-concierge-width-closed,0)}.devsite-sidebar{display:none}}@media screen and (max-width:840px){body[layout=docs] .devsite-main-content{display:block;min-width:100%}devsite-content-footer{padding:0 24px}[layout][concierge=closed],[layout][concierge=open],[layout][concierge]{--devsite-concierge-width:0px}.devsite-main-content[has-book-nav]~.devsite-footer,.devsite-main-content[has-book-nav]~devsite-footer-promos,.devsite-main-content[has-book-nav]~devsite-footer-utility{margin-inline:0}}@media screen and (max-width:600px){devsite-content-footer{padding:0 16px}}.devsite-icon:before,::part(material-icon){font:normal normal normal 24px/1 Material Icons;-webkit-font-feature-settings:"liga";-moz-font-feature-settings:"liga";font-feature-settings:"liga";-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;text-transform:none;word-wrap:normal}.devsite-icon-arrow-drop-down:before{content:"arrow_drop_down"}.devsite-icon-close:before{content:"close"}.devsite-icon-code:before{content:"code"}.devsite-icon-code-dark:before,.devsite-icon-code-light:before{content:"brightness_medium"}.devsite-icon-copy:before{content:"content_copy"}.devsite-icon-edit:before{content:"edit"}.beta,.caution,.deprecated,.dogfood,.experimental,.key-point,.key-term,.note,.objective,.preview,.special,.success,.tip,.warning,aside{border-top:1px solid var(--devsite-notice-border-color,transparent);border-bottom:1px solid var(--devsite-notice-border-color,transparent);border-radius:var(--devsite-notice-border-radius,0);display:block;font-size:14px;margin:var(--devsite-notice-margin);padding-block:var(--devsite-notice-padding-block);padding-inline:var(--devsite-notice-padding-inline)}.beta :link,.beta :visited,.caution :link,.caution :visited,.deprecated :link,.deprecated :visited,.dogfood :link,.dogfood :visited,.experimental :link,.experimental :visited,.key-point :link,.key-point :visited,.key-term :link,.key-term :visited,.note :link,.note :visited,.objective :link,.objective :visited,.preview :link,.preview :visited,.special :link,.special :visited,.success :link,.success :visited,.tip :link,.tip :visited,.warning :link,.warning :visited,aside :link,aside :visited{text-decoration:underline}.beta a:focus,.beta a:hover,.caution a:focus,.caution a:hover,.deprecated a:focus,.deprecated a:hover,.dogfood a:focus,.dogfood a:hover,.experimental a:focus,.experimental a:hover,.key-point a:focus,.key-point a:hover,.key-term a:focus,.key-term a:hover,.note a:focus,.note a:hover,.objective a:focus,.objective a:hover,.preview a:focus,.preview a:hover,.special a:focus,.special a:hover,.success a:focus,.success a:hover,.tip a:focus,.tip a:hover,.warning a:focus,.warning a:hover,aside a:focus,aside a:hover{background:hsla(0,0%,100%,.7);border-radius:2px;margin:-4px;padding:4px;text-decoration:none}.beta pre,.caution pre,.deprecated pre,.dogfood pre,.experimental pre,.key-point pre,.key-term pre,.note pre,.objective pre,.preview pre,.special pre,.success pre,.tip pre,.warning pre,aside pre{background:hsla(0,0%,100%,.75)}.beta code,.caution code,.deprecated code,.dogfood code,.experimental code,.key-point code,.key-term code,.note code,.objective code,.preview code,.special code,.success code,.tip code,.warning code,aside code{border:0;font-weight:700;padding:0}.beta:before,.caution:before,.deprecated:before,.dogfood:before,.experimental:before,.key-point:before,.key-term:before,.note:before,.objective:before,.preview:before,.special:before,.success:before,.tip:before,.warning:before,aside:before{font:normal normal normal 24px/1 Material Icons;-webkit-font-feature-settings:"liga";-moz-font-feature-settings:"liga";font-feature-settings:"liga";-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;text-transform:none;word-wrap:normal;margin-block:0;margin-inline:-36px 0}[dir=ltr] .beta:before,[dir=ltr] .caution:before,[dir=ltr] .deprecated:before,[dir=ltr] .dogfood:before,[dir=ltr] .experimental:before,[dir=ltr] .key-point:before,[dir=ltr] .key-term:before,[dir=ltr] .note:before,[dir=ltr] .objective:before,[dir=ltr] .preview:before,[dir=ltr] .special:before,[dir=ltr] .success:before,[dir=ltr] .tip:before,[dir=ltr] .warning:before,[dir=ltr] aside:before{float:left}[dir=rtl] .beta:before,[dir=rtl] .caution:before,[dir=rtl] .deprecated:before,[dir=rtl] .dogfood:before,[dir=rtl] .experimental:before,[dir=rtl] .key-point:before,[dir=rtl] .key-term:before,[dir=rtl] .note:before,[dir=rtl] .objective:before,[dir=rtl] .preview:before,[dir=rtl] .special:before,[dir=rtl] .success:before,[dir=rtl] .tip:before,[dir=rtl] .warning:before,[dir=rtl] aside:before{float:right}aside var{background:inherit;font-weight:700;padding:0}.beta,.experimental,.note,.preview,.special,.tip,aside{background:var(--devsite-note-notice-background);border-color:var(--devsite-note-notice-border-color);color:var(--devsite-note-notice-color)}.beta :link,.beta :link code,.beta :visited,.beta :visited code,.beta code,.experimental :link,.experimental :link code,.experimental :visited,.experimental :visited code,.experimental code,.note :link,.note :link code,.note :visited,.note :visited code,.note code,.preview :link,.preview :link code,.preview :visited,.preview :visited code,.preview code,.special :link,.special :link code,.special :visited,.special :visited code,.special code,.tip :link,.tip :link code,.tip :visited,.tip :visited code,.tip code,aside :link,aside :link code,aside :visited,aside :visited code,aside code{background:var(--devsite-note-notice-background);border-color:var(--devsite-note-notice-border-color);color:var(--devsite-note-notice-color)}.note:before,.special:before,.tip:before,aside:before{content:"star"}.beta:before,.experimental:before,.preview:before{content:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'><path d='M20.21,17.64l-6.15-8.22V5.57h2.57V3H6.35v2.57h2.57v3.86l-6.3,8.4c-0.44,0.6-0.5,1.41-0.15,2.08C2.8,20.58,3.49,21,4.24,21h14.5c1.11,0,2.01-0.9,2.01-2.01C20.75,18.48,20.53,18,20.21,17.64z' fill='%2301579b'/></svg>")}.caution{background:var(--devsite-caution-notice-background);border-color:var(--devsite-caution-notice-border-color);color:var(--devsite-caution-notice-color)}.caution :link,.caution :link code,.caution :visited,.caution :visited code,.caution code{background:var(--devsite-caution-notice-background);border-color:var(--devsite-caution-notice-border-color);color:var(--devsite-caution-notice-color)}.caution:before{content:"error"}.deprecated{background:var(--devsite-status-notice-background);border-color:var(--devsite-status-notice-border-color);color:var(--devsite-status-notice-color)}.deprecated :link,.deprecated :link code,.deprecated :visited,.deprecated :visited code,.deprecated code{background:var(--devsite-status-notice-background);border-color:var(--devsite-status-notice-border-color);color:var(--devsite-status-notice-color)}.deprecated:before{content:"not_interested"}.dogfood{background:var(--devsite-status-notice-background);border-color:var(--devsite-status-notice-border-color);color:var(--devsite-status-notice-color)}.dogfood :link,.dogfood :link code,.dogfood :visited,.dogfood :visited code,.dogfood code{background:var(--devsite-status-notice-background);border-color:var(--devsite-status-notice-border-color);color:var(--devsite-status-notice-color)}.dogfood:before{content:"pets"}.key-point{background:var(--devsite-key-point-notice-background);border-color:var(--devsite-key-point-notice-border-color);color:var(--devsite-key-point-notice-color)}.key-point :link,.key-point :link code,.key-point :visited,.key-point :visited code,.key-point code{background:var(--devsite-key-point-notice-background);border-color:var(--devsite-key-point-notice-border-color);color:var(--devsite-key-point-notice-color)}.key-point:before{content:"lightbulb_outline"}.key-term{background:var(--devsite-key-term-notice-background);border-color:var(--devsite-key-term-notice-border-color);color:var(--devsite-key-term-notice-color)}.key-term :link,.key-term :link code,.key-term :visited,.key-term :visited code,.key-term code{background:var(--devsite-key-term-notice-background);border-color:var(--devsite-key-term-notice-border-color);color:var(--devsite-key-term-notice-color)}.key-term:before{content:"font_download"}.objective{background:var(--devsite-success-notice-background);border-color:var(--devsite-success-notice-border-color);color:var(--devsite-success-notice-color)}.objective :link,.objective :link code,.objective :visited,.objective :visited code,.objective code{background:var(--devsite-success-notice-background);border-color:var(--devsite-success-notice-border-color);color:var(--devsite-success-notice-color)}.objective:before{content:"school"}.success{background:var(--devsite-success-notice-background);border-color:var(--devsite-success-notice-border-color);color:var(--devsite-success-notice-color)}.success :link,.success :link code,.success :visited,.success :visited code,.success code{background:var(--devsite-success-notice-background);border-color:var(--devsite-success-notice-border-color);color:var(--devsite-success-notice-color)}.success:before{content:"check_circle"}.warning{background:var(--devsite-warning-notice-background);border-color:var(--devsite-warning-notice-border-color);color:var(--devsite-warning-notice-color)}.warning :link,.warning :link code,.warning :visited,.warning :visited code,.warning code{background:var(--devsite-warning-notice-background);border-color:var(--devsite-warning-notice-border-color);color:var(--devsite-warning-notice-color)}.warning:before{content:"warning"}.beta :focus code,.beta :hover code,.caution :focus code,.caution :hover code,.deprecated :focus code,.deprecated :hover code,.dogfood :focus code,.dogfood :hover code,.experimental :focus code,.experimental :hover code,.key-point :focus code,.key-point :hover code,.key-term :focus code,.key-term :hover code,.note :focus code,.note :hover code,.objective :focus code,.objective :hover code,.preview :focus code,.preview :hover code,.special :focus code,.special :hover code,.success :focus code,.success :hover code,.tip :focus code,.tip :hover code,.warning :focus code,.warning :hover code,aside :focus code,aside :hover code{background:transparent}.devsite-no-page-title>.beta:first-child,.devsite-no-page-title>.caution:first-child,.devsite-no-page-title>.deprecated:first-child,.devsite-no-page-title>.dogfood:first-child,.devsite-no-page-title>.experimental:first-child,.devsite-no-page-title>.key-point:first-child,.devsite-no-page-title>.key-term:first-child,.devsite-no-page-title>.note:first-child,.devsite-no-page-title>.objective:first-child,.devsite-no-page-title>.preview:first-child,.devsite-no-page-title>.special:first-child,.devsite-no-page-title>.success:first-child,.devsite-no-page-title>.tip:first-child,.devsite-no-page-title>.warning:first-child,.devsite-no-page-title>aside:first-child{clear:right}.devsite-banner{border-bottom:1px solid var(--devsite-banner-border-color,transparent);font:var(--devsite-banner-font,inherit);font-size:var(--devsite-banner-font-size,14px);letter-spacing:var(--devsite-banner-letter-spacing,normal);margin:var(--devsite-banner-margin)}.devsite-banner :link,.devsite-banner :visited{text-decoration:underline}.devsite-banner-message{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-pack:var(--devsite-banner-message-justify-content,normal);-webkit-justify-content:var(--devsite-banner-message-justify-content,normal);-moz-box-pack:var(--devsite-banner-message-justify-content,normal);-ms-flex-pack:var(--devsite-banner-message-justify-content,normal);justify-content:var(--devsite-banner-message-justify-content,normal);margin:0 auto;max-width:var(--devsite-banner-message-max-width,1488px);padding:var(--devsite-banner-message-padding)}.devsite-banner-message-text{-webkit-margin-end:var(--devsite-banner-message-text-margin-x-end,auto);-moz-margin-end:var(--devsite-banner-message-text-margin-x-end,auto);margin-inline-end:var(--devsite-banner-message-text-margin-x-end,auto)}.devsite-banner a:not(.button):focus,.devsite-banner[background] a:not(.button):focus{background:var(--devsite-inverted-text-rgba);border-radius:2px;margin:-4px;padding:4px;text-decoration:none}.devsite-banner[background=white]{border-bottom:var(--devsite-primary-border)}.devsite-banner-announcement,.devsite-banner-announcement :link:not(.button),.devsite-banner-announcement :visited:not(.button){background:var(--devsite-banner-background,var(--devsite-note-notice-background));border-color:var(--devsite-banner-border-color,var(--devsite-note-notice-border-color))}[layout=docs] .devsite-banner:first-of-type{border-radius:var(--devsite-banner-border-radius,0)}.devsite-banner-announcement[background] :link:not(.button),.devsite-banner-announcement[background] :visited:not(.button){background:0}.devsite-banner-confidential{background:var(--devsite-caution-notice-background);border-color:var(--devsite-caution-notice-border-color);color:var(--devsite-caution-notice-color)}.devsite-banner-confidential .devsite-banner-message:before{content:"warning";font:normal normal normal 24px/1 Material Icons;-webkit-font-feature-settings:"liga";-moz-font-feature-settings:"liga";font-feature-settings:"liga";-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;text-transform:none;word-wrap:normal;-webkit-margin-end:16px;-moz-margin-end:16px;margin-inline-end:16px}.devsite-banner-translated{background:var(--devsite-background-3);border-color:var(--devsite-translated-notice-border-color,transparent);color:var(--devsite-secondary-text-rgba)}.devsite-banner-translated :link{text-decoration:none}.devsite-banner .button,.devsite-banner button{-webkit-box-flex:0;-webkit-flex:0 0 auto;-moz-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;margin:-6px 0;-webkit-margin-start:16px;-moz-margin-start:16px;margin-inline-start:16px;text-decoration:none}.devsite-banner .material-icons{margin:-2px 0;vertical-align:middle}.devsite-banner-translated-image{margin:4px 0 -4px;-webkit-margin-end:24px;-moz-margin-end:24px;margin-inline-end:24px;width:122px}.devsite-banner-heading{font-weight:700}@media screen and (max-width:1253px){.devsite-banner-translated .devsite-banner-translated-text{display:block}}@media screen and (max-width:840px){[layout=docs] .devsite-banner-announcement{border-radius:0}}@media screen and (max-width:600px){[layout][template] .devsite-banner-message{display:block}.devsite-banner .button,.devsite-banner button{margin:12px 0 0;-webkit-margin-start:0;-moz-margin-start:0;margin-inline-start:0}}[items-across="1"]{--devsite-columns:1}[items-across="2"]{--devsite-columns:2}[items-across="3"]{--devsite-columns:3}[items-across="4"]{--devsite-columns:4}.devsite-card-group{display:grid;gap:var(--devsite-item-gap,24px);grid:auto-flow/repeat(var(--devsite-columns,3),1fr)}.devsite-card-wrapper{min-width:0}.devsite-card-wrapper[hidden]{display:none}.devsite-card h3{font:var(--devsite-h2-font);letter-spacing:var(--devsite-h2-letter-spacing);margin:0 0 10px}.devsite-card{background:var(--devsite-card-background);border:var(--devsite-card-border);border-radius:var(--devsite-card-border-radius);box-shadow:var(--devsite-card-box-shadow);display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-moz-box-orient:vertical;-moz-box-direction:normal;-ms-flex-direction:column;flex-direction:column;height:100%;overflow:hidden;position:relative;-webkit-transition:var(--devsite-card-transition,0);transition:var(--devsite-card-transition,0)}.devsite-card-image{height:100%;object-fit:var(--devsite-card-image-object-fit,cover);position:absolute;width:100%}.devsite-card-image-container{background-image:url(../images/dynamic-content-card-default.png);background-position:50%;background-repeat:no-repeat;background-size:cover;padding:0 0 56.25%}.devsite-card-image-no-background{background-image:none!important;overflow:hidden;position:relative}.devsite-card-content-wrapper{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-flex:1;-webkit-flex:1 0;-moz-box-flex:1;-ms-flex:1 0;flex:1 0;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-moz-box-orient:vertical;-moz-box-direction:normal;-ms-flex-direction:column;flex-direction:column}.devsite-card-buttons,.devsite-card-content,.devsite-card-skill{padding:var(--devsite-card-content-padding,16px)}.devsite-card-content{-webkit-box-flex:var(--devsite-card-content-flex,1 0);-webkit-flex:var(--devsite-card-content-flex,1 0);-moz-box-flex:var(--devsite-card-content-flex,1 0);-ms-flex:var(--devsite-card-content-flex,1 0);flex:var(--devsite-card-content-flex,1 0);word-break:break-word}.devsite-card-category{background-color:var(--devsite-label-background-color,transparent);border-radius:var(--devsite-label-border-radius,4px);color:var(--devsite-label-color,inherit);font:var(--devsite-label-font,700 12px/22px var(--devsite-primary-font-family));letter-spacing:var(--devsite-label-letter-spacing,.3px);margin:var(--devsite-label-margin,0 0 16px);padding:var(--devsite-label-padding,0);text-transform:var(--devsite-label-text-transform,uppercase)}.devsite-card-summary{-webkit-box-orient:vertical;-webkit-line-clamp:4;color:var(--devsite-card-summary-color,inherit);display:-webkit-box;font:400 16px/24px var(--devsite-primary-font-family);margin:var(--devsite-card-summary-margin,16px 0 0);max-height:96px;overflow:hidden}.devsite-card-attribution{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;border-top:var(--devsite-card-attribution-border,var(--devsite-primary-border));-moz-box-sizing:content-box;box-sizing:content-box;color:var(--devsite-card-attribution-color,inherit);display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;font-size:var(--devsite-card-attribution-font-size,12px);font-weight:var(--devsite-card-attribution-font-weight,normal);gap:0 16px;-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;-ms-flex-pack:center;justify-content:center;line-height:var(--devsite-card-attribution-line-height,16px);margin:var(--devsite-card-attribution-margin,0);min-height:var(--devsite-card-attribution-min-height,40px);padding:var(--devsite-card-attribution-padding,16px);position:relative}.devsite-card-icon-container{color:var(--devsite-secondary-text-color);display:grid;height:32px;place-content:center;width:32px}.devsite-card-icon-container[background]{background-color:var(--devsite-background-color);border-radius:50%;overflow:hidden}.devsite-card-attribution-text-container{-webkit-box-flex:1;-webkit-flex:1;-moz-box-flex:1;-ms-flex:1;flex:1;text-align:end}.devsite-card-icon-image{height:32px}.devsite-card-icon.material-icons{color:var(--devsite-foreground-color);font-size:32px}.devsite-card-icon-container[background] .devsite-card-icon{font-size:24px}.devsite-card-attribution-author,.devsite-card-attribution-date,.devsite-card-attribution-name,.devsite-card-date,.devsite-card-duration{margin:0}.devsite-card-attribution-author+.devsite-card-attribution-date,.devsite-card-attribution-name+.devsite-card-attribution-author{margin-top:8px}.devsite-card-section{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;gap:16px;-webkit-box-pack:justify;-webkit-justify-content:space-between;-moz-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between}.devsite-card-attribution+.devsite-card-buttons,.devsite-card-content+.devsite-card-buttons,.devsite-card-content+.devsite-card-section .activity-card-icons,.devsite-card-content+.devsite-card-section .devsite-card-buttons,.devsite-card-content+.devsite-card-skill,.devsite-card-skill+.devsite-card-attribution,.devsite-card-skill+.devsite-card-buttons{padding-top:0}.devsite-card-date,.devsite-card-duration{color:var(--devsite-card-date-color,var(--devsite-secondary-text-color));font:var(--devsite-card-date-font,400 12px/16px var(--devsite-primary-font-family));letter-spacing:var(--devsite-card-date-letter-spacing,.3px)}.devsite-card-icons{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;gap:12px;padding:12px}.devsite-card-icon{height:32px;width:32px}.devsite-card-api-references{list-style:none;padding:0}.devsite-card-api-references{color:var(--devsite-card-api-references-color,var(--devsite-secondary-text-color));font-size:14px;line-height:18px;margin-top:12px}.devsite-card-api-references-item{margin:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.devsite-card-skill{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;color:var(--devsite-card-skill-color);display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;font:var(--devsite-card-skill-font,14px/20px var(--devsite-primary-font-family));-webkit-box-pack:var(--devsite-card-skill-justify-content);-webkit-justify-content:var(--devsite-card-skill-justify-content);-moz-box-pack:var(--devsite-card-skill-justify-content);-ms-flex-pack:var(--devsite-card-skill-justify-content);justify-content:var(--devsite-card-skill-justify-content)}.devsite-card-skill-icon{height:24px;margin:var(--devsite-card-skill-icon-margin,0 4px 0 -6px);width:24px}.devsite-card-skill-icon-filled{fill:currentColor}.devsite-card-skill-icon-unfilled{fill:var(--devsite-background-5)}.devsite-card-buttons{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:reverse;-webkit-flex-direction:row-reverse;-moz-box-orient:horizontal;-moz-box-direction:reverse;-ms-flex-direction:row-reverse;flex-direction:row-reverse;margin:auto 0 0}[template=activity] .devsite-card h3{margin-bottom:4px}.devsite-card-list{border:var(--devsite-card-border);border-radius:var(--devsite-card-border-radius);list-style:none;overflow:var(--devsite-card-list-overflow,visible);padding:0}.devsite-card-list-item{border:var(--devsite-card-list-item-border,0);border-radius:var(--devsite-card-list-item-border-radius,2px);box-shadow:var(--devsite-card-box-shadow,0 1px 2px 0 var(--devsite-elevation-key-shadow-color),0 1px 3px 1px var(--devsite-elevation-ambient-shadow-color));margin:var(--devsite-card-list-item-margin,0 0 20px)}.devsite-card-list-item:not(:last-child){border-bottom:var(--devsite-card-list-item-border,var(--devsite-card-border,0))}.devsite-card-list-item:last-child{border-bottom:var(--devsite-card-list-item-border,0);margin:0}.devsite-card-list-link{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;color:var(--devsite-card-list-link-color,var(--devsite-link-color));display:-webkit-inline-box;display:-webkit-inline-flex;display:-moz-inline-box;display:-ms-inline-flexbox;display:inline-flex;font:var(--devsite-card-list-link-font,var(--devsite-h2-font));letter-spacing:var(--devsite-h2-letter-spacing);padding:var(--devsite-card-list-link-padding,16px 20px);-webkit-transition:background .2s,color .2s;transition:background .2s,color .2s;width:100%}.devsite-card-list-link:focus,.devsite-card-list-link:hover{background:var(--devsite-card-list-link-background-hover,var(--devsite-link-background-hover));color:var(--devsite-card-list-link-color-hover,var(--devsite-link-color));text-decoration:none}.devsite-card-list-link:after{font:normal normal normal 24px/1 Material Icons;-webkit-font-feature-settings:"liga";-moz-font-feature-settings:"liga";font-feature-settings:"liga";-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;text-transform:none;word-wrap:normal;content:"arrow_forward";margin-left:auto;opacity:0;-webkit-transform:translateX(-20px);transform:translateX(-20px);-webkit-transition:opacity .2s,-webkit-transform .2s;transition:opacity .2s,-webkit-transform .2s;transition:opacity .2s,transform .2s;transition:opacity .2s,transform .2s,-webkit-transform .2s}.devsite-card-list-link:focus:after,.devsite-card-list-link:hover:after{opacity:1;-webkit-transform:translateX(0);transform:translateX(0)}@media screen and (max-width:840px){.devsite-card-group,[items-across="3"],[items-across="4"]{--devsite-columns:2}}@media screen and (max-width:600px){.devsite-card-group{display:block}.devsite-card-wrapper:not(:first-of-type){margin-top:16px}.devsite-card-summary{font-size:14px;line-height:20px;max-height:80px}}.pre-style,code,pre{background:var(--devsite-code-background);color:var(--devsite-code-color);direction:ltr!important;font:400 100%/1 var(--devsite-code-font-family);padding:var(--devsite-inline-code-padding,1px 4px);text-align:left!important}code{border:var(--devsite-inline-code-border,0);border-radius:var(--devsite-inline-code-border-radius,0);font:500 90%/1 var(--devsite-code-font-family);word-break:break-word}.pre-style code,pre code,table code{font-weight:400;word-break:normal}.pre-style,pre{font:14px/20px var(--devsite-code-font-family);margin:16px 0;overflow-x:auto;padding:24px;position:relative}.pre-style code,pre code{background:0;border:var(--devsite-inline-nested-code-border,0);font-size:14px;padding:0}b code,strong code{font-weight:700}cite code,em code,i code{font-style:italic}pre.devsite-code-highlight>code>span,pre.devsite-code-highlight>span{-webkit-filter:grayscale(1);filter:grayscale(1)}td>pre:only-child{padding:0}td>devsite-code pre.inline-code,td>devsite-code:only-child pre,td>div:first-child:empty+devsite-code:last-child pre{padding:0 64px 0 0}td>devsite-code pre.inline-code,td>devsite-code:not([dark-code]):only-child pre,td>div:first-child:empty+devsite-code:not([dark-code]):last-child pre{background:0}td>devsite-code pre.inline-code~.devsite-code-buttons-container,td>devsite-code:only-child pre~.devsite-code-buttons-container,td>div:first-child:empty+devsite-code:last-child pre~.devsite-code-buttons-container{top:-6px}h1 code,h2 code,h3 code,h4 code,h5 code,h6 code{background:0;color:var(--devsite-primary-text-color);padding:0}h1 code{color:#80868b}:link code,:visited code,code :link,code :visited,pre :link,pre :visited,td :link code,td :visited code,td code :link,td code :visited{color:var(--devsite-contrast-link-color)}body[layout] .devsite-main-content var span,var,var code{color:var(--devsite-var-color);-moz-osx-font-smoothing:auto;-webkit-font-smoothing:auto;font-weight:500}pre.clear-for-copy{all:initial;left:-100vw;position:absolute;top:-100vh;white-space:pre}pre.clear-for-copy *{all:unset;font-family:var(--devsite-code-font-family);white-space:pre}fieldset{border:0;margin:0;padding:0}input[type=radio]{-webkit-appearance:none;background:var(--devsite-background-1);border-radius:2px;cursor:pointer;font:normal normal normal 24px/1 Material Icons;-webkit-font-feature-settings:"liga";-moz-font-feature-settings:"liga";font-feature-settings:"liga";-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;text-transform:none;word-wrap:normal;height:18px;margin-block:-2px 2px;margin-inline:0 8px;outline:0;position:relative;-webkit-transition:color .2s;transition:color .2s;vertical-align:middle;width:18px}input[type=radio]{color:var(--devsite-secondary-text-color)}input[type=radio]{border-radius:50%;-webkit-transition:none;transition:none}input[type=radio]:focus:before{background:var(--devsite-background-4)}input[type=radio]:checked{color:var(--devsite-link-color)}input[type=radio]:focus:before{background:var(--devsite-input-background-focus,var(--devsite-link-background))}input[type=radio]:after{content:"check_box_outline_blank";position:relative;top:-3px;z-index:1}[dir=ltr] input[type=radio]:after{right:3px}[dir=rtl] input[type=radio]:after{left:3px}input[type=radio]:after{content:"radio_button_unchecked"}input[type=radio]:checked:after{content:"radio_button_checked"}input[type=radio]:before{border-radius:50%;content:"";display:block;height:36px;position:absolute;top:-9px;-webkit-transition:background .2s;transition:background .2s;width:36px}[dir=ltr] input[type=radio]:before{left:-9px}[dir=rtl] input[type=radio]:before{right:-9px}input[type=radio]:disabled{color:var(--devsite-input-color-disabled,var(--devsite-tertiary-text-color));cursor:default}input[type=date],input[type=datetime-local],input[type=datetime],input[type=email],input[type=month],input[type=number],input[type=password],input[type=search],input[type=tel],input[type=text],input[type=time],input[type=url],input[type=week],select[multiple],select[size],textarea{background:var(--devsite-input-background);border:var(--devsite-input-border);border-radius:var(--devsite-input-border-radius,2px);color:var(--devsite-input-color,var(--devsite-primary-text-color));font:var(--devsite-input-font,16px/20px var(--devsite-primary-font-family));height:var(--devsite-input-height,auto);margin:var(--devsite-input-margin,0);max-width:100%;outline:0;padding:var(--devsite-input-padding,7px);-webkit-transition:border-color .2s;transition:border-color .2s;vertical-align:middle;width:var(--devsite-input-width,auto)}input[type=date]:focus,input[type=datetime-local]:focus,input[type=datetime]:focus,input[type=email]:focus,input[type=month]:focus,input[type=number]:focus,input[type=password]:focus,input[type=search]:focus,input[type=tel]:focus,input[type=text]:focus,input[type=time]:focus,input[type=url]:focus,input[type=week]:focus,select[multiple]:focus,select[size]:focus,textarea:focus{border-bottom:var(--devsite-input-border-bottom-focus,2px solid var(--devsite-link-color));padding-bottom:var(--devsite-input-padding-bottom-focus,6px)}input[type=date]:disabled,input[type=datetime-local]:disabled,input[type=datetime]:disabled,input[type=email]:disabled,input[type=month]:disabled,input[type=number]:disabled,input[type=password]:disabled,input[type=search]:disabled,input[type=tel]:disabled,input[type=text]:disabled,input[type=time]:disabled,input[type=url]:disabled,input[type=week]:disabled,select[multiple]:disabled,select[size]:disabled,textarea:disabled{background:var(--devsite-background-3)}body input[type=file]{height:auto;line-height:1;padding:var(--devsite-input-file-padding,8px 16px)}select{-moz-appearance:none;-webkit-appearance:none;background-color:var(--devsite-select-background-color);border:var(--devsite-select-border,var(--devsite-secondary-border));border-radius:var(--devsite-select-border-radius);box-shadow:none;color:var(--devsite-select-color,var(--devsite-primary-text-color));cursor:pointer;display:inline-block;font:var(--devsite-select-font,500 14px/36px var(--devsite-primary-font-family));height:var(--devsite-select-height,36px);line-height:var(--devsite-select-line-height,34px);max-width:var(--devsite-select-max-width,340px);min-width:72px;outline:0;overflow:hidden;padding:var(--devsite-select-padding,0 27px 0 7px);text-align:left;text-indent:.01px;text-overflow:ellipsis;-webkit-transition:background-color .2s;transition:background-color .2s;vertical-align:middle;white-space:nowrap;background-image:var(--devsite-select-background-image);background-position:100%;background-repeat:no-repeat}select:focus,select:hover{background-color:var(--devsite-select-background-color-hover,var(--devsite-background-3));border:var(--devsite-select-border-hover,var(--devsite-select-border,var(--devsite-secondary-border)));color:var(--devsite-select-color-hover)}select:active{background-color:var(--devsite-select-background-color-active,var(--devsite-background-4));color:var(--devsite-select-color-active)}select:disabled{background-color:var(--devsite-background-3);border-color:transparent;color:var(--devsite-tertiary-text-color);cursor:default}select:disabled{background-image:url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="20" height="4" viewBox="0 0 20 4"><path d="M0,0l4,4l4-4H0z" fill="%23bdc1c6"/></svg>')}@media screen and (-ms-high-contrast:active){select{background-image:url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="20" height="4" viewBox="0 0 20 4"><path d="M0,0l4,4l4-4H0z" fill="white"/></svg>')}}@media screen and (-ms-high-contrast:black-on-white){select{background-image:url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="20" height="4" viewBox="0 0 20 4"><path d="M0,0l4,4l4-4H0z" fill="black"/></svg>')}}input[type=checkbox]{-webkit-appearance:none;background:var(--devsite-background-1);border-radius:var(--devsite-checkbox-border-radius);cursor:pointer;height:var(--devsite-checkbox-size);margin-block:var(--devsite-checkbox-margin-block);margin-inline:var(--devsite-checkbox-margin-inline);outline:0;position:relative;-webkit-transition:color .2s;transition:color .2s;vertical-align:middle;width:var(--devsite-checkbox-size)}input[type=checkbox]{color:var(--devsite-secondary-text-color)}input[type=checkbox]:focus:before{background:var(--devsite-background-4)}input[type=checkbox]:checked,input[type=checkbox]:indeterminate{color:var(--devsite-link-color)}input[type=checkbox]:checked:focus:before,input[type=checkbox]:indeterminate:focus:before{background:var(--devsite-input-background-focus,var(--devsite-link-background))}input[type=checkbox]:after{content:"check_box_outline_blank";font:normal normal normal 24px/1 Material Icons;-webkit-font-feature-settings:"liga";-moz-font-feature-settings:"liga";font-feature-settings:"liga";-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;text-transform:none;word-wrap:normal;position:relative;right:var(--devsite-checkbox-offset-x);top:var(--devsite-checkbox-offset-y);z-index:1}:host-context([dir=rtl]) input[type=checkbox]:after,[dir=rtl] input[type=checkbox]:after{left:var(--devsite-checkbox-offset-x);right:auto}input[type=checkbox]:checked:after{content:"check_box"}input[type=checkbox]:indeterminate:after{content:"indeterminate_check_box"}input[type=checkbox]:before{border-radius:var(--devsite-checkbox-icon-canvas-border-radius);content:"";display:block;font:normal normal normal 24px/1 Material Icons;-webkit-font-feature-settings:"liga";-moz-font-feature-settings:"liga";font-feature-settings:"liga";-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;text-transform:none;word-wrap:normal;height:var(--devsite-checkbox-icon-canvas-size);position:absolute;top:var(--devsite-checkbox-icon-canvas-offset-y);-webkit-transition:background .2s;transition:background .2s;width:var(--devsite-checkbox-icon-canvas-size)}:host-context([dir=ltr]) input[type=checkbox]:before,[dir=ltr] input[type=checkbox]:before{left:var(--devsite-checkbox-icon-canvas-offset-x)}:host-context([dir=rtl]) input[type=checkbox]:before,[dir=rtl] input[type=checkbox]:before{right:var(--devsite-checkbox-icon-canvas-offset-x)}input[type=checkbox]:disabled{color:var(--devsite-input-color-disabled,var(--devsite-tertiary-text-color));cursor:default}label{color:var(--devsite-secondary-text-color);display:block;font-size:12px}input+label{color:var(--devsite-primary-text-color);display:inline;font-size:16px}label[for]{cursor:pointer}input:disabled+label{color:var(--devsite-input-color-disabled,var(--devsite-tertiary-text-color));cursor:default}devsite-book-nav .devsite-breadcrumb-list,devsite-content .devsite-breadcrumb-list,devsite-header .devsite-breadcrumb-list{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;display:var(--devsite-breadcrumb-list-display);padding:var(--devsite-breadcrumb-list-padding);white-space:nowrap}.devsite-search-project .devsite-breadcrumb-list,devsite-book-nav .devsite-breadcrumb-list,devsite-header .devsite-breadcrumb-list{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;font-family:var(--devsite-font-family,var(--devsite-primary-font-family))}devsite-header .devsite-breadcrumb-list{letter-spacing:var(--devsite-header-lower-breadcrumb-letter-spacing,0);text-transform:var(--devsite-header-lower-breadcrumb-text-transform,none)}devsite-content .devsite-breadcrumb-list{background:var(--devsite-breadcrumb-list-background,var(--devsite-background-1));display:var(--devsite-breadcrumb-list-display,inline-flex);-webkit-box-flex:1;-webkit-flex:1;-moz-box-flex:1;-ms-flex:1;flex:1;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;font-size:var(--devsite-breadcrumb-list-font-size,13px);width:var(--devsite-breadcrumb-list-width)}devsite-book-nav .devsite-breadcrumb-item,devsite-content .devsite-breadcrumb-item,devsite-header .devsite-breadcrumb-item{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;margin:0;padding:var(--devsite-breadcrumb-padding)}devsite-book-nav .devsite-breadcrumb-guillemet,devsite-book-nav .devsite-breadcrumb-link,devsite-header .devsite-breadcrumb-guillemet,devsite-header .devsite-breadcrumb-link{color:var(--devsite-secondary-text-rgba);fill:var(--devsite-secondary-text-rgba)}devsite-book-nav .devsite-breadcrumb-guillemet:focus,devsite-book-nav .devsite-breadcrumb-guillemet:hover,devsite-book-nav .devsite-breadcrumb-link:focus,devsite-book-nav .devsite-breadcrumb-link:hover,devsite-header .devsite-breadcrumb-guillemet:focus,devsite-header .devsite-breadcrumb-guillemet:hover,devsite-header .devsite-breadcrumb-link:focus,devsite-header .devsite-breadcrumb-link:hover{color:var(--devsite-primary-text-rgba)}devsite-book-nav .devsite-breadcrumb-guillemet:focus .devsite-google-wordmark-svg-path,devsite-book-nav .devsite-breadcrumb-guillemet:hover .devsite-google-wordmark-svg-path,devsite-book-nav .devsite-breadcrumb-link:focus .devsite-google-wordmark-svg-path,devsite-book-nav .devsite-breadcrumb-link:hover .devsite-google-wordmark-svg-path,devsite-header .devsite-breadcrumb-guillemet:focus .devsite-google-wordmark-svg-path,devsite-header .devsite-breadcrumb-guillemet:hover .devsite-google-wordmark-svg-path,devsite-header .devsite-breadcrumb-link:focus .devsite-google-wordmark-svg-path,devsite-header .devsite-breadcrumb-link:hover .devsite-google-wordmark-svg-path{fill:var(--devsite-primary-text-rgba)}devsite-book-nav .devsite-breadcrumb-guillemet,devsite-header .devsite-breadcrumb-guillemet{font-size:24px;margin:0 4px;width:24px}devsite-content .devsite-breadcrumb-guillemet{color:var(--devsite-secondary-text-color);font-size:18px;margin:0 4px;width:18px}devsite-book-nav .devsite-breadcrumb-guillemet:before,devsite-content .devsite-breadcrumb-guillemet:before,devsite-header .devsite-breadcrumb-guillemet:before{content:"chevron_right"}[dir=rtl] devsite-book-nav .devsite-breadcrumb-guillemet:before,[dir=rtl] devsite-content .devsite-breadcrumb-guillemet:before,[dir=rtl] devsite-header .devsite-breadcrumb-guillemet:before{content:"chevron_left"}devsite-book-nav .devsite-breadcrumb-link,devsite-content .devsite-breadcrumb-link,devsite-header .devsite-breadcrumb-link{display:inline-block;-webkit-transition:color .2s;transition:color .2s}devsite-header .devsite-doc-set-nav-row .devsite-breadcrumb-link,devsite-header .devsite-product-description-row .devsite-breadcrumb-guillemet,devsite-header .devsite-product-description-row .devsite-breadcrumb-link{color:var(--devsite-header-foreground-lower-hover,var(--devsite-inverted-text-color));fill:var(--devsite-header-foreground-lower-hover,var(--devsite-inverted-text-color))}devsite-header .devsite-doc-set-nav-row .devsite-breadcrumb-link:focus,devsite-header .devsite-doc-set-nav-row .devsite-breadcrumb-link:hover,devsite-header .devsite-product-description-row .devsite-breadcrumb-guillemet:focus,devsite-header .devsite-product-description-row .devsite-breadcrumb-guillemet:hover,devsite-header .devsite-product-description-row .devsite-breadcrumb-link:focus,devsite-header .devsite-product-description-row .devsite-breadcrumb-link:hover{color:var(--devsite-header-foreground-lower,var(--devsite-inverted-text-rgba));fill:var(--devsite-header-foreground-lower,var(--devsite-inverted-text-rgba))}devsite-book-nav .devsite-breadcrumb-link:focus,devsite-book-nav .devsite-breadcrumb-link:hover,devsite-header .devsite-breadcrumb-link:focus,devsite-header .devsite-breadcrumb-link:hover{text-decoration:none}devsite-content .devsite-breadcrumb-link{color:var(--devsite-breadcrumb-link-color,var(--devsite-secondary-text-color))}devsite-content .devsite-breadcrumb-link:focus,devsite-content .devsite-breadcrumb-link:hover{color:var(--devsite-breadcrumb-link-hover,var(--devsite-link-color));text-decoration:none}.devsite-nav{font-size:var(--devsite-nav-font-size,13px)}.devsite-nav-list,.devsite-nav-responsive-tabs,.devsite-nav-section{list-style-type:none;padding:0}.devsite-nav-item{line-height:var(--devsite-nav-item-line-height,16px);margin:0}.devsite-nav-title{color:var(--devsite-nav-title-color,var(--devsite-primary-text-color));display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;padding:var(--devsite-nav-title-padding,4px 0);-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.devsite-nav-title[href]:focus,.devsite-nav-title[href]:hover{color:var(--devsite-nav-color-hover,var(--devsite-link-color));text-decoration:none}.devsite-nav-heading>.devsite-nav-title{color:var(--devsite-nav-heading-color,var(--devsite-secondary-text-rgba));font-weight:700}.devsite-nav-active{font-weight:var(--devsite-nav-font-weight-active,500)}@media screen and (-ms-high-contrast:active),screen and (prefers-contrast:high){.devsite-nav-active{font-weight:700;text-decoration:underline}}.devsite-nav-active,.devsite-nav-active.devsite-nav-title,.devsite-nav-active.devsite-nav-title>.devsite-nav-icon:before,.devsite-nav-deprecated .devsite-nav-active.devsite-nav-title{color:var(--devsite-nav-color-active,var(--devsite-link-color-active,var(--devsite-link-color)))}.devsite-nav-text{overflow:hidden;text-overflow:ellipsis}.devsite-nav-accordion>.devsite-expandable-nav>.devsite-nav-title-no-path:focus,.devsite-nav-title-no-path:focus{color:var(--devsite-link-color)}.devsite-nav-icon{cursor:default;font-size:18px;margin:-1px 0 -1px 4px}[dir=rtl] .devsite-nav-icon{margin:-1px 4px -1px 0}.devsite-nav-icon:before{color:var(--devsite-secondary-text-color);content:"info"}.devsite-nav-icon[data-icon=alpha]:before,.devsite-nav-icon[data-icon=beta]:before,.devsite-nav-icon[data-icon=experimental]:before,.devsite-nav-icon[data-icon=preview]:before{content:url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18"><path d="M15.78,13.39L11,7V4h2V2H5v2h2v3l-4.9,6.53c-0.34,0.47-0.39,1.1-0.12,1.62C2.24,15.67,2.77,16,3.36,16h11.28 c0.86,0,1.56-0.7,1.56-1.56C16.2,14.04,16.03,13.67,15.78,13.39z" fill="%2380868b"/></svg>')}[appearance=dark] .devsite-nav-icon[data-icon=alpha]:before,[appearance=dark] .devsite-nav-icon[data-icon=beta]:before,[appearance=dark] .devsite-nav-icon[data-icon=experimental]:before,[appearance=dark] .devsite-nav-icon[data-icon=preview]:before{content:url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18"><path d="M15.78,13.39L11,7V4h2V2H5v2h2v3l-4.9,6.53c-0.34,0.47-0.39,1.1-0.12,1.62C2.24,15.67,2.77,16,3.36,16h11.28 c0.86,0,1.56-0.7,1.56-1.56C16.2,14.04,16.03,13.67,15.78,13.39z" fill="%239aa0a6"/></svg>')}.devsite-nav-deprecated .devsite-nav-title,.devsite-nav-deprecated.devsite-nav-accordion .devsite-nav-title,.devsite-nav-icon[data-icon=deprecated]:before,.devsite-nav-icon[data-icon=unsupported]:before{color:var(--devsite-secondary-text-color)}.devsite-nav-icon[data-icon=deprecated]:before,.devsite-nav-icon[data-icon=unsupported]:before{content:"not_interested"}.devsite-nav-icon[data-icon=external]:before{content:"open_in_new"}[dir=rtl] .devsite-nav-icon[data-icon=external]:before{display:inline-block;-webkit-transform:scaleX(-1);transform:scaleX(-1)}.devsite-nav-icon[data-icon=forward]:before{content:"arrow_forward";cursor:pointer}[dir=rtl] .devsite-nav-icon[data-icon=forward]:before{content:"arrow_back"}.devsite-nav-icon[data-icon=limited]:before{content:"verified_user"}.devsite-nav-icon[data-icon=new]:before{content:"new_releases"}.devsite-nav-icon[data-icon=nightly]:before{content:"nights_stay"}.button,.devsite-footer-utility-button>a,button,input[type=button],input[type=file],input[type=image],input[type=reset],input[type=submit]{-moz-appearance:none;-webkit-appearance:none;background:var(--devsite-button-background,var(--devsite-background-1));border:var(--devsite-button-border,0);border-radius:var(--devsite-button-border-radius,2px);box-shadow:var(--devsite-button-box-shadow,0 1px 2px 0 var(--devsite-elevation-key-shadow-color),0 1px 3px 1px var(--devsite-elevation-ambient-shadow-color));-moz-box-sizing:border-box;box-sizing:border-box;color:var(--devsite-button-color);cursor:pointer;display:inline-block;font:var(--devsite-button-font,500 14px/36px var(--devsite-primary-font-family));height:var(--devsite-button-height,36px);letter-spacing:var(--devsite-button-letter-spacing,0);line-height:var(--devsite-button-line-height,36px);margin:var(--devsite-button-margin,0);-webkit-margin-end:var(--devsite-button-margin-x-end);-moz-margin-end:var(--devsite-button-margin-x-end);margin-inline-end:var(--devsite-button-margin-x-end);max-width:var(--devsite-button-max-width,none);min-width:36px;outline:0;overflow:hidden;padding:var(--devsite-button-padding,0 16px);text-align:center;text-decoration:none;text-overflow:ellipsis;text-transform:var(--devsite-button-text-transform,uppercase);-webkit-transition:background-color .2s,border .2s,box-shadow .2s;transition:background-color .2s,border .2s,box-shadow .2s;vertical-align:middle;white-space:nowrap;width:var(--devsite-button-width,auto)}.button:focus,.button:hover,.devsite-footer-utility-button>a:focus,.devsite-footer-utility-button>a:hover,button:focus,button:hover,input[type=button]:focus,input[type=button]:hover,input[type=file]:focus,input[type=file]:hover,input[type=image]:focus,input[type=image]:hover,input[type=reset]:focus,input[type=reset]:hover,input[type=submit]:focus,input[type=submit]:hover{background:var(--devsite-button-background-hover);border:var(--devsite-button-border-hover,0);color:var(--devsite-button-color-hover,var(--devsite-button-color));font-weight:500;-webkit-text-decoration:var(--devsite-button-text-decoration-hover,none);-moz-text-decoration:var(--devsite-button-text-decoration-hover,none);text-decoration:var(--devsite-button-text-decoration-hover,none)}.button:focus,.devsite-footer-utility-button>a:focus,button:focus,input[type=button]:focus,input[type=file]:focus,input[type=image]:focus,input[type=reset]:focus,input[type=submit]:focus{box-shadow:var(--devsite-button-box-shadow-focus,none)}.button:active,.devsite-footer-utility-button>a:active,button:active,input[type=button]:active,input[type=file]:active,input[type=image]:active,input[type=reset]:active,input[type=submit]:active{background:var(--devsite-button-background-active);border:var(--devsite-button-border-active,0);box-shadow:var(--devsite-button-box-shadow-active,0 1px 2px 0 var(--devsite-elevation-key-shadow-color),0 2px 6px 2px var(--devsite-elevation-ambient-shadow-color));-webkit-transform:var(--devsite-button-transform-active,none);transform:var(--devsite-button-transform-active,none)}[foreground] .button,[foreground][background] .button{border-color:var(--devsite-foreground-button-border-color,transparent)}[foreground] .button,[foreground] .button:active,[foreground] .button:focus,[foreground] .button:hover,[foreground][background] .button,[foreground][background] .button:active,[foreground][background] .button:focus,[foreground][background] .button:hover{color:var(--devsite-foreground-button-color,var(--devsite-foreground-color,var(--devsite-primary-color,var(--devsite-button-color))))}[foreground] .button:active,[foreground] .button:focus,[foreground] .button:hover,[foreground][background] .button:active,[foreground][background] .button:focus,[foreground][background] .button:hover{background:var(--devsite-foreground-button-background-hover);border-color:var(--devsite-foreground-button-border-color-hover,transparent);color:var(--devsite-foreground-button-color-hover,var(--devsite-foreground-color,var(--devsite-primary-color,var(--devsite-button-color))))}[foreground] .button:active,[foreground][background] .button:active{background:var(--devsite-foreground-button-background-active,var(--devsite-foreground-button-background-hover));border-color:var(--devsite-foreground-button-border-color-active,transparent)}[background]:not(.devsite-landing-row-cards) .button:not([disabled]){background:var(--devsite-background-button-background,var(--devsite-background-1));border-color:var(--devsite-background-button-border-color,transparent);color:var(--devsite-foreground-button-color,var(--devsite-background-button-color,var(--devsite-button-color)))}[background]:not(.devsite-landing-row-cards) .button:not([disabled]):active,[background]:not(.devsite-landing-row-cards) .button:not([disabled]):focus,[background]:not(.devsite-landing-row-cards) .button:not([disabled]):hover{background:var(--devsite-background-button-background-hover,var(--devsite-button-background-hover));border-color:var(--devsite-background-button-border-color-hover,transparent);color:var(--devsite-foreground-button-color-hover,var(--devsite-foreground-button-color,var(--devsite-background-button-color-hover,var(--devsite-button-color))))}[background]:not(.devsite-landing-row-cards) .button:not([disabled]):active{border-color:var(--devsite-background-button-border-color-active,transparent)}.button.button-disabled,.button.button-disabled:active,.button.button-disabled:focus,.button.button-disabled:hover,[background] .button.button-disabled,[background] .button.button-disabled:active,[background] .button.button-disabled:focus,[background] .button.button-disabled:hover,[foreground] .button.button-disabled,[foreground] .button.button-disabled:active,[foreground] .button.button-disabled:focus,[foreground] .button.button-disabled:hover,body[theme] [background] .button.button-disabled,body[theme] [background] .button.button-disabled:active,body[theme] [background] .button.button-disabled:focus,body[theme] [background] .button.button-disabled:hover,body[theme] [foreground] .button.button-disabled,body[theme] [foreground] .button.button-disabled:active,body[theme] [foreground] .button.button-disabled:focus,body[theme] [foreground] .button.button-disabled:hover,button[disabled],button[disabled]:active,button[disabled]:focus,button[disabled]:hover,input[type=button][disabled],input[type=button][disabled]:active,input[type=button][disabled]:focus,input[type=button][disabled]:hover,input[type=file][disabled],input[type=file][disabled]:active,input[type=file][disabled]:focus,input[type=file][disabled]:hover,input[type=image][disabled],input[type=image][disabled]:active,input[type=image][disabled]:focus,input[type=image][disabled]:hover,input[type=reset][disabled],input[type=reset][disabled]:active,input[type=reset][disabled]:focus,input[type=reset][disabled]:hover,input[type=submit][disabled],input[type=submit][disabled]:active,input[type=submit][disabled]:focus,input[type=submit][disabled]:hover{background:var(--devsite-button-disabled-background,#ddd);border:var(--devsite-button-disabled-border,0);box-shadow:none;color:var(--devsite-button-disabled-color,var(--devsite-tertiary-text-rgba));cursor:default;line-height:var(--devsite-button-disabled-line-height,36px);pointer-events:none}.button-blue,.button-green,.button-primary,.button-red,body devsite-footer-utility .devsite-footer-utility-button>a{background:var(--devsite-button-primary-background,var(--devsite-button-color));color:var(--devsite-button-primary-color,var(--devsite-inverted-text-color));line-height:var(--devsite-button-primary-line-height,36px)}.button-blue,.button-blue:active,.button-blue:focus,.button-blue:hover,.button-green,.button-green:active,.button-green:focus,.button-green:hover,.button-primary,.button-primary:active,.button-primary:focus,.button-primary:hover,.button-red,.button-red:active,.button-red:focus,.button-red:hover,body devsite-footer-utility .devsite-footer-utility-button>a,body devsite-footer-utility .devsite-footer-utility-button>a:active,body devsite-footer-utility .devsite-footer-utility-button>a:focus,body devsite-footer-utility .devsite-footer-utility-button>a:hover{border:0}.button-blue:hover,.button-green:hover,.button-primary:hover,.button-red:hover,body devsite-footer-utility .devsite-footer-utility-button>a:hover{box-shadow:var(--devsite-button-primary-box-shadow-hover,0 1px 2px 0 var(--devsite-elevation-key-shadow-color),0 1px 3px 1px var(--devsite-elevation-ambient-shadow-color))}.button-blue:focus,.button-blue:hover,.button-green:focus,.button-green:hover,.button-primary:focus,.button-primary:hover,.button-red:focus,.button-red:hover,body devsite-footer-utility .devsite-footer-utility-button>a:focus,body devsite-footer-utility .devsite-footer-utility-button>a:hover{background:var(--devsite-button-primary-background-hover);border:var(--devsite-button-primary-border-hover);color:var(--devsite-button-primary-color-hover,var(--devsite-inverted-text-color))}.button-blue:active,.button-green:active,.button-primary:active,.button-red:active,body devsite-footer-utility .devsite-footer-utility-button>a:active{background:var(--devsite-button-primary-background-active);box-shadow:var(--devsite-button-primary-box-shadow-active,0 1px 2px 0 var(--devsite-elevation-key-shadow-color),0 2px 6px 2px var(--devsite-elevation-ambient-shadow-color));color:var(--devsite-button-primary-color-active,var(--devsite-inverted-text-color))}[background]:not(.devsite-landing-row-cards) .button-primary:not([disabled]){background:var(--devsite-background-button-primary-background,var(--devsite-background-1));color:var(--devsite-background-button-primary-color,var(--devsite-button-color))}[background]:not(.devsite-landing-row-cards) .button-primary:not([disabled]):active,[background]:not(.devsite-landing-row-cards) .button-primary:not([disabled]):focus,[background]:not(.devsite-landing-row-cards) .button-primary:not([disabled]):hover{color:var(--devsite-background-button-primary-color-hover,var(--devsite-background-button-primary-color,var(--devsite-button-color)))}[background]:not(.devsite-landing-row-cards) .button-primary:not([disabled]):focus,[background]:not(.devsite-landing-row-cards) .button-primary:not([disabled]):hover{background:var(--devsite-background-button-primary-background-hover)}[background]:not(.devsite-landing-row-cards) .button-primary:not([disabled]):active{background:var(--devsite-background-button-primary-background-hover)}[foreground] .button-primary,[foreground][background] .button-primary{background:var(--devsite-foreground-button-primary-background);color:var(--devsite-foreground-button-primary-color,var(--devsite-inverted-text-color))}[foreground] .button-primary:active,[foreground] .button-primary:focus,[foreground] .button-primary:hover,[foreground][background] .button-primary:active,[foreground][background] .button-primary:focus,[foreground][background] .button-primary:hover{background:var(--devsite-foreground-button-primary-background-hover);color:var(--devsite-foreground-button-primary-color-hover,var(--devsite-foreground-button-primary-color,var(--devsite-inverted-text-color)))}.button-white{background:0;line-height:var(--devsite-button-white-line-height,36px);padding:0 8px}.button-white,.button-white:active,.button-white:focus,.button-white:hover{border:0;color:var(--devsite-button-white-color,var(--devsite-button-color))}.button-white,.button-white:hover{box-shadow:var(--devsite-button-white-box-shadow-hover,none)}.button-white:active,.button-white:focus,.button-white:hover{-webkit-text-decoration:var(--devsite-button-white-text-decoration-hover,none);-moz-text-decoration:var(--devsite-button-white-text-decoration-hover,none);text-decoration:var(--devsite-button-white-text-decoration-hover,none)}.button-white:focus,.button-white:hover{background:var(--devsite-button-white-background-hover,var(--devsite-button-background-hover))}.button-white:focus{box-shadow:var(--devsite-button-white-box-shadow-focus,none)}.button-white:active{background:var(--devsite-button-white-background-active,var(--devsite-button-background-active));box-shadow:var(--devsite-button-white-box-shadow-active,none)}[background]:not(.devsite-landing-row-cards) .button-white:not([disabled]){background:transparent}[background]:not(.devsite-landing-row-cards) .button-white:not([disabled]),[background]:not(.devsite-landing-row-cards) .button-white:not([disabled]):active,[background]:not(.devsite-landing-row-cards) .button-white:not([disabled]):focus,[background]:not(.devsite-landing-row-cards) .button-white:not([disabled]):hover{color:var(--devsite-background-button-white-color,var(--devsite-inverted-text-color))}[background]:not(.devsite-landing-row-cards) .button-white:not([disabled]):hover{background:var(--devsite-background-button-white-background-hover)}[background]:not(.devsite-landing-row-cards) .button-white:not([disabled]):focus{background:var(--devsite-background-button-white-background-focus)}[background][foreground] .button-white,[background][foreground] .button-white:active,[background][foreground] .button-white:focus,[background][foreground] .button-white:hover,[foreground] .button-white,[foreground] .button-white:active,[foreground] .button-white:focus,[foreground] .button-white:hover{color:var(--devsite-foreground-button-white-color,var(--devsite-foreground-button-color,var(--devsite-foreground-color)))}[background][foreground] .button-white:focus,[background][foreground] .button-white:hover,[foreground] .button-white:focus,[foreground] .button-white:hover{background:var(--devsite-foreground-button-white-background-hover,var(--devsite-foreground-button-background-hover))}[background][foreground] .button-white:active,[foreground] .button-white:active{background:var(--devsite-foreground-button-white-background-active,var(--devsite-foreground-button-background-active,var(--devsite-foreground-button-background-hover)))}[background=theme]:not(.devsite-landing-row-cards) .button-white{color:var(--devsite-text-color,var(--devsite-inverted-text-color))}.button-white.button-disabled,.button-white[disabled]{background:0}.button-raised{background:var(--devsite-button-raised-background,var(--devsite-background-1));box-shadow:0 1px 2px 0 var(--devsite-elevation-key-shadow-color),0 1px 3px 1px var(--devsite-elevation-ambient-shadow-color);line-height:var(--devsite-button-raised-line-height,36px)}.button-raised,.button-raised:active,.button-raised:focus,.button-raised:hover{border:0;color:var(--devsite-button-raised-color,var(--devsite-button-color))}.button-raised:focus,.button-raised:hover{background:var(--devsite-button-raised-background-hover,var(--devsite-button-background-hover));box-shadow:0 1px 2px 0 var(--devsite-elevation-key-shadow-color),0 2px 6px 2px var(--devsite-elevation-ambient-shadow-color)}.button-raised:active{background:var(--devsite-button-raised-background-active,var(--devsite-button-background-active));box-shadow:0 1px 3px 0 var(--devsite-elevation-key-shadow-color),0 4px 8px 3px var(--devsite-elevation-ambient-shadow-color)}[background]:not(.devsite-landing-row-cards) .button-raised{background:var(--devsite-background-1)}.button+.button,button+button,input[type=button]+input[type=button],input[type=file]+input[type=file],input[type=image]+input[type=image],input[type=reset]+input[type=reset],input[type=submit]+input[type=submit]{-webkit-margin-start:var(--devsite-button-sibling-gap-x,16px);-moz-margin-start:var(--devsite-button-sibling-gap-x,16px);margin-inline-start:var(--devsite-button-sibling-gap-x,16px)}.button-flat+.button-flat,.button-white+.button-white,button+.button{margin-left:8px}[dir=rtl] .button-flat+.button-flat,[dir=rtl] .button-white+.button-white,[dir=rtl] button+.button{margin-left:0;margin-right:8px}.button-flat{padding:0 8px}.button-flat,.button-flat:active,.button-flat:focus,.button-flat:hover{background:0;border:0;box-shadow:none}.button-flat:disabled{background-color:transparent}[foreground] .button-primary:active,[foreground] .button-primary:focus,[foreground] .button-primary:hover,[foreground] .button-raised:active,[foreground] .button-raised:focus,[foreground] .button-raised:hover,[foreground] .button-white:active,[foreground] .button-white:focus,[foreground] .button-white:hover{border:0}.button-transparent{padding:0 8px}.button-transparent,.button-transparent:focus,.button-transparent:hover{background-color:transparent;border:0;box-shadow:none}.button-text-white{color:var(--devsite-inverted-text-color)}.button-text-blue{color:var(--devsite-link-color)}.button-lowercase{text-transform:none}[dir=ltr] .button-unindented{margin-left:var(--devsite-button-unindented-margin-x,-8px)}[dir=rtl] .button-unindented{margin-right:var(--devsite-button-unindented-margin-x,-8px)}.button-icon,.button>.material-icons,button>.material-icons{font-size:18px;height:18px;width:18px}.button.button-with-icon,.button.external{padding:var(--devsite-button-with-icon-padding,0 16px)}.button-primary.button-with-icon,.button-primary.external,.button-raised.button-with-icon,.button-raised.external{padding:var(--devsite-button-primary-with-icon-padding,0 16px)}.button-white.button-with-icon,.button-white.external{padding:0 16px}.button>.material-icons,button>.material-icons{margin:0 8px;position:relative;top:-2px;vertical-align:middle}.button>.button-icon,button>.button-icon{margin:0 8px}.button-with-icon>.button-icon,.button-with-icon>.material-icons{margin:0 8px 0 -4px}[dir=rtl] .button-with-icon>.button-icon,[dir=rtl] .button-with-icon>.material-icons{margin:0 -4px 0 8px}.button-with-icon>.icon-after,.button.external:not(.button-with-icon):after,button.external:not(.button-with-icon):after{margin:0 -4px 0 8px}[dir=rtl] .button-with-icon>.icon-after,[dir=rtl] .button.external:not(.button-with-icon):after,[dir=rtl] button.external:not(.button-with-icon):after{margin:0 8px 0 -4px}[dir=ltr] .button:not(.button-with-icon)>.material-icons:not(.icon-after){margin-left:var(--devsite-button-material-icon-margin-x,-4px)}[dir=rtl] .button:not(.button-with-icon)>.material-icons:not(.icon-after){margin-right:var(--devsite-button-material-icon-margin-x,-4px)}[dir=ltr] .button:not(.button-with-icon)>.icon-after{margin-right:var(--devsite-button-material-icon-margin-x,-4px)}[dir=rtl] .button:not(.button-with-icon)>.icon-after{margin-left:var(--devsite-button-material-icon-margin-x,-4px)}[dir=ltr] .button-white:not(.button-with-icon)>.material-icons:not(.icon-after){margin-left:var(--devsite-button-white-material-icon-margin-x,4px)}[dir=rtl] .button-white:not(.button-with-icon)>.material-icons:not(.icon-after){margin-right:var(--devsite-button-white-material-icon-margin-x,4px)}[dir=ltr] .button-white:not(.button-with-icon)>.icon-after{margin-right:var(--devsite-button-white-material-icon-margin-x,4px)}[dir=rtl] .button-white:not(.button-with-icon)>.icon-after{margin-left:var(--devsite-button-white-material-icon-margin-x,4px)}.devsite-landing-row-item[foreground=grey] .button,[foreground=grey] .button{background:var(--devsite-secondary-text-color)}.devsite-landing-row-item[foreground=grey] .button:active,.devsite-landing-row-item[foreground=grey] .button:focus,.devsite-landing-row-item[foreground=grey] .button:hover,[foreground=grey] .button:active,[foreground=grey] .button:focus,[foreground=grey] .button:hover{background:#3c4043}[layout=docs] h1,[layout=docs] h2,[layout=docs] h3,[layout=docs] h4,[layout=docs] h5,[layout=docs] h6{overflow:hidden;text-overflow:ellipsis}.devsite-article h1:first-of-type{display:inline;margin-top:0;vertical-align:middle}.devsite-article[has-bookmark] h1:first-of-type{-webkit-margin-end:83px;-moz-margin-end:83px;margin-inline-end:83px}.devsite-landing-row h2,.devsite-landing-row-item-description h3,h1{color:var(--devsite-heading-color,var(--devsite-secondary-text-color))}.devsite-landing-row h2,.devsite-landing-row-large-headings .devsite-landing-row-item-description h3,h1{font:var(--devsite-h1-font);letter-spacing:var(--devsite-h1-letter-spacing);margin:var(--devsite-h1-margin)}.devsite-landing-row-1-up.devsite-landing-row-hero .devsite-landing-row-item-description h3,.devsite-landing-row-large-headings h2{font:var(--devsite-display-font);letter-spacing:var(--devsite-display-letter-spacing)}.devsite-landing-row .devsite-catalog-alphabet-letter-heading h2{margin:20px 0}[layout=docs] h2{border-bottom:var(--devsite-h2-border,var(--devsite-secondary-border));padding:var(--devsite-h2-padding)}.devsite-landing-row h3,h2{font:var(--devsite-h2-font);letter-spacing:var(--devsite-h2-letter-spacing);margin:var(--devsite-h2-margin)}h3{font:var(--devsite-h3-font);letter-spacing:var(--devsite-h3-letter-spacing);margin:var(--devsite-h3-margin)}.devsite-landing-row h4,.devsite-landing-row-item-no-media h3{font:var(--devsite-h3-font);margin:var(--devsite-h3-margin,32px 0 12px);padding:0}.devsite-landing-row-large-headings .devsite-landing-row-item-list h4{font:400 20px/32px var(--devsite-primary-font-family);letter-spacing:-.01em}h4,h5,h6{margin:32px 0 16px}h4{font:var(--devsite-h4-font);letter-spacing:var(--devsite-h4-letter-spacing)}h5{font:var(--devsite-h5-font);letter-spacing:var(--devsite-h5-letter-spacing)}h6{font:var(--devsite-h6-font);letter-spacing:var(--devsite-h6-letter-spacing)}h1+dl>dt:first-child,h1+h1,h1+h2,h1+h3,h1+h4,h1+h5,h1+h6,h2+dl>dt:first-child,h2+h1,h2+h2,h2+h3,h2+h4,h2+h5,h2+h6,h3+dl>dt:first-child,h3+h1,h3+h2,h3+h3,h3+h4,h3+h5,h3+h6,h4+dl>dt:first-child,h4+h1,h4+h2,h4+h3,h4+h4,h4+h5,h4+h6,h5+dl>dt:first-child,h5+h1,h5+h2,h5+h3,h5+h4,h5+h5,h5+h6,h6+dl>dt:first-child,h6+h1,h6+h2,h6+h3,h6+h4,h6+h5,h6+h6{margin-top:0}table{border:0;border-collapse:collapse;border-spacing:0;font:14px/20px var(--devsite-primary-font-family);margin:16px 0 15px;width:100%}caption{background:var(--devsite-background-3);font-weight:500;padding:12px 8px;text-align:center}tr{background:var(--devsite-table-row-background,0);border:0;border-bottom:var(--devsite-table-row-border,var(--devsite-primary-border))}tr:first-child{border-top:var(--devsite-table-row-border,var(--devsite-primary-border))}td,th{border:0;margin:0;text-align:left}[dir=rtl] td,[dir=rtl] th{text-align:right}th{font:var(--devsite-table-heading-font,500 16px/24px var(--devsite-primary-font-family));height:48px;padding:var(--devsite-table-heading-padding,8px);vertical-align:middle}th>h2,th>h3{border:0;font:var(--devsite-table-heading-font,500 16px/24px var(--devsite-primary-font-family));margin:0!important;padding:0!important}td>.expandable>h2.showalways,td>.expandable>h3.showalways,td>h2:only-child,td>h3:only-child{border:0;font:500 14px/20px var(--devsite-primary-font-family);margin:0;padding-bottom:0}td>.expandable>h2.showalways,td>.expandable>h3.showalways{line-height:24px}table h4,table h5,table h6{margin-left:0!important;margin-right:0!important;padding-left:0!important;padding-right:0!important}td b,td strong,th b,th strong{font-weight:500}td{padding:var(--devsite-table-cell-padding,7px 8px 8px)}td code,th code{background:0;border:0;font:500 100%/1 var(--devsite-code-font-family);-moz-osx-font-smoothing:auto;-webkit-font-smoothing:auto;padding:0}td pre code{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}table.responsive td,table.responsive th{min-width:214px}table.responsive table:not(.responsive) td,table.responsive table:not(.responsive) th{min-width:120px}table.responsive td code,table.responsive th code{word-break:break-all;word-break:break-word}table.responsive td tr:not(.alt) td:first-child,table.responsive tr:not(.alt) td td:first-child,td{background:var(--devsite-table-cell-background);vertical-align:top}table.fixed{table-layout:fixed}table.fixed td,table.fixed td code,table.fixed th,table.fixed th code{word-break:break-word}.devsite-table-wrapper{margin:var(--devsite-table-margin,16px 0);overflow:auto}.devsite-table-wrapper .devsite-table-wrapper{margin:0;overflow:visible}.devsite-table-wrapper table{margin:0}.devsite-table-wrapper .devsite-table-wrapper table{margin:16px 0}table.responsive table.responsive{margin:0}table.responsive td tr:first-child td{padding-top:0}table.responsive td tr:last-child td{padding-bottom:0}[dir=ltr] table.responsive td td:first-child{padding-left:0}[dir=rtl] table.responsive td td:first-child{padding-right:0}table.responsive>*>tr>th:not(:first-child),table.responsive>tr>th:not(:first-child){display:none}table.columns tr{border:0}table table tr:first-child{border-top:0}devsite-selector .devsite-table-wrapper:last-child tr:last-child,table table tr:last-child{border-bottom:0}th,th code{background:var(--devsite-table-heading-background,#e8eaed);color:var(--devsite-table-heading-color,var(--devsite-primary-text-color))}table.vertical-rules tr>td:not(:last-child),table.vertical-rules tr>th:not(:last-child){border-right:var(--devsite-table-row-border,var(--devsite-primary-border))}.alt td,table.alternating-even-rows tr:nth-child(2n) td,table.alternating-odd-rows tr:nth-child(odd) td,td.alt{background:var(--devsite-alt-table-cell-background)}table.responsive>*>tr:not(.alt) td:first-child,table.responsive>tr:not(.alt) td:first-child{background:var(--devsite-responsive-table-first-column-background)}.devsite-article-body>.devsite-full-width-table,.devsite-article-body>table.full-width{margin:16px -40px}@media screen and (max-width:840px){.devsite-article-body>.devsite-full-width-table,.devsite-article-body>table.full-width{margin:16px -24px}}@media screen and (max-width:600px){.devsite-article-body>.devsite-full-width-table,.devsite-article-body>table.full-width{margin:16px -16px}}.devsite-article-body>.devsite-full-width-table td:first-child,.devsite-article-body>.devsite-full-width-table th:first-child,.devsite-article-body>table.full-width td:first-child,.devsite-article-body>table.full-width th:first-child{padding-left:40px}@media screen and (max-width:840px){.devsite-article-body>.devsite-full-width-table td:first-child,.devsite-article-body>.devsite-full-width-table th:first-child,.devsite-article-body>table.full-width td:first-child,.devsite-article-body>table.full-width th:first-child{padding-left:24px}}@media screen and (max-width:600px){.devsite-article-body>.devsite-full-width-table td:first-child,.devsite-article-body>.devsite-full-width-table th:first-child,.devsite-article-body>table.full-width td:first-child,.devsite-article-body>table.full-width th:first-child{padding-left:16px}}.devsite-article-body>.devsite-full-width-table td:last-child,.devsite-article-body>.devsite-full-width-table th:last-child,.devsite-article-body>table.full-width td:last-child,.devsite-article-body>table.full-width th:last-child{padding-right:40px}@media screen and (max-width:840px){.devsite-article-body>.devsite-full-width-table td:last-child,.devsite-article-body>.devsite-full-width-table th:last-child,.devsite-article-body>table.full-width td:last-child,.devsite-article-body>table.full-width th:last-child{padding-right:24px}}@media screen and (max-width:600px){.devsite-article-body>.devsite-full-width-table td:last-child,.devsite-article-body>.devsite-full-width-table th:last-child,.devsite-article-body>table.full-width td:last-child,.devsite-article-body>table.full-width th:last-child{padding-right:16px}}.devsite-full-width-table table table td:first-child,.devsite-full-width-table table table th:first-child{padding-left:0}@media screen and (max-width:840px){.devsite-full-width-table table table td:first-child,.devsite-full-width-table table table th:first-child{padding-right:0}}.devsite-full-width-table table table td:last-child,.devsite-full-width-table table table th:last-child{padding-right:0}@media screen and (max-width:840px){.devsite-full-width-table table table td:last-child,.devsite-full-width-table table table th:last-child{padding-left:0}}@media screen and (max-width:840px){table.responsive td,table.responsive th,table.responsive tr{display:block}table.responsive table:not(.responsive) tr{display:table-row}table.responsive table:not(.responsive) td,table.responsive table:not(.responsive) th{display:table-cell}table.responsive>*>th,table.responsive>th{height:auto;padding:var(--devsite-responsive-table-heading-padding,14px 8px)}table.fixed.responsive col{display:contents}}.devsite-book-nav::-webkit-scrollbar,.devsite-dialog::-webkit-scrollbar,.devsite-popout::-webkit-scrollbar,.devsite-table-wrapper::-webkit-scrollbar,.devsite-tabs-overflow-menu::-webkit-scrollbar,.devsite-toc::-webkit-scrollbar,[scrollbars]::-webkit-scrollbar,pre::-webkit-scrollbar{height:8px;width:8px}.devsite-book-nav::-webkit-scrollbar-thumb,.devsite-dialog::-webkit-scrollbar-thumb,.devsite-popout::-webkit-scrollbar-thumb,.devsite-table-wrapper::-webkit-scrollbar-thumb,.devsite-tabs-overflow-menu::-webkit-scrollbar-thumb,.devsite-toc::-webkit-scrollbar-thumb,[scrollbars]::-webkit-scrollbar-thumb,pre::-webkit-scrollbar-thumb{background:var(--devsite-scrollbar-thumb-background);border-radius:8px}.devsite-doc-set-nav-row::-webkit-scrollbar,.devsite-header-upper-tabs::-webkit-scrollbar,[no-horizontal-scrollbars]::-webkit-scrollbar{height:0;width:0}.devsite-table-wrapper::-webkit-scrollbar-corner,[scrollbars]::-webkit-scrollbar-corner,pre::-webkit-scrollbar-corner{background:0}.devsite-cse-confidential-results{background:var(--devsite-confidential-results-background);margin:16px -40px;padding:0 40px 16px}.devsite-cse-confidential-results+aside{margin-top:-16px!important}.devsite-search-results-stats{margin-bottom:8px}.devsite-search-results .gs-title{font-weight:500}.devsite-search-results .gs-title:link,.devsite-search-results .gs-title:visited{color:var(--devsite-link-color)}.devsite-search-results .gs-webResult .gs-visibleUrl{color:var(--devsite-search-results-breadcrumb-color);font-size:14px}.devsite-search-results .gs-snippet{margin-top:0}.devsite-search-results .gs-webResult:not(.gs-no-results-result):not(.gs-error-result) .gs-snippet{color:var(--devsite-primary-text-color)}.devsite-result-item-link .devsite-result-item-confidential,.devsite-search-results .gs-title-label{background:var(--devsite-caution-notice-background);border-radius:4px;color:var(--devsite-caution-notice-color);display:inline-block;font:500 11px/16px var(--devsite-primary-font-family);letter-spacing:.8px;margin:0 8px;padding:5px 8px 3px;text-transform:uppercase}body[template=search] .gsc-webResult .gsc-result{border:none;margin:24px 0;padding:0}.devsite-search-page-controls{margin-top:8px}.devsite-search-project{border-bottom:var(--devsite-primary-border);margin-bottom:24px;padding-bottom:23px}.devsite-search-project .devsite-project-scoped-results-title{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-bottom:8px}.devsite-search-project .devsite-project-scoped-results-title .devsite-product-name-wrapper{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-flex:0;-webkit-flex:0 0 auto;-moz-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;height:36px;margin:6px 0}.devsite-search-project .devsite-project-scoped-results-title .devsite-product-name-link,.devsite-search-project .devsite-project-scoped-results-title .devsite-site-logo-link{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;opacity:1;-webkit-transition:opacity .2s;transition:opacity .2s}.devsite-search-project .devsite-project-scoped-results-title .devsite-product-name-link:focus,.devsite-search-project .devsite-project-scoped-results-title .devsite-product-name-link:hover,.devsite-search-project .devsite-project-scoped-results-title .devsite-site-logo-link:focus{opacity:.7;text-decoration:none}.devsite-search-project .devsite-project-scoped-results-title .devsite-site-logo{height:var(--devsite-logo-height,32px)}.devsite-search-project .devsite-project-scoped-results-title .devsite-has-google-wordmark>.devsite-breadcrumb-link,.devsite-search-project .devsite-project-scoped-results-title .devsite-has-google-wordmark>.devsite-product-name{direction:ltr}.devsite-search-project .devsite-project-scoped-results-title .devsite-google-wordmark{height:24px;margin:0 4px 0 0;position:relative;top:5px}.devsite-search-project .devsite-project-scoped-results-title .devsite-google-wordmark-svg-path{-webkit-transition:fill .2s;transition:fill .2s}.devsite-search-project .devsite-project-scoped-results-title .devsite-site-logo-link canvas{height:auto!important}.devsite-search-project .devsite-project-scoped-results-title .devsite-site-logo-link picture{display:contents}.devsite-search-project .devsite-project-scoped-results-title .devsite-product-logo-container{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;border-radius:50%;color:var(--devsite-primary-color,var(--devsite-primary-text-color));display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;height:36px;-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;-ms-flex-pack:center;justify-content:center;margin-inline:0 4px;width:36px}.devsite-search-project .devsite-project-scoped-results-title .devsite-product-logo-container[background]{background:var(--devsite-primary-color,var(--devsite-primary-text-color));color:var(--devsite-inverted-text-color)}.devsite-search-project .devsite-project-scoped-results-title .devsite-product-logo{color:inherit;font-size:32px;height:32px;max-width:32px;min-width:32px;overflow:hidden;white-space:nowrap}.devsite-search-project .devsite-project-scoped-results-title .devsite-product-logo-container[background] .devsite-product-logo{font-size:28px;height:28px;max-width:28px;min-width:28px}.devsite-search-project .devsite-project-scoped-results-title .devsite-product-name{font:var(--devsite-wordmark-font,400 20px/32px var(--devsite-primary-font-family));letter-spacing:0;margin:0;max-height:32px;overflow:hidden;text-overflow:ellipsis;-webkit-transition:color .2s;transition:color .2s;white-space:nowrap}.devsite-search-project .devsite-project-scoped-results-title .devsite-site-logo:not([src*=".svg"]){height:auto;max-height:32px}.devsite-search-project .devsite-project-scoped-results-title .devsite-breadcrumb-link>.devsite-product-name{color:inherit}@media screen and (max-width:840px){.devsite-search-project .devsite-project-scoped-results-title .devsite-product-name-wrapper{-webkit-box-flex:0;-webkit-flex:0 1 auto;-moz-box-flex:0;-ms-flex:0 1 auto;flex:0 1 auto;min-width:0}.devsite-search-project .devsite-project-scoped-results-title .devsite-product-name-wrapper .devsite-breadcrumb-item:not(:first-of-type),.devsite-search-project .devsite-project-scoped-results-title .devsite-product-name-wrapper .devsite-site-logo-link+.devsite-product-name{display:none}.devsite-search-project .devsite-project-scoped-results-title .devsite-product-name-wrapper .devsite-breadcrumb-item,.devsite-search-project .devsite-project-scoped-results-title .devsite-product-name-wrapper .devsite-breadcrumb-link,.devsite-search-project .devsite-project-scoped-results-title .devsite-product-name-wrapper .devsite-breadcrumb-list,.devsite-search-project .devsite-project-scoped-results-title .devsite-product-name-wrapper .devsite-product-name{width:100%}.devsite-search-project .devsite-project-scoped-results-title .devsite-product-name-wrapper .devsite-breadcrumb-link{overflow:hidden;text-overflow:ellipsis}}.devsite-search-project .devsite-project-scoped-results-title .devsite-product-name-wrapper{position:relative;margin-left:.3em}.devsite-search-project .devsite-breadcrumb-list,.devsite-search-project .devsite-project-scoped-results-title{font:var(--devsite-wordmark-font,400 20px/32px var(--devsite-primary-font-family))}.devsite-search-project .devsite-breadcrumb-link,.devsite-search-project .devsite-breadcrumb-link:hover{color:var(--devsite-primary-text-color)}.devsite-search-project .devsite-product-logo-container{color:var(--devsite-primary-color,var(--devsite-primary-text-color))}.devsite-search-project .devsite-product-logo-container[background]{background:var(--devsite-primary-color,var(--devsite-primary-text-color));color:var(--devsite-inverted-text-color)}.devsite-search-project .devsite-breadcrumb-link .devsite-google-wordmark{fill:currentColor}.devsite-steps{border-top:var(--devsite-steps-border,0);display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;margin:var(--devsite-steps-margin,0);padding:var(--devsite-steps-padding,24px 0 40px)}.devsite-steps .steps-direction{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-moz-box-orient:vertical;-moz-box-direction:normal;-ms-flex-direction:column;flex-direction:column;-webkit-box-flex:1;-webkit-flex-grow:1;-moz-box-flex:1;-ms-flex-positive:1;flex-grow:1;font-weight:500;-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;-ms-flex-pack:center;justify-content:center;position:relative}.devsite-steps .steps-previous{margin-left:var(--devsite-steps-prev-next-margin-x,40px)}.devsite-steps .steps-next{margin-right:var(--devsite-steps-prev-next-margin-x,40px);text-align:right}.devsite-steps .steps-link:hover{-webkit-text-decoration:var(--devsite-steps-text-decoration-hover,none);-moz-text-decoration:var(--devsite-steps-text-decoration-hover,none);text-decoration:var(--devsite-steps-text-decoration-hover,none)}.devsite-steps .steps-link:focus{text-decoration:none}.devsite-steps .steps-link-direction{color:var(--devsite-steps-direction-color,var(--devsite-link-color));display:block;font:var(--devsite-steps-direction-font,500 14px/24px var(--devsite-primary-font-family))}.devsite-steps .steps-link-title{color:var(--devsite-steps-title-color);display:var(--devsite-steps-title-display,inline);font:var(--devsite-steps-title-font,500 18px/24px var(--devsite-primary-font-family))}.devsite-steps .steps-link:hover .steps-link-title{border-bottom:var(--devsite-steps-title-border-hover,none)}.devsite-steps .steps-link:focus .steps-link-title{border-bottom:var(--devsite-steps-title-border-focus)}.devsite-steps .steps-link-arrow{color:var(--devsite-steps-arrow-color,var(--devsite-link-color));position:absolute}.devsite-steps .steps-link-arrow-left{left:var(--devsite-steps-arrow-x-start,-40px)}.devsite-steps .steps-link-arrow-right{right:var(--devsite-steps-arrow-x-start,-40px)}@media screen and (max-width:840px){.devsite-steps .steps-link-title{font:var(--devsite-steps-title-font,500 14px/24px var(--devsite-primary-font-family))}.devsite-steps .steps-previous{margin-left:var(--devsite-steps-prev-next-margin-x,24px)}.devsite-steps .steps-next{margin-right:var(--devsite-steps-prev-next-margin-x,24px)}.devsite-steps .steps-link-arrow-left{left:var(--devsite-steps-arrow-x-start,-24px)}.devsite-steps .steps-link-arrow-right{right:var(--devsite-steps-arrow-x-start,-24px)}.devsite-steps .steps-link-arrow{bottom:var(--devsite-steps-arrow-y-end,4px);font-size:16px}}@media screen and (max-width:600px){.devsite-steps{padding:8px 0 16px}.devsite-steps .steps-previous{margin-left:var(--devsite-steps-prev-next-margin-x,0)}.devsite-steps .steps-next{margin-right:var(--devsite-steps-prev-next-margin-x,0)}.devsite-steps .steps-link-arrow{display:var(--devsite-steps-arrow-display,none)}}.devsite-jsfiddle-hide{display:none}html[cached] .devsite-wrapper{display:none}.devsite-dialog:not([is-upgraded]),iframe.devsite-embedded-youtube-video:not([is-upgraded]){pointer-events:none;visibility:hidden}.code-sample,.data-sample,.ds-selector-dropdown,.ds-selector-tabs,.kd-tabbed-horz,.kd-tabbed-vert{display:none}.expandable{display:none}devsite-selector{pointer-events:none;visibility:hidden}devsite-search .devsite-searchbox{background:var(--devsite-searchbox-background,var(--devsite-background-3));border-radius:2px}iframe.framebox,iframe.inherit-locale{display:block;width:100%}[background]{background-color:var(--devsite-background-color,var(--devsite-primary-color))}[background],[background]:not([foreground]){color:var(--devsite-text-color,var(--devsite-inverted-text-color))}[background] :link:not(.button),[background] :visited:not(.button){color:var(--devsite-foreground-color,var(--devsite-link-color))}[background] :focus>:not(.material-icons),[background] :link>:not(.material-icons):hover,[background] p>a:not(.button){-webkit-text-decoration:var(--devsite-background-text-decoration,underline);-moz-text-decoration:var(--devsite-background-text-decoration,underline);text-decoration:var(--devsite-background-text-decoration,underline)}[background] p>a:focus{background:var(--devsite-inverted-text-rgba);border-radius:2px;margin:-4px;padding:4px;text-decoration:none}[foreground] :focus>:not(.material-icons),[foreground] :link>:not(.material-icons):hover{color:var(--devsite-foreground-color,var(--devsite-primary-color,var(--devsite-link-color)));text-decoration:underline}[foreground] h2 a:not(.button),[foreground] h3 a:not(.button){color:var(--devsite-foreground-color,var(--devsite-primary-color,var(--devsite-link-color)))}.devsite-landing-row-item[foreground] h2 a:not(.button),.devsite-landing-row-item[foreground] h3 a:not(.button){color:var(--devsite-foreground-color,var(--devsite-primary-color,var(--devsite-link-color)))}devsite-content{display:block;position:relative}body[layout=docs] devsite-content{align-self:start;grid-column:2;grid-row:1;margin:24px 0;max-width:936px;min-width:0}body[layout=docs] .devsite-article{background-color:var(--devsite-background-1);border:var(--devsite-page-border,0);border-radius:var(--devsite-page-border-radius,2px);box-shadow:var(--devsite-page-box-shadow,0 1px 2px 0 var(--devsite-elevation-key-shadow-color),0 1px 3px 1px var(--devsite-elevation-ambient-shadow-color));padding:40px}body[layout=docs][template=landing] .devsite-article{padding:0}.devsite-article-meta{display:grid;grid-gap:0 16px;grid-template-areas:"breadcrumbs ratings";grid-template-columns:1fr auto;margin:var(--devsite-article-meta-margin,0 0 16px)}.devsite-article-meta .devsite-breadcrumb-list{grid-area:breadcrumbs}.devsite-article-meta devsite-thumb-rating{grid-area:ratings}.devsite-banner+.devsite-article-meta{margin-top:-16px}body[layout=full] .devsite-article-meta,body[template=landing] .devsite-article-meta{margin:0}devsite-feedback[position=header]{display:block}[dir=ltr] devsite-feedback[position=header]{float:right;margin-left:24px}[dir=rtl] devsite-feedback[position=header]{float:left;margin-right:24px}body[layout=full] devsite-feedback[position=header],body[template=landing] devsite-feedback[position=header]{display:none}[template=page] .devsite-article-body{margin-top:16px}[template=page] .devsite-article-body>:first-child{margin-top:0}@media screen and (max-width:840px){body[layout=docs] devsite-content{margin:0}body[layout=docs] .devsite-article{border:0;border-radius:0;box-shadow:none;padding:24px}.devsite-banner+.devsite-article-meta{margin-top:0}}@media screen and (max-width:600px){body[layout=docs] .devsite-article{padding:16px}.devsite-article-meta{display:block;margin:0 0 12px}[dir] devsite-feedback[position=header]{float:none;margin:0 0 12px;position:static}[dir] article[has-bookmark] devsite-feedback[position=header]{margin:0 0 12px}}#devsite-support-form{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;margin:0 0 0 -40px}#devsite-support-form>*{-webkit-box-flex:0;-webkit-flex:0 0 100%;-moz-box-flex:0;-ms-flex:0 0 100%;flex:0 0 100%;padding:0 0 0 40px}.devsite-support-form-error{color:#dd2c00}.devsite-support-form-hidden{display:none}.devsite-support-form-field{margin:0 0 8px}.devsite-support-form-field input:not([type=checkbox]):not([type=radio]),.devsite-support-form-field select,.devsite-support-form-field textarea{width:100%}.devsite-support-form-cc{color:var(--devsite-secondary-text-color);display:block;font-size:13px}#devsite-support-form>.devsite-support-form-half{-webkit-box-flex:0;-webkit-flex:0 0 50%;-moz-box-flex:0;-ms-flex:0 0 50%;flex:0 0 50%}.devsite-support-quota{font:italic 400 12px/20px var(--devsite-primary-font-family);margin-bottom:8px}.devsite-support-quota-help{font-size:18px;margin-left:4px;vertical-align:top}.devsite-support-quota-help:after{color:var(--devsite-tertiary-text-color);content:"help"}@media screen and (max-width:600px){#devsite-support-form{display:block}}.devsite-404,.devsite-offline{font:var(--devsite-404-font);letter-spacing:var(--devsite-404-letter-spacing);margin:var(--devsite-404-margin,120px auto 0);max-width:var(--devsite-404-max-width,804px);min-height:var(--devsite-404-min-height);position:relative;text-align:var(--devsite-404-text-align,center)}.devsite-404 devsite-search,.devsite-offline-reload,.devsite-offline-suggestions{margin:var(--devsite-404-search-margin);position:relative;z-index:1}.devsite-404 devsite-search .devsite-popout-result{max-height:304px}.devsite-404 devsite-search,.devsite-404 devsite-search .devsite-searchbox{width:100%}.devsite-404 devsite-search .devsite-search-button{display:none}.devsite-404 h3,.devsite-offline h3{color:var(--devsite-offline-heading-color,var(--devsite-secondary-color,var(--devsite-primary-text-color)))}.devsite-404 h3{font:400 64px/64px var(--devsite-code-font-family)}.devsite-404-error{background:var(--devsite-404-error-background);padding:var(--devsite-404-error-padding);text-align:var(--devsite-404-error-text-align,center)}.devsite-404-error-message,.devsite-404-error>h3{position:relative;z-index:2}.devsite-404-error>h3{display:var(--devsite-404-error-heading-display,block)}.devsite-404-error-message{font:var(--devsite-404-error-message-font);letter-spacing:var(--devsite-404-error-message-letter-spacing);margin:var(--devsite-404-error-message-margin,0 0 20px)}.devsite-404-links{border-top:var(--devsite-404-links-border,var(--devsite-primary-border));margin:var(--devsite-404-links-margin,0 calc(50% - 50vw) 40px);padding:var(--devsite-404-links-padding,0 calc(50vw - 50%));text-align:start}.devsite-404-links h3{color:var(--devsite-primary-text-color);font:var(--devsite-404-links-heading-font,var(--devsite-h3-font))}.devsite-404-links ul{display:grid;gap:0 24px;grid:auto-flow/repeat(var(--devsite-404-links-columns),1fr);list-style:none;padding:0}.devsite-404-links li{margin:var(--devsite-404-links-item-margin,12px 0)}.devsite-offline .devsite-offline-suggestions{text-align:start}.devsite-offline .devsite-offline-suggestions h3,.devsite-offline .devsite-offline-suggestions ul{margin:0}.devsite-offline h3{font:400 32px/48px var(--devsite-code-font-family)}.devsite-offline-reload{text-align:center}@media screen and (max-width:840px){.devsite-404,.devsite-offline{margin-top:40px}}body[embed] .devsite-book-nav-bg,body[embed] .devsite-book-nav-bg[fixed],body[embed] .devsite-book-nav-blur,body[embed] .devsite-book-nav-toggle,body[embed] .devsite-sidebar,body[embed] devsite-book-nav,body[embed] devsite-feature-tooltip.devsite-page-bookmark-tooltip,body[embed] devsite-feedback[position=header],body[embed] devsite-footer-linkboxes,body[embed] devsite-footer-promos,body[embed] devsite-footer-utility,body[embed] devsite-header,body[embed] devsite-panel,body[embed] devsite-thumb-rating[position=header],body[embed] devsite-toc,body[ready][embed] .devsite-book-nav-bg,body[ready][embed] .devsite-book-nav-bg[fixed],body[ready][embed] .devsite-book-nav-blur,body[ready][embed] .devsite-book-nav-toggle,body[ready][embed] .devsite-sidebar,body[ready][embed] devsite-book-nav,body[ready][embed] devsite-feature-tooltip.devsite-page-bookmark-tooltip,body[ready][embed] devsite-feedback[position=header],body[ready][embed] devsite-footer-linkboxes,body[ready][embed] devsite-footer-promos,body[ready][embed] devsite-footer-utility,body[ready][embed] devsite-header,body[ready][embed] devsite-panel,body[ready][embed] devsite-thumb-rating[position=header],body[ready][embed] devsite-toc{display:none}body[layout=docs][embed] .devsite-article{box-shadow:none}body[layout=docs][embed] devsite-content{margin:0}@media print{.prettyprint a,:link,:visited,a .atn,a .atv,a .com,a .dec,a .kwd,a .lit,a .pln,a .pun,a .str,a .tag,a .typ,a [class^=devsite-syntax-],a code,aside :link,aside :visited,body,code,h1,h1 code,h2,h2 code,h3,h3 code,h4,h4 code,h5,h5 code,h6,h6 code,html,pre,pre .atn,pre .atv,pre .com,pre .dec,pre .kwd,pre .lit,pre .pln,pre .pun,pre .str,pre .tag,pre .typ,pre [class^=devsite-syntax-],td,td code,th,th :link,th :visited,th code,var{color:#000!important;padding-left:0!important;padding-right:0!important}.beta,.caution,.deprecated,.dogfood,.experimental,.key-point,.key-term,.note,.objective,.preview,.special,.success,.tip,.warning,aside{color:#000!important;margin-left:0!important;margin-right:0!important;padding-left:0!important;padding-right:0!important}.beta a,.caution a,.deprecated a,.dogfood a,.experimental a,.key-point a,.key-term a,.note a,.objective a,.preview a,.special a,.success a,.tip a,.warning a,aside a{color:#000!important;margin-left:0!important;margin-right:0!important;padding-left:0!important;padding-right:0!important}#gc-wrapper{margin:0!important}devsite-code{margin-left:0!important;margin-right:0!important;padding-left:0!important;padding-right:0!important}devsite-expandable>:not(.showalways):not(.exw-control):not(.exw-expanded-content):not(.expand-control){display:block!important}:link,:visited{text-decoration:underline}.devsite-article-meta,.devsite-banner-confidential .button,.devsite-banner-translated .button,.devsite-book-nav-bg,.devsite-book-nav-blur,.devsite-book-nav-toggle,.devsite-code-buttons-container,.devsite-page-bookmark-tooltip,.devsite-sidebar,devsite-book-nav,devsite-bookmark,devsite-concierge,devsite-feedback,devsite-footer-linkboxes,devsite-footer-promos,devsite-footer-utility,devsite-googler-buttons,devsite-header,devsite-recommendations,devsite-snackbar,devsite-thumb-rating{display:none!important}.devsite-article,.devsite-main-content,devsite-content{background:0!important;border:0!important;box-shadow:none!important;display:block!important;margin:0!important;max-width:none!important;padding:0!important;width:auto!important}.devsite-banner{margin-top:0}.attempt-left,.attempt-right,.video-wrapper{float:none;margin:16px 0}img,video{display:block!important;page-break-inside:avoid!important}.devsite-main-content a[href]:after{content:" (" attr(href) ")";display:inline-block;font:14px/20px var(--devsite-primary-font-family);max-width:100%;word-wrap:break-word}}@page{margin:.75in}.devsite-product-platform-row{margin:8px 0;padding:0 24px}.devsite-header-no-lower-tabs .devsite-product-platform-row{margin-top:-12px;padding-bottom:24px}.devsite-platform-container{display:inline-block}.devsite-platform-container+.devsite-platform-container{margin-left:16px}.devsite-platform-icon-container{background:var(--devsite-background-1);border-radius:50%;height:40px;margin:0 auto;width:40px}.devsite-platform-icon{color:var(--devsite-secondary-text-color);font-size:24px;height:24px;margin:8px;width:24px}@media screen and (max-width:1000px){div.devsite-collapsible-section,div.devsite-header-background{background-image:none}}@media screen and (max-width:600px){.devsite-product-platform-row{padding:0 16px}}.devsite-landing-row-cards .devsite-landing-row-item{border:var(--devsite-card-border);border-radius:var(--devsite-card-border-radius);box-shadow:var(--devsite-card-box-shadow);overflow:var(--devsite-card-overflow,hidden);position:relative}.devsite-landing-row-cards .devsite-landing-row-item,.devsite-landing-row-cards[background] .devsite-landing-row-item{--devsite-link-color:#1a73e8;--devsite-text-color:var(--devsite-primary-text-color)}.devsite-landing-row-cards .devsite-landing-row-item:not([background]){background-color:var(--devsite-card-background)}body[theme] .devsite-landing-row-cards[background=theme] :link:not(.button),body[theme] .devsite-landing-row-cards[background=theme] :visited:not(.button){color:var(--devsite-link-color)}.devsite-landing-row-cards .devsite-landing-row-column .devsite-landing-row-item{display:block}.devsite-landing-row-cards .devsite-landing-row-item[description-position] .devsite-landing-row-item-media+.devsite-landing-row-item-description{margin:0}.devsite-landing-row-cards .devsite-landing-row-item-description{padding:16px}.devsite-landing-row-cards .devsite-landing-row-item-buttons{padding-top:16px}.devsite-landing-row-cards[background=theme] .devsite-landing-row-item-icon{color:var(--devsite-secondary-text-color)}.devsite-landing-row-cards .devsite-landing-row-item-no-media h3{font:var(--devsite-h2-font);margin:0 0 20px}.devsite-landing-row-cards.devsite-landing-row-1-up .devsite-landing-row-item-media{-webkit-box-flex:1;-webkit-flex:1 0;-moz-box-flex:1;-ms-flex:1 0;flex:1 0;margin:0}@media screen and (max-width:840px){.devsite-landing-row-cards.devsite-landing-row-1-up .devsite-landing-row-item{display:block}}@media screen and (max-width:600px){.devsite-landing-row-cards.devsite-landing-row-1-up .devsite-landing-row-item-media+.devsite-landing-row-item-description{margin:0;padding:16px}}.devsite-landing-row-cta{text-align:center}.devsite-landing-row.devsite-landing-row-cta:not([background]){background:var(--devsite-cta-background,var(--devsite-primary-color));color:var(--devsite-text-color,var(--devsite-inverted-text-color))}.devsite-landing-row.devsite-landing-row-cta .devsite-landing-row-item{display:block}.devsite-landing-row.devsite-landing-row-cta .devsite-landing-row-item-description{margin:0 auto;max-width:856px}.devsite-landing-row-cta.devsite-landing-row h2,.devsite-landing-row-cta.devsite-landing-row-large-headings .devsite-landing-row-item-description h3{color:var(--devsite-text-color,var(--devsite-inverted-text-color))}.devsite-landing-row-cta h3{font:var(--devsite-h1-font,400 34px/40px var(--devsite-primary-font-family));letter-spacing:var(--devsite-h1-letter-spacing);margin-bottom:16px;text-decoration:inherit}.devsite-landing-row-cta h3 a:not(.button){color:var(--devsite-text-color,var(--devsite-inverted-text-color))}.devsite-landing-row-cta h3+.devsite-landing-row-item-buttons{margin-top:8px}@media screen and (max-width:600px){.devsite-landing-row-cta .devsite-landing-row-item-description{font:400 16px/24px var(--devsite-primary-font-family)}}.devsite-landing-row-header{background:var(--devsite-landing-row-header-background);border-radius:var(--devsite-landing-row-header-border-radius);display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;margin:0 auto;max-width:var(--devsite-landing-row-header-max-width);padding:var(--devsite-landing-row-header-padding)}.devsite-landing-row[header-position=left] .devsite-landing-row-header,.devsite-landing-row[header-position=right] .devsite-landing-row-header{display:block;margin:0}.devsite-landing-row[header-position=left] .devsite-landing-row-header{grid-column:var(--devsite-landing-row-header-grid-column,1)}.devsite-landing-row[header-position=right] .devsite-landing-row-header{grid-column:var(--devsite-landing-row-header-grid-column,3);-webkit-box-ordinal-group:3;-webkit-order:2;-moz-box-ordinal-group:3;-ms-flex-order:2;order:2}.devsite-landing-row[header-position=top] .devsite-landing-row-header+.devsite-landing-row-group{margin:var(--devsite-landing-row-group-margin,32px auto 0)}.devsite-landing-row-header-text{-webkit-box-flex:1;-webkit-flex:1 1 auto;-moz-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto;margin:var(--devsite-landing-row-header-text-margin);max-width:var(--devsite-landing-row-header-text-max-width)}.devsite-landing-row-header-text>h2{margin:0}.devsite-landing-row-description{color:var(--devsite-text-color,var(--devsite-primary-text-color));font-family:var(--devsite-landing-row-description-font-family,var(--devsite-primary-font-family));font-size:var(--devsite-landing-row-description-font-size,18px);letter-spacing:var(--devsite-letter-spacing);line-height:var(--devsite-line-height,24px);max-width:var(--devsite-landing-row-description-max-width,856px)}[background] .devsite-landing-row-description{color:var(--devsite-text-color,var(--devsite-inverted-text-color))}.devsite-landing-row:not([background]):not([foreground]) .devsite-landing-row-description{color:var(--devsite-text-color,var(--devsite-heading-color,var(--devsite-secondary-text-color)))}h2+.devsite-landing-row-description{margin-top:var(--devsite-row-header-contents-gap,16px)}.devsite-landing-row-header-buttons{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-flex:0;-webkit-flex:0 1 auto;-moz-box-flex:0;-ms-flex:0 1 auto;flex:0 1 auto;margin-block:0;margin-inline:0 auto}.devsite-landing-row-header-centered .devsite-landing-row-header,.devsite-landing-row-header[icon-position=top]{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-moz-box-orient:vertical;-moz-box-direction:normal;-ms-flex-direction:column;flex-direction:column}.devsite-landing-row-header-centered .devsite-landing-row-header-buttons,.devsite-landing-row-header[icon-position=top] .devsite-landing-row-header-buttons{margin-inline:0}.devsite-landing-row-header-centered .devsite-landing-row-header{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;text-align:center}.devsite-landing-row-header-centered .devsite-landing-row-description{margin-left:auto;margin-right:auto}.devsite-landing-row-header-centered .devsite-landing-row-header-buttons{-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;-ms-flex-pack:center;justify-content:center}.devsite-landing-row-header-centered .devsite-landing-row-header-buttons,.devsite-landing-row-header[icon-position=top] .devsite-landing-row-header-buttons,.devsite-landing-row[header-position=left] .devsite-landing-row-header-buttons,.devsite-landing-row[header-position=right] .devsite-landing-row-header-buttons{margin:var(--devsite-buttons-margin,24px 0 0)}@media screen and (max-width:840px){.devsite-landing-row-header+.devsite-landing-row-group{margin-top:32px}.devsite-landing-row-header{display:block}}@media screen and (max-width:840px){.devsite-landing-row-header-text+.devsite-landing-row-header-buttons{display:block;margin:24px 0 0}}@media screen and (max-width:600px){.devsite-landing-row-header-text+.devsite-landing-row-header-buttons{margin:16px 0 0}}.devsite-landing-row-1-up .devsite-landing-row-item-description[icon-position=left],.devsite-landing-row-item-description[icon-position]{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-moz-box-orient:horizontal;-moz-box-direction:normal;-ms-flex-direction:row;flex-direction:row}.devsite-landing-row-item-description[icon-position=right]{-webkit-box-orient:horizontal;-webkit-box-direction:reverse;-webkit-flex-direction:row-reverse;-moz-box-orient:horizontal;-moz-box-direction:reverse;-ms-flex-direction:row-reverse;flex-direction:row-reverse}.devsite-landing-row-item-description[icon-position=top]{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-moz-box-orient:vertical;-moz-box-direction:normal;-ms-flex-direction:column;flex-direction:column}.devsite-landing-row-item-description[icon-position^=bottom]{-webkit-box-orient:vertical;-webkit-box-direction:reverse;-webkit-flex-direction:column-reverse;-moz-box-orient:vertical;-moz-box-direction:reverse;-ms-flex-direction:column-reverse;flex-direction:column-reverse}.devsite-landing-row-header-icon-container,.devsite-landing-row-header-icon-container[background],.devsite-landing-row-item-icon-container,.devsite-landing-row-item-icon-container[background]{color:var(--devsite-foreground-color,var(--devsite-icon-color,var(--devsite-secondary-text-color)))}.devsite-landing-row-header-icon-container,.devsite-landing-row-item-icon-container{height:var(--devsite-icon-canvas-size);-webkit-box-flex:0;-webkit-flex:0 0 auto;-moz-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;-webkit-transition:background .2s,box-shadow .2s,color .2s;transition:background .2s,box-shadow .2s,color .2s;width:var(--devsite-icon-canvas-size)}.devsite-landing-row-header-icon-container{margin-block:var(--devsite-header-icon-canvas-margin-block,0 8px);margin-inline:var(--devsite-header-icon-canvas-margin-inline,0 20px)}.devsite-landing-row-item-icon-container{display:var(--devsite-icon-canvas-display,inherit);inset:var(--devsite-icon-canvas-inset);margin-block:var(--devsite-icon-canvas-margin-block,0 8px);margin-inline:var(--devsite-icon-canvas-margin-inline,0 20px);overflow:var(--devsite-icon-canvas-overflow);position:var(--devsite-icon-canvas-position)}.devsite-landing-row-item-description[icon-position=bottom] .devsite-landing-row-item-icon-container,.devsite-landing-row-item-description[icon-position=bottom]>a,.devsite-landing-row-item-description[icon-position=right] .devsite-landing-row-item-icon-container,.devsite-landing-row-item-description[icon-position=right]>a{-webkit-align-self:center;-ms-flex-item-align:center;align-self:center}.devsite-landing-row-item-description[icon-position=bottom-right] .devsite-landing-row-item-icon-container,.devsite-landing-row-item-description[icon-position=bottom-right]>a{-webkit-align-self:flex-end;-ms-flex-item-align:end;align-self:flex-end}.devsite-landing-row-header-icon-container[background],.devsite-landing-row-item-icon-container[background]{background:var(--devsite-background-color,var(--devsite-primary-color,var(--devsite-primary-text-color)))}.devsite-landing-row-header-icon-container[background][foreground=theme],.devsite-landing-row-header-icon-container[foreground=theme],.devsite-landing-row-item-icon-container[background][foreground=theme],.devsite-landing-row-item-icon-container[foreground=theme]{color:var(--devsite-primary-color,var(--devsite-primary-text-color))}.devsite-landing-row :focus .devsite-landing-row-header-icon-container[background][foreground=theme],.devsite-landing-row :focus .devsite-landing-row-item-icon-container[background][foreground=theme],.devsite-landing-row :link .devsite-landing-row-header-icon-container[background][foreground=theme]:hover,.devsite-landing-row :link .devsite-landing-row-item-icon-container[background][foreground=theme]:hover{color:var(--devsite-primary-color,var(--devsite-primary-text-color))}.devsite-landing-row-header-icon,.devsite-landing-row-item-icon{aspect-ratio:1}.devsite-landing-row-header-icon{font-size:var(--devsite-header-icon-size,var(--devsite-icon-size));height:var(--devsite-header-icon-size,var(--devsite-icon-size));margin-block:var(--devsite-header-icon-margin-block,0);margin-inline:var(--devsite-header-icon-margin-inline,0);width:var(--devsite-header-icon-size,var(--devsite-icon-size))}.devsite-landing-row-item-icon{font-size:var(--devsite-icon-size);height:var(--devsite-icon-size);margin-block:var(--devsite-icon-margin-block,0);margin-inline:var(--devsite-icon-margin-inline,4px 0);width:var(--devsite-icon-size)}.devsite-landing-row-item-centered [icon-position=top] .devsite-landing-row-item-icon-container,.devsite-landing-row-item-centered [icon-position=top]>a{margin-inline:auto}.devsite-landing-row-header-icon-container[background],.devsite-landing-row-item-icon-container[background]{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;border-radius:50%;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;-ms-flex-pack:center;justify-content:center}[background] .devsite-landing-row-header-icon-container:not([foreground]),[background] .devsite-landing-row-item-icon-container:not([foreground]){color:var(--devsite-icon-color,var(--devsite-inverted-text-color))}:focus .devsite-landing-row-header-icon-container,:focus .devsite-landing-row-item-icon-container,:link .devsite-landing-row-header-icon-container:hover,:link .devsite-landing-row-item-icon-container:hover{color:var(--devsite-link-color)}[foreground] .devsite-landing-row-item :focus .devsite-landing-row-item-icon-container,[foreground] .devsite-landing-row-item :link .devsite-landing-row-item-icon-container:hover,[foreground] :focus .devsite-landing-row-header-icon-container,[foreground] :link .devsite-landing-row-header-icon-container:hover{color:hsla(210,6%,63%,.5)}[background] .devsite-landing-row-item :focus .devsite-landing-row-item-icon-container,[background] .devsite-landing-row-item :link .devsite-landing-row-item-icon-container:hover,[background] :focus .devsite-landing-row-header-icon-container,[background] :link .devsite-landing-row-header-icon-container:hover{color:var(--devsite-icon-color-hover,var(--devsite-inverted-text-rgba))}:focus .devsite-landing-row-header-icon-container[background],:focus .devsite-landing-row-item-icon-container[background],:link .devsite-landing-row-header-icon-container[background]:hover,:link .devsite-landing-row-item-icon-container[background]:hover{color:var(--devsite-foreground-color,var(--devsite-icon-color,var(--devsite-secondary-text-color)));box-shadow:0 1px 2px 0 var(--devsite-elevation-key-shadow-color),0 2px 6px 2px var(--devsite-elevation-ambient-shadow-color)}[background] :focus .devsite-landing-row-header-icon-container[background],[background] :focus .devsite-landing-row-item-icon-container[background],[background] :link .devsite-landing-row-header-icon-container[background]:hover,[background] :link .devsite-landing-row-item-icon-container[background]:hover{color:var(--devsite-foreground-color,var(--devsite-icon-color,var(--devsite-inverted-text-color)));text-decoration:none}@media screen and (max-width:840px){.devsite-landing-row-item-description[icon-position^=bottom]{-webkit-box-orient:horizontal;-webkit-box-direction:reverse;-webkit-flex-direction:row-reverse;-moz-box-orient:horizontal;-moz-box-direction:reverse;-ms-flex-direction:row-reverse;flex-direction:row-reverse}.devsite-landing-row-item-description[icon-position^=bottom] .devsite-landing-row-item-icon,.devsite-landing-row-item-description[icon-position^=bottom] .devsite-landing-row-item-icon-container,.devsite-landing-row-item-description[icon-position^=bottom]>a{-webkit-align-self:center;-ms-flex-item-align:center;align-self:center}}.devsite-landing-row-1-up .devsite-landing-row-item{display:var(--devsite-item-display,grid);grid-gap:var(--devsite-item-gap);grid-template-columns:var(--devsite-1-up-grid-template-columns)}.devsite-landing-row-1-up.devsite-landing-row-hero .devsite-landing-row-item{-webkit-box-align:var(--devsite-hero-align-items,center);-webkit-align-items:var(--devsite-hero-align-items,center);-moz-box-align:var(--devsite-hero-align-items,center);-ms-flex-align:var(--devsite-hero-align-items,center);align-items:var(--devsite-hero-align-items,center)}.devsite-landing-row-1-up .devsite-landing-row-item-description,.devsite-landing-row-1-up .devsite-landing-row-item-media-left{-webkit-box-ordinal-group:2;-webkit-order:1;-moz-box-ordinal-group:2;-ms-flex-order:1;order:1}.devsite-landing-row-1-up .devsite-landing-row-item-media,.devsite-landing-row-1-up .devsite-landing-row-item-media-left+.devsite-landing-row-item-description{-webkit-box-ordinal-group:3;-webkit-order:2;-moz-box-ordinal-group:3;-ms-flex-order:2;order:2}.devsite-landing-row-1-up .devsite-landing-row-item-description{display:block;grid-column:1/span 4}.devsite-landing-row-1-up .devsite-landing-row-item-media{grid-column:var(--devsite-media-grid-column,5/span 8);margin:0}.devsite-landing-row-1-up .devsite-landing-row-item-media-left{grid-column:var(--devsite-media-left-grid-column,1/span 8)}.devsite-landing-row-1-up .devsite-landing-row-item-media-left+.devsite-landing-row-item-description{grid-column:9/span 4}.devsite-landing-row.devsite-landing-row-1-up .devsite-landing-row-item-description{margin-top:0}.devsite-landing-row-1-up .devsite-landing-row-item-no-media .devsite-landing-row-item-description{grid-column:var(--devsite-1-up-no-media-description-grid-column)}.devsite-landing-row-50 .devsite-landing-row-item-description{grid-column:1/span 6}.devsite-landing-row-50 .devsite-landing-row-item-media{grid-column:var(--devsite-row-50-media-grid-column,7/span 6)}.devsite-landing-row-50 .devsite-landing-row-item-media-left{grid-column:var(--devsite-row-50-media-left-grid-column,1/span 6)}.devsite-landing-row-50 .devsite-landing-row-item-media-left+.devsite-landing-row-item-description{grid-column:7/span 6}.devsite-landing-row-67 .devsite-landing-row-item-description{grid-column:var(--devsite-row-67-description-grid-column,1/span 8)}.devsite-landing-row-67 .devsite-landing-row-item-media{grid-column:var(--devsite-row-67-media-grid-column,9/span 4)}.devsite-landing-row-67 .devsite-landing-row-item-media-left{grid-column:var(--devsite-row-67-media-left-grid-column,1/span 4)}.devsite-landing-row-67 .devsite-landing-row-item-media-left+.devsite-landing-row-item-description{grid-column:var(--devsite-row-67-description-left-grid-column,5/span 8)}.devsite-landing-row-75 .devsite-landing-row-item-description{grid-column:1/span 9}.devsite-landing-row-75 .devsite-landing-row-item-media{grid-column:var(--devsite-row-75-media-grid-column,10/span 3)}.devsite-landing-row-75 .devsite-landing-row-item-media-left{grid-column:var(--devsite-row-75-media-left-grid-column,1/span 3)}.devsite-landing-row-75 .devsite-landing-row-item-media-left+.devsite-landing-row-item-description{grid-column:4/span 9}.devsite-landing-row-100 .devsite-landing-row-group,.devsite-landing-row-100 .devsite-landing-row-item-media{width:100%}.devsite-landing-row-100 .devsite-landing-row-item{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-moz-box-orient:vertical;-moz-box-direction:normal;-ms-flex-direction:column;flex-direction:column}.devsite-landing-row-100 .devsite-landing-row-item-media+.devsite-landing-row-item-description{margin-bottom:32px}@media screen and (max-width:840px){.devsite-landing-row-1-up .devsite-landing-row-item-description,.devsite-landing-row-1-up .devsite-landing-row-item-media-left{grid-column:1;grid-row:1;-webkit-box-ordinal-group:2;-webkit-order:1;-moz-box-ordinal-group:2;-ms-flex-order:1;order:1}.devsite-landing-row-1-up .devsite-landing-row-item-media-left+.devsite-landing-row-item-description,.devsite-landing-row-1-up .devsite-landing-row-item-media:not(.devsite-landing-row-item-media-left){grid-column:2}}@media screen and (max-width:600px){.devsite-landing-row-1-up .devsite-landing-row-item{display:var(--devsite-item-display,block)}}.devsite-landing-row-item-buttons{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-left:-12px;padding-top:8px}.devsite-landing-row-1-up.devsite-landing-row-hero .devsite-landing-row-item-buttons{padding-top:var(--devsite-landing-row-hero-buttons-padding-top,32px)}.devsite-landing-row-item-buttons .button{margin:4px 4px 4px 12px}.devsite-landing-row-item-buttons .button>.material-icons{top:-1px}.devsite-landing-row-item-buttons .button-white:not(.button-raised),.devsite-landing-row-item-buttons .button-white:not(.button-raised)+.button-white:not(.button-raised){margin:0 4px}.devsite-landing-row-cta .devsite-landing-row-item-buttons{-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;-ms-flex-pack:center;justify-content:center;margin:24px 0 0}p+.devsite-landing-row-item-buttons{margin-top:-8px}.devsite-landing-row-item-media{margin:var(--devsite-item-media-margin,0);min-width:0;max-height:var(--devsite-item-media-max-height);overflow:var(--devsite-item-media-overflow);padding:var(--devsite-item-media-padding,0);width:var(--devsite-item-media-container-width)}.devsite-landing-row-item-code devsite-code{margin:0}.devsite-landing-row-item-video{display:block;width:100%}.devsite-landing-row-item-description{color:var(--devsite-text-color,inherit);max-width:var(--devsite-item-text-max-width);padding:var(--devsite-item-text-padding);text-align:var(--devsite-item-text-align)}.devsite-landing-row-item-media+.devsite-landing-row-item-description{margin:var(--devsite-item-description-margin,32px 0 0)}.devsite-landing-row-item[description-position=left] .devsite-landing-row-item-description,.devsite-landing-row-item[description-position=left] .devsite-landing-row-item-media,.devsite-landing-row-item[description-position=right] .devsite-landing-row-item-description,.devsite-landing-row-item[description-position=right] .devsite-landing-row-item-media{-webkit-box-flex:0;-webkit-flex:0 0 var(--devsite-item-media-width,calc(50% - 12px));-moz-box-flex:0;-ms-flex:0 0 var(--devsite-item-media-width,calc(50% - 12px));flex:0 0 var(--devsite-item-media-width,calc(50% - 12px));margin:0}.devsite-landing-row-item[description-position=left] .devsite-landing-row-item-media{-webkit-box-ordinal-group:3;-webkit-order:2;-moz-box-ordinal-group:3;-ms-flex-order:2;order:2}.devsite-landing-row-item[description-position=left] .devsite-landing-row-item-description{-webkit-box-ordinal-group:2;-webkit-order:1;-moz-box-ordinal-group:2;-ms-flex-order:1;order:1}.devsite-landing-row-item[background] .devsite-landing-row-item-description,.devsite-landing-row-item[background][description-position=left] .devsite-landing-row-item-description,.devsite-landing-row-item[background][description-position=right] .devsite-landing-row-item-description{padding:var(--devsite-item-description-padding,16px)}[dir=ltr] .devsite-landing-row-cards .devsite-landing-row-item[description-position=left] .devsite-landing-row-item-description,[dir=ltr] .devsite-landing-row-item[background][description-position=left] .devsite-landing-row-item-description{padding-right:0}[dir=rtl] .devsite-landing-row-cards .devsite-landing-row-item[description-position=left] .devsite-landing-row-item-description,[dir=rtl] .devsite-landing-row-item[background][description-position=left] .devsite-landing-row-item-description{padding-left:0}[dir=ltr] .devsite-landing-row-cards .devsite-landing-row-item[description-position=right] .devsite-landing-row-item-description,[dir=ltr] .devsite-landing-row-item[background][description-position=right] .devsite-landing-row-item-description{padding-left:0}[dir=rtl] .devsite-landing-row-cards .devsite-landing-row-item[description-position=right] .devsite-landing-row-item-description,[dir=rtl] .devsite-landing-row-item[background][description-position=right] .devsite-landing-row-item-description{padding-right:0}.devsite-landing-row-item[description-position=top] .devsite-landing-row-item-media{-webkit-box-ordinal-group:3;-webkit-order:2;-moz-box-ordinal-group:3;-ms-flex-order:2;order:2}.devsite-landing-row-item[description-position=top] .devsite-landing-row-item-description{-webkit-box-ordinal-group:2;-webkit-order:1;-moz-box-ordinal-group:2;-ms-flex-order:1;order:1}.devsite-landing-row-item[description-position=top] .devsite-landing-row-item-media+.devsite-landing-row-item-description{margin:var(--devsite-item-description-top-margin-override,var(--devsite-item-description-top-margin,0 0 32px))}.devsite-landing-row-item-body,.devsite-landing-row-item-description{-webkit-box-align:var(--devsite-item-description-align-items);-webkit-align-items:var(--devsite-item-description-align-items);-moz-box-align:var(--devsite-item-description-align-items);-ms-flex-align:var(--devsite-item-description-align-items);align-items:var(--devsite-item-description-align-items);display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-flex:1;-webkit-flex:1 1 auto;-moz-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-moz-box-orient:vertical;-moz-box-direction:normal;-ms-flex-direction:column;flex-direction:column;height:var(--devsite-item-description-height,auto);min-width:0}.devsite-landing-row-item-body{display:var(--devsite-item-body-display,flex);grid:var(--devsite-item-body-grid);grid-gap:var(--devsite-item-body-grid-gap)}.devsite-landing-row-item-body h3{grid-area:heading}.devsite-landing-row-item-buttons{grid-area:buttons;margin:var(--devsite-buttons-margin,auto 0 -8px);padding:var(--devsite-buttons-padding,8px 0 0)}[dir=ltr] .devsite-landing-row-item-buttons{margin-left:-12px}[dir=rtl] .devsite-landing-row-item-buttons{margin-right:-12px}.devsite-landing-row h3:first-child,.devsite-landing-row h3:first-of-type,.devsite-landing-row h4+p,.devsite-landing-row h4:first-child,.devsite-landing-row h5:first-child,.devsite-landing-row h6:first-child,.devsite-landing-row p:first-child,.devsite-landing-row-item-description h2,.devsite-landing-row-large-headings h3{margin-top:0}.devsite-landing-row-item-description-content{font:var(--devsite-description-content-font,inherit);grid-area:content}.devsite-landing-row-item-description-content>:last-child{margin-bottom:0}.devsite-landing-row-item-centered .devsite-landing-row-item-description-content,.devsite-landing-row-item-centered h3{text-align:center}.devsite-landing-row-item-centered .devsite-landing-row-item-buttons{-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;-ms-flex-pack:center;justify-content:center}@media screen and (max-width:840px){.devsite-landing-row-item[description-position] .devsite-landing-row-item-description,.devsite-landing-row-item[description-position] .devsite-landing-row-item-media{max-width:none}.devsite-landing-row-item[description-position] .devsite-landing-row-item-media{-webkit-align-self:var(--devsite-item-media-align-self);-ms-flex-item-align:var(--devsite-item-media-align-self);align-self:var(--devsite-item-media-align-self);-webkit-box-flex:0;-webkit-flex:0 0 auto;-moz-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;margin:var(--devsite-item-media-margin,0);-webkit-box-ordinal-group:NaN;-webkit-order:var(--devsite-item-media-order,1);-moz-box-ordinal-group:NaN;-ms-flex-order:var(--devsite-item-media-order,1);order:var(--devsite-item-media-order,1);width:var(--devsite-item-media-width)}.devsite-landing-row-item[description-position] .devsite-landing-row-item-description{-webkit-box-ordinal-group:NaN;-webkit-order:var(--devsite-item-description-order,2);-moz-box-ordinal-group:NaN;-ms-flex-order:var(--devsite-item-description-order,2);order:var(--devsite-item-description-order,2)}.devsite-landing-row-item[description-position=top] .devsite-landing-row-item-media{-webkit-box-ordinal-group:3;-webkit-order:2;-moz-box-ordinal-group:3;-ms-flex-order:2;order:2}.devsite-landing-row-item[description-position=top] .devsite-landing-row-item-description{-webkit-box-ordinal-group:2;-webkit-order:1;-moz-box-ordinal-group:2;-ms-flex-order:1;order:1}[dir] .devsite-landing-row-cards .devsite-landing-row-item[description-position] .devsite-landing-row-item-description,[dir] .devsite-landing-row-item[background][description-position] .devsite-landing-row-item-description{padding:var(--devsite-item-description-padding,16px)}}@media screen and (max-width:600px){.devsite-landing-row-1-up .devsite-landing-row-item-media+.devsite-landing-row-item-description{margin:var(--devsite-item-description-margin,32px 0 0);padding:0}}.devsite-landing-row-item-custom-image{aspect-ratio:16/9}.devsite-landing-row-item-custom-image,.devsite-landing-row-item-custom-image-icon-wrapper{display:grid;place-content:center}.devsite-landing-row-item-custom-image:not([background]){background-color:var(--devsite-background-color,var(--devsite-primary-color,var(--devsite-primary-text-color)))}.devsite-landing-row-item-custom-image[background=grey]{background:var(--devsite-background-color,var(--devsite-background-3))}.devsite-landing-row-item-custom-image[background=white]{background:var(--devsite-background-1)}.devsite-landing-row-item-custom-image-icon-container[background],.devsite-landing-row-no-image-background .devsite-landing-row-item-custom-image:not([background]){background:0}.devsite-landing-row-item-custom-image-icon{color:var(--devsite-inverted-text-color);font-size:var(--devsite-custom-image-icon-font-size);max-height:var(--devsite-custom-image-icon-max-height);width:var(--devsite-custom-image-icon-width)}.devsite-landing-row-item-custom-image[background=grey]:not([foreground]) .devsite-landing-row-item-custom-image-icon,.devsite-landing-row-item-custom-image[background=white]:not([foreground]) .devsite-landing-row-item-custom-image-icon{color:var(--devsite-icon-color,var(--devsite-secondary-text-color))}.devsite-landing-row-item-custom-image-icon.material-icons{opacity:.8}.devsite-landing-row-item-description-callout{font-weight:700}.devsite-landing-row-item-description-feature{margin-top:16px;position:relative}.devsite-landing-row-item-description-feature+.devsite-landing-row-item-description-feature{margin:0}.devsite-landing-row-item-description-feature-link{border-bottom:var(--devsite-secondary-border);font-weight:500;padding:12px 0 11px}.devsite-landing-row-item-description-feature-tooltip{background:#455a64;color:hsla(0,0%,100%,.7);box-shadow:0 1px 2px 0 var(--devsite-elevation-key-shadow-color),0 2px 6px 2px var(--devsite-elevation-ambient-shadow-color);font:14px/20px var(--devsite-primary-font-family);min-width:200px;opacity:0;padding:24px;position:absolute;-webkit-transition:opacity .2s,visibility .2s;transition:opacity .2s,visibility .2s;visibility:hidden;width:67%;z-index:1020}.no-touch .devsite-landing-row-item-description-feature-link:hover+.devsite-landing-row-item-description-feature-tooltip{opacity:1;visibility:visible}.devsite-landing-row-item-description-feature-tooltip:before{border-bottom:8px solid #455a64;border-left:8px solid transparent;border-right:8px solid transparent;content:"";position:absolute;top:-8px}.devsite-landing-row-item-description-feature-tooltip h3,.devsite-landing-row-large-headings .devsite-landing-row-item-description-feature-tooltip h3{color:#fff;font:14px/20px var(--devsite-primary-font-family);margin-bottom:8px;padding:0}.devsite-landing-row-item-image{-webkit-align-self:flex-start;-ms-flex-item-align:start;align-self:flex-start;height:var(--devsite-item-image-container-height);-webkit-transform:var(--devsite-item-image-transform);transform:var(--devsite-item-image-transform);width:var(--devsite-item-image-container-width)}.devsite-landing-row-item-image:not([background]){background:var(--devsite-background-4)}.devsite-landing-row-item-image img{min-width:var(--devsite-item-image-min-width);vertical-align:middle;width:var(--devsite-item-image-width,100%)}.devsite-landing-row-item-image a{display:block}.devsite-landing-row-no-image-background .devsite-landing-row-item-image:not([background]){background:0}.devsite-landing-row-item-list{padding:0}.devsite-landing-row-item-description-content+.devsite-landing-row-item-list{margin-top:32px}.devsite-landing-row-item-list-item{list-style:none}.devsite-landing-row-item-list-item-content{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex}.devsite-landing-row-item-list-item-content[icon-position=top]{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-moz-box-orient:vertical;-moz-box-direction:normal;-ms-flex-direction:column;flex-direction:column}.devsite-landing-row-item-list-item-icon-container,.devsite-landing-row-item-list-item-icon-container[background]{color:var(--devsite-foreground-color,var(--devsite-icon-color,var(--devsite-secondary-text-color)))}.devsite-landing-row-item-list-item-icon-container{-webkit-box-flex:0;-webkit-flex:0 0 auto;-moz-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;height:40px;margin-block:0;margin-inline:0 20px;-webkit-transition:background .2s,box-shadow .2s,color .2s;transition:background .2s,box-shadow .2s,color .2s;width:40px}.devsite-landing-row-item-list-item-icon{font-size:32px;height:32px;width:32px}.devsite-landing-row-item-list-item-icon-container[background]{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;background:var(--devsite-background-color,var(--devsite-primary-color,var(--devsite-primary-text-color)));border-radius:50%;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;-ms-flex-pack:center;justify-content:center}.devsite-landing-row-item-list-item-icon-container[background] .devsite-landing-row-item-list-item-icon{font-size:24px;height:24px;width:24px}.devsite-landing-row-item-list h4{font:400 16px/20px var(--devsite-primary-font-family)}.devsite-landing-row .devsite-landing-row-item-list h4{margin:0 0 4px}.devsite-landing-row-item-list-item-description{-webkit-box-flex:1;-webkit-flex:1;-moz-box-flex:1;-ms-flex:1;flex:1;font:400 14px/20px var(--devsite-primary-font-family);max-width:calc(100% - 40px)}@media screen and (max-width:840px){.devsite-landing-row-item-list-item-description{max-width:none}}.devsite-landing-row-item-list-item:not(:last-child) .devsite-landing-row-item-list-item-description-content{margin-bottom:24px}[background] :focus>.devsite-landing-row-item-list-item-icon-container,[background] :link>.devsite-landing-row-item-list-item-icon-container:hover{text-decoration:none}:focus .devsite-landing-row-item-list-item-content .devsite-landing-row-item-list-item-icon-container[foreground=theme],:link .devsite-landing-row-item-list-item-icon-container[foreground=theme]:hover{color:var(--devsite-icon-color-hover,var(--devsite-primary-color,var(--devsite-inverted-text-rgba)))}[foreground] :focus .devsite-landing-row-item-list-item-content .devsite-landing-row-item-list-item-icon-container,[foreground] :link .devsite-landing-row-item-list-item-content:hover .devsite-landing-row-item-list-item-icon-container{color:hsla(210,6%,63%,.5)}[background] :focus .devsite-landing-row-item-list-item-content .devsite-landing-row-item-list-item-icon-container,[background] :link .devsite-landing-row-item-list-item-content:hover .devsite-landing-row-item-list-item-icon-container{color:var(--devsite-icon-color-hover,var(--devsite-inverted-text-rgba))}:link .devsite-landing-row-item-list-item-description h4+p{color:var(--devsite-primary-text-color);text-decoration:none}[background] :link .devsite-landing-row-item-list-item-description h4+p{color:var(--devsite-text-color,var(--devsite-inverted-text-color))}:focus .devsite-landing-row-item-list-item-content .devsite-landing-row-item-list-item-icon-container[background],:link .devsite-landing-row-item-list-item-content:hover .devsite-landing-row-item-list-item-icon-container[background]{background:var(--devsite-inverted-text-rgba);box-shadow:0 1px 2px 0 var(--devsite-elevation-key-shadow-color),0 2px 6px 2px var(--devsite-elevation-ambient-shadow-color)}.devsite-landing-row :focus .devsite-landing-row-item-list-item-description>:first-child,[background] :link .devsite-landing-row-item-list-item-description>:first-child{text-decoration:underline}.devsite-landing-row-item-labels>a,.devsite-landing-row-item-labels>span{color:var(--devsite-label-color,inherit);display:inline-block;font:var(--devsite-label-font,500 11px/16px var(--devsite-primary-font-family));letter-spacing:var(--devsite-label-letter-spacing,.8px);margin:var(--devsite-label-margin,0 0 8px);text-transform:var(--devsite-label-text-transform,uppercase)}.devsite-landing-row-item-labels>a+a,.devsite-landing-row-item-labels>a+span,.devsite-landing-row-item-labels>span+a,.devsite-landing-row-item-labels>span+span{margin-left:8px}.devsite-landing-row-item-labels>a[background],.devsite-landing-row-item-labels>span[background]{border-radius:4px;margin-bottom:16px;padding:4px 8px}.devsite-landing-row-column>.devsite-landing-row-item:nth-of-type(n+2){margin:32px 0 0}.devsite-landing-row-item{-webkit-box-align:var(--devsite-item-align-items);-webkit-align-items:var(--devsite-item-align-items);-moz-box-align:var(--devsite-item-align-items);-ms-flex-align:var(--devsite-item-align-items);align-items:var(--devsite-item-align-items);border-radius:var(--devsite-item-border-radius);display:var(--devsite-item-display,flex);-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:var(--devsite-item-flex-direction,column);-moz-box-orient:vertical;-moz-box-direction:normal;-ms-flex-direction:var(--devsite-item-flex-direction,column);flex-direction:var(--devsite-item-flex-direction,column);gap:var(--devsite-item-gap);-webkit-box-pack:var(--devsite-item-justify-content);-webkit-justify-content:var(--devsite-item-justify-content);-moz-box-pack:var(--devsite-item-justify-content);-ms-flex-pack:var(--devsite-item-justify-content);justify-content:var(--devsite-item-justify-content);max-height:var(--devsite-item-max-height);max-width:100%}.devsite-landing-row-item[description-position=left],.devsite-landing-row-item[description-position=right]{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-moz-box-orient:horizontal;-moz-box-direction:normal;-ms-flex-direction:row;flex-direction:row;-webkit-box-pack:justify;-webkit-justify-content:space-between;-moz-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between}.devsite-landing-row-column,.devsite-landing-row-item{-webkit-box-flex:1;-webkit-flex:1 0;-moz-box-flex:1;-ms-flex:1 0;flex:1 0;min-width:0}.devsite-landing-row-column>.devsite-landing-row-item{display:block}.devsite-landing-row-item-hidden{visibility:hidden}@media screen and (max-width:840px){.devsite-landing-row-item[description-position]{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-moz-box-orient:vertical;-moz-box-direction:normal;-ms-flex-direction:column;flex-direction:column;-webkit-box-pack:start;-webkit-justify-content:flex-start;-moz-box-pack:start;-ms-flex-pack:start;justify-content:flex-start}}@media screen and (max-width:600px){.devsite-landing-row-item[description-position=top]{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-moz-box-orient:vertical;-moz-box-direction:normal;-ms-flex-direction:column;flex-direction:column}}.devsite-landing-row-logos .devsite-landing-row-item-custom-image{aspect-ratio:unset;height:96px}.devsite-landing-row-logos .devsite-landing-row-item-custom-image:not([background]){background:0}.devsite-landing-row-logos .devsite-landing-row-item-custom-image-icon{opacity:1}.devsite-landing-row-logos .devsite-landing-row-item-description{margin:0;text-align:center}@media screen and (max-width:840px){.devsite-landing-row-logos.devsite-landing-row-3-up .devsite-landing-row-group{grid-template-columns:repeat(3,1fr)}.devsite-landing-row-logos.devsite-landing-row-4-up .devsite-landing-row-group{grid-template-columns:repeat(4,1fr)}}@media screen and (max-width:600px){.devsite-landing-row-logos.devsite-landing-row-2-up .devsite-landing-row-group,.devsite-landing-row-logos.devsite-landing-row-4-up .devsite-landing-row-group,.devsite-landing-row-logos.devsite-landing-row[header-position] .devsite-landing-row-group{grid-template-columns:repeat(2,1fr)}}.devsite-landing-row-1-up.devsite-landing-row-marquee,.devsite-landing-row-1-up.devsite-landing-row-marquee[background]{padding:0}.devsite-landing-row-1-up.devsite-landing-row-marquee .devsite-landing-row-header{margin:0;padding:40px 0 0}.devsite-landing-row-1-up.devsite-landing-row-marquee .devsite-landing-row-item-description,.devsite-landing-row-1-up.devsite-landing-row-marquee .devsite-landing-row-item-media{-webkit-align-self:center;-ms-flex-item-align:center;align-self:center}.devsite-landing-row-1-up.devsite-landing-row-marquee .devsite-landing-row-item-media{margin:0}.devsite-landing-row-1-up.devsite-landing-row-marquee .devsite-landing-row-item-image{background:0}.devsite-landing-row-1-up.devsite-landing-row-marquee .devsite-landing-row-item-description{padding:40px 0}@media screen and (max-width:840px){.devsite-landing-row-1-up.devsite-landing-row-marquee .devsite-landing-row-item{display:block}.devsite-landing-row-1-up.devsite-landing-row-marquee .devsite-landing-row-item-description,.devsite-landing-row-1-up.devsite-landing-row-marquee .devsite-landing-row-item-media{width:100%}.devsite-landing-row-1-up.devsite-landing-row-marquee .devsite-landing-row-item-description,.devsite-landing-row-1-up.devsite-landing-row-marquee .devsite-landing-row-item-media-left+.devsite-landing-row-item-description{margin:0}}.devsite-landing-row{overflow:var(--devsite-landing-row-overflow);padding:var(--devsite-landing-row-padding)}.devsite-landing-row:not([background]){background-color:var(--devsite-background-1)}body[layout=docs] .devsite-landing-row:first-of-type{border-radius:var(--devsite-first-row-border-radius,2px 2px 0 0)}body[layout=docs] .devsite-landing-row:last-of-type{border-radius:var(--devsite-last-row-border-radius,0 0 2px 2px)}.devsite-landing-row:not([background]):not(.devsite-landing-row-cta)+.devsite-landing-row:not([background]):not(.devsite-landing-row-cta):not([class^=devsite-landing-row-padding-]),.devsite-landing-row[background=grey]:not(.devsite-landing-row-cta)+[background=grey]:not(.devsite-landing-row-cta):not([class^=devsite-landing-row-padding-]),.devsite-landing-row[background=theme]+[background=theme]:not(.devsite-landing-row-cta):not([class^=devsite-landing-row-padding-]){padding-top:0}.devsite-landing-row[background=blue-grey]+[background=blue-grey]:not([class^=devsite-landing-row-padding-]){padding-top:0}.devsite-landing-row[background=blue-grey-dark]+[background=blue-grey-dark]:not([class^=devsite-landing-row-padding-]){padding-top:0}.devsite-landing-row[background=cyan]+[background=cyan]:not([class^=devsite-landing-row-padding-]){padding-top:0}.devsite-landing-row[background=deep-orange]+[background=deep-orange]:not([class^=devsite-landing-row-padding-]){padding-top:0}.devsite-landing-row[background=deep-purple]+[background=deep-purple]:not([class^=devsite-landing-row-padding-]){padding-top:0}.devsite-landing-row[background=google-blue]+[background=google-blue]:not([class^=devsite-landing-row-padding-]){padding-top:0}.devsite-landing-row[background=google-green]+[background=google-green]:not([class^=devsite-landing-row-padding-]){padding-top:0}.devsite-landing-row[background=google-red]+[background=google-red]:not([class^=devsite-landing-row-padding-]){padding-top:0}.devsite-landing-row[background=google-yellow]+[background=google-yellow]:not([class^=devsite-landing-row-padding-]){padding-top:0}.devsite-landing-row[background=indigo]+[background=indigo]:not([class^=devsite-landing-row-padding-]){padding-top:0}.devsite-landing-row[background=orange]+[background=orange]:not([class^=devsite-landing-row-padding-]){padding-top:0}.devsite-landing-row[background=pink]+[background=pink]:not([class^=devsite-landing-row-padding-]){padding-top:0}.devsite-landing-row[background=purple]+[background=purple]:not([class^=devsite-landing-row-padding-]){padding-top:0}.devsite-landing-row[background=teal]+[background=teal]:not([class^=devsite-landing-row-padding-]){padding-top:0}.devsite-landing-row[background=blue]+[background=blue]:not([class^=devsite-landing-row-padding-]){padding-top:0}.devsite-landing-row[background=green]+[background=green]:not([class^=devsite-landing-row-padding-]){padding-top:0}.devsite-landing-row[background=light-blue]+[background=light-blue]:not([class^=devsite-landing-row-padding-]){padding-top:0}.devsite-landing-row[background=light-green]+[background=light-green]:not([class^=devsite-landing-row-padding-]){padding-top:0}.devsite-landing-row[background=navy]+[background=navy]:not([class^=devsite-landing-row-padding-]){padding-top:0}.devsite-landing-row[background=pale-blue]+[background=pale-blue]:not([class^=devsite-landing-row-padding-]){padding-top:0}.devsite-landing-row:not([background])+.devsite-landing-row-cta:not([class^=devsite-landing-row-padding-]){padding-top:40px}.devsite-landing-row:not([background])+.devsite-landing-row-cta.devsite-landing-row-padding-small{padding-top:32px}.devsite-landing-row:not([background])+.devsite-landing-row-cta.devsite-landing-row-padding-medium{padding-top:64px}.devsite-landing-row:not([background])+.devsite-landing-row-cta.devsite-landing-row-padding-large{padding-top:96px}.devsite-landing-row:not([background])+.devsite-landing-row-cta.devsite-landing-row-padding-xlarge{padding-top:128px}.devsite-landing-row-inner{margin:var(--devsite-landing-group-margin,0 auto);max-width:var(--devsite-landing-row-max-width,1488px);padding:var(--devsite-landing-group-padding)}.devsite-landing-row-group,.devsite-landing-row-html{margin:0 auto}.devsite-landing-row-group{background:var(--devsite-landing-row-group-background);border:var(--devsite-landing-row-group-border);border-radius:var(--devsite-landing-row-group-border-radius);display:grid;grid:var(--devsite-landing-row-group-grid);grid-auto-rows:var(--devsite-grid-auto-rows);grid-gap:var(--devsite-item-gap);max-width:var(--devsite-landing-row-group-max-width);padding:var(--devsite-landing-row-group-padding)}.devsite-landing-row-1-up .devsite-landing-row-group{display:block}.devsite-landing-row[header-position=left] .devsite-landing-row-inner,.devsite-landing-row[header-position=right] .devsite-landing-row-inner{display:grid;grid:var(--devsite-landing-row-inner-grid,1fr/repeat(3,1fr));grid-gap:var(--devsite-item-gap)}.devsite-landing-row[header-position=left] .devsite-landing-row-group{grid-column:var(--devsite-landing-row-group-grid-column,2/span 2)}.devsite-landing-row[header-position=right] .devsite-landing-row-group{grid-column:var(--devsite-landing-row-group-grid-column,1/span 2);-webkit-box-ordinal-group:2;-webkit-order:1;-moz-box-ordinal-group:2;-ms-flex-order:1;order:1}@media screen and (max-width:840px){.devsite-landing-row[header-position] .devsite-landing-row-inner{display:block}.devsite-landing-row:not([background])+.devsite-landing-row-cta.devsite-landing-row-padding-large,.devsite-landing-row:not([background])+.devsite-landing-row-cta.devsite-landing-row-padding-medium,.devsite-landing-row:not([background])+.devsite-landing-row-cta.devsite-landing-row-padding-small,.devsite-landing-row:not([background])+.devsite-landing-row-cta.devsite-landing-row-padding-xlarge,.devsite-landing-row:not([background])+.devsite-landing-row-cta:not([class^=devsite-landing-row-padding-]){padding-top:24px}}@media screen and (max-width:600px){.devsite-landing-row:not([background])+.devsite-landing-row-cta.devsite-landing-row-padding-large,.devsite-landing-row:not([background])+.devsite-landing-row-cta.devsite-landing-row-padding-medium,.devsite-landing-row:not([background])+.devsite-landing-row-cta.devsite-landing-row-padding-small,.devsite-landing-row:not([background])+.devsite-landing-row-cta.devsite-landing-row-padding-xlarge,.devsite-landing-row:not([background])+.devsite-landing-row-cta:not([class^=devsite-landing-row-padding-]){padding-top:16px}}[theme=web-theme]{--devsite-header-lower-box-shadow:none;--devsite-header-border:var(--devsite-primary-border);--devsite-upper-tab-marker-color:#6001ff;--devsite-upper-tab-marker-color-inactive:#6001ff;--devsite-card-border-radius:10px;--devsite-card-border:1px solid #d2d3d7;--devsite-card-box-shadow:0;--devsite-button-box-shadow:none;--devsite-button-color:var(--devsite-primary-color)}[theme=web-theme] .devsite-landing-row-cards{--devsite-foreground-color:var(--devsite-primary-text-color)}devsite-a11y-announce{background:transparent;color:transparent;display:block;left:-500vw;position:absolute;top:-500vh;z-index:-1}devsite-analytics>iframe{display:none}devsite-anselm{display:block;-webkit-box-flex:1;-webkit-flex-grow:1;-moz-box-flex:1;-ms-flex-positive:1;flex-grow:1}devsite-anselm .anselm-loading{display:none}devsite-anselm .anselm-loading devsite-spinner{margin:0 auto}devsite-anselm[loading] .anselm-loading{display:block}devsite-anselm[type=playlist] .anselm-results{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-pack:start;-webkit-justify-content:flex-start;-moz-box-pack:start;-ms-flex-pack:start;justify-content:flex-start;margin:0 -12px}devsite-anselm h3:first-child{margin-bottom:4px}devsite-anselm[active] .anselm-suggest-container input{box-shadow:0 1px 3px 0 var(--devsite-elevation-key-shadow-color),0 4px 8px 3px var(--devsite-elevation-ambient-shadow-color)}devsite-anselm[pending-suggestions] .anselm-suggest-container .anselm-suggest-search-icon{opacity:0}devsite-anselm[pending-suggestions] .anselm-suggest-container .anselm-suggest-spinner{opacity:1}devsite-anselm[has-query] .anselm-suggest-container .anselm-suggest-close-icon{opacity:1;pointer-events:all}devsite-anselm[has-suggestions][active] .anselm-suggest-container input{border-radius:2px 2px 0}devsite-anselm .anselm-suggest-container{max-width:492px;margin-bottom:36px}devsite-anselm .anselm-suggest-container form{position:relative}devsite-anselm .anselm-suggest-container input{border:0!important;border-radius:4px;box-shadow:0 1px 2px 0 var(--devsite-elevation-key-shadow-color),0 1px 3px 1px var(--devsite-elevation-ambient-shadow-color);color:#3c4043;line-height:26px;padding:8px 46px;width:100%}devsite-anselm .anselm-suggest-container input:hover{box-shadow:0 1px 3px 0 var(--devsite-elevation-key-shadow-color),0 4px 8px 3px var(--devsite-elevation-ambient-shadow-color)}devsite-anselm .anselm-suggest-container input:focus{border:0!important;padding-bottom:8px}devsite-anselm .anselm-suggest-container .anselm-suggestions{background:var(--devsite-background-1);border-top:1px solid #ccc;border-radius:0 0 4px 4px;box-shadow:0 2px 3px 0 var(--devsite-elevation-key-shadow-color),0 6px 10px 4px var(--devsite-elevation-ambient-shadow-color);position:absolute;width:100%;z-index:100}devsite-anselm .anselm-suggest-container .anselm-suggestions:empty{box-shadow:none}devsite-anselm .anselm-suggest-container .anselm-suggest-result{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;line-height:56px;-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center}devsite-anselm .anselm-suggest-container .anselm-suggest-result a{color:#3c4043;-webkit-box-flex:1;-webkit-flex-grow:1;-moz-box-flex:1;-ms-flex-positive:1;flex-grow:1;padding:0 16px}devsite-anselm .anselm-suggest-container .anselm-suggest-result a:focus,devsite-anselm .anselm-suggest-container .anselm-suggest-result a:hover,devsite-anselm .anselm-suggest-container .anselm-suggest-result.highlight a{text-decoration:none;background:#f1f3f4}devsite-anselm .anselm-suggest-input-container{position:relative}devsite-anselm .anselm-suggest-input-container .anselm-suggest-close-icon,devsite-anselm .anselm-suggest-input-container .anselm-suggest-search-icon,devsite-anselm .anselm-suggest-input-container .anselm-suggest-spinner{color:#5f6368;opacity:0;pointer-events:none;position:absolute;-webkit-transition:opacity .3s cubic-bezier(0,.795,0,1);transition:opacity .3s cubic-bezier(0,.795,0,1)}devsite-anselm .anselm-suggest-input-container .anselm-suggest-close-icon,devsite-anselm .anselm-suggest-input-container .anselm-suggest-close-icon:focus{text-decoration:none}devsite-anselm .anselm-suggest-input-container .anselm-suggest-search-icon{opacity:1}devsite-anselm .anselm-suggest-input-container .anselm-suggest-search-icon,devsite-anselm .anselm-suggest-input-container .anselm-suggest-spinner{top:8px;left:16px}devsite-anselm .anselm-suggest-input-container .anselm-suggest-close-icon{top:8px;right:16px}devsite-anselm .anselm-more{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;-ms-flex-pack:center;justify-content:center;padding:20px 0 32px}devsite-anselm .anselm-cell{opacity:0;-webkit-transition:opacity .3s cubic-bezier(.4,0,1,1);transition:opacity .3s cubic-bezier(.4,0,1,1)}devsite-anselm .anselm-cell[show]{opacity:1}devsite-anselm .anselm-cell .bull{padding:0 4px}devsite-anselm .anselm-cell .anselm-meta{font-family:var(--devsite-primary-font-family);font-size:12px;color:#6a6e74;letter-spacing:.3px;text-align:left;line-height:16px}devsite-anselm .anselm-cell .anselm--tags span{display:-webkit-inline-box;display:-webkit-inline-flex;display:-moz-inline-box;display:-ms-inline-flexbox;display:inline-flex;font-family:var(--devsite-primary-font-family);font-size:12px;color:#5f6368;letter-spacing:.3px;text-align:left;line-height:16px;border:var(--devsite-primary-border);border-radius:16px;height:30px;padding:12px;-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center}devsite-anselm .anselm-cell--list p{font-family:var(--devsite-primary-font-family);font-size:14px;color:#3c4043;letter-spacing:.2px;line-height:20px;margin:8px 0;text-align:left}devsite-anselm .anselm-card{background:var(--devsite-card-background);border:var(--devsite-card-border);border-radius:var(--devsite-card-border-radius);box-shadow:var(--devsite-card-box-shadow);display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-moz-box-orient:vertical;-moz-box-direction:normal;-ms-flex-direction:column;flex-direction:column;height:100%}devsite-anselm .anselm-card .anselm-card--top{border-radius:var(--devsite-card-content-border-radius,1px 1px 0 0);height:158px;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;-ms-flex-pack:center;justify-content:center;position:relative}devsite-anselm .anselm-card .anselm-card--top .badge-icon{width:110px;height:110px;position:relative;z-index:2;opacity:0;-webkit-transform:scale(0);transform:scale(0)}@-webkit-keyframes bounce{0%{opacity:0;-webkit-transform:scale(.2);transform:scale(.2)}50%{opacity:1;-webkit-transform:scale(1.3);transform:scale(1.3)}to{-webkit-transform:scale(1);transform:scale(1);opacity:1}}@keyframes bounce{0%{opacity:0;-webkit-transform:scale(.2);transform:scale(.2)}50%{opacity:1;-webkit-transform:scale(1.3);transform:scale(1.3)}to{-webkit-transform:scale(1);transform:scale(1);opacity:1}}devsite-anselm .anselm-card .anselm-card--top .badge-icon.bounce{-webkit-animation-duration:1s;animation-duration:1s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-name:bounce;animation-name:bounce;opacity:1;-webkit-transform:scale(1);transform:scale(1)}devsite-anselm .anselm-card devsite-progress .devsite-progress--indeterminate .devsite-progress--indeterminate-2,devsite-anselm .anselm-card devsite-progress .devsite-progress--indeterminate .devsite-progress--indeterminate-4{background:#dadce0}devsite-anselm .anselm-card .anselm-card--progress{overflow:hidden;height:2px;background:#dadce0}devsite-anselm .anselm-card .anselm-card--progress .anselm-card--progress--bar{background:#fbbc04;height:2px;-webkit-transform:translateX(-101%);transform:translateX(-101%);-webkit-transition:background .213s cubic-bezier(0,0,.2,1),-webkit-transform .213s cubic-bezier(0,0,.2,1);transition:background .213s cubic-bezier(0,0,.2,1),-webkit-transform .213s cubic-bezier(0,0,.2,1);transition:transform .213s cubic-bezier(0,0,.2,1),background .213s cubic-bezier(0,0,.2,1);transition:transform .213s cubic-bezier(0,0,.2,1),background .213s cubic-bezier(0,0,.2,1),-webkit-transform .213s cubic-bezier(0,0,.2,1)}devsite-anselm .anselm-card .anselm-card--progress .anselm-card--progress--bar.completed{background:#34a853}devsite-anselm .anselm-card .anselm-card--progress--info:empty:before{content:" "}devsite-anselm .anselm-card .anselm-card--progress--info{font-size:12px;font-weight:700;color:#45494c;padding:0 16px;opacity:0;-webkit-transform:translateY(12px);transform:translateY(12px);-webkit-transition:opacity .213s cubic-bezier(.4,0,1,1),-webkit-transform .213s cubic-bezier(.4,0,1,1);transition:opacity .213s cubic-bezier(.4,0,1,1),-webkit-transform .213s cubic-bezier(.4,0,1,1);transition:transform .213s cubic-bezier(.4,0,1,1),opacity .213s cubic-bezier(.4,0,1,1);transition:transform .213s cubic-bezier(.4,0,1,1),opacity .213s cubic-bezier(.4,0,1,1),-webkit-transform .213s cubic-bezier(.4,0,1,1)}devsite-anselm .anselm-card .anselm-card--progress--info.show{opacity:1;-webkit-transform:translateY(0);transform:translateY(0);-webkit-transition:opacity .213s cubic-bezier(0,0,.2,1),-webkit-transform .213s cubic-bezier(0,0,.2,1);transition:opacity .213s cubic-bezier(0,0,.2,1),-webkit-transform .213s cubic-bezier(0,0,.2,1);transition:transform .213s cubic-bezier(0,0,.2,1),opacity .213s cubic-bezier(0,0,.2,1);transition:transform .213s cubic-bezier(0,0,.2,1),opacity .213s cubic-bezier(0,0,.2,1),-webkit-transform .213s cubic-bezier(0,0,.2,1)}devsite-anselm .anselm-card .anselm-card--body{-webkit-box-flex:1;-webkit-flex:1;-moz-box-flex:1;-ms-flex:1;flex:1;padding:0 16px}devsite-anselm .anselm-card .anselm--tags:not(:empty){border-bottom:var(--devsite-primary-border);margin:0 16px;padding:0 0 16px}devsite-anselm .anselm-card .anselm-card--bottom{margin:16px}devsite-anselm .anselm-card .anselm-card--summary{font-family:var(--devsite-primary-font-family);font-size:12px;color:#6a6e74;letter-spacing:.3px;text-align:left;line-height:16px}devsite-anselm .anselm-card .anselm-card--actions{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-pack:end;-webkit-justify-content:flex-end;-moz-box-pack:end;-ms-flex-pack:end;justify-content:flex-end}devsite-anselm .anselm-cell--card{-webkit-flex-basis:calc(33.33% - 24px);-ms-flex-preferred-size:calc(33.33% - 24px);flex-basis:calc(33.33% - 24px);margin:12px}devsite-anselm .anselm-cell--list{margin-bottom:32px}devsite-anselm .anselm-cell--list a{color:#346cf2}devsite-anselm .anselm-no-results-found{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;width:100%;margin-top:36px}devsite-anselm .anselm-no-results-found .no-results-text{-webkit-flex-basis:50%;-ms-flex-preferred-size:50%;flex-basis:50%;padding:0 12px}devsite-anselm .anselm-no-results-found .no-results-text h3{font-size:28px;color:#3c4043;line-height:36px;margin:0}devsite-anselm .anselm-no-results-found .no-results-text p{margin:0;padding:8px 0 0;font-size:14px;color:#5f6368;line-height:20px}devsite-anselm .anselm-no-results-found .no-results-img{margin:0 12px;padding:0 12px;-webkit-flex-basis:50%;-ms-flex-preferred-size:50%;flex-basis:50%;background-image:url(../../images/not-found.svg);-webkit-box-flex:1;-webkit-flex-grow:1;-moz-box-flex:1;-ms-flex-positive:1;flex-grow:1;background-repeat:no-repeat;background-size:contain;background-position:50% 50%;height:206px}devsite-anselm .anselm-results-container{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-webkit-justify-content:space-between;-moz-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between}devsite-anselm .anselm-results-container .anselm-results-cell{-webkit-box-flex:1;-webkit-flex-grow:1;-moz-box-flex:1;-ms-flex-positive:1;flex-grow:1}devsite-anselm .anselm-results-container .anselm-featured-cell{display:none;-webkit-box-flex:1;-webkit-flex-grow:1;-moz-box-flex:1;-ms-flex-positive:1;flex-grow:1;max-width:292px;padding-left:18px}devsite-anselm .anselm-results-container .anselm-featured-cell h4{font-size:10px;font-weight:500;color:#666;line-height:16px;text-transform:uppercase}devsite-anselm.has-featured .anselm-no-results-found{display:block}devsite-anselm.has-featured .anselm-no-results-found .no-results-img{margin:48px 12px;height:295px}devsite-anselm.has-featured .anselm-no-results-found .no-results-text{text-align:center}devsite-anselm.has-featured .anselm-results-container .anselm-results-cell{max-width:491px}devsite-anselm.has-featured .anselm-results-container .anselm-featured-cell{display:block}devsite-anselm .anselm--featured{border:var(--devsite-card-border);border-radius:var(--devsite-card-border-radius);box-shadow:var(--devsite-card-box-shadow);margin-bottom:12px;padding:16px}devsite-anselm .anselm--featured .topic__meta{border-top:1px solid #d8d8d8;color:#3c4043;font-size:12px;line-height:16px;margin:16px 0 8px;padding:16px 0 0}devsite-anselm .anselm--featured .topic__updated{padding-top:4px}@media screen and (max-width:840px){devsite-anselm .anselm-cell--card{-webkit-flex-basis:calc(50% - 24px);-ms-flex-preferred-size:calc(50% - 24px);flex-basis:calc(50% - 24px)}devsite-anselm.has-featured .anselm-results-container .anselm-featured-cell{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex}devsite-anselm .anselm-results-container{-webkit-box-orient:vertical;-webkit-box-direction:reverse;-webkit-flex-direction:column-reverse;-moz-box-orient:vertical;-moz-box-direction:reverse;-ms-flex-direction:column-reverse;flex-direction:column-reverse}devsite-anselm .anselm-results-container .anselm-featured-cell{-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;overflow-x:auto;min-width:100%;margin:0 0 24px;padding:24px 0 0;position:relative}devsite-anselm .anselm-results-container .anselm-featured-cell h4{position:absolute;top:0;left:0}devsite-anselm .anselm-results-container .anselm--featured{min-width:200px;margin-right:8px;-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;max-width:300px}devsite-anselm .anselm-results-container .anselm--featured .devsite-landing-row-item-description{position:relative}devsite-anselm .anselm-results-container .anselm--featured a{position:absolute;right:8px;top:8px;padding:0;height:30px;width:30px}devsite-anselm .anselm-results-container .anselm--featured a .devsite-landing-row-item-icon-container{width:30px;height:30px}devsite-anselm .anselm-results-container .anselm--featured a .devsite-landing-row-item-icon-container img{width:30px;height:30px;margin:0}devsite-anselm .anselm-results-container .anselm--featured h3{margin:0}devsite-anselm .anselm-results-container .anselm--featured .devsite-landing-row-item-body a{position:static;margin:12px;text-overflow:ellipsis;margin-right:54px;width:auto;height:auto}devsite-anselm .anselm-results-container .anselm--featured .devsite-landing-row-item-body .topic__meta{margin-top:0}devsite-anselm .anselm-results-container .anselm--featured .devsite-landing-row-item-body .devsite-landing-row-item-buttons,devsite-anselm .anselm-results-container .anselm--featured .devsite-landing-row-item-body p{display:none}}@media screen and (max-width:600px){devsite-anselm .anselm-cell--card{-webkit-flex-basis:calc(100% - 24px);-ms-flex-preferred-size:calc(100% - 24px);flex-basis:calc(100% - 24px)}devsite-anselm .anselm-no-results-found{margin-top:12px;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}devsite-anselm .anselm-no-results-found .no-results-img,devsite-anselm .anselm-no-results-found .no-results-text{-webkit-flex-basis:100%;-ms-flex-preferred-size:100%;flex-basis:100%}devsite-anselm .anselm-no-results-found .no-results-img{margin-top:32px;height:163px}}devsite-dialog[open].devsite-henhouse-dialog{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;padding:0}.devsite-henhouse-inner{background:var(--devsite-background-1);display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-flex:1;-webkit-flex-grow:1;-moz-box-flex:1;-ms-flex-positive:1;flex-grow:1;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-moz-box-orient:vertical;-moz-box-direction:normal;-ms-flex-direction:column;flex-direction:column;margin-top:2px;overflow:hidden}.devsite-henhouse-spinner-container{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-flex:1;-webkit-flex-grow:1;-moz-box-flex:1;-ms-flex-positive:1;flex-grow:1;-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;-ms-flex-pack:center;justify-content:center;min-height:240px}.devsite-credentials-spinner-region{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;-ms-flex-pack:center;justify-content:center}.devsite-henhouse-cross-container{height:160px;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-align:start;-webkit-align-items:start;-moz-box-align:start;-ms-flex-align:start;align-items:start;-webkit-box-pack:end;-webkit-justify-content:flex-end;-moz-box-pack:end;-ms-flex-pack:end;justify-content:flex-end}.devsite-henhouse-cross{margin:16px;float:right;cursor:pointer}.devsite-apix-error{padding:32px}.devsite-apix-controls{position:absolute;right:8px;z-index:1001}.devsite-apix-controls .button-flat{cursor:pointer!important}.devsite-apix-controls .devsite-dock-apix:before,.devsite-apix-controls .devsite-fullscreen-apix:before,.devsite-apix-controls .devsite-hide-apix:before{color:var(--devsite-primary-text-color)}.devsite-apix-controls .devsite-hide-apix:before{content:"close"}.devsite-apix-controls .devsite-fullscreen-apix:before{content:"fullscreen"}.devsite-apix-controls .devsite-dock-apix:before{content:"fullscreen_exit"}.apis-explorer{background:var(--devsite-background-3)}.devsite-apix{background:var(--devsite-background-3);-webkit-transform:translateZ(0);transform:translateZ(0);will-change:height,transform}.devsite-apix:not(.dialog) .devsite-apix-controls{top:24px}.devsite-apix:not(.dialog) .devsite-apix-controls .devsite-dock-apix{display:none}.devsite-apix.dialog{border-radius:2px;box-shadow:0 17px 17px rgba(0,0,0,.15),0 27px 55px rgba(0,0,0,.3);font:14px/20px var(--devsite-primary-font-family);max-width:calc(100% - 48px);overflow:auto;padding:8px;position:fixed;z-index:10012;max-height:none!important}.devsite-apix.dialog .apis-explorer{height:100%;min-height:100%}.devsite-apix.dialog .devsite-fullscreen-apix,.devsite-apix.dialog .devsite-hide-apix{display:none}.devsite-has-apix .devsite-main-content{z-index:auto}.devsite-has-apix .devsite-main-content devsite-googler-buttons{z-index:1003}@media screen and (min-width:1201px){.devsite-apix:not(.dialog){box-shadow:0 0 4px rgba(0,0,0,.14),0 4px 8px rgba(0,0,0,.28);display:none;max-height:100vh;overflow:auto;position:fixed;right:0;top:96px;width:400px;z-index:1001}.devsite-apix.dialog{bottom:20px;left:calc(50% - 576px);margin:0;top:50px;width:1152px}.devsite-has-apix .devsite-apix{display:block}}@media screen and (max-width:1200px){.devsite-apix{display:block}.devsite-apix:not(.dialog){margin-top:32px;max-height:none!important;position:relative;-webkit-transform:none!important;transform:none!important;top:auto!important;height:auto!important}.devsite-apix.dialog{bottom:20px;left:24px;margin:0;top:50px;width:calc(100% - 48px)}.devsite-hide-apix{display:none}}.devsite-page-insights-dialog.has-dashboard{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-moz-box-orient:vertical;-moz-box-direction:normal;-ms-flex-direction:column;flex-direction:column;height:100%;padding:0;width:100%}.devsite-page-insights-dialog.has-dashboard .devsite-dialog-contents{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-moz-box-orient:vertical;-moz-box-direction:normal;-ms-flex-direction:column;flex-direction:column;height:100%;padding:0}.devsite-page-insights-dialog.has-dashboard .dialog-title{-webkit-border-after:1px solid #dadce0;border-block-end:1px solid #dadce0;display:grid;gap:12px;grid-gap:12px;grid-template-areas:"title message close";grid-template-columns:auto 1fr auto;-webkit-margin-after:8px;margin-block-end:8px;padding-block:20px;padding-inline:24px;width:100%}.devsite-page-insights-dialog.has-dashboard h3{font:400 18px/30px var(--devsite-headline-font-family);grid-area:title;text-align:initial}.devsite-page-insights-dialog.has-dashboard p{font:14px/20px var(--devsite-primary-font-family);grid-area:message}.devsite-page-insights-dialog.has-dashboard h3,.devsite-page-insights-dialog.has-dashboard p{-webkit-align-self:baseline;-ms-flex-item-align:baseline;align-self:baseline;margin:0}.devsite-page-insights-dialog.has-dashboard .devsite-dialog-close{align-self:flex-start;grid-area:close;margin:-4px}.devsite-page-insights-dialog.has-dashboard aside{display:grid;grid-template-columns:auto 1fr auto;-webkit-margin-after:12px;margin-block-end:12px;-webkit-margin-before:16px;margin-block-start:16px;margin-inline:auto;max-width:800px}.devsite-page-insights-dialog.has-dashboard .dismiss-aside{background:var(--devsite-note-notice-background)}.devsite-page-insights-dialog.has-dashboard .dashboard-embed{height:100%;width:100%}.devsite-page-insights-dialog.has-link aside{-webkit-margin-after:0;margin-block-end:0}.devsite-page-insights-dialog.has-link .devsite-dialog-buttons{-webkit-box-pack:start;-webkit-justify-content:flex-start;-moz-box-pack:start;-ms-flex-pack:start;justify-content:flex-start;-webkit-padding-after:16px;padding-block-end:16px;-webkit-padding-before:8px;padding-block-start:8px;padding-inline:16px}@-webkit-keyframes badgeGrowIn{0%{-webkit-transform:scale(0);transform:scale(0)}to{-webkit-transform:scale(1.3);transform:scale(1.3)}}@-webkit-keyframes badgeGrowOut{0%{-webkit-transform:scale(1.3);transform:scale(1.3)}to{-webkit-transform:scale(1);transform:scale(1)}}@-webkit-keyframes badgeFadeIn{0%{opacity:0}12%{opacity:0}87%{opacity:100%}}@-webkit-keyframes counterHide{0%{opacity:0}to{opacity:0}}.devsite-claim-badge-dialog.devsite-claim-badge-dialog,devsite-badge-awarded.devsite-claim-badge-dialog{padding:0}.devsite-claim-badge-dialog .card,devsite-badge-awarded .card{box-shadow:0 1px 2px 0 rgba(60,64,67,.3),0 1px 3px 1px rgba(60,64,67,.15);border-radius:5px;background:var(--devsite-background-1);display:block;max-width:856px;border-top:5px solid #1a73e8;position:relative;overflow:hidden;margin:0 auto}.devsite-claim-badge-dialog .card .card-content,devsite-badge-awarded .card .card-content{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-moz-box-orient:vertical;-moz-box-direction:normal;-ms-flex-direction:column;flex-direction:column;max-height:calc(100vh - 32px);overflow:visible}.devsite-claim-badge-dialog .card .illustration-container,.devsite-claim-badge-dialog .card .text-container,devsite-badge-awarded .card .illustration-container,devsite-badge-awarded .card .text-container{width:50%}@media screen and (max-width:600px){.devsite-claim-badge-dialog .card .illustration-container,.devsite-claim-badge-dialog .card .text-container,devsite-badge-awarded .card .illustration-container,devsite-badge-awarded .card .text-container{width:100%}}.devsite-claim-badge-dialog .card .profile-creation-container,devsite-badge-awarded .card .profile-creation-container{-webkit-box-flex:1;-webkit-flex:1;-moz-box-flex:1;-ms-flex:1;flex:1;overflow:auto;max-height:50vh;border-top:1px solid #e8eaed;padding:16px 24px}.devsite-claim-badge-dialog .card .profile-creation-container p,devsite-badge-awarded .card .profile-creation-container p{margin:8px 0;color:#3c4043;font-size:14px;line-height:22px}.devsite-claim-badge-dialog .card .profile-creation-container-email-options,devsite-badge-awarded .card .profile-creation-container-email-options{margin-top:8px}.devsite-claim-badge-dialog .card .profile-creation-container-email-options .profile-creation-container-email-option,devsite-badge-awarded .card .profile-creation-container-email-options .profile-creation-container-email-option{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center}.devsite-claim-badge-dialog .card .profile-creation-container-email-options .profile-creation-container-email-option input,devsite-badge-awarded .card .profile-creation-container-email-options .profile-creation-container-email-option input{margin-top:0}.devsite-claim-badge-dialog .card .profile-creation-container-email-options .profile-creation-container-email-option label,devsite-badge-awarded .card .profile-creation-container-email-options .profile-creation-container-email-option label{font-size:14px}.devsite-claim-badge-dialog .card .spinner-container,devsite-badge-awarded .card .spinner-container{position:absolute;width:100%;height:100%;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;-ms-flex-pack:center;justify-content:center;background:hsla(0,0%,100%,.8);z-index:100;pointer-events:none;opacity:0;-webkit-transition:opacity .3s cubic-bezier(.4,0,.2,1);transition:opacity .3s cubic-bezier(.4,0,.2,1)}.devsite-claim-badge-dialog .card .content-container,devsite-badge-awarded .card .content-container{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex}@media screen and (max-width:600px){.devsite-claim-badge-dialog .card .content-container,devsite-badge-awarded .card .content-container{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-moz-box-orient:vertical;-moz-box-direction:normal;-ms-flex-direction:column;flex-direction:column}}.devsite-claim-badge-dialog .card .text-container,devsite-badge-awarded .card .text-container{padding:36px 24px;-webkit-box-flex:1;-webkit-flex-grow:1;-moz-box-flex:1;-ms-flex-positive:1;flex-grow:1}@media screen and (max-width:600px){.devsite-claim-badge-dialog .card .text-container,devsite-badge-awarded .card .text-container{padding:24px}}.devsite-claim-badge-dialog .illustration-container,devsite-badge-awarded .illustration-container{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;min-height:164px;min-width:303px;height:164px;width:303px;-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;position:relative;background-image:url(../images/badge-award-background.svg);background-size:100% calc(100% + 2px);background-position:1px -1px;background-repeat:no-repeat}.devsite-claim-badge-dialog .illustration-container.show .badge-icon,devsite-badge-awarded .illustration-container.show .badge-icon{opacity:1;-webkit-transform:scale(1);transform:scale(1)}.devsite-claim-badge-dialog .illustration-container.animate .badge-icon,devsite-badge-awarded .illustration-container.animate .badge-icon{-webkit-animation:badgeGrowIn .33s cubic-bezier(.75,0,.71,.97),badgeGrowOut .17s cubic-bezier(.85,-.14,.83,.83) .33s,badgeFadeIn .5s linear;animation:badgeGrowIn .33s cubic-bezier(.75,0,.71,.97),badgeGrowOut .17s cubic-bezier(.85,-.14,.83,.83) .33s,badgeFadeIn .5s linear}.devsite-claim-badge-dialog .illustration-container .badge-icon,devsite-badge-awarded .illustration-container .badge-icon{width:124px;height:124px;z-index:1000;opacity:0;-webkit-transform:scale(0,0,0);transform:scale(0,0,0);-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards}.devsite-claim-badge-dialog .illustration-container .badge-icon.incomplete,devsite-badge-awarded .illustration-container .badge-icon.incomplete{-webkit-filter:grayscale(100%);filter:grayscale(100%)}.devsite-claim-badge-dialog .illustration-container .badge-animation,devsite-badge-awarded .illustration-container .badge-animation{position:absolute;width:195px;height:170px;background-image:url(../images/badge-award-animation.gif);background-size:100% 100%}.devsite-claim-badge-dialog .completed-title,devsite-badge-awarded .completed-title{font-size:20px;margin-bottom:8px;line-height:28px;color:#000;font-family:var(--devsite-headline-font-family)}.devsite-claim-badge-dialog .claim-badge-text,.devsite-claim-badge-dialog .completed-text,.devsite-claim-badge-dialog .create-profile-text,.devsite-claim-badge-dialog .error-text,.devsite-claim-badge-dialog .not-eligible-text,.devsite-claim-badge-dialog .sign-in-text,devsite-badge-awarded .claim-badge-text,devsite-badge-awarded .completed-text,devsite-badge-awarded .create-profile-text,devsite-badge-awarded .error-text,devsite-badge-awarded .not-eligible-text,devsite-badge-awarded .sign-in-text{font-size:14px}.devsite-claim-badge-dialog .buttons-container,devsite-badge-awarded .buttons-container{border-top:1px solid #e8eaed;padding:0 8px;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-webkit-justify-content:space-between;-moz-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between}.devsite-claim-badge-dialog .buttons-container .buttons,devsite-badge-awarded .buttons-container .buttons{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}.devsite-claim-badge-dialog .buttons-container .dismiss,devsite-badge-awarded .buttons-container .dismiss{position:relative;overflow:visible}@media screen and (max-width:600px){.devsite-claim-badge-dialog .buttons-container,devsite-badge-awarded .buttons-container{-webkit-box-orient:vertical;-webkit-box-direction:reverse;-webkit-flex-direction:column-reverse;-moz-box-orient:vertical;-moz-box-direction:reverse;-ms-flex-direction:column-reverse;flex-direction:column-reverse;padding-top:0;text-align:center;-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center}.devsite-claim-badge-dialog .buttons-container .button,devsite-badge-awarded .buttons-container .button{margin:10px auto 0}.devsite-claim-badge-dialog .buttons-container .buttons,devsite-badge-awarded .buttons-container .buttons{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-moz-box-orient:horizontal;-moz-box-direction:normal;-ms-flex-direction:row;flex-direction:row;margin-top:5px}}.devsite-claim-badge-dialog[loading] .card .spinner-container,devsite-badge-awarded[loading] .card .spinner-container{opacity:1;pointer-events:all}.devsite-claim-badge-dialog .qr-code-container,devsite-badge-awarded .qr-code-container{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;height:225px;background-image:url(../images/claim-badge-dialog-background.png);-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;background-position:50%;background-size:700px}.devsite-claim-badge-dialog .qr-code-container canvas,devsite-badge-awarded .qr-code-container canvas{display:none}.devsite-claim-badge-dialog .qr-code-container img,devsite-badge-awarded .qr-code-container img{height:150px;width:150px;padding:10px;background:var(--devsite-background-1)}.devsite-claim-badge-dialog .redeem-code-section,devsite-badge-awarded .redeem-code-section{padding:18px 24px 0;margin-bottom:-15px}.devsite-claim-badge-dialog .redeem-code-title,devsite-badge-awarded .redeem-code-title{text-transform:uppercase;font-size:10.5px;font-weight:600;color:#80868b;margin-bottom:3px}.devsite-claim-badge-dialog .redeem-code,devsite-badge-awarded .redeem-code{display:inline-block;font-size:18px;font-weight:500;letter-spacing:12px;color:#000;padding:8px 2px 8px 12px;border:2px solid #1a73e8;border-radius:4px;background-color:rgba(227,242,253,.6)}.devsite-claim-badge-dialog .illustration-container.animate .badge-icon-counter,devsite-badge-awarded .illustration-container.animate .badge-icon-counter{-webkit-animation:counterHide 1s,badgeGrowIn .33s cubic-bezier(.75,0,.71,.97) 1s,badgeGrowOut .17s cubic-bezier(.85,-.14,.83,.83) 1.33s,badgeFadeIn .5s linear 1s;animation:counterHide 1s,badgeGrowIn .33s cubic-bezier(.75,0,.71,.97) 1s,badgeGrowOut .17s cubic-bezier(.85,-.14,.83,.83) 1.33s,badgeFadeIn .5s linear 1s;opacity:1;-webkit-transform:scale(1);transform:scale(1)}.devsite-claim-badge-dialog .illustration-container .badge-icon-counter,devsite-badge-awarded .illustration-container .badge-icon-counter{padding:3px 10px;font-size:14px;border-radius:19px;color:#fff;font-weight:500;background-color:#1976d2;position:absolute;bottom:17px;z-index:10001;opacity:0;-webkit-transform:scale(0);transform:scale(0);box-shadow:0 4px 8px 3px rgba(60,64,67,.149),0 1px 3px 0 rgba(60,64,67,.302)}.devsite-claim-badge-dialog .badge-name,devsite-badge-awarded .badge-name{font-weight:500}.devsite-claim-badge-dialog .buttons-container .more-badges-marker,devsite-badge-awarded .buttons-container .more-badges-marker{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;position:absolute;top:-12px;right:-12px;background:#e53935;min-width:24px;min-height:24px;border-radius:50px;-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;-ms-flex-pack:center;justify-content:center;text-align:center;color:#fff;font-weight:700;max-height:24px;max-width:24px;line-height:24px;font-size:12px}@media screen and (max-width:600px){.devsite-claim-badge-dialog .buttons-container .sharing,devsite-badge-awarded .buttons-container .sharing{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-moz-box-orient:horizontal;-moz-box-direction:normal;-ms-flex-direction:row;flex-direction:row;padding:2px 0 20px}}.devsite-claim-badge-dialog .buttons-container .actions .button,.devsite-claim-badge-dialog .buttons-container .actions button,devsite-badge-awarded .buttons-container .actions .button,devsite-badge-awarded .buttons-container .actions button{margin:8px}.devsite-claim-badge-dialog .buttons-container .sharing,devsite-badge-awarded .buttons-container .sharing{font-size:14px;color:#3c4043;padding-left:16px;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center}.devsite-claim-badge-dialog .buttons-container .sharing .share-buttons-container,devsite-badge-awarded .buttons-container .sharing .share-buttons-container{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}.devsite-claim-badge-dialog .buttons-container .sharing span,devsite-badge-awarded .buttons-container .sharing span{margin:0 8px}.devsite-claim-badge-dialog .buttons-container .sharing .button,.devsite-claim-badge-dialog .buttons-container .sharing button,devsite-badge-awarded .buttons-container .sharing .button,devsite-badge-awarded .buttons-container .sharing button{box-shadow:none;margin:0 8px;padding:0;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;-ms-flex-pack:center;justify-content:center;border:0;height:auto;min-width:0;-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0}.devsite-claim-badge-dialog .buttons-container .sharing .button:focus,.devsite-claim-badge-dialog .buttons-container .sharing .button:hover,.devsite-claim-badge-dialog .buttons-container .sharing button:focus,.devsite-claim-badge-dialog .buttons-container .sharing button:hover,devsite-badge-awarded .buttons-container .sharing .button:focus,devsite-badge-awarded .buttons-container .sharing .button:hover,devsite-badge-awarded .buttons-container .sharing button:focus,devsite-badge-awarded .buttons-container .sharing button:hover{background:none}.devsite-claim-badge-dialog .buttons-container .sharing .button:active,.devsite-claim-badge-dialog .buttons-container .sharing button:active,devsite-badge-awarded .buttons-container .sharing .button:active,devsite-badge-awarded .buttons-container .sharing button:active{box-shadow:none}.devsite-claim-badge-dialog .buttons-container .sharing a:active,.devsite-claim-badge-dialog .buttons-container .sharing a:focus,.devsite-claim-badge-dialog .buttons-container .sharing a:hover,devsite-badge-awarded .buttons-container .sharing a:active,devsite-badge-awarded .buttons-container .sharing a:focus,devsite-badge-awarded .buttons-container .sharing a:hover{text-decoration:none}.devsite-claim-badge-dialog .buttons-container .sharing .material-icons,devsite-badge-awarded .buttons-container .sharing .material-icons{color:#5f6368;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;-ms-flex-pack:center;justify-content:center;margin:0 8px}devsite-badge-redeemer{display:block;opacity:1;-webkit-transition:opacity .7s ease-in;transition:opacity .7s ease-in}devsite-badge-redeemer .redeem-code-page-subtitle{margin-bottom:50px;margin-top:-28px;font-size:18px;color:#202124;font-family:var(--devsite-headline-font-family)}devsite-badge-redeemer devsite-badge-awarded{display:block}devsite-badge-redeemer.redeem-success{opacity:0}devsite-badge-redeemer .waiting-container{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-moz-box-orient:vertical;-moz-box-direction:normal;-ms-flex-direction:column;flex-direction:column}devsite-badge-redeemer .waiting-container devsite-spinner{margin-top:15px;-webkit-align-self:center;-ms-flex-item-align:center;align-self:center}devsite-badge-redeemer .change-account-button,devsite-badge-redeemer .create-profile-button,devsite-badge-redeemer .sign-in-button{margin-top:10px}devsite-badge-redeemer .enter-button{margin-top:15px}devsite-badge-redeemer .redeem-code-title{text-transform:uppercase;font-size:10.5px;font-weight:600;color:#80868b;letter-spacing:1px}devsite-badge-redeemer .redeem-code-error-icon,devsite-badge-redeemer .redeem-code-error-message,devsite-badge-redeemer .redeem-code-success-icon{display:none}devsite-badge-redeemer.redeem-success .redeem-code-input{border-color:#1e8e3e!important;color:default!important}devsite-badge-redeemer.redeem-success .redeem-code-success-icon{display:inline;font-size:25px;color:#1e8e3e;margin-left:10px;line-height:44px}devsite-badge-redeemer.redeem-error .redeem-code-input{border-color:#d93025}devsite-badge-redeemer.redeem-error .redeem-code-error-message{display:block;font-size:12px;color:#80868b;font-style:italic;font-weight:600}devsite-badge-redeemer.redeem-error .redeem-code-error-icon{display:inline;font-size:25px;color:#d93025;margin-left:10px;line-height:44px}devsite-badge-redeemer .redeem-code-spinner{display:inline-block;margin-left:10px;top:6px}devsite-badge-redeemer .redeem-code-input{display:inline-block;font-size:18px;font-weight:500;letter-spacing:12px;color:#000;padding:8px 2px 8px 12px;border:2px solid #1a73e8;border-radius:4px;background-color:rgba(227,242,253,.6);width:450px;height:45px}devsite-badge-redeemer .redeem-code-input:disabled{border-color:#80868b;color:#80868b}devsite-badger{display:none}.static-badge-awarded-container{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-moz-box-orient:vertical;-moz-box-direction:normal;-ms-flex-direction:column;flex-direction:column}.static-badge-awarded-container .devsite-badger-award-inner{padding:10px}.static-badge-awarded-container .dismiss{display:none}.devsite-badger-award{bottom:0;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;-ms-flex-pack:center;justify-content:center;left:0;pointer-events:none;position:fixed;right:0;z-index:99999}.devsite-badger-award .devsite-badger-award-inner{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-flex:1;-webkit-flex-grow:1;-moz-box-flex:1;-ms-flex-positive:1;flex-grow:1;max-width:670px;width:670px;margin-bottom:16px;pointer-events:all;position:absolute;-webkit-transform:translateY(150%);transform:translateY(150%);-webkit-transition:bottom .2s,margin-right .2s,-webkit-transform .2s cubic-bezier(.4,0,1,1);transition:bottom .2s,margin-right .2s,-webkit-transform .2s cubic-bezier(.4,0,1,1);transition:bottom .2s,margin-right .2s,transform .2s cubic-bezier(.4,0,1,1);transition:bottom .2s,margin-right .2s,transform .2s cubic-bezier(.4,0,1,1),-webkit-transform .2s cubic-bezier(.4,0,1,1)}@media screen and (max-width:600px){.devsite-badger-award .devsite-badger-award-inner{width:calc(100% - 20px);margin-bottom:10px}}.devsite-badger-award .devsite-badger-award-inner[show]{-webkit-transform:translateY(0);transform:translateY(0);-webkit-transition:bottom .2s,margin-right .2s,-webkit-transform .2s cubic-bezier(0,0,.2,1);transition:bottom .2s,margin-right .2s,-webkit-transform .2s cubic-bezier(0,0,.2,1);transition:bottom .2s,margin-right .2s,transform .2s cubic-bezier(0,0,.2,1);transition:bottom .2s,margin-right .2s,transform .2s cubic-bezier(0,0,.2,1),-webkit-transform .2s cubic-bezier(0,0,.2,1)}.devsite-badger-award .devsite-badger-award-inner[show] .devsite-badger-award-actions,.devsite-badger-award .devsite-badger-award-inner[show] .devsite-badger-award-details{opacity:1}.devsite-badger-award .devsite-badger-award-inner:first-child{bottom:10px;z-index:15}.devsite-badger-award .devsite-badger-award-inner:nth-child(2){bottom:5px;margin-right:-10px;z-index:14;-webkit-filter:grayscale(100%) brightness(110%);filter:grayscale(100%) brightness(110%)}.devsite-badger-award .devsite-badger-award-inner:nth-child(3){bottom:0;margin-right:-20px;z-index:13;-webkit-filter:grayscale(100%) brightness(110%);filter:grayscale(100%) brightness(110%)}.devsite-badger-award .devsite-badger-award-inner:nth-child(4){bottom:-5px;margin-right:-30px;z-index:12;-webkit-filter:grayscale(100%) brightness(110%);filter:grayscale(100%) brightness(110%)}.devsite-badger-award .devsite-badger-award-inner:nth-child(n+5){bottom:-5px;margin-right:-30px;display:none}@media screen and (max-width:600px){.devsite-badger-award .devsite-badger-award-inner:first-child{bottom:0;z-index:15}.devsite-badger-award .devsite-badger-award-inner:nth-child(2){bottom:0;margin-right:0}.devsite-badger-award .devsite-badger-award-inner:nth-child(n+3){display:none}}.devsite-badger-award .devsite-badger-award-actions{-webkit-box-align:end;-webkit-align-items:flex-end;-moz-box-align:end;-ms-flex-align:end;align-items:flex-end;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-moz-box-orient:vertical;-moz-box-direction:normal;-ms-flex-direction:column;flex-direction:column;opacity:0;-webkit-transition:opacity .3s cubic-bezier(.4,0,.2,1);transition:opacity .3s cubic-bezier(.4,0,.2,1);border-top:1px solid #d8d8d8;padding:8px}devsite-book-nav{max-height:100vh;overflow-x:hidden;overflow-y:auto;position:relative;z-index:1004}.devsite-book-nav-bg,body[pending] devsite-book-nav{background:var(--devsite-book-nav-background);box-shadow:var(--devsite-book-nav-box-shadow,0 1px 2px 0 var(--devsite-elevation-key-shadow-color),0 1px 3px 1px var(--devsite-elevation-ambient-shadow-color))}body[pending] devsite-book-nav{height:100vh}body[ready] devsite-book-nav[fixed]{box-shadow:none;contain:content;max-height:100%;position:fixed;-webkit-transform:translateY(var(--devsite-js-book-nav-y-offset,0));transform:translateY(var(--devsite-js-book-nav-y-offset,0));will-change:top,max-height,transform}body[ready] .devsite-book-nav-bg[fixed]{bottom:0;display:block;position:fixed;top:0;z-index:1}body[ready] .devsite-book-nav-bg[animatable],body[ready] devsite-book-nav[animatable]{-webkit-transition:-webkit-transform .2s cubic-bezier(.4,0,.2,1);transition:-webkit-transform .2s cubic-bezier(.4,0,.2,1);transition:transform .2s cubic-bezier(.4,0,.2,1);transition:transform .2s cubic-bezier(.4,0,.2,1),-webkit-transform .2s cubic-bezier(.4,0,.2,1)}.devsite-book-nav-bg:after{bottom:-10px;content:"";display:block;height:10px;position:fixed;width:279px}[dir=ltr] .devsite-book-nav-bg:after{left:0}[dir=rtl] .devsite-book-nav-bg:after{right:0}devsite-book-nav .devsite-book-nav-filter{background:var(--devsite-book-nav-background);border-bottom:var(--devsite-primary-border);display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;margin-bottom:12px;padding:24px 24px;position:-webkit-sticky;position:sticky;top:0;z-index:2}devsite-book-nav input[type=text]{background:var(--devsite-searchbox-inactive);border:0;border-radius:4px;color:var(--devsite-searchbox-placeholder,var(--devsite-secondary-text-color));font-size:var(--devsite-nav-font-size,13px);height:var(--devsite-book-nav-input-height);padding-inline:var(--devsite-book-nav-input-height);width:100%}devsite-book-nav input[type=text]:hover{background:var(--devsite-searchbox-hover)}devsite-book-nav input[type=text]:focus{background:var(--devsite-search-form-background-active);border:0;box-shadow:var(--devsite-search-active-box-shadow,none);color:var(--devsite-search-form-text-active,var(--devsite-primary-text-color));padding:16px var(--devsite-book-nav-input-height)}devsite-book-nav .devsite-nav-list{padding-bottom:56px}devsite-book-nav .devsite-nav-list>.devsite-nav-item:not(.devsite-nav-accordion):not(.devsite-nav-divider):first-child{border-top:0;margin-top:20px;padding-top:0}devsite-book-nav .devsite-book-nav-filter:not(.hidden)+.devsite-book-nav .devsite-nav-list>.devsite-nav-item:not(.devsite-nav-accordion):not(.devsite-nav-divider):first-child{margin-top:0}devsite-book-nav .devsite-book-nav-filter:before,devsite-book-nav .filter-clear-button{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;color:var(--devsite-searchbox-placeholder,var(--devsite-secondary-text-color));display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;font:normal normal normal 14px/1 Material Icons;height:var(--devsite-book-nav-input-height);-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;-ms-flex-pack:center;justify-content:center;position:absolute;top:24px;width:var(--devsite-book-nav-input-height)}devsite-book-nav .devsite-book-nav-filter:before{content:"filter_list";inset-inline:24px auto}devsite-book-nav .filter-clear-button{cursor:pointer;inset-inline:auto 24px;outline:0}devsite-book-nav .filter-clear-button:before{content:"close"}devsite-book-nav .filter-clear-button:focus:before,devsite-book-nav .filter-clear-button:hover:before{background:var(--devsite-background-5);border-radius:50%;padding:4px}devsite-book-nav .devsite-nav-text mark{background:#feefc3;border-radius:4px}[dir=ltr] devsite-book-nav li .devsite-nav-title{padding-left:24px}[dir=rtl] devsite-book-nav li .devsite-nav-title{padding-left:8px;padding-right:24px}[dir=ltr] devsite-book-nav .devsite-expandable-nav li .devsite-nav-title{padding-left:40px}[dir=rtl] devsite-book-nav .devsite-expandable-nav li .devsite-nav-title{padding-right:40px}[dir=ltr] devsite-book-nav .devsite-expandable-nav li li .devsite-nav-title{padding-left:56px}[dir=rtl] devsite-book-nav .devsite-expandable-nav li li .devsite-nav-title{padding-right:56px}[dir=ltr] devsite-book-nav .devsite-expandable-nav li li li .devsite-nav-title{padding-left:72px}[dir=rtl] devsite-book-nav .devsite-expandable-nav li li li .devsite-nav-title{padding-right:72px}[dir=ltr] devsite-book-nav .devsite-expandable-nav li li li li .devsite-nav-title{padding-left:88px}[dir=rtl] devsite-book-nav .devsite-expandable-nav li li li li .devsite-nav-title{padding-right:88px}[dir=ltr] devsite-book-nav .devsite-expandable-nav li li li li li .devsite-nav-title{padding-left:104px}[dir=rtl] devsite-book-nav .devsite-expandable-nav li li li li li .devsite-nav-title{padding-right:104px}[dir=ltr] devsite-book-nav .devsite-expandable-nav li li li li li li .devsite-nav-title{padding-left:120px}[dir=rtl] devsite-book-nav .devsite-expandable-nav li li li li li li .devsite-nav-title{padding-right:120px}[dir=ltr] devsite-book-nav li.devsite-nav-divider .devsite-nav-title{padding-left:0}[dir=rtl] devsite-book-nav li.devsite-nav-divider .devsite-nav-title{padding-right:0}[dir=ltr] devsite-book-nav .devsite-nav-title{margin-right:var(--devsite-nav-title-margin-x,0);padding-right:8px}[dir=rtl] devsite-book-nav .devsite-nav-title{margin-left:var(--devsite-nav-title-margin-x,0);padding-left:8px}devsite-book-nav .devsite-nav-title.devsite-nav-active{background:var(--devsite-nav-title-background-active,0)}[dir=ltr] devsite-book-nav .devsite-nav-title.devsite-nav-active{border-radius:var(--devsite-nav-title-border-radius,0 12px 12px 0)}[dir=rtl] devsite-book-nav .devsite-nav-title.devsite-nav-active{border-radius:var(--devsite-nav-title-border-radius,12px 0 0 12px)}[dir=ltr] devsite-book-nav .devsite-nav-item:not(.devsite-nav-accordion):not(.devsite-nav-heading)>.devsite-nav-title:not(.devsite-nav-active),[dir=ltr] devsite-book-nav .devsite-nav-item:not(.devsite-nav-accordion)>.devsite-expandable-nav>.devsite-nav-title-no-path{border-radius:var(--devsite-nav-title-border-radius,0 12px 12px 0)}[dir=rtl] devsite-book-nav .devsite-nav-item:not(.devsite-nav-accordion):not(.devsite-nav-heading)>.devsite-nav-title:not(.devsite-nav-active),[dir=rtl] devsite-book-nav .devsite-nav-item:not(.devsite-nav-accordion)>.devsite-expandable-nav>.devsite-nav-title-no-path{border-radius:var(--devsite-nav-title-border-radius,12px 0 0 12px)}devsite-book-nav .devsite-nav-item:not(.devsite-nav-accordion):not(.devsite-nav-heading)>.devsite-nav-title:not(.devsite-nav-active):focus,devsite-book-nav .devsite-nav-item:not(.devsite-nav-accordion):not(.devsite-nav-heading)>.devsite-nav-title:not(.devsite-nav-active):hover,devsite-book-nav .devsite-nav-item:not(.devsite-nav-accordion)>.devsite-expandable-nav>.devsite-nav-title-no-path:focus,devsite-book-nav .devsite-nav-item:not(.devsite-nav-accordion)>.devsite-expandable-nav>.devsite-nav-title-no-path:hover{background:var(--devsite-nav-title-background-hover,0)}devsite-book-nav .devsite-nav-item:not(.devsite-nav-accordion):not(.devsite-nav-heading)>.devsite-nav-title:not(.devsite-nav-active):focus,devsite-book-nav .devsite-nav-item:not(.devsite-nav-accordion):not(.devsite-nav-heading)>.devsite-nav-title:not(.devsite-nav-active):hover{color:var(--devsite-nav-title-color-hover,var(--devsite-link-color))}devsite-book-nav .devsite-nav-list>.devsite-nav-heading:not(.devsite-nav-divider){border-top:var(--devsite-primary-border);padding-top:11px}devsite-book-nav .devsite-nav-heading:not(.devsite-nav-divider){margin-top:12px}[dir=ltr] devsite-book-nav .devsite-nav-heading:not(.devsite-nav-divider) .devsite-nav-title-no-path{padding-left:24px}[dir=rtl] devsite-book-nav .devsite-nav-heading:not(.devsite-nav-divider) .devsite-nav-title-no-path{padding-right:24px}[dir=ltr] devsite-book-nav .devsite-expandable-nav .devsite-nav-heading:not(.devsite-nav-divider) .devsite-nav-title-no-path{padding-left:40px}[dir=rtl] devsite-book-nav .devsite-expandable-nav .devsite-nav-heading:not(.devsite-nav-divider) .devsite-nav-title-no-path{padding-right:40px}[dir=ltr] devsite-book-nav .devsite-expandable-nav li .devsite-nav-heading:not(.devsite-nav-divider) .devsite-nav-title-no-path{padding-left:56px}[dir=rtl] devsite-book-nav .devsite-expandable-nav li .devsite-nav-heading:not(.devsite-nav-divider) .devsite-nav-title-no-path{padding-right:56px}[dir=ltr] devsite-book-nav .devsite-expandable-nav li li .devsite-nav-heading:not(.devsite-nav-divider) .devsite-nav-title-no-path{padding-left:72px}[dir=rtl] devsite-book-nav .devsite-expandable-nav li li .devsite-nav-heading:not(.devsite-nav-divider) .devsite-nav-title-no-path{padding-right:72px}[dir=ltr] devsite-book-nav .devsite-expandable-nav li li li .devsite-nav-heading:not(.devsite-nav-divider) .devsite-nav-title-no-path{padding-left:88px}[dir=rtl] devsite-book-nav .devsite-expandable-nav li li li .devsite-nav-heading:not(.devsite-nav-divider) .devsite-nav-title-no-path{padding-right:88px}[dir=ltr] devsite-book-nav .devsite-expandable-nav li li li li .devsite-nav-heading:not(.devsite-nav-divider) .devsite-nav-title-no-path{padding-left:104px}[dir=rtl] devsite-book-nav .devsite-expandable-nav li li li li .devsite-nav-heading:not(.devsite-nav-divider) .devsite-nav-title-no-path{padding-right:104px}[dir=ltr] devsite-book-nav .devsite-expandable-nav li li li li li .devsite-nav-heading:not(.devsite-nav-divider) .devsite-nav-title-no-path{padding-left:120px}[dir=rtl] devsite-book-nav .devsite-expandable-nav li li li li li .devsite-nav-heading:not(.devsite-nav-divider) .devsite-nav-title-no-path{padding-right:120px}[dir=ltr] devsite-book-nav .devsite-nav-accordion>.devsite-expandable-nav>.devsite-nav-title-no-path{margin-right:0}[dir=rtl] devsite-book-nav .devsite-nav-accordion>.devsite-expandable-nav>.devsite-nav-title-no-path{margin-left:0}devsite-book-nav .devsite-nav-heading.devsite-nav-divider{background:var(--devsite-nav-divider-background);border-bottom:var(--devsite-primary-border);border-top:var(--devsite-primary-border);padding:4px 24px 2px}devsite-book-nav .devsite-nav-heading.devsite-nav-divider:first-child{padding-top:4px}devsite-book-nav .devsite-nav-divider>.devsite-nav-title{font:500 11px/16px var(--devsite-primary-font-family);letter-spacing:.8px;text-transform:uppercase}devsite-book-nav .devsite-nav-accordion+.devsite-nav-accordion,devsite-book-nav .devsite-nav-divider+.devsite-nav-accordion{border-top:0;padding-top:12px}devsite-book-nav .devsite-nav-accordion+.devsite-nav-divider{border-top:0;padding-top:4px}devsite-book-nav .devsite-nav-item:not(.devsite-nav-accordion) .devsite-nav-heading>.devsite-nav-title-no-path{border-radius:0;cursor:default}devsite-book-nav .devsite-nav-item:not(.devsite-nav-accordion) .devsite-nav-heading>.devsite-nav-title-no-path:focus,devsite-book-nav .devsite-nav-item:not(.devsite-nav-accordion) .devsite-nav-heading>.devsite-nav-title-no-path:hover{background:0}devsite-book-nav .devsite-nav-item.devsite-nav-deprecated:not(.devsite-nav-accordion) .devsite-nav-heading>.devsite-nav-title-no-path:focus,devsite-book-nav .devsite-nav-item.devsite-nav-deprecated:not(.devsite-nav-accordion) .devsite-nav-heading>.devsite-nav-title-no-path:hover{color:var(--devsite-nav-title-no-path-color-hover,var(--devsite-link-color))}devsite-book-nav .devsite-nav-accordion+.devsite-nav-item:not(.devsite-nav-accordion):not(.devsite-nav-divider),devsite-book-nav .devsite-nav-divider+.devsite-nav-item:not(.devsite-nav-accordion):not(.devsite-nav-divider),devsite-book-nav .devsite-nav-item:not(.devsite-nav-accordion):not(.devsite-nav-divider)+.devsite-nav-accordion,devsite-book-nav .devsite-nav-item:not(.devsite-nav-accordion):not(.devsite-nav-divider)+.devsite-nav-divider{margin-top:12px}devsite-book-nav .devsite-nav-break{height:24px}#devsite-hamburger-menu,devsite-book-nav .devsite-mobile-header,devsite-book-nav .devsite-mobile-nav-top{display:none}devsite-book-nav .devsite-mobile-header{background:var(--devsite-header-color-upper,var(--devsite-background-1));border-bottom:var(--devsite-header-border,var(--devsite-primary-border))}#devsite-hamburger-menu:before,devsite-book-nav #devsite-close-nav:before{border-radius:50%;padding:8px;-webkit-transition:background .2s;transition:background .2s}#devsite-hamburger-menu:focus:before,#devsite-hamburger-menu:hover:before,devsite-book-nav #devsite-close-nav:focus:before,devsite-book-nav #devsite-close-nav:hover:before{background:var(--devsite-background-3)}#devsite-hamburger-menu:before{content:"menu"}[dir=ltr] devsite-book-nav #devsite-close-nav:before{content:"arrow_back"}[dir=rtl] devsite-book-nav #devsite-close-nav:before{content:"arrow_forward"}devsite-book-nav[top-level-nav] #devsite-close-nav:before{content:"close"}.devsite-book-nav-toggle{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;background-color:var(--devsite-book-nav-toggle-background);border:var(--devsite-book-nav-toggle-border,0);bottom:16px;box-shadow:var(--devsite-book-nav-toggle-box-shadow,0 1px 2px 0 var(--devsite-elevation-key-shadow-color),0 2px 6px 2px var(--devsite-elevation-ambient-shadow-color));color:var(--devsite-book-nav-toggle-color,var(--devsite-secondary-text-color));cursor:pointer;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;height:40px;-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;-ms-flex-pack:center;justify-content:center;min-width:24px;padding:0;position:fixed;text-decoration:none;-webkit-transform:translateX(calc(var(--devsite-js-book-nav-scrollbar-width, 0px) - var(--devsite-nav-title-margin-x, 8px)));transform:translateX(calc(var(--devsite-js-book-nav-scrollbar-width, 0px) - var(--devsite-nav-title-margin-x, 8px)));-webkit-transition:border-radius .2s ease,-webkit-transform .2s cubic-bezier(.4,0,.2,1);transition:border-radius .2s ease,-webkit-transform .2s cubic-bezier(.4,0,.2,1);transition:transform .2s cubic-bezier(.4,0,.2,1),border-radius .2s ease;transition:transform .2s cubic-bezier(.4,0,.2,1),border-radius .2s ease,-webkit-transform .2s cubic-bezier(.4,0,.2,1);z-index:1004}.devsite-book-nav-toggle:focus,.devsite-book-nav-toggle:hover{background-color:var(--devsite-book-nav-toggle-background-hover);border:var(--devsite-book-nav-toggle-border-hover,0);box-shadow:var(--devsite-book-nav-toggle-box-shadow-hover,0 1px 2px 0 var(--devsite-elevation-key-shadow-color),0 2px 6px 2px var(--devsite-elevation-ambient-shadow-color));color:var(--devsite-book-nav-toggle-color-hover,var(--devsite-secondary-text-color))}.devsite-book-nav-toggle[aria-expanded]{border-radius:50%;width:40px}[dir=ltr] .devsite-book-nav-toggle[aria-expanded]{-webkit-transform:translateX(calc(229px - var(--devsite-js-book-nav-scrollbar-width, 0px) - var(--devsite-nav-title-margin-x, 8px)));transform:translateX(calc(229px - var(--devsite-js-book-nav-scrollbar-width, 0px) - var(--devsite-nav-title-margin-x, 8px)))}[dir=rtl] .devsite-book-nav-toggle[aria-expanded]{-webkit-transform:translateX(calc(-229px + var(--devsite-js-book-nav-scrollbar-width, 0px) + var(--devsite-nav-title-margin-x, 8px)));transform:translateX(calc(-229px + var(--devsite-js-book-nav-scrollbar-width, 0px) + var(--devsite-nav-title-margin-x, 8px)))}.devsite-book-nav-toggle:not([aria-expanded]){-webkit-border-start:0;-moz-border-start:0;border-inline-start:0;-webkit-transition:width .2s ease,border-radius .2s ease,-webkit-transform .15s cubic-bezier(.4,0,.2,1);transition:width .2s ease,border-radius .2s ease,-webkit-transform .15s cubic-bezier(.4,0,.2,1);transition:width .2s ease,transform .15s cubic-bezier(.4,0,.2,1),border-radius .2s ease;transition:width .2s ease,transform .15s cubic-bezier(.4,0,.2,1),border-radius .2s ease,-webkit-transform .15s cubic-bezier(.4,0,.2,1);width:24px}[dir=ltr] .devsite-book-nav-toggle:not([aria-expanded]){border-radius:0 20px 20px 0}[dir=rtl] .devsite-book-nav-toggle:not([aria-expanded]){border-radius:20px 0 0 20px}.devsite-book-nav-toggle:not([aria-expanded]):focus,.devsite-book-nav-toggle:not([aria-expanded]):hover{width:40px}[dir=ltr] body[ready] .devsite-book-nav-bg[collapsed]{-webkit-transform:translate(-279px);transform:translate(-279px)}[dir=rtl] body[ready] .devsite-book-nav-bg[collapsed]{-webkit-transform:translate(279px);transform:translate(279px)}[dir=ltr] body[ready] devsite-book-nav[collapsed]{-webkit-transform:translate(-279px,var(--devsite-js-book-nav-y-offset,0));transform:translate(-279px,var(--devsite-js-book-nav-y-offset,0))}[dir=rtl] body[ready] devsite-book-nav[collapsed]{-webkit-transform:translate(279px,var(--devsite-js-book-nav-y-offset,0));transform:translate(279px,var(--devsite-js-book-nav-y-offset,0))}.devsite-book-nav-toggle .devsite-book-nav-toggle-icon{font-size:20px;height:20px;position:static;width:20px}.devsite-book-nav-toggle .devsite-book-nav-toggle-icon:before{content:var(--devsite-book-nav-toggle-icon)}[dir=ltr] .devsite-book-nav-toggle,[dir=rtl] .devsite-book-nav-toggle[aria-expanded]{--devsite-book-nav-toggle-icon:"chevron_right"}[dir=ltr] .devsite-book-nav-toggle[aria-expanded],[dir=rtl] .devsite-book-nav-toggle{--devsite-book-nav-toggle-icon:"chevron_left"}devsite-book-nav~.devsite-book-nav-blur{background-color:var(--devsite-book-nav-background);bottom:0;height:64px;-webkit-mask-image:-webkit-linear-gradient(transparent,#000 28px);mask-image:linear-gradient(transparent,#000 28px);pointer-events:none;position:fixed;width:calc(269px - var(--devsite-js-book-nav-scrollbar-width, 0px));z-index:1004;-webkit-transition:-webkit-transform .2s cubic-bezier(.4,0,.2,1);transition:-webkit-transform .2s cubic-bezier(.4,0,.2,1);transition:transform .2s cubic-bezier(.4,0,.2,1);transition:transform .2s cubic-bezier(.4,0,.2,1),-webkit-transform .2s cubic-bezier(.4,0,.2,1);-webkit-transform:translate(0);transform:translate(0)}[dir=ltr] devsite-book-nav~.devsite-book-nav-blur{left:0}[dir=rtl] devsite-book-nav~.devsite-book-nav-blur{right:0}[dir=ltr] devsite-book-nav~.devsite-book-nav-blur[collapsed]{left:0;-webkit-transform:translate(-281px,var(--devsite-js-book-nav-y-offset,0));transform:translate(-281px,var(--devsite-js-book-nav-y-offset,0))}[dir=rtl] devsite-book-nav~.devsite-book-nav-blur[collapsed]{right:0;-webkit-transform:translate(281px,var(--devsite-js-book-nav-y-offset,0));transform:translate(281px,var(--devsite-js-book-nav-y-offset,0))}@media screen and (max-width:840px){devsite-book-nav{display:none;height:100vh;max-height:100vh!important;top:0!important;z-index:1013}body[ready] .devsite-book-nav-bg,body[ready] devsite-book-nav{-webkit-transition:-webkit-transform .2s cubic-bezier(.4,0,.2,1);transition:-webkit-transform .2s cubic-bezier(.4,0,.2,1);transition:transform .2s cubic-bezier(.4,0,.2,1);transition:transform .2s cubic-bezier(.4,0,.2,1),-webkit-transform .2s cubic-bezier(.4,0,.2,1)}[dir=ltr] body[ready] devsite-book-nav{-webkit-transform:translate(-281px);transform:translate(-281px)}[dir=rtl] body[ready] devsite-book-nav{-webkit-transform:translate(281px);transform:translate(281px)}.devsite-book-nav-blur{display:none}body[ready] .devsite-book-nav-bg[fixed]{display:none}body[ready] devsite-book-nav[fixed]{background:var(--devsite-book-nav-background);display:block!important;box-shadow:0 1px 2px 0 var(--devsite-elevation-key-shadow-color),0 2px 6px 2px var(--devsite-elevation-ambient-shadow-color)}devsite-book-nav[visually-hidden]{opacity:1!important;pointer-events:auto!important;visibility:visible!important}#devsite-hamburger-menu,devsite-book-nav #devsite-close-nav{height:100%;position:relative;width:auto;z-index:20}#devsite-hamburger-menu{display:block;width:40px}[dir=ltr] #devsite-hamburger-menu{margin:0 0 0 -4px}[dir=rtl] #devsite-hamburger-menu{margin:0 -4px 0 0}devsite-book-nav #devsite-close-nav{color:var(--devsite-secondary-text-color);-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0}[dir=ltr] devsite-book-nav #devsite-close-nav{margin:0 0 0 -12px}[dir=rtl] devsite-book-nav #devsite-close-nav{margin:0 -12px 0 0}devsite-book-nav .devsite-mobile-nav-top{display:block}devsite-book-nav .devsite-book-nav-wrapper{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-transition:-webkit-transform .2s cubic-bezier(.4,0,.2,1);transition:-webkit-transform .2s cubic-bezier(.4,0,.2,1);transition:transform .2s cubic-bezier(.4,0,.2,1);transition:transform .2s cubic-bezier(.4,0,.2,1),-webkit-transform .2s cubic-bezier(.4,0,.2,1)}[dir=ltr] devsite-book-nav .devsite-book-nav-wrapper{-webkit-transform:translateX(-269px);transform:translateX(-269px)}[dir=rtl] devsite-book-nav .devsite-book-nav-wrapper{-webkit-transform:translateX(269px);transform:translateX(269px)}devsite-book-nav .devsite-nav-list{padding-bottom:120px}devsite-book-nav .devsite-nav-list>.devsite-nav-item:not(.devsite-nav-accordion):not(.devsite-nav-divider):first-child{margin-top:0}devsite-book-nav .devsite-mobile-nav-bottom .devsite-nav-list>.devsite-nav-item:not(.devsite-nav-accordion):not(.devsite-nav-divider):first-child{margin-top:13px}devsite-book-nav .devsite-mobile-nav-top .devsite-nav-text{-webkit-box-flex:1;-webkit-flex-grow:1;-moz-box-flex:1;-ms-flex-positive:1;flex-grow:1}devsite-book-nav[top-level-nav] .devsite-book-nav-wrapper{-webkit-transform:translateX(0);transform:translateX(0)}devsite-book-nav:not([top-level-nav]) .devsite-mobile-nav-top,devsite-book-nav[top-level-nav] .devsite-mobile-nav-bottom{height:calc(100vh - 64px);overflow:hidden}devsite-book-nav .devsite-mobile-nav-top>.devsite-nav-list>.devsite-nav-item{border-bottom:var(--devsite-primary-border)}devsite-book-nav .devsite-mobile-nav-top>.devsite-nav-list>.devsite-nav-item>.devsite-nav-title{font-weight:700;padding-bottom:15px;padding-top:16px}devsite-book-nav .devsite-mobile-nav-top>.devsite-nav-list>.devsite-nav-item>.devsite-nav-active{background:0}devsite-book-nav .devsite-mobile-nav-top>.devsite-nav-list>.devsite-nav-item>.devsite-nav-title:not(.devsite-nav-active){color:var(--devsite-secondary-text-color)}devsite-book-nav .devsite-mobile-nav-top>.devsite-nav-list>.devsite-nav-item:not(.devsite-nav-accordion):not(.devsite-nav-heading)>.devsite-nav-title{border-radius:0}devsite-book-nav .devsite-mobile-nav-top>.devsite-nav-list>.devsite-nav-item:not(.devsite-nav-accordion):not(.devsite-nav-heading)>.devsite-nav-title:focus,devsite-book-nav .devsite-mobile-nav-top>.devsite-nav-list>.devsite-nav-item:not(.devsite-nav-accordion):not(.devsite-nav-heading)>.devsite-nav-title:hover{background:0}devsite-book-nav .devsite-mobile-nav-bottom,devsite-book-nav .devsite-mobile-nav-top{-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;width:269px}devsite-book-nav .devsite-mobile-header{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;height:49px;padding:0 16px;position:-webkit-sticky;position:sticky;top:0;z-index:100}devsite-book-nav .devsite-mobile-header .devsite-nav-active{font-weight:400}devsite-book-nav .devsite-nav-responsive-tabs{margin-bottom:12px;margin-top:-11px}devsite-book-nav .devsite-lower-tab-item{margin:0}devsite-book-nav .devsite-nav-responsive-tabs>.devsite-nav-item:last-child{margin-bottom:8px}devsite-book-nav~.devsite-book-nav-toggle{display:none}devsite-book-nav .devsite-book-nav-filter{display:none}}@media screen and (max-width:600px){#devsite-hamburger-menu,devsite-book-nav #devsite-close-nav{margin:0 4px 0 -12px}}.devsite-expandable-nav{display:block;position:relative}.devsite-expandable-nav>.devsite-nav-section{max-width:100%;overflow-y:hidden;-webkit-transition:height .2s;transition:height .2s;width:100%;will-change:height}.devsite-expandable-nav:not([animatable])>.devsite-nav-section{-webkit-transition:height 1ms;transition:height 1ms}.devsite-expandable-nav>.devsite-nav-section .devsite-nav-heading:not(.devsite-nav-divider):first-child{margin-top:0}.devsite-expandable-nav:not(.expanded)>.devsite-nav-section{display:none}.devsite-expandable-nav:not(.expanded)>.devsite-nav-section{height:0}.devsite-expandable-nav>.devsite-nav-title-no-path{cursor:pointer;outline:0}.devsite-expandable-nav>.devsite-nav-title{-webkit-padding-start:24px;-moz-padding-start:24px;padding-inline-start:24px}.devsite-expandable-nav .devsite-expandable-nav>.devsite-nav-title{-webkit-padding-start:40px;-moz-padding-start:40px;padding-inline-start:40px}.devsite-expandable-nav .devsite-expandable-nav .devsite-expandable-nav>.devsite-nav-title{-webkit-padding-start:56px;-moz-padding-start:56px;padding-inline-start:56px}.devsite-expandable-nav .devsite-expandable-nav .devsite-expandable-nav .devsite-expandable-nav>.devsite-nav-title{-webkit-padding-start:72px;-moz-padding-start:72px;padding-inline-start:72px}.devsite-expandable-nav .devsite-expandable-nav .devsite-expandable-nav .devsite-expandable-nav .devsite-expandable-nav>.devsite-nav-title{-webkit-padding-start:88px;-moz-padding-start:88px;padding-inline-start:88px}.devsite-expandable-nav .devsite-expandable-nav .devsite-expandable-nav .devsite-expandable-nav .devsite-expandable-nav .devsite-expandable-nav>.devsite-nav-title{-webkit-padding-start:104px;-moz-padding-start:104px;padding-inline-start:104px}.devsite-expandable-nav .devsite-expandable-nav .devsite-expandable-nav .devsite-expandable-nav .devsite-expandable-nav .devsite-expandable-nav .devsite-expandable-nav>.devsite-nav-title{-webkit-padding-start:120px;-moz-padding-start:120px;padding-inline-start:120px}.devsite-expandable-nav>.devsite-nav-toggle{cursor:pointer;font:normal normal normal 24px/1 Material Icons;-webkit-font-feature-settings:"liga";-moz-font-feature-settings:"liga";font-feature-settings:"liga";-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;text-transform:none;word-wrap:normal;text-decoration:none}.devsite-nav-item:not(.devsite-nav-accordion)>.devsite-expandable-nav>.devsite-nav-toggle{font-size:18px;position:absolute;top:var(--devsite-nav-toggle-y-start,2px);-webkit-transform:rotate(0);transform:rotate(0);-webkit-transition:-webkit-transform .2s ease;transition:-webkit-transform .2s ease;transition:transform .2s ease;transition:transform .2s ease,-webkit-transform .2s ease;will-change:transform}.devsite-nav-item:not(.devsite-nav-accordion)>.devsite-expandable-nav:not([animatable])>.devsite-nav-toggle{-webkit-transition:-webkit-transform 1ms;transition:-webkit-transform 1ms;transition:transform 1ms;transition:transform 1ms,-webkit-transform 1ms}[dir=ltr] .devsite-expandable-nav>.devsite-nav-toggle{left:4px}[dir=rtl] .devsite-expandable-nav>.devsite-nav-toggle{right:4px}[dir=ltr] .devsite-expandable-nav .devsite-expandable-nav>.devsite-nav-toggle{left:20px}[dir=rtl] .devsite-expandable-nav .devsite-expandable-nav>.devsite-nav-toggle{right:20px}[dir=ltr] .devsite-expandable-nav .devsite-expandable-nav .devsite-expandable-nav>.devsite-nav-toggle{left:36px}[dir=rtl] .devsite-expandable-nav .devsite-expandable-nav .devsite-expandable-nav>.devsite-nav-toggle{right:36px}[dir=ltr] .devsite-expandable-nav .devsite-expandable-nav .devsite-expandable-nav .devsite-expandable-nav>.devsite-nav-toggle{left:52px}[dir=rtl] .devsite-expandable-nav .devsite-expandable-nav .devsite-expandable-nav .devsite-expandable-nav>.devsite-nav-toggle{right:52px}[dir=ltr] .devsite-expandable-nav .devsite-expandable-nav .devsite-expandable-nav .devsite-expandable-nav .devsite-expandable-nav>.devsite-nav-toggle{left:68px}[dir=rtl] .devsite-expandable-nav .devsite-expandable-nav .devsite-expandable-nav .devsite-expandable-nav .devsite-expandable-nav>.devsite-nav-toggle{right:68px}[dir=ltr] .devsite-expandable-nav .devsite-expandable-nav .devsite-expandable-nav .devsite-expandable-nav .devsite-expandable-nav .devsite-expandable-nav>.devsite-nav-toggle{left:84px}[dir=rtl] .devsite-expandable-nav .devsite-expandable-nav .devsite-expandable-nav .devsite-expandable-nav .devsite-expandable-nav .devsite-expandable-nav>.devsite-nav-toggle{right:84px}[dir=ltr] .devsite-expandable-nav .devsite-expandable-nav .devsite-expandable-nav .devsite-expandable-nav .devsite-expandable-nav .devsite-expandable-nav .devsite-expandable-nav>.devsite-nav-toggle{left:100px}[dir=rtl] .devsite-expandable-nav .devsite-expandable-nav .devsite-expandable-nav .devsite-expandable-nav .devsite-expandable-nav .devsite-expandable-nav .devsite-expandable-nav>.devsite-nav-toggle{right:100px}.devsite-nav-item:not(.devsite-nav-accordion)>.devsite-expandable-nav:not(.expanded)>.devsite-nav-toggle{-webkit-transform:rotate(-90deg);transform:rotate(-90deg)}[dir=rtl] .devsite-nav-item:not(.devsite-nav-accordion)>.devsite-expandable-nav:not(.expanded)>.devsite-nav-toggle{-webkit-transform:rotate(90deg);transform:rotate(90deg)}.devsite-expandable-nav>.devsite-nav-toggle:before{content:"arrow_drop_down"}.devsite-nav-accordion{border-bottom:var(--devsite-primary-border);border-top:var(--devsite-primary-border);padding:11px 0}.devsite-nav-accordion>.devsite-expandable-nav{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}.devsite-nav-accordion>.devsite-expandable-nav>.devsite-nav-title{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;color:var(--devsite-secondary-text-rgba);display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-flex:1;-webkit-flex:1 0 196px;-moz-box-flex:1;-ms-flex:1 0 196px;flex:1 0 196px;font-weight:700;overflow:hidden}.devsite-nav-accordion>.devsite-expandable-nav>.devsite-nav-toggle{color:var(--devsite-secondary-text-color);font-size:24px;margin-block:0;margin-inline:0 8px;-webkit-box-ordinal-group:2;-webkit-order:1;-moz-box-ordinal-group:2;-ms-flex-order:1;order:1;-webkit-transform:rotateX(0deg);transform:rotateX(0deg);-webkit-transition:-webkit-transform .5s;transition:-webkit-transform .5s;transition:transform .5s;transition:transform .5s,-webkit-transform .5s}.devsite-nav-accordion>.devsite-expandable-nav:not([animatable])>.devsite-nav-toggle{-webkit-transition:-webkit-transform 1ms;transition:-webkit-transform 1ms;transition:transform 1ms;transition:transform 1ms,-webkit-transform 1ms}.devsite-nav-accordion>.devsite-expandable-nav:not(.expanded)>.devsite-nav-toggle{-webkit-transform:rotateX(180deg);transform:rotateX(180deg)}.devsite-nav-accordion>.devsite-expandable-nav>.devsite-nav-toggle:before{content:"expand_less"}.devsite-nav-accordion>.devsite-expandable-nav>.devsite-nav-section{-webkit-box-ordinal-group:3;-webkit-order:2;-moz-box-ordinal-group:3;-ms-flex-order:2;order:2}devsite-book-nav .devsite-product-id-row{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-webkit-justify-content:space-between;-moz-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;min-height:60px;padding:var(--devsite-product-id-row-padding,20px 24px 2px)}devsite-book-nav .devsite-header-no-lower-tabs .devsite-product-id-row{min-height:72px;padding:var(--devsite-product-id-row-padding,20px 24px)}devsite-book-nav .devsite-product-description-row{color:var(--devsite-header-foreground-lower-description,var(--devsite-header-foreground-lower-hover,var(--devsite-inverted-text-color)));font:var(--devsite-header-lower-description-font,400 20px/32px var(--devsite-primary-font-family))}devsite-book-nav .devsite-product-description{font:16px/24px var(--devsite-primary-font-family);margin-block:0;margin-inline:0 180px}devsite-book-nav .devsite-breadcrumb-list+.devsite-product-description{margin-block:8px 0}devsite-book-nav .devsite-product-button-row{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;margin-block:0;margin-inline:24px 0;z-index:1}@media screen and (max-width:840px){devsite-book-nav .devsite-product-id-row{min-height:72px;padding:var(--devsite-product-id-row-padding,20px 24px)}devsite-book-nav .devsite-product-description{margin-inline:0}}@media screen and (max-width:600px){devsite-book-nav .devsite-header-no-lower-tabs .devsite-product-id-row,devsite-book-nav .devsite-product-id-row{-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;padding:var(--devsite-product-id-row-padding,20px 16px)}devsite-book-nav .devsite-product-button-row{-webkit-flex-basis:100%;-ms-flex-preferred-size:100%;flex-basis:100%;margin-block:16px 0;margin-inline:0}}devsite-book-nav .devsite-product-name-wrapper{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-flex:0;-webkit-flex:0 0 auto;-moz-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;height:36px;margin:6px 0}devsite-book-nav .devsite-product-name-link,devsite-book-nav .devsite-site-logo-link{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;opacity:1;-webkit-transition:opacity .2s;transition:opacity .2s}devsite-book-nav .devsite-product-name-link:focus,devsite-book-nav .devsite-product-name-link:hover,devsite-book-nav .devsite-site-logo-link:focus{opacity:.7;text-decoration:none}devsite-book-nav .devsite-site-logo{height:var(--devsite-logo-height,32px)}devsite-book-nav .devsite-has-google-wordmark>.devsite-breadcrumb-link,devsite-book-nav .devsite-has-google-wordmark>.devsite-product-name{direction:ltr}devsite-book-nav .devsite-google-wordmark{height:24px;margin:0 4px 0 0;position:relative;top:5px}devsite-book-nav .devsite-google-wordmark-svg-path{-webkit-transition:fill .2s;transition:fill .2s}devsite-book-nav .devsite-site-logo-link canvas{height:auto!important}devsite-book-nav .devsite-site-logo-link picture{display:contents}devsite-book-nav .devsite-product-logo-container{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;border-radius:50%;color:var(--devsite-primary-color,var(--devsite-primary-text-color));display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;height:36px;-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;-ms-flex-pack:center;justify-content:center;margin-inline:0 4px;width:36px}devsite-book-nav .devsite-product-logo-container[background]{background:var(--devsite-primary-color,var(--devsite-primary-text-color));color:var(--devsite-inverted-text-color)}devsite-book-nav .devsite-product-logo{color:inherit;font-size:32px;height:32px;max-width:32px;min-width:32px;overflow:hidden;white-space:nowrap}devsite-book-nav .devsite-product-logo-container[background] .devsite-product-logo{font-size:28px;height:28px;max-width:28px;min-width:28px}devsite-book-nav .devsite-product-name{font:var(--devsite-wordmark-font,400 20px/32px var(--devsite-primary-font-family));letter-spacing:0;margin:0;max-height:32px;overflow:hidden;text-overflow:ellipsis;-webkit-transition:color .2s;transition:color .2s;white-space:nowrap}devsite-book-nav .devsite-site-logo:not([src*=".svg"]){height:auto;max-height:32px}devsite-book-nav .devsite-breadcrumb-link>.devsite-product-name{color:inherit}@media screen and (max-width:840px){devsite-book-nav .devsite-product-name-wrapper{-webkit-box-flex:0;-webkit-flex:0 1 auto;-moz-box-flex:0;-ms-flex:0 1 auto;flex:0 1 auto;min-width:0}devsite-book-nav .devsite-product-name-wrapper .devsite-breadcrumb-item:not(:first-of-type),devsite-book-nav .devsite-product-name-wrapper .devsite-site-logo-link+.devsite-product-name{display:none}devsite-book-nav .devsite-product-name-wrapper .devsite-breadcrumb-item,devsite-book-nav .devsite-product-name-wrapper .devsite-breadcrumb-link,devsite-book-nav .devsite-product-name-wrapper .devsite-breadcrumb-list,devsite-book-nav .devsite-product-name-wrapper .devsite-product-name{width:100%}devsite-book-nav .devsite-product-name-wrapper .devsite-breadcrumb-link{overflow:hidden;text-overflow:ellipsis}}devsite-bookmark.show{display:-webkit-inline-box;display:-webkit-inline-flex;display:-moz-inline-box;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;background:var(--devsite-bookmark-background);border:0;box-shadow:none;cursor:pointer;height:36px;-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;-ms-flex-pack:center;justify-content:center;margin:0;min-width:66px;padding:0;vertical-align:middle;width:66px}devsite-bookmark.show.devsite-legacy-bookmark{border-radius:18px;min-width:36px;width:36px}devsite-bookmark.show.devsite-legacy-bookmark:focus,devsite-bookmark.show.devsite-legacy-bookmark:hover{background:var(--devsite-bookmark-background-hover-legacy)}devsite-bookmark.show.devsite-page-bookmark,devsite-feature-tooltip.devsite-page-bookmark-tooltip{-webkit-margin-end:8px;-moz-margin-end:8px;margin-inline-end:8px;-webkit-margin-start:-74px;-moz-margin-start:-74px;margin-inline-start:-74px}devsite-bookmark input.bookmark-checkbox{background:var(--devsite-bookmark-background);color:var(--devsite-bookmark-icon-color);margin:0}devsite-bookmark devsite-dropdown-list{--devsite-button-box-shadow:none}devsite-bookmark devsite-dropdown-list .bookmark-icon{color:var(--devsite-bookmark-icon-color);-webkit-transition:color .2s;transition:color .2s}devsite-bookmark devsite-dropdown-list:where(:hover,:focus,:active) .bookmark-icon{color:var(--devsite-dropdown-list-toggle-color-hover)}devsite-bookmark devsite-dropdown-list .bookmark-icon.toggled{color:var(--devsite-bookmark-icon-color-saved)}devsite-bookmark devsite-dropdown-list:where(:hover,:focus,:active) .bookmark-icon.toggled{color:var(--devsite-bookmark-icon-color-saved-hover)}devsite-bookmark input.bookmark-checkbox:after{content:"bookmark_border"}devsite-bookmark input.bookmark-checkbox:checked:after{content:"bookmark"}devsite-bookmark input.bookmark-checkbox:checked:focus:before,devsite-bookmark input.bookmark-checkbox:focus:before{background:var(--devsite-bookmark-background-focus-legacy)}devsite-bookmark input.bookmark-checkbox:checked,devsite-bookmark[saved] input.bookmark-checkbox,devsite-bookmark[saved] input.bookmark-checkbox:checked{color:var(--devsite-bookmark-icon-color-saved)}.devsite-bookmark-dialog .create-profile-spinner{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;background:hsla(0,0%,100%,.8);bottom:0;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;-ms-flex-pack:center;justify-content:center;left:0;opacity:0;pointer-events:none;position:absolute;right:0;top:0;-webkit-transition:opacity .3s cubic-bezier(.4,0,.2,1);transition:opacity .3s cubic-bezier(.4,0,.2,1);z-index:10}.devsite-bookmark-dialog.loading .create-profile-spinner{opacity:1}.devsite-receive-updates-dialog{padding:24px}.devsite-receive-updates-dialog .devsite-dialog-contents{padding:0}.devsite-receive-updates-dialog .no-link{text-align:left}.devsite-receive-updates-dialog .devsite-dialog-buttons{-webkit-box-pack:left;-webkit-justify-content:left;-moz-box-pack:left;-ms-flex-pack:left;justify-content:left;padding:0}.devsite-receive-updates-dialog .devsite-dialog-buttons .devsite-dialog-close{-webkit-margin-start:16px;-moz-margin-start:16px;margin-inline-start:16px}devsite-carousel>:where(ul,ol,[role=list]){display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;gap:var(--devsite-carousel-item-gap);list-style:none;padding:0}devsite-carousel:not(:defined) :where(ul,ol,[role=list]){display:none}devsite-carousel>:where(ul,ol,[role=list])>:where(li,[role=listitem]){-webkit-box-align:start;-webkit-align-items:start;-moz-box-align:start;-ms-flex-align:start;align-items:start;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-box-flex:var(--devsite-carousel-item-flex);-webkit-flex:var(--devsite-carousel-item-flex);-moz-box-flex:var(--devsite-carousel-item-flex);-ms-flex:var(--devsite-carousel-item-flex);flex:var(--devsite-carousel-item-flex);margin:0;scroll-snap-align:start}devsite-carousel[data-items-per-slide=auto]>:is(ul,ol,[role=list])>:is(li,[role=listitem]):last-child:empty{border:0;padding:0;padding-block:0;padding-inline:0;visibility:hidden;width:var(--devsite-carousel-ghost-item-width)}devsite-catalog{display:block;margin:20px 0;width:100%}devsite-catalog>*{display:none}devsite-catalog>.catalog-container{-webkit-box-align:start;-webkit-align-items:start;-moz-box-align:start;-ms-flex-align:start;align-items:start;display:grid;gap:30px;grid:var(--devsite-catalog-grid)}devsite-catalog .catalog-sidebar{grid-area:sidebar}devsite-catalog .catalog-main{grid-area:main}devsite-catalog .catalog-checkbox-controls-container,devsite-catalog .catalog-checkbox-controls-group,devsite-catalog .catalog-main-filter-controls{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex}devsite-catalog .catalog-checkbox-controls-container,devsite-catalog .catalog-checkbox-controls-group{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-moz-box-orient:vertical;-moz-box-direction:normal;-ms-flex-direction:column;flex-direction:column}devsite-catalog .catalog-checkbox-controls-group,devsite-catalog .catalog-checkbox-controls-subtitle,devsite-catalog .catalog-checkbox-controls-title,devsite-catalog .catalog-checkbox-label,devsite-catalog .catalog-filter-bar{text-align:var(--devsite-catalog-text-align,start);width:100%}devsite-catalog .catalog-checkbox-controls-container{border:var(--devsite-primary-border);border-radius:var(--devsite-card-border-radius);color:var(--devsite-secondary-text-color)}devsite-catalog .catalog-filter-chips{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;gap:var(--devsite-chips-gap)}devsite-catalog .catalog-checkbox-controls-filter-chips-container{display:none}devsite-catalog .catalog-main-filter-chips>:only-child{margin-bottom:24px}devsite-catalog .catalog-main-filter-chips>div{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;gap:16px 8px}devsite-catalog .catalog-main-filter-chips>div:empty{display:none}devsite-catalog .catalog-filter-chip{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;border-radius:16px;display:-webkit-inline-box;display:-webkit-inline-flex;display:-moz-inline-box;display:-ms-inline-flexbox;display:inline-flex;height:32px}devsite-catalog .catalog-filter-chip:after{font:normal normal normal 24px/1 Material Icons;-webkit-font-feature-settings:"liga";-moz-font-feature-settings:"liga";font-feature-settings:"liga";-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;text-transform:none;word-wrap:normal;-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;content:var(--devsite-button-icon-content);display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;font-size:18px;height:18px;-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-margin-end:var(--devsite-button-icon-margin-x-end);-moz-margin-end:var(--devsite-button-icon-margin-x-end);margin-inline-end:var(--devsite-button-icon-margin-x-end);-webkit-margin-start:var(--devsite-button-icon-margin-x-start);-moz-margin-start:var(--devsite-button-icon-margin-x-start);margin-inline-start:var(--devsite-button-icon-margin-x-start);width:18px}devsite-catalog .catalog-checkbox-controls-group{-webkit-box-align:start;-webkit-align-items:flex-start;-moz-box-align:start;-ms-flex-align:start;align-items:flex-start;padding:0 20px 20px}devsite-catalog .catalog-container .catalog-clear-group-checkboxes-button,devsite-catalog .catalog-container .catalog-select-group-checkboxes-button{-webkit-margin-start:-8px;-moz-margin-start:-8px;margin-inline-start:-8px}devsite-catalog .catalog-checkbox-controls-group>devsite-pagination{margin:0}devsite-catalog .catalog-checkbox-controls-group>devsite-pagination .button{border:0;-webkit-margin-start:-10px;-moz-margin-start:-10px;margin-inline-start:-10px}devsite-catalog .catalog-checkbox-controls-buttons-container{display:none}devsite-catalog .catalog-checkbox-controls-title{border-bottom:var(--devsite-primary-border);color:var(--devsite-catalog-title-color);font:var(--devsite-catalog-title-font,500 13px/20px var(--devsite-primary-font-family));letter-spacing:var(--devsite-catalog-title-letter-spacing,1.5px);margin:var(--devsite-catalog-title-margin,0 0 20px);padding:var(--devsite-catalog-title-padding,15px 20px 11px);text-transform:var(--devsite-catalog-title-text-transform,uppercase)}devsite-catalog .catalog-checkbox-controls-subtitle{color:var(--devsite-primary-text-color);font:var(--devsite-catalog-subtitle-font,16px/24px var(--devsite-headline-font-family));padding:var(--devsite-catalog-subtitle-padding)}devsite-catalog .catalog-checkbox-container{margin:6px 0}devsite-catalog .catalog-checkbox-label{color:var(--devsite-catalog-label-color,--devsite-secondary-text-color);font:var(--devsite-catalog-label-font,500 14px/20px var(--devsite-primary-font-family))}devsite-catalog .catalog-main-filter-controls{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;gap:24px;-webkit-box-pack:start;-webkit-justify-content:flex-start;-moz-box-pack:start;-ms-flex-pack:start;justify-content:flex-start}devsite-catalog .catalog-filter-bar-container{-webkit-box-flex:1;-webkit-flex:1;-moz-box-flex:1;-ms-flex:1;flex:1;position:relative;width:100%}devsite-catalog .catalog-filter-bar-container:before{font:normal normal normal 24px/1 Material Icons;-webkit-font-feature-settings:"liga";-moz-font-feature-settings:"liga";font-feature-settings:"liga";-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;text-transform:none;word-wrap:normal;color:var(--devsite-catalog-filter-bar-container-color);content:var(--devsite-catalog-filter-bar-container-content);position:var(--devsite-catalog-filter-bar-container-position);top:var(--devsite-catalog-filter-bar-container-top)}[dir=ltr] devsite-catalog .catalog-filter-bar-container:before{left:var(--devsite-catalog-filter-bar-container-x-start)}[dir=rtl] devsite-catalog .catalog-filter-bar-container:before{right:var(--devsite-catalog-filter-bar-container-x-start)}devsite-catalog .catalog-filter-bar{margin:0 0 24px;max-width:var(--devsite-catalog-filter-bar-max-width,725px);min-width:150px}devsite-catalog .catalog-show-sidebar-button{display:var(--devsite-catalog-sidebar-button-display);margin:var(--devsite-catalog-sidebar-button-margin,0)}devsite-catalog .catalog-filter-bar-container+.catalog-show-sidebar-button{margin:4px 0 auto}devsite-catalog devsite-pagination{margin-top:20px}devsite-catalog devsite-dynamic-content .devsite-dynamic-content-no-results{border:0;padding:0;width:auto}devsite-catalog devsite-dynamic-content .devsite-dynamic-content-no-results-image{width:425px}@media screen and (max-width:1253px){devsite-catalog .catalog-sidebar{border-radius:var(--devsite-catalog-sidebar-border-radius);box-shadow:var(--devsite-card-box-shadow);height:calc(100vh - var(--devsite-js-header-height, 0) - 4px);margin-block:calc(var(--devsite-js-header-height, 0) + 4px) 0;-webkit-margin-end:0;-moz-margin-end:0;margin-inline-end:0;position:fixed;top:0;-webkit-transition:width .2s;transition:width .2s;visibility:hidden;width:0;z-index:1007}[dir=ltr] devsite-catalog .catalog-sidebar{right:0}[dir=rtl] devsite-catalog .catalog-sidebar{left:0}devsite-catalog .catalog-sidebar[expanded]{max-width:90%;visibility:visible;width:340px}devsite-catalog .catalog-sidebar:before{background-color:rgba(0,0,0,.4);bottom:0;content:"";left:0;margin:-200px;opacity:0;pointer-events:none;position:fixed;right:0;-webkit-tap-highlight-color:transparent;top:0;-webkit-transition:opacity .2s cubic-bezier(.4,0,.2,1),visibility .2s linear;transition:opacity .2s cubic-bezier(.4,0,.2,1),visibility .2s linear;visibility:hidden;z-index:-1}devsite-catalog .catalog-sidebar[expanded]:before{content:"";cursor:pointer;opacity:1;pointer-events:auto;-webkit-transition:opacity .2s ease;transition:opacity .2s ease;visibility:visible}devsite-catalog .catalog-checkbox-controls-title{margin-bottom:10px}devsite-catalog .catalog-checkbox-controls-buttons-container{border-top:var(--devsite-primary-border);display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-pack:end;-webkit-justify-content:flex-end;-moz-box-pack:end;-ms-flex-pack:end;justify-content:flex-end;margin-top:auto;padding:16px 20px}devsite-catalog .catalog-checkbox-controls-container{background:var(--devsite-card-background,var(--devsite-background-1));height:100%;overflow-y:scroll}devsite-catalog .catalog-checkbox-controls-filter-chips-container{display:block;margin-block:0 2px;margin-inline:16px 12px}devsite-catalog .catalog-main{width:100%}}devsite-catalog-body-badges .loading{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;-ms-flex-pack:center;justify-content:center;padding:36px 0}devsite-catalog-body-badges p{margin:0}devsite-catalog-body-badges .no-results{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;-ms-flex-pack:center;justify-content:center;padding:64px 0;gap:8px;opacity:.5}devsite-catalog-body-badges .profile-cards-grid{display:grid;grid-template-columns:1fr 1fr 1fr;grid-gap:22px}devsite-catalog-body-badges .profile-cards-controls{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;-ms-flex-pack:center;justify-content:center;gap:8px;margin-top:20px}@media screen and (max-width:1253px){devsite-catalog-body-badges .profile-cards-grid{grid-template-columns:1fr 1fr}}@media screen and (max-width:600px){devsite-catalog-body-badges .profile-cards-grid{grid-template-columns:1fr}}devsite-catalog-body-badges .transparent{opacity:0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}devsite-catalog-body-badges .profile-card{border-radius:8px;border:var(--devsite-primary-border);padding:32px 16px;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-moz-box-orient:vertical;-moz-box-direction:normal;-ms-flex-direction:column;flex-direction:column;-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;text-align:center}devsite-catalog-body-badges .profile-card-image,devsite-catalog-body-badges .profile-card-image-placeholder{width:118px;height:118px;min-width:118px;min-height:118px;border-radius:118px}devsite-catalog-body-badges .profile-card-image-placeholder{background:var(--devsite-background-5)}devsite-catalog-body-badges .profile-card-name{font-family:var(--devsite-headline-font-family);font-size:24px;line-height:32px;color:var(--devsite-secondary-color);margin-top:20px}devsite-catalog-body-badges .profile-card-details,devsite-catalog-body-badges .profile-card-location{font-family:var(--devsite-primary-font-family);font-size:16px;line-height:24px}devsite-catalog-body-badges .profile-card-location{color:#3c4043;margin-top:8px}devsite-catalog-body-badges .profile-card-details{color:var(--devsite-secondary-color);margin-top:8px;-webkit-box-flex:1;-webkit-flex-grow:1;-moz-box-flex:1;-ms-flex-positive:1;flex-grow:1}devsite-catalog-body-badges .profile-card-button{margin-top:20px}devsite-checkbox:not([ready]){background:0;visibility:hidden}devsite-checkbox[ready]{visibility:visible}devsite-code{border:var(--devsite-code-border,0);border-radius:var(--devsite-code-border-radius,0);clear:both;direction:ltr!important;display:block;margin:var(--devsite-code-margin,16px 0);overflow:hidden;position:relative}devsite-code .devsite-code-buttons-container{position:absolute;right:var(--devsite-code-buttons-container-right,0);top:0;z-index:1}devsite-code .devsite-code-buttons-container button{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;background:0;border:0;border-radius:0;box-shadow:none;color:#202124;display:-webkit-inline-box;display:-webkit-inline-flex;display:-moz-inline-box;display:-ms-inline-flexbox;display:inline-flex;font-size:18px;height:var(--devsite-code-button-size,24px);-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;-ms-flex-pack:center;justify-content:center;margin:0;min-width:auto;padding:0;-webkit-transition:color .2s;transition:color .2s;width:var(--devsite-code-button-size,24px)}devsite-code .devsite-code-buttons-container button:focus,devsite-code .devsite-code-buttons-container button:hover{color:#5f6368}devsite-code .devsite-code-buttons-container button.material-icons,devsite-code .devsite-code-buttons-container button.material-icons:hover{cursor:pointer}devsite-code .devsite-code-buttons-container button{color:var(--devsite-code-buttons-color)}devsite-code .devsite-code-buttons-container button:focus,devsite-code .devsite-code-buttons-container button:hover{color:var(--devsite-code-buttons-hover)}devsite-code .devsite-code-buttons-container .devsite-toggle-dark{display:var(--devsite-code-buttons-toggle-dark-display)}devsite-code .devsite-code-buttons-container .devsite-toggle-light{display:var(--devsite-code-buttons-toggle-light-display)}devsite-code pre{margin:0;padding-block:var(--devsite-code-padding-block,24px);padding-inline:var(--devsite-code-padding-inline,24px)}devsite-code pre::-webkit-scrollbar-thumb{background:var(--devsite-scrollbar-thumb-background)}devsite-code pre .com,devsite-code pre .devsite-syntax-c,devsite-code pre .devsite-syntax-c1,devsite-code pre .devsite-syntax-ch,devsite-code pre .devsite-syntax-cm,devsite-code pre .devsite-syntax-cp,devsite-code pre .devsite-syntax-cpf,devsite-code pre .devsite-syntax-cs{color:var(--devsite-code-comments-color)}devsite-code pre .dec,devsite-code pre .devsite-syntax-il,devsite-code pre .devsite-syntax-m,devsite-code pre .devsite-syntax-mb,devsite-code pre .devsite-syntax-mf,devsite-code pre .devsite-syntax-mh,devsite-code pre .devsite-syntax-mi,devsite-code pre .devsite-syntax-mo,devsite-code pre .lit{color:var(--devsite-code-numbers-color)}devsite-code pre .devsite-syntax-k,devsite-code pre .devsite-syntax-kc,devsite-code pre .devsite-syntax-kd,devsite-code pre .devsite-syntax-kn,devsite-code pre .devsite-syntax-kp,devsite-code pre .devsite-syntax-kr,devsite-code pre .devsite-syntax-kt,devsite-code pre .devsite-syntax-nt,devsite-code pre .devsite-syntax-ow,devsite-code pre .kwd,devsite-code pre .tag{color:var(--devsite-code-keywords-color)}devsite-code pre .atv,devsite-code pre .cpf,devsite-code pre .devsite-syntax-dl,devsite-code pre .devsite-syntax-s,devsite-code pre .devsite-syntax-s1,devsite-code pre .devsite-syntax-s2,devsite-code pre .devsite-syntax-sa,devsite-code pre .devsite-syntax-sb,devsite-code pre .devsite-syntax-sc,devsite-code pre .devsite-syntax-sd,devsite-code pre .devsite-syntax-se,devsite-code pre .devsite-syntax-sh,devsite-code pre .devsite-syntax-si,devsite-code pre .devsite-syntax-sr,devsite-code pre .devsite-syntax-ss,devsite-code pre .devsite-syntax-sx,devsite-code pre .str{color:var(--devsite-code-strings-color)}devsite-code pre .atn,devsite-code pre .devsite-syntax-bp,devsite-code pre .devsite-syntax-fm,devsite-code pre .devsite-syntax-gh,devsite-code pre .devsite-syntax-go,devsite-code pre .devsite-syntax-gp,devsite-code pre .devsite-syntax-gr,devsite-code pre .devsite-syntax-gt,devsite-code pre .devsite-syntax-gu,devsite-code pre .devsite-syntax-na,devsite-code pre .devsite-syntax-nb,devsite-code pre .devsite-syntax-nc,devsite-code pre .devsite-syntax-nd,devsite-code pre .devsite-syntax-ne,devsite-code pre .devsite-syntax-nf,devsite-code pre .devsite-syntax-ni,devsite-code pre .devsite-syntax-nl,devsite-code pre .devsite-syntax-nn,devsite-code pre .devsite-syntax-no,devsite-code pre .devsite-syntax-nv,devsite-code pre .devsite-syntax-vc,devsite-code pre .devsite-syntax-vg,devsite-code pre .devsite-syntax-vi,devsite-code pre .devsite-syntax-vm,devsite-code pre .typ{color:var(--devsite-code-types-color)}devsite-code .prettyprint :not(.devsite-github-link)>a:not(.devsite-github-link),devsite-code a,devsite-code a :is(.atn,.atv,.com,.dec,.kwd,.lit,.pln,.pun,.str,.tag,.typ),devsite-code a [class^=devsite-syntax-]{-moz-osx-font-smoothing:auto;-webkit-font-smoothing:auto;font-weight:700}devsite-code[dark-code] .prettyprint :not(.devsite-github-link)>a:not(.devsite-github-link),devsite-code[dark-code] a,devsite-code[dark-code] a :is(.atn,.atv,.com,.dec,.kwd,.lit,.pln,.pun,.str,.tag,.typ),devsite-code[dark-code] a [class^=devsite-syntax-]{color:#669df6}devsite-code .prettyprint a:focus,devsite-code .prettyprint a:hover,devsite-code a:focus :is(.atn,.atv,.com,.dec,.kwd,.lit,.pln,.pun,.str,.tag,.typ),devsite-code a:focus [class^=devsite-syntax-],devsite-code a:hover :is(.atn,.atv,.com,.dec,.kwd,.lit,.pln,.pun,.str,.tag,.typ),devsite-code a:hover [class^=devsite-syntax-]{text-decoration:underline}devsite-code .devsite-terminal:before{color:#bdc1c6;content:"$";padding-right:8px}devsite-code .devsite-terminal[data-terminal-prefix]:before{content:attr(data-terminal-prefix)}devsite-code .devsite-github-link{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-pack:end;-webkit-justify-content:flex-end;-moz-box-pack:end;-ms-flex-pack:end;justify-content:flex-end}devsite-code a.devsite-github-link:focus,devsite-code a.devsite-github-link:hover{text-decoration:none}devsite-code .devsite-github-link:after{background:no-repeat var(--devsite-github-link-icon);content:"";display:block;height:18px;margin-left:8px;width:18px}devsite-code[dark-code] .devsite-github-link>a{color:#669df6}devsite-code devsite-selector pre{margin:0}body[layout=full] devsite-code{overflow:visible}body[layout=full] devsite-code:after{background:var(--devsite-code-background);content:"";display:block;height:100%;left:calc(50% - 50vw);position:absolute;top:0;width:100vw;z-index:-1}:is(aside,.beta,.caution,.deprecated,.dogfood,.experimental,.key-point,.key-term,.note,.objective,.preview,.special,.success,.tip,.warning) devsite-code pre{background:var(--devsite-code-background)}devsite-codelab-catalog .controls{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-webkit-justify-content:space-between;-moz-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between}devsite-codelab-catalog .catalog-selector,devsite-codelab-catalog .category-selector,devsite-codelab-catalog .sort-controls{-webkit-box-flex:1;-webkit-flex:1;-moz-box-flex:1;-ms-flex:1;flex:1}devsite-codelab-catalog .controls{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}devsite-codelab-catalog .catalog-selector,devsite-codelab-catalog .category-selector{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex}devsite-codelab-catalog .catalog-selector{-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;-ms-flex-pack:center;justify-content:center;margin:0;width:auto}devsite-codelab-catalog .category-selector{-webkit-box-pack:end;-webkit-justify-content:flex-end;-moz-box-pack:end;-ms-flex-pack:end;justify-content:flex-end}devsite-codelab-catalog[sortorder=-timestamp] .button[sortorder=-timestamp],devsite-codelab-catalog[sortorder=displaytitle] .button[sortorder=displaytitle],devsite-codelab-catalog[sortorder=durationminutes] .button[sortorder=durationminutes]{border-bottom:2px solid;border-radius:4px 4px 0 0}@media screen and (max-width:840px){devsite-codelab-catalog .sort-controls{-webkit-box-flex:0;-webkit-flex:0 1 auto;-moz-box-flex:0;-ms-flex:0 1 auto;flex:0 1 auto;padding-bottom:16px;width:100%}devsite-codelab-catalog .catalog-selector{-webkit-box-pack:start;-webkit-justify-content:flex-start;-moz-box-pack:start;-ms-flex-pack:start;justify-content:flex-start}}@media screen and (max-width:600px){devsite-codelab-catalog .catalog-selector{padding-bottom:16px}devsite-codelab-catalog .category-selector{-webkit-box-pack:start;-webkit-justify-content:flex-start;-moz-box-pack:start;-ms-flex-pack:start;justify-content:flex-start}}devsite-concierge{--devsite-concierge-border:1px solid #bdc1c6;bottom:0;display:none;position:fixed;right:0;top:var(--devsite-concierge-top,48px);z-index:1006}[dir=rtl] devsite-concierge{left:0;right:auto}[appearance=dark] devsite-concierge{--devsite-concierge-border:1px solid #bdc1c6}body[ready] devsite-concierge{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;bottom:var(--devsite-panel-height,0)}body[ready][concierge=modal] devsite-concierge{top:0;left:0;right:0;bottom:0;z-index:1014;-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;-ms-flex-pack:center;justify-content:center}.devsite-concierge-container{background:var(--devsite-background-1);display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;width:var(--devsite-concierge-width-closed,54px)}.devsite-concierge-container:before{--devsite-elevation-key-shadow-color:rgba(0,0,0,.3);--devsite-elevation-ambient-shadow-color:rgba(0,0,0,.15);content:"";box-shadow:0 1px 2px 0 var(--devsite-elevation-key-shadow-color),0 1px 3px 1px var(--devsite-elevation-ambient-shadow-color);height:100%;position:absolute;width:100%;z-index:-1}[dir=ltr] .devsite-concierge-container:before{-webkit-clip-path:inset(0 0 0 -3px);clip-path:inset(0 0 0 -3px)}[dir=rtl] .devsite-concierge-container:before{-webkit-clip-path:inset(0 -3px 0 0);clip-path:inset(0 -3px 0 0)}body[ready][concierge=modal] .devsite-concierge-container{height:80vh;width:80vw;border-radius:8px;box-shadow:0 1px 3px 0 var(--devsite-elevation-key-shadow-color),0 4px 8px 3px var(--devsite-elevation-ambient-shadow-color)}body[ready][concierge=modal] .devsite-concierge-container:before{display:none}.devsite-concierge-menu{border-top:1px solid #bdc1c6;-webkit-padding-before:8px;padding-block-start:8px;z-index:1}body[ready][concierge=modal] .devsite-concierge-menu{border-top:0;border-radius:8px 0 0 8px}.devsite-concierge-panel{display:none;background:var(--devsite-background-1);border-top:1px solid #bdc1c6;-moz-box-sizing:border-box;box-sizing:border-box;height:100%;overflow:hidden;z-index:2}[dir=ltr] .devsite-concierge-panel{border-left:var(--devsite-concierge-border,0)}[dir=rtl] .devsite-concierge-panel{border-right:var(--devsite-concierge-border,0)}.devsite-concierge-panel>*{display:none}.devsite-concierge-panel>[active]{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-moz-box-orient:vertical;-moz-box-direction:normal;-ms-flex-direction:column;flex-direction:column;-webkit-box-flex:1;-webkit-flex-grow:1;-moz-box-flex:1;-ms-flex-positive:1;flex-grow:1}body[ready][concierge=modal] .devsite-concierge-panel{border-radius:0 8px 8px 0;border-top:0}.devsite-concierge-menu{overflow:visible}.devsite-concierge-panel-open{width:var(--devsite-concierge-width-open,355px)}.devsite-concierge-panel-open .devsite-concierge-panel{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-flex:1;-webkit-flex-grow:1;-moz-box-flex:1;-ms-flex-positive:1;flex-grow:1}.devsite-concierge-menu-item{height:56px;position:relative;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;width:56px}.devsite-concierge-menu--hidden{display:none}.devsite-concierge-menu-icon{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;background-color:transparent;border-radius:50%;color:#5f6368;cursor:pointer;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;height:40px;-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;-ms-flex-pack:center;justify-content:center;margin:0 auto;-webkit-transition:background-color .3s cubic-bezier(.4,0,.2,1);transition:background-color .3s cubic-bezier(.4,0,.2,1);width:40px}.devsite-concierge-menu-icon:active,.devsite-concierge-menu-icon:hover{background-color:#e5edfc;border-radius:50%}.devsite-concierge-menu-icon .material-icons{font-size:20px}.devsite-concierge-menu-icon svg path{fill:#5f6368}[appearance=dark] .devsite-concierge-menu-icon svg path{fill:#9aa0a6}[appearance=dark] .devsite-concierge-menu-icon:active,[appearance=dark] .devsite-concierge-menu-icon:hover{background-color:#3c3d40}.devsite-concierge-menu-item--selected .devsite-concierge-menu-icon{background-color:#e5edfc}.devsite-concierge-menu-item--selected .devsite-concierge-menu-icon svg path{fill:#1a73e8}[appearance=dark] .devsite-concierge-menu-item--selected .devsite-concierge-menu-icon{background-color:#3c3d40}[appearance=dark] .devsite-concierge-menu-item--selected .devsite-concierge-menu-icon svg path{fill:#8ab4f8}.devsite-concierge-menu-item--selected:after{background:#1967d2;content:"";height:42px;position:absolute;top:0;width:4px}[appearance=dark] .devsite-concierge-menu-item--selected:after{background-color:#8ab4f8}[dir=ltr] .devsite-concierge-menu-item--selected:after{border-radius:4px 0 0 4px;right:0}[dir=rtl] .devsite-concierge-menu-item--selected:after{border-radius:0 4px 4px 0;left:0}.devsite-concierge-notification-dot{width:10px;height:10px;position:absolute;border-radius:50%;background:#0b57d0;top:2px;right:8px;-webkit-animation-name:notificationDotAnimation;animation-name:notificationDotAnimation;-webkit-animation-duration:1s;animation-duration:1s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-iteration-count:3;animation-iteration-count:3}@-webkit-keyframes notificationDotAnimation{0%{-webkit-transform:scaleX(1);transform:scaleX(1)}30%{-webkit-transform:scale3d(1.25,.75,1);transform:scale3d(1.25,.75,1)}40%{-webkit-transform:scale3d(.75,1.25,1);transform:scale3d(.75,1.25,1)}50%{-webkit-transform:scale3d(1.15,.85,1);transform:scale3d(1.15,.85,1)}65%{-webkit-transform:scale3d(.95,1.05,1);transform:scale3d(.95,1.05,1)}75%{-webkit-transform:scale3d(1.05,.95,1);transform:scale3d(1.05,.95,1)}to{-webkit-transform:scaleX(1);transform:scaleX(1)}}@keyframes notificationDotAnimation{0%{-webkit-transform:scaleX(1);transform:scaleX(1)}30%{-webkit-transform:scale3d(1.25,.75,1);transform:scale3d(1.25,.75,1)}40%{-webkit-transform:scale3d(.75,1.25,1);transform:scale3d(.75,1.25,1)}50%{-webkit-transform:scale3d(1.15,.85,1);transform:scale3d(1.15,.85,1)}65%{-webkit-transform:scale3d(.95,1.05,1);transform:scale3d(.95,1.05,1)}75%{-webkit-transform:scale3d(1.05,.95,1);transform:scale3d(1.05,.95,1)}to{-webkit-transform:scaleX(1);transform:scaleX(1)}}.devsite-concierge-notification{font-size:12px;top:8px;border-radius:12px;white-space:nowrap;color:#fff;background:#0b57d0;padding:0 12px;position:absolute;cursor:pointer;pointer-events:none;-webkit-animation:notifcationAnimation .5s ease-out .15s forwards;animation:notifcationAnimation .5s ease-out .15s forwards;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-iteration-count:1;animation-iteration-count:1;-webkit-animation-delay:1s;animation-delay:1s;opacity:0}[dir=ltr] .devsite-concierge-notification{right:calc(100% - 8px)}[dir=rtl] .devsite-concierge-notification{left:calc(100% - 8px)}@-webkit-keyframes notifcationAnimation{0%{opacity:1;-webkit-transform:translateZ(0) scaleX(1);transform:translateZ(0) scaleX(1)}to{opacity:0;-webkit-transform:translate3d(12px,0,0) scale3d(.9,.9,.9);transform:translate3d(12px,0,0) scale3d(.9,.9,.9)}}@keyframes notifcationAnimation{0%{opacity:1;-webkit-transform:translateZ(0) scaleX(1);transform:translateZ(0) scaleX(1)}to{opacity:0;-webkit-transform:translate3d(12px,0,0) scale3d(.9,.9,.9);transform:translate3d(12px,0,0) scale3d(.9,.9,.9)}}@media screen and (max-width:840px){body[ready] devsite-concierge,devsite-concierge{display:none}}devsite-concierge-ai-panel .devsite-concierge-panel-header{padding:12px 16px;border-bottom:var(--devsite-concierge-border)}devsite-concierge-ai-panel .devsite-concierge-panel-loading{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-moz-box-orient:vertical;-moz-box-direction:normal;-ms-flex-direction:column;flex-direction:column;height:100%;-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;-ms-flex-pack:center;justify-content:center;text-align:center;width:100%;gap:15px}devsite-concierge-ai-panel .devsite-concierge-panel-header-row{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-webkit-justify-content:space-between;-moz-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;gap:2px}devsite-concierge-ai-panel .devsite-concierge-panel-header-row h2{--devsite-h2-margin:0;--devsite-h2-font:500 16px/24px var(--devsite-headline-font-family);-webkit-box-flex:1;-webkit-flex-grow:1;-moz-box-flex:1;-ms-flex-positive:1;flex-grow:1;font-size:16px;line-height:24px;-webkit-margin-end:10px;-moz-margin-end:10px;margin-inline-end:10px}devsite-concierge-ai-panel .devsite-concierge-panel-header-row h3{--devsite-h3-margin:0;--devsite-h3-font:500 12px/16px var(--devsite-headline-font-family);background:#feefe3;border-radius:4px;color:#bf360c;font-size:12px;line-height:16px;padding:2px 6px;text-transform:uppercase}devsite-concierge-ai-panel .devsite-concierge-panel-header-button{-webkit-align-self:flex-start;-ms-flex-item-align:start;align-self:flex-start;color:#5f6368;font-size:20px;text-decoration:none;line-height:28px;border-radius:50%;width:40px;height:40px;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;-ms-flex-pack:center;justify-content:center}devsite-concierge-ai-panel .devsite-concierge-panel-header-button:active,devsite-concierge-ai-panel .devsite-concierge-panel-header-button:focus,devsite-concierge-ai-panel .devsite-concierge-panel-header-button:hover{background:#e8eaed;text-decoration:none}[appearance=dark] devsite-concierge-ai-panel .devsite-concierge-panel-header-button{color:#9aa0a6}[appearance=dark] devsite-concierge-ai-panel .devsite-concierge-panel-header-button:active,[appearance=dark] devsite-concierge-ai-panel .devsite-concierge-panel-header-button:focus,[appearance=dark] devsite-concierge-ai-panel .devsite-concierge-panel-header-button:hover{background:#3c3d40}devsite-concierge-ai-panel .devsite-concierge-panel-sections{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-moz-box-orient:vertical;-moz-box-direction:normal;-ms-flex-direction:column;flex-direction:column;-webkit-box-flex:1;-webkit-flex-grow:1;-moz-box-flex:1;-ms-flex-positive:1;flex-grow:1;gap:10px;overflow:auto;padding:16px}devsite-concierge-ai-panel .devsite-concierge-panel-section{border:var(--devsite-concierge-border);border-radius:8px;-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0}[layout=docs] devsite-concierge-ai-panel .devsite-concierge-panel-section h1,[layout=docs] devsite-concierge-ai-panel .devsite-concierge-panel-section h2,[layout=docs] devsite-concierge-ai-panel .devsite-concierge-panel-section h3,[layout=docs] devsite-concierge-ai-panel .devsite-concierge-panel-section h4,[layout=docs] devsite-concierge-ai-panel .devsite-concierge-panel-section h5,[layout=docs] devsite-concierge-ai-panel .devsite-concierge-panel-section h6{-webkit-margin-end:0;-moz-margin-end:0;margin-inline-end:0;-webkit-padding-end:0;-moz-padding-end:0;padding-inline-end:0}devsite-concierge-ai-panel .devsite-concierge-panel-section-header{border-bottom:var(--devsite-concierge-border);padding:14px 16px}devsite-concierge-ai-panel .devsite-concierge-panel-section-content{padding:16px}devsite-concierge-ai-panel .devsite-concierge-panel-section-fill{min-height:200px;overflow:auto;-webkit-flex-shrink:1;-ms-flex-negative:1;flex-shrink:1}devsite-concierge-ai-panel .devsite-concierge-panel-feedback{-webkit-align-self:flex-end;-ms-flex-item-align:end;align-self:flex-end;justify-self:flex-end;-webkit-box-flex:1;-webkit-flex-grow:1;-moz-box-flex:1;-ms-flex-positive:1;flex-grow:1;-webkit-box-align:end;-webkit-align-items:flex-end;-moz-box-align:end;-ms-flex-align:end;align-items:flex-end;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex}devsite-concierge-ai-panel .devsite-concierge-panel-section h3{--devsite-h3-margin:0;--devsite-h3-font:700 13px/21px var(--devsite-headline-font-family);font-size:13px;line-height:21px;color:#5f6368}[appearance=dark] devsite-concierge-ai-panel .devsite-concierge-panel-section h3{color:#e8eaed}devsite-concierge-ai-panel .devsite-concierge-panel-section p{font-weight:400;font-size:13px;line-height:21px;margin:0}[concierge=modal] devsite-concierge-ai-panel .devsite-concierge-panel-close,[concierge=modal] devsite-concierge-ai-panel .devsite-concierge-panel-fullscreen{display:none}devsite-concierge-ai-panel .devsite-concierge-panel-dock{display:none}[concierge=modal] devsite-concierge-ai-panel .devsite-concierge-panel-dock{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex}devsite-concierge-ai-panel .devsite-concierge-panel-section--loading{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;gap:4px;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-moz-box-orient:vertical;-moz-box-direction:normal;-ms-flex-direction:column;flex-direction:column}@-webkit-keyframes pulse{0%,to{opacity:1}50%{opacity:.5}}devsite-concierge-ai-panel .devsite-concierge-panel-section--loading .devsite-concierge-panel-section-header{border-bottom:1px solid transparent}devsite-concierge-ai-panel .devsite-concierge-panel-section--loading h2.devsite-concierge-panel-skeleton{height:21px}devsite-concierge-ai-panel .devsite-concierge-panel-section--loading .devsite-concierge-panel-skeleton{background:var(--tenant-background-3);border-radius:4px;margin:0 0 4px;font-size:13px;height:21px;-webkit-animation:pulse 2s infinite;animation:pulse 2s infinite}devsite-concierge-ai-panel .devsite-concierge-panel-section--loading>.devsite-concierge-panel-skeleton:first-child{width:100%}devsite-concierge-ai-panel .devsite-concierge-panel-section--loading>.devsite-concierge-panel-skeleton:nth-child(2){width:50%}devsite-concierge-ai-panel .devsite-concierge-panel-section--loading>.devsite-concierge-panel-skeleton:nth-child(3){width:33%}devsite-concierge-ai-panel .devsite-concierge-panel-section--loading>.devsite-concierge-panel-skeleton:nth-child(4){width:66%}devsite-concierge-ai-panel .devsite-concierge-panel-section--loading>.devsite-concierge-panel-skeleton:nth-child(5){width:25%}devsite-concierge-ai-panel .devsite-concierge-panel-section--loading>.devsite-concierge-panel-skeleton:nth-child(6){width:44%}[appearance=dark] devsite-concierge-ai-panel input[type=text]{--devsite-input-color:$GREY_400}devsite-concierge-ai-panel .devsite-concierge-panel-chat-section{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-moz-box-orient:vertical;-moz-box-direction:normal;-ms-flex-direction:column;flex-direction:column;-webkit-box-flex:1;-webkit-flex-grow:1;-moz-box-flex:1;-ms-flex-positive:1;flex-grow:1;padding:0}devsite-concierge-ai-panel .devsite-concierge-panel-chat-header{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;border-bottom:var(--devsite-concierge-border);display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-flex:0;-webkit-flex-grow:0;-moz-box-flex:0;-ms-flex-positive:0;flex-grow:0;padding:12px 16px}devsite-concierge-ai-panel .devsite-concierge-panel-chat-header-titles{-webkit-box-flex:1;-webkit-flex-grow:1;-moz-box-flex:1;-ms-flex-positive:1;flex-grow:1;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;gap:8px}devsite-concierge-ai-panel .devsite-concierge-panel-chat-header h2{color:#5f6368;font-size:16px;font-weight:500;line-height:21px;margin:0}[appearance=dark] devsite-concierge-ai-panel .devsite-concierge-panel-chat-header h2{color:#e8eaed}[layout=docs] devsite-concierge-ai-panel .devsite-concierge-panel-chat-header h3,[layout=full] devsite-concierge-ai-panel .devsite-concierge-panel-chat-header h3{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;background:#e6f4ea;border-radius:4px;color:#5f6368;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;font-size:12px;font-weight:500;gap:6px;line-height:14px;margin:0;padding:3px 6px;-webkit-padding-end:8px;-moz-padding-end:8px;padding-inline-end:8px;text-transform:uppercase}[layout=docs] devsite-concierge-ai-panel .devsite-concierge-panel-chat-header h3 .material-icons,[layout=full] devsite-concierge-ai-panel .devsite-concierge-panel-chat-header h3 .material-icons{font-size:12px}[layout=docs][appearance=dark] devsite-concierge-ai-panel .devsite-concierge-panel-chat-header h3,[layout=full][appearance=dark] devsite-concierge-ai-panel .devsite-concierge-panel-chat-header h3{background:#a59d97;color:#40251f}devsite-concierge-ai-panel .devsite-concierge-panel-chat--reset,devsite-concierge-ai-panel .devsite-concierge-panel-chat--reset[disabled]{--devsite-button-color:#5f6368;--devsite-button-line-height:21px;--devsite-button-border:0;--devsite-button-disabled-border:0;--devsite-button-disabled-line-height:24px;min-width:auto}devsite-concierge-ai-panel .devsite-concierge-panel-chat-body{background:#f3f6fc;border-radius:0 0 8px 8px;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-moz-box-orient:vertical;-moz-box-direction:normal;-ms-flex-direction:column;flex-direction:column;-webkit-box-flex:1;-webkit-flex:1 1 auto;-moz-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto;overflow:hidden;gap:8px}[appearance=dark] devsite-concierge-ai-panel .devsite-concierge-panel-chat-body{background:#36373a}devsite-concierge-ai-panel .devsite-concierge-panel-chat-form{background:#fff;border-radius:30px;border:1px solid #dadce0;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;gap:4px;padding:0;-webkit-padding-start:20px;-moz-padding-start:20px;padding-inline-start:20px;margin-bottom:8px;--devsite-input-border:0;--devsite-input-padding:0;--devsite-input-border-bottom-focus:0;--devsite-input-padding-bottom-focus:0;--devsite-input-height:45px}devsite-concierge-ai-panel .devsite-concierge-panel-chat-form[disabled]{--devsite-input-background:var(--devsite-background-3);background:var(--devsite-background-3)}[appearance=dark] devsite-concierge-ai-panel .devsite-concierge-panel-chat-form{--devsite-input-background:#2a2b2e;background:#2a2b2e}devsite-concierge-ai-panel .devsite-concierge-panel-chat-header,devsite-concierge-ai-panel .devsite-concierge-panel-chat-inputs{--devsite-button-border:0;--devsite-button-padding:0;--devsite-button-height:auto;--devsite-button-background-hover:0;--devsite-button-border-hover:0;--devsite-button-box-shadow-active:0;--devsite-button-background-active:0;--devsite-button-border-active:0;--devsite-button-disabled-background:0;--devsite-button-disabled-border:0}devsite-concierge-ai-panel .devsite-concierge-panel-chat-inputs{padding:0 16px 16px}devsite-concierge-ai-panel .devsite-concierge-panel-chat-input{--devsite-input-border-radius:0;--devsite-background-3:#2a2b2e;-webkit-box-flex:1;-webkit-flex-grow:1;-moz-box-flex:1;-ms-flex-positive:1;flex-grow:1;font-size:13px}devsite-concierge-ai-panel .devsite-concierge-panel-chat-button{--devsite-button-background:0}[dir=rtl] devsite-concierge-ai-panel .devsite-concierge-panel-chat-button{-webkit-transform:rotate(180deg);transform:rotate(180deg)}[appearance=dark] devsite-concierge-ai-panel .devsite-concierge-panel-chat-button{color:#5f6368}devsite-concierge-ai-panel .devsite-concierge-panel-chat-user-button{--devsite-button-padding:0 16px;--devsite-button-border:1px solid #dadce0;--devsite-button-border-hover:1px solid #dadce0}devsite-concierge-ai-panel p.devsite-concierge-panel-chat-disclaimer{color:rgba(0,0,0,.55);font-size:11px;font-weight:400;line-height:16px;margin:0;padding:0;text-align:center}[appearance=dark] devsite-concierge-ai-panel p.devsite-concierge-panel-chat-disclaimer{color:#9aa0a6}devsite-concierge-ai-panel .devsite-concierge-panel-chat-container{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-moz-box-orient:vertical;-moz-box-direction:normal;-ms-flex-direction:column;flex-direction:column;max-width:calc(var(--devsite-concierge-width-open) - 91px);padding:16px 16px 0;position:relative;-webkit-box-flex:1;-webkit-flex:1 1 auto;-moz-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto;overflow:scroll}devsite-concierge-ai-panel .devsite-concierge-panel-chat-loading,devsite-concierge-ai-panel .devsite-concierge-panel-chat-requires-access{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-moz-box-orient:vertical;-moz-box-direction:normal;-ms-flex-direction:column;flex-direction:column;height:100%;-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;-ms-flex-pack:center;justify-content:center;text-align:center;width:100%}devsite-concierge-ai-panel .devsite-concierge-panel-chat-requires-access{text-align:center;gap:8px}devsite-concierge-ai-panel .devsite-concierge-panel-chat-requires-access h3{font-size:14px;font-weight:400;line-height:20px;color:#202124}devsite-concierge-ai-panel .devsite-concierge-panel-chat-requires-access .button{--devsite-button-background:none;margin-top:16px}devsite-concierge-ai-panel .devsite-concierge-panel-chat-row{-webkit-animation:fadeInChatRow .5s;animation:fadeInChatRow .5s;margin:8px 0}devsite-concierge-ai-panel .devsite-concierge-panel-chat-row:first-child{margin-top:0}@-webkit-keyframes fadeInChatRow{0%{opacity:0;-webkit-transform:translate3d(0,12px,0);transform:translate3d(0,12px,0)}to{opacity:1;-webkit-transform:translateZ(0);transform:translateZ(0)}}@keyframes fadeInChatRow{0%{opacity:0;-webkit-transform:translate3d(0,12px,0);transform:translate3d(0,12px,0)}to{opacity:1;-webkit-transform:translateZ(0);transform:translateZ(0)}}devsite-concierge-ai-panel .devsite-concierge-panel-chat-from-system,devsite-concierge-ai-panel .devsite-concierge-panel-chat-from-user,devsite-concierge-ai-panel .devsite-concierge-panel-chat-quickprompt-questions{color:#3c4043;font-size:13px;font-weight:400;line-height:17px;overflow-wrap:break-word;word-wrap:break-word;word-break:break-word;-webkit-hyphens:auto;-moz-hyphens:auto;-ms-hyphens:auto;hyphens:auto}[appearance=dark] devsite-concierge-ai-panel .devsite-concierge-panel-chat-from-system,[appearance=dark] devsite-concierge-ai-panel .devsite-concierge-panel-chat-from-user,[appearance=dark] devsite-concierge-ai-panel .devsite-concierge-panel-chat-quickprompt-questions{color:#e8eaed}devsite-concierge-ai-panel .devsite-concierge-panel-chat-from-system,devsite-concierge-ai-panel .devsite-concierge-panel-chat-quickprompt-questions{background:#fff;border-radius:8px;padding:16px 0}[appearance=dark] devsite-concierge-ai-panel .devsite-concierge-panel-chat-from-system,[appearance=dark] devsite-concierge-ai-panel .devsite-concierge-panel-chat-quickprompt-questions{background:#2a2b2e}devsite-concierge-ai-panel .devsite-concierge-panel-chat-quickprompt-questions{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;gap:8px;padding:16px}devsite-concierge-ai-panel .devsite-concierge-panel-chat-quickprompt-questions-icon{padding-top:2px}devsite-concierge-ai-panel .devsite-concierge-panel-chat-quickprompt-questions-icon svg{width:16px;height:16px;fill:#1a73e8}[appearance=dark] devsite-concierge-ai-panel .devsite-concierge-panel-chat-quickprompt-questions-icon svg{fill:#8ab4f8}devsite-concierge-ai-panel .devsite-concierge-panel-chat-from-system dd,devsite-concierge-ai-panel .devsite-concierge-panel-chat-from-system ol,devsite-concierge-ai-panel .devsite-concierge-panel-chat-from-system p,devsite-concierge-ai-panel .devsite-concierge-panel-chat-from-system ul,devsite-concierge-ai-panel .devsite-concierge-panel-chat-quickprompt-questions dd,devsite-concierge-ai-panel .devsite-concierge-panel-chat-quickprompt-questions ol,devsite-concierge-ai-panel .devsite-concierge-panel-chat-quickprompt-questions p,devsite-concierge-ai-panel .devsite-concierge-panel-chat-quickprompt-questions ul{padding:0 16px}devsite-concierge-ai-panel .devsite-concierge-panel-chat-from-system ol,devsite-concierge-ai-panel .devsite-concierge-panel-chat-from-system ul,devsite-concierge-ai-panel .devsite-concierge-panel-chat-quickprompt-questions ol,devsite-concierge-ai-panel .devsite-concierge-panel-chat-quickprompt-questions ul{-webkit-margin-start:16px;-moz-margin-start:16px;margin-inline-start:16px}devsite-concierge-ai-panel .devsite-concierge-panel-chat-references{padding:16px}devsite-concierge-ai-panel .devsite-concierge-panel-chat-references h3{color:#80868b;font-size:10px;line-height:14px;font-weight:500;text-transform:uppercase}devsite-concierge-ai-panel .devsite-concierge-panel-chat-references ul{padding:0;-webkit-margin-start:0;-moz-margin-start:0;margin-inline-start:0}devsite-concierge-ai-panel .devsite-concierge-panel-chat-references ul li{-webkit-margin-start:0;-moz-margin-start:0;margin-inline-start:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;margin:0 0 2px;list-style:none}devsite-concierge-ai-panel .devsite-concierge-panel-chat-references ul li a{--devsite-link-color:#1967d2}devsite-concierge-ai-panel .devsite-concierge-panel-chat-quickprompt-questions ul{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-moz-box-orient:vertical;-moz-box-direction:normal;-ms-flex-direction:column;flex-direction:column;gap:16px;list-style:none;margin:8px 0 0;padding:0}devsite-concierge-ai-panel .devsite-concierge-panel-chat-quickprompt-questions ul li{line-height:21px;margin:0}devsite-concierge-ai-panel .devsite-concierge-panel-chat-quickprompt-questions a{font-size:13px}devsite-concierge-ai-panel .devsite-concierge-panel-chat-communicating{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;gap:4px;padding:0 16px}devsite-concierge-ai-panel .devsite-concierge-panel-chat-communicating span{-webkit-animation:devsite-concierge-panel-chat-dot-blink 1.5s infinite;animation:devsite-concierge-panel-chat-dot-blink 1.5s infinite;-webkit-animation-fill-mode:both;animation-fill-mode:both;background-color:#0b57d0;border-radius:50%;height:6px;opacity:0;width:6px}devsite-concierge-ai-panel .devsite-concierge-panel-chat-communicating span:nth-child(2){-webkit-animation-delay:.2s;animation-delay:.2s}devsite-concierge-ai-panel .devsite-concierge-panel-chat-communicating span:nth-child(3){-webkit-animation-delay:.4s;animation-delay:.4s}[appearance=dark] devsite-concierge-ai-panel .devsite-concierge-panel-chat-communicating span{background-color:#8ab4f8}@-webkit-keyframes devsite-concierge-panel-chat-dot-blink{0%,to{opacity:.1}20%{opacity:1}}@keyframes devsite-concierge-panel-chat-dot-blink{0%,to{opacity:.1}20%{opacity:1}}devsite-concierge-ai-panel .devsite-concierge-panel-recommendations{min-height:200px}devsite-concierge-ai-panel pre code{font-size:13px}devsite-concierge-ai-panel devsite-code pre{--devsite-code-padding-inline:16px}[concierge=modal] devsite-concierge-ai-panel .devsite-concierge-panel-sections{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-moz-box-orient:horizontal;-moz-box-direction:normal;-ms-flex-direction:row;flex-direction:row}[concierge=modal] devsite-concierge-ai-panel .devsite-concierge-panel-recommendations{-webkit-flex-basis:286px;-ms-flex-preferred-size:286px;flex-basis:286px}[concierge=modal] devsite-concierge-ai-panel .devsite-concierge-panel-chat-section{height:100%;-webkit-box-flex:1;-webkit-flex-grow:1;-moz-box-flex:1;-ms-flex-positive:1;flex-grow:1;-webkit-flex-shrink:1;-ms-flex-negative:1;flex-shrink:1}[concierge=modal] devsite-concierge-ai-panel .devsite-concierge-panel-chat-container{max-width:100%}devsite-concierge-apix{height:100%}devsite-concierge-apix .apis-explorer{background:inherit;overflow:auto;height:100%}devsite-concierge-apix .apis-explorer iframe{height:100%;width:100%}devsite-concierge-api-explorer-panel .devsite-concierge-panel-header{padding:12px 16px;border-bottom:var(--devsite-concierge-border)}devsite-concierge-api-explorer-panel .devsite-concierge-panel-loading{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-moz-box-orient:vertical;-moz-box-direction:normal;-ms-flex-direction:column;flex-direction:column;height:100%;-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;-ms-flex-pack:center;justify-content:center;text-align:center;width:100%;gap:15px}devsite-concierge-api-explorer-panel .devsite-concierge-panel-chat-user-button{--devsite-button-padding:0 16px;--devsite-button-border:1px solid #dadce0;--devsite-button-border-hover:1px solid #dadce0}devsite-concierge-api-explorer-panel .devsite-concierge-panel-header-row{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-webkit-justify-content:space-between;-moz-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;gap:2px}devsite-concierge-api-explorer-panel .devsite-concierge-panel-header-row h2{--devsite-h2-margin:0;--devsite-h2-font:500 16px/24px var(--devsite-headline-font-family);-webkit-box-flex:1;-webkit-flex-grow:1;-moz-box-flex:1;-ms-flex-positive:1;flex-grow:1;font-size:16px;line-height:24px;-webkit-margin-end:10px;-moz-margin-end:10px;margin-inline-end:10px}devsite-concierge-api-explorer-panel .devsite-concierge-panel-header-row h3{--devsite-h3-margin:0;--devsite-h3-font:500 12px/16px var(--devsite-headline-font-family);background:#feefe3;border-radius:4px;color:#bf360c;font-size:12px;line-height:16px;padding:2px 6px;text-transform:uppercase}devsite-concierge-api-explorer-panel .devsite-concierge-panel-header-button{-webkit-align-self:flex-start;-ms-flex-item-align:start;align-self:flex-start;color:#5f6368;font-size:20px;text-decoration:none;line-height:28px;border-radius:50%;width:40px;height:40px;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;-ms-flex-pack:center;justify-content:center}devsite-concierge-api-explorer-panel .devsite-concierge-panel-header-button:active,devsite-concierge-api-explorer-panel .devsite-concierge-panel-header-button:focus,devsite-concierge-api-explorer-panel .devsite-concierge-panel-header-button:hover{background:#e8eaed;text-decoration:none}[appearance=dark] devsite-concierge-api-explorer-panel .devsite-concierge-panel-header-button{color:#9aa0a6}[appearance=dark] devsite-concierge-api-explorer-panel .devsite-concierge-panel-header-button:active,[appearance=dark] devsite-concierge-api-explorer-panel .devsite-concierge-panel-header-button:focus,[appearance=dark] devsite-concierge-api-explorer-panel .devsite-concierge-panel-header-button:hover{background:#3c3d40}devsite-concierge-api-explorer-panel .devsite-concierge-panel-sections{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-moz-box-orient:vertical;-moz-box-direction:normal;-ms-flex-direction:column;flex-direction:column;-webkit-box-flex:1;-webkit-flex-grow:1;-moz-box-flex:1;-ms-flex-positive:1;flex-grow:1;gap:10px;overflow:auto;padding:16px}devsite-concierge-api-explorer-panel .devsite-concierge-panel-section{border:var(--devsite-concierge-border);border-radius:8px;-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0}[layout=docs] devsite-concierge-api-explorer-panel .devsite-concierge-panel-section h1,[layout=docs] devsite-concierge-api-explorer-panel .devsite-concierge-panel-section h2,[layout=docs] devsite-concierge-api-explorer-panel .devsite-concierge-panel-section h3,[layout=docs] devsite-concierge-api-explorer-panel .devsite-concierge-panel-section h4,[layout=docs] devsite-concierge-api-explorer-panel .devsite-concierge-panel-section h5,[layout=docs] devsite-concierge-api-explorer-panel .devsite-concierge-panel-section h6{-webkit-margin-end:0;-moz-margin-end:0;margin-inline-end:0;-webkit-padding-end:0;-moz-padding-end:0;padding-inline-end:0}devsite-concierge-api-explorer-panel .devsite-concierge-panel-section-header{border-bottom:var(--devsite-concierge-border);padding:14px 16px}devsite-concierge-api-explorer-panel .devsite-concierge-panel-section-content{padding:16px}devsite-concierge-api-explorer-panel .devsite-concierge-panel-section-fill{min-height:200px;overflow:auto;-webkit-flex-shrink:1;-ms-flex-negative:1;flex-shrink:1}devsite-concierge-api-explorer-panel .devsite-concierge-panel-feedback{-webkit-align-self:flex-end;-ms-flex-item-align:end;align-self:flex-end;justify-self:flex-end;-webkit-box-flex:1;-webkit-flex-grow:1;-moz-box-flex:1;-ms-flex-positive:1;flex-grow:1;-webkit-box-align:end;-webkit-align-items:flex-end;-moz-box-align:end;-ms-flex-align:end;align-items:flex-end;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex}devsite-concierge-api-explorer-panel .devsite-concierge-panel-section h3{--devsite-h3-margin:0;--devsite-h3-font:700 13px/21px var(--devsite-headline-font-family);font-size:13px;line-height:21px;color:#5f6368}[appearance=dark] devsite-concierge-api-explorer-panel .devsite-concierge-panel-section h3{color:#e8eaed}devsite-concierge-api-explorer-panel .devsite-concierge-panel-section p{font-weight:400;font-size:13px;line-height:21px;margin:0}[concierge=modal] devsite-concierge-api-explorer-panel .devsite-concierge-panel-close,[concierge=modal] devsite-concierge-api-explorer-panel .devsite-concierge-panel-fullscreen{display:none}devsite-concierge-api-explorer-panel .devsite-concierge-panel-dock{display:none}[concierge=modal] devsite-concierge-api-explorer-panel .devsite-concierge-panel-dock{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex}devsite-concierge-api-explorer-panel .devsite-concierge-panel-section--loading{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;gap:4px;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-moz-box-orient:vertical;-moz-box-direction:normal;-ms-flex-direction:column;flex-direction:column}devsite-concierge-api-explorer-panel .devsite-concierge-panel-section--loading .devsite-concierge-panel-section-header{border-bottom:1px solid transparent}devsite-concierge-api-explorer-panel .devsite-concierge-panel-section--loading h2.devsite-concierge-panel-skeleton{height:21px}devsite-concierge-api-explorer-panel .devsite-concierge-panel-section--loading .devsite-concierge-panel-skeleton{background:var(--tenant-background-3);border-radius:4px;margin:0 0 4px;font-size:13px;height:21px;-webkit-animation:pulse 2s infinite;animation:pulse 2s infinite}devsite-concierge-api-explorer-panel .devsite-concierge-panel-section--loading>.devsite-concierge-panel-skeleton:first-child{width:100%}devsite-concierge-api-explorer-panel .devsite-concierge-panel-section--loading>.devsite-concierge-panel-skeleton:nth-child(2){width:50%}devsite-concierge-api-explorer-panel .devsite-concierge-panel-section--loading>.devsite-concierge-panel-skeleton:nth-child(3){width:33%}devsite-concierge-api-explorer-panel .devsite-concierge-panel-section--loading>.devsite-concierge-panel-skeleton:nth-child(4){width:66%}devsite-concierge-api-explorer-panel .devsite-concierge-panel-section--loading>.devsite-concierge-panel-skeleton:nth-child(5){width:25%}devsite-concierge-api-explorer-panel .devsite-concierge-panel-section--loading>.devsite-concierge-panel-skeleton:nth-child(6){width:44%}devsite-concierge-info-panel{--devsite-toc-border-width:0;--devsite-nav-list-padding-x-start:0}devsite-concierge-info-panel .devsite-concierge-panel-header{padding:12px 16px;border-bottom:var(--devsite-concierge-border)}devsite-concierge-info-panel .devsite-concierge-panel-loading{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-moz-box-orient:vertical;-moz-box-direction:normal;-ms-flex-direction:column;flex-direction:column;height:100%;-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;-ms-flex-pack:center;justify-content:center;text-align:center;width:100%;gap:15px}devsite-concierge-info-panel .devsite-concierge-panel-chat-user-button{--devsite-button-padding:0 16px;--devsite-button-border:1px solid #dadce0;--devsite-button-border-hover:1px solid #dadce0}devsite-concierge-info-panel .devsite-concierge-panel-header-row{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-webkit-justify-content:space-between;-moz-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;gap:2px}devsite-concierge-info-panel .devsite-concierge-panel-header-row h2{--devsite-h2-margin:0;--devsite-h2-font:500 16px/24px var(--devsite-headline-font-family);-webkit-box-flex:1;-webkit-flex-grow:1;-moz-box-flex:1;-ms-flex-positive:1;flex-grow:1;font-size:16px;line-height:24px;-webkit-margin-end:10px;-moz-margin-end:10px;margin-inline-end:10px}devsite-concierge-info-panel .devsite-concierge-panel-header-row h3{--devsite-h3-margin:0;--devsite-h3-font:500 12px/16px var(--devsite-headline-font-family);background:#feefe3;border-radius:4px;color:#bf360c;font-size:12px;line-height:16px;padding:2px 6px;text-transform:uppercase}devsite-concierge-info-panel .devsite-concierge-panel-header-button{-webkit-align-self:flex-start;-ms-flex-item-align:start;align-self:flex-start;color:#5f6368;font-size:20px;text-decoration:none;line-height:28px;border-radius:50%;width:40px;height:40px;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;-ms-flex-pack:center;justify-content:center}devsite-concierge-info-panel .devsite-concierge-panel-header-button:active,devsite-concierge-info-panel .devsite-concierge-panel-header-button:focus,devsite-concierge-info-panel .devsite-concierge-panel-header-button:hover{background:#e8eaed;text-decoration:none}[appearance=dark] devsite-concierge-info-panel .devsite-concierge-panel-header-button{color:#9aa0a6}[appearance=dark] devsite-concierge-info-panel .devsite-concierge-panel-header-button:active,[appearance=dark] devsite-concierge-info-panel .devsite-concierge-panel-header-button:focus,[appearance=dark] devsite-concierge-info-panel .devsite-concierge-panel-header-button:hover{background:#3c3d40}devsite-concierge-info-panel .devsite-concierge-panel-sections{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-moz-box-orient:vertical;-moz-box-direction:normal;-ms-flex-direction:column;flex-direction:column;-webkit-box-flex:1;-webkit-flex-grow:1;-moz-box-flex:1;-ms-flex-positive:1;flex-grow:1;gap:10px;overflow:auto;padding:16px}devsite-concierge-info-panel .devsite-concierge-panel-section{border:var(--devsite-concierge-border);border-radius:8px;-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0}[layout=docs] devsite-concierge-info-panel .devsite-concierge-panel-section h1,[layout=docs] devsite-concierge-info-panel .devsite-concierge-panel-section h2,[layout=docs] devsite-concierge-info-panel .devsite-concierge-panel-section h3,[layout=docs] devsite-concierge-info-panel .devsite-concierge-panel-section h4,[layout=docs] devsite-concierge-info-panel .devsite-concierge-panel-section h5,[layout=docs] devsite-concierge-info-panel .devsite-concierge-panel-section h6{-webkit-margin-end:0;-moz-margin-end:0;margin-inline-end:0;-webkit-padding-end:0;-moz-padding-end:0;padding-inline-end:0}devsite-concierge-info-panel .devsite-concierge-panel-section-header{border-bottom:var(--devsite-concierge-border);padding:14px 16px}devsite-concierge-info-panel .devsite-concierge-panel-section-content{padding:16px}devsite-concierge-info-panel .devsite-concierge-panel-section-fill{min-height:200px;overflow:auto;-webkit-flex-shrink:1;-ms-flex-negative:1;flex-shrink:1}devsite-concierge-info-panel .devsite-concierge-panel-feedback{-webkit-align-self:flex-end;-ms-flex-item-align:end;align-self:flex-end;justify-self:flex-end;-webkit-box-flex:1;-webkit-flex-grow:1;-moz-box-flex:1;-ms-flex-positive:1;flex-grow:1;-webkit-box-align:end;-webkit-align-items:flex-end;-moz-box-align:end;-ms-flex-align:end;align-items:flex-end;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex}devsite-concierge-info-panel .devsite-concierge-panel-section h3{--devsite-h3-margin:0;--devsite-h3-font:700 13px/21px var(--devsite-headline-font-family);font-size:13px;line-height:21px;color:#5f6368}[appearance=dark] devsite-concierge-info-panel .devsite-concierge-panel-section h3{color:#e8eaed}devsite-concierge-info-panel .devsite-concierge-panel-section p{font-weight:400;font-size:13px;line-height:21px;margin:0}[concierge=modal] devsite-concierge-info-panel .devsite-concierge-panel-close,[concierge=modal] devsite-concierge-info-panel .devsite-concierge-panel-fullscreen{display:none}devsite-concierge-info-panel .devsite-concierge-panel-dock{display:none}[concierge=modal] devsite-concierge-info-panel .devsite-concierge-panel-dock{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex}devsite-concierge-info-panel .devsite-concierge-panel-section--loading{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;gap:4px;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-moz-box-orient:vertical;-moz-box-direction:normal;-ms-flex-direction:column;flex-direction:column}devsite-concierge-info-panel .devsite-concierge-panel-section--loading .devsite-concierge-panel-section-header{border-bottom:1px solid transparent}devsite-concierge-info-panel .devsite-concierge-panel-section--loading h2.devsite-concierge-panel-skeleton{height:21px}devsite-concierge-info-panel .devsite-concierge-panel-section--loading .devsite-concierge-panel-skeleton{background:var(--tenant-background-3);border-radius:4px;margin:0 0 4px;font-size:13px;height:21px;-webkit-animation:pulse 2s infinite;animation:pulse 2s infinite}devsite-concierge-info-panel .devsite-concierge-panel-section--loading>.devsite-concierge-panel-skeleton:first-child{width:100%}devsite-concierge-info-panel .devsite-concierge-panel-section--loading>.devsite-concierge-panel-skeleton:nth-child(2){width:50%}devsite-concierge-info-panel .devsite-concierge-panel-section--loading>.devsite-concierge-panel-skeleton:nth-child(3){width:33%}devsite-concierge-info-panel .devsite-concierge-panel-section--loading>.devsite-concierge-panel-skeleton:nth-child(4){width:66%}devsite-concierge-info-panel .devsite-concierge-panel-section--loading>.devsite-concierge-panel-skeleton:nth-child(5){width:25%}devsite-concierge-info-panel .devsite-concierge-panel-section--loading>.devsite-concierge-panel-skeleton:nth-child(6){width:44%}devsite-concierge-info-panel .devsite-concierge-info-panel-tags{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-flow:row wrap;-moz-box-orient:horizontal;-moz-box-direction:normal;-ms-flex-flow:row wrap;flex-flow:row wrap;gap:6px;list-style:none;margin:0;padding:0}devsite-concierge-info-panel .devsite-concierge-info-panel-tags li{background:#f1f3f4;font-size:14px;line-height:20px;margin:0;padding:0 8px}[appearance=dark] devsite-concierge-info-panel .devsite-concierge-info-panel-tags li{background:#36373a;color:#9aa0a6}devsite-concierge-info-panel .devsite-concierge-info-panel-toggle-tags{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;font-size:14px;font-weight:500;line-height:20px;margin-top:6px}devsite-concierge-info-panel .devsite-concierge-info-panel-toggle-tags:active,devsite-concierge-info-panel .devsite-concierge-info-panel-toggle-tags:hover{text-decoration:none}devsite-concierge-info-panel devsite-toc .devsite-nav-heading{display:none}devsite-concierge-info-panel devsite-toc ul ul{--devsite-nav-list-padding-x-start:12px}devsite-concierge-info-panel devsite-toc a.devsite-nav-title{color:var(--devsite-nav-title-color,var(--devsite-primary-text-color))}@media screen and (max-width:1253px){devsite-concierge-info-panel devsite-toc.devsite-toc,devsite-concierge-info-panel devsite-toc[visible].devsite-toc{display:block}}devsite-concierge-my-activity-panel{width:100%;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex}devsite-concierge-my-activity-panel .devsite-concierge-panel-header{padding:12px 16px;border-bottom:var(--devsite-concierge-border)}devsite-concierge-my-activity-panel .devsite-concierge-panel-loading{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-moz-box-orient:vertical;-moz-box-direction:normal;-ms-flex-direction:column;flex-direction:column;height:100%;-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;-ms-flex-pack:center;justify-content:center;text-align:center;width:100%;gap:15px}devsite-concierge-my-activity-panel .devsite-concierge-panel-chat-user-button{--devsite-button-padding:0 16px;--devsite-button-border:1px solid #dadce0;--devsite-button-border-hover:1px solid #dadce0}devsite-concierge-my-activity-panel .devsite-concierge-panel-header-row{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-webkit-justify-content:space-between;-moz-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;gap:2px}devsite-concierge-my-activity-panel .devsite-concierge-panel-header-row h2{--devsite-h2-margin:0;--devsite-h2-font:500 16px/24px var(--devsite-headline-font-family);-webkit-box-flex:1;-webkit-flex-grow:1;-moz-box-flex:1;-ms-flex-positive:1;flex-grow:1;font-size:16px;line-height:24px;-webkit-margin-end:10px;-moz-margin-end:10px;margin-inline-end:10px}devsite-concierge-my-activity-panel .devsite-concierge-panel-header-row h3{--devsite-h3-margin:0;--devsite-h3-font:500 12px/16px var(--devsite-headline-font-family);background:#feefe3;border-radius:4px;color:#bf360c;font-size:12px;line-height:16px;padding:2px 6px;text-transform:uppercase}devsite-concierge-my-activity-panel .devsite-concierge-panel-header-button{-webkit-align-self:flex-start;-ms-flex-item-align:start;align-self:flex-start;color:#5f6368;font-size:20px;text-decoration:none;line-height:28px;border-radius:50%;width:40px;height:40px;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;-ms-flex-pack:center;justify-content:center}devsite-concierge-my-activity-panel .devsite-concierge-panel-header-button:active,devsite-concierge-my-activity-panel .devsite-concierge-panel-header-button:focus,devsite-concierge-my-activity-panel .devsite-concierge-panel-header-button:hover{background:#e8eaed;text-decoration:none}[appearance=dark] devsite-concierge-my-activity-panel .devsite-concierge-panel-header-button{color:#9aa0a6}[appearance=dark] devsite-concierge-my-activity-panel .devsite-concierge-panel-header-button:active,[appearance=dark] devsite-concierge-my-activity-panel .devsite-concierge-panel-header-button:focus,[appearance=dark] devsite-concierge-my-activity-panel .devsite-concierge-panel-header-button:hover{background:#3c3d40}devsite-concierge-my-activity-panel .devsite-concierge-panel-sections{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-moz-box-orient:vertical;-moz-box-direction:normal;-ms-flex-direction:column;flex-direction:column;-webkit-box-flex:1;-webkit-flex-grow:1;-moz-box-flex:1;-ms-flex-positive:1;flex-grow:1;gap:10px;overflow:auto;padding:16px}devsite-concierge-my-activity-panel .devsite-concierge-panel-section{border:var(--devsite-concierge-border);border-radius:8px;-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0}[layout=docs] devsite-concierge-my-activity-panel .devsite-concierge-panel-section h1,[layout=docs] devsite-concierge-my-activity-panel .devsite-concierge-panel-section h2,[layout=docs] devsite-concierge-my-activity-panel .devsite-concierge-panel-section h3,[layout=docs] devsite-concierge-my-activity-panel .devsite-concierge-panel-section h4,[layout=docs] devsite-concierge-my-activity-panel .devsite-concierge-panel-section h5,[layout=docs] devsite-concierge-my-activity-panel .devsite-concierge-panel-section h6{-webkit-margin-end:0;-moz-margin-end:0;margin-inline-end:0;-webkit-padding-end:0;-moz-padding-end:0;padding-inline-end:0}devsite-concierge-my-activity-panel .devsite-concierge-panel-section-header{border-bottom:var(--devsite-concierge-border);padding:14px 16px}devsite-concierge-my-activity-panel .devsite-concierge-panel-section-content{padding:16px}devsite-concierge-my-activity-panel .devsite-concierge-panel-section-fill{min-height:200px;overflow:auto;-webkit-flex-shrink:1;-ms-flex-negative:1;flex-shrink:1}devsite-concierge-my-activity-panel .devsite-concierge-panel-feedback{-webkit-align-self:flex-end;-ms-flex-item-align:end;align-self:flex-end;justify-self:flex-end;-webkit-box-flex:1;-webkit-flex-grow:1;-moz-box-flex:1;-ms-flex-positive:1;flex-grow:1;-webkit-box-align:end;-webkit-align-items:flex-end;-moz-box-align:end;-ms-flex-align:end;align-items:flex-end;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex}devsite-concierge-my-activity-panel .devsite-concierge-panel-section h3{--devsite-h3-margin:0;--devsite-h3-font:700 13px/21px var(--devsite-headline-font-family);font-size:13px;line-height:21px;color:#5f6368}[appearance=dark] devsite-concierge-my-activity-panel .devsite-concierge-panel-section h3{color:#e8eaed}devsite-concierge-my-activity-panel .devsite-concierge-panel-section p{font-weight:400;font-size:13px;line-height:21px;margin:0}[concierge=modal] devsite-concierge-my-activity-panel .devsite-concierge-panel-close,[concierge=modal] devsite-concierge-my-activity-panel .devsite-concierge-panel-fullscreen{display:none}devsite-concierge-my-activity-panel .devsite-concierge-panel-dock{display:none}[concierge=modal] devsite-concierge-my-activity-panel .devsite-concierge-panel-dock{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex}devsite-concierge-my-activity-panel .devsite-concierge-panel-section--loading{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;gap:4px;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-moz-box-orient:vertical;-moz-box-direction:normal;-ms-flex-direction:column;flex-direction:column}devsite-concierge-my-activity-panel .devsite-concierge-panel-section--loading .devsite-concierge-panel-section-header{border-bottom:1px solid transparent}devsite-concierge-my-activity-panel .devsite-concierge-panel-section--loading h2.devsite-concierge-panel-skeleton{height:21px}devsite-concierge-my-activity-panel .devsite-concierge-panel-section--loading .devsite-concierge-panel-skeleton{background:var(--tenant-background-3);border-radius:4px;margin:0 0 4px;font-size:13px;height:21px;-webkit-animation:pulse 2s infinite;animation:pulse 2s infinite}devsite-concierge-my-activity-panel .devsite-concierge-panel-section--loading>.devsite-concierge-panel-skeleton:first-child{width:100%}devsite-concierge-my-activity-panel .devsite-concierge-panel-section--loading>.devsite-concierge-panel-skeleton:nth-child(2){width:50%}devsite-concierge-my-activity-panel .devsite-concierge-panel-section--loading>.devsite-concierge-panel-skeleton:nth-child(3){width:33%}devsite-concierge-my-activity-panel .devsite-concierge-panel-section--loading>.devsite-concierge-panel-skeleton:nth-child(4){width:66%}devsite-concierge-my-activity-panel .devsite-concierge-panel-section--loading>.devsite-concierge-panel-skeleton:nth-child(5){width:25%}devsite-concierge-my-activity-panel .devsite-concierge-panel-section--loading>.devsite-concierge-panel-skeleton:nth-child(6){width:44%}devsite-concierge-recommendations-panel .devsite-concierge-panel-header{padding:12px 16px;border-bottom:var(--devsite-concierge-border)}devsite-concierge-recommendations-panel .devsite-concierge-panel-loading{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-moz-box-orient:vertical;-moz-box-direction:normal;-ms-flex-direction:column;flex-direction:column;height:100%;-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;-ms-flex-pack:center;justify-content:center;text-align:center;width:100%;gap:15px}devsite-concierge-recommendations-panel .devsite-concierge-panel-chat-user-button{--devsite-button-padding:0 16px;--devsite-button-border:1px solid #dadce0;--devsite-button-border-hover:1px solid #dadce0}devsite-concierge-recommendations-panel .devsite-concierge-panel-header-row{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-webkit-justify-content:space-between;-moz-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;gap:2px}devsite-concierge-recommendations-panel .devsite-concierge-panel-header-row h2{--devsite-h2-margin:0;--devsite-h2-font:500 16px/24px var(--devsite-headline-font-family);-webkit-box-flex:1;-webkit-flex-grow:1;-moz-box-flex:1;-ms-flex-positive:1;flex-grow:1;font-size:16px;line-height:24px;-webkit-margin-end:10px;-moz-margin-end:10px;margin-inline-end:10px}devsite-concierge-recommendations-panel .devsite-concierge-panel-header-row h3{--devsite-h3-margin:0;--devsite-h3-font:500 12px/16px var(--devsite-headline-font-family);background:#feefe3;border-radius:4px;color:#bf360c;font-size:12px;line-height:16px;padding:2px 6px;text-transform:uppercase}devsite-concierge-recommendations-panel .devsite-concierge-panel-header-button{-webkit-align-self:flex-start;-ms-flex-item-align:start;align-self:flex-start;color:#5f6368;font-size:20px;text-decoration:none;line-height:28px;border-radius:50%;width:40px;height:40px;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;-ms-flex-pack:center;justify-content:center}devsite-concierge-recommendations-panel .devsite-concierge-panel-header-button:active,devsite-concierge-recommendations-panel .devsite-concierge-panel-header-button:focus,devsite-concierge-recommendations-panel .devsite-concierge-panel-header-button:hover{background:#e8eaed;text-decoration:none}[appearance=dark] devsite-concierge-recommendations-panel .devsite-concierge-panel-header-button{color:#9aa0a6}[appearance=dark] devsite-concierge-recommendations-panel .devsite-concierge-panel-header-button:active,[appearance=dark] devsite-concierge-recommendations-panel .devsite-concierge-panel-header-button:focus,[appearance=dark] devsite-concierge-recommendations-panel .devsite-concierge-panel-header-button:hover{background:#3c3d40}devsite-concierge-recommendations-panel .devsite-concierge-panel-sections{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-moz-box-orient:vertical;-moz-box-direction:normal;-ms-flex-direction:column;flex-direction:column;-webkit-box-flex:1;-webkit-flex-grow:1;-moz-box-flex:1;-ms-flex-positive:1;flex-grow:1;gap:10px;overflow:auto;padding:16px}devsite-concierge-recommendations-panel .devsite-concierge-panel-section{border:var(--devsite-concierge-border);border-radius:8px;-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0}[layout=docs] devsite-concierge-recommendations-panel .devsite-concierge-panel-section h1,[layout=docs] devsite-concierge-recommendations-panel .devsite-concierge-panel-section h2,[layout=docs] devsite-concierge-recommendations-panel .devsite-concierge-panel-section h3,[layout=docs] devsite-concierge-recommendations-panel .devsite-concierge-panel-section h4,[layout=docs] devsite-concierge-recommendations-panel .devsite-concierge-panel-section h5,[layout=docs] devsite-concierge-recommendations-panel .devsite-concierge-panel-section h6{-webkit-margin-end:0;-moz-margin-end:0;margin-inline-end:0;-webkit-padding-end:0;-moz-padding-end:0;padding-inline-end:0}devsite-concierge-recommendations-panel .devsite-concierge-panel-section-header{border-bottom:var(--devsite-concierge-border);padding:14px 16px}devsite-concierge-recommendations-panel .devsite-concierge-panel-section-content{padding:16px}devsite-concierge-recommendations-panel .devsite-concierge-panel-section-fill{min-height:200px;overflow:auto;-webkit-flex-shrink:1;-ms-flex-negative:1;flex-shrink:1}devsite-concierge-recommendations-panel .devsite-concierge-panel-feedback{-webkit-align-self:flex-end;-ms-flex-item-align:end;align-self:flex-end;justify-self:flex-end;-webkit-box-flex:1;-webkit-flex-grow:1;-moz-box-flex:1;-ms-flex-positive:1;flex-grow:1;-webkit-box-align:end;-webkit-align-items:flex-end;-moz-box-align:end;-ms-flex-align:end;align-items:flex-end;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex}devsite-concierge-recommendations-panel .devsite-concierge-panel-section h3{--devsite-h3-margin:0;--devsite-h3-font:700 13px/21px var(--devsite-headline-font-family);font-size:13px;line-height:21px;color:#5f6368}[appearance=dark] devsite-concierge-recommendations-panel .devsite-concierge-panel-section h3{color:#e8eaed}devsite-concierge-recommendations-panel .devsite-concierge-panel-section p{font-weight:400;font-size:13px;line-height:21px;margin:0}[concierge=modal] devsite-concierge-recommendations-panel .devsite-concierge-panel-close,[concierge=modal] devsite-concierge-recommendations-panel .devsite-concierge-panel-fullscreen{display:none}devsite-concierge-recommendations-panel .devsite-concierge-panel-dock{display:none}[concierge=modal] devsite-concierge-recommendations-panel .devsite-concierge-panel-dock{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex}devsite-concierge-recommendations-panel .devsite-concierge-panel-section--loading{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;gap:4px;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-moz-box-orient:vertical;-moz-box-direction:normal;-ms-flex-direction:column;flex-direction:column}devsite-concierge-recommendations-panel .devsite-concierge-panel-section--loading .devsite-concierge-panel-section-header{border-bottom:1px solid transparent}devsite-concierge-recommendations-panel .devsite-concierge-panel-section--loading h2.devsite-concierge-panel-skeleton{height:21px}devsite-concierge-recommendations-panel .devsite-concierge-panel-section--loading .devsite-concierge-panel-skeleton{background:var(--tenant-background-3);border-radius:4px;margin:0 0 4px;font-size:13px;height:21px;-webkit-animation:pulse 2s infinite;animation:pulse 2s infinite}devsite-concierge-recommendations-panel .devsite-concierge-panel-section--loading>.devsite-concierge-panel-skeleton:first-child{width:100%}devsite-concierge-recommendations-panel .devsite-concierge-panel-section--loading>.devsite-concierge-panel-skeleton:nth-child(2){width:50%}devsite-concierge-recommendations-panel .devsite-concierge-panel-section--loading>.devsite-concierge-panel-skeleton:nth-child(3){width:33%}devsite-concierge-recommendations-panel .devsite-concierge-panel-section--loading>.devsite-concierge-panel-skeleton:nth-child(4){width:66%}devsite-concierge-recommendations-panel .devsite-concierge-panel-section--loading>.devsite-concierge-panel-skeleton:nth-child(5){width:25%}devsite-concierge-recommendations-panel .devsite-concierge-panel-section--loading>.devsite-concierge-panel-skeleton:nth-child(6){width:44%}devsite-concierge-recommendations-panel .devsite-concierge-panel-section{border:0}devsite-concierge-recommendations-panel .devsite-concierge-panel-recommendations{-webkit-box-flex:1;-webkit-flex-grow:1;-moz-box-flex:1;-ms-flex-positive:1;flex-grow:1}devsite-concierge-recommendations-panel devsite-recommended-content{--devsite-card-border:var(--devsite-concierge-border)}devsite-concierge-recommendations-panel devsite-recommended-content .skeleton-item{--tenant-primary-border:var(--devsite-concierge-border)}devsite-concierge-recommendations-panel devsite-recommended-content .devsite-recommended-content-list{--devsite-columns:1;--devsite-item-gap:10px}devsite-concierge-recommendations-panel devsite-recommended-content .devsite-recommended-content-item{padding:16px}[appearance=dark] devsite-concierge-recommendations-panel devsite-recommended-content .devsite-recommended-content-item-doc-type:before{color:#9aa0a6}devsite-concierge-recommendations-panel devsite-recommended-content h3.devsite-recommended-content-item-heading{min-height:auto;font-weight:500}[layout=docs] devsite-concierge-recommendations-panel devsite-recommended-content h3.devsite-recommended-content-item-heading,[layout=full] devsite-concierge-recommendations-panel devsite-recommended-content h3.devsite-recommended-content-item-heading{min-height:0;-webkit-margin-end:0;-moz-margin-end:0;margin-inline-end:0;-webkit-padding-end:0;-moz-padding-end:0;padding-inline-end:0}devsite-concierge-recommendations-panel devsite-recommended-content .devsite-recommended-content-item-description{min-height:auto}devsite-concierge-recommendations-panel devsite-recommended-content .skeleton-list{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-moz-box-orient:vertical;-moz-box-direction:normal;-ms-flex-direction:column;flex-direction:column}devsite-concierge-recommendations-panel devsite-recommended-content .skeleton-list .skeleton-item{width:100%}[concierge=modal] devsite-concierge-recommendations-panel .devsite-concierge-panel-sections{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-moz-box-orient:horizontal;-moz-box-direction:normal;-ms-flex-direction:row;flex-direction:row}[concierge=modal] devsite-concierge-recommendations-panel .devsite-concierge-panel-recommendations{-webkit-flex-shrink:1;-ms-flex-negative:1;flex-shrink:1}[concierge=modal] devsite-concierge-recommendations-panel devsite-recommended-content .devsite-recommended-content-list{--devsite-columns:4;--devsite-item-gap:24px}@media screen and (max-width:1253px){[concierge=modal] devsite-concierge-recommendations-panel devsite-recommended-content .devsite-recommended-content-list{--devsite-columns:3}}.devsite-content-excellence-dialog.has-dashboard{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-moz-box-orient:vertical;-moz-box-direction:normal;-ms-flex-direction:column;flex-direction:column;height:100%;padding:0;width:100%}.devsite-content-excellence-dialog.has-dashboard .devsite-dialog-contents{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-moz-box-orient:vertical;-moz-box-direction:normal;-ms-flex-direction:column;flex-direction:column;height:100%;padding:0}.devsite-content-excellence-dialog.has-dashboard .dialog-title{-webkit-border-after:1px solid #dadce0;border-block-end:1px solid #dadce0;display:grid;gap:12px;grid-gap:12px;grid-template-areas:"title message close";grid-template-columns:auto 1fr auto;-webkit-margin-after:8px;margin-block-end:8px;padding-block:20px;padding-inline:24px;width:100%}.devsite-content-excellence-dialog.has-dashboard h3{font:400 18px/30px var(--devsite-headline-font-family);grid-area:title}.devsite-content-excellence-dialog.has-dashboard p{font:14px/20px var(--devsite-primary-font-family);grid-area:message}.devsite-content-excellence-dialog.has-dashboard h3,.devsite-content-excellence-dialog.has-dashboard p{-webkit-align-self:baseline;-ms-flex-item-align:baseline;align-self:baseline;margin:0}.devsite-content-excellence-dialog.has-dashboard .devsite-dialog-close{align-self:flex-start;grid-area:close;margin:-4px}.devsite-content-excellence-dialog.has-dashboard aside{display:grid;grid-template-columns:auto 1fr auto;-webkit-margin-after:12px;margin-block-end:12px;-webkit-margin-before:16px;margin-block-start:16px;margin-inline:auto;max-width:800px}.devsite-content-excellence-dialog.has-dashboard .dismiss-aside{background:var(--devsite-note-notice-background);-webkit-margin-start:16px;-moz-margin-start:16px;margin-inline-start:16px}.devsite-content-excellence-dialog.has-dashboard .dashboard-embed{height:100%;padding-inline:40px;width:100%}.devsite-content-excellence-dialog.has-link h3{text-align:initial}.devsite-content-excellence-dialog.has-link aside{-webkit-margin-after:0;margin-block-end:0}.devsite-content-excellence-dialog.has-link .devsite-dialog-buttons{-webkit-box-pack:start;-webkit-justify-content:flex-start;-moz-box-pack:start;-ms-flex-pack:start;justify-content:flex-start;-webkit-padding-after:16px;padding-block-end:16px;-webkit-padding-before:8px;padding-block-start:8px;padding-inline:16px}devsite-content-footer{clear:both;color:var(--devsite-secondary-text-rgba);display:block;font:13px/20px var(--devsite-primary-font-family)}devsite-content-footer :link,devsite-content-footer :visited{color:var(--devsite-contrast-link-color)}devsite-countdown{--devsite-countdown-box-height:158px;--devsite-countdown-box-margin:0 12px;--devsite-countdown-box-width:220px;--devsite-countdown-display:flex;--devsite-countdown-gap:unset;--devsite-countdown-grid:unset;--devsite-countdown-label-font:500 32px "Google Sans";--devsite-countdown-number-font:700 64px/56px "Google Sans"}@media screen and (max-width:825px){devsite-countdown{--devsite-countdown-box-height:100px;--devsite-countdown-box-margin:0;--devsite-countdown-box-width:100%;--devsite-countdown-display:grid;--devsite-countdown-gap:10px 18px;--devsite-countdown-grid:auto-flow/1fr 1fr;--devsite-countdown-label-font:500 22px "Google Sans";--devsite-countdown-number-font:700 44px/56px "Google Sans"}}devsite-countdown{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;display:var(--devsite-countdown-display);gap:var(--devsite-countdown-gap);grid:var(--devsite-countdown-grid);-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;-ms-flex-pack:center;justify-content:center;padding:20px}devsite-countdown .devsite-countdown-box{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;border:1px solid #dadce0;border-radius:8px;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-moz-box-orient:vertical;-moz-box-direction:normal;-ms-flex-direction:column;flex-direction:column;height:var(--devsite-countdown-box-height);-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;-ms-flex-pack:center;justify-content:center;margin:var(--devsite-countdown-box-margin);width:var(--devsite-countdown-box-width)}devsite-countdown .devsite-countdown-number{font:var(--devsite-countdown-number-font)}devsite-countdown .devsite-countdown-label{font:var(--devsite-countdown-label-font)}devsite-credentials-dialog{border:1px dashed #f439a0;cursor:pointer;padding:2px}.devsite-credentials-dialog .devsite-credentials-dialog-credentials,.devsite-credentials-dialog .devsite-credentials-dialog-oauth-message,.devsite-credentials-dialog .devsite-credentials-dialog-projects{margin-top:16px}.devsite-credentials-dialog devsite-spinner{margin:auto}.devsite-credentials-dialog .devsite-credentials-dialog-selector{width:100%}devsite-cse{display:block}devsite-cse table{border-collapse:inherit;margin:0}devsite-cse tr{background:var(--devsite-background-1);border:0}devsite-cse td{padding:0}devsite-cse .gsc-control-cse,devsite-cse .gsc-control-cse .gsc-table-result{background:0;border:0;font:400 16px/24px var(--devsite-primary-font-family);padding:0}devsite-cse .gsc-above-wrapper-area{display:none}devsite-cse .gsc-results{width:100%}devsite-cse .has-cse-filter .gsc-webResult.gsc-result:has(.gs-spelling){display:none}devsite-cse .gsc-results .gsc-imageResult,devsite-cse .gsc-webResult.gsc-result,devsite-cse .gsc-webResult.gsc-result:hover{background:0}devsite-cse .gsc-results .gsc-cursor-box{margin:8px 0}devsite-cse .gsc-table-result,devsite-cse .gsc-thumbnail-inside,devsite-cse .gsc-url-top{padding-left:0;padding-right:0}devsite-cse .gs-error-result .gs-snippet,devsite-cse .gs-no-results-result .gs-snippet,devsite-cse .gs-webResult:not(.gs-no-results-result):not(.gs-error-result) .gs-snippet{color:var(--devsite-primary-text-color)}devsite-cse .gs-error-result .gs-snippet,devsite-cse .gs-no-results-result .gs-snippet{background:0;border:0;margin:0;padding:0}devsite-cse .gcsc-find-more-on-google{margin:0}devsite-cse .has-cse-filter .gcsc-find-more-on-google{display:none}devsite-cse .gcsc-find-more-on-google,devsite-cse .gsc-control-cse .gs-imageResult a.gs-title:link,devsite-cse .gsc-control-cse .gs-imageResult a.gs-title:link b,devsite-cse .gsc-control-cse .gs-imageResult a.gs-title:visited,devsite-cse .gsc-control-cse .gs-imageResult a.gs-title:visited b,devsite-cse .gsc-control-cse .gs-result .gs-title,devsite-cse .gsc-control-cse .gs-result .gs-title *,devsite-cse .gsc-control-cse .gs-webResult.gs-result a.gs-title:link,devsite-cse .gsc-control-cse .gs-webResult.gs-result a.gs-title:link b,devsite-cse .gsc-control-cse .gs-webResult.gs-result a.gs-title:visited,devsite-cse .gsc-control-cse .gs-webResult.gs-result a.gs-title:visited b{color:var(--devsite-link-color);font:500 16px/24px var(--devsite-primary-font-family);height:auto;text-decoration:none}devsite-cse .gcsc-find-more-on-google-magnifier{fill:var(--devsite-link-color)}devsite-cse .gsc-results .gsc-cursor-box .gsc-cursor-page{background:0;border-color:transparent;color:var(--devsite-link-color)}devsite-cse .gsc-control-cse .gs-imageResult a.gs-title:focus,devsite-cse .gsc-control-cse .gs-result .gs-title:focus,devsite-cse .gsc-control-cse .gs-webResult.gs-result a.gs-title:focus{text-decoration:underline}devsite-cse .gsc-control-cse .gs-result .gs-title b{font-weight:700}devsite-cse .gs-imageResult div.gs-visibleUrl,devsite-cse .gs-webResult div.gs-visibleUrl{color:var(--devsite-search-results-breadcrumb-color);font-size:14px}devsite-cse .gcsc-branding{display:none}devsite-device{display:block;margin:16px 0}devsite-device>.devsite-device-options{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;gap:12px;margin:0 0 24px}devsite-device .devsite-device-input{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;margin:0 0 24px}devsite-device .devsite-device-input>input{-webkit-box-flex:1;-webkit-flex:1;-moz-box-flex:1;-ms-flex:1;flex:1;margin-inline:0 16px}devsite-device [type=radio],devsite-device [type=radio]:after,devsite-device [type=radio]:before{display:none}devsite-device [type=radio]+label{border:var(--devsite-primary-border);box-shadow:none;font:500 14px/36px var(--devsite-headline-font-family);-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;border-radius:16px;color:var(--devsite-link-color);display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;height:32px;padding:0 16px;-webkit-transition:background .2s,border .2s,box-shadow .2s,color .2s;transition:background .2s,border .2s,box-shadow .2s,color .2s}devsite-device [type=radio]+label:focus,devsite-device [type=radio]+label:hover{background:var(--devsite-link-background-active)}devsite-device [type=radio]:checked+label{background:var(--devsite-link-color);border-color:var(--devsite-link-color);color:var(--devsite-inverted-text-color)}devsite-device>.devsite-device{overflow:hidden;position:relative}devsite-device[device=desktop]>.devsite-device{max-width:100%;padding-bottom:62.5%}devsite-device[device=tablet]>.devsite-device{max-width:60%;padding-bottom:80%}devsite-device[device=mobile]>.devsite-device{max-width:32.109375%;padding-bottom:57.109375%}devsite-device iframe{background:var(--devsite-background-1);border:solid var(--devsite-device-border-color);height:166.6666666667%;position:absolute;-webkit-transform:scale(.6);transform:scale(.6);width:166.6666666667%}[dir=ltr] devsite-device iframe{-webkit-transform-origin:0 0;transform-origin:0 0}[dir=rtl] devsite-device iframe{-webkit-transform-origin:100% 0;transform-origin:100% 0}devsite-device[device=desktop] iframe{border-radius:16px;border-width:32px 16px}devsite-device[device=tablet] iframe{border-radius:24px;border-width:60px 16px}devsite-device[device=mobile] iframe{border-radius:36px;border-width:60px 12px}devsite-dropdown-list:not([ready]){background:0;visibility:hidden;position:relative;z-index:2}devsite-dropdown-list[ready]{visibility:visible}devsite-dynamic-content{display:block;margin:var(--devsite-dynamic-content-margin,20px 0);width:100%}.devsite-dynamic-content-display-tag-container{list-style:none;padding:12px 0}.devsite-dynamic-content-display-tag-container:empty{display:none}devsite-dynamic-content .devsite-card-progress{background:var(--devsite-progress-background);height:2px;margin:0 -16px;overflow:hidden;width:auto}devsite-dynamic-content .devsite-card-progress-bar{background:var(--devsite-progress-bar-color);height:2px;-webkit-transform:translateX(-101%);transform:translateX(-101%);-webkit-transition:background .213s cubic-bezier(0,0,.2,1),-webkit-transform .213s cubic-bezier(0,0,.2,1);transition:background .213s cubic-bezier(0,0,.2,1),-webkit-transform .213s cubic-bezier(0,0,.2,1);transition:transform .213s cubic-bezier(0,0,.2,1),background .213s cubic-bezier(0,0,.2,1);transition:transform .213s cubic-bezier(0,0,.2,1),background .213s cubic-bezier(0,0,.2,1),-webkit-transform .213s cubic-bezier(0,0,.2,1)}devsite-dynamic-content .devsite-card-progress-info{font:13px/20px var(--devsite-primary-font-family);margin-top:2px;opacity:0;-webkit-transform:translateY(12px);transform:translateY(12px);-webkit-transition:opacity .213s cubic-bezier(.4,0,1,1),-webkit-transform .213s cubic-bezier(.4,0,1,1);transition:opacity .213s cubic-bezier(.4,0,1,1),-webkit-transform .213s cubic-bezier(.4,0,1,1);transition:transform .213s cubic-bezier(.4,0,1,1),opacity .213s cubic-bezier(.4,0,1,1);transition:transform .213s cubic-bezier(.4,0,1,1),opacity .213s cubic-bezier(.4,0,1,1),-webkit-transform .213s cubic-bezier(.4,0,1,1)}devsite-dynamic-content .devsite-card-progress-info.show{opacity:1;-webkit-transform:translateY(0);transform:translateY(0);-webkit-transition:opacity .213s cubic-bezier(0,0,.2,1),-webkit-transform .213s cubic-bezier(0,0,.2,1);transition:opacity .213s cubic-bezier(0,0,.2,1),-webkit-transform .213s cubic-bezier(0,0,.2,1);transition:transform .213s cubic-bezier(0,0,.2,1),opacity .213s cubic-bezier(0,0,.2,1);transition:transform .213s cubic-bezier(0,0,.2,1),opacity .213s cubic-bezier(0,0,.2,1),-webkit-transform .213s cubic-bezier(0,0,.2,1)}devsite-dynamic-content .devsite-card-progress-info:empty:before{content:" "}.devsite-dynamic-content-display-tag{background:var(--devsite-background-3);border-radius:var(--devsite-display-tag-border-radius);color:var(--devsite-display-tag-color,var(--devsite-secondary-text-color));display:inline-block;font:var(--devsite-display-tag-font,500 14px/20px var(--devsite-primary-font-family));margin-block:0 12px;margin-inline:0 4px;padding:var(--devsite-display-tag-padding,1px 8px)}devsite-dynamic-content .devsite-label-confidential{font:500 11px/16px var(--devsite-primary-font-family);letter-spacing:.8px;background:var(--devsite-caution-notice-background);border-radius:var(--devsite-label-border-radius,4px);color:var(--devsite-caution-notice-color);display:inline-block;margin-block:0 8px;padding-block:5px 3px;padding-inline:8px;text-transform:uppercase}devsite-dynamic-content .devsite-dynamic-content-no-results{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;background:var(--devsite-background-1);border:var(--devsite-secondary-border);border-radius:var(--devsite-card-border-radius);display:-webkit-inline-box;display:-webkit-inline-flex;display:-moz-inline-box;display:-ms-inline-flexbox;display:inline-flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;gap:32px;-webkit-box-pack:justify;-webkit-justify-content:space-between;-moz-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;max-width:100%;padding:25px 55px;width:100%}devsite-dynamic-content .devsite-dynamic-content-no-results-image{display:var(--devsite-dynamic-content-no-results-image-display,block);max-width:100%;width:250px}devsite-dynamic-content devsite-pagination{margin-top:20px}devsite-dynamic-hero{display:none}devsite-dynamic-hero img{object-fit:contain;padding:50px}devsite-dynamic-hero .scale-down img{max-height:180px;object-fit:scale-down;padding:0}devsite-dynamic-hero a:focus{text-decoration:none}devsite-dynamic-hero .devsite-landing-row-item-description-content{-webkit-box-orient:vertical;display:-webkit-box;-webkit-line-clamp:2;max-width:90%;overflow:hidden;text-overflow:ellipsis}devsite-dynamic-hero .devsite-landing-row-item-image .material-icons{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;font-size:190px;-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;-ms-flex-pack:center;justify-content:center;padding:55px}.dgc-hero.fade-in{-webkit-animation:dynamic-hero-fade-in 1s;animation:dynamic-hero-fade-in 1s;background:url(../images/dynamic-hero-background.svg) 100%/contain no-repeat;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-moz-box-orient:vertical;-moz-box-direction:normal;-ms-flex-direction:column;flex-direction:column;-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;-ms-flex-pack:center;justify-content:center}[appearance=dark] .dgc-hero.fade-in{background-image:url(../images/dynamic-hero-background-dark.svg)}.dgc-hero.fade-in devsite-dynamic-hero{display:block}.dgc-hero.fade-out{-webkit-animation:dynamic-hero-fade-out .5s forwards;animation:dynamic-hero-fade-out .5s forwards}.dgc-dynamic-hero{display:none}@media screen and (max-width:840px){.dgc-hero.fade-in{background-image:url(../images/dynamic-hero-background-cropped.svg)}[appearance=dark] .dgc-hero.fade-in{background-image:url(../images/dynamic-hero-background-dark-cropped.svg)}devsite-dynamic-hero .devsite-landing-row-item-image .material-icons,devsite-dynamic-hero img{padding:0 30px 0 0}devsite-dynamic-hero .devsite-landing-row-item-description-content{-webkit-line-clamp:3;max-width:100%}}@media screen and (max-width:600px){.dgc-hero.fade-in{background:unset}[appearance=dark] .dgc-hero.fade-in{background:unset}devsite-dynamic-hero .devsite-landing-row-item-image .material-icons,devsite-dynamic-hero img{padding:0}}@-webkit-keyframes dynamic-hero-fade-in{0%{opacity:0}to{opacity:1}}@keyframes dynamic-hero-fade-in{0%{opacity:0}to{opacity:1}}@-webkit-keyframes dynamic-hero-fade-out{0%{opacity:1}to{opacity:0}}@keyframes dynamic-hero-fade-out{0%{opacity:1}to{opacity:0}}.pac-container{z-index:2000}devsite-edit-profile{display:grid;grid:auto/calc(50% - 12px) calc(50% - 12px);margin-block:0 18px;margin-inline:24px;gap:20px}devsite-edit-profile .waiting-container{margin:auto}devsite-edit-profile .devsite-edit-profile-error-incorrect,devsite-edit-profile .devsite-edit-profile-error-missing{display:none;color:#e53935;font-size:12px;margin:2px 0 0 14px}devsite-edit-profile .devsite-edit-profile-textarea{grid-column:1/3;min-height:110px}devsite-edit-profile .devsite-edit-profile-input{display:block;position:relative;min-height:86px}devsite-edit-profile .devsite-edit-profile-input[incorrect] .devsite-edit-profile-error-incorrect,devsite-edit-profile .devsite-edit-profile-input[missing] .devsite-edit-profile-error-missing{display:inline-block}devsite-edit-profile .devsite-edit-profile-input-length,devsite-edit-profile .devsite-edit-profile-private-chip{color:var(--devsite-secondary-text-color);font-size:12px;font-weight:500;margin:2px 0 0 14px;display:inline-block}devsite-edit-profile .devsite-edit-profile-input-length .material-symbols-outlined,devsite-edit-profile .devsite-edit-profile-private-chip .material-symbols-outlined{font-size:12px;font-variation-settings:"FILL" 0,"wght" 400,"GRAD" 0,"opsz" 48;top:2px;position:relative}devsite-edit-profile.devsite-edit-profile-small{grid:auto/auto}devsite-edit-profile.devsite-edit-profile-small .devsite-edit-profile-textarea{grid-column:unset}devsite-expandable{display:block;min-height:24px}devsite-expandable:not([expanded])>:not(.showalways):not(.expand-control):not(.exw-control){display:none}devsite-expandable .exw-control>h2.showalways{margin:40px 0 20px;padding-bottom:7px}devsite-expandable .exw-control>h3.showalways{margin:34px 0 20px}devsite-expandable .exw-control>h4.showalways{margin:36px 0 20px}devsite-expandable .expand-control:not(button):not(.button){color:var(--devsite-link-color);cursor:pointer}devsite-expandable a.exw-control:active,devsite-expandable a.exw-control:focus,devsite-expandable a.exw-control:hover{color:var(--devsite-link-color);cursor:pointer;outline:0;text-decoration:none}devsite-expandable a.exw-control>.showalways:before{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;color:var(--devsite-secondary-text-color);content:"add_circle";display:-webkit-inline-box;display:-webkit-inline-flex;display:-moz-inline-box;display:-ms-inline-flexbox;display:inline-flex;font:normal normal normal 24px/1 Material Icons;-webkit-font-feature-settings:"liga";-moz-font-feature-settings:"liga";font-feature-settings:"liga";-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;text-transform:none;word-wrap:normal;height:20px;-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-margin-end:12px;-moz-margin-end:12px;margin-inline-end:12px;-webkit-transform:translate3d(0,-1px,0);transform:translate3d(0,-1px,0);-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;vertical-align:middle;width:20px}devsite-expandable.arrow-icon a.exw-control>.showalways:before{content:"chevron_right"}[dir=rtl] devsite-expandable.arrow-icon a.exw-control>.showalways:before{content:"chevron_left"}devsite-expandable .exw-control>h2.showalways:before{-webkit-transform:translate3d(0,-2px,0);transform:translate3d(0,-2px,0)}devsite-expandable[expanded]>a.exw-control>.showalways:before{content:"remove_circle"}devsite-expandable.arrow-icon[expanded]>a.exw-control>.showalways:before{content:"keyboard_arrow_down"}devsite-expandable a.exw-control:focus>.showalways:before,devsite-expandable a.exw-control:hover>.showalways:before{color:var(--devsite-link-color)}devsite-expandable .collapse-content-msg,devsite-expandable[expanded] .expand-content-msg{display:none}devsite-expandable[expanded] .collapse-content-msg{display:inline}devsite-content devsite-expandable devsite-expandable{margin-left:40px}devsite-extradory{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center}devsite-extradory .devsite-extra-dory-iframe{width:100%;height:100%;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;-ms-flex-pack:center;justify-content:center}devsite-extradory .devsite-extra-dory-iframe iframe{width:100%;height:100%;border:0}devsite-extradory h2{font-size:24px;color:#424242;text-align:center;line-height:32px;margin:0;-webkit-align-self:center;-ms-flex-item-align:center;align-self:center}devsite-extradory .devsite-extradory-create-profile{-webkit-align-self:center;-ms-flex-item-align:center;align-self:center}devsite-extradory .devsite-extradory-step1,devsite-extradory .devsite-extradory-step2,devsite-extradory .devsite-extradory-wrapper{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-moz-box-orient:vertical;-moz-box-direction:normal;-ms-flex-direction:column;flex-direction:column;-webkit-box-align:start;-webkit-align-items:start;-moz-box-align:start;-ms-flex-align:start;align-items:start;width:100%;padding:20px}devsite-extradory .devsite-extradory-create-profile{margin-top:26px}devsite-extradory p{font-size:16px;color:#424242;line-height:24px}devsite-extradory .devsite-extradory-cta label,devsite-extradory .devsite-extradory-cta p{font-size:14px;color:#424242;line-height:29px;margin:0}devsite-extradory .devsite-extradory-buttons,devsite-extradory .devsite-extradory-join-group,devsite-extradory .devsite-extradory-try-again-buttons{margin-top:36px}devsite-extradory .devsite-extradory-spinner{padding:64px;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;-ms-flex-pack:center;justify-content:center;width:100%}devsite-extradory .devsite-extradory-try-again-buttons{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;-ms-flex-pack:center;justify-content:center;width:100%}devsite-extradory .devsite-extradory-authorize,devsite-extradory .devsite-extradory-change-account,devsite-extradory .devsite-extradory-join-group,devsite-extradory .devsite-extradory-not-eligible,devsite-extradory .devsite-extradory-sign-in,devsite-extradory .devsite-extradory-try-again{-webkit-align-self:center;-ms-flex-item-align:center;align-self:center}.devsite-fast-track-creator-dialog{padding:24px}devsite-fast-track-profile-creator label{font-size:16px}devsite-fast-track-profile-creator h4{margin:0 0 10px}devsite-fast-track-profile-creator .sub-text{color:var(--devsite-secondary-text-color);font:400 12px/16px var(--devsite-primary-font-family);letter-spacing:.3px;-webkit-padding-start:16px;-moz-padding-start:16px;padding-inline-start:16px;margin:5px 0 20px}devsite-fast-track-profile-creator .tos{margin:12px 0 24px}devsite-fast-track-profile-creator devsite-spinner{margin-right:8px}devsite-fast-track-profile-creator .devsite-devprofile-callout-buttons{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-pack:end;-webkit-justify-content:end;-moz-box-pack:end;-ms-flex-pack:end;justify-content:end}devsite-feature-tooltip:not([ready])>[slot]{display:none}devsite-feature-tooltip{display:block}devsite-feature-tooltip [slot].step{display:none}devsite-feature-tooltip [slot].step.current{display:block}devsite-dialog.devsite-feedback .devsite-dialog-contents{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-moz-box-orient:vertical;-moz-box-direction:normal;-ms-flex-direction:column;flex-direction:column;padding:0}devsite-dialog.devsite-feedback h3{margin:0 0 20px;padding:16px 16px 0}devsite-dialog.devsite-feedback .devsite-feedback-items{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;padding:0 6px}devsite-dialog.devsite-feedback .devsite-feedback-item{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;color:var(--devsite-secondary-text-color);display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-flex:1;-webkit-flex:1 0 0;-moz-box-flex:1;-ms-flex:1 0 0px;flex:1 0 0;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-moz-box-orient:vertical;-moz-box-direction:normal;-ms-flex-direction:column;flex-direction:column;text-decoration:none}devsite-dialog.devsite-feedback .devsite-feedback-item-type{color:var(--devsite-link-color)}devsite-dialog.devsite-feedback .devsite-feedback-item:focus>.devsite-feedback-item-type{text-decoration:underline}devsite-dialog.devsite-feedback .devsite-feedback-item-icon-container{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;height:48px;-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;-ms-flex-pack:center;justify-content:center;margin:8px 0;width:48px}devsite-dialog.devsite-feedback .devsite-feedback-item-icon-color{background-color:var(--devsite-feedback-icon-background,var(--devsite-primary-color,var(--devsite-primary-text-color)));border-radius:50%;color:var(--devsite-inverted-text-color)}devsite-dialog.devsite-feedback .devsite-feedback-item-icon{font-size:32px}devsite-dialog.devsite-feedback .devsite-feedback-item-icon-container img{max-width:100%}devsite-dialog.devsite-feedback .devsite-feedback-notice,devsite-dialog.devsite-feedback .devsite-feedback-support{padding:16px 16px 0;text-align:center}devsite-dialog.devsite-feedback .devsite-feedback-support-icon{font-size:18px;margin-right:4px;vertical-align:middle}devsite-dialog.devsite-feedback .devsite-feedback-support-icon+span{vertical-align:middle}devsite-dialog.devsite-feedback .devsite-feedback-buttons{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-pack:end;-webkit-justify-content:flex-end;-moz-box-pack:end;-ms-flex-pack:end;justify-content:flex-end;padding:var(--devsite-feedback-buttons-padding,16px 0 0)}devsite-filter{display:block}.devsite-filter-input,devsite-filter input[type=text]{--devsite-input-width:100%}devsite-filter>.devsite-table-wrapper:first-child>table{margin-top:0}devsite-filter [results-count-container]{color:var(--devsite-filter-results-count-color);font-family:var(--devsite-filter-results-count-font-family);margin:var(--devsite-filter-results-count-margin,16px 0)}devsite-filter[sortable] th:hover{cursor:pointer}devsite-filter th[sort-ascending],devsite-filter th[sort-descending]{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}devsite-filter th[sort-ascending]:after,devsite-filter th[sort-descending]:after{content:"arrow_drop_down";display:inline-block;font:normal normal normal 24px/1 Material Icons;-webkit-font-feature-settings:"liga";-moz-font-feature-settings:"liga";font-feature-settings:"liga";-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;text-transform:none;word-wrap:normal;margin:-2px 0 0;position:absolute;-webkit-transform:rotate(0deg);transform:rotate(0deg);-webkit-transition:-webkit-transform .2s;transition:-webkit-transform .2s;transition:transform .2s;transition:transform .2s,-webkit-transform .2s;vertical-align:middle}devsite-filter th[sort-descending]:after{-webkit-transform:rotate(-180deg);transform:rotate(-180deg)}devsite-filter[hide-if-empty][empty]{display:none}devsite-filter[highlight] mark{background-color:#ffe168}devsite-filter[highlight] mark:after,devsite-filter[highlight] mark:before{-webkit-clip-path:inset(100%);clip-path:inset(100%);clip:rect(1px,1px,1px,1px);height:1px;overflow:hidden;position:absolute;white-space:nowrap;width:1px}devsite-filter[highlight] mark:before{content:" [highlight start] "}devsite-filter[highlight] mark:after{content:" [highlight end] "}devsite-filter .devsite-filter-input-container{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-flex:1;-webkit-flex-grow:1;-moz-box-flex:1;-ms-flex-positive:1;flex-grow:1;position:relative}devsite-filter .devsite-filter-clear-button{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;color:var(--devsite-searchbox-placeholder,var(--devsite-secondary-text-color));cursor:pointer;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;font:normal normal normal 14px/1 Material Icons;height:var(--devsite-input-height,36px);inset-inline:auto 0;-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;-ms-flex-pack:center;justify-content:center;outline:0;position:absolute;width:var(--devsite-input-height,36px)}devsite-filter .devsite-filter-clear-button:before{content:"close"}devsite-filter .devsite-filter-clear-button:focus:before,devsite-filter .devsite-filter-clear-button:hover:before{background:var(--devsite-background-5);border-radius:50%;padding:4px}devsite-footer-linkboxes{background:var(--devsite-footer-background,var(--devsite-background-1));color:var(--devsite-footer-color);display:block;font:var(--devsite-footer-linkboxes-font,400 14px/16px var(--devsite-primary-font-family));padding:var(--devsite-footer-linkboxes-padding)}devsite-footer-linkboxes .devsite-footer-linkboxes-list{border-bottom:var(--devsite-primary-border);display:grid;grid-gap:24px;grid-template-columns:var(--devsite-footer-linkboxes-grid-template-columns);list-style:none;padding:24px 0}devsite-footer-linkboxes .devsite-footer-linkbox{margin:0}devsite-footer-linkboxes .devsite-footer-linkbox-heading{font:var(--devsite-footer-heading-font,500 14px/16px var(--devsite-primary-font-family));margin:var(--devsite-footer-heading-margin,0 0 8px);text-transform:var(--devsite-footer-heading-text-transform)}devsite-footer-linkboxes .devsite-footer-linkbox-list .devsite-footer-linkbox-heading{margin:var(--devsite-footer-list-heading-margin,40px 0 0)}devsite-footer-linkboxes .devsite-footer-linkbox-list{list-style-type:none;padding:0}devsite-footer-linkboxes .devsite-footer-linkbox-item{margin:0}devsite-footer-linkboxes .devsite-footer-linkbox-link{color:var(--devsite-footer-link-color,var(--devsite-primary-text-color));display:inline-block;padding:8px 0}devsite-footer-linkboxes .devsite-footer-linkbox-link:focus,devsite-footer-linkboxes .devsite-footer-linkbox-link:hover{color:var(--devsite-footer-link-hover,var(--devsite-link-color));font-weight:var(--devsite-footer-link-font-weight-hover);text-decoration:none}devsite-footer-linkboxes .devsite-footer-linkbox-description{color:var(--devsite-secondary-text-color);font:var(--devsite-footer-description-font,14px/20px var(--devsite-primary-font-family));margin:0 0 16px}devsite-footer-linkboxes .devsite-footer-linkbox-icon{margin-block:0 4px}devsite-footer-promos{background:var(--devsite-footer-background,var(--devsite-background-1));border-top:var(--devsite-footer-border,var(--devsite-primary-border));color:var(--devsite-footer-color);display:block;font:14px/20px var(--devsite-primary-font-family);padding:0 24px}devsite-footer-promos .devsite-footer-promos-list{border-bottom:var(--devsite-primary-border);display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;gap:0 24px;list-style:none;-webkit-justify-content:space-around;-ms-flex-pack:distribute;justify-content:space-around;padding:18px 0}devsite-footer-promos .devsite-footer-promo{-webkit-box-flex:0;-webkit-flex:0 1 192px;-moz-box-flex:0;-ms-flex:0 1 192px;flex:0 1 192px;margin:20px 0;text-align:center}devsite-footer-promos .devsite-footer-promo-icon{color:var(--devsite-text-color,var(--devsite-primary-text-rgba));display:block;font-size:48px;height:48px;margin-block:0 8px;margin-inline:auto;width:48px}devsite-footer-promos .devsite-footer-promo-title{color:var(--devsite-footer-heading-color,var(--devsite-primary-text-rgba));display:block;font:var(--devsite-footer-heading-font);font-weight:var(--devsite-footer-heading-font-weight,500)}devsite-footer-promos .devsite-footer-promo-title:focus,devsite-footer-promos .devsite-footer-promo-title:hover{color:var(--devsite-footer-link-hover,var(--devsite-link-color));font-weight:var(--devsite-footer-link-font-weight-hover);text-decoration:none}@media screen and (max-width:1253px){.devsite-main-content[has-book-nav]~devsite-footer-promos .devsite-footer-promos-list{-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;gap:unset;-webkit-box-pack:start;-webkit-justify-content:flex-start;-moz-box-pack:start;-ms-flex-pack:start;justify-content:flex-start}.devsite-main-content[has-book-nav]~devsite-footer-promos .devsite-footer-promo{-webkit-box-flex:0;-webkit-flex:0 0 50%;-moz-box-flex:0;-ms-flex:0 0 50%;flex:0 0 50%;padding-block:0;padding-inline:20px}}@media screen and (max-width:840px){.devsite-main-content[has-book-nav]~devsite-footer-promos .devsite-footer-promos-list,devsite-footer-promos .devsite-footer-promos-list{-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-pack:start;-webkit-justify-content:flex-start;-moz-box-pack:start;-ms-flex-pack:start;justify-content:flex-start;padding:12px 0}.devsite-main-content[has-book-nav]~devsite-footer-promos .devsite-footer-promo,devsite-footer-promos .devsite-footer-promo{-webkit-box-flex:0;-webkit-flex:0 0 50%;-moz-box-flex:0;-ms-flex:0 0 50%;flex:0 0 50%;margin:0;padding-block:8px;padding-inline:0;text-align:start}devsite-footer-promos .devsite-footer-promo-icon{height:32px;margin-block:0;margin-inline:0 8px;width:32px}devsite-footer-promos .devsite-footer-promo-title{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;font-weight:400}devsite-footer-promos .devsite-footer-promo-description{display:none}}@media screen and (max-width:600px){devsite-footer-promos{padding:0 16px}devsite-footer-promos .devsite-footer-promos-list{display:block}}devsite-footer-utility{background:var(--devsite-footer-background,var(--devsite-background-1));color:var(--devsite-footer-color);display:block;font:400 14px/16px var(--devsite-primary-font-family);padding:0 24px}devsite-footer-utility .devsite-footer-sites-list,devsite-footer-utility .devsite-footer-sites-logo-link,devsite-footer-utility .devsite-footer-utility-button,devsite-footer-utility .devsite-footer-utility-item,devsite-footer-utility .devsite-footer-utility-list,devsite-footer-utility nav{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex}devsite-footer-utility .devsite-footer-utility-button,devsite-footer-utility .devsite-footer-utility-list,devsite-footer-utility nav{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center}devsite-footer-utility nav{gap:16px;padding:24px 0}devsite-footer-utility .devsite-footer-sites,devsite-footer-utility .devsite-footer-sites-list{gap:0 40px}devsite-footer-utility .devsite-footer-sites{-webkit-border-after:var(--devsite-primary-border);border-block-end:var(--devsite-primary-border);padding:24px 0 23px}devsite-footer-utility .devsite-footer-sites-list,devsite-footer-utility .devsite-footer-utility-list{-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;list-style:none;padding:0}devsite-footer-utility .devsite-footer-sites-item,devsite-footer-utility .devsite-footer-utility-item{margin:0}devsite-footer-utility .devsite-footer-sites-link{color:var(--devsite-primary-text-color);display:block;padding:8px 0}devsite-footer-utility .devsite-footer-sites-link:focus,devsite-footer-utility .devsite-footer-sites-link:hover{color:var(--devsite-link-color);text-decoration:none}devsite-footer-utility .devsite-footer-sites-logo{height:32px;margin-top:-4px;width:185px}devsite-footer-utility .devsite-footer-utility-links,devsite-footer-utility .devsite-footer-utility-list{-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}devsite-footer-utility .devsite-footer-utility-list{gap:16px 8px;-webkit-box-flex:var(--devsite-footer-utility-list-flex,1);-webkit-flex:var(--devsite-footer-utility-list-flex,1);-moz-box-flex:var(--devsite-footer-utility-list-flex,1);-ms-flex:var(--devsite-footer-utility-list-flex,1);flex:var(--devsite-footer-utility-list-flex,1);min-height:36px}devsite-footer-utility .devsite-footer-utility-link{color:var(--devsite-footer-link-color,var(--devsite-primary-text-color))}devsite-footer-utility .devsite-footer-utility-link:focus,devsite-footer-utility .devsite-footer-utility-link:hover{color:var(--devsite-footer-link-hover,var(--devsite-link-color))}devsite-footer-utility a:focus,devsite-footer-utility a:hover{font-weight:var(--devsite-footer-link-font-weight-hover)}devsite-footer-utility .devsite-footer-utility-item{-webkit-box-flex:0;-webkit-flex:0 0 auto;-moz-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto}devsite-footer-utility .devsite-footer-utility-item-centered{margin:0 auto}devsite-footer-utility .devsite-footer-utility-button{gap:0 16px;line-height:20px;margin-inline:auto 0}devsite-footer-utility .devsite-footer-utility-button>a:focus{text-decoration:none}devsite-footer-utility .devsite-footer-utility-item:before{content:"|";-webkit-margin-end:8px;-moz-margin-end:8px;margin-inline-end:8px}devsite-footer-utility .devsite-footer-utility-button:before,devsite-footer-utility .devsite-footer-utility-item-centered:before,devsite-footer-utility .devsite-footer-utility-item-no-marker:before,devsite-footer-utility .devsite-footer-utility-item:first-child:before{content:"";-webkit-margin-end:0;-moz-margin-end:0;margin-inline-end:0}devsite-footer-utility devsite-language-selector{-webkit-align-self:flex-end;-ms-flex-item-align:end;align-self:flex-end;margin:var(--devsite-language-selector-margin,0)}@media screen and (max-width:1253px){[has-book-nav]~devsite-footer-utility .devsite-footer-sites,[has-book-nav]~devsite-footer-utility .devsite-footer-sites-list{-webkit-box-align:start;-webkit-align-items:start;-moz-box-align:start;-ms-flex-align:start;align-items:start;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-moz-box-orient:vertical;-moz-box-direction:normal;-ms-flex-direction:column;flex-direction:column}[has-book-nav]~devsite-footer-utility .devsite-footer-sites{gap:16px 0}}@media screen and (max-width:840px){devsite-footer-utility .devsite-footer-sites,devsite-footer-utility .devsite-footer-sites-list{-webkit-box-align:start;-webkit-align-items:start;-moz-box-align:start;-ms-flex-align:start;align-items:start;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-moz-box-orient:vertical;-moz-box-direction:normal;-ms-flex-direction:column;flex-direction:column}devsite-footer-utility .devsite-footer-sites{gap:16px 0}devsite-footer-utility .devsite-footer-utility-list{-webkit-box-flex:100%;-webkit-flex:100%;-moz-box-flex:100%;-ms-flex:100%;flex:100%}devsite-footer-utility .devsite-footer-utility-button{-webkit-box-flex:100%;-webkit-flex:100%;-moz-box-flex:100%;-ms-flex:100%;flex:100%;margin-inline:0}devsite-footer-utility .devsite-footer-utility-button:before{display:none}}@media screen and (max-width:600px){devsite-footer-utility{padding:0 16px}devsite-footer-utility .devsite-footer-utility-item-centered{margin:12px 0}}.devsite-fully-clickable{background-color:var(--devsite-fully-clickable-background,var(--devsite-background-color));border-radius:var(--devsite-fully-clickable-border-radius);position:relative}.devsite-fully-clickable:before{border-radius:var(--devsite-fully-clickable-border-radius);box-shadow:var(--devsite-fully-clickable-box-shadow,0 14px 25px 0 rgba(60,64,67,.08),0 4px 13px 0 rgba(60,64,67,.12));content:"";display:block;height:100%;left:0;opacity:0;pointer-events:none;position:absolute;top:0;-webkit-transition:opacity .2s ease-out;transition:opacity .2s ease-out;width:100%}.devsite-fully-clickable:focus-within:before,.devsite-fully-clickable:hover:before{opacity:1}.devsite-fully-clickable:active:before{opacity:.4}.devsite-fully-clickable-link:active,.devsite-fully-clickable-link:focus,.devsite-fully-clickable-link:hover{-webkit-transform:none!important;transform:none!important}.devsite-fully-clickable-link:not(.button):active,.devsite-fully-clickable-link:not(.button):focus,.devsite-fully-clickable-link:not(.button):hover{text-decoration:none!important}.devsite-fully-clickable-link:before{bottom:0;content:"";display:block;left:0;position:absolute;right:0;top:0;z-index:1}devsite-googler-buttons{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;bottom:calc(var(--devsite-panel-height, 0px) + 24px);display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;font:normal normal normal 24px/1 Material Icons;-webkit-font-feature-settings:"liga";-moz-font-feature-settings:"liga";font-feature-settings:"liga";-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;text-transform:none;word-wrap:normal;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-moz-box-orient:vertical;-moz-box-direction:normal;-ms-flex-direction:column;flex-direction:column;position:fixed;z-index:1004}[dir=ltr] [concierge] devsite-googler-buttons{right:calc(12px + var(--devsite-concierge-width))}[dir=ltr] [concierge=modal] devsite-googler-buttons,[dir=ltr] devsite-googler-buttons{right:24px}[dir=rtl] [concierge] devsite-googler-buttons{left:calc(12px + var(--devsite-concierge-width))}[dir=rtl] [concierge=modal] devsite-googler-buttons,[dir=rtl] devsite-googler-buttons{left:24px}devsite-googler-buttons>a:focus{text-decoration:none}devsite-googler-buttons .devsite-googler-button{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;background:var(--devsite-background-1);border-radius:50%;cursor:pointer;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;height:40px;-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;-ms-flex-pack:center;justify-content:center;margin:-48px auto;outline:0;position:relative;-webkit-transition:background .2s,box-shadow .2s,margin .2s;transition:background .2s,box-shadow .2s,margin .2s;width:40px}devsite-googler-buttons[active] .devsite-googler-button{box-shadow:0 1px 3px 0 var(--devsite-elevation-key-shadow-color),0 4px 8px 3px var(--devsite-elevation-ambient-shadow-color);margin:4px auto}devsite-googler-buttons .devsite-googler-button:focus,devsite-googler-buttons .devsite-googler-button:hover,devsite-googler-buttons a:focus>.devsite-googler-button{background:#e3f2fd}devsite-googler-buttons .devsite-googler-button:active,devsite-googler-buttons a:active>.devsite-googler-button{background:#bbdefb}devsite-googler-buttons .devsite-googler-admin:before{color:#80868b;content:"storage"}devsite-googler-buttons .devsite-googler-page-insights:before{color:#12b5cb;content:"bar_chart"}devsite-googler-buttons .devsite-googler-analytics:before{color:#e8710a;content:"timeline"}devsite-googler-buttons .devsite-googler-bug:before{color:#e52592;content:"bug_report"}devsite-googler-buttons .devsite-googler-cache{background:#689f38}devsite-googler-buttons .devsite-googler-cache:hover{background:#7cb342}devsite-googler-buttons .devsite-googler-cache:active,devsite-googler-buttons .devsite-googler-cache:focus{background:#8bc34a}devsite-googler-buttons .devsite-googler-cache[active]{background:#d93025}devsite-googler-buttons .devsite-googler-cache[active]:hover{background:#ea4335}devsite-googler-buttons .devsite-googler-cache[active]:active,devsite-googler-buttons .devsite-googler-cache[active]:focus{background:#ee675c}devsite-googler-buttons .devsite-googler-cache:before{color:var(--devsite-inverted-text-color);content:"cached"}devsite-googler-buttons .devsite-googler-cache[active]:after{background:var(--devsite-background-1);border-bottom:2px solid #d93025;content:"";display:block;height:4px;position:absolute;-webkit-transform:rotate(45deg) translateY(1px);transform:rotate(45deg) translateY(1px);width:28px}devsite-googler-buttons .devsite-googler-cache[active]:active:after,devsite-googler-buttons .devsite-googler-cache[active]:focus:after{border-color:#ee675c}devsite-googler-buttons .devsite-googler-devrel:before{color:#607d8b;content:"build"}devsite-googler-buttons .devsite-googler-edit:before{color:#689f38;content:"edit"}devsite-googler-buttons .devsite-googler-source:before{color:#1e88e5;content:"code"}devsite-googler-buttons .devsite-googler-env:before{color:#673ab7;content:"swap_horiz"}devsite-googler-buttons .devsite-googler-content-excellence:before{color:#1e88e5;content:"local_police"}devsite-googler-buttons .devsite-googler-speed-dial{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;box-shadow:0 1px 3px 0 var(--devsite-elevation-key-shadow-color),0 4px 8px 3px var(--devsite-elevation-ambient-shadow-color);height:56px;margin:0;width:56px}devsite-googler-buttons[active] .devsite-googler-speed-dial{margin:16px 0 0}devsite-googler-buttons .devsite-googler-speed-dial:before{content:url(../../images/fab.svg);-webkit-transition:-webkit-transform .2s;transition:-webkit-transform .2s;transition:transform .2s;transition:transform .2s,-webkit-transform .2s}devsite-googler-buttons[active] .devsite-googler-speed-dial:before{content:"close";-webkit-transform:rotate(90deg);transform:rotate(90deg)}devsite-header{display:block;position:relative;z-index:1006}body[ready] devsite-header[fixed]{contain:layout;pointer-events:none;position:fixed;top:0;width:100%}body[ready][concierge] devsite-header[fixed]{contain:unset;top:auto;position:static;z-index:unset}devsite-header .devsite-top-logo-row-wrapper-wrapper{border-bottom:var(--devsite-header-border,0);position:relative;z-index:1}body[ready][concierge] devsite-header[fixed] .devsite-top-logo-row-wrapper-wrapper{position:fixed;z-index:1007;left:0;right:0}devsite-header .devsite-top-logo-row-wrapper-wrapper,devsite-header .devsite-top-logo-row-wrapper-wrapper:before{background:var(--devsite-header-color-upper,var(--devsite-background-1))}body[ready] devsite-header[fixed] .devsite-top-logo-row-wrapper-wrapper:before{content:"";height:400px;position:absolute;-webkit-transform:translateY(-400px);transform:translateY(-400px);width:100%}devsite-header[fixed] .devsite-top-logo-row-wrapper-wrapper{pointer-events:all}devsite-header .devsite-collapsible-section{position:relative}body[ready][concierge] devsite-header[fixed] .devsite-collapsible-section{position:fixed;left:0;right:0;top:var(--devsite-js-top-row--height,49px);z-index:1005}[dir=ltr] body[ready][concierge] devsite-header[fixed] .devsite-collapsible-section{right:var(--devsite-concierge-width,0)}[dir=rtl] body[ready][concierge] devsite-header[fixed] .devsite-collapsible-section{left:var(--devsite-concierge-width,0)}devsite-header .devsite-collapsible-section,devsite-header[no-lower-row][fixed]{box-shadow:var(--devsite-header-lower-box-shadow,0 1px 2px 0 var(--devsite-elevation-key-shadow-color),0 2px 6px 2px var(--devsite-elevation-ambient-shadow-color))}devsite-header[fixed] .devsite-collapsible-section{contain:style;pointer-events:all;-webkit-transform:translateZ(0);transform:translateZ(0);will-change:transform}devsite-header .devsite-top-logo-row{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;background:var(--devsite-header-color-upper,var(--devsite-background-1));display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;gap:16px;height:48px;padding:0 16px 0 24px;position:relative;-webkit-transform:translateZ(0);transform:translateZ(0)}[dir=rtl] devsite-header .devsite-top-logo-row{padding:0 24px 0 16px}devsite-header .devsite-top-button{background:var(--devsite-header-link-background,0);border-radius:var(--devsite-header-link-border-radius,var(--devsite-button-border-radius,2px));color:var(--devsite-header-link-color,var(--devsite-secondary-text-rgba));padding:var(--devsite-header-link-padding,0 8px);-webkit-text-decoration:var(--devsite-header-link-text-decoration);-moz-text-decoration:var(--devsite-header-link-text-decoration);text-decoration:var(--devsite-header-link-text-decoration);-webkit-transition:background .2s,box-shadow .2s,color .2s;transition:background .2s,box-shadow .2s,color .2s}devsite-header .devsite-top-button,devsite-header .devsite-top-button:active,devsite-header .devsite-top-button:focus,devsite-header .devsite-top-button:hover{border:0}devsite-header .devsite-top-button:active,devsite-header .devsite-top-button:focus,devsite-header .devsite-top-button:hover{color:var(--devsite-header-link-color-active,var(--devsite-primary-text-rgba));-webkit-text-decoration:var(--devsite-header-link-text-decoration-active);-moz-text-decoration:var(--devsite-header-link-text-decoration-active);text-decoration:var(--devsite-header-link-text-decoration-active)}devsite-header .devsite-top-button:focus{background:var(--devsite-header-link-background-focus,var(--devsite-header-link-background-hover,var(--devsite-header-link-background-active,var(--devsite-background-3))))}devsite-header .devsite-top-button:hover{background:var(--devsite-header-link-background-hover,var(--devsite-header-link-background-active,var(--devsite-background-3)))}devsite-header .devsite-top-button:active{background:var(--devsite-header-link-background-active,var(--devsite-background-3));box-shadow:var(--devsite-header-link-box-shadow-active,none)}devsite-header .devsite-header-icon-button{color:var(--devsite-header-icon-color,var(--devsite-secondary-text-rgba));display:none;-webkit-box-flex:0;-webkit-flex:0 0 auto;-moz-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;height:24px;min-width:24px;padding:0;-webkit-transition:color .2s;transition:color .2s;width:24px}devsite-header .devsite-header-icon-button:active,devsite-header .devsite-header-icon-button:focus,devsite-header .devsite-header-icon-button:hover{color:var(--devsite-header-icon-color-active,var(--devsite-primary-text-rgba))}devsite-header .devsite-top-logo-row-middle{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-flex:1;-webkit-flex-grow:1;-moz-box-flex:1;-ms-flex-positive:1;flex-grow:1;position:relative}devsite-header .devsite-collapsible-section{background-color:var(--devsite-header-color-lower,var(--devsite-primary-color,var(--devsite-secondary-text-color)))}@media screen and (max-width:840px){devsite-header{-webkit-transform:translateZ(0);transform:translateZ(0)}body[ready][concierge] devsite-header[fixed]{contain:layout;position:fixed;z-index:1006}devsite-header .devsite-top-logo-row{padding:0 16px;gap:8px}devsite-header .devsite-header-upper-tabs devsite-tabs{margin:0 0 0 16px}[dir=rtl] devsite-header .devsite-header-upper-tabs devsite-tabs{margin:0 16px 0 0}devsite-header .devsite-header-upper-tabs .devsite-doc-set-nav{display:none}}devsite-header .devsite-header-billboard{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;background-color:var(--devsite-header-color-lower,var(--devsite-primary-color,var(--devsite-background-1)));display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;-ms-flex-pack:center;justify-content:center;padding:40px 24px 20px;position:relative;z-index:100}devsite-header .devsite-header-billboard h1{line-height:var(--devsite-h1-line-height,1);overflow:visible;padding:0}devsite-header .devsite-header-billboard-logo{max-height:64px}devsite-header .devsite-header-billboard-search{margin:0 auto;max-width:816px;padding-bottom:48px}devsite-header .devsite-header-billboard-search devsite-search{width:100%}devsite-header .devsite-header-billboard-search devsite-search .devsite-popout-result{max-height:50vh}devsite-header .devsite-header-billboard-search .devsite-search-background,devsite-header .devsite-header-billboard-search devsite-search .devsite-searchbox:before{background:var(--devsite-header-color-lower,var(--devsite-primary-color,var(--devsite-background-1)))}@media screen and (max-width:840px){devsite-header .devsite-header-billboard-search{margin:0 24px}}devsite-header .devsite-doc-set-nav-row{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;border-bottom:var(--devsite-header-lower-tabs-border-bottom,none);display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-webkit-justify-content:space-between;-moz-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;min-height:48px;padding:0 24px 0 0}[dir=rtl] devsite-header .devsite-doc-set-nav-row{padding:0 0 0 24px}[dir=ltr] devsite-header .devsite-doc-set-nav-row .devsite-breadcrumb-list{padding-left:24px}[dir=rtl] devsite-header .devsite-doc-set-nav-row .devsite-breadcrumb-list{padding-right:24px}@media screen and (max-width:840px){devsite-header .devsite-doc-set-nav-row{display:none}}@media screen and (max-width:600px){devsite-header devsite-language-selector{display:none}}devsite-header .devsite-header-link{-webkit-transition:background .2s,box-shadow .2s,color .2s;transition:background .2s,box-shadow .2s,color .2s}devsite-header .devsite-header-link,devsite-header .devsite-header-link:visited{color:var(--devsite-header-link-color,var(--devsite-secondary-text-rgba))}devsite-header .devsite-header-link:focus,devsite-header .devsite-header-link:hover{color:var(--devsite-header-link-color-active,var(--devsite-primary-text-rgba))}@media screen and (max-width:840px){devsite-header .devsite-header-link{display:none}}devsite-header .devsite-product-name-wrapper{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-flex:0;-webkit-flex:0 0 auto;-moz-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;height:36px;margin:6px 0}devsite-header .devsite-product-name-link,devsite-header .devsite-site-logo-link{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;opacity:1;-webkit-transition:opacity .2s;transition:opacity .2s}devsite-header .devsite-product-name-link:focus,devsite-header .devsite-product-name-link:hover,devsite-header .devsite-site-logo-link:focus{opacity:.7;text-decoration:none}devsite-header .devsite-site-logo{height:var(--devsite-logo-height,32px)}devsite-header .devsite-has-google-wordmark>.devsite-breadcrumb-link,devsite-header .devsite-has-google-wordmark>.devsite-product-name{direction:ltr}devsite-header .devsite-google-wordmark{height:24px;margin:0 4px 0 0;position:relative;top:5px}devsite-header .devsite-google-wordmark-svg-path{-webkit-transition:fill .2s;transition:fill .2s}devsite-header .devsite-site-logo-link canvas{height:auto!important}devsite-header .devsite-site-logo-link picture{display:contents}devsite-header .devsite-product-logo-container{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;border-radius:50%;color:var(--devsite-primary-color,var(--devsite-primary-text-color));display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;height:36px;-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;-ms-flex-pack:center;justify-content:center;margin-inline:0 4px;width:36px}devsite-header .devsite-product-logo-container[background]{background:var(--devsite-primary-color,var(--devsite-primary-text-color));color:var(--devsite-inverted-text-color)}devsite-header .devsite-product-logo{color:inherit;font-size:32px;height:32px;max-width:32px;min-width:32px;overflow:hidden;white-space:nowrap}devsite-header .devsite-product-logo-container[background] .devsite-product-logo{font-size:28px;height:28px;max-width:28px;min-width:28px}devsite-header .devsite-product-name{font:var(--devsite-wordmark-font,400 20px/32px var(--devsite-primary-font-family));letter-spacing:0;margin:0;max-height:32px;overflow:hidden;text-overflow:ellipsis;-webkit-transition:color .2s;transition:color .2s;white-space:nowrap}devsite-header .devsite-site-logo:not([src*=".svg"]){height:auto;max-height:32px}devsite-header .devsite-breadcrumb-link>.devsite-product-name{color:inherit}@media screen and (max-width:840px){devsite-header .devsite-product-name-wrapper{-webkit-box-flex:0;-webkit-flex:0 1 auto;-moz-box-flex:0;-ms-flex:0 1 auto;flex:0 1 auto;min-width:0}devsite-header .devsite-product-name-wrapper .devsite-breadcrumb-item:not(:first-of-type),devsite-header .devsite-product-name-wrapper .devsite-site-logo-link+.devsite-product-name{display:none}devsite-header .devsite-product-name-wrapper .devsite-breadcrumb-item,devsite-header .devsite-product-name-wrapper .devsite-breadcrumb-link,devsite-header .devsite-product-name-wrapper .devsite-breadcrumb-list,devsite-header .devsite-product-name-wrapper .devsite-product-name{width:100%}devsite-header .devsite-product-name-wrapper .devsite-breadcrumb-link{overflow:hidden;text-overflow:ellipsis}}devsite-header .devsite-product-id-row{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-webkit-justify-content:space-between;-moz-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;min-height:60px;padding:var(--devsite-product-id-row-padding,20px 24px 2px)}devsite-header .devsite-header-no-lower-tabs .devsite-product-id-row{min-height:72px;padding:var(--devsite-product-id-row-padding,20px 24px)}devsite-header .devsite-product-description-row{color:var(--devsite-header-foreground-lower-description,var(--devsite-header-foreground-lower-hover,var(--devsite-inverted-text-color)));font:var(--devsite-header-lower-description-font,400 20px/32px var(--devsite-primary-font-family))}devsite-header .devsite-product-description{font:16px/24px var(--devsite-primary-font-family);margin-block:0;margin-inline:0 180px}devsite-header .devsite-breadcrumb-list+.devsite-product-description{margin-block:8px 0}devsite-header .devsite-product-button-row{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;margin-block:0;margin-inline:24px 0;z-index:1}@media screen and (max-width:840px){devsite-header .devsite-product-id-row{min-height:72px;padding:var(--devsite-product-id-row-padding,20px 24px)}devsite-header .devsite-product-description{margin-inline:0}}@media screen and (max-width:600px){devsite-header .devsite-header-no-lower-tabs .devsite-product-id-row,devsite-header .devsite-product-id-row{-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;padding:var(--devsite-product-id-row-padding,20px 16px)}devsite-header .devsite-product-button-row{-webkit-flex-basis:100%;-ms-flex-preferred-size:100%;flex-basis:100%;margin-block:16px 0;margin-inline:0}}devsite-header[search-expanded] .devsite-header-upper-tabs{opacity:0;position:absolute}devsite-header[search-expanded] devsite-search{-webkit-box-flex:1;-webkit-flex:1 0;-moz-box-flex:1;-ms-flex:1 0;flex:1 0}devsite-header [transition]{-webkit-transition:-webkit-transform .2s;transition:-webkit-transform .2s;transition:transform .2s;transition:transform .2s,-webkit-transform .2s}devsite-header[search-active] .devsite-search-background:after{background:var(--devsite-searchbox-active,var(--devsite-background-3))}devsite-header devsite-search[search-active] .devsite-search-field::-webkit-input-placeholder{color:var(--devsite-searchbox-placeholder-active,var(--devsite-secondary-text-color))}devsite-header devsite-search[search-active] .devsite-search-field::-moz-placeholder{color:var(--devsite-searchbox-placeholder-active,var(--devsite-secondary-text-color))}devsite-header devsite-search[search-active] .devsite-search-field:-ms-input-placeholder{color:var(--devsite-searchbox-placeholder-active,var(--devsite-secondary-text-color))}devsite-header devsite-search[search-active] .devsite-search-field::-ms-input-placeholder{color:var(--devsite-searchbox-placeholder-active,var(--devsite-secondary-text-color))}devsite-header devsite-search[search-active] .devsite-search-field::placeholder{color:var(--devsite-searchbox-placeholder-active,var(--devsite-secondary-text-color))}devsite-header devsite-search[search-active] .devsite-search-field,devsite-header devsite-search[search-active] .devsite-search-field:hover{background:var(--devsite-searchbox-active,var(--devsite-background-3));color:var(--devsite-searchbox-text-active,var(--devsite-primary-text-color))}devsite-header devsite-search[search-active] .devsite-search-image{color:var(--devsite-searchbox-placeholder,var(--devsite-secondary-text-color))}@media screen and (max-width:840px){devsite-header[search-active] .devsite-product-name-wrapper,devsite-header[search-active] devsite-language-selector,devsite-header[search-active] devsite-user{display:none}devsite-header[search-active] devsite-search{-webkit-box-flex:1;-webkit-flex-grow:1;-moz-box-flex:1;-ms-flex-positive:1;flex-grow:1;-webkit-transform:none!important;transform:none!important}devsite-header[search-active] .devsite-header-upper-tabs{-webkit-box-flex:0;-webkit-flex:0 1;-moz-box-flex:0;-ms-flex:0 1;flex:0 1;overflow:hidden}devsite-header[search-active] .devsite-top-logo-row devsite-search{margin:6px 0}devsite-header .devsite-top-logo-row devsite-search[search-active] .devsite-searchbox{width:100%}devsite-header devsite-search[search-active] .devsite-search-form{border-radius:var(--devsite-search-border-radius,0);box-shadow:var(--devsite-search-active-box-shadow,none);left:0;overflow:var(--devsite-search-active-overflow,visible);position:var(--devsite-search-form-position,relative);top:0}[dir=ltr] devsite-header devsite-search[search-active] .devsite-search-form{right:var(--devsite-search-form-position-end,auto)}[dir=rtl] devsite-header devsite-search[search-active] .devsite-search-form{left:var(--devsite-search-form-position-end,auto)}devsite-header devsite-search[search-active] .devsite-search-field,devsite-header devsite-search[search-active] .devsite-search-field:hover{background:var(--devsite-search-form-background-active,var(--devsite-background-3));color:var(--devsite-search-form-text-active,var(--devsite-primary-text-color))}[dir=ltr] devsite-header .devsite-header-billboard-search devsite-search[search-active] .devsite-search-form{right:var(--devsite-search-form-position-start,auto)}[dir=rtl] devsite-header .devsite-header-billboard-search devsite-search[search-active] .devsite-search-form{left:var(--devsite-search-form-position-start,auto)}devsite-header .devsite-top-logo-row devsite-search[search-active] .devsite-searchbox .devsite-search-image{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex}devsite-header .devsite-top-logo-row devsite-search .devsite-searchbox:before,devsite-header .devsite-top-logo-row devsite-search[search-active] .devsite-popout{width:var(--devsite-popout-width,calc(100vw + 16px))}[dir=ltr] devsite-header .devsite-top-logo-row devsite-search .devsite-searchbox:before,[dir=ltr] devsite-header .devsite-top-logo-row devsite-search[search-active] .devsite-popout{left:var(--devsite-popout-position-start,-60px)}[dir=rtl] devsite-header .devsite-top-logo-row devsite-search .devsite-searchbox:before,[dir=rtl] devsite-header .devsite-top-logo-row devsite-search[search-active] .devsite-popout{right:var(--devsite-popout-position-start,-60px)}devsite-header .devsite-top-logo-row devsite-search[search-active] .devsite-search-button{margin-block:0;margin-inline:var(--devsite-search-button-margin-before,16px) 0}devsite-header .devsite-top-logo-row devsite-search[search-active] .devsite-search-button[search-open]{display:none}devsite-header .devsite-top-logo-row devsite-search[search-active] .devsite-search-button[search-close]{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex}devsite-header [transition]{-webkit-transition:none;transition:none}}devsite-header .devsite-search-background{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;-moz-box-sizing:content-box;box-sizing:content-box;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-pack:stretch;-webkit-justify-content:stretch;-moz-box-pack:stretch;-ms-flex-pack:stretch;justify-content:stretch;margin-block:0;margin-inline:24px 0;padding:6px 0;pointer-events:none;position:absolute;-webkit-transition:-webkit-transform .2s;transition:-webkit-transform .2s;transition:transform .2s;transition:transform .2s,-webkit-transform .2s;will-change:transition;z-index:9}[dir=ltr] devsite-header .devsite-search-background{right:0;-webkit-transform-origin:right center;transform-origin:right center}[dir=rtl] devsite-header .devsite-search-background{left:0;-webkit-transform-origin:left center;transform-origin:left center}devsite-header .devsite-search-background,devsite-header .devsite-searchbox:before{background:var(--devsite-header-color-upper,var(--devsite-background-1))}devsite-header .devsite-search-background:after{content:"";-webkit-box-flex:1;-webkit-flex-grow:1;-moz-box-flex:1;-ms-flex-positive:1;flex-grow:1;height:100%;-webkit-transition:background .2s;transition:background .2s}devsite-header .devsite-search-background:after,devsite-header devsite-search input.devsite-search-field{background:var(--devsite-searchbox-inactive)}devsite-header devsite-search input.devsite-search-field::-webkit-input-placeholder{color:var(--devsite-searchbox-placeholder,var(--devsite-secondary-text-color))}devsite-header devsite-search input.devsite-search-field::-moz-placeholder{color:var(--devsite-searchbox-placeholder,var(--devsite-secondary-text-color))}devsite-header devsite-search input.devsite-search-field:-ms-input-placeholder{color:var(--devsite-searchbox-placeholder,var(--devsite-secondary-text-color))}devsite-header devsite-search input.devsite-search-field::-ms-input-placeholder{color:var(--devsite-searchbox-placeholder,var(--devsite-secondary-text-color))}devsite-header devsite-search input.devsite-search-field::placeholder{color:var(--devsite-searchbox-placeholder,var(--devsite-secondary-text-color))}devsite-header devsite-search input.devsite-search-field:hover{background:var(--devsite-searchbox-hover)}devsite-header devsite-search .devsite-search-image,devsite-header devsite-search input.devsite-search-field{color:var(--devsite-searchbox-placeholder,var(--devsite-secondary-text-color))}devsite-header[billboard] .devsite-search-background{display:none}devsite-header[billboard][bottom-row--hidden] .devsite-search-background{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex}devsite-header[billboard] .devsite-top-logo-row devsite-search .devsite-search-form{opacity:1;-webkit-transition:opacity .2s,-webkit-transform .2s;transition:opacity .2s,-webkit-transform .2s;transition:opacity .2s,transform .2s;transition:opacity .2s,transform .2s,-webkit-transform .2s}devsite-header[billboard][bottom-row--hidden] .devsite-top-logo-row devsite-search .devsite-search-form{-webkit-transform:translateZ(0);transform:translateZ(0)}body[template="404"] devsite-header .devsite-top-logo-row .devsite-search-form,devsite-header[billboard]:not([bottom-row--hidden]) .devsite-top-logo-row devsite-search .devsite-search-form{opacity:0;pointer-events:none}[dir=ltr] body[template="404"] devsite-header .devsite-top-logo-row .devsite-search-form,[dir=ltr] devsite-header[billboard]:not([bottom-row--hidden]) .devsite-top-logo-row devsite-search .devsite-search-form{-webkit-transform:translate3d(200px,0,0);transform:translate3d(200px,0,0)}[dir=rtl] body[template="404"] devsite-header .devsite-top-logo-row .devsite-search-form,[dir=rtl] devsite-header[billboard]:not([bottom-row--hidden]) .devsite-top-logo-row devsite-search .devsite-search-form{-webkit-transform:translate3d(-200px,0,0);transform:translate3d(-200px,0,0)}devsite-header[billboard][bottom-row--hidden] .devsite-header-billboard-search devsite-search{opacity:0}devsite-header[billboard] .devsite-header-billboard-search devsite-search{margin-inline:0}devsite-header[billboard] .devsite-header-billboard-search devsite-search .devsite-popout{max-height:calc(100vh - 255px)}@media screen and (max-width:840px){devsite-header .devsite-top-logo-row devsite-search{width:auto}devsite-header .devsite-top-logo-row devsite-search .devsite-searchbox{width:0}devsite-header .devsite-search-background,devsite-header .devsite-search-background:after,devsite-header devsite-search .devsite-search-field,devsite-header devsite-search .devsite-search-field:hover,devsite-header[search-active] .devsite-search-background:after{background:0}devsite-header .devsite-top-logo-row devsite-search .devsite-searchbox .devsite-search-image{display:none}devsite-header .devsite-top-logo-row devsite-search .devsite-search-button{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;color:var(--devsite-secondary-text-color);display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;z-index:1}devsite-header .devsite-top-logo-row devsite-search .devsite-search-button[search-open]{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex}devsite-header .devsite-top-logo-row devsite-search .devsite-search-button[search-close]{display:none;margin-right:6px}devsite-header .devsite-top-logo-row devsite-search .devsite-search-button[search-open]:before{content:"search"}devsite-header .devsite-top-logo-row devsite-search .devsite-search-button[search-close]:before{content:"cancel"}devsite-header .devsite-top-logo-row devsite-search .devsite-result-item a,devsite-header .devsite-top-logo-row devsite-search .devsite-result-label,devsite-header .devsite-top-logo-row devsite-search .devsite-suggest-footer,devsite-header .devsite-top-logo-row devsite-search .devsite-suggest-header{padding-inline:var(--devsite-search-content-padding-start,60px) 8px}}devsite-header .devsite-header-upper-tabs{-webkit-box-flex:1;-webkit-flex:1 1 0;-moz-box-flex:1;-ms-flex:1 1 0px;flex:1 1 0;margin-block:0;margin-inline:var(--devsite-upper-tab-margin-x,32px) 0;opacity:1;position:relative;z-index:8}devsite-header devsite-tabs tab a:focus,devsite-header devsite-tabs tab a:hover{text-decoration:none}devsite-header cloudx-tabs-nav.upper-tabs .devsite-tabs-wrapper,devsite-header devsite-tabs.upper-tabs .devsite-tabs-wrapper{background:var(--devsite-header-color-upper,var(--devsite-background-1))}devsite-header devsite-tabs.upper-tabs>.devsite-tabs-wrapper>tab>a:focus,devsite-header devsite-tabs.upper-tabs>.devsite-tabs-wrapper>tab>a:hover{color:var(--devsite-upper-tab-active,var(--devsite-primary-text-color))}devsite-header devsite-tabs.upper-tabs>.devsite-tabs-wrapper>tab>a:focus:after,devsite-header devsite-tabs.upper-tabs>.devsite-tabs-wrapper>tab>a:hover:after{border-color:var(--devsite-upper-tab-marker-color-inactive,var(--devsite-upper-tab-inactive,var(--devsite-secondary-text-color)))}devsite-header cloudx-tabs-nav.lower-tabs a,devsite-header devsite-tabs.lower-tabs .devsite-tabs-content,devsite-header devsite-tabs.lower-tabs a{color:var(--devsite-header-foreground-lower,var(--devsite-inverted-text-color));letter-spacing:var(--devsite-header-lower-tabs-letter-spacing,0)}devsite-header cloudx-tabs-nav.lower-tabs a:focus,devsite-header cloudx-tabs-nav.lower-tabs a:hover,devsite-header devsite-tabs.lower-tabs .devsite-tabs-content:focus,devsite-header devsite-tabs.lower-tabs .devsite-tabs-content:hover,devsite-header devsite-tabs.lower-tabs a:focus,devsite-header devsite-tabs.lower-tabs a:hover{color:var(--devsite-header-foreground-lower-hover,var(--devsite-header-foreground-lower,var(--devsite-inverted-text-rgba)))}devsite-header cloudx-tabs-nav.lower-tabs tab[active]>a,devsite-header devsite-tabs.lower-tabs tab[active]>.devsite-tabs-content,devsite-header devsite-tabs.lower-tabs tab[active]>a{color:var(--devsite-header-foreground-lower-active,var(--devsite-inverted-text-color))}devsite-header cloudx-tabs-nav.lower-tabs tab[active]>a:focus,devsite-header devsite-tabs.lower-tabs tab[active]>.devsite-tabs-content:focus,devsite-header devsite-tabs.lower-tabs tab[active]>a:focus{color:var(--devsite-header-foreground-lower-active-focus,var(--devsite-header-foreground-lower,var(--devsite-inverted-text-rgba)))}@media screen and (-ms-high-contrast:active),screen and (prefers-contrast:high){devsite-header cloudx-tabs-nav.lower-tabs tab[active]>a,devsite-header devsite-tabs.lower-tabs tab[active]>.devsite-tabs-content,devsite-header devsite-tabs.lower-tabs tab[active]>a{color:inherit}}devsite-header cloudx-tabs-nav.lower-tabs>.devsite-tabs-wrapper>tab>a:after,devsite-header devsite-tabs.lower-tabs>.devsite-tabs-wrapper>tab>a:after{border-radius:var(--devsite-lower-tab-marker-border-radius,var(--devsite-tab-marker-border-radius,0))}devsite-header devsite-tabs.lower-tabs>.devsite-tabs-wrapper>tab>a:focus:after,devsite-header devsite-tabs.lower-tabs>.devsite-tabs-wrapper>tab>a:hover:after{border-color:var(--devsite-lower-tab-marker-color-inactive,var(--devsite-header-foreground-lower,var(--devsite-inverted-text-rgba)))}devsite-header cloudx-tabs-nav.lower-tabs>.devsite-tabs-wrapper>tab[active]>a:after,devsite-header devsite-tabs.lower-tabs>.devsite-tabs-wrapper>tab[active]>a:after{border-color:var(--devsite-lower-tab-marker-color-active,var(--devsite-header-foreground-lower-active,var(--devsite-background-1)))}devsite-header cloudx-tabs-nav tab[overflow-tab]>a:after,devsite-header devsite-tabs tab[overflow-tab]>a:after{display:none}devsite-header devsite-tabs.upper-tabs tab[overflow-tab]:after{background:var(--devsite-header-color-upper,var(--devsite-background-1))}devsite-header cloudx-tabs-nav.upper-tabs .devsite-tabs-overflow-menu,devsite-header devsite-tabs.upper-tabs .devsite-tabs-overflow-menu{border-top:var(--devsite-header-border,0)}@media screen and (max-width:840px){[dir=ltr] devsite-header .devsite-header-upper-tabs{margin-left:0}[dir=rtl] devsite-header .devsite-header-upper-tabs{margin-right:0}devsite-header devsite-tabs.lower-tabs,devsite-header devsite-tabs.upper-tabs{display:none}}[layout=docs] h2:not(.no-link),[layout=docs] h3:not(.no-link),[layout=docs] h4:not(.no-link),[layout=docs] h5:not(.no-link),[layout=docs] h6:not(.no-link),h1.add-link{-webkit-margin-end:-40px;-moz-margin-end:-40px;margin-inline-end:-40px;-webkit-padding-end:40px;-moz-padding-end:40px;padding-inline-end:40px}.devsite-heading-link.material-icons{color:var(--devsite-icon-color,var(--devsite-secondary-text-color));height:24px;opacity:0}.devsite-heading-link.material-icons:focus,.devsite-heading-link.material-icons:hover{color:var(--devsite-icon-color-hover,var(--devsite-link-color));cursor:pointer!important}.devsite-landing-row-item-list h4>.devsite-heading-link.material-icons,h1>.devsite-heading-link.material-icons,h2>.devsite-heading-link.material-icons,h3>.devsite-heading-link.material-icons{vertical-align:middle}.devsite-landing-row-item-list h4>.devsite-heading-link.material-icons,th>h2>.devsite-heading-link.material-icons,th>h3>.devsite-heading-link.material-icons{margin:-4px 0}.devsite-heading-link.material-icons:focus,.devsite-heading-link.material-icons:hover,:focus>.devsite-heading-link.material-icons,:hover>.devsite-heading-link.material-icons{opacity:1}.devsite-heading-link:after{content:"link"}devsite-iframe{display:block;width:100%}devsite-iframe+*{position:relative}devsite-iframe+devsite-iframe{margin-top:16px}devsite-iframe iframe{height:100%;width:100%}devsite-iframe iframe[src*=".frame"]{height:calc(100% + 32px);margin:-16px;width:calc(100% + 32px)}devsite-info-popout:not(:defined){visibility:hidden}devsite-jump-to{display:block;margin:40px 0 0!important;opacity:0;padding-bottom:96px;pointer-events:none;position:relative;-webkit-transition:opacity .5s;transition:opacity .5s}devsite-jump-to[visible]{opacity:1;pointer-events:auto}devsite-jump-to .devsite-jump-to-link{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;background:var(--devsite-link-background,var(--devsite-link-color))!important;border-radius:50%;box-shadow:0 1px 2px 0 var(--devsite-elevation-key-shadow-color),0 1px 3px 1px var(--devsite-elevation-ambient-shadow-color);color:var(--devsite-link-color,var(--devsite-inverted-text-color))!important;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;font-size:24px;height:56px;-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;-ms-flex-pack:center;justify-content:center;overflow:hidden;position:absolute;-webkit-transition:background .2s,box-shadow .2s,color .2s;transition:background .2s,box-shadow .2s,color .2s;width:56px}devsite-jump-to .devsite-jump-to-link:focus,devsite-jump-to .devsite-jump-to-link:hover{background:var(--devsite-link-background-hover,var(--devsite-background-1))!important;color:var(--devsite-link-color)!important;text-decoration:none}devsite-jump-to .devsite-jump-to-link:active{box-shadow:0 1px 2px 0 var(--devsite-elevation-key-shadow-color),0 2px 6px 2px var(--devsite-elevation-ambient-shadow-color)}[dir=ltr] devsite-jump-to .devsite-jump-to-link{right:0}[dir=rtl] devsite-jump-to .devsite-jump-to-link{left:0}devsite-jump-to[pinned] .devsite-jump-to-link{bottom:40px;box-shadow:0 1px 3px 0 var(--devsite-elevation-key-shadow-color),0 4px 8px 3px var(--devsite-elevation-ambient-shadow-color);position:fixed}devsite-jump-to[pinned] .devsite-jump-to-link:active{box-shadow:0 2px 3px 0 var(--devsite-elevation-key-shadow-color),0 6px 10px 4px var(--devsite-elevation-ambient-shadow-color)}devsite-jump-to .devsite-jump-to-link:before{content:"arrow_upward";font:normal normal normal 24px/1 Material Icons;-webkit-font-feature-settings:"liga";-moz-font-feature-settings:"liga";font-feature-settings:"liga";-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;text-transform:none;word-wrap:normal}@media screen and (max-width:840px){devsite-jump-to{margin:40px 0 0!important;padding-bottom:80px}devsite-jump-to[pinned] .devsite-jump-to-link{bottom:24px}}devsite-language-selector:not(:defined) ul,devsite-language-selector:not([open]) ul{display:none}devsite-language-selector ul{display:block;list-style:none;padding:0}devsite-language-selector li{font-size:14px;margin:0;min-width:100%}devsite-language-selector a{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;min-height:48px;min-width:0;overflow:hidden;padding-inline:16px;text-overflow:ellipsis;white-space:nowrap}devsite-language-selector a:is(:link,:visited){color:var(--devsite-primary-text-color)}devsite-language-selector a:is(:hover,:focus){background-color:var(--devsite-background-3);text-decoration:none}devsite-language-selector a[aria-current]{background-color:var(--devsite-item-background-selected,var(--devsite-background-3));font-weight:var(--devsite-item-font-weight-selected,500)}@media screen and (-ms-high-contrast:active),screen and (prefers-contrast:high){devsite-language-selector a[aria-current]{font-weight:700;text-decoration:underline}}.devsite-dialog-wrapper{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;bottom:0;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;-ms-flex-pack:center;justify-content:center;left:0;pointer-events:none;position:fixed;right:0;top:0;z-index:1014}.devsite-dialog-wrapper.below-site-mask{z-index:1011}devsite-dialog{background:var(--devsite-background-1);border-radius:var(--devsite-border-radius,2px);color:var(--devsite-secondary-text-color);box-shadow:0 1px 3px 0 var(--devsite-elevation-key-shadow-color),0 4px 8px 3px var(--devsite-elevation-ambient-shadow-color);font-size:14px;line-height:20px;max-height:calc(100vh - 48px);max-width:calc(100vw - 48px);pointer-events:all;overflow:auto;padding:var(--devsite-dialog-padding,8px);width:var(--devsite-content-excellence-dialog-width,480px)}@media screen and (max-width:840px){devsite-dialog{max-height:calc(100vh - 32px);max-width:calc(100vw - 32px)}}devsite-dialog:not([open]){display:none}devsite-dialog .devsite-dialog-contents{color:var(--devsite-secondary-text-color);overflow:hidden;padding:var(--devsite-dialog-contents-padding,16px)}devsite-dialog .devsite-dialog-close{cursor:pointer}devsite-dialog .devsite-dialog-close:not(.button):not(button){border-radius:16px;height:32px;width:32px;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;-ms-flex-pack:center;justify-content:center}devsite-dialog .devsite-dialog-close:not(.button):not(button):HOVER{background-color:#f1f3f4}devsite-dialog .devsite-dialog-contents>p:first-child:last-child{margin:0}devsite-dialog h2,devsite-dialog h3{color:var(--devsite-heading-color,inherit)}devsite-dialog h3{font:var(--devsite-heading-font,400 20px/32px var(--devsite-primary-font-family));margin:0 0 20px;outline:0;text-align:var(--devsite-heading-text-align,inherit)}devsite-dialog .devsite-dialog-buttons{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-pack:end;-webkit-justify-content:flex-end;-moz-box-pack:end;-ms-flex-pack:end;justify-content:flex-end;padding:4px 4px 0}devsite-lightbox{pointer-events:all;position:relative}devsite-lightbox:not([open]){display:none}devsite-lightbox .devsite-dialog-contents{padding:0}devsite-lightbox .devsite-lightbox-icon-close{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;background:rgba(0,0,0,.54);border:0;border-radius:0;cursor:pointer;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;height:40px;-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;-ms-flex-pack:center;justify-content:center;outline:0;padding:0;position:absolute;top:0;width:40px;z-index:1}[dir=ltr] devsite-lightbox .devsite-lightbox-icon-close{right:0}[dir=rtl] devsite-lightbox .devsite-lightbox-icon-close{left:0}devsite-lightbox .devsite-lightbox-icon-close:hover{background:rgba(0,0,0,.43)}devsite-lightbox .devsite-lightbox-icon-close:active{box-shadow:none}devsite-lightbox .devsite-lightbox-icon-close:after{font:normal normal normal 24px/1 Material Icons;-webkit-font-feature-settings:"liga";-moz-font-feature-settings:"liga";font-feature-settings:"liga";-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;text-transform:none;word-wrap:normal;color:#f1f1f1;content:"close";-webkit-transition:color .3s ease-in-out;transition:color .3s ease-in-out}devsite-lightbox .devsite-lightbox-icon-close:focus:after,devsite-lightbox .devsite-lightbox-icon-close:hover:after{color:#fff}devsite-lightbox img{max-height:100vh}.devsite-lightbox-image{cursor:pointer;outline:0}.devsite-lightbox-image:focus{-webkit-filter:brightness(75%);filter:brightness(75%)}.MathJax_SVG_Display{overflow-x:auto}@media screen and (max-width:600px){.MathJax_SVG_Display{margin:1em -16px!important;padding:0 16px 16px;width:calc(100% + 32px)!important}}devsite-multiple-choice{background-color:var(--devsite-multiple-choice-background);border:var(--devsite-multiple-choice-border);border-radius:var(--devsite-multiple-choice-border-radius);display:block;margin:16px 0;overflow:var(--devsite-multiple-choice-overflow);visibility:hidden!important}devsite-multiple-choice[ready]{visibility:visible!important}devsite-multiple-choice .devsite-multiple-choice-question{background-color:var(--devsite-multiple-choice-question-background);color:var(--devsite-multiple-choice-question-color);font:var(--devsite-table-heading-font,500 16px/24px var(--devsite-primary-font-family));padding:16px 24px}devsite-multiple-choice .devsite-multiple-choice-answer{border-bottom:var(--devsite-multiple-choice-answer-border-bottom);border-top:var(--devsite-multiple-choice-answer-border-top)}devsite-multiple-choice .devsite-multiple-choice-answer,devsite-multiple-choice .devsite-multiple-choice-answer:focus,devsite-multiple-choice .devsite-multiple-choice-answer:hover{outline:0}devsite-multiple-choice .devsite-multiple-choice-answer:not([clicked]):focus,devsite-multiple-choice .devsite-multiple-choice-answer:not([clicked]):hover{color:var(--devsite-link-color);cursor:pointer}devsite-multiple-choice .devsite-multiple-choice-option{padding:16px 72px 16px 24px;position:relative}devsite-multiple-choice .devsite-multiple-choice-option:after{content:"check_box_outline_blank";font:normal normal normal 24px/1 Material Icons;-webkit-font-feature-settings:"liga";-moz-font-feature-settings:"liga";font-feature-settings:"liga";-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;text-transform:none;word-wrap:normal;height:100%;position:absolute;right:24px;top:calc(50% - 12px)}devsite-multiple-choice [correct]{background-color:var(--devsite-multiple-choice-correct-background)}devsite-multiple-choice [incorrect]{background-color:var(--devsite-multiple-choice-incorrect-background)}devsite-multiple-choice [correct] .devsite-multiple-choice-option:after{color:var(--devsite-multiple-choice-correct-color);content:"check"}devsite-multiple-choice [incorrect] .devsite-multiple-choice-option:after{color:var(--devsite-multiple-choice-incorrect-color);content:"not_interested"}devsite-multiple-choice .devsite-multiple-choice-explanation{font-size:14px;padding:0 24px 16px}devsite-multiple-choice .devsite-multiple-choice-explanation-correctness{font-weight:500;margin-top:16px}devsite-multiple-choice [correct] .devsite-multiple-choice-explanation-correctness{color:var(--devsite-multiple-choice-correct-color)}devsite-multiple-choice [incorrect] .devsite-multiple-choice-explanation-correctness{color:var(--devsite-multiple-choice-incorrect-color)}devsite-my-activity-light.devsite-my-activity-wide-ui .activities{-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;width:calc(100% + 20px);-webkit-align-content:flex-start;-ms-flex-line-pack:start;align-content:flex-start}devsite-my-activity-light.devsite-my-activity-wide-ui .activity{width:calc(33% - 20px);min-width:300px}devsite-my-activity-light.devsite-my-activity-wide-ui .my-activity-show-more{display:none}devsite-my-activity-light{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;height:100%}devsite-my-activity-light .waiting-container{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;-ms-flex-pack:center;justify-content:center;width:100%}devsite-my-activity-light .tooltip{background-color:var(--devsite-link-color);border-radius:10px;box-shadow:0 1px 2px 0 rgba(60,64,67,.3),0 1px 3px 1px rgba(60,64,67,.15);color:var(--tenant-inverted-text-color);padding-block:20px 10px;padding-inline:20px;position:absolute;z-index:1;inset-inline-start:28px;top:50px;-webkit-margin-end:5px;-moz-margin-end:5px;margin-inline-end:5px}devsite-my-activity-light .tooltip .arrow{color:var(--devsite-link-color);font-size:60px;inset-inline-start:4px;position:absolute;top:-34px}devsite-my-activity-light .tooltip .title{font-weight:500;font-size:100%;font-family:var(--devsite-headline-font-family)}devsite-my-activity-light .tooltip .button{color:#fff;float:end;-webkit-margin-before:10px;margin-block-start:10px}devsite-my-activity-light .tooltip .button:hover{background-color:var(--devsite-link-color)}devsite-my-activity-light .my-activity-date-range{font-weight:500;color:var(--tenant-secondary-text-color);line-height:20px;font-size:13px;-webkit-margin-after:8px;margin-block-end:8px}devsite-my-activity-light .my-activity-container{height:100%;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-moz-box-orient:vertical;-moz-box-direction:normal;-ms-flex-direction:column;flex-direction:column;width:100%}devsite-my-activity-light .activities{-webkit-box-flex:1;-webkit-flex:1;-moz-box-flex:1;-ms-flex:1;flex:1;overflow:auto;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-moz-box-orient:vertical;-moz-box-direction:normal;-ms-flex-direction:column;flex-direction:column;gap:10px;-webkit-margin-end:-15px;-moz-margin-end:-15px;margin-inline-end:-15px;-webkit-padding-end:15px;-moz-padding-end:15px;padding-inline-end:15px;position:relative}devsite-my-activity-light .activity{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-moz-box-orient:vertical;-moz-box-direction:normal;-ms-flex-direction:column;flex-direction:column;border:var(--devsite-primary-border);border-radius:8px;padding:12px 8px 10px}devsite-my-activity-light .activity-expanded{border:2px var(--devsite-link-color) solid;padding:11px 7px 9px}devsite-my-activity-light .my-activity-overview-section{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex}devsite-my-activity-light .activity-icon{background-position:50%;background-repeat:no-repeat;background-size:22px;height:20px;margin:4px;-webkit-margin-end:10px;-moz-margin-end:10px;margin-inline-end:10px;min-width:20px;width:20px}devsite-my-activity-light .activity.badge .activity-icon{background-image:url(../images/activity-badge.svg)}devsite-my-activity-light .activity.android .activity-icon{background-image:url(../images/activity-android.png)}devsite-my-activity-light .activity.cloud .activity-icon{background-image:url(../images/activity-cloud.png)}devsite-my-activity-light .activity.bazel .activity-icon{background-image:url(../images/activity-bazel.svg)}devsite-my-activity-light .activity.other .activity-icon{background-image:url(../images/activity-other.png)}devsite-my-activity-light .activity.firebase .activity-icon{background-image:url(../images/activity-firebase.svg);background-size:15px}devsite-my-activity-light .activity-title-tags{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-moz-box-orient:vertical;-moz-box-direction:normal;-ms-flex-direction:column;flex-direction:column;-webkit-box-flex:1;-webkit-flex:1;-moz-box-flex:1;-ms-flex:1;flex:1;overflow:hidden}devsite-my-activity-light .activity-link{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;overflow:hidden;-webkit-box-flex:1;-webkit-flex-grow:1;-moz-box-flex:1;-ms-flex-positive:1;flex-grow:1;font-weight:500;font-size:14px}devsite-my-activity-light .activity-text{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}devsite-my-activity-light .activity-tags{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;color:var(--tenant-secondary-text-color);font-size:12px;line-height:20px}devsite-my-activity-light .activity-tag:after{content:"•";font-size:14px;line-height:14px;top:1px;position:relative;-webkit-margin-end:5px;-moz-margin-end:5px;margin-inline-end:5px;-webkit-margin-start:3px;-moz-margin-start:3px;margin-inline-start:3px}devsite-my-activity-light .activity-tag:last-child:after{content:""}devsite-my-activity-light .activity-expand-arrow{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;cursor:pointer}devsite-my-activity-light .activity-link-out{font-size:17px;line-height:24px;margin:0 4px}devsite-my-activity-light .my-activity-show-more{border:var(--devsite-primary-border);border-radius:8px;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;padding:8px;-webkit-padding-end:9px;-moz-padding-end:9px;padding-inline-end:9px;-webkit-padding-start:16px;-moz-padding-start:16px;padding-inline-start:16px;font-weight:500;color:var(--devsite-link-color);font-size:14px;line-height:20px;width:-webkit-fit-content;width:-moz-fit-content;width:fit-content;-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;gap:8px;cursor:pointer}devsite-my-activity-light .activity-details{border-top:var(--devsite-primary-border);margin:10px -7px 0;padding:0 12px}devsite-my-activity-light .activity-details-section{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;border-bottom:var(--devsite-primary-border);padding:12px 0}devsite-my-activity-light .updated-chip{background-color:var(--devsite-link-background-active);-webkit-margin-end:12px;-moz-margin-end:12px;margin-inline-end:12px;color:var(--devsite-contrast-link-color);padding:1px 8px;text-align:center;font-size:13px;font-weight:500;line-height:21px}devsite-my-activity-light .my-activity-view-release-notes-container{line-height:21px;font-size:13px;font-weight:500}devsite-my-activity-light .activity-details-section:last-child{border-bottom:none;-webkit-padding-after:0;padding-block-end:0}devsite-my-activity-light .activity-details-section-nomenclature{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-moz-box-orient:vertical;-moz-box-direction:normal;-ms-flex-direction:column;flex-direction:column}devsite-my-activity-light .activity-details-title{-webkit-margin-end:5px;-moz-margin-end:5px;margin-inline-end:5px;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center}devsite-my-activity-light .activity-date{font-size:13px;line-height:21px;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;color:var(--tenant-secondary-text-color)}devsite-my-activity-light .activity-bookmarked-container{-webkit-box-flex:1;-webkit-flex:1;-moz-box-flex:1;-ms-flex:1;flex:1;text-align:end}devsite-my-activity-light .activity-bookmarked-container devsite-bookmark devsite-dropdown-list{--devsite-dropdown-list-toggle-border-radius:4px;--devsite-dropdown-list-toggle-button-padding:0 8px}devsite-my-activity-light .activity-bookmarked-container devsite-bookmark{-webkit-box-pack:end;-webkit-justify-content:end;-moz-box-pack:end;-ms-flex-pack:end;justify-content:end}devsite-my-activity-light .activity-details-title{font-size:13px;font-weight:700;line-height:21px;color:var(--tenant-secondary-text-color)}devsite-my-activity-light .activity-nom-tags{-webkit-margin-before:6px;margin-block-start:6px;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;gap:8px;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}devsite-my-activity-light .activity-nom-tag{background-color:var(--devsite-background-3);color:var(--tenant-secondary-text-color);font-size:14px;font-weight:500;padding:1px 8px;text-align:center}devsite-my-community{font-size:16px}devsite-my-community .devsite-my-community-feature-not-available{text-align:center;margin:50px 0}devsite-my-community .waiting-container{margin:auto}devsite-my-community .devsite-my-community-card{margin-bottom:24px;height:unset}devsite-my-community .devsite-my-community-header{padding:24px;border-bottom:var(--devsite-card-border);display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center}devsite-my-community .devsite-my-community-icon{max-width:66px;max-height:66px;-webkit-margin-end:18px;-moz-margin-end:18px;margin-inline-end:18px}devsite-my-community .devsite-my-community-title-container{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-moz-box-orient:vertical;-moz-box-direction:normal;-ms-flex-direction:column;flex-direction:column;-webkit-box-align:start;-webkit-align-items:flex-start;-moz-box-align:start;-ms-flex-align:start;align-items:flex-start;-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;-ms-flex-pack:center;justify-content:center}devsite-my-community .devsite-my-community-title{font:var(--devsite-h2-font);font-weight:400;font-size:28px;line-height:36px;color:var(--devsite-heading-color,var(--devsite-secondary-text-color))}devsite-my-community .devsite-my-community-member-chip{font-family:Roboto;font-weight:500;font-size:14px;line-height:20px;-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;color:var(--devsite-success-notice-color);background-color:var(--devsite-success-notice-background);padding:1px 8px;-webkit-margin-before:7px;margin-block-start:7px}devsite-my-community .devsite-my-community-description{padding:0 24px 20px;white-space:pre-line}devsite-my-community .devsite-my-community-button-container{padding:0 24px 24px}devsite-my-community .devsite-my-community-button-container button.button{margin:6px 6px 0 0}devsite-my-community .devsite-my-community-button-container devsite-spinner{display:inline-block;margin-left:24px;position:absolute}devsite-my-community .devsite-my-community-details-container{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-moz-box-orient:vertical;-moz-box-direction:normal;-ms-flex-direction:column;flex-direction:column;-webkit-transition:border-color,max-height,.5s ease-out;transition:border-color,max-height,.5s ease-out;border-top:1px solid transparent;margin-top:4px;max-height:0}devsite-my-community .devsite-my-community-details-container[opened]{border-top:var(--devsite-card-border);-webkit-transition:border-color,max-height,.5s ease-in;transition:border-color,max-height,.5s ease-in;max-height:3000px}devsite-my-community .devsite-my-community-missing-info-warning,devsite-my-community .devsite-my-community-profile-not-allowed{gap:10px;color:var(--devsite-caution-notice-color);background-color:var(--devsite-caution-notice-background);padding:9px 24px;font-size:14px;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-margin-after:24px;margin-block-end:24px;-webkit-margin-before:3px;margin-block-start:3px}devsite-my-community .devsite-my-community-missing-info-warning .material-symbols-outlined,devsite-my-community .devsite-my-community-profile-not-allowed .material-symbols-outlined{font-variation-settings:"FILL" 1,"wght" 400,"GRAD" 0,"opsz" 48}devsite-my-community .devsite-my-community-no-profile-info{color:var(--devsite-note-notice-color);background-color:var(--devsite-note-notice-background);padding:9px 24px;font-size:14px;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-margin-after:24px;margin-block-end:24px}devsite-my-community .devsite-my-community-no-profile-info .material-symbols-outlined{-webkit-margin-end:10px;-moz-margin-end:10px;margin-inline-end:10px}devsite-my-community .devsite-my-community-profile-attributes-title{font-size:18px;margin:0 24px 9px;font-family:var(--devsite-headline-font-family)}devsite-my-community .devsite-my-community-legal-title{font-size:18px;margin:0 0 16px;font-family:var(--devsite-headline-font-family)}devsite-my-community .devsite-my-community-profile-attributes{display:grid;grid:auto/calc(50% - 12px) calc(50% - 12px);margin:0 24px 18px;gap:24px;font-size:18px}devsite-my-community .devsite-my-community-profile-attributes-text{margin:0;font-size:16px;grid-column:1/3}devsite-my-community .devsite-my-community-error-incorrect,devsite-my-community .devsite-my-community-error-missing{display:none;color:#e53935;font-size:12px;margin:2px 0 0 14px}devsite-my-community .devsite-my-community-legal-container{margin:0 24px 24px}devsite-my-community .devsite-my-community-legal-container[missing] .devsite-my-community-error-missing{display:inline-block}devsite-my-community .devsite-my-community-legal-container[missing] .devsite-my-community-legal-copy{border:2px solid #e53935}devsite-my-community .devsite-my-community-profile-attribute-input{display:block;position:relative;min-height:86px}devsite-my-community .devsite-my-community-profile-attribute-input[incorrect] .devsite-my-community-error-incorrect,devsite-my-community .devsite-my-community-profile-attribute-input[missing] .devsite-my-community-error-missing{display:inline-block}devsite-my-community .devsite-my-community-email-preference{padding:0 24px 24px}devsite-my-community .devsite-my-community-email-pref-input{margin-top:8px}devsite-my-community .devsite-my-community-profile-title{margin:24px 24px 16px;font-size:18px;font-family:var(--devsite-headline-font-family)}devsite-my-community .devsite-my-community-profile-text{margin:0 24px 16px}devsite-my-community .devsite-my-community-private-explanation{margin:0 24px 24px}devsite-my-community .devsite-my-community-private-explanation span{color:var(--devsite-secondary-text-color);font-size:12px;font-weight:500;display:-webkit-inline-box;display:-webkit-inline-flex;display:-moz-inline-box;display:-ms-inline-flexbox;display:inline-flex;vertical-align:bottom;line-height:23px}devsite-my-community .devsite-my-community-private-explanation span:before{content:"lock";font-family:Material Symbols Outlined;font-size:12px;font-variation-settings:"FILL" 0,"wght" 400,"GRAD" 0,"opsz" 48;-webkit-margin-end:3px;-moz-margin-end:3px;margin-inline-end:3px}devsite-my-community .devsite-my-community-private-chip{color:var(--devsite-secondary-text-color);font-size:12px;font-weight:500;margin:2px 0 0 14px;display:inline-block}devsite-my-community .devsite-my-community-private-chip .material-symbols-outlined{font-size:12px;font-variation-settings:"FILL" 0,"wght" 400,"GRAD" 0,"opsz" 48;top:2px;position:relative}devsite-my-community .devsite-my-community-legal-copy{padding:16px;font-size:14px;background-color:var(--devsite-background-3);display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex}devsite-my-community .devsite-my-community-legal-copy input{background-color:transparent;-webkit-margin-before:5px;margin-block-start:5px;-webkit-margin-end:11px;-moz-margin-end:11px;margin-inline-end:11px}.devsite-my-community-leave-title{font-family:Google Sans;font-weight:500;font-size:18px;line-height:24px;color:var(--devsite-heading-color,var(--devsite-secondary-text-color));margin-bottom:16px}.devsite-my-community-leave-buttons{margin-top:24px}devsite-my-community.devsite-my-community-small .devsite-my-community-title{font-size:22px}devsite-my-community.devsite-my-community-small .devsite-my-community-profile-attributes{grid:auto/auto}devsite-my-community.devsite-my-community-small .devsite-my-community-profile-attributes-text{grid-column:1/2}devsite-nav-buttons{display:block}devsite-nav-buttons button{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;border:var(--devsite-button-border);box-shadow:none;display:-webkit-inline-box;display:-webkit-inline-flex;display:-moz-inline-box;display:-ms-inline-flexbox;display:inline-flex;font-weight:500;text-transform:none}devsite-nav-buttons button,devsite-nav-buttons button:focus,devsite-nav-buttons button:hover{color:var(--devsite-button-color)}devsite-nav-buttons button:focus,devsite-nav-buttons button:hover{background:var(--devsite-button-background-hover);border:var(--devsite-button-border-hover)}devsite-nav-buttons button,devsite-nav-buttons button[class^=button-]{border-radius:16px;height:32px;line-height:30px;padding:var(--devsite-button-padding,0 12px)}devsite-nav-buttons button[class^=button-][selected],devsite-nav-buttons button[selected]{border:var(--devsite-button-border-selected);padding-left:8px}devsite-nav-buttons button[class^=button-],devsite-nav-buttons button[class^=button-][selected]{border:0}devsite-nav-buttons button[selected]{background:var(--devsite-button-background-selected);color:var(--devsite-button-color-selected)}devsite-nav-buttons button.button-white[selected]{background:var(--devsite-button-white-background-selected,var(--devsite-link-color));color:var(--devsite-button-white-color-selected,var(--devsite-inverted-text-color))}devsite-nav-buttons button.button-primary[selected]{background:var(--devsite-button-primary-background-selected);color:var(--devsite-button-primary-color-selected,var(--devsite-inverted-text-color))}devsite-nav-buttons button[selected]:before{font:normal normal normal 24px/1 Material Icons;-webkit-font-feature-settings:"liga";-moz-font-feature-settings:"liga";font-feature-settings:"liga";-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;text-transform:none;word-wrap:normal;content:"checked";margin-right:8px;width:24px}devsite-pagination{display:block;font:var(--devsite-pagination-font,inherit);letter-spacing:var(--devsite-pagination-letter-spacing,normal)}devsite-pagination[buttons],devsite-pagination[initial-results]{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;-ms-flex-pack:center;justify-content:center}devsite-pagination button[hidden]{display:none}devsite-pagination .devsite-pagination-page-numbers-controls{-webkit-box-align:stretch;-webkit-align-items:stretch;-moz-box-align:stretch;-ms-flex-align:stretch;align-items:stretch;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex}devsite-pagination .devsite-pagination-next-button,devsite-pagination .devsite-pagination-previous-button{border:0}devsite-pagination .devsite-pagination-next-button:not([disabled]),devsite-pagination .devsite-pagination-previous-button:not([disabled]){border:0;color:var(--devsite-secondary-text-color)}devsite-pagination .devsite-pagination-previous-button:before{content:"chevron_left"}devsite-pagination .devsite-pagination-next-button:before{content:"chevron_right"}devsite-pagination .devsite-pagination-page-numbers{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex}devsite-pagination .devsite-pagination-ellipsis,devsite-pagination a{margin:var(--devsite-pagination-link-margin,0 7px)}devsite-pagination a[selected]{text-decoration:underline}devsite-pagination .devsite-pagination-ellipsis{-webkit-align-self:flex-start;-ms-flex-item-align:start;align-self:flex-start;padding-top:1px}[dir] devsite-pagination .button,[dir] devsite-pagination .button+.button{margin-left:10px;margin-right:10px}devsite-panel{bottom:0;display:block;height:var(--devsite-panel-height,auto);left:0;max-height:var(--devsite-panel-max-height,50vh);overflow:auto;position:fixed;right:0;z-index:1017}devsite-panel[always-on-top]{z-index:1019}devsite-panel[devsite-size=content-area]{background-color:var(--devsite-background-1)}devsite-playlist{display:block;margin-bottom:48px}devsite-playlist .devsite-playlist--inner{margin:0 auto;max-width:var(--devsite-playlist-max-width);padding:0 var(--devsite-playlist-padding-x)}devsite-playlist .devsite-playlist--header{background-color:#133041}devsite-playlist .devsite-playlist--header .devsite-playlist--inner{padding-bottom:24px}devsite-playlist .devsite-playlist--header-details{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-webkit-justify-content:space-between;-moz-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between}devsite-playlist .devsite-playlist--header-badge-info,devsite-playlist .devsite-playlist--header-details-info{color:#fff;padding-top:40px;width:calc(50% - 20px)}devsite-playlist .devsite-playlist--header-badge-info{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;-ms-flex-pack:center;justify-content:center;position:relative}devsite-playlist .devsite-playlist--header-badge-info--bg{background:url(../images/playlist_header.svg) no-repeat 0 -20px/cover;content:"";height:213px;left:0;position:absolute;top:0;width:510px}devsite-playlist .devsite-playlist--header-badge-info--container{-webkit-align-self:center;-ms-flex-item-align:center;align-self:center;justify-self:center;position:relative}devsite-playlist .devsite-playlist-badge-details-icon,devsite-playlist .devsite-playlist-badge-details-icon-container{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;-ms-flex-pack:center;justify-content:center}devsite-playlist .devsite-playlist-badge-details-icon-container-signin-enabled.devsite-playlist-badge-details-icon-container{margin-bottom:-48px;position:relative;z-index:1}devsite-playlist .devsite-playlist-badge-details-icon{background:var(--devsite-background-1);border-radius:50%;height:135px;padding:7px;position:relative;width:135px}devsite-playlist .devsite-playlist-badge-details-icon-container-signin-enabled .devsite-playlist-badge-details-icon{-webkit-transform:translate3d(0,-44px,0);transform:translate3d(0,-44px,0);-webkit-transition:-webkit-transform .2s cubic-bezier(0,0,.2,1);transition:-webkit-transform .2s cubic-bezier(0,0,.2,1);transition:transform .2s cubic-bezier(0,0,.2,1);transition:transform .2s cubic-bezier(0,0,.2,1),-webkit-transform .2s cubic-bezier(0,0,.2,1)}devsite-playlist .devsite-playlist--progress-bar--outer,devsite-playlist .devsite-playlist--progress-text,devsite-playlist .devsite-playlist-badge-details-action,devsite-playlist .devsite-playlist-badge-details-icon img,devsite-playlist .devsite-playlist-badge-details-subtext{opacity:1;position:relative;-webkit-transition:opacity .2s cubic-bezier(.4,0,1,1),-webkit-transform .2s cubic-bezier(.4,0,1,1);transition:opacity .2s cubic-bezier(.4,0,1,1),-webkit-transform .2s cubic-bezier(.4,0,1,1);transition:opacity .2s cubic-bezier(.4,0,1,1),transform .2s cubic-bezier(.4,0,1,1);transition:opacity .2s cubic-bezier(.4,0,1,1),transform .2s cubic-bezier(.4,0,1,1),-webkit-transform .2s cubic-bezier(.4,0,1,1);z-index:2}devsite-playlist .devsite-playlist-badge-details-icon img{-webkit-animation:badgeGrowIn .33s cubic-bezier(.75,0,.71,.97),badgeGrowOut .17s cubic-bezier(.85,-.14,.83,.83) .33s,badgeFadeIn .5s linear;animation:badgeGrowIn .33s cubic-bezier(.75,0,.71,.97),badgeGrowOut .17s cubic-bezier(.85,-.14,.83,.83) .33s,badgeFadeIn .5s linear;opacity:1;-webkit-transform:scale(1);transform:scale(1)}devsite-playlist .devsite-playlist-badge-sharing{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;border-top:var(--devsite-secondary-border);display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-webkit-justify-content:space-between;-moz-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;margin:12px -16px -16px;padding:8px 0;-webkit-padding-start:12px;-moz-padding-start:12px;padding-inline-start:12px}devsite-playlist .devsite-playlist-share-buttons{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;-ms-flex-pack:center;justify-content:center}devsite-playlist .devsite-playlist-badge-sharing span{color:var(--devsite-secondary-text-color);font-size:14px;line-height:1}devsite-playlist .devsite-playlist-badge-sharing img{width:18px}devsite-playlist .devsite-playlist-badge-sharing button{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;border:0;box-shadow:none;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;height:auto;-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;-ms-flex-pack:center;justify-content:center;min-width:0;padding:4px}devsite-playlist .devsite-playlist-badge-sharing button:focus,devsite-playlist .devsite-playlist-badge-sharing button:hover{background:none}devsite-playlist .devsite-playlist-badge-sharing button+button{margin:0 8px}devsite-playlist .devsite-playlist-badge-details-icon img{position:static}devsite-playlist .devsite-playlist-badge-details-icon devsite-spinner{opacity:0;position:absolute;-webkit-transition:opacity .2s cubic-bezier(.4,0,1,1);transition:opacity .2s cubic-bezier(.4,0,1,1)}devsite-playlist .devsite-playlist--progress-text{color:var(--devsite-primary-text-color);font-size:16px;font-weight:500;line-height:20px;text-align:center}devsite-playlist .devsite-playlist--progress-bar{-webkit-transition:opacity .2s cubic-bezier(.4,0,1,1);transition:opacity .2s cubic-bezier(.4,0,1,1)}devsite-playlist .devsite-playlist--progress-bar.hide{opacity:0}devsite-playlist .devsite-playlist--progress-bar--outer{background:var(--devsite-link-background-active);border-radius:24px;height:10px;margin:14px 0 0;position:relative}devsite-playlist .devsite-playlist--progress-bar--inner{background:var(--devsite-link-color);border-radius:24px;display:inline-block;height:100%;position:absolute;-webkit-transition:width .3s cubic-bezier(0,0,.2,1);transition:width .3s cubic-bezier(0,0,.2,1);white-space:nowrap;width:0}devsite-playlist .devsite-playlist-badge-details-action,devsite-playlist .devsite-playlist-badge-details-subtext{font-size:14px;line-height:16px;text-align:center}devsite-playlist .devsite-playlist-badge-details-subtext{color:var(--devsite-secondary-text-color);padding:28px 0 0}devsite-playlist .devsite-playlist-badge-details-action{font-weight:700;padding:4px 0 0}devsite-playlist .no-badge .devsite-playlist-badge-details-icon-container{display:none}devsite-playlist .badge-earned .devsite-playlist-badge-details-subtext{padding:0 0 12px}devsite-playlist .not-eligible .devsite-playlist--progress-bar,devsite-playlist .not-eligible .devsite-playlist--progress-text{display:none}devsite-playlist .not-eligible.no-badge .devsite-playlist-badge-details-subtext{padding-top:0}devsite-playlist .loading{pointer-events:none}devsite-playlist .loading .devsite-playlist-badge-details-icon-container{bottom:0;left:0;margin-bottom:0;position:absolute;right:0;top:0}devsite-playlist .loading .devsite-playlist-badge-details-icon{background:0;-webkit-transform:translateZ(0);transform:translateZ(0)}devsite-playlist .loading .devsite-playlist--progress-bar--outer,devsite-playlist .loading .devsite-playlist--progress-text,devsite-playlist .loading .devsite-playlist-badge-details-action,devsite-playlist .loading .devsite-playlist-badge-details-subtext{opacity:0}devsite-playlist .loading .devsite-playlist-badge-details-icon img{opacity:0;position:absolute}devsite-playlist .loading .devsite-playlist-badge-details-icon devsite-spinner{opacity:1}devsite-playlist .devsite-playlist--header h1:first-of-type{color:#fff;font:var(--devsite-h1-font)}devsite-playlist .devsite-playlist-details{color:var(--devsite-secondary-text-color);font-size:12px;line-height:16px}devsite-playlist .devsite-playlist--header p{line-height:24px;margin:22px 0;padding:0}devsite-playlist .devsite-playlist-return-button{margin-top:24px}devsite-playlist .devsite-playlist-summary{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;font:normal 700 12px/24px var(--devsite-primary-font-family)}devsite-playlist .devsite-playlist-badge-details{background:var(--devsite-background-1);border-radius:8px;height:auto;max-width:213px;padding:16px;width:100%;min-width:64px;min-height:64px}devsite-playlist .profile-notification{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;-ms-flex-pack:center;justify-content:center}devsite-playlist .profile-notification--inner{box-shadow:0 1px 2px 0 var(--devsite-elevation-key-shadow-color),0 2px 6px 2px var(--devsite-elevation-ambient-shadow-color);border-radius:4px;color:var(--devsite-secondary-text-color);margin:0 auto;padding:16px}devsite-playlist .devsite-playlist--section{padding:24px 0;position:relative}devsite-playlist .devsite-playlist--section .arrow--up,devsite-playlist[not-signed-in] .devsite-playlist--item--meta em,devsite-playlist[not-signed-in] .devsite-playlist--section .playlist-skip{display:none}devsite-playlist .devsite-playlist--item-top{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex}devsite-playlist .devsite-playlist--item-top:before{background:var(--devsite-background-5);content:"";display:block;height:0;-webkit-margin-start:15px;-moz-margin-start:15px;margin-inline-start:15px;margin-top:2px;position:absolute;top:54px;-webkit-transition:height .2s cubic-bezier(.4,0,1,1),opacity .2s cubic-bezier(.4,0,1,1);transition:height .2s cubic-bezier(.4,0,1,1),opacity .2s cubic-bezier(.4,0,1,1);width:1px;z-index:1}devsite-playlist .devsite-playlist--item-top-index{-webkit-box-flex:0;-webkit-flex:0 0;-moz-box-flex:0;-ms-flex:0 0;flex:0 0;position:relative;width:30px}devsite-playlist .devsite-playlist--item-top-index span{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;background:var(--devsite-primary-text-color);border-radius:50%;color:var(--devsite-inverted-text-color);display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;height:30px;-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;-ms-flex-pack:center;justify-content:center;margin-top:2px;opacity:1;width:30px}devsite-playlist .devsite-playlist--item-top-index i{color:var(--devsite-playlist-icon-color);font-size:36px;height:36px;left:-3px;opacity:0;position:absolute;top:-1px;-webkit-transform:rotate(45deg);transform:rotate(45deg);width:36px}devsite-playlist .devsite-playlist--item-top-index devsite-spinner{opacity:0;position:absolute;top:2px}devsite-playlist .devsite-playlist--item-top-index devsite-spinner,devsite-playlist .devsite-playlist--item-top-index i,devsite-playlist .devsite-playlist--item-top-index span{-webkit-transition:background .2s cubic-bezier(.4,0,1,1),opacity .2s cubic-bezier(.4,0,1,1);transition:background .2s cubic-bezier(.4,0,1,1),opacity .2s cubic-bezier(.4,0,1,1)}devsite-playlist .devsite-playlist--item-top-controls{width:32px}devsite-playlist .devsite-playlist--item-top-controls button{box-shadow:0 1px 2px 0 var(--devsite-elevation-key-shadow-color),0 2px 6px 2px var(--devsite-elevation-ambient-shadow-color);-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;border-radius:50%;color:var(--devsite-playlist-button-color,var(--devsite-primary-text-color));display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;height:32px;-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;-ms-flex-pack:center;justify-content:center;min-width:0;padding:0;width:32px}devsite-playlist .devsite-playlist--item-top-controls button:focus,devsite-playlist .devsite-playlist--item-top-controls button:hover{color:var(--devsite-playlist-button-color-hover)}devsite-playlist .devsite-playlist--item-top-controls button:active{color:var(--devsite-playlist-button-color-active)}devsite-playlist .devsite-playlist--item-top-controls button .material-icons{cursor:pointer;font-size:24px;height:24px;margin:0;position:static;top:auto;width:24px}devsite-playlist .devsite-playlist--item-top-title{cursor:pointer;-webkit-box-flex:1;-webkit-flex:1;-moz-box-flex:1;-ms-flex:1;flex:1;padding:0 18px}devsite-playlist .devsite-playlist--item-top-title h2{font-size:28px;line-height:36px;margin:0;padding:0}devsite-playlist .devsite-playlist--item--content,devsite-playlist .devsite-playlist--item--meta{padding:0 48px}devsite-playlist .devsite-playlist--item--meta{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;color:var(--devsite-secondary-text-color);display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;font-size:12px;line-height:16px;margin:4px 0}devsite-playlist .devsite-playlist--item--meta em{-webkit-padding-start:16px;-moz-padding-start:16px;padding-inline-start:16px}devsite-playlist .devsite-playlist--item--meta .material-icons{font-size:18px;height:18px;-webkit-margin-end:4px;-moz-margin-end:4px;margin-inline-end:4px;width:18px}devsite-playlist .devsite-playlist--item--actions,devsite-playlist .devsite-playlist--item--content{display:none}devsite-playlist .devsite-playlist--item--actions{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:end;-webkit-justify-content:flex-end;-moz-box-pack:end;-ms-flex-pack:end;justify-content:flex-end;padding:8px 0 32px;-webkit-padding-start:48px;-moz-padding-start:48px;padding-inline-start:48px}devsite-playlist [ready] .devsite-playlist--item-top:before{height:calc(100% - 30px)}devsite-playlist [expanded]{background:#f5f5f7 url(../images/playlist_active.svg) repeat-x top}devsite-playlist [expanded] .arrow--down{display:none}devsite-playlist [expanded] .arrow--up{display:block}devsite-playlist [expanded] .devsite-playlist--item-top-index span{background:var(--devsite-link-color)}devsite-playlist [expanded] .devsite-playlist--item--content{display:block}devsite-playlist [expanded] .devsite-playlist--item--actions{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex}devsite-playlist [type=game] .devsite-playlist--item--content,devsite-playlist [type=video] .devsite-playlist--item--content{padding:12px 48px}devsite-playlist [completing] devsite-spinner{opacity:1}devsite-playlist [completed] .devsite-playlist--item-top-index span{opacity:0}devsite-playlist [completed] .devsite-playlist--item-top-index i{opacity:1;-webkit-transform:rotate(0);transform:rotate(0)}devsite-playlist [completed] .playlist-skip{display:none}devsite-playlist [completed][expanded] .devsite-playlist--item-top-index i{background-color:rgba(230,240,255,.24)}devsite-playlist [last] .devsite-playlist--item-top:before{display:none}devsite-playlist .devsite-playlist--section-quiz{border:var(--devsite-primary-border);border-radius:4px;padding:24px}devsite-playlist .devsite-playlist--section-quiz h2{margin:0;padding:0}devsite-playlist .devsite-playlist--section-project-header{-webkit-box-align:start;-webkit-align-items:start;-moz-box-align:start;-ms-flex-align:start;align-items:start;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-moz-box-orient:vertical;-moz-box-direction:normal;-ms-flex-direction:column;flex-direction:column;gap:0 8px}devsite-playlist .devsite-playlist--project--status{background:var(--devsite-background-3);border-radius:4px;font:500 11px/16px var(--devsite-primary-font-family);letter-spacing:.8px;padding-block:4px;padding-inline:8px;text-transform:uppercase}devsite-playlist .devsite-playlist--footer,devsite-playlist .devsite-playlist--section-quiz .devsite-playlist--item--actions{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex}devsite-playlist .devsite-playlist--footer{-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;-ms-flex-pack:center;justify-content:center;margin-top:20px;padding:4px 0}.devsite-playlist-dialog{box-shadow:0 1px 3px 0 var(--devsite-elevation-key-shadow-color),0 4px 8px 3px var(--devsite-elevation-ambient-shadow-color);background:var(--devsite-background-1);border-radius:8px;padding:24px;position:relative}.devsite-playlist-dialog .devsite-playlist-dialog-spinner{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;background:var(--devsite-background-1);bottom:0;display:none;-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;-ms-flex-pack:center;justify-content:center;left:0;position:absolute;right:0;top:0;z-index:100}.devsite-playlist-dialog.loading .devsite-playlist-dialog-spinner{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex}.devsite-playlist-dialog .devsite-playlist-dialog-inner{color:var(--devsite-secondary-text-color);position:relative}.devsite-playlist-dialog .devsite-playlist-dialog-inner h4{font-family:var(--devsite-headline-font-family);font-size:16px;line-height:24px;margin:0 0 16px}.devsite-playlist-dialog .devsite-playlist-dialog-inner label{font-size:14px;line-height:22px}.devsite-playlist-dialog .devsite-playlist-dialog-inner p{color:var(--devsite-secondary-text-color);font-size:12px;line-height:16px}@media screen and (max-width:600px){devsite-playlist .devsite-playlist--header-details{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-moz-box-orient:vertical;-moz-box-direction:normal;-ms-flex-direction:column;flex-direction:column}devsite-playlist .devsite-playlist--header-badge-info,devsite-playlist .devsite-playlist--header-details-info{width:100%}devsite-playlist .devsite-playlist--header-badge-info--bg{background-position:0;top:84px}}devsite-playlist-earnable-badges{display:block}devsite-playlist-earnable-badges.loading{position:relative}devsite-playlist-earnable-badges .spinner-container{position:absolute;top:0;right:0;bottom:0;left:0;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;-ms-flex-pack:center;justify-content:center}devsite-playlist-summary{display:block}devsite-playlist-summary.loading{position:relative}devsite-playlist-summary .progress-container{position:absolute;top:0;right:0;left:0;z-index:1000}devsite-playlist-summary .devsite-playlist-summary-image.hide,devsite-playlist-summary .devsite-playlist-summary-info.hide{opacity:0;-webkit-transform:translateY(12px);transform:translateY(12px);-webkit-transition:opacity .213s cubic-bezier(.4,0,1,1),-webkit-transform .213s cubic-bezier(.4,0,1,1);transition:opacity .213s cubic-bezier(.4,0,1,1),-webkit-transform .213s cubic-bezier(.4,0,1,1);transition:transform .213s cubic-bezier(.4,0,1,1),opacity .213s cubic-bezier(.4,0,1,1);transition:transform .213s cubic-bezier(.4,0,1,1),opacity .213s cubic-bezier(.4,0,1,1),-webkit-transform .213s cubic-bezier(.4,0,1,1)}devsite-playlist-summary .devsite-playlist-summary-image,devsite-playlist-summary .devsite-playlist-summary-info{opacity:1;-webkit-transform:translateY(0);transform:translateY(0);-webkit-transition:opacity .213s cubic-bezier(0,0,.2,1),-webkit-transform .213s cubic-bezier(0,0,.2,1);transition:opacity .213s cubic-bezier(0,0,.2,1),-webkit-transform .213s cubic-bezier(0,0,.2,1);transition:transform .213s cubic-bezier(0,0,.2,1),opacity .213s cubic-bezier(0,0,.2,1);transition:transform .213s cubic-bezier(0,0,.2,1),opacity .213s cubic-bezier(0,0,.2,1),-webkit-transform .213s cubic-bezier(0,0,.2,1)}devsite-playlist-summary .devsite-playlist-summary-progress-background{overflow:hidden}devsite-playlist-summary.not-signed-in .devsite-playlist-summary-progress-background{margin-right:0}devsite-playlist-summary.not-signed-in .devsite-playlist-summary-progress-bar-value{display:none}devsite-playlist-summary .devsite-playlist-summary-progress-bar{-webkit-transform:translateX(-101%);transform:translateX(-101%);-webkit-transition:-webkit-transform .213s cubic-bezier(0,0,.2,1);transition:-webkit-transform .213s cubic-bezier(0,0,.2,1);transition:transform .213s cubic-bezier(0,0,.2,1);transition:transform .213s cubic-bezier(0,0,.2,1),-webkit-transform .213s cubic-bezier(0,0,.2,1)}devsite-playlist-summary .devsite-playlist-summary-progress-bar-value:empty:before,devsite-playlist-summary .devsite-playlist-summary-status:empty:before{content:" "}devsite-product-catalog .devsite-product-catalog-alphabet{border-bottom:var(--devsite-primary-border);border-top:var(--devsite-primary-border);color:var(--devsite-secondary-text-color);display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;font-size:20px;-webkit-box-pack:justify;-webkit-justify-content:space-between;-moz-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;padding:16px 0}devsite-product-catalog .devsite-product-catalog-alphabet-link,devsite-product-catalog .devsite-product-catalog-alphabet-link-disabled{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-flex:1;-webkit-flex:1 1 auto;-moz-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto;padding:10px 0}devsite-product-catalog .devsite-product-catalog-alphabet-letter:not(:last-child){border-bottom:var(--devsite-primary-border)}devsite-product-catalog .devsite-product-catalog-alphabet-letter-heading{margin:20px 0}devsite-product-catalog .devsite-product-catalog-alphabet-letter-list{-webkit-column-count:3;-moz-column-count:3;column-count:3;-webkit-column-gap:40px;-moz-column-gap:40px;column-gap:40px;list-style:none;margin:0 0 40px;padding:0}devsite-product-catalog .devsite-product-catalog-alphabet-letter-list-item{-webkit-column-break-inside:avoid;break-inside:avoid;margin:0 0 16px}devsite-product-catalog .devsite-product-catalog-alphabet-letter-link{display:block;padding:8px 0}devsite-product-catalog .devsite-product-catalog-item-name{margin:0}devsite-product-catalog devsite-filter:not(:first-of-type){border-top:var(--devsite-primary-border)}devsite-product-catalog .devsite-filter-input+.devsite-product-catalog-alphabet{margin-top:32px}devsite-product-catalog .devsite-filter-input:valid+.devsite-product-catalog-alphabet{display:none}@media screen and (max-width:840px){devsite-product-catalog .devsite-product-catalog-alphabet{-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-pack:start;-webkit-justify-content:flex-start;-moz-box-pack:start;-ms-flex-pack:start;justify-content:flex-start}devsite-product-catalog .devsite-product-catalog-alphabet-letter-list{-webkit-column-count:2;-moz-column-count:2;column-count:2}devsite-product-catalog .devsite-product-catalog-alphabet-link,devsite-product-catalog .devsite-product-catalog-alphabet-link-disabled{display:block;-webkit-box-flex:0;-webkit-flex:0 0 44px;-moz-box-flex:0;-ms-flex:0 0 44px;flex:0 0 44px;text-align:center}}@media screen and (max-width:600px){devsite-product-catalog .devsite-product-catalog-alphabet{padding:0 0 20px}devsite-product-catalog .devsite-product-catalog-alphabet-letter-list{-webkit-column-count:1;-moz-column-count:1;column-count:1}}devsite-progress{pointer-events:none;-webkit-transform-origin:50% 0;transform-origin:50% 0;-webkit-transform:scaleY(0);transform:scaleY(0);-webkit-transition:-webkit-transform .2s ease;transition:-webkit-transform .2s ease;transition:transform .2s ease;transition:transform .2s ease,-webkit-transform .2s ease}devsite-progress[type=indeterminate]{height:2px;-webkit-transform:scaleY(1);transform:scaleY(1);contain:size layout style paint}devsite-progress .devsite-progress--indeterminate{position:relative;height:2px}devsite-progress .devsite-progress--indeterminate-1,devsite-progress .devsite-progress--indeterminate-2,devsite-progress .devsite-progress--indeterminate-3,devsite-progress .devsite-progress--indeterminate-4{bottom:0;left:0;position:absolute;right:0;top:0;-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:scaleX(0);transform:scaleX(0)}devsite-progress .devsite-progress--indeterminate-1{-webkit-animation:progress-indeterminate-1 2.5s linear infinite;animation:progress-indeterminate-1 2.5s linear infinite;background:var(--devsite-progress-background-1,var(--devsite-background-1));z-index:1}devsite-progress .devsite-progress--indeterminate-2{-webkit-animation:progress-indeterminate-2 2.5s ease-in infinite;animation:progress-indeterminate-2 2.5s ease-in infinite;background:var(--devsite-progress-background-2,var(--devsite-background-1));z-index:2}devsite-progress .devsite-progress--indeterminate-3{-webkit-animation:progress-indeterminate-3 2.5s ease-out infinite;animation:progress-indeterminate-3 2.5s ease-out infinite;background:var(--devsite-progress-background-3,var(--devsite-background-1));z-index:3}devsite-progress .devsite-progress--indeterminate-4{-webkit-animation:progress-indeterminate-4 2.5s ease-out infinite;animation:progress-indeterminate-4 2.5s ease-out infinite;background:var(--devsite-progress-background-4,var(--devsite-background-1));z-index:4}devsite-progress .devsite-progress--indeterminate-1,devsite-progress .devsite-progress--indeterminate-2,devsite-progress .devsite-progress--indeterminate-3,devsite-progress .devsite-progress--indeterminate-4{-webkit-animation-play-state:var(--devsite-progress-animation-play-state);animation-play-state:var(--devsite-progress-animation-play-state)}@-webkit-keyframes progress-indeterminate-1{0%{-webkit-transform:scaleX(0);transform:scaleX(0)}50%,to{-webkit-transform:scaleX(1);transform:scaleX(1)}}@keyframes progress-indeterminate-1{0%{-webkit-transform:scaleX(0);transform:scaleX(0)}50%,to{-webkit-transform:scaleX(1);transform:scaleX(1)}}@-webkit-keyframes progress-indeterminate-2{0%,20%{-webkit-transform:scaleX(0);transform:scaleX(0)}70%,to{-webkit-transform:scaleX(1);transform:scaleX(1)}}@keyframes progress-indeterminate-2{0%,20%{-webkit-transform:scaleX(0);transform:scaleX(0)}70%,to{-webkit-transform:scaleX(1);transform:scaleX(1)}}@-webkit-keyframes progress-indeterminate-3{0%,60%{-webkit-transform:scaleX(0);transform:scaleX(0)}90%,to{-webkit-transform:scaleX(1);transform:scaleX(1)}}@keyframes progress-indeterminate-3{0%,60%{-webkit-transform:scaleX(0);transform:scaleX(0)}90%,to{-webkit-transform:scaleX(1);transform:scaleX(1)}}@-webkit-keyframes progress-indeterminate-4{0%,75%{-webkit-transform:scaleX(0);transform:scaleX(0)}to{-webkit-transform:scaleX(1);transform:scaleX(1)}}@keyframes progress-indeterminate-4{0%,75%{-webkit-transform:scaleX(0);transform:scaleX(0)}to{-webkit-transform:scaleX(1);transform:scaleX(1)}}@keyframes badgeGrowIn{0%{-webkit-transform:scale(0);transform:scale(0)}to{-webkit-transform:scale(1.3);transform:scale(1.3)}}@keyframes badgeGrowOut{0%{-webkit-transform:scale(1.3);transform:scale(1.3)}to{-webkit-transform:scale(1);transform:scale(1)}}@keyframes badgeFadeIn{0%{opacity:0}12%{opacity:0}87%{opacity:100%}}@keyframes counterHide{0%{opacity:0}to{opacity:0}}devsite-quiz{display:block;font-size:14px}devsite-quiz input[type=checkbox],devsite-quiz input[type=radio]{margin-top:0;position:relative;top:3px}devsite-quiz devsite-bookmark input.bookmark-checkbox{top:0}devsite-quiz input+label{font-size:14px;vertical-align:middle}devsite-quiz devsite-select .devsite-select-toggle{min-width:200px}devsite-quiz [answered] .variant-success:checked{color:var(--devsite-quiz-correct-color)}devsite-quiz [answered] .variant-success:checked:focus:before{background:var(--devsite-quiz-correct-background)}devsite-quiz [answered] input[type=text].variant-success{background-color:var(--devsite-quiz-correct-background);border-color:var(--devsite-quiz-correct-border-color)}devsite-quiz [answered] input[type=text]:focus.variant-success{border-bottom-color:var(--devsite-quiz-correct-border-color-focus)}devsite-quiz [answered] .variant-error:checked{color:var(--devsite-quiz-error-color)}devsite-quiz [answered] .variant-error:checked:focus:before{background:var(--devsite-quiz-error-background)}devsite-quiz [answered] input[type=text].variant-error{background-color:var(--devsite-quiz-error-background);border-color:var(--devsite-quiz-error-border-color)}devsite-quiz [answered] input[type=text]:focus.variant-error{border-bottom-color:var(--devsite-quiz-error-color)}devsite-quiz .devsite-quiz-header{background:var(--devsite-background-2);border-bottom:var(--devsite-primary-border)}devsite-quiz .devsite-quiz-header-content{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-webkit-justify-content:space-between;-moz-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;margin:0 auto;padding:48px 16px}devsite-quiz .devsite-quiz-title{margin-bottom:8px;padding:0;top:0}devsite-quiz .devsite-quiz-tagline{color:var(--devsite-quiz-secondary-text-color);font-weight:400;font-size:14px;line-height:20px;margin:0}devsite-quiz .devsite-quiz-tagline:empty{min-height:40px}devsite-quiz .devsite-quiz-return-button{margin-top:15px}devsite-quiz .devsite-quiz-badge{display:none}devsite-quiz .devsite-quiz-partially-correct-indicator{background-color:var(--devsite-quiz-partially-correct-indicator-background)}devsite-quiz .devsite-quiz-body{margin:0 auto;padding:48px 16px 0}devsite-quiz [answered] .devsite-quiz-feedback{margin-bottom:18px;opacity:1;-webkit-transform:translateX(0);transform:translateX(0);-webkit-transition:opacity .2s cubic-bezier(0,0,.2,1),-webkit-transform .2s cubic-bezier(0,0,.2,1);transition:opacity .2s cubic-bezier(0,0,.2,1),-webkit-transform .2s cubic-bezier(0,0,.2,1);transition:opacity .2s cubic-bezier(0,0,.2,1),transform .2s cubic-bezier(0,0,.2,1);transition:opacity .2s cubic-bezier(0,0,.2,1),transform .2s cubic-bezier(0,0,.2,1),-webkit-transform .2s cubic-bezier(0,0,.2,1)}devsite-quiz .devsite-quiz-submit-error{background:var(--devsite-quiz-error-background);border-radius:4px;font-size:16px;font-weight:500;line-height:30px;padding:6px 12px}devsite-quiz .devsite-quiz-submit-error i{color:var(--devsite-quiz-error-color);line-height:30px;-webkit-margin-end:8px;-moz-margin-end:8px;margin-inline-end:8px}devsite-quiz .devsite-quiz-submit-button{margin-top:64px}devsite-quiz .devsite-quiz-submit-button devsite-spinner{display:inline-block;-webkit-margin-start:15px;-moz-margin-start:15px;margin-inline-start:15px;top:5px}devsite-quiz .devsite-quiz-question-list{font:400 18px/30px var(--devsite-headline-font-family);font-weight:500;list-style-position:inside;-webkit-padding-start:0;-moz-padding-start:0;padding-inline-start:0}devsite-quiz .devsite-quiz-question{margin:0 0 64px}devsite-quiz .devsite-quiz-question:last-child{margin-bottom:0}devsite-quiz .devsite-quiz-question-header{font:400 18px/30px var(--devsite-headline-font-family);font-weight:500;margin:0}devsite-quiz .devsite-quiz-question-sub-header{color:var(--devsite-quiz-secondary-text-color);font-size:12px;font-style:italic;line-height:16px;margin:0}devsite-quiz .devsite-quiz-answer{-webkit-box-align:start;-webkit-align-items:flex-start;-moz-box-align:start;-ms-flex-align:start;align-items:flex-start;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;margin:16px 0;position:relative}devsite-quiz .devsite-quiz-answer label{font-family:var(--devsite-primary-font-family);font-weight:400;line-height:24px;-webkit-margin-end:15px;-moz-margin-end:15px;margin-inline-end:15px}devsite-quiz .devsite-quiz-answer .devsite-landing-row-item-media{-webkit-margin-end:15px;-moz-margin-end:15px;margin-inline-end:15px;min-width:auto}devsite-quiz .devsite-quiz-match-question{border-top:var(--devsite-primary-border);margin:24px 0 0}devsite-quiz .devsite-quiz-match-question-row{border-bottom:var(--devsite-primary-border);display:block}devsite-quiz .devsite-quiz-feedback,devsite-quiz .devsite-quiz-match-question-row-element{margin:24px 0}devsite-quiz .devsite-quiz-problem-item{font-size:14px;line-height:20px;margin:0}devsite-quiz .devsite-quiz-fill-in-the-blank-container{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-moz-box-orient:vertical;-moz-box-direction:normal;-ms-flex-direction:column;flex-direction:column;font-size:14px;margin:8px 0 0}devsite-quiz .devsite-quiz-fill-in-the-blank-question{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;display:block;line-height:32px;margin-bottom:0}devsite-quiz .devsite-quiz-fill-in-the-blank-question+.devsite-quiz-feedback{margin-top:8px}devsite-quiz .devsite-quiz-text-input{font-family:var(--devsite-primary-font-family);font-size:14px;font-weight:400;-webkit-margin-start:0;-moz-margin-start:0;margin-inline-start:0;padding:3px 7px}devsite-quiz .devsite-quiz-text-input::-webkit-input-placeholder{font-size:14px;font-style:italic;line-height:20px}devsite-quiz .devsite-quiz-text-input::-moz-placeholder{font-size:14px;font-style:italic;line-height:20px}devsite-quiz .devsite-quiz-text-input:-ms-input-placeholder{font-size:14px;font-style:italic;line-height:20px}devsite-quiz .devsite-quiz-text-input::-ms-input-placeholder{font-size:14px;font-style:italic;line-height:20px}devsite-quiz .devsite-quiz-text-input::placeholder{font-size:14px;font-style:italic;line-height:20px}devsite-quiz .devsite-quiz-footer{background:transparent;min-height:48px;-webkit-transition:background .2s cubic-bezier(.4,0,1,1);transition:background .2s cubic-bezier(.4,0,1,1);margin:64px 0 -68px}devsite-quiz devsite-badge-awarded{max-width:720px;display:block;margin:0 auto}devsite-quiz [show]{background:var(--devsite-background-2);-webkit-transition:background .2s cubic-bezier(0,0,.2,1);transition:background .2s cubic-bezier(0,0,.2,1)}devsite-quiz [show] .devsite-quiz-footer-content{opacity:1;-webkit-transform:translateY(0);transform:translateY(0);-webkit-transition:opacity .2s cubic-bezier(0,0,.2,1),-webkit-transform .2s cubic-bezier(0,0,.2,1);transition:opacity .2s cubic-bezier(0,0,.2,1),-webkit-transform .2s cubic-bezier(0,0,.2,1);transition:opacity .2s cubic-bezier(0,0,.2,1),transform .2s cubic-bezier(0,0,.2,1);transition:opacity .2s cubic-bezier(0,0,.2,1),transform .2s cubic-bezier(0,0,.2,1),-webkit-transform .2s cubic-bezier(0,0,.2,1)}devsite-quiz .devsite-quiz-footer-content{opacity:0;padding:48px 16px;-webkit-transform:translateY(24px);transform:translateY(24px);-webkit-transition:opacity .2s cubic-bezier(.4,0,1,1),-webkit-transform .2s cubic-bezier(.4,0,1,1);transition:opacity .2s cubic-bezier(.4,0,1,1),-webkit-transform .2s cubic-bezier(.4,0,1,1);transition:opacity .2s cubic-bezier(.4,0,1,1),transform .2s cubic-bezier(.4,0,1,1);transition:opacity .2s cubic-bezier(.4,0,1,1),transform .2s cubic-bezier(.4,0,1,1),-webkit-transform .2s cubic-bezier(.4,0,1,1)}devsite-quiz .static-badge-awarded-container{min-height:68px;background:var(--devsite-background-2)}devsite-quiz .static-badge-awarded-container .devsite-badger-award-inner:first-child{padding-top:30px}devsite-quiz .static-badge-awarded-container .devsite-badger-award-inner:last-child{padding-bottom:30px}devsite-quiz .devsite-quiz-results-container{width:100%}devsite-quiz .devsite-quiz-footer-header{font:400 32px/40px var(--devsite-headline-font-family)}devsite-quiz .devsite-quiz-score{font-weight:500}devsite-quiz .devsite-quiz-score-copy{font:400 24px/32px var(--devsite-headline-font-family);margin-bottom:8px}devsite-quiz .devsite-quiz-score-success{font-size:20px;margin-bottom:20px}devsite-quiz .devsite-quiz-score-fail .devsite-quiz-score{color:var(--devsite-quiz-error-color)}devsite-quiz .devsite-quiz-score-success .devsite-quiz-score{color:var(--devsite-quiz-correct-color)}devsite-quiz .devsite-quiz-score-subtext{color:var(--devsite-quiz-secondary-text-color);margin-top:8px}devsite-quiz .devsite-quiz-action-buttons{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex}devsite-quiz .devsite-quiz-rating{border-top:var(--devsite-primary-border);display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;-ms-flex-pack:center;justify-content:center;padding:32px 0}devsite-quiz .devsite-quiz-feedback{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;color:var(--devsite-primary-text-color);display:-webkit-inline-box;display:-webkit-inline-flex;display:-moz-inline-box;display:-ms-inline-flexbox;display:inline-flex;margin:0;opacity:0;position:relative;-webkit-transform:translateX(-24px);transform:translateX(-24px);-webkit-transition:opacity .2s cubic-bezier(.4,0,1,1),-webkit-transform .2s cubic-bezier(.4,0,1,1);transition:opacity .2s cubic-bezier(.4,0,1,1),-webkit-transform .2s cubic-bezier(.4,0,1,1);transition:opacity .2s cubic-bezier(.4,0,1,1),transform .2s cubic-bezier(.4,0,1,1);transition:opacity .2s cubic-bezier(.4,0,1,1),transform .2s cubic-bezier(.4,0,1,1),-webkit-transform .2s cubic-bezier(.4,0,1,1)}devsite-quiz .devsite-quiz-feedback-container{border-radius:4px;display:-webkit-inline-box;display:-webkit-inline-flex;display:-moz-inline-box;display:-ms-inline-flexbox;display:inline-flex;margin:-9px 0;padding:4px 12px}devsite-quiz .devsite-quiz-feedback-container:before{font:normal normal normal 24px/1 Material Icons;-webkit-font-feature-settings:"liga";-moz-font-feature-settings:"liga";font-feature-settings:"liga";-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;text-transform:none;word-wrap:normal;line-height:inherit;-webkit-margin-end:8px;-moz-margin-end:8px;margin-inline-end:8px}devsite-quiz .correct{background:var(--devsite-quiz-correct-background)}devsite-quiz .correct:before{color:var(--devsite-quiz-correct-color);content:"check_circle_outline"}devsite-quiz .partially-correct{background:var(--devsite-quiz-partially-correct-background);margin:15px 0 0}devsite-quiz .partially-correct:before{color:var(--devsite-quiz-partially-correct-color);content:"remove_circle_outline"}devsite-quiz .incorrect{background:var(--devsite-quiz-error-background)}devsite-quiz .incorrect:before{color:var(--devsite-quiz-error-color);content:"not_interested"}devsite-quiz .devsite-quiz-feedback-text{font-family:var(--devsite-headline-font-family);font-size:14px;line-height:20px;margin:5px 0}devsite-quiz .devsite-quiz-feedback-title{font-family:var(--devsite-headline-font-family);font-size:16px;font-weight:500}devsite-quiz .devsite-quiz-feedback-message{font-family:var(--devsite-primary-font-family)}@media screen and (max-width:600px){devsite-quiz .devsite-quiz-question{margin-bottom:36px}devsite-quiz .devsite-quiz-match-question-row-element{margin:12px 0}devsite-quiz .devsite-quiz-feedback{margin:0 0 12px;top:0}}@media screen and (min-width:601px){devsite-quiz .devsite-quiz-body,devsite-quiz .devsite-quiz-footer-content,devsite-quiz .devsite-quiz-header-content{-webkit-padding-start:24px;-moz-padding-start:24px;padding-inline-start:24px;-webkit-padding-end:24px;-moz-padding-end:24px;padding-inline-end:24px}devsite-quiz .devsite-quiz-badge{display:block;height:122px;min-width:122px;opacity:0;-webkit-transform:scale(1);transform:scale(1);width:122px}devsite-quiz .devsite-quiz-badge.show{-webkit-animation:badgeGrowIn .33s cubic-bezier(.75,0,.71,.97),badgeGrowOut .17s cubic-bezier(.85,-.14,.83,.83) .33s,badgeFadeIn .5s linear;animation:badgeGrowIn .33s cubic-bezier(.75,0,.71,.97),badgeGrowOut .17s cubic-bezier(.85,-.14,.83,.83) .33s,badgeFadeIn .5s linear;-webkit-margin-start:48px;-moz-margin-start:48px;margin-inline-start:48px;opacity:1;-webkit-transform:scale(1);transform:scale(1)}devsite-quiz .devsite-quiz-badge img{height:120px;width:120px}devsite-quiz .devsite-quiz-match-question{border:0;display:table;max-width:600px;width:100%}devsite-quiz .devsite-quiz-match-question-row{border:0;display:table-row}devsite-quiz .devsite-quiz-match-question-row-element,devsite-quiz .devsite-quiz-match-question-row>.devsite-quiz-feedback{display:table-cell;margin:0;padding:24px;position:relative;top:0;vertical-align:middle}devsite-quiz .devsite-quiz-match-question-row-element{border-top:var(--devsite-primary-border)}devsite-quiz .devsite-quiz-match-question-row:last-child>.devsite-quiz-match-question-row-element{border-bottom:var(--devsite-primary-border)}devsite-quiz .devsite-quiz-problem{-moz-box-sizing:border-box;box-sizing:border-box;-webkit-padding-start:0;-moz-padding-start:0;padding-inline-start:0;width:100%}devsite-quiz .devsite-quiz-answer{-webkit-padding-end:0;-moz-padding-end:0;padding-inline-end:0}devsite-quiz .devsite-quiz-feedback-container{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex}}@media screen and (min-width:841px){devsite-quiz .devsite-quiz-body,devsite-quiz .devsite-quiz-footer-content,devsite-quiz .devsite-quiz-header-content{max-width:768px}devsite-quiz .devsite-quiz-header-text{max-width:488px}devsite-quiz .devsite-quiz-footer{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;-ms-flex-pack:center;justify-content:center}devsite-quiz .devsite-quiz-footer-content{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;width:100%}devsite-quiz .devsite-quiz-footer-content+.devsite-quiz-footer-content{margin-top:0}devsite-quiz .devsite-quiz-footer-content:nth-last-child(2),devsite-quiz .devsite-quiz-footer-content:nth-last-child(2)+.devsite-quiz-footer-content{max-width:384px}devsite-quiz .devsite-quiz-footer-content:nth-last-child(2){-webkit-box-pack:end;-webkit-justify-content:flex-end;-moz-box-pack:end;-ms-flex-pack:end;justify-content:flex-end}}devsite-recommendations{border-top:var(--devsite-primary-border);display:block;-webkit-box-flex:1;-webkit-flex:1;-moz-box-flex:1;-ms-flex:1;flex:1;margin:40px -40px -40px;padding:20px 40px 40px}body[layout=full] devsite-recommendations{padding:12px 0}body[layout=docs][template=landing] devsite-recommendations{margin:0;padding:12px 40px}devsite-recommendations .significatio-overview{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-webkit-justify-content:space-between;-moz-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;position:relative}body[layout=full] devsite-recommendations .significatio-overview{margin:0 auto}body[layout=full] devsite-recommendations .significatio-body,body[layout=full] devsite-recommendations .significatio-overview{max-width:1488px;padding:0 24px}devsite-recommendations .significatio-heading{font:var(--devsite-h2-font);-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;border:0;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;margin:0;padding-right:4px}devsite-recommendations .significatio-body{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-webkit-justify-content:space-between;-moz-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;margin:12px 0 0;width:100%}body[layout=full] devsite-recommendations .significatio-body{margin:16px auto 0}devsite-recommendations .significatio-heading-icon{fill:currentColor;margin-inline:0 4px;width:24px}devsite-recommendations .significatio-buttons{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-moz-box-orient:horizontal;-moz-box-direction:normal;-ms-flex-direction:row;flex-direction:row}devsite-recommendations .significatio-buttons button{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;border-radius:50%;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;font-size:20px;height:40px;-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;-ms-flex-pack:center;justify-content:center;padding:0;-webkit-transition:background .2s;transition:background .2s;width:40px}devsite-recommendations .significatio-buttons button:focus,devsite-recommendations .significatio-buttons button:hover{background-color:#aecbfa}devsite-recommendations .significatio-buttons .material-icons{top:auto}devsite-recommendations .significatio-buttons .material-icons:not(:link){pointer-events:none}devsite-recommendations .significatio-loading{display:none}devsite-recommendations[loading] .significatio-loading{display:block;-webkit-box-flex:1;-webkit-flex:1;-moz-box-flex:1;-ms-flex:1;flex:1}devsite-recommendations .significatio-loading devsite-spinner{margin:0 auto}devsite-recommendations .significatio-recommendations{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;gap:0 24px}devsite-recommendations:not([loading]) .significatio-recommendations{width:100%}devsite-recommendations .significatio-card{background:var(--devsite-card-background);border:var(--devsite-card-border);border-radius:var(--devsite-card-border-radius);box-shadow:var(--devsite-card-box-shadow);color:var(--devsite-primary-text-color);display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-flex:1;-webkit-flex:1 1;-moz-box-flex:1;-ms-flex:1 1;flex:1 1;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-moz-box-orient:vertical;-moz-box-direction:normal;-ms-flex-direction:column;flex-direction:column;max-width:calc(33.3333333333% - 16px);min-width:0;opacity:0;padding:18px 20px 20px;-webkit-transition:opacity .2s cubic-bezier(.4,0,1,1);transition:opacity .2s cubic-bezier(.4,0,1,1)}devsite-recommendations .significatio-card:hover{box-shadow:0 1px 2px 0 var(--devsite-elevation-key-shadow-color),0 1px 3px 1px var(--devsite-elevation-ambient-shadow-color)}devsite-recommendations .significatio-card.error{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;-ms-flex-pack:center;justify-content:center}devsite-recommendations .significatio-card[show]{opacity:1}devsite-recommendations .significatio-card-heading{font:500 16px/24px var(--devsite-primary-font-family);margin:0 0 8px;-webkit-line-clamp:2;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden;text-overflow:ellipsis;color:var(--devsite-link-color)}devsite-recommendations .significatio-card-description{-webkit-box-orient:vertical;display:-webkit-box;font-size:14px;-webkit-line-clamp:2;margin:0 0 20px;max-height:48px;overflow:hidden}devsite-recommendations .significatio-card.error .significatio-card-description{color:#80868b;font:400 12px/16px var(--devsite-primary-font-family);letter-spacing:0;-webkit-line-clamp:3;margin:12px 0;text-align:center}devsite-recommendations .significatio-card.error .significatio-card-description+.significatio-card-description{margin-top:0}devsite-recommendations .significatio-card-meta{font:400 14px/16px var(--devsite-primary-font-family);color:var(--devsite-secondary-text-color);margin:auto 0 0}devsite-recommendations .info-container,devsite-recommendations .significatio-popout-container,devsite-recommendations .significatio-recommend-popout-container{-webkit-box-flex:1;-webkit-flex-grow:1;-moz-box-flex:1;-ms-flex-positive:1;flex-grow:1;position:relative}devsite-recommendations .info-button,devsite-recommendations .significatio-popout-toggle{color:#5f6368}devsite-recommendations .significatio-attr-toggle{height:16px;color:#80868b;padding:0 5px;min-width:0;display:-webkit-inline-box;display:-webkit-inline-flex;display:-moz-inline-box;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;-ms-flex-pack:center;justify-content:center;overflow:visible}devsite-recommendations .significatio-attr-toggle .significatio-attr-info{height:16px;width:16px;fill:#80868b;position:relative;top:-2px;margin:0}devsite-recommendations .significatio-attr h4{font:500 14px/16px var(--devsite-primary-font-family);color:#3c4043;line-height:20px}devsite-recommendations .significatio-attr p{font:400 14px/16px var(--devsite-primary-font-family);color:#3c4043;line-height:20px}devsite-recommendations .significatio-info-container{border-radius:50%;height:36px;-webkit-transition:opacity .2s,-webkit-transform .2s;transition:opacity .2s,-webkit-transform .2s;transition:opacity .2s,transform .2s;transition:opacity .2s,transform .2s,-webkit-transform .2s}devsite-recommendations .significatio-info-container:hover{background-color:var(--devsite-background-4)}devsite-recommendations .significatio-error-icon,devsite-recommendations .significatio-icon-info{fill:currentColor;vertical-align:text-bottom;width:18px;height:36px}devsite-recommendations .significatio-popout{box-shadow:0 1px 2px 0 var(--devsite-elevation-key-shadow-color),0 1px 3px 1px var(--devsite-elevation-ambient-shadow-color);background:var(--devsite-background-1);max-width:400px;opacity:0;padding:20px 24px;position:absolute;top:calc(100% + 8px);-webkit-transform:translateY(-12px);transform:translateY(-12px);-webkit-transition:opacity .2s,-webkit-transform .2s;transition:opacity .2s,-webkit-transform .2s;transition:opacity .2s,transform .2s;transition:opacity .2s,transform .2s,-webkit-transform .2s}[dir=ltr] devsite-recommendations .significatio-popout{left:-12px}[dir=rtl] devsite-recommendations .significatio-popout{right:-12px}devsite-recommendations .significatio-popout.significatio-attr{box-shadow:0 1px 3px 0 var(--devsite-elevation-key-shadow-color),0 4px 8px 3px var(--devsite-elevation-ambient-shadow-color);border-radius:4px;padding:16px 17px;width:150px}[dir=ltr] devsite-recommendations .significatio-popout.significatio-attr{left:calc(-75px + 50%)}[dir=rtl] devsite-recommendations .significatio-popout.significatio-attr{right:calc(-75px + 50%)}devsite-recommendations .significatio-popout.significatio-attr h4{margin-bottom:8px}devsite-recommendations .significatio-popout.significatio-attr p{margin-bottom:0}devsite-recommendations .significatio-popout-heading{margin-top:0}[dir=ltr] body[layout=full] devsite-recommendations .significatio-popout{right:32px}[dir=rtl] body[layout=full] devsite-recommendations .significatio-popout{left:32px}devsite-recommendations .significatio-popout[active]{opacity:1;-webkit-transform:translateY(0);transform:translateY(0)}devsite-recommendations .significatio-popout p{margin-top:0}devsite-recommendations .significatio-interaction-container{height:36px}devsite-recommendations .significatio-internal-only{line-height:12px;size:12px;margin:14px 0;color:#a50e0e}@media screen and (max-width:1253px){body[layout] devsite-recommendations .significatio-recommendations{display:block}body[layout] devsite-recommendations .significatio-card{max-width:none}[dir] body[layout] devsite-recommendations .significatio-card:not(:first-child){margin:24px 0 0}}@media screen and (max-width:840px){body[layout][template] devsite-recommendations{margin:24px -24px -24px;padding:24px}body[layout=full] devsite-recommendations .significatio-body,body[layout=full] devsite-recommendations .significatio-overview{padding:0}[dir=ltr] body[layout=full] devsite-recommendations .significatio-popout{right:-8px}[dir=rtl] body[layout=full] devsite-recommendations .significatio-popout{left:-8px}}@media screen and (max-width:600px){body[layout][template] devsite-recommendations{margin:32px -16px -16px;padding:16px}[dir] body[layout] devsite-recommendations .significatio-card:not(:first-child){margin:16px 0 0}}devsite-recommendations-dropdown{display:block;-webkit-box-flex:1;-webkit-flex:1;-moz-box-flex:1;-ms-flex:1;flex:1}.devsite-recommendations-dropdown-toggle{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex}.devsite-recommendations-dropdown-icon{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;height:100%;pointer-events:none;top:0}[dir=ltr] .devsite-recommendations-dropdown-icon{right:8px}[dir=rtl] .devsite-recommendations-dropdown-icon{left:8px}.devsite-recommendations-dropdown-icon:before{font-size:18px;content:"keyboard_arrow_down"}.devsite-recommendations-dropdown-toggle.active>.devsite-recommendations-dropdown-icon:before{content:"keyboard_arrow_up"}.devsite-recommendations-dropdown-list{background:var(--devsite-background-1);border:var(--devsite-list-border,var(--devsite-secondary-border));border-radius:var(--devsite-list-border-radius,2px);box-shadow:0 1px 2px 0 var(--devsite-elevation-key-shadow-color),0 2px 6px 2px var(--devsite-elevation-ambient-shadow-color);display:none;font:400 14px/20px var(--devsite-primary-font-family);opacity:0;outline:0;overflow-y:auto;pointer-events:none;position:absolute;-webkit-transition:opacity .2s,visibility .2s;transition:opacity .2s,visibility .2s;z-index:1005;list-style-type:none;padding:0 14px}.devsite-recommendations-dropdown-list.active{display:block;opacity:1;pointer-events:auto}devsite-recommendations-dropdown .devsite-select-item{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;margin:0;min-height:48px;min-width:100%;white-space:nowrap;border-bottom:1px solid #dadce0;padding:14px 0}devsite-recommendations-dropdown .devsite-select-item:hover{background-color:var(--devsite-background-3);cursor:pointer}devsite-recommendations-dropdown .devsite-select-item>.significatio-card-heading{margin:0}devsite-recommendations-sidebar{display:var(--devsite-js-recommendations-sidebar-display,block);position:relative}devsite-recommendations-sidebar .devsite-recommendations-sidebar-heading{font-weight:700;margin-bottom:8px;-webkit-margin-start:-8px;-moz-margin-start:-8px;margin-inline-start:-8px}devsite-recommendations-sidebar .devsite-recommendations-sidebar-heading-link{color:var(--devsite-recommendations-accent);padding:0}devsite-recommendations-sidebar .devsite-nav-text,devsite-recommendations-sidebar .devsite-recommendations-sidebar-icon{pointer-events:none}devsite-recommendations-sidebar .devsite-recommendations-sidebar-icon{fill:var(--devsite-recommendations-accent);height:24px;-webkit-margin-end:8px;-moz-margin-end:8px;margin-inline-end:8px;width:24px}devsite-recommendations-sidebar .devsite-nav-active .devsite-recommendations-sidebar-icon,devsite-recommendations-sidebar .devsite-recommendations-sidebar-heading-link:focus .devsite-recommendations-sidebar-icon,devsite-recommendations-sidebar .devsite-recommendations-sidebar-heading-link:hover .devsite-recommendations-sidebar-icon{fill:var(--devsite-nav-color-hover,var(--devsite-link-color))}devsite-recommendations-sidebar>.devsite-nav-list{-webkit-border-start:var(--devsite-toc-border-width,4px) solid var(--devsite-recommendations-accent);-moz-border-start:var(--devsite-toc-border-width,4px) solid var(--devsite-recommendations-accent);border-inline-start:var(--devsite-toc-border-width,4px) solid var(--devsite-recommendations-accent);-webkit-padding-start:var(--devsite-nav-list-padding-x-start,12px);-moz-padding-start:var(--devsite-nav-list-padding-x-start,12px);padding-inline-start:var(--devsite-nav-list-padding-x-start,12px)}devsite-recommendations-sidebar .devsite-nav-item{padding:var(--devsite-nav-title-padding,4px 0)}devsite-recommendations-sidebar .devsite-nav-item:first-of-type,devsite-recommendations-sidebar .devsite-nav-title:first-of-type{padding-top:0}devsite-recommendations-sidebar .devsite-nav-title{padding-bottom:0;text-decoration:none}devsite-recommendations-sidebar .significatio-card-meta{color:var(--devsite-secondary-text-color);font-size:11px;line-height:14px;margin:4px 0 0}@-webkit-keyframes fadeIn{0%{opacity:0}to{opacity:1}}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}devsite-recommended-content:not(:defined){min-height:354px}@keyframes pulse{0%,to{opacity:1}50%{opacity:.5}}devsite-recommended-content .skeleton-filters,devsite-recommended-content .skeleton-list{-webkit-animation:fadeIn .5s;animation:fadeIn .5s;list-style:none;padding:0}devsite-recommended-content .skeleton-list{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;gap:var(--devsite-item-gap,24px);-webkit-flex-wrap:var(--devsite-recommended-content-filters-flex-wrap);-ms-flex-wrap:var(--devsite-recommended-content-filters-flex-wrap);flex-wrap:var(--devsite-recommended-content-filters-flex-wrap);padding-bottom:38px}devsite-recommended-content .skeleton-filters{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;gap:8px;-webkit-flex-wrap:var(--devsite-recommended-content-filters-flex-wrap);-ms-flex-wrap:var(--devsite-recommended-content-filters-flex-wrap);flex-wrap:var(--devsite-recommended-content-filters-flex-wrap);overflow:hidden;padding-bottom:2px}devsite-recommended-content .skeleton-header{grid-area:header}devsite-recommended-content .skeleton-item{align-self:start;background:var(--tenant-background-1);border:var(--tenant-primary-border);border-radius:8px;display:grid;grid:var(--skeleton-item-grid);margin:0;padding:16px}devsite-recommended-content .skeleton-filters .skeleton-item{gap:8px 0;-webkit-box-flex:1;-webkit-flex-grow:1;-moz-box-flex:1;-ms-flex-positive:1;flex-grow:1;-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0}devsite-recommended-content .skeleton-list .skeleton-item{gap:8px 0;-webkit-box-flex:1;-webkit-flex-grow:1;-moz-box-flex:1;-ms-flex-positive:1;flex-grow:1}devsite-recommended-content .skeleton-filters,devsite-recommended-content .skeleton-filters-header,devsite-recommended-content .skeleton-item-heading,devsite-recommended-content .skeleton-item-icon,devsite-recommended-content .skeleton-item-meta,devsite-recommended-content .skeleton-item-text{-webkit-animation:pulse 2s infinite;animation:pulse 2s infinite}devsite-recommended-content .skeleton-filters-header>div,devsite-recommended-content .skeleton-item-heading>div,devsite-recommended-content .skeleton-item-icon,devsite-recommended-content .skeleton-item-meta,devsite-recommended-content .skeleton-item-text>div{background:var(--tenant-background-3);border-radius:4px}devsite-recommended-content .skeleton-filters-header{height:40px;padding-top:6px}devsite-recommended-content .skeleton-filters-header>div{border:var(--tenant-primary-border);background:var(--tenant-background-1);width:20%;height:24px}devsite-recommended-content .skeleton-item-heading>div{height:26px}devsite-recommended-content .skeleton-item-heading>div:first-child{margin-block:4px 0;width:95%}devsite-recommended-content .skeleton-item-heading>div:nth-child(2){margin-block:8px 0;width:55%}devsite-recommended-content .skeleton-item-meta,devsite-recommended-content .skeleton-item-text{margin-block:4px 0}devsite-recommended-content .skeleton-item-meta{height:14px;width:45%}devsite-recommended-content .skeleton-item-text>div{height:14px}devsite-recommended-content .skeleton-item-text>div:first-child{width:100%}devsite-recommended-content .skeleton-item-text>div:nth-child(2){margin-block:8px 0;width:70%}devsite-recommended-content .skeleton-item-text>div:nth-child(3){margin-block:8px 0;width:60%}devsite-recommended-content .skeleton-item-icon{height:32px;width:32px}@media (max-width:1128px){devsite-recommended-content:not(:defined){min-height:496px}devsite-recommended-content .skeleton-filters-header{height:114px}devsite-recommended-content .skeleton-filters{padding-bottom:6px}devsite-recommended-content .skeleton-list .skeleton-item:nth-child(4){display:none}}@media (max-width:820px){devsite-recommended-content .skeleton-list .skeleton-item:nth-child(3){display:none}}@media (max-width:600px){devsite-recommended-content:not(:defined){min-height:334px}devsite-recommended-content .skeleton-list .skeleton-item:nth-child(2){display:none}devsite-recommended-content .skeleton-list{padding-bottom:18px}devsite-recommended-content .skeleton-list .skeleton-item{max-width:85%}devsite-recommended-content .skeleton-filters{padding-bottom:2px}devsite-recommended-content .skeleton-filters-header{height:40px}}devsite-recommended-content .devsite-recommended-content-filters-spacer{min-height:100px}devsite-recommended-content .devsite-recommended-content-profile-cta{min-height:46px;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;-ms-flex-pack:center;justify-content:center;gap:16px;-webkit-animation:fadeIn .5s;animation:fadeIn .5s;--devsite-background-button-background:transparent;--devsite-background-button-background-hover:transparent;--devsite-background-button-border-color-hover:var( + --devsite-background-button-border-color + )}devsite-recommended-content .devsite-recommended-content-profile-cta .devsite-recommended-content-profile-cta-badge{height:46px;width:190px;border-bottom:1px solid #dadce0}devsite-recommended-content .devsite-recommended-content-profile-cta .button{-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0}devsite-recommended-content .devsite-recommended-content-profile-cta .text{color:#1a73e8;line-height:1}@media (max-width:820px){devsite-recommended-content .devsite-recommended-content-profile-cta .devsite-recommended-content-profile-cta-badge{display:none}}@media (max-width:600px){devsite-recommended-content .devsite-recommended-content-profile-cta{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-moz-box-orient:vertical;-moz-box-direction:normal;-ms-flex-direction:column;flex-direction:column;padding-top:18px;text-align:center}devsite-recommended-content .devsite-recommended-content-profile-cta .text{line-height:20px}}devsite-recommended-content{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;gap:16px 0;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-moz-box-orient:vertical;-moz-box-direction:normal;-ms-flex-direction:column;flex-direction:column}devsite-recommended-content .devsite-recommended-content-header{-webkit-animation:fadeIn .5s;animation:fadeIn .5s;-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-webkit-justify-content:space-between;-moz-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between}@media (max-width:600px){devsite-recommended-content .devsite-recommended-content-header{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-moz-box-orient:vertical;-moz-box-direction:normal;-ms-flex-direction:column;flex-direction:column;-webkit-box-align:start;-webkit-align-items:flex-start;-moz-box-align:start;-ms-flex-align:start;align-items:flex-start}}devsite-recommended-content .devsite-recommended-content-heading{-webkit-animation:fadeIn .5s;animation:fadeIn .5s;-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;gap:8px;line-height:24px}devsite-recommended-content .devsite-recommended-content-heading-message,devsite-recommended-content .devsite-recommended-content-item-updated{color:var(--devsite-secondary-text-color);font-size:14px}devsite-recommended-content .devsite-recommended-content-heading-label{font-size:16px;line-height:36px}devsite-recommended-content devsite-rich-tooltip{font:14px/20px var(--devsite-primary-font-family)}devsite-recommended-content .devsite-recommended-content-heading-message{font-style:italic}devsite-recommended-content .devsite-recommended-content-toggle{display:var(--devsite-recommended-content-toggle-display)}devsite-recommended-content .devsite-recommended-content-filters-wrapper{position:relative}devsite-recommended-content devsite-feature-tooltip{top:24px}devsite-recommended-content .devsite-recommended-content-filters{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;gap:8px;-webkit-flex-wrap:var(--devsite-recommended-content-filters-flex-wrap);-ms-flex-wrap:var(--devsite-recommended-content-filters-flex-wrap);flex-wrap:var(--devsite-recommended-content-filters-flex-wrap);grid-area:filters;margin-block:var(--devsite-recommended-content-filters-margin-block,-8px);margin-inline:var(--devsite-recommended-content-filters-margin-inline,0);overflow:var(--devsite-recommended-content-filters-overflow);padding-block:var(--devsite-recommended-content-filters-padding-block,8px);padding-inline:var(--devsite-recommended-content-filters-padding-inline,0);-webkit-transition:opacity .5s;transition:opacity .5s;width:var(--devsite-recommended-content-filters-width,100%)}devsite-recommended-content .devsite-recommended-content-filters::-webkit-scrollbar{background:0;height:0;width:0}devsite-recommended-content .devsite-recommended-content-filters-item input[type=checkbox]{display:inline}devsite-recommended-content .devsite-recommended-content-filters-item input[type=checkbox]:after,devsite-recommended-content .devsite-recommended-content-filters-item input[type=checkbox]:before{display:none}devsite-recommended-content .devsite-recommended-content-filters-item label{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;background:var(--devsite-background-1);border:var(--devsite-primary-border);border-radius:8px;color:var(--devsite-primary-text-color);display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;font:var(--devsite-button-font,500 14px/36px var(--devsite-primary-font-family));height:32px;padding:0 16px;-webkit-transition:background .2s,border .2s,box-shadow .2s,color .2s;transition:background .2s,border .2s,box-shadow .2s,color .2s;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;white-space:nowrap}devsite-recommended-content .devsite-recommended-content-filters-item label:hover{background:var(--devsite-background-2)}devsite-recommended-content .devsite-recommended-content-filters-item input:disabled+label:hover{background:var(--devsite-background-1)}devsite-recommended-content .devsite-recommended-content-filters-item input[type=checkbox]:focus+label{background:var(--devsite-background-3);border-color:var(--devsite-primary-text-color)}devsite-recommended-content .devsite-recommended-content-filters-item input[type=checkbox]:checked+label{background:var(--devsite-link-background-hover);border-color:transparent;color:var(--devsite-link-color)}[background=grey] devsite-recommended-content .devsite-recommended-content-filters-item input[type=checkbox]:checked+label{border-color:var(--devsite-link-color)}devsite-recommended-content .devsite-recommended-content-filters-item input[type=checkbox]:checked+label:hover{box-shadow:0 1px 2px 0 var(--devsite-elevation-key-shadow-color),0 1px 3px 1px var(--devsite-elevation-ambient-shadow-color)}devsite-recommended-content .devsite-recommended-content-filters-item input[type=checkbox]:checked:disabled+label:hover{box-shadow:revert}devsite-recommended-content .devsite-recommended-content-filters-item input[type=checkbox]:checked:focus+label{color:var(--devsite-contrast-link-color)}.devsite-recommended-content-filters-item input[type=checkbox]:disabled{pointer-events:none}devsite-recommended-content .devsite-recommended-content-list-header{grid-area:list-header}devsite-recommended-content .devsite-recommended-content-list{-webkit-animation:fadeIn .5s;animation:fadeIn .5s;display:grid;gap:var(--devsite-item-gap,24px);grid:auto-flow/repeat(var(--devsite-columns,4),1fr);grid-area:content}devsite-recommended-content devsite-carousel .devsite-recommended-content-list{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex}devsite-recommended-content .devsite-recommended-content-item{background:var(--devsite-card-background);border:var(--devsite-card-border);border-radius:var(--devsite-card-border-radius);box-shadow:var(--devsite-card-box-shadow);-moz-box-sizing:border-box;box-sizing:border-box;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-moz-box-orient:vertical;-moz-box-direction:normal;-ms-flex-direction:column;flex-direction:column;gap:8px;min-width:0;padding:16px}devsite-recommended-content .devsite-recommended-content-item:nth-child(n+5){display:var(--devsite-recommended-content-item-show-all-display)}devsite-recommended-content .devsite-recommended-content-item-doc-type{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;font-size:12px;font-weight:500;line-height:16px;margin-bottom:0;text-transform:uppercase}devsite-recommended-content .devsite-recommended-content-item-doc-type:before{font:normal normal normal 24px/1 Material Icons;-webkit-font-feature-settings:"liga";-moz-font-feature-settings:"liga";font-feature-settings:"liga";-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;text-transform:none;word-wrap:normal;color:#5f6368;display:inline;font-size:16px;margin-right:4px}devsite-recommended-content .devsite-recommended-content-item-doc-type-article:before,devsite-recommended-content .devsite-recommended-content-item-doc-type-blog:before,devsite-recommended-content .devsite-recommended-content-item-doc-type-case_study:before,devsite-recommended-content .devsite-recommended-content-item-doc-type-concept:before,devsite-recommended-content .devsite-recommended-content-item-doc-type-course:before,devsite-recommended-content .devsite-recommended-content-item-doc-type-guide:before,devsite-recommended-content .devsite-recommended-content-item-doc-type-marketing:before,devsite-recommended-content .devsite-recommended-content-item-doc-type-pathway:before,devsite-recommended-content .devsite-recommended-content-item-doc-type-quickstart:before,devsite-recommended-content .devsite-recommended-content-item-doc-type-release_notes:before,devsite-recommended-content .devsite-recommended-content-item-doc-type-support:before,devsite-recommended-content .devsite-recommended-content-item-doc-type-topic:before,devsite-recommended-content .devsite-recommended-content-item-doc-type-troubleshooting:before,devsite-recommended-content .devsite-recommended-content-item-doc-type-tutorial:before{content:"article"}devsite-recommended-content .devsite-recommended-content-item-doc-type-best_practices:before{content:"check_circle"}devsite-recommended-content .devsite-recommended-content-item-doc-type-api_reference:before,devsite-recommended-content .devsite-recommended-content-item-doc-type-reference:before,devsite-recommended-content .devsite-recommended-content-item-doc-type-sample:before{content:"code"}devsite-recommended-content .devsite-recommended-content-item-doc-type-playlist:before{content:"format_list_numbered"}devsite-recommended-content .devsite-recommended-content-item-doc-type-pricing:before{content:"monetization_on"}devsite-recommended-content .devsite-recommended-content-item-doc-type-podcast:before{content:"podcasts"}devsite-recommended-content .devsite-recommended-content-item-doc-type-quiz:before{content:"quiz"}devsite-recommended-content .devsite-recommended-content-item-doc-type-codelab:before{content:"science"}devsite-recommended-content .devsite-recommended-content-item-doc-type-media:before,devsite-recommended-content .devsite-recommended-content-item-doc-type-video:before{content:"smart_display"}devsite-recommended-content .devsite-recommended-content-item-doc-type-content_navigator:before,devsite-recommended-content .devsite-recommended-content-item-doc-type-landing:before,devsite-recommended-content .devsite-recommended-content-item-doc-type-landing_page:before,devsite-recommended-content .devsite-recommended-content-item-doc-type-product:before{content:"web"}devsite-recommended-content .devsite-recommended-content-item-heading{-webkit-box-orient:vertical;color:var(--devsite-link-color);display:-webkit-box;-webkit-line-clamp:2;line-height:28px;min-height:56px;-webkit-box-ordinal-group:2;-webkit-order:1;-moz-box-ordinal-group:2;-ms-flex-order:1;order:1;overflow:hidden}devsite-recommended-content[truncate] .devsite-recommended-content-item-heading{display:initial;max-width:100%;text-overflow:ellipsis;white-space:nowrap}devsite-recommended-content .devsite-recommended-content-item-description,devsite-recommended-content .devsite-recommended-content-item-updated{margin:0}devsite-recommended-content .devsite-recommended-content-item-description{-webkit-box-orient:vertical;display:-webkit-box;-webkit-line-clamp:3;line-height:24px;min-height:72px;-webkit-box-ordinal-group:4;-webkit-order:3;-moz-box-ordinal-group:4;-ms-flex-order:3;order:3;overflow:hidden;word-break:break-word}devsite-recommended-content .devsite-recommended-content-item-updated{-webkit-box-ordinal-group:3;-webkit-order:2;-moz-box-ordinal-group:3;-ms-flex-order:2;order:2}devsite-recommended-content .devsite-recommended-content-item-products{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-ordinal-group:5;-webkit-order:4;-moz-box-ordinal-group:5;-ms-flex-order:4;order:4}devsite-recommended-content .devsite-recommended-content-item-icon{display:grid;margin-block:auto 0;-webkit-margin-end:8px;-moz-margin-end:8px;margin-inline-end:8px;place-content:center;width:32px}devsite-recommended-content .devsite-recommended-content-item-icon img,devsite-recommended-content .devsite-recommended-content-item-icon picture{height:32px}devsite-recommended-content .devsite-recommended-content-item-icon .material-icons{color:var(--devsite-foreground-color,var(--devsite-secondary-text-color));font-size:32px}devsite-recommended-content .devsite-recommended-content-item-product-tag{background:var(--devsite-background-3);color:var(--devsite-display-tag-color,var(--devsite-secondary-text-color));display:inline-block;font:var(--devsite-display-tag-font,500 14px/20px var(--devsite-primary-font-family));-webkit-margin-end:8px;-moz-margin-end:8px;margin-inline-end:8px;padding:2px 4px}devsite-recommended-content devsite-rich-tooltip{--devsite-rich-tooltip-button-size:24px;--devsite-rich-tooltip-button-hover-background:0;--devsite-rich-tooltip-padding-block:8px;--devsite-rich-tooltip-padding-inline:16px;--devsite-rich-tooltip-width:auto;--devsite-rich-tooltip-min-width:200px;height:var(--devsite-rich-tooltip-button-size);width:var(--devsite-rich-tooltip-button-size)}devsite-recommended-content devsite-rich-tooltip:defined{background:var(--devsite-background-3);display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex}devsite-recommended-content devsite-rich-tooltip button[label-type=icon]:is(:hover,:focus){background:0}devsite-recommended-content .devsite-recommended-content-cta{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;letter-spacing:.25px;--devsite-button-border:0;--devsite-button-border-hover:0;--devsite-button-disabled-border:0;--devsite-background-button-background:transparent;--devsite-button-border-active:0;--devsite-button-box-shadow-active:0}devsite-recommended-content .devsite-recommended-content-cta .material-icons{top:auto;font-size:20px}devsite-recommended-content .devsite-recommended-content-cta devsite-spinner{margin-right:7px}devsite-recommended-content .ctable{display:none}devsite-recommended-content .devsite-table-wrapper{display:none}devsite-reference-results{background:var(--devsite-background-1);display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;box-shadow:0 1px 2px 0 var(--devsite-elevation-key-shadow-color),0 1px 3px 1px var(--devsite-elevation-ambient-shadow-color);max-height:305px;padding:20px 10px 20px 28px;margin:16px 0}devsite-reference-results:empty{display:none}devsite-reference-results .devsite-reference-results{height:auto;width:100%}devsite-reference-results .devsite-reference-results h3{margin-top:0}devsite-reference-results .devsite-reference-results-list{-webkit-column-count:2;-moz-column-count:2;column-count:2;padding-left:0}devsite-reference-results .devsite-reference-results-list-item{-webkit-column-break-inside:avoid;break-inside:avoid;margin:0 0 0 -8px;outline:0;overflow:hidden;padding:10px 8px;text-decoration:none;text-overflow:ellipsis;-webkit-transition:background .2s;transition:background .2s;white-space:nowrap}devsite-reference-results .devsite-reference-results-list-item:focus,devsite-reference-results .devsite-reference-results-list-item:hover{background:var(--devsite-background-3)}devsite-reference-results .devsite-reference-results-list-link{color:var(--devsite-primary-text-color);font:13px/20px var(--devsite-primary-font-family)}@media screen and (max-width:600px){devsite-reference-results{overflow-y:scroll}devsite-reference-results .devsite-reference-results-list{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-moz-box-orient:vertical;-moz-box-direction:normal;-ms-flex-direction:column;flex-direction:column;padding-bottom:20px}devsite-reference-results .devsite-reference-results{width:auto}}devsite-related-entities{--devsite-chips-gap:8px;--devsite-button-background-active:var(--devsite-background-2);--devsite-button-background-hover:rgba(var(--devsite-primary-text-color),0.1);--devsite-button-border-hover:var(--devsite-button-border,0);--devsite-button-color:var(--devsite-primary-text-color)}devsite-rich-tooltip{display:none;position:relative;z-index:2}devsite-rich-tooltip:defined{background:0;display:revert}devsite-rich-tooltip>[slot]{margin:0!important;padding:0!important}devsite-rich-tooltip ul{list-style:none}devsite-rich-tooltip li{margin-block:2px}devsite-search{border-radius:var(--devsite-search-border-radius);display:inline-block;-webkit-box-flex:0;-webkit-flex:0 0 auto;-moz-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;height:var(--devsite-search-height);margin:6px 0 6px 24px;overflow:hidden;position:relative;text-align:left;-webkit-transform:translateZ(0);transform:translateZ(0);vertical-align:top;width:200px;will-change:transition;z-index:10}[dir=rtl] devsite-search{margin:6px 24px 6px 0;text-align:right}body[pending] devsite-search{visibility:hidden!important}devsite-search .devsite-search-image{color:var(--devsite-search-image-color,var(--devsite-secondary-text-color));position:absolute;top:var(--devsite-search-image-top);-webkit-transition:color .2s;transition:color .2s}[dir=ltr] devsite-search .devsite-search-image{left:var(--devsite-search-image-x)}[dir=rtl] devsite-search .devsite-search-image{right:var(--devsite-search-image-x)}devsite-search .devsite-search-image:before{content:"search"}devsite-search .devsite-search-container{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex}devsite-search .devsite-suggest-results-container{border-top:var(--devsite-primary-border)}devsite-search input.devsite-search-field{background:none;border:var(--devsite-search-field-border);border-radius:var(--devsite-search-field-border-radius);color:var(--devsite-secondary-text-color);height:var(--devsite-search-field-height);outline:0;padding:8px;-webkit-padding-start:var(--devsite-search-field-padding-x-start);-moz-padding-start:var(--devsite-search-field-padding-x-start);padding-inline-start:var(--devsite-search-field-padding-x-start);-webkit-transition:background .2s,color .2s;transition:background .2s,color .2s;width:100%}devsite-search input.devsite-search-field::-webkit-input-placeholder{color:var(--devsite-search-field-placeholder-color,var(--devsite-secondary-text-color));font:var(--devsite-search-field-placeholder-font);-webkit-transition:color .2s;transition:color .2s}devsite-search input.devsite-search-field::-moz-placeholder{color:var(--devsite-search-field-placeholder-color,var(--devsite-secondary-text-color));font:var(--devsite-search-field-placeholder-font);-moz-transition:color .2s;transition:color .2s}devsite-search input.devsite-search-field:-ms-input-placeholder{color:var(--devsite-search-field-placeholder-color,var(--devsite-secondary-text-color));font:var(--devsite-search-field-placeholder-font);-ms-transition:color .2s;transition:color .2s}devsite-search input.devsite-search-field::-ms-input-placeholder{color:var(--devsite-search-field-placeholder-color,var(--devsite-secondary-text-color));font:var(--devsite-search-field-placeholder-font);-ms-transition:color .2s;transition:color .2s}devsite-search input.devsite-search-field::placeholder{color:var(--devsite-search-field-placeholder-color,var(--devsite-secondary-text-color));font:var(--devsite-search-field-placeholder-font);-webkit-transition:color .2s;transition:color .2s}devsite-search input.devsite-search-field:focus{border:var(--devsite-search-field-border);padding-bottom:8px}devsite-search .devsite-searchbox{width:100%}devsite-search .devsite-searchbox:before{background:var(--devsite-background-1);content:"";display:var(--devsite-searchbox-before-display,block);height:500px;opacity:0;pointer-events:none;position:absolute;top:-458px;-webkit-transition:opacity 1ms .2s;transition:opacity 1ms .2s;width:calc(100% + 12px);will-change:opacity;z-index:-1}[dir=ltr] devsite-search .devsite-searchbox:before{left:-6px}[dir=rtl] devsite-search .devsite-searchbox:before{right:-6px}devsite-search[search-active]{overflow:visible}devsite-search[search-active] .devsite-searchbox:before{opacity:1}devsite-search[search-active] .devsite-searchbox:hover{background:var(--devsite-searchbox-background-active,var(--devsite-background-3))}.devsite-header-billboard-search devsite-search[search-active] .devsite-search-form,body[template="404"] devsite-search[search-active] .devsite-search-form,devsite-header[search-expanded] .devsite-search-form{border-radius:var(--devsite-search-border-radius,0);box-shadow:var(--devsite-search-active-box-shadow,none);overflow:var(--devsite-search-active-overflow,visible)}.devsite-header-billboard-search devsite-search[search-active] .devsite-popout,body[template="404"] devsite-search[search-active] .devsite-popout,devsite-header[search-expanded] devsite-search .devsite-popout{display:var(--devsite-popout-active-display,block)}.devsite-header-billboard-search devsite-search[search-active] .devsite-search-field,.devsite-header-billboard-search devsite-search[search-active] .devsite-search-field:hover,body[template="404"] devsite-search[search-active] .devsite-search-field,body[template="404"] devsite-search[search-active] .devsite-search-field:hover,devsite-header[search-expanded] devsite-search[search-active] .devsite-search-field,devsite-header[search-expanded] devsite-search[search-active] .devsite-search-field:hover{background:var(--devsite-search-form-background-active);color:var(--devsite-search-form-text-active,var(--devsite-primary-text-color))}devsite-search[search-active] .devsite-search-field{color:var(--devsite-primary-text-color)}devsite-search[search-active] .devsite-search-field::-webkit-input-placeholder{color:var(--devsite-secondary-text-color)}devsite-search[search-active] .devsite-search-field::-moz-placeholder{color:var(--devsite-secondary-text-color)}devsite-search[search-active] .devsite-search-field:-ms-input-placeholder{color:var(--devsite-secondary-text-color)}devsite-search[search-active] .devsite-search-field::-ms-input-placeholder{color:var(--devsite-secondary-text-color)}devsite-search[search-active] .devsite-search-field::placeholder{color:var(--devsite-secondary-text-color)}devsite-search[search-active] .devsite-search-image{color:var(--devsite-search-active-image-color,var(--devsite-secondary-text-color))}devsite-search .devsite-popout,devsite-search[search-active] .devsite-popout{display:var(--devsite-popout-display,block)}devsite-search .devsite-popout{margin-top:var(--devsite-popout-margin-top,6px);position:var(--devsite-popout-position,absolute);-webkit-transform:var(--devsite-popout-transform,translateY(-100vh));transform:var(--devsite-popout-transform,translateY(-100vh));-webkit-transition:var(--devsite-popout-transition,transform .2s);transition:var(--devsite-popout-transition,transform .2s);visibility:hidden;width:100%;z-index:var(--devsite-popout-z-index,-2)}devsite-search[search-active] .devsite-popout{-webkit-transform:translateY(0);transform:translateY(0);-webkit-transition-delay:.2s;transition-delay:.2s;visibility:visible;will-change:transform}devsite-search .devsite-popout-result{background:var(--devsite-background-1);box-shadow:var(--devsite-popout-box-shadow,0 1px 2px 0 var(--devsite-elevation-key-shadow-color),0 2px 6px 2px var(--devsite-elevation-ambient-shadow-color));max-height:calc(100vh - 56px);overflow-y:auto}devsite-search .devsite-popout-result:empty,devsite-search[search-active][no-suggest] .devsite-popout{display:none}devsite-search .devsite-suggest-wrapper{padding:16px 0 0;font-size:14px}devsite-search .devsite-result-item,devsite-search .devsite-result-label{font:13px/20px var(--devsite-primary-font-family);margin:0}devsite-search .devsite-result-label{padding-left:40px}[dir=rtl] devsite-search .devsite-result-label{padding-left:0;padding-right:40px}devsite-search .devsite-result-item a{color:var(--devsite-primary-text-color);display:block;outline:0;padding:8px;text-decoration:none;-webkit-transition:background .2s;transition:background .2s;will-change:transition}[dir=ltr] devsite-search .devsite-result-item a{padding-left:40px}[dir=rtl] devsite-search .devsite-result-item a{padding-right:40px}devsite-search .devsite-result-item a:focus,devsite-search .devsite-result-item a:hover,devsite-search .devsite-result-item.highlight a{background:var(--devsite-background-3)}devsite-search .devsite-result-item b{font-weight:500}devsite-search .devsite-suggest-footer{border-top:var(--devsite-primary-border);margin:8px 0 0;padding:7px 0 8px 40px}[dir=rtl] devsite-search .devsite-suggest-footer{padding:7px 40px 8px 0}devsite-search .devsite-suggest-footer>.button{display:inline-block;margin:6px 0;max-width:calc(100% - 16px)}[dir=ltr] devsite-search .devsite-suggest-footer>.button{margin-right:16px}[dir=rtl] devsite-search .devsite-suggest-footer>.button{margin-left:16px}devsite-search .devsite-suggest-footer>.button-white{max-width:100%}[dir=ltr] devsite-search .devsite-suggest-footer>.button-white{margin-left:-8px}[dir=rtl] devsite-search .devsite-suggest-footer>.button-white{margin-right:-8px}devsite-search .devsite-suggest-header{font:500 11px/16px var(--devsite-primary-font-family);letter-spacing:.8px;margin:12px 0;padding-left:40px;text-transform:uppercase}[dir=rtl] devsite-search .devsite-suggest-header{padding-left:0;padding-right:40px}devsite-search hr+.devsite-suggest-sub-section>.devsite-suggest-header{margin-top:24px}devsite-search .devsite-suggest-header .devsite-suggest-project:before{content:"|";margin:0 8px}devsite-search hr{margin:8px 0}devsite-search .devsite-suggestion-fragment+.devsite-suggestion-fragment:before{content:"|";margin:0 8px}devsite-search .devsite-search-disabled{padding-bottom:16px}devsite-search[compact]{width:auto}devsite-search[compact] .devsite-search-field,devsite-search[compact] .devsite-searchbox{background-color:transparent}devsite-search[compact] input.devsite-search-field{width:0}devsite-search[compact] .devsite-search-image{left:calc(50% - 12px);pointer-events:none}[dir=ltr] devsite-search[compact][search-active] .devsite-search-image{left:8px;right:auto}[dir=rtl] devsite-search[compact][search-active] .devsite-search-image{right:8px;left:auto}devsite-search[compact][search-active] input.devsite-search-field{width:100%}@media screen and (max-width:840px){devsite-search input.devsite-search-field{padding-left:40px}[dir=rtl] devsite-search input.devsite-search-field{padding-left:0;padding-right:40px}.devsite-search-background,.devsite-search-background:after,[search-active] .devsite-search-background:after,devsite-search .devsite-search-field,devsite-search .devsite-search-field:hover{-webkit-transition:none;transition:none}devsite-search .devsite-search-image{left:8px}[dir=rtl] devsite-search .devsite-search-image{left:auto;right:8px}devsite-header devsite-search{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;margin-left:8px;overflow:visible}[dir=rtl] devsite-header devsite-search{margin-left:0;margin-right:8px}devsite-header devsite-search .devsite-search-form{-webkit-box-flex:1;-webkit-flex-grow:1;-moz-box-flex:1;-ms-flex-positive:1;flex-grow:1}devsite-header .devsite-top-logo-row devsite-search:not([search-active]) input.devsite-search-field{padding:0}}devsite-select{display:var(--devsite-select-display);margin:var(--devsite-select-margin);position:relative}devsite-select+devsite-select,devsite-select~.button,devsite-select~button{-webkit-margin-before:var(--devsite-select-sibling-gap-y);margin-block-start:var(--devsite-select-sibling-gap-y);-webkit-margin-start:var(--devsite-select-sibling-gap-x);-moz-margin-start:var(--devsite-select-sibling-gap-x);margin-inline-start:var(--devsite-select-sibling-gap-x)}devsite-select select{display:none!important;pointer-events:none!important;position:absolute;z-index:-1}devsite-select .devsite-select{position:relative}devsite-select .devsite-select-toggle{-moz-appearance:none;-webkit-appearance:none;background-color:var(--devsite-select-background-color);border:var(--devsite-select-border,var(--devsite-secondary-border));border-radius:var(--devsite-select-border-radius);box-shadow:none;color:var(--devsite-select-color,var(--devsite-primary-text-color));cursor:pointer;display:inline-block;font:var(--devsite-select-font,500 14px/36px var(--devsite-primary-font-family));height:var(--devsite-select-height,36px);line-height:var(--devsite-select-line-height,34px);max-width:var(--devsite-select-max-width,340px);min-width:72px;outline:0;overflow:hidden;padding:var(--devsite-select-padding,0 27px 0 7px);text-align:left;text-indent:.01px;text-overflow:ellipsis;-webkit-transition:background-color .2s;transition:background-color .2s;vertical-align:middle;white-space:nowrap;position:relative}devsite-select .devsite-select-toggle:focus,devsite-select .devsite-select-toggle:hover{background-color:var(--devsite-select-background-color-hover,var(--devsite-background-3));border:var(--devsite-select-border-hover,var(--devsite-select-border,var(--devsite-secondary-border)));color:var(--devsite-select-color-hover)}devsite-select .devsite-select-toggle:active{background-color:var(--devsite-select-background-color-active,var(--devsite-background-4));color:var(--devsite-select-color-active)}devsite-select .devsite-select-toggle:disabled{background-color:var(--devsite-background-3);border-color:transparent;color:var(--devsite-tertiary-text-color);cursor:default}devsite-select .devsite-select-toggle-icon{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;height:100%;pointer-events:none;position:absolute;top:0}[dir=ltr] devsite-select .devsite-select-toggle-icon{right:var(--devsite-select-toggle-icon-x,8px)}[dir=rtl] devsite-select .devsite-select-toggle-icon{left:var(--devsite-select-toggle-icon-x,8px)}devsite-select .devsite-select-toggle-icon:before{font-size:18px}devsite-select .devsite-select-toggle-count{-webkit-margin-start:var(--devsite-select-count-margin-inline-start,6px);-moz-margin-start:var(--devsite-select-count-margin-inline-start,6px);margin-inline-start:var(--devsite-select-count-margin-inline-start,6px)}devsite-select .devsite-select-toggle-count[parens]:not(:empty):before{content:"("}devsite-select .devsite-select-toggle-count[parens]:not(:empty):after{content:")"}devsite-select .devsite-select-list{background:var(--devsite-background-1);border:var(--devsite-list-border,var(--devsite-secondary-border));border-radius:var(--devsite-list-border-radius,2px);box-shadow:0 1px 2px 0 var(--devsite-elevation-key-shadow-color),0 2px 6px 2px var(--devsite-elevation-ambient-shadow-color);display:none;font:var(--devsite-list-font,400 14px/20px var(--devsite-primary-font-family));max-height:304px;min-width:var(--devsite-list-min-width);opacity:0;outline:0;overflow-y:auto;padding:8px 0;pointer-events:none;position:absolute;-webkit-transition:opacity .2s,visibility .2s;transition:opacity .2s,visibility .2s;z-index:1005}devsite-dialog devsite-select .devsite-select-list{z-index:1015}devsite-select[menu--open] .devsite-select-list{display:block;pointer-events:auto}devsite-select[menu--show] .devsite-select-list{opacity:1}devsite-select[menu-position=above] .devsite-select-list{bottom:var(--devsite-list-position-y,36px)}devsite-select[menu-position=below] .devsite-select-list{top:var(--devsite-list-position-y,36px)}devsite-select .devsite-select-item{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;margin:0;min-height:48px;min-width:100%;padding:8px 16px;white-space:nowrap}devsite-select .devsite-select-item.devsite-focused,devsite-select .devsite-select-item:focus,devsite-select .devsite-select-item:hover{background-color:var(--devsite-background-3);cursor:pointer}devsite-select .devsite-select-item[data-selected]{background-color:var(--devsite-item-background-selected,var(--devsite-background-3));color:var(--devsite-item-color-selected);font-weight:var(--devsite-item-font-weight-selected,500)}@media screen and (-ms-high-contrast:active),screen and (prefers-contrast:high){devsite-select .devsite-select-item[data-selected]{font-weight:700;text-decoration:underline}}devsite-select.devsite-select--multiple .devsite-select-item{padding-left:48px;position:relative}devsite-select.devsite-select--multiple .devsite-select-item:before{font:normal normal normal 24px/1 Material Icons;-webkit-font-feature-settings:"liga";-moz-font-feature-settings:"liga";font-feature-settings:"liga";-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;text-transform:none;word-wrap:normal;color:#80868b;content:"check_box_outline_blank";display:block;font-size:24px;left:16px;position:absolute;top:50%;-webkit-transform:translateY(-50%);transform:translateY(-50%)}devsite-select.devsite-select--multiple .devsite-select-item[data-selected]:before{color:#1976d2;content:"check_box"}devsite-selector{background:var(--devsite-selector-background,var(--devsite-background-1));border:var(--devsite-border,var(--devsite-secondary-border));border-radius:var(--devsite-border-radius,0);display:block;margin:var(--devsite-selector-margin,16px 0)}devsite-selector devsite-tabs{display:none}devsite-selector devsite-tabs[connected]{border-bottom:var(--devsite-border,var(--devsite-secondary-border));display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex}devsite-selector devsite-tabs tab a{cursor:pointer;display:inline-block;-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;line-height:var(--devsite-selector-tab-line-height,48px);margin:0;max-width:200px;overflow:hidden;text-align:center;text-overflow:ellipsis;-webkit-transition:color .2s;transition:color .2s;white-space:nowrap}devsite-selector devsite-tabs tab a,devsite-selector devsite-tabs tab a:link,devsite-selector devsite-tabs tab a:visited{color:var(--devsite-secondary-text-color)}devsite-selector devsite-tabs tab a:focus,devsite-selector devsite-tabs tab a:hover{color:var(--devsite-link-hover,var(--devsite-link-color))}devsite-selector devsite-tabs tab[active] a:link,devsite-selector devsite-tabs tab[active] a:visited{color:var(--devsite-link-color)}@media screen and (-ms-high-contrast:active),screen and (prefers-contrast:high){devsite-selector devsite-tabs tab[active] a:link,devsite-selector devsite-tabs tab[active] a:visited{color:inherit}}devsite-selector devsite-tabs>div>tab[tab] a:focus:after,devsite-selector devsite-tabs>div>tab[tab] a:hover:after{border-color:var(--devsite-tab-marker-color,transparent)}devsite-selector devsite-tabs>div>tab[active] a:after,devsite-selector devsite-tabs>div>tab[active] a:focus:after,devsite-selector devsite-tabs>div>tab[active] a:hover:after{border-color:var(--devsite-link-color)}devsite-selector devsite-tabs tab[two-line] a{line-height:20px;padding-top:4px;white-space:normal}devsite-selector tab[two-line] [tab-label]:after{content:attr(tab-label);display:block;font-size:12px}body devsite-selector devsite-tabs tab[overflow-tab] .devsite-tabs-overflow-menu tab a{height:auto;min-height:48px;width:100%}devsite-selector devsite-tabs[overflow-menu--open] tab[overflow-tab]{background:var(--devsite-overflow-tab-background,0);border-radius:var(--devsite-overflow-tab-border-radius,0)}body devsite-selector devsite-tabs tab[overflow-tab] .devsite-tabs-overflow-menu tab a:focus,body devsite-selector devsite-tabs tab[overflow-tab] .devsite-tabs-overflow-menu tab a:hover{background:var(--devsite-overflow-link-background-hover,var(--devsite-background-3))}devsite-selector>section{display:none;outline:0}devsite-selector>section[active]{display:block;padding:0 23px}devsite-selector>section .devsite-table-wrapper:first-child tbody tr:first-child,devsite-selector>section .devsite-table-wrapper:first-child thead tr{border-top:0}devsite-selector>section>.devsite-table-wrapper,devsite-selector>section>.github-docwidget-gitinclude-code>devsite-code,devsite-selector>section>.github-docwidget-include,devsite-selector>section>aside.beta,devsite-selector>section>aside.caution,devsite-selector>section>aside.deprecated,devsite-selector>section>aside.dogfood,devsite-selector>section>aside.experimental,devsite-selector>section>aside.key-objective,devsite-selector>section>aside.key-point,devsite-selector>section>aside.key-term,devsite-selector>section>aside.note,devsite-selector>section>aside.preview,devsite-selector>section>aside.success,devsite-selector>section>aside.warning,devsite-selector>section>devsite-code,devsite-selector>section>table{margin:0 -23px}devsite-selector>section>:first-child:not(:empty):not(aside):not(devsite-code):not(table):not(.devsite-table-wrapper):not([class^=github-]){margin-top:var(--devsite-selector-content-margin-y,15px)}devsite-selector>section>:last-child:not(aside):not(devsite-code):not(table):not(.devsite-table-wrapper):not([class^=github-]){margin-bottom:var(--devsite-selector-content-margin-y,15px)}devsite-selector .devsite-table-wrapper:last-child,devsite-selector>section>.github-docwidget-gitinclude-code>devsite-code:last-child>pre,devsite-selector>section>aside:last-child,devsite-selector>section>devsite-code:last-child>pre{border-radius:var(--devsite-content-border-radius,0)}devsite-selector .devsite-table-wrapper+.devsite-table-wrapper{margin-top:16px}devsite-selector>section table devsite-code{margin:16px 0}devsite-selector>section>devsite-code pre{padding-left:23px}.devsite-article devsite-selector .material-icons{font-size:var(--devsite-selector-icon-font-size,18px);vertical-align:text-bottom}devsite-selector[ready]{pointer-events:auto;visibility:visible}devsite-shell-activate-button{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;height:100%;-webkit-justify-content:space-around;-ms-flex-pack:distribute;justify-content:space-around}devsite-shell-activate-button[tooltip--shown]{z-index:104}@media screen and (max-width:840px){devsite-shell-activate-button{display:none}}devsite-shell-activate-button ul li{text-align:left}devsite-shell-activate-button button{border:none;color:#5f6368;height:auto;margin:0 0 0 11px;min-width:0;padding:9px 13px;width:auto}devsite-shell-activate-button button.cloudshell-dogfood{padding-right:0}devsite-shell-activate-button button.cloudshell-dogfood:before{background:var(--devsite-background-1);border-radius:100%;border:var(--devsite-header-border);box-shadow:1px 1px 1px var(--devsite-background-0);color:#1976d2;content:"pets";float:right;font-family:Material Icons;font-size:14px;font-weight:400;height:20px;line-height:18px;overflow:hidden;position:relative;right:7px;text-align:center;text-rendering:optimizelegibility;top:7px;width:20px}devsite-shell-activate-button button[disabled].cloudshell-dogfood:before{color:#9aa0a6}devsite-shell-activate-button button:active{background:var(--devsite-background-4);border:none}devsite-shell-activate-button button:focus{background:none;border:none;color:#5f6368}devsite-shell-activate-button button:hover{background:var(--devsite-background-4);border:none;color:#5f6368}devsite-shell-activate-button cloud-mdc-rich-tooltip::part(richTooltip){-webkit-transform:translateX(-36px);transform:translateX(-36px)}devsite-shell-activate-button button[disabled]{border:none}devsite-shell-activate-button button svg{display:block;margin:auto;pointer-events:none}devsite-shell-activate-button .tooltip-title{color:#3c4043;font-size:16px;font-weight:500;margin:2px 0 8px;padding:0}devsite-shell-activate-button [slot=contents].tooltip-contents{color:#3c4043;font-family:var(--devsite-wordmark-font-family);font-size:14px;font-weight:400}devsite-shell-activate-button p.tooltip-contents{text-align:left;margin:0}devsite-shell-activate-button ul.tooltip-contents{margin:8px 0 0}devsite-shell-activate-button ul.tooltip-contents li{margin:0}devsite-shell-activate-button .tooltip-buttons{float:left;margin:24px 0 2px}body[free-trial] devsite-shell-activate-button[free-trial-hide]{display:none}body[free-trial] devsite-shell-activate-button[force-visibility]{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex}devsite-sitemask{background:rgba(0,0,0,.4);bottom:-200px;cursor:pointer;left:-200px;opacity:0;pointer-events:none;position:fixed;right:-200px;top:-200px;-webkit-transition:opacity .2s cubic-bezier(.4,0,.2,1),visibility .2s linear;transition:opacity .2s cubic-bezier(.4,0,.2,1),visibility .2s linear;visibility:hidden;z-index:1012;-webkit-tap-highlight-color:transparent}devsite-sitemask[visible]{opacity:1;pointer-events:auto;-webkit-transition:opacity .2s ease;transition:opacity .2s ease;visibility:visible}devsite-snackbar{bottom:0;left:0;margin-right:24px;min-width:288px;position:fixed;right:0;z-index:1018}devsite-snackbar .devsite-snackbar-snack{bottom:0;-moz-box-sizing:border-box;box-sizing:border-box;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-moz-box-orient:vertical;-moz-box-direction:normal;-ms-flex-direction:column;flex-direction:column;max-width:var(--devsite-snack-max-width,none);min-width:var(--devsite-snack-min-width,auto);padding:0 0 24px 24px;position:absolute;-webkit-transform:translateY(100px);transform:translateY(100px);-webkit-transition:-webkit-transform .2s cubic-bezier(.4,0,1,1);transition:-webkit-transform .2s cubic-bezier(.4,0,1,1);transition:transform .2s cubic-bezier(.4,0,1,1);transition:transform .2s cubic-bezier(.4,0,1,1),-webkit-transform .2s cubic-bezier(.4,0,1,1);width:var(--devsite-snack-width,auto)}devsite-snackbar [show].devsite-snackbar-snack{-webkit-transform:translateY(0);transform:translateY(0)}devsite-snackbar .devsite-snackbar-inner{-webkit-align-content:center;-ms-flex-line-pack:center;align-content:center;-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;background:var(--devsite-snackbar-inner-background,#3c4043);border-radius:var(--devsite-snackbar-inner-border-radius,2px);box-shadow:0 1px 3px 0 var(--devsite-elevation-key-shadow-color),0 4px 8px 3px var(--devsite-elevation-ambient-shadow-color);color:var(--devsite-snackbar-inner-color,#fff);display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-flow:row var(--devsite-snackbar-inner-flex-wrap,nowrap);-moz-box-orient:horizontal;-moz-box-direction:normal;-ms-flex-flow:row var(--devsite-snackbar-inner-flex-wrap,nowrap);flex-flow:row var(--devsite-snackbar-inner-flex-wrap,nowrap);font-size:14px;min-height:48px;padding:0}devsite-snackbar .devsite-snackbar-message{-webkit-box-flex:var(--devsite-snackbar-message-flex,1 1);-webkit-flex:var(--devsite-snackbar-message-flex,1 1);-moz-box-flex:var(--devsite-snackbar-message-flex,1 1);-ms-flex:var(--devsite-snackbar-message-flex,1 1);flex:var(--devsite-snackbar-message-flex,1 1);font:var(--devsite-snackbar-message-font,inherit);letter-spacing:.2px;line-height:20px;font-weight:400;overflow:hidden;padding:var(--devsite-snackbar-message-padding,24px);text-overflow:ellipsis;word-break:break-word}devsite-snackbar .devsite-snackbar-message a{color:var(--devsite-snackbar-link-color,#669df6)}devsite-snackbar .devsite-snackbar-action,devsite-snackbar .devsite-snackbar-link{-webkit-align-self:center;-ms-flex-item-align:center;align-self:center;color:var(--devsite-snackbar-link-color,#eeff41);cursor:pointer;display:inline-block;-webkit-box-flex:0;-webkit-flex:0 0;-moz-box-flex:0;-ms-flex:0 0;flex:0 0;float:right;font:var(--devsite-snackbar-action-font,inherit);height:auto;letter-spacing:.25px;line-height:20px;margin-left:0;margin-right:var(--devsite-snackbar-action-margin-right,0);min-width:-webkit-fit-content;min-width:-moz-fit-content;min-width:fit-content;outline:none;padding:var(--devsite-snackbar-action-padding,14px 24px);position:relative}devsite-snackbar .devsite-snackbar-action,devsite-snackbar .devsite-snackbar-action:active,devsite-snackbar .devsite-snackbar-action:focus,devsite-snackbar .devsite-snackbar-action:hover,devsite-snackbar .devsite-snackbar-link,devsite-snackbar .devsite-snackbar-link:active,devsite-snackbar .devsite-snackbar-link:focus,devsite-snackbar .devsite-snackbar-link:hover{background:0;border:0;box-shadow:none}devsite-snackbar .devsite-snackbar-link:focus{text-decoration:none}devsite-snackbar [type=cookie-notification] .devsite-snackbar-link,devsite-snackbar [type^=notification-] .devsite-snackbar-action{margin-left:var(--devsite-snackbar-action-margin-left,0)}@media screen and (max-width:840px){devsite-snackbar{margin-right:0;max-width:100%}devsite-snackbar [type=cookie-notification] .devsite-snackbar-inner,devsite-snackbar [type^=notification-] .devsite-snackbar-inner{-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}devsite-snackbar [type=cookie-notification] .devsite-snackbar-message,devsite-snackbar [type^=notification-] .devsite-snackbar-message{-webkit-box-flex:0;-webkit-flex:0 0 100%;-moz-box-flex:0;-ms-flex:0 0 100%;flex:0 0 100%;padding:var(--devsite-snackbar-message-padding,24px 24px 0)}devsite-snackbar .devsite-snackbar-inner{border-radius:0}devsite-snackbar .devsite-snackbar-snack{left:0;padding:24px 0 0;right:0}}devsite-spinner.devsite-send-spinner{margin-left:78px}#devsite-support-form-button-wrapper{height:36px}.devsite-support-projects{position:relative}.devsite-support-projects .devsite-support-projects-placeholder{height:36px;position:absolute}devsite-tabs{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-flex:1;-webkit-flex:1;-moz-box-flex:1;-ms-flex:1;flex:1;height:var(--devsite-tabs-height,48px);margin:var(--devsite-tabs-margin);max-width:calc(100% - 208px);position:relative;width:var(--devsite-tabs-width)}devsite-tabs[connected]{max-width:none}devsite-tabs .devsite-tabs-wrapper{bottom:0;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;left:0;overflow:hidden;position:absolute;right:0;top:0}[dir=ltr] devsite-tabs.lower-tabs .devsite-tabs-wrapper{left:var(--devsite-tabs-wrapper-x,0)}[dir=rtl] devsite-tabs.lower-tabs .devsite-tabs-wrapper{right:var(--devsite-tabs-wrapper-x,0)}devsite-tabs[no-overflow] .devsite-tabs-wrapper{overflow:auto}devsite-tabs[dropdown--open] .devsite-tabs-wrapper,devsite-tabs[overflow-menu--open] .devsite-tabs-wrapper{overflow:visible}devsite-tabs tab{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;position:relative}devsite-tabs tab>.devsite-tabs-content,devsite-tabs tab>a{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;font:var(--devsite-link-font,500 14px/20px var(--devsite-primary-font-family));letter-spacing:var(--devsite-link-letter-spacing,normal);margin:0;padding:var(--devsite-link-padding,0 24px);text-transform:var(--devsite-link-text-transform,uppercase);-webkit-transition:color .2s;transition:color .2s;white-space:nowrap}devsite-tabs tab>.devsite-tabs-content,devsite-tabs tab>.devsite-tabs-content:focus,devsite-tabs tab>.devsite-tabs-content:hover,devsite-tabs tab>a,devsite-tabs tab>a:focus,devsite-tabs tab>a:hover{text-decoration:none}devsite-tabs.upper-tabs tab a{font-weight:var(--devsite-upper-tab-font-weight,400);text-transform:none}devsite-tabs.upper-tabs tab>a{color:var(--devsite-upper-tab-inactive,var(--devsite-secondary-text-color))}devsite-tabs.upper-tabs tab[active]>a{font-weight:500}@media screen and (-ms-high-contrast:active),screen and (prefers-contrast:high){devsite-tabs.upper-tabs tab[active]>a{color:inherit}}devsite-tabs.upper-tabs>.devsite-tabs-wrapper>tab[active]>a{color:var(--devsite-upper-tab-active,var(--devsite-primary-text-color))}devsite-tabs.upper-tabs>.devsite-tabs-wrapper>tab[active]>a:hover{color:var(--devsite-upper-tab-active-hover,var(--devsite-upper-tab-active,var(--devsite-primary-text-color)))}devsite-tabs.upper-tabs>.devsite-tabs-wrapper>tab[active]>a:focus{color:var(--devsite-upper-tab-active-focus,var(--devsite-secondary-text-color))}devsite-tabs.upper-tabs>.devsite-tabs-wrapper>tab[active]>a:after{border-color:var(--devsite-upper-tab-marker-color,var(--devsite-secondary-color,var(--devsite-primary-text-color)))}devsite-tabs.upper-tabs>.devsite-tabs-wrapper>tab[active]>a:hover:after{border-color:var(--devsite-upper-tab-marker-color-hover,var(--devsite-upper-tab-marker-color,var(--devsite-secondary-color,var(--devsite-primary-text-color))))}devsite-tabs tab>a:focus:after,devsite-tabs tab>a:hover:after,devsite-tabs tab[active]>a:after{border-radius:var(--devsite-tab-marker-border-radius,0);border-top:var(--devsite-tab-marker-height,2px) solid transparent;bottom:0;content:"";display:block;position:absolute}[dir=ltr] devsite-tabs tab>a:focus:after,[dir=ltr] devsite-tabs tab>a:hover:after,[dir=ltr] devsite-tabs tab[active]>a:after{left:var(--devsite-tab-marker-position-x,0);right:var(--devsite-tab-marker-position-x-end,var(--devsite-tab-marker-position-x,0))}[dir=rtl] devsite-tabs tab>a:focus:after,[dir=rtl] devsite-tabs tab>a:hover:after,[dir=rtl] devsite-tabs tab[active]>a:after{left:var(--devsite-tab-marker-position-x-end,var(--devsite-tab-marker-position-x,0));right:var(--devsite-tab-marker-position-x,0)}devsite-tabs tab[dropdown]>a{padding-block:0;padding-inline:var(--devsite-dropdown-tab-padding-x,24px) 0;position:relative;z-index:2}[dir=ltr] devsite-tabs tab[active][dropdown] a:not(.devsite-tabs-dropdown-toggle):after,[dir=ltr] devsite-tabs tab[dropdown] a:not(.devsite-tabs-dropdown-toggle):focus:after,[dir=ltr] devsite-tabs tab[dropdown] a:not(.devsite-tabs-dropdown-toggle):hover:after{right:var(--devsite-tab-marker-inset-x,0)}[dir=rtl] devsite-tabs tab[active][dropdown] a:not(.devsite-tabs-dropdown-toggle):after,[dir=rtl] devsite-tabs tab[dropdown] a:not(.devsite-tabs-dropdown-toggle):focus:after,[dir=rtl] devsite-tabs tab[dropdown] a:not(.devsite-tabs-dropdown-toggle):hover:after{left:var(--devsite-tab-marker-inset-x,0)}devsite-tabs.upper-tabs tab[dropdown] .devsite-tabs-dropdown a{font-weight:var(--devsite-upper-tab-dropdown-link-font-weight)}devsite-tabs.upper-tabs tab[dropdown] .devsite-tabs-dropdown a,devsite-tabs.upper-tabs tab[dropdown] .devsite-tabs-dropdown a:visited{color:var(--devsite-upper-tab-dropdown-link,var(--devsite-primary-text-color))}devsite-tabs.upper-tabs tab[dropdown] .devsite-tabs-dropdown a:focus,devsite-tabs.upper-tabs tab[dropdown] .devsite-tabs-dropdown a:hover{color:var(--devsite-upper-tab-dropdown-link-hover,var(--devsite-secondary-text-color))}devsite-tabs.upper-tabs tab[dropdown] .devsite-tabs-dropdown a:focus .devsite-nav-item-title,devsite-tabs.upper-tabs tab[dropdown] .devsite-tabs-dropdown a:hover .devsite-nav-item-title{-webkit-text-decoration:var(--devsite-nav-item-title-text-decoration-hover,none);-moz-text-decoration:var(--devsite-nav-item-title-text-decoration-hover,none);text-decoration:var(--devsite-nav-item-title-text-decoration-hover,none)}devsite-tabs.upper-tabs tab[dropdown] .devsite-nav-item-description{color:var(--devsite-upper-tab-dropdown-description,var(--devsite-secondary-text-color));font-weight:var(--devsite-upper-tab-dropdown-description-font-weight);margin:var(--devsite-upper-tab-dropdown-description-margin)}devsite-tabs .devsite-tabs-dropdown-content{border-top:var(--devsite-header-border,0)}devsite-tabs.lower-tabs tab[dropdown] .devsite-tabs-dropdown-content,devsite-tabs.lower-tabs tab[overflow-tab] .devsite-tabs-overflow-menu,devsite-tabs.upper-tabs tab[dropdown] .devsite-tabs-dropdown-content,devsite-tabs.upper-tabs tab[overflow-tab] .devsite-tabs-overflow-menu{border-radius:var(--devsite-upper-tab-dropdown-corner-radius,0)}devsite-tabs.upper-tabs tab[dropdown] .devsite-tabs-dropdown-toggle:before,devsite-tabs.upper-tabs tab[overflow-tab] .devsite-icon-arrow-drop-down:before{color:var(--devsite-upper-tab-dropdown-inactive,var(--devsite-upper-tab-inactive,var(--devsite-secondary-text-color)))}devsite-tabs.upper-tabs tab[active][dropdown] .devsite-tabs-dropdown-toggle:before{color:var(--devsite-upper-tab-dropdown-active,var(--devsite-upper-tab-active,var(--devsite-primary-text-color)))}devsite-tabs tab[dropdown] .devsite-tabs-dropdown-toggle{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;cursor:pointer;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;padding-block:0;padding-inline:0 var(--devsite-dropdown-toggle-padding-x,0)}devsite-tabs tab[dropdown] .devsite-tabs-dropdown-toggle:before,devsite-tabs.upper-tabs .devsite-icon-arrow-drop-down:before{-webkit-transform:rotate(0deg);transform:rotate(0deg);-webkit-transition:background .2s,color .2s,-webkit-transform .2s;transition:background .2s,color .2s,-webkit-transform .2s;transition:background .2s,color .2s,transform .2s;transition:background .2s,color .2s,transform .2s,-webkit-transform .2s}devsite-tabs tab[dropdown] .devsite-tabs-dropdown-toggle:focus:before{background:var(--devsite-background-3);border-radius:50%}devsite-tabs tab[dropdown--open] .devsite-tabs-dropdown-toggle:before,devsite-tabs.upper-tabs[overflow-menu--open] tab:hover .devsite-icon-arrow-drop-down:before{-webkit-transform:rotate(-180deg);transform:rotate(-180deg)}devsite-tabs tab[overflow-tab]{-webkit-box-flex:1;-webkit-flex-grow:1;-moz-box-flex:1;-ms-flex-positive:1;flex-grow:1;position:relative}devsite-tabs tab[overflow-tab][collapsed]{-webkit-box-flex:0;-webkit-flex-grow:0;-moz-box-flex:0;-ms-flex-positive:0;flex-grow:0}devsite-tabs.upper-tabs tab[overflow-tab]:after{content:"";height:48px;position:absolute;z-index:-1}[dir=ltr] devsite-tabs.upper-tabs tab[overflow-tab]:after{left:-6px;right:-100%}[dir=rtl] devsite-tabs.upper-tabs tab[overflow-tab]:after{left:-100%;right:-6px}devsite-tabs tab[overflow-tab] tab>a{padding:var(--devsite-overflow-tab-padding,0 24px)}devsite-tabs tab[overflow-tab] a{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:reverse;-webkit-flex-direction:row-reverse;-moz-box-orient:horizontal;-moz-box-direction:reverse;-ms-flex-direction:row-reverse;flex-direction:row-reverse;position:relative}devsite-tabs tab[overflow-tab] tab .devsite-tabs-dropdown,devsite-tabs tab[overflow-tab] tab .devsite-tabs-dropdown-toggle{display:none}devsite-tabs tab[overflow-tab] .devsite-tabs-overflow-menu{background:var(--devsite-overflow-menu-background,var(--devsite-background-1));border-radius:var(--devsite-overflow-menu-border-radius,2px);box-shadow:0 1px 2px 0 var(--devsite-elevation-key-shadow-color),0 2px 6px 2px var(--devsite-elevation-ambient-shadow-color);display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-moz-box-orient:vertical;-moz-box-direction:normal;-ms-flex-direction:column;flex-direction:column;max-height:320px;overflow-y:auto;padding:16px 0;position:absolute;top:var(--devsite-overflow-menu-top,-16px);z-index:1005}devsite-tabs.upper-tabs tab[overflow-tab] .devsite-tabs-overflow-menu{border-radius:0 0 2px 2px;box-shadow:0 1px 2px 0 var(--devsite-elevation-key-shadow-color),0 2px 6px 2px var(--devsite-elevation-ambient-shadow-color),inset 0 4px 6px -4px var(--devsite-elevation-inset-shadow-color);top:48px;-webkit-transform:translateZ(0);transform:translateZ(0);-webkit-transition:-webkit-transform .2s;transition:-webkit-transform .2s;transition:transform .2s;transition:transform .2s,-webkit-transform .2s;z-index:-1}devsite-tabs.upper-tabs .devsite-tabs-overflow-menu .devsite-tabs-dropdown-toggle{display:none!important}devsite-tabs.upper-tabs tab[overflow-tab] .devsite-tabs-overflow-menu[hidden]{display:block!important;pointer-events:none;-webkit-transform:translate3d(0,-150%,0);transform:translate3d(0,-150%,0)}devsite-tabs tab[overflow-tab] .devsite-tabs-overflow-menu tab a{background:var(--devsite-background-1);color:var(--devsite-secondary-text-color);-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-moz-box-orient:horizontal;-moz-box-direction:normal;-ms-flex-direction:row;flex-direction:row;-webkit-box-flex:1;-webkit-flex-grow:1;-moz-box-flex:1;-ms-flex-positive:1;flex-grow:1;height:48px}devsite-tabs tab[overflow-tab] .devsite-tabs-overflow-menu tab a:focus,devsite-tabs tab[overflow-tab] .devsite-tabs-overflow-menu tab a:hover{background:var(--devsite-background-3);color:var(--devsite-primary-text-color)}devsite-tabs .devsite-tabs-dropdown{display:block;font-size:13px;left:-6px;min-width:calc(100% + 12px);outline:0;overflow:hidden;padding:0 6px 6px;pointer-events:none;position:absolute;top:100%;z-index:-1}[dir=rtl] devsite-tabs .devsite-tabs-dropdown{right:-6px;left:auto}devsite-tabs [dropdown-full] .devsite-tabs-dropdown{left:0;padding:var(--devsite-dropdown-full-padding,0 0 6px);width:var(--devsite-dropdown-full-width,100vw)}[dir=rtl] devsite-tabs [dropdown-full] .devsite-tabs-dropdown{left:auto;right:0}devsite-tabs .devsite-tabs-dropdown-content{background-color:var(--devsite-background-1);display:var(--devsite-dropdown-content-display,flex);box-shadow:0 1px 2px 0 var(--devsite-elevation-key-shadow-color),0 2px 6px 2px var(--devsite-elevation-ambient-shadow-color),inset 0 4px 6px -4px var(--devsite-elevation-inset-shadow-color);grid-template-columns:var(--devsite-dropdown-content-grid-template-columns,none);grid-template-rows:var(--devsite-dropdown-content-grid-template-rows,none);overflow:auto;max-height:600px;max-width:100vw;padding:var(--devsite-dropdown-content-padding,0 12px);pointer-events:none;-webkit-transform:translate3d(0,-150%,0);transform:translate3d(0,-150%,0);-webkit-transition:-webkit-transform 0s;transition:-webkit-transform 0s;transition:transform 0s;transition:transform 0s,-webkit-transform 0s;white-space:nowrap}devsite-tabs .devsite-tabs-dropdown[dropdown-transition] .devsite-tabs-dropdown-content{-webkit-transition:-webkit-transform .5s;transition:-webkit-transform .5s;transition:transform .5s;transition:transform .5s,-webkit-transform .5s}devsite-tabs tab[dropdown--open] .devsite-tabs-dropdown-content{pointer-events:all;-webkit-transform:translateZ(0);transform:translateZ(0)}devsite-tabs .devsite-tabs-dropdown-column{background:var(--devsite-dropdown-column-background,none);border-top:var(--devsite-dropdown-column-border-top,0);-moz-box-sizing:var(--devsite-dropdown-column-box-sizing,inherit);box-sizing:var(--devsite-dropdown-column-box-sizing,inherit);display:var(--devsite-dropdown-column-display);margin:var(--devsite-dropdown-column-margin,0);max-width:var(--devsite-dropdown-column-max-width,none);min-width:var(--devsite-dropdown-column-min-width,180px);padding:var(--devsite-dropdown-column-padding,0)}devsite-tabs [dropdown-full] .devsite-tabs-dropdown-column{-webkit-box-flex:1;-webkit-flex:1;-moz-box-flex:1;-ms-flex:1;flex:1;grid-row:var(--devsite-dropdown-column-grid-row,auto);min-width:0}devsite-tabs .devsite-tabs-dropdown-section{list-style:none;margin:var(--devsite-dropdown-section-margin,0);padding:var(--devsite-dropdown-section-padding,0 12px)}devsite-tabs .devsite-tabs-dropdown-section:first-child{margin:var(--devsite-dropdown-first-section-margin,18px 0 0)}devsite-tabs .devsite-tabs-dropdown-section:not(:first-child){margin-top:54px}devsite-tabs tab[dropdown] .devsite-nav-item,devsite-tabs tab[dropdown] .devsite-nav-title{line-height:18px;margin:var(--devsite-nav-text-margin,0 0 18px)}devsite-tabs tab[dropdown] .devsite-nav-title{border-bottom:var(--devsite-nav-title-border-bottom,0);color:var(--devsite-nav-title-color,var(--devsite-secondary-text-color));font:var(--devsite-nav-title-font,inherit);font-weight:var(--devsite-nav-title-font-weight,700);outline:none;padding:var(--devsite-nav-title-padding,0);text-transform:var(--devsite-nav-title-transform,none);white-space:var(--devsite-nav-title-white-space)}devsite-tabs tab[dropdown] .devsite-nav-item-title{display:var(--devsite-nav-item-title-display,block);font:var(--devsite-nav-item-title-font,inherit);letter-spacing:var(--devsite-nav-item-title-letter-spacing,normal);line-height:var(--devsite-nav-item-title-line-height,inherit);margin:var(--devsite-nav-item-title-margin,0)}devsite-tabs [dropdown-full] .devsite-nav-item>a,devsite-tabs [dropdown-full] .devsite-nav-title{display:block;overflow:hidden;text-overflow:ellipsis;white-space:normal}devsite-tabs tab[dropdown] .devsite-nav-description,devsite-tabs tab[dropdown] .devsite-nav-item-description{font:var(--devsite-nav-description-font,inherit);font-size:var(--devsite-nav-description-font-size,inherit);line-height:var(--devsite-nav-description-line-height,inherit)}devsite-tabs tab[dropdown] .devsite-nav-description{color:var(--devsite-nav-description-color,inherit);display:var(--devsite-nav-description-display,inherit);margin:var(--devsite-nav-description-margin,12px 0);white-space:var(--devsite-nav-description-white-space,inherit)}devsite-tabs tab[dropdown] .devsite-nav-item-description{color:var(--devsite-secondary-text-color);padding:var(--devsite-padding,0);white-space:normal}body[theme] devsite-tabs .devsite-tabs-dropdown a,body[theme] devsite-tabs .devsite-tabs-dropdown a:visited{color:var(--devsite-primary-text-color);display:var(--devsite-dropdown-link-display,block);font-weight:400}body[theme] devsite-tabs .devsite-tabs-dropdown a:focus,body[theme] devsite-tabs .devsite-tabs-dropdown a:hover{color:var(--devsite-link-color)}devsite-tabs[render-hidden]{width:100%}devsite-tabs tab[overflow-tab][render-hidden],devsite-tabs[render-hidden] tab[overflow-tab]{-webkit-box-flex:0;-webkit-flex:none;-moz-box-flex:0;-ms-flex:none;flex:none}devsite-tabs tab[dropdown] .devsite-tabs-close-button{color:var(--devsite-primary-text-color);cursor:pointer;position:absolute;right:24px;top:24px;visibility:hidden;z-index:1}devsite-tabs tab[dropdown] .devsite-tabs-close-button:focus,devsite-tabs tab[dropdown] .devsite-tabs-close-button:hover{color:var(--devsite-link-color)}devsite-tabs tab[dropdown--open] .devsite-tabs-close-button{visibility:visible}devsite-thumb-rating{display:block}devsite-thumb-rating[position=footer]{text-align:center}devsite-thumb-rating .devsite-thumb-rating{border-radius:4px;display:grid;grid-gap:0 8px;grid-template-areas:"label thumbs";grid-template-columns:auto 1fr}devsite-thumb-rating .devsite-thumb-label{font-size:13px;grid-area:label}devsite-thumb-rating .devsite-thumbs{grid-area:thumbs}devsite-thumb-rating[position=header] .devsite-thumbs,devsite-thumb-rating[position=main] .devsite-thumbs{margin:-3px 0}devsite-thumb-rating .devsite-thumb{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;background:0;border:0;border-radius:50%;box-shadow:none;cursor:pointer;display:-webkit-inline-box;display:-webkit-inline-flex;display:-moz-inline-box;display:-ms-inline-flexbox;display:inline-flex;fill:var(--devsite-secondary-text-color);height:30px;-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;-ms-flex-pack:center;justify-content:center;min-width:30px;padding:0;width:30px}devsite-thumb-rating .devsite-thumb:focus,devsite-thumb-rating .devsite-thumb:hover{background:var(--devsite-background-3)}devsite-thumb-rating .devsite-thumb+.devsite-thumb{margin:0}devsite-thumb-rating[rating=down] .devsite-thumb-down,devsite-thumb-rating[rating=up] .devsite-thumb-up{fill:var(--devsite-link-color)}devsite-thumb-rating[rating=down] .devsite-thumb-down:focus,devsite-thumb-rating[rating=down] .devsite-thumb-down:hover,devsite-thumb-rating[rating=up] .devsite-thumb-up:focus,devsite-thumb-rating[rating=up] .devsite-thumb-up:hover{background:var(--devsite-link-background-active)}devsite-thumb-rating .devsite-thumb-icon{-webkit-box-flex:0;-webkit-flex:none;-moz-box-flex:0;-ms-flex:none;flex:none;height:18px;pointer-events:none;width:18px}devsite-thumb-rating[position=footer] .devsite-thumb-rating{display:block;margin-top:24px}.devsite-thumb-rating-dialog{position:relative}.devsite-thumb-rating-dialog .devsite-thumb-rating-categories{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-moz-box-orient:vertical;-moz-box-direction:normal;-ms-flex-direction:column;flex-direction:column}.devsite-thumb-rating-dialog .devsite-thumb-rating-category{padding-bottom:12px}[dir=ltr] .devsite-thumb-rating-dialog h3{text-align:left}[dir=rtl] .devsite-thumb-rating-dialog h3{text-align:right}.devsite-thumb-rating-dialog h3:only-child{margin-bottom:8px}.devsite-thumb-rating-dialog .devsite-dialog-buttons{-webkit-box-pack:start;-webkit-justify-content:flex-start;-moz-box-pack:start;-ms-flex-pack:start;justify-content:flex-start;padding:0 16px 16px}.devsite-thumb-rating-dialog .devsite-feedback-icon{fill:currentColor;top:0}[dir=ltr] .button+devsite-feedback[position=thumb-rating]{margin-left:16px}[dir=rtl] .button+devsite-feedback[position=thumb-rating]{margin-right:16px}devsite-feedback[feedback-type=thumb-rating][position=header]{margin-top:4px}devsite-feedback[feedback-type=thumb-rating][position=footer]{display:block;margin-top:8px;text-align:center}.devsite-thumb-rating-dialog .devsite-dialog-contents{color:var(--devsite-primary-text-color)}.devsite-thumb-rating-dialog input+label{font-size:14px}.devsite-thumb-rating-dialog .account-note{color:var(--devsite-secondary-text-color);font:400 12px/16px var(--devsite-primary-font-family);letter-spacing:.3px}.devsite-thumb-rating-dialog .create-profile-spinner{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;background:hsla(0,0%,100%,.8);bottom:0;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;-ms-flex-pack:center;justify-content:center;left:0;opacity:0;pointer-events:none;position:absolute;right:0;top:0;-webkit-transition:opacity .3s cubic-bezier(.4,0,.2,1);transition:opacity .3s cubic-bezier(.4,0,.2,1);z-index:10}.devsite-thumb-rating-dialog.loading .create-profile-spinner{opacity:1}@media screen and (max-width:600px){devsite-thumb-rating[position=header] .devsite-thumb-rating{margin:16px 0 8px}devsite-thumb-rating[position=main] .devsite-thumb-rating{margin:8px 0}devsite-thumb-rating[position=footer] .devsite-thumb-rating{margin-bottom:24px}}devsite-toc.devsite-toc{overflow:auto;width:160px}devsite-toc>.devsite-nav-list{-webkit-border-start:var(--devsite-toc-border-width,4px) solid var(--devsite-toc-border,var(--devsite-primary-color));-moz-border-start:var(--devsite-toc-border-width,4px) solid var(--devsite-toc-border,var(--devsite-primary-color));border-inline-start:var(--devsite-toc-border-width,4px) solid var(--devsite-toc-border,var(--devsite-primary-color));width:160px}.devsite-sidebar[fixed] devsite-toc>.devsite-nav-list{-webkit-padding-end:8px;-moz-padding-end:8px;padding-inline-end:8px}devsite-toc>.devsite-nav-list>:first-child>.devsite-nav-title{padding-top:0}devsite-toc>.devsite-nav-list>:last-child>.devsite-nav-list>:last-child>.devsite-nav-title:last-child,devsite-toc>.devsite-nav-list>:last-child>.devsite-nav-title:only-child{padding-bottom:0}devsite-toc .devsite-nav-list{-webkit-padding-start:var(--devsite-nav-list-padding-x-start,12px);-moz-padding-start:var(--devsite-nav-list-padding-x-start,12px);padding-inline-start:var(--devsite-nav-list-padding-x-start,12px)}devsite-toc .devsite-nav-list .devsite-nav-list .devsite-nav-title{color:var(--devsite-nav-title-nested-color,var(--devsite-nav-title-color,var(--devsite-primary-text-color)))}devsite-toc .devsite-nav-list .devsite-nav-list .devsite-nav-title:focus,devsite-toc .devsite-nav-list .devsite-nav-list .devsite-nav-title:hover{color:var(--devsite-nav-nested-color-hover,var(--devsite-nav-color-hover,var(--devsite-link-color)))}devsite-toc .devsite-nav-list .devsite-nav-list .devsite-nav-active{color:var(--devsite-nav-color-active,var(--devsite-link-color-active,var(--devsite-link-color)))}devsite-toc.devsite-toc-embedded{display:none}devsite-toc.devsite-toc-embedded>.devsite-nav-list{width:auto}devsite-toc.devsite-toc-embedded .devsite-nav-item{display:none}devsite-toc.devsite-toc-embedded .devsite-nav-item[visible],devsite-toc.devsite-toc-embedded[expanded] .devsite-nav-item{display:block}devsite-toc.devsite-toc-embedded .devsite-nav-item.devsite-toc-toggle,devsite-toc.devsite-toc-embedded[expanded] .devsite-nav-item.devsite-toc-toggle{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex}devsite-toc .devsite-nav-more-items,devsite-toc .devsite-nav-show-all{display:none}devsite-toc[expandable] .devsite-nav-more-items,devsite-toc[expandable] .devsite-nav-show-all{color:var(--devsite-secondary-text-color);display:block;height:24px;padding:0}devsite-toc .devsite-nav-show-all{margin:-4px 0 0 4px;min-width:20px}devsite-toc .devsite-nav-show-all:before{content:"expand_more"}devsite-toc .devsite-nav-more-items{margin-bottom:-8px;min-width:0}devsite-toc .devsite-nav-more-items:before{content:"more_horiz"}devsite-toc[expanded] .devsite-nav-more-items:before,devsite-toc[expanded] .devsite-nav-show-all:before{content:"expand_less"}devsite-toc .devsite-toc-toggle{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;margin:0}devsite-toc .devsite-show-apix{margin-top:12px}@media screen and (max-width:1253px){devsite-toc.devsite-toc,devsite-toc[visible].devsite-toc{display:none}devsite-toc.devsite-toc-embedded:not(:empty){display:block;margin:28px 0 24px}body[layout][concierge] devsite-toc.devsite-toc-embedded{display:none}devsite-toc.devsite-toc-embedded:not(:empty)~.devsite-article-body>:first-child{margin-top:0}body[template=landing] devsite-toc.devsite-toc-embedded:not(:empty){margin:20px 40px 24px}}@media screen and (max-width:840px){body[template=landing] devsite-toc.devsite-toc-embedded:not(:empty){margin:20px 24px 24px}body[layout][concierge] devsite-toc.devsite-toc-embedded:not(:empty){display:block}}@media screen and (max-width:600px){body[template=landing] devsite-toc.devsite-toc-embedded:not(:empty){margin:20px 16px 24px}}.devsite-tooltip-msg{border-radius:2px;background:rgba(95,99,104,.9);color:#fff;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;font:500 10px/10px var(--devsite-primary-font-family);margin:8px 0;max-width:300px;opacity:1;padding:6px 8px;pointer-events:none;position:fixed;-webkit-transition:opacity .2s;transition:opacity .2s;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;z-index:1020}devsite-topic{display:block}devsite-topic .devsite-topic--inner{max-width:936px;padding:0 40px;margin:0 auto}devsite-topic .devsite-topic--header{background-color:var(--devsite-background-1);background-image:url(../images/devsite_topics_header.svg);background-repeat:no-repeat;background-position:top;background-size:1440px auto;margin-bottom:40px}devsite-topic .devsite-topic--header .devsite-topic--inner{padding-top:168px}devsite-topic .devsite-topic--header h1{margin:0;top:auto;font-size:36px;line-height:44px;color:#202124;font-family:var(--devsite-headline-font-family)}devsite-topic .devsite-topic--header p{margin:0;padding:0;color:#202124;font-size:18px;line-height:24px;font-family:var(--devsite-headline-font-family)}devsite-topic .devsite-topic--header .jump-links{border-bottom:1px solid #ddd;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;font-family:Google Sans;font-weight:500;-ms-flex-pack:distribute;-webkit-justify-content:space-around;justify-content:space-around;list-style:none;padding:26px 0 0;width:100%}devsite-topic .devsite-topic--header .jump-links a:after{content:"arrow_downward";font:normal normal normal 18px/1 Material Icons;margin-left:8px;vertical-align:text-bottom}devsite-topic .devsite-topic--header .jump-links a{text-decoration:none!important}devsite-topic .devsite-topic--header .jump-links a:link,devsite-topic .devsite-topic--header .jump-links a:visited{color:#5f6368!important}devsite-topic .devsite-topic--header .jump-links a:focus,devsite-topic .devsite-topic--header .jump-links a:hover{color:#1a73e8!important}devsite-topic .devsite-topic--section{padding:40px 0}devsite-topic .devsite-topic--section:nth-child(odd){background:#f8f9fa}devsite-topic .devsite-topic--section:first-child(){background:none}devsite-topic .devsite-topic--section h2{margin:0;padding:0;font-size:32px;color:#202124;line-height:40px;font-family:var(--devsite-headline-font-family)}devsite-topic .devsite-topic--section .devsite-topic-section-description{margin:0;padding:0;font-size:16px;color:#3c4043;line-height:24px;font-family:var(--devsite-primary-font-family);max-width:calc(66.6666666667% - 13.3333333333px)}devsite-topic .devsite-topic-section--row{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;margin:0 -12px;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}devsite-topic .devsite-topic-section--row .devsite-topic-section--card{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;min-width:0;max-width:100%;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-moz-box-orient:vertical;-moz-box-direction:normal;-ms-flex-direction:column;flex-direction:column;margin:0 12px 24px}devsite-topic .devsite-topic-section--row .devsite-topic-section--card .devsite-topic-section-card--title{font-size:24px;color:#202124;line-height:32px;font-family:var(--devsite-primary-font-family)}devsite-topic .devsite-topic-section--row .devsite-topic-section--card .devsite-topic-section-card--title a{color:#202124}devsite-topic .devsite-topic-section--row .devsite-topic-section--card .devsite-topic-section-card--description{font-size:16px;color:#3c4043;letter-spacing:.1px;line-height:24px;-webkit-box-flex:1;-webkit-flex-grow:1;-moz-box-flex:1;-ms-flex-positive:1;flex-grow:1}devsite-topic .devsite-topic-section-card--label{padding:16px}devsite-topic .devsite-topic-section-card--label span{border-radius:4px;padding:2px 8px;font-family:var(--devsite-primary-font-family);font-size:12px;color:rgba(0,0,0,.87);text-transform:uppercase}devsite-topic .devsite-topic-section--hero{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:reverse;-webkit-flex-direction:row-reverse;-moz-box-orient:horizontal;-moz-box-direction:reverse;-ms-flex-direction:row-reverse;flex-direction:row-reverse}devsite-topic .devsite-topic-section--hero-media{margin-left:12px}devsite-topic .devsite-topic-section--hero-media .devsite-landing-row-item-image{background:none}devsite-topic .devsite-topic-section--hero-description{margin-right:12px}devsite-topic .devsite-topic-section--hero-description p.devsite-topic-section-description{max-width:100%}devsite-topic .devsite-topic-section--hero-description,devsite-topic .devsite-topic-section--hero-media{-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;width:calc(50% - 12px)}devsite-topic .devsite-topic-section--cards{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;padding-top:24px;margin:0 -12px;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}devsite-topic .devsite-topic-section--cards .devsite-topic-section--card{box-shadow:0 1px 2px 0 var(--devsite-elevation-key-shadow-color),0 2px 6px 2px var(--devsite-elevation-ambient-shadow-color);background:var(--devsite-background-1);display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;min-width:0;max-width:100%;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-moz-box-orient:vertical;-moz-box-direction:normal;-ms-flex-direction:column;flex-direction:column;border-radius:4px;margin:0 12px 24px;width:calc(50% - 24px)}devsite-topic .devsite-topic-section--cards .devsite-topic-section--card .devsite-topic-section-card--title{padding:0 16px}devsite-topic .devsite-topic-section--cards .devsite-topic-section--card .devsite-topic-section-card--title a{font-family:var(--devsite-headline-font-family);font-size:24px;color:#202124;line-height:32px}devsite-topic .devsite-topic-section--cards .devsite-topic-section--card .devsite-topic-section-card--description{padding:8px 16px 24px;border-bottom:1px solid #ddd;-webkit-box-flex:1;-webkit-flex-grow:1;-moz-box-flex:1;-ms-flex-positive:1;flex-grow:1}devsite-topic .devsite-topic-section--cards .devsite-topic-section--card .devsite-topic-section-card--description p{font-size:16px;color:#3c4043;line-height:24px}devsite-topic .devsite-topic-section--cards .devsite-topic-section--card .devsite-topic-section-card--meta{padding:16px 16px 12px;font-size:12px;line-height:16px}devsite-topic .devsite-topic-section--cards .devsite-topic-section--card .devsite-topic-section-card--meta-byline{color:#202124}devsite-topic .devsite-topic-section--cards .devsite-topic-section--card .devsite-topic-section-card--meta-date{color:#3c4043}devsite-topic .devsite-topic-section--cards .devsite-topic-section--card .devsite-topic-section-card--buttons{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:end;-webkit-justify-content:flex-end;-moz-box-pack:end;-ms-flex-pack:end;justify-content:flex-end;padding:12px 8px 8px}devsite-topic .devsite-topic-section--1-up .devsite-topic-section--card{width:calc(100% - 24px);margin-bottom:0}devsite-topic .devsite-topic-section--2-up .devsite-topic-section--card{margin-bottom:0}devsite-topic .devsite-topic-section--3-up .devsite-topic-section--card{width:calc(33% - 24px)}@media screen and (max-width:840px){devsite-topic .devsite-topic--inner{max-width:768px;padding:0 40px}}@media screen and (max-width:600px){devsite-topic .devsite-topic--inner{max-width:100%;padding:0 24px}devsite-topic .devsite-topic--section{padding:24px 0}devsite-topic .devsite-topic--section .devsite-topic-section--card{width:calc(100% - 24px)}devsite-topic .devsite-topic-section--hero{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-moz-box-orient:vertical;-moz-box-direction:normal;-ms-flex-direction:column;flex-direction:column}devsite-topic .devsite-topic-section--hero-description,devsite-topic .devsite-topic-section--hero-media{margin:0;width:100%}devsite-topic .devsite-topic-section--hero-media{margin-bottom:24px}}devsite-tracking-question{background-color:var(--devsite-background-3);display:block;padding:8px}devsite-tracking-question .devsite-tracking-question-text{font-weight:700}devsite-tracking-question .devsite-tracking-question-hidden{display:none}devsite-tracking-question .devsite-tracking-question-choice-button{background:var(--devsite-background-1);border-radius:2px;box-shadow:0 2px 5px 0 rgba(0,0,0,.26);color:var(--devsite-primary-text-color);cursor:pointer;line-height:50px;margin:8px 0;padding:0 20px;-webkit-transition:background .2s,box-shadow .2s;transition:background .2s,box-shadow .2s}devsite-tracking-question .devsite-tracking-question-choice-button:focus,devsite-tracking-question .devsite-tracking-question-choice-button:hover{background:#bdc1c6;box-shadow:0 4px 8px 0 hsla(210,6%,63%,.5)}devsite-user{display:block;-webkit-box-flex:0;-webkit-flex:0 0 auto;-moz-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto}devsite-user[signed-in],devsite-user[signed-in].not-eligible{min-width:44px}devsite-user[signed-in][enable-profiles]{min-width:84px}devsite-user[signed-in][enable-profiles].not-eligible{min-width:44px}devsite-user[signed-in][enable-profiles][fp-auth]{min-width:88px}devsite-user[signed-in][enable-profiles][fp-auth].not-eligible{min-width:44px}devsite-user #devsite-signin-btn{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;font:500 14px/36px var(--devsite-primary-font-family)}devsite-user devsite-spinner{margin:4px 8px 4px 20px}devsite-user devsite-spinner.hide{opacity:0;-webkit-transition:opacity .45s ease;transition:opacity .45s ease;-webkit-animation-delay:.45s;animation-delay:.45s}devsite-user .ogb-wrapper{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;gap:8px;-webkit-box-pack:end;-webkit-justify-content:flex-end;-moz-box-pack:end;-ms-flex-pack:end;justify-content:flex-end;opacity:1;-webkit-transition:opacity .2s cubic-bezier(.4,0,.2,1);transition:opacity .2s cubic-bezier(.4,0,.2,1)}devsite-user .ogb-pending{opacity:0}devsite-user .gb_Mb>.gb_Lb,devsite-user .gb_Nb>.gb_Mb,devsite-user .gb_Pd>.gb_Za,devsite-user .gb_Rb>.gb_Qb,devsite-user .gb_Sb>.gb_Rb{-moz-box-sizing:content-box;box-sizing:content-box}devsite-user button.devsite-user-change-account,devsite-user button.devsite-user-signout{height:auto;color:var(--devsite-primary-text-color)}devsite-user button.devsite-user-change-account .material-icons,devsite-user button.devsite-user-signout .material-icons{margin:0;height:auto;width:auto;top:auto}devsite-user button.devsite-user-change-account{border-left:0;border-right:0;border:0}@media (-webkit-min-device-pixel-ratio:1.25),(min-resolution:1.25dppx),not all{[dir=rtl] devsite-user .gb_xa:before{-webkit-transform-origin:right 0;transform-origin:right 0}}devsite-user .devsite-user-dialog{display:none}devsite-user .devsite-user-dialog a:link,devsite-user .devsite-user-dialog a:visited{text-decoration:none}devsite-user[dialog--open] .devsite-user-dialog{background:#f3f6fc;border:1px solid rgba(0,0,0,.2);border-radius:8px;box-shadow:0 2px 10px rgba(0,0,0,.2);color:rgba(0,0,0,.87);display:block;max-height:calc(100vh - 86px);outline:none;overflow:auto;position:absolute;right:24px;top:62px;width:354px}[dir=rtl] devsite-user[dialog--open] .devsite-user-dialog{left:24px;right:auto}devsite-user .devsite-user-dialog-photo,devsite-user .devsite-user-dialog-toggle,devsite-user .devsite-user-dialog-toggle .devsite-user-dialog-letter{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;border-radius:50%;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;-ms-flex-pack:center;justify-content:center;margin:0;overflow:hidden;padding:0}devsite-user .devsite-user-dialog .devsite-user-dialog-photo,devsite-user .devsite-user-dialog-signin .devsite-user-dialog-letter{background:var(--devsite-user-avatar-background,var(--devsite-background-color,var(--devsite-primary-color,var(--devsite-primary-text-color))));color:var(--devsite-user-avatar-color,var(--devsite-text-color,var(--devsite-inverted-text-color)))}devsite-user .devsite-user-dialog-toggle{border:4px solid transparent;-moz-box-sizing:content-box;box-sizing:content-box;height:32px;margin:0 4px 0 0;overflow:hidden;text-decoration:none;width:32px}[dir=rtl] devsite-user .devsite-user-dialog-toggle{margin:0 0 0 4px}devsite-user .devsite-user-dialog-toggle:focus{border-color:var(--devsite-link-background-active)}devsite-user .devsite-user-dialog-photo-thumbnail{height:32px;width:32px}devsite-user[js-signin] button{box-shadow:none}devsite-user[js-signin] .devsite-user-dialog-toggle{opacity:0;-webkit-transition:opacity .45s ease;transition:opacity .45s ease}devsite-user[js-signin] .devsite-user-dialog-toggle.show{opacity:1}devsite-user .devsite-user-dialog-toggle .devsite-user-dialog-letter{-webkit-box-flex:0;-webkit-flex:0 0 32px;-moz-box-flex:0;-ms-flex:0 0 32px;flex:0 0 32px;font-size:17px;height:32px}devsite-user .devsite-user-dialog-learn-more{background-color:var(--devsite-link-background-active);border-radius:4px;color:var(--devsite-secondary-text-color);font:12px/16px var(--devsite-primary-font-family);margin:4px 4px 0;padding:4px 29px;text-align:center}devsite-user .devsite-user-dialog-learn-more a,devsite-user .devsite-user-dialog-learn-more span{font-weight:500}devsite-user .devsite-user-dialog-learn-more a{color:var(--devsite-contrast-link-color)}devsite-user .devsite-user-dialog-learn-more a:focus,devsite-user .devsite-user-dialog-learn-more a:hover{text-decoration:underline}devsite-user .devsite-user-dialog-user{background:#fff;border-radius:0 0 16px 16px;margin:0 4px 4px;padding:20px 33px 23px;text-align:center}devsite-user .devsite-user-dialog-photo{margin:0 auto 16px;position:relative;left:-2px}devsite-user .devsite-user-dialog-photo,devsite-user .devsite-user-dialog-photo-portrait{height:80px;width:80px}devsite-user .devsite-user-dialog-letter{text-transform:uppercase}devsite-user .devsite-user-dialog-photo .devsite-user-dialog-letter{font-size:52px}devsite-user .devsite-user-dialog-email,devsite-user .devsite-user-dialog-name{text-overflow:ellipsis;overflow:hidden}devsite-user .devsite-user-dialog-name{color:var(--devsite-primary-text-color);font:500 16px/22px var(--devsite-headline-font-family);letter-spacing:.29px}devsite-user .devsite-user-dialog-email{color:var(--devsite-secondary-text-color);font:400 14px/19px var(--devsite-primary-font-family)}devsite-user .devsite-user-manage{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;background:0;border:var(--devsite-primary-border);border-radius:17px;display:-webkit-inline-box;display:-webkit-inline-flex;display:-moz-inline-box;display:-ms-inline-flexbox;display:inline-flex;font:500 14px/20px var(--devsite-headline-font-family);height:34px;letter-spacing:.25px;margin:16px 0 0;padding:0 16px;white-space:nowrap}devsite-user .devsite-user-manage:link,devsite-user .devsite-user-manage:visited{color:var(--devsite-primary-text-color)}devsite-user .devsite-user-manage:focus,devsite-user .devsite-user-manage:hover{background-color:var(--devsite-background-2)}devsite-user .devsite-user-manage:active{box-shadow:0 1px 2px 0 var(--devsite-elevation-key-shadow-color),0 2px 6px 2px var(--devsite-elevation-ambient-shadow-color);background-color:var(--devsite-background-4);border-color:transparent}devsite-user .devsite-user-dialog-buttons{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-moz-box-orient:vertical;-moz-box-direction:normal;-ms-flex-direction:column;flex-direction:column}devsite-user .devsite-user-dialog .developer-profile:link,devsite-user .devsite-user-dialog .developer-profile:visited,devsite-user .devsite-user-dialog .devsite-user-developer-profile:link,devsite-user .devsite-user-dialog .devsite-user-developer-profile:visited,devsite-user .devsite-user-dialog .devsite-user-signin:link,devsite-user .devsite-user-dialog .devsite-user-signin:visited,devsite-user .devsite-user-signout:link,devsite-user .devsite-user-signout:visited{color:var(--devsite-primary-text-color)}devsite-user .devsite-user-dialog .developer-profile:focus,devsite-user .devsite-user-dialog .developer-profile:hover,devsite-user .devsite-user-dialog .devsite-user-developer-profile:focus,devsite-user .devsite-user-dialog .devsite-user-developer-profile:hover,devsite-user .devsite-user-dialog .devsite-user-signin:focus,devsite-user .devsite-user-dialog .devsite-user-signin:hover,devsite-user .devsite-user-signout:focus,devsite-user .devsite-user-signout:hover{background-color:var(--devsite-background-2)}devsite-user .devsite-user-dialog .developer-profile:active,devsite-user .devsite-user-dialog .devsite-user-developer-profile:active,devsite-user .devsite-user-dialog .devsite-user-signin:active,devsite-user .devsite-user-signout:active{background-color:var(--devsite-background-4)}devsite-user .devsite-user-dialog .devsite-user-developer-profile,devsite-user .devsite-user-dialog .devsite-user-signin{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;font:500 14px/16px var(--devsite-headline-font-family);letter-spacing:.25px;padding:15px 39px 16px;width:100%}devsite-user .devsite-user-dialog-buttons>:first-child{border-top:var(--devsite-secondary-border)}devsite-user .devsite-user-dialog .devsite-user-signin{border-bottom:var(--devsite-secondary-border)}devsite-user .devsite-user-dialog .new-notification{background:var(--devsite-notification-background);border-radius:10px;color:var(--devsite-inverted-text-color);font-weight:700;font-size:12px;letter-spacing:.3px;padding:2px 8px}[dir=ltr] devsite-user .devsite-user-dialog .new-notification{margin-left:12px}[dir=rtl] devsite-user .devsite-user-dialog .new-notification{margin-right:12px}devsite-user .devsite-user-signin .devsite-switch-account-icon{fill:currentColor;-webkit-margin-end:12px;-moz-margin-end:12px;margin-inline-end:12px}devsite-user .devsite-user-developer-profile .google-dev-icon{width:28px;position:relative}[dir=ltr] devsite-user .devsite-user-developer-profile .google-dev-icon{margin-left:-4px;margin-right:8px}[dir=rtl] devsite-user .devsite-user-developer-profile .google-dev-icon{margin-left:8px;margin-right:-4px}devsite-user .devsite-user-signout{border:var(--devsite-primary-border);border-radius:4px;display:inline-block;font:500 14px/16px var(--devsite-headline-font-family);letter-spacing:.15px;margin:16px auto;padding:10px 24px}devsite-user .devsite-user-signout:active{box-shadow:0 1px 2px 0 var(--devsite-elevation-key-shadow-color),0 2px 6px 2px var(--devsite-elevation-ambient-shadow-color);background-color:var(--devsite-background-4);border-color:transparent}devsite-user .devsite-user-dialog-footer{border-top:var(--devsite-secondary-border);display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;-ms-flex-pack:center;justify-content:center;padding:14px 20px}devsite-user .devsite-user-dialog-footer-link{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-inline-box;display:-webkit-inline-flex;display:-moz-inline-box;display:-ms-inline-flexbox;display:inline-flex;margin:0}devsite-user .devsite-user-dialog-footer-link:not(:first-child):before{color:var(--devsite-secondary-text-color);content:"•";font-size:13px}devsite-user .devsite-user-dialog-footer-link>a{border-radius:4px;display:inline-block;font:400 12px/16px var(--devsite-primary-font-family);padding:4px 8px}devsite-user .devsite-user-dialog-footer-link>a:link,devsite-user .devsite-user-dialog-footer-link>a:visited{color:var(--devsite-secondary-text-color)}devsite-user .devsite-user-dialog-footer-link>a:focus,devsite-user .devsite-user-dialog-footer-link>a:hover{background-color:var(--devsite-background-2)}devsite-user .devsite-user-dialog-footer-link>a:active{background-color:var(--devsite-background-4)}devsite-user .devsite-devprofile-wrapper{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:end;-webkit-justify-content:flex-end;-moz-box-pack:end;-ms-flex-pack:end;justify-content:flex-end;position:relative;opacity:0}devsite-user .devsite-devprofile-wrapper.show{opacity:1;-webkit-transition:all .15s cubic-bezier(.4,0,.2,1) 0s;transition:all .15s cubic-bezier(.4,0,.2,1) 0s}devsite-user .devsite-devprofile-wrapper devsite-spinner{margin:0}devsite-user .devsite-devprofile-wrapper .devsite-devprofile-notifications-indicator{border-radius:8px;background-color:#1a73e8;width:8px;height:8px;position:absolute;top:0;right:0;z-index:1}devsite-user .devsite-devprofile-wrapper .devsite-devprofile-button{height:32px;width:32px;min-width:32px;min-height:32px;margin:0;padding:0;border:var(--devsite-primary-border);display:-webkit-inline-box;display:-webkit-inline-flex;display:-moz-inline-box;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;-ms-flex-pack:center;justify-content:center;position:relative;--devsite-button-background-hover:#e8eaed;--devsite-button-background-active:#e8eaed;--devsite-button-border-hover:none;--devsite-button-border-radius:50%;--devsite-button-box-shadow:none;--devsite-button-box-shadow-active:none}devsite-user .devsite-devprofile-wrapper.open .devsite-devprofile-button{background:#e8eaed}devsite-user .devsite-devprofile-wrapper .devsite-devprofile-callout,devsite-user .devsite-devprofile-wrapper .devsite-devprofile-popout{max-width:378px;width:100vw}devsite-user .devsite-devprofile-wrapper .devsite-devprofile-callout .devsite-devprofile-notch,devsite-user .devsite-devprofile-wrapper .devsite-devprofile-popout .devsite-devprofile-notch{border-bottom:8px solid var(--devsite-background-1);border-left:9px solid transparent;border-right:9px solid transparent;-webkit-clip-path:inset(-8px -8px 0);clip-path:inset(-8px -8px 0);height:0;position:absolute;right:9px;top:-8px;width:0;-webkit-filter:drop-shadow(0 1px 2px var(--devsite-elevation-key-shadow-color)) drop-shadow(0 2px 6px var(--devsite-elevation-ambient-shadow-color));filter:drop-shadow(0 1px 2px var(--devsite-elevation-key-shadow-color)) drop-shadow(0 2px 6px var(--devsite-elevation-ambient-shadow-color))}devsite-user .devsite-devprofile-wrapper .devsite-devprofile-callout .devsite-devprofile-notch:before{background:var(--devsite-background-1)}devsite-user .devsite-devprofile-wrapper .devsite-devprofile-popout{position:absolute;background:var(--devsite-background-1);box-shadow:0 1px 2px rgba(60,64,67,.3),0 2px 6px 2px rgba(60,64,67,.15);border-radius:8px;font-family:var(--devsite-primary-font-family);padding:8px 0;margin-top:8px;margin-right:-2px;top:100%;right:0;opacity:0;-webkit-transform-origin:top right;transform-origin:top right;-webkit-transform:scale(.8);transform:scale(.8);-webkit-transition:all .15s cubic-bezier(.4,0,.2,1) 0s;transition:all .15s cubic-bezier(.4,0,.2,1) 0s;pointer-events:none;display:none;z-index:1007}devsite-user .devsite-devprofile-wrapper .devsite-devprofile-popout .devsite-devprofile-notch:before{background:var(--devsite-background-1)}[dir=rtl] devsite-user .devsite-devprofile-wrapper .devsite-devprofile-popout{left:0;right:auto}devsite-user .devsite-devprofile-wrapper .devsite-devprofile-popout.show{opacity:1;-webkit-transform:scale(1);transform:scale(1);pointer-events:all}devsite-user .devsite-devprofile-wrapper .devsite-devprofile-popout.visible{display:block}devsite-user .devsite-devprofile-wrapper .devsite-devprofile-popout .devsite-devprofile-notifications-container{margin-left:10px;font-weight:500;color:#fff;font-size:12px;background-color:#1a73e8;border-radius:16px;padding:0 5px 0 4px;height:16px;line-height:16px}devsite-user .devsite-devprofile-wrapper .devsite-devprofile-popout .profile-links-header{color:var(--devsite-primary-text-color);font-weight:500;font-size:11px;line-height:16px;letter-spacing:.8px;text-transform:uppercase;padding:12px 14px}devsite-user .devsite-devprofile-wrapper .devsite-devprofile-popout .profile-link{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;padding:14px 16px;color:var(--devsite-primary-text-color);font-size:16px;font-weight:400;line-height:24px;text-decoration:none}devsite-user .devsite-devprofile-wrapper .devsite-devprofile-popout .profile-link:hover{background:#f1f3f4}devsite-user .devsite-devprofile-wrapper .devsite-devprofile-popout ul{margin:0;padding:0}devsite-user .devsite-devprofile-wrapper .devsite-devprofile-popout ul li{margin:0;padding:0;list-style:none}devsite-user .devsite-devprofile-wrapper .devsite-devprofile-popout[popup-type=view-profile]{max-width:232px}devsite-user .devsite-devprofile-wrapper .devsite-devprofile-popout[popup-type=view-bookmarked-pages],devsite-user .devsite-devprofile-wrapper .devsite-devprofile-popout[popup-type=view-rated-pages]{background:var(--devsite-link-color);color:var(--devsite-inverted-text-color);padding:16px 24px}devsite-user .devsite-devprofile-wrapper .devsite-devprofile-popout[popup-type=view-bookmarked-pages] .devsite-devprofile-notch,devsite-user .devsite-devprofile-wrapper .devsite-devprofile-popout[popup-type=view-rated-pages] .devsite-devprofile-notch{border-bottom:8px solid var(--devsite-link-color)}devsite-user .devsite-devprofile-wrapper .devsite-devprofile-popout[popup-type=view-bookmarked-pages] .devsite-devprofile-notch:before,devsite-user .devsite-devprofile-wrapper .devsite-devprofile-popout[popup-type=view-rated-pages] .devsite-devprofile-notch:before{background:var(--devsite-link-color)}devsite-user .devsite-devprofile-wrapper .devsite-devprofile-popout[popup-type=view-bookmarked-pages] .devsite-devprofile-notch svg g path,devsite-user .devsite-devprofile-wrapper .devsite-devprofile-popout[popup-type=view-rated-pages] .devsite-devprofile-notch svg g path{fill:var(--devsite-link-color)}devsite-user .devsite-devprofile-wrapper .devsite-devprofile-popout[popup-type=view-bookmarked-pages] .buttons,devsite-user .devsite-devprofile-wrapper .devsite-devprofile-popout[popup-type=view-rated-pages] .buttons{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-pack:end;-webkit-justify-content:flex-end;-moz-box-pack:end;-ms-flex-pack:end;justify-content:flex-end;margin-top:16px}devsite-user .devsite-devprofile-wrapper .devsite-devprofile-popout[popup-type=view-bookmarked-pages] .buttons .button:hover,devsite-user .devsite-devprofile-wrapper .devsite-devprofile-popout[popup-type=view-rated-pages] .buttons .button:hover{--devsite-link-color:#1e88e5}devsite-user .devsite-devprofile-wrapper .devsite-devprofile-popout[popup-type=view-bookmarked-pages] .button-white,devsite-user .devsite-devprofile-wrapper .devsite-devprofile-popout[popup-type=view-rated-pages] .button-white{color:var(--devsite-inverted-text-color)}devsite-user .devsite-devprofile-wrapper .devsite-devprofile-popout[popup-type=view-bookmarked-pages] .button-white:focus,devsite-user .devsite-devprofile-wrapper .devsite-devprofile-popout[popup-type=view-bookmarked-pages] .button-white:hover,devsite-user .devsite-devprofile-wrapper .devsite-devprofile-popout[popup-type=view-rated-pages] .button-white:focus,devsite-user .devsite-devprofile-wrapper .devsite-devprofile-popout[popup-type=view-rated-pages] .button-white:hover{background:var(--devsite-link-color);color:var(--devsite-button-background-hover)}devsite-user .devsite-devprofile-wrapper .devsite-devprofile-popout[popup-type=create-profile]{font-family:var(--devsite-primary-font-family);padding:12px 20px}devsite-user .devsite-devprofile-wrapper .devsite-devprofile-popout[popup-type=create-profile] .devsite-devprofile-callout-logo{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;-ms-flex-pack:center;justify-content:center;height:36px;margin:20px 0}devsite-user .devsite-devprofile-wrapper .devsite-devprofile-popout[popup-type=create-profile] .devsite-devprofile-callout-subhead{font-weight:500;font-size:16px;line-height:24px;text-align:center;letter-spacing:.1px;color:var(--devsite-primary-text-color);margin-bottom:8px}devsite-user .devsite-devprofile-wrapper .devsite-devprofile-popout[popup-type=create-profile] .devsite-devprofile-callout-body{font-size:14px;margin-bottom:24px}devsite-user .devsite-devprofile-wrapper .devsite-devprofile-popout[popup-type=create-profile] .devsite-devprofile-callout-buttons{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-pack:end;-webkit-justify-content:flex-end;-moz-box-pack:end;-ms-flex-pack:end;justify-content:flex-end}devsite-user .devsite-devprofile-wrapper .devsite-devprofile-callout{position:absolute;background:var(--devsite-background-1);box-shadow:0 1px 2px rgba(60,64,67,.3),0 2px 6px 2px rgba(60,64,67,.15);border-radius:8px;font-family:var(--devsite-headline-font-family);margin-top:8px;top:100%;right:-2px;padding:16px;max-width:378px;width:100vw;opacity:1;-webkit-transform:scale(1);transform:scale(1);-webkit-transition:all .15s cubic-bezier(.4,0,.2,1) 0s;transition:all .15s cubic-bezier(.4,0,.2,1) 0s}[dir=rtl] devsite-user .devsite-devprofile-wrapper .devsite-devprofile-callout{left:0;right:auto}devsite-user .devsite-devprofile-wrapper .devsite-devprofile-callout.hide{opacity:0;-webkit-transform-origin:top right;transform-origin:top right;-webkit-transform:scale(.8);transform:scale(.8)}devsite-user .devsite-devprofile-wrapper .devsite-devprofile-callout .devsite-devprofile-callout-error,devsite-user .devsite-devprofile-wrapper .devsite-devprofile-callout .devsite-devprofile-callout-step1,devsite-user .devsite-devprofile-wrapper .devsite-devprofile-callout .devsite-devprofile-callout-step2,devsite-user .devsite-devprofile-wrapper .devsite-devprofile-callout .devsite-devprofile-callout-step3,devsite-user .devsite-devprofile-wrapper .devsite-devprofile-callout .devsite-devprofile-callout-step4{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-moz-box-orient:vertical;-moz-box-direction:normal;-ms-flex-direction:column;flex-direction:column}devsite-user .devsite-devprofile-wrapper .devsite-devprofile-callout .devsite-devprofile-callout-step3{padding:24px 0}devsite-user .devsite-devprofile-wrapper .devsite-devprofile-callout .devsite-devprofile-logo{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;-ms-flex-pack:center;justify-content:center}devsite-user .devsite-devprofile-wrapper .devsite-devprofile-callout .devsite-devprofile-logo svg{width:74px}devsite-user .devsite-devprofile-wrapper .devsite-devprofile-callout h4{margin:20px 0 8px;padding:0;font-size:16px;line-height:24px;letter-spacing:.1px;color:var(--devsite-primary-text-color);text-align:left}devsite-user .devsite-devprofile-wrapper .devsite-devprofile-callout p{margin:0;padding:0;font-size:14px;line-height:20px;letter-spacing:.25px;color:var(--devsite-primary-text-color)}devsite-user .devsite-devprofile-wrapper .devsite-devprofile-callout .account-note,devsite-user .devsite-devprofile-wrapper .devsite-devprofile-callout .sub-text,devsite-user .devsite-devprofile-wrapper .devsite-devprofile-callout .tos{color:var(--devsite-secondary-text-color);font:400 12px/16px var(--devsite-primary-font-family);letter-spacing:.3px}devsite-user .devsite-devprofile-wrapper .devsite-devprofile-callout .sub-text,devsite-user .devsite-devprofile-wrapper .devsite-devprofile-callout .tos{font-size:14px}devsite-user .devsite-devprofile-wrapper .devsite-devprofile-callout .sub-text{-webkit-padding-start:16px;-moz-padding-start:16px;padding-inline-start:16px}devsite-user .devsite-devprofile-wrapper .devsite-devprofile-callout .devsite-devprofile-callout-newsletter,devsite-user .devsite-devprofile-wrapper .devsite-devprofile-callout .devsite-devprofile-callout-occupation{width:100%;margin-bottom:16px}devsite-user .devsite-devprofile-wrapper .devsite-devprofile-callout .devsite-devprofile-callout-newsletter label,devsite-user .devsite-devprofile-wrapper .devsite-devprofile-callout .devsite-devprofile-callout-occupation label{font-size:14px;letter-spacing:.25px;color:var(--devsite-primary-text-color);display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;line-height:16px}devsite-user .devsite-devprofile-wrapper .devsite-devprofile-callout .devsite-devprofile-callout-buttons{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;width:100%;-webkit-box-pack:end;-webkit-justify-content:flex-end;-moz-box-pack:end;-ms-flex-pack:end;justify-content:flex-end;margin-top:24px}devsite-user .devsite-devprofile-wrapper .devsite-devprofile-callout .devsite-devprofile-callout-buttons .button-dismiss{--devsite-button-border:0;--devsite-button-border-hover:0;--devsite-button-background-hover:#fff;--devsite-button-background-active:#fff;--devsite-button-border-active:0;--devsite-button-box-shadow-active:none}@media screen and (max-width:840px){devsite-user[dialog--open] .devsite-user-dialog{right:16px}[dir=rtl] devsite-user[dialog--open] .devsite-user-dialog{left:16px;right:auto}devsite-user .devsite-devprofile-wrapper .devsite-devprofile-callout{max-width:calc(100vw - 80px)}devsite-user .devsite-devprofile-wrapper .devsite-devprofile-popout{max-width:calc(100vw - 64px)}}devsite-var{position:relative;white-space:nowrap}devsite-var .devsite-var-input-wrapper{bottom:-2px;-moz-box-sizing:content-box;box-sizing:content-box;display:none;left:-4px;position:absolute;width:100%}devsite-var[active] .devsite-var-input-wrapper{display:inline-block}devsite-selector devsite-var .devsite-var-input-wrapper{bottom:-3px}table devsite-var .devsite-var-input-wrapper{bottom:-3px}devsite-code devsite-var .devsite-var-input-wrapper{bottom:-2px}devsite-var .devsite-var-input-wrapper+var{border-bottom:1px dotted var(--devsite-var-color);cursor:pointer}devsite-var input.devsite-var-input{border:1px solid #80868b;font-family:inherit;font-size:inherit;padding:1px 3px 0;width:inherit}devsite-var input.devsite-var-input:focus{border-bottom:1px solid #80868b;padding-bottom:0}devsite-var button.devsite-icon-edit{color:var(--devsite-var-color);margin:0 0 2px 5px}devsite-var .material-icons.devsite-icon-edit{vertical-align:middle}devsite-var .devsite-icon-close{bottom:0;position:absolute;right:-4px;top:0}devsite-var .devsite-icon-close,devsite-var .devsite-icon-close:hover{color:#202124}devsite-var .devsite-var-wrapper .material-icons{background:none;border:none;font-size:inherit;height:inherit;min-width:inherit;padding:0}devsite-var .devsite-var-wrapper .material-icons:active{box-shadow:none}devsite-var .devsite-var-wrapper .material-icons:hover{cursor:pointer}devsite-version-selector{display:block;padding:0 24px}devsite-version-selector .devsite-version-selector-select{width:100%}.devsite-future-version,.devsite-future-version *{color:var(--devsite-tertiary-text-rgba);text-decoration:none}devsite-video{aspect-ratio:16/9;display:block;overflow:hidden;position:relative;width:100%}devsite-video .devsite-video-placeholder img,devsite-video .devsite-video-placeholder span,devsite-video iframe{position:absolute}devsite-video iframe{height:101%;left:-.5%;top:-.5%;width:101%}devsite-video .devsite-video-placeholder span{color:var(--devsite-primary-text-color);padding:8px}devsite-video .devsite-basic-video-player{border:0;height:100%;position:absolute;width:100%}.devsite-view-release-notes-dialog-container{height:80%;width:720px}.view-notes-link{display:block;margin-bottom:10px}devsite-view-release-notes-dialog{color:#000;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-moz-box-orient:vertical;-moz-box-direction:normal;-ms-flex-direction:column;flex-direction:column;height:100%;padding:15px}[appearance=dark] devsite-view-release-notes-dialog{color:#fff}devsite-view-release-notes-dialog .devsite-dialog-header{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-webkit-justify-content:space-between;-moz-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;margin-bottom:10px}devsite-view-release-notes-dialog .devsite-dialog-header .title{text-align:initial}devsite-view-release-notes-dialog .devsite-dialog-header devsite-dropdown-list{-webkit-align-self:end;-ms-flex-item-align:end;align-self:end;border:var(--devsite-primary-border);border-radius:5px;height:-webkit-min-content;height:-moz-min-content;height:min-content;font-weight:500;--devsite-bookmark-icon-arrow-color:#5f6368;--devsite-button-width:144px;--devsite-dropdown-list-border-radius:2px;--devsite-dropdown-list-toggle-border-radius:4px;--devsite-dropdown-list-min-width:144px;--devsite-dropdown-list-toggle-background-hover:var(--devsite-background-3);--devsite-dropdown-list-toogle-button-justify-content:space-between;--devsite-dropdown-list-toggle-button-padding:8px 16px}devsite-view-release-notes-dialog .devsite-dialog-header .chip-wrapper{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;gap:4px}devsite-view-release-notes-dialog .devsite-dialog-header .selected-date-toggle{color:#1a73e8;line-height:10px;margin:0;margin-right:8px}[appearance=dark] devsite-view-release-notes-dialog .devsite-dialog-header .selected-date-toggle{color:#8ab4f8}devsite-view-release-notes-dialog .devsite-dialog-contents{border:var(--devsite-primary-border);-webkit-box-flex:1;-webkit-flex-grow:1;-moz-box-flex:1;-ms-flex-positive:1;flex-grow:1;overflow-y:scroll}devsite-view-release-notes-dialog .devsite-dialog-contents .release-note-date-section{margin-bottom:24px}devsite-view-release-notes-dialog .devsite-dialog-contents .release-note-date-section .release-note-date-header{text-align:left;font-size:18px;margin-bottom:12px;margin-top:0}devsite-view-release-notes-dialog .devsite-dialog-contents .release-note-date-section .release-note{-webkit-box-align:baseline;-webkit-align-items:baseline;-moz-box-align:baseline;-ms-flex-align:baseline;align-items:baseline;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex}devsite-view-release-notes-dialog .devsite-dialog-contents .release-note .release-note-content{color:#000;padding:0 8px}[appearance=dark] devsite-view-release-notes-dialog .devsite-dialog-contents .release-note .release-note-content{color:#fff}devsite-view-release-notes-dialog .release-note-type-chip{border-radius:20px;font-weight:700}devsite-view-release-notes-dialog .release-note-type-chip.large{font-size:12px;padding:4px 14px}devsite-view-release-notes-dialog .release-note-type-chip.large.green{background:#137333;color:#fff}devsite-view-release-notes-dialog .release-note-type-chip.large.yellow{background:#ea8600;color:#fff}devsite-view-release-notes-dialog .release-note-type-chip.large.blue{background:#185abc;color:#fff}devsite-view-release-notes-dialog .release-note-type-chip.large.red{background:#b31412;color:#fff}devsite-view-release-notes-dialog .release-note-type-chip.large.orange{background:#c26401;color:#fff}devsite-view-release-notes-dialog .release-note-type-chip.large.grey{background:#3c4043;color:#fff}devsite-view-release-notes-dialog .release-note-type-chip.small{font-size:12px;padding:0 8px}devsite-view-release-notes-dialog .release-note-type-chip.small.green{background:#e6f4ea;color:#137333}devsite-view-release-notes-dialog .release-note-type-chip.small.yellow{background:#fef7e0;color:#ea8600}devsite-view-release-notes-dialog .release-note-type-chip.small.blue{background:#e8f0fe;color:#185abc}devsite-view-release-notes-dialog .release-note-type-chip.small.red{background:#fce8e6;color:#b31412}devsite-view-release-notes-dialog .release-note-type-chip.small.orange{background:#feefe3;color:#c26401}devsite-view-release-notes-dialog .release-note-type-chip.small.grey{background:#f8f9fa;color:#3c4043}devsite-view-release-notes-dialog .devsite-dialog-footer{padding:10px 0 0}devsite-view-release-notes-dialog .devsite-dialog-footer .devsite-dialog-close{color:#1e88e5}devsite-visibility-analytics[counterfactual]{display:block;height:1px;opacity:0}devsite-visibility-analytics[counterfactual] *{display:none}devsite-vplus .devsite-vplus-content-container{border:1px solid #000;height:0;padding-bottom:56.25%;position:relative;visibility:hidden}devsite-vplus .devsite-vplus-slide-frame{height:100%;left:0;overflow:auto;position:absolute;top:0;width:100%}devsite-vplus .devsite-vplus-video{bottom:0;height:26%;position:absolute;right:0;-webkit-transition:width 1.3s ease,height 1.3s ease,position 1.3s ease;transition:width 1.3s ease,height 1.3s ease,position 1.3s ease;width:26%;z-index:1}devsite-vplus .devsite-vplus-video.devsite-vplus-large{height:100%;width:100%}devsite-vplus .devsite-vplus-video-container{bottom:0;cursor:pointer;height:26%;position:absolute;right:0;-webkit-transition:width 1.3s ease,height 1.3s ease,position 1.3s ease;transition:width 1.3s ease,height 1.3s ease,position 1.3s ease;width:26%;z-index:1}devsite-vplus .devsite-vplus-video-container.devsite-vplus-large{height:100%;width:100%}devsite-vplus .devsite-vplus-video-container>video{width:100%}@media (max-width:1049px){#video-caption-container span{font-size:1.9vw}}@media (min-width:1050px){#video-caption-container span{font-size:1.1vw}}devsite-vplus .devsite-vplus-controls{background-color:#fff;border-radius:6px;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;height:100%;margin:0 auto;max-width:490px;padding:6px;text-align:center}devsite-vplus .devsite-vplus-controls-text{font-size:16px;font-style:normal;font-weight:700}devsite-vplus .devsite-vplus-slide-status{margin:auto}devsite-vplus .devsite-vplus-slide-status span{font-size:18px}devsite-vplus .devsite-vplus-slide-status span:not(:first-of-type){padding-left:5px}devsite-vplus .devsite-vplus-player-controls{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;margin:8px 16px}devsite-vplus .devsite-vplus-control-button{cursor:pointer;box-shadow:none;height:43px;padding-top:0;width:50px}devsite-vplus .devsite-vplus-control-button:hover{box-shadow:0 2px 4px #aaa;border-radius:4px}devsite-vplus .devsite-vplus-video-controls-container{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex}devsite-vplus .devsite-vplus-play-icon{margin-left:0}devsite-vplus .devsite-vplus-pause-icon{margin-left:0}devsite-vplus .devsite-vplus-play-button{padding-left:0;margin-left:16px;width:50px}devsite-vplus .devsite-vplus-next-button{padding-left:0;margin-left:16px;width:50px}devsite-vplus .devsite-vplus-triangle{border-style:solid;height:0;margin:auto;position:relative;width:0}devsite-vplus .devsite-vplus-back{border-color:transparent #24508d transparent transparent;border-width:8px 16px 8px 0}devsite-vplus .devsite-vplus-back-triangle-1{left:-8px;top:15px}devsite-vplus .devsite-vplus-back-triangle-2{left:8px;top:-1px}devsite-vplus .devsite-vplus-forward-single{border-color:transparent transparent transparent #24508d;border-width:16px 0 16px 25px;top:5px}devsite-vplus .devsite-vplus-forward{border-color:transparent transparent transparent #24508d;border-width:8px 0 8px 16px;top:5px}devsite-vplus .devsite-vplus-forward-triangle-1{left:-8px;top:15px}devsite-vplus .devsite-vplus-forward-triangle-2{left:8px;top:-1px}devsite-vplus .devsite-vplus-pause{background-color:#24508d;height:30px;width:9px}devsite-vplus .devsite-vplus-rect-1{left:12px;position:relative;top:6px}devsite-vplus .devsite-vplus-rect-2{left:29px;position:relative;top:-24px}devsite-vplus .devsite-vplus-playbackrate select:hover{box-shadow:0 2px 4px #aaa}devsite-vplus .devsite-vplus-playbackrate .material-icons{margin-top:10px}devsite-vplus .devsite-vplus-playbackrate select{border-color:transparent;font-size:18px;height:46px;padding-bottom:2px;padding-top:2px;-moz-text-align-last:center;text-align-last:center;text-transform:none}devsite-vplus .devsite-vplus-caption-control-container{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;margin-top:8px}devsite-vplus .devsite-vplus-caption-control{background-color:#24508d;border:0;border-radius:16px;color:var(--devsite-inverted-text-color);display:inline-block;height:35px;line-height:39px;margin-right:10px;margin-top:1px;padding:0;text-align:center;text-decoration:none;text-indent:0;vertical-align:10%;width:50px}devsite-vplus .devsite-vplus-captions-off{background-color:#fff;color:#24508d}devsite-vplus .devsite-vplus-controls .devsite-vplus-control-button.disabled{background-color:transparent}devsite-vplus .devsite-vplus-prev-button.disabled .devsite-vplus-triangle{border-right-color:#94969a}devsite-vplus .devsite-vplus-prev-button:hover:not(.disabled) .devsite-vplus-triangle{border-right-color:#18345c}devsite-vplus .devsite-vplus-next-button:hover:not(.disabled) .devsite-vplus-triangle{border-right-color:#18345c}devsite-vplus .devsite-vplus-next-button.disabled .devsite-vplus-triangle{border-left-color:#94969a}.next-button:hover:not(.disabled) .devsite-vplus-triangle,devsite-vplus .devsite-vplus-play-button:hover:not(.disabled) .devsite-vplus-triangle{border-left-color:#18345c}devsite-vplus .devsite-vplus-navigation-button-container{margin:0 auto;text-align:center}devsite-vplus .devsite-vplus-navigation-button-link{text-decoration:none}devsite-vplus .devsite-vplus-navigation-button{background-color:#24508d;box-shadow:0 1px 3px rgba(0,0,0,.12),0 1px 2px rgba(0,0,0,.24);color:var(--devsite-inverted-text-color);display:inline-block;font-size:16px;margin:12px 36px;padding:12px 36px}devsite-vplus .devsite-vplus-addendums{border-top:0;border:1px solid #000;cursor:pointer}devsite-vplus .devsite-vplus-addendums-header{background-color:var(--devsite-background-5);outline:none;padding:8px 8px 8px 0;width:100%}devsite-vplus .devsite-vplus-addendums-control{cursor:pointer;display:table-cell;vertical-align:middle}devsite-vplus .devsite-vplus-addendums-control .material-icons.devsite-vplus-caption-button{cursor:pointer}devsite-vplus .devsite-vplus-addendums-control>div{white-space:nowrap;margin-left:8px;margin-right:8px}devsite-vplus .devsite-vplus select{outline:2px}devsite-vplus .devsite-vplus select:hover,devsite-vplus .devsite-vplus-notes-control>div>div:hover,devsite-vplus .devsite-vplus-transcript-control>div>div:hover{box-shadow:0 2px 4px #aaa;background-color:#e1f3fc}devsite-vplus .devsite-vplus select:focus{background-color:#e1f3fc}devsite-vplus .devsite-vplus-addendums-control.devsite-vplus-search-widget>div{margin-left:0;margin-right:0}devsite-vplus .devsite-vplus-addendums-label{white-space:nowrap}devsite-vplus .devsite-vplus-addendums-control .devsite-hidden{display:none}devsite-vplus .devsite-vplus-notes-control .devsite-vplus-addendums-closed,devsite-vplus .devsite-vplus-notes-control .devsite-vplus-addendums-opened,devsite-vplus .devsite-vplus-transcript-control .devsite-vplus-addendums-closed,devsite-vplus .devsite-vplus-transcript-control .devsite-vplus-addendums-opened{display:none}devsite-vplus .devsite-vplus-notes-control.goog-zippy-collapsed .devsite-vplus-addendums-closed,devsite-vplus .devsite-vplus-notes-control.goog-zippy-expanded .devsite-vplus-addendums-opened,devsite-vplus .devsite-vplus-transcript-control.goog-zippy-collapsed .devsite-vplus-addendums-closed,devsite-vplus .devsite-vplus-transcript-control.goog-zippy-expanded .devsite-vplus-addendums-opened{display:inline}devsite-vplus .devsite-vplus-search-widget{background:var(--devsite-background-3);padding:2px 4px;position:relative;width:100%}devsite-vplus .devsite-vplus-search-widget>div{width:100%}devsite-vplus .devsite-vplus-search-input{background-color:transparent;border-width:0;font-size:14px;width:100%}devsite-vplus .devsite-vplus-search-input:hover{box-shadow:0 2px 4px #aaa}devsite-vplus .devsite-vplus-search-autocomplete{position:relative;white-space:normal;width:100%;z-index:1}devsite-vplus .devsite-vplus-search-autocomplete .ac-renderer{background:var(--devsite-background-1);border:1px solid var(--devsite-secondary-text-color);box-shadow:2px 2px 2px hsla(0,0%,40%,.4);font:normal 13px Arial,sans-serif;position:absolute;width:100%}devsite-vplus .devsite-vplus-search-autocomplete .ac-row{cursor:pointer;padding:6px}devsite-vplus .devsite-vplus-search-autocomplete .ac-highlighted{font-weight:700}devsite-vplus .devsite-vplus-search-autocomplete .ac-active{background-color:#bdc1c6}devsite-vplus .devsite-vplus-addendums-control div.devsite-vplus-captions-language-selector-wrapper,devsite-vplus .devsite-vplus-addendums-control div.devsite-vplus-video-language-selector-wrapper{display:inline-block;height:auto;margin-right:2px;padding:0;vertical-align:bottom}devsite-vplus .devsite-vplus-captions-language-selector-wrapper .material-icons,devsite-vplus .devsite-vplus-video-language-selector-wrapper .material-icons{vertical-align:middle}devsite-vplus .devsite-vplus-captions-language-selector-wrapper:focus-within .material-icons,devsite-vplus .devsite-vplus-video-language-selector-wrapper:focus-within .material-icons{display:none}devsite-vplus .devsite-vplus-captions-language-selector-wrapper select,devsite-vplus .devsite-vplus-video-language-selector-wrapper select{background-color:var(--devsite-background-5);min-width:0;padding-right:16px;width:0}devsite-vplus .devsite-vplus-captions-language-selector-wrapper select:focus,devsite-vplus .devsite-vplus-video-language-selector-wrapper select:focus{outline:5px auto -webkit-focus-ring-color;padding-right:27px;width:auto}devsite-vplus .devsite-vplus-captions-language-selector-wrapper select.kd-select,devsite-vplus .devsite-vplus-video-language-selector-wrapper select.kd-select{border-color:transparent;font-size:small;height:auto;padding-bottom:2px;padding-top:2px;-moz-text-align-last:right;text-align-last:right}devsite-vplus .devsite-vplus-addendums-opened .material-icons{width:1em}devsite-vplus .devsite-vplus-addendums-closed .material-icons{background-color:#bdc1c6;color:var(--devsite-inverted-text-color);width:1em}devsite-vplus .devsite-vplus-notes{border-top:1 solid #000;height:100px;margin:0;overflow:auto;padding:16px;position:relative;resize:vertical;width:100%}devsite-vplus .devsite-vplus-transcript-captions{border-top:1 solid #000;height:4.5em;margin:0;overflow:auto;padding:0;position:relative;resize:vertical;width:100%}devsite-vplus .devsite-vplus-transcript-captions table{border-collapse:separate;margin:0}devsite-vplus .devsite-vplus-transcript-caption{padding:.15em 1em;width:100%}devsite-vplus .devsite-vplus-transcript-slide-separator{font-weight:700;font-style:italic}devsite-vplus .devsite-vplus-transcript-slide-separator hr{padding:1px 0}devsite-vplus .devsite-vplus-transcript-caption:focus{outline-offset:-3px}devsite-vplus .devsite-vplus-transcript-caption td{background-color:#fff;border-color:#fff;padding:0 .25em;text-shadow:0 0 0 currentColor}devsite-vplus .devsite-vplus-transcript-caption:hover td{text-shadow:.5px 0 .1px #5f6368,-.5px 0 .1px #5f6368}devsite-vplus .devsite-vplus-transcript-caption:hover .devsite-vplus-transcript-caption-bullet{visibility:visible}devsite-vplus .devsite-vplus-transcript-caption.devsite-vplus-caption-highlighted td{background-color:#fff176}devsite-vplus .devsite-vplus-transcript-caption .devsite-vplus-transcript-caption-bullet{padding:0 0 0 4px;visibility:hidden}devsite-vplus .devsite-vplus-transcript-caption-time{font-weight:lighter;min-width:2.5em;text-align:right}devsite-vplus .devsite-vplus-transcript-caption-text{width:100%}devsite-vplus .devsite-vplus-fullscreen-icon{color:#24508d;padding:0;text-overflow:inherit;text-transform:none}devsite-vplus .devsite-hidden{display:none}devsite-youtube{aspect-ratio:16/9;display:block;overflow:hidden;position:relative;width:100%}devsite-youtube .devsite-video-placeholder img,devsite-youtube .devsite-video-placeholder span,devsite-youtube iframe{position:absolute}devsite-youtube iframe{height:101%;left:-.5%;top:-.5%;width:101%}devsite-youtube .devsite-video-placeholder span{color:var(--devsite-primary-text-color);padding:8px}devsite-youtube .devsite-basic-video-player{border:0;height:100%;position:absolute;width:100%}body[codelabs-content-type=paginated] google-codelab{width:100%;height:100%;display:grid;grid-template:64px 1fr 56px/256px 1fr;grid-template-areas:"title title" "drawer main" "metadata main"}body[codelabs-content-type=paginated] google-codelab #main{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-moz-box-orient:vertical;-moz-box-direction:normal;-ms-flex-direction:column;flex-direction:column;grid-area:main;position:relative;background:#f8f9fa}body[codelabs-content-type=paginated] google-codelab #codelab-title{background:#fff;box-shadow:0 1px 2px 0 rgba(60,64,67,.3),0 2px 6px 2px rgba(60,64,67,.15);color:#3c4043;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;grid-area:title;-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-webkit-justify-content:space-between;-moz-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;height:64px;padding:0 36px 0 16px;-webkit-font-smoothing:antialiased;z-index:1000;max-width:100vw}body[codelabs-content-type=paginated] google-codelab #codelab-title h1{font-size:20px;font-weight:400;margin:0 8px;font-family:Roboto,Noto,sans-serif;-webkit-box-flex:1;-webkit-flex-grow:1;-moz-box-flex:1;-ms-flex-positive:1;flex-grow:1;-webkit-flex-shrink:1;-ms-flex-negative:1;flex-shrink:1;white-space:nowrap;text-overflow:ellipsis;overflow:hidden;width:0;display:inline-block}body[codelabs-content-type=paginated] google-codelab #codelab-title h1 a{color:#3c4043;text-decoration:none}body[codelabs-content-type=paginated] google-codelab #codelab-title h1 a:focus,body[codelabs-content-type=paginated] google-codelab #codelab-title h1 a:hover{color:#212121;text-decoration:underline}body[codelabs-content-type=paginated] google-codelab #codelab-title .time-remaining{-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;-webkit-box-flex:0;-webkit-flex-grow:0;-moz-box-flex:0;-ms-flex-positive:0;flex-grow:0;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;font-size:16px;font-weight:400;white-space:nowrap}body[codelabs-content-type=paginated] google-codelab #codelab-title .time-remaining i{margin-right:3px}body[codelabs-content-type=paginated] google-codelab #codelab-nav-buttons{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-flex:0;-webkit-flex-grow:0;-moz-box-flex:0;-ms-flex-positive:0;flex-grow:0;-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0}body[codelabs-content-type=paginated] google-codelab #codelab-nav-buttons #arrow-back,body[codelabs-content-type=paginated] google-codelab #codelab-nav-buttons #menu{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;text-decoration:none;color:#3c4043;width:40px;height:40px;-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center}body[codelabs-content-type=paginated] google-codelab #controls{position:absolute;bottom:32px;left:0;right:0;padding:0 32px;z-index:1001}body[codelabs-content-type=paginated] google-codelab #fabs{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-webkit-justify-content:space-between;-moz-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;margin:0 auto;max-width:1025px}body[codelabs-content-type=paginated] google-codelab #done,body[codelabs-content-type=paginated] google-codelab #next-step,body[codelabs-content-type=paginated] google-codelab #previous-step{border-radius:4px;font-family:Google Sans,Arial,sans-serif;font-size:14px;font-weight:600;letter-spacing:.6px;line-height:24px;padding-bottom:6px;padding-left:24px;padding-right:24px;padding-top:6px;pointer-events:auto;text-transform:none;background:#fff;color:#1a73e8;-webkit-transform:scale(1);transform:scale(1);-webkit-transition:-webkit-transform .3s ease-in-out;transition:-webkit-transform .3s ease-in-out;transition:transform .3s ease-in-out;transition:transform .3s ease-in-out,-webkit-transform .3s ease-in-out;box-shadow:0 2px 2px 0 rgba(0,0,0,.14),0 1px 5px 0 rgba(0,0,0,.12),0 3px 1px -2px rgba(0,0,0,.2);text-decoration:none;-webkit-font-smoothing:antialiased}body[codelabs-content-type=paginated] google-codelab #next-step{color:#fff;background:#1a73e8}body[codelabs-content-type=paginated] google-codelab #done{background:#1e8e3e;color:#fff}body[codelabs-content-type=paginated] google-codelab #fabs a[disappear]{-webkit-transform:scale(0);transform:scale(0)}body[codelabs-content-type=paginated] google-codelab #done{background:#0f9d58}body[codelabs-content-type=paginated] google-codelab #drawer .codelab-time-container{display:none}body[codelabs-content-type=paginated] google-codelab .metadata{background:#f8f9fa;color:#777;font-size:14px;grid-area:metadata;padding:16px}body[codelabs-content-type=paginated] google-codelab .metadata a{color:currentcolor;margin-left:4px}body[codelabs-content-type=paginated] google-codelab .metadata a:focus,body[codelabs-content-type=paginated] google-codelab .metadata a:hover{color:#212121}@media (max-width:768px){body[codelabs-content-type=paginated] google-codelab{grid-template:64px 1fr 56px/1fr;grid-template-areas:"title" "main" "metadata";padding-top:0}body[codelabs-content-type=paginated] google-codelab #codelab-title{padding:0 16px}body[codelabs-content-type=paginated] google-codelab #codelab-title .codelab-time-container{display:none}}body[codelabs-content-type=paginated] google-codelab #drawer{width:256px;grid-area:drawer;position:relative;z-index:100;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-moz-box-orient:vertical;-moz-box-direction:normal;-ms-flex-direction:column;flex-direction:column;background:#f8f9fa;overflow:auto}body[codelabs-content-type=paginated] google-codelab #drawer .steps{-webkit-flex-shrink:1;-ms-flex-negative:1;flex-shrink:1;-webkit-box-flex:1;-webkit-flex-grow:1;-moz-box-flex:1;-ms-flex-positive:1;flex-grow:1;overflow-x:visible;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex}body[codelabs-content-type=paginated] google-codelab #drawer .steps:only-child{max-height:100%}body[codelabs-content-type=paginated] google-codelab #drawer ol{margin:0;padding:16px 12px;counter-reset:li-count;list-style:none;overflow-x:visible;overflow-y:auto;-webkit-box-flex:1;-webkit-flex-grow:1;-moz-box-flex:1;-ms-flex-positive:1;flex-grow:1}body[codelabs-content-type=paginated] google-codelab #drawer ol li{display:block;counter-increment:li-count}body[codelabs-content-type=paginated] google-codelab #drawer ol li a{text-decoration:none;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;font-size:14px;color:#80868b;padding:3px 10px;min-height:48px;font-weight:400;line-height:20px;-moz-box-sizing:content-box;box-sizing:content-box;position:relative;font-family:Roboto,Noto,sans-serif;-webkit-font-smoothing:antialiased;-webkit-transition:all .3s ease-in-out;transition:all .3s ease-in-out;border:1px solid #dadce0;border-radius:5px;margin:6px 0;background:#fff}body[codelabs-content-type=paginated] google-codelab #drawer ol li a:active,body[codelabs-content-type=paginated] google-codelab #drawer ol li a:focus{background:#c6c6c6;-webkit-tap-highlight-color:transparent;outline:0;border-color:#c6c6c6!important}body[codelabs-content-type=paginated] google-codelab #drawer ol li a .step{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center}body[codelabs-content-type=paginated] google-codelab #drawer ol li .step:before{content:counter(li-count);display:inline-block;font-style:normal;width:26px;min-width:26px;color:#fff;background:#80868b;border-radius:50%;text-align:center;height:26px;vertical-align:middle;line-height:26px;margin-right:8px;font-weight:400;position:relative;z-index:2;-webkit-transition:all .3s ease-in-out;transition:all .3s ease-in-out}body[codelabs-content-type=paginated] google-codelab #drawer ol li a:focus,body[codelabs-content-type=paginated] google-codelab #drawer ol li[selected] a{color:#212121;font-weight:600;box-shadow:0 1px 2px 0 rgba(60,64,67,.3),0 2px 6px 2px rgba(60,64,67,.15)}body[codelabs-content-type=paginated] google-codelab #drawer ol li[selected] a{border-color:#fff}body[codelabs-content-type=paginated] google-codelab #drawer ol li[selected] .step:before{font-weight:600}body[codelabs-content-type=paginated] google-codelab #drawer ol li[completed] a{color:#212121}body[codelabs-content-type=paginated] google-codelab #drawer ol li[completed] .step:before{background-color:#1a73e8;color:#fff}body[codelabs-content-type=paginated] google-codelab #codelab-nav-buttons #menu{display:none}body[codelabs-content-type=paginated] google-codelab #drawer ol ::-webkit-scrollbar{-webkit-appearance:none;width:7px}body[codelabs-content-type=paginated] google-codelab #drawer ol ::-webkit-scrollbar-thumb{border-radius:4px;background-color:rgba(0,0,0,.5);-webkit-box-shadow:0 0 1px hsla(0,0%,100%,.5)}@media (max-width:768px){body[codelabs-content-type=paginated] google-codelab #codelab-nav-buttons #arrow-back{display:none}body[codelabs-content-type=paginated] google-codelab #codelab-nav-buttons #menu{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex}body[codelabs-content-type=paginated] google-codelab #drawer{grid-area:auto;width:256px;position:absolute;left:0;top:0;bottom:0;z-index:10000;will-change:transform;box-shadow:2px 2px 4px transparent;pointer-events:none;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0);-webkit-transition:box-shadow .3s,-webkit-transform .3s ease-in-out;transition:box-shadow .3s,-webkit-transform .3s ease-in-out;transition:transform .3s ease-in-out,box-shadow .3s;transition:transform .3s ease-in-out,box-shadow .3s,-webkit-transform .3s ease-in-out}body[codelabs-content-type=paginated] google-codelab[drawer--open] #drawer{box-shadow:2px 2px 4px rgba(0,0,0,.15);-webkit-transform:translateZ(0);transform:translateZ(0);pointer-events:all}body[codelabs-content-type=paginated] google-codelab #main:before{content:"";top:0;left:0;right:0;bottom:0;position:absolute;-webkit-transition:opacity .38s ease-in-out;transition:opacity .38s ease-in-out;background-color:rgba(0,0,0,.3);z-index:10;pointer-events:none;opacity:0}body[codelabs-content-type=paginated] google-codelab[drawer--open] #main:before{opacity:1;pointer-events:all}body[codelabs-content-type=paginated] google-codelab #drawer .codelab-time-container{display:block;padding:20px 10px 10px 23px}body[codelabs-content-type=paginated] google-codelab #drawer .time-remaining i{margin-right:9px}}body[codelabs-content-type=paginated] google-codelab #steps{overflow:hidden;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-moz-box-orient:vertical;-moz-box-direction:normal;-ms-flex-direction:column;flex-direction:column;position:relative;-webkit-box-flex:1;-webkit-flex-grow:1;-moz-box-flex:1;-ms-flex-positive:1;flex-grow:1}body[codelabs-content-type=paginated] google-codelab google-codelab-step{display:none;width:100%;-webkit-transform:translateZ(0);transform:translateZ(0);position:absolute;top:0;left:0;right:0;bottom:0;padding-top:32px;overflow-y:auto;overflow-x:hidden}body[codelabs-content-type=paginated] google-codelab google-codelab-step[animating],body[codelabs-content-type=paginated] google-codelab google-codelab-step[selected]{display:block;-webkit-transform-origin:0 50% 0;transform-origin:0 50% 0;-webkit-animation-fill-mode:both;animation-fill-mode:both}body[codelabs-content-type=paginated] google-codelab google-codelab-step[animating]{pointer-events:none;position:absolute;overflow:hidden}@media (max-width:768px){body[codelabs-content-type=paginated] google-codelab google-codelab-step{padding-top:8px}}body[codelabs-content-type=paginated] google-codelab #drawer ol li{padding:0;margin:0}body[codelabs-content-type=paginated] google-codelab{bottom:0;left:0;position:fixed;top:0}body[codelabs-content-type=paginated] google-codelab #codelab-title h1{width:auto;color:#3c4043;top:0}body[codelabs-content-type=paginated] google-codelab .title{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-flex:1;-webkit-flex-grow:1;-moz-box-flex:1;-ms-flex-positive:1;flex-grow:1;margin-left:10px;overflow:hidden}body[codelabs-content-type=paginated] google-codelab .no-return-url{display:none!important}body[codelabs-content-type=paginated] google-codelab #drawer .metadata .material-icons,body[codelabs-content-type=paginated] google-codelab-about .about-card .material-icons{top:0!important}body[codelabs-content-type=paginated] body[template=codelab] devsite-footer-utility .devsite-footer-utility-button>a,body[codelabs-content-type=paginated] google-codelab .button-blue,body[codelabs-content-type=paginated] google-codelab .button-green,body[codelabs-content-type=paginated] google-codelab .button-primary,body[codelabs-content-type=paginated] google-codelab .button-red{color:#fff!important}body[codelabs-content-type=paginated] google-codelab #codelab-title devsite-language-selector{margin:0 16px}body[codelabs-content-type=paginated] google-codelab #controls devsite-language-selector{background:var(--devsite-background-1);display:none}@media screen and (max-width:840px){body[codelabs-content-type=paginated] google-codelab #codelab-title devsite-language-selector{margin:0 8px}}@media screen and (max-width:600px){body[codelabs-content-type=paginated] google-codelab #codelab-title devsite-language-selector{display:none}body[codelabs-content-type=paginated] google-codelab #controls devsite-language-selector{display:block}body[codelabs-content-type=paginated] google-codelab #main #controls{padding:0 8px}body[codelabs-content-type=paginated] google-codelab #controls .spacer{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;-ms-flex-pack:center;justify-content:center}}body[codelabs-content-type=paginated]{color:#5c5c5c;font-family:var(--devsite-primary-font-family);overflow:hidden}body[codelabs-content-type=paginated] google-codelab{opacity:0}body[codelabs-content-type=paginated] devsite-googler-buttons{bottom:148px}body[codelabs-content-type=paginated][ready] google-codelab{opacity:1}body[codelabs-content-type=paginated] .devsite-main-content{max-width:100%!important;padding:0!important}body[codelabs-content-type=paginated] a:focus{text-decoration:none}body[codelabs-content-type=paginated] .devsite-badger-award{left:256px}body[codelabs-content-type=paginated] .devsite-back-to-top-link,body[codelabs-content-type=paginated] .devsite-banner,body[codelabs-content-type=paginated] .devsite-book-nav-bg,body[codelabs-content-type=paginated] .devsite-book-nav-bg[fixed],body[codelabs-content-type=paginated] .devsite-book-nav-blur,body[codelabs-content-type=paginated] .devsite-book-nav-toggle,body[codelabs-content-type=paginated] .devsite-footer,body[codelabs-content-type=paginated] .devsite-heading-link,body[codelabs-content-type=paginated] .devsite-page-bookmark-tooltip,body[codelabs-content-type=paginated] .devsite-page-title,body[codelabs-content-type=paginated] .devsite-sidebar,body[codelabs-content-type=paginated] devsite-book-nav,body[codelabs-content-type=paginated] devsite-bookmark,body[codelabs-content-type=paginated] devsite-header{display:none}body[codelabs-content-type=paginated] devsite-code:after{display:none}body[codelabs-content-type=paginated] devsite-user[signed-in][enable-profiles]{min-width:44px}body[codelabs-content-type=scrolling][type=codelab] .devsite-sidebar[fixed] .devsite-sidebar-content{-webkit-padding-start:0;-moz-padding-start:0;padding-inline-start:0}body[codelabs-content-type=scrolling][type=codelab] .devsite-sidebar[fixed] devsite-toc{-webkit-padding-end:8px;-moz-padding-end:8px;padding-inline-end:8px}body[codelabs-content-type=scrolling][type=codelab] devsite-toc .devsite-nav-show-all{margin:0}body[codelabs-content-type=scrolling][type=codelab] devsite-toc .devsite-nav-more-items{-webkit-margin-after:0;margin-block-end:0}body[codelabs-content-type=scrolling][type=codelab] devsite-toc>.devsite-nav-list,body[codelabs-content-type=scrolling][type=codelab] devsite-toc[fixed]>.devsite-nav-list{border:0;counter-reset:steps;padding:0}body[codelabs-content-type=scrolling][type=codelab] devsite-toc .devsite-nav-item{-webkit-margin-after:8px;margin-block-end:8px;-webkit-margin-start:2px;-moz-margin-start:2px;margin-inline-start:2px}body[codelabs-content-type=scrolling][type=codelab] .devsite-toc-toggle,body[codelabs-content-type=scrolling][type=codelab] devsite-toc .devsite-nav-item:last-child>a{padding:12px 8px}body[codelabs-content-type=scrolling][type=codelab] devsite-toc .devsite-nav-item>a{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;background:var(--devsite-background-1);border-radius:4px;color:var(--devsite-secondary-text-color);display:grid;font-family:var(--devsite-headline-font-family);font-size:14px;grid-gap:0 8px;grid-template-columns:26px 1fr;padding:12px 8px;border:var(--devsite-primary-border);box-shadow:none}body[codelabs-content-type=scrolling][type=codelab] devsite-toc .devsite-nav-item[completed]>a{color:var(--devsite-primary-text-color)}body[codelabs-content-type=scrolling][type=codelab] devsite-toc .devsite-nav-item>a:before{background:var(--devsite-tertiary-text-color);border-radius:100%;color:var(--devsite-inverted-text-color);content:counter(steps);counter-increment:steps;height:26px;line-height:26px;text-align:center;width:26px}body[codelabs-content-type=scrolling][type=codelab] devsite-toc .devsite-nav-text{color:var(--devsite-primary-text-color)}body[codelabs-content-type=scrolling][type=codelab] devsite-toc .devsite-nav-active.devsite-nav-title{border:0;box-shadow:0 1px 2px 0 var(--devsite-elevation-key-shadow-color),0 1px 3px 1px var(--devsite-elevation-ambient-shadow-color)}body[codelabs-content-type=scrolling][type=codelab] devsite-toc .devsite-nav-active.devsite-nav-title,body[codelabs-content-type=scrolling][type=codelab] devsite-toc .devsite-nav-active.devsite-nav-title:focus,body[codelabs-content-type=scrolling][type=codelab] devsite-toc .devsite-nav-active.devsite-nav-title:hover{color:var(--devsite-primary-text-color)}body[codelabs-content-type=scrolling][type=codelab] devsite-toc .devsite-nav-active.devsite-nav-title:before,body[codelabs-content-type=scrolling][type=codelab] devsite-toc .devsite-nav-item[completed]>a:before{background:var(--devsite-link-color)}body[codelabs-content-type=scrolling][type=codelab] .codelab-banner{background-color:var(--devsite-background-2);color:var(--devsite-button-color);font:500 14px/36px var(--devsite-primary-font-family);line-height:24px}body[codelabs-content-type=scrolling][type=codelab] .codelab-banner .devsite-banner-message{padding:16px 40px}body[codelabs-content-type=scrolling] .devsite-banner :link,body[codelabs-content-type=scrolling] .devsite-banner :visited{text-decoration:underline}body[codelabs-content-type=scrolling][type=codelab] .codelab-banner :link,body[codelabs-content-type=scrolling][type=codelab] .codelab-banner :visited{color:var(--devsite-button-color);overflow:hidden;text-decoration:none;text-overflow:ellipsis;white-space:nowrap}body[codelabs-content-type=scrolling][type=codelab] .codelab-banner .material-icons{color:var(--devsite-button-color);margin:0;vertical-align:bottom}body[codelabs-content-type=scrolling][type=codelab] .devsite-nav-item.devsite-toc-toggle{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;-webkit-margin-after:0;margin-block-end:0}body[codelabs-content-type=scrolling][type=codelab] .devsite-toc-toggle .devsite-nav-title{padding:0}body[codelabs-content-type=scrolling][type=codelab] devsite-toc:not(.devsite-toc-embedded) .devsite-toc-toggle:before{color:var(--devsite-secondary-text-color);content:"schedule";-webkit-margin-end:8px;-moz-margin-end:8px;margin-inline-end:8px;font:normal normal normal 24px/1 Material Icons;-webkit-font-feature-settings:"liga";-moz-font-feature-settings:"liga";font-feature-settings:"liga";-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;text-transform:none;word-wrap:normal}body[codelabs-content-type=scrolling][type=codelab] h3>.devsite-heading>a[href*=github],body[codelabs-content-type=scrolling][type=codelab] h3>.devsite-heading>a[href*=github]:visited{color:#000;text-decoration:none;padding-left:24px;background-repeat:no-repeat;background-size:18px;background-image:url(data:image/png;base64,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)}body[codelabs-content-type=scrolling][type=codelab] .faq a[href*="cloud.google.com"]{padding-left:22px;background-size:20px;background-repeat:no-repeat;background-image:url(data:image/png;base64,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)}body[codelabs-content-type=scrolling][type=codelab] .faq a[href*="stackoverflow.com"]{padding-left:22px;background-size:24px;background-repeat:no-repeat;background-image:url(data:image/png;base64,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)}body[codelabs-content-type=scrolling][type=codelab] .faq a[href*="support.google.com/webmasters/"]{padding-left:24px;background-size:24px;background-repeat:no-repeat;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAMAAAD04JH5AAAAolBMVEUAAADW1tbW1tZ6enrQ0dJ6enrMzMzq6+zq6+x6enru7+/m5+ju7+/m5+j////S09REi/XW1tbm5+ju7+9PT0/Q0dK8vLxGjfVZWVlNTU16enrMzMzIyMj09PS/0uuSkpJpaWmbm5tim/e0tLSEhIStx+3e3+GsrKxwcHBZk/dPk/R1p/KPtu/U3eqmpqZlZWVfmO5woeqHreWvwN6nu9qLi4vZSE73AAAADnRSTlMAEcxmzO7MzDMz7u6IiHn/rpYAAALMSURBVHja7dXpjtowFIZhUkqZlSV1ncQdEsK+zD7T+7+1xjTiwxVOAmeORyP5+2UspPchEtDy8/Pz8/Pz8/M7cZeduHKdyxbL0FfVAMUraHdUHUB12i22tZWqBRSDgKFfC4CApV8PgIClXw/gE6hyTd/lAR7gAV8fEHwbWtc/ul/WfQ8IfQKAIECfCoCA3sdq+nQB+nQABIQ+CQABtY9Z+lQB+gwACBj6AFAE6DM9AL0fAalPB/yGgNAfntwHAAJKnwCAwNLneQAAVAvM/ttzVLlB4z2/A6AFVoDRf43IfewVgGKNAG/Uvrl39BsCXqh9cy8nA/51tmk63+jDZp6m9wTA4DzANiyW6lOqTxAMHAD22XASReuwpKDvELCNookBGJwx9E8B3OvsQp8e9GmOviNANA/Dh4k+TApBukHfFSBa7/I7whqf3xWA/gOAoU8DDJwBCHk+wIAw9CsAPw/W++CFB/MAD/hCgL59PXPS8toRYKHEndkTauEQIIUQ0hToG2eAXOicKdBXmSPAo9CTpkDo5U4Ad6IEGILy0gFgFJctCACIh/yATABwIChvVyE3IBR7AAQAiOmIGZADAMEBQMkRL+AJAAgOALGUI07AQgBgCPb3uRbwAaYAGAIAZlIL2AA5AIYAgJXUAjaAAsAQADCWO4EjAAQGQAvYAUsDsDQAeuwAMZvu89PZ/jZhBmQCi2dl60+MPiMAf8UgZEUpK/LoJ4oX0C9LIIyF0U8yXkBPVCzRWzIDZjX9sWQG9Kv7ScYN6KnKfizZAf2qfpLzA3p5RV9JboDeytp/kk4Ao5WtP+UFQKCO9sdTSQQ03+OR/kxKdgAWZv/11VI6AWBmP5HSNQD5zwQknwxIqIBu468hBgDqNYCuFXBDASSNAbdWQHB1PiBpDLgOWtZdXPEDri/QswjYAOjbF9x0OQHd26Dl5+fn5+fn5+dn7i/3LEaKJNV/0wAAAABJRU5ErkJggg==)}body[codelabs-content-type=scrolling][type=codelab] .faq a[href*="developer.android.com"],body[codelabs-content-type=scrolling][type=codelab] .faq a[href*=android-developer]{padding-left:20px;background-repeat:no-repeat;background-size:20px;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAAq1BMVEX///+lyjmfxyGhyCqkyjakyTP+/vuiyS7z+OWlyjKgxyTX57ChyCfa6bTx9uLy9+Sz0l6szk/D24Tt9NrN4ZnK4JSiyCyexh34+/D6/PTp8dPh7cjf7L7k78vc6rnW5qzU5ajS5KPP4p+21GWnzD3F3Yi813Kx0ViqzUWexhr8/vjv9d7Z6LKy0lyZxADh7cLA2n2rzkr1+erJ35C61m6uz1KcxRHn8M6/2XgEePWtAAACr0lEQVRo3u3Z2XKiQBiG4Y9ebNO2aCCyzOC+7zH7/V/ZRJZQZaJpWnKS4TlJUItXbX4pFJXK71DTusvccI6z5oMSAutdhDP2uzpK4CxwxsRBGYJdA19qLAOU4s4LkyUN7G4Ude2glmzuRihHKDqAPZhNuJRKSckms37rvctrKMnG728l5cxKMU7JuCF7KEvf87h1gnu0iXK4B2p9Sc3dUgZNMusMLvu42r20LiBXT8JMWRepN1xlGu+fK8/6xFPxwsvH697/eP/j7uDTOvB+dxwX/AaM2SQ+6icrYHDyGmgfWE3irNeCqTaPAwcArydroboAbuMAb8NQRNJn20SYtHK8HaKZzoffhZl5tlNxsD5PsnUQ2b9jwwnO35WvRo3lN/o2TDwKS5M3gokF0w2wZxgIlpY2FpgsgdQPkLXJQar0A/LVIDB6Idp2GxQQrJI/rbq2Voijlc5S9LZs8uYCqBVyXLTZhLW/fSn3hDMmZAQ05I020gT2PmeM+w4uGpLksFs+oEEtbaqJVnpUkz4uyebf6xQK0CY6XjoSC1xQ9/PPr4KB52zuvTrOa5EssC0auM0C0tYKtI0DqgpUgSpQBapAFfifAj90Tn5YZoGnooH8eutB56KDDosGhlTrYiTyk0epVdFAKJLn9rLHRSNfcE4tF0UDcAXlXPhDfGPtjGejEMUDCEdPY8eFHoOADvPAxiDQLBBQkUHAJfoB34UBS/9CfAETe6lZYKZft/QIFe94vicRy7tcvKOkB0PhYOo4zlNWYNvjpjOdZwU+O24OQlynK62EGCF2J9IbpIsy/P0I3CHW+Qj8qQJVoAr8VOCx3EB+YvDSwIDmXzaW4oZZseU6Lfr5aaAUPT8uyPuT33VeIpRkI5RHyRQfHEKFUj2UJuh1GjaQsxudKECl8jv8A6GtQkKSkMLrAAAAAElFTkSuQmCC)}@media screen and (max-width:840px){body[codelabs-content-type=paginated] .devsite-badger-award{left:0}body[codelabs-content-type=scrolling][type=codelab] .codelab-banner .devsite-banner-message{padding:16px 24px}}body[codelabs-content-type=paginated] google-codelab-about .codelab-title{width:100%;text-align:center;font-size:32px;margin:20px auto 30px auto;line-height:45px;max-width:700px}body[codelabs-content-type=paginated] google-codelab-about .codelab-title .token{display:inline-block;margin:0 5px}body[codelabs-content-type=paginated] google-codelab-about .about-card{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-moz-box-orient:vertical;-moz-box-direction:normal;-ms-flex-direction:column;flex-direction:column;border:1px solid #dadce0;border-radius:5px;background:#fff;max-width:800px;margin:0 auto 30px auto;padding:20px}body[codelabs-content-type=paginated] google-codelab-about .about-card h2{font-weight:500;font-weight:400!important;line-height:1em!important;margin:0!important;font-size:28px}body[codelabs-content-type=paginated] google-codelab-about .about-card>:not(:first-child){padding-top:30px}body[codelabs-content-type=paginated] google-codelab-about .about-card .material-icons{margin-right:10px;top:6px;position:relative}body[codelabs-content-type=scrolling][ready] google-codelab-about{border-radius:4px;border:var(--devsite-primary-border);border-left:solid 4px var(--google-codelab-about-active-border-color);display:block;margin-top:32px;padding:32px}body[codelabs-content-type=scrolling] google-codelab-about .caption{color:var(--devsite-primary-text-color);font:400 12px/16px var(--devsite-primary-font-family);letter-spacing:.3px;margin:0 0 24px;text-transform:uppercase}body[codelabs-content-type=scrolling] google-codelab-about .about{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex}body[codelabs-content-type=scrolling] google-codelab-about .about-item{-webkit-border-end:solid 1px var(--devsite-background-5);-moz-border-end:solid 1px var(--devsite-background-5);border-inline-end:solid 1px var(--devsite-background-5);-webkit-padding-end:16px;-moz-padding-end:16px;padding-inline-end:16px;-webkit-padding-start:16px;-moz-padding-start:16px;padding-inline-start:16px}body[codelabs-content-type=scrolling] google-codelab-about .about-item:first-child{-webkit-padding-start:0;-moz-padding-start:0;padding-inline-start:0}body[codelabs-content-type=scrolling] google-codelab-about .about-item:last-child{-webkit-border-end:0;-moz-border-end:0;border-inline-end:0;-webkit-padding-end:0;-moz-padding-end:0;padding-inline-end:0}body[codelabs-content-type=scrolling] google-codelab-about .authors,body[codelabs-content-type=scrolling] google-codelab-about .duration,body[codelabs-content-type=scrolling] google-codelab-about .last-updated{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;font:14px/20px var(--devsite-primary-font-family)}body[codelabs-content-type=scrolling] google-codelab-about .material-icons{color:var(--devsite-secondary-text-color);-webkit-margin-end:8px;-moz-margin-end:8px;margin-inline-end:8px}@media screen and (max-width:840px){body[codelabs-content-type=scrolling] google-codelab-about .about{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-moz-box-orient:vertical;-moz-box-direction:normal;-ms-flex-direction:column;flex-direction:column;gap:16px;padding:0}body[codelabs-content-type=scrolling] google-codelab-about .about-item{border:0;padding:0}}body[codelabs-content-type=paginated] google-codelab-step{line-height:24px;display:block}body[codelabs-content-type=paginated] google-codelab-step:focus{outline:none}body[codelabs-content-type=paginated] google-codelab-step code,body[codelabs-content-type=paginated] google-codelab-step pre{font-family:Source Code Pro,Helvetica,Arial;font-size:inherit;border-radius:4px;overflow-x:auto;overflow-y:visible}body[codelabs-content-type=paginated] google-codelab-step code{background-color:#e8eaed;padding:.1em .3em}body[codelabs-content-type=paginated] google-codelab-step pre{display:block;color:#fff;background-color:#28323f;padding:14px;-webkit-text-size-adjust:none;line-height:1.4}body[codelabs-content-type=paginated] google-codelab-step pre>code{padding:0;background-color:transparent}body[codelabs-content-type=paginated] google-codelab-step code em{color:#97c8f2}body[codelabs-content-type=paginated] google-codelab-step code .str,body[codelabs-content-type=paginated] google-codelab-step pre .str{color:#34a853}body[codelabs-content-type=paginated] google-codelab-step code .kwd,body[codelabs-content-type=paginated] google-codelab-step pre .kwd{color:#f538a0}body[codelabs-content-type=paginated] google-codelab-step code .com,body[codelabs-content-type=paginated] google-codelab-step pre .com{color:#bdc1c6}body[codelabs-content-type=paginated] google-codelab-step code .typ,body[codelabs-content-type=paginated] google-codelab-step pre .typ{color:#24c1e0}body[codelabs-content-type=paginated] google-codelab-step code .lit,body[codelabs-content-type=paginated] google-codelab-step pre .lit{color:#4285f4}body[codelabs-content-type=paginated] google-codelab-step code .pun,body[codelabs-content-type=paginated] google-codelab-step pre .pun{color:#f8f9fa}body[codelabs-content-type=paginated] google-codelab-step code .pln,body[codelabs-content-type=paginated] google-codelab-step pre .pln{color:#f8f9fa}body[codelabs-content-type=paginated] google-codelab-step code .tag,body[codelabs-content-type=paginated] google-codelab-step pre .tag{color:#24c1e0}body[codelabs-content-type=paginated] google-codelab-step code .atn,body[codelabs-content-type=paginated] google-codelab-step pre .atn{color:#eda912}body[codelabs-content-type=paginated] google-codelab-step code .atv,body[codelabs-content-type=paginated] google-codelab-step pre .atv{color:#34a853}body[codelabs-content-type=paginated] google-codelab-step code .dec,body[codelabs-content-type=paginated] google-codelab-step pre .dec{color:#5195ea}body[codelabs-content-type=paginated] google-codelab-step paper-button{display:-webkit-inline-box;display:-webkit-inline-flex;display:-moz-inline-box;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;-ms-flex-pack:center;justify-content:center;position:relative;-moz-box-sizing:border-box;box-sizing:border-box;min-width:5.14em;margin:0 .29em;background:transparent;-webkit-tap-highlight-color:transparent;font:inherit;text-transform:uppercase;outline-width:0;border-radius:3px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;cursor:pointer;z-index:0;padding:.7em .57em;font-family:Roboto,Noto,sans-serif;-webkit-font-smoothing:antialiased;box-shadow:0 2px 2px 0 rgba(0,0,0,.14),0 1px 5px 0 rgba(0,0,0,.12),0 3px 1px -2px rgba(0,0,0,.2)}body[codelabs-content-type=paginated] google-codelab-step h2.step-title{font-family:Google Sans,Arial,sans-serif!important;font-size:28px!important;font-weight:400!important;line-height:normal!important;margin:0 0 30px!important}body[codelabs-content-type=paginated] google-codelab-step .step-title a{color:#3c4043;text-decoration:none}body[codelabs-content-type=paginated] google-codelab-step .step-title a:focus,body[codelabs-content-type=paginated] google-codelab-step .step-title a:hover{color:#212121;text-decoration:underline}body[codelabs-content-type=paginated] google-codelab:not([theme=minimal]) google-codelab-step .instructions{box-shadow:0 1px 2px 0 rgba(60,64,67,.3),0 2px 6px 2px rgba(60,64,67,.15);background:#fff;max-width:800px;font-size:14px;margin:0 auto;margin-bottom:90px;border-radius:4px}body[codelabs-content-type=paginated] google-codelab-step .instructions .inner{padding:24px}body[codelabs-content-type=paginated] google-codelab[theme=minimal] google-codelab-step .instructions .inner{padding:0 24px}@media (max-width:800px){body[codelabs-content-type=paginated] google-codelab .instructions{margin:0 0 16px 0}}body[codelabs-content-type=paginated] google-codelab:not([theme=minimal]) google-codelab-step .instructions :not(.step-title)>a,body[codelabs-content-type=paginated] google-codelab:not([theme=minimal]) google-codelab-step .instructions :not(.step-title)>a:visited{color:#1a73e8}body[codelabs-content-type=paginated] google-codelab:not([theme=minimal]) google-codelab-step .instructions h2,body[codelabs-content-type=paginated] google-codelab:not([theme=minimal]) google-codelab-step .instructions h3,body[codelabs-content-type=paginated] google-codelab:not([theme=minimal]) google-codelab-step .instructions h4{font-weight:400;margin:0}body[codelabs-content-type=paginated] google-codelab:not([theme=minimal]) google-codelab-step .instructions h2{font-weight:300;line-height:1em;font-size:22px}body[codelabs-content-type=paginated] google-codelab:not([theme=minimal]) google-codelab-step .instructions{line-height:24px}body[codelabs-content-type=paginated] google-codelab:not([theme=minimal]) google-codelab-step .instructions li{margin:.5em 0}body[codelabs-content-type=paginated] google-codelab:not([theme=minimal]) google-codelab-step .instructions h2{font-weight:500;margin:20px 0 0 0;font-size:20px}body[codelabs-content-type=paginated] google-codelab:not([theme=minimal]) google-codelab-step .instructions h3{font-size:16px;font-weight:500;margin:20px 0 0 0}body[codelabs-content-type=paginated] google-codelab:not([theme=minimal]) google-codelab-step .instructions aside{padding:.5em 1em;margin:2em 0;border-left:4px solid;border-radius:4px}body[codelabs-content-type=paginated] google-codelab:not([theme=minimal]) google-codelab-step .instructions aside p{margin:.5em 0}body[codelabs-content-type=paginated] google-codelab:not([theme=minimal]) google-codelab-step .instructions aside.note,body[codelabs-content-type=paginated] google-codelab:not([theme=minimal]) google-codelab-step .instructions aside.notice{border-color:#ea8600;background:#fef7e0;color:#212124}body[codelabs-content-type=paginated] google-codelab:not([theme=minimal]) google-codelab-step .instructions aside.special,body[codelabs-content-type=paginated] google-codelab:not([theme=minimal]) google-codelab-step .instructions aside.tip{border-color:#137333;background:#e6f4ea;color:#212124}body[codelabs-content-type=paginated] google-codelab:not([theme=minimal]) google-codelab-step .instructions aside.warning{border-color:#ea8600;background:#fef7e0;color:#212124}body[codelabs-content-type=paginated] google-codelab-step .instructions aside.callout{background-color:#e8f0fe;margin:20px 0;padding:15px;border-left:3px solid #185abc;border-radius:4px;color:#212124;font-size:14px;line-height:1.5}body[codelabs-content-type=paginated] google-codelab-step aside.callout b{color:#185abc}body[codelabs-content-type=paginated] google-codelab-step .instructions ul.checklist{list-style:none;padding:0 0 0 1em}body[codelabs-content-type=paginated] google-codelab-step .instructions ul.checklist li{padding-left:24px;background-size:20px;background-repeat:no-repeat;background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAMAAABg3Am1AAAAWlBMVEUAAAAxokwwoks1pFAxokwxokwxokwxokwxokwnnkQnnkQnnkRou3y84cTS69cxokwonkQxokwnnkRqvH1VsmtluXlVsmsnnkRdtnLw+PIxokwqn0YinEAfmj3goh/UAAAAGnRSTlMA2CcEo+6AQT7+2IOBJxPl27alhoBnX15SCCe258UAAAB+SURBVEjH7dA5EoAgEERR3BcQ923Q+1/T0SqKlNbMouP3gxkRFvZpyQb64VSQT4mOcYc8mU5DnqIG8zXoozj4d34tML+YrET8XBFx4e2F4oAL4N7J3EUB/EfSUwD/zG3hvFdROu9XtL31vgXguQA9F6DnAvM8WbOHpkXYD3cBBCcPjtASYjwAAAAASUVORK5CYII=")}body[codelabs-content-type=paginated] google-codelab-step .instructions h2 code,body[codelabs-content-type=paginated] google-codelab-step .instructions table code{background:#fff}body[codelabs-content-type=paginated] google-codelab-step .instructions .indented{margin-left:40px}body[codelabs-content-type=paginated] google-codelab-step .instructions strong{font-weight:600}body[codelabs-content-type=paginated] google-codelab-step .instructions :link paper-button{text-decoration:none!important}body[codelabs-content-type=paginated] google-codelab-step .instructions paper-button{display:inline-block;border-radius:4px;color:#fff;font-family:Google Sans,Arial,sans-serif;font-size:14px;font-weight:600;letter-spacing:.6px;padding-bottom:6px;padding-left:12px;padding-right:16px;padding-top:6px;text-transform:none}body[codelabs-content-type=paginated] google-codelab-step .instructions paper-button a{text-decoration:none;color:inherit!important}body[codelabs-content-type=paginated] google-codelab-step a paper-button{display:inline-block}body[codelabs-content-type=paginated] google-codelab-step .instructions paper-button.colored{background-color:#1e8e3e}body[codelabs-content-type=paginated] google-codelab-step .instructions paper-button.red{background-color:#d93025}body[codelabs-content-type=paginated] google-codelab-step .instructions iron-icon{vertical-align:sub;margin-right:7px;margin-left:3px;font-size:16px;top:-1px;position:relative}body[codelabs-content-type=paginated] google-codelab-step .instructions img{max-width:100%;vertical-align:bottom}body[codelabs-content-type=paginated] google-codelab-step .instructions .image-container{text-align:center}body[codelabs-content-type=paginated] google-codelab-step .instructions table{border-spacing:0}body[codelabs-content-type=paginated] google-codelab-step .instructions td{vertical-align:top;border-bottom:1px solid #ccc;padding:8px}body[codelabs-content-type=paginated] google-codelab-step .instructions table p{margin:0}body[codelabs-content-type=paginated] google-codelab:not([theme=minimal]) .instructions h3.faq{border-bottom:1px solid #ddd}body[codelabs-content-type=paginated] google-codelab:not([theme=minimal]) .instructions ul.faq{list-style:none;padding-left:1em}body[codelabs-content-type=paginated] google-codelab:not([theme=minimal]) .instructions .faq li{font-size:1.1em;margin-bottom:.8em}body[codelabs-content-type=paginated] google-codelab:not([theme=minimal]) .instructions .faq a{color:inherit;text-decoration:none}body[codelabs-content-type=paginated] google-codelab:not([theme=minimal]) .instructions .faq a:hover{text-decoration:underline}body[codelabs-content-type=paginated] google-codelab-step .instructions .faq a[href*="cloud.google.com"]{padding-left:22px;background-size:20px;background-repeat:no-repeat;background-image:url("data:image/png;base64,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")}body[codelabs-content-type=paginated] google-codelab-step .instructions .faq a[href*="stackoverflow.com"]{padding-left:22px;background-size:24px;background-repeat:no-repeat;background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAATwAAAE8CAMAAABq2/00AAAA4VBMVEUAAACCg4aCg4aCg4bIj0P1fx/2hh+ojHCojHCojHD2ih/UjCn0eiD0eiD2hB/2hR/RjjDUjCnKkkPUjCnUjCn2ih/UjCnCllPCllP2ih/CllPCllPCllP2ih/CllPCllPCllP2ih/2ih/CllPCllP2ih/2ih/CllPUjCnCllPUjCn0eiD0eiD2ih+ojHD0eiDUjCn0eiD0eiCojHDUjCn0eiDUjCn0eiDUjCnUjCn0eiCojHD0eiCojHD2ih+ojHD2ih+ojHCojHCdiXaViHuCg4aojHD0eiDCllPUjCn2ih8XYwy7AAAARXRSTlMAv0CAEEAQv4BA7++/gCBQQN8wIIDPv2Dfv5+PUDDPryCAcO+/r49wn4Bg79/frJ9QcGDPr6+Pj3DPz2AwIJ9wYOaPVDAbIL/gAAAGhElEQVR42uzbsYrCQBDG8WmyxaJJlcIixQmxMSIRgiBB7Bbm/R/oPAnH3e0SxwSvyf/3DLt8zDeMAAAAAAAAAAAAAAAAAAAAAAAAAAAA4F9k7Xm1Xwlek53WqyY87AVWfbHumvCTE5hkIZYJTFyIrQU2+xA5CmxWIULcWq1DTGBzCrFcMDluC4ENcTtDEyKdwKYLkYuAuH27ggFtuj7ETgLiNo0B7Z3c1YnNMUQaWbTC6/W1uKUPHbha7wr60GnP7ot3YpGHWCsL5Wod1JP70LMsU+H12424nfDsBj4XgzMD2kN20F82YtDSh965nf61JW7Nzy7iKwY067OLlfJcw/qx1KQPQ9zSh1aaVtGHGnxoUummrB97WZhSk3byRM/6UST3mpQRtwZbTTo4GXdhQLvbaNJVxnX0oSMftyBuDQpN8o4BzaDWpFrG5KwfH5zXpJuMCfShox83pw812GnSxrx+XPI5hjvowF7ttawfB5km+Yq4nf5xS84x5lR7nGPMqfaI2znVHgPajGqPc4w51R7nGJ/sm29P2zAQh49h1kJgJHGWlrbQItAIebNO67owadpgwOzv/4Wm8S8NLsXxGSTu/HyEk/O78+McRu0FH4pQe2EdA6P2wjoGRu2FdotQe2EdA6P2wjoGRu2FdotQe+GChlF7DNcxKulN7bFbx4h1lPlSe+x8aKK1Tqae1B6zdYxM35BLP2qP1TqGjPQdmfCi9ji125l+ICp9qD1G6xixXiSPPag9PusYiW5SCLza49JuK/2YKEOrPSYXNBFpkyTGqj0e6xiFXkoukWqPwzpGrJ8iEyi1x8GHnuknSUqU2qO/jlHpVeQpwhB8oL6OISK9mkK4qz3q7bbQzxFV7mqP9jpGqi1IYme1R3sdI060BTPpaAiot9ss0hZkwk3tUb+gyUJbkEzd1B55HxqfaQvy1Ent0V/HKCNtwVy0NwSfGPhQMdcWRJWD2uOwjiFzbcFZ3F7tsVjHmDqMLTZqj3S7bTm2RJloZwh2maxjyJnd2NJS7XFZx7AcW2QrtUe93dZUDmOLjdrbaTTa7e9fNgj1i7ZjS9lK7dU+dPvzzgaRZ8elpPZji73a2/j749vOLuWytRtbCmmv9jghLMcWuw936zfwwnZssTAEexw+VidTmstn1N4Wr2/2gcrBlO6HY3eHKNqPLYfh2FmPLeZ/aXvh2D1Q2o0tYkHt8ZxQliIybTm2NNXex30IWI8tcePDPYSAywPv+61w7NwfeHfJHrvJS44tSQmUGan+oCfAgTi3fOCly1D952A4eqkH3gTocqDuOT5NX2JsmQJZhFrkaHwy8fzAmwNdeuoRRgQiTakEugyUSR2B+LFlDoTpK4M6AvH/pUUC6JIqAyMCMQ+8pMe8E2XgGIFlxKxbAIyVgUUEWj/wUh6QAZQBIgJlzqlbQKwMUBE4Tdh0C4ChMsBFoMgiJt2ivpvVoCNQznh0CxDKAB2B9dgSA2l6ygAbgfUDbwG0GSgDPxEo5tS7xYq7GT4CU8Im6pbRsNkxMBFIex5ezqQ3qM8fPgL5kZ6Mj1QNLgKpR90y4tNjpbxFID+ExwjsAUN8ReAYmOIjAlmePF8RyLHv+orAPgScI3AIb531tQZ/XjECR3DL5VoTeDOsXTVYf8UIFHDLu6sm8GZAFA8ZgccQimcgLCPwNBRvOROLCExD8Z4mXR2BRxCK5+wCx6F47hHYC8Vzj8BJKJ5zBPYhFM85Agf0i3dx3ulcdLubm5e+I3BEv3id65r7Ov70EoGCV/EW+NrpdLu/cHWkX7zz65pn6hiK9689O8hJKIaiMCxK0nYzTBgSYxDs/pekiTohEq/v0eRKv28J/+zkXMbrF2IdxQvEC3ScOF7r6+3LrtZDa1vxVinfHaeId+qjTBCv9kGO4i1XJoi365/EWxCv9EF24i1XJ4jXv4iXKd7p/uNt+yjt/uO1PspZvOVmmGcPrZ1q3ZUi3qoDaNva4WYdj5PFu2nHMm+8nzqKF4y3vuOreL923PcrqngRz6291FrKXrxbdWzifXB6iydehHh5iDco3maQpxnivQ2yEU888cQLEi8R8cSLES8R8cSLES8R8cSLES8R8cSLES8R8QbFexzkPEO86xxA4on3F+LlIZ54QeLlIZ54QeLlIZ54QeLlId6qeOk8/BviiRciXibiiRciXibiiRciXibiiRciXibiiQcAAAAAAAAAAAAAAAAAwHTeAe21evvWi2VXAAAAAElFTkSuQmCC")}body[codelabs-content-type=paginated] google-codelab-step .instructions .faq a[href*="support.google.com/webmasters/"]{padding-left:24px;background-size:24px;background-repeat:no-repeat;background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAMAAAD04JH5AAAAolBMVEUAAADW1tbW1tZ6enrQ0dJ6enrMzMzq6+zq6+x6enru7+/m5+ju7+/m5+j////S09REi/XW1tbm5+ju7+9PT0/Q0dK8vLxGjfVZWVlNTU16enrMzMzIyMj09PS/0uuSkpJpaWmbm5tim/e0tLSEhIStx+3e3+GsrKxwcHBZk/dPk/R1p/KPtu/U3eqmpqZlZWVfmO5woeqHreWvwN6nu9qLi4vZSE73AAAADnRSTlMAEcxmzO7MzDMz7u6IiHn/rpYAAALMSURBVHja7dXpjtowFIZhUkqZlSV1ncQdEsK+zD7T+7+1xjTiwxVOAmeORyP5+2UspPchEtDy8/Pz8/Pz8/M7cZeduHKdyxbL0FfVAMUraHdUHUB12i22tZWqBRSDgKFfC4CApV8PgIClXw/gE6hyTd/lAR7gAV8fEHwbWtc/ul/WfQ8IfQKAIECfCoCA3sdq+nQB+nQABIQ+CQABtY9Z+lQB+gwACBj6AFAE6DM9AL0fAalPB/yGgNAfntwHAAJKnwCAwNLneQAAVAvM/ttzVLlB4z2/A6AFVoDRf43IfewVgGKNAG/Uvrl39BsCXqh9cy8nA/51tmk63+jDZp6m9wTA4DzANiyW6lOqTxAMHAD22XASReuwpKDvELCNookBGJwx9E8B3OvsQp8e9GmOviNANA/Dh4k+TApBukHfFSBa7/I7whqf3xWA/gOAoU8DDJwBCHk+wIAw9CsAPw/W++CFB/MAD/hCgL59PXPS8toRYKHEndkTauEQIIUQ0hToG2eAXOicKdBXmSPAo9CTpkDo5U4Ad6IEGILy0gFgFJctCACIh/yATABwIChvVyE3IBR7AAQAiOmIGZADAMEBQMkRL+AJAAgOALGUI07AQgBgCPb3uRbwAaYAGAIAZlIL2AA5AIYAgJXUAjaAAsAQADCWO4EjAAQGQAvYAUsDsDQAeuwAMZvu89PZ/jZhBmQCi2dl60+MPiMAf8UgZEUpK/LoJ4oX0C9LIIyF0U8yXkBPVCzRWzIDZjX9sWQG9Kv7ScYN6KnKfizZAf2qfpLzA3p5RV9JboDeytp/kk4Ao5WtP+UFQKCO9sdTSQQ03+OR/kxKdgAWZv/11VI6AWBmP5HSNQD5zwQknwxIqIBu468hBgDqNYCuFXBDASSNAbdWQHB1PiBpDLgOWtZdXPEDri/QswjYAOjbF9x0OQHd26Dl5+fn5+fn5+dn7i/3LEaKJNV/0wAAAABJRU5ErkJggg==")}body[codelabs-content-type=paginated] google-codelab-step .instructions .faq a[href*="developer.android.com"],body[codelabs-content-type=paginated] google-codelab-step .instructions .faq a[href*=android-developer]{padding-left:20px;background-repeat:no-repeat;background-size:20px;background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAAq1BMVEX///+lyjmfxyGhyCqkyjakyTP+/vuiyS7z+OWlyjKgxyTX57ChyCfa6bTx9uLy9+Sz0l6szk/D24Tt9NrN4ZnK4JSiyCyexh34+/D6/PTp8dPh7cjf7L7k78vc6rnW5qzU5ajS5KPP4p+21GWnzD3F3Yi813Kx0ViqzUWexhr8/vjv9d7Z6LKy0lyZxADh7cLA2n2rzkr1+erJ35C61m6uz1KcxRHn8M6/2XgEePWtAAACr0lEQVRo3u3Z2XKiQBiG4Y9ebNO2aCCyzOC+7zH7/V/ZRJZQZaJpWnKS4TlJUItXbX4pFJXK71DTusvccI6z5oMSAutdhDP2uzpK4CxwxsRBGYJdA19qLAOU4s4LkyUN7G4Ude2glmzuRihHKDqAPZhNuJRKSckms37rvctrKMnG728l5cxKMU7JuCF7KEvf87h1gnu0iXK4B2p9Sc3dUgZNMusMLvu42r20LiBXT8JMWRepN1xlGu+fK8/6xFPxwsvH697/eP/j7uDTOvB+dxwX/AaM2SQ+6icrYHDyGmgfWE3irNeCqTaPAwcArydroboAbuMAb8NQRNJn20SYtHK8HaKZzoffhZl5tlNxsD5PsnUQ2b9jwwnO35WvRo3lN/o2TDwKS5M3gokF0w2wZxgIlpY2FpgsgdQPkLXJQar0A/LVIDB6Idp2GxQQrJI/rbq2Voijlc5S9LZs8uYCqBVyXLTZhLW/fSn3hDMmZAQ05I020gT2PmeM+w4uGpLksFs+oEEtbaqJVnpUkz4uyebf6xQK0CY6XjoSC1xQ9/PPr4KB52zuvTrOa5EssC0auM0C0tYKtI0DqgpUgSpQBapAFfifAj90Tn5YZoGnooH8eutB56KDDosGhlTrYiTyk0epVdFAKJLn9rLHRSNfcE4tF0UDcAXlXPhDfGPtjGejEMUDCEdPY8eFHoOADvPAxiDQLBBQkUHAJfoB34UBS/9CfAETe6lZYKZft/QIFe94vicRy7tcvKOkB0PhYOo4zlNWYNvjpjOdZwU+O24OQlynK62EGCF2J9IbpIsy/P0I3CHW+Qj8qQJVoAr8VOCx3EB+YvDSwIDmXzaW4oZZseU6Lfr5aaAUPT8uyPuT33VeIpRkI5RHyRQfHEKFUj2UJuh1GjaQsxudKECl8jv8A6GtQkKSkMLrAAAAAElFTkSuQmCC")}body[codelabs-content-type=paginated] google-codelab-step .instructions h3>a[href*=github],body[codelabs-content-type=paginated] google-codelab-step .instructions h3>a[href*=github]:visited{color:#000;text-decoration:none;padding-left:24px;background-repeat:no-repeat;background-size:18px;background-image:url("data:image/png;base64,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")}body[codelabs-content-type=paginated] google-codelab-step .youtube-video{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;margin:auto;width:560px;height:315px;border:none;max-width:100%;max-height:51vw}body[codelabs-content-type=paginated] google-codelab-step .embedded-iframe{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;margin:auto;width:560px;height:315px;border:none;max-width:100%;max-height:51vw}body[codelabs-content-type=paginated] google-codelab google-codelab-step .note:before,body[codelabs-content-type=paginated] google-codelab google-codelab-step .special:before,body[codelabs-content-type=paginated] google-codelab google-codelab-step aside:before{content:unset!important}body[codelabs-content-type=paginated] google-codelab google-codelab-step .instructions aside.special,body[codelabs-content-type=paginated] google-codelab google-codelab-step .instructions aside.warning{margin:10px 0!important;padding:15px 20px!important}body[codelabs-content-type=paginated] iron-icon{font:normal normal normal 24px/1 Material Icons;-webkit-font-feature-settings:"liga";-moz-font-feature-settings:"liga";font-feature-settings:"liga";-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;text-transform:none;word-wrap:normal;font-size:inherit}body[codelabs-content-type=paginated] iron-icon[icon=file-download]:after{content:"cloud_download"}body[codelabs-content-type=paginated] google-codelab .warning,body[codelabs-content-type=paginated] google-codelab .warning :link,body[codelabs-content-type=paginated] google-codelab .warning :visited,body[codelabs-content-type=paginated] google-codelab .warning code{background:#fef7e0}body[codelabs-content-type=paginated] google-codelab .special :link,body[codelabs-content-type=paginated] google-codelab .special :visited,body[codelabs-content-type=paginated] google-codelab .special code,body[codelabs-content-type=paginated] google-codelab aside :link,body[codelabs-content-type=paginated] google-codelab aside :visited,body[codelabs-content-type=paginated] google-codelab aside code{background:#e6f4ea}body[codelabs-content-type=paginated] google-codelab-step td{background:transparent}body[codelabs-content-type=paginated] google-codelab-step .instructions h3>a[href*=github],body[codelabs-content-type=paginated] google-codelab-step .instructions h3>a[href*=github]:visited{background-position:0 3px}body[codelabs-content-type=paginated] google-codelab-step code{font:500 90%/1 var(--devsite-code-font-family)}body[codelabs-content-type=paginated] google-codelab-step pre{background:var(--devsite-code-background,#f1f3f4);border-radius:0;color:var(--devsite-code-color,inherit);font:14px/20px var(--devsite-code-font-family);margin:16px 0;overflow-x:auto;padding:8px 80px 8px 8px;position:relative}body[codelabs-content-type=paginated] google-codelab-step devsite-code pre{margin:0}body[codelabs-content-type=paginated] google-codelab-step pre,body[codelabs-content-type=paginated] google-codelab-step pre code{font:14px/20px var(--devsite-code-font-family)}body[codelabs-content-type=paginated] google-codelab-step code .com,body[codelabs-content-type=paginated] google-codelab-step pre .com{color:var(--devsite-code-comments-color)}body[codelabs-content-type=paginated] google-codelab-step code .dec,body[codelabs-content-type=paginated] google-codelab-step code .lit,body[codelabs-content-type=paginated] google-codelab-step pre .dec,body[codelabs-content-type=paginated] google-codelab-step pre .lit{color:var(--devsite-code-numbers-color)}body[codelabs-content-type=paginated] google-codelab-step code .kwd,body[codelabs-content-type=paginated] google-codelab-step code .tag,body[codelabs-content-type=paginated] google-codelab-step pre .kwd,body[codelabs-content-type=paginated] google-codelab-step pre .tag{color:var(--devsite-code-keywords-color)}body[codelabs-content-type=paginated] google-codelab-step code .atv,body[codelabs-content-type=paginated] google-codelab-step code .str,body[codelabs-content-type=paginated] google-codelab-step pre .atv,body[codelabs-content-type=paginated] google-codelab-step pre .str{color:var(--devsite-code-strings-color)}body[codelabs-content-type=paginated] google-codelab-step code .atn,body[codelabs-content-type=paginated] google-codelab-step code .typ,body[codelabs-content-type=paginated] google-codelab-step pre .atn,body[codelabs-content-type=paginated] google-codelab-step pre .typ{color:var(--devsite-code-types-color)}body[codelabs-content-type=paginated] google-codelab-step code .pln,body[codelabs-content-type=paginated] google-codelab-step code .pun,body[codelabs-content-type=paginated] google-codelab-step pre .pln,body[codelabs-content-type=paginated] google-codelab-step pre .pun{color:inherit}google-codelab-survey{visibility:hidden}google-codelab-survey[upgraded]{visibility:visible}google-codelab-survey{display:block;margin:2em 0;padding:0;background:#e8f0fe;border-left:4px solid #185abc;border-radius:4px;color:#3c4043}google-codelab-survey h4{font-size:16px;font-weight:400;padding:.8em 0 0;margin:0}google-codelab-survey .survey-question-wrapper{padding:.4em 0 1.1em 30px}google-codelab-survey .survey-question-options{padding:.8em 0 0}.survey-option-wrapper{cursor:pointer;display:block;padding:0 0 4px;position:relative;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;vertical-align:middle}google-codelab-survey .option-text{color:#212121;font-size:16px;padding-left:24px}.survey-option-wrapper input{position:absolute;opacity:0}.custom-radio-button{position:absolute;top:5px;left:0;height:13px;width:13px;background-color:#fff;border:2px solid #3f51b5;border-radius:50%}.custom-radio-button:after{content:"";position:absolute;display:none}.survey-option-wrapper input:checked~.custom-radio-button:after{display:block}.survey-option-wrapper .custom-radio-button:after{top:1px;left:1px;width:7px;height:7px;border-radius:50%;background:#3f51b5} + /* stylelint-enable */ + diff --git a/site/_static/static/dcc/bringing-safety-thumb.jpg b/site/_static/static/dcc/bringing-safety-thumb.jpg new file mode 100644 index 0000000000000000000000000000000000000000..c521ca31f5deb411ba2680ffb3cc6011cb0b5827 GIT binary patch literal 8255 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 literal 0 HcmV?d00001 diff --git a/site/_static/static/dcc/case-study-thumb.jpg b/site/_static/static/dcc/case-study-thumb.jpg new file mode 100644 index 0000000000000000000000000000000000000000..26b4bae162fb5055704766a0a7b2911000517e94 GIT binary patch literal 10708 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 L525VPyQTjH1?I$} literal 0 HcmV?d00001 diff --git a/site/_static/static/dcc/chrome-117-beta.jpg b/site/_static/static/dcc/chrome-117-beta.jpg new file mode 100644 index 0000000000000000000000000000000000000000..82dfe9099d94ff75bdc343a5cb9a0d3d40b302e5 GIT binary patch literal 11959 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 T(y57A6^Y*S4|1RQ{a*b)YTgiy literal 0 HcmV?d00001 diff --git a/site/_static/static/dcc/chrome-at-io-thumb.jpg b/site/_static/static/dcc/chrome-at-io-thumb.jpg new file mode 100644 index 0000000000000000000000000000000000000000..6a989d2757b9e8f8b88ab001156c1f264c7aa283 GIT binary patch literal 6941 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 literal 0 HcmV?d00001 diff --git a/site/_static/static/dcc/chrome-devtools-thumb.svg b/site/_static/static/dcc/chrome-devtools-thumb.svg new file mode 100644 index 000000000..dcfaaba55 --- /dev/null +++ b/site/_static/static/dcc/chrome-devtools-thumb.svg @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Generator: Adobe Illustrator 27.8.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> +<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" + viewBox="0 0 120 120" style="enable-background:new 0 0 120 120;" xml:space="preserve"> +<style type="text/css"> + .st0{fill:#3483F6;} +</style> +<path class="st0" d="M60,56.9c3.6,0,6.6,3,6.6,6.6c0,3.6-3,6.6-6.6,6.6c-3.6,0-6.6-3-6.6-6.6C53.4,59.8,56.3,56.9,60,56.9z M60,55.2 + h15c-2.9-5.3-8.6-8.9-15-8.9c-5.5,0-10.5,2.6-13.6,6.7l5.4,9.4C52.3,58.4,55.7,55.2,60,55.2z M60,71.7c-3.1,0-5.7-1.7-7.1-4.1 + l-7.5-13c-1.6,2.6-2.5,5.6-2.5,8.9c0,8.7,6.5,15.9,14.9,17l5.4-9.4C62.2,71.5,61.1,71.7,60,71.7z M72.1,35.2V28 + c0-1.4-1.7-1.6-2.8-1.6H52.1c-1,0-2.8,0.2-2.8,1.6v7.2h0c0,0,0,0,0,0.1L72.1,35.2C72.1,35.2,72.1,35.2,72.1,35.2z M120,60 + c0,33.1-26.9,60-60,60S0,93.1,0,60S26.9,0,60,0S120,26.9,120,60z M97.8,45.6c0-5.7-5-10.3-11.1-10.3H74.9c0,0,0,0,0-0.1V28 + c0-2.7-2.2-4.4-5.6-4.4H52.1c-3.4,0-5.6,1.7-5.6,4.4v7.2c0,0,0,0,0,0.1H33.3c-6.1,0-11.1,4.6-11.1,10.3v17h19.1c0,0.3,0,0.6,0,0.9 + c0,0.2,0,0.3,0,0.5H22.2v24.9c0,0.5,0.4,0.9,0.9,0.9h73.8c0.5,0,0.9-0.4,0.9-0.9V64H78.6c0-0.2,0-0.3,0-0.5c0-0.3,0-0.6,0-0.9h19.2 + V45.6z M64.9,56.9c2,1.5,3.3,3.9,3.3,6.6c0,1.5-0.4,2.9-1.1,4.1v0l-7.5,13c0.1,0,0.2,0,0.4,0v0c9.4,0,17.1-7.7,17.1-17.1 + c0-2.3-0.5-4.6-1.3-6.6H64.9z"/> +</svg> diff --git a/site/_static/static/dcc/chrome-extensions-thumb.svg b/site/_static/static/dcc/chrome-extensions-thumb.svg new file mode 100644 index 000000000..8eca23a2a --- /dev/null +++ b/site/_static/static/dcc/chrome-extensions-thumb.svg @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Generator: Adobe Illustrator 27.8.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> +<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" + viewBox="0 0 120 120" style="enable-background:new 0 0 120 120;" xml:space="preserve"> +<style type="text/css"> + .st0{fill:#F5B840;} +</style> +<path class="st0" d="M60,0C26.9,0,0,26.9,0,60s26.9,60,60,60s60-26.9,60-60S93.1,0,60,0z M93.9,67.3c-0.6,4.9-5.1,8.4-10,7.8 + l-1.5,12.4c-0.5,4-4.2,6.9-8.2,6.4l-11.9-1.5c0.6-4.9-2.9-9.4-7.8-10.1c-4.9-0.6-9.4,2.9-10,7.8l-0.1,0l-11.8-1.5 + c-4-0.5-6.9-4.2-6.4-8.2l1.5-12.4c4.9,0.6,9.4-2.9,10-7.8c0.1-0.6,0.1-1.2,0-1.7c-0.3-4.2-3.5-7.8-7.9-8.3l1.5-12.4 + c0.5-4,4.2-6.9,8.2-6.4l11.9,1.5c0.6-4.9,5.1-8.4,10-7.8c3.9,0.5,6.9,3.4,7.7,7c0.2,1,0.3,2,0.1,3.1l11.9,1.5c4,0.5,6.9,4.2,6.4,8.2 + l-0.1,1l-1.4,11.3l0,0C91.1,57.9,94.5,62.4,93.9,67.3z"/> +</svg> diff --git a/site/_static/static/dcc/chrome-twitter.svg b/site/_static/static/dcc/chrome-twitter.svg new file mode 100644 index 000000000..2e42e26e7 --- /dev/null +++ b/site/_static/static/dcc/chrome-twitter.svg @@ -0,0 +1,11 @@ +<svg width="55" height="55" viewBox="0 0 55 55" fill="none" xmlns="http://www.w3.org/2000/svg"> +<circle cx="27.5" cy="27.5" r="27.5" fill="black"/> +<g clip-path="url(#clip0_1_20)"> +<path d="M30.8555 25.1953L42.0234 12.5H39.375L29.6797 23.5234L21.9336 12.5H13L24.7109 29.1719L13 42.4844H15.6484L25.8867 30.8438L34.0664 42.4844H43L30.8516 25.1953H30.8555ZM27.2305 29.3164L26.043 27.6562L16.6016 14.4492H20.6641L28.2852 25.1094L29.4727 26.7695L39.3789 40.625H35.3125L27.2305 29.3164Z" fill="white"/> +</g> +<defs> +<clipPath id="clip0_1_20"> +<rect width="30" height="31" fill="white" transform="translate(13 12)"/> +</clipPath> +</defs> +</svg> diff --git a/site/_static/static/dcc/chrome-web-store-thumb.svg b/site/_static/static/dcc/chrome-web-store-thumb.svg new file mode 100644 index 000000000..a1005ce52 --- /dev/null +++ b/site/_static/static/dcc/chrome-web-store-thumb.svg @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Generator: Adobe Illustrator 27.8.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> +<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" + viewBox="0 0 120 120" style="enable-background:new 0 0 120 120;" xml:space="preserve"> +<style type="text/css"> + .st0{fill:#EA3323;} +</style> +<path class="st0" d="M64.7,83.1h12.2c0.8,2.1,1.3,4.4,1.3,6.7c0,1.1-0.1,2.2-0.3,3.3H67.4c0.4-1,0.7-2.1,0.7-3.3 + C68,87.1,66.7,84.6,64.7,83.1z M59.6,81.4h16.5c-3.1-6-9.3-10.1-16.5-10.1l0,0c-5.9,0-11.1,2.7-14.5,7l6.1,10.6 + C51.7,84.6,55.3,81.4,59.6,81.4z M59.6,83.1c-3.7,0-6.7,3-6.7,6.7c0,1.2,0.3,2.3,0.9,3.3h11.8c0.5-1,0.9-2.1,0.9-3.3 + C66.3,86.1,63.3,83.1,59.6,83.1z M53.6,56.6h12c1.3,0,2.3-1.1,2.3-2.3V54c0-1.3-1.1-2.3-2.3-2.3h-12c-1.3,0-2.3,1.1-2.3,2.3v0.3 + C51.3,55.6,52.4,56.6,53.6,56.6z M120,60L120,60c0,33.1-26.9,60-60,60h0C26.9,120,0,93.1,0,60v0C0,26.9,26.9,0,60,0h0 + C93.1,0,120,26.9,120,60z M77.6,26c0,0.3,0.3,0.6,0.6,0.6h2v2c0,0.3,0.3,0.6,0.6,0.6s0.6-0.3,0.6-0.6v-2h2c0.3,0,0.6-0.3,0.6-0.6 + s-0.3-0.6-0.6-0.6h-2v-2c0-0.3-0.3-0.6-0.6-0.6s-0.6,0.3-0.6,0.6v2h-2C77.9,25.3,77.6,25.6,77.6,26z M67.9,30.9l1.6,1.6l1.6-1.6 + l-1.6-1.6L67.9,30.9z M58.3,23c0,0.7,0.6,1.4,1.4,1.4c0.7,0,1.4-0.6,1.4-1.4c0-0.7-0.6-1.4-1.4-1.4C58.9,21.7,58.3,22.3,58.3,23z + M53,39.9c0,1.3,1.1,2.4,2.4,2.4c1.3,0,2.4-1.1,2.4-2.4c0-1.3-1.1-2.4-2.4-2.4C54.1,37.4,53,38.5,53,39.9z M44.6,31.8 + c0,0.3,0.3,0.6,0.6,0.6h2.9v2.9c0,0.3,0.3,0.6,0.6,0.6s0.6-0.3,0.6-0.6v-2.9h2.9c0.3,0,0.6-0.3,0.6-0.6c0-0.3-0.3-0.6-0.6-0.6h-2.9 + v-2.9c0-0.3-0.3-0.6-0.6-0.6s-0.6,0.3-0.6,0.6v2.9h-2.9C44.9,31.1,44.6,31.4,44.6,31.8z M33.1,47.5h19.1c0-0.1,0-0.3,0-0.4v-0.2 + c0-1.2,1-2.1,2.1-2.1h11c1.2,0,2.1,1,2.1,2.1v0.2c0,0.1,0,0.3,0,0.4h18.9l-6.8-6.9l-20.1,0c-0.4,1.8-2,3.1-3.9,3.1 + c-1.9,0-3.5-1.3-3.9-3.1l-9.7,0L33.1,47.5z M86.3,48.5l-53.2,0l0,0v41.3c0,2.7,2.2,4.8,4.8,4.8h43.5c2.7,0,4.8-2.2,4.8-4.8 + L86.3,48.5z M51.8,93.1l-7.7-13.4c-1.9,2.9-3,6.4-3,10.1c0,1.1,0.1,2.2,0.3,3.3H51.8z"/> +</svg> diff --git a/site/_static/static/dcc/chrome-youtube.svg b/site/_static/static/dcc/chrome-youtube.svg new file mode 100644 index 000000000..730499324 --- /dev/null +++ b/site/_static/static/dcc/chrome-youtube.svg @@ -0,0 +1,12 @@ +<svg width="55" height="55" viewBox="0 0 55 55" fill="none" xmlns="http://www.w3.org/2000/svg"> +<circle cx="27.5" cy="27.5" r="27.5" fill="#FB0301"/> +<g clip-path="url(#clip0_1_2)"> +<path d="M27.17 14C28.84 14.03 30.67 14.05 32.49 14.09C33.63 14.12 34.76 14.16 35.9 14.21C36.79 14.25 37.67 14.3 38.55 14.37C39.42 14.43 40.3 14.51 41.16 14.64C42.11 14.79 42.99 15.1 43.75 15.7C44.67 16.42 45.26 17.36 45.52 18.5C45.72 19.34 45.85 20.18 45.97 21.04C46.09 21.98 46.18 22.91 46.24 23.85C46.32 25.18 46.37 26.5 46.35 27.83C46.34 28.83 46.32 29.83 46.27 30.83C46.22 31.82 46.13 32.8 46.04 33.79C45.94 34.84 45.78 35.89 45.57 36.92C45.2 38.76 43.72 40.27 41.88 40.68C41.3 40.81 40.71 40.9 40.12 40.96C39.22 41.05 38.33 41.13 37.43 41.2C36.82 41.25 36.2 41.28 35.59 41.3C33.99 41.36 32.38 41.42 30.78 41.45C29.11 41.48 27.43 41.48 25.76 41.47C24.12 41.47 22.49 41.43 20.85 41.39C19.59 41.36 18.33 41.3 17.07 41.24C16.04 41.19 15.02 41.11 14 41.02C13.19 40.95 12.38 40.87 11.58 40.7C10.37 40.45 9.4 39.82 8.65 38.84C8.19 38.23 7.9 37.53 7.75 36.78C7.55 35.81 7.41 34.83 7.31 33.85C7.02 31.34 6.96 28.81 7.02 26.27C7.04 25.18 7.1 24.08 7.17 22.99C7.26 21.69 7.4 20.4 7.63 19.11C7.72 18.59 7.83 18.07 8.06 17.58C8.7 16.21 9.75 15.3 11.2 14.88C11.56 14.77 11.93 14.73 12.31 14.68C12.99 14.59 13.67 14.51 14.36 14.44C14.95 14.38 15.53 14.34 16.12 14.3C17.26 14.23 18.4 14.17 19.54 14.12C20.51 14.08 21.48 14.06 22.45 14.04C23.97 14.02 25.49 14.01 27.17 13.99V14ZM22.88 21.86C22.85 22.03 22.85 33.48 22.88 33.61C26.29 31.65 29.7 29.7 33.13 27.74C29.7 25.77 26.29 23.82 22.88 21.86Z" fill="white"/> +<path d="M22.88 21.86C26.29 23.82 29.7 25.77 33.13 27.74C29.71 29.71 26.3 31.66 22.88 33.61C22.85 33.48 22.84 22.03 22.88 21.86Z" fill="#FB0301"/> +</g> +<defs> +<clipPath id="clip0_1_2"> +<rect width="39.35" height="27.49" fill="white" transform="translate(7 14)"/> +</clipPath> +</defs> +</svg> diff --git a/site/_static/static/dcc/get-inspired-icon.svg b/site/_static/static/dcc/get-inspired-icon.svg new file mode 100644 index 000000000..107e0d90d --- /dev/null +++ b/site/_static/static/dcc/get-inspired-icon.svg @@ -0,0 +1,11 @@ +<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg"> +<circle cx="20" cy="20" r="20" fill="#3982F7"/> +<g clip-path="url(#clip0_1_2)"> +<path d="M12.6794 9.6707V17.8293V17.7458V28.6053V9.6707ZM15.4504 20.8087H20.6285C20.8356 20.4913 21.0595 20.1961 21.3003 19.9177C21.541 19.6392 21.8153 19.3775 22.112 19.138H15.4504V20.8087ZM15.4504 25.5424H19.8168C19.7608 25.2639 19.716 24.9855 19.688 24.707C19.6601 24.4286 19.6545 24.1501 19.6712 23.8717H15.4448V25.5424H15.4504ZM12.6794 30.276C12.2316 30.276 11.8397 30.109 11.5038 29.7748C11.1679 29.4407 11 29.0508 11 28.6053V9.6707C11 9.22518 11.1679 8.83535 11.5038 8.50121C11.8397 8.16707 12.2316 8 12.6794 8H22.7837L28.9135 14.0981V18.3862C28.6504 18.2581 28.3817 18.1467 28.1018 18.0521C27.8219 17.9574 27.5308 17.885 27.2341 17.8293V14.8499H21.944V9.6707H12.6794V28.6053H21.4962C21.8712 28.9952 22.2855 29.3293 22.7445 29.6077C23.2036 29.8862 23.7018 30.109 24.2448 30.276H12.6794ZM26.1145 27.2131C26.9934 27.2131 27.7267 26.9179 28.3145 26.3332C28.9023 25.7484 29.199 25.0189 29.199 24.1446C29.199 23.2702 28.9023 22.5407 28.3145 21.9559C27.7267 21.3712 26.9934 21.076 26.1145 21.076C25.2356 21.076 24.5023 21.3712 23.9145 21.9559C23.3267 22.5407 23.03 23.2702 23.03 24.1446C23.03 25.0189 23.3267 25.7484 23.9145 26.3332C24.5023 26.9179 25.2356 27.2131 26.1145 27.2131ZM31.8244 31L28.8239 28.0206C28.4377 28.2823 28.0122 28.4884 27.5532 28.6499C27.0941 28.8114 26.6127 28.8893 26.1089 28.8893C24.7878 28.8893 23.6626 28.4271 22.7389 27.5082C21.8153 26.5893 21.3506 25.47 21.3506 24.1501C21.3506 22.8303 21.8153 21.7165 22.7389 20.7976C23.6626 19.8787 24.7878 19.4165 26.1145 19.4165C27.4412 19.4165 28.5608 19.8787 29.4845 20.7976C30.4081 21.7165 30.8728 22.8358 30.8728 24.1501C30.8728 24.6513 30.7944 25.1303 30.6321 25.5869C30.4753 26.0436 30.2626 26.4613 29.9995 26.8511L32.9944 29.8361L31.8188 31.0056L31.8244 31Z" fill="white"/> +</g> +<defs> +<clipPath id="clip0_1_2"> +<rect width="22" height="23" fill="white" transform="translate(11 8)"/> +</clipPath> +</defs> +</svg> diff --git a/site/_static/static/dcc/hero.webp b/site/_static/static/dcc/hero.webp new file mode 100644 index 0000000000000000000000000000000000000000..3243542b5b78a926652dee97390f7c5fbcd9b31c GIT binary patch literal 106046 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 P0000000000000001pB|u literal 0 HcmV?d00001 diff --git a/site/_static/static/dcc/new-in-chrome-116.jpg b/site/_static/static/dcc/new-in-chrome-116.jpg new file mode 100644 index 0000000000000000000000000000000000000000..0dbfe7192103579431e44d92368442e8130c3078 GIT binary patch literal 11570 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 literal 0 HcmV?d00001 diff --git a/site/_static/static/dcc/new-in-devtools-118-thumb.webp b/site/_static/static/dcc/new-in-devtools-118-thumb.webp new file mode 100644 index 0000000000000000000000000000000000000000..754dcdf5e32ea1c04bcd0ac8786bed6282f6caec GIT binary patch literal 33714 zcmagFV~j3L6s6m?ZQFLAwr$(CZJVd<K5g5!ZQFLg^G)u|++=c-TfZu)?4+`i+Rxg% zs+6U~#VbRAfHcH}71b5Fi1PlM&nE!q0@DzI4g&vS#)=jxA}&kDSwXS{1#4{cd#7u` zW`mUjSm&&*6Rrf{fAdj0i2M$Hq5opOk)BMp{E*(Yy#js$&b`E{3`!6K6ez#fz7$^b zH|uTz0KnN#2LSYE>kILga6({S;MA`_KvJL+VEWVk``;>nF*x8l|FK6ffa5p+H{+}C z_HHuab?<&}mw&~79FX(7^BZyu`Z4!Hs5AH0J0Q@Q*PlPz*BH?I4frqyhyVn>&+aT1 zD6i*!0-pDJ355VNfQEq4@3RjeK*c5S*W5Mm<=%zCS>Nb8`%l+b{#)Nh{&nAHkKVV= zsX$qP*N^4z!0*$Kzy#u(KmF(2FXelHa$lUE{b#@%;ltj6KpWr|!2G82-uJYZPI&4^ z{2}opaQt@Kw$6AYFdFbL!09LScMLG}t+AG|@jK(eXC-h2u<#4=<N8o|OSlO*4p<6s z|CxFX_%->uyLPzC7|%BrSO^IHnfhG=0PaEG_Z|~&4YmOz0hs`J0N__(2k`8R3jqD? z`_2F83uHVtSO}N_L<4jH<=>b9z)xQ^U<A+uVE?rMNW9nmr`|8ouhB2&&)$3AbHHc7 zYybc-^a=az@iF(2e+xM3yZA2_0Pwk^1vqphZ0>yt<O9U=s|B6~1jf59x*bRBIDKZ0 z!r8sLb{+7Tt7dkeJP+dZ?ccJ;;H;lKx_7xuG_re6ABJ$cckVdju~ts+y#Bv~BF-5B zznl#kC}8nl7$7TjS`NdUBIesE>!_kyC*AUGyH;ya$Lk3ri%T?swq*XZu?y{g6$X2f zd;O4<X0}%Aq%hIPXgot){tB|2vQa8D#tTM@Q(r1~5q}n}p|MFSXTKChiC%6gW^tmX zSvue8Og))Sw8eAO(R#T~$FnZYhTlvYYkrEVSdG+u!d|1Ht<<iL(cU&e)Zbafz7z0k zRq<H}jxT?T{<>Yrfu!qILU#p_RvoPJKkX>p8gK=-Q}>`?R~$9@n!9S>)nn@!ovZi9 ztVXh+<)5(hh1glPk6nH;A>)067BW;<`&a61<!Ru&hc`Ybg<-Rij;Dw}s08|Va?3Q| z*L}}XXB<pwH}JUWcKt79O_x+Odc8#*^w=IX&QljC627~G;$?X}KR-XPytC3fR-%G) zA;7{0j>2x^qO?x&n!(u^UBv0@^l(6k=X|0eyZAYLP+BIhyda#xQj_ap9absNc1sE# zS-pVT8kI``=G30GRFZATyn@$+J@8RPQ1DEm9l9s0`?qhTEz4U?88w~%OG3#Jmcrat zPMv{J1od^`#|hFHNtuW!C0%<}L43Y)Y(nWNb?BS}{)wGF`9gP(Y&IK88cp9ae?C=~ z#Se&j+JYIU`<P!JN@;hOE~hvJnK!A9{OwnTU&4;u%Y@@^YSh7%+c<$^Tz643rg%ua z5JZTmviU(Nbaju-U~$RHrXFA5bvM%t4oIQWoY*ip$U!T&+q1xY$5>*e6CG!J9+=&w z0{WxS<*NQ?;H4AF{^XwRZWT@WKP_|^{sDJ~220r~1OcgVI`BG(azrKx6#=o_1099C zln<Kd9Jddo{_#F`Yn>74_d1O2KMO<UY`5>MkbZZwiqKKL{mV+xM9_6VXzNpk1Ls@? z@#=fDVLrljKTPZgr**1*Y>yk2D0kQgxvvFD$u!k>EnrbLx_u`tdaZ>s@db1nXQ^;z z{-N8DoH^Uh6TOCI-}hJ8JH=n8SLubFziUyTV_?XH4V+xljv+h^-E}l$mZ#Ms(18cA zPO~(n^+IaCFOH@zcRlRkE=yhmbkK$}AnN-ds!<NzDgVjRyNtpKI_mSkkDPcJ^2RcS z0*hD5bgpk1PwoHQOl*>xh2K9i)95PR8zEBcqrVsSP?%&xEmVKeyIWdmOLpOSFZee4 z?_5@DOtbfXD|QV4ABo`B;u0|b4vFP3c_qtZ<R9Xa!TNAnqZv63$9nbeXtQH17~i>E z#zqUGM`X5OL~Brv7%rHsr=SxICww((x}0wEq1Q(ngBsUYUx#+R<fU!FKZZz8d3a?+ z5d3WyEwOqNn6ts7vMsNWkG4-y_cpSwXp*t1SLCK||7xar&!QtIDs+;Nn<T<LAfE46 z^VMSGtBz>LV=-YFxz0qpU97eg^of@$>9lw-mW3rF%QG&JZKV5lp-D(bAQ*}g7+9{( zNpm^};<>bjM%cnW>a*}(FTxx>WnPSds32u*&IDsA&!!l$`>;!SsJ6`>*2d^AbPa&f z0RrB}P&$hMl1Y9m|K{@Nftk2wc`|uI|AnP0XQloPp&H9g{xa!9Aj`jNR@3SPiqKI1 zFgna;#%Jw1MWXHXRF*5mu!P_U*UR*T5a;<AwM(Q+?Z8V}5~gwGN;ylsx5@8I)Tc=N znEX*BTWZxTKXfyl!Oz`G)e*fA{_e#^lD3zQ8M~&g+%@+R!|O|%Dw=&=f{VIv<^kI} zVY@5kh|G-<NMK~iHq|DD`r3NgNbWXKL=z3v?~vrlN2ZFW#=%ds><iu9LS~f_`k6_I z2*q{S;=vDD7U+;^DY6^8pf%1);t}<^9c2Z~?WMS`ITw{L)A86&^5_d$X`;bY$JIZ; zJJpv0h=W>#`go$<+)~|7ox53e<ZMl&RQ4$#Qg-?wZ`yHz=eyuD945B9Df}v_OBtlX zPu&Kz=WpL6vEH={^V|k}qb9|OjOln$cd2^jy994#Iz|pI5t~G(BzmSu5Phw>nn{o4 zhBtQ<UqARrF-zA20ANLY_AsBKQ}2wwOsBTm!SR)z8iKpijxb~1l>EKYgVSj=FW|7l z+=dp5&2L1#wwU@(B~K&KkvXo+z8!FM!|wA;bn5DLoL(GoA1QY((n)GvtKlBE&BGAx z<h9k;zT4S`m3&6wbbC_FatH=kDLOl}29dm=nZ?#?FAO3753Y=+w<;3xNUM%3Keb3V zWVnu`>HlVE!o@TZRIgWJ({oq52Ql{4uC0vsJIH$;U|9eUvINIL|1EPmq-L|1qBWfV z(TgRYRJ2+=8jKwD$lq+-z^gC@<ln>aKj0AeyHAHRL@thpD^g5OA++of2BGbo1R_-O zf#5KR_7LSxghms$U`dl;$a~=ZFS3SGnO&^(a(2aL-`pAf37)ayB(Fm!U8)_j5xzjk zF7O>NFr6{+m{KFy*%fVSWFFno`YXG+b6(}#DyH^dDk5a81F`2P!16O<Sw{0YbXN>6 ze5`<?$8qxIKr{jUh=W}j{nOK(N@>&qTf}W3gr??Is@PY!O4BqASI}(Z-R{#Beeqtm zL%PE*@3GV!jBC2ataj=8+~0yd-7j2R6If;9Zrn$NucGu7Jp+m++P<DtZ%l?Jnj7u= zJ2%mg@;9krOT8PMPg3y<i`~VUn--e|{;mxL_X@nda(lQ2L&Yu{n8ep5|4z%w%Gsu6 z9E(3$vZi7_6KEo8gthVPq)j8cdtm8_-4QeCS}BN=#!y*}y`i47lRBSe95no^Pld|W zCvND)b@Jcv0be(g(_;0f-am#GzS46S$Qg_Lz!y39-eu(~<Q&oCr7%syI9><VRuszY z>4r85N&TYLu<7a(A20RODd7;R`?-B*8RB6-aI}n<!n1|(5R=H1?2jVR7DdZIy>U)< z$I)t?sRA|hC#??1kgCKGF))sR&`yj**m`)U=p?4Qk~{Jc4yfsyml%=Hwhp|OP$nDO zbEK72vt=P3qHPv%I^U|eKF@>LQx-aS!lp!gJ+!^KDTzJ$>b(|jS1m>HUzh-qpQ#iV zqx<x(*7d92NggHZAkQ^okxPtAna{NQ%^V;!ItFSWIM;_QwyVk*A@2XzT*1vU`d_LD z%0=C}_|J#c$TxFP6Qy4{?r{|2KEe@_AmXBX<QCXM)^0Mxlf5iG^D4>#a29CRC;kst zd(mqDgz-b2z|Ud4T&b;(^pynvL;LM)qr2;f(F>`2cmLl^`#%_g3pvi<ju!~xO6zm_ zo}$wcF1OO*og&Z00u24%upv`#K2r|yyz!PYl|u6VI1;bUT7BC7zrCVcgJ<&8`g-L} zezVzs>~hB*kSv1#|F@0*x7W-A0{R6kRR;q7H{g%I=(J}z=Th)Ye-7z#Ak86!U&g>A zw<W~FDjAi&>|ojaa+79mYRn{DDl$$_d`x`OT|hLK?S6h5AYL(R&0RTu`^OLBOnJ}P zEpnLFWsNP%w!RF%e2D+4&?$w4^(Odzk1QK)99WJ!Jq>`MRSw`EGPIgIL{wM}t`1!A z%$BVohP(_Ow?cnTT?h$I`&vQD=HXDD%R)hbs);5wTs9VY=bz6durwyaxR(ZhIkV0E zXm%2*<Z<QKGE6czzEBdy%c^-!H}JY@&ufx`Betg(xCx(B)}xT3w~BeY91hS^Al|fe zEng2xkr8|IUUq&Yw7t+>04?D8w&wFpoO+G^-aZ!PM6^L(x~!u3U6imbXRexjI_R>Y zJb`~!n0`ukWT2Gfo-^lh3|=JI8tbEucLZzQwKtvq4yx-Po22(G@f61J6eOAp8|iiX zYfbG(g|bmi7fi}*ldRex_SYEOBmA}_1Yk0yty|<JS0Ln@RMI0xH@i=Kt{&QgT30=h zcC;PxC-NweRrst-HwDA7b_QM)aT&1>cf`u4ofy8`^uH|l3+;ON@J=YCRW0~H=1q<o z$8_m^EH-mm50JVxnt*qfpMx!XVO>_~=Mw%Y4fc;*mgbq^#0J8q9cs^+&VY>oRDI~a zwQ2QTLJiSXKJ_@s<l8Pd1sx+!J0gM^x7u$qZ(Z5s(cEda;liw{KILW1THi01XA~?o zPHz>-DS3|5FX`Flku5*&d9YK6>q{zWtZTU#X#asWO`Q7C5@Oyx&w>T70KT8F8Ev5S z2cS<xc2LyRqh+<HIb!_e6F@%xMv|DtOR$|H#lX-gS6D1Yf0)ypmos1tCAQX3wP>;W zVTB_Eww0RJ$$q!VFci4_jfHfpjlJHH@9}D`mql|i;KSwU77uj5Kr1sj|6`e6CjGDE zE$N%Pzyg&-Bi`&uaF((jwuqTX*AvQy`ZXLj&&%r9qmGsbCNyRPsp`zRkibv(Z*~jr z37FCNsb5{&&cO@D_e=?M?r?h&25{I&ya;OS`e=z1nB~nUR0YyUgDwmiSd+syNGu8F z2B`}u*WJ57(ne4SBDY*ZQDIPqiI>}9LBt3_8#*!%JNmRhpMAB=kAtoq3PuL=s!W;8 zV3tWDWnYP^V;@xbDgWdjrfr3WhYpQ4hmqeu>Z%T}+Kdp=4Y?&^yrhM!M!Ias(t_j| z!Qz1zIu<b$ILOEzF5%%o%3l94>Zat-zig4I<=<uE5%aqk;SrSet*nshvZK~m)EQFT zkxK^C&QR+%wPl%fqmTkyOK1*R*zV$xTn5&`oLJfJCCkDE5<bG~Q4})AXl0SZSv`m{ zp<P9Z@?0zgneV^bnY^?3a~Mp5kjQPK#_$xqv1f`s7W-Bj?Mgg;H@W}X=HQVwqcDrX zwkq;F0`1z?2HH%U>9r?NYATs8<4y>0FptW_q71kmLw<ndnw^czI}Y60MbJZys?rDa zCP<hH#cp2R-^N0gHn(%%N$i@LGwHUS2Sp?|p4wxR9v^Vydy-3OUdCA@Agc8I=B!uU zAvl640XLc(c%&R3qSrW!MT7Y8Bw|0)3GR{t`OxSwBIR#5y4!if*=^Xd}&u^}3s zuLKPSvFMeisG;QLsMP&5U2?Vj`UGc)Sky2~2&FaM;r`g9XIwB;3@q7!36G~oL7^h6 zosKH~v5MoG|6n7+IAGnSGyoqtV-9+G&$}fXn=~`Q3}R7&6yYOT^5@#9^!AkTxDCDG zgZnjA;sX+w{O!Y-EJ^vJ^EVf_Vye_vgMLl6mbKIo2N{L?UR4evOU72@=JX$Zs0VP& z&@0T*8O%T>hF<|rjEVCh3DIsescayW%Lw)SzuW>==OJKwUmW$;J59DQnObbL+Dwvp z9p}&w*>B?1%AS1S(qFuN`nXbC^=e7@*qMhSlP3;bzz^*jKt)SfV(2NAsVyuBS)LF7 zK;vqhJwlWKDb5~?Su`=*viGQ#PVD#;aL?9%FYKGu4;X*9-g&1a6v)^5E=u<jeG|M% zEZ202?l#;0PCvw#N)k4^#bI6wuUhFUu|TyfmuNDpaIj{?Wy~6R{l4Xtk`))wdRnvZ zp_flMsDqXRvW2(bpa@gjOq2?fo@eGRqDzjAQHgR{N0K&It=5Z{Ng`@*<c}?;valS> zPG*Z?UEi2n`W>cocB*@TM7o5r$p4w!>ivf*dWCKB*HLM9tFPcTN#t!Q=a?fxvA(AF zA0;T7;!6L%^ZSd9>PhA9C^=|}@`Nl;DTZ&Wezktu)ZL%t>PD&`EShoN0t|`=@BSF+ zvwtvSVGBP-vB<K(JtBKVDQ{Zfwzm<gHJN87k|Rcf5QH)>W3}xX@=3Gn4iuW>f+)$5 zSgFl~OPy7f`0byM_J^?QQpVomKUSB_symMv*-=eKkv5}c-6#P8`~+K~wdzuOE)RR_ z{re}Vq-lP=CdsG3cT6ly4vIm>C^{F%atc{MdjuIGQ+d#jq;6TjtqtJGwD&m(ACf39 zt4}`j7v5H=f2^w^LF+mYj6Wz*)eP~7tDHuy9&3ArwomubqQBhU(i5j$#B8OVXXJ9R zF|70Sb3dz3W;)Nq<qPd8EO-V^g42+5@i>oLl6&+!tZ8+4LZ5<$Jek@GIghMW|1=d} z-@c8WJ7ngniBM4{jB`QmZt2IGcWqR!EdI+@Uh>j5`t#Rj#C>&oK9@jkZ9BH1dkp^c zg}hkQV`DVeMM_t=BMf(srk*|(jzS&y@q8=MxE^ttXwLk@>1`0*G|Lw3<^q#C`q2o? zd-QgLi?qqb(BsTGUGS8S?t0yddM|BRw5q{x?8=^e7K=9y@9R{}0g+n*M-$ZDtz(_u z*d}(+Yw{q|(_@ufn+=4>8>(*vJzs$#pPe1~A^)kw-?$W}9!~%56N%x>2E-H#P#iO% zcelQchRGuQEx^sAjD-g@SyY~8mv93beCd|saFY4#OC_jB;p8Bk3R@2%6?uRF<PpfR z{e>!)n}reEEuaJ9B+oHyZnWOHo^oWU^Rv3~Z8istFm@V}#knV|--~{Pm5O84fu~Zm z#Kmrdfkq2hKh+C^Y5P)s>G~+A2G6aVl7@a<H*_U@DT57!m>Q!>@Kwqb7h5`&3*P+P zhIHa(Na;X=c6yDHo(B_Dnyrc}VD9VC8DLSkX#^V9@v=osa{qAjEqc4YcymjZ{Qhp9 zn`lww2R0=dvP<9hwe8yH@c=PR^TJt&16`t${9DU2fw6{bwU_>7U>m5&RUXiVIqEw& z(>J73jVhB?M2GeP|Ke~jNLhv3YN&}|6{xa0Vg7A&!ZaS-BJB3<YdslmD~EIxN^aWa z7toHR`(#Puo^(El;zXv+*AH<5qa0V<Kx3qlp_rzFYF_sXg+a|61j25rA21_P3WYMp z1+c_7xx7YU&p(d#%ET!iF!gijT(Hnnzi|=Ez?F&uPfY`JJSf11w&{jugjhfAF-D*p z6oW5x@xO$Jll5CNXGsbMvF{D{ahyewTPI~G(YT|wU7w0{SL~^jE0;JSZ*1`C%p@x# zTZ74lYjh8js>*T%K$beZU6-PUXe-$2*?kszz}K{)>ml5}63}70Rf=CaL$)J00e(#L zI~nhX*9Y>Ak3l`=>{B;AR;;b~!tV`$$NKW&VEp7*($o~Qhdq&Ey?<t@L~-1BbIQ0f z$J>*ql{e{fwK-|MZ)k<)|H&9U)<j-r912q5T0)vtd5+x2NE0LJ@t`xS)*F4&Tam9z z|CQp0=QDD0zBqLxTGa$19=NU0wmqn_L&zMDdB_oq#vB#2zlMXo8Gr<g6A8~PNf}ZK zIknJEiV_y*<JuW(@ue0FsAQWwA~$<KhooBm{v{#z?XD+Ig$%jlxQz^VJ`ncf4y;b- z3)+(UlkYSIR2req%EuMyJb)0<q)$i;;gO=2>SL+;+I!g&-J|nY7tYIvNC62i?OTO7 zNm5;HzXt5M<~vY~-IQaSSl^8yP{PyE<;yCkR;A}`t?s&i!r<0MPIEa&ee>B{R2f)l zA#`(yButiRt2OgF1%Py|dqS2QtXriaW!ay!N$Lq4G*oY6pN&34S_<g`#X$~%>IFB7 zLls{A!}!js#7=}0rE>LP1smN*k$z85G*c|*<0s~pwC;-@AdOZSVWYSnKjss{cLbiN zvtI7$V?HWJ5S&pV)1wzLt->F+>P+CVsWg(hL$%ddD%%KK?qy`YaxfAn57n>J?Y@$@ zJh4?NaVH8Asw|f`==jR+hj&es6m~MmC(%gV)5YTe(o;v*F>KxYEnMbl2Ax5R1_k8o zGUoL_OIBPXj;Ry(<=#C9e|`CoH6rD+#-VIKOerKtEVaJGBG~jv05PKV7yMDO1(sS7 z{_Qr_(==K^b1&HJ;=Xof1Wih?NKS>XIa^+gq@f%7<Lg};dRIajZ|ettGx;;srv4WH z$|HfDe%WshefqmWjhqAi_>ivs+T(78B2Cp9d5vMZqj5cQ-W8}SH@S@rfhox`h#(T1 zT?Y|6Ak5wJ<k{58&HY$AUVKF62@`-mlOVd9eA$vP>7mdMJpvA^U4Vm1)c<DrEr|pV zQ)(M8&#UoGTiBL^<$H|JbRTWgZeGW_6O!4p#uWcD=;M0q$;D-#6nDvmOc>2ZIDS}C z$)=4t8hJzKE=^&itI)lM-7fzS929{B;gjg(03Rjct`g^V5)!8Sd<bs5P=YnDVSjcu zc&Jo>4T-kHzEx2I92TP~*KCM0Mr#*CF{U`TpSa@&8O-~1aWKcz_mjA4QT3hxtxtzW zS*TC1odeVk+P8-BDtnMtEdIDOEK*-OY~Ip$9;B%BlmhGq^}BMb*0tHjh_#hL{de`a zG7sLv8l$Ux1L8LQ`&6PQb-m&>rJ>=X_*nkf-bth%-G6gRd}_#+5<Nf*)15C|TKA>` zHwaqAlh=otU*dggnt;;)hD2~`nuJ8@nQ#VlD%KPgU-<7z@7ZVCtljO$ov--7R5)i- z63dY&qc~GuGV|96BGq@^XVs6tvVcA$rkVJRptHslB8hH7!hz`Ah7Um_xu&=h@h_RI zI-$dOOJZM7TTGj)*Dze4yYXEwe`V+XmL0E;(<BV5HMySD&agUbc0C>&=pcVYP|?-z z<UhxTq+EIL6NwqK{tJ7PFIfH~w%0{;XM%Uu^p2UQmP?JTvu@@f2OtC@wo`!SF$>=o zvr81z;U0Nbb5|znK*)7K3973@OEcu(Zg10SLY+n_XS(67zn(y-9^R~hYJR8gf*EIq zkjvudl6haaDAjeAw0@=tg*)xy&3R2*NqVsA-`q9Q7TNPz>vkq0#5kfZp{$L@H`fcE zeWSB*81Bi@APT3bHfv{lk6KSAPEk*NGq;CU8F*iJ@?_IpFcY>4c4z{vrPY<BN-t>L zBi~ManEETMXa2c>G-LOdgI9Qy8d1sI-RFNN*sU~DDiJ3|=s(|O933<GZ?+soYb~^z zGRvF_?-2*jZ>C$%yJL0)>q1Fi>#{;bi~QAx+S|rH>^EfNf~v(FT~hamaRi%&lxJqp zSB%KlD~G*ki__+z_p4K-pg#j}{@`XDZfYD?ixZk=GhH#}vyceqpwg~6G$p1@?<rnJ z<GL9}hb*}9=^)sKQ~wH$qx{HmNq)64%v<!EwU7wrQ~yb8!gmO~>(leC?L4gbzRv-~ zp(QiBNlPVEJX+@pX155!IH&}wr=)S(<*4w48Qd!;a>QqYur<*GdIxyaoulT~XB#gw z<m0B9VGnyma@sJ35FFFfG3SCX@x7-*Gmz1}O1r;zyvqkg<WJdq<z$r>-wR+1wa2T7 zw76diiKY<T{5n~nVPlIZ2ATyIpMzD5-elum%ieWB4|Z^<YDT2|5pEWUF3*4avT&s! zu%>(kv*E&1-O>m*-dJ0#Ghmq`d~M|^#R(eiBn;xd9UkK>BXr5?aK^*CaYy~IxLRg` z$_|tKd&)of&VAD*ZJXHE6gfljW>d?>o8Es~7J+=QY4P<GJt{4aZU%!`>9HxDcFQeT zZbG8G<zR$dy~POYk_k^{Ni)=ct3VDNX^vTDs8K`tF6GLOBf^|+#_!`ShTg(O%GuHk zu^a437Pm<kxp$kf9*Wa+cICx<0kPrwj(YozhJ8;Fn6^Ak>EWQIl9?zMsNGSWo;C3b z1G#kn2xx^}>Q~s4I+Z_%N-Nl)G$1uPvi2r8DdqXQNjMe8sYCj)^0Z}yUW=)5&QvGu zrKLfbt-5H@BP)7YkiedlW-^J6xJ6GAQf-yEfMpGb8Gn<=0IRaKM<x@{9`pL7oJ>%0 zMH_5Q@F}f3yb?9XpAWo2E^EBjg>Xx~t||#+3wn~64C)9ro89Vo*4RsGsqIXrxzkQw z;xjywH~XrH`*omiV5*X_7cTTzl7<LaZxFa<nDR%lwVbDNpltBq0sM*|Cq{g!$pQ9Q zr&V&0yv;JDc1&7beu)>b+Yq{F*vhRxB=(9_n(gBiiFrmyRP~l8pq*jwBv4xJX@O@| z{0`=6NTM3=H4b}0{y8^pHbmceMHs;wLNd_HUaqhP3seluaz>mBJE~G8oeDq5$CvzS zA|zCr>plJXdv|ep8lkGn0v8*Prl>Eo4tmIRM54u^tJ;Wy#K5tDs(z=?q&y^Ww5W1M zAh$SN&Sgp1GWUmk5|X5>8FBTVcu}mf*vz-|bb{A(HzACsk9x|EF|(R!&IU~o>Qu44 zOueAse-#BvCx~2D9Q^1()k<mI0dG=*AH;J6T}3^DiIe-IEX?5LeALn>xBM~KkbKHg zo6!-I7W-PUa<9u0;K2c?uM~~*F`VR3y-kT)TZLY~f16dR_NfCNvEt5}^s{LD>A?;O zXf6h!Os_?~h7_Sf%ik*yuL#I4&Od;=_0d7(lp|);eu}8v5?4&^J;c0Bv$^9EoB@WE z>w6`@>#-u~hU+wHJc5JAFQ;mOKR7QQ`hSV9G;t;tp%()@IG`z-(+FxIwYeMoDuC{~ zSk<BvB?}>&Ct#9s$nKR(RNmM|fNwr}qvys8(<&44gO;jaHL#NU1gMUvA0k~i`$lZN ziSzvfJlnAr@K|hqt-{!7)c9Yx#c6XVOrE<akZ|%aY0{*iv^lqgQf)erSZg8nyS-Gj zaQf0ja`kT_ZSSR=BFYzRGs=JX_Fhd-f>!VYacd;1UCz59NIX}<!yx*`e%N2JeIRGT zbvGV{57QnNu|`Ww#?n^>dm@35Z?H`t+mb!MzJR#0+s<SKgy=nL@Z$tBU>22>VYu>h zQD+LReU*G;=9spYbE4t0_;NT>?Q^Gsn6;fbC)dnS%^yMq<Gq-)CW8L!(rJhKZj1`P zzm;H2X0iyAPP?5jdMw)<<l_~pqn#vuOfv%;CHP}|ln!<nQJ!xL&2)(k;7PsmvX?o! z_1fAIR_jiEkK*cAe|3snG65U?!y_G%ItvUWuA~O17rpoy(KkhGNNr!v931eDrRk+v z7C}D6`YTan+gVF?ny6qej$~Gn23==SgAQaS$N)+t(pA#{vhYD)LP>2NOi-j0M0U|P zIqw+@ry{cc`CQ)c$3)ylU@oYC64S<kn>wMDmb_0^h#UzAJ<KC5y`1NWHlWlqrV&3k z*0(|P((JEGnZMic7X;$ZO{71o`(Np9%;x4;Q>1oJ`Ljji!|k0k30k3;BA4~wKrZjT z0PMIyo#lR+=oGE@2F_6+p692H<%EA6>E(=T%6WF5LFK%f$&iS%pc1A5kD{*Y5&i{r zdJRwBK!e(QqCVmm(LoS0L>#UWqDQA13`;Ep?jIk2V{`76ZMUEv&YfO357x*lIP|}+ zlBRLz(IM+fZk_{d!`OpG6C%thnXKORu=^z4;61oq9Lf@T%=O;`i(tu<Pj(DmrV{ZX zo<AO+2_p6zzD~U;ya(}Rpxk0x;;QK2cH{yTYWPwurd(<03_AS<MTXK$Ydj06vXU06 z-ST@ex=W@%!<*ogkvM5@eW&92fS~9uKidULJ^!$;CKV667@XnSzb(4LJy=Q5I@~e$ z7D;4#mB(dKi(pa0aa~}4{}eZc)w|WEOk~H*&T5R^>kbYfTCrVmhfDdXY=ncaW;M1K z6oo8vZ*<>ckY`T!tdko3R=4-NNNfVL{nYTe=_1Fd+qex3v6GokMJN-X6qiGrv8j<J zGou!z-gPOLRKw!`^RPi?lzl}##m~Y4nLS6SAx@@84<wVHKtjY}8n<v?Rl<-Qtq_|f zL71ggImtXI(L`KNQYM6nQ%uZzijh6403YCQwbsmkl}oL5334V)&do3(AsWloiQ@P& zCR2xnl|&OzDKxJev###mqa&2Xcf5#3Avdy*r->D`k(IP(Ycna^OjpJk%G2`bzN=s~ zkAOrU9j~X%Uj6z7OG}p-)?nybt#RO-6(p??WuO3-&Ifv21tVeH%GNlif)FyM-9Iui zwIoPJ*0$+MO%2=C`y{Ar&sBnhLOq~0&z$XZlB0nqTLL+SkI&x%g%w5#t+q2D_Bekd z2T`#)fUj$vn@&jGUgyKd6Pry9bn34F!Z*{nT{qAmcuhdrswjQIC-iW~g~?Ztj}4Eu zOzs1FSXGZ!jU8}>HI+;0Pp*R~=9BvrN7DHU+ypTcmo>ep_vDtTx{RAT<;<qW2Ktop z!-w)MS%H^(C~OWu;KGPwNSPSP^Fyz6Kj5T3xxzzb)EyfwONlldsEYki0t{}pk+MXJ z!GYGDZm+pFH65aH(#O+_yD8!e`Wx5SlYK|*Xca_9q1T!#`}@vJs+|smVT;n4zeE9* zxQ#00(Zz`d*<jwev8l`ceZpOB7>W3Z?84Z_jDS;>>d%^B#H*~&)%F_fL_~6iuq|p* zvfs!8Yx23NV#=^CpRr>85Da?MGgzX{sLcS`6qxpK4KoGRRfBvz4_36utIQdM6mDs( zl<6yv=RynexRPtC9#a<x@Lj#D$;=aK@&Q?CBNJ_^37V$J_A^ckt<CWKeoDlYpk?** z0)G}`EO9w5G1#hn{|j^XfQ-NB&hm&DCWyd++ADZtc&?v07oU8g%fH6jH;&0xX-Q(9 z^RW%<L+jiQ!+U_c#%PeH7|!DgOj;b%ezka7+kB<0@Cb(%1tT(iU4KgAp<QuUx8cx= zB8!TS&@pZVlVx(h1eLlxysVO{E$=zA=<_c?jTqQ6)cIZrs}~zeKvG`1Axr<~6ATrE zOs^lR-U-9`Q(0i+P=aC<<Nef($`aumw*jm7jV>J7iQ}^GfM!tzu;X?*&*)UH?9S_U zfCrg*Z3DENy2R^M^-xz!s=NAcZpzu^zAo4!z8;uc`V<Z3AWO=95_1*Vw5xUi&MRp} zvh*I={?;z1qn*nFnBP~dK>14q(%T-l3Q=V-8~PSYm}@^}P?N}c8B~E*z(o}MbA>oa z+z=J&7&k*eom9{P`u@-D?U1IaXAle%<lmzGc>4tO$Mj<x=Vex25vG8-Y}5M)O(o!l zT7s`KM>$gAiuv!8RWrW=AUuxG!)5f56XVevQLc)A-gXI<0atQAE*!$QON#~M209w9 zDW)!Z{#j<rT8GqD@ml(bSo;rkmp)LU_M5}h2Kw~Y+`30TN?EF&uXwYM<Ss$MiIjgS zte<dvP)?&hV~a`jd@Ozq+B@uL^q+tvuTrZt+-_U13mSMc#7$z#CY`@Fs-~=+Ocf{- z*r*>?CcIT6)m{&t{hM@E9&IY*t#=4`$A8Ush~C!*1@eFdt5W2%ho#=Jx4{p)(RD+@ zeH!X0%ow#pBjyE~eCxl9p{`lInsRWH+<_~RoxB57`k!h(q|5wDG?9?8$fi(`#{E_p zdu9{jzkTEfX%uB7p}t#>su`2|@83iW2rzSLa<8-ZDKQKT#O`v<ekkHd2#;M!aIc=a zntER{pM^_!_%2-j5bksGxc%gfCt*2;-XN7t8EQbuG}3LXnrgnqxx|oHQ!kda(a*+1 zY4zXiXCaOyhG|n{J5QoE#9_hpUcpjS%P!fQS$H~P7|TJ*MGbV`f^A9|so~2UzCTeK z7E`meR8y-Q4Y)4h_GZkSuEgPM{=m?sokQM$mbJ`No5fW{?!Y=TEkBTCy#~SzzK<TK z?Mfb0J1^pv!yj@=yy22&;cv=On5RBOwZLTxk%AJ94HYzFfi!Svh6y??{p`5SR(VJV zz}iHeor3Z@3fccFSaj@q$`8`Y(p!`j{;!4_^PlmE<4%P!7Zzd|YFhL-z$iLTEZ<F& z46Z2MhDq>PfBBrCLHw|hxY;BWAa!lX&RVFwCBz|`(%jr&IuI?A+Xk(vEpY1(Cv<?8 z)+lkDniU;C?Cz{4rVBhvSX-Dzsf3Ie79Uo=6WgX>54{7C?L@BU(K<>+VngAuYtlPN z7PNf{ET+TGt=MLZY>Ns{xb8ja7>MEP4$EbVz0r^;qf@#;vKV>bvPx@+c&B{ISTYZ0 z6t;KbDTaSJ$v#SCf$4+v-wdZV*J=k%Y<f7c3wi&wNwT$ujZaRJ`(pKc9q-}VM%-Zn zN3|^pJS5Icua&;CzGG)ri#8Q~>V<UDps2&-aT)PidkxqY;$93;Jdby?R&%T7fg50< z&GV#X+=691T{~3s7IA|XoXTv>wrZ*T`cmO->=$d97v{o3C2jlJLcH(EA(Efud&=;o zwZw6Li--K^eyS4y+eyiK6C+|moAB<gVcz~qBB+X$fD*umS?GzD6~wjK6@uNBG6M+_ zg)pjgp_sWqS7kS~s4q{mCgQEnztaeeQ8rf^dV8ZzbhOmUv^sVkcnq0&ZDFELQ6UQ2 z)x$M`Y(93Kp!vR%JLGiw%cE{dmlYu?S(4BSd!yC6Nt2Wq6&$#L#$Zt%2f+^nFBsJ* zx6{uFZ#dBMc;?^*vs%5z^Xi1^Qh^8;DAFB724WaV^xC+Yv`pdLMVlB;Ex?>0>mEeg z=mC1}(?NIgz&eX!yzQK5z?-%J)|Ya{K$PH@YT1Cs#r<BbV)MBxB+FvZYe%Y2L(-q* zLu&E>@g+&VJh%1RyUX>V+AvFZ?q4q*!-R#_9GS?ROJ&VB9`r;o0Me3ZY|~Vut?l*{ zs6;emz1@Kt&NU!ON54q)J#!GNVfxOU)L{+2{)5Uguks=}I6$oaTPs!-PpdiGt9?62 zI|^jO@CFSuTOF209_DIv4qRXg=F6NtW|br|_blgXmWL+C`zFqMA}8^!b+t7^9aG6o zD5@Fa*mN$_r8K+)geDP8$EHI{ke0i`JQJ3$qKlD~A+85Wmgxcu>rL4L_QYQAJP$E< z{&7}yM%A=bPe+8#E{3ch;l3oH-I6j&^3cb5l=oyEIGUn!-xnTwY4A>T*jR`6sns`m z=WbkFo0VvLg?{+Sdy}9z*Vy2R+s>|oWjL1BSpb!8Ta6JSZuYJas-X9HK2_R-a~o!n z(MB-PPS4d(^N>QOR8lm=a0P1e2Xwy(@dl+!xq(lb*cxJG`JZ>5{H*6q%!yZNXI!(? z2WknVNPLhX{!HZ06b07;afe4kSzqOxmdX>{1WQlkf&|hw&~IEHW*=>b@hHaAT4CzD z5L4_RLI2vCNe#E@y;h<cxOB*p&MY$|6keDnxc^k^GwL=|Xdq*MX4bfnB}U@myk`8B zVkA&6_{i#Fq)q5^ZtX5j4KQm6T+|dAW1ZWCB$%a*55|VW^mdxt0FV2Njg@2ge|J)Z z=W|JfPm_A~Dw3;u6^in~ndJu+;Dj0*TDA~m9opan`<mhrSLU^2nle2jqVRBk_L2TU z6(MQW3Ia>J+JMq3sWo3v187y7jk7luUVi<Y25xa?tg#5RBCNFHCq7n`5ZAJyEHlX) zlZ3jNX8OS<9mJ+F$2_(LoPg4repUqDkbH;(uK&pI2$PFRE8ZG$AyScY0>L%BV!W>) zl}{GP7IJYR@0u;LThx1WOq7aMvENvg;c3BD6Kp>{*(%RMq^!<Jkp6qTmNhW3*Tm<# zRa1in)e`X#sk5u7Qg2Av?5Do!^6VKpjeQHKr#h|fB_a+(C|F)R_l-xH-*!>m<8JRn z)U(qa6qI}p7a`uO8I>4sd+qbG;n!hfEi_-5JSw}mRR3rSmFKewHs@dNm*s`7w1R!o zrhKV@q)(3-Y-R4Yt&Tn7A|I@3$mwI?o||V8vojy`Ot+0hrzv`dhpL3=DIDrz+S-#2 zf~~4U39|RHUuXGXF<BtEw9}wuU)bg(bWGc3MisOl7z9@GHg^BDG}6mtA-i-U<=I5Q zc{eesXBC|iJn~^q&4}0!@hRKra{X2PjEW<FU`aLwNYS9qqmfPLf*nv_qbQ$lv6^6> z9JFEYZL@+e(WoPr-_tIfpI_%2py9=jOm*j1O3T96ZZPN0GOF3pSo50Z4)DBFRh~{8 z2W!wT%{jTG;qxyZh6VaHT(y%xvcUj#&pa%Dbr>co3zwQlPJp3{8QzQhyunwigrsk9 zTWn+xD2*E55Y4fwb#P=YW-IjVk}MD6qM&TS8^_tLXfI0->=|7H^m=mHdr3ngK)vuo zOZiIaLNY)7mAD?}A@9IF`I|o_vIT*{eE;*A!LCpBfDVuV-ibmYlIp49KV)9v)9ozE zZ?<rZXn*kDhu*OGhYrdu?UFA7bw!`}4^(-6^@zS;hgK3!hx`8^!=Sv99j4F^%q5)4 z0HaQ}j4kn<4O!SL=kNUFX%m=9HlXd3SgAEHSZUg(B?svLhEKR@%t=3%yDco)ku=oc zWlf8HL(eZDHQG4^he{6Ryz=Sf?~$}#=DdR27HBO-Cn7b9oYL@kTs6E&8l5%SMEuox zQM1!BwW{f)xYyVTO?VZ4WUrl$k-?@qN}PV|O7$W~xm(cdibrocQRSG*Hk?mR?>3iR zOv4QJjEk)W3|{m}=Nn2hBfiGK$}eX?($=0v<cbLX2%Xj<K{bW-qjomBcJd1APcY`^ zOMHI1)Fa@+i_Hu1y_V(NQU;FCHM98D7W9Q3M)O*>Dt3<gKs+*8`|9v6Kh7EZ$0fX@ zZXB0_PGDa5x2r{ZZaFd2CHgS0k;`H#N%S9i!*P}W%))Y}1ryOTWwjDCELG|Vdng$6 z!9n+kebI9L9Qj2&J^hd_KddlCtnaD};W*ZY6C>G6Jw`=6NGd*)>bTF}z1*d(@_RPi zf0`_SCC0pf2ERHjuaN_8idM`#{w?#zXjttBHMVo$)TEqEwfYJTKwIQw*{5;r9+fc8 z&~$K_P-Z{Z`o@Hvq^_~$c#C`elV+4cu)}7%PRrsUOa3Ab^3N)+xdO{q@HFdgoSQ>Q zzE`y?CERSQy6RYvB}pbOX^|p%U}3;id~6|r#88~bQFn5JthaIZAW*a!&Mi{^7EIDy zQmwF0PkJAh(`MIypQElfw$w_hhCPbvK=Et~Ga|o8!rdQ2Gtu7}*fKM2ALDLAky70X zJ`!nQ_oc-~M`X|6qL8O^uNlM6e)7o^UA@pbO+S_ZBHZVPD{7&DuBS*8EkN(%94GV5 z3?BXmn*d*RYe;anLC|Co=y{1vK`d$GrCA~Rp}IMt{ni=Gfi$2Wd|6#3Q^87E&-J^2 zc1^5s-0PtI4iB++Xz^B<$tE8WGRH70ZZT2t#&_srB36Mk)-jj@+W5VD%&?DW{pJtK z9rT&N;{U9*(<L2(EqbHCZ`;jtn*2Q%VI{KH$VS-xpeMKMsfg8OUTpJQK;G6>40_xx z=&2d`yAjDS2)<I)XGCn81=oq5Pd@#bbjz2CRjM<j(b=sGQp?z66j+(a%%QXNjYaU8 zJdSn}Xb2_IveDf~p3{ZU&*5+bHbsgw8q4FDh5v|aLuxLWRmH+cf_kO<EUo5jk8*Y` z(PpaT<dP}_f#mjIH!ZYS{kG)(uVeS*cUJb7Ja2rF!?#j>a~{qic3>fnreRNYY5^)w z`S$8LDy|?es!%U2Lq1$WUFd0jC7c5dWc0kQ%`p#N@GC442ZaG=1@VZHK&^&HgxeFy zT!sce8@XeQ+Q!U~xIGADc8Af31DEEwzv3Eg7Nay+HaSv#<lH3V>?S-9^S!{M9=kyU z+JCh?8R0kN^Cv-;#xMcht~$y)4nvc@BcR2Jj66Zyi-tl?_{9oq`~e7&?mZ&9MSGL9 zCQ)G;OOr0!uYpaIUX;Dmxty(shUzVOm^b7V4a2&N5_2|1Kfn6=<XsI8*#wV+b&)a6 z$bxewm133RvHQ%VezW*2f2mZ_5Apm+FcDR(E?ydpUiUJ!Sdwu7j<!Ea?-gOmMVU*~ zf<-*N77n@DZ)l3Sh!E27%DGp*bxZ>j0#WIhac_{fVtgnERbXjLA}WP>v(!{Z3FV|= zNm3-T0kH<JPkKHpq2ZF&eI?fQ6eF;jaJI%p&D0H|BFYS;8Jw%0@c11=NB`Wixstf4 z7&Y>jW&hcUcSOk%0V9SLvP{$_m>9UnkgPdRYm#|*z&1s`j4KX$x!yS;uAd=%aNAX! z9ZUChxp@YU!0DH$VF9FzSU*yV_+zB%>^rK?4sL_3v$>y9ll;E8Jr~&1E}6>BWIM;6 z+L<pvIwI?=jAH5@9@|Bq=g_fCQG<=gJ^9RP0_lh|ro$gNtU7Ne)Qfz8$q1G!n>cNd z(xzEU#1^IO^|y;|+=PwasQi1T8mX2q1vseD<u@`J%xl?PY=IbMyH!Kd3#3&tn}ogM zsubFTegHUD#I+g!9lDk466#QMAB#!rcj%c@#P@*?vs1o79nP}nn4PfcpW4&vr*980 zBM1-8Lc2k9<-wXKc2$_oAv3{vp;jW5z1GvPDS@C;{s$}F6%MvDF){rG4@E)D7u<lF z6fduC?=xrC;PcOgrt9Zy%Kh)bI2r>7N!6h>XRB9y+VrwSj^03%a~$VTx2!Paw3BR) z!G}NofrLrr!!h0z@|B0)AN0#-?X2$sq*Nx;Kchg3|CY%jLI3-nVA)$ZanFuFi|C>V zwKO&_?ozrh$;L_T(1d*N(P|IX1Brgn{YX6MWB8Uk4|1-C47<mzgRb<9M~G2T0hcBx zfP++Bz@hAR^{PbeGD$8kGJ%7K7N?OeL{{8Hq~;O>DSIga8G^SQ25xZ^s(gQhtQtN; zK4CG8?3)B3{kRn@NpgPtSUk*y&tE~ag7woYx4|U`qIp%G(U@hUzjNMB@2;XrclR%# z&6lK!%H~-UOb!Wu%`fM6seEi&V?$5`K%OU9fASTVT00GWi=^EM>N~6%HNb^XYf_Mt zvqiJ*`7a?Y<0ZJ>#}w_V@FwRBpY0LYV|$X1L-%W3A<O7Y;E3PaF6AGV&*#`?9PnPW z<HB^_iOKtx<Cd8AChk`N>0Ukbr7Lrkp_~8dPnwTeF#Iw}(bHpR{ycA+&Zc7-lf02p zzdc;=IXZhlvDi+esSq+UyS4aTs?>6nCg1;jL=D9GhAAX)g-n^9WN*eLSz_ktlhFO= zK(vqRT0*q8^{D=|H_ZN`&o|#}G%Vgj2xXigZq;?58(5B~Cix#|pekWKR>)&*D&9U& z#eu@7rV<QazxOq(LBZOu3az?09q~_yMPCU0;9^b?v>X;GM5U&@$X~>D+_z<tdRmnc zD=?WzDf21gsDOE=jPteU_cW%O)9!$!Bz_|~GGdxh7>5&MB-xH$6=g7o>BW9zBI@}A z+jNAZ8(p6beX7K6hq%^1R3a3#&AJu+3(9d#qq&PNq9zn+_LE2@3OgNZy6O!DV1aN1 zjVki(z>m#HzG-aZOMDp~Ydu$xK7ULMW6*aI|89kvq`tU+o@vc10ppfR1+jV81xilU zaL?s?#KD#di)yUdQ}2q;MV<XTZ(v1ZDlMMZiZUfbln}3-qv`!6+T-NqgjrU7BCAD0 zsvof`xrz|Cu{m+FEuQ>Z0(sibo}O(kB{grDWu|xr(L@2kEA-&xlbZt_>;aIRl{y9W zLtJV0CKADbl?Qg2339INw_aGU6gcWUh6)QAVwLJQ;|!=`xbA|36=w%TAe|lYON3WV zqDQk}ZGJxm!UcZ+!Y>`D>Za(Hjzr2FPMgiMm&i4B=a_Ri6=TWOXw$&qhD!#`82&~Y z>8DwA3_lo~@0BT3^MWF~-ml?Wbg4cMnG`z;Mn5)$P&!BRN3P+O-!G-`URbXu+!)(i z%^W4Ctv7-xNQb9a2CIRwMm<fZ^c;}JCv?1zBmmBDYLzhiGdy%D`4qur*+;`kxXN45 z6FgR)Y?Vmr!X`oTJN1D9y?d&VF=Lf8Iq>4XX75&)E1xJ#q8bNQXWwIVzc^xo!KRpk zcPJ9gc}1HEejeID9b&)%2fTe7O~hN{l9QmZ9Fh*S!eii&qm!#n)5iv^(C1?>NJ0{G zOY3J`2>@2QAH<^CBpiR}6<7_%SrAJ|;7?uU+w_4x+sQ>Js)2}7kqpuvc%Y77vXf0h zNG*za{SQO&D}Y)`z{2M}&i;(z?E*m&O~?w+l_WFjGv06lGj&c+la@)6#kb1{Hrk}L z#&aNyw6^Oh;@(2H(;#O@6wO6FCTRg!M2T3fc2;kD6#c{wZ*azh&x||@+;5X6>MT5h z0CrW$nCCe%VWW`ez^L~+erIsM_`nK77Z{LA+LIBi=vU5|Lm?=fBeP%1e0~I`f|VO8 zA0rPoqh-kINb5tDqXTMycacp%duXx{_@HH+roHax>3Uq(LEWAgMD&$d=1r7&VVWLL zq}S+*9+-o4owmRp$)_HQDD1<#)Ik(V5GOfp^wR*JGqZI^la|&o;3(o_A2y_im%Id0 zARI<54-r;aWCX&DsT+YktYd?~B4tkz+=MP5&*WlKs?!8+TC1y+;^TB5m&_ar1gkd~ zp2j(J=sL@stjL`+JCSTU+RE;fj9aq5n$?XmCi192bB@5G0{)wqhV~S2G383(;!dsS zuqF5Wn;u(0UZovKj;`r}>U&+Fw}@LBElgFg14*NTq~G6ejyyz@INPX2jz>S_lYHMf zib>U*Eup{>8Ung{O&$W}w=$Bm)eUK|6<;ObH$<(Qmf(W`5Qs+4&O5snES15=le4cl z*bDoT5`x&=@lKO_0+0N-T6Zpho!SreaEQQEN-h{)G@!0vQfb3z)O8{{Ah~X#3=e5I z-=lD%locQ-p7tCalbrhlCny3s{E=dgkLhBe8gg-STJzdCiCSx3k$FRvHueXaswPYH z$kRI%%>W7r<#r!H%1gAfX76p_I#~r9YYg`|<~2_VZP-vu=@{OLrJY*43V0lGY-J~u z{G{`XolLRJq;VD>t=y1d@Igi8b27s7<%!3ul+Qm-77HYOAOba>--%KrM!4`CpAv!C zUrS3QE}rEKCe(Kq6)i7)2>p~er(aS%I0?OSyaK@-&qvb?5JzshV4XS=j#h?T78YVg zsyFDa)0d9wqig~_ZAmXUI-t#Jq^8(LzA^qIWUrAJ9et>P*2UEg=sSp9tU`A9J^FDp zDVn>rE=s+v>hDRS9{gmmL_J@xD@lQ>+gFAnp)(pxr9#w)7VICXYiV}PuQyrXBjAPc z<sCz|7Yjv;A@5^=_BpJeSQYqZ@Rk8qgz_W4he+aHm6>L8%RWsNSfmOfgJ;6@saPKF zf^8Pfng9Cw>zb=RWz3L<ybe_uUIgTBkCwCRp^PG}18Hc}23s{Ftr#iXZ7XhT95(Hs zt^BlT_K#+iXPp`XM3GS}Jtk1gtmVkfg8NyG0`sQ19W}$doDx)u3Qt3sll-Ets|>y5 z1a48hD<mE_@#u!7Hr~eme*iH+&c9r=>>9o;{>#tiiKQX@3d<9<rV<t!B+y8;eYTtq z*O;0g1&rmtY=Dhq%WEXmFl@H6d}#RtTN(+?!jv=*NW|5KbqH^)L5GVdfmm|n6eEuc zhR2T72$L(mRm;k3mf8!L2LSjWW|>?sip)N|gnwPES7LwS1X1_FenY=A9*wL6oH)<6 zoa&D5jErqmAQxInR7!E;7wg1mfxxJ>;$*WM<MiTycOAWkT)a83DgcZ%(TK`@S&<(F z$l8UF17kebN5H4Ld==M6wH9Afo`b_yuI9w3t)5XUYqN`<SIs4KSARi%|1t^nbO63| zxNlc=;h^XKs;UIj3Yjtz<MiD#Wku>+Q&&htv}S9Ws`>K5A)-y<zkeb-c71?#X121= z2pc?CEp68cGXf5!0mO0FAXe2nqZ7vBnGHy2!!oZ2_$c3t^@`N0<f7!KrA0ePiDBt# zZjLPx_f8I;lJAD9Ihl&82<{tv6b&8UhRchfjO+=$0zQ-#y?PcmDd^#at)k@&Z2I~! zqplvw+Z6?#vjBAgjbUJSqEL#wa9l((8R9Xa)7VikS>~ut9HL-ojB4HbOK5YMx*K3? z67ns!4ELLo-F7JTy2CD`F<}S)PON1l0w006)r_J@tz>}_7x@@OH5p1i1~wWkmu$XC zac{R(9`eT=%UDV0Zk8Cw)E~W6Vj*fX+Bl$g&y6DKeY8oYeM%fgH&xW^;@mzoHswR! z%}_|o>R4T)a@4RklWv&y;t4Nkg9Z8>gUQYV?P{KZHJorZU0}0Sev1;zmk<xbwf}r? zpb7la&6A~7mcjggncv+EK-162{fLCozK3QezS<c5jydpArNi_}RLJi3wkglp5p-TO zpqN7ZQFS@B+S9I5TrDcE*dPL?{nh<|iwV1A=VLB~$Hr75PA}#}h)qxD+mF?QNn-kX z44b@$a+t^L?_jTa(@QD2GqPwVJ1-Q_t)-Db2%KP*uMm)C!ar4xjNRMAVCJilgA_r1 zs3x*5Ez%F%SQ?$5uR}upc;$n8ROQP<2|1mz>*Zh!-I<GohO^&Rw6JMgMB&zRy=Y=$ zDPTJpc-MeMxOc!XLQNxQXuId+YYS$t;>D&0iX$)@d%d&ta4p`6>j>qD5M^Z_SsE!C zoL4`C5|fu$+S+lHLH`JC7YDwJ%YE9BVd7t6o%Lp|Pl+TvdT#Uo22Iz|ulvJw!PON6 znuBJ>f2i~$*)0m}Tw_Q#28MRH4FDVn!%TdFP>X~`YoesM#5B|^Y!K4yOsT~Y@}x1^ zn`_fsG)o|RSJ>5q%COpzFaZ>3L3s+|b;meb=>5jy5_W^dx0TS14F#yV%o;7t!Eo{! zGeF$%V-=*Y=Lr+Ti4`N<qbgoSm;?)6Xeo};_?ZwS!_Wd?4l_MT>_x>-<7LBhW9Ife z7tPusrnlP$b1ZS+M`Ua)3sEd&*Y+_lf~Ua;isR_C(VDCpi>i~x8;3%#SODp7v0!^A z8uHTU|1wd_w83{?D#led&)8Y$hMCD@8{;E83%uq_zLg<r=N*gMbt-I#zpyK%#uZDP z;i(w=4pz?t6@uy^31$HW?N~Fzm$U&(uLyj}^tug!A`b6s2PIKY!0~B9#gx}$N;=0L zG}WLKsxgtv{#u~1f)U=uHwhesBss8Zz$H$Z^!>yUNzIh2j6-)ecwkH`N8(=~SHRNb zKR~-CBo~w>u3p=imlc-_ErK%ELMWd`7iJ53IVD1<P(i2lGP&a#gewJHuJkz&8ExX% zm+%ki5_a-e69WH}-{Y(kNb2B)G%A{rGpg{9`Ug+_w=esg$j4VEmO_C&a(i}jN*j$H z=xb^M&gQp*`5ltI3$?Kw5O1UlDI5l={C27QehB5dl7I)c3Vc6b;7k_(C9h2V#Uf3H zK)0GNZ(0WjvxGsPG_;t|E)9rg*c+_6CI#A0uQ|{Oyj+N>&;~xO2!>8<a#zf?59w`E zY{SR1ZR*D0INq7ax=9~uP@+uNA3kGN_m|4S2zg-I3vcFj_4iXs2Z_?IO!f-FD90o~ zr$}Mob9yORCc1)!=b*DN5PLCGTi8YG?*WA;NJAl(bu{L4pa(76#m;ZZB>zA%&XK7l zBTCX3n$*Mx`rzYXMqcTavZAC-oCwbcoa@(#Hv;CBQL7V*Xqkwo^Dhl6`=UW7dEa1g zL-op%ujCq_Mmj8t#CI+|MFE}dmT+FF)a+dZw7)2G5bN@FndK7dz5z&0m>f1%L4s+Z z-CbB{3a9hI)cB>Fu8(dg800=5aF(=bxA}Tl9kxhO2e&Yt%Z3YS02?~nl`7MKAccu` z-jG8V@>5@)d2R8YJzkmdB130#g7Ov|YIDlON^>5T(uLuyePYb@kJ;^wa_vKfZBX`% zrV;PaC9Pc&j+S?&e@~eHzYkOI0Y!n@(v(ET69RL_FTn4Rc;0{qc>xNI#=Ly-u+;*Z zr}@BfRBA^7rNpK797P3xJ=6o6H3AkGhzTwsUv^l7ks$YnOSg4Pfq7jwWjC4`SlJX# zOcMd^+on{0`$TgAwaK{o|NDP8|6=BZC8M`*kw{Su$7%>Vi|?K|!iT@rL`T^P>GCfQ z5&?w(9FRkx!X<4It`k&Zh#gh-1(dhQqtP&^RdH7ib@AbmkTfR~REB7*i?`I7jA1}B zmxJz#xw_`zYf7+%+>+UYnHc#?3Xr9TnZhZ^-_xY2ChH5?L{rNXa>5b_t?HWeLV!0A zYBzl^)H1xSUQKg_i!#eoDCNTpX&YY-Xdh4{A+nRiT=?Sq)~hoq*<Z%2E9^d0LsVD7 z_Lq#OOf=>BYpeR%Wy{?j7P+s~LUIY^*p-qgawCf4@0H0^{(Uauu=ty7domU#J0cyd zFBEo_1Q?D?5EDCh8wg>spi08Jch6TGdtspJ+EcN%xC=${L?3QZI!&XpF&|W(T)qSY z0eh)25qpj_#g+js^{*O6JKM-Kt|KvG_cQo<nD|@gBO6pJxYV)KIn@>3g2>cDHN7Vn zeG1F)P;RJ8fanjV74|N<LGmHZ^KM}<vE_%5M+^GnM?;0SN}Ow{DidmcmCXt_;jJg0 z6ys5-m8jFy{+|Y2D!v-7M_bA~OR*m8mEZLq_No^O_o*m|+3?`S34lszEul=~m%_>w zaq9E83o&kg%#2<#XV<Yq_ei&II8+f4dwIkbMgz;Q?oGRz0xaB?pSs!8;SUdkOd++! z{c+$C<r5`MMv-ez;14L6>>P`huuu@gxT{aQIKy68NdN}ZhZo~9y|&273W@jc0|bn! zO(knmO50N$wD~!qS-mY^|5d7A6w$HbEMQtUpa_=JZHaXh?t){B=;Rh=si4bb=5cv> z%=u$+9sfku0uo9A+DYk|dAW@G-OB*_inTq3E12vQH_bI(E^l4S3>kCA#zKqbq`f?@ zDzhW)_g)O}4MRXMt~Sm&1+6gSIIOP7N(jBQ5-(KWc>*OW5YT(>Dj3PqWfMlhk`KLr zwzcQ^+k_hwARKH#rWh4(P!J4R9vIr`%adOX-g0W++}>3C@}sszLCft~BPusy$_6V5 zdAMeiopR(I%(@=EP_&to@A%YBg?#A<629MG0o;rZh76#bE5eWP5hXE4UomP(rFwB^ zt1ATDPZWf4NKx*G-~bedJ1tiHmexMEyML(vI99a35vyMf<ijEyl;he`HRDF*m5u$5 z8S$4Y1kT=1aixYXWC}fyG<K~FSJQm!7*FnV#b4gveMcqx$^s0dqA2&t|2!giICixG zrFZ`q7E-0n(^F+J$Wh*iUvX*mPe^Lt7)}vw-|)I{MV$g7``2owkO%vFSh62G8SjrV zxr&YS#RL<DcFfLy$3gq;_>yS9jV+dl-N4g|E<h~}lUuxdcis(h7I~cX=-%1|aqlF! zU#H77P8MMNT9XrURYVX;>sV)^IfctJ!Y`Cgdr6oHoJY<dAtwxUICWfnIu!i%j$NjJ zY;2Z4E3p~Y7e4KZDbL+gsDAF4{I=&|GW=?X(B!)+0rU^oO~!GBy1O>Z9<YG@oZEAA zK@!&K>X~dT{LYfaa3UB&WGwW>J-uyrjMBLIFZaDf*7)Rqa>LbHC;WKu5xe6BAQMt1 z_iHvW{6H}=rvsIgp6JnRrM#1nq6VR+;x*iw)6Qt?ANCecH>o5B|B~iAR#3_%&`0t0 zDY6ltsmeYEs4zGm-0)?oHbwSk6z*^b3}G(Cu12T?a5yaTuC#%#u_kK(1P3Z95@HW= zn?dmSS*AI<18h-qzYfnz!m~oGZdw0D;w6Fx+RlzFFp)kyzlf0ZXQFpl3ml*Fp(m=R zJx}veJ#^C00FHV>;a2j(>xor`(Ocg)uDM0`K@98sfqaG*VHjah!bs1^AoO4gpbenY zJGv3?H#d87=uX<aUP-XeX9M{jyQz6lt5-HiD7ZL-E5oe)brCLEnXEXh#<PD2;l082 z4Qtt?hNg?-n(qa+-N+#J3RvXP9T{m6(dS<pl=(!|Sb-%R`COVyj^GbCr|Rhv<hpm% z)k87h8Y^6aB%55t1(b+*+|vf`_|GQ(@iG0P-d45WVQEAfwS-0h@5W0kt(UV$hWx#( z{!j;X=!MF}_9`J_47(nKn@d;zH&v}JDUx@s!GFM9I@RxeR|lk3UUTQ{+DhU=TYKwa z$7px|;Q}3EtWp0zET%k6OA&LV_y>CjTjo#wvq*U1N&x_Ksj2WXMpyTsaiFa9q!RYH zW1e=2(h>*iS`s4C!WK)3X}g=?(tm+(P}Wk#hY=q5BejCr?^*rLQq$?la4NApGTtf& zkPmpy7-p1LAqYr>cd|t7PP6+x+dMUn<x6Q^R0(5tyFqfk3Ug3%5_9xA0n~UzTGI@M zV|S<SDGZOviUmN{*BYu2%s0AlL?i#NKwv?@guTkBm!h{#xJ`@zp5N^|8KPh@pce!~ zYWiP>#1>!3R10_WJ`02}YadGA&XIL$0)m~7OfEH1W(G{lpCpV#pF>sVU$Mpz>aMDf z*HrR0N%wua!vE1*U>`X(Hr+iT!L$v!>MudR%=whie6GP3J1FlDOlHF-FNieTmwp-Z zYZNHYA+&qcXhQq;g_#h5<x)l{XsOIxclo2t)+`n<?Nvygd``#BgqNE&NbGAdyF|Jd zul#dDu}XDOHoUUvP~*8L48m803j5FrUqxY<)RmhZogP*P7XB4hk?{*F!(sJ;M7BZM z)s+G}H8%k^0nb~UBm927ffwxf&n<aHN$iAgVp;s+nM;BWZTB0K98~kQsfU$$Qn$#Y z+zJ+CDzFUn`xiI-x@{-^<L9)ktX$Eg^L#=3(FpO-*W*4pUdD9#yT@$9P>FsKe9&RE z@2^fdB_cWi|0^{#pCo{xHfW1g2DL?-TFGz^@Mc>-t0AHK%_KTfJ2GCG=0u_{LrJ0O z+wcixZS<P~>fWur3>A4%S#xo`l7`UxOIJL=B*-R{s2$8pd|oL2a}rAG^J&67h2XHU z=-b;z`n#}6N9#*q2|Ld1-;(e`C*bNF7a-f8c>ne}2b7?7)oSN|jBheJx-`I#DOd0S zX7n%gKfrgM=9W^@MNPYN$BzRX%)blBuB+?)mQc*+M_LY#JT~PbPaYY9*8|WgCiu?H zPmv7v8LXS@h2=bVS#}8v7SL}*G<OJSaLEyBY!BwU9&jd;!Zp1O5lodJvoVU@J)$dN zm#J_SQhr?va7t>7TgP=gQw;JFY3CP=>IveT7Ht7KrIJ_a)}lfEMiPxD8<}rDvO=u1 z@!Mv}=<S?USLBdgzkQ}FjYx+Zn5u{;4L~V0U^=j~ov=!!S;m_k0bSQ`w_@+z>u1&) z8uNm`zM<S#OX6BHmYyv@ueRQreenxXv#C9986YII&c)A<rGqlPP4m>$z6;4;z-=6X zXS<`q-*GVC5@DTJyEF=xf-Nb6;R1hEc{xly%9Jz*a+6Oxn}TT9*>n_WH*#eKX2wZ} zSsIE);@H{`nq+2iLn$APnE3xsmr9WnP6ez#a$L1X>D&ryH&t*fpJJAPBp!|$D5K{p z1(H&3^-O2_myBH6P`=5Zsx>f+fR@y)VT~&-5@ZI7c4*&EF=N6JeBqGeCez}qOUdq3 z1_;Bwqc`ws1E2C}76ztnzTSRa{-Vr3J802fYwm0j_Pk{-YVAD!j1>XA9n%l@3q!F@ z$1G38ZV|&oM?V63FOZCzTbJiJP(!<`2`0po6)-<U%*Ch5%tz~e2jPyKH4C7p&*#P) zH9x*MU+#jZLssg%@u(QOZ0r|NxX#0fTPBnQnHUX>f3bQhg*bD<PV3-}V4e+m%oor& zJp?M@;EaT_jb9VH9}MXR(#@SPUUn+Wr)k7g)<YjpE%19AARF4+gl)q222x%NiOVtm zL-t9>WM}?pUZ_frk8wx`yC7|=?f)=-PTQMO*s_5nLOQs&?$VSSL~ftNlqr&d>SE9E zBOu#fd43dAlP)||+E6)0M#tPr=nWlzmXCH!J}SY1hU{j$YewzSeOlPd(<IH`-uL~f zT+nSu?IFOo*}+`9YxRv1Kt8k1xNsAMSgc_(=~B>DQV@kXoN!_=f@vr1RiOiQr6V;r zq;_N%F*HmlQ=(nLlUkifGke3P&rW`MTzxgW2OmOxWgZX!-h6IEK{Bhusc(HPyC5gF zhPP?*=b$r}P7XpopkB$1vsMWD>`sc95+~T#IQENkbPMoONMB;>eY?D$Egz6*s<%k@ zxcE6w|B*T@8C~uk@q*kiH^4*a7(`SD+AAf}D&z$<^antPBzm$>k|e?i0)*8#chcg$ z{KBs=G!E}{Q<T*mbpFP^;v~`|vkc&`^xWyuZkqCEZaj#Ex8<h&FF>YB--j#2{6k=u zN>~s+1EAa1!)5|{xuAv#X#IwlJcvUO-%cNJZf%zWojw~B2c7>No0u%#7n<($*SMy3 zS!D6Z0$p9^s}qQ#upDZZ03+Nw$5p|CQloTdj90da0?8w7kqvAs8`6!TSSgh~UOO;4 z;r!28TuB#oRy*--wD8V@;k;y{F4T3cLZaEMTb6}U)$?{N^5ehZ^<+f|t)&zzl!bPS z`8tG-ZSt8ih$;gl8x)7-AT&-*zSw-h;S7-Smpb+6^9g<Bqo3eMog#F~*v=i}lM38K z7(nuefrvG3?I`<cPtS`xWW>j1&ye(1(q`NMP^ispSJ*>0kZJvnpe1&&eamKmS|b}R zULIA|WB*u(-w^5;c{*Kum%!U|T>5<5a@4t7^vTuk<aej_S+aO}fwYWX$<6!2A~INo z_k&X7*|Pp5fVnvFmvQaBe0S2HP+CO7)!<sJ1EVv&MMV;+gl$#AhO0(x$koX(HVLIa z!azlw-cKZbfCzM3pMaygTn8#ls11jKaFDMnA?Hs6U@=VJvPd%SU`o}4@9G*BH82}W zlsD8yf}&XGwi-x$@!c%PGro|l!}DLF*pEepw#rdv;of1srk|A9Ts8@*#@N5mf;5cy zbCYyA$MZic7FHpzAA5D5ZBmHm=!!xP@V%7Y)f@rfMV>4G;D!59rPNKTDs=$$H!4GI zkls58CT+l)wc6ats?GH{aCIV06Y*{q0fjXG5L<`b{nOs0zarJF@u%7%K;G@VICp;F zH>LXql>X$_1b@2AxPmrYukfd8a4eQ!?X@5a0Nbou<3Y-XIhpq>8xhP-lIz9!X@c;I zq_uh2aoH8GTV$r~D^4DcuUJF^5Bmhk_Y!f6LeCtAr?XQ5x<j^=CrVlill#;RpP94h zUB=pZ-EkPUbJKHYDo0d<)P^`WWH0X7!DlP8W1G^U|AqBrkt&o-!AW5XPozaupkHuL zxEcDl(IPz;M*MY9C8E7+Mi-}l9Ewbwtn2XEZ0u4Pnc%RuRAcNm19WW}db$-h;uK`m zk2gBO#yyV`;jOT{&lQHQ<{G0dvuvw+2;bYw!!9^#)JV2Z5pfGur&+)i&^GO0h)Qbq z4px%cU2%eHI^l2$eH;+5F2cG1pV?CqAL;@HLd>}iPbyK=CE=Jb;s&sgtPiwVkGU#h z&XG^c>KL4a0n__>$l{F(dushk!K2%$?QgqosZNvxJ&U{DEZ}sJ#8_C<v!!M9k%cvN z(Pw&taJtPHg2ALKc^;J*k#DKKQRy?K8X4mW`Cn$oC;qeHw|OK0o*({%`Dym7J}GWZ z&1z<40l*It2Ps_s;-ys{=w96v|JOb6L4iqq4Da~n0Yppnu#2^0aNRELlcg9lmxkfE zraQ@k69sGjsPrwJoa|6hQ^QY9{vGLpbI~*FGqPBt%Mfdi03M|U0aRFGSK%J&&qRwp zu<QHIN2TYVliypuOo$4wy}AGrS!kv#a@^KDMq9;M<-xB51p*bXGZi@XEkSc1MUbs9 zT^JeUPlYfYh~vf8*G1Kd9|T%Hzwo}G*g)P_lQ~&J!$aNDj+DX`NDqYG<kY|WjNG#o z4K=vn2xG`Rb5Su_Kd)YJ@&ubQ&^Z)H$<JorbhNYut&pG(_FfDE$4zkt^u4jDqixAE zV}VT7>G_{J5Co};i#C0SLwF1qIe;xPhFk=Kj~|X;ro0?QXt4-G;H{D0T5I>wrtex2 z0<ETAJpH;_y@hqvskcOd{p_9jMk_p#^VJSR`)l{V7a=ACak|X-R5(){Q=sGRu1e;; zOw@qY*6CdwhHWNt_?*M<cz+jBTa_>83(%W^Q4##pV358;mCdTLoS<Tv2vBzoA-WI- zIQ2hzb#}TyqQeahT8&rR-S%Cn?4`V1rh_<T*ZsXcRuf~&>f14g@#Z>1475|iQ^ovP z%2owjk$J?KfGg>uP!=oE62i9eSNQos>!oB=M#At?t~#ka!D6y+;nDGFZ(2;{*9rJs z07Wrx{e40~IR05tUOFk=8Oluy=}TN9_r$!=zogyZuBVau_G}kD_3b+;lOT^|CFF_< z^o>Xi`rs3gzkgnLY83#4LTds$vPWQ+>FoKEgS)v8%n`JmR+O^=fI-^~9~Rzf=aM4u zR~=e6{>`!1G+;PRSC7gh^6i5j>Xt|-;{DWUq^!l}%lCm$IB|v|i)}1n0~-@w0S`<g z#QTFyr<_^RUzH>WL*}*H@jf@dny^)%?C2D|HiAGW_73)a$Pn%SYFy;UUXgLImf{-z zF;CMSJU(%x9V<y?-mz^hC8ZoF1A83NOH}ewi9+@9B-fPteST#U8OL{uhrd%SFk!r2 zPlX$->eL^j_$jCzmtR3Zxoy@ZO|U~9{LBp56Z3-8%6iVd=Uz3<xi6`DiSoho;v`hq z!e>)+$IkWZw38s}GUlNJRVi@Lv`wvJB4KtR3*jrzrv#lSE=F>{EUu2Gb$%mxzVdJ~ zS0=SO89|w{7zKd6qSFuR9|~<47aS1K#43Ql=Kq&{lULiGL4~aco?VBoQvrBUt<U}^ zi4CEKQj&QJVD_^{>Albic^BQ`Ssr&srYdvw#v7ZiJypB@Npv@W?Q=%DKfcwt)<lL1 zl{SG3rolq6?|N4~LWLZ3^Gg<i$75hI!dCkB=%0(BT-6Q~{)xm>nxoecXD;{4#*GA+ zyaXBxrldTnO?d%~A=q~RH_@~T@n#AuuiNDsAQwI{^KSo-c3gjL_K0buocEQVmGYr- zuO<+Rdkl|%o;(nV4^`x-@ft@j=(gPs9Kmj#GS}}%6w=D68YU{2#3F8ud&3g?ke3~% zXV5ZEcL02sJfcupwh>LOn6k%$tPr~FxCQb0p09D&)W?d?=k6b$PrV~6MuSOHXo_r; zFYS?Dn0Y;$L2q()0>7zO6n>%!a}hO=*`E3faEY?9NsgSVCXACJRMtgzOju9&EA-5D zT>ncU=&)2*=EFha8iaOigJhLX=e}k2#{o`C(GF1_)<KJo2<w?Aafo=cg(X1+JYCN= z_3BUOb$)#c)ecUNVd;d@!9<d(JondC2Lj&ncG97QuRL?tQT@N#Me-D;JN%aO!J72Q z7;^IRvLXiiLYD1TI-`SO;OeLtIkS@zBfZn(4k4vFNxMLd-oL>ckE!ztB{Rp^zQwa# zimhg18}{6Ofy<@-&USdpYrK2dnNocsW-~7nu>)_gjn8I!&&Cn)POb|EEV>D{yz2>M zD7QoE&1pSSE!J18W)z?DkDQ}~W%kn2RNG|xQ=%Rk`YA2-x0Dnj%=#dby8XMW5`j!2 zyELQ_UKC9JtojC4W^up(fMAxJ>hb5l1(ADgD2fA3DmWA(Yh?hwM!<^S7@iu~9IdK1 zF9H+yEh$w^B}2&oj$>m3yRmrOaS*Jy<hor>sAL4ki%~)8hsHYlSZ{y)MLHFen`>Cb zqj-g^?qJiY_4;D&FGWl|Lk6e$xcRP>;4ZPP%_Euzg_q5v*^7QeeZMyKCdO0h)zhq5 zMf}fyN|!Nm$Pb6v^X(CixEVJ(CX~*xzsVr_Lw4cJlkAJ)6q5u?Dt*9@8ZRoSC+}lB znv7Sb_LYu*#WvJ7#)X_`F(%+@A&<Q}&V?brUk<)s4uR0nD0w?y=u2{3+`JNd-E<|} z1CvT!mC9qBRR}nL9?ELf?5?UCLKjUIcF|cNZiKtx?Ki}~2!#vtgS9G+3=*3AikGjA zD=uTqj9WfKw_q(24yc3I%vT{EH+Ufl!&%3XmJ#>j;r|xC>K9<L3nO9U#N;P80aFA! z+gn=UR68M{7HBU8Ay17*793JKM?#yo;yMV~X)`en)W`XEa)7Kh7%Cu^)1u?2*4|KG zK5u0HIjS01G+k4av&h}_I}v2m?*RgYDAH&l^a$4;&r`>caEoLddjs=#Wjgq*@q0t1 zr9u$ulcr2G6vDVL7r*=Eqo_N8OtJHA>mRuxg&?a^wNND)2@jejlKS@8`&wfH%_2ec z@943JxTXV9f^j#W3Cf|Wgb-_TS4>>ZKMF;*3rVa6LumjA3KbgINWxh1tAYha+b~aF zB0`9}_JDf-z&DN&BEps{lp`vE4=COzlNDoa2S|CoeB8vjSc8&;qmrKmKAA5DWu`0W zhE|F1h=I0N=9oD)YtntRM+o@ZyEB7f^XS&9FvO2SXeABDUV0SAl>jT`-W0cEg2(^3 z%bcAX@w}a!RKIC^_L1!RXC>_Fs7#(lFE%rv+Ik#Kp%Sj<0ij4m;hF-~+HAe!)_up; ziwG}ro0eAU*093`--JuotrH$@6ii#0$)5SVt;e4*h4sfR<)#N0C*0^<1oJ)a!?2IG z@H#W_;+M?wZvo4Rg+&x|4o(meXlpWHlHz{jNr!kjMm+Boo6Y1_{b{lL>eeo+HODjz z$78}qk$=P`1t0|%M`(NE=SiqJQ{b_Q1zv3{_9IF%kubg>*#a%(q+Q}m^gfPnTkth3 zY%pCZxNhh8Pp|?S<y-=rq_+ZRZyeru<uFnL+j-&FBCk&gIweu?5bll98`~GN02k~u z^Ip~j_Q&>PYY=wt`d92#xGx`L?8FeX^vDRVc`bmpoxm3Q#?N0e9o?s$%6?x#Ou>+7 zoN*|J@&3aYZ<Vo7>ay5<%gMkmNH^t6C7>#q<3rw{InMNza{lBA{FZofoCAOc{KUEJ zbG4q(smqaWMIkx~f^&Vw94p6#mCS0Kk1ajC1ycUsu<!fs+iFb0v4C`lL@P>y%!f5` zocg}0z)SHlr7nc%nzD<}fgcy1ftjWuZfDtGv!F5ti&3Xlo*=1kS>|e)7Uo@3&c-XR zu@}4(Ew4hBZxRkaZnK<EwX@PUdO76Z7-CJMo4xkW3nk4I>eh4ua@c`3#S5faNK~lK zUte>z)$c2D&!&4#V`xW|XxMd6KvE9!PjEb?m;^}>nyw4%mY^X)8J;G!xw$Hgst<~3 z6Rt^@7xNz+Xq6`f0%gBWm|(Qu%B7Q{ki~&KY>QcAdkp%P@RhKrd?&0o&9;rjaxmE2 zJ?{AN482;;E70d6ZVD-|-a|_mui2<FlFa`Nu>9oCr9y=asGYq_Q8$+aG@kBKiA>3* z0482p^7cVO2pwM6jZ6;&n*>w1XAJS$<HNeZ!Gaf49@e6@^_q{UG5J;sz%dTkt6S0h zB3upTZ!@O@6i%N~r-`;1tAp~TL5Zmhty8j`w~mZ%UO=Fy0!cHYl)|rlUkv5|R~#UB zrtXhhTWV;%rQx@>E*Zh29_3&FkCu&l?4vvlXo>^u+gW7r%r%j9rZt&8liL+T*IxHB zF*Or{Eb(NV@Z_@>t`gffX4hE=A$YIki!`D_n+F_MWYlLG^Lepz;M%*fB{QXWa^lbV zX?V(!f5k7)Nw<>B3R^&Hcyqzm;MyEbwo)Kfz`DM@Zp(<CN}zb+>be<m;W=rInfn$l z{%dZrzhv$w>ue~2UzJ?bH#96~6DyJc*%!MYPy9M|C<|@2Ze)s}(s@_AzSj+?bxQ(F zRUY>lI~T;TycwVy43#&e1&s~N3hKO*i=?hqZXkx1IQ7X~Mv8q9YZ!s^8$7pNXAEX> zN?o=AlWGV*8NJ~G5a$6+*XW_X%ZXSp%~0zxuYx7vv}W%|LZ7v4#fi*#K9P+?^bbe( zT=do>TdSZohwq?PUsEg21)HD|R^<w9$L{0R)tvQgMKTg5nft||K92si!}tjO4K>^m z`BFap$@b+_V@JJL>6_Emh@a)(z^p^>03MyXugJuVz4(B<{yQe;vds8}U1iz?HP^V3 zb&(UG|2=3gE+OW8*X^X}cyEguossAs=m#nkcaxqzt3;9Bw=Wv4Pu<8j8PX*mfWzEM zUTtq&VPLT4!JgeXnH=rSt&D58Vj8U354Hj6#F3KyJ;+@3yZ)^Ds7eM#6U7pvG)!P? z1xRLH|0cge5f^LMIvqtnfPAN)n1%JvI{^4mR+z6{AL=HHVQ$wj75?9fnnAy3@t`<Z zz}#NtCao_|bVW{1Gk6!YClO{*Fe6A*Ygw%*X?sbOK<rjaa7S^6LcvC%RVs@j^i6S| ztoQQ1R;)sqGy*Sp+-jmZ7ocaFM|xftFUH0-UjnIOJ@iGf8<_q#O)6Y%)Z9$$E(-_* zawG%Lmq&IlyT+DQy*H0s$<=WtcjCq2#Y4}SOfC*x13N<8f%4x^907Z>8utDb$Q^h> zQ9_3^JSxh|gIDZ|R{ywT<6ot0ItUfoq9?_~IyGlbextmduBx<GKQaq++41Y5bK;V2 z!56~P*M82EQTy&G5}`FlG<5tV(+~^dJ9I-9oD^VuCUV{guFaj$x_mL;f1f!Cgmzk9 zypE-!DmE2eJT2Me=(*#uVszKgNAV(&SQsHY8QU?wf}dO&_F?v<sOq>gqAWB6lo%HQ z5@sj#?(NBLT(nmuTu>*b&A@n>Mk2n(ASdA|l~w!m3Aij-CvLh$SLnHb=82^U?G*)v z*YTYLiTL;>_93;|SoHsuc<VLQtd;_As=9WuIELQbEL}BkN^2d&0z73p8zI8+Tx2^z z%$6C`wd!BLW@1S^T|Exo{Q5`f)9MXPpOuw>Jd1L07K3Q*{NN2GoD2tTB3{>-HrA1_ zWod}PSQ;&EGZ`VD^0A+Mw4-|v#J2tNUgP2y83m+vFD@M;QPbSBBLn#*-g%2kh(N8_ z{O>)0fBo{dD~G|qWZVxPVUBFoa)wwBrWj!y{kNa&C#oJ(|IGLR8Y%>@p=lmm6ipH% zZuk^hK8&l<jjm;RO<_AN+>D6*3wFlGM@u@_;6`M{mCgI;^mJqJ8RG2*Hb(^*pgMRT z@xXjUKAdk=_d#cp2|(OBQd@aFCA-MT1{l5@!3*KSQIc3Chmd>@FKi+vV!)5Dv1EUa z0%{K|Q;h_48;}W+`185}u_6pLgA3z_BE~zf&&?;!tTtZMnMiTIR4zISMuiiYhO`g) z{<9aOCwr~o;yCYrZ)E)f4H&_h=83vOas;@Yi5J~d+()2jh^-w~$NUPaYw4!v2yyOa zI(`(~8M;4R!7kEGbgYF9NJ6D3y+DpWF-LJ&Ej8aiJ1w0(>mO-#?tBKA=MfcfZ}B!B zJIr@#$7k7k>dE@TV|!S_42i>!jZ(ZEOfOU0dxzU5R^*~zjbOT5hce^E)Tj<1KT?&i zRv`*4;PLT+9`3n?x4wzdZktK`7q<^zdk08zrHB#Q$8x3N@=Bm!a8n3(%uY)JiH$4g zwCIJ<;@}5JANRw?q7f&7D4LPUPA{Qgmuk6kwRoN?m&CmGHn4GXTLy^DvZGUAsG%e6 z56(CgW3Vzw7g4BM`cx8(X>MJ$JJM3-f$|3##=HzdrDT_-1iyV%y4W~O-~K+$i&h}Y z%rGRB5dpm^w?}Tm`)>>8vkCin4Lp%^@MJk<4n8QA%_7q+6vm+A>d2Fj7KkBeY6p<; zxEN3i7k+OZKJ7XlEj^Jko>0Xk5-&at;u|PEPRFTJGa*z~l-SJXmB@N6?tG`5LB~&J zGx2Mwoc;rDA2U`h?WmdKaO&2-R4ebP2BoWrnxumu13@Q?(dd|hqB2^R0%}v9O`*;B zxyJd{Bm+!3RKCo7q9a4Cm)T|K-gXWbLJRIiU0m|H^nWgi_>Q)rETT%iIkZNnpWLRN zD3}BG#NmNQy@v^>2%8!nPeqArWIC^E)yU{9DInaqi<5e*%#DVfNP6u2AM8!ySVRn? z3w;qY2NX1X|HM0Tu<j`)e8gpNDFBa%iY$R*mH7UNcS}36&6e=09sbv?s-GC)hZBr0 z<1VKq0w`7vqgsqc8D0l!v9%xy_n_I}yS>vSd*wE!sfE5gp2D($<`=h#qxtDj`b&o= zv?`)l8{0k;N*~X^4j3(!-1(C8R#A>-PD{wG(CD(lamht#f$x5VUow@JJx7Pm4$Idy z45I73Z3?rf;AO``rad^}<@@9kwf~#RIe-1=%LgF?M0_u(yw_}cv3p)Xhms=>T{hn$ zw{@cU=d;~enhQsq!%abbbxV&&r?!)w7ZO4K($Vj^#FDLkEdEsn$3q~pp4lmc_>eUz z&np9&FbC15=bI4DecH^NRf|ec0!Iku8@A)cJhFkF3PjdHBTa=MfkGt9sOQ8|DiK@s zCrX6f16=>ZM&@ZmMbQ?uJ3YrVHIU_DB;-cI{wnSj0Ctr_^7$sX<S9PTiE+TbL6E(A z9PHin0l~-ipgo9K=9-O=<P%7+ofPw8SSpU)X~6;zEBR;aL!}ias|kd{Fw&0S>fjf{ z912uUu(z607LnzFyBrgTsVp2L?qkPvGU#m9{E=LUnoKfhg^5LpCadMv<#^JsCU;Tp zzH#3TKI1Ft=b`efu4V|633Ta4Wid)F$h$xlwuu(yAJEwsw;`a>{dNXQwL|7LQC1)& zCPF(2>q|Ov6KAf@%DhIrF^5JptqPgRvzzJ1qE{ih#|w-j#@P0{_Ro_*3C}dDxGL2W zX8L*=EPe<+{-|shHH0P})d<90M5sdt!NfAN^(s+0e>GO8g}7NLWE9Lal^VFU>}U6- zs${x-#&3wlv58f5jNs$@)T+O_p*u+!N>}nu?s)fx5bEc=!0j)zWahW}lN5^I*AK*I z{U_^$mK)ga-~Z+?nrx1Jx|YFcLFz=9j*4YeS3MK3IL!m*5$}qbX4~)RPc3U*1qUQj zF7P}_{7HsXBjf>+DWJo8xy`+HZJ4b4>3IB5tE0CvD!?96DAApHF=Vg}f9~{#)TwCf zq6^l@*DRJ^;sI}MejKqL$6U>l`^O^f@g*9H<O6jnvDalbfkch~@X+CYqHcP^3<4h% zB4CZr9kccAtP{lhL!{;EWH|^QCNBP&I1?}rNJ|SeRckLqJJ*E!AHU+P=4}cQYsf4Q z5Qzqo2Zc0ov-@B5=Fnb4t~H_RHycz){;@X9SIWNWS?)CLFr~zBZWH4XUl=tVPY%s7 zpO@-f#oksnd-6Yg;};gcq`T)Zvl|sZttGax$2u&l0qd7lWjvvT)*aYL1RJae3Q`JV zFU7hx^kx6sC*8>_6eMn|$t7Z|^C6^sGNolQFhFUMBuG3A7$KC1k6_wkbYyA{>lL=w z=ssB1lV=9Co7suoDVNCINnu~k8nxEzSYcn_eyZ^?L#_1t3aXDu1!eE{ES_fcx((Gl zVKUZUhjzG%g9on<ZwUuJ=04j=53S}hUM@1D2YU4j#!FKA>l&Bl^aVrW^i5DO6e>q< z-m?gk6aU+ZG~fV&7HrTwdHTsco-dXdeOVbC7AYbziff$eJEEKv4Pr%a`g9X$6$I*C zQ=9L5z+>6Nt{2Pt$1sik*RGgfI3)hkXPmi<K(OGuDQZ>nkM?NXJ_)NSjAUqq&~(ja zIuP*X-*fvZus%y54%>ODdlNPD<Dz1_z+@jH;)GAXI)s!P=C$bnWV1aPfBfF>Fs3Lb z0+q1T;<f!o;acSYwihIAJnW;TS?zX^5kyb{bhph92x)&VxD>df0a45p%oQG88@9$G z;uOBh9vnDd(pl(Rv0g?X+S3GTcxw;vmT2T3fFf40{S7SUWN8T^WRaC*SXdyaPWboI ziIRd)r*l&ROvyhvnYMN42H%juu%-=?E-=f0qAR0UG?W!MEqBTxQLaEy*J7#}1ec8w z-o!)c0?VDv=lSaeldhM%-Id!$_DXDoc#H%pu5hL`bo+*~>@+qnSyU1UTl&AALt=F@ zdJp{e5J=W%HJ-1s@utp}Wvqt03%Xl)E!a$<ugJ~z&}H|iRc+mT%Id9!dj=<6YpwM# zIl)6GMO1l&wYW8O72!_wVQh+q@$B^V{aG}Q&hS2_Eh-cucxCg_8p2-HB8*_5v%xhS zEri~ve~Gw`@<sJFW;ro86<w(I=^ww1rLZ*^6x3}f4W~&JlHDS`W@|QlRT6^`irkis z)n^-lgG!3Gs)*u9D#9=eCC{Zu)^6&CQ!JEDu2w7~FQ0Lli}r8%S|{r9$Wpg+;uX;g zQ@yp{CUrW<FfK=7cJ)}ojJ#vFhdwX%=j>>=o(GxBxSYw|D$2((|D5>P`W>2qhoUO) zvluC~2d&(f&{~2w=iy&s#FjQg^3KRo1w|0=myGh)Oazeg26EYu7@ADS3ORUB{shKC zYbQbPM+u?qhYQ*2v(4%M4*10?Z)=(#|4QQcDGk0=oz7T4i^5TYcIGo*(a@>XND2k6 z1h?mOIz-ECCXYvf7QA<H{To19iBDV0MY2cP5xa2NP|}JBbo#K>eV{hM>f$f~1c}EO zq@`qNhaeriRo4+}Rr!X%M=!Ac3F&wa?3rRr^{*V4k%J(kNytHNJ9R#Cd!;8<=D&IT zCnONF!)o#d+w>y2B&DyrX6>|uJZ%C}<H9Hd%o{WZbk}Y`ERfR}$Hsm$Zdd5v<$FNP z8S6B7!{*4^hkqv#?wOAL%$8hADJ=4i8z-Ho*W|6aWzV!vfm{Bd?s*j-c1DAgT8VIR zcVU2}X!%sY7;P?cS4GPoV(5>Gw)b*yD7vnRSdazX=Px_E<*#}xW5j`|;Q9QO#fL!V zWqkSp%n3Mm@(O^nHrBgYgb|DU|KN|Qqv?1KpJ}flMx^Ja+@NwDn~eLIYuw&-cm-dh z&}pEdFR070(D;9LdpQgxX%K9{gXJb_%G>rBLiEWPp_lc9qWc?@`K0)CS#^0;FaDSk zA*;9AOE%mi^5L?W|G7^^Ji2u;DEsSGaM#7nS2P~{0`tk$s)?^DJN4pZ*@BcL`<9%* zN&?2Um8aN*`>Ch@3EWI7>BW5JCXo1vLaV)6woZfP5nX59P6<%EnVz4XszM@4-U7d$ zJ@>t-(#q?wCY*GCyJYhmS>MEEU^1MjzXLq-#9nN3!t5#rE>g}nsqBaOQu3;j<ct4- z`!8Dicp^_b=6$nM$tbIrc8&Tcv|a9i4Njxw^cd+vj0Jidlh*h@5=0)PNi-*HQwC~? zM0{Y1wC5-h58x*Gw88v*94-bf8u9CXJ<y41k-b-+i_E#{!SP_uzNB}Yjf;;nccr=H zch4mPURId<psYF;v4`a0DRRtwV4hyjQOCt{B3bd(Qimjhrb9?TXWo&&JNg9#U}OWv zm<$z9wRTOf$CP!_;`F=}@#_7LC5%HD>A|*tQF}u5I~wi~f!9<m!Yz`GAXZDfHq>!| zCC1|$<-3r^UU7C<3)h&X0bt(*ZRKb^#_t}+TRE3%VkJmV-pIR3Ukveg;zP78-;KQr z(90S%y<1D!S&B#9^8j;wc`3}ggL<@%hu(HJ=i+kLk>X3=NJKGO#T~QP)<5YrRPwHY z<TxFeWU5W`nlA`Tsr5KlqR>$c>(=qmp51n<mMH*dDYsyNo?wCDUw`hNxY|C{#dJ$h zO_3I2rwzd0PB6CYwaZScs<`w|)C)!gC`2Mu=1}0Oo-&eQTZZ7`NsipeOJ=YYh*iTf z#G$i1MN+nLm14<3yj@#E%^RSas(DvuzG~f<esip`ZCvFF!J|EbdFu9lkp>C@dsN-o zF|(@yq@ef?xwGCOoKYInIsycQ1(ssv0Xg`>3Cf~C+dvNTozuFk1>nawwvMTw-DPj^ z!IMbbC>DkJF9Mv#b0^CNBrT&$9DH1id;Fm6VgVOFJ*b>lX>OOy53J6iur{TnwLhlu z-c^S&$?VKv^aBfAS2$FW7+08DGebq^AQnx0TT_u{4U7dA2VwKw`HBW8=`(v+?Z`i1 zBi=1u0RPIaJ~lQFD)RSKB~ri+r_;859yBogD9Uggb<DiB!|P9L?_|u$#KAD%*#+bD zEpcA_q+z0=8P`j(IpM3+qKoN=BP}6LvnJX{fHExHBSwxWKwtx3GyR59g+g>cf?eh? z{puk_SkU&bl>PmPH~Cp!A?5qO^HdLLXp?MCCM~hr-4`Q{H8WJ-U6kUdLK~MHHF^zm zt65RjTN5<@-@j37snY1Bd!0wL^A|vS0_rX<Hvs|SToeEp4cD!~KDoqW`e_rjR%h|Q zqHO?P-&R#KFdd<Pw5R3I*OdT8CN*kbtY|8cg1`lVByW^J8o>T|oE5D-n*W6aHQ6>{ z$vf$cp>^5Hw7_EX9Yw(4t&akEuzGh|Tm%Qj2;JE&_Qw_v9Li1#=v6%^es3&gBj)bO z@P1pt%Ja?eaEQTDe08@EY^1O8sdmN^2+G~_CB@TpCs9I6eein5nyU-Tm&FoE`O-){ z0jB>o2qO)F_&bS?ZTw94=J+|G;?MEDv6B<=CLK*2cJgJZY}C?I!9)!Q<lDI|_pxf- zz3s-1KENoqSGW~4MzN%JGDj}0xiC&TL)jgmY63*(O00gvWh;4~fe~4NI+j~k9u>gz zP(!~-%H=;bO-~>>%U7S<5qxO8_s^axe-b7db7m2531u`2m&in-&?lHJy6jWYH~ZLu zZ9)KX^(Osz#NWYCa?qFdz+uP2y%pzIPMGrE!E!&w7Y1pE$p}Ko8HXLEqTA(ggV1Sh zLPI}yi_!p+uH&Wr5@9W@;gWruq3Wxh3O>YheSSgS+PL8pVEn^*Zpe(Nc(EOl>Aj$| z^?wyi=MSS@HkvaG;E6O)9p@5Am3qiWo2FdN(_?%xqfsb1p>+a)vy7&3>2{Dx<sL|{ zDuO9x)OAb_vOj~Cyt%6@v?QAi`(-g~KMTh{v%PT$={!TMT!*Xxny*i?_yrt^+D3m> zyjIF&`G6mg9CP9UdyB=fk-g3@r<K5OPYpi^zqCU^+GPWbRrj8-znA9aoeplQQE9R3 z3`P$ufQ$f0p`<^DN9xqBh!K$70yy)dVai11VOKVtkhz7OmeJHzRU10Fc6*=;+yrnk z=TDzeYo+3Z(dwc0GP$lJpmFBDh6zQWHEh0nE|pY9CXyQrhr#4<VJACQu=}AAZ?w}S zjh-eDk)5#czrzc-OG~4GCAJPAJ2+CuxiLZhj}gT-@xPS>+HGVl#xSfI{nW!?*-);} zxyrM>MLFl1tyW#(oDS;RZ6nry=-Ke(RBw(SiKR4OlM@f^U-AnAPc{XqQShNz$vrEH zXu>=*q_Bkf|D>7H>f(@rHnDJ^LC+g;PSBnZ1-S}fNYn`-)ItOElgq8gCq<&N2KyNA zUr6hmxLIgqJTN`Z$N%uL=PB53(e+p0=PJEC1L6!kDh5{U;%!CQHXe}`8r0q(Wysn0 zTRhHjSWV;m_PHMEj}R)yYPYkbE8i=Qt9jvRZ|z{LBsB{tBjo6S0`3Ri)|K~x)wsZy zKZJ4bfSl~~#OK+;<*cz&#z!rC#JE%a=w3~1@|>w36pEZ12TQAw0rG=)*Xi1s<d3Fy zQ@xolCqm$!7SlM!AB07eUK?m^1>Is3Mp-NY`=H;jgCO5?7D6oVv7PZ2H3Pa7^cbqm zm^(cr1!aX6orLY#;HNX={MnP`{a+zgs7nUS<lS{lV9%zHzeQyvvQz(r{0JRpo!Cwn z{&Kc{hf<<+&DCODZjor3ucfU__TXf!K^BetBFuhsC9v1A_-VY0>$!WnY#9O@x+P#k zxKHGGobr398Cj`c{tAuj$F()JB<#%0PEz$a?kFO6<$ZIg8?w5{0g#xCB_H|u##+l} z--uW0QJl<sUJ`N-NU~3mD90s<Ys1FE&G{h!MnW&HWKt~&D!x#*qOZ0EA)sR&sr?+0 zE{!>@N_}mA6THcl=HEm86LS1^%vz7ML3j%Grk?&7CKqEBj(y^l_(wGlrXh3e-Rva& z^dsfT?UIH^Z{n^f8do>rpYgiV;jJ~x*N7dzD5BkcJ_lL>_)dxv<BpO+G$8cxWCyOg zp-1>5o2;n^)Lny-k9%{fDV3m>CJ<b#N)TIadn3G+1|IQt`#_l9VDs>Bb=X0Cl$qg) z%xXc%sa_UcY>?$~FXyGEl4+4%KyH@WH#Q4>c*ByOwE%h^aFn<b*9|+h;6GKMdYm-z zuOw7TwGqS}lN2V$^XU0?I(|T+HJ&)S`*A?7sCP6ZnbT)C;W^2eR#|~1uP}H1TAP2n zou@H;NhC~N+_&2L0(hPW7sk$j$V7P!j!kk^K-c#(H8e`-s@b};gCq#m-xq`pSbIGQ zpt5q1ebVAyzPJ&xJH$X9UANp;qQmX1^iO}gyK~bBKZfo{UxyK~WAD^a>ok4Osn!<W z$>F_lPEmoX658E9jp%rpl2|z~(jV14Y^nUVtC>c^aZmRuNmkG7NRP^<RJYAOK=dpu z1g{uN;EVIo@>!g2oGiB-nVV#wNMI=c6qv8}pl`wFCB)R(b>4voY`w0{@{XxlQ$*># zw9Ox+eCYx>?SY8t;s!M8`vN_*d^n+fqvEQThs|Cr9J?l#Qw7W?uAjQf$p=hpd6^du zH_8A{Xy06PW8o{TfH$2fpjOp`dL@&=^uDFwFXs)&`kg&*DNVa<Pm1j1DF6rHY=bb| zeW45C)_i6PY(FTc8`)93&I?Vm2q!x;9@3@PoGwSDc=ikJ^W;FoBrGVvk6?UH(fdpO zfyzDbwl8T-#T#`9Q6>&7k0oDUM}FhAVV=1K%)_;-X>B~(CfL&I3+^2%9y`UGi<g!$ zSwnER^LldL%=QiK{`V`blC*vU7x)mC_(E3?jajF%5@Csu?LCl_3{AlCFCfE#Sxkfc zK8CIN&v_N9Z1<_9nAn{`h=y285z;x$SjhCz!df0|k4~ITeM@9c%>X)iBQmgEp3`<C z<gdMKuzu_4X1onB63qenJI?_<vK%F;(IEo>j~vR;P+lX0XRL53=Y-9eZueEUqB8sa z9BOT_c0sb?gBZmIcR0C8MQ7g&pXRuyhH&PG!)5={UkH*$(X8YphW2lT$ha7ti;WJH zT!r0^1O%1pjhk2N#$X-z??t+{MmLo^OV{5vRzW0<WelJ-<p9^xcgt&>eS(*QcZQ`* z`sjoF>rg!gV6v+j+|4K`Wc`;W!R-A3y#hl0wZ{?-c%Vz9v`mg5EBAbgS3bz*DSMra z@I@2BiM}Lxr_`Xn+KknZ_~v3vPW7J2VK!L|pu86_`Ra33<TT^tbhFcf98Dkq00J!H z&Oi_|RctupOs}YPEQf|vhFmds2n?&?3YM8aPw32}Q#ltfHjE{wuuln9@cqHmL2ljG zMq>@LXfVJCP_~t5$MN@Rn6HD>eyb^^yzDs6Ep|yb4EBr#l6AYp9b%tRw6KqztjeHd z^$FPINw(LSxtclJI@R#;cMG*0W&i6aYcSiJF;PRp3ZIWNBoPtuqxhYqG5Mvp{E*RY zT-iACZ30^F*)h(Nxn2u%ihm(EV{Ne+aGG>!jj`BWj^R1E=fwXzHd<KAoPSC}4m7UT zsF43@yA<qv)DKu%Wc@By1H+l=RQ$7)?d4D4Vo%EY6R~iFaytF;L@3dFSy2KOOZ+-t zNo+(v!DyapLFKqk5HHT$lH9H^v{R4yu}EqL0CB^)9DoYs<%mg>imE?HG;v}B^ACq< zf;$J<yceD~7Q?QUqLjX~axalf%%@IX8TX}lR**F6oNOh-cNBSn9cc7I%;(}UNn)kS zwCc3M!~%pUF;qvV&oRG!zG9Y_9U^bUd@2LxR{nee(=@o#ntYA0wKokc*-hmHCf=%y zILh77hcqGZg;=VEw$%cY8L*9{lvrr+A+9xp#Sd*JYf#W%cXF4;RqrBQaR5GDSRu%i za1re2jbCd6>xM*2V)y)7&JN9xRy+UzBx}lxDYnPLP15Y-reGEE!CCqNACI~z!d)O0 z3%EzH0;KT>^^>LTZcj9W0$MQodJ_yW?Up!j6VMlqyU_)@nffXnLLvREY1U17bhj@O zWZndnZk1O&JrE`}?}J))Z*0SaH*^adsbV#%4^LZ|M_f75^($#;t+G#=80Y{100000 E09``72LJ#7 literal 0 HcmV?d00001 diff --git a/site/_static/static/dcc/open-icon.webp b/site/_static/static/dcc/open-icon.webp new file mode 100644 index 0000000000000000000000000000000000000000..401d3dfabffa6e3fc7237cdf5db877b80f44504b GIT binary patch literal 33334 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⩔pXR|BU&GO$OQm`bs!ewrmA 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 literal 0 HcmV?d00001 diff --git a/site/_static/static/dcc/powerful-icon.webp b/site/_static/static/dcc/powerful-icon.webp new file mode 100644 index 0000000000000000000000000000000000000000..d06692c6912f40afd5b57743a68b54a20658882d GIT binary patch literal 38934 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 E03`FL1^@s6 literal 0 HcmV?d00001 diff --git a/site/_static/static/dcc/productivity-icon.webp b/site/_static/static/dcc/productivity-icon.webp new file mode 100644 index 0000000000000000000000000000000000000000..1e433a7d64be65f82f9322d685a729e80b313b70 GIT binary patch literal 34092 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 ICIA2c0PJ{FPXGV_ literal 0 HcmV?d00001 diff --git a/site/_static/static/dcc/solutions-icon.webp b/site/_static/static/dcc/solutions-icon.webp new file mode 100644 index 0000000000000000000000000000000000000000..fc955ed96960a7f6d0a8310aa1ce24d64cce3dc2 GIT binary patch literal 27966 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 K000000001T&)M$) literal 0 HcmV?d00001 diff --git a/site/_static/static/dcc/web-on-android-thumb.svg b/site/_static/static/dcc/web-on-android-thumb.svg new file mode 100644 index 000000000..535273830 --- /dev/null +++ b/site/_static/static/dcc/web-on-android-thumb.svg @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Generator: Adobe Illustrator 27.8.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> +<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" + viewBox="0 0 120 120" style="enable-background:new 0 0 120 120;" xml:space="preserve"> +<style type="text/css"> + .st0{fill:#4DA949;} +</style> +<path class="st0" d="M64.3,58.4V37h-8.7v21.4L37.9,79.1c-0.4,0.4-0.5,1.1-0.2,1.6c0.2,0.5,0.8,0.9,1.4,0.9h41.8 + c0.6,0,1.1-0.3,1.4-0.9v0c0.2-0.5,0.2-1.2-0.2-1.6L64.3,58.4z M80,79.8c0,0.1-0.1,0.2-0.4,0.2H40.3c-0.2,0-0.3-0.2-0.4-0.2 + c0-0.1-0.1-0.2,0.1-0.4l11.9-13.8h16.2L80,79.3C80.1,79.5,80,79.7,80,79.8z M60,0L60,0C26.9,0,0,26.9,0,60v0c0,33.1,26.9,60,60,60h0 + c33.1,0,60-26.9,60-60v0C120,26.9,93.1,0,60,0z M87.1,82.7c-0.9,1.9-2.3,2.9-4.4,2.9H37.3c-2.1,0-3.5-1-4.4-2.9 + c-0.9-1.9-0.6-3.7,0.8-5.2L52,56.9V37h-3.8c-0.6,0-1.2-0.2-1.6-0.6c-0.4-0.4-0.6-1-0.6-1.6c0-0.6,0.2-1.2,0.6-1.6 + c0.4-0.4,1-0.6,1.6-0.6h23.6c0.6,0,1.2,0.2,1.6,0.6c0.4,0.4,0.6,1,0.6,1.6c0,0.6-0.2,1.2-0.6,1.6c-0.4,0.4-1,0.6-1.6,0.6H68v19.9 + l18.3,20.6l0,0C87.7,79.1,88,80.8,87.1,82.7z"/> +</svg> diff --git a/site/en/index.md b/site/en/index.md index 6de2f182a..98cf3437c 100644 --- a/site/en/index.md +++ b/site/en/index.md @@ -1,4 +1,4 @@ --- -title: Chrome Developers -layout: 'layouts/home.njk' +title: Chrome for Developers +layout: 'layouts/devsite-home.njk' --- From 81903333924aa28fc3569d52eacb5ba607374f77 Mon Sep 17 00:00:00 2001 From: Matthias Rohmer <mrohmer@google.com> Date: Tue, 19 Sep 2023 21:37:00 -0700 Subject: [PATCH 799/982] chore: update site title to Chrome for Developers --- site/_data/site.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/_data/site.json b/site/_data/site.json index b75639ec9..2360616aa 100644 --- a/site/_data/site.json +++ b/site/_data/site.json @@ -1,5 +1,5 @@ { - "title": "Chrome Developers", + "title": "Chrome for Developers", "description": "Build the next generation of web experiences.", "url": "https://developer.chrome.com", "imgixDomain": "wd.imgix.net", From 76410aacffe73c686d1096f6602221750f923a8f Mon Sep 17 00:00:00 2001 From: Sofia Emelianova <42939855+sofiayem@users.noreply.github.com> Date: Wed, 20 Sep 2023 12:20:04 +0100 Subject: [PATCH 800/982] add partials for 118 (#7342) --- site/en/_partials/devtools/whats-new.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/site/en/_partials/devtools/whats-new.md b/site/en/_partials/devtools/whats-new.md index 0a4e471ab..3d26011f0 100644 --- a/site/en/_partials/devtools/whats-new.md +++ b/site/en/_partials/devtools/whats-new.md @@ -4,6 +4,20 @@ A list of everything that has been covered in the [What's New In DevTools](/tags {# $content #} +### Chrome 118 {: #chrome118 } + +* [New section for custom properties in Elements > Styles](/blog/new-in-devtools-118/#css) +* [More local overrides improvements](/blog/new-in-devtools-118/#overrides) +* [Enhanced search](/blog/new-in-devtools-118/#search) +* [Improved Sources panel](/blog/new-in-devtools-118/#sources) +* [Streamlined workspace in the Sources panel](/blog/new-in-devtools-118/#workspace) +* [Reorder panes in Sources](/blog/new-in-devtools-118/#reorder-panes) +* [Syntax highlighting and pretty-printing for more script types](/blog/new-in-devtools-118/#syntax) +* [Emulate prefers-reduced-transparency media feature](/blog/new-in-devtools-118/#reduced-transparency) +* [Lighthouse 11](/blog/new-in-devtools-118/#lighthouse) +* [Accessibility improvements](/blog/new-in-devtools-118/#accessibility) +* [Miscellaneous highlights](/blog/new-in-devtools-118/#misc) + ### Chrome 117 {: #chrome117 } * [Network panel improvements](/blog/new-in-devtools-117/#network) From bb551e0dbc4d588a772b59c651377af6b66fce5d Mon Sep 17 00:00:00 2001 From: Rachel Andrew <rachelandrew@google.com> Date: Wed, 20 Sep 2023 07:32:14 -0700 Subject: [PATCH 801/982] add post (#7338) * add post * Homepage refresh (#7302) * chore: update site title to Chrome for Developers * adding homepage feature. * fix link * fix id --------- Co-authored-by: Ewa <devnook@gmail.com> Co-authored-by: Matthias Rohmer <mrohmer@google.com> --- site/_includes/layouts/devsite-home.njk | 23 +++---- .../static/dcc/chrome-for-devs-thumb.png | Bin 0 -> 842093 bytes .../we-are-chrome-for-developers/index.md | 58 ++++++++++++++++++ 3 files changed, 70 insertions(+), 11 deletions(-) create mode 100644 site/_static/static/dcc/chrome-for-devs-thumb.png create mode 100644 site/en/blog/we-are-chrome-for-developers/index.md diff --git a/site/_includes/layouts/devsite-home.njk b/site/_includes/layouts/devsite-home.njk index 7e8620dab..797cd7caf 100644 --- a/site/_includes/layouts/devsite-home.njk +++ b/site/_includes/layouts/devsite-home.njk @@ -14,7 +14,7 @@ "> <figure class="devsite-landing-row-item-image"> <img - alt="A cartoon-style rendering of a diverse set of people building a website on a whiteboard" + alt="A cartoon-style rendering of a diverse set of people building a website on a whiteboard." src="/static/dcc/hero.webp" loading="lazy" width="1160" @@ -47,12 +47,13 @@ header-position="top"> <div class="devsite-landing-row-inner"> <div class="devsite-landing-row-group"> - <div class="devsite-landing-row-item dcc-blog-card" description-position="left"> + + <div class="devsite-landing-row-item dcc-blog-card" description-position="bottom"> <div class="devsite-landing-row-item-media "> <figure class="devsite-landing-row-item-image"> - <a href="/blog/chrome-at-io23"> - <img alt="" src="/static/dcc/chrome-at-io-thumb.jpg" loading="lazy" width="534" height="685"> + <a href="/blog/we-are-chrome-for-developers/"> + <img alt="" src="/static/dcc/chrome-for-devs-thumb.png" loading="lazy" width="376" height="240"> </a> </figure> </div> @@ -63,18 +64,18 @@ ">FEATURED</span> </div> - <h3 id="10-updates-at-google-io" data-text="10 updates at Google I/O" class="hide-from-toc no-link"> - <a href="/blog/chrome-at-io23"> - 10 updates at Google I/O + + <h3 id="we-are-chrome-for-developers" data-text="We are Chrome for Developers" class="hide-from-toc no-link"> + <a href="/blog/we-are-chrome-for-developers/"> + We are Chrome for Developers </a> </h3> <div class="devsite-landing-row-item-description-content"> - We're wrapping things up on this year's Google I/O, with more than 100 new APIs, components, and tools discussed on the - keynote stage, and in Chrome's on-demand sessions. + Celebrating Chrome's 15th anniversary and our role as a trusted, helpful partner to developers. </div> <div class="devsite-landing-row-item-buttons"> - <a href="/blog/chrome-at-io23" class="button - " aria-label="Read the Google I/O recap blog.">Explore Now</a> + <a href="/blog/we-are-chrome-for-developers/" class="button + " aria-label="Read the Chrome for Developers blog post.">Read more</a> </div> </div> </div> diff --git a/site/_static/static/dcc/chrome-for-devs-thumb.png b/site/_static/static/dcc/chrome-for-devs-thumb.png new file mode 100644 index 0000000000000000000000000000000000000000..f847e8b19c3aecbf251c2e1e11617de416044a46 GIT binary patch literal 842093 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Μ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%0D7K<&{Y zfaLHpqzE2a;2cR}4D+!}gZH4U*!_ofE~d_PJLT{>h|myyay`f=1c|zirVsg_k1Vb5 z)UCc=d8m2?i`a=SV%G*2OoGKX0e=qd3J1<0VQlY%Be$`CoyYuy;^mrrUqWKZqB7*! zRN1c`Uzz4wMDf6JShz(|9SB991kst*@mLqhIo78nkg@TkB=vF=ewuzuq#d$<ZJvWE z3B?>bvH&6eREifp944=O_3H5Ylh5empx}#(f<aFZfGj!$&O!~mNj2l&4o{_%)vnEl z0Lwmzl~Rs3E@6O%N|{2If9rfVhn5-Q{9SROa!)i#pe+$>ToE`)a-A)UuoGdIVOm}a zsZoNN<&^!%>@X>cai**e6rzl^$F5-r5%@%13>Y_s;rU^{TZcT?H@QwpTFK)Qf`E>t zMAD@!LlAn!mN(dJ4QJo|JPYsQ$M=<Px-b&sswSp(fl}Nb%TO@FUgXL68a{^}C^#~m zKvCU&O@f_NQjYyPT*Bp~U*NEf)|;DlQ570#c1)9^6g@7jSa<dZ(HuEqr3<^mNXxr# zIn5Vbvy;0*(TjSDtFxU4usAWnKIa0WC=pTJ2w<9j(8848S6R)Jg5H4O%X9YgG~3HQ zdA$ATy4mVoI@8%~z@4*`Aw#~wrfaLW(oFh^im9TK)~FZ|g1JZ|@>1H3xlWif-NZWs za&6P0#s!!c{bU60=w}T<&_xfs$JQleE1hbq+m;9*1@&5@(kfhbg=D<NJUwToKo6MJ z3RE(d-5ANLP<|8YRN@_uv-vYpNY&5ku4UZ|Rw@m#j($dyNJT$ZBIJnk7Xzp83#CH$ zb0Ovjy`FCqOQw+d!PVK9EcG9(bPUzXiH^^bil&*1BD&#rnb<iJlZ5^L$ZH9>0FqtA zA7Xgw2*S{25so%1&w^6*=G|i4Hn3Q&CHT__-F#jn0GBALZHpM|Zaxn~BNdGt-n@Lg zIV{sUy`i<*<369eH}aR>@B5Xmn?ARPtGijbSx?SihR>xu+=km_&+hrcPfKCS`+t@5 z|96^m6_wYPb8F1Oxd_GM5Frw2Xh_r%A;a2tAk`kQ9sxW6*lq<9^#TZpGz$HZ!Zz{S zLyskNr#Z^YOUB$ZjSM7NN$4v&TD-s2Q`i6N<YN`+v9o5gQ&-&kVkQ?KJ|BI=_O#HC za(ANKyky&Y0$}M1OplW2*%-v}>F7^rFGO!*Oi#M$L>z#iYJ%sOMkvSI*m4)mAEky6 zJZWwr=Qlxi+#8v3=~%CkOYD~8@7~a(yhpW9UJ~7*Z(jPJ*Q<qKeX}<H*Kvz&4UUSh zEw@k&NozT?iws)FjweDg=_BgL6!Z2Z2&Xp}9nYLDGAgk|_`Kz0d_3G#bMa{Gk9;4G zI=J>*>iq88nrQQcsn}God|5yL@00D=!pWvyNGvYs9q8xBK}ZNo(|=v()`k3i+1qb6 zC(*N)JTE6NC;Hp;eLNQUett4o&E4NfnnC`lbpQZd><m~DR;~A)3-!qyXtKI<lVz<u zfP^!kN-#Mse**6=bMy68m;P#DLzOq$ar{-)1r(Q4RZTvu+W5aLfUH%8lI%7Ie%R2~ z{a;PTPb_3$lJEqJg$}joQqW-@=GF$K<uxr9u{)9+yoMTRT^baKI5mKIsrXiVyK5bG zfULY8*)&_ZOj?YjRnl_|A#B(L0}LBjS3!$_ftM7EH=aN^P1|`aY;10=>3brdN|{&z zilM+=qD-cME2;-&jdD_(q5|*<dS?E7PA7D|pFPi(O&1dsmH@||Xs+lqWSJf^Hyk%X zQR*UehM<J5xBKS9BYRpF+4-#5x(9`278ER6O<|{yj1Q7|XU;R8QOnS2%e|RKKulCM z*8~ZcP7RgAc|3Zb<>nu!=3Q@d9@^W#KutcHlqZA@P6^3cp<;lZi2;ZAg=BsZp+lh0 z2gwN|5!!k=Eo>52M7!Y@l{{Ekl|-bn1UH9hzzY&*S<}qQ>?Ut2NFN0)z!#8x29)-K zpwwMM*y2S&2oOCwuj`keEq$XNk4b$n4afc5Mh-MLx;9S68qH??aAg{ebW%(pHCp8v zrl=SXIA_X@T&Rp=gAN2;u2e|qo&wfGNNop%5Ro+^8_kds8itsi5@KM}_c>pKzeeA_ z2rCGJRr~T%+Ya}La#~aagNQYuC|bx(t!6@UNgXY0mEWxPWSS8qr%7uq8ofJA+i3Dv zJiqSr)EGZ6KrXmV`*HBu8=sL(j~F(=f&Pw)E8qB;2PiqC-{)q9^KX)(cf<sVBo`~Q zXJ_$BGE)YPAGKKGO*i$A#hr>%MG$#9SH}l&S*nUhO@XcUUl`eR=J{4BWH?dg<1`H% zkb{3*7&XA$GlUB{Io8Db#B|DpO(Of}yr}dJ^(5&yqI}SGMxjH&`Ezr#zlQ-OG}hbS zW4270Fkr!^BUVTe-p(`<y}Fl}PMw$#@_igSBIADdCFQwLvAMR>j<YEo=s>yP=O|me zs_9oacNSI?G}i{d&<zHp2UBv(D!!dgAE+C{MAnfbH!K(XUL+x}C}qXYV|uMh!XiYi zoCRrmHxc<U1j|U5_JaE8WG#`M<@e5c$)0^az58O#r|Y;9hX*xeh{BKjx6i!FR)jRu zk_?WGvkD|ngY*<Yi9OMbN<)Ih!jL0E&jb`$z}ccEi_L#IMdZN-7N<qwnZ*YVYGFOP zYj_90UlUqNC38+;TR9Xcrsr12F&ITT5K~A^O{|P;*4x?Vqx#YD!IiEoJLS{sUYk5z z?~mC<?7|}%L0&#i8o9hH#P5+|Z<GJc%Ff49u6Fjpm0&~S(MSP>1uW|7g~N{~aKLZy zC3}Z0iXo1lxv6X0)u>HQ2aBQ-0klF$DAg;-dXB*H5ZU37`4QRyVAcmcWVlcq4njpm zwVc+H!ZONu>|#3?^RfF%8i{a0n2IpIh@$b*m1n2zg#YK{W%sx9Z@|oUL@cI=8s=w2 zB3vyQ)HH4-<2F@2_T*EE0AFzAT@m9^ci{`2JgrK|{kPF2YjNYYapJ9SE(+CvN)fA7 zsM>eg(@W}l+XJtR6<$@1n_5?Q4(F=(RRieLQ!^P2T$JzILI?lt@wr4FpM;$+E4C>c zV2Ybxm#sz1X#TW{7jb~%B~nTcmwwkpa9>?dwW!?7;C0P~XcDP9&jUx`T&@v-iE- zyJCOFswe+`M3eifL3$V1)&s||xBc<r=xor^Vi(L;7Z2haGQ|95{-SMz$NLy*o9hD$ z=qi@)%h|c;bDN6e$M<)1f1Gfq@9X@Pn$Ilo`VAfdftunmtD52C4~((T<zi#j5oqfl zQZThMas7NLFf4k9EPs0Rcp&<gcr$s8WOO5DD9lcH5SCU@PB97k(y_QE8=#YD-A5Q< zQVa1ECxr&U-V2G@P^PbRBQWXc_B&;1;m8X6rOh{*R-6}@{K|^w!_h2TVhtW=uJy8d zz(SWdNM>BACcMfi@JE`2@;8Iy8Go~Ok!l*9D)ENwT(UHta=`00v<DhBMxhO+4Ujz2 zh@S5ShL=LfYD3j{3y)1&(~&-nm_N2CoMP~aqru$T*~KDc<PcbN!+b7sV9-kTzzs}? zZ*iy85>vM#b~6CZs+!m&ZS*%+&1(YbK?L5dP32q5sCPU91PdZ=sU>{KB(s)!BTs!n zCuQnlOM~BjH0f|)zz*On9i+ugcDiHJqQ&{M92E(;mRDDmQN;gT`&mgQwn_DBYR<#D z0)Vv#P3=Y4S?=A4qVHWSyrJfY%`CthisHkL>W#~=a}O^7!s(BHK6um67TT%ImU5tB zEAt^Bu3J2kBhGwuHH%<ebx~a|ANJxrkX0H6*i%`Jq=)F2nmoA@>!8MIXJoNtXL`_G zdhdLw2w_>GHu*zXq=6H!dX(le?-7f~mb&Q74&E}`s@iz293rc%-9V5xMoH-;1r(>k z`U^m?xjm0KeLiwu?6%)5e)i^$jO0AXQ08ejs%y-nnJT9}P75-O3iaxeQ`+^`!o>+Q zY1o4$BV?|S%6i4^?Dh`0xDr$ZG$-1&GErY6g!G-W9@K*-8y#as;P$H#VMm(iw~JX5 z2FVg@1F=&;!5Y~crH&Sd!!?R;W9K9&02jgS1D^_JYcPq)7(o<fTSVWHsW!?3!kzA3 z^5>q}fga6t`Y~d~FvrfvC%{kux9FBzr7S>f<rPrE@|GO#mct4Fr);U>l1MaMS)D9L zL*1Sbk-rC}0?kkk2EOyy1j?ytTl|pcQxI3##3P{!vgjU#MsJW@4$sAInLAo8P+ba& z=p1x0*QBcTEM*a5uAB-y5HXNy{y}@`EB0_lyQm+Y+LqE8v_0h>FE&ojHFF)Cj!Smr zBGHz&VEnaWc$_E7<;)U&n;jjtkK^%%z(X~^iLI-#Cpcvtb$Sl{!;BR`ld&<>)aM|~ zY~6^0gsrTO7`-bzj_?>-6^<4(oXG(#>Np{=kTX4XB$&3&gMXkK;V#>xr8ec|nqnub zbNp*Xt9lz)3V(U=|8Vs7@^yOJUVnO_zqyoktDUXwVcqUw%kA-`q-VP#s51rV=l^e_ zxoKtcJJGCCTi)q{mlR`&5j5$Rz%W-p7=F3M%-Qq=y72+D_kr;R!tcixR6qciFCOOr zFBKj?oZt3d6<q17tgK>I6kz~4>x3wjba%Vi(QUcVzxer%1?a*2t&8f6)h%7z$JOo( z8z=r09~zr@`MvE8Jz5pUP+aAxr>vn3a=0|{BU0IFEhf3=<EigC`P$ZtUq*JN$)9tL z*Pls`-8*{OQ}aG$%4`6YXzfP@_fw>IbbT$=m&ZHjTK4G-K5m*^VfLS&2f>)z+y2J+ z?1y?YX?_q?!_elXNr$U)TBPn{D%Y!3ERpvlv{XWrf7Hhl7HJjyp{S|1rml_#8I1M9 zuKYL}Z(`cSYj_<mZtnIASLu7*HUhhruO5$!Px^3T$V6gEG|zyHDKR6`d$T$@__*Ic zCvG2iuEX(TuJtQxcUkKEAJ55mY5Tq(PY<MlA%7+~^6CtW>oyr4)6XA59sOP(KW`l) zIgOOvto-4Q$bEvUE1r9@WypiE+t)q+PIH3k68g>O(!bXVU!ry&V#OFYWHLJoC$!Tj zHN}wnIX|kCsT)8{YK=M;Jfz!i9IddCb_#%QZTe%^n5gq=$YR=B+N!v$BWituR;X&8 z=uo>^fdk%JW>74o2G@}dy8|+Xgk7Z}O2tk``>^>$(7xb79Rg0+ni5Gn+961awu%v( z?x2mJhcmCz*WI9c>W(!x(Zr4vl~#nT&0GXyK=i+Z!DM01=%g3^B^*w#Eu>iG@$w0b zOEUsG=3?6flcY4E0K+8n02mOA={9JRUd%PEGnd^^giAV$uV+SGw!}Z4>bnTQlPCYE zW8LM`FaN7ZeI_i}D?m__&I-)}U!~1M!1cjUJ}PyJOlKBFt3OnooxBqKVDo;XsL#ma zARst=6q}&bxR%}2eyl8w=Ko@NtBQA%|A{~nmN=KyG|aRyv}>NOnf<K}+zkS)7lhu- ztB)*Mf#45S9GvOKLURYI-tR)vLKJQ<8B&1G1TT+1d%~Ke6h;Y<iwO-93YHI%_~h4r zXl%u$5XF`9EP6sh%XWBM1p+og-^%z0>sZV?bB<@jHTZ?1wUC@kHiU*sfdY)tVS0qD zQDb^e?%TJg&~}siruS#8j^Fp^2)!(PPD3Ir3ERbv!31;5i%g)Sv;hPRrH)u{R&Pb3 zzg0|=rAQYJ%#+Wq*!hYf3K75pg?LM)bgUf-JQiE{8~DUaQrM&{t{Qf0cTUFgvjmhG z?+GBynkSv89X0Ff#YuJelahH?OT{(7T4;1M@;mt6Hef(Z^aw%$Jx`W{ZLz}d?q7Bt z+)iiH-5>i=e_pa=NDgL2(=%pmX0?~Ipi1=4P&tp-<*zOQnp^86>jl`FKL+_}n^L!_ zx_ayDx0Rhtg=W+cYph(*vn@Qie>5cKQl7Ne(L*O~Br)F!X-7+p#jo2Lu>TC7so;i4 z(0c5r00s6&?bp%%6JZQhq1{p0@tOWths2-JL0mXKiKIlRyDTb_b_`4iv7BPt%$%I! z>567JMW<;FP3s>0hd2rnm9|U;4s~X>yW}M<s2G7lC;;q4b}9;1TXi}kVYocqS<b3D z)!B;e0K5y0#{!k+Nk>n8C&3giv*=TYj3^PZI1w|YWZ>;>x+1XCkpvkQ)ZWYg`eVt= zI^2eNXM;_RUOq1um;Z7uZ#v%3d+Q2gGs&{-w`=VF+S#eu^lpPI-K=xbHNOh`>*y*> z`9%KTmRr^ySrVb<{H)<%xFHzP=9R-?Z7GVE@Cr1N+uaZL6B#b2<AFQDZR8rXc>}bW z0)hx4j<?mk6MI>GZa8ut$`X*4PBfAAPR4BXI_p}!Zf6r<K6`DLtXG6!zvN+49<Frg zPEQ>R3Sp{|J=^()oE@NqIbfC<qTPCp)J!q@8F0guhNpo(4^(ngp{rUj;C<STwO~$& zMX`)+|M;dR&&G=I?66DzzG-IRW;lP7dfyv`=*d#;VSTDE|LdJd_w9|0NHqpN{Z3f+ zvm<3?yia%7_X{gIF%)ry(5H!0O{LqF_xjrAX8^6XwZS`N_UeF>+%dw-l#`xJKCiFG z%Wl|At*rLBxf|T2G`6)Ql41S&$Bm(Pki_C1)2KI5#!g-yS1ZV~jAp>~+he}l@Ai41 zN7~&!-u~wKqW9)a=qdMT#7C6hHQ>VG;QPBceCeZ)9)EYe@9qSf*8^?kmE^B*_#_qD zu7S-LcMjWVJBOEY@^_fzLB_8!j^N^t&j|F>c-m(PJ(}vsD^=1wc}<tDDq>VC>un)q zc{LK*=lvna-~9uS<x0T2-Kt<3?qM;pC-COzWLPT=ZH0|EQIvj9{tln3sx8YyIj28v zXJT3$feYZLCWOXQ1qHE1bU<QoQ9^Q%u;h3vaB8aftsuq)nVPYGuBV@4D(b#cYaX5P z)@bgsZ8C|0Mj5j4Sf5T#tNczB(?Z>@+>pvjBpK7$qji%Q$++lS*A*idGhc~&gMtW( zP0J8OV3U~riKGSI;5ex3AmPrSTm;wjS;TT0;)~|>m9thWwEUtD^-zxFSHa@HHEK;5 zsNXMB1W=FCyOpDTh=g!~QgRrFxB6^xS8nih!KzL@#>=3gWVqcFFJ2T<=%7#5IhC>f zGMJ_LVq>leyJ*DlmV*TQr&gCRvg(vH-i-!84C9SxkDy4FIEh~>v`v&SGUv7CAjz_n zQ<b75xw%=PFr}^bPzaDD7ga~(ykL$9qzOdt5)A-S%TFd#iG%6KjF@<I5hu(lEJY^; zvphAJv7#DDHkgg`i{z;W;i;6W^^(^X5(TRMAdJgl1WT+WY~DL*s;*OCG8@(RIDe&U zhu7uNn=Oqj6!u?|V2@N*5CCvU#?1#%M-JJ~2FA!R_E*^eRe1l-=DOr|JDH>Fr=e0{ zaJ2P`T-K?j=UvPMsaj}~1=;!e<=2H-+)9O{=pIAw>O7gSFpP`jGfVm+nP<GsPot)c z#);9gQF0<QmL?J;N!Vui{dsFHRO?oM^x=wReYh8jDF&dVGvQ%qTOeYmwwQDkR0}kt z!R8T8{{k(&TMXE|Mwa5_!os?q2J%QL9kW|6RR%TD<ts3?@txM&lEe%0aj<h{R9J~@ zGS>OSys_Rv>4sJ=Hj}xDFciWoeo3ftOy+BoakSlIWum4qb#StGWMvBX`scP{NdCA% zYAPvdvpd*U*lyiilT|^TMx{y+LJ@(}aVK|+B^n7v(m^a%_w!S*>h^g3UBwI4DlNi= z8{Th^<j5^OP~13|UbT1OQ?Q2tli5HW#t%w%F7wOAOMO??89Bxn&)F2FXs1LL)*%dY z;t-MOeYEucYmj^nZ<xlQ8{&jf@6qSM@BMN<(lmu$`^}N{S>NUE=VIsY&a;jg2OgX| z_|Ym<ANfN7@Q?VvHgMbS*ZMg&m$@E4>}Ev{m`Y$5P$>~XP4~gk^N-U5)C1517B5K8 zAsm4~6@`LSR=KUkofrSqXQsA>gaAZEC~u3Tq31g*H}`@6=YiWB(2M`snE$)@?s@&H zuI~pBeJu2rW_5M)V1xCG49DUhRG49aBJ4u#RBOa|$Cj&gN)_|v7N41ZOdY+g^3@|N z%}2l<rLA{yN$t5QS-#W`p@4Ruv9P~Qp<wNj_EbLD?%Lz_dz(H!ugC4o{?~_ivSv*E z<%1`B66uBeuJW0L@$uyaiz)I7xIe%lwch3{Z7gt&Zs{1RdwP~##>!J?Ca=%q(o)wA zj{K$^yRF9&vhE9z$qg3MwES$Z_vcl(?8R3|P8dy`gQm5bs55jquf=Bv4&GhUSib+; zHM;u-_wfGd;82;Xj5e}`pTud*8)44Oua%v}4+y}1MzDT%(MdtfyO_kunDX-i|GMs~ z&IqFF1ieBVH6_I3w0*f{)_(n;S9lej(%(d9h(zhu$S2L!yiNEdzdgjRjLSo*qRvT~ zM;rG`;c9C~No9^19!{qm$n@fBxDB>#w`HXg4O|(rho#krfu!<<f+{AL5g{cR&W=|> z0T+{thM{pGdI?Or<do0_=kw^SD9_foEa$XGXgg-r#2%JCLDEvo5lSGGyaHOlEYHM< zGX0*Y!tm|kWxvmfaw@8=_@FPr5@Cppq^2}0&N8|C&$-e;lYwfVD>!jW?A9-}=@y4Y zV}x*2)~3JMnnHgCY*XY@IuMm<%KhW}H5q1FY>}#0*pD#~_}>i}-_F;k^kBD2q7xs1 zTHdve)|1F=eCdyL=XLI>oS0VI7~<+T|CEXyUx{?s%LLk#re1g#rX)P5N;}GcNzhb= zW%SJWD}<0HgE;v(E!cLta=-CI&o^Uv$Ql<rCw^?F_Np2zpV$CALXn^fs>_B76M|@N zng}9H_24XWcXU0t!VIM(#$Y^A$%L7Rw*0N!DuCjsQ3u(A8B)*dV8KFZNO}y6Azj^l z^OPM-)E1FOSD=t=beciSLVC^d*d6jX?bGBPCWw2v_Vc;9f6<@qQs=b$Ych@pu4a^J zCqk};<ldwsepqZ&+$`)2Ph~2sLh?0jx{{=gnMo?;jQaLzE?pKSLP;evqPQ>7ef2I% zy{4jSX0||rU`&>8Ooh<^HAo3yb&>(m)jKf(H9QP}#R1vxsqdvQoiv=dV|F<$VA%|T zksD7>H>XdNPG0uE-|Bl?QB`%bRa<crA@vk;q+&+Jj*KYts9E6LEb3_Ga$==U0YMcg z$w7)Vt+>j_S^-uCy}wmb><n2LN%ch`Li=veqAxRCwoF8Ww35keyc`cSy1Q09f+wpK zQ@s7zQ34VoV_lOdlU9~<6TWQV4^K(N*(rkiE{<@TDeOYJfl~V|5vO8CfexU}8Rns% zuf!ryElPzR)kqZ0+(gMKgfwoVx&-8azyZU9vbAGaGN}H`pY`+6ODoZ96e{$oDO0Yj z<DoQP+5{{69t_22iKNbg<z>NpR<dwD68N5}+=FWfA`j!|y`#~N{;Qz+O5Ee25MP+N zEv_REpyd?l+V|-Ee0{#R2EL5ernkq}=Y`MMvxT$El{=Hp_7)FkCT*EgaoMGNzO9?5 zQ-245e*FK+o1{IqI6`Pu+ZmxKRHMnd7|tOQ$oRl5CHYVJ;qGw~h}a>CgaI}Zr5&^K zHm-{5%QQj?E&-#>xM4npV<N{P&C~hvOB~RnBkroB@1LU_?yBHv*JtV}mdXvA?9OKe z0hJGF+)s~mB;Ee`@Bld1+e4bIxI817I_ucwfZ(!{#Hr418FZ!Ntk~%pVR?THIPA>E zvAQ;S1vCN-(0t+@I{R9^Z=cj&U%xw16VPYc0rq=PtbPr_YiF!6uO6x)d4_90d>e?< z1Ddd@<}Ylk?w)7bxtpY<3XY<G5TK(q>SuKqBS)8s$6Tzi_8)O&H?|)O*suU)seYc! zANOuY)be<PGC^`)x6-h^_gyVE0r+_SKf}Cd{>&Af%e7eiW_NKgfAsatZyr+cd$)r8 zZ!}#RLe1rOUjn=vHm<zBp64(&l7QvVmvGqDCj09|T%)UMuN>I2TWy6YgI2Dy#6S{j ziJQa7CAEqs0!dVgTy9@LCcZCU4TaJmA~1}vXp9o#+5Q}&SiUo*_xrPyCXS{H<nnz_ z${**O6f;#UQEOMYCDR{?_t30tz88bcNjohJ1{R&>mN`5O6bWg^6oa;;VsqUDs69#< zMPJAYhp1IO!7;{<FU5nRPqij?`;u0`$uw;nZGNJ=@BKI{0uEl)-l@cLG=nruh3RI7 zfQB8St+mbPa^}c1WRf%CZD|Q$!9i?Q8*(#yeyc`sqDhi;!Ueym$_%~~%+)(}N^>E8 zZ)S)&l1oUJSSShc5zwjs7&!eLUqnBg)!BDykZGIJrEPD5X~`@}5tl}iV@79HA;!=a zlO$xW%G{CE=$Hk0vS}G%Np2ULD7LmhK@*T53ZHpX*V?fiGA#wThmT8GEUu)^8s*=L zwdeJ1j~qEUa(=ONJ&$SXP^piq{&f{Tw2gMLi6(?@ucRQ6u_qK2fFovt8aD7FC0N|? zx6=Va5kgd&#&umkYoDnBNVPNvIEp~2Ke*+U9xHF4M(F2Y`(tQc1Dz3qKlE*x#&zZt zs(~NqOjV(Eq6WMkZJgG#P7-d^A$G5D(i4{R9g-0kb&r}Gw8qNKH}dK2lj?lE?oO}w z^>|?B2-_aLHZl(gAEx|Ie^ZorqZ%qA#=D5OACV)w_aSbrg^~bEn=-k{7+KsO$&ZSl zjFqW8#T|0d2eXZkOmbxx)2jH0)?`8yXC)ziOmTc6ZD|pNhFT#fh5Y%9`42MDu4(mE zXPgo;OaiAL3##Bb>Wdk%<{!!q7NuzROdQ6@kS;)n7@~FC75`5+SHHVkzf06HSNn8l zJElxHR;jy(IGAn#P^%oMGoo~Z&WvK|ClxmYBYq2oo>(odiw`PW%caKCig%NqBw~%p zrosftA)T^n7=m-w%kLLnd#%es&5BfsT%fLTVN2rBtPBnwJS8XhBn8SSXsHD2AqK_k zNlD=9RcGfK>hWr$Zi<(ufq+Q*@o4n2?nt1yYeO<$K<Xc<{C$kj*pVpa&79!KQzI5i z45b`S0|8jzv8~zzWy$@4L>ujNJd-@xL!{W*3m3Lz{^?{j#!ZqURm9|t+NUR3p4>q9 zi8Bpv)FKuU!g8h)n%f=#gFmtOvI4Ss@x$rZ1bnd=t{N>2*^KBsSX_l232bCr7(x}g z3f4R}XUM};Y*TJuUOk^*v91NVj615Xs&hWR`xnS3Wyxpj!Qt{J=IP`QzpUx$)#OR< z%!Ka%ZgYKY$IxM9101psO|J&PfA;@9cqM-cfGB=-m0p;0F_PnEL{0#3f{DQiNRE5r zNAaYeh;R}Sz(~>}AW;#)DBP{)rPjjs73X;51PD;srEr`wrB`n5uFDrUzEf}kJF(kq zv3-^V`!m#E@Kv&#PpAc`7EM<lE&2;`Lr3q{IP_vohwqc0P$Dr0eaS`U7u@K4)u+tL zizZ`u6*K5N{!w1l*XP8moC!f|DQj<#Y*i@ZiQ%ycZSc9Dk4_=;lR>{y<T8G~@8{?` z|6bplKvt99JEL4V9&ca0*QUa}bvO7fr5q|B9@|uPBCbIY55F0Vy8Xj=YEHa9PaNC) zt%jRyvwC~qhsVR~nu|0|_z^=GgUuR~N%?%Cv!~}!n5M7bx;)>XGpD6Z-db_Ndft|m zTHC;T<<=#{GwK@_@TKJI?0PJ^qyl~1*~Skx<^ubNAH2G~_a96oz>dD5x2c&sMO&VN zv<oW(X;s!HmsrN&7o?F^J@{Eox0qO=n<u`A2LN;pO$$e%{J%2fRLudrCa^;#%L?=r zJ-8A^hGsC*lH@@qj@3{zSJ*fH7MJ`gYXyR<Yo*d0Tw~P9qE|NzCFh~#BDg?V?2~sB zlr1D*#Ft@&-2s!T6E(&@NyijW&hrRp`5;^Dm+e**JG9bNg<D);V2Z`oub!}e1nf%t zwAV%I-^2B4%lE}(=%d4gt*He2g%#{Pg0izRshE`YtjIr@rX_g*p0y+c#TpXDS12tO zGT3+Srtg*|aDZLXO{4-~%R2@C20j<=CT_5R0cp~rv(qn=lbex%$B={%*8|h!>X?&= z!~;AePUjm}{>+GMnWZNhK~IZEd#2W}C`}i=qvmjxZlP*#!?vUgeDV!v<>1*$bsp4H zQtx?4<bgjXWyg5n3fvRo^ZGkp{oD3m$ngLk>IfqxvJoG!<GHLM5*t!1Ig`mK=>iH} z8)XMjT@;GwnWi3Kh$xZ<(O`QvoF%M8_LKye8u=H|rS?}7hH&&WYm^IpZB+Z8LO7YD z5>d}mIEFBSELfB;$O}A)0{!rzRUEM9+7b;k0_R#nY%Hd40i_HAC)pi#Bp-RY({obm z+rn!w#s6giR!5CGetx--J}*ZnnB9a5J&{9Eeu(;jOgQ2$vqzH<2&U~#qCa#+A54js z*^c9@0}^$t&e~w2b!?@jl4OAa+d%P*dPINxROE`3P-V6uUmfS;Qg?87o?yVG?j=R; zbXfl;#dNGGEf)xNXox8bb)*9)xn<PPzgV!t4lR+#-)wz(r1!R9+q+;Gn=wOrDo--o ztlOSWDu2={AeT7%vQIOjJLf2dNY1;|+^X`F$)~lRm>el!oBC-uE4ltbKtCLM=PQQ{ z09C*<t;1@d&BFI(lmQvsM?t4EPd7CbC_r+DW~7-+9U2<)e!1~~J}rE~ize*zDY->L zK(QL5l2;w$ERVyHWI^tz-h65{4VCnosju{i#%6U`?m^ulZh;Xe6^H(Zuz^DvPa1|2 zh7v^hWZ2lrw-9DmXkjg|L^1;A_$Pz;1hd6ypa_r!$;PC^j3FhC3OXNAvZ16BjQwOC z-g0H3+5$(kI*gzQpRyzgL-M{MvU}EIa{{cGRnbLDiB?lDNY+IsHhLvt4HE$G0dttl zm>j}qZ~()c$jrz~0iLB$dZ%_S?;*^LvVEn+mfiiT`s%$`zuk^czq@Cxue007xVM{U zQ+xLLSawMC9iL1}*_h#V`R(j(LB1-z59UI-kMF?{Vu)-pbypy+_AGsMM_aFBdFExa z)mfIB_ONqZ<0Pxp5OK~QrVuPZf1SH&=NGd8wYtH3jY*Fv#Q+FNlTcFd340&(<B0%& z8{jb@q**NzX&ZBOmbWp#UFn?x0V83P<<)q3*W9)J3tYJF*j<O3{|!xT-o3<zhrjgw zJa^mT*RGp0#vfgY{`}h!if`eg!?i9UtKCw3&ut{%;bfawNP4`5OLu_*#Ib9<CWJ+9 z8fV`eBeN$5zSJG9K>Wxg7plyoC@>aZ(Hh<dxfUFs!Z@(P(97lhIqt&$8?H~6WtRHa zmBQS2x`o%uN$WyCrr~wjT|ph@0G~;Zpj6noX!l)p^G~|W=Sm-;X1sZ6%Xv<hg`0l2 z&$pGQ%lrm~*x(HN>r(@pUP9D{_1F6S?f(4}@Gi#<OEiIKdSzr4qGzKWL><%9Mksxy z_2AqE+35`84~P7Le%!zIsd36DcJ+$BQG#L-GgvUq6+SPwq6|Kfc^ae3@cK4xdB(u8 zrYFjyWhw=9?AIo#yZ#jb(xA=ndC5fNQ+?S3iR@r8zZ9ETD(a0Wb1}eqa9ZVUi9=xH zZSZ{F@3MbL?Po8eZBiT<<JHV5WmK}cMD7rD^G<ux$%Wce(i0Nme2#yOaI$8i$*XWD zbDKelu5w%8r#}kAJh~Oaa+|uJrs_L&YoIoZ+74=mG!95e{c@mXN^k?AY#!Hym97*? zFtLj3mGk{mlpqTY-pvLg!9Y!iq|`wCEi8F%Fe;FO9dtvYiidMb;sb6`cN}2|WCc(9 z$OX9hxxX!*pPH5lEZgFcuML{SO#fA@j8}F}(d;BJQobt)8Nlm7Ob<~1BNXiiu<3Iy z#HF}|A-&qgIt`o1P{SHH)ujOeGJ(+rF6*1@N2D`MC?K~=HGDOmJ|8o;=kx#M?=wW? zjr2B`jn|YGtjgFDAA})^2@-%m)**jB0@?lR!++d48|cXxt%$IwSa?sOrs*YSYU1bs z-?dU}86XdMRwtlGqzXD?B#>PHw*=6ziH}m4&esP{_%2Oj>GE1wg2R9m!X}ObB1VOz zkxKGB!V?h!bPG7>B!ckY!p|bZC=M>a)$vE$5K~#eOW{lgiPhbp;lxq`M37IChzbRg zPshTTw<>4#@J6`5)XFcg&T~BrHLTZ+hR_VgpqiR7sK*M1J;0yty(=;tE;3f)2#i}l zYUfQRB_U{AG(tP@nh?sZ`BBQjF#7zDXr@xo^GaysVoaytzj(nXn8TmwRr-(Ko6as! z1p6_!&kDnsvrahE0WbeJ&CFz82+7nxxX0%>h&GuPL*4!rE2eTg%1Qg=1;%nLGp@<1 zV!$l$eq}^`O77U2vE>%32eu#?(=l<30Uk`J?O}tel4SX>y$kTyy&m_!M>2<xkB?Pl z@>L&Exsw`-Y(=A3dK-+=A*>dAqD=)fQ+#q%`}5X}cGho?Q_2zAbQ&k&WyzEy6<b(6 z#?r;I#zf0h;e?NraHJ%_jf}L0l-`Q!oOsHj7U~oKI2@B6hUUj7_2zMq{=(l-YO5hl z!D22OR$x!vv(X=K2wTc8P({o}N?8YK8E)g?*|wf0#7JRW%7kj5q!rS2vaB@1?wAOO zryHm!ow21yjD`L)QKexJeJ_A&W-!vInHe$5NGaII2*yi0(L#otv)JU=eRtcL<vP(m zF}K}pY1&@@G`QLMXtL|m#$jp79i4+A10TOkoCkvssX!T;-`)9vBx>F_~RU$uOt zgtwR02t7^U3YM|8_1Wxj+jD#VG{PtQ6^a-+yBY(_#BZ>F_k4us<MF@0CKI20OGniz zoumI>2O9r7hpc_kQ{7y{VuB<l9FCws0upte2!uuw+)u++7m53fdsB|!_76}d0tAl} zG)a@mm~mT;`W2tpdJ`anAW9!{Y3g<A_Nb`)-e|J{JeJySlzut?rlw-<5U{?rAcqV% zS}mN2hb^`Z?%PoqTG%{re%61yK_fel-F^E`bEt=8Bvw)D;TEeG9ajmA(WDO6YJKVg zt6cM#LulHVybm0+U2)X%D;SS42G`FX^8I{#5bSq7UxqX=pgFW42+u{sR;9INm&*HL zV{GHhVx<6LBVlFl)YAMvCmBDBd3$g?^uBWx)8m%*I@dvce-3Y#UUoI_*VNnAjd=Wa z)#!m)_uD&Ko?cJSzOM8@q=aZxkz8^!Yr;rsuZ||C_Lj#-F?(}Bc$;w}(R`eYehqmq ztS_sq!#}BL!Tj8QSzkJLFlo}_&t%u=&epW%cgUoA*y@|yvpG4sR2Q}@FHY_UMhjy( z>oNk(qe%41-6tefa1-HJmMyo17!GMZ_)?5$3u7iC`(roAo^ZiNEF$XfAgcZq0oAzj zJH5^?zmoZY)~00k4|CCRn!gm|P<+%Ks3dUF>Bwprk>^j<77`JtyYY=X3f_r|;^+?w zZ}lAo!nmSfcU{x_o-b&GFl}vHTZx$*8qDjaTah~-erjua&#Y}rzAdl;VsO>rBr#4$ zd~m|ZMVcj!wCWOJGZaJAU-&(FSmzJnU*x2r*@jMmMli<2@#I!r1@`-&Y^NwkE~ zb3{#PYZQslCB3!V3k94WEBd?M0PXHC$E&-#IrLIU^-_UyDLaUebx@2Z2j#jlFwU!a zKm{P+cNx}@MFf{2He-M=u}2eYQu-Vy`H^#cjRSE_gdXB-_vDB*(KT$rHXXtNoKaf? z5EC$&WN}a*M>+Ukw^PC3nEzaBa}t~_YKC`2TOenpb2%V*6h(K>FC|5oijugpq$)Jk ze(&Cx3N}g)33;S>MN%)Y+Yv~`wLJ}-1kD*ER+k$)9g7pH=CwN1jG+*#SNIQgA}Gb< zD#i(DI_g8<sP52~iCLQ9z!dGFPAvYhfI&7Ti0~1tqAGZoTz+_dZUQv_@}9K0@qHdA zitYO*CdT~8)TUwv?wzITW2bdEv%61%%_Ifma-0%~fmclNlAHSHH5F{MdG%7w`?rJB zHZ+QR6nqa8q@sNALd(RGl&CHpY8%~(69MnPx>HO>3dAG!1}JQi3n#&&QgX2*ld0QH z=;+PjXwN3RpZ$pG6rB>8Ea3>r0Uk(Gq`q<uOg}3mcQmz~KA&Fy9ll!J?_8-nOxSId z_7o8A|Dvc`*5(n8wm#Xx*jSX4SQnVH)94jycK%9ltH6Jt{_C(sI#-b*TtJ-xfzd1g zHt2*wt~~NYs*uMLDX>oDFM01iV^f}?L5vOG0{}xzfE8jhUP+^)Vzs~_Fa%67DqT9; z+1dHEKYf3H4~6UJ<>tbYVE{{4aB`=+u?V2r2iJsazSVW8Wl%L%drvH*bY+QH$Df-y zy8+;)K@O}yl%<iyi48L}(@7djP^R-OkrKax4v<NL(~V-q5X2)6DN#JFDNtzQ(yOd+ z(a>PZ)k*ZMfYys$q$#<R-%}k6mft|FI7>JDdox|{O&r60?X{6li?3b06jwPfPSYoK z44^HuJs~OCBrKQUO7)RT)3JMsGx4}iDML{L#7BW77b85hNVV9DWz@ia`;3|g*R6@I z&qSg??I#EYotaa7l|M%^<6J;jiLy)-GvVHsz)%un)2<7QJ1#sdcx6ftzqq7(sOFz0 z$lGYAurzX*l%KPCpX$iRO+PWPP|=wSYS@>P>&l1UGa8*D(lc`_p6h!(KlsSUeBb?x z63f{4p9#FjjzknCwCY@~&3xs4PU`|yYcB)`GSY%riAY?e8!o;dI)U~^U=o=?h$Oha zxjJFx)tqN(`zd&~Lv@=M#2Ohuiv@KiM(kO}Ro;EM<HXOLT;OKZ?sBw`y*u4}Y$`jc zoLiA7r%5+ybNS1uVa-frO%e~+6RL^P|2e~;M)GkRuWI?~zTkOQCUSJsKI>5H7r5|7 zfZ)<C+c(}6(g%5AXk(glCg;S0qi!xBL%?5qqh3e<dy80Bl`P*Ia*Z~#Nw<xdq21RX zLuE*{DU)3zhU-Q~qb~lo)}=NBQcUiXGwd$ET|9OQsifbMUYdRo9X*wf@7piXu~4S_ zXCHD;M;QC0efh3fQ%DqjM|V8BihqZP-xfC=LSyQ$M50h{p6vXk{4CDCwrBvj%)Gd? z^ACW=Q{91=uEN6269!w=CVSuUxop*Xs$~cqbO@CQr=TX7z~CdW6NIvqFT5%xvtI(5 zIX6RM4yNfEoi}Bbk0=fUl2myP*)x*SX7$zP@>8Z193hU|25tWpsA9H!oIKix_|KjR z_b!V(oOpyi=g)<o!SSwQ5w#2dxEssBGToF@E~1pLOTXq(Y`-wp#i#Q6@N}?-5(oUb zuUT6K<yWan$<itQzE<xITY`bx`@=5gN=MoQjTbG|7)zD1#-`s>1;q3qp-Inh;S<WS z3NjI$7amm7x(jAvSm)HSA~K`y99Kx$GDV7XKF|twJQln@1v@7p5tTE0hU^Xq6Rb)# zlT!~_&q7bt=hOb%K$Gvs2N*wpw1THkULcoIwvB`tVSoVA-Z-{$eN@#7G7Fg>SnPOJ zrPqNhemOJA@?4D8>p-a*Cg2I}Dfq4IQcnm-=uV29wN~NCy5IPgWD)70MUT|hMO!uo z_|4DUo@EepIkgS(Md4MY$q+3M!=#qylAFCAC*+JmF6Zg&);ro5xEG*2Q;p`Z0ZR7( zGI3deTZ);YHxpB(mt5v>lCg`Xl*0-G$Dc?~;M<06ZMv@7V0$kc>F|I{MGpvJprDBo zgTVl*U{|J)a%+y9!o(NQ*VAGk7VR4*oe89tuxi;G%CKJeAz-@iF&OKsvHaf8yN?^0 zwW&hrq0x#Zd>7WS-BR4nLQ4oR?4)+JnxIInV1;ys+rf&u^+pV&2pak=rdhwZ=4WcX zp>tsBdS>>Wq;41@@eX^V;liPd$5ia`eZhuGsHrft*vYEbQqwZFbM^q%(0@6$+BqZw zT8auM09FEpR8aYHQo!`S@AKczP;y$Q3oEti?0vf5_j_``(>H&QoV+}>lSWEv&nsZ2 z<q2(`K}l>F7gzSFUqz8SG-}!TWU4JkvHV|#{)O%TN7FelR=PAmI<{@wwlgs&wllG9 z+qP}nwr$&XviWxJ{)cnw?XIq>M*&wlvLvHWQ&^duvN(+wLm7@1)7Kp~v}w^~!T_pD z$}TYpdc^enc(OpRisYzX!O7U<_3`lV_I4J-!P(i_+xz>fLbd&(Y={SpDshyz=$p%l z$6{tj%ZU7eU*`E_9B`st;ZIx?Ef!cFrN=Z4mP2E#*WHH>nnBlkniZad6|wm`qhBxz z=?Q4%+%gHig8WV67|}Z0zCB~H;w_n3Kwju+%%N~SlRqJ)MufFvxM{UrxwKUYxUN)g zn{6rXev|g8_KpdggPu@Wifu6pN5b;`n=?rPiPaOdWcP4S#U0g=E+iAp__{>kQ=bu0 z;y-+x4VQR4#nxKwYr7FgTIe!poR`p;{u&`K{1Z3~qx0Z@Unq)#{E*IcV^CJBOtEW& zEu8LYkjlchR>c5QPRJ~#&)|95{{(UydqZYdE!?LB>hkxeyJR;HDay1pO|tPWpDsKd zP-||&$A6|)bhoy)J)hsuZz387F&_R)7iCTTuS*_e^X2%mdJu-1K>$(@Ku_f6hhp3Z z)Q6pW3&aCW--mt6rb7nd2NEAwPY^E5(9F!c^%OGQrM$#U==TTe58w(_y(pfGOHupz zrbCYdseo=&g&pg6S6<?J+Sv$tfz<}<2Av52+t%9An&!$7F6FkVvJ1Awnb$)0A?3jJ zPQ}a_CVs-zMC<v~wQMt03U6q&mCDk>XGyHyTa#4DdX*>V(+w@#3G4Mxu)B7`VS@`N z5kzZ0`?Zh9O~=|4{Y%Z&yLeZ@LJ~aop{0i5Upe%I7FAUB`aC5$wK~{J`>l?pXy$K; zIz=1tE&2nm>~58!Myn}xZlBK!`jUye;Z6tCihAq7?a5fr^S-K|4Kc3P?$(dfzLJL` zbuD0ZwZT!Ut{O&pwn3-ACG0)we9P)P78eH%xXw{&Af{u4B>5rejvsF!9OycJ0AB7A z@bqT^yy-n~wA{n1zZeyGpW`jt*eLqvP)pBePB;DnTfnv2Wj6*kw1_O_oeqSPjVuRm zM?uZHchOmx%5x76j9qxpVi3D{Jmk#wVG!#{lX71Gz&dbbB+zi)ZpSA>W)063ts(c5 zW7-Alu3qCWMd7sJX&1$yock3e3hAeh+w26`+E$_|C~ixpa)M^V$S6hww_r87_!r|= zZag;SZvIub4_|KL?$z|b><nbkUUE0<H<Us6$9tkc)m^$zU0CNw!!^RBw263j3d&SU zVYX3^UDilIdY$N&Wh(qv4yD?&w<lv1xidZ3DB1qa;$fu;j9~SOt<VGGUK&6l!1qdJ zGie&l5ww0snz|qkVkYclJYGPZTC*QXUvCeeySa~sgq;ua&v*fNs)7(FQBehprCnrU zV$5!Q#Ss=ThTON@D%v--ePE;}*e5@DMd>BeN)1@fvN7=L*>StyTE`GD0N{y#<(mO) z2<@iuEtr;&|C1vmQ{>s>W|Wr=`i~hP7ND<&cnM;7?Q*mJA(Xs$Wm>obAUNJ-<6F@f zG*lQ$R7`&<c-P<_OymgSc*9buW-rGMRiKQ>oE$NFZ()_YT9xGn;|J*U`6v-|yp*tj zlZgBg$pVqM7wiNJy^JLGu~<Q@Z?NHs(Rf5ZQrNq<-g<Cccbz3BbNWRhjO7uitr~5} z9;aY0J?Azr$EwfG0670P=|&m^K%+I3RTRf1BH1+o2}v9L<<>H1Ai{i2@;uz7B@Cy3 zyQTCa9G=6hlz;N50Afv>6IM}5bHsMhZXT-%J-3``A%sweX*v;OWc;-Vk#nKI)iN68 zfqW(<w#af4Q3dXO4xeEs=k4D@#!eRLcq;l5C3{fSux|J~&BUssp|`Ib@7AX~avQCc z=Ox#M;k~^*OE%4_V5m~0a2tt>$P10U(3#Y^%?0AQbaj;IrB1Cem3ye;rN5?plKCG> zlyg;n>`d%!T#kx$ohUnx>xjZi_ewzSN8%~=4b|z559=dw7eVE@OQl%(5k*)jZjO$P zEiL5yoen1v2?+@Y2M18LGmMeQfn3;w4&+r3&7a|N>b1k=<qB}?e#?`1L1}r@rD-bM zXh&Vk;Y{N`1j(!e3`W->0zF}`p~@3R&@uCE^-#Nc(Xsv)Ldb;-v9vq(`ui-ZZ^5_o zriHWFUTS*m5fxnb+k7pdrr`^Aa&VTFP;#31I?@5S;6{T)$AfdvS`m;1k8S7qEyO~- z5NYib({@$%Fih_vjk^M^t@;XZQUt-qNNcC-i?s_P)ztLsV=-f{+Y0cI$EPGOsXZFb z^IT<_dU4pT`4UDv*>Gg^Ge#Lzpc?JwDBR;?lqK~oyp)CVCV=T%v+^?yR8;{>JtDOn zWU&$cZol(q>FNybPKI)Cj9VYxYR{H_@{hlo99Q4M|IvA+b3%9u3Xb^o-|6@NiSosE z^>rOMH6aiUW~^~2Y8@b<;OYa&9-=EVTPL6t2_8T_EVUs5G=v(6;Y4=!^}FE9rY5UZ z3^73jh=}6-csAaP<ICbqnL|$lrU%>qmW|q)RbATgWv4r;*og$Rt4*`CS9CHv{`#+D z7bj^aNr{V?Iq}&7D;R2bX9lk;%iSiWVA$Cs`D^7TMkU47bSiU(+7m_qqHwI3^<uFH zl8va)h%(~JOxM>6D#9GBo#pW3;s4;=Y;SmJ-lfERAXt;op*sM`6xx~Sq+c#q|JC_o z()}1{VrJ9q!va3SOb3$~V;ObvayWTi;dh4L(PAcCF*?s^My#gXx!rWSoc_F~FCo9N zo+)ESW??XFWkiM5vffyjylIR-d!TOEs~K93!nfNFD^S-2wV(;e;Ppc3!ub>8e*C<E z{4&&XJ!i=My&(MZMn0n%98E|wEe8sq9Z6{3E#=>TI}p1FmM2TSXNK@3e5><X?aS9- zlRh!QCsoE*KE$XRk}_C+*3=s-o|{}sT<Fbs&L$6WOcci1L?QkXyDG1HS^xLUG20s8 z6kRiqKDntX3(_37y;e8LPWsvFk8~uVz?=mX+lbi?5y2%|njfKaw_s%ymJALGNoBg; z-#`EvHz1|S_E=;a)|X`I5|elq+|C{j)!U2WuM|;DT6Alaq*RabHMVnk87@q7kTe7M zK8!!*vc_9j%#>2iPbff9gd^e+sTc1J0!ov(X!)<yLwP8;K=attW}y23O4^zvW_5hV zF3S@f^Umxp#_QHQ>0Y)s%PTSO5dc+8`cY&Tv!Vp8g<8ajsJsTNZA##vbA(RpA_MnE z5}@VWYe<Qx@00%`tT7czhOreyl1}*>Ac$3EFYMRHkNC#f|Nv+Pz03MEHHmgmw3R znx}}4o(S40F~ycRMR*3f(e5HgS<2-T|3YR(fFvMEJ@<gR0Nx)6I^#7Eo?4{2X%%U- zU2Y_U+~F&SBxQ3(meYtsPH^Pj5}_EAZ%~tJBWV3~fD%IxO#CCgYJgIvhasYl5%(~o zFoc9XeJRf!MP<rk#zT`baF5Tx^i%J&b$R<0<IVl8bDrgO(ocXGHZ6{RZzJ4DUmXae zAx<Dnx*~%xw}#2+i^$ntD6-}YAl~Qi`B#ZNHU*JLj1&0-Ne&B|oa%3t0yt|%>0h$a zfJT;JrQD6i^wdO@agbZ3<;B4LK_lsBm=<#ia{PVM{B$e#p-NpbI|NA=<dLJHwS;cn z%gfG7%<+upeJsSQt1B<hpYMSiJh*{)l+hA}-(PL2*>6);nb@I^Zv)`3CAibXl#rDG zRcS<+LZ{@obEyt~w$bvcmV^YZ>KW#{i!d%a__WgNG}m-_XC;)~Qu>-dZ=p?`qarTx zmAs3st$f+V$Hxaeo~N^;qvQRDgmJuS+$NPagN(25X&QD47Kk9jxuPd=p8G>^3pV=$ zPs*WrnbI6$s)bo)J`O+}g{jq=qC-0yFl%<0Awk)A{MH}!O5>7JSd_wDo>`xbdUond zsdfuTS9>n?cG3EE-O7R5I@(JUM3u2wsv-BJUX8j^t@64!d!>B_dyIu=HsZ`q0qVBF z%l%?AAw`JOAFT1H#9pQq29=4n7V=W*K(nXJus)78<rNqc9(txiE~E;30PR3Ug&^Im zQ<#zvPckobx@7Bdlm^&>RyrDV62@Fo=W{(@fvsdsoFg$fl^bWWPm3_wSZHR50O=4i zEy}I%l2vgEM{LcRnjTRX>yU2v`pDQ14$p_Bln$FMuahqLCxfq?42SFgpC_2I))YbE zdpPjO$}oT^LKUG9Dpe4y6&mNRHA(`l>22l#pm7U&MvYZ73X*>Svg`m-wo{&yY;+#0 z@jBVYbnJHc=edvzB_aUmh9Y7|#Qps0{%_i)JBJmZ3-6*1@8>jC%goX<b6&GCALOBU z2;8X0tzK>U;4VB>iqu1FxD9!5C}*a_DYHio@1JcAkesHKwF#=xbQv~5b7OxJi>4sB zlrx496{lf90$dU5VdK7F&+DNQ7;0Lxv%Tlz>2Ar#!UA>+Uqi4q$H{~%#6uLSt7ZMt zgRf}zB!edLkKJgmEU@`8{@_p6hjAXFt~H9kU>XBjJhzLA3|z4s-*&f-8~y_Hk8W9h z&}BCBBRvoNCQMkh3>kd(%#PdFU|U#7J7scIOQ)dE{1WEJ=jcdW1dgelJ_{;u<{3S7 zjoX_7&P`=eg(@AV--y)vF`h%t#OhC)jrY?TDgLc}fp#XJ50kN>yk7x}1}z$AK|`~Z z=8cx`YdYvt-iBp*w+WdRZ}r-2LWiXMvdjKof-?8obWmq9PqE@?ce3n29hv;Tho-Jm zsHLYEpj6%X6|pp1z>mfAtqgpXnn!s<YF+jW0<pmd?X0{c1Z(3w|2Rnfv4U*lAs7up z5mAXwgc-jO3<hrLQ-jL**W3Gkvmj(Et7$i}IP@eS-dPQVxxGuwr>lyr(x3g+%BYr1 zEo3Lcr2D1NJmwJa=fvO$3;%VDsQ?2^XelkA!iqX?FWvir*NT|-K;bNU4XyZY=*Xcr zMBG1L+YQqV7x|{&hSw|4!O=iLY>~R>;H_&)_?<t;Q7hSeS#?Zor07H?*_g4KAF0zq zm7R_zPtYi<C|vzTra@f8$;8t8vV^0-<~ZyL`>klJGUkkQIj&*RvY#x3hP^Pc?q24Z zK$?V9;4sBRV|j^Al(fR>Q!zC<Km59en_l3M8oV1rn&k8(>w1#ud}b0|TZpG4?}yvD zmF#GnCcZaSPZ$3`3jicUg5s)6OWa8@Sfm=_(r4BP0+jNOu)897UmMIQ<F*p|*1x|- z%jw}oeitwwM|fNIX6Cr7(qP<_1V_ZUJegt#!VIHe=iDv^9M7*JpeG3Ii{@kJ-pRxL zB~`qL@i0fu&HsJ7wNHVeN&3sJC5vIUiK5NJmChll=!J-tYgf@+ThX%z!2zjZ7CB$5 z2T8XeZf<4}yc)VtIYN}bdkAr1@t5+L*@5&Tv0AGq_K{^>SoO8E8u9`fxt?wYACR}L zFR$hXtK<&!k+e`zT>LYd(@I*VC5RNE?B_bzFOp!^vD!2e^04!7W*Oko{j;jTEPbP; zXLDm?W2fiEmJ9Z>!cY<cC|!{fbw#9rXd32*Dod?7MjDc=X-NK3?M8J_I4u(dg3Vms zmXV)&DW3_I2_UO%T%%<)m_`UTgO>$L<7zTo)u5g?be34fZ5EjLA7j+c_BI{B<1b@x zdV2cT+uh=JNjYt_qX>O5jQripZE9L#nL0QN(8ZVW3g4a$Rk$)UlDV23U5i8A0dLhj z3??e6pbD*!SY)sfu*S>T&4N;W6p7p20;CKeHsMC#%<Z$q>D{et;T5j_>x?^&_S=5K z(=s%SNB)6n6e)s0&dP}u#=u=JXFe{9%cuQA(VcS0<G&>x4S2fROsn<wYMUV~8!_*$ zE{nE_L}JsV7@cyil4KJv+B$}wIi-wyBOk~`<UD@Pz{!ZHWcoZ{i>vg<lL*+_h7w$Z z2#X5;G=Y+os+xitS1(k=ShkYp!`~Lz<g}MxAe7$My=cXPUyW>*M5<t&+_1kMv_aQ_ z(hV7oM{K(2-@vBl3=P^pwvfFH#vYu_pYILs9G|<V4I8bG6ne`)kK7(64cKCcB75&= z&#smOs|RyxAkc2WHE}eqVEm-qBxp3Nb^3mteY-T4kc6OVyAq!X*=J|fLNA$`OT27h z@<s^$l<Ja3oU(FqGOGXA#`OYGk9ksy@o}`YhU3FwQ4WaA%5FZb+`_n4dWs~e?Q9U= z2!k7*vum#xSo`?k<$brhH$?BB%r{XinF>5+<5*E7RGpmpvT^9D&ssO{(A`EavwAV% zlO~JeK6+!5(WF17r`P>-eCE0K;af+19nLWB%w(@~FxbduZ<~m}4t)D&<$r|R8PR!k zJb@{##mf3rP232n3*voh^|(_=Z~nI%QNG&g-ju4n!?(6$b-mX6aFqH@?J)uEcU0^6 z+@9H;`sK-j!_@-VC#%G6gRiwdZd|omWB3Ce2=aA8cG{i72|XLo1KaYnbQb<Tc{fmF z5W(kea=CX9ZS3UX@)q&Dgw5&*u|564M)AZHiw<sC=cqd&x;a$=+FWPdh7xI}j@Br? zFxgb9+%|Hi-CXe*Qq=2Ew5%Wr?vjyCN?gdLp)GX(CYmy7#FLY#xdFb=1;4F&=acw1 z<=WjMmS53q`n;RdMg5*Tj6@tQ<oNM$)D_Dd=`jo26gKT{d&**tc%pwvV0d>Lyy72D zvwaCBuHkfSNyO9j@sdiN=gs`+k24Iria^4yc)dX~LR_7Ve)0#t24p=s1U}sIVrtw) zriz7e-V(FEsTp?@<nxpwkuAzwX5=Ct1FYL5%78tU;P{YI6^Uo}N0j}x+%R_zFXha? zhf|ehKNS`#HyP|m8UVcU+|fPW6O!6x0>J@n(5=p;872Y*!4ul9yz<23^lD$ipy%pj z?QhR^^vl0fwDYO2_Qer*M@v&BKWAs;!<vX_IM|V(eo+f{5K`L6PY|-qHW`C(+dN{L z^gK23vTIc~3;<YA-DZd|dMu$xSO~+QGU}gmv0{(_5-f~sac*NZ&=4)iDJ;d%^sKr3 zz!UV2Rw2|Sul?s(*&5l*{EW(ba*d-q#Qns7>P(?2+qIRJ48A!a;Lh4Nuw$O#(b$;{ zbPR|aV5N`cTNi5ud>H<5kdnJLj#b)@8!6}Y3@H^aSIRw0L-hJ!M4`czenk9}fds7d z0l_f6R1rXIF-6&}b~C1Hu&qx`LW3hm#iblSXPYW@hz;^EP<X;J=)cm48*U5`jN8}u z_F(?_YKej4S6@4=9&zV6uU(ccS@^w(|Hi0(Z{+xLax*hC7J{GUo{=*`My*=s^$eIg za|x1Ge7HuZ4j>1<FuE`q$%}X{=@Uin37Af;_B^vOXgLysX9S4&(j}CkqH-i`8y4Iu z!(CdQtV||!nPlM2zcQRKR(Q$uJY~w_{{FZ&G&J;daj~_fJ$8Z*=fW_2zzA}>=d$DZ zb(NyaQd0wEax}5<u;+$9sA*va$#w~0q$iw5X9SE92-{`!C9B0w+177*lj!I<iiZ>p z?p6&x5e>iG1mcm3jE<=qZ%d*AfwIf9fO&K$dS6B)M+`lV-0dk1?v?_BS&n+4QKZkC z_oU?$OBc<R6H%7;$FNKPkIQ9jIkw`8eb@jAUMmV82~s`JGprs4XT%E2FiJjh$F|3i z0`AmQoU9A2F~;w-9#$|4rIEcM1yw4YIV~eqh=zAoKomg9NU6LHfkdGW^s(sj-COk7 ze4tf~+KAWLMlh>v8}%iy?V(-R*5K7uTR>P>2lSE_U1@bi#K}%hP8N>WXC?pIchCUF z1NeW<08N|UBWlpevBNn_9X9Hc3@Rm1pesPoJ@UQc`p+2lxv-l+*&wOBD}Y$J(B(Xm z?z9!yRoC-mTB-tMtfXLe3JH1i)#^#4$+FIerY4{}ce5e)_9?^g=339&mnY{YroKT^ zF`f)}=9(wx+72rua8{a2gIyH*9QAbC;cE#^^y+2O`yQx;MZUt|Dh1Sio%O@b1NV6E zG%Th;=EMz~r9TG~wc~l^<<@*9A2P$;+vR;nO^)<{*bTlH(ChF}dj$x->(`G2(;e#^ zuR^(plt6I!bdG{G!3<pZc5F|l4};h*wB$hTne;1K+Fu8@(%HHerh}j7<LNd_Q!9JM zI{AC(!Uc2QpV23hz`AejdRlcxEMcf$Lu~ICSQ=SDq8=AqiGolMK578zq4tZv=_uYX zGHKiz2Hdyl^w!cTd-=A;eV;h1h~fV}i-MY6+HZLu0-di;{9}<%JFO&hz=2IGQh;Hx zd;umj&|Z#<nISAfXIF30S1{t?TI?faZHT&Is@;OS9g~io59@VM@DA7jLs<pke9@~D z0la>`ebq6L<--Y_j?@W88V1*`7&eN0W_PBcUuxwe(%`unzCZabFY(^oT#fyz1Dp=; z)@`f8<34?^9Hm@#{s%BF<Wy5i*vN%qjkXF+H4tqpx`zV{?Ozqeco@HOGqL0>wrR35 z)YQjkwR$tIe{8II2}!%#WpCK4^fQUDRpBB1vGYu@B=n)}hz@MC#q`&RWifTQ=L2GK z>3zQLLeNop_t(3F^2OI()CYbv-$%2C1<UMsSfG5a|5}_zr9@x-c<{qGaUA4cAYbmy zl0$y+QaKq>h-W3VGqEWh1EpYJ?=u<#n23khztCDT3{6>m1>|u^DG0&0h_$7P@a&%) zz{dbJQ@}sV63T#Nz|>%TV``sQoO!3#;P70_ovjAo^KmVWu+Lb3zpcoNY0KbKOCcYT zLt+e~5Y*J1nwCM4xj^u+g#R(si(_-33qq4R(0#FHab`ia(?7o8&Wif7a&!z1prL9m zusCTeOPIZf{I1w|+;}r&@Ljc!%g>^D1SmK5Q1%52_#G=mBn=Vun6|1@1zMzr)fvI; z*4;Nv(Q(QpX3B1wml=>;O9HUWI!#Yn5Orv3t$j*@Ia49=88cwiYPScyz|%PeXU-}T zJ?Jd>W`>IbBKVz#0SpfG2%iOOd)(jcajvRjHfiW|rGCvfTmAif35ahwpvBX;=<4eF ze-36tLj!q9$-=|g<H_0E8)t^kM{}(-R`gmRVf8|Tvp6n00GIjdm&_4)v^HvEqa&gS z?Wz$r8SdY3s`3>o<AV|@4r9XM_QV;`QxM?3m&|8L!Xgp%=#hhZ8nJ^rQ<nDM`@O4c zXcJ>_)AQ-+X<tByauZ&R4Q$9jJxxS@?rDsgpR+de&s|1|u4i;nP?&i=4>7Sjh0q&D zW|7k5ugP0FoG8~MBwL%5h(qRR8hAWw0#{41_*d+{%CMI?Y;OI1m%)Qk91l9KG3*Eu z0p}m>mdjjKrI2UBsc(`urP;GD;6Mat|AWS8!&^G)M)aO0OcK+2n?GN%t4LI|1gQwb zOr=>mnl4?xC7zIlH5_!mjwUNZHnys%On#-yq6li4>1Ol1`?MlVZ$c<LH&@4KXeBtH zc<G_{!hWBuG9)f`P@m#G)m2JU%n<6aB%=^k@wXaCu5t_uWq*X+b0&>V&ULlZB7z7b zXD19o3zVv)o(X}%&Q@4gW{@%|>PN~$M8kqu&i2pi^x>{mHd>-W5Ac7a!~Y5B(8=_q z2V2=za-#yupCUS;a-j`SY$7LNcA5^8k(_aVD^fKje~3TfKz+)gnxBXtQ|Rp{(>(m- zg-8mh2vbIgV@<eEZag-}n+`rFlD^$ost4v;&#jE7B|9c8tvc4CZtw<CY)`p%(HUqR zNcQMeo#$ly<X-bT8M&&xQPXb41=IF_W}05!O+a;Is7afZow&jF6@W#5?e(auH`*pS zHJdJexxLZTlTy#yhquSu-H{u3^o)+2cp~(rF`{ngyj02+R|4E|v6HT8tt3>F!hulj z9wL*$qbAiHx08p0hx_Xz^^RCvCsFEiOy-)J9*nN^Eh$u^lqKj6=etH(b<UscB96Y8 z7whlGk-d?x?m5mXA)bJ+ak&#<wE#rNa-gz;E%^5-*XLr45JH@Jdh+w>4;$Cy^ZERr zGYl<+CZ{o&)3LFM#Yrd((lJOCp13}-iB^f?E!GK9I*S9(o|T7b+GKBz)lfpV>4*<1 zl*?d;%OZx^L`-MPhvBXM-96z-kEFl_H4B8UAO_^i86<@wUbX^`ff`R5{A<3~72+h< z4y_lCtf<UO1x4#19c4QvG<jM2SoliTh+$~HrGPCM^#uL0d@;>K_Hiz?U%<RT&3w(t zeGfg$fW3DFrn&s4u$i%dwseV2M9sTwRQo*87M)IcC(t-}Rhf1T*Ax9z7INqU$SVC$ z2TT8nWHGQ`U6*cX45d3pS!^WON8KXHp)bmjU>YO=Qn_@GYMgp#x;iF#jqHt9W(<{~ zZPknI%k%N@osC0wC}7;PvI6UI#?labjYtp(Do8^(VT-*G8^<6SA<9Vj$DjOX_3nTV z*72AA5Iq7@G0z(91jRsRE|4hd$TNhR7D3aDaHL6MM%nfGyH}Je^q-9c=%j6WmUNC_ z4&o|AQa3vfw_YCD&|X_-eX3A<ToD=-uD<GI_<F25pUqR8&{k>aphi+RF($NTrqqh? zyV+H!=yjO%SRfLL{7&<UgnTi~AW%gW=yRPb+?M*?m~)~j0p*oLEr#TZ!O+Zk0h{<< z|3ZEoCJXDu+v&EWeJjXWjf)Qat)IO$b{ShgZeSK<4d6wP0$3(UyT47VIDfI`+x#+} z9K(|H5n65J*1cx|=o0wjM;}aQ_4OQ=A%L(}3=toT#_NGPkNNDKqrm?_Vx8hj>&cZ9 zDz7#rb{!fhoqXR7{sV<OSXv9Jl2}1?nV2{ssgF&xJ-h}EN4=OvOdbrEZqUlai8*dC z)7CW*{4npVD5$>p^-Qa(s(v+g%!mmuCMG&sv|#QxJk{4X0}f6vd*X0{YYD~Kqus4o z#jxp~&n?1K_Hv9?ld2eW|H}o{Z|B`VBx_g%g3-hQuZmqL1FgA;EqE{eRHkzDK(SW< z$l-^e9%T3dL@+_6O`G}UNxUDaw%AyQ)^FatgbeJZEmc-u{BpV?$UqRcx?Fzd4#<0W zew;Z!76|61(Qc|}X%2nK2#NJbbY$!JPh|Yibdbkx3X6b2L9P1F2h7I)I@7Pa@0+Mp ze&6#Zug+U`?LQ~doKSaXT;Swo)s3&g?`b>pHZ)IsAY`E)3$4r(1&q-2ANxY<#LMTk zbk+)Lg2r-jjT;LZLdb3tz{c!PBFu0zyke0~vuMxOkgF_dCO5mvA$dZ;lFH3lNGd12 zcd=|jY_!PQz@TZAteIuXE`X&$SyE6v!PpT+kXV~H|8Dr9U2Sp`Wte_n&efBt7Fhlm z?cZw4WLGHV&Jz|$mV*6jB4{A3EDa@a%axHmC*^73*$G{1C(g1-8_XjfkZsHxKiAB7 z>}%%21J3P#!TtGMTiNlt-+iFZ{!WpZl`QM|FC{DWKh4c9!Dq3`;;^OyQq~Nc7eN;( zUyTL*@tFWCRDfIzT{X*MX*T%ScFTRpVqRgFg=!Q>6v~#_uNb`ddYznf=^jDz-Tpng zMsMH+e7JO_3+cFn{*XM*J|`<biQrQ^;aJ8uL0!8Z1Q!~Y+roP3{KPF|%ah6BEtQ`; zbJuH9zhS&{eXfD2W5Y*Pa)`f_tJl%kfdsaj6Xa<^u#&liGgekCeT<FG)cC{{;Je)L zhpN*CV9{SRf>nXK&SQ(aO$Zb?kz%nqcJJAY^B)h#R6$Iz?;H@L+gDjz;408wL`GF? z&eD4<Yqf6=Iof&Jy*a*2lWBM*ZF(~=Ro$^t;JcNq_;@utaP&N8Rg<Gj6(SxN3+6gp zJX?7-Z+@%msAYBVRi0Bn7;g9ze;+NGiF!q`e9erw=*B^hJl%a2%=pa6;c}k5oiUbz zLrGp0lGI5K0bH@!8jx9WLNroZ&8H6;jFlfLi$r66d8_Wf*5a1-A?$gQcVh!4k8EQl zBWhSwwC~4SFu5TsGjS{m-4mDgGn~P+Y+!cyygprNr^moZqWmr@u!<REMQ)qI9GM?B z$0`Qqb7D#)<}1Pp-a@~LOm7YTp+PJbLbq?c96yg8<*r5u0@*ffriD^z(pp?X^Zh>D z!?g*Cs0c$OLcD)G&CnaFHPANGE3QmM!;<;{l$N6nB$$o}z-(L<sjt%uD-x-t%0@t_ zN;@CT_lqrHZw|&$;b0+US2cEe-n)^w9$p6@$QmJL|E2}8EOUTl+Es)_1h8d^ga*bk z<VRR-N+FOBkRinuM>9m6;(~0&m2aUO9ya@XiOAWEXb&E4d7$Q24JoPMp?41P0lPdn zosygK?E`2Upv4W>R{+cA{8ZXYM77fC2RfR0E-6d}Hz5OZt10%3?iYJ87?w5*<S;ZR zBbFH+fqI}244RnBnMilR1z}*of(?f2Y6M7!z}1(rC!m0OPYZkatjo;;o>pj6YA4R5 z@2r684%o&}hV)kWTGqQVY6N-pxXfwDnH<UVo6^w!?qpoW-@?X|MsJYc3tJd(jaEVQ zLV?u_lKz9KJq-kHbR8LQ&ja3H5&=;Z*D!FjChm!b-@g(d$2=esj;A_Xs;s{nr^$k2 z=*Opszs#9)M(R;sDqE9doB1Ve5YD*hO2MP-n_iDHO1sIu30fu+#^li!Pm=neXD@Bv z1#wKa<~~VRr?+?M_^JQyUE2Yg+j5W`%ouDH{VQ?@<Z>z#M{{#?mTcVo{5dlx=;-JP zcdw6I9b-nG_akG!F#sAg#DI34G6`U+GoO7Z?N(v~rPOo>L~Q|@EbX^vR5+`F5@n=< zaVi#>Pfd`Szl-K<K=ec}G3CmS?Rs&g*!ydvGL*-%*bhgxHybDPq5(c47-!BNGdkVt z+#Eb^%q1F_{?6GMeVb1r(p9}@w=pC01k6oo#SRf`n0jW#P-0JgwUqg2zI;*@lD3LQ z@07T#f-})*d$-XLi-(by*U4%0mFm8NXfx{*`+}CoZOpm2dKSY2bwaVM0aT@p`flLv zGoei~p%$XEy7~gdw*Bz{@sV-J_A0a?GKp5XDqI*l+^&yP0|O?f*@`hd@)q#*i0KUq zvP(r=-4)(W|IiA&xw}rj2*8kqk7(xdI!T4i3Wzu@J{ngdT;At=CHw7ZbUslq(r1zs zDI)6CO{Um(CA88LjWlar!leOItvUXHlw&sgQMr>``lp|UlqMZ?QF~O$rv#aI`Rj?Q zn{<vBcpY#Tm#dMb%#hjaeBLiisPad`;eDG>XDFP@{bvJM*kJ$8;GIlPS7)(>DYgXr z#s>YN%JuZ!0rW}E0onsT%FmSqn_q6t8%@cg=1Re|$s|LRQ3#`WAWf>*wp#8uNPFo# zahozuZT(rGpq+0yi*diOL%lk%-i*S=9Zub2`#f52Ka;{oo~q;!Tlo^{z;MQ?8%kY| zE0-foYZGzx>Z*17gGjBf*pYOQ*`V3Q<)oz4J^BQ>P)w0gScd{VO?N(duQYV*ISdUW z@4aM4=m70-du_z_^)_<zV|x%V(<2RKDeprk?<iT4*;|%*xM>$2?)5$z$xV4Lo}%>( zwtAm2iY-yr6w+GoSW?~NdO#<oi*X(X$S(U&9iDuK417Qi63{)l+D<>l>ExPmZr-%D z<zaj7vZV{R!YQXg#*}iYiS!?_Gr3#6B9iZu^6bn<)CNLs2Sl`olB)NcMigD-t((P1 zgTna*`T2%$AfL+!yWHX_ZoY>hM8sL($BiU60R5TfNrsNFY}jPPtR8JzmSEE|8|?WU zEfUG-rL;4s^^|CjjxmSS#Oz(Rbv2kVZZJ19rA$P*WS0qL{Zs-Ws;66jZb4e#V++`? z|8c#X$!rV8+*A(Z@_@=r%)c=I2~i(luubR(-PqY;$y(HtQME&Zn758$s1rzahF-En zUVTa2aP=o_`Y-3Yq74Tkl6Y5S|Niajj(5oJ>r4RixVR+Q6uP8HLv5C8NG=ltsCL%h ze_HO6PQ~^00pfn}rfO`#S3HdqN#%f2UA_HD1VF1sfxNG~ry`Q;gP*wSaSd1-7mT}L z#Wi#_j08c3H9u>w-+PBQoTL?h^Le`t79|yM{-K`h#pW1!t0jy}h<Oss*{w*({9<D; zk&BuNM+1C)2nCn#5;%O)L<DL@dmF{pu?-1g#aG7K5du`7IIjrNqZ6weS@o8PbgoEJ z;2M4ECS)K50xlE^lV+I*I14CbR6gYrDJ0nRqxitUItW0;g|1d@u+wx<SW;jT(cQaw zqVs9Qw|E70l7?s$Ez(>5!rM;A>uA-TK}SRv8?b_t&KV(tS}Z%^IynNBs~nO=7RT>S zrGKuYx(&nwEi8`m53@*L%gAnfTqrupAUXPY*!&!fG>jpdN_0+TL4`K$;&~mb6T^Ue zj4R5L3eVVybgcrgmI%d976g$4CkkdEqzFC*lsA_8=52#Z04B1N69e5QkUa9!v5vh) z2HP+1*gZQ(^L0@0iQUvGf`PNlBFqN!Veud`S_qRE5-mC%Y40<q81=UkSwnPLz?v+H z`Y`ckce{4;fBykmvp#D*b9q*YuHWR1$nGfi+X?EbYHw+Junn})&fPq3)~-^yGH=qN zL2Dk`%WSB2Li4FsscNEi606L7nb!E${Zq0BMb%yZ+mt`sb7?q}nkv*2ge298Q8XrF zR8IXxI(_wZvPVkPgi&QtY|1?uNsX*RD}Xr&CaUNOD(JK+iOkuDHHyhQbHev&`V2*j zU|h$H=z2Qcf4a21lIz=OQ~k4|J615SbxgIFLR?^|e-nH*`>i0*K8ey{5z_}CJ=bD` z0LrFskoYzj#$8G8;9$HMQ0?>C)zKO|LK@~EqDO)9)MXqDM_j||`c=o9grliGD8PxK zNH$7}1Fp1<sR9F$Q-EiqZXobXd7xHRnf43Qwn`F!h*kZaVRiCxVfZxF`?$s|^>u5| z^EWrBROy>UD_$ztDz@HL8!<LstXQ%B*bC?b2gh@B90TXK+1Ry$dDR;_Y)<iJQRDr# zRl%MgRvb&9VN}L30VtY}yJ2InlSdCr7csy09kC>&PN=3Ka;Ra-iW1&g<B}0ag6pR| z()z|IbIxVGygn6!f4qZclmxel@qXW1(apYw+v!P0%g?}&Ec5v<d^Pi%h(#E#@M!mN zUKwTdxdb7JClH}PWRK?TqlND!z9s4eu<3=iJ?IUC-j_sC7ZS9E2&3iJ%UreaaOq;+ zT8b(!_gJ>L1VJRXuWTfue!gDi?rK<I*7bV&n7n@7>~8+yr#qDG!n7F<!c@Z7>27Rt z-aW@FB=#*zG&dRf5X8!WhA*R-3)<Hz-Xqbob-7UKzJlo{&kljcqH$cT+TT@x+2XdQ zo@V!ROQJ2>#9X~Sb$D=LRv7sdw%0^w2-+n-m|G9nx#nNK*=a8T?VcO-Vv0GEIPK5T z{|EG%!nL_q5M7sT!mRGO;_&{x$ur&cn(!$mmXCJA7P7CNjlBkynxYk_Yi>BQq-W^i z(F5saLV%l*{KkI&IM;QVs@In`bvNI%wKsn6p`nSmYB)}bxwXM8^)F**jT4q<;>c|G zvv3MmI_2Ggv?~X{?;GVAF3)6ln`>;A7r4pqNW@*K6(`|22*ecN^&HN#Lvr>+jQe&B z_4O0X)7iXZTMF~wZWR6pP03|UnOYlKn$9|7nG?H|QGKGSvk48j87~FQYn~HWL&}D+ zL@5qws~O@jwg9Ie!Jwwu^CFH)IJ$E=#CwL3DuIoJ9Nhv~uoW4neV#yQ>|LBQOQPrL z8rAXUlhd>4!C_v$VA%X1)~>?da)OlH<6OywIkDk@qdCs@;Zk)^)Q#rssB-0DPD%s5 zD3&yul;mp;Yj5Cq`VuK9UTqNpI=0r|!Gj=i7|uPzlY28GJD|;dD!6d}RC<jT8buXB z*$#P#2;V{*;X#XkQ~;>^jKD5wQO7o!0>Ua{8NlUdK^5{cj?YMu@?;cL&K4`#w@EUg z_ZYv~x;}iO(T;Xos@`6L{cK=r%qML-NbqL4Ns78+pb7EZ$UkN{wnqm`II61h@8o{& zRw4njg%Sj(TJ3>>U53y&j<yr|#IGqv03h*4P-!wp)&v&X+3p+>7?d{F4d2XAn&uew zAL)b{<KUl>Cb1+Is67Rd0dXhBaC|n5P8V{cK|UW4o&e1N<~PzAED}Ved2%?BP-ShW z@Et9#adGuzI3_Pg8AWZNUrd27rLW;U21=VTFlq(WZ+>?dY!qfDyvUrBIRl~doJbCm zp<Gd4f%$Ymuh<ow5#nKt{|=s$kl=_8ma;Z&@l2?!V&pHGl@UQb16kuV1R@NIXelIv zz3b|A^t^i7R)CIHoBPAdJ9(j3NpEy$_8a|TjZ8lBzh17lBx6--BIAmE90EZ?iEJVx zI0|%Qac(l27|%zE?&KbdV8?gGKSCx>YQL}Q*ymKPGm0ajQHxL*AjExHq_^@J;e!a? z=~WlvDi6KKPve{$EU*Wrr{z$L@j`|$etCwC!-c+lvjvfT`gEB1GD%H^ly2}`(ZO;p z-|Ou>mX#i8wwF%$^k2*#c_V#~sF%1aa%VZf?5CWkwEgpCa^Bux0uWO#JDy%IAvXY; zBvI>%J9q|c6AG~5+(JqsPF!@fm<T@9KVt9DiNivrC(Zor--q_mP}%2pm7V9Mg{Ls1 z<l$5;*+X--CM@X`5Bp^#UmLofZC!QUcN5x4A33iY3gqfUO^1jRT;rwOj9g0TD9+Xe zdlz8mvXKg#2KNInQbd*=iJfTlbW5#kMA~t^c!opdypN?s_esI=4!H&@80_k?8uW-r z;S)QJ;bTc<1v|z5ma4PHh$K$(=boif*?F5Z3LoOfQ6dtIwarLq7`~KdEREiO2@|gA z;~TnFU(VZY`W1P-<ogn9loMw|afYX&%z0iP@1I1ZvO>UmZ*U`3s(XH)BVyja8ELE9 zMQc;bA(G_Q3(U=M*UJ`TMEUnXSDkUGl)Z-}kDgS=6F$pNrKS8^Z^ubw*pjc=bAf4Q zc$^rG`JLcUMpc~I@;qWbh<S&MeM-?Ejq<ENoE)RgHdtuW=?aAA7ga!(%i;NFHRb&O z0S745evj0=sNQIIxoxaEgujCSZ*;$9nIoD4;>GD-Q!-H%DLH`%5kf#8q25oBz$iS# z;mt84{Fnnl?jVBypFfro6%*#gB^|;`XLHf2LMpxeeV2XkqTMvy9SaNECDW=>AS3n3 zO_lKS*g2Kyu4)FIPBr28T3%^h8_iFp{Kjywvk{@88|*}FEeCK+IcP1k4kL7v#D3fe ztSkdM7jpyc|3b>}hJKfg#u=IvgrAyKxkLD`>vBZAq62LlNAY;pcYcKBy45u?M+&Rk zKid&Q4S$NkLnHZK1g3PKGz7c)9J38gY_tN~Tx|C0J1c^luQv_|(WOVqNkYT}{YS>i z`7+7|4jM{wWcK@e@W%JLw%&`+znVRzc^yArmmVGKw>3_n74NaCov_h71%vSl%@b2J z?)1?zwK#1E*`=bWpROD}uSa$kRX5HTSbK9bWMxdwYuI1k<a(&rbUeEpVk+EBzHWhf z@T%vta$e5(eNI*-fAqe;3=Hs40_Qy_IpE+7M%v5iev4*Z4Gj~i26%4Z5|RXow(KOc z;zQk#Hzj8O098z*XwjRLyp|f7)^`RiD+PomBnU)ZrKzYJx#L9SH9h3SDlXt%i>|eo z-87@PPDN%F-?5#2Yw?ql126o^SnT`#iVcHAh@x!((}A&0rI96BI@K(ON=+%4iU1|6 zA^atRGSiS_dIXM8xI{bt*nYm`N2^+6*8kYT1q7|#Gb4a=eHD4B>6*njC8~-T$Qu7k zb;rSmlnM9&5p@zWTaPtEW8(~{#rBX#Wg3r<Q?==ET@rfCw}GSu_s_#Ti_U;KDJw{@ z#Sg4zJ6=Pt(7j&#=wTZxMqHLf1#n&=JVIP2MI!-?$J44i99N>@<xr^?8FG)|MwF$b zSiHSdEfg?_PYLMPsF)Q2Cx-7H^Y_l(z-sq^1VNxc0mj#-973rJvPseTZkE~#P{031 z7g<7z=gv7$nbekiLV@!Xo4pla!-YLb6x5$1B><WQqYE!Tgj$b(F{L$|#v|*+iTVpV zHbBf6)r_<mqfa9--oI<V5*M~-aA`DM)Rk^`+b^kLAb~h30i0+gJW1FnYNo1+tBUD1 zIG+A*EJ9qnQDwps9pR@9;`HpQtrnukkXS3?MPd0(>>}gfY3lfsV^EI?Rli$*&K4Hj zuJkKq&-CoT&1R0*I3&q}wLP#%n4r`&DU6@eYh7BFMH_~pLZp1GEwU=5hW#tvHG=71 z2!Dt?O4CzXrC)nBA>dtml1h;at{d-RNO`l_Y;dKhcCTgRi)`b)L6*v#K(zB=tzlAc z11nNjm0bZREtIPVqt}*Jw$CQeV?AHBdrQH>y19i%i!+_x0EQA~M;zoT$=@6y@?}cR zu>Dg++;SM%`?u%~8Fd4HyOH8}>Hs`EcPn{WnR&zu{1k}CD2XCwTLImv>1DR<0k!Sn zgshYuFMeJw4$jX7$xYmUWJ+d06YT-&lvfZ3=nZVXdP1B?7cGUXdiec!WK)d_&lqDE zM1bua6^SN4oMdKH12<NwED%>{DbwRxpbYq?IEyN1?3Yq;M*>PIS&GCmrMFP&<N!pO zkjL^|f~nJNf7L^5DE4Z1YZLS<vX3&^ZBa}DP+1e6(2oeLXuWPYI@otPg%NE|9@O`z zcJDRau&GOw2lz6ps2!It+$%fGyuKS&PCT3U=P?X7raRNl18zNCT#&ECN$Yw~5hVHh z^X2d!nvx1TGaI9h`Y|vOkUWx-FzJI$Mu%fIo8qGh+5qfjOU^*1;u06f(kwntdM<PD zaPj0+7Pk!>UIr~~&X(-TsXfojB-T?Rr^W_(u}&hOtrzRhg&Z7j&7JL<o9$fCp1`S# z7XLGav!wnv-u1uY?(cjdhYDG<Fp+-Ypx>Wfe_9$u{si70;5zWaT0O)e1pk6Kzt^Nm zN0%j9NBk{jw&T1(U*saR<f9NHIsW2{O^5D-opuz><_LAGdCrrIN4c(B^Mt(qTlR~o z_QZ<viYKb6F{Nc}QO814&!%S66J_Nx`-O=bYU@MhoK$7Owx458|68i8emdNaB6S}6 z3)M<zq6_4nIum{Lq0D{yib&rgW~~K__t9elcKRWisFlR*M}qIo$>)=UfdKHGogFLZ z>&>rU*I;(?*ez}bC<9!k6GrGk!H$m>w1$AgeaPcYmmYW6C%^XRV6sAay7%@4w#O$L zW=i?;QwcDWQ+x8_SK6&?bU-cap1^0GT602_)wR_o8~w?D=lj6rY=)r>^o-@mF0t(1 z4Q2Lodo~n(eE9WhjZxxLe?Ne@vj^V!oj%g%4UF$|k3oU>4<qCuBoey!Pv~<>e?G7F zy#CdP2gnQrBV9%@I$KSU`k~-d1E6Ue#8I%zu;U?S6_{}oE&RP8uqn(E{&(aKAGT2e zgh?Wmg1`fEbNqnfIwPGd2e0)v)SxSo8aC5RvCd1R-IZb0|JY{JyC+*KoZTB5@w_fN z)%ADuAviW00lIIkcxqWRpRo{yXLRX6ykKljvFhK7U3~^U@&ugeiREK-q1+4@JIkB} z$pVz1awLgmUQ-*soBqyHK&z|wr%#V;%{CIK`lGS-Wzd}?MEKOWH`!BK9~J-^sWY!e z6TjpgMgr{F!{Xd;2V+d`!0-MYW;XY?4<ej~G5Rc_UVZK$R)(FgKvW~4ybesvtz71s z1^4_73E8^)(;al&wXq<_m+IZXy&;$Rcu4P0*=L43v-?q;AX7pHgxWH%jlTMw;5Lrp zZ?PW9E3mS*@5l33yZIB?G2Pt+3rmagNkdXxh7nc!39~e6ku;mOtv|{(@rHHVU`2nS zlYp1Zwc!rwGrwf!)EcvE@7UkRjyF3Jq~->|{+y+W;8=Yu@)u22STOqgrylKEJDX0% znawADpaFq);G}S}4u?i1d!~P=0%!xA8ReWjWTaajw~rXtHY}xAs5BxSlnj(25_&AQ zFx&VuxY$f|OF~4Cdi+yZI7l+&i!#Zhd4jD`kI6YC>j1@|oi8LnL+2D5KNewujH8{( za$eqe_dMNIuvQS?(f^KoG&5FC`=knnaX(D~15FZ*j>}<3O9&4J69bksur2o^72|@J zX}QcfL&e6V8DLVwM**vJd{o_9zQ4=o7k}z*=uxn8J+jYZ3_6M>Srq4)dOAux5{6{! z=gYVpB9Nd<CioE9H+WihoT5jUyd&-LK)8chs~#I^pm;=Vz?aH<9_`)zJ$-B}Yu+=N zj{A+ia(U4L#%auzhkmQ9>3nkCp*ti#;EXji%M%4M(ESu_0Oi<Eo-5VPa1!d0JCyI9 zg;8aQ(|4=xo0zR_hSa=lK?_K|zC0JH8}6vh=;z}1kWetNCWpV>;e=R|srhrckkAFL z>wVWIxQ)rQ>;Fd|h{EC~KcTS9AD6>i#J^nMlwmE1QWMotb7D+uq@BW_hustx|A3ie zdM``n(jrt`E`#xqW{arb@tBh*s)1>bAu(n~*TvIis&bimk)ymr9hy|XR`ZWJ?%^1w z>oq^&CI~`37NF@(?3|J^s{ixU=oG3k&S<uiym(f`lZJK-abY{$I5^{eGTnCTUtU=y z#7CG?f;l&MLV?QR)Q$LzeXd0n0V$jERO$rF^*k60NlT2DbrkKzW57R%hXwpNq!l=b z-m<`Zbx(aHq{X>Y8X1CwnS7hl^xb4#64Wo*<NlPPV6-osJL}zTZdd1>tUKTK_fOlN zNDIq_niUI1v^JJW)X0je445g{D__^}gMP)k5wsp1J4Xp4nj4B^B|6Q<k#D&FH#MO> zVgKtlU!`aePt+T7bLa!=PmoDDdje29d(u%i(@?0%`&Ix+6p0&*MH@=h7vnGTmUxIJ zD<)DZAW%5D8LGou{A(|{X*;Pi7WiE@`emUqR5Ff)93(UZ**LSy&lYZ-tz~p=-H96P zrvJ5x!92#3?hI<!wkOgVVfQ#^P-Dnq1tpF_Oik!W?ZdW_=Oul$nB+V!F3?H=DnMsH z`et^xCQgF>YRl?rbA7&`-}&-<pF61OL{|J>W9qUt+y?MpThu1!sL8N@tkm;5xRcpA z&p5Dx!*&tPsi;z(xvnO7y^<^@FQgV89bO&MyZ?OI`Iiy_|Ln{*eZdvp_5GToDlSp> z&-3PEVQsF9^ua&;Sh*rUT+_p=%kllEOG}SEI&Ax{;$qie{)70*u*tBypl*0*-)0Z@ zXVSEwy<O#?MZG+DR)>#2?hN7!uebO*(bULDgdYbf4B=5wEuq<0e!4GR&ap3DG)({p zD7zBcOByCOj#=ll-8HY%Y7)ph?@;A&b8#ph{MO<xz+pT<Nz;?}%kC@hTsr1OrA>Hw z!En9VRuy3Rji)b@hBTMRKsDGCQOOzei4?Zt0q)owZpsc;mlh}l!xI$=<PHcqR=l;X zQsnM;wRd~54<0|q(c97Q^W8)MsPOnuGv1&B-tA<xP&ubKDIo9IOfO`X8zvOH<Wq&? z_3srjcSC+sze0)i;SebUwQwxmpwl#bQ5n0gCj}}VYWMt!!l`I(!EO9Z7G!>`_3d%) zaPI4@0zG#ru_Hsvf{|3e!+$OfxtFFI*ut(m85~gePq8(x<d-B>Y#NZVR<{GTJ=O9c z0_;Q~S^)52BP3E<&^I!y!@UIyJb*f7s_<vdNXF}2bZ^R#Dz<t}{_#**;a6cLFxqjt z7L*}lUf>7Cohd0v)8st|Gt)d*Qmx7e+9>M_@!V;(COlq`X}OH?8QH8ykPE)>?(cpM z&%Ilom!O=KQ1-5QrISVw)@+JED{~yKG{M}x3c+z7HWp%r5L$r_H}=JvFYxo0!u@Bp zXalqN>m5127q=26L@k}rrFgYqnsO3uZ!@*T;jkKG)Y+9%8+1iJUHO>Vxg{p(c#nY% z;dWVVRPY)^iM0RUb}(e-1#%QP%Byl^sywURb>ADf@_$4OeiY)`tr%_Mr%i_}6sb&A zgY#7L|A(h@V9PXI!*w;;w)?Ve+fABWll^7ewmEUKZQHhOPOjbBYwi6P-s5<l<9V<9 zy3dn*P!rAy9R{>`Cm@>$H$?e?GF2WED`t5<)iqw`TPyq?I`k1rq;-AorKdEQFaqo0 zI4VqTYXK`X;?~I{Y5+7zw9AmsLx?YoD3THRsA$2bosy9ljVJ#Zj2u}$jy0Wg@czP^ zu30d9QqS1+zMEM+os*-4_{*j=9j=c*hoMSeD8&<{=J!ir#rA{_tS;AXk0XZbOZEb0 zGHqMHXq^WtSVJ1Kv@4ptf-MCGx`MhPHVQg}u3WK20h6f&Dw$s6{DzJJ4C`uPOdjYx zzqL7P#Vf4l3O6ih5l>u{|3%s-SY~xq55_Gt7<%+mblPdTp9YR(HScXzB9(Y+xrboG z>jpE@&stmTvXzLPi8Y!AhF3Gek!akqjfh;xI(2M>=(wGQ%Nd?<)<J1^`JwV}o1$p6 zgYT?54z3SsNL8}8JhrJTnj%(qH2!qqyrp8d#|}eCV!^WkORVItaX$WB!EA<!hgZAr zezb)zCqB_Yp!XZNStz0c*75x6g9&u++tY0Dw_@f0)o;gb$-d`q=Sz!CwYPDg<hU@k zQvnb)2BR65e4`icQ2#ohfPJKaY~}{N;zP_ovj)6N;ds8d7rT&!0;GcCt>S}$1j*la z)32B5CnAWGeXf}OXW)<*4@-HB_K0}fK=GC*5pV8E(^%3)muQW{OXgQgQzUrVwWr<j zX8*WyR6*NXAW%r3SL_E+(5l?TG+A_e-Lm044Ktac+?!f$N8utq<Q4z5O85P4e>^hM z?%#_wOSJUnKlj-n4F|_3_7j55mz~}>$n$b-q*}svCwE_#ulGyemy0|t`t8xGF>Q+M z*eFG|8e|VEj;U>q$Gy9=&Q;^(+m31wpy2bL6+5aKBU&yO7tL(FDjy!+N@q1`9?ZYG zHE&)Tcg;F6m&P0S&Q|=lA8o7J-N!)n_Or*3qu&?Fn~aJ2Urn&*MM9EA-yr-uAqaA0 z)>8x<;&KAo@u1BWHs~Q0T}h@f`%6b@bU>1$m?(GNbYgi)bj_)U(^LFa)IZ00YaUbp z8wyC8Xc;-lIJ!mkib!&rh-AI%(EZ=nJiELvTk~J7uk_CZK}Qoy1N7De#~j*H&xn4D zpjX#NtVuYlfJxp+=>p+^u0KcSLvao1mS$HxyYI6Ifi#jyIq=fv7%)U%A~N=!S^^=h zufEYD{<z3;5f)(&;}}d0-@;l|t`4UWu)Sr<E(T^I<Zv_GyX>=9)ueN_7NZfcSUR7b zB=%u2jVx+ERu<a$fDyWMsXQ9tkPd5Q=+1lJ+-0-MkLUM;`TIrA$a737E4Vl1R4O<@ z91Oc604skSmmOdnj4Z!Hs3go&s=*Xx4L!05#V=kt+t|l=uMc$^d6O*<3xmz3>5qjI zGTD0^Vpdv78c9*-svzsNq}Nlrp(L(jfSw!#g#>&c7tF^`xO+_)I1yH_;P+Wf^^@PT zP=DDRGOW%#C8Siwo9+w0M;mZS11AyS$LvoP$okk%CkFX(d2vf12_X;wv_JBx5wM)q zN^{hek5hNQrZIi^%=y?AB3DT89j6S*_mC}0(cQ#prO=2PR(8%`H|NcK_~gBz8qhzI z9^(S&vusLT<Iwb3Mf5dyqkDWSLZh>-br2?CWrFZ@{oXY4qv$ml5mz}hyTT?Wku9l2 zrOA6l8Yt;NdN_=IA>}8;3hnI?W}&yJ!--R7&i#}m*{umm<%p$W;v0NyXvrGM8_50N z%i1P47Z3BV+uJ@R4IaNwktBCc7GL(1;#y`Vwlys1x<cfcoq~uqu@!4>kObCbTne8E zEg5;{j{~Lw+W|{9eg<S?h{Av%L1K`&GIIv2#jPq|pO3QZH>miphNbDPubr1j#;(t^ z@xyYs%I1$QWw_~)mt+pzaWBNtp2#(OR`5MAwW9}Klw5a5DJ-rC)PX~VNF3~FCGeBb z-3%#ojPCiHc!0_}_JF{M3Z^#1QW05-<36CH2l^1%SE!L`j(KPcHrpOXg<z?%O}(m2 zb?I@$$p23em>2S**y?B2ZzawK9FC!-EgZ81a?(cAzg*k{7M&~wqwBitE*w3>F@1qe z$wY^CYTUZq&F2?&Qa^H3(F!~)McDKlw@818{~;X4c5a<W4f-)YuYRYOB&M010XUL8 zR86Mses)-47nx)*CKc8tL=d4Oq%GL<n#-B$^I8KN*B#agt+&WDJO4LY&1veM+O2PM zH@=+febB)vKmKw>6Ecak?d|!wOSzTH*QcUN{mA>jf|r%mx)geL>IGZVJ<GGKjBH*F z9Ua{R(u3K>^2ca!UmvE7KvDyng$&`AJV2ZEFvrmhkjx>Um!!mpjmEpAK`8CWew^bu zRc-CvZjsq!@zi>GIYqOMd6&fTTX@Z6|J<Vp_>cnyh8>KR*+0}%0t{RF*V^W?BCoPs zBvQl(vU!<6zkMHE1f-ACiml*{i=tBcJGs|q+=)H=OQ&*5Fz4fKdVKj;BxURuGDto< zC8rIV3Y4)KJf}*MhyF%*I69lxiP{QY^PS`C$^GT|^ZM*D@ZbS%mXV0cs=fC~;wrRE zsZ!!ik}~zSo-Tl(Z{lU-pZk{nsv|c%6mLD2Syxr{U>(tiA9l+9oJr9pdD;AB0dv(- zGO+(?9Y#;b)sWz+Lw7SRQTG1I>xPS4K*2_Ih_2Qw1|>d#-OdbJoni(JoCZQ_&BGnX zigcWi$3xwpQtigiq_rkTxb}hYLbvv3!uoEb3zeCsA0T+V4uiS9(^=JUqf7ocvU2o_ zf7dSWy-gV=229AuR8?z?ED09@35}1pb9iwaM9z`K+mjKug^8Yop|n#??-!aD*k}&@ zU{NbrZ#%Vq9M@wi79L#RwXIH2TL1+Xr0i&pL-G-uFiuC-*Ak5<D%5h4Peql*C>JKP zlS|}aa)M!t+JZ_coii6O9a9REn2*65)m@KmL^GmmSogO5rT5=;tZ5>wGRaMU6mFT} zgv=|b$Rtl9Qok`6*OJ5}Q>{jd>Le8*OsOjdwi(=hDBiiVJntlSyO4q<jk!9F&*ET< ze)CINK9eya1#-t7%umbM`y1|LlDhQh;Aq2khBlLds^H*AOSs@@@rqE1PZ6eq88-e~ zQfnA-6bfG(W-AIs#1mF<W_s8fR^OB!2+cMFU{ML!6QY?JJXl46FPVh9uu}xTE2Ao? zVG8%>aEoQevnZ(f@rIMxQ?C<NT>N-ky{vdqWKS)8^K@NKu`Va96kMkuC{YXrRv=}~ z=S%ye<!ppouOYP2ZGL0=b6f){ZzFLN?J!Xmr|M5JC>s2PniSIFq&KOtKy`d$h<OMA zv=%xlIcE3|ESYaO)G6C3HbLCu?=*v3B^mq0g>NeS<K(nm#(IPNn}rP@;WUwei#x@m zyCw-2TR`zFUD*(YJOMX@I{14ePrn4kvK+OC8j=S^IS3K#a9T;z{vu-uP(|P8-R|Qn zyTb2!F3Yj|<K^N--xoNIMP1HSRseo4qwY?K=wv(5$i^SCr2W&~&oL;l3*&iWiTZ<g z7)1e#yP`)D#2PK)uzVq|Ul6;f;}sKR`H@Zbh!2*cdIJilT%x{BRyjYkfJ{@8Pb_$( z?pfR+_tG3LPkK*m$K_@$7@=w)X6)!XuC>Z}D7ug+w+0nPLM*O_)TOu8pg+a>SX<N9 z4P6^XP0YA6?h@f0o9HfGNzKr^<p^1da09B^ChCQo>k{AhTo%USPN%Jpkhi?5X+;$G z%7G8CP;-WmIiHle)C)+Ht&DoIP)#3g%9fwlYRFMcjU0XJAH6NeZdSx1LVQYjd#j%x zkCVe!OMeZy`8qmT^!<hPbe}SceGl`$zgSCjVf4!52LJ^MK@c7IVDyQ?vaQbP)HaqF zRs?wB&cWe;oS@7VcXL_$FcbsWkZ}Yu&pdy&&sG`F(}v^s4)K3%^dFg+B4PhTc>m35 z1nX>O5alAQ)>u-lh?f4q)+`T^h_g1$ik_+nHM|R`VaZ&3bi3WzPVaRQ^i699w(C@P zw3&(}Ed}d&6>tmcdwo9dUg~*1&05vs%9{Gb4{{ELdD)Zd2%r7Jd{tg!e%+|Io;VZu zY%?J|%%xiHALn_cMKHiEXq2Le7+W6tOx^Dn=SNNW-2D7P)O8xlk-H|EP|WmLHR(+d z6BW6iXTNaeE0jP|-?73=^awk+@B{7iwRHI$!6{q+g7o_omp%2m)=ilx@Ua^u9=WNt z)t2Jsj0+TcA-Fj~gtJ-q?k>se7QUyc961slTdlKm6DL(YaqhbUyG(WX(R&!~I@%Q% zw3%G?jtXa7ez|&Od|y_=Cz8OElE$R2H9gaM<d53;N+qqj70`4ED<o-;+NzUtpeZ{V zfa(BpTRyBylK>H@p;iNzY$MddBgo5~YIfr+s+C@>)xI|9CVrpvIYH#d$D?m@#3)$H z@gquAm6HyI>EoM?t22KL;K6trF=<RvJJp)wFqtYEpr}&Z&TOdgWxN%zO_cV!v$JYC z3^#u>bjqa4P&IHJoN<3AKg@%S(lMEDDNm*^XvtZ%#?&YE9)nPjo>f-M{Iv}ZVo@^I zs2n8QwbW=P6pDQDXZNR_^f+z=f3TLOR%X2A^L8mT{EDIOGKl>ZBpG-kk3$4Kmx+0L zmI-(W?B=c%Ma{(O>BEA9F&M8f7n&jD70Ymwzh6k`IvqeQn|2kf?$DSaMy!ey?-hVO zHN;$x6($tZmE6fb9yx9zq;197+ytDy>ZOna@iXS%mdg3?n=)114><&Ioxf9vigH-6 zF8!qov-KbhqDi|k)tJmnP=_7?<rDV%A`z>N2Xi8yJL8~jwO}*b6+|&fHV81sC(l`r z`IQ69T~_EHh$JS9&T9YC=nS?wGD)7@X|ZnV^K5c^`LK5EymToscS7;qE&Oj6fc^R- za99yWBSmi|#hpwKh+WqtJzweWBhrQ(3|vVR{oRjnOc}6~4@VKkh3xHQxk6viI5>Jc zJNu4W?Gbgm8kst+-?`e>T)t{maMWEUC%g$KZFT4$Br@di40<c^qx-KX$c84k@iiQm zliwwA<R!Z85w;&h1)*PK5OeCEiQmYkI!+t`a+hL)JSZlZi6WQX7)~Zaci4Aa`P1s= z%N$k`OMQl?Ww10ji$S+Z9}qDRes#`T)qQk-PK;H1ofWuj93(S}e}qQ&F5&$G{k&pw zvX?i?svZcUpfA-5%AjqrbQ2jwkr|UcJ)dDkvH#~zQZVhG+e6J90ov6MB%;qVGhEIw zXdpf1gVcezqNK$6c~Y1!C&!f^Mec?cU>rn=#v9&LCZ|?3X;IIwJJHm=l}<R}l8?l) zzL9oh2D-id_VD>|aAG;+Vl;vDugZiohBRWS-BS*gdLSMQZfR9~536n$N~3Q7$MZ^9 zD71B46iT=e-rviss;Y=@E-5>I%ny{hB)?+o=*#q3x8nA;vn|JIelsMY>tUaZ;ZU5R zG*8{EzpEz|mPYm9P~P3{{0!@7PM+paf;uFl=R04O_TSH^e+xW&iCohhua1~BGZ{FZ zXtL^H$+ZX1rN#u`+I8Fq^mwKG>2bCgO5e}hd8F<3=^TL$-xdJ-#LJ-C#&5SnuMgI4 zIL&Rs1o|<Z7nLtWd-Y|K$IW)2&m@gqxw>S9P3YyJj84Ezzr3vPH^6J?cxj@=Mx&W_ z;Fgn&*7<q#Xjp|6KG3NhXrc`aXwF=6QU?}HABJ*{zbs;op&*<ve+FU>zw4*a$d5a@ zzdO=<)&N^dmMD~2ZcUOhj!v?%m<G)GC!M@%O*=A<(%N=TYgMte4U>Y>1Oq-p)Z1Y! zS(nbFOh5xIk^3YAv6Dudq{eIxR~rl(5&Va8^V&V1M_h>_nP5$uubU~z9t~|~+;96U zs6^5JVe}c0wh+JbQr*m1EA`DtxPn8fCI#%m{iU|ZFVieEKriMXIGL;O_8^kc*US2Q z=si37L1mWG+*)C<u9n>)^0MSasG{a5!P)qyiL+6_@5outM2iWBN<R!1Tm@YRLb<!Q zV#nbCpPJR=vnO7Pn!oQt5CcQ^;OB@bLn3a-)7^RGxPv{j1_37_9l)XwLwcjAL_Y=0 zG}%F!yqkSe3yrvuY)og6LnB<+lBN!slsi9rwlc0X-JO))=vIs~A43cW)-t`^l%ZB2 zZ{u?t^khbpp{&CN24SRdv{Y$-6)oBrW2MOM0r%IMlFVEZrhWWk98{XPtPA~|5sTxl znN$xh=`6-yVI||JbC1%ZU3YNgKjZKqYj6M=HndgFY32cQz)qNB)V#5@gZ4=D-x|4` zeG#o1S}7<+j?bUa6sa=C&h}IDZmk0^F0q%UjyE^=j9$xd;dm-D?nD7XbT&CyI^j&9 zY%VQ0vm>&pTHn{K5Q^rUcyXs{7OGn7EnCJFg@qc_7O!H%9J}EuwK?K8mir-}hZwO^ zZ}xGzS+3X}IgizAm*WPf1xJY}mIxMZF`Y`kaHrUTElei%n$0eF`W!>7f-}{W{66+E z^|6<ahr_?K1DD#*kCj*?-iD>vT(5Ar0Zg!}DhQPevX%*h37P1+g!a+1)CN7vyl~uc z%st?cbbR_&Zp{j7+n>3RUJU3Cx>fF??1j^m!|M6OZJ&=r7bMZ`C&lj1qjF%k=fiXO zZ??DwrP#!{e5>T212i&vWObV6wICU`2AR;Sj3c~ZIOR(vJnMS~;5DoE%>KWT$a$e@ zmkDxr*jk3vnUm{DMM-6&)Kp_QYF>9Sr=Nz^(Ht7+!xv1-Ybkhbr9!HS!~5{}kBFW5 z_rQqojR4~zIE>`%DBiYFmT51P=U&H`hN{N=4`<I$-=ST%0N%AZULDLDft%2%G!J_y ziDq-JY}wB;N9ds>T4S?gm7$E&$qW1%-M#UY9fzGY8mfA<kjDtpXikf$W6HtnDF`c3 z(1Oveqc(hKy*HWC6mOhIgDG{MeOL}q@_0b9tF@3d4Mwu>@l0#O>1E*CZtveGsr4q; z>z$@0l!evt{rO*v;>5Q`crvA&|7)aA+OA8W2b(d3E+}TxSnP9X7LW8r@(E#XqI-{D zz2Uq2SHYr-$8q5?W_{m^%e7RFpAnu@@Z{~m@gR_QKM;0;4N#E9?M>bOqY`2H(`>}s zv|kV%y1nW7_<nHpaV_7aTy(DG%41F=%ULR3$E?g4tN4*gjNlkZ!<$h&O!+n0z{hMl z*H}POOK2#GcV7~8R2%DH6!(~(j&B!y!lWf(GfTA42|;XnV+K^z6ZqOU`7#Frr?K%8 zxGzMzuLL+Ce)8q4G}?9Fxp{2XdmbKs9fA7vP*J|?9qsEtG?lkp$<I3{I|}dCY;1FF zGaw=<J`onV^n+TStpbacQa*Mkb4jtF_QE}De4TEL1+db!{2e)dEpdrFm6zx?Bzy@C zaq6GgA9pslp)K~GSbhHGOvGEBewv_pXA8ZaHu6Q>E4fl|)M+<?Fqmm7x~fn>Blq09 zdqKvZ<5TbV^DYK|G@H$eM~MU=cgz{jnNHG2v6YncMCckwl{zCdE>w{`w4Ugf^&hDk z!HnyzXz-?APhdSA&VvZ4%p+5o9C_5K)Fyrh^p)9YQtAywqr_xlg;M{dZEQoL@7bA# z@<BlQp?z-4f&vPbc{JT47Rnx@LIk!PWmc;+z^(3Uw2Dp!y}K|!Vwo;9;41GKrMz1c z*d7$?H_j*MF&b-oNoj(oksWO|LF+`lt7$fi%hWmZPtWya+37pw!B8E>nix2t!AunW z7(^*h;p51H$FnZlBQqb`v-ZmLyWAcBtzSzrA~GPxFz6EvXYr^DBd5s<uSN~F_9YEE ze#;K9<!WB<<=6@5(YIRmuuRBKFkJ2Lgnz=T9T>&oq2NOz--~=vF~d`H)ADf+Y-q|c z>EF!^F<nwi>&&7iramXDk8ug*Krf)qD3-ANnABgFs2PE|G&e%SxYbLuDX|hQEmVzw z%eRkr+7yYCUm&+I;{f5iFHP(9fQLaB2OR&I*#%gp#z^@)2&o!a(sBoBoi5LV=5?je z$4g+Klg-ZbF{U%{`?f|j>jJE@w7uGS+Z|oqTyYDapuUAWAxVDK><}EHvFT&hc%`L3 z2FI<(T<Q#}XMGsF>PrcMN=nwG!)P*|^m`}t!P-4)Y|2N5yF80hA`4u@_#I&j92MY! zIlGSus`#sa{vx{tg6|+x)xX3+V@?JS=bVBCYw~ioRFH`M{TWORUq0U*8~CK!{C$49 zqH5oEcCBwGE!|0KN43tPi$Q4Mf2rO?TR^Fw4B^&|Bv5C#B!KE|7mgLp9U>-c;>V9A zDH#So`f54OSxf@t)3$x%eP3T(PVIOj2NVAaDs->8e^1vWt3Tz|_(%Ty?01j!GS)sz zy_lHePM2q3FP~ZP0)abBUqvXAjyW*HWJWRFLuSg;mi!G1sx6>et<M>CvrodM6p_Uk zRajH9Ts|I9`w6RgB$C|N@~cN&Yki*SetgIE*n-DOnazgNgk&-)X`l|JoEIDqoeUk4 z@xBQo5&8zHw_D)qi$#zxhaYnl>GuuuIs?11p<jyk1%+d!FCKlL`*rF#m)O%|_Nn!r zSlu#PWZ{GOPM&|`zIrU3P|E4Dbi{cI^QVlptc$b+6{K4nc?q%(M^&-cKqVW8cN>XK zG_Z#d)mcoP+=`XF+k)Sdek0OmeMs|C0yXp4Q8#+lI>IJTKf9A3rWu^Hd-HeH%eM>U z>+9lweU|gtMOMPtJrs=rFi{REIs;+M7qxfJrixXPUPKs7D&oUS173R;B-iEre9!61 zoES7PFn~y!Ui8JRn~uu=H7OmhS8}#nxn5TJUTV=HdcBUW7Fg>M@4K6=ul5$VAG{TV z8D0{T$J%tcsdi47K4j6JO~ZlhYh+H6vsd~CmzQN2K{0!j`>vfSG=+G&0cKqOfa|%V zJl-R(1SUCdRQy7^`n=n}Onegj=+jP(a9>L{tBvw%Sv>N>;A_Dc9j?0B^(CB9Yt+4{ zP8)2R`^SZ|&pu5EX>7*>l%D~=+M`Nd6MA@Bf;=`_;nfx3_U&r*sp(ep*H`cS%0i5x zFJyON&fWHLxZHo_30jh+I7bF}o6vF{$aDz&8CaWZ5l9);@Dup-Zs_-2`<(c^iX2WN z!}UFc!hA_Y1)21)ht50DnGJw($K_5vWjn}f&lw#j#g`s$a;){?taY{GvzpH$BH(k7 zMgiy!tY;ebHEFJOVGJjks07>bbVy$ennt=FUw4>YX3kHUR3fc&mR_zmAjl*W-Or2y z>_@t*kX4}X(u!J@)`>HI_k@a|sS3EI=yLT*vsDDDrY_7<>{Lgo1msW<7GXO^OcMP# zb6I|NRFmgU%n=7!y(bj%F2%7k1M&L{c~+B^aAptmQb`7iLEGuo>CsIPMn_Pz<gGf5 zvO|XS)SAfZ`*p(s7_66I<O?;l?bt6ROar<#y0rWlxU;i!ygw#8iG1_~xXuZ)pT_0G z4|vd+V9-hxLio(G+F|YC8%oV6N`O)Z=unkW5)^`mu7u(Vp_8g1`OxE21<+u>fC}l} zjdc$NKI`TTFhug%D?O1vA3B%^<127?=>?l=uxUDHYob^4hxMb-A|cYe#rTZS%_xJZ zgZO%U7(GhRR)}pyEOk<;GcnpzH9X>5PqVQ%sp=J@;Q+M*)>h^ky7<zh$#sv>_;>Yk zKmT!Io$B<mO2;R;^|;bZ5!-m#D~MU%b;-cw3mDn_CQptqu}YJ~ZYU{yDT?0M#?wB= z3|+1!Af#6$%D|^~wpLb`bRg$awiieFnTIf=6}Ox2ST#X~{V17j3b3&&e4#3SjYcU2 zkU^nHob8~#rz<}Y_Q@;>0nS4^v#|c=)W%fKD0_a#S3%3ESES*n%oGxz3nJ^7rTk;K z@}jvxbWjFN_16lvpUMjdC*|mj%al*oIzInioUSkXXs@fjo*D&ni3qpdUQY-&n5WbQ z5zd_PiAeN4y5f~hZ16VBU?}w6lf-bq8xn0w0N{N3yQ1cP*oa(ruHek_n;tLcAH38> z$bEv((!??+iJ8sH7u|1X<L%qNvRRtOZl!h-v}?8_@a3k2pNx^VLRo8Aum^7RoL0P{ zYI0-`3PUh!hQa(gLZyuZA}nGmmqUGFI3{Y?cEjmmQ8Lt^Co&mgg%hxp5Or)K56q;T zl>2+urfVs_{ONKnq_iDIdVUW_W@n@cuL9NW`1jUx3b>iy@SHb+Y@L<S=>3_ipVZ}Q z-T7?W#|fFu=(6rz#V#z)O>8N=H7W{!k26Eh3u61Ah!k?&+s_hh{&}qfkj;PIHDjD> z`(Kig1{&Ck-99Z6n!;>=Z@ggq%VS3-#I`_8oJR=wtfX7gP-A<5prqsOVIe>x7Aw@2 zw!jL4S1on#X4`ZmNxM>pr`_mEoSr6p^5$IkRUw599ml@M``<v|zZ>7jj|I}%VhEt5 z$TYNoATbm;4r`4YLCrczy0|ujL0ENF;vzmR8FSplXtXzhqu_6TW)%U}K)EvML4710 z_rK?@R<o{q{{L8!I2uc7X$u~&G+YG666Wd(5v<;<|2frlCfDD?5qB8NJoUPGZ`Z)5 zYd={r$R$qX>J_0&GRaSj;T_%tZDAguo@gs6Ykn>m*n|Y7+g`Aydwg}}@MKr!8rkW3 zdN_Dpw-*e44u^6!d7;ZAchl+6IN{a8;y?9N>PRLs#=F4Tb@EkKl5~9)F17afYD}Zl zm`IGO3uMuCRQBm#Eyo>dK{|1;R!=H+3v6|}dtzj3cHKK-;`=`K&fsX0mt6)H?0W)Z zhf$C8cLZ-bUQh)XQXL^QQ+#bM$H9dyXWf2Be`*UIYtq}=e6$~SzsgYe`jWj)tWS@K zBa-d!^yVqc&ttFf2kJ5rt~Ledwky|J=!QA4;3`|H90h_k5f@YH@Y02VA@o4})Fc2A zL!$)CqGQ75fik9n2?He4vHIqlGEGRH%9%eFs(OYtKk0ezzg7^wit;9{A?x!(l_oa` z9~GE1h@v)CC4aa2Y0|3t`~mwo5e#b@YRM26l&eE3-#_|Fb!f_~tz3jRv^c3C9J=}I zYPE9=R1I|D>{284x~wfR@~6%WIB>IW&bclEWgXr-MM7Dsud~<ya7bOvQE6}dzh=Fz zLnxJXW8ApCC4G$m#Q3GY7cqGApPCqs20WUj$nX#{?O4nZh=f6^DRL|ItH=a43V$!x z3|%JoLf>Kq+TV5}t8=rPEv}T&K%Nn4Sc4qULqg+g1PwQ5^yKxHoc^IrMUIWoAr)0C zlI8QMk<#kKD_SMxe{TuxTP0)zsfV`84Ue|Y<4L9c)Yx!i_tC+ntzJfBK@nVt{E~;L zIFO%-us)zeeuROe%<ow$G4zc2EiOP7Pdm|&U&9XNk#mg~_CPqxo}(K>BT{N>xWG&4 zf_?Hc!Oc}GMG)gic|x5Gs6Ri#9GODF2bJNjJ0m&@YcNqOIjPiP?perTdL=ag6JsG< zXpVoZi}^ud5?jVA>u@QydW5`F)ey{L$r{hVc(eYAfiFNq#(#%16CwlN7o|SwyI<aZ z0LAg$ln%8>pi-{1D8TF19r9OWLg^v%D9xdn*YdPCu(eI3ekEI_vD=~6uy|(<%z&IW zVrU+S$swd)D;lYm7g|}tn>JKI{uoN>bPO*JUr;kdQH6A+5|pQ%$!hE!Q_=<tMdqjp z*czGb%dft=+d->R2l3h|E0FFyI9qy&<2pw*HouPX70}9>rr`Bl28_6>WWHXTRC=F( zAo;u>mG^|0x+OuZ37y)4t^6Gk>)$g~;dWtzl_$f$N(qpQxEH6kU^4s_M}4H^p6h{O zb8sOn9D>O+Gl`?a$^TNRH*slvJouTTJhp4@ble}i<#jx@sVMmJIX<0vYGJtSEtgA` z4*iM<G6=Jd=uPc+r3p*YKq9C0Q2aQ6*c6|>OPv_L;sX87#Py!I6kdD@$%{m(Jt9<w zB0Nw3ZkBLmerL$QpyY2;gl0lei<B#~AmQhM5|j_x_>`@9zXVi#pR$Fxk1h-$8-K-1 z4pcFQnNXq|lqOknM)xR*PS4hFI5wkUFs(n@Rr%Ozhsw*IY9B11d{k}b1UhT^=U#OP zrWfPAX)`;C`Jve0DVpVPdTd$~!8)S%4{Gvb6T#EMEg~BI^BPfD)#t6`kx$u+p&r}H zihd>rPjy_A9E-p?vvdeRXv4?!zU7ELrJSVWo=U~pTsc@@+Gl|v5XK8UhEukVK51KN zVsg!oFDj*3j<04XV$Q)AtiZzJZTFo@Y0F0yc}M*3Lsa*_yWx(PD++ULWyr!bL?{>{ zB6|UN&v5TB3@>VSvCnuqq$CjmLaHJ*FnNXH`+z1_vm<zq>GaKtd6|-YWtD^02t)VA z^N+Ob|E!5GgFSdu4109c<u!IWTHP49v@&PtkRA5F;fEB(cSsW2zA3d0?IZ&$ojRW2 zXK7brrm8XrO;)K6+vpu*f=&;6`1TVn-F<%V<-o^G7lg7{R8bGmtF{FKm8>&PM{j|G z+rBL;>%LzF-|X@;J3=G9_=IYrz&7PS&R;^WlABlW7|l-*!x4p9YSo2b@TdE2pzTl9 zdv+?*+?>BI&<Dq7=uRqjnhC#d5B5E;)ti<pH@_UpFG_rkB6O%nw4!NU?LL<_SFO#C zn{GuEE(|N+f(wkw`JRw}LDRHg&lU4-Zm%aR5@nYuKIuPj`tVCAIH&QS22&q4^+r+S zT(}-JHFDts*__FMdVTXVnu}pXK`}jGPAM_FVsj8tsWl|^vS2kfN&wu^4bgqOggu`z zzuI2q=weS>GfeC-<T%g2BW{9gTR1VCz!{{-<Sx#ph&^{?Jv%EQ6;%TYQYcw$Omh1& z5mq}0)i6REl$<C)5^IGR{wY(B<#FY2Ew-!Tq~z{4d$skgD$>I{<t&!<A~=7ns9BF& z8sDO2_k*o|+!Qm~kjV}DqqaX>i<tO^*6S(*1OUol*qQ+70WeF4HzMHyT;X2~xXg7{ z1Gkz8+(^+~Z7~`+yyu3XIua5z>*O0OEq6HzqE7~qc|H#}C*?pyA2%k!*24aA<Abr^ zNRK9}y%{t=e5qT7lqn`~rNsLa(v3RUlt@(nshHy4GKFdw&ta1!`jZhOjIWSO=$c`O zphA@-Br|F-Gx@+Fa)B$0sn?%tu1~1z@IgR_H~PWvtZaS}q8kjn(j*ej<QV8Ep&8F1 zogn%j6Vd|F@kWw1T16!N3v%-72<Z_e*2`q>LFQAQ=r@B{LeKKY80P$t1vNy-5wGc& zCGeubKQbUpjD+;=wAy>Aiju(46|D$(Hws3E=XMNfmKPA1$<wi$58O%P&N9XQ=%qbU z8=RJ%f2{Iz;#}>Rp3qn)#LqMS!XSvIT<2{c;&~9^oyJOEq&S2|0|9%rQxQeS{N?`p zq-HoOQ6Tz0hG_A^a(~{qP%xwUT8YoVyL+Z^S2<)j%Nqg0An?sUZPvf?x0$jznQw6Y z?-qN!v$}giPBec9T%!g=ehE2hlVwp-;rS#s>&lL5848<XiW}P+Z3PFcqkDINxntKI zOEZtYZdSHl)^u1xCo`b@8)5s!)v$E!eUs;ybCHk+;lG{?fJ?3A4$hQHvs!bY4D}aL zj?o!7%;Imt6s@AaAT14Xa83M^AS1&upI>wzPOD7KU}|PIf4Ve|`Nzb(5_q}s`5wu5 z?R~fE`W<r~D{dDUq_f<+t`z-dGvHgHuR6$MkN~qo6|4f+x^aYOFzY`;b>Gs;Aq?ni zFG91(g#D4hYLFB^NbgEFx_wa}2ib+#^_ztqK1?WF5i1U@wh`ZUd&oEt0MF5+q_Z&Y zuG{?*v$auGQLC+;nJ`O(X`@+t|7{(L*YXgf%Di>Uul#zn`}fwXT%^SL;>PU|7)|8c z>TCb-Y*!Wv%<A-ZHEf#cRA08}T4={ZTX+)j#>qIXaQCPhYR^QJiuKT3mYly8Skp7Y z%cM(i<p$Y2{A{wN2!NetLR;`4k4ulx>>3}P*$c$1$F=OeY-_?UZS4(%19^W?G=J@b zLI5`>K%>-VI5h;N__vj<gHYowchtcfMl$QJv>KW3)6Z*n_oV-LN6~dgTlD$At#3^r zo*Me_HAf_WOsPEP_w#k33{~Xv2WoCWEIgyPZ~$doNr@5)tjv6IGy$&*AFHeQaTf2s zJs6*V+sH3>2Z{P^lc|^7ZC~D1>-8p^^>yo9Z;zYtQHyTu8V<dvM9utxGZ}2FIl$!# za+AZ(zsv(IiUi<@&9d;Uv(jTmB2moL2X<@}_>`S@YDN2-o6s5*v6cL(H{!fEolV4B zI9C*8*KRiL_~Pp6X#IZV?kp#)fv>fCYpcC)|J6wYSNaB5@Ra5)yUTv=`XsiMV_6hX zN7Jm`_7AtU%&_RO{^U?4(D2v9R%=TOdwQY2rJ@x5y!)tG<LdceJh9}dR%gWzNQBJB zn<jIi&36rWiQ)O>Kw)`~o1Be6t+=tHOLKavYJzrpA;c(o28Kq&(EUx{&dC`HSq?AY zx#s!cLKVX@BhU&ySXP|~EW!>HXY>c>A9M8~5&3Fm89Wud<#CmY2iFqvc&+6J5@2>g zSO{pe&dH%PUSGjrRze@P4s9saeIZ1-WD#T;9e6~Cx!Op*p+*#v>YDGHtIcMM6l+dl zZGPa0m)NLHf;9pRj|({LCP^`Ooj@?MG^v$MaGXVc&ox|pt8ot`9d?}QP1!@?SWQlN z(gEr$EMr_JVlWDh%JU~DkHb}#E<IL(>yBxsesqT}_-`HR)gInfcCQ1fdw43mqa{d` z%~KddIk(ZBd}W*mzA1Kyjw~;?7Iy4Ko4w$hN$~KX5{m{B>|>0f4k0|bH2nyjT|!+} z>F@B1*~7WW*XMO_G?vlFjfc0DNfyBw0@H+3Ba}!C_G21KeSQPZ&~lG+4tWv{^af$} zCY!j9jx0VcZx>e`(7#enaKh2(Z_f9dFzWGk`UMb=>5cId13k<-X6_FNi{0x5<t^qt zay=yi3hwRCI6+ya_a|Xaatz6GQZq6Ke@-F#0R*^-jJM)FnYaVk-W_B<5G7VSR_;{- zPcw4Mvh>&z^Q5QzDx{6Pu##xaTA?m?JHFT+L;n$UbTP*gv7vqUzG&P_x@;ok7!)a( zAHQ@h{4<z=1S93#P%CzFLq-uOo+y?z!i(bUyHxg})xcxFd<JyZHEeX<uVchdi;Nh= zD|Djh)Fugbma{7H7&QU5MkY4vAkHc768Su#Rxu7}${rK}IQVU_#&iQRP!U1o<HK`Z zaSh1Z^0e4-38F;Sowe{&A-Lt(e0B<KO{@fyv;<f}Q09Fc73l!ISPg8%!=se`SXf6` zrBk9p*tmK2ywVdHmAcM=&c!tYPF0v2WgJJ`1sCPB#k<MX@peh1*AE*xgLQ$dCf_%O z+IIcyBt4!hn;RA;EC^7p85m5ozLqA01kWI94=7EJ?G}1uZm5CMhLD2AvRIU5V$xDX zD20oat>GA7Zhl|)_u<X{>96j!0J`z+_p@_Pr0(a_QP=6NFPFRH>qkS-M@+W3{(P{? zuG)U62UUO;UIMccihq;K6dv}Zj!|Ot5=lY<V{PCd7<U~cCPa_YXMmqI#5|(v?>}f9 zWU<E2(Zu3>^#^~({RZgmoX_1JI4Izx(k`;gD{_;y4n2T^mro!_&8+y)b@-HMD{g~% zjoPq$I2Z7-i1UVAs=RxNv%7(w&Cv)ZYTW{!>@=#*=K}k0`?|bc?AQ<Z=sGNFi+tmE zG~R2p|E~*RXvUVFsh^v=kzq1A_3Nb|^kcsMboAY;G3}G%eA8El<}_&M{CYd=Bazty z`B*n<`3IM5g*!lXbsqia{fLPO7uSYejWP&|6TrOxUdR_o3ah6)d<!q?mTx+E>?|WS z`PwXwwX1C4p7Ud@j;``aAVf__tzPJlB?%fi6h!VM^(hQgw!B{QuW{EJN!FoH!)qOn zeX4vaooXLr(}@9lxg=<6QYmOaic}cH#p;dXYK_<);|+3MzyO%|(7y2=7xS&0U^(oj zBhYyoAUp;Z6kU9<$hXG-QF6xPeC6sAI9YYMR`rouNjF|<rI%}rT*9`t*fw?iG8D-Z zOlLh7y5DRfwDVBO8T0&O-Vm8hG}n4IUQKGE@t|Kj(|3?6aygn=Wm!F&aYVA7d<!w0 z6~Kv{TITNI;qWl7c=?%nz1_7ArS@p~^GUn*GqY$D&%^WemMjl&dBc%nY$d7xbqcgC z80EEvexrT>ioR?$@dJGw{s<zW-fUk(uTQWu&8)3-sMT*15qv9i{nhhR5zx^(OAUe6 zUR>U#U@4_q`!EqQmxo8oi@lpzsji5Q1+2+Z8}Z|Z%GLu?&npipv6MWB=Caps$HRin zxn8#%@rcWuK{Y;IH;?34k<@uP(Ii21h8*&jbsdymkiSXSn$+T>faf6>8Q;M?HtjG} z6Z}}Tw6H}9Ls}uv4W|ZSGVB%PE4pV<Z=LGii@b2^9$A0>SM*Ee>1VrCZ=1;E5n5)d zeTT|O>kiW@&Js7NRWB77@eOq9v?NNHW~}Lx{t?~Z;9lm4GRrxulggN+h@J)gI>DV0 zY-v}Nh+(19AKGcZUjeZd`g%I0fiBTna=tZJXH-r?QgRvO8~z3g+1-m4)Ntc8?+}J4 z|KxsQa<Kiu=L&BD!4KL=!{l}6*$t$F_)Q1}k+pAQSLsd^Hi?YE$9y)c>G*K-unQaq zb_sF|Tr-?0xe|Vocjevyv&G(AHC~C!MCLL?<y4FOpDRox<<8=Eb=CdJGFJW~Y|9gC z{a76a$%(LTh9#NHfCY;IKb&e5MphVo+Yl!aNxWVj@HdhTpmv7-BcOBawA^f-l`?%1 zvcpR+>!k4F0~oi8DKf66V?d}I9&hJ~+a*koCE(6yN3?GP4`vZAbyEPN52hMTv<gI~ zCoq;f(2;AYnN8O?E?cD0LaN1+;5iEjWBHvu4}RD)7)(f`)XAE3g1uI}e^9b=za#W3 zkGRqT2mI6g>W2yl+w#nNeQ2t6;0Q^@Cm$u2yA#v)?kPe*(vZ0HBWZe|U?w`=0t8py z&paz~tnTYN<G4UXlmqUBDp#5m7tN_86sNZkXDfB8=VBvaN#+{_lB{=gbmHH5^o^?$ z`Mn3TlB^p+Ug5@8&{QO24w8NB1gbd3r_HmdKa>i7&dLaFA5Yya7XWxb%5h)KVzF#= z<tcb+=Bqw@wKP*)uLQXSxh2X#T5WzT-n%`g$Iq4iP`M$?DX5Wx|9c&W1m()uF)bs@ zPz46$tn0>5Y-M%_{;8g`!*B~xuhtXrbU5q$`UU6Our$AVabMl_c{4xl^L(`~7~|tr ztFwT0j8Dj5b+}LvhdasaZQ&BEBvP_4HScF-9CzFXBaKMBimgrR04_uZPjob>c&XuL zhSqBBDy0e882%%oZ^sceCj?3)%4@`X`CqD<rzYo<?QkZitc{JPsk>(Jnrz~PMa6MI zS=7ZIX>;hCWj^MTxb{Rp-Tm0Vtp%vHlyOg_x<5#x!+HI@g9$aFZCMIWSKWV)>+$5% z(zJ<|oe3gbcrNeqy}V4PQ|`;gJXEN<n<xsAE$E98uilwW4IYxsk&5&Xvgan?u^jY* zpb<L$-pSGRy7kr)Oc?wCjd%s}s2dQ@1xPNJ|HZPe4s*whkgK+Agw%(bKrQMhKRcn+ zDG_BY4lt}w7!@xs)?%0UhPXB_TG0RhVJw+A^3~ND&U$$EUyXbKbmdCFj9=U{!aK~= zyWEuya<lkYf?9(x3bGBVAn7{me5{DtB0u3ZO%G_2?g0;=X>Vo!o9+9!__P8tlexA~ zOjsYqJPdW%=-8u!#DLCMd-0h1=%APYb+=blKhVlvIYMJLVI=)gbr0$CU5Y(UKT(s3 z#9<x;5I3HOpj$rbWaH5jbI{qd<ObqUmnXP1c^g>P6u8>*ba4xM+A|A!zpgHWCP$uG z_R9UaTD^v(bJ2s~6&!1tvyyDkLwd44zdp}<YIflQW`|zs>hRN%paQ$IuQ;<`hQsk- z@x{$Sb(q`QI^OqI=jk&^-W#|*pxC~6v0@f?$x$D6%SWw&s_8axQ4SG(blgCvlNqam zAIa1gv}^2dtRCI0RDb7BcX#uQ#rRa`i+I*P#`nGS;fzYE7_t41?D<iZ>1HJYI8kmj z^N?1q`}50i*eT`}`zNN0?J;`-Y;jj}i`W1u=xA3K)E<KB(Trib!ew6J0`?>`OI#9) zgai<fdGO^8y~9b<nBW2O-dy;Ez8-cDqy6>C!_+4>tDi1BpABz{M~t*aAxV<K87s(9 z?;3WEtgHUQ9mfsDZbRaS9;7Kzv!-N-Bbd_$@`-y}Nyg2Q<ym}wFx04Msr}_#oMs-L zAHtu30+x-kcCrCOQ)?~CaR!JO`xLTxb$K`bJYeCN#{D=VB~bjr$hC*7HHA5CNG};G z|6YJHOKbsLWbOXi(-tW~Dv?{ta``Z0;zqk~xn^e7wnOul>IHBoqd&$-LO*AqFlw?{ zZ?ERzYDBBCkqVi^q?`u3O9<Xhv&>7e*%S$3H-Az&mcO724S<u$KAGCEyvQ4Ca2vr- zL16BUA;&|MP=Q#<b>iW;5W<h=Kj%uCu{?43U(kh5!RiVi73Na_GQ7g#>kl;6CQN4< zFy}`Clv3)1tmmpFCNv@r{XP3(YE$g>_ZTG!ld-jHP{5hj8fyoH{-S_^tc<|a2WX)c zWeCf06!m0vN=sv-%Lh}Zz_PouNkgI?PKH1)p+e#+H<7GES)_DHCKhwyjs@7=>cK!9 z{!SoqF#G-xi{?OIs|H@su%V3nYOg^qCW|@aK}?ato!bZhAJ$wng+3DeX*LpFIkTSe zMdODcEWdt@9^ks8_ZQ1il)AZT5C38t0Vut9F^{T*F)<7g@{ou(^sNV2bLI~y%wo=i zH<g2R#T`yVDFsOh5C$~1&QOUZz{ROiamdS;kqrdAJW|&sp-T>Fjq!H8Tt2@0G(90L z=zbr(P-T#t@7r(6_nm}`62>-ykzH$4>8~dLHs{{OxTg*n@1T*)F+3g)Dy4t~Ko?C@ z*FcT|J>i}t5a1G*pUI~5&)NHF_&V~%%j~K95{fNSH3y%-_x{qgespv3W%V#JcS}ca zqvLZ>4X%mdAN~;>w_2k-%|R_`^-(JcEGl-|7CTUw%MHny*7wk#qEak_KBQ3h@FF}- z>laRxN+uMvp2Ncde6u}H!(8ymd7I0=_{WhCGj?0zyhDweIYub2=uh55y8Wfo0f2L8 z5cbd?QC-|k+G7v~=STJPE@ex(kt#I}To|CK{rJv9A-)Y`N@VKC?r5rHpr7b*Z51um z(e3`njn{U)=JV`Sc4Kb^?vx9BZuafkpFez5%iMj+c4jXVJy|qqTxxtH=-n|*`X<fR zdu0~dOhT2O{DRm9VUv=IF~iM+<LfWgiH9>BV?7gCf67L^*^nbjD4sOX8*a%su+r)z zwW~3+Z>qEyj;?nf%aUHv{+p|61JNasgWEk!T}%l&tnjSS8BmeJpnMQ~`4y!BBH$zr z2XI!GA1s>$YT0F5x|m7;A?BKUkdzLl<;zn6=QCbUP>=4*=8u1Z-$=Qxr(<AX|Gvr% z<BmRNWjU@QcZ=fuKy&5Pzf_q#qIq%)D1!J!Q)P2P*D|e?*6|eD)WwOXtd3Q-a-uxF z=E7b(&BZC!%_X4NX6@^QP33PMoUf19#qs->)p;!WznbE%^<n+Vi{YGzvg1W~sK7Nl zLEy@t=IL9(Es;xT2a0=J{Y72Hmn*f&9pfhwdN)>S2hVDY580017XsZIk4eTzORj(Y zqZL;lg;mE-pT`J94-7B;ETPTG_O1Jyb<dRe`kn1wN}Sf_q+@^+X9Ixu4jrqh@#UV0 z;A&l&Mu<Rn#=_y>mj3dc*KLY`K=!iPMk*AA7cd7Hfb>McwZ_au$C9m4#TaVz-n*zl zxAxyFDqA7-weJvBs3D0)4<>YlEvih+NT3QxqGY7m*Dl@=fShN&^RD$-Pnz^Mu)uS2 z_t);Z_tX(D`!TYX9;xOl^{VSC#UJpmy7#!cSulOZ--uFLQH3Zpy^35@X~sVm@bWk% z9=0R@9VFd@z=DIK#TTg1qdgv-?KSB(Yj+npTfu_k--3~^Q78AB+V*pCZ2~NUxM7v) z&cJyY6QMe)jHPPp-wT<z2^I!R${G2{df1GJR97PX(V0(@L@y;|pB(U8Nc8#sZln?s zAEVp^S|*T0sw~Gj*8njRbIYmj{M;`irBL(JtjWt8Ktr9)<U+3F9U0+ZNuzF41$X46 z$Xunqr1NIPpuKQYyIn5Ffqbp)lJb~l-OH1aF%_-VhC!HrYD5XB!{2D2&J!0Yi9L)9 zDo&_SQxEBNX%&G%nbaD`X-;8>gLVf4-2i{*B6uC0X=wj@gH>AkV5f~=TL|;qT*I`* z>S<|SGyVjP%Hm?<5bwIwd4G0g8HGR8&s{k<$nE${Xbi}k^Tj%TzYP-1m}^~co&NmE z%^5tJE9CS@uCb!oEE$8Tr8WYai){%<y=BKN6q5@~*RcsxPQX3)=Z|j}wx|d83A;R{ z17P<ARRmvTe>zl=8JXwzmE=1Ese8yydT&6@;mwoaLr!pf0`}t#!Cl40hMb`;AdX(C zyzugbJV7eV_IJHFKDxR!-!7px6o~jP2>-1OW@S3i<@%e+{~^|P<A+qm);aVZ+W!^x zQ+rNmWNiL-H6&PE$+LV3tz1|%s%@I_US{9UnV}o&^BS1b)>s)2cjvZX>)Z3{{djZr z*Xv_yBxiNi_B(T{01`{gNc+}sny4Q$hEi(XCyw!vMYN_z6CdC=XWxJX9Sg2{hx8)_ z%DCUvpVND(bU-@s>4a$Ak3?gt;lVP3siWnBRi{R`yP6i?rRRXN;&~^$x)@ph)@+Es z2jq-v;@Zz$j5OLVnMSMRG^ELW1fwr^7qelVrpk=Rt~~y5wX=f}I?JQS5n=+W0?h8# zq(OxpdjPz*`fct?vq0*2dcfpi$^|zH3*~}2FWj@mf#Z!zeP1;rW^2mFXYW2XRN}4h zUwoo$1x&Mk3*H?0br*~>52tUL)8&~PdaUB!;UAuh2`1Vbh}g4Ne3~sw_T23u|4r^E z#{ac8Jr(gJzik+!U`?V-pjzaXF9pioqTOGv=8GIM3sjY*M#R{e-V<bP$6K1~LWyO{ z%B1ebFc#4jj~+y<$2o7j|5FHk9y8-2(6Y0>0%W3cE@B#+Sk;yxhSRG%8q>7DCi{#< z<8(aTY(#>J7+-(OEbB)9%h@PbJKVe_{%Fn8HY*iftV&Y06hdTny0qqb`B>IZ3CztQ z$^q$$r)(yvK5wzwmW;SM&v&&y5ojS?M;{;O+<2dcid_;U?Bne+_r9*=1sp!k^f_0E zuhun{Lb=Zr4*D~fMcZsVUmjfF-pH|p-fwnlc;{5;bNW;*TGXFTHEF5!-%h92@7vp4 zf*dK`xJ`zn^Z1J0UE$0em?9}k{77D0>=3~57V-O(kt_ik@|$g^;Gb>$n&)294;K0~ zxr%j}a<MV^Sz!~uA7pB?B$_-%!c?BLz!vHA)nwxax=qp=wK9A#8K5Pv+YcBVOwvfq zkJfCs$hi+lZf9P)j?Q__mi+sm-E8DN2&<6(P}MUno<Nt(!NyV7jnAPjactryYXC<N z0<Qi}9*#1A8bXLoKVn^^e!nv@9un|Mg<@hTIIE>QxwYBe)Vyy*2G=0cn^Un9mGnle zPpV#hMZ-Kd&O6D?V*PPTe7|G^Y21ok;+QK(UDi<X+K{02!+Lg$WU`KGp{`BJTgseh zoB^>&443(*0CM^KYys8NCglw<vuhBNR=I)Y1}E?c983tTCrli*JxAPMb#P&WlMLD* zsPo0^r9Va<(o04vvX#oz4|p^&R+q4_y@-~P3rB2+&HYV}$=}fO_TYO~g`4;#D23ug z_*<cH&Curm&~#4Wl}1aujcwbuZQHhO+qToOla6h5Y}>Z&<Yb?J@9TBBo;km&S#OPD z%^=EX6PXsICe{B~kbcDBy9tI=)?!s!@TWibgn*pOJc;9bHd)9W+{jmCJedT!X_2dn z`OvZys6)kQYzvH<Wn%C!rnCjsX^Al)d--D-WOGuLFl=E28(WwGf*d3+Mh-?*22=~h z<+asi?Es~G{sR+Zws?-i{q}NEz4L0HDm*Pt<MQ+tC`HSm#%B#FLB!=`k}<~TcJ;n0 z1BzA&E|JSdzogL96o!J4Q6`cn9ZIMU%!}KQh=>SXutQjqg}OJD)X6zY(5RL}k-!|< zOc{g<i##TlWddf|+gkTD!pYe2tZ*3{NcUshGbzvTMW%}%?b|&6(0F5$PpfG2mw@7r z2YyggWUo&{XI^|cq_m@t=zCWuGM!@>5@&|qNVm$2rqxUWO|_iIsDGpek5J$}ps)j* z7%?R1eztaab@^F~zLV!Wwlk~c{(AXp;Pdzyj!!>Lep2h7^?i5$zV*02RXKFT;u0$) ztR~rxR<0r0w+6u+0p+9!4GZ00y%;=E2(fgW%@N1QL>MJV`uJz$<RObp(gR@q1)&aI z3C3})=|R-pPq()=YoN&IdF%SrU`LDDhv`w3^hm{6YIA43u=X>i+}bJKR~2&sd-Rna zPbg(VXEy0b@UIf~uPg@eFG0>6DCO|LVHa^r@ke)0>A$~;BLMb1?l!eg&XQopHzm}C zp_EHrVTXGhl8AVM3_#lZl-t|6{H~t<H)j4`)o$QpF!l@IU3^_#W3JeApX|}4?HTkt zUHUpx1Jj?)QPs<xDQ_}gv_rMSIDd|eQSwuj@c(<OZTx2fK77)#y(%ZAEG40=0Nq81 z8n_$y^Ajr$f+VCcH=m+nX-gir;+>HZJZ-w1B^?+p1n8+pM0&Trb~!!mbHd$gPyK(W z8g0Dk_6=`S*C}h8SUoqdcCGXyi-+C4Zde#Rs1;GAZ@pSCH~}bi6*B-;cG-U%PC2$F znLs#`CB*va1xv>ZR@FN@c|AIG%c=D4!vS2uHnq3EvkW7?kF)R_JoOiRzIU!bD9M~E z<76-TyQ70=latDuhY_}uO7OE@E8l?vu;cR;eEZ-=jHu@HoYA!nNCqCwEWFCTXz-L{ zm@G8d_4S%RJluZYyTL`i+B%M01Gj~<oR$b+_J!>H-7ZY0rp9IR;`q6fxtsJ*GU3Qh zq>1Z~Q`aZoGDnNXkp0%@PdV;zDN3#G{UByiSH0IIKbin6EDt9IS_%)%kp&mg_?uQ! zGBF4XZI2fnX6!~A%^I$X6_#8#h^|7_%VYVQ2^7wg4D*x3n_$4=UE-dcAa)MHrO=nJ z(vZYSN-&oXq?Exq7MT$Eiw!v(Ga~WhcaPVJuKv>p-{Ikop=0>~v|PqU#02y*XI4_a zY2@V7^~2(sU=>Kq8u<=r9Y)C9WC%&p>ShuD+_dIjP*=c44XC!Ti!aSJ*ygbV+||YW zFzL`5Q;1xT>__xF*$tR$M?;1;;AwG8Y#YYHpuxmgj7$UmQ4(pBkEUGf1Qu`MTSW2# z$uovs$`;E20ediyRaVtevDc`P0h=fVH>?{}0j?`kF4Wr96O?jt<sO+(*O3J7W3S6v z*W7vB&k>mlTG~6K)A8bsMOAgB^Ce}^L1EfggN*kf0PcPQM@U}IQZlKAWN*DC1{lH< zGQRiLb;RD=g%$I~`4sE++>32-uYT<4SJDVj2f`EpMgHhF0g03P62SPvSzzL|{LYw2 zS!u9g?wsKQ(@(A0A~?nRGK-=H1!Nmzn+Nw2o-IKoymvXnIgilH{{*Nz#sq<aGSnCh zLcRDVpUQH9k{g<hvPjKfZNw6LI-T_)u03voYZ<bxHlVI*+_Z<xu~gSj$Knj#b$bG8 zS^K{3Cg=5jm1g!T0GW;Ole<89+N3m1aB<{NPvt?;yIsnb(cz7onK<}E^>NI&2hYw0 z3M|K@0CJ{xSriQRLm*T?h4jV2pq5w$4$;DJ#xQD`Ha&ri4vPUC=q%!70EjY16)a@i zV|fhyg}fEy6-#NC8N^F$`DGM6JW#<JvccKgPxRWv*mf$=tDBogv-?&2X4bc_+gwk! z;_-a_J`Y|>S;skmIK-1r^@`VVrW0qSN4xxtgaK5~QtF67{t>XW#|nqxyOV{3Ay+|d z0mg*LLCWQQdEGyz%lE#X+Ybrsa4_UsbZ}=}<MDpBS#Nmh>Q3tG(j1>Wq|@i}=w;*N zeLXj6(i)!<G`U~}P?GFAq)Bju&+1!aB-)bZD;T^r71uA`OXvG&>61AoBGwE0r34uP zATqr1v*@m{6<Bqsn^!KFcK^*95Pmu`Kk^1g)^FSTH50j8m9vozaRe$hE*0u~lcaWN zv@XX)_aE6Bw3I(+Z4|BO9{mOGrwd=LQK1+=`*UXW)uRYNh&LvaZDDw?B!9wG)v{k( zDpfbGYuT>P?0wokB<+acacnuxi5$ky?xo0%L<?K4Wz%jPwr4Dg_)<C^o^K2~8^Qr? zys%A`xtzU2d(os{;(cP>tsfp;u~lF4BwgLd$%0@omngB2Z}3(d<E<$5_1~<}l>G)9 z#_$`VbdwRc^c+ry5w6>+Y5G+|uc7}}4KEr*UBN(Ffuo6b;b=O}HoTNoGAc$G;e}al zwn&4qufpNLiLc*D`$&7vMmw+L0LIbqCVbHl;LB#ya<jF!KN4_!(tLWTk@llxcT8li zsp^+N;FM`(LmL-rhKK>Bz)a1MIBna6f4$5%m9;*vd#!(u>bd8E);x>@5HN!L$N)Y6 zR#(rOzTcCusVvCTbXg~(oc_LI_P$Cr|H`}!_i4D<!N`VEw(k7Q_J`QSGdb6H@wz<S zK?eBUHXppc3{tk95Xrc7${Vd?U6Ae;?$gH33%C0ez|K+M^ujcB*dcfyHvCC>`@hbb z_2ZGR_qAt@L}&`fhC+vZ>8WKQvb<&N<KW?m=egFaOn>Ezf{TtTao^cI9ccvN7wsf& zImi$bC$R(=sF1(=Z70K=F+U+qVqE?}De>wy4aOHl0!Gf*gM-&{EZo#rRxr)QSJZfa zl02fyN*ad2S?KDlMA_&YM5)&W<Y0QVee1is{O;&oM6f!AG<C>mhI}cC%(g`)w|oE_ z1mvRv9<?c<KSSbT7<GQ*^I0g@*%Y5^b*kB|*+{L`iite0Y4x0(z@}v>K42*#9|MHK z3g&?C^ek+z=SXyf-EtWv7HEN<X<=}uBm}&VV2sJLR)(mWC5BOYiZGedJpQsUr8CP( zU;GXKs!_vLg(^s#*&L~w{?OiiQbn>D0H({kPkIiTlE_%+8)<nJpdJ$<)NgCJc~e#J zGnjOYjDs<oqu(!ynyHx#R!1RQM$spkV8nVOqR2*Y!Ej9&-Q^a5u`m~{YIo3cTxE|3 zC?X2GS1Tl;MHl}rdfT*Kl{uDt#)f6|x(Y+l^SesS<>NmME});_kslO&#CT&Q1;?6H zS%{IE#%APZEaXvA4V3n$i}0q*M^RD}G47x$=hBX-?ulm^*_!udmahDvH5~nv?&fgH zVjSWIiv{VTGQ0(LYGwLjRi+0)v518MsF2Mw{}P3jmkOT)jw-2{FGryNNpyR<?AX$| z&SJBK9q4X*rQ{Mm(IDD@5k`kbPm3y7O%$m!TSp5ao~;fgliJJ;b-ibxMvR2D)Rx@f zLN=hvl34^H4&ERs<nQHAx7Y(v8kUN5W;s<b!Qd4pZ9mu7Ig}KH7+xPXTq4kALJBs9 zaFT{M9UAA)rI!gBX5IDUc`~+HMz^=$&cFTA5BJI4_^GH~x%y?$*knVeFbK29sN$&8 z&&7(p1|{9=3FW(%NCEJEs3ILmDXui0f+FzQYwD9erD0`hqtre>hF@PlFT)ErukkDe zvJbONvrb>}bpi!o^snsr-Fz7DY<={+_}!Kba6As2{hsDmKMuU0mxEdG9pRW&<GoWn zsSY(GL3U<4w4gLWI=cN(hT~JprPcWgtXaQH?=Xx53?cT{fw5lhcm0>IEd>2;l^x#& zpYQv^t)`X+^iEmPKkh9(5KMCtx=?*a?Rhb~@KiNwQ(_U5?IH!YyBU<iOpWP-6)0jD zLI-X#%(+*JJWR`zF==z}JV2C_Kahc=l3B<!{!syR@~1jZTqaP|`U2=Ds&^X9nGA$u zh=>gyce0Z7uMv#ZmC8*Ve_||C`<4={x`P29Em@u@mxXNzTBj<?ZNwwZDZY&rseJ3y zD)`;xUH5#8DNDZpI}p+SPkoqM+1;ZqSEz=dvh8tD?;oH)EiWL13PD&*W(5sM8rS)J zy$Q#au3Nj%b%(J2PB9*gTw7glZhp+YbL8^Ou~aVi^w^yF!Ee|4aHL5m4$+7od+tr5 z;<O8e?%eLRS{G~;&Z5a`5RRM6>hpJ`6#5Sa@%#jdsz9_)^Mi*U$S#hTu=}5DFHY}v zYkyDgX09JE9o1z+1AmLGte2Hq|8L4F|2CdZ8PO%g@6EEf<)Xb+D`8kwF$V&1d`LyW zFo=($Cq^nB8E~IJyB;8`_>RT!D}jBxc%-oBeW8oH74ZNIUr%0C1%#78!R1Z1llxOk z8}|Cy+`$`Q9=C40dlxX8XW}GI9G}AEC<}f1UG3f9c34e#S<_DHEePFl-=|Y}d?0j> zL>osi<^Rh9&?ky?+*55_wNz035(4CRZ{YJP0A1i@t8OG7Cf0cdcxr`~Cnu>SAi)Dg zTvp93v(i+3WF;o=k4XG}qdiR1RTsqBD9H&a_tRlu=77TU#XT)D5p*Unw$%|Uud6ic zeonE(4j_4q8MS7WKgJeFP;)sqjmVfJ^TKzbd@>|^qo~7}um^aYDBCxsIygq$AV<lX z3@&zaIqlSr17}go5cmU_IpYQ`7WLU^$240T{eI#VS7kVV<tu-sa;H}sv4@#K9=608 zQVG-wx{LUtf>?qzT$NB-01*f<#`Z!cL?l=)v+!&%2|*#`wL)|(9EcbRQdMOCthMGJ z%_~EP4_-flY0mf<6O0`=3loeyW~~B18VxXw4iZ>Wh$7W#k@AcKBNvLd#KS?&HT)|u zmyA?m7_Yb0A_H6*ArkGN2QFBUNpjPtwMpG6Irr)1OHV=qn5FR>nD!UrMOfnh0A|x} zy1c&u&$eA*s(VmOjXhS;@zADESB54kl?4|5{Ph+m!%=gEoHiIyKq8LYZzNoU0*SM* zQ>zE%eS=VTM#MO$Swqr{PqzfBVl+@-{7Q#g8<bn%6f3mCggRHSK%Lr$tA90kTxf^~ zXPXzx{fUZYM6gEXt16;)gd|K)=_6{Q{@fgio%?p4I(|6Y&!{aW1lKvH*bcZZkb78` z|1@y`Z92TOy5*zs)x?APEJS;6cpl~msdw-rfJ5~zO^*Df{2A2{1W{cE#JL}48z}`? zhAbzpu-)|m;&LJ}ZXru|IJ#1_wPD4;ql#l&<94_oB1zF0Sqv;-47rbrkia7tHajPj z3q!epbysE;2GwuJiW%E~cf5DkTpZm$pkrpAPf+q>RnzCv)92o>w+4OGqew8<ro(KO zq))u7XAf(+5MpXeutYnmmQ*7<7CX0g3ZKBy7GOi@0xRo??ng#@#2G%!Og;NCdvgJF z&|lgqsU}1IYj@#bZWO#do)B=BOu-85Z7eR6qD~ng5P=#q<4aKhx~!OMnVMRv{XLdl z-Y?n~hWhDKz7mN>7S3^$SI>?s!&5a|*9$FEveWdv^R+#-J?+`N+VpA{p$~pM8MEev zBxkw}Ul!=lnru@g0_!6kPesiS#=fH==?`F7VxHB1vz8m{7~;xpRov{fBx|M+ZDp<F zpSOG<eRsR-#U=gsO_ZDw?*&&XLV__cngFJyC>~}*S)(7o?xa@-M7v%wcyAQkBIgNy zsLYAiGIld1tH%m|e|5=xZ(xxHOrF5~NUU>;akAp1LJzP1uKUvX{5mX2c~9?dys#~b z=)dKBsPBB<PbzlOMkEnXsQ?Lb0QC>d8`{~IcNl<`Kz$RSh$N`FDAv1~M&~-2<d9QJ zP(W=K&E+16>~0}v&izk9ycOv2_f5mC>+3Gxc2*yNCxx04cKnb=&!h439ljE4ne0SI zeX`~xg{@?CC4Pmj``$ox;hC2agybxtI!9QU{Vm<jGl|_s|84kb8U&wz`>F58$LaO< z?%RTeZCH;^5AWys;$iLZtQ8#K6e!!hz*yVDGQ7)oD@)5csPko@_jKBw0%J%dJ3oYV z05<t%D}3MroU#eJjc|H<zREs<gH3Nxx5P^qNTTh|*$D^pzWdx@{mo{(or6isma6~f zGqZML#p5Blqr8neWb7|zW|n-KNf4Tpdx1k;UBj@Kjm2?x7WhTjJIaB{CIp`07fs`u z4OdQD%;d#gE)hrA1b_HjhR>SO8*pQ73rLm3rmpFQYHLH93grn-doJL6Uu48ETe!xG zSkDrcpb#@H7BVZ2g`F?XpJdr27qG}A>uD|7Texo`G?H2UPjb;CEoH~%>Wv)Bt)6H& z7bUP}(Q6;|j0(a-Wif*kwOE@41S>WWQn`~9m*MvLEKUw~I~wVkJ`|yHrP0UBDh2fr z8-l%gv$uGiLjfm|B&SHQjuMy1LF2OGo8Nf+(y71cUhhi%S^}ao4}m~^8}eyFM$n~Q zu{<Xj7{z^*I0DeSPQV7x=?u)!(BI3Tlinm=K|(b(T6Mv(j6d=0HU?#8o?^9ivP+<| zQM}7QYH&E#VS#^UT;%GZx+xao7LY8ZED>;-S|go$8SK4O3@ZXZ;AXL0=vJk``B*Gd z_W%f!Ttt}|b%AAR$7f4GgAQCg09Bzlw_yf-XPhv#ZQkfkh+kN#?NCf{9HjW7%;Z$5 zi-pwhVMr6GSwD9K-}N8C^W-azzp5_3M&@F)=7|Onn7O%y?7kH=mSOp#CcH5R+oWz` zDSc<3kKcG#hJNcTzH<yoyrp5La$sUsadYUrV>u}N!fFbErDP(Up@SFzRaH*;e8T}B zs}r0R6jaFxP%)an1xQBa1l&0p_A<%hj?u9z<6(bddwF;zLfwQVW*J2b!Bi%;!EtZ5 zK~6g?pL2g<_}@%AQ<U9Ms!q7Q$%@X;q?J;VrAKCfyu&Ihtd^acy=6)i>XM)(<0`Q@ z?|&9xNd;EStwpz0b1s<tH7(S2&c`hChZ%w*^SGeuC>=G84uj)=fpV-PD)UQP)ICDK zs7=-FPQ&Ixr2y9Tzjp0PK+gqMjPw+YZx9bdI0~^Nw#KQXdMTn3553br9DH84ODiu- zW&dfZhZUr*<nVo;kJuXzPPj}P>CnYVak8pWn^vqK5o8%P&C*~Y()t7io%h+&^)SOz z+i=3Q<irt+_TL?%hCrk{8|43RLj-g4a`Jq99gc~A+$_Q*fJVX5+Yf_j=4qI+UVPlh z<@&xa#Pie8#VtmwpFCW@(&XwDi-Jpo`+~^(YBnWb-R!-9A4iuR<a9f7Te_EVAHZu- z6)Dv@A*Ew-E4F13SI+T;(!op&+2HAgDt`RMldZ#{bKVXF!BGc`&=QfR50EY(mw#D8 z^-^Z#j!@m(v%O`ficK}MgD6ue4QRJ!IM#qVV=ZFU@mbRu8x<83JU6w8{`)-S5(K(T zq{OCNcBrCI4B`ebtGE9Z1&OPJ5bJ}cK!!P^mk&dd$a0@=#3C_h?)3D?SXj1<8&rll zjM}i9o1&IZuiv$&(jE^8;Q#AM`p=H{#INz|7yr7>J`-d656nmyC83Z4q26#Ni{Q?x z3x=Bn8qJ2mDFxx5`v~5Q%hs&Foazh*$gedS%+hKvbZOz&`K7CRvgqIApA(?h>Z;w! zzQe}W0sFvwL8^>H2097l%HGk#n<qoW-I~&M7!<1zmjYbxp1{%j+yQnAgufQcrk~4q zwH~$*Ayt0n!i5)mV-W-1?TqC^=@H$8vX(OV8vLc3(a*kv-}Ut!Ja()-lZW?9dF}o< zq_&QM-#0;<*1a?KYNk!;ktSThhx>5;7*c0h3vHRqg=hzQk9&T5x<87cpwuTHucd|P z>${<+m94ZCY^2CbCZ+9a3wD=9dFUgE6#}X5sww?CZGC8T>@G@GaBtiW&Jg~NRe~As zY+B@QukeoKOlrkU;jw;>lY_@+t5(7V4`lQX9%BI*PMcP_h19Ia2*P)N+SgmK42D-v zSJ&Rqp1^hVq+U-wK>7(yOX_@G(#1`O4Q&eeXEF%;jpamfapJq+T5J<xOUk<l8@L0i z5J{Q7?yc3~ybp=Rml|(xea&i}-(I{K5+k~D!$SZpbv&X#r3#A$$OWL-s-n6Px9urk zTO5QgEv<~2)i+oNsE2#<ssAiBg8<gS9QZ_%+rY-?@UHP>ayv?;<wuRVjv#?!ecQLH zvQE$*kZquNifos;)g_T`h1AK>&l|o~)peoE?|<-e?!O2Y!5l9XhZGPPa}+z}kvw{D zlGq@V6m{zh(F|&n?g65C8(qb+I<n?w>yRYx0oD*2BYe#<KP-%Qog%Yrag!3=GcSWt zEI@U01o$UkV`2<AD^b9V18Qegk5aQB8ZWD1BIzFl%NL+CAS4x-j0dVlv@}EUK}%W) zYc{%hH*856romq)rQE>j-Ea$9d-H6c;|n6_DU6gf6(bROCJF+NHAo=(R7N5(+LG8; za8uwy*}tJJQhwiS+x{aa8s%nLWb$qzgQKj|BLB!`dECj1t)<jYS0#Xfj-pxbo&*^M z(-utQ1tCg^r-cpe?|CJp2xN&Z3pKf9vDig#VFiPZL;`D6BbI_+R$1#&;U3_yA=eF3 zq7udM8+c;`5&QVj@q?Ld>hngUEN@c;{z4E^B(((>VgfskAq<0ScJ|m?NAxx=yPDe7 z&}BQT>i%5h5SMJO_3qfk*vma!mae)H1TXW_g9_b(nOITHoe-uZLnq}+HgQ+}IYz~K z7cz6;?D`R!ZHZd5S7riDEnWJTjr^~;nvh!Po+bYzr<z@I%trARp{u%rgeeco<g&)u zH!p}dgU2nH2$te<bF?=6<|JE}scOA6>2`Z)ZF9zZ<n+9S$rgA)i14WECRDx!iU0d{ zt4KbtDqqcRYx&B))sAKR=XEcz+I#mhSS8X;OEspCWK0o2``(JqLW)S?8<DIZ(OW?Y z`5n+S;n508tsYEBOgUL49z}E+40`c(bP)2)<9YvWEZV%XT<Gh>_N_2Q$#!GQ|8r>Q zE<Jq5ullM{p6#;RyRoR~jh_5$pKA(IoCR+TetQYuclG+3#nya8yJ&1V<TDutn{B}> zY;%+`3nr1V!sPSv=<V+8>dmI1eWfWms3n1vrKC-k)ROoetJ#F_?d<aS{Qgkr!>p;> z)<%6*ylOQ6%bCUt#?^($Ec3)Pb38kC)D6!RJjYcf=wgK9oMy<-K#!6P%?W}}C1OrU zejJ8(g2h%%d*F|nLOpc0A*HNr*JXeyT2K5rZpokzpaO(hY_Urku|hWj6n!5rBc!8h zWOE5Z;~A?bZB-hT6vW+sX|Xv||B(rVe)zK_*<g+kk`1CzrxDu!>%4X00g+x_Qxrul z4Olf`phPB?wKRK==X!aLIb6j?Ln*A%Yd_?dtt|6?f8^a+gP#3pvHy79VJ}&1gfHc% z&64EBcj;~5(6~^uUi8{syz_&)*2rNBLT}MqJxzsA{cI@Il0WIye-3j;@*$uRf#^fX zY59EAkoEzWPsD#+5c2VQPGo(5a<}j4eSg~DpU3y{W69EIzoKuQI;x0O(k%XCJw&I> z1+_$qBLm}kp&dGuRkJFl*yT^Fy+iN1PwZvYNq_HFy5G%)13tl{lv#oydPsZZHGA{$ zXHH?B2&~YlFMV^Ua1(vHT>;{^HtqGQdx*y0$>!yCjFPZ+I&kyfRc~d$$9D8VSsK|f z!cIYnj^x&-%Vm#soVI9mT$qSW`Svq?QOh*G?Q=AI*pmN@-?+YT&N~!?<jsv#H-~?@ zrE6WS{Wx;9Nk7~UHN}`^Pi*gq0#&%#LmA%2y06!(P7t<;)vU?P7FETp00=Gxcq0}| zW0T0}4_4X%ojuJSLc`K(A^GGQgu@3)1%<#DI>I@ti%e-lI#>KN`#17mwK6^q@6V;F zA;hItvesH;*y}zdQbc=nrFL|RUcfrZ@q+a~L-<YGQ_f-)sfMv=qcY@6XaU7H0k@iL zy=q>0U0g2d2iTERtdMXqTihLQoc=;n#TR1;+r~}Fkg>RypumDiu}0A(t6<bvH#kC+ z0hWj>3lrTxmA=j}n2m6;KsVB{CM#v*lsCwSd@8I)JAqh-0r(3|Wk&-85@2h5BEk+9 z08kc?nD>jM##pGa$@wKwz-1NiCNBhK;VmLXv9ChfDy-JY)o`3y5KF5kI+jON3u2ns zJ%d2=3ZzDeLhWH3<rptC;J`3~`XnWv35J@m((-p#`_)`U5cgT-hsmqWD%;YC(Gu)S zJWZ($IwLGN_H<THV{47#O!MbwRU{&4*U*Oa$|{#Gae;b!)6hOHj3DAvT%eLjS*w2& zVX2`<G7gPpSo?q*3Shqp_|%g*Nm9*-cq{-9lRRunQo_?lH!BtQrnwy=6YWccS9NJ< z;HK64?-lP;m;kTu96zS9i-3n=_&g8KN;X~jAOkLeYwD`WlPfYQBK!4-ho+uXcbb2a zT)z&_&K_?^SE06KbjS5RX<+SiCkqtOHX7BkL7-h4@Z=5<`8jwn%qj%PBWPTM6tN_` z>cA6%@>yUQ4}dfCIkR*5DIAbo4@wqRPlcrgAbM8)BF<5QPa^t2>;WS-6!J88XTy-i zjbfHHO=UXm`n+Jrz_Vcw(u#%0B#$bhLYxSRDoVJ^W0#lJ3@UZ9{eKtTbort3`g(Yi z%yK?%e+5|w<a<`I#egO4W*Nj}9R#a)0mg(<z-l4>(|`hm*{23jC9hyX4HG01abg|x zoX{NO#P>F`^(9cx%znEA-I$FQ-(Kzy8>rLsn?LnTNBFH{#ePpi>E!f!-?#6T7kRxI z)7yA?kGj|%==L!Ua@f%$F=t(T8j}}mGQ{}Xw{cAIJjnfCh;%ejn<I7CnMa)$t&Tb9 z(F?%`%EPA*8waUK%q??BxiT~5Z1wh;8(GIQCDYfpW960bscer;XqJv728n78)k;<D z4G@bGPo=Xlh+`!8yCl<^9{ph@I>mt^ZP6?W97=a$1AJ6t{7`t(U@tQ1uwG*|`=Hq% zX0~VNlFlQ0VMKP~hN%l$lSJ%Q><UHo(L;nx+niY{$hy9YZf8GGbJf_Z_ii=`5QN`g z|AP$u`UgTUmbO~BBXbx`Pz0hh>WyZC{HMb}X*_KZgoqh~P>qI3?mRBt+*N<ub+zUV zHH|p30Bh5+$Srzz*DdF3cRA401&-JSj~`)c-`_Q!4xNj&jPWL+@-I};xn^aRkn#&$ zV@x=kZe!$nz6u?<wy=7L>gI|I=Y!I$EA6KD2Cjqd9kz{!{d`W|ME1A@ByofN&oTTR zp56|f&)0=$d_OnrtDg7kEcK02P`MSV0|9#$(EZ*R))to2G@9yA>><tY@(k-<7Rs}} z1nP>5J-+J~9`sQBYC3#DDLg@b{1p4fD*OYFba;-5gM*snBKlNE(Is4%!FW4a9D7bP z|EhHx`^uw>snVxZ>P!BwkK9nEe!JLKhMWGmdIqsjr@Q;7iJ2KIXbno;5=r|R4OHJ( zT+CMjks-;e#XUdj>T@EWx3T;8w<m!8*Y|XP(x9S^nvN&jptFYOWb8_CU%`fHn+svh zv?NB2eM54$YV=;zQ*6dG4@4wmU86gKX=;x`%lz$TJ+9{No1vy?6>4iCINc;B{ZUUM zN<`{%!oQ6wPeVsjS08+4@$i>eIJ0YawNE|vgm}7(VT^`kefdLr;asG-Jmr8QlwT*x z1tcqqRShg{cT6l)#z&s>Msl&t91%dH7o;R3#j+5DJZla~WxxFQHvUwv2(qHW*-9H8 zG)395UxheCvXhj%H_ADqF&pODn3w`Sg1#QtCxuW{%7Q>iYhVyal#5YK=}rbLpv_XT zERvZ_Wg-VgMEM$f<tQu-NLNF9<sgF;9EV2qQ}Ye%ZDVGy;Bu{RcG|iLD7>i^Hlyzm zjKQX~uo^*Rhn=Eu_zg6S`;K##DnbN=AuOY@>7SWp_$z=Sy<Hg}5mi~Kn^no^;;+}a zMyq!cPwpEd88T+$Z1eLxmscRVX;#|G0kmaf<Aq6Cu@FYet_V7_iFwHm9cL6XnYC09 z{%8VL3M#7FU1p78gq2zN#vHabAO%*joRo^dQ*Z`0<+>1(eGfo}&m@$&J+<JTqgnPT zIfrKoz6aeM>7B4@C>|74(;*v*F~rlA%JAJzcb5cnSKe}Zhg}`aPTQFvB`ACr;rrBI z^N||T_cu!A7}eQ33ExT4NKj`>C@^OjJ9uLrfXcT(GNn|ZE~oG=*yhA=c#HIYYBQ8n z0N4(4B*bM(zOl}6x`alT3}#r6M#^E*-*vRd60;Sz91(%S9yNL0AS>?h$TnzP5e8uv z9;xeWhkiHLUcK7?oVHhbSmVjJ{qy^Gv#%5Uwn$A&;AA(FoKIGnDdP1A=1Qkr5_9Qu zW)<EHu8+qAcy5*Zu2LD@sM`7JHEmKQv>t#U`;|?4{pQYNf29Di2}{*2zvrRP;0^R0 z|BlbE4R-&p7Hd4Cod#F1^>)DU4j%o<$}yD<slb*YN|}>Mep0O_@RSMm0`E@Et=@L+ zAu_#5{_LsR>MRoQIlrq?RYd?%@O9;gf`=)qPA`p}YH42HEdEL}XJcqhm0}m)CUCSl zR0uiA<=Q`v5}v~`{Yg?UK550M)E$I^ICn3EsN<At@wD2RtQMNINwn8<e}?7d&}evu zq(_~dDga`KhA3rWohV5wz*^*3JZXYOz|(R`yRPmg@vDp0>GzhT-t5xb66Gx^O8$4r zP5r0K4!uxQRezcExXqJ+5d-RjqJ$;^fnMeTq3_$c1Bt*zf`Wpe%p&L~5pdXS8NqXR z|H^l^|LwM+q>BaJstZNNTuQfmE2nv1xL<%CzdH0^tf`l;wVkmy6mv2C3!1e&JM>&- zl`H4|P@hgVu@TwNW{lLWZ~R7JR{ffnN67Ji1uE{zrD46H?B}){(<cwIk)Ao`)Yi)X zd}Xtb)|o9g(ewB|FO%bY{T~mr?D2nYeeN!g?tygbDOn#3u#U`Brv6%`IGR{X%$JUz zYMd^H#UPijua5UMYmW_awk+7RWk+Lkc$bXK<xh^5CSj^xj<wSFsEn~B(Jkx5DXrLB znpq|vGcNl{zR+ew9f>I{m)Z*#>X)%%3klXVT{pF}ebCQLyPdaMciW-b+zV|J6jjE4 zXs28u8uNY=U@FP-db)g1i%%?PMvV<ANH)ZYSbO_Y?Iw_9!Y|-`_${@0`R-wNhyO9! zXaNTYzYkA+;}1h9y|$U_)`~clxzzxjC%gT%FX9jGf|jp;bXaOwt1V|1fNKme&b7ct zmi1W-Rhg$<0cn$!-xz*WQC)QRo_(3@-&Vu*wMzwn7AuYTM+eKVM*lOn_l(grEFkgG zxG4P)Z|okRecj$}8(mZe!XvpcSn2sx8T2Lf9!6QyO>Us+bJR;J>=yt|ylE~dfZkU` zDIz>s0jwNfhvNXNP~g3f0P<$8Qlpl%r*Y^glmY(mzB_lh=xL|b6WR(Z*4Jx)lOv@f z%rK=2o2e{M!JkEZ4HGtHTQk>Et-FB<<d{t6EdacYl`?(Oq{KrMAi{>^&35RFbeblQ zn>QlZ#vonF<%Hp&Fn2`1#~ZAeQcV13Kd?S-jTr%})~y@6^UOD0%Fzyj2HqWB2DX(y zI(C!j#0SSSO)5tFZy#!f{12dF&=&Z!ICVh?MW878bsGUn-oUYMU?KuDOCXs#rB>nv zQ0Eh)Y!;Sq9={Jj?dg`rl#7)PZn~|>U!cxNXldw!K936|{034nh9hxqszj8d#F6y# zqeUs7U39sU7Ba8e)Ho{CFpZQtK{WX;jj{fJITF`AAm1n&>6}k=AoP1pubenuCK{qJ zUB!!z{Uqdfo^j1kKw7Bv;S3MciRGwXmoj>38kEG`SW|g7uBITa-5px*d%Z~cy1Mvy zd7oCRR`$59G41QdP9}>$P+lqe(;2;iGIHV55M6U&QX+Kb3~_=*iQ4C64SjjuR9dq< z{l8loc-5dU^zvjGf4fA$B<5+v!39dp7s2hiZ@>}X3tWq7#E8GFZ!hDbbyr?|?Wt{$ zau!f0rkvJ>)d>5LC>G&(;?aK6#s}R0Rtvj-twf)Qi@TdH?)q(oii$jRe;vH=>+rl~ z^c&389C7G%xxf&pd_FRU5S!O0!GuM~Mbh-gFsc}%K~bI+QYB(1cbU(jrSK{8fsfTw zyz={bckuA<WbCAd$V+nb_}p$^r|Z+t^m6&$z1}~bO)cdO$X3qhr>HPSXUdT&2Swc! zFEUYz74-VJJ-ryYI%0L4R=j<_j>@{l+M<LrG_L%SSXsYH%A!1Z1(6*%y4hNjuY8__ zXUXg4UR!IOk~!l#nZh!z%-G^&oXV{sr<y^D^2v6Zrg1{~R~-dmd}?&5f}?b*ie+?; z>bVUm)}w-!bC(yTlg}GH$9F{LwU+4YI_&6lYk@SenFNq&5*;TLFN+Mw1sen*B@Whk zdj?QNb$ujkI;;`18sek_r>)imNGm(&__kYcQ;cB0q$KtA-#1E4`~MH(-GeE&h(xA# z%dw+)M?s-LAdr9i`N<df08VPN)X{WmPRcH6JDE<1NlFKjH7?E+A4oW5G!Nr>*}TaH z`TzA{8~Okib9Mi6vle=N<Aaeso12S+ExB+HItRN5(a3h^hIX!Upc2g4jQGLbTQb3= zRr9<H$^7lMK2JNv1e0Ys{umSvRP$MXoFC!1MU&s#{@Sl^EOXiRdCJSXO>=W=vj*M0 z(>?kqtCgL7V(aR-u5Ifk$EI-2^U4)9N^0G4F_nc_F-2)3xSV7Tk5FFtkJ>tgXm@g^ zP@qJ1ivcpk^niJ!AA!%<<0A<-l{334Q)6`_8!mXG+hq7P%4J|J*LZGtY7gu4PYlci z0`MJ&uMB@#itt~Rq9%5D{qByQ?3v0Sf`|d=)7}qY<>y<e_}KMe!xRq=zK^Gum6=M! zOwDpuJV_x5X}t4IO$noqMt48&R+b&TZgT@%i`nq6f|`qa<XNhpEJR_875|PcDoj*S zIB_Q%ndj3jFs#@@Itj*ATWh;^K7!AnLR>;NM>*o|JFD1MqdH;;iSuTqQiX6|+%cbW zoWjQh;nAG!M;gmBX<ihEQPKu^=W#O&%keoIKh;0yd@{cSWjb*rFHNJ-gm;9v=Y%FP zqh2;AJvM2!Kw?z@dIiC@LtkVEkAF}3PGcZx-6ThjUIj^<zyFns5qZFgYLi|L$f-X= zM_gvrjq8W$C6&I!TcMmZSvwJ<n86l9ajG>a29rPBcCfD)8R$3U_nb}K^O||d7-l&V zDj`V&(>TnT6iN}$8cIif-QfSS0FbfN02?qXF$L0lBF#YR!sS6)e}o=2iyC0(umCcR zX`tgKNoeYJzYiYCA>5qZz**8Ig<@iXQ-aHx032VlNoJt4--#%+#DVa$_wih~M#|}g z`neR20vP7VQKY8JhTwO;dJPx@%P}kI)jAXp<EC~N@8=aW@}+KcschQ?4<Lw@r> za6>-H_k=Up?45s8qxe{HlF#uaC0rldL=(emY=O6RQG>wiGn6BN9L6ImB4?-?ZM2+t z(Xl)wEqBoJbqRS83H3+Mh_F1y4W?;91N@3cEfSzg|J4v^NxX_&s!$%iEwLvl5;AR# z_+Ts17XLdwA5|i2`xL(Kmf?QO&kcu|ZW2kAlTN%cUwtus2U#=M%*P03PAV<+hgHW} zooF#l`tF2`X=CeyAX}si4jAJNTUE%e3f9a~t8Y%L09ghzGE4-L>v7#wUQEBn?J(k~ zk&<?EHh*@xz217d$n*32uAO<d%pNw!SzZ@M*H=A=tbGA-ApgRIwAYy4lpJ&fjcQQ= zDC0SBnDrx9R<g6BLfj=Y&`$#dbd7WwRH1_$43`iwSf5Jw@7mg|?q8_om!bIy0_UyN z_Ga_v@^x8jadlp033t79eWZQ(nny+^o>aoBSzT`0S|d_eY_L|d_gkZ7(`rd>wB+QY z7h~RyVIjY_;-(u(hoAPRAx{@&Ex>>@;u>0dvcIyjtaM_@%DCH9QMM&tmxJbBE^S&` z<nz$U@wKnWIM=GIuYbT+I9x8&3m^lKaA<aJCg*<MX4PJ~_I*gVXWzCB-WZvU&=^rr zR@SlzwIFB?KTMKiWDA53+ARl9$qi9bQo3hv1jQ+f5&I;Zem^uR;AZSjWui%$QhsAQ zVmGKxl!@SiWbOLXfD?OD0IUUZ$L?+3urZ7%I#;2-1T2{xC8HccgUtqn8Ms%~aA*Gk z-8D|{k(z^p5oQ_{Oi{n4D|{Pf#YTy(37SZ}EJP3zws={8-t}?K3vfEX5i`(+4h$fd z2gC2vg9n3eUj!;Crj7FEbtT!`_;bIl*m;gCw<!sJi9zLKZBgy-`|yE(vqMNQ!DMZ# zs*3&_&7Yak-iWm=o5=-uri-~|*Z?s%HoH1V#Kniz<HL1k$$*YHWNWU>$)i<USbK8u zdvNvR&8hx=_u<sl@y*zxQFlFZIoey+wx6)@=DL`h>1ioxXlDzZh5{{4W#e>>F<Ul? zC`%M?v|3jPrweG}aW9^=^44gfw2#zkzB;5zRl50S@dmun_)k{s%5g0{=VD8rl#?4X zOiScsSB5QXMSZ1Gk#F1}?_z}4J{FfbetPAt<q6zWPU}nY>vO^>4IT7ogLF(O0j>^i zwA4~!H_8=xt3$m7)}`|&nD4hd9y0*~nDV7z`x$_!u~Sp8Uvs!dMLjQi^o6wS=YR)Z zX4N2?S5(a^rMSm1mTfQv-pw{XG2+otY#v!g=y&5=g;|PqJ>YPIeHb5YLMcE!HBlop z54hqGaMsV2x>x35A2Q(Z^Q+nWmNOurmJk*uep3&I$jcA}(W!$7Q7NoWCiIMl5SQ?u znXB@tG_W8Hb1USvjzeOToz*Ar5qTrIylWTDK~W)FLLo(SlcFt6|5>_wLj(^l$O)I{ zzFA3Pmt@IU295l{j6_wIxoZRE_t@5uf+Ga&VTWs{y%1cB2>xW2@Xp+IPXL7kSG;!; zjj?8^O7g%vCt6DlEVR<<31gBWnU+{i5XYWhb$-N=qBKq{K(aY7;+H4#A|8U7)edF1 zG+fxALqbvg!+P#((hI)5a5#jrMkkORtjr{Mfr13NB;5$d56i#|{!}Lrc3i6;M<$OK z<rYIkk-3`<<T5XSizbSQctkSBOuv36Rn*Frn|U~32;nJW*>e;kRex+yF;RQ>PcEgZ zeAvG@Wkcl@);89v`JsA*g>`UuT4e5-u&o%VU_ML^xnA8$uW!7tNGuIQ*SJ_5fQ1yc zBH`FAFyA79Q?R2};8{W_2dVfgefZA9sIj3&%_ronKPHCtbo@zY_(qO<s8Rpgkw74S z2tSrrUr?w7f|(<yc!AOLd2lgDjLU=$8>5Q+R(78kA7rW>BLXMD3cv&;HtP7aOF5Th z21LTcDU4>V&YG$@@8CPwz88Hf%?IAeTgHp8Ado^2y6`O`J&*3Y*3vTk&Hx;P+3)?b zEP26;@nKdZYJ@;m0EV(x&MWM1Rc&hV^Y}cI6Kte!pyn*{+ZdH^pyFnfc5J+bABy+i z(2XM_&OFZsDlZH2z@^#c^@dAoS10%2IA|2VHl2M-&hrA?R_7^$*Ftr?752P;DGB`Z z3D)Di0yk1wM_&iqb8EY=ntE`vCCPZz+aG<WRg)imwX)l-L$f9&Q|~PvCil5hA5D&S z7T#OaVm-`-#f>1-XC>FUrR6I<<vQI?Q?Zrycf!6KHfa;J{&s5UP|J)einc6J;yjTV zo<TjP*c{Y_FS4D-lIX;1dI#tE7xin9to_l*(xgD+3r&2skzf`i@Ab8Q-rmpqORtA4 z!gT(<VM^!r|J`qqcK*)*#ok>$UJGx+O@|UROB6?=SVKVtO%p)+Ti}}>+YclaR<#S4 zfs9S5Du#6d{(N(T7jF+lO$D=1&%$tmcxu4CR6g$`ry8IeccUKH-4y4V{rm))NDMRP zk=J<ADVBjn8=G|*uW_@TQLMy6*tok|vUI;kG3ppT?pQqD@AJ8RGdzaTb^{L|pIug& z0N&~{46mbdyhUtd3&j$8CJ@t*DQlnIg2+6!Q33oI95#n%bf;<6!#CoBPN!M76E1yX z>5TrQtha}!*TdE8`QGT4aoS6dR@*t`s-s+eF^rvl9!Aq-Y2>N3R&Mmdq5xo4SfOP( zArn8&WP|l72qJ{CBByDQdQ)wop{JS!cT;>%LX*s~IK`VJ1`R&oxHfw%UJ!=uUu-B3 zCejAq0n0tXpQirN7>UVIT;v`Pl3(S7HurWMvh8FC|6BUFIRCsI-7l=M1~F*38LkT| z4U`ZANgcw_NtE^I>Rzchwrp%(u2`TS^+OO=sa3AoJnMr9gkMxX9YLpYdc5QNF!Dv` zz-}!hc`uV^E~0KaFi5N6Hj<Gi94C`N2?bmOlUGpIb5fLa;5lj9R*nM9p2Z!oUHuhA z4KOg(;ABlY0sGXx$B`A|Y^6`N1Dm`n^L{yw$J+@UcwRQFT37?*ZQ+c6XT4uAzCJ^n zXiUUOhT(}^FI?z($z=i~V?G0E-t%=qOF<S8s`nW1u#wG?Pa~J+D_$>F+6(C~aBk%b z)~27C*>0<7#kI%bGw{P)AgGhdEQ<Il&o*jODAnP19G{KCOs4$XtFc>6$N;(Sz!j^O zL`S>}y&TDex)~0F$#je|_RmD*@st1n_Ur_OH}wPA@kGd=BWPCepHdB#kJV11tIEpj z>t74^D5X{K{Uw-yEa7!m0w@<>E1fErp<!E@31Jd-!I<Ynsx~(l^#1&+P>Q|4sI95Q zhYN(t)enM6omV<v77KZ`Tz6!JGnfL&wW_JV2Y-=X7l807V9I#Qa{WHPyMvFn+Nn5O z;66j9-4n7u@U~6#$Z?jfAA|}-NX{+`q5jTOJ?2=Ot$_?>EtD26Qg<ooxG!_ofcxx$ z&WvEjS&qSz^qG=CF76|nBH&tD51cR?d?}7n#eCMlsF6~Z{C>v98>#kC8O1p<rwK#A zw!9NfII<DcO#`u^Lk9@@`A4WC8QF{dl>>6Gt~%EO?bFB9^K*&`+U}L;9e?P3kYSYD z*w)@B6>;xxYM@7XfPYe5N*JW0jMQ=zs3+_GQJMUp1Q`)~?jKA_#z#@Ah3E<FeH^~` z+e!v0Cx?Q=MthmYnD;Pq!My8HH`vWr2PQw;P#;2p>NOv#Akxt$LwyO`UDORUzV_Iu z|7Z2~+x*u}ygdLPC&$<Ix|g-+E-8**B*(WGDOtS#x4}IFn*2np5~;7?0f`<@89AMt zc+i{`2{QR~aZO)<b6c*FrTX2~+wFbf;DUU)hnk>#<G@z+h@Rhk267k2HMBFz`*rT? z0NHE_md}u`IVMT%o@+fwWq;u9?t72fP)EY^+dK6Qzn9I7Ws^cWW6*=4i%_!QWOY?N zy78vx+v#ne`Wj_{(p3bPUSSaC@F0sDxM3F2OrQ`c1o~ono_G-)%4g!=AWA@sAz7$+ zJHps80fuH3>IYjmoPj#6A9iep&-YNHe6HW|W>bf^IxgbZ|9Sj=RSPKMzYm042aIk6 zPzC}7Xo?Lah(g;(@Q1zJotFsM#)Q3K*=P0M9UWA^Bao-bUDaY9oIhHG&@z=B9hL8! z&b^JO|EHL#iSd4MD|;qkl(76ticzDxbekxFH<Z=G3xq!yb#44>4$#acxkF@9MPqY+ z_xygF4p$c9-b668X5;4K;^N_f;j`)>V6N)hlf}2Wbff#R7bezSpmo3B@Gm@Biptk7 zQtiyrxNIs;?fs~4dxjrpbV*Fg!*}v4;rMFmvVu47i?LHHThE7!x09zcJI9}=r%kH~ zKYWO(+4ovS0!=2~1lwZ4Z~YBd^rFeFNCKAxW@}c`mO}2L!8L3DtennbAEE@;l||J0 z&T#2_!D)rfoJ(EWqg`H9HRX*2j0?lJ$oBCAU(OtSCfD!4wT<++=9slM=gX-($!hq! zilQ!4wVF&#|MW(VPEL<47816~zbS*N*g&<0dShUWEq0=Y`{VX|DLTAArL8$;v5n!E zQd(QKuz~K|Dn3oAr$6*|G#)EmiSkiyiw}O1-Im(8=??nQXuN!%gaIpUG@MZUgiT&4 zV9JR!Sg^)HBi<L+pyuGV2AfG54#5Jx3dAVHE7;YR_S)bGsk#hk>!-CbwjF%79o)%N z24;YxJ>_&1ZXKH054)7gL4jwk$nr4003aIl-jFycL+qjNvFDQH4?)ech|RgFcHTi0 z!p;;v8xt>u7Q)u&N_A9Y%UoUhb0qWSKYUJFBz2hYlZKXVAGt|G8m5D4d5Bprxibp` ztSgCLRJM;DCX_U5ewN4{6=UBO($!cc2>>R`6{Mybf@Bujr)*rTNRX^=3E~2<p!zfk zz2SzG;+#;BGm@8qTox2gn7I~==ld67jT{f2c!NV=FF{mW^-0H|_Y<#(5a-cca|3BC z1?=xO2(yHq_Znptgc*|HAE=b<X9qt6$Dt%(TQR6uLzvGOd9rx?Eq8rb0IhN$+q7W^ zp4~J?F#u7{=?1+0q-YRkI0O@<WfINzN0pKmRyF8y%^1Ib2w8d|d)LQiw9S7QA_y7T z*zWjSd_mrK0$!3{6YZVIkTMlRrj;VEy%pkEnZRJLvHaql(PGFzCpH)!@9S<4G^I5~ zshV|qP?1AACu522U6_w}lx)At_k>@c$9`!dj9McywE&HKnX$f2WV0mYE{QNPs8-Il zE5lWVpWr1S_GVqbjAV2`U9D+@qBKp6@ejQ}CBtWhI12k|TZq`<6YXyQ>Iw-2Q12B3 z7DhJ>5yxo{Jx)LJ{oo!&K6XJ`tE&-monvT7;xRF45E~n;XDt(;8N}sO3o<@m&!^OU zx8vyTFRyQQ{9jjDx$oYwK;_k(ju1tdGXY?e9w|vpp<2`ZLw%(W<fH;!cIhfb=y0t> z3J{Ab08@#hQ#9(KEIIsM+~%g;UwYCgwt7wf@m_uDFUflz{=@#%@01u_*p>R2?W*Jd zdjHrj=KYBU#I^Pqo!d#i*ucm-HkchBd+#I}e(a9>i=~ERM2R95RPehKKuRPD{5l;_ zU<iW(rVVMjSaYK!w;kSD&iBiR1^MroHXix+f~vIRy{tF?$0NfqPhrIT4+t`$A)-M@ zXq=3nqw*6_O=8T7WRyq*k>t5;qxP)kI%>LG)fQN69L!QgN4oRtR9*F{+_~2oAs_x~ z7VfHog$OG?Zo7uQdI!=m*&OA-T$B+9##zI0ILFMV7{kr|a71_W4!q^`@%s5<Asq&6 z;HJm_m!ICav@f*H#m|o)KVoifp7g5#td6{R0zBVyPB?9QuzLxV4?XjxJ@&fU$`_3s zdP?KrvS;RUD|4@*<VCy!Sa+$cn5|OFI(l!QP=9dx^3(d%t%?$5rB!Pz^x^mA)~|{- zb*;D5IzQXak79e4Yr-c$K{Sa6c_CO?X^~$>-dupm9cGDLts111c#{lOT1-5@#Z`Kd z&hz-|y4+B5?4_Q~rsHBY$}&7<UioI_IgsbTw>$#wN^fjjd*o@~SS)k%s`?8O7zB|O zvfH{B6!8T!Wn6Ua)=69F_4|1aNB8czBt{X(E^Bn!70>&*t6W8}Yx>i&#I-j1U@N@w zP`dg9+KY-`qoMlryH}P-q(LrZF?1{*fo{MX?elNQJxsZZXv0$#LIT(1f%MQUpw}4T zO_dHMj!&AY$<RA^9@BfcluOpd=c48*xY9==!_t6@P8$fqjhe2VjCg5`Sr`~&#s?ZR zjervvW<0LmB-X;6@d(2yA?KKOD3iR)VEhRp1}jecv2r{iqU|baIXbCv`~UHDPT`eB z+qO={c2coz+qPG1I~Chzg%xvEY&#X(wrv|X`|NY>>wKKw9DVlDdux9~yzBm&Zxc`8 zC_3m}_bo)}SJM7Uu17{o=B`ZzES5TpkxfQ{f8@{YZOc1iJKum*beo!JoD*h994yPA zq(0Ybl>tcV*_c2`whdtUg-s0CDjFlgB>OcH?&9jBOh6VApupPfUADTxCtx*@MmXBa z3Y=?^EE?+2JyR1F`vdcqg~KoM-9cB@N25?;xSuKi^b^q1Wb5W8MlanClI&oE4K>*2 zNqdk4q5fD89CA8OZ9W|V@^VV{eWg%Q1epXq#>*)EYV9+7XVo9!;djR`+q0cdF{h*} zFM#$EA(pjV*|Sb;L^}N&8k~cnS{f+DQ}l>}fzcB<7u2)qB#|rTB2|&+{D+xo<DJ%N zUOy(kc5)FgCI^s_@M8cn*L;*w%-6wT&cGEsZ~v2?3ZXni#*&@jjMa=pX?}-D9coxi zdb99<e`LXtw4-<CT})fv%pS??=%56^VXc~`D_I0{gJ4R;crs6r<4hjJ=v-z7REVED zka*Lt=&#VLuc(pWugvS__w#V%|EZBA<wHfT%8(GQu;hQmQ6m!nO=rNBYlFvgq>G<{ zLuhM;6Xq>z#xDQ7MdZiU&@T5ol$MpR_4E8i5s6TcA9_0c@qzuyyZJI(zx`vPsAC!- zI1JgJfNWEUpg{_m4;6d-R9|KyBGD^;76p{C+j?HE#v;Xuu6^Dopo}qcAm+@XxjgD3 zw|XkojJb=KTUXb>k(33PnKTC_*tIggcxUi3Pdl<CKkCsmA-(8?J6l%W5h1;7R;iQf z$b@CpGLD!^sW0<_rQ6(c5Pq!|uon|yJY{3C;H5h8>8Sxo?feA5k9~W6;r_2E{pZ&B zU6k5B3?o=%0*GaXEeps{p)qYWiE0Dc1!D~QauAHUjp5)xl~I3;aNQZMe(zQJr(2s> z3E*Ie^YdVwDhCM~&Dz%hdf)7q?2EzgkUkUMs?llftrmfghml0fEUwI!G~wj3vbOeL zrDE?6Dhv!`Ah>N;6emV^@fgI~)hgqSt1GRKD@O)?Zxc%sghRjF-8Oc1c3gNiye$-w zOlw>zcDnU7ziQRf7=Hkl;?^6ZI`VZLI_l-m?hQUOIoTe6+%T(c(aNT%Cq-2$zMn1! zszeE857apT^&hPS46?G=>-Xk>D<jb>E9VW|c5#`}M;3Qg+=|f*jmnH(3pQKnqtDXw zh_DYrF98l2cr^q~5<wk~>jJP9k~cmwz15@TkCY=I`sqdCYKH9bR5yRk#91us|7NF7 z<y<Nd#@RZORd+@IV;1`mtwy)%R#aG@*wX*>DK5)?s!NyCLPyRjPD8KfY>OUvf3o;} zwY7==Thiw3?qIIDRCoyMJBg}O!N$h+DEjAbr}LCy*sLB@(PTCS)RQEPA3I!6c%EvW zOKf*tzaL6y2rRl}gG`p<(UsEf3NoYP>&hx3f4n!$v|PSniB!>2%7ir9`Y+O&Gpv6Q zlv%_0Q*X-BcaC^neTKU<nyIoV;HF09^<@5ROAcz2fJx#)UfJSj@+X!NX&I4ohGSk; z9*8rKi`tEzPGl&pz{{i;DPAv@k;2ckc1_MvNe74J4$?~;f7fF;q<$RitQtxGx-qO4 zbc5sb#MouUixLf`#~3J$FsFbaQYj^lkC$aCSHqze6bgS(dj~AvJaW0Kk$93#FeYd% z?T}zWt5;m66hic6V4Y<~I~CQ1pJN5pb}lI8{y<kR%Mn_$=arhB(*~I?t6Nbz7jnpr z$)e!DnjhZJm}fa$RXUJHg?ND-7-~XPb&8ONuiQ+JzpaZs|3ut;X+qGACV|8Tt1(=; zz%zClSdZP&^cupH3(7PV43h@CRNDPq;N^UOL$Z$@(%`he2f)Li4IT(V(nQuCKxGBF z;8Gq|X&yn&i|^cNTF7QfT~?MSvr|Ky;df}flcdX!COT5u31GjPo0d6G?B5LA{X?Dk zUEdeV5S5mma_1_=?TQa>k73x)p+HnZWb0BnSz1N|k|DBfrWQZy<ELC3fwO?&;Snos zJWM_zW<~#LtZx&8_4j1;QU`cbUdg}S=6&5+t=hc(lxJ-D&=wG)ClG{OzhD~@w!{Y+ zdy*dGTEVVG@%;|~p+gzpkMQr$x(X!#4MX+kxg=4v<;T>M>GRZU8wXhp+{Xj!x~tex z2@g%QJC`%;Wei&IS5ejxt~~0x!ovLap`$6|7J1;Md2P!mgAm!YA(k`#bbsrYM_SaH z9rP6Rb$;qZ5_mbDW3<28S}U7cyZMJVnAUtnu)Z$H<@JhIn5Uy}n2drdzYmH~9?*e9 z98v@A=Yi^`W+mJ=D<{_n+uL(Q4|bCunb;uLJ)i&bBV|HX;pBLPvACYp^-89GuW4@! ziNwqO%Y@}J{HiPJ!Z{_JmjGtrM}pNxdaM;8AM1KNsdAH*T@|@z+8MS)>F~>R3yx!O zaqPor59fgIH+9QO$etzrT<l>u&e~nz_iw_F<*Z!!t>xCB`ZkqQ#s3|P@j86NtU`|* zE!?GNkYo}dcqf5OsNJDIIITc=B?8!}RbDvvk&0yTp<jNS=q^LYi{(=%c*U=7ctSj_ z>uJ{!iBW@&!4wlo1?ejH9h{G6J9pJH2vx6rhrY90H`~Vyk9)})UY0jy49h9L^KT(C zOy3uJwRp{M9oF|+d_3xGt_z~EPjNO6Wf};)Js#!y@$scm4Jd_fY-|)O=4`IC&ZR0& zCFe{nWr*jJ1;oi7w7iO>c#@y_o(1Q4PGFS!@T18bINK&7cG)K5ARLF`Io3}T{!V!< z3HP|I>O!)rwLPSKxGCW0(NZY76MQ;KT7s(Y8`yNY`ZYrr=Yw|dhz6`AL2zM?DKb5E zVV;MU0{3X!y=4=mi*=0}@KVq^Rk?W+@gv*^OKG_L#+id}V4<B468`)0`Vzj6WRO77 z&nNsmMEJW<Lg$~J%9|-`Qt2FbQ7K(l(fW$#QG0mSmLpGD->I?1|8+R~&*c*jtJU29 zQD(#U`nSL}uN`*|0eezvVl$QZbuSTxQ$&)nMx*c`(KO!S{E#qUJG~^9`unUhV#HGo zepNAz8e3T20WDp9aR<KID>@<FfK{TGfy1^OLq8HGFwbe+5LErwhY~k1be;q{4}HrL z5<r0#DkI(1m0RzdZ_W*(8;^Txgenm^;Jw}2b2aKH8OK>#y!J63t;*JFg{=AYy0VO} z?R@idPOtAG3#GN*_PkR7U&F>d-pjJ5qQd#Tca1JrTP&$6qQ$!G)dWdYbl4G`5uRRO zjDmp4bUrlhDul$ZG+XH(kg}w(m;_PSPkh_G^agL=BhN9SxFET?5{yc6Gx-joKg+7` zTo5Yh&W1D|yFzXQDGq=hHMOO(viTadd_aa8`*u(slA01gS)sKGNQ;Lt2-T>3Y*Z-j z3lm)0^BJEQm1!$0Ui5ABHK=t_?+%HO-1ApLUj^^7MI@4;)kB372cvrHz3E=b!snUR zs(KqpgHjNDwYBlKak28b_HWR#M{kW=c~C5_YnDPB??Dx}-Nk+pn1}VXVu94DD(J^t zBNr;SgbQ+E+Anx|?{K9vkenwtn=ajE7KAKfYDV~}Ga{U94}Q?|)6y??Vj@vlt>h02 zkPjTX8k`^-KEXjJ1+8_Kv+~!F@fl3ddshAsrDP5MWAT^_M5l=IH?|28jPh>q`8zGX ztBZT{RpXyYk5F@Tuznm-25YPo*rDVPh7>Zo(Fp9GJeDjp3^S2VE}+A}a{<<=)efhn z@LwaAFiZ~(g+Fp3io@Dxqr{J3T8DVP6XrqPTP?a4q*=&O7l=yzI<WD8L~<PfbNSo> z3pkSEk3Kd$<$bU~%mTY@#f@HTLsj*z2OioZyl~MX^(5D-8t8Qb+x6Gem#198&w?^Y zjpLecuhmoIMh8EE!<8lphV^-jR!dysq#So&9sNiiR9hffr+I>a6baSTo`>r|wW1-e zkwS`^pg4p9O`i{0j31RIvk1r7-pZ$o@9jGw4tMj%PTx{4-<tQ0sDdO{Qk$pypBkB! z@#9`pt|(GU{M5=wJ~mM)k`+++<9>7@k_b;v8N@YW68r80T#f>Jf)YTL3@cV*cKMcm z7neZR#d@bd0^GDr>A(LiWE0<f0<6I!XZKD8Xh0NLVc`#DWR(T5-7xe?srR9*(F8Qq zpF$Btvt`Ng%aQor?niL^SG;HTvob`0={&DE>57WM`n#L)yU(0hkWQ=2Caa~Ad_KX( z7tdK7mmlpB)Xj{4%9Yu1Lg39^-LBsmfAt7VZDGlDwTk%V8DDMsoZT^Yy??el{6_Rg zCXp|m3*X}7<Kjw_qtKP(0l|+RlW}IeY2Nhs^?zD`j%(qnXJGj0-Rl+9tLImIRv*Kc zKEU^q5JA4rmm2$~2<rC`O%0$Ro&~#+wanpSkxuIki{HAj5YA}Dr5xa1YkhdPa7Ae` zC+_}jaAVBan_F4&abw}n$Y!q>uZN{66Im`xQvb77unamEEI-$jI4ol7$x}><>aAS= z;}p9BtY*x3WnpY!xA#&l6$oAJ(zlS@x5Me39#D6QM1Z6|a`*Z;cf$BRnMS+Kke?<? zlelVcvYITS{O$j7^BI2CQQMgfMi!17&#tg@3lOX4ie>)f(0JqhI)C#jr1x6N`P%tO zN#}gs6oy?bXG?^pD`dxrZ!h|bIjqt#wrmTeRfd*?*LfV>G3(7o>bto_`jjv#l(Ji5 zMqPcgjK$=Rjf#7wdQ1(B=`Ei`0RbR5m^pd<TLflr+{9)sb!bQjFpRt;mS(az2eqgR z{H*zojUELYAKT87K}d3`a23g5M}sOFN$=xRMM>PC8&z824y8N`MBph5-Wao~uw(qN zCg%&*9KhK`yp6ijzQHMM?^JUpu8qy6#{1YdT_>7MbA*189Pu$WB;zgSi>yQ^mw<Rc z&SSo65a3ee_S^RAJ3HpHYGKY?A!a6yWh!7Y_;nw1jCU`f`o!D}%Zbbat4J#@Cp;AL zE&}Z>v8>`^dW;hruzk$uXGz!6Ag{J3^JleqzA2xEjm>mFR3>W<Wg16zU708gSv$@A zf%`Uo0p}^Tvd;+5lC<NB*ke3}ndo~AtSyF}BEq8Lm7y02N&E(~^LMu1Rc!_;I3gv+ z;VM?}!*mLB;LE<G!!(#rD_KZKEZhM@Rrr!IuCY(e(w4-HRa}1dR{UT04PZYAwh&HQ zocp{X=pHv%VjL`{A){itBFhPsSO6`X1EQmijaxE(L{Ox3J4i~w>H@moG`g2t^2juz zl5Equ&^5582icek4wo$mDmJKoGvEf_)7liC4XB~DFrYv*;H2iTk#;V(+4(UO?2RPQ z?&@w(>Yuu&1z6bJ@QxNF>~oX5LRZ0L*BGYuYc|UxImuZWM|LCBIl@QQuaL2cHDhUs zs3Owjc!Wzxf0L0>{i8ePuuZE->@s0YF>ErK+Ei+hYa)H1Kmi}XLP4?#OG}q;2|%TR zw0I?>t*D1bGJ9u>)bFxW);6VAluJI2ANxFQYif#D(F)a2rvOZ29t&bEf1mK`niK$g z>)ofv+eCEJ4Wve%2;}*=i@88PcEzP;SR!VWyF+63Ov098DX}1JDR(IH34D}n7FVut zJcf`&`ZCzWJAPq-v!vixgY>hHytY>C<CQ;#kGs#a>wWPG=2SHIfVA^9au&~|^bCoQ zbZQHJzDI(qzNf!`3>Y}1t?<LI28)8(!YmSnc&w^gwWjL_Da-7*Ts#5a+vD%vvZ{(O zR22H=r?<u2ngoW#&Ko;xZT8?xUIT>807*HWb)>i!QGcDv3)(x2AB4&$h%7Q{O<n{E zGBms0MT?uU_o1KKQHML;(g`H-Du`cwB&yZ^dd$^B)>FsS3Lf`=kn~kb*d|TU=F8or zN$Mh-1u{Atn<xAChK%8YBR2YdKdMWUJb(Tp+w5}rELP9ed-=HB>>0}4^!K>i$n}4} zbh$TW!@(ycM1l<N>+92RUNYv=c6|mI-_HiFmnHqQuF;R0xA}Hf^=JQ)b)&X$lvj~Y zRTr+*m9N&n#OOFVP~5*s*{`$BZ5p>-;&FwY+d3`jj8pk|RP5E*o2!U(ofas&)B5o7 z;=oZ1@0;06+S&Vt+&<g#dGeHhoVd7g$RD|CgR|d_WLAbi_bW7Dq!EyJ I0man?l zH4RZxLVaXIlD7UtJGN1ICs#e;@$tS8%vq)70`izWeB9ap<K1AC31pHO6y|s^7T_iP z9fsupd^p(D_O!DR!>HN53lVRU0#;en<NHZ2cE>27>R&8FBmU(QYA!(dIU>B*5tWE$ zmi-Wu9>sDt7KGbYH2@aIeU{diQs{%H18>#EZ=EZQm;6^g(&(Cq2r&j?2%H2e_yum9 zT{6ncvkpWlhy<##@%Wc~2e@C;+a$h*u50z5!#P2_GKuI{pqa#E6PCGf#BAN@j=k?r zx9S+12>7m2UVK*XqrIXUUX3wRy2^QY4_`wv!Z#kIh^u=hxBeFVExwd9Yo_YR!K3h# zKXjq6m9vR4y{d!^-i6%g6}urD8y|~-*yg9b3>5vCH*DSdG?P`r8(M2Rjj%6^?1^qU z^(?i+A1YFuc%7m0g7XUO5(e~>;|8}u4vG?FXB`Y=kmzAyj0NNTDAX;WfstHwT}p7Z zIg0H;fO%Y5OaqPNa*NC?OQ%NV5@uU|a7FsCi-K!XyiysElvO)^I_@6CQE_i2qQ#=k zF5wjYcqf%!kF{g6MiR^~foY=g(*5Fm^)q|z&ENI?Ku~FMwane_6~4{ZR0=;e)X<ma z@3i;>%Lj?0_XsDXxM8?n21?L*s?>7r$ONiJo#+lQuUm`ashkW+b@nj{T*CS!ka<S! z29wk*=vyL;4jI{3>xdb&udjV*WPRe!&Gk!KA(+=&Ibd6iv$h^jQBn#djkYR=7;nA9 z_kJW8DGt)1)3@A%envVd(C_|2!y}joXPOy}+0aGES!@fFnZeSD&GU$j9v~TZhTT8% zTQ(lk`1+g{rl_y+hKxxV*gQWk6Q&Ws0TV;9z)Z5FJmyK9WjXjoW0KLPjPgMhP;-ky z;s69k{Ou~dz{5+Im*km^VP_oRG*2q-HzW_C?mosffG%H_DV2Th!-Cl5$q(06D&JYk zGI+k_Rb5~2&EXYvM<4&2VJcl+z|j#?)MSfwcKM)|VOWB@01UVVzD&%Eg)0@~#=$b) zHw7vIl!a@7;;(M;dEQIS?Rd)MT>Z*#SmbTztorvgV|ssfzi*?EDnrT50)e+$i-nN* zJCwbNWYp;(ozR<$vX2a^e~1DLpuVfzBR<^Nd$<`kX6h}wqgHLhlY*~!`0wlS*z(sE zEbMnP_8sf~AJ4zu|HNr#U%6&!T5W)%35XQJ0w9Qq*}Kt_p$MKK-XZ;Pzk-{Ih}8hd zG!QdwLZ$yy96B~P(uJSawU%l{LIX&EuL5L=*&E}NlauFJ-k03CAYN#h%l%&B)$JSp zTqoylD|>}nUxm(YY=2+Hid_l>q5;rt2}XY=Hf>)R86K*1Vj=SA3OhW{I{VHz{aT(j zrUbL)DEs#I_Wb_&yS!OCI4IUL%LfZHBI>@3P%07*lGnzCRPeXQ95^uc-z6Mi+<OA7 z_it%CbUnOILe`&)^d_ncfi0yn{n-@><R_+eOQ^dU$POsysFq+yzT?r>Jmoo)WjADm zF%-cwb3b4dk;3=tDffmfUVL~M#`20npNiy*A`rV>7HfGsBR2%S?fjX>nkwydRM6a1 zxR46~BK{$oEs6qXV{m%pIGtB;AAv}*sEX@7BiHvOs<#LS^t-lh0yyt}UQSDZy(xhg z9~&E5Y>_IE&7auQct}OBV|$r`3J1mEQ`lzy)D@qqAg|>P13$06=I)&5Uyk2rp1_UR zYLyNi1vG6&XL0SU(-5r5;cD`OtBYUYZzt{n{bT%iN#GWHqR{EiJ>hj_KbVJ&6$)k- zOHN#hgqG<>yT7QWZO~_Sg&OY9yHc9wPxNQju+SgoV}ZQ45Oceqq46^99Lxy5BhUP@ zwTuLm>2xQW&19$IDUf@Pf7<Arkc14;3%A+Z6PTG0dTyZc&{}^;4Z|><M*yQTHPJ{V zsj2_K3HZn{wi1Wz@)<nk=w_Dq)cNb~BWb-hQRfgLM$Hs3laVnxd88+TI$7e4dg|<e zooP>B%uQn%*P^?z{B;4viYCjDE2%Qhw<1S-j5Ws4(zp+y*sU?Ovd&LbGX%dvO}3-| z!QThNOq0O9ORteqqu!KVLopty31kIA*MUP%(my2>qLQq_mm&y7(O_akVdVu%Uz4nY zeYiss2l7jT=z^vy_MslevXf`=J-(4(Z~|+DQKfa!QnE@+)1$IC7v5INwQMRoB@C3L zsFAk(Ean9(k66un!SIOfQlV#jV3xcm_W6`jlHSN~J%l|{rY%aQogWw*=+p3#is+b( zE2#r3h^VlEO>u)&)t)|4$PMgV2*h~}1*#1Fi9GR?BK}U2$rS*3pm-vT9X*b`bw*>v zs>8JxS{CWdX$;l_Vi0CV=|*ouRxKcY<6~*-<9cs{R^w}IQ^4b{ZK7%9U&6HswGTDS zFnQ`h8KOksMhv`hU0DD!hL?cT4lFLZwF!Caz$u&H(DoR2wSg1_Ce@Y3FXrS?ta4U# zJaJTr1;`{$F@cjG^NGpTe8p&_ggYf!5#iyG(LRw}^obpU(m*BpAR;gC<X&Tic%nqn zH4drBJ-*X!s{&}h=QW^{enXS~poJY8Bf!Pr<l+%=@E@O&QYz3Y-h4SiGP$lCTy73W zhU7(`t_c|-q2wk$i3kCDHY$oLVz&Sdf-3WmQ0_B?n)vKr;74`w)6|{M)9BZDp%0or zqg2FRtj^vLAw1z`Wz_mxS=FJ;{Po`=tySxj3ae&qhG2a{>+HF%fCy+gfxOT#EXdv# zj>!BTu*}<p?KHAorMj`+(W>Ngm;T2%zOjK$hpw)Vne5BP#&T>7k@x>bSnB-`#-y?h zu))8VUVF#HVHg+`j7)SBUl&Mj(4B}t+l5U0XgY+62~F-)ArxWaeeUU*_2}Xb$oIB) z^`_uJ7AD~~zU+;zeLKmhI(42hfe~V~(Hd*hZfvc+yu3;~<2;yIT~^ivCOtN4DO22L zkQM&ypwHlu%yl*CxzWXTji#!xZ|2S2e0fje&6OVnN+P*GetJA#xNmK3b~Sc(b~Zkk zkID?T4Dju~$1q;=N%`(14VnuvI$1TEV$x-;;~j8(o~l4TixWo4M$Y=*jI48qSTLLx zY=~Lrtw3BhDJ<`iPyu;LH*|wTbPQCjW!0S~-?Ct4_JbxZ7Ou$%bFv=Zf_n^IT=<sP zu6|R7Cnaq(&aD~Ta{#X2fHOTV9Qi39EWB8X^$QOT-obh#b7brd#w8Y1?3x_kWRHe! z(bIJ_@r4zG?|4b_#y^EmiUwbXUZ%o93}ePF>x77L1n;k^Q<w(+4`$7CmGmyaNRftD z{r<dzuy>Dmzq`Iz>7J5_jjb=gZvaD~diEs4OL;r*m+RCWKmqD{3pobN8f@4D8?oxc zl>P)e0EsSysG)k)NByx4zo+!TyiYaRNS&$zhR+i6?`+IY<S3MlCp|#DYvJ(R?{7Kw zh`b7!Enh7K5&m4`sk<MM0c?UaZu6#p!qS&hRA72?z1a2QRbim2MRwV@S@07~TO&dL z=R_!k6l$1LBGyS^<j?Q`BBB;*aw+JNIjNp9UR5%vM07OrqVDee8o~u=Ay2JL!EF7H zOi%H$iUP`HwhkY9O)H|jVcTlYw@5Sf(z`grU=oQV=4%c%FrkE;%zsSt#2Cn9Cm=0R zCoJ0~kb1a^!Wqa>LHG{WQMm1nA!2^9^wQn}EPLzcAic;=f36P;RV!m=EG9Hr&TzCN znW|M~(-#t9yBYAZj;1OJ-GCT4v^ha$FyvO#W(PzDhA|llvqU-Hp&q9o*PWh1VKNP) zH#DYku*$rn)duiGIzlBI7`&HVO*);h1QLwJn_fp7d!4@tHr`sf@S&i@xxnJ|y+DL` zJ4jD>0(^>rxiAvgCW9pCXj+kf2tfOY<G%NxW6pn+g^&{;@jA>RxZ03Q-+buqA!dk_ z17pm5v>@ujN__=R{XOB6N=JJwTY$!OWbi-XrpSAMFpCO4uagPqD%exHwu_*ec7}PM zSz5h}6<+1#otd};bJB)DvfbQKLx$VLQd!WiJNV(eq+^V3UO15HSYs|MjUVQ$g60V= zR0=Z4*~sI&<eGJHR)~#fkh;T~SKVKs%Ob`LAXkAu*^f`T^rqmh=b&+luuUttBuzNB z-AFU7!7T<BLU6%kf<-6NAhz6EG1GtTj~z*VP!4E)!us<5X{_+q&{}N!99(;Q@=MP? z*bfF`9cr!dFEUsKeZbI`=)c^}spez~oBQXBs|G8H0x1&aX7o?r5zt>t-c4C>5K}?! zzl!TB7A`B^$^eI>+_9xusa#=H^-U=mY>koP$1K%(ppM;Ul{F|6q!MvR3R-5W`Vqo# z<YyqY)_YbM?re}_@vs+7r>-Y8)kuU_0-o<{-h_TW3*UUJ|3B5&bC{Pv51UG_wdj1L z_@;FdrTmVHmH`0N0LirRmW(fGACw=YAH2H6WMm8=GbPF)sIz2bWE)6VtE>wzSk>-* z7!6e2Ipqu12YSCR8jtv|_^xCE^cTw1UAsoLb<BzSH%d~D@ivN9*5>+zXY&7qQS~zj zv0*kWd~dCGoA1$f^y;%&)vdtk#$s<5FRuKat$5PUFS}Ox`FObew5pI;Bu5y;bK2SD zRs7DEOamXW!ShX`FPANJE_|x)CIyQ)bKK{R&v$|xcwE@e>a8ENkVlL`_IjV`ooRQQ z*dof$BJ~NX$)&aZ$TFi3y;GAu;!@Jqbvu=a;6WG`V+p5z;n;4(%W>y$6fI5Zu0B_v z8CtW@hTNDs@!$}~Dm1%se3i};n-5KYIdj=fi_8)N9=gq}7{ShTGY%JdWUW26j2Trz zYgtXHMK)>m&+WdrN|0}U`8#;uy?jnCa%zkkTy8Q(^+E}5)fRFLk_7GjwivkjjftLA z*?dimbxa3QIN@f^MgDf@Ao%agJk{FieRYb0CQ(8b!zAM@<Txp|fIZ^WkWGcqQEh@R z6o<Tkv|f{LQF0%P{3=2n&wL-Jkg6#xpe3+b=rjbV<o77=yh_kej`uRsWg-7FX$fZ? zg_)KU5;yg;KKn~>?B2=Eddvlqm%B6}46Xk~e$iZ5_w5;qoX|e#N{15DinKwEz-X5n zt5HgJ8DA%VfJYcsvad^Ir2p(4zh45oxP9zrtfHboWDg$_yIsF=)oLtc*DWuMFtIBQ zh}SRS86TG&7o|_E9<&>HhcqrLczpGFc)yEw@I(1%6TMy7P;oTlVo5sIsOp(kR_{vi z<0?P9Pn0lp$4xI$Mi$AqOLGY&i`1G(+P^SGn5W2c_`2=Ak`7$G@n(li5&bdeLxop6 zAaVou0mDvz#gZ~?vHfzcu_bFmB;NdqZt5it)RHGLGb>ob&u|COIy^LeTUnDEA8y}x zpB5L#IQ_4(@XoXG&gCR2#Y~9uyD&e}c>HZk5Kv?Wf1x!=;d-)C5hZrc+LnP*ctlvN z$a+~BX2B8~Gx9S;?nd2v^6b8IinsbCMp0#AELA324F9niX*8=iF>}Jy0WDhmyRUg7 zGaY#>tk*X?ZFpKXvx#d`DR`^Id&FSy&$Hw0=g2?0V_60CN(G_Q3^Mpjc)Ef+XX=6= z8O`xxI5l;AZ~}DS(faQQ<%>es3kc2N={91lEMrqLT)RGNo1W;4>?*pmmr>;v&9<~Z zH!C4LKQ0X*BUKESIOubUf}nmCQB$7;fs)Xn&4`z<1{gayyqWg_Kdkw*XRI_HR#Iyp zM<*Pb2?Q(R5KXnDBBIS>@6St{DdH>{cVIgf$A>cW>CQnQQI)q8jWh+?RMVUxw`19| zgoXIKX`}OU<PH9<cDd~ho{GGQjB4{z{TsbQrF{F#1Kjg@;9(|~Z@nAl`q`R)2g8<| zE#Vq;xrY$)cSsIViyh~<2zbviLTw*B{^FvLRKt<?ep-fOFW~R>v;>7G@hc7%<P+k5 z)e{an0QAtOm8134%6>bk@*waM3?&I7rBD#&?cdi>X*bPjtP=3?5m<rqWxE)q$S_gK zY<^qb`j!{YRrs0kG#F*j9Y85Zbl#?FU*E}98-E*0p(|^R_BQQ-aYlUgp(HDQtjDq2 zj@s(e)fH5Myk%VIx9e`Z0S|fz-In!eUKzX6+RWMWE$)#{r_rc0^IzXAm`K*`?=>i8 z{lL8~i~hI;bBnMl1|%1h+#;Ji03gB8_tabdTwT$tZ|YLvH|(?~{^EhQ?#Ml<T?sW{ zyk4W=(2q4JTh*qAi)z#HPGdt>r%gM9JGC21H1L^oL|RDlV8H#EKoyN6*2jW4QVQR< zAhRNc53eG1FSOTO+2`cXNcC}<jjQ1Idl>&}ZE{lE+iO!mD~mtJ)t})VD2RDv&J?-O z-^VvqgtI7LIq^_u8B@j1UST~E$}zMvurzoSn)81BF>`+Y^t9FWw%O@^+UEEA*>7QB z@b-Rm0kdd<o)=j{-Tdw0;maFRZS%dB<7_X(T7Ta+%9$^k2IdTyM+<x8G*@y+)IHqn zUR2P6jK$5Z)K$q&tT#nqgRQGeAxldJrvb3mT$O4YiT5)LSB&ZwQ;?gPdZ#KvzdJ`4 zy0dq>bVtQk^_Ak3mf_RIGY5=^O~JeEuLGJe(zN+JBJ(zppo;38w=Nq@RxzE5i8{Ia zkzx2i=^Q9IfK9r^&-t)BRH&hO*D4$}>3+IsG9}T=2E<iSvz7;i`crCzWIMEJRjvq6 zW1qHYGym1oEG9y;4wA!9%be)r@Y?~<bsOI6#(n}zvLPYX?Ur&qk#0vd_3KgXdRGRR z_PFn7-2pYU*|T3%2&5(N1PiOj=(xoVXr43_O0ik;^q)pGR!Ifvqlpz@Zlbu>G-Wi_ z?Uwjqbf+x7Y?!@V+HN`Q7wphx*=yZ7VTI=jRBM`ZYj`D=sk7HX)1b@Trceba1>}-S zR8v|53P+y-5_w9<XhdA?#^g?{W2b4_2Q7kSN6q@5HzU`cI!4th)P;!pTzJ0Mj!O({ z1Mf?@1Oi;Ir}z7s+R%8w;Iwn*iLoG@2{u*BjN`jP`y6fD*Stq-RiTJ`1>L)S@yWq{ z&(p92P2X~MLz$jdGEGXdB-vTkqB$eCF!`U|GCo25$8f4tEW5av?@YtR`vt1R)>EJ& z080@kx=zb+RC*#tOJfc(ahzdfCMS>2aHFqRqtl<EVk?6izh+s{9kJ`-xiHqMLMz6! ze-2X#i9p5-^Dt)sIC7OykKdMi|Dw{~q<AO5|2>H?If$X&SC*xO5<(9aCJB!j%8Nnm zBNw9T_G0>!=`xvzd8E&9lY&nMeG=N!q}s49BnM@eQKcQRomoR(Ns8NyoD2*_yT1AR zC+WtA<#Dr^EJp9*^q;l}r`O$QY^KG(50Xx=gea3OcyZQcabiK>9&Y;U-?;f46d}G0 z=jGV#%2E}PuEBJTHk+VLs1JB6mO4OT%)98@X#3lipYv7UZzkN@@-JcPfhGH{Hvj9W z%xrL8QMzAhST|&;oG;wLGKUI<&U9x53;k8&oRCw6EUwbf>3`09{8$-Z8xyt>v}TXw zL@K5wNO9m>F5cZG4HN`k?#o^-Baa#Xce|)#v#yRFIwg;z$JZ5tLrLr_PmS=c;Td|5 z`dpeF`UDrm!l9C8l6GW>v-xcy0d%JIz95~j%-AP4gkSJv@-U~Xm`QMHcwF7Wap2g) z8sf6wXz_RPxP9`}y0De@m5{AS;!i<rriT8A&tx3iDc1=*{_05Id`W!c+@R&Th1k%p zle-{XM}czZ5R9ZOx2)8o`)OhEbL@bR%Z3WED_`iJaa}WSWx2JA9DI)>dvQP6QH<Q= zE-{t~7*?mc8`Rg!Y8+m>;%J~;2RSWL+I-zz*ie4qt4+hPyuksEP>U;B!SbtqbIU@3 zMlMt#=%xm$=!c;*b_iF#6w^v-?D-R_&b2^;KD#5yWy<2~V7a;}p1ypW6!hK8ZSL7i zd-QJy!5sfC6^mHDE=^r?-X&v}Y=ZT23Zw@!zn9Y!MR&rF_kyxAyIQ|JDi>_06EF?= z=Z7ak1%`jfx7S0Z&kCq6{MgXb4gyIZt&;;glkRp+gjMNl<w(D3UCEK4wTMGva$=>Q z*;TZcaISCjewH-ZRX(}uL0)Ca8U_(K;);&5Xd6{(;|5W|!WuY<tr2Br-sO``M2C$m z#xY~wXSqj#qth%t&*P+1;Q7A^e%@AaZf)G=N8>=pEeEqN3X1*P5^?LCCfUJBBa!oS zhNJ%`T*4q`NkG@;bRO2(b(X|qEn-`1&70Ip<wFG*(~`-oaJvE3h1|qyTXI}&79D+T z;$xYxA?I9DHWqN~XTXuBwav95(bZ7DpuE_cS+?(uLSYA~#4(j+=L8N7UlRWohWv`) zxp%=il<~qU$IvlD^;yKl3>EfVM0UeZn~9LI0Ab^n?F>p{6+_Lt6H$ZUr(>l5&_)Hx zuog&X>aR+vL>PuEv?)8{;)X>j^c^qxBu*2N<AvrdK7K{*Z3B;y^mO?eMg%oMK9)c_ zot^=Jo{KFtL-&-IDgjq2=O;IUw+_QOVhEUT6;l9u>JQcnIiH?Rey?HHaLNq?5%A~< zVt-W#sz`+I;6=YzN4gqhUSL%vZGcJ;@4!@CB6}k9_&6+l44H+3F{Fhy;~cO|;}j0< zgQ(!7JS!U^BC=<MNo9ooG#JtlK7(QE9R(~?*MZ|S8@a<?0Ge7l>?`c5dv|RrJVr0Y zo;+`!)o-c=qK0z7y*eZuLdN|KBIE#<jTKvfT858}8VL(zfZu?fLkvkIe4KHJT11v8 zR&XlMoF_^!8g;U2;h}F9n9IuV?imVY(Bd$66s;gjcA|FC>o~^Sn$C8jQ07%CASj?F zBw0-tnV2$AL_10rpfsrrA&&uL=ujFU{Df6y`O>7NJH_XfWB)lu_<c5==I1s#flw@C zYPt}RYrlB4w~s?U@roGgrTSg+I6-)UI*d=u$_xS-<MC75g+;UI+gh6S1;nuay|iE{ zS)4ZyBejig=y_j)K&rD3sNWX3`c><o(RL%AUmx(>(C&0a@vK>yeCzN3rv=EdPBMs# z%Ad7ydL#P>i+j&p>!JSOyBmqsH`r08)~?E(`LZ(brs3b|b9?_%dAk8e{AqUOqfJH~ zL`9IEpp~-0dKpsy$Iv?|3?Zz{_xkZJks~(Ux5)<wOQNqkgQDSX(bmpV&vGDcx}e5O z@1?mS%*z1ADzB*F`Z3~lv-=dsnQ4N5rs-a_cm~kW;rXK_<nE|<=oc~KDfpIFobVWo z9{I0A;<RHzxJVS!L^P?`1EzAhJwwsMaMq%y>sv23HDyt5on2?`6mzp;|8_>PShr?Z z9k$^%?%1jC38kTPv|)`Q0*z=(m6J|zH?%SZmeo^pS2VBXsNYun#5r}oBS2wvfC=hd z>yOyW^JgY>OfcQI^+oZj=@@1`qLo$W<?xLw<bi5Vzlc8<y&$#)9H-`o0;jQ(#c@eh zZYtN|+!H}p;)zJOmJ#`=NmP4QcwElrKld(e-~GyLDfH&YmEQi&cbDgvK28^33Cbgv zwk6Zg&*rtaPr`-YiYI%DH@(gJK&YqVSk{QiTz|MXRunxx%D4J!PJ&cnb@92IyvHMy zyJv>NADCvf$6i-q#L+8J#xj#HRd?LtJ;Dt}KG|Y;HVF9rHUY*fJVSj9QN+m$cnI~y z$b5M$N6HWOzPIXvseZsl;Zhyg1~WI`maprJqo$iLr`FH@7W-2g`5z0c$L=DeX>PNp zhI(_@xJ+t~(nme?HwB@VK&iblHb12#V(CroA@MA>hE@M$f|!)zLY|(0{Kn?jss zT<8*?@9(YZG^mCc;83Nas$k#Q8b))10cnv19VDE{5s<dJ&>j?{-j}E{e6dO*<N#=} zA&u0@*ipvN^8b^Lrd`8DtwPW~i4iN}AT7frzDpCKVJs4o41a;&L+4=G9!k)HIBZA{ zp&Zg#zW7%yYY$-2$tqfw4<y1ogC7_DAtT(8pU7%4t7Li^_!kAfTtMN11ef~{8?$I4 z^dD>|4n)~?EN5opDYJ?A6#hZ9#;rv!r>4(U{+9J;UU!g==~EHtGu5W9Um;7Lw(fp- zNibLzM%ifva+Z8EJpCZip+8@{9*`B0-Dpl>7?1<_$Li_S42g}Pb9!(rlM2i7vI4D} zCWQkCN?DExMVtnOl_4HT>9x2ML!Yx}exN{PJz#6W&=pFZXP5F>*Q=`GK%R)~t9L-9 zp*HUS+zvo2cU=lc<sAk3s8Jn5+a<e2nE(^Uym&+^Erx85?kO)2unQf)&=H1QLZ{XM zEZmY{D>!INK&oM~7F2xS8MEJVcz{;^(az<zL`kj{@(o8i@*z#xz6oadrMQ*8U+Mj0 zboH1;a<XM4oTfn30kIm1anP<NI*~!>iU4JJ*c6|Kx1=mpMX1-~A)ZD5(vGL<e=n07 z20kjn<>Ae(<RWKE85P476132d`W|Aidmv>pnpPs#oOWgK3>G8LWFxZE>^YSZfo@H) z8^#DqWxluH*2MC1<T%RJufpY44Mu^M_e<rD&y{(q;4Ux0o*<PwaESLUDS7Lx+0-3Q ziuTRACrjt;h?KYpF{qMA_#`EI(fZb9^sz%<-<NUyPh*bE_XFV6rtg=ixX4BVNrB-1 zDX!xFtBnV^x33XQnGUK%ganXB^Fbj6Xc8}a7S!zXdw`H>_GI7-1{$G2%Tb*CE7Lj7 zI^`I23t<CA53%7OjlFnu(fFEgJ@Pvu6UrU@rgqqHW;s7GzB}wu9rLe$xP2$TJ|5he z&B^IcTnr<jNb0uV@jhjbpQKH;`rfFwWe@9{+e>WNUoBg#>9Ic{efFE8k4;pBK8eq< zp|K{xH6VlDI<7T+E0^%?+n8gxS>2^@!nzi)7S9$AI-?Jq8f|eZ1R@@W-7_n<GtCVz zf6S5MqoleYw^gqySFZ}b`L8mIT~V*TvE1h)t=eyK^(n;pWeWQC{vb2!tr4nFvz~Li z^nK#+3RYiiV_AHh^NQj0X29j|G@g(X6li+oZyLDh;x`zkB;54A+AHSdRFqdve@Nk8 zODh<Mj%$yFvblQ(yIVjTo?e2A-*oV6-5Vl!2Rm6=%0*)wd^qu2A#(kgo`2wqTagOK z)Dy}z5ezZY<Eh18yOvGx!@4_1LQb~Z(OY_8{zf^4vZO<=llV#oNy=Oxr?r7c!v3&= zzqd%szd=;dFt?+SKm+C57VD><<g`dd`YiJQBqXe=7<hp<y|%ZG%02W{hvh!%Z}ow- zc$R1y4~ouKG*9Sl_lvPyb5nKKcRRq?6g~q!b3s<p=1UqQLLIy#Wmu0zTmIclOQ_n% z(Jr!ox`30PNuL958^o+MLI={*=#DsVI3JD1cfO~MaLExDyx@z>!LO&`DX(0_k!GpK zmh`@#^T$1qbtM4vk&*KGQy^T*v8eS)3F6QGSW)a39MZ8eGgbcTl@DkyZ^!^`51el? zwbxqIqpv;2mZ;Ykb_#=FK?lsxl?V)}5$EDlejrcu_ATODLDQf7wR?-GL;J~n-3{6s zAc2<6%@p)=Est9lS#?G=E;X5GB2cXtL?y|pJCcCq7kSm`eCNyLPr+=Kj7Lc=z=V@l z%7LL_eRUq;U~emy$X{LK{=+V4bbc~vq$h^pdvX~gx_zq|XnZy5^oZhJLhhB2Km0*5 zj_g7qe+!A1#xWR(mHT7@{YYofg?<T_^B4>mI6eI=L!Ne_+7J2yQG#w_r?{A5g~VlM zwII&aPWG`gZJZ%>Q>2W1+`=!fclC9v`k<c_ui-4f*d8TEQ&cj~k51>TgdZ|ju*^fj z;hn${grJWag5W$1PUvMaJbastQWdyFSxDMl27-WyK>k=KNmv3Gwhf3Rrdq=`bbv}9 z!sIUGD7yn_c>*lgIRZ{Z_b7hh>{n9_m}!pgWWzmA^5i>&P=i&Nl#Mw?HB3?hca8|V z@K?WS1O8wRt~kYxN5mu!oo_W%n0-vE<1r?Ar!MY;3o|Ic(0}!oh+k&@G)owY+#}7h zo<wH<lU~>XO(V$j7QCM3tbF|$A<Kwcf*d!^|Ml=X@}!YDaRTz`KX~}L_S1pSHrJQ4 z>p6jYhTxz#q<7y`HeF8<Ix+MCJSC=t=XBfp>}TkY6+%I0GEtakjNSLUdcNG;`0Gqc z5(mLSeZ8W?Rad+B+j_;Vuj3i>JDh<dEE7Md|IVGhcXa^du(NfqLDt89Q#>?OM#G69 zqFU3b90(+kGd|f(B3Uvr0`N$P3euotBJsfO%)y>HUxv`r>bbo~ayax6h5qD@8n(Gd zU4^aB*R!`Jcl<N$rMAshmcjL{>`ouQ4o{m+Ud1<0S3w?Ky!F=Xp0Rezw$70C<9f)c z(y7z|F@dDGv%$W9tm|3Ti8=EBMz{eFpi;mbV@)%Q145D&33PCjAHK-z=C{Oyaj3J8 zn3R%|;gXV2l+gpbxf~drnOj?(-dDg4Bnkv&eU6;wW{UdC6PLOfwpeFCS{3)11zTLo zn-c^Pe{l_x_^A=Yu63WV&n|XLFavhh)Qq6|;t419I@sIGXfMB*$-kGkj-W%~2ej(y zj@N&lX53~EUfJAA`QUmH{vEHb`q#tN`qut8HO&_UzMUT%Pf+MOtNz4-xH@cWFAvo( zg(;7Or+56XH#%PLXdl;b+3-Sm8KTb<!ObsgD%?4P|8lKpJD;X{4KwRS(kqn&xFav| zR1~)1)|&K+vN(&;A|S9XA)VB~3i~g^m^Z6r#TKD<B+Eav@b%^QdS3QNsGwQY;SF&5 zC2Ogc15*Cwqk-X+Ksf!_+I;H|omuO;IHRE~5bf-r<z&@7b9Fe$AFts%qmNZsNR^?% z;-le-Z!z=5pR*AGu+5)TBjdySE;Xg{0F7d5KKen7>l;)<)1Q{z$SIGuG8G?+WFRbc zKXF~jpG@HsV%3GHV$^@}pKjBZFG@|M2OdwYL}U-NGzDYSLf0r}Y0Vl^jY`NY*wep3 zkU)tGG2npU*e>k|Ca@9s5MgK4wq=NQ({MwX7|(#al9oD13}Tkh_Xgwy1x}l>;%5>m zG9;XP><{e<>It>L_w<h^Sf0yYt4}I`7Kp=}pgy!Z)_8Dl4Zx=&x<^U|^`{u1lVq{P z3j0#zyTy+_1(k*lH8SX8a0NzN;rTxtgd^p45uyN>bT?nj*&bs#$$6N!<W1}$LU$!b zAf(HZkO&c|@cPI4wNi~j|9qDHqFfMD?D0sXFdSqiwD0;v9fSO1;cnO?W%5@ccB~F* zw(mf#4G(9`DOYEoVl^`{D-Oz(qc=gAN@WLJCvT*Z&y=+!h2qyyeQKIWlJsgEWc|?j zNRm8?GnTG>?+^a;Nw>?cP5+)6#Nd+*P5#(H<0Yt9$kd`VCMxxGHE7%Zzaa4|gHBP* zlA2keKNv$SSLjW{4KGZ_(gE|KY4s1W!^0=&pN^S5D<y*=Dom@$8RlqRHmZr#W2#`F zQB)HsC~CV6bOF2QO*sMnCKfDb&tPOMR%lpm)*}sA`L&=B%J+#FjqleBV{V>a_0c|h z-!_Ykjn$mXb=m6N;hgiB5lk>dcI2P+WaJ5b(?Z1eGkiAthT=$(b|MHBT+O_s>-2rx zR-`2XNq<JFRGh3kba&=IZth2lbNMxokU#xt*e2fh7$0-L)^pyeXC&qcLof!4^2miK zb_!GVfBi8_K9AU-8pa2?<eb?iGjCN(a*lP{1i73>&h~3V^<<L6#kJ?j-`iWK|DF5s zx#rV#cUi$h^7^ff`cE8+Y_#rwX5yY3I?XhJC3dJJ7tyBiTs1IJyWI)fLcg{ZhnKhZ zk&uVtvP-!}go22e>yg=OX-*V2hCD}B-`2enz~M{qOZchUPRdTp+NxD;sy`|_K{~5_ zFV5H&L+`4~*4!Js$nEDmvKu??L?Tv~@k>=>14Gt$4&q)rUajur%P%C)Wil0+1qAmr zI3^C2zedbZRm_j-yLGu^!oyQdVtRnz95}*UJVCD(O}fLom*A>1o!rLEPM?$GQCtlM zeI7n<a|*D0T58_GYwx8nPr@)vX6_4v5ynad3mlCf$N3qn>=S>hXpSoWpq`&=t8R^R z|HX(ka&4!cth#CyjovJwC%jMMqCCSJ#uzsCi4a2<kTsheIO(`?(OEOP`<hOh;3E0O zY0&#@x+Z9Ax0VvAQ+f4Q-N9(jFIT_P!Drg%fwZd^zf*vpv(S0s{dhvi#pucE%V^^n zS>`@<%a;H2EVJd~9A_GDN^fIV-<B|C5E^qn@JSV`IIF&osoP|1KBjGUOaK<qa0L;w zu)Qf-$eC*jsXs9aU}B@T_11(0h{dlu^JbobAS5?4S$VYOR75V7bqNzwGP4LgN5;-L zP($s(gkwKLtk&~i_35LgQw6|wEjsDbK*tq`-I3HPtxNr8yK^F-(F&p=hN0uKQ2Zl` z7hc-99Yzej3y%g`0_{mAFWRynlO$IV6*oZAkXB=6k1o$x=(8m**y8nA;8XUclP^zI z;9Rs&6rz#PBCg`*mjGZt5~9d0i>g%S#vOZ)<w~55EZvN$sFfH(_w9Dv4xUDisCF5I z5?VYs13wxTcEs$rm6@?r-81fXd?$|jlkJiSEp{TH6x5D>dRIq!CNzzNV*FT<FP-9z zMD%QHj1WpdwIf|wgrSHPuB#<S-vGA1i<5`A@izYgUWmhBacnkDE-at5s|<N=E=L;} zo?!r1x7s4yOQ1E8t1MDc;Gz*wK3T?mf5U4*sNcc!-u9*a8N#xtJ~1zk6K6e+IRR?} zo$NuYhBl#axGx%&QW;1Fummu}^p@apmBlj+8FQUaLcg)4Yd#K_u!|E0TgO1$&YO<{ zVDRVBNB*YyUN7$my%3K*3gQ2X7A&$%QuP!X0*g)jyBp9iI!V@FRgxl&2o-fWEG>b` zy1yA!FJu)Cq<jAQ+^ftydFgBZZ24dfCAhrAizkGeVk*GFZjAvlIrownyS{`bnjdmZ zK_$ebpwo(i4n!@vqY4dM{H8+z)>)3NI$c?8pHF7J3advPGh3ml0d&p`o#ODotylwA zg}HG%mNqrR-dV-*1uU>Oh|N42ykB%pTu3ZfRA_*<R)2b^cPp`3r1$J_kg9nkP}>G_ z$M%l0msgj%^h?T4UoV~n+B}~)lMtG%J%7mB%pvr;7 Q3Z&y-Lj!S6|<>cB#qke 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.flU!Z}( zz6&6^G=3-UVLHYJbkk)pqRp;*BgiYw2@ZWV-Kq>Lr5BsWBApo$I}|<I@6{ms<oTQj zju<}sJ5fexbeNyw)c?`%x@!rDDD$ydqpl2I+!Sj*{KNDV^28XD+;pgP_9@V=y<ye< z?vq*TKTIbY;>)E5v_|)|6n)stI7Zo|Ok3z`HC_MrJl9V;V}F^h-t^YtITTy}^imUI zL%$!8TEcKg|D?4b`+zywq>sMVH4Qrn(mAJoUAaRaviP#p(haljhy&~K1VGK{ie3@s zzFS7BA7uC+4oN2AXfXJthRbD%W%ddlHAXX`g^yEtgrU8975|@$k63Eg=3e5=igN5k zUyi1~=2LN@dTak^2Gz1iVXhoXT0CCVkhW$Mc}1&bAoDS+_{(GRb~`%ozbns>FKo}F z{r-UnSKby~k#N#Tql^2Mgtf)MZS=S+@8z-B79KPWl`%viRz3<<$fjO|@65Yl*@qw| z4{69$<piJbfIg40QhN@$&7Cblm2x_C&Seozd3tm0d+J3Z@(L(`9+53;Y#D)1?q84P z)b1VG7A|BQ9b-k<Tk9Z{a^v_pmd0)i?9EW?N(wzmB9@Iv$2ZZ#gWvE6Al#GxkL{YH zWrxFxGJ0hc=cblLZ3C%56#O1Iq@0ZIz8iHvg1(zYpt=t#p$sKzBgD3T+{n#*fz36# zx(;#*4KHD(TFJ7}!8wZeank!^2At1sqRjT+`yL$NR8x6=eujgGkBg0++fuzq{a1LR zruGZE@Njf=^z~)So2@%};HGM8Yx8UoLdBpukOK3@Cy^E$7TWnVxfn40MO%x$_UTPc z+105*q;R?V8YCm-_Rq9_>g#RMA_&lHH8oxE@nPubo<(VdC24{AVR0{hWu?mIaGNio zE4k{h<HfBW(*8u<^AR2Sao*<#zkLnO{0Nlm<YMjY?4*TW2uaan1OCfERgR1k%f`Vk zK8Yi*yf}RL)9ZLS%5K(q(YwBx%Qj7F)RoPT#cD)oTb+gJW_n4#@%J~@ZH}Q9PX0Nt zPto$5Ad!@InyfHy#Zu>bdDvvG6D!KuS}mjR;o(dDeat@`h3RtfvV5fti4Sg!-JGt< z`?h1fbq?!_W$=+b7QxoIEIj>vd-rYGIXJ!;4P(D&tp)L~i|f^FzG~a?Tdm<LH1W1n z`3UQHTK#q^6^kJ?8BLD>g^2p`hkiMm37gIJWm765dW(24%+vGvU00bmesTWp(*Fxs z(5*unKx4@tv<18&&SXPlDLbAAOc*QK0Zt2LGZ!_e7^9BgCTAbab2uoiEO}0bkOQ?F zvlO^PIWn>$2ZL?315pa%IV1%g(>kDaEl;o4{k8WwK66ke&-Z5jqwmFJQygif=z>~z z7Iz&H78ZCW2va<M2mo_3U23)3^n}}ZqAyz;HqTl-ZQ}Oz)gHz3b@OX!F-zIPM$7|5 zh_Y@SNfQ3y?|2bb8K9b0BHP#SMnOYwUNJ^HH?KYM_aHS{%{nBAu2>63AfPbFZ?G(e z$u*pp>sL2pnY#wJlIcAchw_54lUZ#|?vRry)AHG2J^^TV0W4r7A;R$t!iYif8L}2E zJWj112JGXSqZkzflXr7ldY{wA0eLMC6;7$JEN<v$B)-~-%NQsOs2~lY7vcZ+H(L;E z+Z~tb`>>xRP0Q>_YUe}vO(Y(demdQBewj*C4389oY9{BfitmivhBrs7!fqX9kLja= zn5KXWVy3($L?AE%5<v-9LPjc7cQzFXeqjbu+u2Z;sa}8;d4ZXUE^tzMmk0JrQiui{ zkUt>c))U|WjKP{_|GoZvX)dNbNZ{G*;UqM-7}7iinw0k}mow+G1EJjfc+P6k>O?TO zK2-_mwv|2lK^I##V7|tgdoeX|81%;Cgrx6idEeVr{5iLr^6Ddn`S^Tme``81Rj@f3 zY1YPTcI|14DVn-mj)4Y!a=VMoAMgGr9~AzknH4BV%Tvn4A92T@kt{lY;5j+}D|%*I zvQr(zw}-=6|2fJKOz|w9+7MfGhBN#?!HOURFZ}EN&e;e;3<p)ac2-t|%m_EPokl)u zhj$jIQ;Ao+#Ocf$YBf|Q1^S5A2Zq{i1YAey+r}D#=R8NJR0of#8LsR8Egx59HX*K- zSF<LbP6iVXL*@QGxnBn=zgoh_HtI}1ZeOwKvNrc(SY8Osz1<jwbe0E;7o6QpmJ&S2 zEx5qJ80C_6t{8W4-LQ|lNh*6jWj;V2N*SNsAo<{rbUPs9U2K6Uk`2EjT%sf|gz3k& zM95zBn^3^#N+L>Uz8ijOw))s07VkSzXN!4K?1-nev_wnGWd2=`L%u&vuVZ$#)@s<i z;sQq+qpEI}G?K-L<#RStHd%v{JzVvz3(*9oSeY*~4c5_Q@ch8;K!@C*8yjpC?Heli z2@>AQi)Dl}Dz)&CE?D4MSV&CcW4bDgW9qI~CDlw-oSV8sc~spf-XMB}G!0{um!}Z- zR9Hs$xsJi2gG72JoiG02b+m#`iJ;0erUSOLsBhK0ip_;$XWqi6A@O~CWB{(J9Gybw z4y9qBv}(H7@o`2KL$&9~HtXilNnYu4<3FF$ZF=1>r|;k5Bf!tkWsbDnuf;p+_AEHz zn$6)5$VR8o+?IPT3<vo>97VK~FMv;>&}=?W08b*OQx$Hk+BkM(%fS4BAq55WsPIUj zYph({uFdzt{_{4ACva2t)tvXd=({2RbEYzZ&6N0k|CznSv*p<FxAU*}*YWfuI(;th zhY?rKjG0q&QtmWb)bRAQ?5azyquhm78io?ew&+ZBt`0|DuO?%4D;Qm!r*9YrL)xF3 z)j7G#J6gAwAu$tEC;6gi_wJsvx}Wd&Gxp!n)92T_q*j}slivl8zUfWPNO+*roKp{A zLth1f95F8Ih|X@3UJk4(+EjO-=5rgvs76;D@*3`)C;plbe6@>hMcBX3yB@(>hqv!> zSf;qgNv?#h#Ub@Q?2PJI?Cw}3G74}Yx`P5P0&*>#t1RL+4@{M9`Fc9qpRSIM_TD^S z7w1JyVVhrn=QkRhL{+#wA9=t2tge05dj7e54@sW}4B=pnsS~2S1>%ldx)wum@1CCc zZKGbR#pQbc!b^9)?|A{ywQuvA21WV#HF3829aj{1AWTB%*Jj>`7qk7|hsn#}k3=(< z(hV(joNjL6;ut*g1(6W-p#uZ&7+rLXTJ4p%MoAbWnGjV_&6LB*dUuKpfWM=FeTq^7 zPGLBZqv2*~u&*@hZTv^DH^rg*^+nsw0bMjL)q{^Lzu#w%j)KmDn!50JdVM@kZe0%; z&U~F;^*;ax$~kt}Hn(DV$875??vAnstV1%(!}mllg(a!g8X8_~b-Yviw?+m)mC>MM z3n08lywHaMQq53a9+)DNvHr0n9XSJETmpUED4%iiqO@5Ar(CkcK2Mjsz2q#A!Sq<* zJgAtFkC7WSgLR`b0ORtefra;DU1fqrKlxg)>MJy9VGF=^gB?^q3%W_@hNBY*q76S< zxPfUSUF8Z2-)I2WfManhC%QM1yO^`Vk5dq2WfP$ak-FiokH9QD*1~7`H&#)-Lm4%p zV1Xo2kM)W3dZ8pQ7AGd~aNnvjfT1b@>%rUhU=bD-<CsanPLcpFjBCqHE=5bM-%imc zJ!4Y&<MfY#>{K_cXvj`QIM5zHB8L<Odl}EJr*Jj)qm#c`-2=^AD@n^1ev=_`zW5T{ zxyrPW102zeU^p5K0~wA(;>9(>S(+<m#RgBBr<PaMUZnJE0@JvZIi{$fBKRCL((Uu+ z0$&~ot}Ij7-c;~a{s|w8aS$u`)oo~14ik(JEcp}%c)E0P@$|KaG!~!mgrP~yz!Lu- zPv@W{SeR_<vTb(Rwr$(CZQHhO+wQV$cG)&>#hIBKk<XC(-?{J^2MtuyqNa@ALYRa7 zV6ZUputMUg84C~Y5J3*VobDk~cmh@wqmes&F+r17@`24%0-*r)auOY%w`b$BVU%Au zeugw_+@E#}=<2C)G%cw~y*2ICq$tFhCkTt90+9glXo@QyCrq)Y>LL1t*R1Y}|DAYr zo0`GaB*RXe|C<Op$%DD=)kO4QzTItVBSek2Nzb+FjKkt=1Z;u%PWTx0^y$|3t}+~= zh>NdrjmSe3Bnyza#p+2o?>!j<7zN9yGYm!POm|PY{$-Y8OY5qsU>X~U9^nAduv)d! z{8_J$$h0fVv1Af`##K3FvBuW-9>%YkSg9LIpx3bFr+GwrXYjX~WG*HPh9Ky;ygEyH zz~T?;;jK1}2l#R+$(><_NTM|Bc~eWf!Xeom`5kdca1%X;tu4a{{-25?R5xckGzS5a z<Fdps>!Dl?`o1j{!A!hcP>!TUrEA1DQi2Wn!1VEw;#)IJ$T)|vd;&faQG>$;w>JX< zw<_(JH?s#5Rdc@SvMl~{CuQGB9mBXI>-i+huNb|akq9KD1+tSPg^v=QChrcUyYiuR zs}4aA=wCQ2MQSE&kyNQz%n_=!&VkNjisCu$|JJY5Z}5Dy%uKYAXkC}`h?1OLN&Yu( z)8nxJH-HJems|x!FAy2DWqpIhOCvGRdTg+@dK6}P`@x)I{Jy<^pmV5!L?czS=4|)# zWEUL3M;&hRKWUxMQRpsLWtA4)IzAo_gVoql3)ZaZ;kUP_#l@zkrl_cg$z3`-JG+}} z+n@H%4cj(z;%zs_zy=UYYcz=*wkeYj*{jS)3g&!SJzMdk;M`f0h&g?YqN(fmQaze5 zJ>9R@FSp&_^vn7WEdLL5`{%0mtHbm?pYA^g4?EHFmjRv2$I)wgBVnsJN@_e&4tU*k zjkb#O&T3bk-(*^=j8oIij+1SHfqACt*|7I<jOzp*1-qgzApNQU4!iuHRyW&=EwCoq zsfN@YKmF<V@uaNE@3-l<2XwkN8@Kz*FuD~zG!u`!dO5#EuGvcMr+}L8&=GG(3Y{sp z?!GqNT&VX~KpEH18KM(hn)COpy58@r_xt6n)z4nQa<}KJi|y^b^MeUYVop#risgr* zH?k+OJikwC4Vpr+nyFSK+Tmma9XxOnQV*UgeXzJ<2>{S!;EsHGVB?8BL0<`UROx2q zIf~T+rJ!&Ki9ZY`F)$m25$#Q;^(z{SX>%w$>Sj>`R>tBR=>gJs)r_DM776X&ojvW= zJGHf`c(prxx;S*lQJ%V5Hb}K&<Fe9H>^K8LWKNFTBAK{j3_=oP^VB3|imfRkvbukS zlfU8r4tV^}3sAg8vx!+U#X_>N$eN+7il6wfB`a<o`!bKv$B`SrA0!&XfFpZI#^EDf zW?4OZbnmBZos6T?jFe<k1861jC4F>Rp?OrlYdiTDsa-@Mdx6;s`*ZGDG>9hBceij1 zt|yFUg?Q}>7dsTbhh@X!d4T^^tdy>^Ol>9o*I85U3ePNcp*{!+qf+|-oTbv=qbHMc z1A`gW1rds|NZ%BtrhJ6X901S~G&twVa{#E^m0CV7g2nTARtN=vi)#6H9J4~I0GfrB z&OLuHfbc12MS3K_KfPHcoCmx$_3#BuQA}uqZ*JJ19IyDqPmRpqY+_+8PzoDKEhTTH zu^@^IMGL+W@lP{0m72rTR~&;H-&(_Jsue!+BA=j2gooZ=PCc$wzYP|`$T7gN!G`(W zt?6tOhNcji+uoRR4%w2%dheF`Pk^OO;^f1lJ*6c?F3KZ)Fcg}?T$H3S|7-LhGk5l$ zWHXL@Z?+0*Wf`=U*@!-uuyl=NwXcP1&do+Z9q4MwlBSEg+v@t?nU;b9jFUi44E40I zvhphoII;+*<DY;{Nq`z;&EplR1HgcG`oP!?^Bmn+V()oWgKBHp2DR3RXk!;k_C!0X zG2&wa=^Dl!BxxN<h~X}yS8gOWsaRs;NTnsNZ<LyBLnc)TKne&IID1H7xmEu&^zgdm zJV6}NjQ)#Tvv+*Vx&(HNk@)A@4&NOcU&U)M<;fh}{)X4s?Q9E#uq{@`A8c>Jdf_}= za2(XjTXtQ2{Re_We&?otK>mjKI5*L?7tq-?fldN{bHp0*WRT>~wvzg=uE#<xt0PGk ziW5h8tXdZ_Lntk)3d9h}ovLTU*D^o#BRw96LhZQ?^fduiP)Oh6DINp7LC6dmlgY)L zu_((%J;b#^5QS61mnfo&JTneu^PAA?P-A?KWeXJ7o7G(-eO@&LMrpFQ7mWqQXFc<r z2RhvFoxwWF7|#kTy2I2L>92#X#FR(+G!|iz)XL67){!U=)CKy*+NAHR<1w|lG4{s{ za%Ey6-@qb)#s3N9bRQ^f_uWA(k-HuW)Zx6|!@Ygsu$wGN>An=y5%!Vuyc_Oe%4y0& z0el<ZSh`|U1ls>hN8^&EimT&S`=cUJ4VZA?6F3|LBEa`Yxa|)?-@@1*{pA7(3r1~l z=$^MdF8h&Jd8)fQgaUsVzn^LzW!hd|*88PbA^P+F_j+yg;nz~U(V+dyEurHRTZXf` z0$47-Zri+iT3-H5MeYcGnDunNeH_2nT|8N`zyu90oz-3(KX|ZZ38Yr7B&{s6%NCy* zzy!i8tA|)zg()1cMsD{wHUg@7H24F3q1(}XYdw0vqx15o`@HTIrQJ|~af6ld;!`OI zRNSfi82{jzK*qlFUx!hF+LQX&Vlm_;-E6wEx;-~FEly8ndCl(l+&>@3@#VQ}k3N{r zJ<q_I!TPPRNP(`W(>QJl??^*a&K+tXSldU#jzq6)YgJue&y<}_9-Y-Rv{fzF^?iOm z-uIl)>Ea*&#$A6J**kr?J?H&1y7TuhyUxLCXD_ciaZ)_@h3BAY=q*aOJ-eXO07Arr z67+r?2;24h*oNo(a&PgJI3cH<ZJXY{_;!60?dHqNn?e(0AjzZ4^L;p5)$_RrHQU0# zW~KNLr{L{zOO-QiT;2+7rDIeo9xWDMifPVR12Qq<|H4P}O;DB^*Gx<}q>nkULK@05 zE=<rRP_G3cw-(>S6rAWoL1J&1AZLKw5oe_oZ-4pgP=I~xS!&jpBLK-%(w>)&+4E<_ zp=qPFZQ7!#ot>wTokMSCMmE!<NK;|aVgarVMfe!pOp8HwVK5e_pj$x3Zt*BBMO{21 zOr<f$a90BMp&+7{N%$Put=Slc(yB}Hm~GpFR6pel%)3CJMKz0Qc3}qvVh&5OkANjh zzPEK*NG_s=Uu$JUU5XK|(n1qMm*1u}znehbe*i>5vHk$*(BVmVu<XW*zo5h(N4<8Y zQ)5+jqnSUIR0p&@S=ojMyz{X*24G1m<hPU+UqIVGe#RQ02#^^E5PS%lBvMjFu%%ob zR%~z(ov;xa*W|E0IX32I4wK1pTj)qg!br!yKzY-ONj6ECm5m_>mug&Z3~lOxCrn>x z#WfblxWguof#z@IKze(7&&wOT!yLk;@FlDMUB)i1+rFT2NGRu#huQ3|tInoNxjD=c zCd;`(em_+=`<24epcbaSkMLE3h_oNxU-(?AC3Dg*jfLveK=9u#JomPK3a}nHBSd}D zax4eeV8fQ%jZUz`oZu({EWpkM`!rhB+a`CiTz#wS4N*iPouWm4|Jr~%0Be&u7qmi! zdl^0ejX%r-BsK7ge=o3`6LP0DpF9Cxh^nPt*Qy7BqWvd<O=aHa0SSQM+EHf)*oA3y z(cE3zQ~%j#hw3WBoB%-(IKz$N3@Z^PaRic4Sjy`n5*$lA&NO`D_=~?I4$BSW$>~L5 z@zU(w0bNXwxeQyN6*8k^iq+;<Z1L=lRs=~@Udn><-vD-*j4G((kRJU3(9zY+>c97e zCm0R$<(ZxYZfl;*<6R<HN8_@6pSCl7&FN5s;EXFj;Pzkxsd=7qK?UqM!m5Hx6lhEi z6c~hm7{x)nau_Qc4p+hyT$pm9r8zbZ<_C;$(WE3N&LSbl;LwqO({ik00rp_ROOiH3 z0`)wE*=CkF+!gi|(d&PZR*Lh$NY4y%;9GHp4w$FV^^`UsF_dUx?;;Et)s#<<`ee#; zIF-j)KXK}jin1XNLoakJ89a!(v1)_Mi;ZFdSGtVn<w~{K?A2abyw@$A7?u~vq?-32 z{~-4nzyHX2;<6a|cxN~gCp*FPsii;yHP@RNbe4tE0*~%NXoygaxYWY=D!{Uh^je-T z1;IeKycHo8VU;Yo8!M#&oHl-j0(R}sFMUfl^65%t(wyx6bG>nBT+V*-1N5H@1BV@v z7(z%_rB^7CMGMLbIQrlB4dDP-3~WsLy`QW81}9)_4#)aP^NB*Wi;j2t%J)BtjC=j| z{gA}**&nB8@8?fd$o{-CWoOJerHjs)-#1C{&6%Yg-QB-vGd4E1XxvA7n2(Q-t6#&( z$My5})%LdS?*hJgIh?>pm0Us@kJFXrdHiCJUSy7iDLS!$;!(VS4sOaiIb~<ePFAG* z-Ewq*k4oOJkaOMoIX`eDKSY<cB(cze&*`GC^sHVe{G)FY?UAS6H;MS5!bGg{56xI% zYHAl%FL-kiastkHdOZMJF9)r7wO!9mQBBhxWe5x*3)+?x!UVd}N$>mQG`Sl5LOXMw zXoX7m+7)RsUM7!rcDufgK3~7&k-;GnHtvb9I7fH2$Yk^~2Z!+qf(&SYY2WA-h^VNl z+j7g!y+C{SjC<>_6};hhJ-@qUc)Q-8yOX@@@6SO8X2@9Qx#O>}u&;c&tY^a(TiV`_ z&n!DVpY4{M6-{L;UF-P2>1I_ADb{$G_{2guVLMI&jcXwg&{0f1A)!ja1rlG>A%3d! z_S)t25TV}51Qn)w_TH+}>KOb|5&)t^bMamg#0|>Eoq$N=i6Pqg4$qBj{+Q#x<)QS( z-~4+E{z|8!WnMhj&mSj#Hmg-97t2STT6|VBv&v<}7afu8Rs55+oR{y0sHMG=I3Yhg zP&x#&l)@xw`*sYI)r$VOZJ1JAA~;u!HB*M?jn5bNk_n2k;L2u+`PI>-kvsu7${Us} zp#Bm?ZeI)8T1&binXb7rq*A#x(BVe86*8rd;M;I;LGIIBh*|thA?alm1bC>79!rZu zrJdv@OrEWxM3Q;Fk4Cod5@sJp0F`V2`aChmUUPTlE-*nsU-7!M!|FI%0G)f=e1XXm zc;Lcq7&p&*dB2Hg7wTb_FZRWv#`Db5CsgQwT_>MixxsqNO=riBL<7}P@W~wZ$W8zi zQjs%SNZB{TupY@$Oj^fKa+%=;W+t%fTrk6NOhlvN7)Y3K%D<uaRs{JrYOsA0Bwh9Z z87xw)Hw8@vAnMN5_@da<%^lCAUeZdOkwY_~A!7>;OtcvjM%{PP$M6IB5bj!`>j)j1 z4}Oi^@yw<{Dub5-H2DThaD(48)~ATts_~LCik?E)S50nB4KxxV!__TnqgIWjXpu22 zILnmGit&C>>-=7CWDt&4cUJ^$*{O;)$#qQHl~Ty_sWws@o~~96{}c<v2#sH+5R!ew z#!)#p<~iA7i2R}=*4{tJ&XV7<IZ6_P>4;A7i)52K@<|BeafgaEWQQ;rBq@kqATO%T z7Yx7%ca%XfC8d<5Ihqb9KHLQg4zMPd4_#0!&mB2QnQGCa{j^gx(M+f1e>lun(7asi z#V08wS@Zg*<bcg@x!wQx;=S~x|5K}n{~IG19cT$N^I0rahZP&s`HwLuH*@B(TwP{; zM_US^unGjs(Q@#V=tsK&GSwdhb0BGrz6p{3LZSut<WTzZ{`HW}Mz!EDRaeBKnvWxP z(R3)iXO1t{LcH*>{1%pU5TVK{GPvJl@y;|qnHf)F=p@ZZa^$3Q&4kW8VQiW&<ZHa{ zN}ij6{_K!Mq5FfNrr{hlSx2(`W61VSCV@q^+H2k*=##XRbUW0DdV#W}0gV5;`{AUJ zPBVK&<cBAwwn7Dtzyi%~g&l%AZi_N6U@1d(v!Y3Dm>UvdQ~~Qdlyc0`vhI~+c-r%R zxcpw`&Iw`WB(G|u$~`EhR>;MXHs}&cpo}qSm{5#@)dvK@??0W<IXremYzU!dW6P4Q zzeyPaa1f5ecq&D0MDW{LxdcWLe|(#JU|KS*M(0-54*@Wy!MJ~#jJ4v({M0b&x*mM( zlSkYS_c=`dylqZg|2H2$ER!~zIkah$H#<EaXV0lm^KutY$G$C|$E}-J*J?|@$AZDZ zFWZ-r^&3bYx2fW+(1}+Vp*cY(<aw>#B=55@c)m(3lphl>8Q`jlgH@YnP7~hoSTR3t zNM<S66UYOIo|n1DLq56>DKCFv5vM)yKQt;5W+c>UkOxO=p}YcHa?_Xlg>E->=xeQZ z2J~!EeY||O@L_hQPaj90ow@cp3{wl}(G#e-kC3y4>s&-AdK%@F_0N^H1-Y#wtTZ(c zFI9fLUvHzkc01D7*Jx~PV#N|9fj^y6mCChmf+knf5#N-wTpCoIdxE-9<X+@PX~BQQ zdK^Ib@%XHts_JQij;{}{4$?;Td_SH%`cC>&*k^#~$S!=EuFpHZZofA3`o7xR)8Pm6 z3Ctpgp$Z}CtIX1pqQZQsl%65!hFyYJBzDcH7GL(o08>T-ii1^S!>Cm$`WqX?)Bmaw zafbkb%$i3UhoeG8qrHI5@`qV#ulJ<@GLIAH4E!;mcb2M0Y%w9B=KMF_jh`-_kn(O) zJgD1s)#~x?{Mx;yrz3N$mh|T6>7y}iskEvJp#p>aFuWviBK7-giAYJgv`Gn|<4iP~ zUfZs;Bx;iO=gsrHAR){M6MVwb%9V4Rn(MB3t%jjd#wClsIy;89FySp2VtI%m0D3WE zB;Cbr`=5Nnut0pSg5Us1joxZv8Pl@qMG0{Ze4yewsrna`HL8@}zyv=S#G&t8GmRHN zSLFdKNE#TUaK0B=?f0<|PT(&6@@=BYo*{U)&!4p+e2}qHNdq(LfH+zejYyNUU>xy; z!4siXz%@_JC{lUvXk3QJ<F^VcEl#ni?OM-yFO$|pY3iO4{qbphNx2}KW<y(~M6$<f z@(1$H5o&MMtno<&@b&nj_v&IWV$jD+N7+Ez+CwtK+aP5(V}d3FtV!sr;d#O0jDJ52 zyro4LhpG{V`VAKaJ7nLJRfMlV^_@J$#&i07!PK!V@<t?SQKR&p@X9H7aN}nF(~88< z_>nFgX|*@7WzFm{Ap^vjs1rHX^z55Y#>j*6m}^7chBmWdk<AQT5n8M%rb_gUF{CL( zCt{RZt4X!cv+%*e?x$KXXzQl>CpM!e(3juyt>EDRoGyWo0GYh_U$jUoaXLvKNUt9A z<RT}@!7^52aAN?+;hA(UUi*8HVj|bt@g~EeQ0kxiV!awkOAMLc(eut*AqzZ4e?lW= zp6Vt(IIhM(xBI#YBZ1iob9nDO#sGVO(gyWk6+fzLSEEqA&AVzfSh9A(?|pWF9sy{) zcqReH<XrtHaj|Xd=b5&3jN1p;G}Vogl&Ajr457Wy@~d=!$R?faMPJgx@hN^Iebm;C z$7nE;oECvbv0G~Z<8BHS1-Z|XzEJCap*R+&Z()0L3bUTg)w3^GIv+CfQPt(DA;-I8 z+siToEQu$jY=`>tnGWGd9d&%dj_rmgZ<I{gqCumq8`IRQCFw7B=nmMs(ja!$+2Pl5 zi^Q%mM;WhO;JEBaS>OT}b%bVe580tMMZY%6YutKk>fVqSTIduJ@g2WKgwGnLgAHL7 zdy0o6aCt3>)i|<i1<Z2)72i)(0dWXcB2p%v;Fv5OWoy}@Ex78IHcpPGQEa}?EAsTr zj-Uab;MNcX==b}t(V5GR_!r7rd7aU)dK`W24fM;e6C;KY;OFP>4|uJ)rGtp4B_`~M zf`eJfZN6x7>*4w(RWC1ZH$4+NU@o}UZ;W=kzOy_nukN}5<ij7y!~NfUzkni|Y0u2& z>1u03loOzw{Wc$U_WZ^fCx;Dr^ZGoW?&DVL>S}9$Wv$Jlr>k>UC$|$wsPePN<c0P1 z^)hty8*i;=1fw79#?RkcC6tI<Ug7Tx1C@6dAmbax6ueKhF26**Dk(RiHf2I-4%<vY z6BK%lNdRWPIL+AnF1XIzrA|3nz*~u3znHyU-M%-k?+<T>%gZ!8USDSCnL=HA9fI`0 z>R9Fb4B?yRg}ecOUwp5o+OYMhoZc|8QOJ3+Ce6Ckv@|;3ZwrUFlapPapT~8v>4kxJ zwikmrc!z8yOJC1?!s}I&?b342coe(v5inNx%oV9Y%k8&sg70NnT-1RONN~6N<IlUd zxLs~|qt~Z4^r#Dx`@znOt2=srdOe@#UlS?s&*A#$dWSAmTYR_WSeZ8=^mCAy+&7fn zR`~wGiUVjP4S_|Q8%{40ZSWk0R}Zk&QhW@Eal|Kv2<Eael@ORbyOY3t11hSrK04R_ zG#C-|;(TF@;6C%-y!(XH+|CRTwEqyCL2=38DMVT7sjPa;QZx4uw)*xf>g$`e7qk9N zKWwYtZca{T5)qg4S^;8Ill7o7k$SqS&6y?gvGXF!c`W@`2cj1FujqZD6mi-NI)XEm zX0PEfv^*%^84u#qh{=$TDV!p$qX-F3ba}BdSY=^Ljj6HcFQHA*_zSYFc0w_GLzx%D zYFjSQn={szQ5Z=Zoo~-o&RumIv;UK>eY4Vu@s}Parg;6|d~v~z#FIa$a3K83{&uP_ zR`xIo+fEcautIzerUrgG2(x;4#{Q15Vz;y64Tl7frLmYsL;BbuBN4K9S>Q|S1wLxs zz}6)w3?)01Q{I;)m+b&2RvSG?9w2(*7tl!ix^3%$DGpm{{I1GQx3hh~DoSAt2~6sQ zypH}9mH7RY8m_?(E{$rmf*$kj2-aJhAuNd`TQ<5f;y)-(%g32umXP(%LsK$(oB}c@ zaVuO49I*}?34FPQWyI5@WUBDE*i3TaVd1xHg+B?a*a-Ie3{1@x4Fnpin)J9TcG^nY zn3Jf%nGq<VEw8-yC8Bp9MSpM!uf~*58RA3q_20Avel2?pA{tRlkF=%DPXihl)mm}B z7fw|6-cIH7gpc|`5DHA9Bfd$YBw7pUK&Io?nt=E!lh+~2M9C2aU{d(6{Ns?N|A3G9 z%zZ(Or!(qJ1{fx(day!q597daeuTuvTXjlMaxDwSxX|%A>;6!}p6ysZYL2r2gTh)j z2f?XqH~{uzId}RtfD_qjOrnmj4|r$Aal&k8-9G~kz+!j(L3G*~DhG4^Gqm?dlc%R0 z98Qmp>*`XWw&!f_C9WRbr_|=FU3c0qVlxfFPW%otn3vCZk9NF!!U!V5+WnX-E`r4x zBLeL&&mkM+1r$v@vG`rT(JCkwr{D;V2z=*Wjx*^w{!V=(_(g`)&jLqe3rhQiW7rf# zBZ{d3HUT~Q8BE4Nq2N#<aCW=c{Y$>53gi_%7uRegY{+~(Ka7c1Rd-<%!C0fk$P!`N zJpYzNV=k)O3V230$<nrfgL%<OqNOC~2V1m1RKhB0wXSyuEPfS|gD0VdB<=8uaNVyS zrbvV;C+a(5faEz4pwvK8E`0noO@q4D>8*z+)e?nT$Z5A;>ql7@(r6)zTVNT}EEF9} z;{it<g~!ZBfW_Y^(tu^ouiIhZ;f{7x%t}(acdr~J#IZzqw;Sz+9L{m#Q1!WVtxn#g z#9{r>J3cJ~F+Y<2{}ESqM88Y;JQs6Rf|Q^dA^Z>|e77GG1fAFy=u?%Q$iWak8|^R2 zLTHRC!l>@7dnxvEQI*w5>=0%L&2U7{nTPY!MO9rd=P%#Yk@`RLQ$@&Smw2g8o2I6w z7Af}P)2C6Fw{lUoe4aNt%J%Z&=H}+Nv-ACZzC1XXRaU05>LP95)!SjQ`OL?g>ZAXx z;o10gh_KV<*H2)7k3h|>fv3rP=w#+`?BukE<Dcti^_^~$yYNY8x>uV0GqR$^OiRy= zDPR@~6&y>+&8tTv=kSrUZ`h<^^Ra68)7#7KH&2Vc1FV3HY&KHxfXI^?q8c$b;Tb^v zr~x{Z4{XW6zxa9#;>Tz)^FgY-e0G0$-xK!nk;eD6X2YuI^E0?Ug_H|!dDYgMB7==d z_$YAb8LOC97BNQ)R4dC^FwK7gBQN>wFqj?u1?CuPn=~jH^X%LUIukFnSrhf}d_mW1 zEjR1?{gl?#ryDfKJ9v`k`@GGzyW{O0(*yGmC}WKeEjPGTtoVL<8MOQ7$6PVy?(fnZ zL1(5T_%q~Ok-s{k1b1Y9kXCT#ez4)#9yE$+be!=}>A^A|7M4P;LNtEoQaoQ!F}HX( z>hEXKflqO<Hgq8}Aq1qkKcJ(Pd~`Azm$?G*tf5!*mw)FVfTex8J;rsp{0awF?sLmS zJva!-+)_m+<fYJJ<Kl~i1{yt8xQ1NRps_6lg>S<VQu!idd#{^s%)(8qE(kd-GmO#r zMMB51ThLDR`l>D*rU7mQazeC^u%zl?rRlmfGNR0g_6v6r21>lNjk8QvA1D-sac7gi z<zpd<w9JQL9`#F#6v1h|;Z6*_NLOsTnnOfN$d@Dv72Bt;5=5r(#Q_7uo&P~ubX1_r zGHu!>3_;b$KW(e56j9=`|3YwMK+@rqwB-f*B$Ob*r<Tp5AIuEHCdn$0_CPwr7gQg5 zK~qBG9cRo$Y`AHVqg@KXqLTgKMcC&-h~y=Ar@Ukxc$^eExnej=J7s!Wav6)*16|8t z_D+4j1=BVabemV|Zx6uluZy5kRpxiN@SfpNk-iMjO%E}^;nI6T=|vF4_+U_GftrZi zXBcG@_B|AyF9yJ<G{xZvDK;Nc+83QY2iWQAU%)IjDIn(p<0Y2V9vL~u)Fw(v@y|A2 z&Jr~-8~;`lG~+&!BK|Vh17;>Z4}`1V3rl~;r5ed67Yi}$s;%|rgUjtkPwt_=9~(!J zhl3&zir6B-DI5<ftAan>D}V_HNmpQ;ip&K7F?KC_fF2f#caj<M?gm}@Bsjw|)D6q0 z4<q3GNO(8cdo5V7&$yY<9fDlBY|(16VGn{cnbWYZxD2Cjq{;ZUKDdM3TvvpLRkqnP zE&C@AM#e~wu@?F0ru2pKuxuf2)fBwXZGLQAQHmvDCI;XPxS;RZI?l5OY3s{@RX|Ty zuXnJ+lQGIbLoxicnP%a3u}wJuhac~&VqZJ(6Qwo35{?@<V<eXUz~2jVH<%ykvGfLX zXChd_1DKJ^H#MkuC=UORglw$Yyvw<mlZaE<ymVThoIWRwM+=cLIqGH!n@~;}#Zz2X zR_96_iSJpjG@&eWXt~{RVtId<4E@HBe8-lElz_jvx)&-myKdzyP&t{)5OF2VMQWxj zO^wl#le4;sRefahL3!$_f{dP|Of<!%$&44-OGEavXIw*##yBq}>%HCt%*_OlY!PY= z0l*|WXiEWb2!8EP@=-CBlq7IPVE^&CA}y|ODkcAi`;0Qx;NYc7`WPn&`O%vAzWF$0 ztcAMSl-f`Uv#SW5N{?OYEA{FKa$1cR{4`PFv<-bg;*l^Ic%J9Q1ctgN7wXAY-~TKH zR=8{^qfgl#@cXov%*jX)C{WWA>4K`;B^rl9W~(t-GHEvGHVh@f!D|G2T<{WQ*<s8J zIq%TPRs8j%t4z7`r%#JNpR<tsc@q`c|2Lnr(2_~z)~s2-)`6ldlA!rFdv@>6uC9)b zx39L}ZiQaow}W4Q%O7`YL8r`5!Z&4jpS!&~RL#neh9g5OWp9vDZ2z_U)1T*+azEvS z>c8=oM4jHB0wf9#EwoEoW`Zt<4B&I#(h+3T6BsRn<Q5ZufgafVnctE-zjmH`WYfd% zxA|^(dw*^}*H?XR<g?Qa|Ju7~Yn0?;aE7OXn^-}(!;DKHm3aS!>=Af?&ClQwj1QLw zY~fj<h_foFy`jtH?fG*5c%IJs8a_a;(=!sBOr>r^T0X**0&tnk(Smg*V&{EV%XjQh ztysZepF*`n-vgtS1f>@CpG~r=In^{4Q7JQ@eOq<{H91qL>GpQKJF3Fd)#d5y{yw_G z^ZP*+?0&z#|Cp@Wc9qgawa_>pXe>Vo-!25(rvmO*Gn4Cl(XARFfCGx5m=C9>>KFG= z%__X0>VXnmX(ppQs@`1ZjVBXbDz}1be+8W&h(t>#0>Yv8YIFe1p#aEaB~NN$O)Uu& zUvLPCrq^Ys{ht@0;@tVLWjY<~-e~~Oqw%?ZLSB+=4;0~tmYn4v&!6gqLS}RA$~n$( zJKeka<T%RiWjEVyM!_D|0(74#5lo_SsN*}TnVj$ETxP6rwWMzDg4hLm^0-sv&J@}- zlBp<PH8rlGGR7``WmyC<*;p+ohMls+3bb5Vbh3rKQ8RYFL`_P-vw<wxd**=~jzPNE z1nzQq55_^^FIgl~mq6s;zr7yd#9PwFG5=zq%C%)2A|R_$zX&9`!c{g+W@pt8U#3{1 zK#K`d^fCnbh$>f~8*jG3WD_q7IBGcIK)WtlP-n|X27NRs<!{4I4&U$MbEj-KdO-J1 ztyZdv)%^IbGm5DfC;DEdrBCM>>Ga}jq!s{{xB~->Q!S#A>1rurLL>9#X`7gb4Zut_ z?8Zom&vWE9{64JV`By`PXuN&G(V;<sUU}&7+U8lu>e2+D{51Y!Q9M-y&`h%J!GHF4 ztUge2yxTjW9|NV$7v0Czh4FuJ;FQwG9D{egFN1SDmWp^-b+hJ}5w*z1#TldtQ5R(x zuR{UMOAAinazu7S7mOX!uX^wjjE7-kE>Wxl=4^$fh!U(82ABBH5HmU(KH%d2aj)Z% zhzcc0SI4mIoX>PQ!0FE`Y<RJSrI+?MI$K?`7bJ5QAHw_!Q8!)LT#Tqb#G%f?<!3w9 z4?BuK(H5KaT20AVfHK~Lm#kXH8wd3EHmUFQDcU@WlAtGO&~U@frOK8?4^`Z<GG5-8 zij*tWOkkAk?add}3e;GuMI8dj_;r~-E6p9l<Iv|cYDeFfV>Q63*WjsoOD6r=<*L(L zjkyZrGchVp&l*x)S&;D5xRwE~R_|N61sz#MPUlZz&L7h!@P47Qe3&lamMf*Jp70Y1 z3m&4UIN<zXJVKfHG8D2Nx8wVI@xAG?VyU?JE0_rojQo2(n4K(Hqgbt^fR`uoY?by@ zs&N0t2}kOpMPEp20Bp&l6w}`gtdl=o)fHwOdxau-2XMtIFrSBue3FgV_5&Xf_MmYF zI%d>yDh0Z>56re*cMsKPfc1Gys>;?OhxCl+h3J^jAydn*QYRxKjeDfC`3VEfiCH<T zS~P~K32hj|0E$urvI@HsyNew6EqzIE=nr8xH1DXDbxs0EKj_YY+NyflJ`T-3P)e8< zj*VNd{y^M4Zgoyb2hbAPXteORY~)sSg=VwUw*eCjFUi8rW=V?m!(=oQx_pZ4ARdm0 z2&Du^hYzJI=^b9laSCGNp#Y5fao!N^KhW7KwD@zx8B*D6LpM#rviTS!HP;gyL{V$* zd!3KV`3h=Y_^oqgZHY(XL!H>QG>qK)&-r7h5;gFPI{}IshO~nQE;eS6m;o>>==Zm8 ztE6BC=n8*7zk)f_P`kNxWb34)q}&ZpqN4-&tkZ6qbXlieHGb8xSzQrkZAkci98bsb zeMtvl8FF(NF(47LKFG>tQfAK|NQfKc0wu|XXXecb&r&CS5STS?AvW>+&>8`Y#_4Ys z7EaJ_auvb%BlN0(b8Dr{_%zBIF_*Ylb7Ikm;XMa#n*szD=!p2U3OCiV29pGPdwRcY z-u%AC^?E-)pOfM&c28gVEznKiP<W8YF>}_FmRgjyWtTN11fC_eO13%+VDGiow89_S zAQQUfK2qVsvQB23ocelwKGv($^m=@Ggvm{Z0vBf~jjh!^prS-IWcYwj(EX+$m`f^A zB#<>Ip)^u5s9{NtvBa(!ZtY7fiH<@39x8J)x(o_)Px>XFa$M+ozwd|L^zOdkvdL-} z$Kt4YZ>wBemoLm?{WwUi@2zeQPRq1^r^$ioLXERmW4bk7@<yORZ}6@SVigTjRCQD| zJyYhdtg5I3Nn!}9gM!hFBqPi-f+msdH9_+;c-D*hV>Pow`UUly`&baWj%W8g>8}SC zHjc{<&5S3qbvpKm73NOPBT3zH4!xfVpV4{7pIaO@y%F_z`Td-*wdwVBzY%uI+a?{8 zd(>)}!uD+Xtbt{VDwRXAemqsS<?41<@}#Ov0Nc{?wyVgPY?{<ebyj*>H%!cbq^a*w zq6bvBN46IV*cqsdCYUkitz0uuQVnPgZ#l{(x~3u3OJGX2GuBJ&i{gLESiTU<2RGUQ z@yW|MP6Mp;+fYE-!VRGm#SvhwZw~wtxY6xjezt;up}2gvT<=aqz_<0mr{(*F{$vf$ z0Os;i6e;JQ$AWqY`9akg)b9X9f$hnX$5N2_wOjTg|8>B)vV6m!DM`O~*tXUdye0W6 z;t2D2^!HuWUyjX%GP0SaCeNL}s3N4k#wZNEk+qJ>2@fows2y8Bb9uCcxzrw>G0fE? zZ@$S*ZQZb=OmR)2Lhor}g0;>h$i=JmmUsx~n(*YtD!s@u+eBJj^lZyzl=WKaJqdJ^ zs^%B66i3=N+5ehHqMOkjeYJ*EBtbF}E@EL7)#+|HChmO&TCG8~uzyBty)zHRH@=gT z7)Vc<&Qyfa?IlAF@Fd$GF8Vx8y?5A5+k<By*4Aa9_7C?0|2y)*i%kVer*Pu{=^%CX zuepKSp^<&~b&qIpi3B-KWyew(z=DYa>Yg0Vyj5q*lv~nD^VK5!3k6J1v-`#Wbnn2N zpc2s#<&hxLM(Q{lFHVf?501#hmVS3<IYOcxsDzr2ch_}MW?fp+VPjyAQVQl4^Sz3m zYT7Q?#0<Vu-TtbA3+^mfiMNTh_jh=uj)kL8u7Vv$@DZSpAAUkBQwr}#Gdde`1}B_q zH2dWvLJkGT3*F?iH~6NR{KF5HD-PoOQaahUBfues&7T`zhtFIK^r{r#KhExz*4f{r z8_jS8C#azq{n6)fc2>6Rr<~21{;q?23i>6q$?<#zh3Nei@tOns!_u7J?z75DvyOQr z#t3|WIl=Z#MQDcAh7Ce{{w!ARGJC=stQnU<G|rhToI0tB(G^6>I`YvL&eOgEuka&G zBpG53aEBNgf!S}hK0ADMOY@HEgrb|K7qg%O#6YW_6KTCzX{<8}V4U8?f1S>XtQd@w zhqgwpvUF@Ix0-m;KZ9Opn)&3q)o%$npRCzr+E}Fyb+vNCU36}I)=LL>avPt{ZB*~? zDRUL`^ue~gZSB;3wnN5W;HooEx?uSuHM0=#DF0C9cRx+30=B^O)8x=VJ}}I(A{@19 z8|e?|=zI|*=9a7;z%5qf_@#o_;N^sB%zZL5k6;*m|5t{Svc={=2-P6giZmee2Q+F- z4`9onf^qy2fuje<z~>L7-iJ(Fb6nc?R+d-sM$x*59f~2S*tU$Yj(l34?V|;F|8E89 zZxN{^)jddLhK|wPJIP`@{7s_|B&}LzJ?J9tK+fJVP51Q&*z!Ookz3@tc}t)ocCyF9 zQYKokdGlO(?d<!GjSi(fcZujSFyGNWeFxInGr?2^sF+Bu%ab$^@z{8<iOAH72Z%Vq z)NI&I9xopc_ovIxN!F%T(zs}naAVa0ge6P!345avbws92jh8BYnlVhg>lpGb=|7`< zo$@IahG6NDI=CLG9kYu@x8w8k<KyGa*-<|}Z+9<0KNlYzPC=i$L82C?ra$cZr|6>4 zw&497S6t&kg@`ir38-%?qo8+dB{B&s3<Q>4r%3SDn9bZ1M_ox!`XkDZ6zHPnLmo63 zl>u2mQ<h7tpvaYEq+HuQonLr(h!89MV0Jk}W2w*+h(V!1N|Jj+0s&;d@92X43>jGv zB%A#>9D3Y^PW@#0k-Jyu=nHNnXWNj2;LZq;`Q<eR>}(l)7VdB;ZVmuFscN(5eS6J& zp!zbSw+GXvA(l)8L-wJAPTKlnxrekcJiXnYyV<U;zOYY~WucV1P8Y9>%tQiy>wi{H zIn;B5`Y~)$Td>36&F526;bA<6%b_tv;quV#kth)%_EW@X31)oHXgHP}m-$GHS@iS% ze|KnjmBlbA*d--^2(64I`pMU)10E1aoJ5i!8-}t;<wE~4)N&L6j2fz1ZVRtNcRgIQ z<B8PDU~yZmBKXmY1+`~|LnZZyM5m56^plz0c|h)<c@Ol$jV&KrLlhR3z>l%eP*4c= z9J|AKvhLdJnrBy-Fmza&GpbCbI_Vm5R$GB|z36)Wvhi{ZS&3NZ>91Vt^!f;VF@Uj+ z)F_pu6$`e&<RN>>^Dxn*Y;;LygL5@%uMSV9(2!sSOU65c?})>#>XS>V3QaftndQcW zp7TS#Ys64*=(lg0exk=%ic!)`Bm%7SY4&XUCU+c4D`qk0K1JN!0uh`#z~RE>oZL<R zNg}~He<^a)C*`jtrNgi12I6uR8jF*TYU#2^Ag>P!np-7ap?d2P6YRkaA*C6xyL2x> zNMoLu<YYhX09WM#M-jc`f|H^<A?H(pfs>Y|-bY~abTJ~o>H^0YP>Fz4{ZONCGH*Fp zPs9{nl2RV@q~l!WKqs7=XtJU^GLK|z9(8|ux^7+A&@LoC1+Pd-fL`sxhRDJP_C(6P zCw=Xxpw)Wr{+)CeA;@hN28c;q;xtO8fLHcxGUO1LIH)R7-*K;O`sp1WD+S!~HP6bd z_ASw)IvxE|78*Z)aQ5&jWeUsI_WS~V%884^vw5H0gAvS&F)Mk<UIct#syC9Kfrgh| z_f=-yP;R49qA?&JELWo|Rc=0l3;>x73eGZHIwl6SW&zR0Q>T7!azS>yjwjWfGJ%Ih zVS>u^EtU*6$aDKM9Ez^5jJRZ&#-*PHZp;@v_f3(7!We9A#_NG}LfaP9+E+PvC>ejT zUzDtEJ&8P?V8-%c+~aH!<&Gf?X8EM$*V74~lHGRVV`6CVUN;hhtB4-*Z6tA`jBaF5 zSMGxES-p`uX`AAEgu9`=jnlTVUHrmk>C@{QwI8@pS4Wjz;ME0ts$tPIJB{M#t`nL5 z?3rW9nw)EQ_zh2~qN3rEmGgSBa6Cy(o^Q~F%H_6;*K=nHFvsIl`|8SJ<K<Yq`>q-4 zcj<NyS(a)V{RaCVy56SaB0a({OMVh%qBsN`4D9=-$lb_YAIiiNKDET;nY0EM7>}Pj zhd4$_E9Tm4HrEL#UvBh_{Xd0qKac86fpKdSRF+PD#+zsf``Z9%ad>Tfd&*d!dYFz^ z^_8%Uk61pU&cUiL1;e(re02b)t->uKhJCV=2r%Cpk`_atSK<68raWf6CTlk_1JQ<a zsg*q_=0ni>tQzGlhurX83C3<GZ{P3l?-#3+Ul&o6QX3U%8R;{`Dw*Lxg9yducN7sx z#^B6%$+pVGXNgTR6a%@A4GA|Y;>$o#<8oy{4MWNVD+J3H8zHa1eHGWo$D?g_H@v=z zfs%FP1>l&U8(5=AUbf9xUz(M5FCy%PBIv5~AOnDA0SfbDDmFhCQ%c??8;;mr_SIJ| z+Cgr08y~VBMNT%Wdmf96^)}fG>@q#TD&q|56IEOwHeFaR_OC!7wxviWbf{2DbK+=0 zH}DEEi@}{_a~SlW!jWnIFpd4RaKTbYMp&~_GuCR%M&qBz_4T)r=@_hkwLltLi(Cb< z?<Nw`13SfxPg!D#K@x($p#g}BnJ{MdWB(Yu5XKPAGgRo}-7n6bU4PVVZpy<gI>&`| z9A*jmdiVNh=yvzL(w8daL~7SWA(*{Lo)0&TAR67s$zU?J0ze~&CzJi!z=)b6<goR& z=19`?pf=!(l<uF_UkAkZqjfk>x6|v__RMzgtrwSrsnon!B|uVXNGn*e19XAlLMVn% z&h>$)gl(YqM_7|!0wFR&86wD?03QAo`O4snXKHw-ebtL+7OA$D8CeN1J`n$5cDjt; zIjIx3$=*nt6#|PP5RRN-63S?Gt2GQmozPC7NL615P|&U#HgC4Y^v$K10s`Kg7$5dp z@ka?xDt-C*THa)9S>cwEK_e=UXNVgGu=W?X)=LE_{gWST7MdL)LoJYLu(vqk--`a% z<A^oKkc^Y+)Y`u|0@Mwjtj}iE7Q|=IBBeJFDdLKXa>TKd(nJyVHyAc5!M=863^E@o z{Ei(De3zCd#j#uBwDK$)P=sFns;%*v95~8;$Y|8x6o9f`Qc7RSJzFh~=mECZO4b0f zpepK!1!B-o36v@oV$M|5Kbj1xXa?3h@OuRZ4rVTWwJK$Txm|2W1Yf}<`z<<3;s+I4 z3!FqCat8Qkn=}Q8ja%qBx@<8~yvI$SJ7evK8H)*IyoY;t_pc#nCX|9rvkT%NC_bO- z7`bL7D{vwaue=_by0ZzAgsYRQJ!G)at!@=(a#>V;R++%PB#IBeUM&6Y-7O5r#_!l2 z7Dcr^mp9-}nE-6`^>dS_E%JHw!EY&ar+wmFkDTPBY?guhmYE*uT^e@Z|0%=Q-mp)A z_0)wMA}ih~>&|G-yu|dme4oh$z!hS7{H&dxnWqp5dh0yJ5mr8$m4<iS7(4#S+8fwP zf-ANfM<JTi7*%0<r{&yyB9e=F39S)sStEIZCwrXSkbzsroNAwXUk2%{Wqj4}DCe~r zEzsvFWO{LSokHqwyaFYTAojbLj{e`6z=m<97yleRc5qbwHrfzM*M)j(6BR85ZDEZ8 zD=oA~+Sav!Pa^*V<y@I23uv_z`+SQVYD|PbS*}iioB?&;m^00{HJujw)PIVVZMXNN zj0Wtq#>fF`j1Ogvbw!6$1spL?-)q?N&!@#N5CN_V&Wz?fSeQmI{%hgVk#am_g&`5I z*#4tN*<`OMs}h^A^@E~eoHu=Gnuw{zheY8G*_zV9pNU;nY}+cGfO30#YY(1(bG38* zfAcM7bC{8fGpgO~UZ7PoWKZbVa-2|x6SE6P1RuYz{{qG=ceNFKcIf=8JN;#zBe6T3 zA<*%n57+{5gx**~=9z_;hgR#@$Uz7<8g^|nU=Rsy%D(^PubSEJfffD*$<ECsEfpv( zJ+8I3nS8yyail1&UOkk_S?KV7ze6wMZK`Ugw%SE_CuE{9N<f;8!7fN=WDHRg(Pl&3 zt0o|dPw8@(f65}8g_7(e+yl<xt4ZF`dP%krYp?dSlwAnPTKH%QI}45g#mFG<9rXi< zs=3G<n4mV=190-rVwi*<RP<7oq*zTj#emVWGc>B1M!37WANDkQIKz8lRs5`tt=cmt z<e3LZ1dCd%1ip|nZoSi(5>dKo+LslNKAy#;;gOATy-X992|Ljwep2x=Ouk`aiJ}Mq z?nf4wYu<z}c%6M_Pm;*VJ)i=#x?0=lZS=AxzN7kOP~8T>H~7=Y9Fs^`RGyB4LeOUw zOa-&ctuo4Wc#pvo3f;y-I^>40sUJ&=Gn4SG+L+SrYp%|I?Cy8h6-RVjO}6o^@cDVY zeZ7U{?avrp9v@QiwMPN)ax6J9sW0B1UJqP2Dg_+xU68LG%2s?x>)KAq58!A>G<0XX zM=3)qt|jB6mJ~L*1|hnTYu(voY0lFO#plRLVsgu=k9M6&OGqrGYWRqRNVIz!>$+*? zOpDr?8qzUH+dz)<pe;zsZmAjZ+UJ%|Sy0883`rf`BD%?L&Tz|s|08BLgZxS@nP8mD zZ&RT-(k`$g`+2ZOD>4kY>-83CYhCWV9?e~Nw5Px!6RK)F>Hux-X5!}I>Fw_3=H>0} z=|!^DQa21>K_jOgLBt5PY%eX%pXk6i%`Rg+AtY~RiOeMj<lH>z0U=o19n0}4yV=UI zveyQAzaZ*XCA_wlhbqn32<bS;iJY9;tA_BK(aECdExFV=@_b|lKYkOxEm<j9u?nSv z4xlRD6n8PqER(!BG2M&dZJ3I_$w=5L1+mAM<b2V?mL)+Q14lBh&bMzhhwS@Q-wXMR zEi7&--BAcpfY9o<#Cp`N_V>q_n2zvJx{(G+GO2=q1WH0Tbb&%x;l2DGKZ1EyfX5S9 z5hK+$dcj}#+8=eWf|+VmPp|JQh^G=nS4T0}k=anqQT|~@SA8-F&Oq%nk`h;#nR}gd z2$nO++wKelz1u7CMt@U@ed<`58w+kvHR_-^>EERrqG6fou6C<D^lEqT!%c3{B-zWe z4$S*!?a#w*LMx5l`McWR7%4bOn+4EKwQ9R5Pt#Kk)G{owegK)Y!1d9Lm+XnH&1y~* zW4ALB$U1`wl%qKYH)~Z!<jU0c$v>H@7xL`0ofM4*>vI629vLkI{zs4&9K2|zE&%9P z4OKN`&<U#`k&?`MebQ<0*>j<5Hn1(j#$kAbyV?od>G`LoQS+dIGFI^n@3D9$lkbz5 z^xU5I51Yc7gOr#VIDqRZwk^K7C{zwSnfNHNw5cX+g!#;_+c0?ovUjKRS4nTzTpodQ zZ}qt!Zq3a5w^D#0&n?&rx?HQ!o|(~caJXcWnnMirxnA&=Lm<TN{{C;aP>yeKyBAZ3 zw+#?lE3hvfms2+dH&F)SI|P%1ckR$4)3m<SB>w|0%Oq|7u0wu_23J?Zu9xGVpV~|5 zGA4_rESZ&7VWd-ly)+y<&x-;hTvuu>O$iinAow_VH-Puv?Y0ls-Rn)C4?a6K`QsP& z=_fmpInE8oFZ^q&u2b`)D+b(3@29s+cFiF!EUuEBSyZNHD9z&;nj7wQ+S9&&Xo3|` zihkzb-XVC{D<-Q~Xx^zcZuM1VJEQJBis0?X1-tdN=NN83Y{Rdki;I(KbU}>!y?wpB z*Ds5<rb7=85ARo-|J=8xnZi<L%sBf30&)YpU<grbPQwM%95e{R4MFP)n-U<=lMnE; z)GO~&h{7U}1C*~NJEJ*)M8P2yJE<{<X5dHVydHUj<1hRzrqn<vV5s&wH-U0uPi+n2 zTgm|!jSaN^wIrvd7Ulh!t#DCP1k%ERq>-<lf`!GCt}nEAjI6&2g<Dt=HC^@HWbwqN zj*s8=B=z3FbuhZqG(s>bO=y&a-VTSl&c>X3ccr{N-ty&~`W_S<sQSb&LVKKiGE26t zoQ>R;v^TQ%ta=ZX)Dj^T8vyl)BP2iLe#I;U{3_Z6jjbZaS(u<Ow_&)!>RYvX6G*0X z3?=>02#@{-jzxw+8;JYuynYS<epTYkvoJ_gg*q9Mpr!_|6>xt#6Jz(&(VI2E#B?>( z<OQk?_oJoD`|;)E{Zx${JVL{d>4mX7Sx~v?PcXuw)hIxcOF?pbdvci+o21%d{G-DG z+1Q}Z0-`k(*>RqFG25?*BCbz2-{x-+tZIbNuuxhFV9#Py^|MHzRa2(+IbYpV@5F*i ztXM!;A~;mEx)B7rB)_jEC>n5-{Lh-+UO7Qm${vzdtgzclBdFV)M92bCXb~latWnY} z{_Q}NDwIX|z%@?1Y%B!4{8H`FAO`9OHWc%ss3Cw!QB}%fwxm64;Z~9e>LT+E>90gH zMreb5UX7RhH3lU!bri>~0ox5cxS_AdH`a<tW~l>)h`c*S%qBHNiFkPQiucamp#e_F zDK+(hgSFW4!I76zle{8xI;WUgP3^)?6?Kpc^P~i`a|4v)-{V0!E}LHRu7}UtJA0f` z$W>6Kd&)Dx3W;DtJ{h+rjrDPH=~hv#_!}Pp2;nmErUNk&A84EG@F4TXxXS&Q${>Rd zDhp^D+HwimV8xzAGY356loqu?Dv{r|i0I-*3?OINlgY*rX1I3j#xYk$)uuHf>L`?c zlyLdeW%?MwMRdoWFcw04afXNvcp`S)RgpR7q&CL+TbSXf9!?|z3ltL2R)dMt>b3C} zruog6)!)2tJ0;*1y_<8j<1B~VyoK#jbdZ%@AK8Nr#bvYYrhD+Jx$Fan?Z3$!9ey+H zEIUr}OFp3dU9Ot&9b=w)Kc1qlKE18UW#k^Op*p{K%2GQylpjO5*uYFUBpvpgaO0M^ zrC&qo|KsVMf-~#dw%ypa?T&5Rwr#6p+qOHlZ6|kZbnK4pmHM9lT{W-$xiPCo&AP^U z9!GucK>uVe9V)LGrsRN8>qJiB4IHhLeY~ADmf=vLX4&+FYScnQ#Vd^r4h(x#QHXpB zCN26h*i?H<<{$-nlR1sJx}I5jQ*@Yt%H-KOQqhW60NVDE@YMca`n<5u>n{`OhElo~ z(6UKS^=0$cf2#5?%iub-t=7k09Ab_1sI%(6iJPlHYUWTlJsu{G=R;^94p!5#n=^We z{nA&8_)HaIL43bU#^Sxb?!C?PuS*`Y@&pvknC=?zQM+J)bfq}h7i+Kh`xRCJq>{MZ z-j+RkQ+&l803_{>5r}M*%&jb|jqqBt$<W+;=Fm!&9~;bNKvuwYZlauiOXbxAsiuDg zJjC|5*U_$SY?xX9M$S==3&Q`;@{Pk|L!#UCow%Zi01}c+M5_Dv-T^{9gcbq=PMVf& zV+gIBG)wokNcLb=FUrlmx;(S$+Ey!zo9zIeYjd~xZ@!0~psUv-DBuDdAfs)FY<wHv z^A)RQa;ElayFeh|P#)6b4BCoY4mdI<lIk9pRrrj9Gni1Cs7VCNhR%z8tEEEs1v@=^ znM}gV8%N4xGgg=dOwfiWz~Lwh9iEf%|1N-cyLs;*?)mh7+}$hq_q;wn4t<7r^5^RJ zzNx#Iw)=nG{NTiqX<fMv+y{J5z?fcsyO#vjCzu*RaU~L`Zng?zu|}3B^*hG6u82)v z(%?)>rK5@l$GUZ&o??{8x!Za|?B)BfdieMKD4niGFpaW8K6I=xievP38cun4xOsC1 z0jVWLeEtQo&AsPDikpG+poJe1sdGPx0|eLF_z++X#u9cG#kkDjWs)e?f&8e+3`hQ- zP+nKfAGIJBn5$`<8J_oYuGe{s9l2S3+1Z`3Cd%oZXf>keU{oCeAxU&#m)`6mtI%LB z@z6b5kb+2rcoGyqW35WSYg`CJz<b`8T&3A=ZWrQ(EHASc9}h?tCP%Uqs?2Ys<wV^t zrZi9SJr#$OM)JW>DBn18F<B<c*||COC%zGtt-}5ozmWtf4=*7|>SKYg58rQlgS2H= zEx^}<_)>`C>+WyU|78J^`3EASwFTK8cm6hI@nEw&LnycT5z-!14_9I1e%0?Uy`3Mz ze6kF@C-^S^tEn@t@n~H&8}Y?@mMYB+xZ&>6Mj-}WfQDMl4&IVu-2frv`%`4a)p!c5 zN0cONEM4JA4$~YV`<sGN>Tjkh@*%>)QJ;K>I#vjpJb^dvAgdfPvL|xH<m6p1EoiRt zq^NJ|xuPP2%&hT|&uvv|I;h!@k{rp2j4TfcEi5$@EOuLSC)_%mIk&60;{}T{!AwUE zzaLWHQX_?Kx|J4@NrqHH7?7>IVzqdXs#mc}9+U^g!|yB$aZZc%zhs;#zw~?|&~5D7 zPz6Jyr>EyG3u<ML)2ulbu4-+yR~{dq1-d`pmi;;sXkp&djSj?(Yjm}{M}Mwpqxdg4 zX=0yGB7*-Zn8HQ=>Ogo~Uq#(}1CM4VJ!A7$zlu{El6)-oJcf}5FFmjr%+-P`t^_8k zOrVQ)LuyYmN=kzEX!zJOQ|QN;>xl5=Q`|!}%=*Y<T<}C7QAa4M!Z)wjuOBN#Y{HD{ zp%1XQqk}&pOA7?{F)c(qmn&Dicjq4QHCRa{xccLWEv2>x&xbnAI$vnkvrfmzCpdMW zTgWKuZO;o~hOoAz!XWpLk-u-Zec<1wW4(l%lXpxNL70Zem#EFKg^J4iG%($rPY6U8 z^8glvFG5W37kER-CC4=3%h#<fyC#*kQ6_ajEtER2g6d8H0*KchwugdnGoOZo%rYdi zjcv2}kO8&ES0h1(FL6{c)HHnUBks8}m+C{N|8hZvgfusc@J#4r2e!#HE}!~s<54_i zl67Yvsax(dW!vQ*%J$II>)7@m$#HM^L+w)~ZgOn`>=k!0uxcH~q7<{9g{vFTccL0M zqgClaVJOQBc=9~<r|h0<Tx~jwK}@905eqKlHzx2Kz1#LUnq~*hv#PO!Ll{9gz#o;g z`x})7*_D}(aDHu9(KhT|N0bAJ=DQ^)ihwerf43&#f_rPA?u$$ZyDuT)dBb!jh0{4| zxo{U26Rs<8G;b_dPNFO`f$>iS4DYFRobmxcH-z3Ai<^?jqVG1wlwfm>kZYhDpP-Uk zKhn72NP&Lf5-2OgxHK^-^S3HRH8(enc)6eKDJf+uC5y?d>ko_2>+u{$&|tGg@Bijg zAuDZuEjj&!qiS$<SD9tfZMj-q&`SPEzmQWX*)6r@Slz<_OFXaTm}fRdMI<iL6z48o z5lZ2?6N?51D(>ZBKSGMV*i*~y2&j&3%4_h<51dP|QVGu68EvfZfplW?03NVfpJe$P zK`=Pb&G+}m!`buV0aIC<M;ldOR94M0_V>uD0p0b_(zV9lKMa0^BjNHqhmZEk^Wyqy z>vrW0Xr`;(h`Lf_`T}NlcG%ptrV_>_NLk!zce1i?`n7Nbi|#DINwCu`Le1f~x0klS zx0{z|yZ=34?~7n#W%MSsS4pDM1GN~-uom4Hy;PxfbK`X~?7}$lA7gq!L(NvZ^PR*i z!)itasA$$QUusg&2WvpQ_cRp;8@?}Qqm@}B7-Q=~7xcbkSe=?#UUw>I2(p+4e%jfV z#VMMVe)#UT%h%;CV9Z(gj>{Ks7`{gFAGUAWW7x$Yf=Q-vhJ$v6E6Oo>0>M<Qo^Ase z7u|3eKiH3+@)(^dJu|-F7$-v4gkvb#Y+NT6JmEl>aZS}2fIA$c)ypPQI_SCPT{-?@ z&vvV}W<C1vP}#Souv1Z2az!BZrTs|d<KSWQpo_5g{V7+}{f%?D_XMZBVnwHM#u+Y^ zea&L&dQ(W8u1Vhui!ORXUlP$O__utgMgv028%p#X43~1MmnsgyTue5G|B$#`RWE@Y zcKfxhIS^dYpDFl@Hn8|zNeU&~i5NRX+V!0|eS}e@d#nR6TJ)&&a^`7DjBw6Bo>8Of z;?^{Sp#vKcQFG>nG^GuLjB+dV#3eZqCYLB-1tr6HR*%LhHa<+Pv2y+@GHA=nD%1>I z78i7dv!zo6q<~h&w;UIFC_7xjH1lZdKwWEju0OJ7>`Gi9XRCSFGDJpkf~FQ9zAnMT z7G%;KKpQ_BDC{Bx*mV4Vc1!50le1pJ^MTNOxDVhR>>oX#*XHTl>JFFBg!~^bi?e-S z#{6He^=Zb)>k@8P)@w1W#f)y06NgyEe`KPf20+dskOsxKEb{NuVI`zA4>m>d)-|ot zoW9}Qi34Hc1b`(-)^0l7E4l;7Ew7-CEjo_1f2HwNr`a@f*%*-g?HxjilZmLP_hF<F zL@vvEn3Nl|L~pFm4J7wO(sGQ}rpLkzw3ad*64_%0cdZjE3<bOLwOiP+>=$f*T@l<c z-eRAIDPpkc9A=19Pz59=w4*5>!16fnc`Hs`*>^w`ppz6gT0AjM*XtbrWAaFxsN-@_ zhen9O1O;@|um1gRZ@%s0sCw##y6N#V<q=4CEx8BO;dzZc5Tt{~N^obs#Rxg7+8t+j zS!EfPY9tyu%t;sEbB9=svD#%rl9pAgeTb=n6;1KYpLv$63)$7+51TE{Sb~P$7hsQy zJ76(z;IXxP%X3nxRCX9TGEpQeM>dq&I)~8-&$vZL@SoTkhtRDnZ#M#^kxT<?7QSb+ zx#_K9=EYX2?<FYayGw37{(GqdK3i0Y?HcV;luv>KFOvw9o%gE5;nRIzFlm<kYB-yL zo7IjqudBzpR^`AV6~1v8(GIxM`;{+DQA{o6^bcgHGVTLI5nuU6f1oFoZ*`E^d1DXO zvdsCpt;ZT+c->M_n4s&o1<+Vh(`w-1o|j`QYOe$|9go7nj*{{38tF^@EsuY7pSfpE zGqYug91hH*AOBr<>uuWqpaHjW)01dG#e)i@-hn^Ed%?zM+o%%CdeMXec*&rm+U=C5 z(nPOnGBSIn7hDrpfwcQeZ6i}eXXrg<bGS}G1PwO+=>6aLCfkAAA4_A#26iJbxpcHk zHdp)AW?3{n_PrYA;8jG3lW!Oqt1nBIi?1f|R6e7}gwgSc%WCPX;l5dej+$|iXXBy6 zWi8LN;+!LBRQ?hxh1ixG_TtTS$$j~WiADo2Z~x-D(G3XdM9l6}-((`geymcikB1e+ z?v5n>dOa(<sCr+-R+K>mYjE0HySVUd2fvNIPdSDz2nU`&xs<<t^6E+s23Iv~oagE< zzQmGL!#E{C@N|(D1GUa3W6xa|Xyy-(FP(UuE>4yw>&-^|;?2Fj`ue*0I)9Dk%ebei zHIo&hfWg9F=g$9wdZ+O8l7x+_8p+=1Y-O6rXDPOLgy~3E_(W)m1d*K1Ux_wzf51@Z z*Oq3?>E@AX!-zpT03(<_xV*v>V4Ysmq=+Ykq6sqWh%FOQFh{3d#TNb<6bs}U@u9|Y zirIC&llxa;@Hh4kP8SOx3OCpU+(95LI~New`@?U8qZV9!)7O>Z)=Y-Q%vCa1Zo-(f zX-jmk^C&MVgs(?QRd9-19LN`eIbq}p_#|<z`G6w`>$g~<nq?L{2{fQ+UWm{^ajA6P z5>jBXX$VQ+g_2iT^!a#pee>bn!8-s*5$14)d3;@F6MlQX9b!u{HS?#IizLt~p!yy9 zBFJk@4k$Y6E8Qa=>hC~e>W~#Hx>t7MS%a%rDkz;EC(wQn%|Xfq@Z%=GH>ZS}>4A0| zxO!x#l52w(pq`#+MmN%xr^BuiYtvl<xf+%v7Nt_<_@^3#@pvh(07{LtICQ0$;KIn5 zeI#d!G0ENKfs-H#Hf8=Pfr#N@=p*6?S*M7DCsi{ux>_b!04rOA8Sn_g3HeiVLW00< zoZ=;yk0(k}VS#dZdR%v>OUGsdp9eBAChWji_y5T)UEc#3g9V!M#ksfPdu#$MAqA@w z>um!Lsvip=Z7w;rZ8)+4hI@f6>Zpe?KpaJLVV<)QN~BsCM|ox~__VJ%><EW2M>sH_ zN!iG=+z{GbS@8jWc-sAv8`pJyey`{2_k{XCj*sg)|L8LB*aAjzOgLm^%2osG=Ol30 zCRQwrMpGbYYN_!T$yW`i6~GR*TMKq78blu&cLwoQeq#>-S<<{A5+Zm7EMagVvfA-{ zd{}M(BNOvJ@v0dTKExS18Z(e4cIL6vOp$6}f@yeCff%EA!k<>@w^MjYNs(QO@s?9T z6gtb+N*Q$`b81cK2scS-#1?T0?9kRU;N^nQ@WH%SPwu$Q8YT)=b>8#Nehlu2IBm5o zGqN-u_{|L9nqk!e1&6aW*{QN$Ia<RLC<%LOG92)hZ8@oud)X}~>9>zm;V(+Ladmcd z<lo<pPT?s6?*Hmu@$ip(ImNUDNx$)jX!nK4!rKV*lNpV~arH=K4?!w4VVRs0l`%d^ zJb%dHQ4#8sN`h`i&|Oi&pPz4m(s6PLJgf+vqH7vQ>XQ46yCM<6FgO!QZA5X+L^dpA z3g5C0{COrxfnZH@gP=SGf?96Uvk9KfAT2Iv?S-49l`>U8@_5>4*X_I8+uN6WPq1>U z_c4FeiK7O+;`r7oB$KJ9mXPe!(c`zRKczhsgo4F$Ghye=H|QohW!EB@3H7t>YD|ix zB7hm%S|ksSoJDE(+ZV*5>&Yif*I}*iYMB<W%R7OxvRgcNtT0QgU`i*?X5yHuq$pcK zWmHo)8D+HZ2ZH<uuc{s_Ql5aJ5xOT0t2YgI#EL!!Tuan!mPG`7${w|*LEC+A**}Ur zR>h@X3IB`n>rL5Tup{B~lWDmJb<xcEIt6Zie<!%l8~pHC#j`jYOr#F$Ga#v@(-@*^ zI~h^2<jJ(sUgoAVSu6;E9*X%k{+sWfWo4jj&3pF54(ZP^ELa~3AQES4l+UK!=_YqU z`BeJ;re5;&BwN$!$vmnz&5|S8#4XK!x)y&6^T1IUIK~)22MC^-4JT~dj6_P7#@ik{ zCc-aw$5cOa_0jZ>SMA3im=w{@Q&xAq(bV==2Q$S9nHy8x>RM=v`6~I&p99m~7v`Sc zPgdP$<(tHaKva2BD*~ix%;c#x7!#3E@6A?IafJbQb_7yIC7vO#Fdv+lFu#dt=xJY4 zAw&5mi(4&RHQXiQUx?03%wVwNS_MO6?_(Fgnt7ZWByS5b=yF1-Drr^DFn`I43}CXH zDe|cE;+H8lE&5M8SG(UP2MG~9WCB~xq5R#ro>;1B&E?Ra^3cUSa9Own<P37Jk#w7w zJxVCjPDEH#{jCeSpw$3bIP+<dKeVi9`TL#W=gH646OW0epmI7(5<BUmQ=yy^9T><7 zt6pCBhobu{`!AU+s%#A2UP$vMbsp|Po~;52?r;FBbLuK5oRz3>5h!ZTVgzas6_{m; zsO8K;LvzR+wBR{WAOxf4aJoFk0TO_GfbGr2Qh)S;;F4#!Nd{GEa1`r{`-=-MIQ>gS zF`_p9qHVTmX+tdiOtWIiODM6iBa0{%XUel7u)7^CyfP;3ALS;mWYZY!);qj1%Z>{D zl*7O)Iv4JeOtXhxL(~-OHA~kPv<O@}5@b!CgkHA|uAyac7#PdS5eycVP$tGqC2x>V zN=O_O(J>R(PoXp5eVCI}CWb|bO-6v!jjJ(*LCVL+m@({pd;|+u-InSU!$}i4*CX*< z8Aa9ZPF?8hh@M1^u16o*i@kJvy%ZURJ~=mdIveSLRelj|6sZ&|_ulRR@$+i#y3gk~ z_dmqXz51PJ-?odlTDz{&i?`nAj}3Nw;@KaO5MvhdNf@!^EEKyH-@UQ%6s{iO-K=wH zISG1;OwZk_#?(WpcaP?cLwojbS;D;hKEL;l9l{U$=gqo4yziH7BE?wI)JEX}vCw(? z1C|q+5^uyT=6<jXW?g>==_|UB*{K$$Qa5{vZZBaStsQa;Qf%ZqN#(Az3rL)$RGbo& z+Q}K`Zd(}65TZ_EQPbnpKuQ$gMaG!8Au=f>ZXA-*NA*!M!{*p<DB&WHzYV>RdP_*8 zjRkzLUP#mMIfetpNu}tpkqOd|Xe2UmEG$X1V86=W7~u{$#c^bo%B4%oB8_8VLySxw z^6YC&YH;=2)f6Vog>5P_D?AgRK-ck1vjCCZNhy?5J!4bGA-2S97Y!;7;r=^m@9HRc z;7V@{lFif-{&n)Zw#z<<A-&!&fG}_GEH9HmP7*(5Xp|sTd>eZ(t?wk`IcclaYT8{$ z*0mtQM(tEIk>e9)J`6G`DG+aF&{r2`^iHr~F!|%tM&X45U~_niqPd!1Qt&XBA+Fp9 zI}W!mQ4EBhovh-Ki=|hdz{B8_M+*evksUGFV?My;x4_UF3%c*!x-*1jSZsS@EH!8z z^js{j731s?h04QH@bu8nJQ`(@Xi@~VD3z_AW-6(!tmCY)YK9aZo6I5&5b6%GW;1IA z@P9#JFQG~e9>0Aa07P1g1<SO02TReQ$K-y!k5lXI)hSTR{2YsJXS7T2)2(2%z5eU^ zfiI8q>zbN5RxG7-xrI@eEw9ZzG|R^TXD*#QFW<)VgpE<HWm_XbgYEuHNKByr{ldy6 z<FX;y`A*01A!Lit;1vj?L(*vYfkM7K3P!=I9)VDnqjhn1&1@9ULoRPyOR+qGbU4*l zHr~eZ5!C%j)c#4(d4LzxU2fF=-+Xyol2mjoLsEgAPzh8un^O<l5J2u1s2!AL7;_CG zDf^*R%ndY!M|QIx`rBIVANS*$)4avm!iW+^_cR7ndKT_RXH}NN55<G@pi`DVnSp1} zmaB-Upti_EFS(i{PaP{p=SPAKZ<Sqm#uiew+^lGYj4O<`TPSVZt$R7XW`W}smPpU& zwx=wt{MgT<zc3!IAs=U6XZ=1eFVgc#KIgn|fZLdx6vh?Af`trK82-4e+L$0`tZdk~ zem!`0?vSn>;H}Rf3naSh1{~$8Cgw8L2o6Pp2N9E@r$Wz-RC5FA(h#1k6Dovn^1<=Y z0;6Brx4bN1;9z(2kf4w}aXy!^1#z4t8e;p<iwJ(Hm;s%JAtR12f~9m{;W#$%YLBzz zFfC`DKbDTEJGpFXtxpl)kaZ5^yLg42R*L?c=E@~uB5Kn<(;;@Xur6KE3zx36w(0eG z*^loMpwr`oN}VbyH8?sleYHqqny?OQe`OC*p<&mVe4`eWh#-fjMw&ZJ78n$z;<u}d z#2TSV&|)IbRw*3@vk;}3pr8{1&?7B(op*Oa(N{oEBfmk%sGNnUd(D7z{4rWEZ)GPh z8_4F$Op)#E>f7GA9^3u_iVML#q}F<o-T^UF!YcX>M!3u1V`vW}u#nL$ijz}KZ7D@) zrvm9rl3<KHGGj|_a}q{D4HiX2wvcbT8I^g8(^c}U->v)-q!LX+j<_{_9~u%;C<9)A z0QUN@PQ<8E+(854o}>(<%5oRaHJ=u``4pxG!sFExP3%9<sWJH|Y@!G`RUt8h@x9~Z zuvD5Jw;C<MBgf(X$7)_^{j@^@!Ea5GfB_0amH;QbZ-uW_d;ekNOjx@9^GV77t`U&4 zfmBFR(w9V(x9@HFxY{E``0{SrjusM*-M-!{v>v?Jay$+F)Ldf@>;-|mSRRJVc@Q=) z1ArbP@<KpcYekGK7q;qG5@d*}9gxC|F<_-l=%@}~n$Col%|y9t8j`f9A1}W2_&Yv) zC*;-2!)zVw?R&jG-|jVjG<8p1`G31#Z^N&D=;ikZ@4gOh@yVpyrW96ATt^LnfFukL z+6Gt?ggOZ1_+$I&=I!2m6ke}uh2%)5IWIvn?dNe?4Jusux5-20@;URlf*qnHR$rn# zrUFlPxek{IiEFQ_NR>zufoX<gfq6?d)M7mhAhJmp9MXjvJEzOLWD#I^JobTPfszpw zR+}?YC9d<h6H8O6u@HF(YHS;+P`ny}NP1~44V2g8Na`SN{P^&2NcT$79Vu0d20U}o zdSvL$z%-m<krlIv3T3aZVeaFt+r|>~^SV<PwAqDdE&w{MOK)$^p6VIl*zB0ds6zhl z*BWcV1p;alwX_HGmXGr2uM-t|r2OxrZZwMs)JXoZoIA<K!jcyi1Zft^jK3Te?D5m* zs7W&Pw{Q$^oa01&3^K6fN?i-!_M`7q0WW!i2*n~fx!Jt!6I-8beO<8cpm_4<r$qIT zMo+t`=rDJeQ@5@3Ra(7u(eq9XV$|$_{#32Se*}MbF5OKc8ZaE#Zc#(E(n2D=hAKt3 zs*hATHB7Kg)Z(U^(TdcFI>B_rz+~0?A+&3U#OO{(rE|BzI<D1%@$TmlWX6?uR6=yO zIWfyHi0uO&YnCM4%EMX~b<1?^wXD_nhZkWkswM#x<#i02M>0TZ=@l?n=}PN38P)zZ zAac>Z(zpZCb9z9h$5lM}G4wzSRrrh6E86*MK35~G^LG&H!xalayAJ>F7gi?v2f{Mr zp|Six)Q)L%OX2;rD|EB_4GE46uC#)#&_y)V&a?eEo<2<4)L5B4vJIYS24imN)miC6 zQ_M`-`?3!k%m>P!L@N3vz+dWrF2F-2DgAnT)pM@|U)Sr&`}G;9b633QJ9lg8dF}Ku z3&+60){46h*YLi+z~mw}gtOob8viFIQ7?{;ebf;9)ImIcNvt{wA#t*2K0FSNT|`%l zC$nU*l{AVnAvH$mZ>2eu60RvTw&5`dGmvEfd2>yF+^~X3U7OloHLHbGs9#YdgZ77` zo0mpdsBR{j^EHGWH29`srPnMkaO#0G_CQUXW^c@>HRRB-@@44V(=geZgzT@yq9mJ; z1$yz5t((I|=waD>zW1w<dj@&R6FlKr8R2aUYb^wpK*jtFO17evCida;yE0TsYR7A; zNWB|IRqb%F)O+lxR4Mo5!Rrt-0%)3f5;MbmBR7FNCl$CU)|thkO65E<c{6yojQwAU z2jUJmF|N{@!BN#Xe_RL1$ZX;!gK&^VOE`cLv!O<LA<o($m?GQ<aq+w^%w2Z1G@0N; z)1GB+RLwxL-$~0c^*`lY${S7+?9X9sCvB!)H#}HcIyu(d{r{j%z?3LwI945=<nw-h zeU)j^G7<)0QU<5)Yfl0_Sc8-h)h<<Y1X0nseF4j%MLK8n|3(-$mW?u<C7*P)6iq{I zfge6I&q|>oV<=_8bPV||qRA$!muskYgM2!#;+%XQd^SiN%k*}dzT0Eq2oS_a68aT2 z-ccc<sGeQ0z?rwx{X18{I}7*7{!g^7i<V4;rq~pW2eK;dp&ptRO|DEDf2<9T)YTqI z17>^4*->i>?$^9~AT=C4Jf0E6P!$*3yrz9o3wxGs`irq4E}KkAVpz(FRnU3(0YD_G zZuZ0n$4x#s_)*PBT}bLo4I+-l-EILzOdNYY>{kJLzZ{$vL3L>mIyo7P`w-qDNN35R zDFnP_inYXq6$%#d0$;h2=QO{#ss?#BM4<UTm^2Coq&E!pV0XA<Rywv-^+whVK2^^+ z`7Ze_GzH2&C!h(^>%kGo@BR{5@WiN{i@@Qn7ILfeqSNm*JiGS#-N+H2WLEEF*P+L4 zhU9hK@kA)N!~&L_CF0NSsVjJ{3;Zzol%gX?fb+qc@ye0*9j_GihMEpL(a>=&pJu}* zLF)iV@?f*t(0u364WLb-_v8Gc@A}%{<Ll$6ul@QuM)>9R$V}(rUk_<RONY883$Icm zCT&oh#2h`<*uq2>TZxi{GSW_LX#yD&J!EzJI}1U3hoCz2B=Ok@Pz3JC?GAwi6(U4D zGDwcSU@4c2pR<hc3?}H;!-2AErP6PSf?JSMB=7XVuWS_nG8^E^l}2U)wXp$ojz^Te z$LNw{EE<wUL_e1}dI@Az`vPoXr<@ZM4IEWp`aARe^@l->1*yd+12NDF+;}iKingn~ zk&)3X4<%zkBz*vC5>iQkUR|{0Sukk76kT9iZHhi>HdGiQxE)fPw%R7S6bh}!lvy*P z%TfJoweu_wxrNuw-b2Ng)n>l!^V=!#FLMzhzP0aKKPg?~LVK7Ix7snpAMj$a^?PR& zH-#g7>};fCir+v@vO+0j>o6!^vD2yH>(%=h%E^om8v|gt5QE3vv|p}I3<kO1FD`M> z(Gzj{LJO(AA>&J8V?nIb*4J7%T@>rJbUGk;qQW^&oT3{P*hsWc0l(r8UT$s_y~=5l z2tZ2KxiO|C{*a8%-GC0Bbxr~i3;4N>WLqa%|Lcm8`N6nKi$`s4mfX=hEw^Dom*g-) zhkMXy4BoyKt`MJ)-Cc1XWjC(T&ZEDl3fp4OUS`Iw%}=@=V@m(4)tss1H(>$k;HP?g zwNx$bASJ=nt@eCdQPRxScoLlq(D0@B0MbaA2NW(Wnk$w#uNZzkMsL)gz@YSubujFg z|6+}^L2VhT2}Rof-zs7=X;T#GvSYmw%^Os$&~qQsb3c`EH}cybHl)&#ItVm-Esd3< z(%Va%r4h6ultj$B%>A-OqgT=z;F{0xtKG*xFvh_@nfvAtb{{Wsy>|e3@&7y~^x?(% zD}Wsz_Pl#b3>S~T_dz6}y9Q|J1*C|Uk}}W%Py}-(Cgw5IoGDBf`VkZe*6rgU9({@o zgd?DECF_-FlK=_J`^w2h)1yQvHY82f%V+Qq4pFMynNkD%4BSoQTqJ8sOn3<w1(@zG z5J9GaNdc*l8T!aLp8z~4)14}CPv-Q7K{pzKri%V5?;N#a!;z^{<If$h`{&5gmCckf z>QhgiZO@+tlvUW`I^I*~_2(y}&-Z)TtU+&gSC@(=1&r)Np$keq+4{h%@LpQ_0ac8V zXBJKbpbS-7Ou;3G4tk0tkeg8hbC&ff26HzOI~L$5TxlaVu0~uQ71XCB3M%T?WY3#> z#OdHRcEZ3Um#k};1WcXaGQo0sN7P`K^zl=_FSL9XH*N{TyG-8zRNDng{wXTo8I@J~ zrKv17rm3{9Q(n(Elv?(=1(sO-zbpVktDFsDL;EKe7`kpdY|<Vvh<-;~H`O2+>~D%Q zEueZB@_^Gk_<VuXcZ2Q31Jl5g!SNBW%o7E-y%3Q7c-@vFVs4j(Ffx31B5v}alYwL( z3De(+8G9C;b4<kpp*{RJ_rUQC?O1jp)DhSvp_jBF=zejAOz2EuuPE{{?djtJX`rYw zYnj5j#^*mCMMdjI48$};W!}S9N6qtJTqnb~3^K~n$GB58G^O}OA|zAYiT_NEjt=kB zLUm>CganBxM#vE0i%3i&V+4d(+=sV7k(W;9Z~*7hea3<u7_OjVBxeeOsXAF%Ju8(L z9!8r+HWCpk<}1WAdqG9E0T_b?U;I$&ZGxp0MO0d-N565BcbP%!qc(YpdH^%CtW2c$ z8}D(PGbP~xwntP)G2|FzEhL6TY9xCc<y3MPF^>o=$OLL!BvP5bYT9uB#0VK7O(H;} z_{v|PLO*Ue<w;zWBz)FhbY0aGh8e99B0#ZvWZSPE00f6mYIhz#F%nOK$vG9BLB;an z_h%^B2umiR>8R?kCHn@*dx%-V7hn|LphJWr6PDw&w?v!gM%+HOYJvB?QUhXO>Hr1U zu+0fkZ)XnB!d3R~!+4#aO=bDMw?`TV{`Z%!uKf7^-jDlTCj#FuLqBzb(J37Py`ZMQ z@&nqkkd4Twq<mp_vF#6_&p{6^j2-D#^I%%!;{=A7!tKukJd_qyz^&5ukuTL?@|8>r zV82R49_aqyIqI`WHef=(24QhPJnDd%x?+(tr-&fyD6b)vY=aF~kii3WZXNxziX+y7 z*B&8*eH|CAjF;LVH-k+PItj4+Ou{4VZa}4AG*^9t)~^KI941@w5*S>+1zuFDT1!f~ z7qM1`*c?<V6yUzmPpV`~%l28<(4iD0ztKT`neH}5jc8O@&5AYt8P#2RP9<%CD0I-C zw37-{gD4*Gcj%k#V@-SJ+rCpK;KiW2Jf7*@ahw@0Fm}pW3>9mnW3uUW`VK>44k+IT zVS@Y{vWY<v4WZwr+$j%r4H~@uA>Uuqg5Sc`&ku==3$fwI|Gv1s-RD#ncNOp59wR*| zL}?8HJe#<pHkQ1HCvxhsl*0BbHQ{Ne@BZ?EA_;KuQKrHu6a@z}K+V;5`y>hxw!>YT z*s*S!H#cF=Wx_RSoy3xBB2NRaFRmS@W5`lZ!td}IoA8_gKr5j#s7vEi{caL0nsW}- z7^h!yug?-FE`37cPYyADpNU;&y>S8<>iZ7w#4bFO>eW0f%g9On{(*~+omVU`%%z|& zK^|_0^*&*2VAi!-=EiWFB;w_w{YZs*G(7L#itYEOV!d5jbe1o^tUXrhfC2>8yH@_T z+EGbIc>x;lEu&j5*qd>qioU-YYT&cLbrvZq$fM%-d#R+;f`P@JCqhhqwN{TK%jxHN zUvW`F$EonN{5OQF6vJHRn>5EW<eC?h>Sp5u1?PRLPuJkC$M9fTd`YSJ!qM^tW^cgR zm-Ad?<;1I6f)=iy(3zSp)4SZcDa>+#Bw1$Ef4u%MQtuL+YDuyfbHVScD1tXrBqYim zJD&km5%W_$&us0|7sJdY2b{eFWy<)}=ZDZ!EH5L+(geSKe?Q<$3?Q{^+xq)|p6sj= zUfDbNS#OVYbb3A=ehPf|Zu(zN!eCB{2ZM;=Hz05q)xp;TNG!QPfnr%P+UGtA>@hwL zcf&d$y16hs!~8~t@su8dx%LX-Hck_6YRrMP{#^C>IR7}XxAUCRgqqTvj56HAW{W>H zCW3;*SvgAw<&pJ(mxg6aopVBnGL)?5Imegbl{s_4CtuYJs-F<`x!r{x&Ius*I+U&9 zX(TT&6NmDE)-$Y3#-^18D$J50s;r|sT>x&^J?=#B(SLe~e??2)&|^Rj;j0A04^T#= zl8nvSuy0bznE?;BU@<jlBBpT^L^Ow6n;!{d-Tn<TRx}5Ss&<#=!FMXb9xtL7uZ}b{ z1Jd44K*d@31KJc!+9Yyjf`Q{LqjWXX>fi14{&9lorU&~;lL+5H+Q6i2+=B|5rDfuR zydyfj5afDcYltk~q)8O1=Xb7r@8@P(lipJ=n0By)YV!4AG^^v@TCKqp15Sf_d91$^ zGzdNP3iKXThQqjy!Wa9PUh)^02pN_OSWvxtku^2JCkloF#7U<KjYijr&{$!~RB<E% z6g}_Ye628qO7YdlF`_S~eE`meyOs#OlLmJ|(U=po;FJtmdio6M!w}euU=F&WvQn?@ ztP`NMntLheV$!q?JhRnow+ejIy}cs082|%m<zy@EhzYj9f)>w`WUSd%R=^-cOaLO5 zWk4~<$h2btv^VMOlSibfMMoG170%n<vZXf7=`ht0tn6y0#x4iCyYw3Bah0Cl*Zce3 zzWHhI>+9<3emT64U%#jC)zi(}<?<hY%*y6p$T~GfWyImEhQx}rl3Lb6Qd2G}MR;<E zsZJ8ps`x!4*8rGcNoG!%6;Cb`IP!6a06V%3m;&|o`4!0GN2>F^H4~C7_`xlZ1g2@4 zsK)Gl*63ZrV?UzhKxn&o<<?MY=<~Y_kDyyB(V1{=&!N+9u?rZRn)_Z4dpIR*l{UIJ z#lf<A(DFD?^~-^p)!!PO^99_TL<fO@)g&BFN^^=<3VxUimdjEzs3alt+9eiJ(3uXu z==H<#B^M}8{0rNvx{rLjunv5lb#isTL)yOgLz8*GZH@-SQY=l0*pQ!;6i*ZrGzP(5 z8=}8kl&%ct)+kVv=rKuUoXRwS7zIA{15VQ+CV(gTanw*`XRP=66DVxXfMBUtL-1&o z&dU>xmqWbT-f6dBKEAf?@5cOw(y#CH5%S0+sl*gzDNCWRSYZfa9nqLcB0|uo`cP_O zavk<kYxne7Kkv`uv-|X}`>9TQTv}A>Uy75I!Rk4}(kuMI%Ec35B2CGYteG<~V~v8k zwcD<r@nXxrIB!4__<$@H5u8@S?>K4&Cz@*8U(6mA2npD1xJ4SxoC?!+wnxH!$%=F@ z4u3)2H}IVRTX<y<8e-^}?oGHJO6{9rC(&9Ib>GP#<X^-dI%spXNsM+5aVV)s|F3;z z=dj6+L?Lz#NXq5ZY%>xJ2EOFC1%3PO!vK9keR4Zhhm&t@$=v3|kV+idPE4Vi(!*#5 zZ4H$))=ER0;KrXg$@7-4&CZPePG?{Arr7mAEBb0^1%;d}F`PR0cOD_E78}x0kEsk2 zXnk)BHupH6zadzQ=y|vFM6@JayxG@vK(c!}QatVXaWF!^7jO8dbjUh4(cWZ6wp&Y5 zfO45hI<iYs3udwz0_r3Bn?Sa(1ueFw!NlMhijfsmMYSsh;pL`H=mP|Sx1fc%ykBH~ z{Yeo^l*zP#l^yL&FiRwt@<CQGHgUfXKpdIa<TMsAj5b-gGY#PhO^-J)AILK`OZw*L zn+(rb-af!8g;Y;;`S;;j00P$Re7nC{in8PXeD}P={?mZYW7x5+{UO*g2)w5hLxi9v zp>wf>ky1dlsk(J@Y-PwwhksaC!LLcJp2;))$z6dvQJ|uqKE?G2n@k~QOB0NyB_j(C z0bMRP!ovy|q%w(dXxkL1^?&`in<|=ywk&l7TbN>$4s?}_^q(LQ54D4+iEW^_0ii~a zd<bBPj{(cmviY6ZL^4O2)O~U&E(=9UJ@Sgy$vSJFzmzL=%z#W7NBu-UuEmMzA66+U zQahknG7e+&ShsED-F1>nY$TQCqs_239b=Y)K?mFt?!XPnUotKhR{@bSAOl0$pN_I+ z=qD_A#EDT6{2jJrzT5fSd9u+E?3N2)O~-k8Ku`^#&JGeS@~w{oQ^%tj_9o*fwFcWp zAn?&GzyW2=g<Wrs?kv}cUT!Lz?fd=p`1VoMA9+jk!CxtXy>pj=m?O49{453*jEF6l zlMJ@!^v@V59L0cTAWZ?RN%(?Q)K0LDhcLzrs36|fYGzdaHb2C-@oWF==;~Omj%|D% z1S&tVmA^hVlU*EK$t3F8P`0d^GikEo#86aItb)8#dqK4bVYr}(K49ULwcvVg5~i%D zn#&7Cc01G+25r57CTmw2>(?M#q9(^c)-;1?^Qwa&B<m<m@pHI*@IxS{&AHm9u5NWY zon!uHY0Y`3)n<9CQrdEnRee8^;9PmL67i9isPKg%Q-3-gfWptz8bqorxjh=2dktC8 zkubxt_Z4z~nBHEIHo_13P&vc3+O@W{o5HT(`>)^Qzis_T@ruvQD!}nczJ8D2<H6JM z<(@li=ZE&Ac1Q1QkZkOCy6d&^aa%gR5x*Dm3`jmjWQ?KE6R0tu-xD&a3@9EX)N(>x z8u*T0IvWLz!zYyEfYVxpCzcqd&ef1Bjf#vMw2GKMwPU(0Z0@DB4ePMKKO;;M91q^= zk<aQy@NkPeHoHTyNF7Z~4EUyKFv2rTkW~HDOkZla2oW@_eYX=bs~hYRCmoiGfXFPY z5e(a1jadG?$rS>K`-PaFpchUl)>51Fn|ai0VaC$l6M4SjIf3NcT*kX2{2xAUtTL8~ z+-m~`CS~VNN7^yo7Srp{g<o4o#gvEUZ&t|<NVv?`z!q5ih7;!y7;3UCV7|<{MIeF| z9MIata)7F(h){z?X^RTX-+eEtJzJu+bgf^c2I??*#kBnB$ZkYCz@y#Q(}1h`uAZ(7 z);~#yL2Q4pp7WQ)k*$vNaU*69Q(U3MxQQp=Mi0f7kC%(evpV^7nk_K%d9~_RtClP6 zbRKeA$V#Ce>xq$Lixjnp{NdzzmghNvlSkcH@OF!t9&aLL*m;~R;`Kc|>Qymi&CiUE zJzg&m<Jz1KP!;6Ahi6bNbK+x|fxF`KdY%<~#vt!arcss3b_K<~6&&@xe_EH=n)=Jh zdRAP(#qnWdi<h9e+_ee<++KzjWSkT{@H-$DF`v-?)%|~zvYbd1)JaLUQ@=f7(Rv&j zP94@3LEdLEqyI*M^gPUsRczX4*(z_|ij-(h!$~P2Qp#obpb>+NA%hX8jgp;YJM=1? z=O==Gs`!<Edn>-D?IL<yzlTo~T>Z_Ji1k%M416X%Ain7}*>czg#}PRc9R2*`FGXCw zONbQ<Qmj%Cod7(+hKnX!F2_wp$JTY}9^cNQ)n7bl4pzL^gXzUS8ayL}pqbzbVW;F$ z_#@HK#so)-V!Q}HB#g~VnQ@ULYF@~=N?bB;1z}-PvQ|2GoR7eFo>}bMkgXY##{>W1 z);w6lx=QHt-2xN*?l-&sZ~!uc)pt3HFG&P7&Rl+2EmP>z)#LkquX{9Ck(W_PVffo^ z$G#eWl4^@LTQY^VIQI|EJpmrZVlC{_2EpzW<b{{2J4%;8xInQCslq_MD5|i9XxFah z2b_7(M0x3KyLSx#CIt<x)n)eK)ALqeMV@p(q)kLK2LeYzR&I|%fq(Z}I8Z_<6P93= z>b;4e`WHGdWn-WN7#}2H2X;F=X{>x=f{&2LXZPRUrif48%RkS4W3Dqw$VAj|Jd+bZ z%!dN%%^Ah+qM$kLleWLH`6?r<^c<~p48@>7!4ar$)~E$!X8nsap1UDkP*X<JmJ?kF z%BjhT++zT$U2eUsHZh!urO`<>sp2FAC3#SqHVn&pRw5Le`{(^rG#axH!>UL*3tEG7 z<}BsC7FV`HmBd)Q{LfQayzW{#M`%mSu1&^NBtSxE@_3Ghj6kx&>$FG0ymXl>c>?dZ z3m9ij`GCL`oN9`(+J>((!tr3NMkrX0qx0i>{frk#oiXV1`h9yXk%H4w4vAwr;uI+P z17rWL<xx}C0H&5v=Fe7~r?alLxXeZ6trl*e*(l(&a>a_E``1ej*|7w@ldVGAp1}*M zGlzo`22rd%+Cq=9?5YpIj2^jFa&vZuLpyb5uBrr~noBOCGP(p7wvm^$p!qEwU-&|h zt$2Xfx<qC)uV?kv?h*y}bT+ds``WL97dZXqr<~|Bb`W?~OrTp4t))05c$z+$>2kCL zaHl_ztH|T^e#&MNEZVAGwaA~H5y<y{dzoGK$29mc$<55FYoxDMne}YKjP(@x)ia6S zvj)k`K_`d?kN`JD(gVemIt3zhJm{5>16Sc7F%AZSgjLvNwO2Rj5GAvFS34SdgbcM} zICipu=@+liN%CsZv@sbNOGxNnz?$gC_qT+Yq{Lzhhv(7IdopH<c2Ei-gvpvNWb{mv zl`9<lD0|VjrW}dV58@zTahpx4|9sGp_b7-hg`Lj`lc04Pk5sksKDM#hS#BW-d+b;> z8?9&aiQiOv{~g`(c6Q>}`YC>Ln@pMAf90<0IkX!nV8fnIM0&$S*9d^2CR^fnR2dgA zgU)0US(+6dMyn-LJOwo<mf!08`w5V=4{Fxuk?b$%^?|Bjx2<m;jnZ>G-g)(HfLMv% z$X0dFRnnTW0VwWOa?|mM&21S%_~YT8Hpx}*-14N*x@IY1TCQ8@Sy@A-8Dn6vC5dsK zF4tgyz>v?}X4(yTwODoLGvZF?sJK0E0$n-y+pKijA1;MT+T&H;8~zRe*JPjst2lfU z+Kcr%v>&b&-VBWKk9_*9h9Q!;YCd9?l<2bcUIs)FP_!BX@rF?&mR4MC&Fer&WB`IK zv8gxzIwRzcV7<fqcLwUjFLGkF<VL$(rZ7if>L+*xe1DV9@z;2Y8IMR;fwL-}x*BDa z#Las&m~>HtYLn@|SuLHByDh9W<lf`wyFk#*IK{c-9N?Y2oJAm=Xi1T(F5hUnJovy2 z_C1USh-$K%gJfV!%?v>axtd2AVJX5Q7oHip`dF|mpnj|jHxm3qE|Zi1t*B%)2<2hj zW^Jjp0m-ZCGzY>tZU>U~*8jC>$zp_j1uC&SDXlkX5CY!5xq|c@c{RI$J-fY_p1-mC zPW-9wXYg|Lg@9!Ehl?9sl<l(f>a5Aazt8V;wJN<+^~lTZ@#<+r;M=eFl)-J?492cF zz}S3uzDT}MR7#PES;qzGkggn!joK5nPZa5F_%wL8%QxknENtr#gEpC@Nvz;*%JIc# z%|NazyQqDK!|)=6d#0o+@|mCOwjfbj0m`+gtx!@&gpMg66lNXS4^2R53V$vK%2Lb2 zsy<J&)W4m0e4Hn2P-tkFty!Oo5k0b1A9KSC1;Y&`;)-~E9z?8}R=S)j+TBCBks*yz zSsKz%=VCw%0^yHhj)dVhd?0%yb2c-0)_^OA_56WkQUB~fmS9MDlS!|TGP>p-vZWMH z5$VmCxSVF8vrFcgHb-pjd+Eh_Yt?4!`O0Uf!+WcJ^GfF36y3NFbMimU30?Kk+}wR} zEGe&F=6um5ZJ9dCV6<UAZ(y#nUz9&sNEF-o9CcgO!R=>D8C>vnM%c7~kpoHv(=;`^ z_Y=a|HjV4jO<d#r;xWoIzgcDayzBI42@_Mr;HLTtm7oM-yWE}hZf!hZJdh6~UE?P5 zAuW|7X{7-W!ZSELO4-~vNERHH7)T(zrs}>^hPSUf=cW#iy35sUfO*fkdR4D=R;86S zmVLhyk`Fkt%tXhI<LfU(?)Ssg2<7ZvWi>&+_|cS+K+1|X(gH@`MB(W&nlx{!U&$Ov zfOsU#Sy_as`&zZr+02uI0fW`hd$;CAug~2*5yM|QfBinan)?3s`QDqqf1MwUUD|i` z{Po?i6Zlu>!SQ`L!g`c5I*=UNYdu;w167MN^-9TtAYOl6mSTGm5NR>3f7l2zVChoO zO)-v2M8J2H!2{V0sNbSPDeCCiV?0cDSXsxqSxX1aq0Kn~%Xd0TpP<@9-WB8sm=W7% zCpzMdX-tufrFT_h6D$v}*V41vZe^?sd<cVOz{)MW>du0v2|Chl0CwIQElM97pF#PT z#9nm}=IKF8%GJlOOa3uuD>IpF_4$onR?FpHqb4W<LEn=#4jvk&DnatJ$T#+!J~N-a zYZ6qVWI62{K(_#6?I7$aW`*-^zNvHqca_dk_yt!oIwpmqGbr8M>r+1;PxKzRQW08f z&8k`Bs&bUArh-N!oQjE4aG1n)CFBLAcCB@dK#1-UzQj?<=pl@0kudfwV&d4k;CDOx zlH#fh%fzs$xkhrnR%EXfhT9=VY!7vtaUS#W#y|1fKyh9-MlOC}6j7-TH+A}5q4QrT zsP;?fL>&@S_L1isc5e@FH|_JA%YekP5T+Jy74-AIJdQytEFBRI)6AUz$zmux2GMac z;8>M|D&z&?zmv*NVUrQ*NhXKgYT-sbfgRfF-+RgJ_xDh5yxjr>;TlznQh{QU=Uwis zyFQHBM(;8aRE-qs$^OgF?yv(MsK+Y1^}n%)ePruAb-5Hf=B?u@;qkx~o-NNXx>H8> zfGC>*otrYV0=6t}G~${mzk*|Q1#eLSGc}b+tX2zokp-&+2up*vvv?YX$pGuX9C6U$ z;giN;4NR^vc-6RIShnEcM^HAQQ)5&>&^7oEY~FmXx-IB0TjZ{Q*sfUZNqmp=J?GEh zSWy1i65xFC^zm_j6PYyAha)5qFVk4%z)bH7>Wf@XJB*atuA8evsqMzAKCvM=!6GWC zu8%<wNnF{$$Ye>ekn45RyZ?E+8~Axnyf{p|e#$@nCht#IN`h;wD%4cO&=m5G;szEy z30dt|eM$@jv{eew4Kvmz1fa`+YK*8QJVs|AqUWE4C9=Eat(q4EpJ_ZFtVUb*h>=*q z%;^Wt)p_~-aTh@$sgVTDv3x|MLPS7cs<KuV_G>6m|B5Qy7>S*x@*K?5hC=;r(P|dO zX$CIx3QokT_S%c+M4>fyN|H;ABqr-YR%kE0Hri)nOE%owtSFe|ETeoQa9Dj3?L-q9 zE_pF80LUqhw1T7z)c$CYON!Eyxe8Vx0qB>*;A{x@ZNQRPh9XwusXS+4`Y4w}*Y83n zSKu>tdrPr7F5tN>%%$g^H$J%)b|sq-1cE>))g-d(xVR)%?4tt*%KSe6Pv)*Hdi#@& zLn=mL(eXQ+qxZ<NaQe#Hvnb-`f0VWEQk2~K?}P)}14hF0o;@vmdJB}`RJgJbO}21X zx@qV>y;0$tBl2k{Bb+<=vhE(O&rcKwMF~!6N3ScKa*JR^*#Vrvt?@*|>w<yo7)Hft z#7J26*_p5$)yAxK8&`iHe$iuJU(PRTaa>MU&ehu&b5V9rY~^*z^8OvvswbdyPYSX^ z8eP%0&{9`hHg$0J^t8M=J-Tz}&j-}{<>ed5m8E0$+1Fa!@2oaWo$X(>(#w5CHFwap zj)P&R)Fr4DKiP&tsPL~J^gCe+F@{^02g=Ks(qK#9o4w4j)!6_qnIEcWe*llS&MQi! zr^!E+oT;P48X+hf2cd(@8$x)P<{+x&V1h3^sNq>?nZG<*aWiYvi$k>S4-F8}i!-fh zi$22e7V5K7J(952o6Fi9-Gzl&fPbOH=+9n!cOqkKb-k}TvFoiqt{8lug?K$xE$v>u zBSyde`**l_V0>jHp%EBJ&}6iRkndm_tEe=`k1N7QTO?z`9l&5T&e#P8WTJ9CjFe_# z)Qc{<3psdbJxqe*Sg}N8Hm_Le$|~(X292Ta#zJsrB8ltJ!mXNexVQf#bo2NAZkvXN zi0z<)@BQOEdsUq@Z2R^(OPfKjEd5C`bTBxwwr9YK7{#$AIL<u?zLpuWlXG>N@HZs< z^S%7Rw&Qm!g5GpSoBy5q*vjogob*n}999ehY$qEL0ROdPlEE|U{W@#J8m{wMjN_AU z#}3ejW#a$;GC~0N4NkN)Q=L)vHNk?*O!(+^Ku(^$x%@1zph0Ig{Ttjpgi#g+F%l6( zaN_Z)w8nUpRT8^Q^DSZ{QLD4><My@RGn`=lW=HP-4d1-($NT}$<`BgG7VnZPacWiN z2wTEqb;YE%5$Gf&&DLu{HviI=xuoq1q12pVsP#%B67kZW5I_x$3y4ks=;RLT#SF$M z&R9|id=R{S5GFe=LDC2-DlFlYs)4;C-299%1kHLYnX#nSVE;Flo&B6lnqVCmU*Du< z-IK{_Jn!$RFodC-+2`x$$FGa@S%<MIgzGKW&TqMEhN<(NBkn&XnDs#kw1!+}T7o8G zFeG835Y+!4Q{Na^=ktVnV%xTD+iYw#c4Mcp)!4S3G`8K?Y17zta!-Hl|K58(oNw>G zvop^;Gdu6@&iuC+s5RsaE4b|nazmU-5nWXUe$k5OI<$g{p?wFf^OI|0S&|EzdX$0! zd5kPrZK_?zekh2UAJVc7248-CXHN@I&Tpn!NB6g<&)p}U8+9_<vbFx9HD$*wq8r*C zt}?(fjT>y#oD50s-U-W<vUx2Y;&N2Yc?&uaBl%c~K;dJYb_lsqXwL-;t}|TJOb`fN z;zAB##7i1k@OA5xM?-mw6uWj9<~K+BDNw|RJmUO!{k-Ua(GszE%y4Yhiqvh~;G~67 z^^;Stfn^krDB%b7Qc}80wmcG~f}~RIA7^e220s)MtI&q($7y2QmgJ!c6dY7D(d9f= z4>58$P`fo2SEdmdW&=Y{p;?IPt+Lq8F^LdN-a)6&pTlp_D%pfy^T~+d2~B#}G?Pk8 zY$q&#RLe`nhs*z9&z7g$y?VTeBLbEz&&?axGf#$m1ar5i?7wJE40*NbFkL)!RBWBO zoGB`x+F@=cx+yB@oso^mCzt~kp)FUKp<Pt0p|#Y1{3vc_MW+@faJ$RbNa$dX_DC=v zVkSalx-P&*4D*aPgoo_nXY$%KW|me}cV>>=b*kOs4XL0hlaK+6jD#9Q)s5ddEskFI zUQg=c@3R!Vip~W$&6#Vf_M@v=5fnI8B+KqV0C#kAy^P>I`1Za%qWT#dbvk~KW~6Y= zlyxq4(7c0zh;XTL(U`@MAvLOF_4fMurS<6H$VIm%;v2|@leICNe-{C9$hu@{I1j39 zA13wHXkThVo^aF=<XucLu+uW7v#@Q0xPLn%JeUlc<J|xD0uV~glq&=8{j-vpy(XPe z1GcNK6WCF1O-0)3^u0N6jhgdd$Gy8Q*d{X7PALMG`}~z*xi}7#l}t&x!<g?w{BtJU z?}ag!yV(i%XsVv>Hj)kTju)DloVs4K4PR*_=||@p9*^=p@%<hT<}dtSIeNPFHuSe= z?8n2@n>|;OD)pPIlL@m?Ba~U)cHB>lI?*uA2iqsUjSLBc2c`3_BcrM^aZK-uqa>0c zW?<{^$l8QS1!y2I_o;tZYTJmXS<+v$r3&PRea30TN5ngIC^S#0mDe@eYdKuIiPqRv zTZfzJDH$4ns&B>;WN>f0wY*G}u{z|FnK^9MtGOA_5p=bvor$x@);-P<L_Ls^gUae| zX}leFYDG-X^x&H7;u;<ld}bqHTXCwn6KVC0vl%CJx5@d4_kDqJe!#zxfPTvDve8w< zgDgnci|XYZR7~@cc>ehG79@C!_d`)7Aylu90k4j?vI9P}Y3eqAKoGEt$B9aJHn-Yn z0eH5x;9Fmvc56YSj2FT3O&P%htSvpvTjSL%H5&6eSGJHqWDx8jG%u2_MLwVhL+{s# zMsqc(H!2Xi7zyw8&eD<Q=gWY9l1)&7QO2Fl5w6VxlW9u--gbfdel<t<u!uSv%4YuL z=9O|oc;nRdVZ+un;k&{e`^8>RK#;!Y>r<9_l8PeL+x#ad@0aKHO@<din0_m4Gnp)K z5QKqX@Id!a0QIqsw2Fie-Jq`cETSnpWW09InI~OSzV7s@TkDbMh%%Md3?IDf*(Lb+ z3PqBhK8T0`<|m72O%8tu^-bWetSmDTPfBHS@7iDTI<$qY1)pan<F5I|b4P+yLu`y% zrNF1pcYmAnU$4f*vy08;2EV-UxY^HRU}{Dyr++>#IwB3=3IfoDvEFO-va{-n4%1|X z?RAcptRCB$tyF`$!q5}OGN_{z)Dq8Xv1wegGIxWkt4Oz!+V)CxqY0%4d$DU8JmJ{p z7y=SNs90dE#I3|t0ol&Ds=XOx&_gB#3*92Y>N}Ir<9jk=j#>sMpE(MsOj}Pdn$=~` zz{rQXj%~E!z3Lo!P|GEk-pZokiUjf{)1hdvUSh|Oq=STC#UJ;-xQNM#bdAWmF6C3l zxG#`x&LZm-!^ZwV13YC@&)l#pFx6sa)>Ix>l%Kdl5F5|4GniCawbxWuR(w`yHduB= zfU4Ry@`h`%;v2Tsj&Iqvi?=c!JhP5lzES9tSD$NYHAz_j9RatVp&Vlm64mq+?4fSJ z7o0M`QBy+)U-%;0$PRXGl>&1GCf$l+f_R&dio3>?D_YK2Tg+a&${7o%gkNCvH08wH zO$27rnJ6hR#BJdGL$S&xoe4WnCd|p^UP=%Fji|FINE!{`OBT!>QV?sV>`w`~K(Phf zZRhK$UAvv5S$VK{eE!n9_qMrvJu<&5HiA3pS@!Yyxkjz>kSEU3LuG~V=y<%YS@Wfs z7OoXnP})k6B*-aBs3AUEWxK>e1=107F~zJ}G#(Ff52b*8g3+Qesz8e#6H7unW$*6J zRXJ(MEIqOtd&H?tAO(g81g?NNO<rMBS75{uKWtYTvU|5RKGl7#9_2iDeQf0E8y^ST z0FtMzY^e-uIu_h;FN&L82S&R~U;#)JdP71aO~;watAYr`37UFBOu7tOGc&HNL1?MS z#ZA(igzMWh=l3HA{9mhTVw2}Tp0VLysD!4drM;E-EGNAQJFny6;<9_gM$Wf?U7mtn zHpS3GQnmN1(<&S^9Sv>G1>kD`#^Kv(a0d_)@^3k9aLZVfm{3fs@n&m#yP$Us+kR<a z!8CvgtB{=TtLf_-IOz-nd3)&48^He8?p)u-W}O**aUgD`Jn=T(JcI?(<c)b{gysI@ zvq_H;{Jqg^Lz3&6%34tj5$=P*SPJU8Rfj0fV+(sV22TzBSi96g&N|3!w(F9%MYe0p zs%`bw5B9}514(Vd77`!on9j0>jVitLh<PbxeJvKU1PfGDOmrBn>tNc7JQfDaGMNys zeB0`DSDf0k&`Ra=js5`Z9pO}SOCs{?1<5bR+u5<MPf;J}3Ef?>P_8-DvD=-#4_9wt zQBia>kM9P47Qb0Eq8|e3X9Rt_<%3S6%U#Aij^l&GofwI65d}Lyx8aj@Zm|f(eHy+s zASZ19_QakT`#OU(SUaD|eQ($;ok0HhzI*)Y!?SfZg?0R(odPzpiX=*S?+?Q88~D{F zig+iYGnfBCAkIoE_OK>tM<!BbaPgJ}&)*&fysB-i&VWgyRp9ix8M5}Pot+)ro*9Sw zlCnbTXu;+h>NN#^9A2I#u~sw`M4vZ66fRy>3*7ob(C_*5?q{V$J2#Jj3<|<;NuR)d zkOGF%s3t%knAxST!ejv#nQCkAD!88Iqr5%qkkz3s3Q|Vd0{+6+5a31j8xI5A;ZTkZ zi|epK*k6d1yNWatq-<e-OqP=lh`Sg2G+uZ@#$$GeHG^{nR<d$rBzGUs#R*##3s912 z+42k6yGEnp8ttzG=8b(H`qS$*T$y>CS0&F9H56#{0UVcJ?lwW0ctU+@3yKZ*Od>nk z<p6NZ=fX3TJ|`YgM`>ZnO+Ph@@n~2y0UBEn>TinvAV@d8cO0hW5SO?&ODc<`Oo!lV zD9>=`S}Ni2ltmEGJQb*5!7XWsA(qIy*|(YD5J;oZTLRQvG(Y!nzc?ZLyL9+M=?pJ3 z<o{gM_g7eft@SfGF&7=cIak&Zf>PI?(hG7bE}|1yUt+X*3y4C+&Ux+>;H~s>a!@Ma zfE-1%W67N{Z#;5&{&S>gL~4Gwa5cAa?^PB9831fcYJ9G3UqBbh3O%_q#LZ*Fvl)2Z zlK)%ah+`LbIDBtDZv;!NcZOp&T8B|C$@!;fsB#kdK=$0dDeLO$<|ba8)IgsDcVq!I z`~Y?mr@v7yJS2&vvC@KOxt?&>ZD_slHM7eu#Zrf%SX>8`*6Sf%B2*jTD;C0`6pP0p zIJ5R$D=HU$yxUCDmTaMc<pk%v&|ynjBPu5nHq}ZAC3H|VV7!>7&uQ3ajQ;~sVSwYR z2gl5|M%%p(#?6+Gt2Xx&UdhTcoYgPE<>eafT^s=#UBd0j@cq&k>vS~z0((AOdMf*y z#Li+pZ6D~;BRw7G!~&TUwh03dcB5H!R0Ak~`zrMy1+M5PsN3t&=Fib@5dVt3z!D02 zY<3h_m41gtFPn*XI%QKTiNe~4UnaZ4+C2NXFPfcYK#?Qk{cqjV4a=z6L9y823?(W@ zYv5TOpXmozfD6#s|9E`0*<EW@a0)aEUO#ME`wBAc<pOkU3OK=VE_Z(P+BX_=$#<+= z^|V_D;ec_}ZMIj&c_=zkMFf4@%F}N+^R{MtXDMwcS~g4h&U-mCnO0&>hV;z()t9{S zPOk>fZ{1PI!|buutMnv1)6UG;k6na=X@vNvw+8w1jW32hL|Z+0&)sb4^wZP3ZvtQV z*JM>$d8UX&+xfQceX%9Ro+Qv2oP&3knY;^8+S7j#34MX`JviK@)-m7ihWecL@sz1& zP})eW%~<`ksbVzFSu{IM5EgPp6)fopO0jlGzAk7iouWrf!xXx**LyI$a$xQ5J)Bc8 zPigfNsVRy5*@H&+CjN48Jf5^cJ&$gXm`kbNm;XhNt)FctU6=(?7$7;ol`Dvk5Ehge zmDpGrb#&%}vb9I+4<|fo4DXx}diC~-IO3R61l&O_42oZ-7KP1Md_cNvV*NC_zkxkl zkE6<E6d7z=Hpb27A<J(p0xJL=Z$kFlPGn{xAHzf*Fr~8f&DJiUZ#_X^AYKm!|FR?{ zxf}!%48Bb?m!TnvXMz?LUMTkL%3pk>#dq6+<p=)4J#}+3oG6W0TN`=OImz19vH%pW zk+bp-0JOY(d(9B|iGmfnN7KX=ozfU;Jq|xHfnr_+ghmp>u|7O*w7JNoi6w*x&dNwU zCIxeEzGXgzu(%`wM%5?JK4W4`(ZK-LSb2!Nl!5W5u!1uU_>0ic%wMX?GJCG#+J!i% z-C>jpvPaA1XHD(Dnlxa`G=J|RC~ehZ89>-^Eft<srhsx3wb88AsC0>9!uj(Sm|P>P z&w$asT*IHjxa!Nrhr%>RywQ7mdptfpraAgj&?sIScYj9+Ji6U~K4wju+81F)GQVPt z9AH*Z8F#e|;VuQ<7BrZ*|AQgg(JQ=rGz7ZbKU2FM(o|bNC(O;@0Xt;ELsNns$@?t_ z9o4j8bktQ3l7){^bSMxS6$evx5FJ+)53K1Y4P2mf)f#5Z&IIK}&IjA-Eca4W*7}0C zSC<Lbf*u1TZT_ahx#CQ*e?7WgT_l$s2fn^Q^*eo&-!j+T23Fi9uafy<4h3cV=N_wI zhPMg)@5_*qni_e<GIx0ra>kH%v{n4c>I8P>AUZZ_UPJYyywFK^M!BZRa!1KxyTf!t zISa#fLQ=pobGKF$*Ye@sqDe7VnY{OBfWMjc$G@V4a$+Viaws&V!upAV;ab>q@!N+` z<-CnISE`33S(#-RgbRy!B0JkzP-Yl8By=SG`N(-I8$e)!zHyRuf_{0l_oe1;=+en0 zh46j|JLS|^kKw80Cg~jEk?e~Z5%)d#!_f*oo=19);~?EdU3OHFt01H)@S++lTm4rg zNZsBwE3lQpa0?gw5hSEc!?-wEj<6t9Q4EPL1%m<!RSoMNtdmyd6dGk}8rW%L%*CW7 zqVtqoA%<jYHyMp((?(DChn$PXYcov@i9+<Zcd_@cH7y;i3Ni_5aYDIjV&f_t2r{a3 zXL6QKpVxS$cwvb_7lR4?iLiAH(XLPPK;DMFv14;-K?&}j#eFq>Wof6l-OxW(GCd5= zceJeyaU}i7MMhRwD|;w!ImIr@J)-PVw%O9pVlJY2e!hBtUr$vaiPFPQV3+x^TzYnM zBB;=)mef!&o;BF156$>nL=8$?L*-?d)6A|R0B3mz;*o*3onW|4G8m*P-{=xgEndvW zaY}1Q3k3rQ`N1LEP>G5@Bm>2Q1&T4ZtgsWjLEf0#n`|G|Lu9A>=d6Fefv_|b`IVu= zH?zsq%0+7!&kr6=7K@a~9FQ39Su@_Om5?K`p!)*v@ftBA-ov&R+sLqcPR1WFIT9r- zRgfzR!%C<1OZ{HXNo?lf+N!9Z4XbNnh{M44y;_*OsYfY7ydoSegQcM~Bg=8*-bh_8 z2S&%j)?kd$$n4|;S$5SA0b%xFZ_vH4RG;I%GM5`#IAFmyAqaSudrKW5@};ZTp(DV~ zx=DEXjV?h*m|FE^ISX{+q<S)Z3uu|V>6~>MZPb(1PEmo)Z-R4P?EN(h;T<q-WIjG{ zYuKe-tEtE?k!B!rni4wU4lhD5*+9fROLDL2@f0T*#D@~3kyN1dj>2q~5lZUw_J!D@ z#`EJ<*_@v6<22|y&&H{l1=nfhT@R8St#XG~;qSb!EJ?S^7>@JHCLY`tUJz<)2%%@R z{;Ya0=%*fUMEVqOi&s?pc_s{QBZ6=Kr#9=3^F`Zj!W(LjjxN7k>T(e6*zVo2Wu<=z z;Iwc*K_8c0dH3kGe$U3@&jdYifJhwX$!=>J2)YjbCiKsX#u74tZ6CgksIf9Ds?+Ai zXMFUOUW1J>tP9A+*b)2BC0LV3E%h7ol}`o;erIL{6|0OlaPKhyIaJrsHcJNnkvHlg zr%h_oKvdyko4L^mqrmCJW#KU?`cNAQ!+|CdbCzbhL>RIses{{@o!r!GPdM??bs7GU z-Kfv93)+F@2~d*V78LyY@?2aoE~pnnM|08+1zE&T7|^O6#_|5BjUo%KDOy%qx<4>t zC|Xeyw5D{i<p&jLDUl(GEX$*rE0`M1BF3XAy$n-X3a-3_^N8KcrDVrQBgd9ecXrP> zb3sISy;<qgI&pJqma<vePMR$<ZE>LGBi`(2;3!^S<#**k>7mMWW^u(-rq7PhD<KL+ zYY`r7PV1maLov@j)p$B(lh;zU-p<o3Py%LkZKjT4=13nk@YN85;!D6{^ZO<~;!6Q_ zWJ6h|4%LFYJ`~5VqNbMOQb2036QD%l9UM)D6g3@snp?=qqEE(TTItBoxs(9fA3+4Y zS+yGd{&qAue^j2DEixg^PE?_sX)2=%DOmie#LlpYH_&n2s$GNF;hSjPl%(^ZPA1Ic zuK&q|xaJZ*vn6VSgHc>2-;Y|bJh3zO%8vEsg^aI0ISxOob{l@BHHUQ<q#|xv`QgXy z^J(IKm+&#-L_av6K`N?;xJs~r-}bD>{q#<Pg5_@#JBNnt7s7}pTfpKb!g+5jii~To zBHk#7X?gaHKdbav$=G=SJ11+UV!T8)B(&5nyekPv1)&wm7PDrf5|>VocOC+&Y*v?^ zqnY)>jb^(zLH<|r(9PZh123ueyY#p61mOp;S2?|nu%-srTfQj)%UW4{xDCIjzCTgB zZAD*U>wY3W2lLMH;mT2X`99Wfyx8VXL48WPbeWoWKy#NC7FWtkdH91edA8Nwqm#F^ zguR7li3G8Vaz&90GA6wIs+;)6T2Rc@F_4uMi|xr@@7CwX+EnvYt3efm2?46;`#-3! zI{~3C!HLa}cJPC9YA-)-D$HdqSFtpA?l)Zq47bS;@`83Xxkf`UgF}h0kp({?yC~?O zgtyE6DY)<_&Q;Sy1y1eR0vB%@{2fcl`QBdp9}DYVqXH{;9fu&NJks7_U3Z(l0=Ql% z`wc_V%zJf^yIxo%%P$1pINF&k_jl*#>kmXdU$=w=U$-0>$;#0tpF+pBXP;_q$m{zU zmf4Lv?3!`q``gC9!CYs7Uh)UwVJCD8DCZtAAGcr-GY+iq8|LKrcDA*@IXS;QUC$3K z?uA9&EFK;Iemym9qj!RiS5$sThqezk)mMwS@e_yBTQbR;dx`cUEC>o-_yluH9hiLh zn+9!^kg}m_^v1Lqw4n{(XfVl8WCAZlmt+Q&GI>x<-?dA>c3E9LS^eqYsGL4`qJnnf z;4VsDrFGR|S|LL<0wDlZI`CHygN;S6z3G><T0c$;j=D7w75ut<+Z@ubSz~&MsJV(* zR+Os|G$n7EUN`VEOTw`!Kj^fe-TQUHc<YG8vmCp}u0<i2u%IQFB1^^s5VD)2IPC)9 zW1Ns^DK#b|uw*Z2<)()q@_cb;Z);w{%4Cty8mat)2D7Ea^Pq>0OcbrCM)81`bMswR z?mDlE-H{2IazgWT5||U6T-mki{|qRX)`osVWCIl_yG2y|1y#hsGgDBi6Ya<5N^(3C zs=?G}-SwGcwF|{{Ht?>KHFEs6DoN^7n0#C}B$Cm&&AH1biH>fmo5kwOub85IVN=ee zIZGd7hhw;X7TXZQ^6@ZE38r=Kj73r+5u*L~8Oa6}?0PH8^RcsZMp`Dj4hOS0SY?}y zsVorZgmr0cwRl|;twCZJw)KOG-%e|g_%@^QBhxnZ<EFleA%1a#KdhpIzk2DkN}Np~ ze}enBSospjjBPiBAjz@%%Z$xii}hph*N5Nwy)~v^uY3vxE~CM0Y%xPpOAB<QEm9U# zjI>?8^u*EA^fK}+0xrAdY+gWcAii-d+SO+*BU+it>oFlB=0yYzh|h>lm<VqN@-8|D zz?NiAdW|(6@z2PjOo?MR9<T5ByqQyiCG$_O^AG&djuWJm{r+C<*JTHT7a=f}CXBKZ z1qz<9G?aQVXaS#6^25@YS2&M}vGVOpy_Zk6x9%n5J`IG;IWS{yK6DTSe-mTi(mH36 z`<>OCMD&eIuPk$lKn3c~2U=2cP;`P@4)^9FuZeVsh7eF=4ET29G)$$9vf~SjeURue zZt^;yG9y8Lw?PRHmWw(cwMPp5T72N=%hcZ+*OGtX{nJ`v!{EU?K^B!9#v2e_Zo`a0 ztZEpO9YRv?W8ZAW${Lm7P-km6d6Hg?WlLp`cMArSVnNtvN88qdP0=;dq2Cn4S$&sb zSw*m3A3+j!*3Pw%KH$cD<p^@cp-q+_+DDw2AYy+%PM#3R#r}JPov%-dVx}~>12jOj z40KI5EQf|gGR?vp+lo){aJ0Zcz+|NDNcNo}@TZDoKDwYcufg}*yuuEc>_>WEmcwvC zv&^(GC7uj+M~zTWfl}F;{A+v3&oCP_WG0R|%O1@{ANd>px2y^*O{FcBvPP$swO!qX z-&cH?!k&ydz&r^H==*HsMs<_hIM5I3#>OEQFeh!AUyb$D%0OK87g*aSVlpf7tZ5c# z(o{ZvD(v;ZBdIjTdb$=(@A~9MFEaUXB6z3ZxH+p+!2|pa|8e1}N)R(TLe!Z*#dI0d zJ=KDr!|jLR3)n(Aq6%G}nPWoIw~*jstGj@kS+^Zj(BPyj{ON4yLl`tl`84Lwz2C~& zRIvO@>o92H5{)(x6`|hkT9uJ=pJ&Ww=U{#92gr`h10^B1qdD4twx4f0J>9-KeO!Lm zsWupJxM|T2`;0DeC6z=jlVUEDa1K)}Eij^O#nz>P>GX;C*W#+r*MRIy0i<|;L8pUT z{%u|GzTyigWJnRf&&9i`Gh+~v;L&cha!rev)5ZOH*y~b-ch7dZ3hCM6K)ra?m`7{D z+C2$<H<mqCEre_bDK(!6+svYQc=1((r3l5Sg29?<p<Kh&XW!J42-WjncAcBURvE;u zE-56-vHVmqRNEI(1%NO;S8^iS1Sk$MEBVy*6^MbF!~)dS4!LgpU)LbvCJlD#EzWf& zL#w^Q%9zBp-E-p5;}PL2Hm00s30WSPik?SG_^{2ZwkDj5Dk=~z0#3;p`DP_#ESnDN zNnR#o67}qPYZkb9{DF~QG;r<PYXX|+%({vxjv=~gl%(K4aoL3LgWMK~s*G2CDXxxP z;D=3~tv(YR<ELG{5=%o$v9Xu=oQ*9_uOhanJP+^da_$>L8LBknyXs+re4gspA8&OT z_Lc07Pm9OE-`JTYhfNpxEhA0H(XMpNujx#Zc6`**IIU^*GIrWuFb*WLMvoU%MrdGA zZCn9Iit`m%GK+Qk6*DQqC4<BVPV58&Su>s|3IO!{LyrEJAY$~PVeKK)sjVf`w~rn> z-#YJdB;%3(RDT~nJH27gGE3nvM;Ln!-u9GvY^=cFJ3*810Jr#6oMUZ!)jpc#VNZxa zu!L?s>>a&!|Dc9y#$$Vp5M%1Y%@a%P!~55_PB;Ar*AABAknW2Jy#eNL#9E>hu}Oki z{YAlRlw%j-roJ-I<-73_mnxv`0SvYoB>{CIbp<k4)GX2iI@-2$VU#^5%-TsBZ%6bz z1Pom`r#suB9^(D?nx9UR&4xwi5vxKIM{y3=Q`0kJ0{SIy7zVL>a=O>i@{6{KVUh@u zaZ&pG!v~=XUfGPlin$KA?VJRacP5YuNplHX56A|*M0^{d57w4%hjr-nzXBfgeeG2x zPuY`GZziR|aqTx5D$bYtS#3=#C-9cXx{HNk@p52FUpLAgV*O0(j4E~%X|*_^2czt3 z<woe-Ht;=H^^li=l@22$h_Fs4**d$pI8Q8uGgyW<9C)za=}3A{O%;=%HDGh6U%5r? zrv30otp;}P&o$u(gHLyP%M50@TwzB(Gu~J_K9%QRkQFHk1%OR*3o)C3g?sxXV}lj^ zlXCI7#Vxk=mCFa#cKepe3%uxlpZd%*eRj+tA#vD)8gKF#Z}SlOg^}*3t8jX_%I*A# zX-L2$$lqABju=D?ACmr^La^=QV?hE_W4sH4(_zkmkaHKnR|Z>JOaOk{`{y?#qR6`{ zBYUK#uFlI}%otPcs6skS>S%uVy)E&zStE-hxFj)+Mpu?+rZE=%)uZaf8Sd&Q90^wv zD6ZoG@c<<Sv5Naz1P1C*z)blBbckZL2P7JdPBX1CV=HTT`{&m4udO1z;TISAWVccj zg9K!-34xwr6GkD)XWi5dZCpwsH09?^Z(a1Dt5#?!5-+@&(Dbz2&`8ycG}K=P0(ZjT zz)vQ<W8t`7d7fzt8Fo3-PeYA<rU~Ep_b8IJqo1Gi(^R<Wh_|(J+ckDcIZY9+;xAX2 zuIv4xF{AsnOJ**@FQmAUCxS=7hrn4bai!Ap{yZmX85b@^+>u7n%H{+~q1*NOxOdCt z_Dg(~=MfKH5RWc9>=N(DL~!x(O^2tCc@LIsXtGd_Z}%Em%bq=Fj|gap=Fg)eTB|1z zK1=Q+K^pa{1bu|gP5P0W4)(+(q#GiWoZHMFx0d%KoFT~nE^Ns@`OhAXogZwC^f(SW zYvU65Y*|9|k~D#)cZDekd95wLUrsq%k3!H7hHk4yGQM2F?Fw%k<j^Xns9Z*$R!0y5 ztLVUI2h)qJ2SKTP$_i*JoE@%*b~26qHW!T9jVvNvZwPE980zPWMxn}1CG{Ba^`)nk zOmuX@t8Zr1F_%%cbdrRcS%$XS45M?IM(P~XCfSFS7PdAbHp#o5gW77o!Y(QIGG93+ z-&2P6xD!t*WYsYpKeGtR;Yy6Y@l-A7uzWg~<sI$9+f0W&RkP}J9t&)t_~ldxrE*PT z6&RPPOlbP{N|?!h^o$P4Am%8r{=y48;cdyr%wC<PC32_Deh;Z7<#%}jPp48<O*y{L zyPf=VS%=7!?_ldMOJ&Pp`V&J-xPC;{$PkGVgVqzdYtW=*NaYsL2vf-<kmvR<v9S%Z zx`DU`#>X5QC}Y$NJGqTcLidjVj2KApe%E1vbfv^gayZmbDwn0^&|$NzQ<2@%OBGh@ zWAn}kh(>Rrk9L7JiQ=2Vdb)<bsY;VAPJZFHiVj;QM#TQ$6Bwz7F{-=^*)Oocss<_7 zL9T*Ww%MZ4_2N2uQV%jTO6<;vD@DgzF{pC?8NByKN7VAay#O}fEBKi5D=VzGMKj;( zjQa70trTXI5njXirA*R~=ljk={98}li`M6os5XhNgYk`?<-`(ilw{LaJ6Z?;BFL~G zAM<wUnOJJVVm4V+je*zwx8c9Qn+AS5aK8iYpeLj2LMQot32OIQQtdQdejY|lds?$~ z;f$}CF8TFV_*tpFqnpkq>4v@o`h!xYl~W-nB=Q66E0q(EWkWQ;_<L_KXS7}-&1YF5 zVTA-<<z)^>FEu4><iX^n%tHHgk_yW`(W;Vaa#r0c!eQ*UCP4Y{qS0_qW$IaE>!`mM z1P#;4R*KEIu*>|e55q(hQ2pnV>B$@H5t^UA>m;}=2@b?d8Ww`a6&G!r6r_6{s54z9 zxH&zs2Y(JNGoY-TEkOYE{w?QcucL+l4Se?@)PD0VM?}JeE@7&UD8ss4DPc8m0i<bS ztYD%ow_Og<N{+5}=f=|HT*Xo+-A%GZhxo9($(SHb}kQigblsl<RkUSuYHh~-XZ zdJDpbM_CZTGi{WN!h)J^WEU&i`4+LR-g$8?a8=gi#BU>rZEFp;(=_p9pNMB5HS|)A zz9;eY<*=_ly+O$!HY!pnptql+Ufrv$;le}f3xhGo)0EtM(TZt9-|X$7pM(x_?p|os zL{Feda-}1`eG^z9pHfMC7`E^i7&Y8_Shmnk>4VH+g>x!djkj0?K(xX-mNFw<7!1kl zzvz302*ma6n_&j0ZX#1AHrd8^!(=&z`rrKZ(1)V=O4M1AZ}l0j2g0z1Omv&$;(I@E zz_c0nUSw7pV%YDJAkS@!SX=dFdF3V)MfKB~Cxr>4co`M((N(2((T;fI+vn8e0xBX$ zXgTjj+#6#{^Bvnr0{pu}X%F2&Vlc=ZMlOvMxl32tWjvsF+1_XN1&ZdinJe8o_abls zCp9OvsS!RH`QLqWP9SDdf^s}1f6RJ0gGFCYAK;UP{D6@P9f{FN1VicYZ~vfmna3mI zW6;h{6dz$aLev_yuabHld$O(8|2I)xRNzDxUWnGrttI92!iuCD3>6G5DeLHu|Dris zgfLxZ<$yp+=_VICK2|iEiY=7X13{H!xrZC_a~4O;FH8B9<2*G%S@}Ls1zzP(z9Zh* zxE#teSxr>ab$vcg`QOe3O@iybXMT2yU)ZKlVZsuwLK@mJ*RX)#{}M{gFrp`4(+)#N zSQSG6@=KPwIQk|(Phe)#D3FEfHZO{!d`0n%QH})j!!$>;A$v!^&szs8Sf84ST-l|F zB=~Pn)&Gx$A~1D|@?c!IvN@=Qc>G7Cpl5;e?CxVHi>8b|9NmH#^OD)0sB02H`<m_^ z;9=B<yBwIhvOxgqDg|B}lP^UzYzuv-C?&X!#1*|#9FcI&9NC~vV~w+x%xL7wkc@HG zQ_RQpn{@fumkCd&_Jp1Hbm-6mmmtGDE~V(joedEwQtdDarmH4-*3EY^e?o7UDGlaU zQByejyj0y14QJ>{=v)a0=@z>Vf#mcbgZBL~fcPH=L*xiHu|_n`JmYh%A5)e_(SXc@ zAqmdgt^18ivp~W$pB}Zh-DRuPetc9I%Y4Kca=+jUwvRtH<&9Qf^K4jcNWD6X)7^Jf zQ_m?MZMih$KkCJpZ`WWY^r-BQl<c&80$G81!JM8DrI)x%aAtVgjJO-VOe*4;QMmD% z+ecfB%eKC03T1v?fFE-aAEuqkiKe-Q>f3*yO%cj{u~@aENDJ2#M-oi%U$&Ahg4jz8 z4gT{Z&K{`*R(9U9!f1ns!+<@Rnv@Y*7<gwo^f)`wgq7wrqUZ&jYW3ptHNvj~dd~v4 ze&LFF#Y<<0N7^Wg5J7@zE8DUgZYs+UGgL5Id{T%nb@LE1vkGzdre_|<50T=fu<x!W zHc;j0lxTFmp*|v=KIe4wXK-x+-i+)CtkZI_wM~S`b=C$OFIv;d7J1;g*#ol)HJO~q zXwI$z2paJkPh5feDAOa?JiDUeT>n(Q2@8}x#P=iBzK*1E^3B}Yqr1|Q8J6|f=r3OS ze|k5qA+Se&3!cy2@8vGpMre7am0?PBlMx$i>UDR;mL!>(`kEIFzhAK8;(o#VXm=x% zf~wX<8+{`F8#yatZt&(MK{D8EZ=N&$UBGqPOEWA(p_mJcCr9gxaJ13L)(h?j@<h3a zbB6PXlOzYF=Y@ElKD13hUtJ+Z!9U*J{6j#0WGrDQNLtWl>vijn;=DKxR*Wa&&I4wQ z;Qf|T$yk%z1ClgMn^4Ob9uceMfS+;<8#a{tAT$lbk72*z)8v{*KUIE-gBN5UfKdSL zBipa6W+ZvPV$-H5h?Mg6^ZG*kn<28z8=hR<*A8lFN>RO%#jmV0#pq7^cEv`An*s~0 zG_2gk!VBs^9$L=jaV*&t<?2RN7Vn=P=l;kj@$*9{qlG<mT!o0W!JAND*G%((_%8+? zxrUhJvyQ2pk1C2l@To+Ik>fIdG0cd^C?#{%bZ^do+FOa=GGrKL7ZX!=+B;5>W3v4s z!#tLfxs-0%@Wq@!5)4|?<fHA$AIE-ENz{9SHE!|{O1#957@sf0L(Qvq6|5>BWz8r= zhDy7eWx8`^=`mh|5d{cPz{kgFwlb_gF|znFklK1J$F)&t>KXQZVPu}`Gh+EDL3E%= z#L-1<zg}hww%C@Fi;MZk6EZx@w@O+sKV-R^9cF9nk{iTy-zk17%W~*-bHiw5Xq~E* z8$g~$hv<Qp_kE#^X<)X2sIq<zlYT0=;bd*YlFwB{dr(MVBfEW_J@S>wnc2?RzNHdl ziQ*0R`60kl-^mhntg9bG_=ZCm<)E8~Z`+iy`uEsDcHbXSA%Gm<#TVRmT$6`f&F-AY z&Re!qCxG&Yz%Yl41=~_Um%`AGL}psff9pLEk`l?~W8ie%tkIejv8#{1%|9`YPcN;K zZ=FUlrU57i!*`W#>G*YzN8XNQHd=96muROIRMC{?-0;+8xh|=_Z9<pF<7vdyBnJp- z>o?c2x_m4ekIrg)GQWk+FbVyX(9NbP{#zu=?)&5FVpktRYXtJqD(xQHgRAaKQ6ON8 zN-(pc&?G9~9xNQwE7Ol(piAPVle_Ux$J<r&o||jK8|ssH1{Rjy9Cio&hb+^FPupwA zRMOd?^3f5l@SKE{8^s4uE+NSGCC}ot<MGn^+=9-u7~>~S9Lj#Xt!Y|@-CEZ78<B)R zy?>Ppt{dVC&7~vG<P(_=Vs3=`M?yeHh6kSqa%UifObq?Kam-}a-401wl}#W37#c1^ zCOU$%Ob#~T67GuuLdb0A9WpbzVY~8E@BCjmTJzW9tHH$@{i6rHKZq#_M#Sp1s_+%< z_=&QS&6o28T#mJbht2&LVe?Ay-G#_+ag=lEM7-|VV7Q`1*y#R&Ocz#|1RBEbBlCRs zz8wP{MZne^0wu*Mi42q-063KjsCVL+da!s;{6fr@#Qc@g=X+hB6dq<F+3&AzIDAN~ zAWbmeb5wj|3nCrYa}UK1_@6H`Kj+B=y-UwC61@X^NmwLgqp1VCFaTz_!}wAo!vC_v z<{xas17<frew<Wducks*`&@v-(%K&<`9u0Y+-+xX>r!XrwRZLs1jw@`p!gU73qV=! z-eKctON8H|4GxJ)kDAdw4Sa5o^M1o)5u`1rQ1nu43g`YisST0;)Y|*|BlkRC772F9 zm}W5@DV(~GUIc_4K*WaBkvZvdIQfGU-yZ8Svau!Ui|;Y$DpF=Li6u-Sk?ysfb8G3G z)uBG?A)W90qKlF^{@-yo<^GH-F?Z@Wj{?r2e949!vcYy-7pV0T9tyw(T%sx~%bU(} z8@;F{YZva1grtMZ-?lbX&@Jhk3fIeyce)vG3{RbtdoIU+=dY&(u}SnLUUk9nZtdi9 zd&vHw1Lkv9O=z=O6qXaqlko1oLz?i<Mst7YUg8XhUy;h{tXriZ2A+d@VOr^3^N2qv z$qfL9L5_5-9@i>Uw^ozWzo<Cd;WcvJ=Zs3c+-{C8tXR*aJ1Sle_hRyf3W_LI>aa<B z=BvA2c#;p7bb$0oS3oN!^4e(-$%>N0bD!LnszyDdgn=R^im0_pKaTN}6i56kN7mdQ zqe--Wd>r28#aLlVE3?mdI)~@wbr_Uj1HJqbA)MCV_B(EiOy7mE&dGL#YuOKa6!`;m zdd=ngCLuoQ>{j>Ch$F{D1O`n4*HQ5sKC4#H<5*|ii!6JT9arkdt~|eiddP{b1VxCV z5H_BDvgH_(Epews@r%URqeHIn(SK~S`9}`P<rkr*xi}s!8m5AbZ0B-t66f<5<S-DR zLV%6h;F-~z*<AI1pL8U;vd(VrOBxozL62f?33&IlqRD;=^R4&5JgecTv9@Jz>*2Uw zj`PX7Q5lpc{PO<o+m41qE+5O<=MC4F4ryx_8uq<{a=c>hX)E8fg5Xfjs$BwQg!>zw zTFENBEmGFM?NzenfT08)V&V;{8m^gv0Zxb|aI#8XUMoL%Y&XCkC^x|00v$`o%DTKL zlcVD^UZe@QVMD<269Sq{%7!rt;dN6>OL|=CD`mIbN&z2(L6sBf#!#u)_sr+#y}+Lb zOyCy*zTHzwg3k-uX{$rdQM3n{He7njJ-Vg$8;xD_jr1%${J)nqW$ufw@3P&EBS!z8 zT+OckPb^@w0ZaU<qH1xR1vMwG@86|CwG=%_fl+wJhPuvQu#OPy<y28Xr|;t2x)ENT zDw|@}LM!MFLGHNjxMpBsf4-shu1lT+8n3`k%Nl*&vsX98#d1HsS~Xw)yqK*=+=4Rj zL0CXY?ri0-@*tnQyBI5!_cgGxPyB$kp^Zl<)8<2JRj8it&_}kk(-$-TU(Wj%O`9Kn zx1`40sqx_EYdoKhGf8=wQtAG1PbaJyX73vKMMP3UQrzyuu5}#j!a?(6bH9_Bvzy(G zn4kO1MT$i=q}}h>`Snk1{GbA%ol$s^G0(ZNr0BG>cnb$L(QHy&Ij*v4Gi(bmQ*)=b z?y*U5-aV77s?#2inMRB%|2Gf#&v@eNFGRQ|>}HQ=gGk-2RW;#C>F{8GB-wz<<lSM@ z%DNP8FSp(!449^z`Gn?TIZIRR)x6rHC98X6f5)y~;?2lC%WTH*mFm-DTHZMc#WI^W zlX+$%7psfs@aKf(D*RF9AEo<Fr2$onVSzY#+(M&1&MxcllC}AKhCw>%Q50P`24^$L z0qy4&B^D0`xU+K~$)m-ZwQS}se+z8c|D}DBn=e8x9oR+XaBj*g+y@OrumyumY~Ypv zz=}9SDWVj>h$(ffGu{}YLMd*<4PIzLyCCm4!FKYc1lQ%P_dvRC$4+ZM-4}^uc5US# z<DIv-$-Tty;mSZ4v<k4<hFi|oV4HqhwQFueaO6ye5L#!*#LmPk6tb_PwP5MWrs<7E z<T4mO`p<^{5hBFy8<HK?&=Pq`QlRDGq%1fV<LmGEPGVpd-D^lf4bbYdYx(REIlU$A zTbFjLG67WxO*EmwpaNCtR6c`PNb@k_+*zxElJCPc(|%Ae7>GJHj#Uy_ko&N@ENDm{ zrA%oG-o`_ds8ZB?!!K{~SYK5Q5^-d-GxBr3&c;IjX86qSEqwH!ibN3ong7e`Yp`Of z<sw*yjo6%9pprFk;QoU<+~YM8fb%_Imdqk4FtlbOcXEP$qO*{S15!WKgR11=Ow9)J z%uz$Z!f|2qmlsMP=4ACySR~)<^T}$pD#a8jC{v(|L3An11W#;qDX0vMyx~MrPe^Qa z_V`^y3Y6uY{`&tlRy`sB86M)~!*8vutbyHX*WQe{D4q-n6c+&K?-K;;6~|NdZ7g5s z%Lw?Il%$8Q%G_O-q<fMBRsB$(GQE8|{}91QGg*SZ^d&2s!pW8u0#sCl7i{5|3!3(` zuvP5qErckfc+p?-*<|?>mmp?0K7O2$LqCCpwI@ALLg>>rT}G4xaQ!=qW`tWf{Ij>v z#9oWgGxq9oMfEV5wugo0?_$cYmmcgZ$hL2uRx+Nff^yDs`SqZBDMT$E6ITkYGH87s z#nrq1MZbwZNuK1-^asBq2eSQ(QE-XK16}u3>0cyCz%cZPT<J*dj%XrMtH0)6NJdC! zdPwoQVOGM#qziAOp(sezUYwI8^jduEk#5KM`ZZ?Bq8bp#%6<u3z~%s*t#@BNGx7EN z<SFQXiP4$}tUoh6c<=2;Tr8ACWRplyVE-h?ZRZ&$tR-Npz!aR&a)kA0Dv_3^q(W0m zamn$;DhHulSeJOhu&|)bzR->XpoQ@%^*c`N*Uvq*K6Rn7;eQdkwh0R~OXyF>j|YAl zs3c6~n;St*V%6O0A+Tuxzyo=T*B^sT$RcH7gWH|kZ5qBr$<iWM2eLTBM85J&*LJo` z;RQh%@ZIPQ=kXf~mwU)uK=$`=@_z~frX4`=3BP?5o;8yY2gr_n-iHuz(lKoYLFnZ_ zV!PDe_eN^Jcov{JH~WEcB>xfo9=fRkR_|i{C@#cm%c!Q#YUxjda`kt#m3jmKFzWa9 zd@QttT8fH@IC6m`@1W&@V3!Djsn%Th34w>txoB(k#z7*W&oqAiDOT@LME*Cg+-QRV zFhc``8$W)~{0Pl6BKd6(i6X@A51E%}o)fK#5rO&Kc~STzOaV?#L~L@+rEV0dt6m>@ z@!JbwBUfVZZ<yVzhXo1%A^h?Y#|VoXWmy*9p${F;#hr#X3+N>%pYzdJkXgk~d6T8g zS^vq1k2<|sF9kw`jN3bSXtCKbcctSXA^z7ZH(CB9;1Eh)A7Ur75{{OU!$(~KaF*dD zLexObun-=iN3&UKh9iB_fq%0WQ!p956LOAii$|cBST9xl^%`JTFx$(tCV~2AWdvLp zZLs_&m{QkAF&=4ns3i;j7G9??>6Hk?EI=6Rp(n#5!>VQMIBetiCp1&Y9EJ5Vzain0 z1E3pO42-E^1SMJ{jGNT>|Je+ff%iUsNS%}$L4*`2fw38Cku~s?0fV*^_j|C4PVrK9 z*tKGVp#IG)_slO1`HN#ID+@)T=%PXY+{Y|rt;%KFiu1Nw(t^K}UCBrMPi>DMaZCHq zv8JE5I9P-F(12u^+fHbzaui`rwahzYWk$pTS7K;QNzHabX1e5`Z#pYnE94}oM~qVc zcbtt57y!_zdryU$Lx3AH5{5lmMFoR3#Q_Myh{~WGr&#%0Une|f>xW0&G1MMReUsqP zm3sBe5-fK{bLGfLfi&|+SDW=P0AXmbKcg6Z7)JJQ!dj6ds{w_1^+@zk4!iHX*n<Z2 zcK(DJN*Iz%`0ITC-!pHTn50Y_2q>Z%*uZR|JqOfcgnxXK0zk%(2I~8weI>(7LG$-T ze~bbIf8WbT<$MV`$&}eX0%k)VFnsnV#A+WMm3%d{%S84^WMyZ*I)i%pA5MYN0Uzq! z_B(D0ln_RyKR5RfmuLd2UhAhjl)l1{2Pg_~KSx!5K<(C$U9O-WwX6)`zlpKH0g#dX z=UzViGDILD$CN`K%nNJI<xqff=HN9J`b&?`k+Sr3c6Y>l{{e`BM>w6Bj%;|mEh2i# z6Oj`Cy9`+Yo_QyR2NS*!;(!1p=Oyp{We=!89?}p7s|z>=Nm-zq9r+oE$t`)yjUxJ- zS%Pb%6FP3WlTW0f^iNd_eSeGu)_eTUcOv%<Q7Lju0a<j^_8Ty>lG-%}boQlzB)C#T zO2g*l4?KzgbF7U&o(&Hsav|gjdze=c5qKUNuF_crob_R8#6F(2r9a&Xey^1w@FM>Q zqyE<9qJJ9BM*%RygRuY~OP7&0T2C~;gy0VcGOq*NUTp3PTkk?*nK)Rp$Np>G|EFF6 zG+5ss2oc8;JGBPJSQ!L@0e0{UlRmX`>=pqs*`b)f`pL@t%@+R%1_Vp}sSpR8Pt;Dl z0GO;J#2*t%W)K{FxA2Fe!2S9}HdpEjGJHTG^ADyXf1D8@0wg_zz}Rfs@C?tOKo2b# zL;&ZgycAm&v2kxj=ib%2h4u-)kt}%z5f5x=g_r9a**|w#2Wn6l8od6j$C~eZDruGs z0;!-R1Uo=rW1LwQd5R03tv3i4cRJ%GY-N-7pPYXH3Y=HnyI*rqW>8`xxe$60IuJEG zlho*0(+)MNlzRL|n@Dw+mB=1s|C1B=9_GJ}fVYsU_1iw2A2b3K*PrIu5}>1)1t7Gq zy(SUb3?XR2Bm18^@)3ZK{9)i9YKv-W&CpI<U?QE!z*H;aaPBhFXoR^YAA~V>^O1sl z@#~Nc!h9|KmV*rDKWhPX34jJ=e(zaB!^e*<=>p*lM6v|9r8)HmLtZ5qfi-1`gSC?X z&wKu#=7*Ss1A=c?#EN*8fH0Iqo1)nr3E{QuE((P_yd=jx^p2|M!1}+6_#+_@Nj>a1 z#0tED-|_mTw}E-rWz-9P1rk6mIW-gTX{`g5S#(#Hoadk8@ciK?@ZP(R+?IxVX3jw} zHa}wU1`s$)z&QmJl#S@Dk4>~RE=Vt8fTh7AzJCse`c+?Ci45=mn-}nvb+3LLOfCRr z@|SRU@_rB?+dO8Au=m0RS)N<@skv_`<u+l%{a-2nI0<;K`$s-TRn?#*xf7S@HFyGL z4l*bJ-F)CT5mf6Q=Mhh@fgv>p#ORSPQmIJ7KQ0BT<=^~hevplWZ^rn`-v9wg^bIfX zr-+s@ziB2^S_jQqpNCrc%nQZ88E&wE0G}G{eW=9+$zI9Zuo}gOLj?HWP3E-?<KgBF zk!Q4#KRupCXaCQ!{!5<#e`0`CU630xO_J<7pE&r4DKlyT7_L9oWe-5^Smu393DI9p z{^0Q&SzsgPuPpp)pG8f%i0Cl1LU=wgBm3GwuI^OQg1;2H@?Y$fQ2zKRMd(+FPe~~| z$C;o+_=y5!UI2d}HsZGNBZv_g%Pob5z;VY6lSwx|*?t{q*Uv`ttu;pVS~_J{-ll%w z*^jRnfv0M!`1rjup&vUISn+>DGjJsi45$(}A41QuW{j0#^`$XxibyEwIN-^lMLR%4 z0al=#9D9k%<81u68b5%HsL~Z0eAOL2_4RkO0uMdCX9`p67aumx7~`nAV^3NMQ}<T` zJF&%fl?kU$mWL%L^!kpN=ZW-VRKLfUK65=L8^I_~*um~*2>f{OJH^7%lKrRZtiP3( z#1A3fV#z{CCI<A7>8!yrar6Z<6e!@*DGSjWw3n<du>S(Pg<r@CxT@=KSb(-*A+)n9 zRvEQ%VZ0r#WOI6i7^sHtS~L!(i6Zxn(l}{k<g5CTYrJ=qdUsIv@GWGW7k;_fb}Z!V zrjC-A>%~1iw~d&Hwq5q*dwQHbOKVNfg*F2z)?a*P0apM(uyuU+u@hD`E8PjplRNI4 z_I`6B&dApW2Z}_GaF1gI3XcDZ&kkfZ{3+-?t+24)F_ut>$Ign*)7I(~%_e$p`<$X% zIh|2D5;x6=9Q2=>zuEj$Ri+}^;;k0ARg){`Ju+?;%-K5cd9K*fRgTPbt8E|pO)7*~ zo73YJa0&CjMZmv`$)7cDV6lB8GVN%db1xPK0hn^lE-4TSz3xAs;2iK4xBynKf@lE1 z@(#*7X`-4%Y1C@)XQ#$xZYEQW+LvlChx;JKhy5M2Gf?}>gqHTB<2&2bTD$69SoKvm zrWmnT9nElGREpiM;!7XuQ}e}HQkFHsT1hj5XUlWLa6fc*?|LfJk#jStj--aaj+Om4 zzkd1nB*kncFY6pmh@RdilaHaS6KW>$M=+_MJ8+lCqIm#VN?br5+y|Ad^Np3dx2g^A zSdP1Dj54Dy!nkok6jpC#a^ix<8Sw1PZI1?@UBn@ADp&n}^E5A_XN-%y^b8#g@8&t( zf}#!cKxzuVg}TNyZ>hw`m<9LnzgiuzbPOPY79aWeIO<B`S;!9wiSfAj-G};xb@Wec z15ovM0;{;WLGTEGOIXvxj}_%_zRsRStE`ujPTv8UkmD!qpEF#mv5#798S&!RuA6%J z?-~zT-ULpSKC|P+xCtrYiY$~0sAR~+t%tug7DN(pk#DfHN_+i<OZI=MsRWMK2i?4g zT#tsMmCAf4R{;q<_!}xeXE;z>JE3fhy&Xv=bm<Vt<nBDI5P+SCjvKGmoy_C-s0A@~ zuNI!xnOAuC@>c?uVB9Tj+?nOv0Bd)BtQifA18XKjDz~7#b(A??Gjg4VLKClv=a0-P zwnm__|72%>m<L&WZWCDJ7gp2TwWN}Mt%bKlX?B1{1GNP7(tN)Md+~TL<?*LTu5)kz z<SjB@(lRz0IDWxs;7$X6>P6R-5f@RzE)X<HiHQ58Hs5qvj(Nmsicl+-lBJSGAANf* z(j46vceQ^kv}$L5U*|4K2MA<F-+cclj0s+94@C)w%)TKngC`30z()I1Iy>o$0+9zm zAzY?-)Nj#Zp~3>*A#uG(X>~`G6YkH#4jDbZO#?SdOD7F^j>i!a|1w-Zwu-A<nfZ0t zWX9yrxNI4-8;iI|<UD(4>xxVu30Y4bHD&vEmAdg?!6)SB*&9(iF*6q@90uL54@Q$& zM%b%7GGOx48L`QCNzQ6%Bz#lgWO6fX2)VNzp8tYSH0FEPDi>Fg5xm?@dhZt6b5xyI z#qz*1C^K($n3dxm8{lf&8$G*n%<|JjNuK(iOvEQ9C9K$5e_!Zld-<o9EadoqpZxx^ z=6`k6!@Rv=@IHiTPdeJN(#~;=KM~A}SP;q*1OYcMdYzdc4Zgzo1_a;-ZgL2Jhm`y_ z{q$^<>VBz8B)DQ|D~Jj5C5y`iEnAF0Z)quTS=20(=(FVD-qC8n?0EKwS9kmWY46Pc zp<cfL{+Su0>_nEyzAq7xB})idLMmCx(se^3L`;Kb3>n!?LWr@2vfW5jGD=!(LmB&a zQDdhpWt;D3%yjSH@O{1R&!5ldd7bAx=bX<u@AJH#r|aE-<cfM+rOQonK;NTq=LCI| zDTc+-L*^v)go`notWxcn+A`Ik&rzb%(kfPa&>v1fL-?@F9ICj`6Gp!baFIJqvcNq2 z0wvigO?IlkI&H3XXv@YMyW;Jd)KTa^-<6^GP_Ioz(Moio<M?-B<0Hr)4IM=fO@jip ze78Go=WPR7=YJHG7kyE!p)Uj@Xw$k5c;`QQW-DS8)#bPf#98oHoM;^BLsU0vpP*VD zz=1H#dGa__H7sPZ=t))i@n;lkz>&3_^uv*IO0bRGl~~vFlqFKIPNF5aemJ49<SlAr zRj6-KQomKehqriI^JEjR-Y&Q!mf-0VHqd7OaG*}|EJF!&_~%chcAHjrIK`}`fOkt4 ziO0Q8(0#AM0?HuB6o+tEG`|Va2%c|q_U#LE?kqWv&7?{IKM{?K9LpGLG$#CWul`1O zh@%4AVE0->no&lpxI*DP?Ao&M9dd`{Tux$cSCXnQOI42C;sSU)`qoj-lRb>mmd>pV z8>#sh<@2pioKKNF=*c<$=1z*22IzNYXRO|yxckDr$WwzCzOwGy-y}>74n7$gG^q8C ze>&09gU?5QMClv#aslo*eohMASf2LB=rq}JN4sQ2Szz~*!IeOt;<STw7iaV$wyC|1 zwRp_Ccm;mX$_AFW!%tZW5X!U)9Cy#?ZKNfxScG*O$Bz0~HhOupWXW;%XoS;l&l*p| zuv93jXmvApwJvlavHra-r9^B?iYJgB#z!vFf+t}3l3E;vU0CV0jc;ye!9qKX4-z2t z<{@xfQWC7^!S$SC+h+f_cwfGhJjAM5+**=oKohqf72}#5{IRcWl8EdD??U9UV~lA> z!#t+l-*&Y|k`LU?yTb9X2FKIDt_Y@;d|Jw-rZF*G4+gETMR<ISh92CmHp)XU>y%o( z3_qV~it1bp*UcrqzS_H)2%d?}SZfG4AiJqUFm(v=NFntTJJ#Gf`)Md9D=%?ZvCh<& zI$Y1(8WW!sT<VEjOSrOzZ*IAVsGX4yI8Z90y}~MyiCk6Aa7f^-V)Aor{1c_7_$^5T zg?2)%X|Ei0$6YeMiAyM6e|<>WDWA(6j*>kjVwa|_NPhF_N;cdo!)V^8soZH;SWBgH zr8(>1jj5UocgSy{`vO};Vm|w+25)5s7@HHDY%Erh4s6|vN<6^tUXKwck((O;)8yoJ z%086eXM#1t#IsY|-6DjyC)M5)_!+NzCv-k7S=Ku9CN^FMS}^QZz~ngA%Hn-$B|TS+ ztL|PWj8%E3`H8Z#%lmhpCOLF%<V+mEaC1l7e%WfOBJmx|DigaD)$gxo*zQVJdy<}H ztX*EXRv$Wh_3S&6EK^6vjT9kttBjt^RpU;3$<{^Ko3^)ZNModsAyW9&@>Ff|X|uIi z;li_5I}j-EnM77AWFZvSKJhgryEF#b=C6OiInNAkQC-&mxl~^8e(-8saa*%#$zatr z%_+g{9ounAZ)(1$PHml2EH3G3?BCk1sL#g?M)Q0;k~8{aR5r4*V>KCzXvY>M&i$Ut zQubQZ`p$_7@=4{R<V&jOg*WTe@j)-e8rKLS=p}!-oVDVQn&d@2H<FV2ha(Z^HBncf z@`_2KS;@<tc=Q6P6#i%*+mX~c5z79mavLunwd7KQ{((&EtHWmMmlX&)+hOw6-b(_0 z7DCCE4wTE9F>P<G469s`IV;QB6Flo|JrP5?a{_W7-#2=DzO*a5Rfspyx<NThQer0` z4!KxUTo=77`~G{@2vnga)*eCjDuj)X+jH9QyBBBKTA71=jNN>~JK_@mYqkqmX2b$8 z0paF`6L+Xp=|%cFe$t*c*EtIgFPu|`5llWX>mB*=H1guq{ccWpe{=U{{$G?D_C}xP zz!yTn$*aPJ-=lw}Zp}xXF#$8ny+67&h$YxD6ANIIj72B*Uij&-yzKZEvg8{nGk_?m zl&LR{^%fg|-R@vLBE(8;a?|7_YYVcC3SMx-d7?MNwViLII#fJQ*D~>391lUpn=_CM zC?pRzKmvQ%$^%oz3O+t#FB`NU<g4X_1&X?j$Fl8<!xDE)%bcR2zY;a>PYj;!{Il4< zY{=eOvv6)Rl<)c9kM4Ihv3$c-jK#$=iv7K+2Tnp#tptQk<V&L};+84~q$T9VWI)C! z^PN4zYG9!RczHCJsK7s}z?3ud*fnn`;_TzRrLnsrTbswHlAU5>8NAVm1_8k1lc}@U z;i9Z%dL6GM{<LrsAOSgdy@_cC4ek2?g5osJR!KwQj_#J%z^jdjzT=ISmDyS4Qh(4j zw@39rlmZ4y?8r;`f*TvK3=*?Fgv0PXiFwt>Bkf=SOe_#ccAhUZ6+09`E%0_-sf2El zEbg&02H4XP^Y|@l2^lXVu)uFQ=AdGu^5`l>3&ZSQ6bXBc(!B|1>ijOtbjgrsl5n6| zEk1HodF-y&&5}(jx}nwZd1CQfN~}3!xIH$t$6wPe4js5d9DzE2QsN^(9CJ`a85snC z851FYYjEQqYQdp0Y#Bec5wKzf*-rH`_48?A;QWJmUPXKRbTbwSz)p34!bM!Sab7PB z<F(OUj}AeLd239f@pLdf{4bwqx_yxqJ3hkAYWFt`;eIS%owR_67BV3jiD>}gy1K!G z)}hW?AL6Cy42uR(7+{0fk@YsyQVdD(41^;ft&q>LppDeZ$38=VxKo1eZR(@Ue@nRs z>tJBTYa2R4wv)$(Chu2-h!7x}Pm`cO8iT@ncQPbf0Dv%g@xk$r^#8&jEj?t9Qr&*? zI%&Fs9ZXf0lLBDn>egVj5IxJVek0mDP_^wRxomj9iulPWUSo_~xjON3E*Au#T#H$M zQEGei_j3Isx4VP<FXVH~E)z>ChFQC1LrB}$1R;8i1dzIYYx^g6FJJKbCQZ*>2Gw|I z=;yDEsw@tc!_q2)VQ>wiz`7j908HS>&30!%0cd_W2(lXxD>ctG%?f04Az%*_fV=hO zP{g?QOLfC@hiW%K>Us7Y&uX7hvWPEUkMR*WI8Bv59TK5+>5yHHYE>o`1PRE#RRsjs z=Igx4g%J~0VA~7zZjllUuGA0024Mf&>R%3tuzI9;H|Ytp2GMCzo%kVp67~?h$)-0f z<sZ%f3b&s~dlfD!+ViPjjg1q7EAqnVp8`AV+GiP}5C2BCO|@K{;*Q}`p-L@^Ov(g^ zO_}UDjIx+cea9^r5QVlj#?!s89|VISwreJ#KUbYG|H@G_WPIKRRHQMAxu17NyF4ou zGR|8SZuy<DNWaMx+Sx6D)LaySjbu6<0KAf$05Cc=>OjC0y8Ggsf3yXtQBafr+SkpD zSoq3yNW_$s35Pdk;ZibSy_qj8F$<j8*g4jqbItpQG#6d@G}mE=sZy!6Y!7wsABN0e z+MDaZg>o(M0>;PGqv{fvF{Xo@>7O>(GW9a0e_PnUg2}n5X4M{1HCo0nBOk?#gMyD| zO~1JvE@s|CpTq#e4mKSUSp-qi(Bnt-pc;m}BSPa@R&BNh!$5WE3!|k<86n1;|252b zIGzj-?}TuuzLjMH+w!-&D(-x(J&C8=S3kp>>Zv_D{F_JOLe--QYKE|O_Xy^nh67K@ zTlHj96@XCFdCHgZ#Xvq7`@l^h8&o$x!C1l5>g=6&t+4N0;NBPr6Av){WbQA!?ps`4 z%q~uYegJW+CS+A|4Ea-<zBg$=f=1&2LoAhgR5Sh%%i&SeesPIIm95Ue>3|64%&*1M zK^yyX%u}HNTkQvf-KviE(IgkR)E{(lhiI)3deG!ld1sUpM;W1rdKW5!5d7ztoX5|u zp6P4*VRE>tXs*E#vRrMge9=E(>jeAAfRP+SGs9|oeM-_O^$T-$N^G3?k_drcapxr1 zOW8R33R3=HDet)Q5@KZ3<JS^}uZtDaWW5_~jT#yWdFB!taluSEvy7jI9*JDqI9tT` zr|nSDAvIZeqrfjA*+_SMZW@omcwt2%2gOjFTU+1-W<E%t-No;6`6e{-B#+!91B~zB z5zf*D9@$%1^@>y5+p*j!k1aNXPl)!+Bv!Ty$m*qsl|-4_T<Gq<a4z4=5ob9O75P!= zo6PjbX`~7a_x<@=@g;(psApd}w1L~{8M>vX#jN;XSw;GR<}g3L{D{E0L(}Cl)>l*? zD#f#(JC(J_zv7w_^4ws^zo<UqlI`NwoN9u{y5sg0w*(IbHy5?|M^d*urn;`rq*VyC z1UC;MBBf6o8=O7V8{}F7f1l0##d5rUY<jqDRN8&%)`->X&Gk&`rG>N}5I}+M@?e6N z?MC-*pufiAFC2e15~o_9d^>igJgDZX9!54grEI2Rt!7E*n;Boh`RjGoti3@2fA%xU z`Y%wB+LDOkAnwUqJbZzA6}eN2FG$yZ`HFhf_=>f8Ppk`NMclk%`SN<1c00ncUc{j< z_ucKjg7ZUHg<eZL+CBR$(z*m4QI;!B@4P%V+O98k=2X~+{*iKWfY7`7+VJX?zhaN5 z4Q>5cX&JJ+M!`lI2-fmDL8-IIDwE-OF+MlqZL^S9Zc|8!XnNr?K#TXl8^VUIAE#Dn zv#l=}=fFKag<w>m&2umAfsfa0{a9>c>04ZY@v8rx{-=%qY=h=0|IfYv15&G7o+D}| Qc4#xPFtstMG<L`S4?vusK>z>% literal 0 HcmV?d00001 diff --git a/site/en/blog/we-are-chrome-for-developers/index.md b/site/en/blog/we-are-chrome-for-developers/index.md new file mode 100644 index 000000000..3fa02a126 --- /dev/null +++ b/site/en/blog/we-are-chrome-for-developers/index.md @@ -0,0 +1,58 @@ +--- +title: We are Chrome for Developers +description: > + Celebrating Chrome's 15th anniversary and our role as a trusted, helpful partner to developers. +layout: 'layouts/blog-post.njk' +date: 2023-09-20 +hero: 'image/kheDArv5csY6rvQUJDbWRscckLr1/qoyOvOMMXCv8LbhvSr2k.png' +thumbnail: 'image/kheDArv5csY6rvQUJDbWRscckLr1/njSenjQVjvSP6HSNpgxL.png' +alt: > + '' + +--- + +Chrome is celebrating its 15th anniversary this month. It's hard to believe how much the web has changed in that time and we, the Chrome team, feel privileged to have been able to play a part in its evolution, in partnership with one of the most driven, thriving communities. Most of the web's capabilities and exciting experiences today wouldn't exist without the contributions of engineers across browser vendors, standards bodies, frameworks and libraries, and a multitude of open source contributors as well as the work done by web developers. + +When we launched our browser 15 years ago, we also [launched Chromium](https://blog.chromium.org/2008/09/welcome-to-chromium_02.html) as a commitment for our support to the web, evolving our [core values](https://www.chromium.org/blink/guidelines/values/) to meet the changing needs of the web of today to being a responsible user agent, promoting a helpful and innovative web, and partnering to safeguard the openness of the web. + +## Being a responsible user agent + +With the web's latest capabilities, you can now [stream 3D games](https://www.cocos.com/en/post/ODdxxWGryD6DiM6wPJ3yhPklSzCLCCxE), [unleash your creativity](https://stratechery.com/2023/an-interview-with-adobe-chief-strategy-officer-scott-belsky/#web), and do so much more, all through the browser. As we work together to extend the platform's capabilities, it is also our responsibility to maintain trust on the web by keeping people safe and protecting their data. + +We have been focused on providing [more granular control over permissions](/blog/one-time-permissions/) granted to web apps, and using machine learning models to [filter out notifications and permission prompts](https://blog.google/products/chrome/building-a-more-helpful-browser-with-machine-learning/) from apps that are linked to malware and phishing attacks. And, with the [Privacy Sandbox](https://privacysandbox.com/) initiative, we're working closely with the entire ecosystem to improve privacy, while preserving the needs of a thriving digital ecosystem. + +There are billions of sites serving content today, so it's super important that we do this well to build a web that everyone can trust. + +## Promoting a helpful and innovative web + +Even after thirty years, the web remains one of the most powerful tools for getting things done. We want to keep extending its capabilities and efficiency. Over the years, we've made many upgrades to make the browser faster, safer, and more accessible for everyone. Over the next few years, we want to build capabilities that enable new experiences, enriched by the power of AI, and create a development environment that significantly increases developer productivity. + +### Capabilities that enable new experiences + +People use Chrome for all sorts of things—whether it's planning trips and researching holiday gifts, watching videos, or editing photos. We think there's so many more ways people can get things done on the web. Our efforts with [Project Fugu](/capabilities/) brought more than [50 APIs to the browser](/blog/is-project-fugu-done/), and helped companies like [LEGO® Education](/blog/lego-education-spike-web-bluetooth-web-serial/) to deliver their SPIKE(TM) kits to millions of students globally. + +Advances in user interface design play an equally important role in making experiences feel modern and intuitive. With [RenderingNG](/articles/renderingng/), we're getting the browser ready for the next generation of high fidelity content. By championing exciting APIs like [View Transitions](/docs/web-platform/view-transitions/) and [Scroll-driven animations](/articles/scroll-driven-animations/#:~:text=A%20scroll%2Ddriven%20animation%20is,which%20move%20as%20you%20scroll.), we're also pushing the platform's ability to deliver slick navigation and non-linear transitions that users only expect in native apps. + +### A platform primed for AI enabled experiences + +The web has always been the platform of choice for any developer looking to ship their product instantly, and we're seeing the same trend for many new AI products. Chrome Web Store developers offer many [exciting AI powered Chrome Extension experiences](https://chromewebstore.google.com/collection/gen_ai_extensions?hl=en), with over 100 million combined active users across hundreds of extensions that offer services like reading/writing, content summary, voice-to-text, code editing and more. + +With Google pioneering responsible AI, we're committed to bringing the [best of our products and solutions](https://developers.generativeai.google/) to web developers so they can deliver cutting-edge AI experiences to their users without needing to be a machine learning expert. And, by championing APIs like [WebGPU](/blog/webgpu-release/), we are enabling developers to bring their own machine learning models to the web at high speeds. + +### Solutions to significantly enhance developer productivity + +To usher in a more helpful web, it's important to center developers' needs in our work. We want to meet developers where they are—right in their workflows and taking their stack choices into account. +In 2020, we launched [Core Web Vitals](web.dev/web-vitals) that have proven to be a key tool in measuring page quality over the years. With tools like [Chrome DevTools](/docs/devtools/) and [Lighthouse](/docs/lighthouse/overview/#devtools), we made it easier for developers to find opportunities to improve their Web Vitals, right in their workflow. + +We also kicked off [Project Aurora](/aurora/) two years ago, which was an important collaboration between the Chrome team and open source frameworks to bring Core Web Vitals improvements directly to the tools that developers use the most. To help developers debug the code they write and not what gets compiled due to the framework, we launched the [Modern Web Debugging](/blog/devtools-modern-web-debugging/) initiative that has already built in support for many frameworks in Chrome DevTools. + +Finally, cross-browser testing and automation is yet another challenge that developers have to tackle. [Web Driver BiDi](/blog/webdriver-bidi-2023/) now has implementations across all major browser engines, using the best of the WebDriver Classic and the Chrome DevTools Protocol to make cross-browser automation significantly better for developers. + +## Partnering to safeguard the openness of the web + +We recognize that an open and thriving web helps drive more innovation. However, we also know that keeping up with platform changes and the inconsistency of features support across browsers remains one of the [top challenges](https://mdn.dev/archives/insights/reports/mdn-web-developer-needs-assessment-2020.html#needs-assessment-ranking-of-all-needs) for developers. +Over the past few years, we've been working in earnest to address this problem. We started with our collaboration on the [MDN DNA Study](https://web.dev/interop-2022/#it-all-started-in-2019) back in 2019–20, which resulted in the [Compat 2021](https://web.dev/compat2021/) initiative. This is now known as Interop, and continues to deliver positive results for the web, including landing much loved features like [Cascade layers](https://web.dev/interop-2022-wrapup/#cascade-layers) and [Container queries](https://web.dev/cq-stable/). And most recently, we've been working closely with the [WebDX Community Group](https://www.w3.org/community/webdx/) and other browser vendors to simplify updates to the web with [Baseline](web.dev/baseline). + +Over the years, we've actively [contributed to](https://blog.chromium.org/2017/10/building-unified-documentation-for-web.html) and [collaborated on](https://web.dev/open-web-docs/) many initiatives with ecosystem partners to build [an open, stable web](https://io.google/2023/program/528a223c-a3d6-46c5-84e4-88af2cf62670/). This work will continue as we move the platform forward. + +Reflecting back at our journey so far, we find ourselves marveling at the progress the web has made, and the prospect of what's next for Chrome and the web gives us a tingle of excitement. As we continue to play our role in the web ecosystem, we are more motivated than ever to be a trusted, helpful partner in building a powerful web that is made easier for developers. We are _Chrome for Developers_. \ No newline at end of file From edac90a4a137ecfa6cbc0ee19971f020df7b32dc Mon Sep 17 00:00:00 2001 From: Rachel Andrew <rachelandrew@google.com> Date: Wed, 20 Sep 2023 13:00:24 -0700 Subject: [PATCH 802/982] add logo (#7344) --- site/en/blog/we-are-chrome-for-developers/index.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/site/en/blog/we-are-chrome-for-developers/index.md b/site/en/blog/we-are-chrome-for-developers/index.md index 3fa02a126..5b6d0ae5f 100644 --- a/site/en/blog/we-are-chrome-for-developers/index.md +++ b/site/en/blog/we-are-chrome-for-developers/index.md @@ -55,4 +55,6 @@ Over the past few years, we've been working in earnest to address this problem. Over the years, we've actively [contributed to](https://blog.chromium.org/2017/10/building-unified-documentation-for-web.html) and [collaborated on](https://web.dev/open-web-docs/) many initiatives with ecosystem partners to build [an open, stable web](https://io.google/2023/program/528a223c-a3d6-46c5-84e4-88af2cf62670/). This work will continue as we move the platform forward. -Reflecting back at our journey so far, we find ourselves marveling at the progress the web has made, and the prospect of what's next for Chrome and the web gives us a tingle of excitement. As we continue to play our role in the web ecosystem, we are more motivated than ever to be a trusted, helpful partner in building a powerful web that is made easier for developers. We are _Chrome for Developers_. \ No newline at end of file +Reflecting back at our journey so far, we find ourselves marveling at the progress the web has made, and the prospect of what's next for Chrome and the web gives us a tingle of excitement. As we continue to play our role in the web ecosystem, we are more motivated than ever to be a trusted, helpful partner in building a powerful web that is made easier for developers. We are _Chrome for Developers_. + +{% Img src="image/kheDArv5csY6rvQUJDbWRscckLr1/ijjUVcPHYBhjZeNMud6n.gif", alt="The Chrome Developers logo transforming into Chrome for Developers.", width="800", height="208" %} From 52fd993749ae4df7b3c4dbd938446c733618f62e Mon Sep 17 00:00:00 2001 From: Nancymic2 <nmichell@google.com> Date: Wed, 20 Sep 2023 16:10:04 -0400 Subject: [PATCH 803/982] update origin trial info (#7305) * update origin trial info * update origin trial info * update origin trial info * update origin trial info * update origin trial info * update origin trial info * update origin trial info * update origin trial info * update origin trial info * typo - Update ot-end.md * update origin trial info * update origin trial info * update origin trial info * update origin trial info * update topics integration guide * update topics integration guide * update topics integration guide * Update site/en/docs/privacy-sandbox/attribution-reporting-experiment/index.md Co-authored-by: Anusmita <anusmitaray@google.com> * Update index.md --------- Co-authored-by: Anusmita <anusmitaray@google.com> --- .../en/_partials/privacy-sandbox/ar-engage.md | 2 +- .../privacy-sandbox/ar-get-updates.md | 2 +- .../ar-join-discussion-long.md | 4 +- .../privacy-sandbox/detect-features.md | 31 +++++ .../privacy-sandbox/fledge-api-next.md | 2 +- site/en/_partials/privacy-sandbox/ot-end.md | 3 + .../ps-implementation-status.md | 2 +- .../attribution-reporting-features.md | 10 +- .../privacy-sandbox/timeline/chips.md | 2 +- .../timeline/fenced-frames-features.md | 12 +- .../privacy-sandbox/timeline/fenced-frames.md | 2 +- .../timeline/private-aggregation-features.md | 4 +- .../timeline/shared-storage.md | 4 +- .../privacy-sandbox/timeline/topics.md | 2 +- .../privacy-sandbox/topics-feedback.md | 2 +- .../aggregation-service/index.md | 27 ++-- .../index.md | 12 +- .../part-1/index.md | 7 +- .../part-3/index.md | 2 +- .../attribution-reporting-experiment/index.md | 18 +-- .../attribution-reporting-migration/index.md | 11 +- .../attribution-reporting-updates/index.md | 2 +- .../chrome-shipping/index.md | 14 +-- .../attribution-reporting/index.md | 22 ++-- .../summary-reports/index.md | 20 ++- .../system-overview/index.md | 13 +- .../understanding-noise/index.md | 2 +- .../working-with-noise/index.md | 4 +- site/en/docs/privacy-sandbox/chips/index.md | 6 +- site/en/docs/privacy-sandbox/faq/index.md | 2 +- .../fedcm-developer-guide/index.md | 4 +- .../privacy-sandbox/fedcm-updates/index.md | 2 +- site/en/docs/privacy-sandbox/fedcm/index.md | 8 +- .../privacy-sandbox/fenced-frame/index.md | 20 +-- .../en/docs/privacy-sandbox/overview/index.md | 67 ++++------ .../permissions-policy/index.md | 4 +- .../private-aggregation-experiment/index.md | 7 +- .../private-aggregation-fundamentals/index.md | 7 +- .../private-aggregation/index.md | 14 +-- .../proposal-lifecycle/index.md | 15 +-- .../ad-auction/index.md | 7 +- .../protected-audience-api/index.md | 76 ++---------- .../protected-audience-api/opt-out/index.md | 5 +- .../protected-audience-api/reports/index.md | 2 +- .../protected-audience-experiment/index.md | 29 ++--- .../protected-audience/index.md | 16 ++- .../summary-reports/design-decisions/index.md | 4 +- .../privacy-sandbox/summary-reports/index.md | 3 +- .../topics-experiment/index.md | 34 ++--- .../docs/privacy-sandbox/topics/demo/index.md | 4 +- site/en/docs/privacy-sandbox/topics/index.md | 56 +-------- .../topics/integration-guide/index.md | 117 ++---------------- .../privacy-sandbox/topics/latest/index.md | 3 + .../topics/topic-classification/index.md | 6 +- .../unified-origin-trial/index.md | 4 +- .../docs/privacy-sandbox/user-agent/index.md | 2 +- 56 files changed, 266 insertions(+), 496 deletions(-) create mode 100644 site/en/_partials/privacy-sandbox/detect-features.md create mode 100644 site/en/_partials/privacy-sandbox/ot-end.md diff --git a/site/en/_partials/privacy-sandbox/ar-engage.md b/site/en/_partials/privacy-sandbox/ar-engage.md index a7d84cfc3..f7aa64f75 100644 --- a/site/en/_partials/privacy-sandbox/ar-engage.md +++ b/site/en/_partials/privacy-sandbox/ar-engage.md @@ -2,7 +2,7 @@ You can [participate and experiment with this API](/docs/privacy-sandbox/attribution-reporting-experiment/). -* Read the [client-side proposal](https://github.com/WICG/conversion-measurement-api/blob/main/AGGREGATE.md) and [aggregation service proposal](https://github.com/WICG/conversion-measurement-api/blob/main/AGGREGATION_SERVICE_TEE.md), ask questions, and suggest feedback. +* Read about [aggregatable reports](https://github.com/WICG/conversion-measurement-api/blob/main/AGGREGATE.md) and the [aggregation service](https://github.com/WICG/conversion-measurement-api/blob/main/AGGREGATION_SERVICE_TEE.md), ask questions, and suggest feedback. * Read the [Attribution reporting guides](/docs/privacy-sandbox/attribution-reporting/). * Ask questions and join discussions on the [Privacy Sandbox Developer Support repo](https://github.com/GoogleChromeLabs/privacy-sandbox-dev-support). \ No newline at end of file diff --git a/site/en/_partials/privacy-sandbox/ar-get-updates.md b/site/en/_partials/privacy-sandbox/ar-get-updates.md index 5b575be16..22919ea1f 100644 --- a/site/en/_partials/privacy-sandbox/ar-get-updates.md +++ b/site/en/_partials/privacy-sandbox/ar-get-updates.md @@ -2,7 +2,7 @@ * To be notified of status changes in the API, join the [mailing list for developers](https://groups.google.com/u/1/a/chromium.org/g/attribution-reporting-api-dev). * To closely follow all ongoing discussions on the API, click the **Watch** - button on the [GitHub proposal](https://github.com/WICG/conversion-measurement-api). + button on [GitHub](https://github.com/WICG/conversion-measurement-api). This requires you to have or [create a GitHub account](https://docs.github.com/en/get-started/signing-up-for-github/signing-up-for-a-new-github-account). * To get overall updates on the Privacy Sandbox, subscribe to the RSS feed [Progress in the Privacy Sandbox](/tags/progress-in-the-privacy-sandbox/). diff --git a/site/en/_partials/privacy-sandbox/ar-join-discussion-long.md b/site/en/_partials/privacy-sandbox/ar-join-discussion-long.md index 48a9ee383..7d971353c 100644 --- a/site/en/_partials/privacy-sandbox/ar-join-discussion-long.md +++ b/site/en/_partials/privacy-sandbox/ar-join-discussion-long.md @@ -5,8 +5,8 @@ experimenting with the API, your feedback is essential. ### Discuss the API -Like other Privacy Sandbox proposals, this API is documented and discussed publicly on GitHub. -[Read this proposal](https://github.com/WICG/conversion-measurement-api/). +Like other Privacy Sandbox APIs, this API is documented and discussed publicly on GitHub. +[Read about the API](https://github.com/WICG/conversion-measurement-api/). * Join the conversation on [existing issues](https://github.com/WICG/conversion-measurement-api/issues). * [Open a new Issue](https://github.com/WICG/conversion-measurement-api/issues/new) to ask diff --git a/site/en/_partials/privacy-sandbox/detect-features.md b/site/en/_partials/privacy-sandbox/detect-features.md new file mode 100644 index 000000000..0c705a03e --- /dev/null +++ b/site/en/_partials/privacy-sandbox/detect-features.md @@ -0,0 +1,31 @@ +## Detect features {: #feature-detection} + +As with all web features, you should check they are reporting as available in +the browser before attempting to use them. You can do this by checking for the +existence of the relevant API in the right location: + +```js +if (document.featurePolicy.allowsFeature('attribution-reporting')) { + // Attribution Reporting enabled +} + +if ('runAdAuction' in navigator) { + // Protected Audience API enabled +} + +if ('browsingTopics' in document) { + // Topics enabled +} + +if ('HTMLFencedFrameElement' in window) { + // Fenced Frames enabled +} + +if ('sharedStorage' in window) { + // Shared Storage enabled +} + +if (window?.sharedStorage?.selectURL instanceof Function) { + // optionally check specifically for the selectURL function in Shared Storage +} +``` \ No newline at end of file diff --git a/site/en/_partials/privacy-sandbox/fledge-api-next.md b/site/en/_partials/privacy-sandbox/fledge-api-next.md index 386e28dc1..d5c77b24b 100644 --- a/site/en/_partials/privacy-sandbox/fledge-api-next.md +++ b/site/en/_partials/privacy-sandbox/fledge-api-next.md @@ -5,7 +5,7 @@ works for everyone. ### Discuss the API -Like other Privacy Sandbox proposals, this API is documented and +Like other Privacy Sandbox APIs, this API is documented and [discussed publicly](/docs/privacy-sandbox/protected-audience/#engage). ### Experiment with the API diff --git a/site/en/_partials/privacy-sandbox/ot-end.md b/site/en/_partials/privacy-sandbox/ot-end.md new file mode 100644 index 000000000..3e49e2673 --- /dev/null +++ b/site/en/_partials/privacy-sandbox/ot-end.md @@ -0,0 +1,3 @@ + {% Aside 'important' %} + The Privacy Sandbox Relevance and Measurement origin trial ended September 20, 2023 and the APIs are now available for 99% of Chrome users, and origin trial enrollment is now closed. To keep abreast of the percentage of users each API is enabled for, refer to the [Chrome status graphs](https://pscs.glitch.me/). + {% endAside %} diff --git a/site/en/_partials/privacy-sandbox/ps-implementation-status.md b/site/en/_partials/privacy-sandbox/ps-implementation-status.md index 666c407ce..4b6a45559 100644 --- a/site/en/_partials/privacy-sandbox/ps-implementation-status.md +++ b/site/en/_partials/privacy-sandbox/ps-implementation-status.md @@ -1,4 +1,4 @@ -- The [Topics API proposal](https://github.com/jkarlin/topics) has completed the public discussion phase and is currently available in an [origin trial](/docs/privacy-sandbox/unified-origin-trial/). The API is now approaching launch for scaled adoption. +- The [Topics API](https://github.com/jkarlin/topics) has completed the public discussion phase and is currently available to 99 percent of users, scaling up to 100 percent. - To provide your feedback on the Topics API, create an Issue on the [Topics explainer](https://github.com/jkarlin/topics/issues) or participate in discussions in the [Improving Web Advertising Business Group](https://www.w3.org/community/web-adv/participants). The explainer has a number of open questions that still require further definition. - [The Privacy Sandbox timeline](http://privacysandbox.com/timeline) provides implementation timelines for the Topics API and other Privacy Sandbox proposals. - [Topics API: latest updates](/docs/privacy-sandbox/topics/latest/) details changes and enhancements to the Topics API and implementations. diff --git a/site/en/_partials/privacy-sandbox/timeline/attribution-reporting-features.md b/site/en/_partials/privacy-sandbox/timeline/attribution-reporting-features.md index 899bc6468..34a5c648e 100644 --- a/site/en/_partials/privacy-sandbox/timeline/attribution-reporting-features.md +++ b/site/en/_partials/privacy-sandbox/timeline/attribution-reporting-features.md @@ -7,11 +7,11 @@ </thead> <tr> <td>Event-level reports for clicks and views<br><a href="https://github.com/WICG/conversion-measurement-api/blob/main/EVENT.md">Explainer</a></td> - <td>Available in Chrome for origin trial</td> + <td>Now in general availability</td> </tr> <tr> <td>Aggregatable reports for clicks and views<br><a href="https://github.com/WICG/conversion-measurement-api/blob/main/AGGREGATE.md">Explainer</a></td> - <td>Available in Chrome for origin trial</td> + <td>Now in general availability</td> </tr> <tr> <td>Conversion journey: app-to-web<br><a href="https://github.com/WICG/conversion-measurement-api/blob/main/app_to_web.md">Web explainer</a> and <a href="https://developer.android.com/design-for-safety/privacy-sandbox/attribution-app-to-web">Android explainer</a><br><a href="https://groups.google.com/u/0/a/chromium.org/g/attribution-reporting-api-dev/c/7cXZ4x62CmE">Mailing list announcement</a></td> @@ -35,15 +35,15 @@ </tr> <tr> <td>Support for filter-based deduplication keys for aggregatable reports<br><a href="https://groups.google.com/a/chromium.org/g/attribution-reporting-api-dev/c/U-XsiJrxbRQ/">Mailing list announcement</a></td> - <td>Available in Chrome for origin trial in Q1 2023</td> + <td>Now in general availability</td> </tr> <tr> <td>Support for source registration success reports in verbose debugging<br><a href="/docs/privacy-sandbox/attribution-reporting-debugging/part-3/#verbose-debug-report-of-type-source-success">Debugging cookbook</a></td> - <td>Available in Chrome for origin trial in Q1 2023</td> + <td>Now in general availability</td> </tr> <tr> <td>Reducing delays for aggregatable reports<br><a href="https://github.com/WICG/attribution-reporting-api/issues/738">Github issue</a> | <a href="https://github.com/WICG/attribution-reporting-api/blob/main/AGGREGATE.md#aggregatable-reports">Updated Explainer</a></td> - <td>Available in Chrome for origin trial in Q2 2023</td> + <td>Now in general availability</td> </tr> <tr> <td>Phase 1 Lite Flexible Event-Level<br><a href="https://github.com/WICG/attribution-reporting-api/blob/main/flexible_event_config.md#phase-1-lite-flexible-event-level">Flexible event-level configurations explainer</a></td> diff --git a/site/en/_partials/privacy-sandbox/timeline/chips.md b/site/en/_partials/privacy-sandbox/timeline/chips.md index c4bf3e962..daa3f9323 100644 --- a/site/en/_partials/privacy-sandbox/timeline/chips.md +++ b/site/en/_partials/privacy-sandbox/timeline/chips.md @@ -1,3 +1,3 @@ * Enabled by default in [Chrome 114 and higher](https://chromestatus.com/feature/5179189105786880). -* An [origin trial](/origintrials/#/view_trial/1239615797433729025) was available from Chrome 100 to 106. +* An [origin trial](/origintrials/#/view_trial/1239615797433729025), now complete, was available from Chrome 100 to 116. * Read the [Intent to Experiment](https://groups.google.com/a/chromium.org/g/blink-dev/c/_dJFNJpf91U) and [Intent to Ship](https://groups.google.com/a/chromium.org/g/blink-dev/c/JNOQvsTxecI/m/V-OewM3lAwAJ). diff --git a/site/en/_partials/privacy-sandbox/timeline/fenced-frames-features.md b/site/en/_partials/privacy-sandbox/timeline/fenced-frames-features.md index a3032d78b..c3a807402 100644 --- a/site/en/_partials/privacy-sandbox/timeline/fenced-frames-features.md +++ b/site/en/_partials/privacy-sandbox/timeline/fenced-frames-features.md @@ -7,26 +7,26 @@ </thead> <tr> <td>Web API changes for urn to config<br><a href="https://github.com/WICG/fenced-frame/blob/master/explainer/fenced_frame_config.md">Explainer</a></td> - <td>Available in Chrome for origin trial in Q1 2023. </td> + <td>Now in general availability. </td> </tr> <tr> <td>Add size to API for K-Anon check for URLs and Frame Size<br><a href="https://github.com/WICG/turtledove/issues/312">Github Issue</a></td> - <td>Available in Chrome for origin trial in Q2 2023. </td> + <td>Now in general availability. </td> </tr> <tr> <td>Protected Audience Fenced Frames support for event-level reports with Attribution Reporting<br><a href="https://github.com/WICG/turtledove/issues/289">Github Issue</a></td> - <td>Available in Chrome for origin trial in Q1 2023. </td> + <td>Now in general availability. </td> </tr> <tr> <td>Protected Audience, Fenced Frames, and Private Aggregation API support<br>urn-iframes reportEvent<br><a href="https://github.com/WICG/turtledove/issues/309">Github Issue</a></td> - <td>Available in Chrome for origin trial in Q1 2023. </td> + <td>Now in general availability. </td> </tr> <tr> <td>Protected Audience component ads reporting <br><a href="https://github.com/WICG/turtledove/issues/332">Github Issue</a></td> - <td>Available in Chrome for origin trial in Q2 2023. </td> + <td>Now in general availability. </td> </tr> <tr> <td>Deprecate `src` attribute for the config attribute<br><a href="https://github.com/WICG/fenced-frame/blob/master/explainer/fenced_frame_config.md">Github Issue</a></td> - <td>Available in Chrome for origin trial in Q2 2023. </td> + <td>Now in general availability. </td> </tr> </table> diff --git a/site/en/_partials/privacy-sandbox/timeline/fenced-frames.md b/site/en/_partials/privacy-sandbox/timeline/fenced-frames.md index 2a07bba5a..fa14d29f5 100644 --- a/site/en/_partials/privacy-sandbox/timeline/fenced-frames.md +++ b/site/en/_partials/privacy-sandbox/timeline/fenced-frames.md @@ -1,2 +1,2 @@ -* The [Fenced Frames](https://github.com/shivanigithub/fenced-frame) proposal is now [moving to general availability](/blog/privacy-sandbox-launch/). +* The [Fenced Frames](https://github.com/shivanigithub/fenced-frame) proposal is now [in general availability](/blog/privacy-sandbox-launch/). * [Chrome Platform Status](https://chromestatus.com/feature/5699388062040064) diff --git a/site/en/_partials/privacy-sandbox/timeline/private-aggregation-features.md b/site/en/_partials/privacy-sandbox/timeline/private-aggregation-features.md index c2914832e..8ff3d882c 100644 --- a/site/en/_partials/privacy-sandbox/timeline/private-aggregation-features.md +++ b/site/en/_partials/privacy-sandbox/timeline/private-aggregation-features.md @@ -11,11 +11,11 @@ </tr> <tr> <td>Private Aggregation API available for origin trial testing in Chrome stable channel<br><a href="https://github.com/patcg-individual-drafts/private-aggregation-api">Explainer</a></td> - <td>Available in Chrome for origin trial in Q2 2023</td> + <td>Now in general availability</td> </tr> <tr> <td>Prevent invalid Private Aggregation API reports with report verification for Shared Storage<br><a href="https://github.com/patcg-individual-drafts/private-aggregation-api/blob/main/report_verification.md">Explainer</a></td> - <td>Available in Chrome for origin trial in Q2 2023</td> + <td>Now in general availability</td> </tr> <tr> <td>Private Aggregation debug mode availability dependent on 3PC eligibility<br><a href="https://github.com/patcg-individual-drafts/private-aggregation-api/issues/57">GitHub issue</a></td> diff --git a/site/en/_partials/privacy-sandbox/timeline/shared-storage.md b/site/en/_partials/privacy-sandbox/timeline/shared-storage.md index 91deb521a..8f27eda8e 100644 --- a/site/en/_partials/privacy-sandbox/timeline/shared-storage.md +++ b/site/en/_partials/privacy-sandbox/timeline/shared-storage.md @@ -1,6 +1,6 @@ -* The [Shared Storage proposal](https://github.com/WICG/shared-storage) is now [moving to general availability](/blog/privacy-sandbox-launch/). +* The [Shared Storage API](https://github.com/WICG/shared-storage) has now [moved to general availability](/blog/privacy-sandbox-launch/). * A [live demo is available](#try-the-shared-storage-api), as is testing: * URL selection output gate is available for local testing from Chrome M105+. * Private Aggregation output gate is available for local testing from Chrome M107+. - * Measurement with the Private Aggregation API is available in the [Privacy Sandbox Unified Origin Trial](/docs/privacy-sandbox/unified-origin-trial/) from Chrome M107+ Beta. + * Measurement with the Private Aggregation API is now in general availability. * [Chrome platform status](https://chromestatus.com/feature/6256348582903808) diff --git a/site/en/_partials/privacy-sandbox/timeline/topics.md b/site/en/_partials/privacy-sandbox/timeline/topics.md index 9d3954c9a..30039fb8b 100644 --- a/site/en/_partials/privacy-sandbox/timeline/topics.md +++ b/site/en/_partials/privacy-sandbox/timeline/topics.md @@ -1,4 +1,4 @@ -* The [Topics API proposal](https://github.com/jkarlin/topics) is now [moving to general availability](/blog/privacy-sandbox-launch/). +* The [Topics API](https://github.com/jkarlin/topics) is now [in general availability](/blog/privacy-sandbox-launch/). * To provide your feedback on the Topics API, create an Issue on the [Topics explainer](https://github.com/jkarlin/topics/issues) or participate in discussions in the [Improving Web Advertising Business Group](https://www.w3.org/community/web-adv/participants). The explainer has a number of open questions that still require further definition. * [Topics API latest updates](/docs/privacy-sandbox/topics/latest/) details changes and enhancements to the Topics API and implementations. * [Topics Chrome platform status](https://chromestatus.com/feature/5680923054964736): Specific to the Topics API on Chrome. diff --git a/site/en/_partials/privacy-sandbox/topics-feedback.md b/site/en/_partials/privacy-sandbox/topics-feedback.md index 24046bff3..7f0ca6088 100644 --- a/site/en/_partials/privacy-sandbox/topics-feedback.md +++ b/site/en/_partials/privacy-sandbox/topics-feedback.md @@ -1,6 +1,6 @@ ## Engage and share feedback -- **GitHub**: Read the Topics API [explainer](https://github.com/jkarlin/topics), and [raise questions and follow discussion in issues on the proposal repo](https://github.com/jkarlin/topics/issues). +- **GitHub**: Read the Topics API [explainer](https://github.com/jkarlin/topics), and [raise questions and follow discussion in issues on the API repo](https://github.com/jkarlin/topics/issues). - **W3C**: Discuss industry use cases in the [Improving Web Advertising Business Group](https://www.w3.org/community/web-adv/participants). - **Announcements**: [Join or view the mailing list](http://groups.google.com/a/chromium.org/g/topics-api-announce). - **Privacy Sandbox developer support**: Ask questions and join discussions on the [Privacy Sandbox Developer Support repo](https://github.com/GoogleChromeLabs/privacy-sandbox-dev-support). diff --git a/site/en/docs/privacy-sandbox/aggregation-service/index.md b/site/en/docs/privacy-sandbox/aggregation-service/index.md index d2eb69af3..74d8df783 100644 --- a/site/en/docs/privacy-sandbox/aggregation-service/index.md +++ b/site/en/docs/privacy-sandbox/aggregation-service/index.md @@ -8,6 +8,7 @@ description: > Deploy and manage this service to produce summary reports for the Attribution Reporting API or the Private Aggregation API. date: 2022-11-29 +updated: 2023-09-18 authors: - alexandrawhite --- @@ -20,12 +21,12 @@ create a [summary report](/docs/privacy-sandbox/summary-report/). ## Implementation status -* The [Aggregation Service proposal](https://github.com/WICG/attribution-reporting-api/blob/main/AGGREGATION_SERVICE_TEE.md) - is [now moving to general availability](/blog/privacy-sandbox-launch/). +* The [Aggregation Service](https://github.com/WICG/attribution-reporting-api/blob/main/AGGREGATION_SERVICE_TEE.md) + has [now moved to general availability](/blog/privacy-sandbox-launch/). * The [Aggregation Service can be tested](#test) with the Attribution Reporting API and the Private Aggegration API for Protected Audience API and Shared Storage. -The proposal outlines +The explainer outlines [key terms](https://github.com/WICG/attribution-reporting-api/blob/main/AGGREGATION_SERVICE_TEE.md#key-terms), useful for understanding the Aggregation Service. @@ -151,25 +152,13 @@ We recommend reading the corresponding experiment and participate guide for the * [Attribution Reporting API](/docs/privacy-sandbox/attribution-reporting-experiment/) * [Private Aggregation API](/docs/privacy-sandbox/private-aggregation-experiment/) -### Local testing +To test the Aggregation Service on AWS, see [these instructions](https://github.com/privacysandbox/aggregation-service/blob/main/README.md#test-on-aws-with-support-for-encrypted-reports). -We've created a local testing tool to process aggregatable reports for Attribution Reporting and the Private Aggregation API. [Read the instructions](https://github.com/privacysandbox/aggregation-service/blob/main/README.md). - - -### Test on AWS - -To test the Aggregation Service on AWS, [register for the origin trial](/origintrials/#/view_trial/771241436187197441) and complete the -[onboarding form](https://forms.gle/EHoecersGKhpcLPNA). -Once submitted, we'll contact you to verify your information and send the remaining instructions. - -To test on AWS, install [Terraform](https://www.terraform.io/) and the latest -[AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html). - -[Read the instructions](https://github.com/privacysandbox/aggregation-service/blob/main/README.md#test-on-aws-with-support-for-encrypted-reports). +A [local testing tool](https://github.com/privacysandbox/aggregation-service/blob/main/README.md) is also available to process aggregatable reports for Attribution Reporting and the Private Aggregation API. ## Engage and share feedback -The Aggregation Service is a key piece of the Privacy Sandbox measurement proposals. Like other Privacy Sandbox proposals, this is documented and discussed publicly on GitHub. +The Aggregation Service is a key piece of the Privacy Sandbox measurement APIs. Like other Privacy Sandbox APIs, this is documented and discussed publicly on GitHub. -* **Github**: Read the [proposal](https://github.com/WICG/attribution-reporting-api/blob/main/AGGREGATION_SERVICE_TEE.md), [raise questions and participate in the discussion](https://github.com/WICG/attribution-reporting-api/issues). Also take a look at the [Aggregation Service implementation](https://github.com/privacysandbox/aggregation-service) and provide [feedback on the implementation](https://github.com/privacysandbox/aggregation-service/issues). +* **Github**: Read the [explainer](https://github.com/WICG/attribution-reporting-api/blob/main/AGGREGATION_SERVICE_TEE.md), [raise questions and participate in the discussion](https://github.com/WICG/attribution-reporting-api/issues). Also take a look at the [Aggregation Service implementation](https://github.com/privacysandbox/aggregation-service) and provide [feedback on the implementation](https://github.com/privacysandbox/aggregation-service/issues). * **Developer support**: Ask questions and join discussions on the [Privacy Sandbox Developer Support repo](https://github.com/GoogleChromeLabs/privacy-sandbox-dev-support). diff --git a/site/en/docs/privacy-sandbox/attribution-reporting-data-clearing/index.md b/site/en/docs/privacy-sandbox/attribution-reporting-data-clearing/index.md index 277cfe367..2036c860a 100644 --- a/site/en/docs/privacy-sandbox/attribution-reporting-data-clearing/index.md +++ b/site/en/docs/privacy-sandbox/attribution-reporting-data-clearing/index.md @@ -6,7 +6,7 @@ subhead: > description: > How does user-initiated data clearing impact attribution reports? How does that compare with cookie-based measurement? date: 2021-10-19 -updated: 2021-10-19 +updated: 2023-09-18 authors: - maudn --- @@ -23,8 +23,8 @@ Instead, it works as follows: attribution reports that link an ad click with a c generated and stored on the user's device; later, the browser sends these reports to a predefined endpoint. -Sites have experimented with the Attribution Reporting API in Chrome, via an [origin -trial](/docs/privacy-sandbox/attribution-reporting/#status). +Sites have experimented with the Attribution Reporting API in Chrome, via an origin +trial, which has now concluded. One of the insights provided by these early experiments is the impact of **user-initiated data clearing, such as browser history clearing,** on the data advertisers and ad tech companies get from the API. [Aggregate Chrome statistics](https://groups.google.com/u/1/a/chromium.org/g/attribution-reporting-api-dev/c/5Ppe0cL-l1Y) @@ -48,8 +48,8 @@ However, they likely won't be consistently observable for all organizations that use the API. These numbers are aggregated and measured for the set of sites that were running an origin -trial. They differ across sites and are likely to change as more organizations use the API in an -origin trial and use different parameters. +trial (which is now closed). They differ across sites and are likely to change as more organizations have used the API in an +origin trial since these metrics were collected and use different parameters. {% endAside %} **Multiple factors influence these numbers:** @@ -167,7 +167,7 @@ measurement—whether it's based on the Attribution Reporting API or on cookies. Organizations that have experimented with the API via an origin trial may have observed a **discrepancy between cookie-based measurement and Attribution Reporting based measurement**: less conversions may have been reported for Attribution Reporting. User-initiated data clearing -may account for observed loss, but the discrepancy must be monitored in future origin trials in +may account for observed loss, but the discrepancy must be monitored in the future in order to answer this question with certainty. Two elements are known to have played a role in the discrepancy between cookie-based measurement and diff --git a/site/en/docs/privacy-sandbox/attribution-reporting-debugging/part-1/index.md b/site/en/docs/privacy-sandbox/attribution-reporting-debugging/part-1/index.md index 6509fb204..3a04dcc69 100644 --- a/site/en/docs/privacy-sandbox/attribution-reporting-debugging/part-1/index.md +++ b/site/en/docs/privacy-sandbox/attribution-reporting-debugging/part-1/index.md @@ -4,7 +4,7 @@ title: 'Introduction to debug reports' subhead: Part 1 of 3 on debugging Attribution Reporting. Learn why debugging matters and when to use debug reports in testing. description: Part 1 of 3 on debugging Attribution Reporting. Learn why debugging matters and when to use debug reports in testing. date: 2022-12-13 -updated: 2023-09-11 +updated: 2023-09-18 authors: - maudn - alexandrawhite @@ -18,10 +18,7 @@ If you're testing the Attribution Reporting API, you should check that your integration is working properly, understand gaps in measurement results between your cookie-based implementation and your Attribution Reporting implementation, and troubleshoot any issues with your integration. -Debug reports are required to complete these tasks. Therefore, if you're participating -in the -[origin trial](/docs/privacy-sandbox/unified-origin-trial/), -we strongly recommend you set up debug reports. +Debug reports are required to complete these tasks. Therefore, we strongly recommend you set them up. ## Glossary diff --git a/site/en/docs/privacy-sandbox/attribution-reporting-debugging/part-3/index.md b/site/en/docs/privacy-sandbox/attribution-reporting-debugging/part-3/index.md index e51383bed..0f8db7d86 100644 --- a/site/en/docs/privacy-sandbox/attribution-reporting-debugging/part-3/index.md +++ b/site/en/docs/privacy-sandbox/attribution-reporting-debugging/part-3/index.md @@ -121,7 +121,7 @@ This is a subcase of not receiving a debug report: if for a given cookie convers - Fundamental integration issue. Review how to troubleshoot these in [Fix fundamental integration issues](/docs/privacy-sandbox/attribution-reporting-debugging/part-2/#fix-fundamental-issues). - Possible network issues. -- User preferences in browser settings, e.g. Privacy Sandbox turned off, or origin trial not active in the user's browser. +- User preferences in browser settings such as Privacy Sandbox turned off. ## Verbose debug reports reference diff --git a/site/en/docs/privacy-sandbox/attribution-reporting-experiment/index.md b/site/en/docs/privacy-sandbox/attribution-reporting-experiment/index.md index 8eb4dd423..34d21db14 100644 --- a/site/en/docs/privacy-sandbox/attribution-reporting-experiment/index.md +++ b/site/en/docs/privacy-sandbox/attribution-reporting-experiment/index.md @@ -2,17 +2,18 @@ layout: 'layouts/doc-post.njk' title: 'Attribution Reporting: experiment and participate' date: 2022-03-31 -updated: 2022-12-15 +updated: 2023-09-18 authors: - maudn - alexandrawhite --- +{% Partial 'privacy-sandbox/ot-end.njk' %} + Read [Attribution Reporting](/docs/privacy-sandbox/attribution-reporting/) to see the use cases and key concepts for this API and check the most recent [updates](/docs/privacy-sandbox/attribution-reporting-updates/). -Learn why we plan to [ship the Attribution Reporting API](/docs/privacy-sandbox/attribution-reporting/chrome-shipping) -in the first half of 2023. +Learn why [we shipped the Attribution Reporting API](/docs/privacy-sandbox/attribution-reporting/chrome-shipping). ## Try the API @@ -20,21 +21,14 @@ in the first half of 2023. 2. Check the [API status](/docs/privacy-sandbox/attribution-reporting/#status) to learn about ways you can experiment with the API today. 3. Experiment with the API. - * (Optional) If you ran an origin trial with this API in 2021, follow the [migration - guide](https://docs.google.com/document/d/1NY7SScCYcPc9v5wtf_fVAikFxGQTAFvwldhExN1P03Y/edit#) - to participate in the latest origin trial. * To experiment with the API, follow these guides: * [Getting started with the Attribution Reporting API](/docs/privacy-sandbox/attribution-reporting/getting-started/) 4. Experiment with [summary reports](/docs/privacy-sandbox/summary-reports/). * Ad techs can generate summary reports with the [aggregation service](/docs/privacy-sandbox/aggregation-service). Set up - [local testing](https://github.com/google/trusted-execution-aggregation-service/#set-up-local-testing) - or [test in production with Amazon Web Services](https://github.com/google/trusted-execution-aggregation-service/#test-on-aws-with-support-for-encrypted-reports) (AWS) : - * Create or have an [AWS account](https://portal.aws.amazon.com/gp/aws/developer/registration/index.html) available. - * [Register](/origintrials/#/view_trial/771241436187197441) for the - Privacy Sandbox Relevance and Measurement origin trial (OT). - * Complete the aggregation service + [local testing](https://github.com/google/trusted-execution-aggregation-service/#set-up-local-testing). + * Complete the aggregation service [onboarding form](https://forms.gle/EHoecersGKhpcLPNA). After you've submitted this form, we'll send a verification email and instructions. * Refer to the [Getting started guide](/docs/privacy-sandbox/attribution-reporting/getting-started/). diff --git a/site/en/docs/privacy-sandbox/attribution-reporting-migration/index.md b/site/en/docs/privacy-sandbox/attribution-reporting-migration/index.md index fc536d268..10c0b53b0 100644 --- a/site/en/docs/privacy-sandbox/attribution-reporting-migration/index.md +++ b/site/en/docs/privacy-sandbox/attribution-reporting-migration/index.md @@ -4,7 +4,7 @@ title: '[Obsolete] Migration guide (Chrome 92): Conversion Measurement API to At subhead: > The Conversion Measurement API is changing in Chrome 92. date: 2021-06-22 -updated: 2021-06-22 +updated: 2023-09-18 authors: - maudn --- @@ -18,7 +18,7 @@ ask your question. ## What's changing? Following the [API proposal](https://github.com/WICG/conversion-measurement-api)'s changes -in the first months of 2021, the API implementation in Chrome is evolving. Here's what changing: +in the first months of 2021, the API implementation in Chrome is evolving. Here's what's changing: - The API name, and the permissions policy name. - The HTML attribute names and `.well-known` URLs. @@ -28,11 +28,6 @@ in the first months of 2021, the API implementation in Chrome is evolving. Here' What remains unchanged in Chrome 92 is the set of supported features: event-level reports, for clicks only. **Expect updates on this**. After this change, other updates and features will be released in future Chrome versions. -{% Aside %} -To receive updates on the origin trial for this API and upcoming features, subscribe to -the [mailing list](https://groups.google.com/u/1/a/chromium.org/g/attribution-reporting-api-dev). -{% endAside %} - ## When do these changes take effect? These changes take effect starting from [Chrome @@ -45,7 +40,7 @@ Chrome 92 beta was released on June 3rd 2021. There are more changes to the API coming in future versions. They will use the new naming adopted in Chrome 92. {% endAside %} -If you're running an origin trial or have implemented a demo for this API, you have two +If you were running an origin trial or have implemented a demo for this API, you have two options: - **Option 1 (recommended)**: migrate your code now or in the following weeks, ideally before diff --git a/site/en/docs/privacy-sandbox/attribution-reporting-updates/index.md b/site/en/docs/privacy-sandbox/attribution-reporting-updates/index.md index 23973d519..1f8d2a7b4 100644 --- a/site/en/docs/privacy-sandbox/attribution-reporting-updates/index.md +++ b/site/en/docs/privacy-sandbox/attribution-reporting-updates/index.md @@ -42,7 +42,7 @@ If you're new to this API or have not experimented with it yet, read the was updated. * We've published [Experiment with Attribution Reporting: Strategy and tips](https://docs.google.com/document/d/1bU0a_njpDcRd9vDR0AJjwJjrf3Or8vAzyfuK8JZDEfo/edit?usp=sharing) for summary reports. -* **March 31, 2022**: New [origin trial for Ads relevance and measurement APIs](/blog/privacy-sandbox-unified-origin-trial/), which includes the Attribution Reporting API. +* **March 31, 2022**: New [origin trial for Ads relevance and measurement APIs](/blog/privacy-sandbox-unified-origin-trial/), which includes the Attribution Reporting API. Now completed (as of September 20, 2023). * **February 7, 2022**: Documentation for the [header trigger redirect](/blog/attribution-reporting-jan-2022-updates/#header-trigger-redirect) added. * **January 27, 2022**: [Migration for API updates](/blog/attribution-reporting-jan-2022-updates/) published, including: * [API mechanism changes](/blog/attribution-reporting-jan-2022-updates/#mechanism-changes) diff --git a/site/en/docs/privacy-sandbox/attribution-reporting/chrome-shipping/index.md b/site/en/docs/privacy-sandbox/attribution-reporting/chrome-shipping/index.md index 53862c68f..6e6bf3f36 100644 --- a/site/en/docs/privacy-sandbox/attribution-reporting/chrome-shipping/index.md +++ b/site/en/docs/privacy-sandbox/attribution-reporting/chrome-shipping/index.md @@ -1,17 +1,18 @@ --- layout: 'layouts/doc-post.njk' -title: 'Why Chrome plans to ship the Attribution Reporting API' +title: 'Why Chrome shipped the Attribution Reporting API' description: > - Understand why we plan to ship this API in the first half of 2023, while + Understand why we shipped this API while it is in incubation in the Web Incubator Community Group. date: 2022-12-15 +updated: 2023-09-18 authors: - csharrison - cilvento - maudn --- -The Attribution Reporting API is Chrome's proposal to support +The Attribution Reporting API is Chrome's API to support [Attribution Reporting use cases](/docs/privacy-sandbox/attribution-reporting/#use-cases-and-features) while enhancing privacy for users. It's one of many proposals ([1](https://github.com/patcg-individual-drafts/ipa), @@ -20,8 +21,7 @@ while enhancing privacy for users. It's one of many proposals [4](https://github.com/WICG/privacy-preserving-ads/blob/main/Bucketization.md), and more) attempting to solve the same problem. -This article explains our plans to ship the Attribution Reporting API sometime -in the first half of 2023, while it's still in incubation in the +This article explains why we shipped the Attribution Reporting API while it's still in incubation in the [Web Incubator Community Group](https://github.com/WICG/attribution-reporting-api). Chrome is fully committed to participating in the relevant W3C processes, and Chrome teams are working in the @@ -88,7 +88,7 @@ positive signals for Chrome's proposal. Our long-term goal remains an interoperable standard that browsers broadly support, and we are actively working to identify such a solution. -If, after we ship the Attribution Reporting API, a different mutually-agreeable +Now that we've shipped the Attribution Reporting API, if a different mutually-agreeable standard arrives, we would work with the ecosystem to support a thoughtful transition to the new API. At that point, we could explore deprecating the Attribution Reporting API. This would likely mean a significant period when @@ -108,7 +108,7 @@ already in response to developer feedback (such as We welcome further feedback and look forward to continuing to work closely with the community. -* **GitHub**: Read the [Attribution Reporting API proposal](https://github.com/WICG/attribution-reporting-api), +* **GitHub**: Read the [Attribution Reporting API explainer](https://github.com/WICG/attribution-reporting-api), and [raise questions and follow discussion.](https://github.com/WICG/attribution-reporting-api) * **Developer support**: Ask questions and join discussions on the [Privacy Sandbox Developer Support repo](https://github.com/GoogleChromeLabs/privacy-sandbox-dev-support). diff --git a/site/en/docs/privacy-sandbox/attribution-reporting/index.md b/site/en/docs/privacy-sandbox/attribution-reporting/index.md index 3a2bcdd53..8d85de186 100644 --- a/site/en/docs/privacy-sandbox/attribution-reporting/index.md +++ b/site/en/docs/privacy-sandbox/attribution-reporting/index.md @@ -8,7 +8,7 @@ description: > Measure when an ad click or view leads to a conversion, such as a purchase on an advertiser site. date: 2021-05-18 -updated: 2023-03-14 +updated: 2023-09-18 authors: - maudn - alexandrawhite @@ -64,8 +64,6 @@ If you're unfamiliar with some of these terms or concepts, consult the ## Try the API -- The Attribution Reporting API is available for experiments in the - [relevance and measurement origin trial](/docs/privacy-sandbox/unified-origin-trial/). - Test locally in your browser. [Set a _flag_](/docs/web-platform/chrome-flags/), which tells the Chrome browser to enable specific experimental features. @@ -169,7 +167,7 @@ conversion data is too coarse)—is an area of active research. ### Other features -Other features proposed for this API include: +Other features of this API include: - [App-to-web attribution](https://github.com/WICG/conversion-measurement-api/blob/main/app_to_web.md): see or click an ad in an app and convert on the web. @@ -195,16 +193,16 @@ In a future without third-party cookies, this API would be combined with other p {% Details %} {% DetailsSummary 'h3' %} -Differences between the API proposed by Chrome and the API proposed by WebKit +Differences between the Attribution Reporting API and the API proposed by WebKit {% endDetailsSummary %} Though the two APIs are different, Chrome and WebKit are working together in the open to simplify the developer experience, for example by aligning on the attribute names and on the [JSON structure for reports](https://github.com/privacycg/private-click-measurement/issues/30). -The feature set of the Attribution Reporting API proposed by Chrome is different from that of the +The feature set of the Attribution Reporting API is different from that of the Private Click Measurement API proposed by Safari/WebKit. -Most notably, with the Attribution Reporting API proposed by Chrome: +Most notably, with the Attribution Reporting API: - View-through measurement is supported. - Event-level reports can be provided. @@ -421,13 +419,11 @@ They provide conversion insights without tracking users across sites, by using t ## Engage and share feedback -- For questions about the proposal: +- For questions about the API: [create an issue](https://github.com/WICG/conversion-measurement-api/issues) - on the proposal repo. -- If you're an origin trial participant and have technical questions, join the - [Attribution Reporting mailing list](https://groups.google.com/u/1/a/chromium.org/g/attribution-reporting-api-dev) - for developers and ask questions there, or - [file a Chromium bug](https://bugs.chromium.org/p/chromium/issues/list?q=attribution%20reporting). + on the API repo. +- Follow API updates and announcements on the [Attribution Reporting mailing list](https://groups.google.com/u/1/a/chromium.org/g/attribution-reporting-api-dev). +- If you have technical questions, [file a Chromium bug](https://bugs.chromium.org/p/chromium/issues/list?q=attribution%20reporting). - For implementation, integration, and general best practice questions: [create an issue](https://github.com/GoogleChromeLabs/privacy-sandbox-dev-support) on the Privacy Sandbox developer support repo. diff --git a/site/en/docs/privacy-sandbox/attribution-reporting/summary-reports/index.md b/site/en/docs/privacy-sandbox/attribution-reporting/summary-reports/index.md index 96609880a..c31b42fa7 100644 --- a/site/en/docs/privacy-sandbox/attribution-reporting/summary-reports/index.md +++ b/site/en/docs/privacy-sandbox/attribution-reporting/summary-reports/index.md @@ -8,7 +8,7 @@ description: > Measure ad conversions aggregated across users, without revealing individual data. Formerly known as aggregate reports. date: 2022-02-16 -updated: 2022-06-06 +updated: 2023-09-18 authors: - alexandrawhite --- @@ -16,7 +16,6 @@ authors: ## Implementation status * [Chrome platform status](https://chromestatus.com/feature/5762222527610880) -* This API is available in the [ads relevance and measurement origin trial](/blog/privacy-sandbox-unified-origin-trial/). * [Participate and experiment with this API](/docs/privacy-sandbox/attribution-reporting-experiment/). * Keep track of the [API changes](/docs/privacy-sandbox/attribution-reporting-updates/). @@ -99,7 +98,7 @@ They detail cross-site user behavior and by ad tech providers. {% endAside %} -The proposed process to create a summary report is as follows: +The process to create a summary report is as follows: 1. Aggregatable reports are sent to the _reporting origin_, operated by an ad tech provider. @@ -125,7 +124,7 @@ The proposed process to create a summary report is as follows: {% Img class="screehshot", src="image/VbsHyyQopiec0718rMq2kTE1hke2/hoRtQVV2b2MCXIKi1okK.jpg", - alt="The proposed process to create a summary report is represented by encrypted reports sent to a collector server. The collector server sends the data to a secure aggregation service, which has a key to decrypt the data and create the summary report. The report is then sent back to the ad tech provider.", + alt="The process to create a summary report is represented by encrypted reports sent to a collector server. The collector server sends the data to a secure aggregation service, which has a key to decrypt the data and create the summary report. The report is then sent back to the ad tech provider.", width="800", height="168" %} <figcaption> @@ -160,17 +159,14 @@ does—nothing more or less. {% endAside %} [The initial -proposal](https://github.com/WICG/conversion-measurement-api/blob/main/AGGREGATION_SERVICE_TEE.md) +design](https://github.com/WICG/conversion-measurement-api/blob/main/AGGREGATION_SERVICE_TEE.md) asks each ad tech provider to operate their own instance of the aggregation service, in a trusted execution environment (TEE) deployed on a cloud service that supports needed security features. {% Aside %} -You can [participate in an origin trial](/docs/privacy-sandbox/attribution-reporting-experiment/) -for Attribution Reporting with the aggregation service, which will initially -support local testing or testing in TEEs provided by Amazon Web Services. Read -detailed [setup instructions for the aggregation +Read detailed [setup instructions for the aggregation service](https://github.com/google/trusted-execution-aggregation-service/#set-up-aggregation-service-for-aggregatable-reports). In the future, we intend to add support for other cloud providers that meet the @@ -197,8 +193,8 @@ The coordinator has several responsibilities: * Track the aggregatable reports to prevent reuse in aggregation for summary reports, as reuse may reveal personal identifying information (PII). -To make testing of the aggregation service available in an origin trial, -Google will play the role of the coordinator. Longer term, we are working to +To make testing of the aggregation service available in the now-complete origin trial, +Google played the role of the coordinator. Longer term, we are working to identify one or more independent entities who can share this role. ### What information is captured? @@ -276,7 +272,7 @@ taken: The ad tech can use the summary report to inform bidding and to offer reporting to its own customers. A [JSON-encoded scheme](https://github.com/WICG/conversion-measurement-api/blob/main/AGGREGATE.md#aggregate-attribution-reports) -is the proposed format for summary reports. +is the format for summary reports. {% Partial 'privacy-sandbox/ar-engage.njk' %} diff --git a/site/en/docs/privacy-sandbox/attribution-reporting/system-overview/index.md b/site/en/docs/privacy-sandbox/attribution-reporting/system-overview/index.md index 807f53106..f3c5ad32b 100644 --- a/site/en/docs/privacy-sandbox/attribution-reporting/system-overview/index.md +++ b/site/en/docs/privacy-sandbox/attribution-reporting/system-overview/index.md @@ -35,23 +35,16 @@ You should read this article if: * You're an ad tech or advertiser's **technical decision-maker**. You may work in operations, DevOps, data science, IT, marketing, or another role where - you make technical implementation decisions. You're wondering how the many - proposals for Attribution Reporting systems work together to build a tool - for privacy-preserving measurement. + you make technical implementation decisions. You're wondering how the APIs work for privacy-preserving measurement. * You're a **technical practitioner** (such as a developer, system operator, system architect, or data scientist) who will be setting up experiments with this API and Aggregation Service environment. -{% Aside %} -Right now, publishers don't have to take any action with this API. If this changes, this article will be updated accordingly. -{% endAside %} - In this article, you'll read a high-level, end-to-end explanation of how the services work for the Attribution Reporting API. If you're a technical practitioner, you can [experiment with this API](/docs/privacy-sandbox/attribution-reporting-experiment/) -locally or in production with the -[unified Privacy Sandbox Relevance and Measurement Origin Trial](/blog/privacy-sandbox-unified-origin-trial/). +locally. ## Overview @@ -290,7 +283,7 @@ works for everyone. ### Discuss the API -Like other Privacy Sandbox proposals, this API is documented and +Like other Privacy Sandbox APIs, this API is documented and [discussed publicly](/docs/privacy-sandbox/attribution-reporting-experiment/#join-the-discussion). ### Experiment with the API diff --git a/site/en/docs/privacy-sandbox/attribution-reporting/understanding-noise/index.md b/site/en/docs/privacy-sandbox/attribution-reporting/understanding-noise/index.md index c57e77b19..f32ff340f 100644 --- a/site/en/docs/privacy-sandbox/attribution-reporting/understanding-noise/index.md +++ b/site/en/docs/privacy-sandbox/attribution-reporting/understanding-noise/index.md @@ -58,7 +58,7 @@ All the elements that impact noise rely on two primary concepts. This has a few important practical implications that are outlined in the next section. This mechanism is part of the API design, and the practical implications are long-term. They will continue to play an important role when ad techs design and evaluate various aggregation strategies. -1. While the noise is drawn from the same distribution regardless of the summary value, that distribution depends on several parameters. One of these parameters, [epsilon](https://en.wikipedia.org/wiki/Differential_privacy#%CE%B5-differential_privacy), can be altered by ad techs during the origin trial to evaluate various utility/privacy adjustments. Consider the ability to tweak epsilon as temporary. We welcome your feedback on your use-cases and the values of epsilon that work well. +1. While the noise is drawn from the same distribution regardless of the summary value, that distribution depends on several parameters. One of these parameters, [epsilon](https://en.wikipedia.org/wiki/Differential_privacy#%CE%B5-differential_privacy), could be altered by ad techs during the concluded origin trial to evaluate various utility/privacy adjustments. However, consider the ability to tweak epsilon as temporary. We welcome your feedback on your use-cases and the values of epsilon that work well. While an ad tech company is not in direct control of the ways noise is added, it can influence the impact of noise on its measurement data. In the next sections, we'll dive into how noise can be influenced in practice. diff --git a/site/en/docs/privacy-sandbox/attribution-reporting/working-with-noise/index.md b/site/en/docs/privacy-sandbox/attribution-reporting/working-with-noise/index.md index d575da6fa..43cb6501f 100644 --- a/site/en/docs/privacy-sandbox/attribution-reporting/working-with-noise/index.md +++ b/site/en/docs/privacy-sandbox/attribution-reporting/working-with-noise/index.md @@ -133,9 +133,7 @@ An important part of allocating budget between different keys is understanding h ### Experimenting with epsilon -Lower values of epsilon provide greater privacy protection. - -During the origin trial, ad tech companies can choose epsilon within a given range. We recommend you start with epsilon=10. Epsilon can be set to any value between 0 and 64: 0 < epsilon ≤ 64. This range is wide enough to allow for flexible testing. +Ad techs can set epsilon to a value greater than 0 and up to and including 64. This range allows for flexible testing. Lower values of epsilon provide greater privacy protection. We recommend you start with epsilon=10. #### Recommendations to experiment diff --git a/site/en/docs/privacy-sandbox/chips/index.md b/site/en/docs/privacy-sandbox/chips/index.md index 577524016..9797a092b 100644 --- a/site/en/docs/privacy-sandbox/chips/index.md +++ b/site/en/docs/privacy-sandbox/chips/index.md @@ -7,7 +7,7 @@ description: > Allow developers to opt-in a cookie to "partitioned" storage, with a separate cookie jar per top-level site. Partitioned cookies can be set by a third-party service, but only read within the context of the top-level site where they were initially set. date: 2022-02-15 -updated: 2023-08-15 +updated: 2023-09-18 authors: - mihajlija tags: @@ -157,7 +157,7 @@ If you have a use case that relies on a shared cookie partition across sites wit ### Security design -To encourage good security practices, CHIPS proposes cookies only be set by and sent over secure protocols. +To encourage good security practices, with CHIPS, cookies are only set by and sent over secure protocols. Partitioned cookies must be set with `Secure`. @@ -296,5 +296,5 @@ To reset the demo, clear all cookies for the site: ## Resources -+ **GitHub**: Read the [proposal](https://github.com/WICG/CHIPS), [raise questions and follow the discussion](https://github.com/WICG/CHIPS/issues). ++ **GitHub**: Read the [explainer](https://github.com/WICG/CHIPS), [raise questions and follow the discussion](https://github.com/WICG/CHIPS/issues). + **Developer support**: Ask questions and join discussions on the [Privacy Sandbox Developer Support repo](https://github.com/GoogleChromeLabs/privacy-sandbox-dev-support). diff --git a/site/en/docs/privacy-sandbox/faq/index.md b/site/en/docs/privacy-sandbox/faq/index.md index 3f74c44bb..465eee27c 100644 --- a/site/en/docs/privacy-sandbox/faq/index.md +++ b/site/en/docs/privacy-sandbox/faq/index.md @@ -15,7 +15,7 @@ relevant sections of the documentation. Your questions are welcome. If you have a Privacy Sandbox question that is not answered in the documentation, you can: -- File an issue on the explainer repo for the proposal you're asking about. +- File an issue on the explainer repo for the proposal or API you're asking about. Links to these are provided below, and are available from the [Privacy Sandbox status page](/docs/privacy-sandbox/status). - Ask general Privacy Sandbox questions, and questions that cover multiple diff --git a/site/en/docs/privacy-sandbox/fedcm-developer-guide/index.md b/site/en/docs/privacy-sandbox/fedcm-developer-guide/index.md index e6dbd766c..4b40c1033 100644 --- a/site/en/docs/privacy-sandbox/fedcm-developer-guide/index.md +++ b/site/en/docs/privacy-sandbox/fedcm-developer-guide/index.md @@ -4,12 +4,12 @@ title: 'Federated Credential Management API: developer guide' subhead: > Learn how to use FedCM for for privacy-preserving identity federation. date: 2022-04-25 -updated: 2023-07-10 +updated: 2023-09-18 authors: - agektmr --- -[FedCM (Federated Credential Management)](docs/privacy-sandbox/fedcm) is a proposal for a privacy-preserving +[FedCM (Federated Credential Management)](docs/privacy-sandbox/fedcm) is a privacy-preserving approach to federated identity services (such as "Sign in with...") where users can log into sites without sharing their personal information with the identity service or the site. diff --git a/site/en/docs/privacy-sandbox/fedcm-updates/index.md b/site/en/docs/privacy-sandbox/fedcm-updates/index.md index 8cb23ae75..7325ab73c 100644 --- a/site/en/docs/privacy-sandbox/fedcm-updates/index.md +++ b/site/en/docs/privacy-sandbox/fedcm-updates/index.md @@ -8,7 +8,7 @@ description: > authors: - agektmr date: 2022-11-09 -updated: 2023-07-10 +updated: 2023-09-18 --- The Federated Credential Management API is diff --git a/site/en/docs/privacy-sandbox/fedcm/index.md b/site/en/docs/privacy-sandbox/fedcm/index.md index 57379a9d3..6acb4c292 100644 --- a/site/en/docs/privacy-sandbox/fedcm/index.md +++ b/site/en/docs/privacy-sandbox/fedcm/index.md @@ -6,15 +6,15 @@ subhead: > description: > A web platform API that allows users to login to websites with their federated accounts in a manner compatible with improvements to browser privacy. date: 2022-04-25 -updated: 2023-02-27 +updated: 2023-09-18 authors: - agektmr --- ## What is FedCM? -FedCM (Federated Credential Management) is a proposal for a privacy-preserving -approach to federated identity services (such as "Sign in with...") where +FedCM (Federated Credential Management) is a privacy-preserving +approach to federated identity services (such as "Sign in with...") whereby users can log into sites without sharing their personal information with the identity service or the site. @@ -323,7 +323,7 @@ To learn how to use the FedCM API check out the [FedCM developer guide](docs/pri ## Engage and share feedback {: #share-feedback} * **GitHub**: Read the - [proposal](https://github.com/fedidcg/FedCM/blob/main/explainer.md), [raise + [explainer](https://github.com/fedidcg/FedCM/blob/main/explainer.md), [raise issues and follow discussion](https://github.com/fedidcg/FedCM/issues). * **Developer support**: Ask questions and join discussions on the [Privacy Sandbox Developer Support diff --git a/site/en/docs/privacy-sandbox/fenced-frame/index.md b/site/en/docs/privacy-sandbox/fenced-frame/index.md index b65ef0999..7baff69b8 100644 --- a/site/en/docs/privacy-sandbox/fenced-frame/index.md +++ b/site/en/docs/privacy-sandbox/fenced-frame/index.md @@ -10,12 +10,12 @@ authors: - alexandrawhite - kevinkiklee date: 2022-03-07 -updated: 2023-03-14 +updated: 2023-09-18 --- ## Implementation status -This document outlines a proposal for a new HTML element: `<fencedframe>`. +This document outlines a new HTML element: `<fencedframe>`. {% Partial 'privacy-sandbox/timeline/fenced-frames.njk' %} @@ -23,7 +23,7 @@ This document outlines a proposal for a new HTML element: `<fencedframe>`. ## Why do we need fenced frames? -A fenced frame (`<fencedframe>`) is a proposed HTML element for embedded +A fenced frame (`<fencedframe>`) is an HTML element for embedded content, similar to an iframe. Unlike iframes, a fenced frame restricts communication with its embedding context to allow the frame access to cross-site data without sharing it with the embedding context. Some Privacy Sandbox APIs @@ -66,9 +66,9 @@ leakage across first-party storage will be significantly reduced. ### Work with cross-site data {: #cross-site-data } -Fenced frames is a [Privacy Sandbox proposal](/docs/privacy-sandbox/overview/) +Fenced frames is a [Privacy Sandbox feature](/docs/privacy-sandbox/overview/) which suggests top-level sites should partition data. Many Privacy Sandbox -proposals aim to satisfy cross-site use cases without third-party cookies or +proposals and APIs aim to satisfy cross-site use cases without third-party cookies or other tracking mechanisms. For example: * [Protected Audience API](/docs/privacy-sandbox/protected-audience/) allows for interest-based ad serving @@ -77,7 +77,7 @@ other tracking mechanisms. For example: access to unpartitioned cross-site data in a secure environment. Let's consider how fenced frames could work with the -[Protected Audience API](/docs/privacy-sandbox/protected-audience/) proposal. With the Protected Audience API, a user's interests +[Protected Audience API](/docs/privacy-sandbox/protected-audience/). With the Protected Audience API, a user's interests are registered on an advertiser's site in [interest groups](/docs/privacy-sandbox/protected-audience/#interest-group-detail), along with ads that may be of interest to the user. Then, on a separate site (known as a @@ -172,7 +172,7 @@ Fenced frames support fewer external communication options to preserve privacy. ### Will fenced frames replace iframes? Ultimately, fenced frames won't replace iframes and you won't have to use them. -Fenced frames are proposed for a more private frame for usage when data from +Fenced frames are a more private frame for usage when data from different top-level partitions needs to be displayed on the same page. Same-site iframes (sometimes known as friendly iframes) are considered trusted @@ -180,7 +180,7 @@ content. ## Use fenced frames {: #use-cases } -Fenced frames will work in combination with other Privacy Sandbox proposals to +Fenced frames will work in combination with other Privacy Sandbox APIs to display documents from different storage partitions within a single page. Potential APIs are currently in discussion. @@ -355,10 +355,10 @@ browsers](https://chromestatus.com/feature/5699388062040064#consensus). ## Engage and share feedback -The Fenced Frame proposal is under active discussion and subject to change in +Fenced Frames are under active discussion and subject to change in the future. If you try this API and have feedback, we'd love to hear it. -* **GitHub**: Read the [proposal](https://github.com/shivanigithub/fenced-frame), +* **GitHub**: Read the [explainer](https://github.com/shivanigithub/fenced-frame), [raise questions, and follow discussion](https://github.com/shivanigithub/fenced-frame/issues). * **Developer support**: Ask questions and join discussions on the diff --git a/site/en/docs/privacy-sandbox/overview/index.md b/site/en/docs/privacy-sandbox/overview/index.md index a4d8b1a05..7954dbb32 100644 --- a/site/en/docs/privacy-sandbox/overview/index.md +++ b/site/en/docs/privacy-sandbox/overview/index.md @@ -2,16 +2,18 @@ layout: layouts/doc-post.njk title: What is the Privacy Sandbox? subhead: > - A series of proposals to satisfy cross-site use cases without + A series of APIs to satisfy cross-site use cases without third-party cookies or other tracking mechanisms. description: "What's in it, what's it for, and how to get involved." date: 2021-05-18 -updated: 2023-02-27 +updated: 2023-09-18 authors: - samdutton - alexandrawhite --- +{% Partial 'privacy-sandbox/ot-end.njk' %} + The Privacy Sandbox initiative aims to create technologies that both protect people's privacy online and give companies and developers tools to build thriving digital businesses. @@ -34,7 +36,7 @@ direction for browsers. The Privacy Sandbox's vision of the future has browsers providing specific tools to satisfy specific use cases, while preserving user privacy. -## What are the Privacy Sandbox proposals? +## What are the Privacy Sandbox APIs? Chrome and other ecosystem stakeholders have offered more than 30 proposals to date, which can be found in the @@ -52,12 +54,12 @@ Several key proposals are listed below. ### Strengthen cross-site privacy boundaries -* [**CHIPS**](/docs/privacy-sandbox/chips/): Allow developers to opt-in a +* [**CHIPS**](/docs/privacy-sandbox/chips/) (released): Allow developers to opt-in a cookie to partitioned storage, with a separate cookie jar per top-level site. -* [**First-Party Sets**](/docs/privacy-sandbox/first-party-sets): Allow related +* [**First-Party Sets**](/docs/privacy-sandbox/first-party-sets) (released): Allow related domain names owned by the same entity to declare themselves as belonging to the same first party. -* [**Shared Storage**](/docs/privacy-sandbox/shared-storage/): Create a +* [**Shared Storage**](/docs/privacy-sandbox/shared-storage/) (released): Create a general-purpose API which allows sites to store and access unpartitioned cross-site data. This data must be read in a secure environment to prevent leakage. * [**Storage Partitioning**](https://github.com/privacycg/storage-partitioning): @@ -65,39 +67,39 @@ Several key proposals are listed below. such as `localStorage` or cookies, to be double-keyed: by the top-level site as well as the origin of the resource being loaded, rather than a single origin or site. -* [**Fenced Frames**](/docs/privacy-sandbox/fenced-frame): Securely embed +* [**Fenced Frames**](/docs/privacy-sandbox/fenced-frame) (released): Securely embed content onto a page without sharing cross-site data. * [**Network State Partitioning**](https://github.com/MattMenke2/Explainer---Partition-Network-State): Prevent browser network resources being shared across first-party contexts, by ensuring that every request has a network partition key that must match in order for resources to be reused. -* [**Federated Credential Management (FedCM)**](/docs/privacy-sandbox/fedcm/): +* [**Federated Credential Management (FedCM)**](/docs/privacy-sandbox/fedcm/) (released): Support federated identity without sharing the user's email address or other identifying information with a third-party service or website, unless the user explicitly agrees to do so. ### Show relevant content and ads -* [**Topics API**](/docs/privacy-sandbox/topics): Enable interest-based +* [**Topics API**](/docs/privacy-sandbox/topics) (released): Enable interest-based advertising without use of third-party cookies or tracking user behavior across sites. -* [**Protected Audience API**](/docs/privacy-sandbox/protected-audience): Ad selection to serve remarketing +* [**Protected Audience API**](/docs/privacy-sandbox/protected-audience) (released): Ad selection to serve remarketing and custom audience use cases, designed so that it cannot be used by third parties to track user browsing behavior across sites. The Protected Audience API is the first experiment to be implemented in Chromium from the - [TURTLEDOVE](https://github.com/WICG/turtledove) family of proposals. + [TURTLEDOVE](https://github.com/WICG/turtledove) family of APIs. ### Measure digital ads -* [**Attribution Reporting**](/docs/privacy-sandbox/attribution-reporting): +* [**Attribution Reporting**](/docs/privacy-sandbox/attribution-reporting) (released): Correlate ad clicks or ad views with conversions. Ad techs can generate event-level or [summary reports](/docs/privacy-sandbox/summary-reports). -* [**Private Aggregation API**](/docs/privacy-sandbox/private-aggregation/): +* [**Private Aggregation API**](/docs/privacy-sandbox/private-aggregation/) (released): Generate noisy summary reports with cross-site data. ### Prevent covert tracking -* [**User-Agent reduction and User-Agent Client Hints**](/docs/privacy-sandbox/user-agent/): +* [**User-Agent reduction and User-Agent Client Hints**](/docs/privacy-sandbox/user-agent/) (released): Limit passively shared browser data to reduce the volume of sensitive information which leads to fingerprinting. Client Hints allow developers to actively request only the information they need about the user's device or @@ -112,7 +114,7 @@ Several key proposals are listed below. ### Fight spam and fraud on the web -* [**Private State Tokens**](/docs/privacy-sandbox/trust-tokens): Allow +* [**Private State Tokens**](/docs/privacy-sandbox/trust-tokens) (released): Allow websites to convey a limited amount of information from one browsing context to another (for example, across sites) to help combat fraud, without passive tracking. @@ -144,17 +146,6 @@ You can then [run it with flags](https://www.chromium.org/developers/how-tos/run-chromium-with-flags) to allow access to APIs that are in the process of implementation. -{% Aside 'caution' %} -Chrome origin trials are designed to work for Chrome users. Don't rely on Chrome -origin trial tokens to allow trial features in other browsers, including Chromium, -and other Chromium-based browsers. - -For more detailed information, see -[Troubleshooting Chrome's origin trials](/blog/origin-trial-troubleshooting/#chrome). - -Chrome on iOS and iPadOS does not support Chrome origin trials. -{% endAside%} - ## When will the APIs be implemented? The [timeline](https://privacysandbox.com/open-web/#the-privacy-sandbox-timeline) @@ -177,14 +168,6 @@ may be made available for testing. within the more accessible `chrome://flags` interface. `chrome://flags#enable-experimental-web-platform-features` bundles together current experimental features. -- **For your users, in an origin trial** - Once an iteration of a new feature is code-complete and relatively stable, - an [origin trial](/docs/web-platform/origin-trials/) may be provided to allow - individual sites to turn on the feature for Chrome users on their site. If - an [origin trial](/docs/web-platform/origin-trials/) is available for an API you - want to test with your users, - [register for the origin trial](/origintrials/#/trials/active) and provide - a valid trial token with every page load. - **For users of early Chrome releases** When a feature is approved to ship in a given release, it will progress through each [Chrome release channel](/docs/web-platform/chrome-release-channels/), @@ -192,9 +175,9 @@ may be made available for testing. be turned on by default for all users of those channels. {% Aside 'caution' %} -Chrome offers users the ability to opt-out of Privacy Sandbox trials in +Chrome offers users the ability to opt-out of Privacy Sandbox APIs in browser settings. Users who opt-out will not have Privacy Sandbox features -turned on, even on pages which provide a valid origin trial token. +turned on. {% endAside%} ## Will `SameSite` become irrelevant after third-party cookies are deprecated? @@ -211,8 +194,8 @@ turned on, even on pages which provide a valid origin trial token. The exception is cookies that are modified by either the [CHIPS](/docs/privacy-sandbox/chips/) or -[First-Party Sets](/docs/privacy-sandbox/first-party-sets/) proposal. -These allow for a subset of cross-site use cases. As these proposals are +[First-Party Sets](/docs/privacy-sandbox/first-party-sets/). +These allow for a subset of cross-site use cases. As these features and APIs are under active discussion, the final formats and functionality may change. @@ -238,12 +221,12 @@ and the [Web Incubator Community Group](https://github.com/WICG). You can follow the monthly updates to the [Progress in the Privacy Sandbox](/tags/progress-in-the-privacy-sandbox/) series of articles which also includes an [RSS / Atom feed where you can subscribe](/feeds/progress-in-the-privacy-sandbox.xml) with your preferred reader. -The article series links to the matching monthly updates to the [Privacy Sandbox timeline](https://privacysandbox.com/timeline/) which shows the current status and schedule for proposals. +The article series links to the matching monthly updates to the [Privacy Sandbox timeline](https://privacysandbox.com/timeline/) which shows the current status and schedule for Privacy Sandbox APIs. -These high-level resources will provide signposts to changes across the project, but for individual proposals where you want to follow in detail you should: +These high-level resources will provide signposts to changes across the project, but for individual APIs where you want to follow in detail you should: - - Watch or Star proposal repos on GitHub to get notification of new issues and updates: the Privacy Sandbox [status page](/docs/privacy-sandbox/status/) provides a link to the repo for each proposal - - Join the associated [W3C group](https://www.w3.org/groups/) for regular meetings discussing the proposal detail + - Watch or Star API repos on GitHub to get notification of new issues and updates: the Privacy Sandbox [status page](/docs/privacy-sandbox/status/) provides a link to the repo for each API. + - Join the associated [W3C group](https://www.w3.org/groups/) for regular meetings discussing the API detail. - Star the associated entry on [Chrome Platform Status](https://chromestatus.com) for email updates on Chrome implementation changes. ### Get involved diff --git a/site/en/docs/privacy-sandbox/permissions-policy/index.md b/site/en/docs/privacy-sandbox/permissions-policy/index.md index 56dd381c5..cff87bba4 100644 --- a/site/en/docs/privacy-sandbox/permissions-policy/index.md +++ b/site/en/docs/privacy-sandbox/permissions-policy/index.md @@ -4,7 +4,7 @@ title: 'Controlling browser features with Permissions Policy' subhead: > Manage how your page and third-party iframes on your page have access to browser features. description: > - A proposal to manage how your page and embedded third-party iframes access to browser features. + Manage how your page and embedded third-party iframes access to browser features. date: 2022-04-20 authors: - kevinkiklee @@ -27,7 +27,7 @@ the developer can be certain that no third party will gain access to the user's geolocation. {% Aside %} -[Privacy Sandbox](https://web.dev/digging-into-the-privacy-sandbox/) is a series of proposals to satisfy third-party use cases without third-party cookies or other tracking mechanisms. +[Privacy Sandbox](https://web.dev/digging-into-the-privacy-sandbox/) is a series of proposals and APIs to satisfy third-party use cases without third-party cookies or other tracking mechanisms. Privacy Sandbox APIs, such as [User-Agent Client Hints](https://web.dev/user-agent-client-hints/) and the [Topics API](/docs/privacy-sandbox/topics/), are managed by Permissions Policy in the same way that features like `geolocation` and `camera` are managed. For a list of web platform APIs that rely on Permissions Policy, see the [feature list](https://github.com/w3c/webappsec-permissions-policy/blob/main/features.md). Note, this list may not be current. {% endAside %} diff --git a/site/en/docs/privacy-sandbox/private-aggregation-experiment/index.md b/site/en/docs/privacy-sandbox/private-aggregation-experiment/index.md index 3cfec5f23..993e27fed 100644 --- a/site/en/docs/privacy-sandbox/private-aggregation-experiment/index.md +++ b/site/en/docs/privacy-sandbox/private-aggregation-experiment/index.md @@ -2,10 +2,13 @@ layout: 'layouts/doc-post.njk' title: 'Private Aggregation API: experiment and participate' date: 2023-03-02 +updated: 2023-09-18 authors: - alexandrawhite --- +{% Partial 'privacy-sandbox/ot-end.njk' %} + Read the [Private Aggregation API overview](/docs/privacy-sandbox/private-aggregation/) and [Shared Storage overview](/docs/privacy-sandbox/shared-storage/). See the use cases and review @@ -16,9 +19,7 @@ for the Private Aggregation API. 1. Try the [demo](http://goo.gle/shared-storage-demo). The code is available on [GitHub](https://github.com/GoogleChromeLabs/shared-storage-demo). -2. Experiment with the API. The API is available in the [Privacy Sandbox unified origin trial](/docs/privacy-sandbox/unified-origin-trial/) on Chrome Canary, Dev, and Beta M107 or later. - * Learn how you can register for a [third-party origin trial](/docs/web-platform/third-party-origin-trials/). -3. Generate summary reports with the [Aggregation Service](/docs/privacy-sandbox/aggregation-service). +1. Generate summary reports with the [Aggregation Service](/docs/privacy-sandbox/aggregation-service). * Set up [local testing](https://github.com/privacysandbox/aggregation-service/blob/main/README.md). The Aggregation Service for the Private Aggregation API is not yet diff --git a/site/en/docs/privacy-sandbox/private-aggregation-fundamentals/index.md b/site/en/docs/privacy-sandbox/private-aggregation-fundamentals/index.md index 3fe4fb674..f1b18f592 100644 --- a/site/en/docs/privacy-sandbox/private-aggregation-fundamentals/index.md +++ b/site/en/docs/privacy-sandbox/private-aggregation-fundamentals/index.md @@ -6,6 +6,7 @@ subhead: > description: > Key concepts of the Private Aggregation API date: 2022-10-11 +updated: 2023-09-18 authors: - kevinkiklee --- @@ -155,7 +156,7 @@ Each call to the Private Aggregation API is called a _contribution_. To protect When you sum all aggregatable values across all aggregation keys, the sum must be less than the contribution budget. The budget is scoped per-worklet [origin](https://web.dev/same-site-same-origin/#origin), per-day, and is separate for Protected Audience API and Shared Storage worklets. A rolling window of approximately the last 24 hours is used for the day. If a new aggregatable report would cause the budget to be exceeded, the report is not created. -The _contribution budget_ is represented by the parameter `L<sub>1</sub>`, and for the current Privacy Sandbox Origin Trial, the contribution budget has been set to 2<sup>16</sup> = 65,536. The value of the contribution budget is arbitrary where noise is scaled to it, and you can use this budget to maximize signal-to-noise ratio on the summary values (discussed more below in the [Noise and scaling](#noise-and-scaling) section below). +The _contribution budget_ is represented by the parameter `L<sub>1</sub>`, and for now complete Privacy Sandbox Origin Trial, the contribution budget was set to 2<sup>16</sup> = 65,536. The value of the contribution budget is arbitrary where noise is scaled to it, and you can use this budget to maximize signal-to-noise ratio on the summary values (discussed more below in the [Noise and scaling](#noise-and-scaling) section below). To learn more about contribution budgets, see the [explainer](https://github.com/patcg-individual-drafts/private-aggregation-api#contribution-bounding-and-budgeting). Also, refer to [Contribution Budget](/docs/privacy-sandbox/attribution-reporting/contribution-budget/) for more guidance. @@ -247,8 +248,8 @@ See the [Contribution section of the Attribution Reporting strategy guide](https ## Engage and share feedback -The Private Aggregation API proposal is under active discussion and subject to change in the future. If you try this API and have feedback, we'd love to hear it. +The Private Aggregation API is under active discussion and subject to change in the future. If you try this API and have feedback, we'd love to hear it. -* **GitHub**: Read the [proposal](https://github.com/patcg-individual-drafts/private-aggregation-api), [raise questions and participate in discussion](https://github.com/patcg-individual-drafts/private-aggregation-api/issues). +* **GitHub**: Read the [explainer](https://github.com/patcg-individual-drafts/private-aggregation-api), [raise questions and participate in discussion](https://github.com/patcg-individual-drafts/private-aggregation-api/issues). * **Developer support**: Ask questions and join discussions on the [Privacy Sandbox Developer Support repo](https://github.com/GoogleChromeLabs/privacy-sandbox-dev-support). * Join the [Shared Storage API group](https://groups.google.com/a/chromium.org/g/shared-storage-api-announcements) and the [Protected Audience API group](https://groups.google.com/a/chromium.org/g/fledge-api-announce/) for the latest announcements related to Private Aggregation. diff --git a/site/en/docs/privacy-sandbox/private-aggregation/index.md b/site/en/docs/privacy-sandbox/private-aggregation/index.md index 998e970da..ec3fe706c 100644 --- a/site/en/docs/privacy-sandbox/private-aggregation/index.md +++ b/site/en/docs/privacy-sandbox/private-aggregation/index.md @@ -8,13 +8,15 @@ description: > Generate aggregate data reports using data from Protected Audience and cross-site data from Shared Storage. date: 2022-10-11 -updated: 2023-06-29 +updated: 2023-09-18 authors: - kevinkiklee --- +{% Partial 'privacy-sandbox/ot-end.njk' %} + To provide critical features that the web relies on, the Private Aggregation -API has been proposed for aggregating and reporting on cross-site data in a +API has been built for aggregating and reporting on cross-site data in a privacy-preserving manner. ## Implementation status @@ -56,9 +58,7 @@ Attribution Reporting associates data gathered from an impression event and a co ## Test this API -The API is available in the [Privacy Sandbox unified origin trial](/docs/privacy-sandbox/unified-origin-trial/) on Chrome Canary and Dev M107 or later. Learn how you can register for a [third-party origin trial](/docs/web-platform/third-party-origin-trials/). - -The Private Aggregation API can also be locally tested by enabling +The Private Aggregation API can be tested locally by enabling the Privacy Sandbox Ads APIs experiment flag at `chrome://flags/#privacy-sandbox-ads-apis`. @@ -231,8 +231,8 @@ To learn more, see the [report verification explainer](https://github.com/patcg- ## Engage and share feedback -The Private Aggregation API proposal is under active discussion and subject to change in the future. If you try this API and have feedback, we'd love to hear it. +The Private Aggregation API is under active discussion and subject to change in the future. If you try this API and have feedback, we'd love to hear it. -* **GitHub**: Read the [proposal](https://github.com/patcg-individual-drafts/private-aggregation-api), [raise questions and participate in discussion](https://github.com/patcg-individual-drafts/private-aggregation-api/issues). +* **GitHub**: Read the [explainer](https://github.com/patcg-individual-drafts/private-aggregation-api), [raise questions and participate in discussion](https://github.com/patcg-individual-drafts/private-aggregation-api/issues). * **Developer support**: Ask questions and join discussions on the [Privacy Sandbox Developer Support repo](https://github.com/GoogleChromeLabs/privacy-sandbox-dev-support). * Join the [Shared Storage API group](https://groups.google.com/a/chromium.org/g/shared-storage-api-announcements) and the [Protected Audience API group](https://groups.google.com/a/chromium.org/g/fledge-api-announce/) for the latest announcements related to Private Aggregation. diff --git a/site/en/docs/privacy-sandbox/proposal-lifecycle/index.md b/site/en/docs/privacy-sandbox/proposal-lifecycle/index.md index 5bacc15bf..e76da4d30 100644 --- a/site/en/docs/privacy-sandbox/proposal-lifecycle/index.md +++ b/site/en/docs/privacy-sandbox/proposal-lifecycle/index.md @@ -8,7 +8,7 @@ description: > How we collaborate with stakeholders to discuss, test, and adopt privacy-preserving technologies. date: 2022-03-30 -updated: 2023-05-18 +updated: 2023-09-18 authors: - alexandrawhite --- @@ -130,11 +130,8 @@ developers can register to opt in your site or service. This provides you an opportunity to try the feature on production traffic and provide feedback on real-world experience. -The Privacy Sandbox has been running a -[unified origin trial](/docs/privacy-sandbox/unified-origin-trial/) for the -relevance and measurement APIs, which is still open for sign ups. We anticipate -this origin trial will close when these -[APIs enter general availability](/blog/shipping-privacy-sandbox/). +The Privacy Sandbox ran a unified origin trial for the +relevance and measurement APIs, which is now complete. When a feature is initially made available for testing, the focus is generally on **functional or technical testing**. With new code, there is an expectation @@ -221,12 +218,12 @@ come. The following technologies are now available: identifying information with a third-party service or website, unless the user explicitly agrees to do so. FedCM shipped in November 2022. -In July 2023, the relevance and measurement APIs will be +In July 2023, the relevance and measurement APIs became [available for scaled adoption](/blog/shipping-privacy-sandbox/). This means -these APIs will be available by default in Chrome. Developers will be able to +these APIs became available by default in Chrome. Developers can now use these technologies without browser flags or participation in origin trials. -In short, these APIs will be ready for use, at-scale, in a production +In short, these APIs are ready for 99 percent of users, at-scale, in a production environment. #### Phased launches diff --git a/site/en/docs/privacy-sandbox/protected-audience-api/ad-auction/index.md b/site/en/docs/privacy-sandbox/protected-audience-api/ad-auction/index.md index 6ff3a014c..e81bef476 100644 --- a/site/en/docs/privacy-sandbox/protected-audience-api/ad-auction/index.md +++ b/site/en/docs/privacy-sandbox/protected-audience-api/ad-auction/index.md @@ -6,6 +6,7 @@ subhead: > description: > Seller API guide and references for the Protected Audience API ad auction. date: 2022-11-01 +updated: 2023-09-18 authors: - samdutton - alexandrawhite @@ -16,7 +17,7 @@ authors: In this article, you'll find a technical reference for the ad auction, as used in the current iteration of the experimental Protected Audience API. Read the [developer guide](/docs/privacy-sandbox/protected-audience-api) for the full life -cycle of Protected Audience API, and refer to the Protected Audience API explainer for an in-depth proposal of +cycle of Protected Audience API, and refer to the Protected Audience API explainer for an in-depth discussion of how [sellers run on-device auctions](https://github.com/WICG/turtledove/blob/main/FLEDGE.md#2-sellers-run-on-device-auctions). Not a developer? Refer to the [Protected Audience API overview](/docs/privacy-sandbox/protected-audience). @@ -41,9 +42,7 @@ outside world. title="View a larger version of image." target="_blank">view a larger version</a>.</figcaption> </figure> -1. A user visits a site which displays ads. While the Protected Audience API is in an origin trial, - the site must have an available and valid origin trial token. The user must - be in an experimental group (such as Finch). +1. A user visits a site which displays ads. 2. The seller's code executes `navigator.runAdAuction()`. This specifies which ad space is for sale and who can bid. Sellers must also include a script that scores each bid, `scoreAd()`. diff --git a/site/en/docs/privacy-sandbox/protected-audience-api/index.md b/site/en/docs/privacy-sandbox/protected-audience-api/index.md index 2aad7d18b..27377c8e6 100644 --- a/site/en/docs/privacy-sandbox/protected-audience-api/index.md +++ b/site/en/docs/privacy-sandbox/protected-audience-api/index.md @@ -9,7 +9,7 @@ description: > previously visited websites, designed so it cannot be used by third parties to track user browsing behavior across sites. date: 2022-01-27 -updated: 2023-03-14 +updated: 2023-09-18 authors: - samdutton - kevinkiklee @@ -17,8 +17,10 @@ authors: {% Partial 'privacy-sandbox/protected-audience-rename-banner.njk' %} +{% Partial 'privacy-sandbox/ot-end.njk' %} + For those new to the Protected Audience API, read the [Protected Audience API overview](/docs/privacy-sandbox/protected-audience) -for a high-level explanation of the proposal. +for a high-level explanation of the API. This post is written for developers as a technical reference for the most recent iteration of the experimental Protected Audience API. A [demo](#demo) of a basic @@ -31,7 +33,7 @@ Protected Audience API deployment is available, as are ## What is the Protected Audience API? {: #what} -The Protected Audience API is a [Privacy Sandbox](/docs/privacy-sandbox/overview) proposal to serve +The Protected Audience API is a [Privacy Sandbox](/docs/privacy-sandbox/overview) API designed to serve [remarketing](/docs/privacy-sandbox/protected-audience#remarketing) and custom audience use cases, designed so that it cannot be used by third parties to track user browsing behavior across sites. The API enables on-device auctions by @@ -69,59 +71,6 @@ sites is available at [protected-audience-demo.web.app/](https://protected-audie </figcaption> </figure> -### Take part in the origin trial {: #origin-trial} - -The [Privacy Sandbox Relevance and Measurement origin trial](/docs/privacy-sandbox/unified-origin-trial) -has been made available in Chrome Beta 101.0.4951.26 and above on desktop for -the Protected Audience API, [Topics](/docs/privacy-sandbox/topics/), and -[Attribution Reporting](/docs/privacy-sandbox/attribution-reporting/) APIs. - -To take part, [register for an origin trial token](/origintrials/#/view_trial/771241436187197441). - -Once you have successfully enrolled in the trial, you can try out the Protected Audience API -API on pages that provide a valid trial token. For example, to ask -the browser to [join one or more interest groups](#joinadinterestgroup), -and then to run an ad auction to select and display an ad. - -Provide a trial token for every page on which you would like to run Protected Audience API code: - -* As a meta tag in the `<head>`: - ```html - <meta http-equiv="origin-trial" content="TOKEN_GOES_HERE"> - ``` - -* As an HTTP header: - ```text - Origin-Trial: TOKEN_GOES_HERE - ``` - -* By providing a token programmatically: - - ```javascript - const otMeta = document.createElement('meta'); - otMeta.httpEquiv = 'origin-trial'; - otMeta.content = 'TOKEN_GOES_HERE'; - document.head.append(otMeta); - ``` - -An iframe running Protected Audience API code—such as a -[`navigator.joinAdInterestGroup()`](#joinadinterestgroup) -call by an interest group owner—will need to provide a token that matches its origin. - -[Proposed First Protected Audience API Origin Trial Details](https://github.com/WICG/turtledove/blob/main/Proposed_First_FLEDGE_OT_Details.md) -provides more details about the goals of the first trial and explains what -features are supported. - -{% Aside 'caution' %} - -Not all users are eligible for the Privacy Sandbox Relevance and Measurement -origin trial, even on pages that provide a valid trial token. - -The [Relevance and measurement unified origin trial overview](/docs/privacy-sandbox/unified-origin-trial#eligible-users) -explains why this is so, and shows how you can (and should) detect if an origin -trial feature is available before attempting to use it. - -{% endAside %} ### Test with `chrome://flags` or feature flags {: #flags} @@ -160,14 +109,14 @@ This is an in-progress version of the Protected Audience API for early testing. considered complete or indicative of the final implementation. Protected Audience API progress and status are discussed in the regular WICG meetings. -The [Privacy Sandbox timeline](https://privacysandbox.com/timeline) provides implementation timing for Protected Audience API and other Privacy Sandbox proposals. +The [Privacy Sandbox timeline](https://privacysandbox.com/timeline) provides implementation timelines for Protected Audience API and other Privacy Sandbox APIs. {% endAside %} ## Supported features Protected Audience API behind feature flags in Chromium is a first experiment to test the -following features of the Protected Audience API proposal: +following features of the Protected Audience API: - **Interest groups**: stored by the browser, with associated metadata to configure ad bidding and rendering. @@ -528,8 +477,7 @@ manage the list of interest groups that they have been added to across the web sites they have visited. As with the Privacy Sandbox technologies themselves, user settings may evolve with feedback from users, regulators and others. -We'll continue to update the available settings in Chrome as the Protected Audience API -proposal progresses, [based on tests and feedback](/docs/privacy-sandbox/proposal-lifecycle/#collaborate). +We'll continue to update the available settings in Chrome [based on tests and feedback](/docs/privacy-sandbox/proposal-lifecycle/#collaborate). In the future, we plan to offer more granular settings to manage the Protected Audience API and associated data. @@ -548,7 +496,7 @@ To ask a questions and get support with your implementation, the demo, or the documentation: * **GitHub**: Read the - [proposal](https://github.com/WICG/turtledove/blob/main/FLEDGE.md), + [explainer](https://github.com/WICG/turtledove/blob/main/FLEDGE.md), [raise questions, and follow discussion](https://github.com/WICG/turtledove/issues). * **Demo**: Raise an issue on the [demo code repository](https://github.com/GoogleChromeLabs/protected-audience-demo). * **Developer support**: Ask questions and join discussions on the @@ -560,7 +508,7 @@ documentation: or [raise a new issue](https://crbug.com/new). For more general questions about meeting your needs with the Protected Audience API, -[file an issue on the proposal repository](https://github.com/WICG/turtledove/issues/new). +[file an issue on the API repository](https://github.com/WICG/turtledove/issues/new). You can also discuss industry use cases in the W3C's [Improving Web Advertising Business Group](https://www.w3.org/community/web-adv/participants). @@ -577,12 +525,12 @@ as a site owner or an individual user. - For notifications of API status changes, join the [mailing list for developers](https://groups.google.com/u/3/a/chromium.org/g/fledge-api-announce). -- To closely follow all ongoing discussions on the API, click the **Watch** button on the [proposal page on +- To closely follow all ongoing discussions on the API, click the **Watch** button on the [API page on GitHub](https://github.com/WICG/turtledove/blob/main/FLEDGE.md). This requires you have or [create a GitHub account](https://docs.github.com/get-started/signing-up-for-github/signing-up-for-a-new-github-account). - To get overall updates on the Privacy Sandbox, subscribe to the RSS feed [Progress in the Privacy Sandbox](/tags/progress-in-the-privacy-sandbox/). - [Join the scheduled calls for the Protected Audience API](https://github.com/WICG/turtledove/issues/88) - (every second week). Everyone is welcome to join—to participate, + (every second week). Everyone is welcome to join—to participate, first make sure to [join the WICG](https://www.w3.org/community/wicg/). You can actively participate or just listen in! diff --git a/site/en/docs/privacy-sandbox/protected-audience-api/opt-out/index.md b/site/en/docs/privacy-sandbox/protected-audience-api/opt-out/index.md index 62c5287e4..d2c48a5c3 100644 --- a/site/en/docs/privacy-sandbox/protected-audience-api/opt-out/index.md +++ b/site/en/docs/privacy-sandbox/protected-audience-api/opt-out/index.md @@ -6,6 +6,7 @@ subhead: > description: > For developers and users who want to opt-out of the Protected Audience API. date: 2022-10-29 +updated: 2023-09-18 authors: - samdutton - alexandrawhite @@ -20,8 +21,8 @@ You can block access to the Protected Audience API, as a [site owner](#opt-out-s The Protected Audience API will eventually require sites to set a [Permissions Policy](/docs/privacy-sandbox/permissions-policy/) to allow the Protected Audience API functionality to be available. This will help ensure that arbitrary third parties can't use the API without a site's knowledge. However, -to facilitate testing during [the first origin trial](/blog/privacy-sandbox-unified-origin-trial), -this requirement is [waived by default](https://github.com/WICG/turtledove/blob/main/Proposed_First_FLEDGE_OT_Details.md#permissions-policy). +to facilitate testing during the first origin trial, +this requirement was [waived by default](https://github.com/WICG/turtledove/blob/main/Proposed_First_FLEDGE_OT_Details.md#permissions-policy). Sites that would like to explicitly disable Protected Audience API functionality during the testing period can use the relevant Permissions Policy to block access. There diff --git a/site/en/docs/privacy-sandbox/protected-audience-api/reports/index.md b/site/en/docs/privacy-sandbox/protected-audience-api/reports/index.md index 088f13863..74e6f32e6 100644 --- a/site/en/docs/privacy-sandbox/protected-audience-api/reports/index.md +++ b/site/en/docs/privacy-sandbox/protected-audience-api/reports/index.md @@ -18,7 +18,7 @@ Protected Audience API auction wins, as used in the current iteration of the exp Protected Audience API. Read the [developer guide](/docs/privacy-sandbox/protected-audience-api) for the full life -cycle of the Protected Audience API, and refer to the Protected Audience API explainer for an in-depth proposal of +cycle of the Protected Audience API, and refer to the Protected Audience API explainer for an in-depth discussion of [event-level reporting (temporary)](https://github.com/WICG/turtledove/blob/main/FLEDGE.md#5-event-level-reporting-for-now). Not a developer? Refer to the [Protected Audience API API overview](/docs/privacy-sandbox/protected-audience). diff --git a/site/en/docs/privacy-sandbox/protected-audience-experiment/index.md b/site/en/docs/privacy-sandbox/protected-audience-experiment/index.md index 16f41b8cb..11b49088f 100644 --- a/site/en/docs/privacy-sandbox/protected-audience-experiment/index.md +++ b/site/en/docs/privacy-sandbox/protected-audience-experiment/index.md @@ -4,20 +4,22 @@ title: 'The Protected Audience API: experiment and participate' subhead: > Quick guide to implement and test the API. Set up privacy-preserving ad auctions to serve remarketing and custom audience use cases. description: > - The Protected Audience API is a Privacy Sandbox proposal to serve remarketing and custom audience use cases, designed so it cannot be used by third parties to track user browsing behavior across sites. The API enables on-device auctions by the browser, to choose relevant ads from websites the user has previously visited. + The Protected Audience API is a Privacy Sandbox API to serve remarketing and custom audience use cases, designed so it cannot be used by third parties to track user browsing behavior across sites. The API enables on-device auctions by the browser, to choose relevant ads from websites the user has previously visited. date: 2022-03-31 -updated: 2022-08-12 +updated: 2022-09-18 authors: - samdutton --- +{% Partial 'privacy-sandbox/ot-end.njk' %} + {% Partial 'privacy-sandbox/protected-audience-rename-banner.njk' %} ## Learn the essentials * If you're a developer or software engineer, the [Protected Audience API Developer Guide](/docs/privacy-sandbox/protected-audience-api/) provides an - in-depth technical reference for the proposal. + in-depth technical reference. * The [Protected Audience API overview](/docs/privacy-sandbox/protected-audience) offers a higher level explanation for those who work in advertiser and ad tech, who are new to the Privacy Sandbox. @@ -26,10 +28,6 @@ authors: {% Aside 'caution' %} -Not all users may be eligible to experience features from the Privacy Sandbox -Relevance and Measurement origin trial, even on pages that provide a valid -trial token. - Read about [feature detection](/docs/privacy-sandbox/unified-origin-trial/#feature-detection) to learn how to determine if a feature is available before attempting to use it. @@ -45,13 +43,12 @@ to learn how to determine if a feature is available before attempting to use it. * Review the [source code](https://github.com/GoogleChromeLabs/protected-audience-demo). * Watch the [Protected Audience demo video](https://www.youtube.com/watch?v=znDD0gkdJyM&list=PLNYkxOF6rcICntazGfSVKSj5EwuR9w5Nv) to learn how the demo code works and how to use Chrome DevTools for FLEDGE debugging. 3. Experiment with the API. - * Sign up for the [origin trial](/docs/privacy-sandbox/protected-audience-api/#origin-trial) - * Try out FLEDGE for a single user by enabling + * Try out the Protected Audience API for a single user by enabling `chrome://flags/#privacy-sandbox-ads-apis` or by running Chrome from the command line with [Protected Audience feature flags](/docs/privacy-sandbox/protected-audience-api/#flags). - * [Troubleshoot Protected Audience worklets](/docs/privacy-sandbox/protected-audience-api/troubleshoot/) with Chrome DevTools. Learn how to debug FLEDGE bidding and auction code. + * [Troubleshoot Protected Audience worklets](/docs/privacy-sandbox/protected-audience-api/troubleshoot/) with Chrome DevTools. Learn how to debug Protected Audience bidding and auction code. 4. Review the [Protected Audience status](/docs/privacy-sandbox/status/#fledge) for updates - on the implementation of the FLEDGE API. Review the + on the implementation of the Protected Audience API. Review the [pending Protected Audience capabilities](/docs/privacy-sandbox/protected-audience-api/feature-status/) for more details. @@ -69,7 +66,7 @@ about **your implementation**, the **demo**, or the **documentation**: * Raise an issue on the [demo code repo on GitHub](https://github.com/GoogleChromeLabs/protected-audience-demo). * For more general questions about how to meet your **use cases** with the - API, [file an issue on the proposal repository](https://github.com/WICG/turtledove/issues/new). + API, [file an issue on the API repository](https://github.com/WICG/turtledove/issues/new). For bugs and issues with the implementation of the Protected Audience API in Chrome: @@ -79,12 +76,12 @@ For bugs and issues with the implementation of the Protected Audience API in Chr ## Join the discussion -Everyone is welcome to join in discussion of the Protected Audience API proposal. In +Everyone is welcome to join in discussion of the Protected Audience API. In particular, if you're experimenting with the API, your feedback is essential. ### Discuss the API -Like other Privacy Sandbox proposals, this API is documented and discussed publicly. +Like other Privacy Sandbox APIs, this API is documented and discussed publicly. * Read the [FLEDGE explainer on GitHub](https://github.com/WICG/turtledove/blob/main/FLEDGE.md). * Join the conversation about [existing issues](https://github.com/WICG/turtledove/issues). @@ -104,14 +101,14 @@ Discuss industry use cases in the [Privacy Sandbox feedback](/docs/privacy-sandbox/feedback/#fledge-api) explains how to provide other types of feedback, and how to engage in -discussion of Privacy Sandbox proposals. +discussion of Privacy Sandbox APIs. ## Get updates * To be notified of status changes in the API, join the [mailing list for developers](https://groups.google.com/u/3/a/chromium.org/g/fledge-api-announce). * To closely follow all ongoing discussions on the API, click the **Watch** - button on the [proposal page on GitHub](https://github.com/WICG/turtledove/blob/main/FLEDGE.md). + button on the [API page on GitHub](https://github.com/WICG/turtledove/blob/main/FLEDGE.md). This requires you have or [create a GitHub account](https://docs.github.com/get-started/signing-up-for-github/signing-up-for-a-new-github-account). * To get overall updates on the Privacy Sandbox, subscribe to the RSS feed diff --git a/site/en/docs/privacy-sandbox/protected-audience/index.md b/site/en/docs/privacy-sandbox/protected-audience/index.md index 1959bad2d..9c4fcc3f6 100644 --- a/site/en/docs/privacy-sandbox/protected-audience/index.md +++ b/site/en/docs/privacy-sandbox/protected-audience/index.md @@ -5,11 +5,11 @@ subhead: > On-device ad auctions to serve remarketing and custom audiences, without cross-site third-party tracking. description: > - A proposal for on-device ad auctions to choose relevant ads from + An API for on-device ad auctions to choose relevant ads from websites a user has previously visited, designed so it cannot be used by third parties to track user browsing behavior across sites. date: 2022-01-27 -updated: 2022-08-23 +updated: 2022-09-18 authors: - samdutton - kevinkiklee @@ -30,7 +30,7 @@ concepts, but doesn't go into much technical detail. [how Protected Audience works](#overview). * If you're a **developer or software engineer**, the [Protected Audience API Developer Guide](/docs/privacy-sandbox/protected-audience-api) provides more - in-depth technical detail about the proposal. Read the + in-depth technical detail about the API. Read the [latest status of pending Protected Audience capabilities](/docs/privacy-sandbox/protected-audience-api/feature-status/). Refer to the [glossary](/docs/privacy-sandbox/glossary/) for terms used across @@ -50,7 +50,7 @@ The Protected Audience API is the first experiment to be implemented in Chromium [TURTLEDOVE](https://github.com/WICG/turtledove) family of proposals. The difference between Protected Audience and TURTLEDOVE primarily pertain to separation of the on-device role of the ad buyer and seller. The sections below explain how -FLEDGE works. +the Protected Audience API works. ### Protected Audience API in one minute {: #overview} @@ -137,16 +137,14 @@ Read the [developer guide](/docs/privacy-sandbox/protected-audience-api/) and to understand what features are currently available for testing in Chrome. Protected Audience features will be added over time, and we'll regularly update a list of -which features are already implemented and what's still in progress. The Protected Audience API is -currently in an [origin trial](/docs/privacy-sandbox/unified-origin-trial/). +which features are already implemented and what's still in progress. {% endAside %} ## How can I try the Protected Audience API? {: #try-fledge} * The [Protected Audience API developer guide](/docs/privacy-sandbox/protected-audience-api) describes - how to use the API, how to test locally and how to participate in the - [relevence and measurement origin trial](/docs/privacy-sandbox/unified-origin-trial/). + how to use the API and how to test locally. * [protected-audience-demo.web.app](https://protected-audience-demo.web.app/) provides a walkthrough of a basic Protected Audience deployment across advertiser and publisher @@ -527,7 +525,7 @@ We've written an [API developer guide](/docs/privacy-sandbox/protected-audience ## Engage and share feedback -- **GitHub**: Read the [proposal](https://github.com/WICG/turtledove/blob/master/FLEDGE.md), +- **GitHub**: Read the [explainer](https://github.com/WICG/turtledove/blob/master/FLEDGE.md), [raise questions and follow discussion](https://github.com/WICG/turtledove/issues). - **Announcements**: Join or view past announcements on the [Protected Audience API mailing list](https://groups.google.com/u/0/a/chromium.org/g/fledge-api-announce). - **W3C**: Discuss industry use cases in the [Improving Web Advertising Business diff --git a/site/en/docs/privacy-sandbox/summary-reports/design-decisions/index.md b/site/en/docs/privacy-sandbox/summary-reports/design-decisions/index.md index 2392462b6..8806a16eb 100644 --- a/site/en/docs/privacy-sandbox/summary-reports/design-decisions/index.md +++ b/site/en/docs/privacy-sandbox/summary-reports/design-decisions/index.md @@ -17,11 +17,13 @@ tags: - privacy --- +{% Partial 'privacy-sandbox/ot-end.njk' %} + ## About this document When you read this article, you will: -- Understand what strategies to create before generating summary reports in the origin trial. +- Understand what strategies to create before generating summary reports. - Be introduced to [Noise Lab](https://goo.gle/noise-lab), a tool that helps grasp the effects of various noise parameters, and that enables quick exploration and assessment of various noise management strategies. <figure> diff --git a/site/en/docs/privacy-sandbox/summary-reports/index.md b/site/en/docs/privacy-sandbox/summary-reports/index.md index ee208dabd..2c9cbdef0 100644 --- a/site/en/docs/privacy-sandbox/summary-reports/index.md +++ b/site/en/docs/privacy-sandbox/summary-reports/index.md @@ -12,10 +12,11 @@ authors: - alexandrawhite --- +{% Partial 'privacy-sandbox/ot-end.njk' %} + ## Implementation status * Participate and experiment with [Attribution Reporting summary reports](/docs/privacy-sandbox/attribution-reporting-experiment/). - * This API is available in the [ads relevance and measurement origin trial](/blog/privacy-sandbox-unified-origin-trial/). ## What is a summary report? diff --git a/site/en/docs/privacy-sandbox/topics-experiment/index.md b/site/en/docs/privacy-sandbox/topics-experiment/index.md index a01cee981..4bfeef718 100644 --- a/site/en/docs/privacy-sandbox/topics-experiment/index.md +++ b/site/en/docs/privacy-sandbox/topics-experiment/index.md @@ -6,11 +6,13 @@ subhead: > description: > Quick guide to implement and test the API. Access topics with JavaScript and share your feedback. date: 2022-03-31 -updated: 2022-04-19 +updated: 2023-09-18 authors: - samdutton --- +{% Partial 'privacy-sandbox/ot-end.njk' %} + ## Learn the essentials * [Topics API overview](/docs/privacy-sandbox/topics/overview) introduces the API and explains the issues it addresses. @@ -19,28 +21,14 @@ authors: ## Try the API -{% Aside 'caution' %} - -Not all users may be eligible for the Privacy Sandbox Relevance and Measurement origin trial, even -on pages that provide a valid trial token. - -[Testing the Privacy Sandbox ads relevance and measurement APIs](/blog/privacy-sandbox-unified-origin-trial#eligible-users) -explains why this is so, and shows how you can (and should) detect if an origin trial feature is -available before attempting to use it. - -{% endAside %} - 1. Check the Privacy Sandbox [status page](/docs/privacy-sandbox/status/#topics) for updates on the implementation status of the Topics API. 2. Experiment with the API: - * Learn how to take part in the [Privacy Sandbox Relevance and Measurement origin trial](/docs/privacy-sandbox/unified-origin-trial/). * Try out Topics for a single user in Chrome 101 or above by enabling `chrome://flags/#privacy-sandbox-ads-apis` or by running Chrome from the command line with the `--enable-features=PrivacySandboxAdsAPIsOverride` [feature flag](https://www.chromium.org/developers/how-tos/run-chromium-with-flags). Refer to [Topics API demos](/docs/privacy-sandbox/topics/demo/). - * [Use the Topics JavaScript API to access topics](/docs/privacy-sandbox/topics/#access-topics-with-the-javascript-api) - provides a short code example to demonstrate how the API might be used to access topics observed - for the current user. - + * The [Topics API developer guide](/docs/privacy-sandbox/topics/#access-topics-with-the-javascript-api) explains how to use the Topics JavaScript API or the header approach (fetch or iframe) [to access topics](/docs/privacy-sandbox/topics/#access-topics-with-the-javascript-api) observed for the current user. + ## Get support @@ -50,7 +38,7 @@ about **your implementation** or about the **documentation**: * [Open a new issue](https://github.com/GoogleChromeLabs/privacy-sandbox-dev-support/issues/new/choose) on the Privacy Sandbox Dev Support repository. Make sure to select the issue template for Topics. * For more general questions about how to meet your **use cases** with the - API, [file an issue on the proposal repository](https://github.com/jkarlin/topics/issues/new). + API, [file an issue on the API repository](https://github.com/jkarlin/topics/issues/new). For bugs and issues with the implementation of the Topics API in Chrome: @@ -61,14 +49,14 @@ For bugs and issues with the implementation of the Topics API in Chrome: ## Join the discussion -Everyone is welcome to join in discussion of the Topics proposal. In particular, if you're +Everyone is welcome to join in discussion of the Topics API. In particular, if you're experimenting with the API, your feedback is essential. ### Discuss the API -Like other Privacy Sandbox proposals, this API is documented and discussed publicly. +Like other Privacy Sandbox APIs, this API is documented and discussed publicly. -* [Read the proposal explainer on GitHub](https://github.com/jkarlin/topics). +* [Read the explainer on GitHub](https://github.com/jkarlin/topics). * Join the conversation about [existing issues](hhttps://github.com/jkarlin/topics/issues). * [Open a new issue](https://github.com/jkarlin/topics/issues/new) to ask a question, propose a feature, or discuss a use case. @@ -82,14 +70,14 @@ feature, or discuss a use case. * Use the Privacy Sandbox [feedback form](/docs/privacy-sandbox/feedback/#feedback-form) to share feedback privately with the Chrome team outside of public forums. * [Privacy Sandbox Feedback](/docs/privacy-sandbox/feedback/#topics-api) explains how to provide -other types of feedback, and how to engage in discussion of Privacy Sandbox proposals. +other types of feedback, and how to engage in discussion of Privacy Sandbox APIs. ## Get updates * To be notified of status changes in the API, join the [mailing list for developers](https://groups.google.com/u/3/a/chromium.org/g/topics-api-announce). -* To closely follow all ongoing discussions on the API, click the **Watch** button on the [proposal page on +* To closely follow all ongoing discussions on the API, click the **Watch** button on the [GitHub page on GitHub](https://github.com/jkarlin/topics). This requires you have or [create a GitHub account](https://docs.github.com/en/get-started/signing-up-for-github/signing-up-for-a-new-github-account). * To get overall updates on the Privacy Sandbox, subscribe to the RSS feed [Progress in the Privacy diff --git a/site/en/docs/privacy-sandbox/topics/demo/index.md b/site/en/docs/privacy-sandbox/topics/demo/index.md index b02bd17c1..b1ef63460 100644 --- a/site/en/docs/privacy-sandbox/topics/demo/index.md +++ b/site/en/docs/privacy-sandbox/topics/demo/index.md @@ -6,17 +6,17 @@ subhead: > description: > Experiment and learn how topics are inferred from hostnames with minimal setup. date: 2023-03-08 +updated: 2023-09-18 authors: - samdutton --- ## Implementation status {% Partial 'privacy-sandbox/ps-implementation-status.njk' %} +{% Partial 'privacy-sandbox/ot-end.njk' %} The Topics API demo provides a look at how topics are inferred from hostnames. You can preview what topics are observed when you visit a demo site, which requires very little setup. -If you want to test the API with your users, sign up for the [Relevance and Measurement origin trial](/docs/privacy-sandbox/unified-origin-trial/). - Our demo is a preview that demonstrates most features of the Topics API, for you to gain familiarity with how the API is implemented. You can also run the Topics [colab](/docs/privacy-sandbox/topics/colab) to try out the Topics [classifier model](/docs/privacy-sandbox/topics/topic-classification/#classifier-model). diff --git a/site/en/docs/privacy-sandbox/topics/index.md b/site/en/docs/privacy-sandbox/topics/index.md index 655a40d3c..cd5fa1a79 100644 --- a/site/en/docs/privacy-sandbox/topics/index.md +++ b/site/en/docs/privacy-sandbox/topics/index.md @@ -11,68 +11,20 @@ authors: - samdutton --- +{% Partial 'privacy-sandbox/ot-end.njk' %} + ## Implementation status {% Partial 'privacy-sandbox/ps-implementation-status.njk' %} -## Try the Topics API - -Topics is not currently available by default in any version of Chrome, but you can activate the API in two ways, as a single user or at scale: - -- The Topics API demo allows you to try it out as a single user. -- The Topics origin trial allows you to try the API at scale with your website users. +## Try the demo {: #demo} -### Try the demo {: #demo} +The Topics API demo allows you to try it out as a single user. The demo of the Topics API is at [topics-demo.glitch.me](https://topics-demo.glitch.me/). It explains how to try out and debug the API for a single user. You can also run the Topics [colab](/docs/privacy-sandbox/topics/colab/) to try out the Topics [classifier model](/docs/privacy-sandbox/topics/topic-classification/#classifier-model). -### Test Topics in an origin trial {: #origin-trial} - -A Privacy Sandbox Relevance and Measurement [origin trial](/docs/privacy-sandbox/unified-origin-trial/) has been made available in Chrome Beta 101.0.4951.26 and above on desktop for the Topics, [Protected Audience](/docs/privacy-sandbox/protected-audience/), and [Attribution Reporting](/docs/privacy-sandbox/attribution-reporting/) APIs. - -#### Provide an origin trial token - -To take part in the origin trial, you can provide a valid trial token -[programmatically, in a header, or in a meta tag](/docs/web-platform/origin-trials/#take-part-in-an-origin-trial). -Whichever method you choose to provide a trial token, and [whichever way you use the Topics API](#access-topics), -you must provide a valid token **before** calling the API, and the token must be registered for the -appropriate origin. - -<table> - <thead> - <tr> - <th style="text-align: left;">API usage</th> - <th style="text-align: left;">Trial token origin</th> - </tr> - </thead> - <tbody> - <tr> - <td><code>fetch()</code></td> - <td>Origin of the code making the call.</td> - </tr> - <tr> - <td><code>document.browsingTopics()</code></td> - <td>Origin of the code making the call.</td> - </tr> - <tr> - <td style="vertical-align: top; white-space: nowrap"><code><iframe browsingtopics ...></code></td> - <td>The token is required in the document that embeds the iframe: a token must be provided - that has been registered for the same origin as the code that creates the iframe.</td> - </tr> - </tbody> -</table> - -When using the `fetch()` or `document.browsingTopics()` approach in a third-party context, the API -caller must provide a token registered for the origin of the code making the call. That origin will -be the same wherever the code is embedded. For example, multiple sites might include `<script -src="https://adtech.example/js/topics.js">`, which would provide a token registered for -`https://adtech.com` before making an API call. If the Topics API is used from a script element in a -page in an iframe (as opposed to a script included from a different origin) a trial token must be -provided in the page, registered for its origin. - -Always do [feature detection](#feature-detection) before attempting to use an origin trial API. ## Get and set topics {: #epoch} diff --git a/site/en/docs/privacy-sandbox/topics/integration-guide/index.md b/site/en/docs/privacy-sandbox/topics/integration-guide/index.md index 2b557afaa..c3249b766 100644 --- a/site/en/docs/privacy-sandbox/topics/integration-guide/index.md +++ b/site/en/docs/privacy-sandbox/topics/integration-guide/index.md @@ -4,12 +4,15 @@ title: 'Topics API integration guide' subhead: Learn how to use the Topics API to meet specific ad tech use cases. description: Learn how to use the Topics API to meet specific ad tech use cases. date: 2023-06-02 +updated: 2023-09-20 authors: - thiagodiogo - andreeacucu - samdutton --- +{% Partial 'privacy-sandbox/ot-end.njk' %} + {% Aside %} We'd love to know how this article could be improved! @@ -33,13 +36,12 @@ The first step is to familiarize yourself with the Topics API and services. 1. Keep up with the [latest news](/docs/privacy-sandbox/topics/latest/) about the Topics API. 1. Contribute to the conversation via [GitHub issues](https://github.com/patcg-individual-drafts/topics/issues) or [W3C calls](https://github.com/patcg-individual-drafts/topics/issues/115). 1. If you encounter unfamiliar terms, review the [Privacy Sandbox glossary](/docs/privacy-sandbox/glossary/). -1. For more information on Chrome concepts, such as origin trials or Chrome flags, review the short videos and articles available at [goo.gle/cc](http://goo.gle/cc). +1. For more information on Chrome concepts, such as Chrome flags, review the short videos and articles available at [goo.gle/cc](http://goo.gle/cc). ## Build and test locally This section describes how to try out the Topics API as an individual developer. -[Participate in the origin trial](#participate-in-the-origin-trial) explains how to test at scale with your users by taking part in the origin trial. 1. Local testing and deployment (Estimated time: around 2 days) 1. Enable the API with your local browser from the command line with [feature flags](/docs/privacy-sandbox/topics/#feature-flags). Test the [header](https://topics-fetch-demo.glitch.me/) and [JavaScript API](https://topics-demo.glitch.me/) demos to see Topics in action ([walkthrough video](https://www.youtube.com/watch?v=hEBzWuXjeTQ)). @@ -129,7 +131,7 @@ There are two ways to observe and access the topics for a user. You can use * The JavaScript API from within an iframe: * Adding an iframe on target websites (publisher's websites) that contains JavaScript code calling the Topics API using `document.browsingTopics()`. * Headers option: - * Fetch **(which is recommended)** or XHR (**not recommended** and only available during origin trial): + * Fetch **(which is recommended)** or XHR (**not recommended** and was only available during the completed origin trial): * You can access topics from the `Sec-Browsing-Topics` header in requests to the ad tech back end. This is the most performant option (low latency to observe topics of one specific user). * Using an iframe tag with the `browsingtopics` attribute: * You can add an iframe with a `browsingtopics` attribute and Chrome will include topics (observed for the eTLD+1 of the iframe) in the `Sec-Browsing-Topics` header on the request for the iframe. @@ -261,93 +263,6 @@ Topics data can be considered alongside other signals such as URLs, keywords, an As explained in [Maximize ad relevance after third-party cookies](/docs/privacy-sandbox/maximize-ad-relevance/), there are multiple approaches to leveraging Topics to serve relevant ads. Some of these involve using topics to build audiences, and others suggest using Topics as one signal among others to train machine learning models that will be used to infer additional interests of the audience or even to optimize bidding logic. -### Participate in the origin trial - -Now that you've deployed locally, the following section will guide you on how to deploy and test at scale with your users. To achieve this, you must register the eTLD+1 of your code for the [Privacy Sandbox Relevance and Measurement origin trial](/docs/privacy-sandbox/unified-origin-trial/). The Topics API will be activated on any page that provides a valid trial token. You can check the [current status of this Origin Trial](/docs/privacy-sandbox/unified-origin-trial/#status) on the status page. - - -[Origin trials](/docs/web-platform/origin-trials/) are a safe way to test new or experimental web platform features in Chrome. Anyone participating in the trial can test these features and provide feedback on usability and effectiveness. Typically these trials are limited in duration. - -#### Configure your site or app to participate in the origin trial - -The Privacy Sandbox Relevance and Measurement origin trial makes the trial APIs available for both first-party and third-party contexts. This means you can access the trial APIs in code running on your own eTLD+1, and also from JavaScript code from your eTLD+1 that is embedded on a third-party site. - -To allow usage in a third-party context, you must select **Third-party matching** when you register your eTLD+1 for the trial. - -{% Img src="image/80mq7dk16vVEg8BBhsVe42n6zn82/6bRyXMiYLzRfKZ9R3Sxa.png", alt="Registration page for the Privacy Sandbox Relevance and Measurement origin trial.", width="800", height="512" %} -<figcaption>The origin trial registration page with third-party matching.</figcaption> - -{% Aside 'caution' %} -A third-party token must be provided in an external JavaScript file included via a `script` element; a third-party token won't work in a meta tag, inline script, or HTTP header. - -You can register multiple tokens for the same eTLD+1 if necessary—both first- and third-party. -{% endAside %} - -1. **[Register](/docs/privacy-sandbox/unified-origin-trial/#configure) yourself** on behalf of your company. This is recommended when you are going to implement and integrate the Topics API directly in your application (building the iframe, calling the Topics API). - - - In this case you will need to add an origin trial token to your Topics iframe, to help you decide which token you will need in your application. We recommend you use a First-Party Token with the JavaScript API. - - The figure below shows part of the registration page. To register a first-party token, do not check any boxes in this section. - - {% Img src="image/RtQlPaM9wdhEJGVKR8boMPkWf443/mctvCWr97SWNylSRktwW.png", width="715", height="411", alt="Registration page for the Privacy Sandbox Relevance and Measurement origin trial." %} - <figcaption>The origin trial registration page for first-party token.</figcaption> - - The following decision tree can help you decide which token you need. - - {% Img src="image/RtQlPaM9wdhEJGVKR8boMPkWf443/cgWSN3o9pUqFq8ZtRB3e.png", alt="Decision tree to help you determine the type of token you need.", width="800", height="455" %} - <figcaption>Determining which token you need. - </figcaption> - -1. **Register as a third party**. This is recommended when you are not implementing the Topics API directly into your application and are relying on another partner to test it for you. [Learn about third-party origin trials](/docs/web-platform/third-party-origin-trials/). - - -#### Key recommendations - -1. Discuss with your team to make sure you have selected the correct origin trial option for your specific case. -1. After registering, [embed the origin trial token](/docs/web-platform/origin-trials/#iframe) in your iframe code, not in the top-level site where the iframe is embedded. - - -#### Provide a first-party origin trial token - -A first-party token can be provided in a meta tag, an HTTP header, or [programmatically](/docs/web-platform/origin-trials/#programmatic), for the eTLD+1 of the Topics caller. - -For example, here's how to do it in a page in an iframe that includes code (from the same eTLD+1) that calls `document.browsingTopics()`: - -```html -<meta http-equiv="origin-trial" content="OT_FOR_<topics_caller_eTLD+1>"> -``` - -#### Provide a third-party origin trial token - -To use Topics with fetch headers, a third-party origin trial token must be provided programmatically by the party making the fetch call, registered for the same origin as the call (and making sure the token is read before the call is made). Read more about how to [programmatically provide an origin trial token](/docs/web-platform/origin-trials/#programmatic). An example is shown here: - - -```javascript -{ - // Programmatically inject <meta> tag for - // Third-party origin trial token - - const otMeta = document.createElement('meta'); - otMeta.httpEquiv = 'origin-trial'; - otMeta.content = 'YOUR TOKEN HERE'; - document.head.append(otMeta); -} - -fetch('<topics_caller_eTLD+1>', {browsingTopics: true}) - .then((response) => { - // Process the response - }) -``` - -{% Aside %} -Given that the origin trial token has to be generated for the same origin as the code, it is recommended that publishers use a script owned by the ad tech. This way, multiple sites can include the same script (as shown in the example below) which provides a third-party token registered for the ad tech origin (https://adtech.com). -{% endAside %} - -```html -<script src="https://adtech.com/js/topics.js"> -``` - ## Build and deploy 1. Collect topics by observing users in production—not scaled yet (Estimated time: approximately 1 week) @@ -355,7 +270,6 @@ Given that the origin trial token has to be generated for the same origin as the 1. Define the domain of the iframe. 1. Build the JavaScript code, using the [demo app](https://topics-demo.glitch.me/) as a code reference — or implement the headers option. 1. Deploy Topics to your controlled environment (some production sites). - 1. Register for the origin trial. 1. Add the Topics implementation to some target sites (no more than five sites at this time). 1. Functional testing and validation. 2. [Optional] Use Topics data as a contextual signal (with URLs, tags, etc.) (Estimated time: around 3 days). @@ -364,7 +278,7 @@ Given that the origin trial token has to be generated for the same origin as the ### Deploy to some target sites -Now that you have the code and you have registered for the origin trial, let's add it to some target sites for a first test and to make sure the API is stable and working in this controlled environment. +Now that you have the code, let's add it to some target sites for a first test and to make sure the API is stable and working in this controlled environment. We recommend that you pick target websites that: @@ -379,13 +293,13 @@ We recommend that you pick target websites that: When calling the Topics API in this limited environment you can expect: -* An empty array of topics [] if this is the first call of this device, for this site and caller in the last seven days. +* An empty array of topics `[]` if this is the first call of this device, for this site and caller in the last seven days. * A list of zero to three topics, representing the interests of this user. * After seven days of observation you should receive: * One topic representing the interest of that user calculated from the navigation history of that week. - * One important detail: if not enough topics have been observed by you for a user for the Topics API to calculate the top five topics of that week, then Topics will add as many random topics as necessary to arrive at the total number of five. Find [more details in the API proposal](https://github.com/patcg-individual-drafts/topics#specific-details). + * One important detail: if not enough topics have been observed by you for a user for the Topics API to calculate the top five topics of that week, then Topics will add as many random topics as necessary to arrive at the total number of five. Find [more details about the API](https://github.com/patcg-individual-drafts/topics#specific-details). * A new topic entry replacing one of the three if you are calling it after four weeks of observation. - * This happens because the Topics API will be stable for the following weeks, not exposing too many of the user's interests. Find [more details in the API proposal](https://github.com/patcg-individual-drafts/topics#specific-details). + * This happens because the Topics API will be stable for the following weeks, not exposing too many of the user's interests. Find [more details on GitHub](https://github.com/patcg-individual-drafts/topics#specific-details). * If you have not observed topics for the user for more than three weeks, then the Topics API will return an empty array `[]` again. Measure the performance and metrics of your user experience. @@ -403,27 +317,18 @@ Measure the performance and metrics of your user experience. <dd> If you are calling the Topics API within the first week of observing a user, then this is expected. </dd> -<dt> -<strong>I can't see much traffic from users with Topics API enabled visiting my site, what can I do?</strong> -</dt> -<dd> -Make sure your origin trial configuration is correct. <a href="/docs/web-platform/origin-trial-troubleshooting/">Troubleshoot Chrome origin trials</a> provides a checklist to help fix origin trial problems. -When using the JavaScript API from an iframe, a common mistake is to add an origin trial token to the target site (top level site). Instead, the origin trial token must be provided from your iframe. - -</dd> </dl> ### Key recommendations 1. Test your front-end code to make sure your JavaScript is working as expected. - 1. It's important to make sure your origin trial token is valid and can be used in your context. We highly recommend you use the Chrome DevTools (Application tab) to troubleshoot and validate that your origin trial token is being used correctly. More details can be found in the [origin trials troubleshooting guide](/docs/web-platform/origin-trial-troubleshooting/#use-chrome-devtools-to-check-tokens). + 1. Test your back end to receive the topics results. 1. Remember to make sure data types and back-end API parameters are configured correctly. 1. Make sure your back end is configured to scale appropriately. 1. From our experience, it is necessary to allow at least three weeks before starting to get more relevant topics results. -1. Not all users will have Topics enabled during the origin trial: - 1. It depends on the device being selected to participate in this origin trial . +1. Not all users will have Topics enabled: 1. Users can explicitly disable the Topics API. 1. Publisher's pages can control permissions policy. Refer to ([opt-out](/docs/privacy-sandbox/topics/#site-opt-out)) in the Topics API developer guide. 1. Check [chromestatus.com](https://chromestatus.com/) for more details. diff --git a/site/en/docs/privacy-sandbox/topics/latest/index.md b/site/en/docs/privacy-sandbox/topics/latest/index.md index 43bf0156c..c30828a42 100644 --- a/site/en/docs/privacy-sandbox/topics/latest/index.md +++ b/site/en/docs/privacy-sandbox/topics/latest/index.md @@ -6,11 +6,14 @@ subhead: > description: > Updates and enhancements to the design and implementation of the API. date: 2023-01-24 +updated: 2023-09-18 authors: - leeronisrael - joeytrotz --- +{% Partial 'privacy-sandbox/ot-end.njk' %} + {% Aside %} For technical resources, see the developer guides: diff --git a/site/en/docs/privacy-sandbox/topics/topic-classification/index.md b/site/en/docs/privacy-sandbox/topics/topic-classification/index.md index 1f7b904a5..b9c99b7ad 100644 --- a/site/en/docs/privacy-sandbox/topics/topic-classification/index.md +++ b/site/en/docs/privacy-sandbox/topics/topic-classification/index.md @@ -69,7 +69,7 @@ caller must observe and request topics from the same origin. A caller can access topics via the JavaScript API from [within an iframe](/docs/privacy-sandbox/topics/integration-guide/#implement-with-javascript-and-iframes) using `document.browsingTopics()`. -A caller can also access topics from the [`Sec-Browsing-Topics` header](docs/privacy-sandbox/topics/integration-guide/#implement-with-http-headers) of a `fetch()` request, or of an iframe request. XHR requests are also enabled during origin trials (only), but this method is not recommended. +A caller can also access topics from the [`Sec-Browsing-Topics` header](docs/privacy-sandbox/topics/integration-guide/#implement-with-http-headers) of a `fetch()` request, or of an iframe request. XHR requests were enabled during the now-completed origin trials (only). {% endAside %} @@ -108,7 +108,7 @@ A full [taxonomy of topics with IDs](https://github.com/patcg-individual-drafts/ ### Providing feedback or input on the classifier model -There are [several channels](/docs/privacy-sandbox/feedback/) for providing feedback on the Topics proposal. For feedback on the classifier model, we recommend [submitting a GitHub issue](https://github.com/patcg-individual-drafts/topics/issues) or replying to an existing issue. For example: +There are [several channels](/docs/privacy-sandbox/feedback/) for providing feedback on the Topics API. For feedback on the classifier model, we recommend [submitting a GitHub issue](https://github.com/patcg-individual-drafts/topics/issues) or replying to an existing issue. For example: - [What topics taxonomy should be used long term?](https://github.com/patcg-individual-drafts/topics/issues/3) - [What if a site disagrees with the topics assigned?](https://github.com/patcg-individual-drafts/topics/issues/2) @@ -167,7 +167,7 @@ The table below outlines an example (though unrealistically small) of a hypothet </tbody> </table> -At the end of the epoch (currently proposed to be one week) the Topics API generates the browser's top topics for the week. +At the end of the epoch (currently one week) the Topics API generates the browser's top topics for the week. - adtech1.example is now eligible to receive the "Fitness" and "Crafts" topics, since it observed them on yoga.example and also on knitting.example. - adtech1.example is not eligible to receive the "Travel & Transportation" topic for this user as it is not present on any sites the user visited recently that are associated with that topic. diff --git a/site/en/docs/privacy-sandbox/unified-origin-trial/index.md b/site/en/docs/privacy-sandbox/unified-origin-trial/index.md index 2e336e8d6..8ac21f37a 100644 --- a/site/en/docs/privacy-sandbox/unified-origin-trial/index.md +++ b/site/en/docs/privacy-sandbox/unified-origin-trial/index.md @@ -8,13 +8,15 @@ description: > Run unified experiments across Attribution Reporting, Protected Audience API, Topics, Fenced Frames, and Shared Storage. date: 2022-09-08 -updated: 2023-06-05 +updated: 2023-09-18 authors: - anusmitaray - kevinkiklee - rowan_m --- +{% Partial 'privacy-sandbox/ot-end.njk' %} + The Privacy Sandbox includes a selection of proposals to enable advertising use cases without the need for cross-site tracking. [Origin trials](/blog/origin-trials/) provide an opportunity for developers to evaluate diff --git a/site/en/docs/privacy-sandbox/user-agent/index.md b/site/en/docs/privacy-sandbox/user-agent/index.md index d671d6922..adc0086a4 100644 --- a/site/en/docs/privacy-sandbox/user-agent/index.md +++ b/site/en/docs/privacy-sandbox/user-agent/index.md @@ -303,7 +303,7 @@ User-Agent string. * **Origin trial**: [Share your feedback](https://github.com/miketaylr/user-agent-reduction/issues). * **Demo**: Try our [demo of User-Agent reduction](https://uar-ot.glitch.me/). -* **GitHub**: Read the [UA-CH proposal](https://github.com/WICG/ua-client-hints), +* **GitHub**: Read the [UA-CH explainer](https://github.com/WICG/ua-client-hints), [raise questions and follow discussion](https://github.com/WICG/ua-client-hints/issues). * **Developer support**: Ask questions and join discussions on the [Privacy Sandbox Developer Support repo](https://github.com/GoogleChromeLabs/privacy-sandbox-dev-support). From 16c42ede9ff213e2244d2f3fd67d5a43d4725208 Mon Sep 17 00:00:00 2001 From: Barry Pollard <barrypollard@google.com> Date: Wed, 20 Sep 2023 14:57:24 -0700 Subject: [PATCH 804/982] Soft Navs better explanation of LCP time (#7345) --- .../blog/soft-navigations-experiment/index.md | 65 ++++++++++++------- 1 file changed, 41 insertions(+), 24 deletions(-) diff --git a/site/en/blog/soft-navigations-experiment/index.md b/site/en/blog/soft-navigations-experiment/index.md index b2bcde583..deae4f946 100644 --- a/site/en/blog/soft-navigations-experiment/index.md +++ b/site/en/blog/soft-navigations-experiment/index.md @@ -8,7 +8,7 @@ authors: - tunetheweb - yoavweiss date: 2023-02-01 -updated: 2023-09-04 +updated: 2023-09-20 hero: image/W3z1f5ZkBJSgL1V1IfloTIctbIF3/ZJLD5QJvoFcWXkqF8m5P.jpg alt: A compass on top of some booklets labeled Field Notes tags: @@ -72,34 +72,16 @@ For a website that wishes to enable this for all their visitors to see the impac Site owners can choose to include the origin trial on their pages for all, or for just a subset of users. Be aware of the [implications section](#what-are-the-implications-of-enabling-soft-navigations-in-chrome) above as to how this changes how your metrics may be reported, especially if enabling this origin trial for a large proportion of your users. Note that CrUX will continue to report the metrics in the existing manner regardless of this soft navigation setting so is not impacted by those implications. It should also be noted that origin trials are also limited to enabling experimental features on a maximum of 0.5% of all Chrome page loads as a median over 14 days, but this should only be an issue for very large sites. -## How can I measure Core Web Vitals per soft navigation? +## How can I measure soft navigations? -To include soft navigation metric entries, you need to include `includeSoftNavigationObservations: true` in your performance observer's `observe` call: - -```js -new PerformanceObserver((entryList) => { - for (const entry of entryList.getEntries()) { - console.log('LCP candidate:', entry.startTime, entry); - } -}).observe({type: 'largest-contentful-paint', buffered: true, includeSoftNavigationObservations: true}); -``` - -This extra flag on the `observe` method is needed in addition to [enabling the soft navigation functionality in Chrome](#how-do-i-enable-soft-navigations-in-chrome). This explicit opt-in at the performance observer level is to [ensure existing performance observers aren't surprised by these extra entries](https://github.com/WICG/soft-navigations/issues/11) as some additional considerations need to be taken into account when attempting to measure Core Web Vitals for soft navigations. - -Some metrics have traditionally been measured throughout the life of the page: LCP, for example, can change until an interaction occurs. CLS, FID and INP can be updated until the page is navigated away from. Therefore each "navigation" (including the original navigation) will need to finalize these metrics as each new soft navigation occurs, meaning the initial "hard" navigation metrics may be finalised earlier that usual. - -Similarly, when starting to measure the metrics for the new soft navigation of these long-lived metrics, metrics will need to be "reset" or "reinitialized" and treated as new metrics, with no memory of the values that were set for previous "pages". - -Timings will still be returned in respect of the original "hard" navigation start time. So to calculate LCP for a soft navigation for example, you will need to take the LCP timing and subtract the appropriate soft navigation start time to get a timing relative to the soft navigation. This has been done to keep all timings consistent so other performance timings (such as event timings) that are not measured from the "navigation" time can be treated the same. - -### Reporting soft navigations - -Once the soft navigations experiment is enabled, the metrics will be reporting via the [`PerformanceObserver`](https://developer.mozilla.org/docs/Web/API/PerformanceObserver) API as usual, but with an additional `navigationId` added to each metric, corresponding to the navigation entry the metric was emitted for. +Once the soft navigations experiment is enabled, the metrics will be reporting via the [`PerformanceObserver`](https://developer.mozilla.org/docs/Web/API/PerformanceObserver) API as usual. However, there are some extra considerations that need to be taken into account for these metrics. {% Aside 'note' %} Note: [FP and FCP are currently not reported for soft navigations](https://bugs.chromium.org/p/chromium/issues/detail?id=1479350), and [neither is FID](https://bugs.chromium.org/p/chromium/issues/detail?id=1407656). {% endAside %} +### Reporting soft navigations + You can use a `PerformanceObserver` to observe soft navigations. Below is an example code snippet that logs soft navigation entries to the console—including previous soft navigations on this page via the `buffered` option: ```js @@ -113,7 +95,7 @@ This can be used to finalize full-life page metrics for the previous navigation. As soft navigations can only be seen after they have occurred, some metrics will need to be finalized upon this event, and then reported for the previous URL, as the current URL will now reflect the updated URL for the new page. -The `navigationID` attribute of the appropriate `PerformanceEntry` can be used to tie the event back to the correct URL. This can be looked up with the [`PerformanceEntry` API](https://developer.mozilla.org/docs/Web/API/PerformanceEntry): +The `navigationId` attribute of the appropriate `PerformanceEntry` can be used to tie the event back to the correct URL. This can be looked up with the [`PerformanceEntry` API](https://developer.mozilla.org/docs/Web/API/PerformanceEntry): ```js const softNavEntry = @@ -145,6 +127,41 @@ The `startTime` is the time of the initial interaction (for example, a button cl All performance timings, including those for soft navigations, are reported as a time from the initial "hard" page navigation time. Therefore, the soft navigation start time is needed to baseline the soft navigation loading metric times (for example LCP), relative to this soft navigation time instead. +### Measuring Core Web Vitals per soft navigation + +To include soft navigation metric entries, you need to include `includeSoftNavigationObservations: true` in your performance observer's `observe` call. + +```js +new PerformanceObserver((entryList) => { + for (const entry of entryList.getEntries()) { + console.log('Layout Shift time:', entry); + } +}).observe({type: 'layout-shift', buffered: true, includeSoftNavigationObservations: true}); +``` + +The extra `includeSoftNavigationObservations` flag on the `observe` method is needed in addition to [enabling the soft navigation functionality in Chrome](#how-do-i-enable-soft-navigations-in-chrome). This explicit opt-in at the performance observer level is to [ensure existing performance observers aren't surprised by these extra entries](https://github.com/WICG/soft-navigations/issues/11) as some additional considerations need to be taken into account when attempting to measure Core Web Vitals for soft navigations. + +Timings will still be returned in respect of the original "hard" navigation start time. So to calculate LCP for a soft navigation for example, you will need to take the LCP timing and subtract the appropriate soft navigation start time as detailed above to get a timing relative to the soft navigation. For example, for LCP: + +```js +new PerformanceObserver((entryList) => { + for (const entry of entryList.getEntries()) { + const softNavEntry = + performance.getEntriesByType('soft-navigation').filter( + (navEntry) => navEntry.navigationId === entry.navigationId + )[0]; + const hardNavEntry = performance.getEntriesByType('navigation')[0]; + const navEntry = softNavEntry || hardNavEntry; + const startTime = navEntry?.startTime; + console.log('LCP time:', entry.startTime - startTime); + } +}).observe({type: 'largest-contentful-paint', buffered: true, includeSoftNavigationObservations: true}); +``` + +Some metrics have traditionally been measured throughout the life of the page: LCP, for example, can change until an interaction occurs. CLS, FID and INP can be updated until the page is navigated away from. Therefore each "navigation" (including the original navigation) may need to finalize the previous page's metrics as each new soft navigation occurs. This means the initial "hard" navigation metrics may be finalised earlier that usual. + +Similarly, when starting to measure the metrics for the new soft navigation of these long-lived metrics, metrics will need to be "reset" or "reinitialized" and treated as new metrics, with no memory of the values that were set for previous "pages". + ### How should content that remains the same between navigations be treated? FP, FCP, and LCP for soft navigations will measure new paints only. This can result in a different LCP, for example, from a cold load of that soft navigation to a soft load. From 229069d22a428de0dd0acef88824a5d4ad5bc171 Mon Sep 17 00:00:00 2001 From: Ivan Akulov <iamakulov@outlook.com> Date: Wed, 20 Sep 2023 14:58:02 -0700 Subject: [PATCH 805/982] Make it more explicit that `effectiveConnectionType` is not supported (#7340) * Make it more explicit that `effectiveConnectionType` is not supported * Update site/en/docs/crux/history-api/index.md --------- Co-authored-by: Barry Pollard <barrypollard@google.com> --- site/en/docs/crux/history-api/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/en/docs/crux/history-api/index.md b/site/en/docs/crux/history-api/index.md index 8f9a933a6..007cbceb9 100644 --- a/site/en/docs/crux/history-api/index.md +++ b/site/en/docs/crux/history-api/index.md @@ -314,7 +314,7 @@ The URL uses [gRPC Transcoding](https://google.aip.dev/127) syntax. ### Request body -As the CrUX History API uses the same request bodies, you can reference [the daily CrUX API request body documentation](../api/#request-body) for more details. +The CrUX History API uses the same request bodies as [the daily CrUX API](/docs/crux/api/#request-body), with the exception of not supporting the `effectiveConnectionType` request field. For example, to request the desktop Largest Contentful Paint values for the web.dev homepage: From 733c4da2c5c9329245e53706ceb0c4fc35b334d9 Mon Sep 17 00:00:00 2001 From: Rachel Andrew <rachelandrew@google.com> Date: Wed, 20 Sep 2023 18:51:55 -0700 Subject: [PATCH 806/982] update webdriver bidi info (#7346) --- site/en/blog/we-are-chrome-for-developers/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/en/blog/we-are-chrome-for-developers/index.md b/site/en/blog/we-are-chrome-for-developers/index.md index 5b6d0ae5f..ab6089c80 100644 --- a/site/en/blog/we-are-chrome-for-developers/index.md +++ b/site/en/blog/we-are-chrome-for-developers/index.md @@ -46,7 +46,7 @@ In 2020, we launched [Core Web Vitals](web.dev/web-vitals) that have proven to b We also kicked off [Project Aurora](/aurora/) two years ago, which was an important collaboration between the Chrome team and open source frameworks to bring Core Web Vitals improvements directly to the tools that developers use the most. To help developers debug the code they write and not what gets compiled due to the framework, we launched the [Modern Web Debugging](/blog/devtools-modern-web-debugging/) initiative that has already built in support for many frameworks in Chrome DevTools. -Finally, cross-browser testing and automation is yet another challenge that developers have to tackle. [Web Driver BiDi](/blog/webdriver-bidi-2023/) now has implementations across all major browser engines, using the best of the WebDriver Classic and the Chrome DevTools Protocol to make cross-browser automation significantly better for developers. +Finally, cross-browser testing and automation is yet another challenge that developers have to tackle We're actively working with all major browsers on [Web Driver BiDi](/blog/webdriver-bidi-2023/), a new standard that uses the best of the WebDriver Classic and the Chrome DevTools Protocol to make cross-browser automation significantly better for developers. ## Partnering to safeguard the openness of the web From 29433d92ea7e21c2e0f91684c3f9684b3d24e6e2 Mon Sep 17 00:00:00 2001 From: Mathias Bynens <mathias@qiwi.be> Date: Sun, 24 Sep 2023 15:40:56 +0200 Subject: [PATCH 807/982] Mention Chrome for Testing (#7347) --- site/en/blog/we-are-chrome-for-developers/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/en/blog/we-are-chrome-for-developers/index.md b/site/en/blog/we-are-chrome-for-developers/index.md index ab6089c80..aec9c2a9d 100644 --- a/site/en/blog/we-are-chrome-for-developers/index.md +++ b/site/en/blog/we-are-chrome-for-developers/index.md @@ -46,7 +46,7 @@ In 2020, we launched [Core Web Vitals](web.dev/web-vitals) that have proven to b We also kicked off [Project Aurora](/aurora/) two years ago, which was an important collaboration between the Chrome team and open source frameworks to bring Core Web Vitals improvements directly to the tools that developers use the most. To help developers debug the code they write and not what gets compiled due to the framework, we launched the [Modern Web Debugging](/blog/devtools-modern-web-debugging/) initiative that has already built in support for many frameworks in Chrome DevTools. -Finally, cross-browser testing and automation is yet another challenge that developers have to tackle We're actively working with all major browsers on [Web Driver BiDi](/blog/webdriver-bidi-2023/), a new standard that uses the best of the WebDriver Classic and the Chrome DevTools Protocol to make cross-browser automation significantly better for developers. +Finally, cross-browser testing and automation is yet another challenge that developers have to tackle. To this end, we launched [Chrome for Testing](/blog/chrome-for-testing/), ensuring developers access to reliable downloads for browser automation. At the ecosystem level, we're actively working with all major browsers on [WebDriver BiDi](/blog/webdriver-bidi-2023/), a new standard that combines the best of the WebDriver Classic and the Chrome DevTools Protocol to make cross-browser automation significantly better for developers. ## Partnering to safeguard the openness of the web From 9844fe0568b82448a15ab26204a8e8462a5a6cec Mon Sep 17 00:00:00 2001 From: Nancymic2 <nmichell@google.com> Date: Mon, 25 Sep 2023 12:44:38 -0400 Subject: [PATCH 808/982] ua reduction changes (#7360) * ua reduction * ua reduction * ua reduction * ua reduction * Update date * Update UA origin trial * Update index.md * Remove old status partial * Update end dates * Update index.md * Update index.md * Update index.md * Update index.md * Update index.md * Update index.md * Update index.md * Add is_outdated: true * Add is_outdated: true * add is_outdated: true * change aside * Update aside --- .../_partials/privacy-sandbox/timeline/ua-ch.md | 4 ++-- .../en/blog/force-major-version-to-100/index.md | 5 +++++ .../index.md | 6 +++++- .../index.md | 15 ++++++++++++++- .../index.md | 6 ++++++ .../user-agent-reduction-origin-trial/index.md | 14 ++++++++++++-- .../en/docs/privacy-sandbox/user-agent/index.md | 17 +++++------------ 7 files changed, 49 insertions(+), 18 deletions(-) diff --git a/site/en/_partials/privacy-sandbox/timeline/ua-ch.md b/site/en/_partials/privacy-sandbox/timeline/ua-ch.md index 520ef9fa8..1ba7eaa34 100644 --- a/site/en/_partials/privacy-sandbox/timeline/ua-ch.md +++ b/site/en/_partials/privacy-sandbox/timeline/ua-ch.md @@ -1,5 +1,5 @@ -* [Origin trial](/blog/user-agent-reduction-origin-trial/) Chrome 95 to 103 -* [Deprecation trial](/blog/user-agent-reduction-deprecation-trial/) Chrome 103 to Chrome 116 +* [Origin trial](/blog/user-agent-reduction-origin-trial/) Chrome 95 to 103, ended March 7, 2023. +* [Deprecation trial](/blog/user-agent-reduction-deprecation-trial/) Chrome 103 to Chrome 116, ended September 23, 2023. * [Chrome DevTools integration](/blog/new-in-devtools-89/#ua-ch) * Review the [UA-CH Chrome platform status](https://chromestatus.com/feature/5995832180473856) diff --git a/site/en/blog/force-major-version-to-100/index.md b/site/en/blog/force-major-version-to-100/index.md index 2eb8e9858..3880f3775 100644 --- a/site/en/blog/force-major-version-to-100/index.md +++ b/site/en/blog/force-major-version-to-100/index.md @@ -15,8 +15,13 @@ authors: date: 2021-11-01 tags: - chrome-96 +is_outdated: true --- +{% Aside 'warning'%} +This article is outdated. Read the latest about version numbers in User-Agent strings in [User-Agent reduction](/docs/privacy-sandbox/user-agent/). +{% endAside %} + In the first half of 2022, Chrome will reach a three-digit major version number: 100! When browsers first reached version 10 many eons ago, [lots of issues were discovered](https://maqentaer.com/devopera-static-backup/http/dev.opera.com/articles/view/opera-ua-string-changes/index.html) diff --git a/site/en/blog/user-agent-reduction-android-model-and-version/index.md b/site/en/blog/user-agent-reduction-android-model-and-version/index.md index 7923ec47e..20451085a 100644 --- a/site/en/blog/user-agent-reduction-android-model-and-version/index.md +++ b/site/en/blog/user-agent-reduction-android-model-and-version/index.md @@ -7,7 +7,7 @@ subhead: > Chrome is continuing to reduce the information shared in its user-agent string to help protect user's privacy. date: 2023-02-27 # updated: 2021-02-27 -# is_outdated: true +is_outdated: true # new_available_content_url: /docs/privacy-sandbox/user-agent/ authors: - rowan_m @@ -20,6 +20,10 @@ alt: > sharing_image: 'image/VWw0b3pM7jdugTkwI6Y81n6f5Yc2/3VrRwYpBizX3JQA93uzg.png' --- +{% Aside 'warning'%} +This article is outdated as User-Agent reduction is complete. Learn how to [migrate to User-Agent Client Hints](https://web.dev/migrate-to-ua-ch/) and read about why this change was made in [User-Agent reduction](/docs/privacy-sandbox/user-agent/). +{% endAside %} + Starting in Chrome 110 (February 2023) we are gradually introducing a _fixed value for Android version and device model_—the default value will always be `Android 10` on a model `K`. If you rely on the user-agent to detect a visitor's operating system version, Android device model, or detailed browser version then you may need to take action—read on for the details. diff --git a/site/en/blog/user-agent-reduction-deprecation-trial/index.md b/site/en/blog/user-agent-reduction-deprecation-trial/index.md index cf74329f6..c0e490932 100644 --- a/site/en/blog/user-agent-reduction-deprecation-trial/index.md +++ b/site/en/blog/user-agent-reduction-deprecation-trial/index.md @@ -2,7 +2,7 @@ layout: "layouts/blog-post.njk" title: "User-Agent Reduction deprecation trial" subhead: > - Register to continue receiving the full User-Agent string. + The User-Agent Reduction deprecation trial allowed sites to continue receiving the full User-Agent string after UA string reduction. The trial ended September 23, 2023. description: > Starting from Chrome 101, the information available in the User-Agent string will be reduced. Sites that haven’t had time to migrate away from using the reduced User-Agent string can take @@ -11,12 +11,23 @@ authors: - abeyad - victortan date: 2022-02-24 +updated: 2023-09-23 tags: - privacy - origin-trials - chrome-101 +is_outdated: true --- + {% Aside 'warning' %} + The User-Agent Reduction deprecation trial ended September 23, 2023. The information available in the User-Agent string was reduced beginning in Chrome 101. During the deprecation trial, sites were able to continue receiving parts of the UA string, but will now have to rely on other methods. + + To replace functionality that relied on the User Agent string, you can implement the [User Agent client hints API](https://developer.mozilla.org/docs/Web/API/User-Agent_Client_Hints_API#browser_compatibility). + + The [User-Agent Client Hints page](https://web.dev/migrate-to-ua-ch/) provides some background. + + The remainder of this blog post should be considered deprecated. + {% endAside %} Starting from Chrome 101, the information available in the User-Agent (UA) string will be reduced [using a phased approach](https://blog.chromium.org/2021/09/user-agent-reduction-origin-trial-and-dates.html). Sites that haven't had time to migrate away from using the reduced User-Agent string and [move toward User-Agent Client Hints](https://web.dev/migrate-to-ua-ch/) can take part in a deprecation trial to continue receiving the full User-Agent string. @@ -100,3 +111,5 @@ The User-Agent Reduction deprecation trial will run from Chrome 100 to Chrome 11 ## How do I share feedback for the User-Agent Reduction depreciation trial? Submit any issues or feedback to the [User-Agent Reduction GitHub repository](https://github.com/miketaylr/user-agent-reduction/issues). + + diff --git a/site/en/blog/user-agent-reduction-oct-2022-updates/index.md b/site/en/blog/user-agent-reduction-oct-2022-updates/index.md index f184af87b..c7962b3b4 100644 --- a/site/en/blog/user-agent-reduction-oct-2022-updates/index.md +++ b/site/en/blog/user-agent-reduction-oct-2022-updates/index.md @@ -14,10 +14,16 @@ alt: "Timeline of User-Agent Reduction changes." authors: - jney date: 2022-08-25 +updated: 2023-09-23 tags: - privacy +is_outdated: true --- +{% Aside 'warning'%} +This article is outdated as User-Agent reduction is complete. Learn how to [migrate to User-Agent Client Hints](https://web.dev/migrate-to-ua-ch/) and read about why this change was made in [User-Agent reduction](/docs/privacy-sandbox/user-agent/). +{% endAside %} + In October, Chrome will take the next step in reducing the information available in the browser's User-Agent (UA) string, to improve privacy for users. With this change, websites and services that rely on the User-Agent string for diff --git a/site/en/blog/user-agent-reduction-origin-trial/index.md b/site/en/blog/user-agent-reduction-origin-trial/index.md index 9aef6611e..84b251222 100644 --- a/site/en/blog/user-agent-reduction-origin-trial/index.md +++ b/site/en/blog/user-agent-reduction-origin-trial/index.md @@ -3,7 +3,7 @@ layout: "layouts/blog-post.njk" title: "User-Agent Reduction origin trial" subhead: > description: > - Starting in Chrome 95 Beta, an origin trial allows + Starting in Chrome 95 Beta, an origin trial allowed sites to opt into receiving the reduced user agent string, which will contain only the browser's brand and significant version, its desktop or mobile distinction, and the platform it's running on. @@ -11,13 +11,23 @@ authors: - arichiv - abeyad date: 2021-09-14 -updated: 2022-01-07 +updated: 2023-09-23 tags: - privacy - origin-trials - chrome-95 +is_outdated: true --- + {% Aside 'warning' %} + The User-Agent Reduction origin trial ended March 7, 2023. The User-Agent UA string is now fully reduced. + To replace functionality that relied on the User Agent string, you can implement the [User Agent client hints API](https://developer.mozilla.org/docs/Web/API/User-Agent_Client_Hints_API#browser_compatibility). + + The [User-Agent Client Hints page](https://web.dev/migrate-to-ua-ch/) provides some background. + + The remainder of this blog post should be considered deprecated. + {% endAside %} + User-Agent Reduction is an effort to reduce passive fingerprinting surfaces by reducing the information in the [User-Agent](https://developer.mozilla.org/docs/Web/HTTP/Headers/User-Agent) diff --git a/site/en/docs/privacy-sandbox/user-agent/index.md b/site/en/docs/privacy-sandbox/user-agent/index.md index adc0086a4..289bc8a2e 100644 --- a/site/en/docs/privacy-sandbox/user-agent/index.md +++ b/site/en/docs/privacy-sandbox/user-agent/index.md @@ -2,39 +2,32 @@ layout: 'layouts/doc-post.njk' title: 'User-Agent reduction' subhead: > - Limit passively shared browser data to reduce the volume of sensitive information which leads to fingerprinting. + User-Agent reduction limits passively shared browser data to reduce the volume of sensitive information which leads to fingerprinting. The reduction is now complete. description: > - Limit passively shared browser data to reduce the volume of sensitive information which leads to fingerprinting. + User-Agent reduction limits passively shared browser data to reduce the volume of sensitive information which leads to fingerprinting. The reduction is now complete. date: 2021-11-09 -updated: 2023-08-01 +updated: 2023-09-23 authors: - alexandrawhite --- -## Implementation status - -{% Partial 'privacy-sandbox/timeline/ua-ch.njk' %} - ## What is User-Agent reduction? User-Agent (UA) reduction minimizes the identifying information shared in the User-Agent string, which may be [used for passive fingerprinting](https://www.w3.org/2001/tag/doc/unsanctioned-tracking/#unsanctioned-tracking-tracking-without-user-control). Now that these changes have been rolled -out for scaled availability, all resource requests have a reduced `User-Agent` header. As a result, +out for general availability, all resource requests have a reduced `User-Agent` header. As a result, the return values from certain `Navigator` interfaces are reduced, including: `navigator.userAgent`, `navigator.appVersion`, and `navigator.platform`. -Web developers should review their site code for instances and uses +Web developers should review their site code for usage of the User-Agent string. If your site relies on parsing the User-Agent string to read the device model, platform version, or full browser version, you'll need to [implement the User-Agent Client Hints API](https://web.dev/migrate-to-ua-ch/). -[Review the latest timeline](https://www.chromium.org/updates/ua-reduction) for -User-Agent reduction. - {% Aside 'key-term' %} The [`User-Agent` string](https://developer.mozilla.org/docs/Web/HTTP/Headers/User-Agent) is an HTTP request header that allows servers and networks to identify the From 6450900236b28d6021251aea33c4b5c24eb11697 Mon Sep 17 00:00:00 2001 From: Jecelyn Yeen <5917927+jecfish@users.noreply.github.com> Date: Tue, 26 Sep 2023 10:41:25 +0200 Subject: [PATCH 809/982] Update video link WNDT 116 (#7380) * Update video WNDT 116 * Update site/en/blog/new-in-devtools-116/index.md --------- Co-authored-by: Rachel Andrew <rachelandrew@google.com> --- site/en/blog/new-in-devtools-116/index.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/site/en/blog/new-in-devtools-116/index.md b/site/en/blog/new-in-devtools-116/index.md index 94fe19472..7844fc757 100644 --- a/site/en/blog/new-in-devtools-116/index.md +++ b/site/en/blog/new-in-devtools-116/index.md @@ -16,9 +16,7 @@ tags: {% Partial 'devtools/banner.md' %} -*There is no 'What's new in DevTools' video for this release, but you can watch this quick recap of the recent features.* - -{% YouTube id='e8tl_yp5BQg' %} +{% YouTube id='oMRpODeXzho' %} <!-- $contentStart --> From ea6bc7462d587e02e72502563a5286ff2c14735b Mon Sep 17 00:00:00 2001 From: Jecelyn Yeen <5917927+jecfish@users.noreply.github.com> Date: Tue, 26 Sep 2023 11:06:00 +0200 Subject: [PATCH 810/982] Update video link WNDT 117 (#7381) * Update video WNDT 117 * Update site/en/blog/new-in-devtools-117/index.md --------- Co-authored-by: Rachel Andrew <rachelandrew@google.com> --- site/en/blog/new-in-devtools-117/index.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/site/en/blog/new-in-devtools-117/index.md b/site/en/blog/new-in-devtools-117/index.md index 309f55a8e..f5b5f6bd5 100644 --- a/site/en/blog/new-in-devtools-117/index.md +++ b/site/en/blog/new-in-devtools-117/index.md @@ -16,9 +16,7 @@ tags: {% Partial 'devtools/banner.md' %} -*There is no 'What's new in DevTools' video for this release, but you can watch this quick recap of the recent features.* - -{% YouTube id='e8tl_yp5BQg' %} +{% YouTube id='oMRpODeXzho' %} <!-- $contentStart --> From 7770349adb7df729ebe3afd60ba36fcef6c6dfcf Mon Sep 17 00:00:00 2001 From: Silvia Eremia <145469313+silviaeremia7@users.noreply.github.com> Date: Tue, 26 Sep 2023 13:43:34 +0200 Subject: [PATCH 811/982] Add Silvia Eremia and Ioana Forfota (#7359) * Add Silvia Eremia and Ioana Forfota * Add Silvia Eremia and Ioana Forfota --- site/_data/authorsData.json | 12 ++++++++++++ site/_data/i18n/authors.yaml | 11 +++++++++++ 2 files changed, 23 insertions(+) diff --git a/site/_data/authorsData.json b/site/_data/authorsData.json index a69bd7519..fcb1d19a1 100644 --- a/site/_data/authorsData.json +++ b/site/_data/authorsData.json @@ -1921,5 +1921,17 @@ "ferreiram": { "twitter": "charca", "image": "image/1L2RBhCLSnXjCnSlevaDjy3vba73/2nczWyIuJperJ2qSEpA3.jpg" + }, + "silviaeremia7": { + "country": "DE", + "github": "silviaeremia7", + "linkedin": "silvia-eremia-432248234", + "image": "image/5eDxoIGI8JgwfKolhnOVPEVCaGu2/mBEutpRe3fn0X3FDAq3B.png" + }, + "iforfota7": { + "country": "DE", + "github": "iforfota7", + "linkedin": "ioana-forfota-41116b260", + "image": "image/5eDxoIGI8JgwfKolhnOVPEVCaGu2/ld1F0IaoJE3rFI2jlILo.png" } } diff --git a/site/_data/i18n/authors.yaml b/site/_data/i18n/authors.yaml index 655cc6d7b..da978137a 100644 --- a/site/_data/i18n/authors.yaml +++ b/site/_data/i18n/authors.yaml @@ -1572,3 +1572,14 @@ ferreiram: en: 'Maxi Ferreira' description: en: 'Creator, FrontendAtScale' +iforfota7: + title: + en: 'Ioana Forfota' + description: + en: 'STEP Intern, Chrome DevTools team' +silviaeremia7: + title: + en: 'Silvia Eremia' + description: + en: 'STEP Intern, Chrome DevTools team' + From ba8885e25515e426bab3ae6045add5693c8f90bb Mon Sep 17 00:00:00 2001 From: Joe Medley <jmedley@google.com> Date: Tue, 26 Sep 2023 12:23:25 -0700 Subject: [PATCH 812/982] Add date that was forgotten before (#7386) --- site/en/docs/extensions/whatsnew/index.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/site/en/docs/extensions/whatsnew/index.md b/site/en/docs/extensions/whatsnew/index.md index 523468b9e..ac23f8603 100644 --- a/site/en/docs/extensions/whatsnew/index.md +++ b/site/en/docs/extensions/whatsnew/index.md @@ -17,6 +17,8 @@ Check this page often to learn about changes to Chrome extensions, extensions do ### Chrome 118: Changes to opening file: scheme URLs {: #changes-to-file-scheme } +<p class="color-secondary-text type--caption">Posted on <time>September 15, 2023</time></p> + Beginning in Chrome 118, extensions will need the "Allow access to file URLs" setting enabled from the `chrome://extensions` page to open file:// scheme URLs using the [Tabs](/docs/extensions/reference/tabs/) or [Windows](/docs/extensions/reference/windows/) APIs. You can programmatically check for this access by calling [`chrome.extension.isAllowedFileSchemeAccess()`](/docs/extensions/reference/extension/#method-isAllowedFileSchemeAccess). Firefox already restricts file URLs, and Safari supports the change. For more information, read the [post in the extensions Google Group](https://groups.google.com/a/chromium.org/g/chromium-extensions/c/ZtCvVISQU54/m/tOjjlzkfAgAJ). ### Chrome 117: Expanded URL protections on extension API navigations {: #expanded-kill-url } From 8b9b38cd08f93a700d708b8f413e03980b843656 Mon Sep 17 00:00:00 2001 From: amysteamdev <37001393+AmySteam@users.noreply.github.com> Date: Tue, 26 Sep 2023 14:52:26 -0500 Subject: [PATCH 813/982] Remove old extensions samples page and redirect to new one (#7376) * Remove old samples page in favor of new one * Remove from TOC --- redirects.yaml | 4 ++ site/_data/docs/extensions/toc.yml | 1 - site/en/docs/extensions/mv3/samples/index.md | 75 -------------------- 3 files changed, 4 insertions(+), 76 deletions(-) delete mode 100644 site/en/docs/extensions/mv3/samples/index.md diff --git a/redirects.yaml b/redirects.yaml index 116cda086..000aaf135 100644 --- a/redirects.yaml +++ b/redirects.yaml @@ -648,6 +648,10 @@ redirects: - from: /docs/extensions/mv3/known-issues/ to: /docs/extensions/migrating/known-issues/ +# Extension samples +- from: /docs/extensions/mv3/samples/ + to: /docs/extensions/samples/ + # Redirects for docs now on MDN - from: /docs/web-platform/popover-api/backdrop-pseudo-element diff --git a/site/_data/docs/extensions/toc.yml b/site/_data/docs/extensions/toc.yml index 1f6c0c2b3..db475b053 100644 --- a/site/_data/docs/extensions/toc.yml +++ b/site/_data/docs/extensions/toc.yml @@ -44,7 +44,6 @@ - url: /docs/extensions/mv3/service_workers - url: /docs/extensions/mv3/user_interface - url: /docs/extensions/mv3/tut_debugging - - url: /docs/extensions/mv3/samples - title: i18n.docs.extensions.service_workers sections: - url: /docs/extensions/mv3/service_workers diff --git a/site/en/docs/extensions/mv3/samples/index.md b/site/en/docs/extensions/mv3/samples/index.md deleted file mode 100644 index 5b65e6a2b..000000000 --- a/site/en/docs/extensions/mv3/samples/index.md +++ /dev/null @@ -1,75 +0,0 @@ ---- -layout: "layouts/doc-post.njk" -title: "Samples" -seoTitle: "Chrome Extension examples" -date: 2020-12-11 -updated: 2023-02-03 -description: Intro to extension examples GitHub repository ---- - -## Overview {: #overview } - -The [Extensions sample GitHub -repository][gh-samples] provides examples of extensions that address various use cases and call appropriate Chrome -APIs. Use these to learn how extensions work or as a starting point for building your own extensions. - -## Browse by category {: #categories } - -The examples are currently located under the following directories: - -[api-samples/][gh-api] -: Extensions designed to demonstrate the capabilities of a specific API. For example, the [Action API example][gh-action] showcases extension UI elements such as the popup, tooltip, and badges among others. - -[functional-samples/sample...][gh-functional-samples] -: Complete extensions that implement all the basic features for a given purpose. - -[functional-samples/tutorial...][gh-functional-samples] -: Examples covered in the [tutorials][gs-tutorials]. A few examples include [Tabs manager][tut-tabs-man], [Focus mode][tut-fm], and [Reading time][tut-rt]. - -[functional-samples/cookbook...][gh-functional-samples] -: Examples demonstrating a particular concept. - -[functional-samples/reference...][gh-functional-samples] -: Examples linked to documentation on this site. - -{% Details %} -{% DetailsSummary %} -💡 **TIP**: How can I find examples of a particular API quickly? -{% endDetailsSummary %} - -To find all examples of a specific Chrome API use Github's search engine to look for "chrome.NAME_OF_API" in this repository. The following example searches for all uses of "chrome.tabs": - -<figure> -{% Img src="image/BhuKGJaIeLNPW9ehns59NfwqKxF2/2OW6hjG5RLoupNCzZk8u.png", alt="Searching for chrome.tabs in the extension Github repository", width="800", height="122", class="screenshot screenshot--filled" %} <figcaption> -<code>Chrome.tabs</code> search in the extension Github repository. - </figcaption> -</figure> - -{% endDetails %} - -## Try them out {: #testing } - -To test these examples in your local machine, follow these steps: - -1. Clone the repository. -1. Navigate to the directory of the extension you want to try. -1. [Load your extension locally][dev-basics-locally]. - -Many samples have a `README.md` with instructions on how the extension works. (We are working to add READMEs to all samples.) -Read the instructions carefully; each extension is different. For example, some extensions run by clicking on the extension icon, while others run automatically but only run on specific sites. - -## Contributing samples {: #collaborating } - -If you encounter any problems with an example, let us know by [posting an issue][gh-issues]. If you want to submit a new extension, check out the [Contributing Guide][gh-contributing] to find out how to submit a new example to this collection. - -[dev-basics-locally]: /docs/extensions/mv3/getstarted/development-basics/ -[gh-action]: https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/api-samples/action -[gh-api]: https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/api-samples -[gh-contributing]: https://github.com/GoogleChrome/chrome-extensions-samples/blob/main/CONTRIBUTING.md -[gh-issues]: https://github.com/GoogleChrome/chrome-extensions-samples/issues -[gh-samples]: https://github.com/GoogleChrome/chrome-extensions-samples -[gh-functional-samples]: https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/functional-samples -[gs-tutorials]: /docs/extensions/mv3/getstarted/#tutorial -[tut-fm]: /docs/extensions/mv3/getstarted/tut-focus-mode/ -[tut-rt]: /docs/extensions/mv3/getstarted/tut-reading-time/ -[tut-tabs-man]: /docs/extensions/mv3/getstarted/tut-tabs-manager/ From ecb29feb9128ab2949cde514e5bad66f6d6d8a6a Mon Sep 17 00:00:00 2001 From: Joe Medley <jmedley@google.com> Date: Tue, 26 Sep 2023 14:50:54 -0700 Subject: [PATCH 814/982] Refactor 'Improve extension security'. (#7247) * Refactor 'Improve extension security'. * Update site/en/docs/extensions/migrating/improve-security/index.md Co-authored-by: Sebastian Benz <sebastian.benz@gmail.com> * Fix bulleted list. * Update site/en/docs/extensions/migrating/improve-security/index.md Co-authored-by: amysteamdev <37001393+AmySteam@users.noreply.github.com> * Update site/en/docs/extensions/migrating/improve-security/index.md Co-authored-by: amysteamdev <37001393+AmySteam@users.noreply.github.com> --------- Co-authored-by: Sebastian Benz <sebastian.benz@gmail.com> Co-authored-by: amysteamdev <37001393+AmySteam@users.noreply.github.com> --- .../migrating/improve-security/index.md | 56 +++++++++++-------- 1 file changed, 34 insertions(+), 22 deletions(-) diff --git a/site/en/docs/extensions/migrating/improve-security/index.md b/site/en/docs/extensions/migrating/improve-security/index.md index f7241604e..f1edbbd97 100644 --- a/site/en/docs/extensions/migrating/improve-security/index.md +++ b/site/en/docs/extensions/migrating/improve-security/index.md @@ -4,6 +4,7 @@ title: Improve extension security subhead: 'Improving security in Manifest V3' description: 'The last of three sections describing changes needed for code that is not part of the extension service worker.' date: 2023-03-08 +updated: 2023-09-26 --- {% Partial 'extensions/mv3-support.md' %} @@ -17,7 +18,7 @@ You can no longer [execute external logic](/docs/extensions/mv3/intro/mv3-overvi - Move all external code (JS, Wasm, CSS) into your extension bundle. - Update script and style references to load resources from the extension bundle. - Use [`chrome.runtime.getURL()`](/docs/extensions/reference/runtime/#method-getURL) to build resource URLs at runtime. -- Use a sandboxed iframe: `eval` and `new Function(...)` are still supported in sandboxed iframes. For more details read the [guide on sandboxed iframes][sandbox-eval]. +- Use a sandboxed iframe: `eval` and `new Function(...)` are still supported in sandboxed iframes. For more details read the [guide on sandboxed iframes][sandbox-eval]. The `executeScript()` method is now in the [`scripting`](/docs/extensions/reference/scripting/) namespace rather than the `tabs` namespace. For information on updating calls, see [Move executeScript()](/docs/extensions/upgrade-to-mv3/update-code#move-executescript). @@ -29,36 +30,44 @@ There are a few special cases in which executing arbitrary strings is still poss ## Remove remotely hosted code {: #remove-remote-code } -In Manifest V3, all of your extension's logic must be part of the extension package. You can no longer load and execute remotely hosted files. Examples include: +In Manifest V3, all of your extension's logic must be part of the extension package. You can no longer load and execute remotely hosted files according to [Chrome Web Store policy](/docs/webstore/program-policies/mv3-requirements/). Examples include: - JavaScript files pulled from the developer's server. - Any library hosted on a [CDN][mdn-cdn]. +- Bundled third-party libraries that dynamically fetch remote hosted code. -Alternative approaches are available, depending on your use case and the reason for remote hosting. Here are approaches to consider: +Alternative approaches are available, depending on your use case and the reason for remote hosting. This section describes approaches to consider. -Configuration-driven features and logic -: Your extension loads and caches a remote configuration (for example a JSON file) at runtime. The cached configuration determines which features are enabled. +### Configuration-driven features and logic {: #configuration-drive } -Externalized logic with a remote service -: Your extension calls a remote web service. This lets you keep code private and change it as needed while avoiding the extra overhead of resubmitting to the Chrome Web Store. +Your extension loads and caches a remote configuration (for example a JSON file) at runtime. The cached configuration determines which features are enabled. -Embed remotely hosted code in a sandboxed iframe -: Remotely hosted code [is supported in sandboxed iframes][sandbox-eval]. However, this approach does not work if the code requires access to the embedding page's DOM. +### Externalized logic with a remote service {: #externalize-with-remote } -Bundle third-party libraries -: If you are using a popular framework like React or Bootstrap which you were previously loading from an external server, you can download the minified files, add them to your project and import them locally. For example: - ```html - <script src="./react-dom.production.min.js"></script> - <link href="./bootstrap.min.css" rel="stylesheet"> - ``` - In some cases, libraries, such as Firebase, will fetch additional code on a by need basis at runtime. In this case, you have to download all possible dynamic imports at build time. Here is an [example script that bundles Firebase using Rollup.js][firebase]. +Your extension calls a remote web service. This lets you keep code private and change it as needed while avoiding the extra overhead of resubmitting to the Chrome Web Store. -Look for other workarounds -: If the previous approaches don’t help with your use case you might have to either find an alternative solution (i.e. migrate to a different library) or find other ways to use the library's functionality. For example, in the case of Google Analytics, you can switch to the Google measurement protocol instead of using the official remote hosted JavaScript version as described in our [Google Analytics 4 guide][google-analytics]. +### Embed remotely hosted code in a sandboxed iframe {: #embed-in-sandbox } + +Remotely hosted code [is supported in sandboxed iframes][sandbox-eval]. Please note that this approach does not work if the code requires access to the embedding page's DOM. + +### Bundle third-party libraries {: #bundle-third-party } + +If you are using a popular framework such as React or Bootstrap that you were previously loading from an external server, you can download the minified files, add them to your project and import them locally. For example: + +```html +<script src="./react-dom.production.min.js"></script> +<link href="./bootstrap.min.css" rel="stylesheet"> +``` + +To include a library in a service worker set the []`"background.type"` key](/docs/extensions/mv3/manifest/background/) to `"module"` in the manifest and use an `import` statement. + +{% Aside 'caution' %} +Some libraries (Firebase, for example) fetch additional code as needed at runtime. You have two options for avoiding this. You can chose a library that does not use remotely-hosted code. You can also download all possible dynamic imports at build time. Here is an [example script that bundles Firebase using Rollup.js][firebase]. +{% endAside %} ### Use external libraries in tab-injected scripts {: #use-external-libraries } -External libraries may no longer be loaded remotely. They must be part of your extension bundle. Load them at runtime by adding them to the `files` array when calling `executeScript()`. You can still load data remotely at runtime. +You can also load external libraries at runtime by adding them to the `files` array when calling [`scripting.executeScript()`](/docs/extensions/reference/scripting/#method-executeScript). You can still load data remotely at runtime. ```js chrome.scripting.executeScript({ @@ -68,7 +77,7 @@ chrome.scripting.executeScript({ ``` ### Inject a function {: #inject-func } -If you need more dynamism, the new `func` property in `scripting.executeScript()` allows you to inject a function as a content script and pass variables using the `args` property. +If you need more dynamism, the new `func` property in `scripting.executeScript()` allows you to inject a function as a content script and pass variables using the `args` property. <div class="switcher"> {% Compare 'worse', 'Manifest V2' %} @@ -109,7 +118,11 @@ In the background service worker. {% endCompare %} </div> -The [Chrome Extension Samples repo](https://github.com/GoogleChrome/chrome-extensions-samples.git) contains a [function injection example](https://github.com/GoogleChrome/chrome-extensions-samples/blob/main/reference/mv3/intro/mv3-migration/content-scripts/popup.js) you can step through. An example of `getCurrentTab()` is in the [reference](/docs/extensions/reference/tabs/#get-the-current-tab) for that function. +The [Chrome Extension Samples repo](https://github.com/GoogleChrome/chrome-extensions-samples.git) contains a [function injection example](https://github.com/GoogleChrome/chrome-extensions-samples/blob/main/functional-samples/reference.mv3-content-scripts/popup.js) you can step through. An example of `getCurrentTab()` is in the [reference](/docs/extensions/reference/tabs/#get-the-current-tab) for that function. + +### Look for other workarounds {: #look-for-workarounds } + +If the previous approaches don’t help with your use case you might have to either find an alternative solution (i.e. migrate to a different library) or find other ways to use the library's functionality. For example, in the case of Google Analytics, you can switch to the Google measurement protocol instead of using the official remotely-hosted JavaScript version as described in our [Google Analytics 4 guide][google-analytics]. ## Update the content security policy {: #update-csp } @@ -169,4 +182,3 @@ Content security policy values for `sandbox` have no such new restrictions. [send-command]: /docs/extensions/reference/debugger/#method-sendCommand [firebase]: https://gist.github.com/patrickkettner/8c1a91b1b8f9502b3b67d874e7024a7b [google-analytics]: /docs/extensions/mv3/tut_analytics/ - From 5a0641182232181240106f3d9a75c7f8d4862fee Mon Sep 17 00:00:00 2001 From: Eiji Kitamura <agektmr@google.com> Date: Wed, 27 Sep 2023 16:03:05 +0900 Subject: [PATCH 815/982] =?UTF-8?q?Bulk=20update=20from=20'=E9=96=A2?= =?UTF-8?q?=E9=80=A3=E6=80=A7=E3=81=A8=E6=B8=AC=E5=AE=9A'=20to=20'?= =?UTF-8?q?=E5=BA=83=E5=91=8A=E9=96=A2=E9=80=A3'=20(#7368)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../index.md | 10 +++++----- .../index.md | 2 +- .../index.md | 10 +++++----- site/ja/blog/fledge-api/index.md | 6 +++--- site/ja/blog/fledge-service-overview/index.md | 6 +++--- .../ja/blog/generate-summary-reports/index.md | 2 +- .../index.md | 12 +++++------ .../index.md | 6 +++--- .../index.md | 12 +++++------ .../index.md | 14 ++++++------- .../ja/blog/shipping-privacy-sandbox/index.md | 20 +++++++++---------- .../attribution-reporting-experiment/index.md | 2 +- .../attribution-reporting-updates/index.md | 2 +- .../system-overview/index.md | 2 +- .../docs/privacy-sandbox/fledge-api/index.md | 6 +++--- .../fledge-experiment/index.md | 6 +++--- site/ja/docs/privacy-sandbox/fledge/index.md | 2 +- .../topics-experiment/index.md | 6 +++--- site/ja/docs/privacy-sandbox/topics/index.md | 2 +- 19 files changed, 64 insertions(+), 64 deletions(-) diff --git a/site/ja/blog/announce-enrollment-privacy-sandbox/index.md b/site/ja/blog/announce-enrollment-privacy-sandbox/index.md index 8aae15178..3048d6c43 100644 --- a/site/ja/blog/announce-enrollment-privacy-sandbox/index.md +++ b/site/ja/blog/announce-enrollment-privacy-sandbox/index.md @@ -1,8 +1,8 @@ --- layout: layouts/blog-post.njk title: プライバシー サンドボックスの開発者登録 -description: 開発者のアイデンティティを確認し、Chrome と Android におけるプライバシーサンドボックスの関連性と測定 API の構成情報を収集するための新しいプロセスについて。 -subtitle: Chrome と Android におけるプライバシーサンドボックスの関連性と測定 API への新しい開発者登録プロセスを発表します。 +description: 開発者のアイデンティティを確認し、Chrome と Android におけるプライバシーサンドボックスの広告関連 API の構成情報を収集するための新しいプロセスについて。 +subtitle: Chrome と Android におけるプライバシーサンドボックスの広告関連 API への新しい開発者登録プロセスを発表します。 date: 2023-04-13 hero: image/VbsHyyQopiec0718rMq2kTE1hke2/Y7LA3AUuZmhBjHfNlNsq.jpg alt: プライバシー サンドボックスへの登録。 @@ -12,7 +12,7 @@ tags: - privacy --- -アトリビューション レポート、FLEDGE、Topics、プライベート集計、共有ストレージといったプライバシーサンドボックスの関連性と測定 API の一般提供を計画するに際し、これらのテクノロジーが意図したとおりに透明性を持って使用されることを保証したいと考えています。本日、Chrome と Android でのプライバシーサンドボックスの関連性と測定 API の新しい開発者登録プロセスを発表しました。このプロセスは、現在のプライバシーサンドボックスの Android 登録プロセスに置き換わります。 +アトリビューション レポート、FLEDGE、Topics、プライベート集計、共有ストレージといったプライバシーサンドボックスの広告関連 API の一般提供を計画するに際し、これらのテクノロジーが意図したとおりに透明性を持って使用されることを保証したいと考えています。本日、Chrome と Android でのプライバシーサンドボックスの広告関連 API の新しい開発者登録プロセスを発表しました。このプロセスは、現在のプライバシーサンドボックスの Android 登録プロセスに置き換わります。 登録プロセスでは、API を呼び出すエンティティを確認し、これらの API を適切に構成して使用するために必要なデータを収集します。 @@ -26,7 +26,7 @@ tags: 監査可能な透明性を提供するために、会社に関する登録情報が公開されます。一般ユーザーがこの情報にアクセスする方法については、今後のアップデートで詳細をお知らせします。 -API 呼び出し元が受け取ることができるデータの量を制限するために、関連性と測定 API に各開発者のレート制限をすでに組み込んでいます。登録により、独立したサードパーティの検証サービスを使用して、これらのレート制限をより適切に適用できます。 企業のアイデンティティと潜在的な企業関係の確認には、Dun & Bradstreet を起用します。 +API 呼び出し元が受け取ることができるデータの量を制限するために、広告関連 API に各開発者のレート制限をすでに組み込んでいます。登録により、独立したサードパーティの検証サービスを使用して、これらのレート制限をより適切に適用できます。 企業のアイデンティティと潜在的な企業関係の確認には、Dun & Bradstreet を起用します。 この確認プロセスは、ある開発者が別の開発者になりすまして API の使用を制限できないようにするのにも役立ちます。最後に、この取り組みにより、プライバシー サンドボックスの Chrome と Android のエコシステムに共通の登録プロセスが採用されるため、プラットフォーム間で確認作業を繰り返す必要がなくなります。 @@ -47,7 +47,7 @@ API 呼び出し元が受け取ることができるデータの量を制限す すべての API 呼び出し元は、[サイト](https://web.dev/same-site-same-origin/#public-suffix-list-and-etld)を登録する必要があります。サイトは、プライバシーサンドボックス API のプライバシー保護を通知する境界を提供します。 -{% Aside %} この登録は、1 つ以上のプライバシーサンドボックスの関連性と測定 API を呼び出す企業にのみ適用されます。アドテックの顧客であるサイト運営者やその他の企業は、登録する必要はありません。 {% endAside %} +{% Aside %} この登録は、1 つ以上のプライバシーサンドボックスの広告関連 API を呼び出す企業にのみ適用されます。アドテックの顧客であるサイト運営者やその他の企業は、登録する必要はありません。 {% endAside %} 登録は、独立した事業部門または製品に合わせて行う必要があります。レート制限を共有しないエンティティが複数ある場合は、独立したサイトごとに登録を申し込むことができます。API の呼び出しに使用されるオリジンは、登録のサイト境界内にある必要があります。 diff --git a/site/ja/blog/bidding-and-auction-services-availability/index.md b/site/ja/blog/bidding-and-auction-services-availability/index.md index 19fc5c4b0..529040061 100644 --- a/site/ja/blog/bidding-and-auction-services-availability/index.md +++ b/site/ja/blog/bidding-and-auction-services-availability/index.md @@ -35,7 +35,7 @@ FLEDGE の採用と提供規模が拡大し続けているため、先日、オ Chrome の入札およびオークションサービスは、2023 年半ばまでにテスト向けに提供され、2023 年末までには規模が拡大されます。これにより、[privacysandbox.com](https://privacysandbox.com/open-web/#the-privacy-sandbox-timeline) で共有されているサードパーティ Cookie の廃止に関わる Chrome のタイムラインが影響されることはありません。 -アドテックは、[関連性と測定の統合オリジントライアル](/docs/privacy-sandbox/unified-origin-trial/)で、FLEDGE API の上に構築されたソリューションの設計とデプロイを継続することをお勧めします。入札サービスとオークションサービスは、これらのソリューションに統合され、ほぼドロップイン置換ソリューションとして拡張される予定です。 +アドテックは、[広告関連の統合オリジントライアル](/docs/privacy-sandbox/unified-origin-trial/)で、FLEDGE API の上に構築されたソリューションの設計とデプロイを継続することをお勧めします。入札サービスとオークションサービスは、これらのソリューションに統合され、ほぼドロップイン置換ソリューションとして拡張される予定です。 [コンポーネントオークション](https://github.com/privacysandbox/fledge-docs/blob/main/bidding_auction_services_api.md#types-of-auctions)と同じ機能をサポートする設計を含む、[シングルセラーおよびマルチセラーオークション](https://github.com/WICG/turtledove/blob/main/FLEDGE.md#21-initiating-an-on-device-auction)をサポートするための入札およびオークションサービスを計画しています。これらは、2023 年半ばまでにテスト向けに提供され、2023 年末までには規模を拡大したテスト向けに提供されるようになります。 diff --git a/site/ja/blog/expanding-privacy-sandbox-testing/index.md b/site/ja/blog/expanding-privacy-sandbox-testing/index.md index 690903c8f..0567d2831 100644 --- a/site/ja/blog/expanding-privacy-sandbox-testing/index.md +++ b/site/ja/blog/expanding-privacy-sandbox-testing/index.md @@ -1,7 +1,7 @@ --- title: プライバシーサンドボックステストの拡大 description: > - プライバシーサンドボックスのタイムラインの変更に伴い、プライバシーサンドボックスの関連性と測定オリジントライアルの範囲拡大と期間延長、および API の今後の展開を形作るためのテスト方法とフィードバックの提供方法について学びます。 + プライバシーサンドボックスのタイムラインの変更に伴い、プライバシーサンドボックスの広告関連オリジントライアルの範囲拡大と期間延長、および API の今後の展開を形作るためのテスト方法とフィードバックの提供方法について学びます。 layout: 'layouts/blog-post.njk' date: 2022-07-27 authors: @@ -14,7 +14,7 @@ tags: - privacy --- -今日、[ウェブのプライバシーサンドボックスとサードパーティ Cookie の段階的廃止過程に関する最新の計画とタイムライン](https://blog.google/products/chrome/update-testing-privacy-sandbox-web/)が公開されました。 **ウェブ開発者やサイト所有者からのフィードバック**は、提案の整理に時間をかけ、新しいソリューションをテスト、統合、最適化する十分な機会を確保することの重要性を示すうえで有益です。 この記事では、プライバシーサンドボックスの関連性と測定の統合オリジントライアルの 8 月のテスト計画について、トラフィック量を増やし、トライアル期間を延長する意図を含め、詳しく説明します。 +今日、[ウェブのプライバシーサンドボックスとサードパーティ Cookie の段階的廃止過程に関する最新の計画とタイムライン](https://blog.google/products/chrome/update-testing-privacy-sandbox-web/)が公開されました。 **ウェブ開発者やサイト所有者からのフィードバック**は、提案の整理に時間をかけ、新しいソリューションをテスト、統合、最適化する十分な機会を確保することの重要性を示すうえで有益です。 この記事では、プライバシーサンドボックスの広告関連の統合オリジントライアルの 8 月のテスト計画について、トラフィック量を増やし、トライアル期間を延長する意図を含め、詳しく説明します。 {% Aside %} @@ -29,9 +29,9 @@ tags: 現在の状況を細かく見ながら、引き続きテストを行い、フィードバックを提供し、機能の公開に向けた準備を進める上で必要となる情報を確認しましょう。 -## プライバシーサンドボックスの関連性と測定のオリジントライアルの拡大 +## プライバシーサンドボックスの広告関連のオリジントライアルの拡大 -[プライバシーサンドボックスの関連性と測定のオリジントライアル](/blog/privacy-sandbox-unified-origin-trial/)では、[アトリビューション レポート](/docs/privacy-sandbox/attribution-reporting/)、[FLEDGE](/docs/privacy-sandbox/fledge/)、 [Topics](/docs/privacy-sandbox/topics/)、[Fenced Frame](/docs/privacy-sandbox/fenced-frame/) を統合してそれらの技術的安定性と開発者エクスペリエンスをエコシステムでテストできます。[共有ストレージ](/docs/privacy-sandbox/shared-storage/)については、まもなく追加される予定です。 このトライアルは、現在、[Chrome ベータユーザーの 50% で有効](https://groups.google.com/a/chromium.org/g/blink-dev/c/Vi-Rj37aZLs/m/NTItmgLMAQAJ)になっているため、ユーザーを混乱させ過ぎることなく、初期の開発者からのフィードバックやイシューに積極的に取り組むのに役立っています。 +[プライバシーサンドボックスの広告関連のオリジントライアル](/blog/privacy-sandbox-unified-origin-trial/)では、[アトリビューション レポート](/docs/privacy-sandbox/attribution-reporting/)、[FLEDGE](/docs/privacy-sandbox/fledge/)、 [Topics](/docs/privacy-sandbox/topics/)、[Fenced Frame](/docs/privacy-sandbox/fenced-frame/) を統合してそれらの技術的安定性と開発者エクスペリエンスをエコシステムでテストできます。[共有ストレージ](/docs/privacy-sandbox/shared-storage/)については、まもなく追加される予定です。 このトライアルは、現在、[Chrome ベータユーザーの 50% で有効](https://groups.google.com/a/chromium.org/g/blink-dev/c/Vi-Rj37aZLs/m/NTItmgLMAQAJ)になっているため、ユーザーを混乱させ過ぎることなく、初期の開発者からのフィードバックやイシューに積極的に取り組むのに役立っています。 オリジントライアルが進むにつれて、実際のトラフィックの有意義な割合で、API の有用性と有効性をテストする機会を開発者に提供したいと考えています。 [8 月初めの Chrome 104 安定版 のリリース](https://chromiumdash.appspot.com/schedule)により、**トライアルを Chrome 安定版 を使用するデスクトップユーザーに拡大** する予定です。 モバイルユーザーにおいては、Android 版の [Chrome 105 安定版](https://chromiumdash.appspot.com/schedule) からトライアルが拡大される予定です。 現在オリジントライアルは、104 安定版 期間終了時にの終わる予定です。そこで、それ以降でもテストを続けられるように、[Chrome 107(10 月後半)](https://chromiumdash.appspot.com/schedule) までの **[延長を申請](https://groups.google.com/a/chromium.org/g/blink-dev/c/SD8Ot2gpz4g/m/Cc0TGPhoAAAJ)しています。** これは、3 マイルストーンごとのオリジントライアルの延長の申請に関する標準手続きに従うものです。 Google は、API の一般公開まで、テストをサポートすることを約束しています。 @@ -39,7 +39,7 @@ tags: {% Aside %} -* [はじめに: プライバシーサンドボックスの関連性と測定のオリジントライアル](/blog/privacy-sandbox-unified-origin-trial/) +* [はじめに: プライバシーサンドボックスの広告関連のオリジントライアル](/blog/privacy-sandbox-unified-origin-trial/) * [開発者ガイド: アトリビューション レポート](/docs/privacy-sandbox/attribution-reporting-experiment/) * [開発者ガイド: FLEDGE](/docs/privacy-sandbox/fledge-experiment/) * [開発者ガイド: Topics API](/docs/privacy-sandbox/topics-experiment/) diff --git a/site/ja/blog/fledge-api/index.md b/site/ja/blog/fledge-api/index.md index 4bd442e39..a61a8ea68 100644 --- a/site/ja/blog/fledge-api/index.md +++ b/site/ja/blog/fledge-api/index.md @@ -50,7 +50,7 @@ FLEDGE は、[TURTLEDOVE](https://github.com/WICG/turtledove) ファミリの提 ### FLEDGE オリジントライアルに参加する {: #origin-trial} -プライバシーサンドボックスの関連性と測定の[オリジントライアル](/blog/origin-trials/)は、FLEDGE、[Topics](/docs/privacy-sandbox/topics/)、および[Attribution Reporting](/docs/privacy-sandbox/attribution-reporting/) API について、デスクトップの Chrome ベータ版 101.0.4951.26 以降で公開されています。 +プライバシーサンドボックスの広告関連の[オリジントライアル](/blog/origin-trials/)は、FLEDGE、[Topics](/docs/privacy-sandbox/topics/)、および[Attribution Reporting](/docs/privacy-sandbox/attribution-reporting/) API について、デスクトップの Chrome ベータ版 101.0.4951.26 以降で公開されています。 参加するには、[オリジントライアル トークンに登録](/origintrials/#/view_trial/771241436187197441)してください。 @@ -83,9 +83,9 @@ FLEDGE API コードを実行するすべてのページにトライアルトー {% Aside 'caution' %} -有効なトライアルトークンを提供するページであっても、すべてのユーザーがプライバシーサンドボックスの関連性と測定のオリジントライアルの対象となるわけではありません。 +有効なトライアルトークンを提供するページであっても、すべてのユーザーがプライバシーサンドボックスの広告関連のオリジントライアルの対象となるわけではありません。 -[プライバシーサンドボックス広告の関連性と測定 API をテストする](/blog/privacy-sandbox-unified-origin-trial#eligible-users)にはその理由が説明されており、オリジントライアル機能を使用する前に使用可能かどうかを検出する方法(検出する必要があります)が示されています。 +[プライバシーサンドボックス広告関連 API をテストする](/blog/privacy-sandbox-unified-origin-trial#eligible-users)にはその理由が説明されており、オリジントライアル機能を使用する前に使用可能かどうかを検出する方法(検出する必要があります)が示されています。 {% endAside %} diff --git a/site/ja/blog/fledge-service-overview/index.md b/site/ja/blog/fledge-service-overview/index.md index 5f28ad6e7..748098daa 100644 --- a/site/ja/blog/fledge-service-overview/index.md +++ b/site/ja/blog/fledge-service-overview/index.md @@ -34,7 +34,7 @@ FLEDGE はアプリとウェブ向けに構築されているため、サービ 本番環境で FLEDGE をテストしている場合は、**[Key-Value サービス](#key-value-service)** についてよく理解していると思います。この提案は、クラウド実装のための新しい信頼モデルとして更新されました。「Bring Your Own Server」モデルに精通している場合には、[移行方法の詳細とタイムラインの更新](#byos-to-tee)をご覧ください。 -2 つ目のサービスは、FLEDGE の傘下で新たに提案された **[入札・オークション サービス](#bidding-auction-service)** です。この新しい提案では、広告オークションと入札サービスのプライバシーを保護しながら、入札と広告オークションをクライアントからクラウドにオフロードします。新しい入札およびオークション サービスのアイデアと現在のオンデバイス デザインとの比較についてのフィードバックをお待ちしております。特に、進行中の Chrome 広告の関連性と測定のオリジントライアルの一環として、すでに経験を積んでいるテスターからのフィードバックをお待ちしております。この提案は、[提案ライフ サイクルのディスカッションの段階](/docs/privacy-sandbox/proposal-lifecycle/)にあります。入札・オークションサービスは、「Bring Your Own Server」モデルの対象外です。 +2 つ目のサービスは、FLEDGE の傘下で新たに提案された **[入札・オークション サービス](#bidding-auction-service)** です。この新しい提案では、広告オークションと入札サービスのプライバシーを保護しながら、入札と広告オークションをクライアントからクラウドにオフロードします。新しい入札およびオークション サービスのアイデアと現在のオンデバイス デザインとの比較についてのフィードバックをお待ちしております。特に、進行中の Chrome 広告関連のオリジントライアルの一環として、すでに経験を積んでいるテスターからのフィードバックをお待ちしております。この提案は、[提案ライフ サイクルのディスカッションの段階](/docs/privacy-sandbox/proposal-lifecycle/)にあります。入札・オークションサービスは、「Bring Your Own Server」モデルの対象外です。 ### Key-Value サービス {: #key-value-service } @@ -53,7 +53,7 @@ TEE ベースの [FLEDGE Key-Value サービス](https://github.com/WICG/turtled {% Aside %} これは議論中の新しい提案であり、**現在の FLEDGE のオンデバイス入札とオークションのアプローチは変更されていません**。入札・オークションサービスは、必要に応じて入札とオークションの計算を信頼できる実行環境(TEE)にオフロードするための補完的な提案です。 -皆様からの[フィードバックをお待ちしております](#engage-and-share-feedback)。特に、[広告の関連性と測定のオリジントライアル](/blog/privacy-sandbox-unified-origin-trial/)に参加しているテスターからのフィードバックをお待ちしております。 {% endAside %} +皆様からの[フィードバックをお待ちしております](#engage-and-share-feedback)。特に、[広告の広告関連のオリジントライアル](/blog/privacy-sandbox-unified-origin-trial/)に参加しているテスターからのフィードバックをお待ちしております。 {% endAside %} FLEDGE の提案では、広告の入札とオークションの実行をオンデバイスで行うことが提案されています。 @@ -113,7 +113,7 @@ BYOS モデルを実装したアドテックプラットフォームは、FLEDGE - **GitHub**: - [FLEDGE サービスの提案](https://github.com/privacysandbox/fledge-docs/blob/main/trusted_services_overview.md)を読み、[質問を投稿したり、ディスカッションを閲覧](https://github.com/privacysandbox/fledge-docs/issues)したりできます。 - - [入札・オークションサービスの提案](https://github.com/privacysandbox/fledge-docs/blob/main/bidding_auction_services_api.md)を読み、[質問を投稿したり、ディスカッションを閲覧したり](https://github.com/privacysandbox/fledge-docs/issues)できます。特に、広告の関連性と測定のオリジントライアルの参加者からの意見をお待ちしております。現在のオンデバイス設計と比較して、この提案をどう思いますか? + - [入札・オークションサービスの提案](https://github.com/privacysandbox/fledge-docs/blob/main/bidding_auction_services_api.md)を読み、[質問を投稿したり、ディスカッションを閲覧したり](https://github.com/privacysandbox/fledge-docs/issues)できます。特に、広告関連のオリジントライアルの参加者からの意見をお待ちしております。現在のオンデバイス設計と比較して、この提案をどう思いますか? - **W3C**: [Improving Web Advertising Business Group](https://www.w3.org/community/web-adv/participants) では業界のユースケースについて、Web Platform Incubation Community Group の [FLEDGE GitHub リポジトリと定期ミーティング](https://github.com/WICG/turtledove/issues/88)では FLEDGE 設計について話し合えます。 - **開発者サポート**: 以下の場所では質問を投稿したり、ディスカッションに参加したりできます。 - [Privacy Sandbox for the Web Developer Support リポジトリ](https://github.com/GoogleChromeLabs/privacy-sandbox-dev-support) diff --git a/site/ja/blog/generate-summary-reports/index.md b/site/ja/blog/generate-summary-reports/index.md index e681f7c86..f1439253a 100644 --- a/site/ja/blog/generate-summary-reports/index.md +++ b/site/ja/blog/generate-summary-reports/index.md @@ -32,7 +32,7 @@ tags: 初期実装とオリジントライアルにおいては、アドテックは[ローカルテスト](https://github.com/google/trusted-execution-aggregation-service/#set-up-local-testing)をセットアップするか、[Amazon Web Services(AWS)を使用した TEE でテスト](https://github.com/google/trusted-execution-aggregation-service/#test-on-aws-with-support-for-encrypted-reports)できます。 -1. プライバシーサンドボックスの関連性と測定のオリジントライアル(OT)に[登録](/origintrials/#/view_trial/771241436187197441)します。 +1. プライバシーサンドボックスの広告関連のオリジントライアル(OT)に[登録](/origintrials/#/view_trial/771241436187197441)します。 2. [Amazon Web Services アカウント](https://portal.aws.amazon.com/gp/aws/developer/registration/index.html)を作成するか、用意します。 3. 集計サービスの[オンボーディング フォーム](https://forms.gle/EHoecersGKhpcLPNA)に記入します。このフォームに入力すると、登録確認と集計サービスのセットアップ手順が記載されたメールが届きます。 diff --git a/site/ja/blog/privacy-sandbox-origin-trial-increase/index.md b/site/ja/blog/privacy-sandbox-origin-trial-increase/index.md index 80e868364..bb5f77226 100644 --- a/site/ja/blog/privacy-sandbox-origin-trial-increase/index.md +++ b/site/ja/blog/privacy-sandbox-origin-trial-increase/index.md @@ -1,9 +1,9 @@ --- -title: プライバシーサンドボックスの関連性と測定のオリジントライアルを 5% に引き上げ +title: プライバシーサンドボックスの広告関連のオリジントライアルを 5% に引き上げ description: > - 今週 10 月 26 日までに、プライバシーサンドボックスの関連性と測定のオリジントライアルの人口を Chrome 安定版ユーザーの 5% まで引き上げる作業を開始します。 + 今週 10 月 26 日までに、プライバシーサンドボックスの広告関連のオリジントライアルの人口を Chrome 安定版ユーザーの 5% まで引き上げる作業を開始します。 subhead: > - 今週 10 月 26 日までに、プライバシーサンドボックスの関連性と測定のオリジントライアルの人口を Chrome 安定版ユーザーの 5% まで引き上げる作業を開始します。 + 今週 10 月 26 日までに、プライバシーサンドボックスの広告関連のオリジントライアルの人口を Chrome 安定版ユーザーの 5% まで引き上げる作業を開始します。 layout: layouts/blog-post.njk date: 2022-10-24 updated: 2023-01-05 @@ -16,9 +16,9 @@ tags: - privacy --- -{% Aside %} **[関連性と測定の統一オリジントライアル](/docs/privacy-sandbox/unified-origin-trial/)に関する最新のガイダンスをご覧ください。** {% endAside %} +{% Aside %} **[広告関連の統一オリジントライアル](/docs/privacy-sandbox/unified-origin-trial/)に関する最新のガイダンスをご覧ください。** {% endAside %} -今週 10 月 26 日までに、プライバシーサンドボックスの関連性と測定のオリジントライアル人口を Chrome 安定版ユーザーの 5%に引き上げる作業を開始します。制限の引き上げには、常に段階的なアプローチを取っており、Chrome オリジントライアルのイシューを積極的に監視しています。トラフィックレベルの増加は数日間で完了することが予想されます。安定版前のチャンネル、Canary および Beta は、オリジントライアルの適格性を 50/50 に分割して、そのまま継続します。 +今週 10 月 26 日までに、プライバシーサンドボックスの広告関連のオリジントライアル人口を Chrome 安定版ユーザーの 5%に引き上げる作業を開始します。制限の引き上げには、常に段階的なアプローチを取っており、Chrome オリジントライアルのイシューを積極的に監視しています。トラフィックレベルの増加は数日間で完了することが予想されます。安定版前のチャンネル、Canary および Beta は、オリジントライアルの適格性を 50/50 に分割して、そのまま継続します。 実際の運用環境での機能テストを可能にするために[、8 月に Chrome 安定版にトライアルを導入しました](/blog/expanding-privacy-sandbox-testing/)。その結果、API の安定性、開発者向けドキュメント、およびサポートを改善することができました。2022 年まで機能テストを継続し、2023 年のユーティリティテストに備えるために、このテストの規模を 5% に増加しています。 @@ -36,7 +36,7 @@ tags: ## オリジントライアルへの参加を制御する -[専用のオリジントライアルドキュメント](/docs/privacy-sandbox/unified-origin-trial/)で、プライバシーサンドボックスの関連性と測定のオリジントライアルに参加する方法をご覧ください。 +[専用のオリジントライアルドキュメント](/docs/privacy-sandbox/unified-origin-trial/)で、プライバシーサンドボックスの広告関連のオリジントライアルに参加する方法をご覧ください。 オリジントライアルの仕組みは変わりません。API を試したいコンテキストのオリジントライアルトークンを取得します。テスト人口が拡大したため、トライアルを有効にすることを選択したトラフィックのレベルを積極的に監視し、確実に制御することが必要です。 diff --git a/site/ja/blog/privacy-sandbox-unified-origin-trial/index.md b/site/ja/blog/privacy-sandbox-unified-origin-trial/index.md index 9a6d9f456..e147643cd 100644 --- a/site/ja/blog/privacy-sandbox-unified-origin-trial/index.md +++ b/site/ja/blog/privacy-sandbox-unified-origin-trial/index.md @@ -1,6 +1,6 @@ --- -title: プライバシーサンドボックス広告の関連性と測定 API をテストする -description: プライバシーサンドボックスの関連性と測定の API(Topics、FLEDGE、アトリビューション レポート)を統括して実験するための開発者テストと今後のオリジントライアルについて説明します。 +title: プライバシーサンドボックス広告関連 API をテストする +description: プライバシーサンドボックスの広告関連の API(Topics、FLEDGE、アトリビューション レポート)を統括して実験するための開発者テストと今後のオリジントライアルについて説明します。 layout: layouts/blog-post.njk date: 2022-03-31 updated: 2022-06-27 @@ -33,7 +33,7 @@ tags: ## 開発者がオリジントライアルに登録する方法 -[プライバシーサンドボックスの関連性と測定](/origintrials/#/view_trial/771241436187197441)のトライアルに登録します。以下の HTML タグを使用して、API コードを実行するすべてのページにトライアルトークンを提供します。 +[プライバシーサンドボックスの広告関連](/origintrials/#/view_trial/771241436187197441)のトライアルに登録します。以下の HTML タグを使用して、API コードを実行するすべてのページにトライアルトークンを提供します。 - トップレベル ページの `<head>` セクションの `<meta>`タグ: `<meta http-equiv="origin-trial" content="TOKEN_GOES_HERE">` - トップレベル ページのレスポンスの HTTP ヘッダー: `Origin-Trial: TOKEN_GOES_HERE` diff --git a/site/ja/blog/progress-in-the-privacy-sandbox-2022-04/index.md b/site/ja/blog/progress-in-the-privacy-sandbox-2022-04/index.md index c64a56d2e..740e3ae43 100644 --- a/site/ja/blog/progress-in-the-privacy-sandbox-2022-04/index.md +++ b/site/ja/blog/progress-in-the-privacy-sandbox-2022-04/index.md @@ -1,7 +1,7 @@ --- title: プライバシーサンドボックスの進捗状況(2022 年 3 月~4 月) description: > - オリジントライアルで利用可能な多数の API を含む更新: プライバシーサンドボックスの関連性と測定の複合トライアルの一環としての分割した Cookie の CHIPS と アトリビューション レポート、FLEDGE、および Topics。 + オリジントライアルで利用可能な多数の API を含む更新: プライバシーサンドボックスの広告関連の複合トライアルの一環としての分割した Cookie の CHIPS と アトリビューション レポート、FLEDGE、および Topics。 layout: 'layouts/blog-post.njk' date: 2022-05-17 authors: @@ -17,7 +17,7 @@ tags: 今年最初の「**[プライバシーサンドボックスの進捗状況](/tags/progress-in-the-privacy-sandbox/)**」へようこそ。Chrome におけるサードパーティ Cookie の段階的廃止とよりプライベートなウェブに向けた取り組みについて、2022 年 3 月と 4 月のマイルストーンの達成状況をお知らせします。 各エディションでは、[プライバシーサンドボックスのタイムライン](https://privacysandbox.com/open-web/#the-privacy-sandbox-timeline)の更新の概要を、プロジェクト全体の最新情報とともに提供しています。 -## プライバシーサンドボックスの関連性と測定のオリジントライアル +## プライバシーサンドボックスの広告関連のオリジントライアル 引き続き、初期の開発者フィードバックとそのフィードバックに基づいて提案を発展させる能力を最優先事項としています。 **アトリビューション レポート、FLEDGE、および Topics を合わせた複合オリジントライアル**を開始することで、実際の環境でこれらの API に関する初期フィードバックを得られるようにしました。 @@ -92,7 +92,7 @@ User-Agent Client Hints においても、[GREASE の動作を更新する I2S]( Fenced Frame(`<fencedframe>`)は、埋め込みコンテンツ用に提案されている HTML 要素で、iframe に似ています。 ただし、Fenced Frame は、埋め込みコンテキストとの 通信を制限して、フレームが埋め込みコンテキストと共有せずにクロスサイトデータにアクセスできるようにする点で、iframe とは異なります。 たとえば、FLEDGE では、Fenced Frame 内に広告を表示することを意図しています。 -[新しい開発者概要の内容](/docs/privacy-sandbox/fenced-frame/)をお読みください。また、Chrome 102 Beta より、より広範なプライバシーサンドボックスの関連性と測定のオリジントライアルの一環として [Fenced Frames を利用できるようにする I2E](https://groups.google.com/a/chromium.org/g/blink-dev/c/y6G3cvKXjlg)を送信しました。 +[新しい開発者概要の内容](/docs/privacy-sandbox/fenced-frame/)をお読みください。また、Chrome 102 Beta より、より広範なプライバシーサンドボックスの広告関連のオリジントライアルの一環として [Fenced Frames を利用できるようにする I2E](https://groups.google.com/a/chromium.org/g/blink-dev/c/y6G3cvKXjlg)を送信しました。 ## 関連するコンテンツと広告の表示 @@ -102,14 +102,14 @@ Fenced Frame(`<fencedframe>`)は、埋め込みコンテンツ用に提案 ### Topics -[Topics API](/docs/privacy-sandbox/topics/) は、クロスサイトトラッキングを使用せずに、インタレストベース広告を可能にする提案です。 プライバシーサンドボックスの関連性と測定のオリジントライアルの一環として [Topics を含める I2E](https://groups.google.com/a/chromium.org/g/blink-dev/c/oTwd6VwCwqs) を送信しました。 また、オリジントライアル中には、[Topics のテストとフィードバックの提供に関する新しい開発者ガイド](/docs/privacy-sandbox/topics-experiment/)もご利用いただけます。 +[Topics API](/docs/privacy-sandbox/topics/) は、クロスサイトトラッキングを使用せずに、インタレストベース広告を可能にする提案です。 プライバシーサンドボックスの広告関連のオリジントライアルの一環として [Topics を含める I2E](https://groups.google.com/a/chromium.org/g/blink-dev/c/oTwd6VwCwqs) を送信しました。 また、オリジントライアル中には、[Topics のテストとフィードバックの提供に関する新しい開発者ガイド](/docs/privacy-sandbox/topics-experiment/)もご利用いただけます。 これは早期のテスト段階であるため、コード内にイシューが見つかるたびに、それらを積極的に調査して対処しています。 Topics では、クラッシュするバグが発見されたため、オリジントライアル内で API を一時的に無効にし、ユーザーエクスペリエンスに過大な影響を与えることなく、修正をロールアウトしています。 ### FLEDGE -[FLEDGE](/docs/privacy-sandbox/fledge/) は、個人の識別子に依存することなく、以前にアクセスしたサイトまたは製品を利用できる広告を実行することで、リマーケティングとカスタムオーディエンスのユースケースを実現します。 より広範なプライバシーサンドボックスの関連性と測定のオリジントライアルの一環として有効にするために、[FLEDGE の I2E](https://groups.google.com/a/chromium.org/g/blink-dev/c/0VmMSsDWsFg) をもう一度送信しました。 同様に、これに対応する[実験用の開発者ドキュメントも提供](/docs/privacy-sandbox/fledge-experiment/)されています。 +[FLEDGE](/docs/privacy-sandbox/fledge/) は、個人の識別子に依存することなく、以前にアクセスしたサイトまたは製品を利用できる広告を実行することで、リマーケティングとカスタムオーディエンスのユースケースを実現します。 より広範なプライバシーサンドボックスの広告関連のオリジントライアルの一環として有効にするために、[FLEDGE の I2E](https://groups.google.com/a/chromium.org/g/blink-dev/c/0VmMSsDWsFg) をもう一度送信しました。 同様に、これに対応する[実験用の開発者ドキュメントも提供](/docs/privacy-sandbox/fledge-experiment/)されています。 ## デジタル広告の測定 @@ -119,7 +119,7 @@ Fenced Frame(`<fencedframe>`)は、埋め込みコンテンツ用に提案 ### Attribution Reporting API -**[Attribution Reporting API](/docs/privacy-sandbox/attribution-reporting/)** は、広告のクリックや閲覧といった、別のサイトでのコンバージョンにつながるイベントを、クロスサイトトラッキングを有効にせずに測定できる機能を有効にします。 これについても、プライバシーサンドボックスの関連性と測定のオリジントライアルの一環としてテストを拡張し続けるための、[アトリビューション レポート の I2E](https://groups.google.com/a/chromium.org/g/blink-dev/c/jEnNpideO1Y) を送信しました。 +**[Attribution Reporting API](/docs/privacy-sandbox/attribution-reporting/)** は、広告のクリックや閲覧といった、別のサイトでのコンバージョンにつながるイベントを、クロスサイトトラッキングを有効にせずに測定できる機能を有効にします。 これについても、プライバシーサンドボックスの広告関連のオリジントライアルの一環としてテストを拡張し続けるための、[アトリビューション レポート の I2E](https://groups.google.com/a/chromium.org/g/blink-dev/c/jEnNpideO1Y) を送信しました。 オリジントライアルの初期段階では、[デバッグ](/docs/privacy-sandbox/attribution-reporting-changes-january-2022/#debugging)など、開発者のエクスペリエンスと統合に関するフィードバックに焦点を当てていますが、これは、イベントレベルレポートと要約レポート全体のエンドツーエンドテストを網羅するように拡張されます。 diff --git a/site/ja/blog/progress-in-the-privacy-sandbox-2022-06/index.md b/site/ja/blog/progress-in-the-privacy-sandbox-2022-06/index.md index 3193cfef3..6d7a3141c 100644 --- a/site/ja/blog/progress-in-the-privacy-sandbox-2022-06/index.md +++ b/site/ja/blog/progress-in-the-privacy-sandbox-2022-06/index.md @@ -1,7 +1,7 @@ --- title: プライバシーサンドボックスの進捗状況(2022 年 5 月 ~ 6 月) description: > - アトリビューション レポート、FLEDGE、Topics、Fenced Frames、共有ストレージに関するプライバシーサンドボックスの関連性と測定の拡張トライアルを含む更新情報。 2022 年第 1 四半期のフィードバック要約レポートを公開し、さらに多くの開発者オフィスアワーを開催しました。 + アトリビューション レポート、FLEDGE、Topics、Fenced Frames、共有ストレージに関するプライバシーサンドボックスの広告関連の拡張トライアルを含む更新情報。 2022 年第 1 四半期のフィードバック要約レポートを公開し、さらに多くの開発者オフィスアワーを開催しました。 layout: 'layouts/blog-post.njk' date: 2022-07-08 authors: @@ -17,7 +17,7 @@ tags: このエディションの「**[プライバシーサンドボックスの進捗状況](/tags/progress-in-the-privacy-sandbox/)**」へようこそ。Chrome におけるサードパーティ Cookie の段階的廃止とよりプライベートなウェブに向けた取り組みについて、2022 年 5 月と 6 月のマイルストーンの達成状況をお知らせします。 各エディションでは、[プライバシー サンドボックス](https://privacysandbox.com/open-web/)全体の更新情報とニュースをまとめてお届けしています。 -## プライバシーサンドボックスの関連性と測定のオリジントライアル +## プライバシーサンドボックスの広告関連のオリジントライアル **アトリビューション レポート**、**FLEDGE**、および **Topics** の複合オリジントライアルを継続して実行するとともに、**Fenced Frames** と**共有ストレージ**にもこのトライアルを拡張しています。 Fenced Frames は、コンテンツを表示するための制限付きコンテナで、FLEDGE が広告を表示するために使用するフレームです。 共有ストレージは、パーティション化されていないストレージを慎重にゲート化し、そこに保管されたデータへのアクセスを広告選択プロセスの一環として許可することで、Fenced Frames の補完的機能を果たします。 @@ -63,7 +63,7 @@ Cookie 関連の提案が進展するにつれて、自社サイトの `SameSite 共有ストレージを使用すると、サイトは分割されていないデータを保存できますが、慎重に構築された出力ゲートを備えた安全な環境でのみそのデータを読み取ることができます。 共有ストレージは、安全な環境を提供する Fenced Frames と組み合わせることで、キャンペーンに対する A/B テストなどのユースケースを可能にします。 -**[共有ストレージの I2E](https://groups.google.com/a/chromium.org/g/blink-dev/c/jDx8z5a6ovk)** では、より広範な[プライバシーサンドボックスの関連性と測定のオリジントライアル](/origintrials/#/view_trial/771241436187197441)の一環としてテストすることが可能です。 **[開発者向けのドキュメント](/docs/privacy-sandbox/shared-storage/)** には、ユースケースとテストが含まれています。 +**[共有ストレージの I2E](https://groups.google.com/a/chromium.org/g/blink-dev/c/jDx8z5a6ovk)** では、より広範な[プライバシーサンドボックスの広告関連のオリジントライアル](/origintrials/#/view_trial/771241436187197441)の一環としてテストすることが可能です。 **[開発者向けのドキュメント](/docs/privacy-sandbox/shared-storage/)** には、ユースケースとテストが含まれています。 ## 隠されたトラッキングの防止 @@ -106,7 +106,7 @@ Variants: Accept-Language=(de en fr) Fenced Frame(`<fencedframe>`)は、埋め込みコンテンツ用に提案されている HTML 要素で、iframe に似ています。 ただし、Fenced Frame は、埋め込みコンテキストとの 通信を制限して、フレームが埋め込みコンテキストと共有せずにクロスサイトデータにアクセスできるようにする点で、iframe とは異なります。 たとえば、FLEDGE では、Fenced Frame 内に広告を表示することを意図しています。 -[新しい開発者向けの概要コンテンツ](/docs/privacy-sandbox/fenced-frame/)をお読みください。 **[Fenced Frames の I2E](https://groups.google.com/a/chromium.org/g/blink-dev/c/y6G3cvKXjlg)** は公開済みであり、より広範な[プライバシーサンドボックスの関連性と測定のオリジントライアル](/origintrials/#/view_trial/771241436187197441)の一環として登録できるようになっています。 +[新しい開発者向けの概要コンテンツ](/docs/privacy-sandbox/fenced-frame/)をお読みください。 **[Fenced Frames の I2E](https://groups.google.com/a/chromium.org/g/blink-dev/c/y6G3cvKXjlg)** は公開済みであり、より広範な[プライバシーサンドボックスの広告関連のオリジントライアル](/origintrials/#/view_trial/771241436187197441)の一環として登録できるようになっています。 ## 関連するコンテンツと広告の表示 @@ -116,14 +116,14 @@ Fenced Frame(`<fencedframe>`)は、埋め込みコンテンツ用に提案 ### Topics -[Topics API](/docs/privacy-sandbox/topics/) は、クロスサイトトラッキングを使用せずに、インタレストベース広告を可能にする提案です。 プライバシーサンドボックスの関連性と測定のオリジントライアルの一環として [Topics を含める I2E](https://groups.google.com/a/chromium.org/g/blink-dev/c/oTwd6VwCwqs) を送信しました。 また、オリジントライアル中には、[Topics のテストとフィードバックの提供に関する新しい開発者ガイド](/docs/privacy-sandbox/topics-experiment/)もご利用いただけます。 +[Topics API](/docs/privacy-sandbox/topics/) は、クロスサイトトラッキングを使用せずに、インタレストベース広告を可能にする提案です。 プライバシーサンドボックスの広告関連のオリジントライアルの一環として [Topics を含める I2E](https://groups.google.com/a/chromium.org/g/blink-dev/c/oTwd6VwCwqs) を送信しました。 また、オリジントライアル中には、[Topics のテストとフィードバックの提供に関する新しい開発者ガイド](/docs/privacy-sandbox/topics-experiment/)もご利用いただけます。 これは早期のテスト段階であるため、コード内にイシューが見つかるたびに、それらを積極的に調査して対処しています。 Topics では、[クラッシュバグ](https://bugs.chromium.org/p/chromium/issues/detail?id=1321140)が見つかったため、ユーザーエクスペリエンスに過度な影響を与えないよう、オリジントライアルに修正が公開されるまで、API を一時的に無効化しました。 その修正が完了したため、Topics API は現在では総合的なオリジントライアルの一環として [Chrome Beta ユーザーの 50% を対象に公開](https://groups.google.com/a/chromium.org/g/blink-dev/c/oTwd6VwCwqs)されています。 ### FLEDGE -[FLEDGE](/docs/privacy-sandbox/fledge/) は、個人の識別子に依存することなく、以前にアクセスしたサイトまたは製品を利用できる広告を実行することで、リマーケティングとカスタムオーディエンスのユースケースを実現します。 より広範なプライバシーサンドボックスの関連性と測定のオリジントライアルの一環として有効にするために、[FLEDGE の I2E](https://groups.google.com/a/chromium.org/g/blink-dev/c/0VmMSsDWsFg) をもう一度送信しました。 同様に、これに対応する[実験用の開発者ドキュメントも提供](/docs/privacy-sandbox/fledge-experiment/)されています。 +[FLEDGE](/docs/privacy-sandbox/fledge/) は、個人の識別子に依存することなく、以前にアクセスしたサイトまたは製品を利用できる広告を実行することで、リマーケティングとカスタムオーディエンスのユースケースを実現します。 より広範なプライバシーサンドボックスの広告関連のオリジントライアルの一環として有効にするために、[FLEDGE の I2E](https://groups.google.com/a/chromium.org/g/blink-dev/c/0VmMSsDWsFg) をもう一度送信しました。 同様に、これに対応する[実験用の開発者ドキュメントも提供](/docs/privacy-sandbox/fledge-experiment/)されています。 ## デジタル広告の測定 @@ -133,7 +133,7 @@ Fenced Frame(`<fencedframe>`)は、埋め込みコンテンツ用に提案 ### Attribution Reporting API -**[Attribution Reporting API](/docs/privacy-sandbox/attribution-reporting/)** を使うと、アドテクや広告主は、広告のクリックや閲覧といった、別のサイトでのコンバージョンにつながるイベントを、クロスサイトトラッキングを有効にせずに測定できるようになります。 これについても、プライバシーサンドボックスの関連性と測定のオリジントライアルの一環としてテストを拡張し続けるための、[アトリビューションレポート の I2E](https://groups.google.com/a/chromium.org/g/blink-dev/c/jEnNpideO1Y) を提出しました。 +**[Attribution Reporting API](/docs/privacy-sandbox/attribution-reporting/)** を使うと、アドテクや広告主は、広告のクリックや閲覧といった、別のサイトでのコンバージョンにつながるイベントを、クロスサイトトラッキングを有効にせずに測定できるようになります。 これについても、プライバシーサンドボックスの広告関連のオリジントライアルの一環としてテストを拡張し続けるための、[アトリビューションレポート の I2E](https://groups.google.com/a/chromium.org/g/blink-dev/c/jEnNpideO1Y) を提出しました。 オリジントライアルの初期フェーズでは、[デバッグ](/docs/privacy-sandbox/attribution-reporting-changes-january-2022/#debugging)など、開発者のエクスペリエンスと統合に関するフィードバックに焦点を当てていますが、これは、イベントレベルレポートと要約レポート全体のエンドツーエンドテストを網羅するように拡張されます。 diff --git a/site/ja/blog/shipping-privacy-sandbox/index.md b/site/ja/blog/shipping-privacy-sandbox/index.md index 9237aa1b6..62f9869e7 100644 --- a/site/ja/blog/shipping-privacy-sandbox/index.md +++ b/site/ja/blog/shipping-privacy-sandbox/index.md @@ -1,6 +1,6 @@ --- layout: layouts/blog-post.njk -title: プライバシーサンドボックスの関連性と測定 API の出荷の準備 +title: プライバシーサンドボックスの広告関連 API の出荷の準備 authors: - rowan_m - alexandrawhite @@ -14,11 +14,11 @@ tags: - origin-trials --- -プライバシーサンドボックスプロジェクトは、関連性と測定 API を Chrome 安全版に出荷する準備を進めています。[ウェブのプロジェクトタイムライン](https://privacysandbox.com/open-web/#the-privacy-sandbox-timeline)では、Chrome での提供が 2023 年第 3 四半期に始まることが示されています。具体的には、 [Chrome 安定版 115](https://chromiumdash.appspot.com/schedule) をターゲットにする予定です。つまり、2023 年 7 月下旬から API の提供を開始することになります。 +プライバシーサンドボックスプロジェクトは、広告関連 API を Chrome 安全版に出荷する準備を進めています。[ウェブのプロジェクトタイムライン](https://privacysandbox.com/open-web/#the-privacy-sandbox-timeline)では、Chrome での提供が 2023 年第 3 四半期に始まることが示されています。具体的には、 [Chrome 安定版 115](https://chromiumdash.appspot.com/schedule) をターゲットにする予定です。つまり、2023 年 7 月下旬から API の提供を開始することになります。 この記事では、今回のリリースに関わる次の内容について確認します。 -- **出荷内容**。公開予定の関連性と測定 API は、Topics、Protected Audience、アトリビューション レポート、Private Aggregation、共有ストレージ、および Fenced Frames です。これらの API は、潜在的なイシューを監視するために段階的に利用可能になる予定です。 +- **出荷内容**。公開予定の広告関連 API は、Topics、Protected Audience、アトリビューション レポート、Private Aggregation、共有ストレージ、および Fenced Frames です。これらの API は、潜在的なイシューを監視するために段階的に利用可能になる予定です。 - **正式な公開プロセス**。各 API は標準の Chrome 公開プロセスをたどります。このプロセスには、blink-dev メーリングリストに承認を得る目的で公開される個別の「Intent to Ship」メッセージが含まれます。 - **ユーザーコントロールの更新**。ユーザーは、API を管理するための広告プライバシーコントロールを利用できます。 - **オリジントライアルのステータス**。オリジントライアルは安定版リリースまで引き続き利用可能です。 @@ -32,13 +32,13 @@ Chrome での提供が近づきましたら、改めてお知らせいたしま <figure class="screenshot"> <p data-md-type="paragraph"><a href="https://privacysandbox.com/open-web/#the-privacy-sandbox-timeline"> {% Img src="image/VbsHyyQopiec0718rMq2kTE1hke2/ywbyok1JNTBh5B9Xb8xP.png", alt="プライバシーサンドボックスのウェブのタイムライン。", width="800", height="562" %} </a></p></figure> -これらは、[関連性と測定のオリジントライアル](/docs/privacy-sandbox/unified-origin-trial/)でテスト用に提供されている API と同じセットです。テスト中にエコシステムから受け取ったフィードバックは、重要なユースケースに合わせてこの機能を形成する上で不可欠でした。テストの実施、イシューの報告、関係者との結果の共有にご協力いただいた皆さんに感謝します。これこそが共同の取り組みです。 +これらは、[広告関連のオリジントライアル](/docs/privacy-sandbox/unified-origin-trial/)でテスト用に提供されている API と同じセットです。テスト中にエコシステムから受け取ったフィードバックは、重要なユースケースに合わせてこの機能を形成する上で不可欠でした。テストの実施、イシューの報告、関係者との結果の共有にご協力いただいた皆さんに感謝します。これこそが共同の取り組みです。 {: #include-apis } ## 出荷内容 -関連性と測定 API には次のものが含まれます。 +広告関連 API には次のものが含まれます。 - [Topics](/docs/privacy-sandbox/topics/): サイト全体で個人をトラッキングするサードパーティ Cookie やその他のユーザー識別子を使用せずに、インタレストベース広告のシグナルを生成します。 - [Protected Audience](/docs/privacy-sandbox/fledge/): リマーケティングやカスタムオーディエンスのユースケースに対応する広告を選択します。サイト間でのサードパーティのトラッキングを軽減するように設計されています。(この API は以前は FLEDGE という名前でした。リリースに向けて、機能をより適切に反映するように名前を更新しました。) @@ -61,7 +61,7 @@ API は、安定版リリースを使用するすべてのブラウザインス ### 出荷済み {: #shipped } -関連性と測定 API は、プライバシーサンドボックスプロジェクトの重要な部分です。ただし、すでに達成した重要なマイルストーンもいくつかあり、今後さらに多くのマイルストーンが達成されます。 +広告関連 API は、プライバシーサンドボックスプロジェクトの重要な部分です。ただし、すでに達成した重要なマイルストーンもいくつかあり、今後さらに多くのマイルストーンが達成されます。 - [User-Agent の情報量削減](/docs/privacy-sandbox/user-agent/): パッシブに共有されるブラウザデータを制限して、フィンガープリンティングにつながる機密情報の量を削減すると同時に、データをアクティブに要求するための User-Agent Client Hints を提供します。これらの値の削減は 2022 年 5 月に開始され、2023 年 5 月に完了しました。 - [CHIPS](/docs/privacy-sandbox/chips/): トップレベル サイトごとに個別の Cookie ジャーを使用して、開発者がパーティション化されたストレージに Cookie をオプトインできるようにします。CHIPS は 2023 年 2 月に Chrome 安定版で利用可能になりました。 @@ -78,13 +78,13 @@ API は、安定版リリースを使用するすべてのブラウザインス ## オリジントライアル -[プライバシーサンドボックスの関連性と測定のオリジントライアル](/docs/privacy-sandbox/unified-origin-trial/)では、アトリビューション レポート、Protected Audience、Topics、Fenced Frames、および共有ストレージをサイトで総合的に実験することができます。このオリジントライアルは Chrome 安定版 115 まで継続される予定です。オリジントライアルに参加しているテスターは、安定版の展開に伴い、可用性や API からのデータにギャップを体験する可能性があります。テスターがこの移行を管理するのに役立つ追加のガイダンスと詳細を提供します。 +[プライバシーサンドボックスの広告関連のオリジントライアル](/docs/privacy-sandbox/unified-origin-trial/)では、アトリビューション レポート、Protected Audience、Topics、Fenced Frames、および共有ストレージをサイトで総合的に実験することができます。このオリジントライアルは Chrome 安定版 115 まで継続される予定です。オリジントライアルに参加しているテスターは、安定版の展開に伴い、可用性や API からのデータにギャップを体験する可能性があります。テスターがこの移行を管理するのに役立つ追加のガイダンスと詳細を提供します。 進捗に合わせて[ドキュメント](/docs/privacy-sandbox/unified-origin-trial/)を更新する予定です。 ## 登録と次のステップ {: #enrollment } -Chrome での提供と並行して、これらの API が意図どおりに透明性をもって使用されるようにしたいと考えています。 Chrome と Android にわたるプライバシー サンドボックスの関連性と測定 API のための新しい[開発者登録プロセス](/blog/announce-enrollment-privacy-sandbox/)を発表しました。更新情報と手順については、[登録ドキュメント](/docs/privacy-sandbox/enroll/)で共有します。 +Chrome での提供と並行して、これらの API が意図どおりに透明性をもって使用されるようにしたいと考えています。 Chrome と Android にわたるプライバシー サンドボックスの広告関連 API のための新しい[開発者登録プロセス](/blog/announce-enrollment-privacy-sandbox/)を発表しました。更新情報と手順については、[登録ドキュメント](/docs/privacy-sandbox/enroll/)で共有します。 ## Chrome が提供するテスト モード {: #testing } @@ -121,13 +121,13 @@ Chrome は最大 1% のブラウザに対してサードパーティ Cookie を 私たちは、この段階でユーザーエクスペリエンスに影響を与えるイシューを検出し、対処し、サイト所有者に積極的に警告するための緩和策に取り組んでいます。 -さらに、プライバシーサンドボックスの関連性と測定 API が無効になっているモード B 内のトラフィックのごく一部を提供する予定です。First-Party Sets、CHIPS、FedCM などの他の API は無効になりません。この組み合わせは、サードパーティ Cookie を使用しないパフォーマンスのベースラインを確立するのに役立つと予想されており、このサブセットのテストに充てるトラフィックの適切な部分に関する[フィードバック](https://github.com/GoogleChromeLabs/privacy-sandbox-dev-support/labels/chrome-testing)を求めています。 +さらに、プライバシーサンドボックスの広告関連 API が無効になっているモード B 内のトラフィックのごく一部を提供する予定です。First-Party Sets、CHIPS、FedCM などの他の API は無効になりません。この組み合わせは、サードパーティ Cookie を使用しないパフォーマンスのベースラインを確立するのに役立つと予想されており、このサブセットのテストに充てるトラフィックの適切な部分に関する[フィードバック](https://github.com/GoogleChromeLabs/privacy-sandbox-dev-support/labels/chrome-testing)を求めています。 2024 年第 1 四半期にサードパーティ Cookie の 1% を廃止する予定であり、CMA と緊密な連携を通じて、廃止範囲を拡大するためのさらなる措置を講じていく予定です。 ## 貢献とフィードバックの共有 {: #feedback} -関連性と測定のオリジントライアルにまだ参加していない場合でも、[登録してこれらの API を試す](/docs/privacy-sandbox/unified-origin-trial/)ことができます。今すぐ登録すると、これらの API が実際にどのように機能するかをより詳しく知り、広範に提供される前にさまざまな手法を試すことができます。 +広告関連のオリジントライアルにまだ参加していない場合でも、[登録してこれらの API を試す](/docs/privacy-sandbox/unified-origin-trial/)ことができます。今すぐ登録すると、これらの API が実際にどのように機能するかをより詳しく知り、広範に提供される前にさまざまな手法を試すことができます。 ウェブエコシステム全体の多様な関係者からのフィードバックは、プライバシーサンドボックスイニシアチブにとって非常に重要です。専用の[フィードバックセクション](/docs/privacy-sandbox/feedback/)には、フォローしたりディスカッションに参加したりできる既存の公開チャンネルの概要と、いつでも Chrome チームに直接連絡できるフィードバックフォームが用意されています。 diff --git a/site/ja/docs/privacy-sandbox/attribution-reporting-experiment/index.md b/site/ja/docs/privacy-sandbox/attribution-reporting-experiment/index.md index 30e021a93..f41f9ecc5 100644 --- a/site/ja/docs/privacy-sandbox/attribution-reporting-experiment/index.md +++ b/site/ja/docs/privacy-sandbox/attribution-reporting-experiment/index.md @@ -24,7 +24,7 @@ authors: 4. [要約レポート](/docs/privacy-sandbox/summary-reports)の実験を行えます。 - アドテックは[集計サービス](/docs/privacy-sandbox/aggregation-service)で要約レポートを生成できます。[ローカルテスト](https://github.com/google/trusted-execution-aggregation-service/#set-up-local-testing)をセットアップするか、[Amazon Web Services(AWS)の本番環境でテスト](https://github.com/google/trusted-execution-aggregation-service/#test-on-aws-with-support-for-encrypted-reports)することができます。 - [AWS アカウント](https://portal.aws.amazon.com/gp/aws/developer/registration/index.html) を作る、または用意する。 - - プライバシーサンドボックスの関連性と測定オリジン トライアルに[登録します](/origintrials/#/view_trial/771241436187197441)。 + - プライバシーサンドボックスの広告関連オリジン トライアルに[登録します](/origintrials/#/view_trial/771241436187197441)。 - 集計サービスの[オンボーディング フォーム](https://forms.gle/EHoecersGKhpcLPNA)を完了します。フォームが提出されたら、確認メールと手順書をお送りします。 - [要約レポートのストラテジーとコツ](https://docs.google.com/document/d/1bU0a_njpDcRd9vDR0AJjwJjrf3Or8vAzyfuK8JZDEfo/edit?usp=sharing) を参照してください。 diff --git a/site/ja/docs/privacy-sandbox/attribution-reporting-updates/index.md b/site/ja/docs/privacy-sandbox/attribution-reporting-updates/index.md index 54b0d614e..7ea6eed47 100644 --- a/site/ja/docs/privacy-sandbox/attribution-reporting-updates/index.md +++ b/site/ja/docs/privacy-sandbox/attribution-reporting-updates/index.md @@ -29,7 +29,7 @@ authors: - **2022 年 6 月 23 日**: [2022 年 6 月に発行された「アトリビューション レポートの更新」ブログ記事](/blog/attribution-reporting-updates-june-2022)に、いくつかの更新の詳細が記載されています。また、以下の変更があります。 - [API ハンドブック](https://docs.google.com/document/d/1BXchEk-UMgcr2fpjfXrQ3D8VhTR-COGYS1cwK_nyLfg/edit)が更新されました。 - 要約レポートに関する [アトリビューション レポートの実験:戦略とヒント](https://docs.google.com/document/d/1bU0a_njpDcRd9vDR0AJjwJjrf3Or8vAzyfuK8JZDEfo/edit?usp=sharing)を公開しました。 -- **2022 年 3 月 31 日**: [広告の関連性と測定 API のオリジン トライアル](/blog/privacy-sandbox-unified-origin-trial/)を新規公開。これには Attribution Reporting API が含まれます。 +- **2022 年 3 月 31 日**: [広告関連 API のオリジン トライアル](/blog/privacy-sandbox-unified-origin-trial/)を新規公開。これには Attribution Reporting API が含まれます。 - **2022 年 2 月 7 日**: [ヘッダー トリガー リダイレクト](/blog/attribution-reporting-jan-2022-updates/#header-trigger-redirect)のドキュメントが追加されました。 - **2022 年 1 月 27 日**: [API 更新の移行](/blog/attribution-reporting-jan-2022-updates/)が公開されました。以下の内容が含まれます。 - [API の仕組みの変更](/blog/attribution-reporting-jan-2022-updates/#mechanism-changes) diff --git a/site/ja/docs/privacy-sandbox/attribution-reporting/system-overview/index.md b/site/ja/docs/privacy-sandbox/attribution-reporting/system-overview/index.md index e9f35f936..d4f1f6a82 100644 --- a/site/ja/docs/privacy-sandbox/attribution-reporting/system-overview/index.md +++ b/site/ja/docs/privacy-sandbox/attribution-reporting/system-overview/index.md @@ -26,7 +26,7 @@ Attribution Reporting API を使用すると、アドテックや広告主は、 {% Aside %} 現時点では、サイト運営者はこの API を使用して何らかの措置をとる必要はありません。これが変更された場合、この記事はそれに応じて更新されます。 {% endAside %} -この記事では、サービスが Attribution Reporting API でどのように機能するかについて、概要をエンドツーエンドで説明します。技術者は、[統合されたプライバシーサンドボックスの関連性と測定のオリジントライアル](/blog/privacy-sandbox-unified-origin-trial/)を使用して、ローカルまたは本番環境で[この API を試す](/docs/privacy-sandbox/attribution-reporting-experiment/)ことができます。 +この記事では、サービスが Attribution Reporting API でどのように機能するかについて、概要をエンドツーエンドで説明します。技術者は、[統合されたプライバシーサンドボックスの広告関連のオリジントライアル](/blog/privacy-sandbox-unified-origin-trial/)を使用して、ローカルまたは本番環境で[この API を試す](/docs/privacy-sandbox/attribution-reporting-experiment/)ことができます。 ## 概要 diff --git a/site/ja/docs/privacy-sandbox/fledge-api/index.md b/site/ja/docs/privacy-sandbox/fledge-api/index.md index 825bf23a2..d5d6b7e15 100644 --- a/site/ja/docs/privacy-sandbox/fledge-api/index.md +++ b/site/ja/docs/privacy-sandbox/fledge-api/index.md @@ -41,7 +41,7 @@ FLEDGE は、[TURTLEDOVE](https://github.com/WICG/turtledove) ファミリの提 ### オリジントライアルに参加する {: #origin-trial} -[プライバシーサンドボックスの関連性と測定のオリジントライアル](/docs/privacy-sandbox/unified-origin-trial)は、FLEDGE、[Topics](/docs/privacy-sandbox/topics/)、および [Attribution Reporting](/docs/privacy-sandbox/attribution-reporting/) API について、デスクトップの Chrome ベータ版 101.0.4951.26 以降で公開されています。 +[プライバシーサンドボックスの広告関連のオリジントライアル](/docs/privacy-sandbox/unified-origin-trial)は、FLEDGE、[Topics](/docs/privacy-sandbox/topics/)、および [Attribution Reporting](/docs/privacy-sandbox/attribution-reporting/) API について、デスクトップの Chrome ベータ版 101.0.4951.26 以降で公開されています。 参加するには、[オリジントライアルトークンに登録](/origintrials/#/view_trial/771241436187197441)してください。 @@ -76,9 +76,9 @@ document.head.append(otMeta); {% Aside 'caution' %} -有効なトライアルトークンを提供するページであっても、すべてのユーザーがプライバシーサンドボックスの関連性と測定のオリジントライアルの対象となるわけではありません。 +有効なトライアルトークンを提供するページであっても、すべてのユーザーがプライバシーサンドボックスの広告関連のオリジントライアルの対象となるわけではありません。 -[関連性と測定の統一オリジントライアルの概要](/docs/privacy-sandbox/unified-origin-trial#eligible-users)にはその理由が説明されており、オリジントライアル機能を使用する前に使用可能かどうかを検出する方法(検出する必要があります)が示されています。 +[広告関連の統一オリジントライアルの概要](/docs/privacy-sandbox/unified-origin-trial#eligible-users)にはその理由が説明されており、オリジントライアル機能を使用する前に使用可能かどうかを検出する方法(検出する必要があります)が示されています。 {% endAside %} diff --git a/site/ja/docs/privacy-sandbox/fledge-experiment/index.md b/site/ja/docs/privacy-sandbox/fledge-experiment/index.md index c5f4a196f..95256cc98 100644 --- a/site/ja/docs/privacy-sandbox/fledge-experiment/index.md +++ b/site/ja/docs/privacy-sandbox/fledge-experiment/index.md @@ -22,16 +22,16 @@ authors: {% Aside 'caution' %} -有効なトライアルトークンが提供されているページであっても、すべてのユーザーにプライバシーサンドボックスの関連性と測定のオリジントライアルを実施する資格があるわけではありません。 +有効なトライアルトークンが提供されているページであっても、すべてのユーザーにプライバシーサンドボックスの広告関連のオリジントライアルを実施する資格があるわけではありません。 -「[プライバシーサンドボックス広告の関連性と測定 API をテストする](/blog/privacy-sandbox-unified-origin-trial#eligible-users)」には、その理由が説明されています。また、オリジントライアル機能を使用する前に、それが利用可能かどうかを検出する理由と方法が示されています。 +「[プライバシーサンドボックスの広告関連 API をテストする](/blog/privacy-sandbox-unified-origin-trial#eligible-users)」には、その理由が説明されています。また、オリジントライアル機能を使用する前に、それが利用可能かどうかを検出する理由と方法が示されています。 {% endAside %} 1. [デモ](https://fledge-demo.glitch.me)を試す: 基本的な FLEDGE 実装手順が説明されています。 [FLEDGE のデモ動画](https://www.youtube.com/watch?v=znDD0gkdJyM&list=PLNYkxOF6rcICntazGfSVKSj5EwuR9w5Nv)では、デモコードの仕組みと、Chrome DevTools を使用して FLEDGE をデバッグする方法が説明されています。 2. FLEDGE API の実装状況に関する最新情報については、プライバシーサンドボックスの[ステータスページ](/docs/privacy-sandbox/status/#fledge)を確認してください。 3. API を使って実験する: - * [FLEDGE API 開発者ガイド](/blog/fledge-api#try-fledge)には、プライバシーサンドボックスの関連性と測定のオリジントライアルに参加する方法が説明されています。 + * [FLEDGE API 開発者ガイド](/blog/fledge-api#try-fledge)には、プライバシーサンドボックスの広告関連のオリジントライアルに参加する方法が説明されています。 * `chrome://flags/#privacy-sandbox-ads-apis` を有効にするか、コマンドラインから [FLEDGE 機能フラグ](/blog/fledge-api#flags)を指定して Chrome を実行し、単一ユーザーに対して FLEDGE を試してください。 * [開発者ガイド](/blog/fledge-api)には、API メソッドとパラメーターのリファレンスガイドも記載されています。 * [FLEDGE デモ](https://fledge-demo.glitch.me)の[ソースコード](https://github.com/JackJey/fledge-demo)には、独自の実験の開始するための出発点が示されています。 diff --git a/site/ja/docs/privacy-sandbox/fledge/index.md b/site/ja/docs/privacy-sandbox/fledge/index.md index 4a207aad3..b04a61da2 100644 --- a/site/ja/docs/privacy-sandbox/fledge/index.md +++ b/site/ja/docs/privacy-sandbox/fledge/index.md @@ -92,7 +92,7 @@ FLEDGE の機能は、徐々に追加される予定です。[オリジントラ ## FLEDGE を試すには {: #try-fledge} -- [FLEDGE API 開発者ガイド](/docs/privacy-sandbox/fledge-api#try-fledge)では、プライバシーサンドボックスの関連性と測定に関するオリジントライアルに参加する方法と、Chrome のフラグを設定して単一ユーザー向けに FLEDGE を試す方法について説明しています。 +- [FLEDGE API 開発者ガイド](/docs/privacy-sandbox/fledge-api#try-fledge)では、プライバシーサンドボックスの広告関連に関するオリジントライアルに参加する方法と、Chrome のフラグを設定して単一ユーザー向けに FLEDGE を試す方法について説明しています。 - [fledge-demo.glitch.me](https://fledge-demo.glitch.me/) には、広告主とサイト運営者サイトにまたがる基本的な FLEDGE デプロイメントのウォークスルーが提供されています。 diff --git a/site/ja/docs/privacy-sandbox/topics-experiment/index.md b/site/ja/docs/privacy-sandbox/topics-experiment/index.md index c9c641046..74316dfb3 100644 --- a/site/ja/docs/privacy-sandbox/topics-experiment/index.md +++ b/site/ja/docs/privacy-sandbox/topics-experiment/index.md @@ -20,15 +20,15 @@ authors: {% Aside 'caution' %} -有効なトライアルトークンが提供されているページであっても、すべてのユーザーにプライバシーサンドボックスの関連性と測定のオリジントライアルを実施する資格があるわけではありません。 +有効なトライアルトークンが提供されているページであっても、すべてのユーザーにプライバシーサンドボックスの広告関連のオリジントライアルを実施する資格があるわけではありません。 -「[プライバシーサンドボックス広告の関連性と測定 API をテストする](/blog/privacy-sandbox-unified-origin-trial#eligible-users)」には、その理由が説明されています。また、オリジントライアル機能を使用する前に、それが利用可能かどうかを検出する理由と方法が示されています。 +「[プライバシーサンドボックスの広告関連 API をテストする](/blog/privacy-sandbox-unified-origin-trial#eligible-users)」には、その理由が説明されています。また、オリジントライアル機能を使用する前に、それが利用可能かどうかを検出する理由と方法が示されています。 {% endAside %} 1. Topics API の実装状況に関する最新情報については、プライバシーサンドボックスの[ステータスページ](/docs/privacy-sandbox/status/#topics)を確認してください。 2. API を使って実験する: - * [Topics API](/docs/privacy-sandbox/topics/#origin-trial) には、プライバシーサンドボックスの関連性と測定のオリジントライアルに参加する方法が説明されています。 + * [Topics API](/docs/privacy-sandbox/topics/#origin-trial) には、プライバシーサンドボックスの広告関連のオリジントライアルに参加する方法が説明されています。 * Chrome 101 以降で `chrome://flags/#privacy-sandbox-ads-apis` を有効にするか、コマンドラインから `--enable-features=PrivacySandboxAdsAPIsOverride` [機能フラグ](https://www.chromium.org/developers/how-tos/run-chromium-with-flags)を指定して Chrome を実行し、単一ユーザーに対して Topics を試してください。 * 「[Topics JavaScript API を使ってトピックにアクセスする](/docs/privacy-sandbox/topics/#access-topics)」には、API を使用して現在のユーザーで観察されたトピックにアクセスする方法を説明する短いコードサンプルが含まれています。 * 「[Topics API の仕組み](/docs/privacy-sandbox/topics/#what-might-the-topics-javascript-api-look-like)」には、API によって返される値の概要と、機能のサポートと制約に関する詳細情報が示されています。 diff --git a/site/ja/docs/privacy-sandbox/topics/index.md b/site/ja/docs/privacy-sandbox/topics/index.md index 4cc288515..a7fe51a5b 100644 --- a/site/ja/docs/privacy-sandbox/topics/index.md +++ b/site/ja/docs/privacy-sandbox/topics/index.md @@ -28,7 +28,7 @@ Topics API のデモは [topics-demo.glitch.me](https://topics-demo.glitch.me/) ### オリジントライアルで Topics をテストする {: #origin-trial} -Topics、[FLEDGE](/docs/privacy-sandbox/unified-origin-trial/)、および [アトリビューション レポート](/docs/privacy-sandbox/fledge/)の API に関するプライバシーサンドボックスの関連性と測定の[オリジントライアル](/docs/privacy-sandbox/attribution-reporting/)が、デスクトップ版 Chrome Beta 101.0.4951.26 以降で利用できるようになりました。 +Topics、[FLEDGE](/docs/privacy-sandbox/unified-origin-trial/)、および [アトリビューション レポート](/docs/privacy-sandbox/fledge/)の API に関するプライバシーサンドボックスの広告関連の[オリジントライアル](/docs/privacy-sandbox/attribution-reporting/)が、デスクトップ版 Chrome Beta 101.0.4951.26 以降で利用できるようになりました。 ## トピックの取得と設定 {: #epoch} From cb2935b1fc7cde352b73f604ed20cbe2d08d7c1f Mon Sep 17 00:00:00 2001 From: Nancymic2 <nmichell@google.com> Date: Wed, 27 Sep 2023 09:29:10 -0400 Subject: [PATCH 816/982] a few more origin trial mentions (#7352) * a few more origin trial mentions * a few more origin trial mentions * a few more origin trial mentions * Update index.md title (revert) --- site/en/_partials/privacy-sandbox/ot-end.md | 2 +- site/en/docs/privacy-sandbox/fedcm-updates/index.md | 2 +- .../privacy-sandbox/summary-reports/design-decisions/index.md | 2 +- site/en/docs/privacy-sandbox/topics/index.md | 2 +- site/en/docs/privacy-sandbox/unified-origin-trial/index.md | 2 +- site/en/docs/privacy-sandbox/user-agent/index.md | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/site/en/_partials/privacy-sandbox/ot-end.md b/site/en/_partials/privacy-sandbox/ot-end.md index 3e49e2673..12da29e70 100644 --- a/site/en/_partials/privacy-sandbox/ot-end.md +++ b/site/en/_partials/privacy-sandbox/ot-end.md @@ -1,3 +1,3 @@ {% Aside 'important' %} - The Privacy Sandbox Relevance and Measurement origin trial ended September 20, 2023 and the APIs are now available for 99% of Chrome users, and origin trial enrollment is now closed. To keep abreast of the percentage of users each API is enabled for, refer to the [Chrome status graphs](https://pscs.glitch.me/). + The Privacy Sandbox Relevance and Measurement origin trial ended September 20, 2023 and the APIs are now available for 99% of Chrome users, and origin trial enrollment has closed. To keep abreast of the percentage of users each API is enabled for, refer to the [Chrome status graphs](https://pscs.glitch.me/). {% endAside %} diff --git a/site/en/docs/privacy-sandbox/fedcm-updates/index.md b/site/en/docs/privacy-sandbox/fedcm-updates/index.md index 7325ab73c..343d9e1e8 100644 --- a/site/en/docs/privacy-sandbox/fedcm-updates/index.md +++ b/site/en/docs/privacy-sandbox/fedcm-updates/index.md @@ -21,7 +21,7 @@ These updates are for you if: - You are an IdP using the Federated Credential Management API—for example, - [you have run an origin trial](/blog/fedcm-origin-trial/). + [you've run an origin trial](/blog/fedcm-origin-trial/). - You are an IdP or RP and interested in extending the API to fit your use case – e.g. you've been observing or participating in [the discussions on the FedID CG repository](https://github.com/fedidcg/FedCM/issues) diff --git a/site/en/docs/privacy-sandbox/summary-reports/design-decisions/index.md b/site/en/docs/privacy-sandbox/summary-reports/design-decisions/index.md index 8806a16eb..ccac250a5 100644 --- a/site/en/docs/privacy-sandbox/summary-reports/design-decisions/index.md +++ b/site/en/docs/privacy-sandbox/summary-reports/design-decisions/index.md @@ -506,7 +506,7 @@ assess and compare noise management strategies. Use it to: values of epsilon and noise parameters work for you, which don't? Where are the inflection points? -Think of this as a preparation step before running an origin trial. Noise Lab +Think of this as a preparation step. Noise Lab generates measurement data to simulate summary report outputs based on your input. It does not persist or share any data. diff --git a/site/en/docs/privacy-sandbox/topics/index.md b/site/en/docs/privacy-sandbox/topics/index.md index cd5fa1a79..dcd33fd81 100644 --- a/site/en/docs/privacy-sandbox/topics/index.md +++ b/site/en/docs/privacy-sandbox/topics/index.md @@ -302,7 +302,7 @@ Permissions-Policy: browsing-topics=(self "https://example.com") ## Next steps - Learn more about [what topics are and how they work](/docs/privacy-sandbox/topics/topic-classification). <!-- topic classification page and demo and trial links needed--> -- Try out the [demo](/docs/privacy-sandbox/topics/demo) or join an [origin trial](/docs/web-platform/origin-trials/). +- Try out the [demo](/docs/privacy-sandbox/topics/demo). ## Find out more diff --git a/site/en/docs/privacy-sandbox/unified-origin-trial/index.md b/site/en/docs/privacy-sandbox/unified-origin-trial/index.md index 8ac21f37a..8f2398c62 100644 --- a/site/en/docs/privacy-sandbox/unified-origin-trial/index.md +++ b/site/en/docs/privacy-sandbox/unified-origin-trial/index.md @@ -17,7 +17,7 @@ authors: {% Partial 'privacy-sandbox/ot-end.njk' %} -The Privacy Sandbox includes a selection of proposals to enable advertising use +The Privacy Sandbox includes a selection of APIs to enable advertising use cases without the need for cross-site tracking. [Origin trials](/blog/origin-trials/) provide an opportunity for developers to evaluate and provide feedback on new web technologies through real-world testing. The diff --git a/site/en/docs/privacy-sandbox/user-agent/index.md b/site/en/docs/privacy-sandbox/user-agent/index.md index 289bc8a2e..c2e94d5bf 100644 --- a/site/en/docs/privacy-sandbox/user-agent/index.md +++ b/site/en/docs/privacy-sandbox/user-agent/index.md @@ -294,7 +294,7 @@ User-Agent string. ## Engage and share feedback -* **Origin trial**: [Share your feedback](https://github.com/miketaylr/user-agent-reduction/issues). +* **Origin trial**: [Share your feedback on previous origin trials](https://github.com/miketaylr/user-agent-reduction/issues). * **Demo**: Try our [demo of User-Agent reduction](https://uar-ot.glitch.me/). * **GitHub**: Read the [UA-CH explainer](https://github.com/WICG/ua-client-hints), [raise questions and follow discussion](https://github.com/WICG/ua-client-hints/issues). From d17a624e970d0874026b1203e6c41fa3f0c34dfd Mon Sep 17 00:00:00 2001 From: "Kevin K. Lee" <kevinkiklee@google.com> Date: Wed, 27 Sep 2023 12:25:48 -0400 Subject: [PATCH 817/982] Add Protected Audience reporting doc (#7389) * Add PA reporting doc --- site/_data/docs/privacy-sandbox/toc.yml | 1 + .../protected-audience-api/reporting/index.md | 520 ++++++++++++++++++ 2 files changed, 521 insertions(+) create mode 100644 site/en/docs/privacy-sandbox/protected-audience-api/reporting/index.md diff --git a/site/_data/docs/privacy-sandbox/toc.yml b/site/_data/docs/privacy-sandbox/toc.yml index 3ecca82b4..e2430071a 100644 --- a/site/_data/docs/privacy-sandbox/toc.yml +++ b/site/_data/docs/privacy-sandbox/toc.yml @@ -78,6 +78,7 @@ - url: /docs/privacy-sandbox/protected-audience-api/ - url: /docs/privacy-sandbox/protected-audience-api/ad-auction - url: /docs/privacy-sandbox/protected-audience-api/interest-groups + - url: /docs/privacy-sandbox/protected-audience-api/reporting - url: /docs/privacy-sandbox/protected-audience-api/latency - url: /docs/privacy-sandbox/protected-audience-api/opt-out - url: /docs/privacy-sandbox/protected-audience-api/reports diff --git a/site/en/docs/privacy-sandbox/protected-audience-api/reporting/index.md b/site/en/docs/privacy-sandbox/protected-audience-api/reporting/index.md new file mode 100644 index 000000000..923dd4bc1 --- /dev/null +++ b/site/en/docs/privacy-sandbox/protected-audience-api/reporting/index.md @@ -0,0 +1,520 @@ +--- +layout: 'layouts/doc-post.njk' +title: 'Protected Audience API auction reporting' +subhead: > + Measure Protected Audience API auction data and results +description: > + Measure Protected Audience API auction data and results +date: 2023-09-26 +authors: + - kevinkiklee +--- + +In this article, you’ll find a high-level overview of the various mechanisms available for you to report Protected Audience API auction data to your server, along with the transition mechanisms available right now for you to use during the migration until alternative solutions are ready. + +To report on important metrics that you gather from an ad auction, Protected Audience API works with: + +* [Private Aggregation](/docs/privacy-sandbox/private-aggregation/) which collects auction signals and results to generate [summary reports](/docs/privacy-sandbox/summary-reports/). +* [Ads Reporting API](https://github.com/WICG/turtledove/blob/main/Fenced_Frames_Ads_Reporting.md) for [Fenced Frames](/docs/privacy-sandbox/fenced-frame/) and [iframes](https://developer.mozilla.org/docs/Web/HTML/Element/iframe) which is a channel within the frames to communicate with Protected Audience API worklets. The API allows associating event-level data with auction signals. The event-level reporting of the Ads Reporting API is a transitional mechanism until a more private reporting mechanism is designed. +* [Attribution Reporting](/docs/privacy-sandbox/attribution-reporting/) which allows you to associate conversion data with auction signals. +* [Shared Storage](/docs/privacy-sandbox/shared-storage/) which lets you write auction signals to a cross-origin storage, then allows you to report that data later using Private Aggregation. + +{% Aside %} + +We recommend you read the documentation on [Private Aggregation](/docs/privacy-sandbox/private-aggregation/), [Fenced Frames](/docs/privacy-sandbox/fenced-frame/), [Shared Storage](/docs/privacy-sandbox/shared-storage/), and [Attribution Reporting](/docs/privacy-sandbox/attribution-reporting/) before continuing, as core concepts are expanded on in this document. + +{% endAside %} + +## Protected Audience API reporting overview + +<figure> + {% Img src="image/hVf1flv5Jdag8OQKYqOcJgWUvtz1/R35UFscm9XdMmtco0BYH.png", alt="Protected Audience overall workflow", width="800", height="414" %} + <figcaption> + Protected Audience overall workflow + </figcaption> +</figure> + +There are three main time periods where data from the Protected Audience API auction flow can be reported to your server: auction time when the auction is executed from the publisher site, render time when the ad is rendered into a fenced frame or an iframe on the publisher site, and conversion time when the user conducts some action on the another site that can be attributed to the auction. + +During auction time, you can report the auction data using reporting worklets. During render time, you can report engagement data from an iframe or a fenced frame. During conversion time, you can report attribution data from the destination page using the Attribution Reporting API. + +### Reporting locations + +Within an auction, the buyers are able to report signals available in `generateBid()` and `reportWin()` worklets, and the sellers are able to report signals available in `scoreAd()` and `reportResult()`. Outside of an auction, the buyers and sellers can report data from a frame that rendered the ad, and from the site that the conversion was made from. + +<table style="zoom: 0.8"> + <tr> + <td style="background-color: #efefef">Time period + </td> + <td style="background-color: #efefef">Destination + </td> + <td style="background-color: #efefef">Location + </td> + <td style="background-color: #efefef; width: 20%;">Data available + </td> + <td style="background-color: #efefef">Reporting APIs available + </td> + </tr> + <tr> + <td rowspan="4" style="background-color: #d9ead3">Auction + </td> + <td rowspan="2">Buyer + </td> + <td><code>generateBid()</code> + </td> + <td rowspan="4">Signals, auction results, and auction performance + </td> + <td>Private Aggregation API + </td> + </tr> + <tr> + <td><code>reportWin()</code> + </td> + <td>Private Aggregation API +<p> +Ads Reporting API + </td> + </tr> + <tr> + <td rowspan="2">Seller + </td> + <td><code>scoreAd()</code> + </td> + <td>Private Aggregation API + </td> + </tr> + <tr> + <td><code>reportResult()</code> + </td> + <td>Private Aggregation API +<p> +Ads Reporting API + </td> + </tr> + <tr> + <td style="background-color: #c9daf8">Render + </td> + <td>Buyer / Seller + </td> + <td>Frame on the publisher site + </td> + <td>Event-level data within the ad frame + </td> + <td>Private Aggregation API +<p> +Ads Reporting API + </td> + </tr> + <tr> + <td style="background-color: #fce5cd">Conversion + </td> + <td>Buyer / Seller + </td> + <td>Conversion site + </td> + <td>Conversion and event-level data from the conversion site + </td> + <td>Attribution Reporting API +<p> +Private Aggregation API +<p> +Ads Reporting API + </td> + </tr> +</table> + +During each of the time periods listed, buyers and sellers will have access to various reporting APIs available to report data such as auction signals, event-level data, and conversion data. + +### Data available within a Protected Audience API auction + +The following data are available to be reported from a Protected Audience API worklet during the auction. + +#### Signals + +_Signals_ are the auction contextual data, user data, real-time data, and browser data available to the buyers and sellers within a worklet to generate a bid, score an ad, and report the results of an auction. + +<table style="zoom: 0.8"> + <tr> + <td style="background-color: #f3f3f3"><strong>Signal</strong> + </td> + <td style="background-color: #f3f3f3"><strong>Description</strong> + </td> + <td style="background-color: #f3f3f3"><strong>Set location</strong> + </td> + <td style="background-color: #f3f3f3"><strong>Users</strong> + </td> + <td style="background-color: #f3f3f3"><strong>Availability</strong> + </td> + </tr> + <tr> + <td style="background-color: null"><strong>auctionSignals</strong> + </td> + <td>Data available in the context of where the auction is held. This data can include page content information, first-party user data, and more. + </td> + <td>Set by the seller from the publisher site in the auction config. + </td> + <td>Buyer <p> Seller</p> + </td> + <td>generateBid scoreAd reportWin reportResult + </td> + </tr> + <tr> + <td style="background-color: null"><strong>directFromSellerSignals</strong> + </td> + <td>The same data for <code>auctionSignals</code>, <code>perBuyerSignals</code>, <code>sellerSignals</code> but the signals are guaranteed to come from the specified seller. + </td> + <td>Set via HTTP response headers from the seller + </td> + <td>Buyer +<p> +Seller + </td> + <td>generateBid scoreAd reportWin reportResult + </td> + </tr> + <tr> + <td style="background-color: null"><strong>browserSignals</strong> + </td> + <td>Various data provided by the browser (<code>topWindowHostname</code>, <code>interestGroupOwner</code>, <code>renderUrl</code>, <code>adComponents</code>, <code>biddingDurationMsec</code>, <code>IGJoinCount</code>, <code>IGRecency</code>, <code>modelingSignals</code>). + </td> + <td>Set by the browser. + </td> + <td>Buyer +<p> +Seller + </td> + <td>generateBid scoreAd reportWin reportResult + </td> + </tr> + <tr> + <td style="background-color: null"><strong>sellerSignals</strong> + </td> + <td>Signals provided to the seller for ad scoring. + </td> + <td>Set by the seller from the publisher site in the auction config. + </td> + <td>Seller + </td> + <td>scoreAd +<p> +reportWin +<p> +reportResult + </td> + </tr> + <tr> + <td style="background-color: null"><strong>trustedScoringSignals</strong> + </td> + <td>Real-time signals provided to the seller for ad scoring. + </td> + <td>The URL is set by the seller from the publisher site in the auction config. + </td> + <td>Seller + </td> + <td>scoreAd reportResult + </td> + </tr> + <tr> + <td style="background-color: null"><strong>perBuyerSignals</strong> + </td> + <td>Auction contextual data provided to specific buyers. The seller can retrieve the values for the buyers before the auction starts. This is the buyer’s knowledge of the ad opportunity. + </td> + <td>Set by the seller from the publisher site in the auction config. + </td> + <td>Buyer + + </td> + <td>generateBid scoreAd reportWin reportResult + </td> + </tr> + <tr> + <td style="background-color: null"><strong>trustedBiddingSignals</strong> + </td> + <td>Real-time signals provided to the buyers for ad bidding. + </td> + <td>The URL is set by the buyer from the advertiser site when the interest group is set. + </td> + <td>Buyer + </td> + <td>generateBid + </td> + </tr> + <tr> + <td style="background-color: null"><strong>userBiddingSignals</strong> + </td> + <td>User data provided by the buyer. + </td> + <td>Set by the buyer from the advertiser site when the interest group is set . + </td> + <td>Buyer + </td> + <td>generateBid + </td> + </tr> +</table> + +The [auction config](/docs/privacy-sandbox/protected-audience-api/ad-auction/#auctionconfig-properties) object is the primary source of data supplied to become available as signals in worklets. The publisher and seller can supply contextual data and first-party data in the auction config, and these signals can be enriched with the interest group data from the buyer, event-level data from the ad rendering frame, and attribution data from the clickthrough page. The data reported can be used for buyer/seller reporting, billing, budgeting, ML model training, and more. + +#### Other available data + +* _Results data_ that relates to auction win and loss data such as winning bid price and bid rejection reason. +* _Performance data_ that contains latency information, such as how long it took to fetch and execute the bidding worklet. + +### Data available outside a Protected Audience API auction + +Outside of a Protected Audience API auction, there are two time periods where data is available to be reported. + +During render time, when the ad is rendered on the publisher site, the event-level data from inside the iframe or fenced frame can be associated with Protected Audience API auction data, and reported to your server. Example event-level data includes ad impression, clickthrough, hover, and any other events that occur inside the frame. + +During conversion time, when a user conducts some action on the clickthrough page that is attributed back to the auction, the event-level data from the conversion page can be associated with Protected Audience API auction data, and reported to your server. + +## Event-level reporting + +Event-level reports detail information from one or more events. An event can be an auction win, ad impression, or a conversion. [Until at least 2026](/docs/privacy-sandbox/protected-audience-api/feature-status/), event-level auction win reporting will remain in place, fenced frames will not be required to render a Protected Audience ad, and an iframe with unconstrained network access can be used for event-level reporting. Also, the [Ads Reporting API](https://github.com/WICG/turtledove/blob/main/Fenced_Frames_Ads_Reporting.md) is available in fenced frames and iframes for you to associate auction and conversion data with event-level data from the frame. This is designed to let the ecosystem have an easier path to migration, since you can continue to use your existing reporting infrastructure until at least 2026 while you migrate your system to Protected Audience. + +### Event-level auction win reporting with `sendReportTo()` + +A mechanism available for reporting event-level data inside a Protected Audience auction is the <code>[sendReportTo() function](https://github.com/WICG/turtledove/blob/main/Proposed_First_FLEDGE_OT_Details.md#reporting)</code> on an auction win. The function is available in the buyer and seller reporting worklets, and the browser makes a <code>GET</code> request to the supplied URL string when the ad rendering begins. You can encode any signal available in your worklets as query params of the URL. + +For example, a buyer can report the winning bid amount from the `reportWin()` worklet for billing purposes: + +```js +// Buyer reporting worklet +function reportWin(auctionSignals, perBuyerSignals, sellerSignals, browserSignals, directFromSellerSignals) { + sendReportTo(`https://buyer-reporting-server.example/reporting?bid=${browserSignals.bid}`); +} +``` + +The `sendReportTo()` function can be used to generate a win report for the seller when called from `reportResult()`, and a win report for the buyer when called from `reportWin()`. The `sendReportTo()` function is [available until at least 2026](/docs/privacy-sandbox/protected-audience-api/feature-status/#event-level-auction-win-reporting), + + +### Engagement report + +An _engagement report_ contains event-level data from an ad creative such as impression or click data that is associated with the _signals_ of the Protected Audience API auction that rendered the ad. Since the ad is rendered after the auction has concluded, the auction signals are not available inside the frame that renders the ad. To associate these data from different time periods, we provide you with two transition mechanisms to generate engagement reports. + +The `sendReportTo()` function described above can be used to associate auction data with event-level data from an iframe, but it does not work for a fenced frame since a unique ID cannot be passed in from the embedder because the communication between the embedder and the fenced frame is limited. For associating auction data with event-level data from a fenced frame ad, the [Ads Reporting API](https://github.com/WICG/turtledove/blob/main/Fenced_Frames_Ads_Reporting.md) can be used. + +#### Ads Reporting API for fenced frames and iframes + +The [Ads Reporting API](https://github.com/WICG/turtledove/blob/main/Fenced_Frames_Ads_Reporting.md) for fenced frames and iframes provides a mechanism for you to associate user event-level data from an ad frame with signals within a Protected Audience auction. + +In a Protected Audience API reporting worklet, you register an ad beacon with the <code>[registerAdBeacon()](https://github.com/WICG/turtledove/blob/main/Fenced_Frames_Ads_Reporting.md#registeradbeacon)</code> function and set your signals as query params. Then you trigger the event from a fenced frame by calling the <code>[window.fence.reportEvent()](https://github.com/WICG/turtledove/blob/main/Fenced_Frames_Ads_Reporting.md#reportevent)</code> function with the user event-level data payload. + +In the following example, a campaign ID is associated with an event-level payload that the click coordinates: + +```js +// Protected Audience API worklet +function generateBid(interestGroup) { + const { campaignId } = interestGroup.ads.metadata; + registerAdBeacon({ + click: `https://your-server.example/report/click?campaignId=${campaignId}` + }) +} +``` + +```js +// Ad frame +window.fence.reportEvent({ + 'eventType': 'click', + 'eventData': JSON.stringify({'clickX': '123', 'clickY': '456'}), + 'destination':['buyer', 'seller'] +}); +``` + +The Fenced Frames Ads Reporting API will also be available until at least 2026 for [the same reasons as win reporting](/docs/privacy-sandbox/protected-audience-api/feature-status/#event-level-auction-win-reporting). + +For a deeper dive, see the [explainer](https://github.com/WICG/turtledove/blob/main/Fenced_Frames_Ads_Reporting.md). + +#### Unconstrained network access + +Fenced frames will allow loading network resources the same way as an iframe would, and you can send event-level data within fenced frames to your server. You can generate event-level reports on the server-side later by associating the event-level data from a fenced frame with the auction data that was sent with `sendReportTo()` that was discussed in the [auction event-level reporting mechanism](#event-level-auction-win-reporting-with-sendreportto) section above. + +Network access will be constrained sometime after third-party cookie deprecation. + +The event-level reporting mechanisms that exist in Protected Audience API today are transition mechanisms, and an alternative solution will be designed to better support existing use cases. + +### Attribution report + +An _attribution report_ allows you to associate a conversion on a website with an ad that was chosen from a Protected Audience API auction. For example, a user may click on a product ad you serve, redirected to the advertiser’s site, make a purchase there, and you are interested in attributing the purchase to the ad that was shown. The [Attribution Reporting API](https://github.com/WICG/attribution-reporting-api/tree/main) will be integrated with Protected Audience API to combine the auction data from the publisher site and the conversion data from the advertiser site. + +While we design a more permanent solution, you can use the [Ads Reporting API](#ads-reporting-api-for-fenced-frames-and-iframes) for fenced frames as a transitional mechanism for generating an event-level and aggregatable report with Attribution Reporting. Note that these reports are for measuring conversion, and are separate from the event-level and aggregatable engagement reports generated from the auction and the ad frame. We will publish an explainer for a more permanent solution when ready. + +#### Transitional mechanism + +When registering an ad beacon, you can use the keyword `reserved.top_navigation` which will automatically add the `Attribution-Reporting-Eligible` header for the beacon to become eligible to [register as an attribution source](https://github.com/WICG/attribution-reporting-api/blob/main/EVENT.md#registering-attribution-sources). + +```js +registerAdBeacon({ + 'reserved.top_navigation': 'https://adtech.example/click?buyer_event_id=123', +}); +``` + +To attach event-level data to the beacon you registered, you can call <code>[setReportEventDataForAutomaticBeacons()](https://github.com/WICG/turtledove/blob/main/Fenced_Frames_Ads_Reporting.md#api-to-populate-event-data-for-reservedtop_navigation)</code> from the fenced frame with the event payload. + +```js +window.fence.setReportEventDataForAutomaticBeacons({ + eventType: 'reserved.top_navigation', + eventData: 'data from the frame', + destination:['seller', 'buyer'] +}) +``` + +See the [Attribution Reporting section of the Ads Reporting API explainer](https://github.com/WICG/turtledove/blob/main/Fenced_Frames_Ads_Reporting.md#support-for-attribution-reporting) to learn more. + + +### Engagement and conversion reporting example + +In this example, we'll look at it from the buyer perspective who is interested in associating the data from the auction, ad frame, and conversion site together. + +In this workflow, the buyer coordinates with the seller to send a unique ID into the auction. During the auction, the buyer sends this unique ID with the auction data. During render and conversion time, the data from the fenced frame or iframe is also sent out with the same unique ID. Later, the unique ID can be used to associate these reports together. + +Workflow: + +1. Before the auction starts, the buyer sends a unique ID to the seller as part of their programmatic [real-time bidding (“RTB”) bid response](https://github.com/google/ads-privacy/tree/master/proposals/fledge-rtb). The ID can be set as a variable like `auctionId`. The ID is passed in as `perBuyerSignals` in the `auctionConfig` and it becomes available in buyer’s worklets. +2. During auction time, the buyer can register an ad beacon to be triggered during ad render time and conversion time (`registerAdBeacon()`). + 1. To associate auction signals for an ad frame event, set the `auctionId` as a query param of the beacon URL. + 2. To associate auction signals for a conversion event, set the `auctionId` in the beacon URL. +3. During ad render time, the beacons you registered during auction time can be triggered or enhanced with event-level data. + 3. Trigger the frame event with `reportEvent()` and pass in the event-level data. + 4. Add event-level payload to the attribution beacon with `setReportEventDataForAutomaticBeacons()` + 5. Register the ad with the Attribution Reporting API by responding to the ad beacon requests with the `Attribution-Reporting-Register-Source` header. +4. During conversion time, you can trigger the source you registered during auction time. + +After the above process, the buyer will have an auction report, engagement report, and conversion report, all tied together by a single unique key that can be used to associate with each other. + +Similar workflow applies to a seller if it needs access to attribution data, and the seller can also use a unique ID to send with `registerAdBeacon()`. From the frame, the `reportEvent()` call contains a destination property that can be used to send the report to both the buyer and the seller. Note that the SSP must be also present on the landing page for the trigger to be attributed to the source. + +## Aggregating Protected Audience data + +The Private Aggregation API is the mechanism used to report Protected Audience data to generate a [summary report](/docs/privacy-sandbox/summary-reports/), which is a noisy, aggregated report of data collected in buckets. A bucket is represented by an aggregation key, and some information can be encoded into the key. + +For example, an ad impression event can be counted into different buckets, where each bucket represents a different ad campaign. A summary report differs from an event-level report in that it doesn’t reveal information about each individual event. With an event-level report, you can determine that users A, B and C have seen the campaign 123. With summary reports, you can measure the number of users that have seen campaign 123 and [noise is added](/docs/privacy-sandbox/aggregation-service/#noise-scale) to protect user privacy. + +See the [Private Aggregation](/docs/privacy-sandbox/private-aggregation/) article for more on the API. + +### Aggregating auction signals + +You can aggregate the signals available within worklets to your server using Private Aggregation. For signal aggregation, you can use the <code>[privateAggregation.contributeToHistogram()](/docs/privacy-sandbox/private-aggregation/#sendhistogramreport)</code> method available in the buyer bidding worklet, seller scoring worklet , and buyer/seller reporting worklets. + +In this example, the winning bid is aggregated into the interest group owner bucket: + +```js +function convertBuyerToBucket(igOwner) {} +function convertWinningBidToValue(winningBid) {} + +function reportResult(auctionConfig, browserSignals) { + privateAggregation.contributeToHistogram({ + bucket: convertBuyerToBucket(browserSignals.interestGroupOwner), + value: convertWinningBidToValue(browserSignals.bid) + }); +} +``` + +This is the general mechanism to use when the signals you want to aggregate are not associated with event-level data and are not triggered by an event outside of the auction. To learn more about reporting auction signals, see the [explainer](https://github.com/patcg-individual-drafts/private-aggregation-api). + +### Aggregating auction signals with event data + +You can aggregate auction signals with limited information about an event that occurs in an ad frame. For example, you can aggregately measure how many clicks an ad for a campaign has received by creating a bucket that represents that campaign and the click event. Note that, from the ad frame, you can specify what event has occurred, but you cannot attach an event-level payload. + +To aggregate auction signals by events, you can use `privateAggregation.contributeToHistogramOnEvent(eventType, contribution)` that takes a string that specifies the event type and the contribution to be reported when that event is triggered. You can call the method with a custom event type, then, call `window.fence.reportEvent(eventType)` from the ad frame to trigger the report to be submitted. + +Let’s say you want to measure how many clicks an ad for a campaign has received. + +```js +// Protected Audience API worklet +function getClickReportBucketForCampaign(campaignId) { + // return a bucket for the campaign ID and the click event +} + +function generateBid(interestGroup) { + privateAggregation.contributeToHistogramOnEvent('click', { + bucket: getClickReportBucketForCampaign(interestGroup.ads.metadata.campaignId), + value: 1 + }); +} +``` + +In the bid generation function, you can define a bucket as the combination of the campaign ID and the click event, then increase the value for that bucket by 1 every time the event is triggered. + +```js +// Ad frame +window.fence.reportEvent('click'); +``` + +Then, at a later time, from the ad frame, you can trigger the report submission by calling `reportEvent(eventType)`: + +Learn more about triggering Private Aggregation contributions from a frame from the [explainer](https://github.com/WICG/turtledove/blob/main/FLEDGE_extended_PA_reporting.md#triggering-reports). + +### Reporting auction results and performance + +You can also aggregate auction results when triggered by an auction win or loss event with `contributeToHistogramOnEvent(eventType, contribution)` when you pass in a reserved event type keywords (`reserved.win, reserved.loss`, and `reserved.always`). + +Private Aggregation provides [a list of base values](https://github.com/WICG/turtledove/blob/main/FLEDGE_extended_PA_reporting.md#reporting-api-informal-specification) you can calculate the bucket and value of your contribution from. The available base values for auction results are the bid value of the winning ad, the bid value that was scored as second highest, and the reason a bid was rejected from the auction. + +When some base value is provided, like the winning bid amount, you can set how much to add or subtract from that value, then report the final value. For example, if the winning bid of $5 is provided as the base value, you can subtract your bid of $2 to calculate the actual value of $3 of how much you lost your auction by. + +#### Auction results reporting + +Let’s look at an example where you have lost an auction, and you want to learn how far off your bid was from the auction clearing price. + +To learn how much you lost the auction by, you can subtract your bid price from the winning bid price: + +```js +function generateBid() { + const bid = calculateBidAmount(); + + privateAggregation.contributeToHistogramOnEvent('reserved.loss', { + bucket: getBucketForCampaign(interestGroup.ads.metadata.campaignId), + value: { + baseValue: 'winning-bid', + scale: 1 // Scale the value to minimize noise-to-signal ratio + offset: -bid, // Numbers added to browser value after scaling + } + }); +} +``` + +When the report is submitted, the actual reported value will be the scaled `baseValue` shifted by the `offset` value. To learn more, see the [explainer](https://github.com/WICG/turtledove/blob/main/FLEDGE_extended_PA_reporting.md). + +#### Performance reporting + +Buyers and sellers can report how long a script has taken to execute, and how long it has taken to fetch the trusted signals. Sellers can collect the bid generation time and trusted bidding signal time of each buyer with their permission. + +See the [explainer](https://github.com/WICG/turtledove/blob/main/FLEDGE_extended_PA_reporting.md#reporting-per-buyer-latency-and-statistics-to-the-seller) to learn more. + +## Storing auction signals in Shared Storage + +[Shared storage](/docs/privacy-sandbox/shared-storage/) is an unpartitioned and cross-origin storage that you can write freely into, but is guarded with gates when reading and processing the stored values. One of the available gates for the Shared Storage API is Private Aggregation. You can only read the values in shared storage from inside a worklet, and you can report those values using Private Aggregation from the worklet. + +You can also write to shared storage from Protected Audience API bidding, scoring, and reporting worklets. At a later point in time, you can report those values in shared storage to your server using Private Aggregation . You can also use the stored values for the [URL Selection](https://github.com/WICG/shared-storage#url-selection) operation. + +From a Protected Audience API worklet, you can write any keys and values to shared storage: + +```js +// Protected Audience API worklet +function generateBid() { + sharedStorage.set('test-bucket', 123); +} +``` + +At a later time, you can load a shared storage worklet to read and send that value out with Private Aggregation: + +```js +// Shared Storage worklet +class SendReachReport{ + async run() { + const testBucket = await this.sharedStorage.get('test-bucket'); + + privateAggregation.contributeToHistogram({ + bucket: testBucket, + value: 1 + }); + } +} + +register('send-report', SendReachReport); +``` + +To learn more about Shared Storage, see the shared storage section of the Protected Audience API reporting developer guide, [explainer](https://github.com/WICG/shared-storage), [live demo](https://shared-storage-demo.web.app/), and the [demo code on GitHub](https://github.com/GoogleChromeLabs/shared-storage-demo). + +{% Partial 'privacy-sandbox/fledge-api-next.njk' %} From 893072f395b095289641673081155dcd3b4a60cc Mon Sep 17 00:00:00 2001 From: Oliver Dunk <oliverdunk@google.com> Date: Wed, 27 Sep 2023 17:48:08 +0100 Subject: [PATCH 818/982] Add documentation on storage partitioning and partitioned cookies (#6968) * Add first draft of storage and cookies partitioning docs * Address feedback * Update Privacy Sandbox page with updated extension information * Address feedback * Add note on SameSite=None cookies * Update site/en/docs/extensions/mv3/storage-and-cookies/index.md Co-authored-by: Rowan Merewood <rowan@merewood.org> * Apply suggestions from code review Co-authored-by: Joe Medley <jmedley@google.com> * Address feedback * Address feedback * Fix links * Address feedback * Add link for navigator.storage.estimate reference * Mention Chrome 115 as when storage partitioning is enabled * Update site/en/docs/extensions/mv3/storage-and-cookies/index.md Co-authored-by: Joe Medley <jmedley@google.com> * Update site/en/docs/extensions/reference/cookies/index.md Co-authored-by: Joe Medley <jmedley@google.com> * Update site/en/docs/extensions/mv3/storage-and-cookies/index.md Co-authored-by: Oliver Dunk <oliverdunk@google.com> * Clarify behavior of cookie partitioning in extensions * Update site/en/docs/extensions/mv3/storage-and-cookies/index.md Co-authored-by: Oliver Dunk <oliverdunk@google.com> * Apply suggestions from code review Co-authored-by: Joe Medley <jmedley@google.com> * Fix links --------- Co-authored-by: Rowan Merewood <rowan@merewood.org> Co-authored-by: Joe Medley <jmedley@google.com> --- site/_data/docs/extensions/toc.yml | 1 + .../mv3/declare_permissions/index.md | 13 +- .../mv3/storage-and-cookies/index.md | 125 ++++++++++++++++++ .../extensions/reference/cookies/index.md | 18 ++- .../extensions/reference/storage/index.md | 7 +- .../storage-partitioning/index.md | 35 ++--- 6 files changed, 170 insertions(+), 29 deletions(-) create mode 100644 site/en/docs/extensions/mv3/storage-and-cookies/index.md diff --git a/site/_data/docs/extensions/toc.yml b/site/_data/docs/extensions/toc.yml index db475b053..539d05753 100644 --- a/site/_data/docs/extensions/toc.yml +++ b/site/_data/docs/extensions/toc.yml @@ -58,6 +58,7 @@ - url: /docs/extensions/mv3/match_patterns - url: /docs/extensions/mv3/promises - url: /docs/extensions/mv3/cross-origin-isolation + - url: /docs/extensions/mv3/storage-and-cookies - title: i18n.docs.extensions.indepth-security sections: - url: /docs/extensions/mv3/xhr diff --git a/site/en/docs/extensions/mv3/declare_permissions/index.md b/site/en/docs/extensions/mv3/declare_permissions/index.md index 603487fa3..bbd37deff 100644 --- a/site/en/docs/extensions/mv3/declare_permissions/index.md +++ b/site/en/docs/extensions/mv3/declare_permissions/index.md @@ -438,12 +438,9 @@ The following table lists the currently available permissions. See the [Permissi </tr> <tr id="unlimitedStorage"> <td><code>"unlimitedStorage"</code></td> - <td>Provides an unlimited quota for storing client-side data, such as databases and local storage files. - Without this permission, the extension is limited to 10 MB of local storage.<div - class="aside aside--note"><b>Note:</b> This permission applies only to Web SQL Database and application cache - (see issue <a href="http://crbug.com/58985">58985</a>). Also, it doesn't currently work with wildcard - subdomains such as <code>http://*.example.com</code>.</div> - </td> + <td>Provides an unlimited quota for <a href="/docs/extensions/reference/storage">chrome.storage</a>, <a href="https://developer.mozilla.org/docs/Web/API/IndexedDB_API">IndexedDB</a>, + <a href="https://developer.mozilla.org/en-US/docs/Web/API/Cache">Cache Storage</a> and <a href="https://web.dev/origin-private-file-system/">Origin Private File System</a>. For more information, + see <a href="/docs/extensions/mv3/storage-and-cookies">Storage and cookies</a>.</td> </tr> <tr id="vpnProvider"> <td><code>"vpnProvider"</code></td> @@ -492,3 +489,7 @@ The following table lists the currently available permissions. See the [Permissi [vision-optperms]: /docs/extensions/mv3/intro/platform-vision/#improved-user-visibility-and-control [file-scheme-allow]: /docs/extensions/reference/extension/#method-isAllowedFileSchemeAccess [incognito-allow]: /docs/extensions/reference/extension/#method-isAllowedIncognitoAccess +[indexeddb]: https://developer.mozilla.org/docs/Web/API/IndexedDB_API +[cache-storage]: https://developer.mozilla.org/en-US/docs/Web/API/Cache +[opfs]: https://web.dev/origin-private-file-system/ +[storage-and-cookies]: /docs/extensions/mv3/storage-and-cookies diff --git a/site/en/docs/extensions/mv3/storage-and-cookies/index.md b/site/en/docs/extensions/mv3/storage-and-cookies/index.md new file mode 100644 index 000000000..46f0a2683 --- /dev/null +++ b/site/en/docs/extensions/mv3/storage-and-cookies/index.md @@ -0,0 +1,125 @@ +--- +layout: "layouts/doc-post.njk" +title: "Storage and cookies" +seoTitle: "Chrome extensions storage and cookies" +date: 2023-08-01 +description: Overview of how web storage APIs and cookies work in extensions. +--- + +Extensions can store cookies and access web storage APIs similarly to a normal website. However, in +some cases these behave differently in extensions. + +See [`chrome.storage`][chrome-storage-api] for information on the extension API. + +## Storage {: #storage } + +It is often desirable to use web platform storage APIs in extensions. This section explores the +behavior of these APIs in an extension context, which can sometimes differ with how they behave on the +web. + +### Persistence {: #storage-persistence } + +Extension storage is not cleared when a user [clears browsing data][clear-browsing-data]. +This applies to any data stored using web storage APIs (such as +[Local Storage][local-storage] and [IndexedDB][indexeddb]). + +By default, extensions are subject to the normal quota restrictions on storage, which can be checked +by calling [`navigator.storage.estimate()`][storage-estimate]. Storage can also be evicted under +heavy memory pressure, although this is rare. To avoid this: + +- Request the `"unlimitedStorage"` permission, which affects both extension and web storage APIs and +exempts extensions from both quota restrictions and eviction. +- Call [`navigator.storage.persist()`][storage-persist] for protection against eviction. + +Extension storage is shared across the extension's origin including the extension service worker, +any extension pages (including popups and the side panel), and offscreen documents. In content +scripts, calling web storage APIs accesses data from the host page the content script is injected on +and not the extension. + +### Access in service workers {: #storage-in-service-workers } + +The [IndexedDB][indexeddb] and [Cache Storage][cache-storage] APIs are accessible in service +workers. However, [Local Storage][local-storage] and [Session Storage][session-storage] are not. + +If you need to access Local Storage or Session Storage from the service worker, use an [offscreen document][offscreen]. + +### Partitioning {: #storage-partitioning } + +Partitioning is where keys are introduced for stored data to limit where it can be accessed. Storage +has historically been keyed by origin. + +Starting in Chrome 115, [storage partitioning][storage-partitioning] introduces changes to how +partitioning keys are defined to prevent certain types of cross-site tracking. In practice, this +means that if site A embeds an iframe containing site B, site B will not be able to access the same +storage it would usually have when navigated to directly. + +To mitigate the impact of this in extensions, two exemptions apply: + +- If a page with the `chrome-extension://` scheme is embedded in any site, storage partitioning will +not apply, and the extension will have access to its top-level partition. +- If a page with the `chrome-extension://` scheme includes an iframe, and the extension has +[host permissions][declare-permissions] for the site it is embedding, that site will also have +access to its top-level partition. + +## Cookies {: #cookies } + +Cookies provide a way to store key/value pairs associated with a specific domain and path. They have +limited value in extensions but understanding their behavior can be useful if you have a specific +use case or have bundled a third-party script which uses them in its implementation. + +### Secure cookies {: #secure-cookies } + +The [`Secure`][cookies-restrict-access] cookie attribute is only supported for the `https://` +scheme. Consequently, `chrome-extension://` pages are not able to set cookies with this attribute. + +This also means that extension pages cannot use other cookie attributes where the `Secure` attribute is +required: + +- [`SameSite=None`][same-site] +- [`Partitioned`][chips] + +### Partitioning {: #cookies-partitioning } + +{% Aside %} +When an extension embeds a third-party site, that site will use the extension origin as the partition key. This means the site will not be able access the same cookies as if it was navigated to directly. See [https://crbug.com/1463991](https://crbug.com/1463991). +{% endAside %} + +Cookies set on chrome-extension:// pages always use [`SameSite=Lax`][same-site]. Consequently, they +can never be accessed in iframes and partitioning is not relevant. + +When an extension embeds a third-party website inside of a chrome://extension page, the behavior +depends on the choices on Chrome's Privacy and security settings page: + +- If third-party cookies are enabled, the site can access cookies from a partition keyed based on +its origin. +- If third-party cookies are blocked, Chrome uses the extension origin as the partitioning key +for the third-party site's cookies. This means that the site will **not** be able to access +partitioned cookies associated with other partitions such as the cookies it could access if it were +navigated to directly. + +This setting is part of the Privacy Sandbox work and is being adjusted according to this +[timeline][privacy-sandbox-timeline]. + +The [`chrome.cookies`][chrome-cookies] API currently operates on cookies from all partitions. For +more information, see the [API reference][chrome-cookies-partitioning]. + +[clear-browsing-data]: https://support.google.com/chrome/answer/2392709 +[indexeddb]: https://developer.mozilla.org/docs/Web/API/IndexedDB_API +[local-storage]: https://developer.mozilla.org/docs/Web/API/Window/localStorage +[session-storage]: https://developer.mozilla.org/docs/Web/API/Window/sessionStorage +[chrome-storage-api]: /docs/extensions/reference/storage +[offscreen]: /docs/extensions/reference/offscreen +[on-message]: /docs/extensions/reference/runtime/#event-onMessage +[create-offscreen]: /docs/extensions/reference/offscreen/#method-createDocument +[send-message]: /docs/extensions/reference/runtime/#method-sendMessage +[storage-partitioning]: /docs/privacy-sandbox/storage-partitioning +[declare-permissions]: /docs/extensions/mv3/declare_permissions/ +[cookies-restrict-access]: https://developer.mozilla.org/docs/Web/HTTP/Cookies#restrict_access_to_cookies +[chips]: /docs/privacy-sandbox/chips +[same-site]: https://web.dev/samesite-cookies-explained +[privacy-sandbox-timeline]: https://privacysandbox.com/open-web/#open-web-timeline-3pc +[chrome-cookies]: /docs/extensions/reference/cookies +[chrome-cookies-partitioning]: /docs/extensions/reference/cookies#partitioning +[storage-estimate]: https://developer.mozilla.org/docs/Web/API/StorageManager/estimate +[storage-persist]: https://developer.mozilla.org/docs/Web/API/StorageManager/persist +[cache-storage]: https://developer.mozilla.org/docs/Web/API/CacheStorage diff --git a/site/en/docs/extensions/reference/cookies/index.md b/site/en/docs/extensions/reference/cookies/index.md index c4c0942d2..f76094cd5 100644 --- a/site/en/docs/extensions/reference/cookies/index.md +++ b/site/en/docs/extensions/reference/cookies/index.md @@ -22,6 +22,19 @@ to access. For example: } ``` +## Partitioning {: #partitioning } + +[Partitioned cookies][chips] allow a site to mark that certain cookies should be keyed against the +origin of the top level frame. This means that if site A is embedded using an iframe in site B +and site C, a partitioned cookie can have a different value in each. + +`chrome.cookies` does not support partitioning, which means that all methods +read and write cookies from all partitions. The [`cookies.set()`](#method-set) method stores cookies in +the default partition. + +For details on the general impact of partitioning for extensions, see +[Storage and Cookies][cookie-partitioning]. + ## Examples You can find a simple example of using the cookies API in the @@ -30,4 +43,7 @@ the source code, see [Samples][3]. [1]: /docs/extensions/mv3/declare_permissions [2]: https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/api-samples/cookies/cookie-clearer -[3]: /docs/extensions/samples/ +[3]: /docs/extensions/samples +[chips]: /docs/privacy-sandbox/chips +[partitioning-api-proposal]: https://docs.google.com/document/d/1iZKjdUft0x3m6pTH8hnppF5VHinCy0Wlprk7bUwV-XY/edit?usp=sharing +[cookie-partitioning]: /docs/extensions/mv3/storage-and-cookies/#cookies-partitioning diff --git a/site/en/docs/extensions/reference/storage/index.md b/site/en/docs/extensions/reference/storage/index.md index 77d7101c6..a5b43c5f4 100644 --- a/site/en/docs/extensions/reference/storage/index.md +++ b/site/en/docs/extensions/reference/storage/index.md @@ -15,7 +15,7 @@ The Storage API provides an extension-specific way to persist user data and stat {% Details %} {% DetailsSummary %} -💡 Can extensions use the Storage API? +Can extensions use web storage APIs? {% endDetailsSummary %} Even though extensions can use the [`Storage`][mdn-storage] interface (accessible from `window.localStorage`) in some contexts (popup and other HTML pages), it is not recommended for the following reasons: @@ -24,6 +24,7 @@ Even though extensions can use the [`Storage`][mdn-storage] interface (accessibl - Content scripts share storage with the host page. - Data saved using the `Storage` interface is lost when the user clears their browsing history. +To move data from web storage APIs to extension storage APIs from a service worker: 1. Create an offscreen document with a conversion routine and an [`onMessage`][on-message] handler. 1. Add a conversion routine to an offscreen document. @@ -31,6 +32,9 @@ Even though extensions can use the [`Storage`][mdn-storage] interface (accessibl 1. If your data isn't found, [create][create-offscreen] an offscreen document and call [`sendMessage()`][send-message] to start the conversion routine. 1. Inside the offscreen document's `onMessage` handler, call the conversion routine. +There are also some nuances with how web storage APIs work in extensions. Learn more in the +[Storage and Cookies][storage-and-cookies] article. + {% endDetails %} ### Storage areas @@ -265,3 +269,4 @@ To see other demos of the Storage API, explore any of the following examples: [prop-session]: #property-session [prop-managed]: #property-managed [send-message]: /docs/extensions/reference/runtime/#method-sendMessage +[storage-and-cookies]: /docs/extensions/mv3/storage-and-cookies diff --git a/site/en/docs/privacy-sandbox/storage-partitioning/index.md b/site/en/docs/privacy-sandbox/storage-partitioning/index.md index 2171db849..407c6f42a 100644 --- a/site/en/docs/privacy-sandbox/storage-partitioning/index.md +++ b/site/en/docs/privacy-sandbox/storage-partitioning/index.md @@ -190,27 +190,20 @@ partitioned. ### Extension APIs -[Extensions](/docs/extensions/mv3/) are programs -that customize the browsing experience for the user. With Manifest V2, -extensions can create -[background pages](/docs/extensions/mv2/background_pages/) -that have the extension's origin, but can embed iframes with web content's -origins. - -Because partitioning the storage will break some use cases, a -couple of mitigations will be provided. If the extension has -[host_permissions](/docs/extensions/mv2/runtime_host_permissions/) -for the iframe origin, then the iframe will be treated as the top-level frame -and not the extension page. If an extension embeds an iframe with an extension -URL into a top-level site with host permissions, the iframe will be treated as -first-party with the extension rather than partitioned by the top-level site. - -{% Aside %} -Manifest V2 has been -[deprecated](/docs/extensions/mv3/mv2-sunset/) and -will be removed. It is recommended to -[migrate to Manifest V3](/docs/extensions/mv3/intro/mv3-migration/). -{% endAside %} +[Extensions](/docs/extensions/mv3/) are programs that allow users to customize their browsing +experience. + +Extension pages (pages with a `chrome-extension://` scheme) can be embedded on sites +across the web, and in these cases, they will continue to have access to their top-level partition. +These pages can also embed other sites, in which case those sites will have access to their top-level +partition as long as the extension has [host permissions](/docs/extensions/mv3/declare_permissions) +for that site. + +In addition, extensions can use the [`chrome.cookies`](/docs/extensions/reference/cookies) API to +interact with the cookies for a given site. This currently operates on cookies from all partitions +in a way which can be surprising. + +For more information, see the [extension docs](/docs/extensions/mv3/storage-and-cookies). ## Engage and share feedback From 19d63544821941c767cca2cfc624a2e14af51b6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Niedzi=C3=B3=C5=82ka?= <niedziolek@hotmail.com> Date: Wed, 27 Sep 2023 19:46:34 +0200 Subject: [PATCH 819/982] Fix invalid link (#7366) --- site/en/blog/whats-new-css-ui-2023/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/en/blog/whats-new-css-ui-2023/index.md b/site/en/blog/whats-new-css-ui-2023/index.md index cf955cb4b..bc6e0566c 100644 --- a/site/en/blog/whats-new-css-ui-2023/index.md +++ b/site/en/blog/whats-new-css-ui-2023/index.md @@ -213,7 +213,7 @@ The letter’s block-offset, or “sink”, for where the letter will sit. } %} -Learn more about using `intial-letter` [here](](/blog/control-your-drop-caps-with-css-initial-letter/). +Learn more about using `intial-letter` [here](/blog/control-your-drop-caps-with-css-initial-letter/). ### Dynamic viewport units From f1a7db6b6593b7c170198eb3d660cff7581d3f3f Mon Sep 17 00:00:00 2001 From: Charlie Harrison <csharrison@chromium.org> Date: Wed, 27 Sep 2023 12:47:52 -0500 Subject: [PATCH 820/982] Make the definition of site more precise (#7395) * Make the definition of site more precise * Update site.md * Update site.md --- site/en/_partials/privacy-sandbox/glossary-entries/site.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/en/_partials/privacy-sandbox/glossary-entries/site.md b/site/en/_partials/privacy-sandbox/glossary-entries/site.md index fd66fcdc4..3fe9d5591 100644 --- a/site/en/_partials/privacy-sandbox/glossary-entries/site.md +++ b/site/en/_partials/privacy-sandbox/glossary-entries/site.md @@ -1 +1 @@ -Site. See [Top-Level Domain](#tld) and [eTLD](#etld). \ No newline at end of file +A site is equivalent to an [eTLD+1](#etld) along with a scheme (protocol). See also [Top-Level Domain](#tld). From 3095381d6d12483600e585fcc3ff8b589b63cbbe Mon Sep 17 00:00:00 2001 From: Jack J <jxck@google.com> Date: Thu, 28 Sep 2023 14:21:16 +0900 Subject: [PATCH 821/982] Adding FedCM Change Log of Chrome 116/117 (#7314) * Adding Chrome 116/117 Changelog * Update site/en/docs/privacy-sandbox/fedcm-updates/index.md Co-authored-by: Eiji Kitamura <agektmr@google.com> * Update site/en/docs/privacy-sandbox/fedcm-updates/index.md Co-authored-by: Eiji Kitamura <agektmr@google.com> * Update site/en/docs/privacy-sandbox/fedcm-updates/index.md Co-authored-by: Eiji Kitamura <agektmr@google.com> * Update site/en/docs/privacy-sandbox/fedcm-updates/index.md Co-authored-by: Eiji Kitamura <agektmr@google.com> * Update site/en/docs/privacy-sandbox/fedcm-updates/index.md Co-authored-by: Eiji Kitamura <agektmr@google.com> * Update site/en/docs/privacy-sandbox/fedcm-updates/index.md Co-authored-by: Milica <mihajlija@google.com> --------- Co-authored-by: Eiji Kitamura <agektmr@google.com> Co-authored-by: Milica <mihajlija@google.com> --- site/en/docs/privacy-sandbox/fedcm-updates/index.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/site/en/docs/privacy-sandbox/fedcm-updates/index.md b/site/en/docs/privacy-sandbox/fedcm-updates/index.md index 343d9e1e8..ff20afd2f 100644 --- a/site/en/docs/privacy-sandbox/fedcm-updates/index.md +++ b/site/en/docs/privacy-sandbox/fedcm-updates/index.md @@ -37,6 +37,18 @@ If you're new to this API or have not experimented with it yet, read the To stay updated on the FedCM API changes, please subscribe to [our newsletter](https://groups.google.com/g/fedcm-developer-newsletter). +### Chrome 117 (Sep 2023) + +- Origin trial for Idp Sign-In Status API is available on Android from Chrome 117. Learn more about it in [FedCM updates: IdP Sign-In Status API, Login Hint, and more](/blog/fedcm-chrome-116-updates/#idp-signin-status). + +### Chrome 116 (Aug 2023) + +- Added support for following three features in Chrome 116: + - **Login Hint API**: Specify a preferred user account to be signed in. + - **User Info API**: Fetch the information of the returning user so that the identity provider (IdP) can render a personalized sign-in button within an iframe. + - **RP Context API**: Use a title different from 'Sign in' in the FedCM dialog. +- Origin Trial for IdP Sign-In Status API is available. Learn more about it in [FedCM updates: IdP Sign-In Status API, Login Hint, and more](/blog/fedcm-chrome-116-updates/). + ### Chrome 115 (June 2023) - Added support for auto-reauthentication which let users reauthenticate automatically when they come back after their initial authentication using FedCM. This improves the user experiences and enables a more streamlined reauthentication to the RP after the initial consent. Learn more about [FedCM auto-reauthentication](/blog/fedcm-auto-reauthn/). From 2ea8904834cde2556d673b9f7f59b3383ce970a6 Mon Sep 17 00:00:00 2001 From: Abdur Rehman <73696933+ar-assad@users.noreply.github.com> Date: Thu, 28 Sep 2023 16:03:32 +0500 Subject: [PATCH 822/982] Correct shortcut in index.md (#7378) --- site/en/docs/devtools/javascript/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/en/docs/devtools/javascript/index.md b/site/en/docs/devtools/javascript/index.md index e55f411ea..4b0c9b214 100644 --- a/site/en/docs/devtools/javascript/index.md +++ b/site/en/docs/devtools/javascript/index.md @@ -38,7 +38,7 @@ DevTools provides a lot of different tools for different tasks, such as changing load performance, and monitoring network requests. The **Sources** panel is where you debug JavaScript. -1. Open DevTools by pressing Command+Option+I (Mac) or Control+Shift+I (Windows, Linux). This +1. Open DevTools by pressing Command+Option+J (Mac) or Control+Shift+J (Windows, Linux). This shortcut opens the **Console** panel. {% Img src="image/admin/JS6A41j5zLtT1J0xqjqL.png", alt="The Console panel.", width="800", height="494" %} From 5ae33dc1938aa16315315967b6abb884a3bc7d03 Mon Sep 17 00:00:00 2001 From: Barry Pollard <barrypollard@google.com> Date: Thu, 28 Sep 2023 13:51:36 +0100 Subject: [PATCH 823/982] Renew Speculation Rules Origin Trial (#7361) --- site/_includes/layouts/base.njk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/_includes/layouts/base.njk b/site/_includes/layouts/base.njk index 5d0437554..720390a97 100644 --- a/site/_includes/layouts/base.njk +++ b/site/_includes/layouts/base.njk @@ -9,7 +9,7 @@ {# Dogfood document speculation rules origin trial #} <!-- developer.chrome.com origin trial token for speculation rules document rules --> - <meta http-equiv="origin-trial" content="AhaT7AdLUbVk3M0VorYLzXSY8Km9PJZlzg3Xkv6KT2QMZ4zyqA5BfdTJLCj1TVnGhryWtQH66HWQEsIbZDUrsAwAAABseyJvcmlnaW4iOiJodHRwczovL2RldmVsb3Blci5jaHJvbWUuY29tOjQ0MyIsImZlYXR1cmUiOiJTcGVjdWxhdGlvblJ1bGVzUHJlZmV0Y2hGdXR1cmUiLCJleHBpcnkiOjE2OTQxMzExOTl9"> + <meta http-equiv="origin-trial" content="AtXwNtvKLGSNFBuawE0CYB2BnrKRyHz9s9KLZ9LkTTtvcxoK4UIgtNQrwGOD6wQCKsbHAsbYYjdkBdvj3vuk2QAAAABseyJvcmlnaW4iOiJodHRwczovL2RldmVsb3Blci5jaHJvbWUuY29tOjQ0MyIsImZlYXR1cmUiOiJTcGVjdWxhdGlvblJ1bGVzUHJlZmV0Y2hGdXR1cmUiLCJleHBpcnkiOjE3MDk2ODMxOTl9"> {% include 'partials/meta.njk' %} {% block feed %} From 17c763cd78e4ae1274ef195fd84ae80daf984788 Mon Sep 17 00:00:00 2001 From: Barry Pollard <barrypollard@google.com> Date: Thu, 28 Sep 2023 14:29:52 +0100 Subject: [PATCH 824/982] Bump web-vitals to 3.5.0 (#7406) --- package-lock.json | 20 +++++++++++--------- package.json | 2 +- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/package-lock.json b/package-lock.json index 10ced6903..586398eff 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,8 +20,7 @@ "@lhci/cli": "^0.7.2", "@mdn/browser-compat-data": "5.3.6", "@rollup/plugin-node-resolve": "^8.4.0", - "@types/adm-zip": "^0.5.0", - "adm-zip": "^0.5.10", + "adm-zip": "0.5.10", "algoliasearch": "^4.6.0", "async-transforms": "1.0.6", "cheerio": "1.0.0-rc.3", @@ -60,7 +59,7 @@ "typescript": "4.7.4", "unistore": "^3.5.2", "uslug": "^1.0.4", - "web-vitals": "^3.4.0", + "web-vitals": "^3.5.0", "webdev-infra": "1.0.56", "xss": "^1.0.14" }, @@ -107,6 +106,7 @@ "node": ">=14" }, "optionalDependencies": { + "@types/adm-zip": "0.5.0", "@types/cheerio": "^0.22.22", "@types/express": "^4.17.13", "@types/gtag.js": "^0.0.12", @@ -3254,6 +3254,7 @@ "version": "0.5.0", "resolved": "https://registry.npmjs.org/@types/adm-zip/-/adm-zip-0.5.0.tgz", "integrity": "sha512-FCJBJq9ODsQZUNURo5ILAQueuA8WJhRvuihS3ke2iI25mJlfV2LK8jG2Qj2z2AWg8U0FtWWqBHVRetceLskSaw==", + "optional": true, "dependencies": { "@types/node": "*" } @@ -26046,9 +26047,9 @@ } }, "node_modules/web-vitals": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/web-vitals/-/web-vitals-3.4.0.tgz", - "integrity": "sha512-n9fZ5/bG1oeDkyxLWyep0eahrNcPDF6bFqoyispt7xkW0xhDzpUBTgyDKqWDi1twT0MgH4HvvqzpUyh0ZxZV4A==" + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/web-vitals/-/web-vitals-3.5.0.tgz", + "integrity": "sha512-f5YnCHVG9Y6uLCePD4tY8bO/Ge15NPEQWtvm3tPzDKygloiqtb4SVqRHBcrIAqo2ztqX5XueqDn97zHF0LdT6w==" }, "node_modules/webdev-infra": { "version": "1.0.56", @@ -29068,6 +29069,7 @@ "version": "0.5.0", "resolved": "https://registry.npmjs.org/@types/adm-zip/-/adm-zip-0.5.0.tgz", "integrity": "sha512-FCJBJq9ODsQZUNURo5ILAQueuA8WJhRvuihS3ke2iI25mJlfV2LK8jG2Qj2z2AWg8U0FtWWqBHVRetceLskSaw==", + "optional": true, "requires": { "@types/node": "*" } @@ -46554,9 +46556,9 @@ } }, "web-vitals": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/web-vitals/-/web-vitals-3.4.0.tgz", - "integrity": "sha512-n9fZ5/bG1oeDkyxLWyep0eahrNcPDF6bFqoyispt7xkW0xhDzpUBTgyDKqWDi1twT0MgH4HvvqzpUyh0ZxZV4A==" + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/web-vitals/-/web-vitals-3.5.0.tgz", + "integrity": "sha512-f5YnCHVG9Y6uLCePD4tY8bO/Ge15NPEQWtvm3tPzDKygloiqtb4SVqRHBcrIAqo2ztqX5XueqDn97zHF0LdT6w==" }, "webdev-infra": { "version": "1.0.56", diff --git a/package.json b/package.json index 0d7477fb7..ad96341b2 100644 --- a/package.json +++ b/package.json @@ -93,7 +93,7 @@ "typescript": "4.7.4", "unistore": "^3.5.2", "uslug": "^1.0.4", - "web-vitals": "^3.4.0", + "web-vitals": "^3.5.0", "webdev-infra": "1.0.56", "xss": "^1.0.14" }, From 6ad11e604a713a256a496e14fc224d827cfa5e60 Mon Sep 17 00:00:00 2001 From: Joe Medley <jmedley@google.com> Date: Thu, 28 Sep 2023 07:26:18 -0700 Subject: [PATCH 825/982] Update deprecation notice for apps. (#6387) * Update deprecation notice for apps. * Update namespace-reference.njk * Update site/_includes/layouts/namespace-reference.njk Co-authored-by: Sebastian Benz <sebastian.benz@gmail.com> * Update site/_includes/layouts/reference-landing.njk Co-authored-by: Oliver Dunk <oliverdunk@google.com> * Fix and aside. * Update site/_includes/layouts/reference-landing.njk Co-authored-by: amysteamdev <37001393+AmySteam@users.noreply.github.com> * Update site/_includes/layouts/reference-landing.njk --------- Co-authored-by: Sebastian Benz <sebastian.benz@gmail.com> Co-authored-by: Oliver Dunk <oliverdunk@google.com> Co-authored-by: amysteamdev <37001393+AmySteam@users.noreply.github.com> --- site/_includes/layouts/namespace-reference.njk | 3 ++- site/_includes/layouts/reference-landing.njk | 9 +++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/site/_includes/layouts/namespace-reference.njk b/site/_includes/layouts/namespace-reference.njk index e46b683b8..dde6afd84 100644 --- a/site/_includes/layouts/namespace-reference.njk +++ b/site/_includes/layouts/namespace-reference.njk @@ -51,7 +51,8 @@ {% if f.platformAppsOnly %} <div class="aside aside--warning"> - This API is part of the deprecated Chrome Apps platform. + This API is part of the Chrome Apps platform, which was deprecated in 2020. + It remains supported for Enterprise and Education customers on ChromeOS until at least Jan 2025. Learn more about <a href="/docs/apps/migration">migrating your app</a>. </div> {% endif %} diff --git a/site/_includes/layouts/reference-landing.njk b/site/_includes/layouts/reference-landing.njk index 3c3f9f877..05df1eeba 100644 --- a/site/_includes/layouts/reference-landing.njk +++ b/site/_includes/layouts/reference-landing.njk @@ -32,11 +32,12 @@ <h2 id="platform_apps_apis">Platform Apps APIs</h2> <p> - These APIs support Chrome Apps on all platforms. + These APIs support Chrome Apps. </p> <div class="aside aside--warning"> - These APIs are deprecated. - Chrome will be removing support for Chrome Apps on all platforms. + These APIs were deprecated in 2020. They are + supported only for ChromeOS until at least Jan 2025. + It remains supported for Enterprise and Education customers on ChromeOS until at least Jan 2025. Learn more about <a href="/docs/apps/migration">migrating your app</a>. </div> {{ macros.renderReferenceTableForCollection(collections.reference, '', true) }} @@ -78,4 +79,4 @@ {% include 'partials/toc-side.njk' %} </div> </div> -{% endblock %} \ No newline at end of file +{% endblock %} From eaef0ae0270d5b778b1af6c2ee54624a8b299c4f Mon Sep 17 00:00:00 2001 From: Rachel Andrew <rachelandrew@google.com> Date: Fri, 29 Sep 2023 03:25:39 +0100 Subject: [PATCH 826/982] VT case studies article (#7409) * VT case studies article * Extended video width in case study article. * Jiggered some video widths. * Converted GIFs to video. --------- Co-authored-by: Jeremy Wagner <jlwagner@google.com> --- package-lock.json | 3 + site/_data/authorsData.json | 4 + site/_data/i18n/authors.yaml | 6 +- .../view-transitions-case-studies/index.md | 389 ++++++++++++++++++ 4 files changed, 401 insertions(+), 1 deletion(-) create mode 100644 site/en/blog/view-transitions-case-studies/index.md diff --git a/package-lock.json b/package-lock.json index 586398eff..976b0befb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -779,6 +779,7 @@ "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.18.6.tgz", "integrity": "sha512-1auuwmK+Rz13SJj36R+jqFPMJWyKEDd7lLSdOj4oJK0UTgGueSAtkrCvz9ewmgyU/P941Rv2fQwZJN8s6QruXw==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-dynamic-import instead.", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.18.6", @@ -795,6 +796,7 @@ "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz", "integrity": "sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-nullish-coalescing-operator instead.", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.18.6", @@ -811,6 +813,7 @@ "version": "7.21.0", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.21.0.tgz", "integrity": "sha512-p4zeefM72gpmEe2fkUr/OnOXpWEf8nAgk7ZYVqqfFiyIG7oFfVZcCrU64hWn5xp4tQ9LkV4bTIa5rD0KANpKNA==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-optional-chaining instead.", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.20.2", diff --git a/site/_data/authorsData.json b/site/_data/authorsData.json index fcb1d19a1..f54436700 100644 --- a/site/_data/authorsData.json +++ b/site/_data/authorsData.json @@ -1933,5 +1933,9 @@ "github": "iforfota7", "linkedin": "ioana-forfota-41116b260", "image": "image/5eDxoIGI8JgwfKolhnOVPEVCaGu2/ld1F0IaoJE3rFI2jlILo.png" + }, + "saurabhrajpal": { + "twitter": "imsaurabhrajpal", + "image": "image/ZDZVuXt6QqfXtxkpXcPGfnygYjd2/pgfTCNTb5C2ThMcZCzPQ.jpg" } } diff --git a/site/_data/i18n/authors.yaml b/site/_data/i18n/authors.yaml index da978137a..19e7e8a82 100644 --- a/site/_data/i18n/authors.yaml +++ b/site/_data/i18n/authors.yaml @@ -1582,4 +1582,8 @@ silviaeremia7: en: 'Silvia Eremia' description: en: 'STEP Intern, Chrome DevTools team' - +saurabhrajpal: + title: + en: Saurabh Rajpal + description: + en: Web Ecosystem Consultant. diff --git a/site/en/blog/view-transitions-case-studies/index.md b/site/en/blog/view-transitions-case-studies/index.md new file mode 100644 index 000000000..339451d77 --- /dev/null +++ b/site/en/blog/view-transitions-case-studies/index.md @@ -0,0 +1,389 @@ +--- +layout: 'layouts/blog-post.njk' +title: Seamless navigation made possible with view transitions +description: > + An in-depth walkthrough of how and why CyberAgent, RedBus, Nykaa, and PolicyBazaar implemented view transitions. +hero: image/kheDArv5csY6rvQUJDbWRscckLr1/n1NuTA2jvVGsNzbJdNDv.png +thumbnail: image/kheDArv5csY6rvQUJDbWRscckLr1/I0szC9KECv6eSWbggsnh.png +alt: '' +authors: + - yurikoh + - saurabhrajpal +date: 2023-09-28 +--- + +Transitions have numerous benefits for users, including helping to keep them in context and reduce the perception of latency. Developers want the ability to create seamless transitions between pages, helping to increase user engagement with their site. + +However, enabling [state transitions was really hard](/docs/web-platform/view-transitions/#why-do-we-need-this-feature) as it required developers to manage states of two different elements. Even something like a simple cross-fade involves both states being present at the same time. That presents usability challenges, such as handling additional interaction on the outgoing element. For users of assistive devices, there's a period where both the before and after state are in the DOM at the same time. In addition, things may move around the tree in a way that's fine visually, but can easily cause reading position and focus to be lost. + +Launched in Chrome 111, the [View Transitions API](https://developer.mozilla.org/docs/Web/API/View_Transitions_API) enables the creation of smooth and simple transitions between pages. It allows you to make your DOM change without any overlap between states, and to have a transition animation between the states using snapshotted views. + +You might wonder, how easy is it to implement? What kind of use cases are there? How are other developers using view transitions? + +This article takes you through the implementation of view transitions in 4 different websites: [RedBus](#redbus) (travel), [CyberAgent](#cyberagent) (news/blog publisher), [Nykaa](#nykaa) (eCommerce), and [PolicyBazaar](#policybazaar) (insurance) and how their websites benefited in different ways by using the View Transitions API. + +## redBus {: #redbus } + +redBus, part of MakeMyTrip group, is a bus booking and ticketing website headquartered in Bangalore, India with presence across different geographies globally. It was one of the first websites to implement an experience using the View Transitions API. + +### Why did Redbus implement view transitions? + +The team at redBus are firm believers in providing a unified, app-like web experience, one that is as close as possible to their native apps. In fact, they had implemented multiple customized solutions over the years. For example, they rolled out customized JavaScript and CSS based animations for the page transitions even before the View Transitions API was developed. However, that meant they had to deal with performance management in lower segments of network and devices, occasionally leading to differential experience with an [adaptive loading](https://web.dev/adaptive-loading-cds-2019/) strategy in place. + +redBus used view transitions for multiple user journeys. For example, in their self-help section within their mobile app which opened web pages in Custom Chrome Tabs, and in their bus ticket booking funnel where users go from inventory listing page to payments page. In the latter case, view transitions made page to page navigation smoother and resulted in an increase to their conversion rate. This was a result of a better user experience and better [perceived performance](https://developer.mozilla.org/docs/Learn/Performance/Perceived_performance) while the heavy operations—such as fetching the most updated available inventory—were executed. + +{% Video src="video/jL3OLOhcWUQDnR4XjewLBx4e3PC3/unuLWSZrl0daxIzor6KU.mp4", width="554", height="1210", autoplay="true", controls="false", playsinline="true", loop="true" %} + +### Technical details of implementation + +redBus uses React and [EJS](https://ejs.co/) as their frontend tech stack, with a combination of SPAs and MPAs across different journeys. The following code excerpt shows how view transitions are used: + +```js +/* Forward Transition */ +export const goToURL = ( url: string , reactHistory: any ): void => { + if(document.startViewTransition) { + let viewTransition = document.startViewTransition(); + viewTransition.ready.finally(() => { + reactHistory ? reactHistory.push(url) : (window.location.href = url); + }) + } else { + reactHistory ? reactHistory.push(url) : (window.location.href = url); + } +}; + +/* Back Transition */ +export const goBack = ( reactHistory: any ): void => { + if(document.startViewTransition) { + document.documentElement.classList.add('back-transition'); + let viewTransition = document.startViewTransition(); + viewTransition.ready.finally(() => { + reactHistory ? reactHistory.goBack() : history.back(); + }) + viewTransition.finished.finally(() => { + document.documentElement.classList.remove('back-transition'); + }) + } else { + reactHistory ? reactHistory.goBack() : history.back(); + } +}; +``` + +In the following CSS, `slide-to-right`, `slide-to-left`, `slide-from-right`, and `slide-from-left` are css animation keyframes. + +```css +::view-transition-old(root) { + animation: 300ms cubic-bezier(0.4, 0, 1, 1) both fade-out, + 300ms cubic-bezier(0.4, 0, 0.2, 1) both slide-to-left; +} +::view-transition-new(root) { + animation: 700ms cubic-bezier(0, 0, 0.2, 1) 90ms both fade-in, + 700ms cubic-bezier(0.4, 0, 0.2, 1) both slide-from-right; +} +.back-transition::view-transition-old(root) { + animation: 300ms cubic-bezier(0.4, 0, 1, 1) both fade-out, + 300ms cubic-bezier(0.4, 0, 0.2, 1) both slide-to-right; +} +.back-transition::view-transition-new(root) { + animation: 700ms cubic-bezier(0, 0, 0.2, 1) 90ms both fade-in, + 700ms cubic-bezier(0.4, 0, 0.2, 1) both slide-from-left; +} +``` + +## Business impact + +redBus chose to implement view transitions along with INP improvement efforts across their site, which led to [7% more sales](https://web.dev/redbus-inp/). [Amit Kumar](https://amitkumar-v.medium.com/), Senior Engineering Manager at redBus, said that view transitions are really awesome for those who genuinely want better user experience and desire less maintenance overhead. + +<blockquote><p>"We have conducted comprehensive user feedback sessions, incorporating valuable insights from a diverse group of users. Our deep understanding of our user base (bus and rail) and their needs, combined with our expertise, has led us to believe that this feature will provide significant value right from the start, without the need for A/B testing. View transitions are a step towards bridging the gap between app and web with a smooth navigation experience."</p> + +<cite>Anoop Menon, CTO redBus</cite> +</blockquote> + +## CyberAgent {: #cyberagent } + +CyberAgent is a Japan-based IT company that provides many online services, including blog and news publishing. + +### Why did CyberAgent implement view transitions? + +CyberAgent had considered using CSS animations or using a framework to implement animated transitions to improve user experience in the past, but they were concerned with the poor performance in rendering DOM and code maintainability. When Chrome added support for the View transitions API, they were excited to use it to create engaging page transitions that overcame these challenges. + +CyberAgent implemented view transitions between the blog list and the blog page. Here, notice how they added the element transition to the hero image. You can [visit their site](https://about.ameba.jp/ameyoko/) and experience it live today. + +<div style="width:400px;margin: 0 auto;"> + +{% Video src="video/kheDArv5csY6rvQUJDbWRscckLr1/dtTlLXCs6iQFHqStt9Is.mp4", controls="true", playsinline="true", width="400", height="866" %} + +</div> + +They also used media queries to design different animation experiences for different devices. For mobile pages they included element transitions, but this effect had too much movement for desktop. + +```css +@media screen and (min-width: 769px) { + .main-visual { + view-transition-name: none !important; + } +} +``` + +{% Video src="video/kheDArv5csY6rvQUJDbWRscckLr1/KUmW2vQJyUeJ4bc0wtg1.mp4", controls="true", playsinline="true", width="800", height="421" %} + +### Technical details of implementation + +CyberAgent uses [Next.js](http://Next.js) to build their SPA. The following code example demonstrates how they use the View Transition API. + +```js +export const usePageTransition = () => { + const router = useRouter(); + const defferedRef = useRef<Deferred | null>(null); + + useEffect(() => { + const handleRouteChangeComplete = () => { + defferedRef.current?.resolve(); + }; + + const handleRouteChangeStart = (url: string) => { + if (!("startViewTransition" in document)) return; + if (router.asPath === url) return; + + const deffered = new Deferred(); + defferedRef.current = deffered; + (document as Document).startViewTransition(async () => { + await deffered.promise; + }); + }; + + router.events.on("routeChangeStart", handleRouteChangeStart); + router.events.on("routeChangeComplete", handleRouteChangeComplete); + + return () => { + router.events.off("routeChangeStart", handleRouteChangeStart); + router.events.off("routeChangeComplete", handleRouteChangeComplete); + }; + }, [router.asPath]); +}; +``` + +View some more [sample Next.js code](https://github.com/noamr/use-view-transitions#nextjs). + +### View Transitions for MPA with prerendering technology + +CyberAgent also tried out our new [View Transitions API for Multiple Page Apps (MPA)](https://github.com/WICG/view-transitions/blob/main/cross-doc-explainer.md) (currently under the flag `chrome://flags/#view-transition-on-navigation`) on a service called [Ameba News](https://news.ameba.jp/), which is a news portal site. + +View transitions were used in two places: The first is when changing the categories of the news, shown in the following video. + +<div style="width:400px;margin: 0 auto;"> + +{% Video src="video/kheDArv5csY6rvQUJDbWRscckLr1/lBWtlrPjLUNnlJRhUj6j.mp4", controls="true", playsinline="true", width="614", height="1328" %} + +</div> + +The second is between the news highlight page, where an excerpt of the content is shown, and when the user clicks to **See more details**, the rest of the article is faded in. + +The interesting point is that they only added animation to the part that will change after the button is clicked. This little tweak of the animation design makes the MPA page appear more like an SPA from the user point of view, with only the new content animating in: + +<div style="width:400px;margin: 0 auto;"> + +{% Video src="video/kheDArv5csY6rvQUJDbWRscckLr1/iBcOunsEk64gxMtXJSbW.mp4", controls="true", playsinline="true", width="614", height="1328" %} + +</div> + +Here's how they did this: they assigned a different `view-transition-name` to the different parts of the page. For example, they assigned one `view-transition-name` to the top part of the article, another for the bottom part, and added no animation to the top part. + +```css +::view-transition-old(root) { + animation: + var(--animation-disappear-duration) var(--animation-disappear-easing) both fade-out; + } + +::view-transition-new(root) { + animation: + var(--animation-appear-in-duration) var(--animation-appear-in-easing) both fade-in; +} +``` + +{% Img src="image/kheDArv5csY6rvQUJDbWRscckLr1/9jxJ9TC2lF6OhOqS2JQ6.png", alt="A diagram showing how the top part of the page does not animated, while the bottom part transitions.", width="800", height="450" %} + +Another interesting thing about CyberAgent's use of the view transitions API is that they used [quicklink](https://github.com/GoogleChromeLabs/quicklink#quicklinkprerenderurls) to easily implement [prerendering rules](/blog/prerender-pages/#the-speculation-rules-api) on the details page. Here's their sample code: + +```js +import { prerender } from ‘https://.../quicklink.mjs’; + +window.addEventListener('load', () => { + const match = location.pathname.match(/\\/(.+)\\/hl\\/([0-9a-z-_]+)/); + if (!match) return; + const [_, dirname, entryId] = match; + prerender(`/${dirname}/${entryId}/`); + }); +``` + +You can read more about their quicklink implementation from [this article](https://developers.cyberagent.co.jp/blog/archives/37264/). + +### Testimonial + +Kazunari Hara, the Tech Lead of the Ameba service in CyberAgent, said that the view transitions could have significant impact on the business for two reasons. + +Firstly, they guide users on the page. View transitions make it possible to visually focus users on the most important message, and helps them get the most out of the web page. Also, they enhance and emphasize the brand with animation. CyberAgent has a [designated animation design](https://spindle.ameba.design/styles/animation/) to communicate their brand. With view transitions they are able to implement this branded experience without adding the cost of maintaining external libraries. + +<blockquote><p>View Transitions is one of my favorite APIs. The ability to add animations as a standard browser feature makes view transitions easier to implement and maintain compared to other solutions dependent on libraries. We are looking forward to implementing view transitions to more services to communicate our brand.</p> +<cite>Kazunari Hara, CTO of Ameba</cite> +</blockquote> + +## Nykaa {: #nykaa } + +Nykaa is India's largest fashion and beauty eCommerce platform. They aim to make their mobile web experience as close as possible to their native app experience. When previously attempting to implement transition animations, they struggled with writing complex custom JavaScript. This also impacted their website's performance marginally. + +### Why did Nykaa implement view transitions? + +With the arrival of view transitions, Nykaa's team saw an opportunity where these transitions being natively available meant the UX of page transitions could be significantly improved with no cost to performance. Nykaa is heavily using view transitions to transition from the product detail page to the product listing page. + +<div style="width:400px;margin: 0 auto;"> + +{% Video src="video/kheDArv5csY6rvQUJDbWRscckLr1/qFrexqTRjmKDRohEATEh.mp4", controls="true", playsinline="true", width="672", height="1478" %} + +</div> + +### Technical details of implementation + +Nykaa used React and [Emotion](https://emotion.sh/docs/introduction) to build their SPA. More sample code on how to use View Transitions with React can be found [here](/docs/web-platform/view-transitions/#working-with-frameworks). + +```js +if (document.startViewTransition) { + document.startViewTransition(() => { + history.push(productUrl); + }); + } else { + history.push(productUrl); + } + +const fadeIn = keyframes` + from { opacity: 0; } +`; + +const fadeOut = keyframes` + to { opacity: 0; } +`; + +const slideFromRight = keyframes` + from { transform: translateX(300px); } +`; + +const slideToLeft = keyframes` + to { transform: translateX(-300px); } +`; + +const slideToRight = keyframes` + to { transform: translateX(300px); } +`; + +const slideFromLeft = keyframes` + from { transform: translateX(-300px); } +` +``` + +CSS for side drawer animation: + +```css +::view-transition-old(root) { + animation: 300ms cubic-bezier(0.4, 0, 1, 1) both ${fadeOut}, + 1000ms cubic-bezier(0.4, 0, 0.2, 1) both ${slideToLeft}; +} + +::view-transition-new(root) { + animation: 400ms cubic-bezier(0, 0, 0.2, 1) 300ms both ${fadeIn}, + 1000ms cubic-bezier(0.4, 0, 0.2, 1) both ${slideFromRight}; +} + +.back-transition { + display: inherit; +} + +.back-transition::view-transition-old(root) { + animation-name: fade-out, ${slideToRight}; +} + +.back-transition::view-transition-new(root) { + animation-name: fade-in, ${slideFromLeft}; +} +``` + +### Testimonial + +[Sunit Jindal](https://github.com/sunitJindal), the head of apps at Nykaa, said that the biggest benefit of the view transition was the "Perception of speed". Nykaa used the [shimmer effects](https://www.geeksforgeeks.org/shimmer-effect-using-css/) to wait for the contents to load from the backend, but found that showing the shimmer effect did not provide the users with how long they would need to wait for the content to load. +With view transitions, the transition itself provided users the sense that "something is about to happen", which made the wait less painful. + +Nykaa was very excited with the newly enhanced UX of their web page with view transitions, and is ready to implement view transitions on additional pages as well. Here's what their VP of Design said: + +<blockquote><p>We are softly-committed to implement view transitions in all the upcoming features where it makes sense. Some areas have already been identified and the team is actively investing in those.</p> + +<cite>Krishna R V, VP of Design</cite> +</blockquote> + +## PolicyBazaar {: #policybazaar } + +Headquartered in Gurgaon, PolicyBazaar is India's largest insurance aggregator and multinational financial technology company. + +### Why did PolicyBazaar implement view transitions? + +Being a web-first company, PolicyBazaar team has always aimed at providing the best possible user experience across their critical user journeys. It was common practice to implement custom transitions using JavaScript and CSS even prior to the launch of the View Transitions API, as they enhanced the user experience, created a seamless navigation flow, and improved the overall visual appeal of their websites. + +However, these custom implementations came at a cost of occasional performance-based delays, code maintenance complexities and suboptimal compatibility with the frameworks used. The View Transitions API helped them overcome most of these challenges by providing an easy-to-use interface with performance benefits available natively. + +PolicyBazaar used view transitions across different elements in their pre-quote journeys to make it exciting for the potential buyers to provide their required details for purchasing insurance policies. + +{% Columns %} + +{% Column %} + +{% Video src="video/jL3OLOhcWUQDnR4XjewLBx4e3PC3/rV1Py5xQVXTXj1Ng24ZU.mp4", width="420", height="534", autoplay="true", playsinline="true", controls="false", loop="true" %} + +{% endColumn %} + +{% Column %} + +{% Video src="video/jL3OLOhcWUQDnR4XjewLBx4e3PC3/QO0R5HwJ8A3Do5hR7CCZ.mp4", width="600", height="976", loop="true", playsinline="true", controls="false", autoplay="true" %} + +{% endColumn %} + +{% endColumns %} + +### Technical details of implementation + +They use a hybrid framework approach with Angular and React dominating most of their codebase. Here's the VT excerpt from their code written in Angular and shared by Aman Soni (PolicyBazaar's Lead Frontend Developer): + +```js +toggleWidgetAnimation() { + let doc:any = document; + + if (!doc.startViewTransition) { + this.toggleWidget(); + return; + } + + doc.startViewTransition(() => this.toggleWidget()); + } + + toggleWidget() { + let badgeEle = document.querySelector('.animate_init_state_one'); + let textEle = document.querySelector('.animate_init_state_two'); + + badgeEle.classList.toggle('hide'); + textEle.classList.toggle('hide'); + } +``` + +### Testimonial + +Rishabh Mehrotra, their head of Design (Life BU), said that view transitions played a significant role in enhancing the website experience for their users by improving usability, engagement, and overall satisfaction. It helped in providing smooth navigation, guided interaction, reduced cognitive load, modern aesthetics and much more. + +<blockquote><p>Elevating the web experience stands as a paramount objective for PB, and VT has proven to be an instrumental tool in achieving this with remarkable seamlessness. Its widespread appeal among both our developer community and user base has imbued our team with a sense of enthusiasm. As we contemplate its integration across diverse PODs, we anticipate a far-reaching positive impact on satisfaction levels and operational excellence."</p> + +<cite>Saurabh Tiwari (CTO, PolicyBazaar)</cite> +</blockquote> + +## Next steps + +Are you interested in trying out view transitions? Here's are some resources you can follow up to learn more: + +- [developer.chrome.com documentation for view transitions](/docs/web-platform/view-transitions/) +- [View transitions for MPA explainer](https://github.com/WICG/view-transitions/blob/main/cross-doc-explainer.md) +- [Interop proposals to make view transitions available across browsers](https://github.com/web-platform-tests/interop/issues/437) + From a393767d87fcc6ad060070bef1c0cf20afa86d48 Mon Sep 17 00:00:00 2001 From: Thomas Steiner <steiner.thomas@gmail.com> Date: Fri, 29 Sep 2023 01:33:53 -0400 Subject: [PATCH 827/982] [Deprecating Web SQL article] Update deprecation timeline (#7404) * Update deprecation timeline * Update updated timeline article --- site/en/blog/deprecating-web-sql/index.md | 10 +++++----- .../blog/web-sql-deprecation-timeline-updated/index.md | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/site/en/blog/deprecating-web-sql/index.md b/site/en/blog/deprecating-web-sql/index.md index 99a661259..8a8f2049b 100644 --- a/site/en/blog/deprecating-web-sql/index.md +++ b/site/en/blog/deprecating-web-sql/index.md @@ -70,20 +70,20 @@ and outperforms Web SQL in many cases. {% Img src="image/8WbTDNrhLsU0El80frMBGE4eMCD3/AunrHQyWXS6AmECRn9oT.png", alt="Chrome DevTools Issues panel with a warning that reads Web SQL in non-secure contexts is deprecated.", width="800", height="158" %} -- [📍 We are here.] Web SQL access in **insecure contexts** is no longer +- [✅ Done.] Web SQL access in **insecure contexts** is no longer available as of **Chromium 110** ({% ChromeDate '110' %}). An **enterprise policy** to keep using the feature is available from **Chromium 110** ({% ChromeDate '110' %}) to **Chromium 123** ({% ChromeDate '123' %}). -- [🔮 In the future.] Web SQL access in **all contexts** is deprecated as of +- [✅ Done.] Web SQL access in **all contexts** is deprecated as of **Chromium 115** ({% ChromeDate '115' %}) and a warning message is shown in the Chrome DevTools Issue panel. -- [🔮 In the future.] Web SQL access in **all contexts** is no longer available - in **Chromium 119** ({% ChromeDate '119' %}) -- [🔮 In the future.] A +- [📍 We are here.] A [deprecation trial](/docs/web-platform/origin-trials/#deprecation-trials) to keep using Web SQL is available from **Chromium 117** ({% ChromeDate '117' %}) to **Chromium 123** ({% ChromeDate '123' %}). +- [🔮 In the future.] Web SQL access in **all contexts** is no longer available + in **Chromium 119** ({% ChromeDate '119' %}) ## Where to go from here diff --git a/site/en/blog/web-sql-deprecation-timeline-updated/index.md b/site/en/blog/web-sql-deprecation-timeline-updated/index.md index 869985ee0..db1039f14 100644 --- a/site/en/blog/web-sql-deprecation-timeline-updated/index.md +++ b/site/en/blog/web-sql-deprecation-timeline-updated/index.md @@ -31,19 +31,19 @@ removal in insecure contexts and eventually all contexts is planned for Chromium {% Img src="image/8WbTDNrhLsU0El80frMBGE4eMCD3/AunrHQyWXS6AmECRn9oT.png", alt="Chrome DevTools Issues panel with a warning that reads Web SQL in non-secure contexts is deprecated.", width="800", height="158" %} -- [📍 We are here.] Web SQL access in **insecure contexts** is no longer +- [✅ Done.] Web SQL access in **insecure contexts** is no longer available as of **Chromium 110** ({% ChromeDate '110' %}). An **enterprise policy** to keep using the feature is available from **Chromium 110** ({% ChromeDate '110' %}) to **Chromium 123** ({% ChromeDate '123' %}). -- [🔮 In the future.] Web SQL access in **all contexts** is deprecated as of +- [✅ Done.] Web SQL access in **all contexts** is deprecated as of **Chromium 115** ({% ChromeDate '115' %}) and a warning message is shown in the Chrome DevTools Issue panel. -- [🔮 In the future.] Web SQL access in **all contexts** is no longer available - in **Chromium 119** ({% ChromeDate '119' %}) -- [🔮 In the future.] A +- [📍 We are here.] A [deprecation trial](/docs/web-platform/origin-trials/#deprecation-trials) to keep using Web SQL is available from **Chromium 117** ({% ChromeDate '117' %}) to **Chromium 123** ({% ChromeDate '123' %}). +- [🔮 In the future.] Web SQL access in **all contexts** is no longer available + in **Chromium 119** ({% ChromeDate '119' %}) See the post [Deprecating and removing Web SQL](/blog/deprecating-web-sql/) for all details on this deprecation. From 039ac18fea33112f76f279733c2aa5c11f60b7ce Mon Sep 17 00:00:00 2001 From: Joe Medley <jmedley@google.com> Date: Fri, 29 Sep 2023 07:23:26 -0700 Subject: [PATCH 828/982] Add information about active debugger sessions and SWs. (#7387) --- .../service_workers/service-worker-lifecycle/index.md | 10 +++++++--- site/en/docs/extensions/whatsnew/index.md | 7 +++++++ 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/site/en/docs/extensions/mv3/service_workers/service-worker-lifecycle/index.md b/site/en/docs/extensions/mv3/service_workers/service-worker-lifecycle/index.md index aa7277c8a..93a785199 100644 --- a/site/en/docs/extensions/mv3/service_workers/service-worker-lifecycle/index.md +++ b/site/en/docs/extensions/mv3/service_workers/service-worker-lifecycle/index.md @@ -1,17 +1,17 @@ --- layout: 'layouts/doc-post.njk' title: The extension service worker lifecycle -subhead: +subhead: description: Extension service workers respond to both standard service worker events and events in extension namespaces. They are presented together because often one type follows another during an extension's use. date: 2023-05-02 -updated: 2023-06-27 +updated: 2023-09-27 --- Extension service workers respond to both the [standard service worker events](https://developer.mozilla.org/docs/Web/API/ServiceWorkerGlobalScope#events) and to events in extension namespaces. They are presented together because often one type follows another during an extension's use. ## Installation -Installation occurs when the user installs or updates a service worker from the Chrome Web Store or when they [load or update an unpacked extension](/docs/extensions/mv3/getstarted/development-basics/#load-unpacked) using the `chrome://extensions` page. Three events occur in the order below. +Installation occurs when the user installs or updates a service worker from the Chrome Web Store or when they [load or update an unpacked extension](/docs/extensions/mv3/getstarted/development-basics/#load-unpacked) using the `chrome://extensions` page. Three events occur in the order below. ### ServiceWorkerRegistration.install {: #install } @@ -69,6 +69,10 @@ Any global variables you set will be lost if the service worker shuts down. Inst Since the release of Manifest V3, we've made several improvements to service worker lifetimes. This means that if your Manifest V3 extension supports earlier versions of Chrome, there are conditions you will need to be aware of. If these conditions do not affect your extension, you can move on from this section. If they do, consider specifying a [minimum Chrome version](/docs/extensions/mv3/manifest/minimum_chrome_version/) in your manifest. +#### Chrome 118 + +Active debugger sessions created using the [`chrome.debugger`](/docs/extensions/reference/debugger/) API now keep the service worker alive. This prevents service workers from timing out during calls for this API. + #### Chrome 116 Chrome 116 introduced the following service worker lifetime improvements: diff --git a/site/en/docs/extensions/whatsnew/index.md b/site/en/docs/extensions/whatsnew/index.md index ac23f8603..ae47b5f11 100644 --- a/site/en/docs/extensions/whatsnew/index.md +++ b/site/en/docs/extensions/whatsnew/index.md @@ -15,6 +15,13 @@ tags: Check this page often to learn about changes to Chrome extensions, extensions documentation, or related policy or other changes. You'll find other notices posted on the [Extensions Google Group](https://groups.google.com/a/chromium.org/g/chromium-extensions). The [Extensions News](/tags/extensions-news/) tag lists articles about some of the topics listed here. (It even has [an RSS feed](/feeds/extensions-news.xml).) The [Chrome schedule](https://chromiumdash.appspot.com/schedule) lists stable and beta release dates. + +### Chrome 118: Active debugger sessions keep the service worker alive {: #active-debugger-service-worker } + +<p class="color-secondary-text type--caption">Posted on <time>September 27, 2023</time></p> + +Active debugger sessions created using the [`chrome.debugger`](/docs/extensions/reference/debugger/) API now keep the service worker alive. This prevents service workers from timing out during calls for this API. + ### Chrome 118: Changes to opening file: scheme URLs {: #changes-to-file-scheme } <p class="color-secondary-text type--caption">Posted on <time>September 15, 2023</time></p> From baa954012b492ccbd044c246ecaa41eada55c196 Mon Sep 17 00:00:00 2001 From: Joe Medley <jmedley@google.com> Date: Fri, 29 Sep 2023 07:50:17 -0700 Subject: [PATCH 829/982] Add sample search announcement to 'What's new'. (#7413) * Add sample search announcement to 'What's new'. * Update site/en/docs/extensions/whatsnew/index.md Co-authored-by: Oliver Dunk <oliverdunk@google.com> * Update site/en/docs/extensions/whatsnew/index.md * Fix date. --------- Co-authored-by: Oliver Dunk <oliverdunk@google.com> --- site/en/docs/extensions/whatsnew/index.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/site/en/docs/extensions/whatsnew/index.md b/site/en/docs/extensions/whatsnew/index.md index ae47b5f11..9411057b2 100644 --- a/site/en/docs/extensions/whatsnew/index.md +++ b/site/en/docs/extensions/whatsnew/index.md @@ -3,7 +3,7 @@ layout: 'layouts/doc-post.njk' title: What's new in Chrome extensions description: 'Recent changes to the Chrome extensions platform, documentation, and policy' date: 2021-02-25 -updated: 2023-09-15 +updated: 2023-09-29 tags: - extensions-news @@ -15,12 +15,15 @@ tags: Check this page often to learn about changes to Chrome extensions, extensions documentation, or related policy or other changes. You'll find other notices posted on the [Extensions Google Group](https://groups.google.com/a/chromium.org/g/chromium-extensions). The [Extensions News](/tags/extensions-news/) tag lists articles about some of the topics listed here. (It even has [an RSS feed](/feeds/extensions-news.xml).) The [Chrome schedule](https://chromiumdash.appspot.com/schedule) lists stable and beta release dates. +### Extension samples now searchable {: #extension-samples-searchable } -### Chrome 118: Active debugger sessions keep the service worker alive {: #active-debugger-service-worker } +<p class="color-secondary-text type--caption">Posted on <time>September 29, 2023</time></p> -<p class="color-secondary-text type--caption">Posted on <time>September 27, 2023</time></p> +We recently created a page that lets you [search Chrome extension samples](/docs/extensions/samples/). The search page has multiple options. A search box lets you search for text in sample titles. You can restrict the search by permission or extension API. An additional filter lets you restrict search to either API or functional (use case) samples. -Active debugger sessions created using the [`chrome.debugger`](/docs/extensions/reference/debugger/) API now keep the service worker alive. This prevents service workers from timing out during calls for this API. +This new sample page was built by a Google Summer of Code participant, Xuezhou Dai, who also contributed several new samples. You can read about their experiences this past summer in [their post on our blog](/blog/google-summer-of-code-and-chrome-extensions/). + +As before, [our code samples](https://github.com/GoogleChrome/chrome-extensions-samples) are still available on GitHub for cloning or forking. ### Chrome 118: Changes to opening file: scheme URLs {: #changes-to-file-scheme } From f9e86affc9c3f5d8a341774855d15de3924e83b6 Mon Sep 17 00:00:00 2001 From: Jeremy Wagner <malchata@users.noreply.github.com> Date: Fri, 29 Sep 2023 13:08:47 -0500 Subject: [PATCH 830/982] Fixes navigation preload 'after' image size per @tunetheweb. (#7416) --- site/en/docs/workbox/navigation-preload/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/en/docs/workbox/navigation-preload/index.md b/site/en/docs/workbox/navigation-preload/index.md index 946dfabc9..01b40d77a 100644 --- a/site/en/docs/workbox/navigation-preload/index.md +++ b/site/en/docs/workbox/navigation-preload/index.md @@ -20,7 +20,7 @@ Navigation preload is a service worker feature that solves the delay caused by s This isn't ideal, but you can fix it by enabling navigation preload, which ensures that service worker bootup and the navigation request occurs concurrently: -{% Img src="image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/dmuAkLpqiB8AkvIgcRm2.png", alt="Two bars stacked upon one another and left-aligned, representing two concurrent actions. The yellow bar is labeled 'SW boot', and the blue one is labeled 'Navigation request'.", width="800", height="171" %} +{% Img src="image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/WAiYKZYRuErxcouXoFd3.png", alt="Two bars stacked upon one another and left-aligned, representing two concurrent actions. The yellow bar is labeled 'SW boot', and the blue one is labeled 'Navigation request'.", width="800", height="139" %} While navigation preload is a great performance optimization for sites that use service workers, it's not a feature you should enable in all situations. In particular, sites that use a precached app shell don't need navigation preload, as the cache serves the navigation request for the app shell markup without any navigation latency. In these cases, the preloaded response will go to waste, which isn't great. From 127e7b228201d3a38321b140196879e48a136c19 Mon Sep 17 00:00:00 2001 From: Nancymic2 <nmichell@google.com> Date: Fri, 29 Sep 2023 14:46:09 -0400 Subject: [PATCH 831/982] rename FPS (#7379) * rename FPS * rename FPS * rename FPS * redirect FPS * TOC * rename FPS * link * link * Update index.md * Update index.md * Update index.md * Update index.md * Update rollout info * Update index.md * fix a few links * fix a few links --- redirects.yaml | 6 ++ site/_data/docs/privacy-sandbox/toc.yml | 4 +- .../_partials/privacy-sandbox/fps-rename.md | 3 + .../index.md | 2 +- site/en/docs/privacy-sandbox/chips/index.md | 10 +-- site/en/docs/privacy-sandbox/fedcm/index.md | 12 ++-- .../en/docs/privacy-sandbox/overview/index.md | 14 ++--- .../proposal-lifecycle/index.md | 7 +-- .../index.md | 63 ++++++++++--------- .../index.md | 26 ++++---- 10 files changed, 79 insertions(+), 68 deletions(-) create mode 100644 site/en/_partials/privacy-sandbox/fps-rename.md rename site/en/docs/privacy-sandbox/{first-party-sets-integration => related-website-sets-integration}/index.md (78%) rename site/en/docs/privacy-sandbox/{first-party-sets => related-website-sets}/index.md (67%) diff --git a/redirects.yaml b/redirects.yaml index 000aaf135..a14601d18 100644 --- a/redirects.yaml +++ b/redirects.yaml @@ -21,6 +21,12 @@ redirects: # Simple redirects +- from: /docs/privacy-sandbox/first-party-sets/ + to: /docs/privacy-sandbox/related-website-sets/ + +- from: /docs/privacy-sandbox/first-party-sets-integration/ + to: /docs/privacy-sandbox/related-website-sets-integration/ + - from: /docs/privacy-sandbox/trust-tokens/ to: /docs/privacy-sandbox/private-state-tokens/ diff --git a/site/_data/docs/privacy-sandbox/toc.yml b/site/_data/docs/privacy-sandbox/toc.yml index e2430071a..411eaea63 100644 --- a/site/_data/docs/privacy-sandbox/toc.yml +++ b/site/_data/docs/privacy-sandbox/toc.yml @@ -26,8 +26,8 @@ - title: i18n.docs.privacy-sandbox.strengthen-boundaries sections: - url: /docs/privacy-sandbox/third-party-cookie-phase-out - - url: /docs/privacy-sandbox/first-party-sets - - url: /docs/privacy-sandbox/first-party-sets-integration + - url: /docs/privacy-sandbox/related-website-sets + - url: /docs/privacy-sandbox/related-website-sets-integration - url: /docs/privacy-sandbox/first-party-sets-evolution - url: /docs/privacy-sandbox/chips - url: /docs/privacy-sandbox/storage-partitioning/ diff --git a/site/en/_partials/privacy-sandbox/fps-rename.md b/site/en/_partials/privacy-sandbox/fps-rename.md new file mode 100644 index 000000000..7957f6fa7 --- /dev/null +++ b/site/en/_partials/privacy-sandbox/fps-rename.md @@ -0,0 +1,3 @@ +{% Aside 'update' %} +First-Party Sets has been renamed to Related Website Sets. To learn more about the name change, refer to the [blog post](/blog/related-website-sets/). +{% endAside %} \ No newline at end of file diff --git a/site/en/blog/first-party-sets-testing-instructions/index.md b/site/en/blog/first-party-sets-testing-instructions/index.md index fde7bae43..5257516e3 100644 --- a/site/en/blog/first-party-sets-testing-instructions/index.md +++ b/site/en/blog/first-party-sets-testing-instructions/index.md @@ -11,7 +11,7 @@ alt: A diagram showing First-Party Sets. One set contains domains example.com, example.rs, and example.co.uk. The other set contains brandx.site, fly-brandx.site, and drive-brandx.site. is_outdated: true -new_available_content_url: /docs/privacy-sandbox/first-party-sets-integration/ +new_available_content_url: /docs/privacy-sandbox/related-website-sets-integration/ tags: - privacy authors: diff --git a/site/en/docs/privacy-sandbox/chips/index.md b/site/en/docs/privacy-sandbox/chips/index.md index 9797a092b..1db61fdc8 100644 --- a/site/en/docs/privacy-sandbox/chips/index.md +++ b/site/en/docs/privacy-sandbox/chips/index.md @@ -27,7 +27,7 @@ tags: Cookies Having Independent Partitioned State (CHIPS) allows developers to opt a cookie into partitioned storage, with separate cookie jars per top-level site, improving user privacy and security. -Browsers are well under way in phasing out unpartitioned third-party cookies, so CHIPS and [First-Party Sets](/first-party-sets) will be the only way to read and write cookies from cross-site contexts, such as iframes, when third-party cookies are blocked. +Browsers are well under way in phasing out unpartitioned third-party cookies, so CHIPS and [Related Website Sets](/docs/privacy-sandbox/related-website-sets/) ([formerly called First-Party Sets](/blog/related-website-sets/)) will be the only way to read and write cookies from cross-site contexts, such as iframes, when third-party cookies are blocked. Without partitioning, third-party cookies can enable services to track users and join their information from across many unrelated top-level sites. This is known as cross-site tracking. @@ -142,13 +142,13 @@ key={("https", "retail.example"), Chrome has a limit of maximum 180 cookies per partition that cannot exceed 10 KB per-embedded-site. {% endAside %} -#### First-Party Sets and cookie partitioning +#### Related Website Sets and cookie partitioning -[First-Party Sets (FPS)](/first-party-sets-integration) is a web platform mechanism for developers to declare relationships among sites, so that browsers can use this information to enable limited cross-site cookie access for specific, user-facing purposes. Chrome will use these declared relationships to decide when to allow or deny a site access to their cookies when in a third-party context. +[Related Website Sets (RWS)](/docs/privacy-sandbox/related-website-sets-integration/) is a web platform mechanism for developers to declare relationships among sites, so that browsers can use this information to enable limited cross-site cookie access for specific, user-facing purposes. Chrome will use these declared relationships to decide when to allow or deny a site access to their cookies when in a third-party context. -The current First-Party Sets design relies on Storage Access API and does not integrate with CHIPS partitioning. +The current Related Website Sets design relies on Storage Access API and does not integrate with CHIPS partitioning. -Consider First-Party Sets in situations where you need the same cookie to be available to a service that's embedded in multiple related sites. +Consider Related Website Sets in situations where you need the same cookie to be available to a service that's embedded in multiple related sites. CHIPS provides the functionality for a service to act as an isolated component across multiple sites. If the service that's a member of a First-Party Set sets a partitioned cookie, its partition key will be the top-level site and that cookie will not be available to other set members. diff --git a/site/en/docs/privacy-sandbox/fedcm/index.md b/site/en/docs/privacy-sandbox/fedcm/index.md index 6acb4c292..a6510b74a 100644 --- a/site/en/docs/privacy-sandbox/fedcm/index.md +++ b/site/en/docs/privacy-sandbox/fedcm/index.md @@ -127,8 +127,8 @@ We expect FedCM to be useful to you only if **all** these conditions apply: 1. You're affected by the third-party cookie phase out. 1. Your RPs are third-parties. If your RPs are [SameParty](/blog/first-party-sets-sameparty/), you may be better served - by [First-Party - Sets](/docs/privacy-sandbox/first-party-sets/). + by [Related Website + Sets](/docs/privacy-sandbox/related-website-sets/), [formerly called First-Party Sets](/blog/related-website-sets/). ### You're an IdP {: #idp } @@ -156,12 +156,12 @@ that the phase-out is expected to affect. ### Your RPs are third-party If you're an identity provider whose RPs are within the [same -party](/blog/first-party-sets-sameparty/#first-party-sets-policy) as your IdP, we expect [First-Party Sets](/docs/privacy-sandbox/first-party-sets/) -may be a better option. First-Party Sets allow related domain names owned and operated by the same entity to declare themselves as belonging to the same first-party. This allows the same party's third-party cookies to work, even after third-party cookie phase-out. +party](/blog/first-party-sets-sameparty/#first-party-sets-policy) as your IdP, we expect [Related Website Sets](/docs/privacy-sandbox/related-website-sets/) + may be a better option. Related Website Sets allow related domain names owned and operated by the same entity to declare themselves as belonging to the same first-party. This allows the same party's third-party cookies to work, even after third-party cookie phase-out. -First-Party Sets can't always be used. However, if your RPs are +Related Website Sets can't always be used. However, if your RPs are [SameParty](/blog/first-party-sets-sameparty/#first-party-sets-policy), -consider using First-Party Sets. +consider using Related Website Sets. ## How will users interact with FedCM? {: #use-cases} diff --git a/site/en/docs/privacy-sandbox/overview/index.md b/site/en/docs/privacy-sandbox/overview/index.md index 7954dbb32..f382f4f5f 100644 --- a/site/en/docs/privacy-sandbox/overview/index.md +++ b/site/en/docs/privacy-sandbox/overview/index.md @@ -56,7 +56,7 @@ Several key proposals are listed below. * [**CHIPS**](/docs/privacy-sandbox/chips/) (released): Allow developers to opt-in a cookie to partitioned storage, with a separate cookie jar per top-level site. -* [**First-Party Sets**](/docs/privacy-sandbox/first-party-sets) (released): Allow related +* [**Related Website Sets**](/docs/privacy-sandbox/related-website-sets/) ([Formerly called First-Party Sets](/blog/related-website-sets/). Released.): Allow related domain names owned by the same entity to declare themselves as belonging to the same first party. * [**Shared Storage**](/docs/privacy-sandbox/shared-storage/) (released): Create a @@ -67,7 +67,7 @@ Several key proposals are listed below. such as `localStorage` or cookies, to be double-keyed: by the top-level site as well as the origin of the resource being loaded, rather than a single origin or site. -* [**Fenced Frames**](/docs/privacy-sandbox/fenced-frame) (released): Securely embed +* [**Fenced Frames**](/docs/privacy-sandbox/fenced-frame/) (released): Securely embed content onto a page without sharing cross-site data. * [**Network State Partitioning**](https://github.com/MattMenke2/Explainer---Partition-Network-State): Prevent browser network resources being shared across first-party contexts, @@ -83,7 +83,7 @@ Several key proposals are listed below. * [**Topics API**](/docs/privacy-sandbox/topics) (released): Enable interest-based advertising without use of third-party cookies or tracking user behavior across sites. -* [**Protected Audience API**](/docs/privacy-sandbox/protected-audience) (released): Ad selection to serve remarketing +* [**Protected Audience API**](/docs/privacy-sandbox/protected-audience/) (released): Ad selection to serve remarketing and custom audience use cases, designed so that it cannot be used by third parties to track user browsing behavior across sites. The Protected Audience API is the first experiment to be implemented in Chromium from the @@ -91,9 +91,9 @@ Several key proposals are listed below. ### Measure digital ads -* [**Attribution Reporting**](/docs/privacy-sandbox/attribution-reporting) (released): +* [**Attribution Reporting**](/docs/privacy-sandbox/attribution-reporting/) (released): Correlate ad clicks or ad views with conversions. Ad techs can generate - event-level or [summary reports](/docs/privacy-sandbox/summary-reports). + event-level or [summary reports](/docs/privacy-sandbox/summary-reports/). * [**Private Aggregation API**](/docs/privacy-sandbox/private-aggregation/) (released): Generate noisy summary reports with cross-site data. @@ -114,7 +114,7 @@ Several key proposals are listed below. ### Fight spam and fraud on the web -* [**Private State Tokens**](/docs/privacy-sandbox/trust-tokens) (released): Allow +* [**Private State Tokens**](/docs/privacy-sandbox/private-state-tokens/) (released): Allow websites to convey a limited amount of information from one browsing context to another (for example, across sites) to help combat fraud, without passive tracking. @@ -194,7 +194,7 @@ turned on. The exception is cookies that are modified by either the [CHIPS](/docs/privacy-sandbox/chips/) or -[First-Party Sets](/docs/privacy-sandbox/first-party-sets/). +[Related Website Sets](/docs/privacy-sandbox/related-website-sets/). These allow for a subset of cross-site use cases. As these features and APIs are under active discussion, the final formats and functionality may change. diff --git a/site/en/docs/privacy-sandbox/proposal-lifecycle/index.md b/site/en/docs/privacy-sandbox/proposal-lifecycle/index.md index e76da4d30..385fad1a7 100644 --- a/site/en/docs/privacy-sandbox/proposal-lifecycle/index.md +++ b/site/en/docs/privacy-sandbox/proposal-lifecycle/index.md @@ -8,7 +8,7 @@ description: > How we collaborate with stakeholders to discuss, test, and adopt privacy-preserving technologies. date: 2022-03-30 -updated: 2023-09-18 +updated: 2023-09-26 authors: - alexandrawhite --- @@ -209,10 +209,9 @@ come. The following technologies are now available: * [CHIPS](/docs/privacy-sandbox/chips/): Allow developers to opt-in a cookie to partitioned storage, with a separate cookie jar per top-level site. CHIPS became available in Stable in February 2023. -* [First-Party Sets](/docs/privacy-sandbox/first-party-sets/): Declare +* [Related Website Sets](/docs/privacy-sandbox/related-website-sets/) ([formerly called First-Party Sets](/blog/related-website-sets/)): Declare relationships among sites to allow for limited cross-site cookie access using - the Storage Access API. First-Party Sets is slowly rolling out with Chrome - Stable version 113, this week. + the Storage Access API. Related Website Sets is now in general availability. * [Federated Credential Management (FedCM)](/docs/privacy-sandbox/fedcm/): Support federated identity without sharing the user's email address or other identifying information with a third-party service or website, unless the diff --git a/site/en/docs/privacy-sandbox/first-party-sets-integration/index.md b/site/en/docs/privacy-sandbox/related-website-sets-integration/index.md similarity index 78% rename from site/en/docs/privacy-sandbox/first-party-sets-integration/index.md rename to site/en/docs/privacy-sandbox/related-website-sets-integration/index.md index 1e80855f6..18090d035 100644 --- a/site/en/docs/privacy-sandbox/first-party-sets-integration/index.md +++ b/site/en/docs/privacy-sandbox/related-website-sets-integration/index.md @@ -1,6 +1,6 @@ --- layout: 'layouts/blog-post.njk' -title: "First-Party Sets: developer guide" +title: "Related Website Sets: developer guide" date: 2023-01-12 updated: 2023-05-10 thumbnail: 'image/vgdbNJBYHma2o62ZqYmcnkq3j0o1/SV7SXAQRcVnBZEgjgxYc.png' @@ -13,14 +13,15 @@ authors: - sarino --- +{% Partial 'privacy-sandbox/fps-rename.njk' %} -[First-Party Sets (FPS)](docs/privacy-sandbox/first-party-sets/) is a web platform mechanism which helps browsers to understand the relationships amongst a collection of domains. This allows browsers to make key decisions to enable certain site functions (such as whether to allow access to cross-site cookies) and to present this information to users. +[Related Website Sets (RWS)](docs/privacy-sandbox/related-website-sets/) is a web platform mechanism which helps browsers to understand the relationships amongst a collection of domains. This allows browsers to make key decisions to enable certain site functions (such as whether to allow access to cross-site cookies) and to present this information to users. -As Chrome deprecates third-party cookies, its goal is to maintain key use cases on the web while improving privacy for users. For example, many sites rely on multiple domains to serve a single user experience. Organizations may want to maintain different top-level domains for multiple use cases like country specific domains or service domains for hosting images or video. FPS allows sites to share data across domains, with specific controls. +As Chrome deprecates third-party cookies, its goal is to maintain key use cases on the web while improving privacy for users. For example, many sites rely on multiple domains to serve a single user experience. Organizations may want to maintain different top-level domains for multiple use cases like country specific domains or service domains for hosting images or video. Related Website Sets allows sites to share data across domains, with specific controls. -## What is a First-Party Set +## What is a Related Website Set? -At a high level, a First-Party Set is a collection of domains, for which there is a single "set primary" and potentially multiple "set members". +At a high level, a Related Website Set is a collection of domains, for which there is a single "set primary" and potentially multiple "set members." In the example below, `primary` lists the primary domain, and `associatedSites` lists domains that meet the requirements of the [associated subset](https://github.com/GoogleChrome/first-party-sets/blob/main/FPS-Submission_Guidelines.md#set-formation-requirements). @@ -31,19 +32,19 @@ In the example below, `primary` lists the primary domain, and `associatedSites` } ``` -The canonical FPS list is a publicly viewable list in a JSON file format hosted in the [FPS GitHub repository](https://github.com/googlechrome/first-party-sets), which serves as the source-of-truth for all sets. Chrome consumes this file to apply to its behavior. +The canonical Related Website Sets list is a publicly viewable list in a JSON file format hosted in the [Related Website Sets GitHub repository](https://github.com/googlechrome/first-party-sets), which serves as the source-of-truth for all sets. Chrome consumes this file to apply to its behavior. -Only those with administrative control over a domain can create a set with that domain. Submitters are required to declare the relationship between each "set member" to its "set primary". Set members could include a range of different domain types and must be part of a [subset based on a use case](https://github.com/GoogleChrome/first-party-sets/blob/main/FPS-Submission_Guidelines.md#set-formation-requirements). +Only those with administrative control over a domain can create a set with that domain. Submitters are required to declare the relationship between each "set member" to its "set primary." Set members could include a range of different domain types and must be part of a [subset based on a use case](https://github.com/GoogleChrome/first-party-sets/blob/main/FPS-Submission_Guidelines.md#set-formation-requirements). -If your application depends on access to cross-site cookies (also called third-party cookies) across sites within the same First-Party Set, you can use [Storage Access API (SAA)](https://privacycg.github.io/storage-access/) and the [requestStorageAccessFor API](https://privacycg.github.io/requestStorageAccessFor/) to request access to those cookies. Depending on the subset that each site is part of, the browser may handle the request differently. +If your application depends on access to cross-site cookies (also called third-party cookies) across sites within the same Related Website Set, you can use [Storage Access API (SAA)](https://privacycg.github.io/storage-access/) and the [requestStorageAccessFor API](https://privacycg.github.io/requestStorageAccessFor/) to request access to those cookies. Depending on the subset that each site is part of, the browser may handle the request differently. To learn more about the process and requirements for submitting sets, check out the [submission guidelines](https://github.com/GoogleChrome/first-party-sets/blob/main/FPS-Submission_Guidelines.md). Submitted sets will go through various technical checks to validate the submissions. -## FPS use cases +## Related Website Sets use cases -First-Party Sets are a good match for cases when an organization needs a form of shared identity across different top-level sites. +Related Website Sets are a good match for cases when an organization needs a form of shared identity across different top-level sites. -Some of the use cases for FPS are: +Some of the use cases for Related Website Sets are: - **Country customization**. Leveraging localized sites while relying on shared infrastructure (example.co.uk may rely on a service hosted by example.ca). - **Service domain integration**. Leveraging service domains that users never directly interact with, but provide services across the same organization's sites (example-cdn.com). @@ -53,7 +54,7 @@ Some of the use cases for FPS are: - **Analytics**. Deploying analytics and measurement of user journeys across affiliated properties to improve quality of services. -## FPS integration details +## Related Website Sets integration details ### Storage Access API @@ -61,7 +62,7 @@ The [Storage Access API (SAA)](https://privacycg.github.io/storage-access/) prov Embedded resources can use SAA methods to check whether they currently have access to storage, and to request access from the user agent. -When third-party cookies are blocked, but First-Party Sets are allowed, Chrome will automatically grant that permission for sites within the set and deny it for sites outside the set. +When third-party cookies are blocked, but Related Website Sets are allowed, Chrome will automatically grant that permission for sites within the set and deny it for sites outside the set. {% Aside %} SAA is shipping in several browsers, however there are [differences between browser implementations](https://developer.mozilla.org/docs/Web/API/Storage_Access_API#safari_implementation_differences) in the rules of handling storage access. @@ -202,7 +203,7 @@ function rSA() { } ``` -Subsequent requests from within the frame, navigations or subresources, will automatically have permission for accessing cross-site cookies. `hasStorageAccess()` returns true and cross-site cookies from the same First-Party Set will be sent on those requests without any additional JavaScript calls. +Subsequent requests from within the frame, navigations or subresources, will automatically have permission for accessing cross-site cookies. `hasStorageAccess()` returns true and cross-site cookies from the same Related Website Set will be sent on those requests without any additional JavaScript calls. ### Top-level sites requesting cookie access on behalf of cross-origin sites @@ -275,17 +276,17 @@ function checkCookie() { ### Prerequisites -To test FPS locally, use Chrome 113 or higher launched from the command line. +To test Related Website Sets locally, use Chrome 113 or higher launched from the command line. To preview upcoming Chrome features before they're released, download the Beta or Canary version of Chrome. ### Example {% Aside %} -To see a FPS demo in action, visit [https://first-party-sets.glitch.me/](https://first-party-sets.glitch.me/). +To see a Related Website Sets demo in action, visit [https://first-party-sets.glitch.me/](https://first-party-sets.glitch.me/). {% endAside %} -To enable FPS locally, you need to use Chrome's `--enable-features` option with a comma-separated list of flags that are explained in this section. +To enable Related Website Sets locally, you need to use Chrome's `--enable-features` option with a comma-separated list of flags that are explained in this section. Learn more about how to [run Chromium with flags](https://www.chromium.org/developers/how-tos/run-chromium-with-flags/). @@ -295,11 +296,11 @@ Learn more about how to [run Chromium with flags](https://www.chromium.org/devel https://first-party-sets.glitch.me/ ``` -- `FirstPartySets` enables FPS in Chrome.` +- `FirstPartySets` enables Related Website Sets in Chrome.` StorageAccessAPI` enables Storage Access API. - `StorageAccessAPIForOriginExtension` enables top-level sites to use requestStorageAccessFor() to request storage access on behalf of specific origins. -- `PageInfoCookiesSubpage` enables showing FPS in the PageInfo section accessible from the URL bar. -- `PrivacySandboxFirstPartySetsUI` enables FPS UI "Allow related sites to see your activity in the group" option in Chrome settings, under Privacy and Security → Cookies and other site data (chrome://settings/cookies). +- `PageInfoCookiesSubpage` enables showing Related Website Sets in the PageInfo section accessible from the URL bar. +- `PrivacySandboxFirstPartySetsUI` enables Related Website Sets UI "Allow related sites to see your activity in the group" option in Chrome settings, under Privacy and Security → Cookies and other site data (chrome://settings/cookies). ### Declare a set locally @@ -324,19 +325,19 @@ Call the APIs (rSA or rSAFor) from the sites that are being tested and validate ### Reseting permissions to the default -If you want to remove all FPS-mediated permissions and reset to the default state, there are currently two ways to do so: +If you want to remove all Related Website Sets-mediated permissions and reset to the default state, there are currently two ways to do so: - Restart the browser, for example by visiting `chrome://restart`. (Any recent Chrome version.) - Visit `chrome://settings/cookies`, set the "Default behavior" setting to "Block third-party cookies", and toggle the "Allow related sites to see your activity in the group" option off and then on again. Be sure to refresh the page you're testing on as well. (Chrome 116.0.5845.42 or later.) -## FPS submission process +## Related Website Sets submission process To declare the relationship amongst the domains and specify which subset they are part of, follow the steps below: -1. Identify the relevant domains, this includes the **set primary** and **set members**, that will be part of the FPS. Also identify which **subset type** each set member belongs to. +1. Identify the relevant domains, this includes the **set primary** and **set members**, that will be part of the Related Website Set. Also identify which **subset type** each set member belongs to. 1. Ensure the [set formation requirements](https://github.com/GoogleChrome/first-party-sets/blob/main/FPS-Submission_Guidelines.md#set-formation-requirements) and [set validation requirements](https://github.com/GoogleChrome/first-party-sets/blob/main/FPS-Submission_Guidelines.md#set-validation-requirements) are in place. -1. Declare the FPS in the correct [JSON format](https://github.com/GoogleChrome/first-party-sets/blob/main/FPS-Submission_Guidelines.md#set-submissions). -1. Submit the First Party Set by creating a [pull request (PR)](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-pull-requests) to the [`first_party_sets.JSON`](https://github.com/GoogleChrome/first-party-sets/blob/main/first_party_sets.JSON) where Chrome will host the canonical FPS list. (A GitHub account is required to create PRs, and you will need to sign a [Contributor's License Agreement (CLA)](https://cla.developers.google.com/about) to contribute to the list.) +1. Declare the Related Website Set in the correct [JSON format](https://github.com/GoogleChrome/first-party-sets/blob/main/FPS-Submission_Guidelines.md#set-submissions). +1. Submit the First Party Set by creating a [pull request (PR)](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-pull-requests) to the [`first_party_sets.JSON`](https://github.com/GoogleChrome/first-party-sets/blob/main/first_party_sets.JSON) where Chrome will host the canonical Related Website Set list. (A GitHub account is required to create PRs, and you will need to sign a [Contributor's License Agreement (CLA)](https://cla.developers.google.com/about) to contribute to the list.) Once the PR is created, a series of checks will happen to validate that the requirements from step 2 are in place. @@ -344,7 +345,7 @@ Once the PR is created, a series of checks will happen to validate that the requ Before creating a PR, you can [test your submission locally](https://github.com/GoogleChrome/first-party-sets/blob/main/Getting-Started.md#testing-your-submission-locally) to see if it passes the checks. {% endAside %} -If successful, the PR will indicate that checks have been passed. Approved PRs will be manually merged in batches to the canonical FPS list once per week (Tuesdays at 12pm Eastern Time). +If successful, the PR will indicate that checks have been passed. Approved PRs will be manually merged in batches to the canonical Related Website Set list once per week (Tuesdays at 12pm Eastern Time). If any of the checks fails, the submitter will be notified through a PR failure on GitHub. The submitter can fix the errors and update the PR, and keep in mind that: @@ -355,14 +356,14 @@ If any of the checks fails, the submitter will be notified through a PR failure To meet the needs of enterprise users Chrome has a couple of enterprise policies in place: -- Systems that might not be able to integrate with First-Party Sets can disable the First-Party Sets feature in all enterprise instances of Chrome with the [`FirstPartySetsEnabled` policy](https://chromeenterprise.google/policies/#FirstPartySetsEnabled). -- Some enterprise systems have internal only sites (such as an intranet) with registrable domains that differ from the domains in their First-Party Set. If they need to treat these sites as part of their First-Party Sets without exposing them publicly (as the domains may be confidential) they can augment or override their public First-Party Sets list with the [`FirstPartySetsOverrides` policy](https://chromeenterprise.google/policies/#FirstPartySetsOverrides). +- Systems that might not be able to integrate with Related Website Sets can disable the Related Website Sets feature in all enterprise instances of Chrome with the [`FirstPartySetsEnabled` policy](https://chromeenterprise.google/policies/#FirstPartySetsEnabled). +- Some enterprise systems have internal only sites (such as an intranet) with registrable domains that differ from the domains in their Related Website Set. If they need to treat these sites as part of their Related Website Set without exposing them publicly (as the domains may be confidential) they can augment or override their public Related Website Sets list with the [`FirstPartySetsOverrides` policy](https://chromeenterprise.google/policies/#FirstPartySetsOverrides). ## Share feedback Submitting a set on GitHub and working with the Storage Access API and the `requestStorageAccessFor` API are opportunities to share your experience with the process and any issues you run into. -To join discussions about the First Party Sets: +To join discussions about Related Website Sets: -- Join the First-Party Sets [public mailing list](https://groups.google.com/u/2/a/chromium.org/g/first-party-sets-discuss). -- Raise issues and follow the discussion on [First-Party Sets GitHub repo](https://github.com/WICG/first-party-sets). +- Join the Related Website Sets [public mailing list](https://groups.google.com/u/2/a/chromium.org/g/first-party-sets-discuss). +- Raise issues and follow the discussion on [Related Website Sets GitHub repo](https://github.com/WICG/first-party-sets). diff --git a/site/en/docs/privacy-sandbox/first-party-sets/index.md b/site/en/docs/privacy-sandbox/related-website-sets/index.md similarity index 67% rename from site/en/docs/privacy-sandbox/first-party-sets/index.md rename to site/en/docs/privacy-sandbox/related-website-sets/index.md index a1da476d6..09147e4f1 100644 --- a/site/en/docs/privacy-sandbox/first-party-sets/index.md +++ b/site/en/docs/privacy-sandbox/related-website-sets/index.md @@ -1,22 +1,24 @@ --- layout: 'layouts/doc-post.njk' -title: 'First-Party Sets' +title: 'Related Website Sets' subhead: > - First-Party Sets (FPS) is a way for a company to declare relationships among sites, so that browsers allow limited third-party cookie access for specific purposes. + Related Website Sets (RWS) is a way for a company to declare relationships among sites, so that browsers allow limited third-party cookie access for specific purposes. description: > - First-Party Sets (FPS) is a way for a company to declare relationships among sites, so that browsers allow limited third-party cookie access for specific purposes. + Related Website Sets (RWS) is a way for a company to declare relationships among sites, so that browsers allow limited third-party cookie access for specific purposes. hero: image/vgdbNJBYHma2o62ZqYmcnkq3j0o1/OLx3AXkweLjAiDzoDslb.png date: 2023-03-07 -updated: 2023-05-16 +updated: 2023-09-26 authors: - mihajlija --- + +{% Partial 'privacy-sandbox/fps-rename.njk' %} + Many organizations have related sites with different domain names, such as `brandx.com` and `fly-brandx.com`—or domains for different countries such as `example.com`, `example.rs`, `example.co.uk` and so on. {% Img src="image/vgdbNJBYHma2o62ZqYmcnkq3j0o1/OLx3AXkweLjAiDzoDslb.png", alt="Diagram showing brandx.com, fly-brandx.com and drive-brandx.com as one group and example.com, example.rs, example.co.uk as another group.", width="800", height="348" %} - Imagine a company that helps you book a vacation. The company has two related sites: `fly-brandx.com` and `drive-brandx.com` to separate flights and car hire. Over the course of booking one journey, you can go between these sites to select their different options and you'd expect your shopping cart to remember your choices across these sites. Related sites like these often rely on cookies to keep you signed in or show you personalized content. @@ -27,17 +29,17 @@ As [Chrome moves towards blocking third-party cookies](https://blog.chromium.org Cookies set by the site you visit—the one shown in the URL bar—are first-party cookies. A site you visit can embed content from other sites, for example, images, ads, and text. Cookies coming from sites other than the current site are [third-party cookies](https://web.dev/samesite-cookie-recipes/#use-cases-for-cross-site-or-third-party-cookies). {% endAside %} -## Defining related sites with First-Party Sets +## Defining related sites with Related Website Sets -First-Party Sets (FPS) is a way for a company to declare relationships among sites, so that browsers allow limited third-party cookie access for specific [purposes](#first-party-sets-use-cases). Chrome will use these declared relationships to decide when to allow or deny a site access to their cookies when in a third-party context. +Related Website Sets is a way for a company to declare relationships among sites, so that browsers allow limited third-party cookie access for specific [purposes](#related-website-sets-use-cases). Chrome will use these declared relationships to decide when to allow or deny a site access to their cookies when in a third-party context. -At a high level, a First-Party Set is a collection of domains, for which there is a single "set primary" and potentially multiple "set members". +At a high level, a Related Website Set is a collection of domains, for which there is a single "set primary" and potentially multiple "set members." Site authors need to [submit their domains to a set](https://github.com/GoogleChrome/first-party-sets/blob/main/FPS-Submission_Guidelines.md). Set members can include a range of different domain types with [subsets based on use cases](https://github.com/WICG/first-party-sets#defining-a-set-through-use-case-based-subsets). -## First-Party Sets use cases +## Related Website Sets use cases -First-Party Sets are a good match for cases when an organization needs a form of shared identity across different top-level sites. Shared identity in this case means anything from a full single sign-on solution to just needing a shared preference across sites. +Related Website Sets are a good match for cases when an organization needs a form of shared identity across different top-level sites. Shared identity in this case means anything from a full single sign-on solution to just needing a shared preference across sites. An organization may have different top-level domains for: @@ -49,8 +51,8 @@ An organization may have different top-level domains for: ## Find out more -- [First-Party developer guide](/docs/first-party-sets-integration/) -- [First-Party Sets technical explainer](https://github.com/WICG/first-party-sets#introduction) +- [First-Party developer guide](/docs/related-website-sets-integration/) +- [Related Website Sets technical explainer](https://github.com/WICG/first-party-sets#introduction) - [Chrome Platform Status](https://chromestatus.com/feature/5640066519007232) - [Chromium Projects](https://www.chromium.org/updates/first-party-sets) - [Privacy Sandbox Developer Support repo](https://github.com/GoogleChromeLabs/privacy-sandbox-dev-support) From 030d58e25f6cd6050e03a27fd142be135653df90 Mon Sep 17 00:00:00 2001 From: Jecelyn Yeen <5917927+jecfish@users.noreply.github.com> Date: Sat, 30 Sep 2023 00:14:39 +0200 Subject: [PATCH 832/982] Add Debugging Chrome Extensions video (#7405) * Add Debugging Chrome Extensions video * add video link * add a debugging section * Update video links * Update site/en/docs/extensions/mv3/getstarted/extensions-101/index.md Co-authored-by: Joe Medley <jmedley@google.com> * Remove overview heading and move video --------- Co-authored-by: Oliver Dunk <oliverdunk@google.com> Co-authored-by: Joe Medley <jmedley@google.com> --- .../docs/extensions/mv3/getstarted/extensions-101/index.md | 6 ++++++ site/en/docs/extensions/mv3/tut_debugging/index.md | 4 ++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/site/en/docs/extensions/mv3/getstarted/extensions-101/index.md b/site/en/docs/extensions/mv3/getstarted/extensions-101/index.md index e374d9dfb..888370c14 100644 --- a/site/en/docs/extensions/mv3/getstarted/extensions-101/index.md +++ b/site/en/docs/extensions/mv3/getstarted/extensions-101/index.md @@ -92,6 +92,12 @@ Even though web applications and extensions share many of the same technologies, experience is different. Check out [Development Basics][doc-dev-basics] to create a "Hello, Extensions" example and familiarize yourself with the extension development workflow. +## Debugging your extension {: #debugging } + +Extensions can access the same Chrome DevTools as web pages. To become an expert in debugging extensions, you will need to know how to locate logs and errors of the different extension components. Check out [Debugging extensions](/docs/extensions/mv3/tut_debugging/) to learn techniques for debugging your extension. + +{% YouTube id='Ta-YTDhiBIQ' %} + ## Designing your extension features {: #quality } When you start designing your extension and choosing which features to support, make sure it diff --git a/site/en/docs/extensions/mv3/tut_debugging/index.md b/site/en/docs/extensions/mv3/tut_debugging/index.md index 77e2144c9..8b5f96e29 100644 --- a/site/en/docs/extensions/mv3/tut_debugging/index.md +++ b/site/en/docs/extensions/mv3/tut_debugging/index.md @@ -7,10 +7,10 @@ updated: 2023-08-09 description: Instructions for debugging Chrome Extensions. --- -## Overview {: #overview } - Extensions can access the same [Chrome DevTools][chrome-devtools] as web pages. To become an expert in debugging extensions, you will need to know how to locate logs and errors of the different extension components. This tutorial provides fundamental techniques for debugging your extension. +{% YouTube id='Ta-YTDhiBIQ' %} + ## Before you begin {: #prereq } This guide assumes that you have basic web development experience. We recommend reading From 99db4186b27f7dbc80ac064575a14450401ad08f Mon Sep 17 00:00:00 2001 From: wizardofdocs <83661258+wizardofdocs@users.noreply.github.com> Date: Mon, 2 Oct 2023 08:11:09 -0700 Subject: [PATCH 833/982] Updated DevTools page (#7307) * Updated DevTools page Made phrasing more concise and updated headers to follow the Dev Docs style guide. Marked some JavaScript examples that need updating. Other questions in comments. * Update site/en/docs/extensions/mv3/devtools/index.md Clarified method name Co-authored-by: Joe Medley <jmedley@google.com> * Updated devtools page Reformatted Caution aside * Update site/en/docs/extensions/mv3/devtools/index.md fixed capitalization Co-authored-by: Joe Medley <jmedley@google.com> * Update site/en/docs/extensions/mv3/devtools/index.md updated phrasing Co-authored-by: Joe Medley <jmedley@google.com> * Update site/en/docs/extensions/mv3/devtools/index.md Removed reference to deprecated API Co-authored-by: Joe Medley <jmedley@google.com> * Update site/en/docs/extensions/mv3/devtools/index.md Clarified phrasing Co-authored-by: Joe Medley <jmedley@google.com> * Removed extraneous "the"s from devtools page * Update site/en/docs/extensions/mv3/devtools/index.md Made phrasing more concise Co-authored-by: Joe Medley <jmedley@google.com> * Update site/en/docs/extensions/mv3/devtools/index.md Made phrasing more precise Co-authored-by: Joe Medley <jmedley@google.com> * Update site/en/docs/extensions/mv3/devtools/index.md Removed preview label Co-authored-by: Joe Medley <jmedley@google.com> * Clarified source of example code on devtools page * Added figure captions to devtools page * Updated update date on devtools page * Update site/en/docs/extensions/mv3/devtools/index.md Removed preview label Co-authored-by: Joe Medley <jmedley@google.com> * Update site/en/docs/extensions/mv3/devtools/index.md Fixed code formatting Co-authored-by: Joe Medley <jmedley@google.com> * Update site/en/docs/extensions/mv3/devtools/index.md Fixed code formatting Co-authored-by: Joe Medley <jmedley@google.com> * Update site/en/docs/extensions/mv3/devtools/index.md Fixed code formatting Co-authored-by: Joe Medley <jmedley@google.com> * Update site/en/docs/extensions/mv3/devtools/index.md Fixed code formatting Co-authored-by: Joe Medley <jmedley@google.com> * Update site/en/docs/extensions/mv3/devtools/index.md Fixed code formatting Co-authored-by: Joe Medley <jmedley@google.com> * Update site/en/docs/extensions/mv3/devtools/index.md Fixed header formatting in link Co-authored-by: Joe Medley <jmedley@google.com> * Update site/en/docs/extensions/mv3/devtools/index.md Co-authored-by: Joe Medley <jmedley@google.com> * Update site/en/docs/extensions/mv3/devtools/index.md Fixed syntax Co-authored-by: Joe Medley <jmedley@google.com> * Update site/en/docs/extensions/mv3/devtools/index.md Updated phrasing Co-authored-by: Joe Medley <jmedley@google.com> * Updated static declaration instructions on Devtools page * Update site/en/docs/extensions/mv3/devtools/index.md --------- Co-authored-by: Joe Medley <jmedley@google.com> --- site/en/docs/extensions/mv3/devtools/index.md | 259 ++++++++---------- 1 file changed, 117 insertions(+), 142 deletions(-) diff --git a/site/en/docs/extensions/mv3/devtools/index.md b/site/en/docs/extensions/mv3/devtools/index.md index 373144e4d..937b782da 100644 --- a/site/en/docs/extensions/mv3/devtools/index.md +++ b/site/en/docs/extensions/mv3/devtools/index.md @@ -3,51 +3,48 @@ layout: "layouts/doc-post.njk" title: "Extending DevTools" seoTitle: "Extending DevTools with Chrome Extensions" date: 2012-09-17 -updated: 2023-07-12 +updated: 2023-09-15 description: How to create a Chrome Extension that adds functionality to Chrome DevTools. --- -## Overview {: #overview } +DevTools extensions add functionality to Chrome DevTools by accessing DevTools-specific +extension APIs through a DevTools page added to the extension. -A DevTools extension adds functionality to the Chrome DevTools. It can add new UI panels and -sidebars, interact with the inspected page, get information about network requests, and more. -DevTools extensions have access to an additional set of DevTools-specific extension APIs: +<figure> + {% Img src="image/BrQidfK9jaQyIHwdw91aVpkPiib2/kcLMpTY6qtez03TVSqt4.png", + alt="Architecture diagram showing DevTools page communicating with the + inspected window and the service worker. The service worker is shown + communicating with the content scripts and accessing extension APIs. + The DevTools page has access to the DevTools APIs, for example, creating panels.", + height="556", width="522" %} + <figcaption>DevTools extension architecture./figcaption> +</figure> + +The DevTools-specific extension APIs include the following: - [`devtools.inspectedWindow`][api-inspectedwindow] - [`devtools.network`][api-network] - [`devtools.panels`][api-panels] -- [`devtools.recorder` (preview feature)][api-recorder] - -A DevTools extension is structured like any other extension: it can have a service worker, content -scripts, and other items. In addition, each DevTools extension has a DevTools page, which has access -to the DevTools APIs. - -{% Img src="image/BrQidfK9jaQyIHwdw91aVpkPiib2/kcLMpTY6qtez03TVSqt4.png", - alt="Architecture diagram showing DevTools page communicating with the - inspected window and the service worker. The service worker is shown - communicating with the content scripts and accessing extension APIs. - The DevTools page has access to the DevTools APIs, for example, creating panels.", - height="556", width="522" %} +- [`devtools.recorder`][api-recorder] ## The DevTools page {: #devtools-page } -An instance of the extension's DevTools page is created each time a DevTools window opens. The -DevTools page exists for the lifetime of the DevTools window. The DevTools page has access to the -DevTools APIs and a limited set of extension APIs. Specifically, the DevTools page can: +When a DevTools window opens, a DevTools extension creates an instance of its DevTools page that +exists as long as the window is open. This page has access to the DevTools APIs and some other +extension APIs, and can do the following: -- Create and interact with panels using the [`devtools.panels`][api-panels] APIs. +- Create and interact with panels using the [`devtools.panels`][api-panels] APIs, including adding other extension pages as panels or sidebars to the DevTools window. - Get information about the inspected window and evaluate code in the inspected window using the [`devtools.inspectedWindow`][api-inspectedwindow] APIs. - Get information about network requests using the [`devtools.network`][api-network] APIs. -- Extend the [Recorder panel](/docs/devtools/recorder/) using the [`devtools.recorder`][api-recorder] APIs (preview feature). +- Extend the [Recorder panel](/docs/devtools/recorder/) using the [`devtools.recorder`][api-recorder] APIs. -The DevTools page cannot use most of the extensions APIs directly. It has access to the same subset -of the [`extension`][api-extension] and [`runtime`][api-runtime] APIs that a content script has -access to. Like a content script, a DevTools page can communicate with the service worker using -[Message Passing][doc-message-passing]. For an example, see [Injecting a Content -Script][header-injecting]. +The DevTools page can't use most extensions APIs directly. Instead, it uses the same subset of +the [`extension`][api-extension] and [`runtime`][api-runtime] APIs as content scripts do, and +communicates with the service worker using [message passing][doc-message-passing]. For an +example, see [Inject a Content Script][header-injecting]. -## Creating a DevTools extension {: #creating } +## Create a DevTools extension {: #creating } To create a DevTools page for your extension, add the `devtools_page` field in the extension manifest: @@ -61,23 +58,13 @@ manifest: } ``` -An instance of the `devtools_page` specified in your extension's manifest is created for every -DevTools window opened. The page may add other extension pages as panels and sidebars to the -DevTools window using the [`devtools.panels`][api-panels] API. - -{% Aside %} +The `devtools_page` field must point to an HTML page. Because the DevTools +page must be local to your extension, we recommend specifying it it using a relative URL. -The `devtools_page` field must point to an HTML page. The DevTools -page must be local to your extension, so it is best to specify it using a relative URL. +The members of the `chrome.devtools` API are available only to the pages loaded within the DevTools +window while that window is open. Content scripts and other extension pages don't have access +to these APIs. -{% endAside %} - -The `chrome.devtools.*` API modules are available only to the pages loaded within the DevTools -window. Content scripts and other extension pages do not have these APIs. Thus, the APIs are -available only through the lifetime of the DevTools window. - -There are also some DevTools APIs that are still experimental. Refer to [chrome.experimental.\* -APIs][api-index] for the list of experimental APIs and guidelines on how to use them. ## DevTools UI elements: panels and sidebar panes {: #devtools-ui } @@ -86,15 +73,18 @@ DevTools extension can add UI elements to the DevTools window: - A _panel_ is a top-level tab, like the Elements, Sources, and Network panels. - A _sidebar pane_ presents supplementary UI related to a panel. The Styles, Computed Styles, and - Event Listeners panes on the Elements panel are examples of sidebar panes. (Note that the - appearance of sidebar panes may not match the image, depending on the version of Chrome you're - using, and where the DevTools window is docked.) + Event Listeners panes on the Elements panel are examples of sidebar panes. Depending on the + version of Chrome you're using and where the DevTools window is docked, your sidebar panes might + look like the following example image: -{% Img src="image/BrQidfK9jaQyIHwdw91aVpkPiib2/TDNgfhI9byR4eeGQ0Xxv.png", class="screenshot", - alt="DevTools window showing Elements panel and Styles sidebar pane.", height="302", width="770" %} +<figure> + {% Img src="image/BrQidfK9jaQyIHwdw91aVpkPiib2/TDNgfhI9byR4eeGQ0Xxv.png", class="screenshot", + alt="DevTools window showing Elements panel and Styles sidebar pane.", height="302", width="770" %} + <figcaption>DevTools window showing Elements panel and Styles sidebar pane.</figcaption> +</figure> Each panel is its own HTML file, which can include other resources (JavaScript, CSS, images, and so -on). Creating a basic panel looks like this: +on). To create a basic panel, use the following code: ```js chrome.devtools.panels.create("My Panel", @@ -106,9 +96,9 @@ chrome.devtools.panels.create("My Panel", ); ``` -JavaScript executed in a panel or sidebar pane has access to the the same APIs as the DevTools page. +JavaScript executed in a panel or sidebar pane has access to the same APIs as the DevTools page. -Creating a basic sidebar pane for the Elements panel looks like this: +To create a basic sidebar pane, use the following code: ```js chrome.devtools.panels.elements.createSidebarPane("My Sidebar", @@ -120,35 +110,27 @@ chrome.devtools.panels.elements.createSidebarPane("My Sidebar", There are several ways to display content in a sidebar pane: -- HTML content. Call [`setPage`][api-panels-setpane] to specify an HTML page to display in the pane. -- JSON data. Pass a JSON object to [`setObject`][api-panels-setobject]. -- JavaScript expression. Pass an expression to [`setExpression`][api-panels-setexpression]. DevTools - evaluates the expression in the context of the inspected page, and displays the return value. +- HTML content: Call [`setPage()`][api-panels-setpane] to specify an HTML page to display in the pane. +- JSON data: Pass a JSON object to [`setObject()`][api-panels-setobject]. +- JavaScript expression: Pass an expression to [`setExpression()`][api-panels-setexpression]. DevTools + evaluates the expression in the context of the inspected page, then displays the return value. -For both `setObject` and `setExpression`, the pane displays the value as it would appear in the -DevTools console. However, `setExpression` lets you display DOM elements and arbitrary JavaScript -objects, while `setObject` only supports JSON objects. +For both `setObject()` and `setExpression()`, the pane displays the value as it would appear in the +DevTools console. However, `setExpression()` lets you display DOM elements and arbitrary JavaScript +objects, while `setObject()` only supports JSON objects. -## Communicating between extension components {: #solutions } +## Communicate between extension components {: #solutions } -The following sections describe some typical scenarios for communicating between the different -components of a DevTools extension. +The following sections describe some helpful ways to allow DevTools extension components to +communicate with each other. -### Injecting a content script {: #injecting } +### Inject a content script {: #injecting } The DevTools page can't call [`scripting.executeScript()`][api-scripting-executescript] directly. To -inject a content script from the DevTools page, you must retrieve the ID of the inspected window's -tab using the [`inspectedWindow.tabId`][api-inspectedwindow-tabid] property and send a message to +inject a content script from the DevTools page, you must retrieve the inspected window's tab ID +using the [`inspectedWindow.tabId`][api-inspectedwindow-tabid] property and send a message to the background page. From the background page, call -[`scripting.executeScript`][api-scripting-executescript] to inject the script. - -{% Aside %} - -If a content script has already been injected, you can add additional context scripts using the -`eval()` method. See [Passing the Selected Element to a Content Script][header-selected-element] for -more information. - -{% endAside %} +[`scripting.executeScript()`][api-scripting-executescript] to inject the script. The following code snippets show how to inject a content script using `executeScript`. @@ -192,18 +174,27 @@ chrome.runtime.onConnect.addListener(function(devToolsConnection) { }); ``` -### Evaluating JavaScript in the inspected window {: #evaluating-js } +If a content script has already been injected, you can add additional context scripts using the +`eval()` method. See [Pass the selected element to a content script][header-selected-element] for +more information. + +### Evaluate JavaScript in the inspected window {: #evaluating-js } You can use the [`inspectedWindow.eval()`][api-inspectedwindow-eval] method to execute JavaScript code in the context of the inspected page. You can invoke the `eval()` method from a DevTools page, -panel or sidebar pane. +panel, or sidebar pane. + +{% Aside 'caution' %} +Use `eval()` only if you need access to the JavaScript content of an inspected page. Otherwise, +we recommend using the [`scripting.executeScript()`][api-scripting-executescript] method to run scripts. +For more information, see [`inspectedWindow`][api-inspectedwindow]. +{% endAside %} -By default, the expression is evaluated in the context of the main frame of the page. Now, you may -be familiar with the DevTools [Console Utilities API][doc-utilities] features like element -inspection (`inspect(elem)`), breaking on functions (`debug(fn)`), copying to clipboard (`copy()`) -and more. `inspectedWindow.eval()` uses the same script execution context and options as the code -typed at the DevTools console, which allows access to these APIs within the eval. For example, -[SOAK][gh-soak] uses it for inspecting an element: + +By default, the expression is evaluated in the context of the main frame of the page. +`inspectedWindow.eval()` uses the same script execution context and options as code +entered in the DevTools console, which allows access to DevTools [Console Utilities +API][doc-utilities] features when using `eval()`. For example, [SOAK][gh-soak] uses it for inspecting an element: ```js chrome.devtools.inspectedWindow.eval( @@ -212,21 +203,12 @@ chrome.devtools.inspectedWindow.eval( ); ``` -Alternatively, use the `useContentScriptContext: true` option for `inspectedWindow.eval()` to -evaluate the expression in the same context as the content scripts. Calling `eval` with -`useContentScriptContext: true` does not _create_ a content script context, so you must load a -context script before calling `eval`, either by calling `executeScript` or by specifying a content -script in the `manifest.json` file. - -Once the context script context exists, you can use this option to inject additional content -scripts. +You can also set the `useContentScriptContext` to `true` when calling `inspectedWindow.eval()` to +evaluate the expression in the same context as the content scripts. To use this option, use a [static content script declaration][static-declaration] before calling `eval()`, either by calling `executeScript()` or by specifying a content +script in the `manifest.json` file. After the context script context loads, you can also use this option to +inject additional content scripts. -The `eval` method is powerful when used in the right context and dangerous when used -inappropriately. Use the [`scripting.executeScript()`][api-scripting-executescript] method if you -don't need access to the JavaScript context of the inspected page. For detailed cautions and a -comparison of the two methods, see [`inspectedWindow`][api-inspectedwindow]. - -### Passing the selected element to a content script {: #selected-element } +### Pass the selected element to a content script {: #selected-element } The content script doesn't have direct access to the current selected element. However, any code you execute using [`inspectedWindow.eval()`][api-inspectedwindow-eval] has access to the DevTools @@ -235,32 +217,30 @@ selected element. To pass the selected element to a content script: -- Create a method in the content script that takes the selected element as an argument. -- Call the method from the DevTools page using [`inspectedWindow.eval()`][api-inspectedwindow-eval] - with the `useContentScriptContext: true` option. - -The code in your content script might look something like this: +1. Create a method in the content script that takes the selected element as an argument. -```js -function setSelectedElement(el) { - // do something with the selected element -} -``` +<!--Update this code--> + ```js + function setSelectedElement(el) { + // do something with the selected element + } + ``` -Invoke the method from the DevTools page like this: +2. Call the method from the DevTools page using [`inspectedWindow.eval()`][api-inspectedwindow-eval] + with the `useContentScriptContext: true` option. -```js -chrome.devtools.inspectedWindow.eval("setSelectedElement($0)", - { useContentScriptContext: true }); -``` + ```js + chrome.devtools.inspectedWindow.eval("setSelectedElement($0)", + { useContentScriptContext: true }); + ``` The `useContentScriptContext: true` option specifies that the expression must be evaluated in the same context as the content scripts, so it can access the `setSelectedElement` method. -### Getting a reference panel's `window` {: #panel-window } +### Get a reference panel's `window` {: #panel-window } To call `postMessage()` from a devtools panel, you'll need a reference to its `window` object. Get a -panel's iframe window in from the the [`panel.onShown`][api-panels-onshown] event handler: +panel's iframe window from the [`panel.onShown`][api-panels-onshown] event handler: ```js onShown.addListener(function callback) @@ -270,20 +250,19 @@ extensionPanel.onShown.addListener(function (extPanelWindow) { }); ``` -### Messaging from content scripts to the DevTools page {: #content-script-to-devtools } +### Send messages between content scripts and the DevTools page {: #content-script-to-devtools } -Messaging between the DevTools page and content scripts is indirect, by way of the service worker. +Use the service worker to send messages between the DevTools page and content scripts. -When sending a message _to_ a content script, the service worker can use the -[`tabs.sendMessage()`][api-scripting-sendmessage] method, which directs a message to the content +To send a message _to_ a content script, the service worker calls +[`tabs.sendMessage()`][api-scripting-sendmessage], which directs a message to the content scripts in a specific tab, as shown in [Injecting a Content Script][header-injecting]. -When sending a message _from_ a content script, there is no ready-made method to deliver a message -to the correct DevTools page instance associated with the current tab. As a workaround, you can have -the DevTools page establish a long-lived connection with the service worker, and have the -service worker keep a map of tab IDs to connections, so it can route each message to the correct -connection. +To send a message from a content script, you'll need to establish a connection between the DevTools +page and the service worker, and create a map of tab IDs to connections so the service worker +can route each message to the correct connection. +<!--Update this code--> ```js // background.js var connections = {}; @@ -350,17 +329,13 @@ backgroundPageConnection.postMessage({ }); ``` -### Messaging from injected scripts to the DevTools page {: #evaluated-scripts-to-devtools } +### Send messages from injected scripts to the DevTools page {: #evaluated-scripts-to-devtools } -While the above solution works for content scripts, code that is injected directly into the page -(e.g. through appending a `<script>` tag or through -[`inspectedWindow.eval()`][api-inspectedwindow-eval]) requires a different strategy. In this -context, [`runtime.sendMessage()`][api-runtime-sendmessage] will not pass messages to the background -script as expected. - -As a workaround, you can combine your injected script with a content script that acts as an -intermediary. To pass messages to the content script, you can use the -[`window.postMessage()`][mdn-postmessage] method. Here's an example, assuming the background script +Code injected directly into the page without a content script, including by appending a `<script>` +tag or calling [`inspectedWindow.eval()`][api-inspectedwindow-eval], can't send messages to the +DevTools page using [`runtime.sendMessage()`][api-runtime-sendmessage]. Instead, we recommend +combining your injected script wtih a content script that can act as an intermediary, and using +the [`window.postMessage()`][mdn-postmessage] method. The following example uses the background script from the previous section: ```js @@ -393,20 +368,20 @@ window.addEventListener('message', function(event) { }); ``` -Your message will now flow from the injected script, to the content script, to the background +The message is sent from the injected script, to the content script, to the background script, and finally to the DevTools page. -You can also consider [two alternative message passing techniques outlined -here][gh-devtools-messaging]. +Other alternative message-passing techniques can be found [here][gh-devtools-messaging]. -### Detecting when DevTools opens and closes {: #detecting-open-close } +### Detect when DevTools opens and closes {: #detecting-open-close } -If your extension needs to track whether the DevTools window is open, you can add an -[onConnect][api-runtime-onconnect] listener to the service worker, and call -[connect()][api-runtime-connect] from the DevTools page. Since each tab can have its own DevTools -window open, you may receive multiple connect events. To track whether any DevTools window is open, -you need to count the connect and disconnect events as shown below: +To track whether the DevTools window is open, add an [onConnect][api-runtime-onconnect] listener +to the service worker and call [connect()][api-runtime-connect] from the DevTools page. Because +each tab can have its own DevTools window open, you might receive multiple connect events. +To track whether any DevTools window is open, count the connect and disconnect events as shown +in the following example: +<!--Update this code--> ```js // background.js var openCount = 0; @@ -440,7 +415,7 @@ var backgroundPageConnection = chrome.runtime.connect({ ## DevTools extension examples -Browse the source of these DevTools extension examples: +The examples on this page come from the following pages: - [Polymer Devtools Extension][gh-polymer-dt] - Uses many helpers running in the host page to query DOM/JS state to send back to the custom panel. @@ -495,4 +470,4 @@ You can find examples that use DevTools APIs in [Samples][doc-samples]. [header-selected-element]: #selected-element [mdn-postmessage]: https://developer.mozilla.org/docs/Web/API/Window.postMessage [mdn-web-apis]: https://developer.mozilla.org/docs/Web/API - +[static-declaration]: https://developer.chrome.com/docs/extensions/mv3/content_scripts/#static-declarative From d4b45e9ef3512522d4a3aa206b174df5bbff1668 Mon Sep 17 00:00:00 2001 From: amysteamdev <37001393+AmySteam@users.noreply.github.com> Date: Mon, 2 Oct 2023 16:32:01 -0500 Subject: [PATCH 834/982] Add guidance for Publishing an MV3 extension (#7223) * Initial draft * Add to toc * Add header-id, links, some imgs * Change screenshots * Update date * Change description * Apply suggestions from code review Co-authored-by: Sebastian Benz <sebastian.benz@gmail.com> * Move limit features to intro * Tech review tweaks * Add new article to list * Apply suggestions from tech review Co-authored-by: Sebastian Benz <sebastian.benz@gmail.com> * More tweaks * Final tweaks * Review description * Apply suggestions from editorial review Co-authored-by: Joe Medley <jmedley@google.com> * Add manifest links * Move permission warning screenshot * Add section to the checklist * Apply @jpmedley's feedback * Update site/en/docs/extensions/migrating/checklist/index.md * Apply suggestions from code review Co-authored-by: Joe Medley <jmedley@google.com> * Remove link to unpublished article * Fix screenshot --------- Co-authored-by: Sebastian Benz <sebastian.benz@gmail.com> Co-authored-by: Joe Medley <jmedley@google.com> --- site/_data/docs/extensions/toc.yml | 1 + .../extensions/migrating/checklist/index.md | 15 ++ site/en/docs/extensions/migrating/index.md | 17 +- .../extensions/migrating/publish-mv3/index.md | 170 ++++++++++++++++++ .../mv3/permission_warnings/index.md | 11 +- 5 files changed, 211 insertions(+), 3 deletions(-) create mode 100644 site/en/docs/extensions/migrating/publish-mv3/index.md diff --git a/site/_data/docs/extensions/toc.yml b/site/_data/docs/extensions/toc.yml index 539d05753..d108c6180 100644 --- a/site/_data/docs/extensions/toc.yml +++ b/site/_data/docs/extensions/toc.yml @@ -29,6 +29,7 @@ - url: /docs/extensions/migrating/api-calls - url: /docs/extensions/migrating/blocking-web-requests - url: /docs/extensions/migrating/improve-security + - url: /docs/extensions/migrating/publish-mv3 - url: /docs/extensions/migrating/mv2-sunset - url: /docs/extensions/migrating/known-issues - url: /docs/extensions/reference diff --git a/site/en/docs/extensions/migrating/checklist/index.md b/site/en/docs/extensions/migrating/checklist/index.md index 00afd097d..b4a4d05e6 100644 --- a/site/en/docs/extensions/migrating/checklist/index.md +++ b/site/en/docs/extensions/migrating/checklist/index.md @@ -91,3 +91,18 @@ Changes are required to improve the security of extensions. This includes removi * [Remove unsupported content security policy values](/docs/extensions/migrating/improve-security/#remove-unsupported-csv) {% endDetails %} + +{% Details 'open' %} + +{% DetailsSummary %} +## Publish your Manifest V3 extension +{% endDetailsSummary %} + +After converting to Manifest Version 3, it's time to release your extension on the Chrome Web Store. Depending on the changes made, consider a step-wise roll out. This approach allows you to ensure your extension works as expected with a limited audience first, before releasing it to the entire user base. + +* [Publish a beta testing version](/docs/extensions/migrating/publish-mv3/#publish-beta). +* [Gradually roll out your release](/docs/extensions/migrating/publish-mv3/#gradual-rollout). +* [Plan for review times](/docs/extensions/migrating/publish-mv3/#review). +* [Additional tips](/docs/extensions/migrating/publish-mv3/#tips). + +{% endDetails %} \ No newline at end of file diff --git a/site/en/docs/extensions/migrating/index.md b/site/en/docs/extensions/migrating/index.md index 6ecc076a9..797d72620 100644 --- a/site/en/docs/extensions/migrating/index.md +++ b/site/en/docs/extensions/migrating/index.md @@ -4,7 +4,7 @@ title: Migrate to Manifest V3 subhead: A guide to converting Manifest V2 extensions to Manifest V3 extensions. description: A guide to converting Manifest V2 extensions to Manifest V3 extensions. date: 2023-03-09 -updated: 2023-04-14 +updated: 2023-09-14 --- {% Partial 'extensions/mv3-support.md' %} @@ -16,9 +16,22 @@ This section helps you upgrade an extension from Manifest V2 to Manifest V3, the * [Update API calls](/docs/extensions/migrating/api-calls)—Some API calls need to be replaced with more modern equivalents. * [Replace blocking web request listeners](/docs/extensions/migrating/blocking-web-requests)—Blocking or modifying network requests in Manifest V2 could significantly degrade performance and require excessive access to sensitive user data. The Declarative Net Request API allows extensions to block or modify web content with fewer permissions and without hindering performance. * [Improve extension security](/docs/extensions/migrating/improve-security)—Manifest V3 improves extension security in several ways. Besides an enhanced content security policy, support is removed for remotely hosted code and execution of arbitrary strings. +* [Publish your extension](/docs/extensions/migrating/publish-mv3/)—This section describes how to perform a step-wise roll out to ensure your Manifest V3 extension works as expected +by testing it with a limited audience first. We also have an [Extension Manifest Converter](https://github.com/GoogleChromeLabs/extension-manifest-converter). It does not do everything for you, but it will get you started. The converter's README describes what the tool changes. -## New extension features +## Keep the current set of features {: #keep-features } + +To reduce the chances of unexpected issues or bugs, we recommend not adding new functionality when migrating. For instance, adding a feature that requires new permissions may [trigger a permission warning][perm-warn], which will disable your extension until the user accepts the new permissions. + +See [Permission warning best practices][perm-warn] to learn of other ways to add permissions without displaying a warning. + +## New extension platform features Since the release of Manifest V3, we've continued to [add new features](/docs/extensions/whatsnew/), many of which are usable in both Manifest V2 and Manifest V3. You are not required to use them when converting; however, when they replace older features, you should prefer them to the features they replace and expect that the replaced features will eventually be deprecated and removed. + +[host-perms]: /docs/extensions/mv3/declare_permissions/#host-permissions +[content-manifest]: /docs/extensions/manifest/content_scripts +[perm-warn]: /docs/extensions/mv3/permission_warnings/ + diff --git a/site/en/docs/extensions/migrating/publish-mv3/index.md b/site/en/docs/extensions/migrating/publish-mv3/index.md new file mode 100644 index 000000000..245b62b49 --- /dev/null +++ b/site/en/docs/extensions/migrating/publish-mv3/index.md @@ -0,0 +1,170 @@ +--- +layout: 'layouts/doc-post.njk' +title: Publish your extension +seoTitle: Publishing a new Manifest V3 Chrome extension. +description: 'Guidance for publishing a new Manifest V3 extension' +date: 2023-09-04 +# updated: 2023-05-10 +--- + +After [converting your extension][migration-checklist] to Manifest Version 3, the next step is to +release it on the [Chrome Web Store][cws]. Depending on the extent of the changes you made, +it can be advisable to perform a step-wise roll out to ensure your Manifest V3 extension works as expected +by testing it with a limited audience first. + +This article discusses a few ways to publish your new release in stages. For example, releasing a +beta version to testers and gradually rolling out to your user base. We also recommend monitoring +your extension review status and keeping an eye on user feedback to quickly publish any bug fixes if +needed. + +## Publish a beta testing version {: #publish-beta } + +Publishing a beta release allows you to gather feedback and identify any issues with a group of testers before releasing your extension to the rest of your users. Beta releases also go through the [Chrome Web Store review process][cws-review]. + +### Label your beta version {: #label-beta } + +First, you must label the beta release as a testing version in the [manifest.json][manifest] by following these steps: + +1. Add the label “BETA” at the end of the [name][manifest-name] of your extension. +2. Add "THIS EXTENSION IS FOR BETA TESTING" to the [description][manifest-desc]. + +{% Aside 'caution' %} +Skipping this step may result in your extension being rejected for [repetitive content][spam-policy]. +{% endAside %} + +Now that your beta version is clearly labeled, you can either distribute it to specified email addresses, to members of a Google group, or share it as a direct link. + +### Distribute to testers by email {: #dist-email } + +Follow these steps to distribute to a small number of testers: + +1. Go to the **Account tab** of the Developer Dashboard. +1. Scroll down to **Management**. +1. Under Trusted Testers, enter email addresses separated by spaces or commas. + <figure> + {% Img src="image/BrQidfK9jaQyIHwdw91aVpkPiib2/SrVxYFc0lmMgXxtN30gA.png", alt="Screenshot showing trusted tester accounts listed in a Chrome Web Store developer account page", height="395", width="800", class="screenshot" %} + <figcaption> + Trusted tester emails in the Chrome Web Store developer Account page. + </figcaption> + </figure> +1. Save changes at the bottom of the page. +1. [Upload][cws-upload] the beta version of your extension +1. Go to the **Distribution** tab +1. Set the Visibility to **Private**. + +<figure> + {% Img src="image/BhuKGJaIeLNPW9ehns59NfwqKxF2/EfL45p0rsDFExxbjMp0B.png", alt="Setting the Visibility as Private in the Distribution tab", width="500", height="612", class='screenshot' %} + <figcaption> + Visibility set to Private in the Distribution tab. + </figcaption> +</figure> + +### Distribute to members of a Google group {: #dist-group } + +Once you've received enough feedback from your beta testers, you can expand distribution to members of a [Google group][google-group] that you own or manage. + +Go to the **Distribution** tab, set the **Visibility** to Private, and choose your beta tester Google group from the **dropdown menu**. + +<figure> + {% Img src="image/BhuKGJaIeLNPW9ehns59NfwqKxF2/eW95QyUHVYrQw0eThSNc.png", alt="Setting the visibility to private and choosing a google group to distribute the extension to", width="600", height="445" %} + <figcaption> + Distributing to members of a Google Group. + </figcaption> +</figure> + +### Distribute to testers with a direct link {: #dist-link } + +Another alternative is to set the visibility to **Unlisted**. This way, only users who have the direct link to your store listing item can install the extension. + +## Gradually roll-out your release {: #gradual-rollout } + +To ensure that any unexpected problems will have minimal impact, you can roll out your update gradually by following these steps. This is only available for extensions with more than 10,000 active users. + +1. [Upload][cws-upload] your new version. +2. Go to the **Distribution** tab. +3. Enter a percentage in **Percentage rollout** field. + +<figure> +{% Img src="image/BrQidfK9jaQyIHwdw91aVpkPiib2/oZxWW5oMsh7fUSzwvRNp.png", alt="Screenshot of the Chrome Web Store fractional rollout field", height="488", width="800", class='screenshot' %} + <figcaption> + Setting the initial rollout percentage. + </figcaption> +</figure> + +To continue rolling out gradually, navigate to the **Package** tab of your item and increase the percentage located in the **Published** section. Note that the percentage can only be increased, and it doesn't trigger an additional review. + +<figure> + {% Img src="image/BhuKGJaIeLNPW9ehns59NfwqKxF2/UA8vDp8aG89exqqjzY55.png", alt="Screenshot of the Chrome Web Store update percent rollout field", width="800", height="395", class='screenshot' %} + <figcaption> + Updating the rollout percentage. + </figcaption> +</figure> + +## Plan for review times {: #review } + +We recommend planning enough time for your item to be reviewed as review times may vary based on [different factors][review-factors]. Most extensions are reviewed within three days. Consider staging your release and regularly checking your item's status to make changes quickly if necessary. + +### Stage your release {: #staged-release } + +The Chrome Web Store offers a way to stage a release by submitting it for review ahead of time. This way, when you are ready, you can officially release it. + +You can do this by unchecking the "Publish automatically" checkbox when you submit the item. + +<figure> + {% Img src="image/BrQidfK9jaQyIHwdw91aVpkPiib2/BiZituXHHZ74SIkwc3q7.png", alt="Screenshot of the Chrome Web Store confirm submission dialog", height="388", width="800" %} + <figcaption> + Checkbox to stage an extension update. + </figcaption> +</figure> + +Or you can do it later by choosing **Defer publish** in the three-dot menu on the top right. + +<figure> + {% Img src="image/SHhb2PDKzXTggPGAYpv8JgR81pX2/yoMNFt1ht6qSLXzFyrWj.png", alt="Screenshot showing the 'more' menu's defer publish option", width="286", height="184", class='screenshot' %} + <figcaption> + Choosing deferred publishing in menu. + </figcaption> +</figure> + +{% Aside %} +Once your item is approved, you have up to 30 days to publish. After that period expires, the staged submission will revert to a draft, which will have to be reviewed again. You can check your staged submission expiration in the developer dashboard next to each listed item. + +<figure> +{% Img src="image/BhuKGJaIeLNPW9ehns59NfwqKxF2/sYCH3lvreW0bUWznlOsE.png", alt="Staged item +status in the developer dashboard", width="700", height="84", class='screenshot' %} + <figcaption> + Staged item status in the developer dashboard + </figcaption> +</figure> + +{% endAside %} + +### Check your item status {: #check-status } + +When your item has passed or if a violation has been found, you will receive a notification email, usually within 3 days. If you have not received an email in a week, check your item's status in the **Published** section of the **Status** tab. + +<figure> + {% Img src="image/BhuKGJaIeLNPW9ehns59NfwqKxF2/C4wpnEeMriI9YeDAMDIr.png", alt="The Chrome Web Store Status Tab", width="700", height="276", class='screenshot' %} + <figcaption> + Status tab in the Developer Dashboard. + </figcaption> +</figure> + +If your extension has been pending review for over two weeks, [contact developer support][cws-support] to request assistance. + +## Additional tips {: #tips } + +To stay on top of user feedback you can add a link to a [dedicated support site][support-site] under the Support tab of your extension listing. + +[cws-review]: /docs/webstore/review-process/ +[cws-support]: /docs/webstore/review-process/#support +[cws-upload]: /docs/webstore/upload +[cws]: https://chrome.google.com/webstore +[google-group]: https://groups.google.com/my-groups +[manifest-desc]: /docs/extensions/mv3/manifest/description/ +[manifest-name]: /docs/extensions/mv3/manifest/name/ +[manifest]: /docs/extensions/mv3/manifest/ +[migration-checklist]: /docs/extensions/migrating/checklist/ +[review-factors]: /docs/webstore/review-process/#review-time-factors +[spam-policy]: /docs/webstore/troubleshooting/#spam +[support-site]: /docs/webstore/manage/#dedicated-support-site diff --git a/site/en/docs/extensions/mv3/permission_warnings/index.md b/site/en/docs/extensions/mv3/permission_warnings/index.md index 29f2b933e..9239fcd4e 100644 --- a/site/en/docs/extensions/mv3/permission_warnings/index.md +++ b/site/en/docs/extensions/mv3/permission_warnings/index.md @@ -28,7 +28,16 @@ display a warning. Other permissions trigger a warning that users have to allow. When a new permission that [triggers a warning](#permissions_with_warnings) is added, the extension will be disabled until the user accepts the new permission. See [Updating -permissions](#update_permissions) to learn how to test this behavior. Some permissions may not display warnings when paired +permissions](#update_permissions) to learn how to test this behavior. + +<figure> + {% Img src="image/BhuKGJaIeLNPW9ehns59NfwqKxF2/tQgKKMKbzmCzwBEAoatX.gif", alt="Example of an extension that is disabled until the user accepts the new permission.", width="396", height="288" %} + <figcaption> + An extension that is disabled until the user accepts the new permission. + </figcaption> +</figure> + +Some permissions may not display warnings when paired with other permissions. For example, the `"tabs"` warning will not show if the extension also requests `"<all_urls>"`. From 30a8a629934fbad5d94e35ba95b4922cb7dd1b7a Mon Sep 17 00:00:00 2001 From: gr1ntch <63327841+mighty-odewumi@users.noreply.github.com> Date: Mon, 2 Oct 2023 23:38:42 +0100 Subject: [PATCH 835/982] Fixed typo in Chrome extension reference article (#7420) --- site/en/docs/extensions/reference/tabCapture/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/en/docs/extensions/reference/tabCapture/index.md b/site/en/docs/extensions/reference/tabCapture/index.md index 38569fc6c..ad09cef3f 100644 --- a/site/en/docs/extensions/reference/tabCapture/index.md +++ b/site/en/docs/extensions/reference/tabCapture/index.md @@ -56,7 +56,7 @@ returned stream ID can be used: - If `consumerTabId` is specified, the ID can be used by a `getUserMedia()` call in any frame in the given tab which has the same security origin. -- When this is not specified, begininning in Chrome 116, the ID can be used in any frame with the +- When this is not specified, beginning in Chrome 116, the ID can be used in any frame with the same security origin in the same render process as the caller. This means that a stream ID obtained in a service worker can be used in an [offscreen document][offscreen-document]. From 0f7b3d81f44ade7639a9cc969af26a6cf4830d03 Mon Sep 17 00:00:00 2001 From: Jecelyn Yeen <5917927+jecfish@users.noreply.github.com> Date: Tue, 3 Oct 2023 06:07:32 +0200 Subject: [PATCH 836/982] Update index.md (#7425) --- site/en/blog/new-in-devtools-118/index.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/site/en/blog/new-in-devtools-118/index.md b/site/en/blog/new-in-devtools-118/index.md index c1b43b409..bf9c65d47 100644 --- a/site/en/blog/new-in-devtools-118/index.md +++ b/site/en/blog/new-in-devtools-118/index.md @@ -16,9 +16,7 @@ tags: {% Partial 'devtools/banner.md' %} -*There is no 'What's new in DevTools' video for this release, but you can watch this quick recap of the recent features.* - -{% YouTube id='e8tl_yp5BQg' %} +{% YouTube id='Ta-YTDhiBIQ' %} <!-- $contentStart --> From 1cc799ca965d9553313fc2eee7f8dedbc8f022f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Beaufort?= <beaufort.francois@gmail.com> Date: Tue, 3 Oct 2023 09:03:01 +0200 Subject: [PATCH 837/982] What's New in WebGPU (Chrome 118) (#7257) --- site/en/_partials/webgpu/whats-new.md | 6 ++ site/en/blog/new-in-webgpu-118/index.md | 132 ++++++++++++++++++++++++ 2 files changed, 138 insertions(+) create mode 100644 site/en/blog/new-in-webgpu-118/index.md diff --git a/site/en/_partials/webgpu/whats-new.md b/site/en/_partials/webgpu/whats-new.md index 665b237b8..4f2f38a8a 100644 --- a/site/en/_partials/webgpu/whats-new.md +++ b/site/en/_partials/webgpu/whats-new.md @@ -2,6 +2,12 @@ A list of everything that has been covered in the [What's New in WebGPU](/tags/new-in-webgpu/) series. +### Chrome 118 {: #chrome118 } + +* [HTMLImageElement and ImageData support in copyExternalImageToTexture()](/blog/new-in-webgpu-118/#htmlimageelement-and-imagedata-support-in-copyexternalimagetotexture) +* [Experimental support for read-write and read-only storage texture](/blog/new-in-webgpu-118/#experimental-support-for-read-write-and-read-only-storage-texture) +* [Dawn updates](/blog/new-in-webgpu-118/#dawn-updates) + ### Chrome 117 {: #chrome117 } * [Unset vertex buffer](/blog/new-in-webgpu-117/#unset-vertex-buffer) diff --git a/site/en/blog/new-in-webgpu-118/index.md b/site/en/blog/new-in-webgpu-118/index.md new file mode 100644 index 000000000..d4a2493d0 --- /dev/null +++ b/site/en/blog/new-in-webgpu-118/index.md @@ -0,0 +1,132 @@ +--- +layout: "layouts/blog-post.njk" +title: "What's New in WebGPU (Chrome 118)" +description: "Extended source support for copyExternalImageToTexture, experimental support for read-write and read-only storage texture, and more." +hero: "image/vvhSqZboQoZZN9wBvoXq72wzGAf1/9H2CFU1J8kyyvVUH8dgA.png" +alt: "What's new in WebGPU logo" +date: 2023-10-03 +#updated: YYYY-MM-DD +authors: + - beaufortfrancois +tags: + - new-in-webgpu + - webgpu + - chrome-118 +--- + +## HTMLImageElement and ImageData support in copyExternalImageToTexture() + +The [`copyExternalImageToTexture()`](https://developer.mozilla.org/docs/Web/API/GPUQueue/copyExternalImageToTexture) method on `GPUQueue` allows you to copy a snapshot taken from a source image, video, or canvas into a given `GPUTexture`. You can now pass [`HTMLImageElement`](https://developer.mozilla.org/docs/Web/API/HTMLImageElement) and [`ImageData`](https://developer.mozilla.org/docs/Web/API/ImageData) objects as the source. See the following example and [issue chromium:1471372](https://bugs.chromium.org/p/chromium/issues/detail?id=1471372). + +```js +// Fetch and decode image. +const source = document.createElement("img"); +source.src = "my-image.png"; +await source.decode(); + +// Create destination texture. +const size = [source.width, source.height]; +const texture = myDevice.createTexture({ + size, + format: "rgba8unorm", + usage: + GPUTextureUsage.COPY_DST | + GPUTextureUsage.RENDER_ATTACHMENT | + GPUTextureUsage.TEXTURE_BINDING, +}); + +// Copies a snapshot taken from the source image into a texture. +myDevice.queue.copyExternalImageToTexture({ source }, { texture }, size); +``` + +## Experimental support for read-write and read-only storage texture + +The storage texture binding type allows you to perform texture reads without sampling and store to arbitrary positions in shaders. When the `"chromium-experimental-read-write-storage-texture"` feature is available in a `GPUAdapter`, you can now request a `GPUDevice` with this feature and set `GPUStorageTexture` access to either `"read-write"` or `"read-only"` when creating a bind group layout. Previously this was restricted to `"write-only"`. + +To take advantage of this, you must explicitly enable this extension in your WGSL code with `enable chromium_experimental_read_write_storage_texture`. When enabled, you can use `read_write` and `read` access qualifier for storage textures, the `textureLoad()` and `textureStore()` built-in functions behave accordingly, and a new `textureBarrier()` built-in function is available to synchronize texture memory accesses in a workgroup. See the following example and [issue dawn:1972](https://bugs.chromium.org/p/dawn/issues/detail?id=1972). + +This feature is still experimental and may change. While it’s [getting standardized](https://github.com/gpuweb/gpuweb/issues/3838), run chrome with the `--enable-dawn-features=allow_unsafe_apis` [flag](/docs/web-platform/chrome-flags/) to make it available. + +```js +const feature = "chromium-experimental-read-write-storage-texture"; +const adapter = await navigator.gpu.requestAdapter(); +if (!adapter.features.has(feature)) { + throw new Error("Read-write storage texture support is not available"); +} +// Explicitly request read-write storage texture support. +const device = await adapter.requestDevice({ + requiredFeatures: [feature], +}); + +const bindGroupLayout = device.createBindGroupLayout({ + entries: [{ + binding: 0, + visibility: GPUShaderStage.COMPUTE, + storageTexture: { + access: "read-write", // <-- New! + format: "r32uint", + }, + }], +}); + +const shaderModule = device.createShaderModule({ code: ` + enable chromium_experimental_read_write_storage_texture; + @group(0) @binding(0) var tex : texture_storage_2d<r32uint, read_write>; + + @compute @workgroup_size(1, 1) + fn main(@builtin(local_invocation_id) local_id: vec3u) { + var data = textureLoad(tex, vec2i(local_id.xy)); + data.x *= 2; + textureStore(tex, vec2i(local_id.xy), data); + }`, +}); + +// You can now create a compute pipeline with this shader module and +// send the appropriate commands to the GPU. +``` + +## Dawn updates + +The [webgpu.h](https://github.com/webgpu-native/webgpu-headers/blob/main/webgpu.h) C API has renamed the following fields for consistency: `requiredFeaturesCount` to `requiredFeatureCount`, `pipelineStatisticsCount` to `pipelineStatisticCount`, and `colorFormatsCount` to `colorFormatCount`. See [issue dawn:146040](https://dawn-review.googlesource.com/c/dawn/+/146040). + +A new `DawnInfo` program (similar to [vulkaninfo](https://vulkan.lunarg.com/doc/view/latest/windows/vulkaninfo.html)) allows you to list toggles, adapters, adapter features and adapter limits. It is available when building dawn `samples`. Here’s the output below heavily trimmed for brevity. See [change dawn:149020](https://dawn-review.googlesource.com/c/dawn/+/149020). + +```bash +$ ./out/Debug/DawnInfo +Toggles +======= + Name: allow_unsafe_apis + Suppresses validation errors on API entry points or parameter combinations + that aren't considered secure yet. + http://crbug.com/1138528 +[…] + +Adapter +======= +VendorID: 0x106B +Vendor: apple +Architecture: common-3 +DeviceID: 0x0000 +Name: Apple M1 Pro +Driver description: Metal driver on macOS Version 13.5.1 (Build 22G90) +Adapter Type: discrete GPU +Backend Type: Metal +Power: <undefined> + + Features + ======== + * depth_clip_control + Disable depth clipping of primitives to the clip volume + https://bugs.chromium.org/p/dawn/issues/detail?id=1178 +[…] + + Adapter Limits + ============== + maxTextureDimension1D: 16,384 + maxTextureDimension2D: 16,384 +[…] +``` + +This covers only some of the key highlights. Check out the exhaustive [list of commits](https://dawn.googlesource.com/dawn/+log/chromium/5938..chromium/5993). + +{% Partial 'webgpu/whats-new.md' %} From 46b7ea5cee1418c1baa7ba8b5016c7a61b202d50 Mon Sep 17 00:00:00 2001 From: Eiji Kitamura <agektmr@google.com> Date: Tue, 3 Oct 2023 18:01:43 +0900 Subject: [PATCH 838/982] Passkeys on iCloud Keychain blog post (#7382) * Passkeys on iCloud Keychain blog post * Move the article under en * Update * Update site/en/blog/passkeys-on-icloud-keychain/index.md Co-authored-by: Milica <mihajlija@google.com> * Update site/en/blog/passkeys-on-icloud-keychain/index.md Co-authored-by: Milica <mihajlija@google.com> * Update site/en/blog/passkeys-on-icloud-keychain/index.md Co-authored-by: Milica <mihajlija@google.com> * Update site/en/blog/passkeys-on-icloud-keychain/index.md Co-authored-by: Milica <mihajlija@google.com> * Update site/en/blog/passkeys-on-icloud-keychain/index.md * Update index.md Add photo credit * Update index.md * Update index.md * Update index.md * Update index.md --------- Co-authored-by: Milica <mihajlija@google.com> --- .../blog/passkeys-on-icloud-keychain/index.md | 173 ++++++++++++++++++ 1 file changed, 173 insertions(+) create mode 100644 site/en/blog/passkeys-on-icloud-keychain/index.md diff --git a/site/en/blog/passkeys-on-icloud-keychain/index.md b/site/en/blog/passkeys-on-icloud-keychain/index.md new file mode 100644 index 000000000..a60323154 --- /dev/null +++ b/site/en/blog/passkeys-on-icloud-keychain/index.md @@ -0,0 +1,173 @@ +--- +layout: 'layouts/blog-post.njk' +title: Chrome starts supporting passkeys on iCloud Keychain on macOS +description: > + Chrome on macOS starts supporting passkeys on iCloud Keychain. This lets users create passkeys on iCloud Keychain and synchronize them across Apple devices. +subhead: > + Chrome supports passkeys on iCloud Keychain starting in Chrome 118, on macOS 13.5 or later. +date: 2023-10-03 +authors: + - agektmr +tags: + - identity + - passkeys + - webauthn +hero: 'image/YLflGBAPWecgtKJLqCJHSzHqe2J2/szxkH65QmEUz9ZMh0Zgb.jpg' +alt: > + A woman holding four apples. +--- + +Passkeys are a safer and more user friendly alternative to passwords. They +enable users to sign in to apps and websites by unlocking their device +screen–with a biometric sensor (such as a fingerprint or facial recognition), +PIN, or a pattern. With passkeys, users no longer need to remember and manage +passwords. Passkeys are already supported in Chrome across [many operating +systems](https://developers.google.com/identity/passkeys/supported-environments). + +Until today, passkeys created on macOS were only stored locally in [the user's +Chrome profile](https://support.google.com/chrome/a/answer/9025411). They were +not synchronized, even when they were discoverable credentials. + +<figure> + {% Img src="image/YLflGBAPWecgtKJLqCJHSzHqe2J2/z6MiKx76ZC0xQm4lVipE.png", alt="Chrome's passkey dialog to create a new passkey. The passkey will be saved to Chrome profile locally.", width="800", height="602" %} + <figcaption>Chrome's passkey dialog to create a new passkey. The passkey will be saved to Chrome profile locally.</figcaption> +</figure> + +Starting in Chrome 118, on macOS 13.5 or later, users will have the option +to save passkeys in, and use them from, iCloud Keychain. Passkeys stored in +iCloud Keychain are synchronized across the Apple ecosystem. + +## How iCloud Keychain is supported in Chrome + +There are no changes required from developers to align their passkey +implementation with iCloud Keychain. The API behaviors on Safari and Chrome with +iCloud Keychain are identical. Users on Chrome 118 and later on macOS 13.5 or +later will see the following changes: + +### Registration + +When creating a new passkey, macOS's system user verification dialog appears. +This dialog is the same as Safari's. + +<figure> + {% Img src="image/YLflGBAPWecgtKJLqCJHSzHqe2J2/H0sK4DYpiX0TBQ6zqKLy.png", alt="macOS's system user verification dialog that asks for Touch ID to create a new passkey.", width="800", height="563" %} + <figcaption>macOS's system user verification dialog that asks for Touch ID to create a new passkey.</figcaption> +</figure> + +The UI varies depending on the supported user verification method on the device +such as Apple Watch, Touch ID or a system password. When the user verifies their +identity, a new passkey is created and saved to iCloud Keychain. + +iCloud Keychain synchronizes the saved passkey to other Apple devices that run +macOS, iOS or iPadOS where the user is signed in using the same iCloud account, +so that they can use the passkey to sign in to the websites and apps. + +Passkeys stored in iCloud Keychain are available to different browsers as well. +For example, a passkey created on Safari can be available in Chrome on macOS and +vice versa. + +### Authentication + +Users can also sign in to your website using the passkey stored in iCloud Keychain. + +<figure> + {% Img src="image/YLflGBAPWecgtKJLqCJHSzHqe2J2/wY36r97a8mkKTHUheiRe.png", alt="macOS's system user verification dialog that asks for Touch ID to sign in with a passkey saved to iCloud Keychain.", width="800", height="554" %} + <figcaption>macOS's system user verification dialog that asks for Touch ID to sign in with a passkey saved to iCloud Keychain.</figcaption> +</figure> + +Note that passkeys stored to the Chrome profile previously continue to be +available, but ones stored to iCloud Keychain are prioritized. If only a +passkey from Chrome profile is available, it will be used to authenticate the +user. + +<figure> + {% Img src="image/YLflGBAPWecgtKJLqCJHSzHqe2J2/FWFHutWv84m8EYJtyCTa.png", alt="Chrome's passkey dialog to sign in with a passkey saved to Chrome profile.", width="800", height="602" %} + <figcaption>Chrome's passkey dialog to sign in with a passkey saved to Chrome profile.</figcaption> +</figure> + +If authentication is requested using form autofill ([conditional UI](/blog/webauthn-conditional-ui/#conditional-ui)), passkeys +from iCloud Keychain are listed as part of the autofill suggestions if the user +has granted Chrome the necessary permission. If there are passkeys stored in the +Chrome profile, they are suggested too. + +<figure> + {% Img src="image/YLflGBAPWecgtKJLqCJHSzHqe2J2/MHCnKhNhwHM8x6eqrtsT.png", alt="Form autofill suggests passkeys from both iCloud Keychain and the Chrome profile.", width="800", height="535" %} + <figcaption>Form autofill suggests passkeys from both iCloud Keychain and the Chrome profile.</figcaption> +</figure> + +## Saving passkeys to Chrome profile + +Even with iCloud Keychain support, users can choose to save passkeys to their +Chrome profile by default . + +1. In Chrome, visit `chrome://password-manager/settings` +2. Turn off the **Use passkeys across your Apple devices** toggle to explicitly + store passkeys to the Chrome profile by default. + +<figure> + {% Img src="image/YLflGBAPWecgtKJLqCJHSzHqe2J2/QYeEKKTyg3TLXxpy41ow.png", alt="The user can choose to store passkeys to Chrome profile (only available locally and will not sync).", width="800", height="122" %} + <figcaption>The user can choose to store passkeys to Chrome profile (only available locally and will not sync).</figcaption> +</figure> + +Users can also cancel the macOS's user verification dialog and choose iCloud +Keychain or Chrome profile to save a new passkey. + +<figure> + {% Img src="image/YLflGBAPWecgtKJLqCJHSzHqe2J2/XSJAYPiUuUJUbfNJ8XHs.png", alt="If the user cancels the dialog, Chrome asks to choose how to create a passkey.", width="800", height="780" %} + <figcaption>If the user cancels the dialog, Chrome asks to choose how to create a passkey.</figcaption> +</figure> + +{% Aside %} + +On macOS 13.4 or earlier, all passkeys created on Chrome on macOS are stored to +the [Chrome profile](https://support.google.com/chrome/a/answer/9025411) locally +by default and they are not synchronized across devices. The stored passkeys are +visible to the user from `chrome://settings/passkeys`. + +Even on macOS 13.5 or later, passkeys are stored to Chrome profile if the user +is not signed into iCloud Drive. + +{% endAside %} + +## Distinguishing the origin of a passkey + +Again, there are no changes required from developers to align their passkey +implementation with iCloud Keychain. The API behavior between Chrome profile and +iCloud Keychain are already identical. + +Relying parties can find out the origin of a passkey and distinguish whether it's +been created on iCloud Keychain or on Chrome profile, by looking at the +[AAGUID](https://www.w3.org/TR/webauthn/#aaguid) (an identifier indicating the +type of the authenticator) in [the credential's authenticator +data](https://www.w3.org/TR/webauthn-3/#sctn-attestation). + +The AAGUID of a passkey created in Chrome profile is: +`adce0002-35bc-c60a-648b-0b25f1f05503`. In iCloud Keychain it is: +`00000000-0000-0000-0000-000000000000` as of September 2023. You can find known +AAGUIDs in the [crowd sourced AAGUID repository](https://github.com/passkeydeveloper/passkey-authenticator-aaguids). + +## iCloud Keychain activation + +Users must grant Chrome the permission to use iCloud Keychain on macOS the +first time they try. + +If a user tries to use iCloud Keychain passkeys but is not signed into iCloud +or does not have iCloud Keychain syncing enabled, they are directed to System +Settings. + +<figure> + {% Img src="image/YLflGBAPWecgtKJLqCJHSzHqe2J2/1Gj5VCqfoLza5K3zRXDq.png", alt="A dialog shown when iCloud Keychain is not enabled on the user's macOS.", width="800", height="649" %} + <figcaption>A dialog shown when iCloud Keychain is not enabled on the user's macOS.</figcaption> +</figure> + +## Learn more + +* [Passwordless login with passkeys | Authentication | Google for + Developers](https://developers.google.com/identity/passkeys/) +* [Create a passkey for passwordless logins](https://web.dev/passkey-registration/) +* [Sign in with a passkey through form + autofill](https://web.dev/passkey-form-autofill/) +* [Implement passkeys with form autofill in a web + app](https://developers.google.com/codelabs/passkey-form-autofill#0) + +Photo by <a href="https://unsplash.com/@the_meaning_of_love?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Aarón Blanco Tejedor</a> on <a href="https://unsplash.com/photos/CNpYALGZhMo?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Unsplash</a> From 955b7574603a44edfd6387c1b1aa4feffd857818 Mon Sep 17 00:00:00 2001 From: Nancymic2 <nmichell@google.com> Date: Tue, 3 Oct 2023 08:08:45 -0400 Subject: [PATCH 839/982] Update ARA updates index.md (#7393) --- .../privacy-sandbox/attribution-reporting-updates/index.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/site/en/docs/privacy-sandbox/attribution-reporting-updates/index.md b/site/en/docs/privacy-sandbox/attribution-reporting-updates/index.md index 1f8d2a7b4..05723debf 100644 --- a/site/en/docs/privacy-sandbox/attribution-reporting-updates/index.md +++ b/site/en/docs/privacy-sandbox/attribution-reporting-updates/index.md @@ -40,8 +40,8 @@ If you're new to this API or have not experimented with it yet, read the * **June 23, 2022**: Several updates have been detailed in the [Attribution Reporting updates in June 2022 blog post](/blog/attribution-reporting-updates-june-2022). Additionally: * The API handbook was updated. - * We've published [Experiment with Attribution Reporting: Strategy and tips](https://docs.google.com/document/d/1bU0a_njpDcRd9vDR0AJjwJjrf3Or8vAzyfuK8JZDEfo/edit?usp=sharing) - for summary reports. + * We published Experiment with Attribution Reporting: Strategy and tips + for summary reports. As of July 2023, that content has been migrated to [Understanding noise](/docs/privacy-sandbox/attribution-reporting/understanding-noise/) and [Understanding aggregation keys](/docs/privacy-sandbox/attribution-reporting/aggregation-keys/). * **March 31, 2022**: New [origin trial for Ads relevance and measurement APIs](/blog/privacy-sandbox-unified-origin-trial/), which includes the Attribution Reporting API. Now completed (as of September 20, 2023). * **February 7, 2022**: Documentation for the [header trigger redirect](/blog/attribution-reporting-jan-2022-updates/#header-trigger-redirect) added. * **January 27, 2022**: [Migration for API updates](/blog/attribution-reporting-jan-2022-updates/) published, including: From 5afe8567a647cd8764aca29ec6e75042cd9fcb47 Mon Sep 17 00:00:00 2001 From: Nancymic2 <nmichell@google.com> Date: Tue, 3 Oct 2023 08:44:10 -0400 Subject: [PATCH 840/982] ARA dev guide landing page (#7253) * ara landing page * feedback * feedback * feedback * feedback * feedback * feedback * feedback * fix a few links * Update index.njk * getting -> get --- site/_data/docs/privacy-sandbox/toc.yml | 1 + .../developer-guide/index.njk | 140 ++++++++++++++++++ 2 files changed, 141 insertions(+) create mode 100644 site/en/docs/privacy-sandbox/attribution-reporting/developer-guide/index.njk diff --git a/site/_data/docs/privacy-sandbox/toc.yml b/site/_data/docs/privacy-sandbox/toc.yml index 411eaea63..639925e8b 100644 --- a/site/_data/docs/privacy-sandbox/toc.yml +++ b/site/_data/docs/privacy-sandbox/toc.yml @@ -114,6 +114,7 @@ - url: /docs/privacy-sandbox/attribution-reporting-debugging/part-3/ - title: i18n.docs.privacy-sandbox.attribution-reporting-developer-guide sections: + - url: /docs/privacy-sandbox/attribution-reporting/developer-guide/ - url: /docs/privacy-sandbox/attribution-reporting/getting-started/ - url: /docs/privacy-sandbox/attribution-reporting/register-attribution-source/ - url: /docs/privacy-sandbox/attribution-reporting/register-attribution-trigger/ diff --git a/site/en/docs/privacy-sandbox/attribution-reporting/developer-guide/index.njk b/site/en/docs/privacy-sandbox/attribution-reporting/developer-guide/index.njk new file mode 100644 index 000000000..62ad9f2ff --- /dev/null +++ b/site/en/docs/privacy-sandbox/attribution-reporting/developer-guide/index.njk @@ -0,0 +1,140 @@ +--- +layout: 'layouts/landing.njk' +title: 'Attribution Reporting API developer guide' +sections: + intro: + - url: /docs/privacy-sandbox/attribution-reporting/getting-started/ + title: Get started with the Attribution Reporting API + description: Here's where to start, including setup and a quick overview. + - url: /docs/privacy-sandbox/attribution-reporting/register-attribution-sources/ + title: Register sources + description: Learn how to register sources to attribute clicks and views to the appropriate events. + - url: /docs/privacy-sandbox/attribution-reporting/register-attribution-triggers/ + title: Register triggers + description: Learn how to register attribution triggers to measure your conversions. + - url: /docs/privacy-sandbox/attribution-reporting-debugging/ + title: Set up debugging + description: Learn how debugging works and how to set it up. + advanced_concepts: + - url: /docs/privacy-sandbox/attribution-reporting/understanding-noise/ + - url: /docs/privacy-sandbox/attribution-reporting/working-with-noise/ + - url: /docs/privacy-sandbox/attribution-reporting/constraints/ + - url: /docs/privacy-sandbox/attribution-reporting/contribution-budget/ + - url: /docs/privacy-sandbox/attribution-reporting/aggregation-keys/ + - url: /docs/privacy-sandbox/attribution-reporting/web-to-app-attribution/ + customize_reports: + - url: /docs/privacy-sandbox/attribution-reporting/change-attribution-logic/ + - url: /docs/privacy-sandbox/attribution-reporting/define-filters/ + - url: /docs/privacy-sandbox/attribution-reporting/prevent-duplication/ + - url: /docs/privacy-sandbox/attribution-reporting/custom-report-windows/ + - url: /docs/privacy-sandbox/attribution-reporting/multiple-reporters/ + - url: /docs/privacy-sandbox/attribution-reporting/report-schedules/ + tools_demos: + - url: https://arapi-home.web.app/ + title: Attribution Reporting API demo + description: In this demo an advertiser uses an ad-tech provider to run their ads on a publisher site. See how the API generates event-level and aggregatable reports. + - url: https://github.com/privacysandbox/measurement-simulation/blob/main/OVERVIEW.md + title: Measurement Simulation Library + description: Use historical data to see how it would look with the Attribution Reporting API. + - url: https://noise-lab.uc.r.appspot.com/?mode=simple + title: Noise Lab + description: Use Noise Lab to experiment with different values to see the impact of noise. + - url: https://wicg.github.io/attribution-reporting-api/validate-headers + title: Attribution Reporting Header Validator + description: Test out your headers to make sure you have the right fields for your API registrations. + - url: https://arapi-home.web.app/#:~:text=chrome%3A//attribution%2Dinternals + title: Chrome attribution internals + description: The demo illustrates how you can use chrome://attribution-internals/, but you can just type it in your browser to see sources, triggers, and more. + +--- + +{% from 'macros/cards/hero-card-wide.njk' import heroCardWide with context %} +{% from 'macros/cards/blog-card.njk' import blogCard with context %} +{% from 'macros/icon.njk' import icon with context %} +{% from 'macros/landing-section.njk' import landingSection with context %} +{% from 'macros/landing-deco.njk' import landingDeco with context %} +{% from 'macros/landing-section-expanded.njk' import landingSectionExpanded with context %} +{% from 'macros/landing-section-usecases.njk' import landingSectionUseCases with context %} + +{# landing-page-expanded has unique styles, added for Privacy Sandbox and expanded landing section. #} + +{{ heroCardWide( + "Attribution Reporting API developer guide", + "What you need to know to start working with the Attribution Reporting API.", + "", + "", + "", + "image/VbsHyyQopiec0718rMq2kTE1hke2/i1wLexi7cwRpdfIkBYAX.svg" + ) }} + +{{ landingSectionExpanded( + "Get started with the API", + "The first steps to get up and running.", + sections.intro, + "blue", + "top-4", + true, + "image/VbsHyyQopiec0718rMq2kTE1hke2/QDyL1Otpv6Id7sDTconF.svg", + "Graduation cap icon.", + 200, + 129, + "image/VbsHyyQopiec0718rMq2kTE1hke2/QDyL1Otpv6Id7sDTconF.svg" + ) +}} + +{{ landingSectionUseCases( + "Customize reports", + "Take advantage of the flexibility of the API.", + "", + sections.customize_reports, + "", + "", + "", + "green", + "right", + true, + "image/VbsHyyQopiec0718rMq2kTE1hke2/cT27jgN3G7aYl9ftM0lt.svg", + "Analytics icon.", + 284, + 193, + "image/VbsHyyQopiec0718rMq2kTE1hke2/pfYmfQtnte4ZKFE7r9nE.svg" + ) +}} + +{{ landingSectionUseCases( + "Tools and Demos", + "These tools and demos will help you test and understand the API.", + "", + sections.tools_demos, + "", + "", + "", + "red", + "right", + true, + "image/RtQlPaM9wdhEJGVKR8boMPkWf443/CDrmaiLPS4jpwuRRmtdn.svg", + "People icon.", + 429, + 278, + "image/VbsHyyQopiec0718rMq2kTE1hke2/yrsJmUfAnqDIDxjVYhXq.svg" + ) +}} + +{{ landingSectionUseCases( + "Advanced concepts", + "The background you need to achieve your measurement outcomes.", + "", + sections.advanced_concepts, + "", + "", + "", + "green", + "right", + true, + "image/RtQlPaM9wdhEJGVKR8boMPkWf443/Q3IWTvTWN8uWAKGq6hqd.svg", + "People icon.", + 284, + 193, + "image/VbsHyyQopiec0718rMq2kTE1hke2/pfYmfQtnte4ZKFE7r9nE.svg" + ) +}} From a6f4ec34ae82b14223060d3b5ecc32776017535f Mon Sep 17 00:00:00 2001 From: Nancymic2 <nmichell@google.com> Date: Tue, 3 Oct 2023 12:47:26 -0400 Subject: [PATCH 841/982] add grant testing faqs (#7415) * faqs * faqs * faqs * faqs * faqs * Update title per Claudia * Line 45 * add period Co-authored-by: Anusmita <anusmitaray@google.com> * reword Co-authored-by: Anusmita <anusmitaray@google.com> * Capitalization Co-authored-by: Anusmita <anusmitaray@google.com> * Capitalization Co-authored-by: Anusmita <anusmitaray@google.com> * link * remove agg serv Q for now --------- Co-authored-by: Anusmita <anusmitaray@google.com> --- site/_data/docs/privacy-sandbox/toc.yml | 5 +- .../{ => faq}/privacy-compliance-faq/index.md | 0 .../privacy-sandbox/faq/testing-faq/index.md | 68 +++++++++++++++++++ 3 files changed, 72 insertions(+), 1 deletion(-) rename site/en/docs/privacy-sandbox/{ => faq}/privacy-compliance-faq/index.md (100%) create mode 100644 site/en/docs/privacy-sandbox/faq/testing-faq/index.md diff --git a/site/_data/docs/privacy-sandbox/toc.yml b/site/_data/docs/privacy-sandbox/toc.yml index 639925e8b..97859a3b7 100644 --- a/site/_data/docs/privacy-sandbox/toc.yml +++ b/site/_data/docs/privacy-sandbox/toc.yml @@ -21,7 +21,10 @@ - url: /docs/privacy-sandbox/enroll title: i18n.docs.privacy-sandbox.enroll - url: /docs/privacy-sandbox/status - - url: /docs/privacy-sandbox/privacy-compliance-faq + - title: i18n.docs.privacy-sandbox.faq + sections: + - url: /docs/privacy-sandbox/faq/testing-faq/ + - url: /docs/privacy-sandbox/faq/privacy-compliance-faq - url: /docs/privacy-sandbox/feedback - title: i18n.docs.privacy-sandbox.strengthen-boundaries sections: diff --git a/site/en/docs/privacy-sandbox/privacy-compliance-faq/index.md b/site/en/docs/privacy-sandbox/faq/privacy-compliance-faq/index.md similarity index 100% rename from site/en/docs/privacy-sandbox/privacy-compliance-faq/index.md rename to site/en/docs/privacy-sandbox/faq/privacy-compliance-faq/index.md diff --git a/site/en/docs/privacy-sandbox/faq/testing-faq/index.md b/site/en/docs/privacy-sandbox/faq/testing-faq/index.md new file mode 100644 index 000000000..0dccb3eff --- /dev/null +++ b/site/en/docs/privacy-sandbox/faq/testing-faq/index.md @@ -0,0 +1,68 @@ +--- +layout: 'layouts/doc-post.njk' +title: 'Privacy Sandbox testing FAQs' +subhead: > + Answers to frequently asked questions related to Privacy Sandbox testing. +description: > + Answers to frequently asked questions related to Privacy Sandbox testing. +date: 2023-10-02 +--- + +**What are the key coordination areas between DSPs and SSPs for the Protected Audience API?** + +Below are the key aspects that require alignment: + +- **Creative audit**: Does the SSP have a creative pre-registration endpoint for scanning, and will DSP support that workflow? If not, discuss with the SSP what they require from the DSP to implement creative audit for publisher controls. +- **DSP's `renderURL` methodology**. Some SSPs may require the `renderURL` to include metadata such as `seatID` to support scoring and billing. How the DSP structures `renderURL` has implications for critical SSP use cases. +- **ORTB** + - ORTB 2.X bid request: How the SSP will signal PA-eligible auction to the DSP. + - ORTB 2.X bid response: How the DSP will respond to the SSP for PA auction. +- **PA on-device bidding data**: SSP to DSP + - `auctionSignals`: Data the SSP includes in the `auctionConfig` that is made available to all DSP bidding functions. +- **PA on-device scoring data**: DSP to SSP + - Bid: How to handle multi-currencies. Each SSP may have different requirements. + - Ad object (returned from `generateBid()`): The SSP may use this for scoring and publisher controls. DSPs and SSPs need to align on what data is included and on a data structure. +- **PA win reporting**: SSP to DSP + - What SSP's `reportResult()` will make available to the DSP's `reportWin()`. +- **Post-auction reporting**: DSP to SSP. Context: The DSP must capture and delegate post-auction reports to the SSP. If the SSP needs clicks, views, viewability metrics, the DSP must enable them to receive these events. + - What reports the SSP will need. + - The methodology for measuring that event (such as, viewability definition). + - DSP implementation of the `reportEvent()` call to support the SSP requirements. + - SSP implementation of the `registerAdBeacon()` lining up the event naming with what the DSP will trigger in the creative. + +**Is the Attribution Reporting API ready and available for testing?** + +The Attribution Reporting API will be generally available and ramp-up is already in progress. With that, Attribution Reporting will soon be available for use on 100% of traffic. Note that Attribution Reporting can be used with all ads, not just those served by Protected Audience. + +**Are there geographic requirements for testing?** + +There are no geographic requirements. It's up to each tester to determine geographic considerations as part of their test. + +**How does the CMA guidance align with Chrome-facilitated testing?** + +Chrome facilitated testing modes are aligned with the CMA's guidance for quantitative testing of Privacy Sandbox. In the CMA's guidance the treatment group relies on Privacy Sandbox technologies without third-party cookies. Control group 1 uses third-party cookies and not Privacy Sandbox, and Control group 2 uses neither Privacy Sandbox nor third-party cookies. With general availability, the Privacy Sandbox technologies will be available on all Chrome traffic, and the ad tech can choose to use Privacy Sandbox technologies in certain population groups and not in others. Additionally, ad techs can leverage the Mode A Chrome-facilitated testing traffic to coordinate these population groups across multiple parties. + +Starting in Q1 2024, Chrome will deprecate third-party cookies on 1% of traffic and this is referred to as the Mode B Chrome-facilitated testing traffic in Chrome developer documentation. In a small fraction of Mode B Chrome-facilitated testing traffic, Privacy Sandbox technologies will also not be available in addition to third-party cookies being deprecated. Using a combination of all of the above Chrome-facilitated testing modes, ad techs will be able to align their test setups to the testing guidance published by the CMA. Refer to [Chrome-facilitated testing](/docs/privacy-sandbox/chrome-testing/#:~:text=Mode%20A%3A%20Ad%20techs%20can,portion%20of%20all%20Chrome%20users.), which defines Mode A and Mode B and [CMA Guidance](https://assets.publishing.service.gov.uk/media/649d6a5f45b6a2000c3d455f/20230629_CMA_industry_testing_update_B.pdf) defines Control 1, Control 2, Treatment groups (in point number 11). + +**Is there a contact at the CMA we could connect with to better understand what is required for the submitted final report?** + +You can email the CMA case team at <a href="mailto:privacysandbox@cma.gov.uk">privacysandbox@cma.gov.uk</a> and read more about their [testing proposal guidance](https://assets.publishing.service.gov.uk/media/649d6a5f45b6a2000c3d455f/20230629_CMA_industry_testing_update_B.pdf). For additional reference, the CMA lists all their contacts at the bottom of their [Privacy Sandbox page](https://www.gov.uk/cma-cases/investigation-into-googles-privacy-sandbox-browser-changes). + +**Can you clarify the quantitative testing success metrics?** + +Grant participants can define and share as many additional KPIs as they want, beyond those specified in the SOW. The minimum test results that need to be shared are listed in the [CMA Guidance](https://assets.publishing.service.gov.uk/media/649d6a5f45b6a2000c3d455f/20230629_CMA_industry_testing_update_B.pdf). This guidance is purposefully "light" and broad so the CMA can compare many results from different ad techs. + +**Is there a volume threshold for testing, for example, control group ratios versus modes ratios? Do you have additional guidance on valuable KPIs to test beyond the CMA's testing guidance?** + +You can draft these volume / scale requirements in your integration plan. We will work with you to align on the scale required given your business model. You can include specific metrics and tests in your testing plan. Please keep in mind that the testing plan should take into account Mode A and Mode B of Chrome-facilitated testing. We can provide feedback on these once you submit them. + +**What types of publisher inventory integrations are supported by Protected Audience and TOPICS testing?** + +As part of the Market Testing Grants, we don't have any restrictions on the specific integration mechanisms, just that the Protected Audience auction should be end-to-end coordinated with other Privacy Sandbox-integrated parties and should aim to result in billable impressions. + +We understand that other companies' integration decisions could impact the types of inventory where Protected Audience and Topics can be tested. The SOW requirements give the contractor the ability to work within the types of inventory that are available to them based on their integrations with other parties who are using the APIs. + +**How will Google ensure participating DSP platforms are ready for the end-to-end test by January 1, 2024? How will Google facilitate connecting the committed DSPs, when they are ready, with us (partner)?** + +The Market Testing Grants program has both a DSP and SSP track, designed to accelerate both sides of the ecosystem. Participants will be [publicly listed on GitHub](https://github.com/WICG/turtledove/blob/main/fledge-tester-list.md) with contact information for coordination. The Privacy Sandbox team can also make introductions and attend joint meetings with coordinating ad techs. For example, we have had several joint meetings with multiple Privacy Sandbox partners to discuss Protected Audience and Topics integration. + From 6ecdf9329bf17cc5d92795b2437da6e58dbd3304 Mon Sep 17 00:00:00 2001 From: Jecelyn Yeen <5917927+jecfish@users.noreply.github.com> Date: Wed, 4 Oct 2023 11:23:37 +0200 Subject: [PATCH 842/982] Update WNDT 118 video link (#7438) * Update WNDT 118 video link * Update site/en/blog/new-in-devtools-118/index.md --- site/en/blog/new-in-devtools-118/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/en/blog/new-in-devtools-118/index.md b/site/en/blog/new-in-devtools-118/index.md index bf9c65d47..200ea17e5 100644 --- a/site/en/blog/new-in-devtools-118/index.md +++ b/site/en/blog/new-in-devtools-118/index.md @@ -16,7 +16,7 @@ tags: {% Partial 'devtools/banner.md' %} -{% YouTube id='Ta-YTDhiBIQ' %} +{% YouTube id='-dOYxJnRhxQ' %} <!-- $contentStart --> From c24425c2b832e042fec7005d8f1defaf3c503e1c Mon Sep 17 00:00:00 2001 From: Jack J <jxck@google.com> Date: Wed, 4 Oct 2023 18:24:13 +0900 Subject: [PATCH 843/982] Update fedcm-developer guide (#7402) - adding context - adding login_hints --- .../privacy-sandbox/fedcm-developer-guide/index.md | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/site/en/docs/privacy-sandbox/fedcm-developer-guide/index.md b/site/en/docs/privacy-sandbox/fedcm-developer-guide/index.md index 4b40c1033..08c0eb0b5 100644 --- a/site/en/docs/privacy-sandbox/fedcm-developer-guide/index.md +++ b/site/en/docs/privacy-sandbox/fedcm-developer-guide/index.md @@ -103,10 +103,12 @@ The config file's URL is determined by the values provided to the ```javascript const credential = await navigator.credentials.get({ identity: { + context: 'signup', providers: [{ configURL: 'https://accounts.idp.example/config.json', clientId: '********', - nonce: '******' + nonce: '******', + loginHint: 'demo1@example.com' }] } }); @@ -189,8 +191,10 @@ following properties: </tr> </table> +RP could modify the string in the FedCM dialog UI via `identity.context` value for `navigator.credentials.get()` to accommodate predefined authentication contexts. Optional property can be one of `"signin"` (default), `"signup"`, `"use"` or `"continue"`. + {% Img - src="image/VbsHyyQopiec0718rMq2kTE1hke2/rFrfrCL0awt5zmyqvaM9.jpg", alt="How branding is applied to the FedCM dialog", width="600", height="332", class="screenshot" + src="image/PV7xjXdOKHP8LWt9XhstsToJeK82/RZwmFnyJChjlki8QsnBB.png", alt="How branding is applied to the FedCM dialog", width="487", height="244" %} Here's an example response body from the IdP: @@ -293,6 +297,7 @@ Example response body: "email": "john_doe@idp.example", "picture": "https://idp.example/profile/123", "approved_clients": ["123", "456", "789"], + "login_hints": ["demo1", "demo1@example.com"], }, { "id": "5678", "given_name": "Johnny", @@ -300,6 +305,7 @@ Example response body: "email": "johnny@idp.example", "picture": "https://idp.example/profile/456" "approved_clients": ["abc", "def", "ghi"], + "login_hints": ["demo2", "demo2@example.com"], }] } ``` @@ -309,6 +315,8 @@ If the user is not signed in, respond with HTTP 401 (Unauthorized). The returned accounts list is consumed by the browser and will not be available to the RP. +By passing login_hints in the accounts list, the RP can invoke `navigator.credentials.get()` with the `loginHint` property to selectively show the specified account. + #### Client metadata endpoint {: #client-metadata-endpoint } The IdP's client metadata endpoint returns the relying party's metadata such as @@ -401,6 +409,7 @@ Origin: https://rp.example/ Content-Type: application/x-www-form-urlencoded Cookie: 0x23223 Sec-Fetch-Dest: webidentity + account_id=123&client_id=client1234&nonce=Ct60bD&disclosure_text_shown=true ``` From 9e6488b0b6eab388bb8c07a92b11c9f9e10c8aca Mon Sep 17 00:00:00 2001 From: Bramus! <bramus@bram.us> Date: Wed, 4 Oct 2023 13:19:51 +0200 Subject: [PATCH 844/982] Link old popover blogpost to new one (#7429) --- site/en/blog/pop-ups-theyre-making-a-resurgence/index.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/site/en/blog/pop-ups-theyre-making-a-resurgence/index.md b/site/en/blog/pop-ups-theyre-making-a-resurgence/index.md index 1d3bd96a8..9e1726e65 100644 --- a/site/en/blog/pop-ups-theyre-making-a-resurgence/index.md +++ b/site/en/blog/pop-ups-theyre-making-a-resurgence/index.md @@ -10,8 +10,9 @@ tags: - css - html date: 2022-09-13 -last_updated: 2023-01-25 +last_updated: 2023-10-03 is_outdated: true +new_available_content_url: /blog/introducing-popover-api/ --- {% Aside 'caution' %} From a8c78fd182b6c1f58305f5c7025d78df6e639e3f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 4 Oct 2023 13:32:30 +0200 Subject: [PATCH 845/982] Bump @mdn/browser-compat-data from 5.3.6 to 5.3.20 (#7437) --- package-lock.json | 14 +++++++------- package.json | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index 976b0befb..3d233d0b8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,7 +18,7 @@ "@google-cloud/error-reporting": "^2.0.4", "@google-cloud/storage": "^6.7.0", "@lhci/cli": "^0.7.2", - "@mdn/browser-compat-data": "5.3.6", + "@mdn/browser-compat-data": "5.3.20", "@rollup/plugin-node-resolve": "^8.4.0", "adm-zip": "0.5.10", "algoliasearch": "^4.6.0", @@ -2154,9 +2154,9 @@ } }, "node_modules/@mdn/browser-compat-data": { - "version": "5.3.6", - "resolved": "https://registry.npmjs.org/@mdn/browser-compat-data/-/browser-compat-data-5.3.6.tgz", - "integrity": "sha512-sDz0Yjj8m+VTWPiC0TF28rLMCDS2fJTZZmDpFMx5Y0H4NVGzqOs30l4pV8Tpexen4GyT+wYCNjedY8pTNjiW7Q==" + "version": "5.3.20", + "resolved": "https://registry.npmjs.org/@mdn/browser-compat-data/-/browser-compat-data-5.3.20.tgz", + "integrity": "sha512-UoZWTHXYXPm0AOcCgmbeirzJqE3fZ2P16qAs9kgMpckw67yCsYgdrQ2NqhlxJYpe6h/62I10+uX8xUZjwTp1sA==" }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", @@ -28281,9 +28281,9 @@ } }, "@mdn/browser-compat-data": { - "version": "5.3.6", - "resolved": "https://registry.npmjs.org/@mdn/browser-compat-data/-/browser-compat-data-5.3.6.tgz", - "integrity": "sha512-sDz0Yjj8m+VTWPiC0TF28rLMCDS2fJTZZmDpFMx5Y0H4NVGzqOs30l4pV8Tpexen4GyT+wYCNjedY8pTNjiW7Q==" + "version": "5.3.20", + "resolved": "https://registry.npmjs.org/@mdn/browser-compat-data/-/browser-compat-data-5.3.20.tgz", + "integrity": "sha512-UoZWTHXYXPm0AOcCgmbeirzJqE3fZ2P16qAs9kgMpckw67yCsYgdrQ2NqhlxJYpe6h/62I10+uX8xUZjwTp1sA==" }, "@nodelib/fs.scandir": { "version": "2.1.5", diff --git a/package.json b/package.json index ad96341b2..186d451b0 100644 --- a/package.json +++ b/package.json @@ -52,7 +52,7 @@ "@google-cloud/error-reporting": "^2.0.4", "@google-cloud/storage": "^6.7.0", "@lhci/cli": "^0.7.2", - "@mdn/browser-compat-data": "5.3.6", + "@mdn/browser-compat-data": "5.3.20", "@rollup/plugin-node-resolve": "^8.4.0", "adm-zip": "0.5.10", "algoliasearch": "^4.6.0", From 025e3734c1177a40be791b212e54702206d6a705 Mon Sep 17 00:00:00 2001 From: Bramus! <bramus@bram.us> Date: Wed, 4 Oct 2023 13:43:27 +0200 Subject: [PATCH 846/982] Add @scope article (#7427) --- site/en/articles/at-scope/index.md | 309 +++++++++++++++++++++++++++++ 1 file changed, 309 insertions(+) create mode 100644 site/en/articles/at-scope/index.md diff --git a/site/en/articles/at-scope/index.md b/site/en/articles/at-scope/index.md new file mode 100644 index 000000000..a2746a2e6 --- /dev/null +++ b/site/en/articles/at-scope/index.md @@ -0,0 +1,309 @@ +--- +layout: 'layouts/blog-post.njk' +title: Limit the reach of your selectors with the CSS `@scope` at-rule +authors: + - bramus +subhead: > + Learn how to use @scope to select elements only within a limited subtree of your DOM. +description: > + Learn how to use @scope to select elements only within a limited subtree of your DOM. +date: 2023-10-04 +hero: image/AeNB0cHNDkYPUYzDuv8gInYA9rY2/DP7MSi8WT7a2syzdBfiK.jpg +alt: "A street sign to indicate the road is narrowing." +tags: + - css + - chrome-118 +--- + +{% BrowserCompat 'css.at-rules.scope' %} + +## The delicate art of writing CSS selectors + +When writing selectors you may find yourself torn between two worlds. On the one hand you want to be pretty specific about which elements you select. On the other hand, you want your selectors to remain easy to override and not be tightly coupled to the DOM structure. + +For example, when you want to select “the hero image in the content area of the card component”–which is a rather specific element selection–you most likely don’t want to write a selector like `.card > .content > img.hero`. + +- This selector has a pretty high [specificity](https://web.dev/learn/css/specificity/) of `(0,3,1)` which makes it hard to override as your code grows. +- By relying on the direct child combinator it is tightly coupled to the DOM structure. Should the markup ever change, you need to change your CSS as well. + +But, you also don’t want to write just `img` as the selector for that element, as that would select all image elements across your page. + +Finding the right balance in this is often quite the challenge. Over the years, some developers have come up with solutions and workarounds to help you out in situations like these. For example: + +- Methodologies such as BEM dictate that you give that element a class of `card__img card__img--hero` to keep the specificity low while allowing you to be specific in what you select. +- JavaScript-based solutions such as [Scoped CSS](https://vue-loader.vuejs.org/guide/scoped-css.html) or [Styled Components](https://styled-components.com/) rewrite all your selectors by adding randomly generated strings–such as `sc-596d7e0e-4`–to your selectors to prevent them from targeting elements at the other side of your page. +- Some libraries even abolish selectors altogether and require you to put the styling triggers directly in the markup itself. + +But what if you didn’t need any of those? What if CSS gave you a way to be both pretty specific about which elements you select, without requiring you to write selectors of high specificity or ones that are tightly coupled to your DOM? Well, that’s where `@scope` comes into play, offering you a way to select elements only within a subtree of your DOM. + +## Introducing @scope + +With `@scope` you can limit the reach of your selectors. You do this by setting the _scoping root_ which determines the upper boundary of the subtree you want to target. With a scoping root set, the contained style rules –named _scoped style rules_– can only select from that limited subtree of the DOM. + +For example, to target only the `<img>` elements in the `.card` component, you set `.card` as the scoping root of the `@scope` at-rule. + +```css +@scope (.card) { + img { + border-color: green; + } +} +``` + +The scoped style rule `img { … }` can effectively only select `<img>` elements that are [in scope](https://drafts.csswg.org/css-cascade-6/#in-scope) of the matched `.card` element. + +{% Codepen { + user: 'web-dot-dev', + id: 'YzdOydZ', + height: 1000, + theme: 'dark', + tab: 'result' +} %} + +To prevent the `<img>` elements inside the card’s content area (`.card__content`) from being selected you could make the `img` selector more specific. Another way to do this is to use the fact that the `@scope` at-rule also accepts a _scoping limit_ which determines the lower boundary. + +```css +@scope (.card) to (.content) { + img { + border-color: green; + } +} +``` + +This scoped style rule only targets `<img>` elements that are placed between `.card` and `.content` elements in the ancestor tree. This type of scoping–with an upper and lower boundary–is often referred to as a _donut scope_ + +{% Codepen { + user: 'web-dot-dev', + id: 'wvREKRj', + height: 1000, + theme: 'dark', + tab: 'result' +} %} + +## The `:scope` selector + +By default, all scoped style rules are relative to the scoping root. It is also possible to target the scoping root element itself. For this, use the `:scope` selector. + +```css +@scope (.card) { + :scope { + /* Selects the matched .card itself */ + } + img { + /* Selects img elements that are a child of .card */ + } +} +``` + +Selectors inside scoped style rules implicitly get `:scope` prepended. If you want, you can be explicit about it, by prepending `:scope` yourself. Alternatively you can prepend the `&` selector, from [CSS Nesting](/articles/css-nesting/). + +```css +@scope (.card) { + img { + /* Selects img elements that are a child of .card */ + } + :scope img { + /* Also selects img elements that are a child of .card */ + } + & img { + /* Also selects img elements that are a child of .card */ + } +} +``` + +A scoping limit can use the `:scope` pseudo-class to require a specific relationship to the scoping root: + +```css +/* .content is only a limit when it is a direct child of the :scope */ +@scope (.media-object) to (:scope > .content) { ... } +``` + +A scoping limit can also reference elements outside their scoping root by using `:scope`. For example: + +```css +/* .content is only a limit when the :scope is inside .sidebar */ +@scope (.media-object) to (.sidebar :scope .content) { ... } +``` + +Note that the scoped style rules themselves can not escape the subtree. Selections like `:scope + p` are invalid because that tries to select elements that are not in scope. + +## `@scope` and specificity + +The selectors that you use in the prelude for `@scope` do not affect the specificity of the contained selectors. In the example below, the specificity of the `img` selector still is `(0,0,1)`. + +```css +@scope (#sidebar) { + img { /* Specificity = (0,0,1) */ + … + } +} +``` + +The specificity of `:scope` is that of a regular pseudo-class, namely `(0,1,0)`. + +```css +@scope (#sidebar) { + :scope img { /* Specificity = (0,1,0) + (0,0,1) = (0,1,1) */ + … + } +} +``` + +In the following example, internally, the `&` gets rewritten to the selector that is used for the scoping root, wrapped inside an `:is()` selector. In the end, the browser will use `:is(#sidebar, .card) img` as the selector to do the matching. This process is known as _[desugaring](https://en.wikipedia.org/wiki/Syntactic_sugar)_. + +```css +@scope (#sidebar, .card) { + & img { /* desugars to `:is(#sidebar, .card) img` */ + … + } +} +``` + +Because `&` gets desugared using `:is()`, the specificity of `&` is calculated following [the `:is()` specificity rules](https://brm.us/css-is#specificity): the specificity of `&` is that of its most specific argument. + +Applied to this example, the specificity of `:is(#sidebar, .card)` is that of its most specific argument, namely `#sidebar`, and therefore becomes `(1,0,0)`. Combine that with the specificity of `img`–which is `(0,0,1)`–and you end up with `(1,0,1)` as the specificity for the entire complex selector. + +```css +@scope (#sidebar, .card) { + & img { /* Specificity = (1,0,0) + (0,0,1) = (1,0,1) */ + … + } +} +``` + +## The difference between `:scope` and `&` inside `@scope` + +Besides differences in how specificity gets calculated, another difference between `:scope` and `&` is that `:scope` represents the matched scoping root, whereas `&` represents the selector used to match the scoping root. + +Because of this, it is possible to use `&` multiple times. This is in contrast to `:scope` which you can use only once, as you can’t match a scoping root inside a scoping root. + +```css +@scope (.card) { + & & { /* Selects a `.card` in the matched root .card */ + } + :root :root { /* ❌ Does not work */ + … + } +} +``` + +## Prelude-less scope + +When writing inline styles with the `<style>` element, you can scope the style rules to the `<style>` element’s enclosing parent element by not specifying any scoping root. You do this by omitting the `@scope`’s prelude. + +```html +<div class="card"> + <div class="card__header"> + <style> + @scope { + img { + border-color: green; + } + } + </style> + <h1>Card Title</h1> + <img src="…" height="32" class="hero"> + </div> + <div class="card__content"> + <p><img src="…" height="32"></p> + </div> +</div> +``` + +In the example above, the scoped rules only target elements inside the `div` with the class name `card__header`, because that `div` is the `<style>` element’s parent element. + +{% Codepen { + user: 'web-dot-dev', + id: 'JjwaYwG', + height: 1000, + theme: 'dark', + tab: 'result' +} %} + +## @scope in the cascade + +Inside of the [CSS Cascade](https://web.dev/learn/css/the-cascade/), `@scope` also adds a new criterion: _scoping proximity_. The step comes after specificity but before order of appearance. + +{% Img src="image/AeNB0cHNDkYPUYzDuv8gInYA9rY2/SqOlwVfRjOpeRzzbz9L7.svg", alt="Visualization of the CSS Cascade.", width="1920", height="1080" %} + +As [per specification](https://drafts.csswg.org/css-cascade-6/#cascade-proximity): + +> When comparing declarations that appear in style rules with different scoping roots, then the declaration with the fewest generational or sibling-element hops between the scoping root and the scoped style rule subject wins. + +This new step comes in handy when nesting several variations of a component. Take this example, that doesn’t use `@scope` just yet: + +```html +<style> + .light { background: #ccc; } + .dark { background: #333; } + .light a { color: black; } + .dark a { color: white; } +</style> +<div class="light"> + <p><a href="#">What color am I?</a></p> + <div class="dark"> + <p><a href="#">What about me?</a></p> + <div class="light"> + <p><a href="#">Am I the same as the first?</a></p> + </div> + </div> +</div> +``` + +When viewing that little bit of markup, the third link will be `white` instead of `black`, even though it’s a child of a `div` with the class `.light` applied to it. This is due to the order of appearance criterion which the cascade uses here to determine the winner. It sees that `.dark a` was declared last, so it’ll win from the `.light a` rule + +{% Codepen { + user: 'web-dot-dev', + id: 'eYbLpQw', + height: 1000, + theme: 'dark', + tab: 'result' +} %} + +With the scoping proximity criterion this is now solved: + +```css +@scope (.light) { + :scope { background: #ccc; } + a { color: black;} +} + +@scope (.dark) { + :scope { background: #333; } + a { color: white; } +} +``` + +Because both scoped `a` selectors have the same specificity, the scoping proximity criterion kicks into action. It weighs both selectors by proximity to their scoping root. For that third `a` element, it is only one hop to the `.light` scoping root but two to the `.dark` one. Therefore, the `a` selector in `.light` will win. + +{% Codepen { + user: 'web-dot-dev', + id: 'MWZqazx', + height: 1000, + theme: 'dark', + tab: 'result' +} %} + +## Closing note: Selector isolation, not style isolation + +One important note to make is that `@scope` limits the reach of the selectors, it does not offer style isolation. Properties that inherit down to children will still inherit, beyond the lower bound of the `@scope`. One such property is the `color` one. When declaring that one inside of a donut scope, the `color` will still inherit down to children inside the hole of the donut. + +```css +@scope (.card) to (.card__content) { + :scope { + color: hotpink; + } +} +``` + +{% Codepen { + user: 'web-dot-dev', + id: 'BavOoGY', + height: 1000, + theme: 'dark', + tab: 'result' +} %} + +In the example above, the `.card__content` element and its children have a `hotpink` color because they inherit the value from `.card`. + +_(Cover photo by [rustam burkhanov](https://unsplash.com/@rstm) [on Unsplash](https://unsplash.com/photos/a-street-sign-that-is-hanging-from-a-tree-RMpDxhmzHpE))_ From d6fb0289a882a2f6984d2e487ee237d7b1126cef Mon Sep 17 00:00:00 2001 From: Nancymic2 <nmichell@google.com> Date: Wed, 4 Oct 2023 08:11:55 -0400 Subject: [PATCH 847/982] Update fps.md (#7435) * Update fps.md * another FPS * another FPS --- site/en/_partials/privacy-sandbox/demos/fps.md | 12 +++++++----- site/en/docs/privacy-sandbox/chips/index.md | 2 +- site/en/docs/privacy-sandbox/chrome-testing/index.md | 6 +++--- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/site/en/_partials/privacy-sandbox/demos/fps.md b/site/en/_partials/privacy-sandbox/demos/fps.md index f2b3b66aa..2a5286209 100644 --- a/site/en/_partials/privacy-sandbox/demos/fps.md +++ b/site/en/_partials/privacy-sandbox/demos/fps.md @@ -1,18 +1,20 @@ {% Details %} {% DetailsSummary %} -**First-party Sets** +**Related Website Sets** {% endDetailsSummary %} {% Columns %} {% Column %} -First-Party Sets (FPS) is a way for a company to declare relationships among sites, so that browsers allow limited third-party cookie access for specific purposes. Chrome will use these declared relationships to decide when to allow or deny a site access to their cookies when in a third-party context. +Related Website Sets is a way for a company to declare relationships among sites, so that browsers allow limited third-party cookie access for specific purposes. Chrome will use these declared relationships to decide when to allow or deny a site access to their cookies when in a third-party context. [Demo](https://first-party-sets.glitch.me/) -[Docs](/docs/privacy-sandbox/first-party-sets/) +[Docs](/docs/privacy-sandbox/related-website-sets/) + +[Submission JSON generator](https://rws-json-generator.ue.r.appspot.com/) {% endColumn %} {% Column %} -<a href="https://first-party-sets.glitch.me/">{% Img src="image/RtQlPaM9wdhEJGVKR8boMPkWf443/xQbEZnwQ7Fjw8MOYuddS.png", alt="First-Party Sets demo.", width="600", height="400" %}</a> +<a href="https://first-party-sets.glitch.me/">{% Img src="image/RtQlPaM9wdhEJGVKR8boMPkWf443/xQbEZnwQ7Fjw8MOYuddS.png", alt="Related Website Sets demo.", width="600", height="400" %}</a> {% endColumn %} {% endColumns %} -{% endDetails %} \ No newline at end of file +{% endDetails %} diff --git a/site/en/docs/privacy-sandbox/chips/index.md b/site/en/docs/privacy-sandbox/chips/index.md index 1db61fdc8..194ed1bf6 100644 --- a/site/en/docs/privacy-sandbox/chips/index.md +++ b/site/en/docs/privacy-sandbox/chips/index.md @@ -150,7 +150,7 @@ The current Related Website Sets design relies on Storage Access API and does no Consider Related Website Sets in situations where you need the same cookie to be available to a service that's embedded in multiple related sites. -CHIPS provides the functionality for a service to act as an isolated component across multiple sites. If the service that's a member of a First-Party Set sets a partitioned cookie, its partition key will be the top-level site and that cookie will not be available to other set members. +CHIPS provides the functionality for a service to act as an isolated component across multiple sites. If the service that's a member of a Related Website Set sets a partitioned cookie, its partition key will be the top-level site and that cookie will not be available to other set members. If you have a use case that relies on a shared cookie partition across sites within a FPS you can [provide examples and feedback on the GitHub issue](https://github.com/WICG/first-party-sets/issues/94). diff --git a/site/en/docs/privacy-sandbox/chrome-testing/index.md b/site/en/docs/privacy-sandbox/chrome-testing/index.md index c337acf54..783a5b94b 100644 --- a/site/en/docs/privacy-sandbox/chrome-testing/index.md +++ b/site/en/docs/privacy-sandbox/chrome-testing/index.md @@ -74,13 +74,13 @@ opt-in for this mode, as it will be applied globally. There is, of course, the possibility that some site features may be impacted if the site hasn't yet adopted an alternative solution, such as [CHIPS](/docs/privacy-sandbox/chips/) or -[First-Party Sets](/docs/privacy-sandbox/first-party-sets/). +[Related Website Sets](/docs/privacy-sandbox/related-website-sets/). {% Aside %} If you rely on third-party cookie data for site functionality, read our [guide to prepare for third-party cookie phase-out](/docs/privacy-sandbox/third-party-cookie-phase-out/) -to understand if CHIPS or First-Party Sets can address your needs. We've +to understand if CHIPS or Related Website Sets can address your needs. We've launched a [public issue tracker](https://goo.gle/report-3pc-broken), where you can report site issues resulting from third-party cookie deprecation. @@ -91,7 +91,7 @@ owners of issues that impact user experience during this phase. Additionally, we plan to provide a small fraction of traffic within Mode B that also has Privacy Sandbox relevance and measurement APIs disabled. Other APIs, like -First-Party Sets, CHIPS, FedCM, and so on, will not be disabled. We anticipate +Related Website Sets, CHIPS, FedCM, and so on, will not be disabled. We anticipate that this combination will be helpful to establish a baseline of performance without third-party cookies, and we're seeking [feedback](https://github.com/GoogleChromeLabs/privacy-sandbox-dev-support/labels/chrome-testing) on From 6d38e3ee2ba1c0b07b2835bc4ec4e44f6c802236 Mon Sep 17 00:00:00 2001 From: Matthias Rohmer <mrohmer@google.com> Date: Wed, 4 Oct 2023 16:11:17 +0200 Subject: [PATCH 848/982] chore: update webdev-infra to 1.0.57 --- package-lock.json | 30 ++++++++++-------------------- package.json | 2 +- 2 files changed, 11 insertions(+), 21 deletions(-) diff --git a/package-lock.json b/package-lock.json index 3d233d0b8..816874853 100644 --- a/package-lock.json +++ b/package-lock.json @@ -60,7 +60,7 @@ "unistore": "^3.5.2", "uslug": "^1.0.4", "web-vitals": "^3.5.0", - "webdev-infra": "1.0.56", + "webdev-infra": "1.0.57", "xss": "^1.0.14" }, "devDependencies": { @@ -26055,15 +26055,15 @@ "integrity": "sha512-f5YnCHVG9Y6uLCePD4tY8bO/Ge15NPEQWtvm3tPzDKygloiqtb4SVqRHBcrIAqo2ztqX5XueqDn97zHF0LdT6w==" }, "node_modules/webdev-infra": { - "version": "1.0.56", - "resolved": "https://registry.npmjs.org/webdev-infra/-/webdev-infra-1.0.56.tgz", - "integrity": "sha512-r45gQyg+hoEfvIJnD6i+GGKFnoZz5vXqXHjlxYpNbO9DMbGOmIglyNTDH1roHetPKt5jbFXDNttUebEcnFsZTQ==", + "version": "1.0.57", + "resolved": "https://registry.npmjs.org/webdev-infra/-/webdev-infra-1.0.57.tgz", + "integrity": "sha512-objApuzYflthzahdP+bEFpi+G8JDWVLV2LMNc94oW6+qJ7k2SYxBN+ckmkq54BeqXl+2PognIy1VU8pMfq77gA==", "dependencies": { "@11ty/eleventy": "1.0.2", "@11ty/eleventy-cache-assets": "^2.3.0", "@imgix/js-core": "^3.1.3", "@justinribeiro/lite-youtube": "^0.9.1", - "@mdn/browser-compat-data": "5.2.x", + "@mdn/browser-compat-data": "5.3.x", "@swc/html": "0.0.18", "async-transforms": "^1.0.9", "browser-media-mime-type": "^1.0.0", @@ -26091,7 +26091,7 @@ "node": ">=14" }, "peerDependencies": { - "@mdn/browser-compat-data": "5.2.x" + "@mdn/browser-compat-data": "5.3.x" }, "peerDependenciesMeta": { "@mdn/browser-compat-data": { @@ -26099,11 +26099,6 @@ } } }, - "node_modules/webdev-infra/node_modules/@mdn/browser-compat-data": { - "version": "5.2.67", - "resolved": "https://registry.npmjs.org/@mdn/browser-compat-data/-/browser-compat-data-5.2.67.tgz", - "integrity": "sha512-AoLSQvglknsEyYoDHbDMGvMVt78PopMz4Kzzp+cQNlge0zGXn+QtwmIizAU+n0htMXSjNFfQOk2GgpQIrOZu0w==" - }, "node_modules/webdev-infra/node_modules/async-transforms": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/async-transforms/-/async-transforms-1.0.9.tgz", @@ -46564,15 +46559,15 @@ "integrity": "sha512-f5YnCHVG9Y6uLCePD4tY8bO/Ge15NPEQWtvm3tPzDKygloiqtb4SVqRHBcrIAqo2ztqX5XueqDn97zHF0LdT6w==" }, "webdev-infra": { - "version": "1.0.56", - "resolved": "https://registry.npmjs.org/webdev-infra/-/webdev-infra-1.0.56.tgz", - "integrity": "sha512-r45gQyg+hoEfvIJnD6i+GGKFnoZz5vXqXHjlxYpNbO9DMbGOmIglyNTDH1roHetPKt5jbFXDNttUebEcnFsZTQ==", + "version": "1.0.57", + "resolved": "https://registry.npmjs.org/webdev-infra/-/webdev-infra-1.0.57.tgz", + "integrity": "sha512-objApuzYflthzahdP+bEFpi+G8JDWVLV2LMNc94oW6+qJ7k2SYxBN+ckmkq54BeqXl+2PognIy1VU8pMfq77gA==", "requires": { "@11ty/eleventy": "1.0.2", "@11ty/eleventy-cache-assets": "^2.3.0", "@imgix/js-core": "^3.1.3", "@justinribeiro/lite-youtube": "^0.9.1", - "@mdn/browser-compat-data": "5.2.x", + "@mdn/browser-compat-data": "5.3.x", "@swc/html": "0.0.18", "async-transforms": "^1.0.9", "browser-media-mime-type": "^1.0.0", @@ -46597,11 +46592,6 @@ "striptags": "^3.1.1" }, "dependencies": { - "@mdn/browser-compat-data": { - "version": "5.2.67", - "resolved": "https://registry.npmjs.org/@mdn/browser-compat-data/-/browser-compat-data-5.2.67.tgz", - "integrity": "sha512-AoLSQvglknsEyYoDHbDMGvMVt78PopMz4Kzzp+cQNlge0zGXn+QtwmIizAU+n0htMXSjNFfQOk2GgpQIrOZu0w==" - }, "async-transforms": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/async-transforms/-/async-transforms-1.0.9.tgz", diff --git a/package.json b/package.json index 186d451b0..931c6641f 100644 --- a/package.json +++ b/package.json @@ -94,7 +94,7 @@ "unistore": "^3.5.2", "uslug": "^1.0.4", "web-vitals": "^3.5.0", - "webdev-infra": "1.0.56", + "webdev-infra": "1.0.57", "xss": "^1.0.14" }, "optionalDependencies": { From df5f709579d1f24852e183d64a91b9d6e0b700e8 Mon Sep 17 00:00:00 2001 From: Sofia Emelianova <42939855+sofiayem@users.noreply.github.com> Date: Thu, 5 Oct 2023 11:12:25 +0100 Subject: [PATCH 849/982] DevTools tips 27: Debugging Chrome extensions, promo post (#7433) * dtt 27 * fix eof --- site/en/blog/devtools-tips-27/index.md | 34 ++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 site/en/blog/devtools-tips-27/index.md diff --git a/site/en/blog/devtools-tips-27/index.md b/site/en/blog/devtools-tips-27/index.md new file mode 100644 index 000000000..1be3e15a6 --- /dev/null +++ b/site/en/blog/devtools-tips-27/index.md @@ -0,0 +1,34 @@ +--- +title: > + DevTools Tips: Debugging Chrome extensions +description: > + Learn how to use DevTools to debug Chrome extensions. +layout: 'layouts/blog-post.njk' +date: 2023-10-03 +authors: + - sofiayem +hero: 'image/NJdAV9UgKuN8AhoaPBquL7giZQo1/zfNyj8pAWFt4V1kzS5w4.png' +alt: > + DevTools Tips hero logo +tags: + - devtools + - devtools-tips +--- + +Chrome extensions are software programs that you can [build](/docs/extensions/mv3/getstarted/extensions-101/) using web technologies. Extensions let you customize the Chrome browsing experience. You can [publish](/docs/webstore/publish/) them and download them from [Chrome Web Store](https://chromewebstore.google.com/). + +Chrome DevTools provides a number of feature to help you debug extensions. + +{% YouTube id='Ta-YTDhiBIQ' %} + +Watch the video to learn how to: + +- [Load your unpacked extension](/docs/extensions/mv3/getstarted/development-basics/#load-unpacked) to Chrome and enable developer mode. +- View errors and inspect service workers. +- Reload extensions with a click. +- Debug extension memory. +- [Configure DevTools to not ignore content scripts](/docs/devtools/settings/ignore-list/). +- Debug [content scripts](/docs/extensions/mv3/content_scripts/). +- Reorder the **Sources** > **Content scripts** tab. + +To learn more, see [Extensions 101](/docs/extensions/mv3/getstarted/extensions-101/). From 667f301ed4fcdd79d13c5f67ed9fc3ab7df2c3ec Mon Sep 17 00:00:00 2001 From: wizardofdocs <83661258+wizardofdocs@users.noreply.github.com> Date: Thu, 5 Oct 2023 07:05:36 -0700 Subject: [PATCH 850/982] Updated Storage reference page (#7399) * Updated Storage reference page Reordered sections to match the Reference template. Questions in comments. * Update site/en/docs/extensions/reference/storage/index.md Updated phrasing Co-authored-by: Joe Medley <jmedley@google.com> * Update site/en/docs/extensions/reference/storage/index.md Updated API name Co-authored-by: Joe Medley <jmedley@google.com> * Update site/en/docs/extensions/reference/storage/index.md Updated procedure and list formatting Co-authored-by: Joe Medley <jmedley@google.com> * Update site/en/docs/extensions/reference/storage/index.md Updated formatting Co-authored-by: Joe Medley <jmedley@google.com> * Update site/en/docs/extensions/reference/storage/index.md Fixed typo Co-authored-by: Joe Medley <jmedley@google.com> * Update site/en/docs/extensions/reference/storage/index.md Updated phrasing and added explanatory link Co-authored-by: Joe Medley <jmedley@google.com> * Update site/en/docs/extensions/reference/storage/index.md Removed answered question comment Co-authored-by: Joe Medley <jmedley@google.com> * Replaced obscure truck vs pipes metaphor on Storage reference page --------- Co-authored-by: Joe Medley <jmedley@google.com> --- .../extensions/reference/storage/index.md | 88 ++++++++----------- 1 file changed, 37 insertions(+), 51 deletions(-) diff --git a/site/en/docs/extensions/reference/storage/index.md b/site/en/docs/extensions/reference/storage/index.md index a5b43c5f4..f8b35ab7e 100644 --- a/site/en/docs/extensions/reference/storage/index.md +++ b/site/en/docs/extensions/reference/storage/index.md @@ -13,76 +13,63 @@ The Storage API provides an extension-specific way to persist user data and stat - Stored settings persist even when using [split incognito][incognito]. - Includes an exclusive read-only [managed storage area][manifest-storage] for enterprise policies. +## Manifest {: #manifest} + +To use the storage API, declare the `"storage"` permission in the extension +[manifest][doc-manifest]. For example: + +```json +{ + "name": "My extension", + ... + "permissions": [ + "storage" + ], + ... +} +``` + +## Concepts and usage {: #usage } + {% Details %} {% DetailsSummary %} Can extensions use web storage APIs? {% endDetailsSummary %} -Even though extensions can use the [`Storage`][mdn-storage] interface (accessible from `window.localStorage`) in some contexts (popup and other HTML pages), it is not recommended for the following reasons: +While extensions can use the [`Storage`][mdn-storage] interface (accessible from `window.localStorage`) in some contexts (popup and other HTML pages), we don't recommend it for the following reasons: -- Extension's service worker cannot access `Storage`. +- Extension service workers can't use the Web Storage API. - Content scripts share storage with the host page. -- Data saved using the `Storage` interface is lost when the user clears their browsing history. +- Data saved using the Web Storage API is lost when the user clears their browsing history. To move data from web storage APIs to extension storage APIs from a service worker: 1. Create an offscreen document with a conversion routine and an [`onMessage`][on-message] handler. -1. Add a conversion routine to an offscreen document. -1. In the extension service worker check `chrome.storage` for your data. +1. In the extension service worker, check `chrome.storage` for your data. 1. If your data isn't found, [create][create-offscreen] an offscreen document and call [`sendMessage()`][send-message] to start the conversion routine. 1. Inside the offscreen document's `onMessage` handler, call the conversion routine. -There are also some nuances with how web storage APIs work in extensions. Learn more in the +There are also some nuances to how web storage APIs work in extensions. Learn more in the [Storage and Cookies][storage-and-cookies] article. {% endDetails %} ### Storage areas -The Storage API is divided into the following four buckets ("storage areas"): +The Storage API is divided into the following storage areas: [`storage.local`][prop-local] -: Data is stored locally, which is cleared when the extension is removed. The quota limitation is approximately 10 MB, but can be increased by requesting the `"unlimitedStorage"` permission. Consider using it to store larger amounts of data. - -{% Aside 'caution' %} -Before Chrome 114, the quota was approximately 5 MB. -{% endAside %} +: Data is stored locally and cleared when the extension is removed. The storage limit is 10 MB (5 MB in Chrome 113 and earlier), but can be increased by requesting the `"unlimitedStorage"` permission. We recommend using `storage.local` to store larger amounts of data. [`storage.sync`][prop-sync] -: If syncing is enabled, the data is synced to any Chrome browser that the user is logged into. If disabled, it behaves like `storage.local`. Chrome stores the data locally when the browser is offline and resumes syncing when it's back online. The quota limitation is approximately 100 KB, 8 KB per item. Consider using it to preserve user settings across synced browsers. - -{% Aside 'warning' %} -Local and sync storage areas should not store confidential user data because they are not encrypted. When working with sensitive data, consider using the `session` storage area to hold values in memory until the browser is shut down. -{% endAside %} +: If syncing is enabled, the data is synced to any Chrome browser that the user is logged into. If disabled, it behaves like `storage.local`. Chrome stores the data locally when the browser is offline and resumes syncing when it's back online. The quota limitation is approximately 100 KB, 8 KB per item. We recommend using `storage.sync` to preserve user settings across synced browsers. If you're working with sensitive user data, instead use `storage.session`. -[storage.session][prop-session] -: Holds data in memory for the duration of a browser session. By default, it's not exposed to content scripts, but this behavior can be changed by setting [`chrome.storage.session.setAccessLevel()`][method-access-level]. The quota limitation is approximately 10 MB. Consider using it to store global variables across service worker runs. +[`storage.session`][prop-session] +: Holds data in memory for the duration of a browser session. By default, it's not exposed to content scripts, but this behavior can be changed by setting [`chrome.storage.session.setAccessLevel()`][method-access-level]. The storage limit is 10 MB (1 MB in Chrome 111 and earlier). The`storage.session` interface is one of several [we recommend for service workers](/docs/extensions/mv3/service_workers/service-worker-lifecycle/#persist-data). -{% Aside 'warning' %} -Before Chrome 112, the quota was approximately 1 MB. -{% endAside %} - -[storage.managed][prop-managed] +[`storage.managed`][prop-managed] : Administrators can use a [schema][manifest-storage] and enterprise policies to configure a supporting extension's settings in a managed environment. This storage area is read-only. -## Manifest {: #manifest} - -To use the storage API, declare the `"storage"` permission in the extension -[manifest][doc-manifest]. For example: - -```json -{ - "name": "My extension", - ... - "permissions": [ - "storage" - ], - ... -} -``` - -## Usage {: #usage } - The following samples demonstrate the `local`, `sync`, and `session` storage areas: @@ -132,22 +119,21 @@ The following samples demonstrate the `local`, `sync`, and To learn more about the `managed` storage area, see [Manifest for storage areas][manifest-storage]. -## Storage and throttling limits {: #storage-and-throttling-limits} +### Storage and throttling limits {: #storage-and-throttling-limits} -Don't think of adding to the Storage API as putting things in a big truck. Think of adding to -storage as being like putting something in a pipe. The pipe may have material in it already, and it -may even be filled. Always assume a delay between when you add to storage and when it is actually -recorded. +The Storage API has the following usage limitations: +- Storing data often comes with performance costs, and the API includes storage quotas. We recommend being careful about what data you store so that you don't lose the ability to store data. +- Storage can take time to complete. Make sure to structure your code to account for that time. -For details on storage area limitations and what happens when they are exceeded, see the quota information for [`sync`][prop-sync], [`local`][prop-local], and [`session`][prop-session]. +For details on storage area limitations and what happens when they're exceeded, see the quota information for [`sync`][prop-sync], [`local`][prop-local], and [`session`][prop-session]. -## Use cases {: #examples} +## Use cases {: #use-cases} The following sections demonstrate common use cases for the Storage API. ### Synchronous response to storage updates -To track changes made to storage, you can add a listener to its `onChanged` event. When anything changes in storage, that event fires. The sample code listens for these changes: +To track changes made to storage, add a listener to its `onChanged` event. When anything changes in storage, that event fires. The sample code listens for these changes: {% Label %}background.js:{% endLabel %} @@ -215,7 +201,7 @@ chrome.storage.onChanged.addListener((changes, area) => { ### Asynchronous preload from storage {: #asynchronous-preload-from-storage} -Since service workers are not always running, Manifest V3 extensions sometimes need to +Because service workers don't run all the time, Manifest V3 extensions sometimes need to asynchronously load data from storage before they execute their event handlers. To do this, the following snippet uses an async `action.onClicked` event handler that waits for the `storageCache` global to be populated before executing its logic. From feec4b99d68352544cd56216e5f002000e710e60 Mon Sep 17 00:00:00 2001 From: Joe Medley <jmedley@google.com> Date: Thu, 5 Oct 2023 08:26:38 -0700 Subject: [PATCH 851/982] Consolidate action material (#7398) * Consolidate action material If the action material is on the same page is should be in the same place. * Move another action-related content block. * Move additional action instructions. * Move the Tooltip section. * Move popup information to action section. --- .../extensions/mv3/user_interface/index.md | 214 +++++++++--------- 1 file changed, 107 insertions(+), 107 deletions(-) diff --git a/site/en/docs/extensions/mv3/user_interface/index.md b/site/en/docs/extensions/mv3/user_interface/index.md index 754b28af4..8427ea01a 100644 --- a/site/en/docs/extensions/mv3/user_interface/index.md +++ b/site/en/docs/extensions/mv3/user_interface/index.md @@ -9,7 +9,7 @@ description: User interface and design guidelines for Chrome Extensions. Like Chrome's user interface, an extension user interface should be purposeful and minimal. Extensions should allow users to customize or enhance the user's browsing experience without distracting -from it. +from it. This guide explores required and optional user interface features. Use it to understand how and when to implement different user interface elements within an extension. @@ -17,10 +17,10 @@ to implement different user interface elements within an extension. ## The extension action {: #action } The [Action API][api-action] controls the extension's action (toolbar icon). It can either open a -[popup][section-popup] or trigger some functionality when it's [clicked][section-onclick]. +[popup][section-popup] or trigger some functionality when it's [clicked][section-onclick]. Users can trigger an extension's action by expanding the extension menu and selecting the desired -extension. +extension. To make it easier to access an extension, the user may choose to pin the extension's action to the toolbar. Once pinned, the extension's action will appear to the left of the extension menu. Users @@ -29,7 +29,7 @@ order. {% Columns %} -{% Column %} +{% Column %} <figure> {% Img src="image/BhuKGJaIeLNPW9ehns59NfwqKxF2/iouvm1a3lsQWGyg6fSMS.png", alt="Unpinned extension", @@ -39,7 +39,7 @@ width="400", height="374", class="screenshot" %} {% endColumn %} -{% Column %} +{% Column %} <figure> {% Img src="image/BhuKGJaIeLNPW9ehns59NfwqKxF2/KS09fVoCj3YWuIoH5EFn.png", alt="Pinned extension", @@ -81,89 +81,31 @@ When an extension is disabled, the icon is grayed out. If the user clicks the di the extension's context menu will appear. <figure> -{% Img src="image/BhuKGJaIeLNPW9ehns59NfwqKxF2/hlYsQJPFsF7WBAjJZ6DS.png", -alt="Clicked Disabled extension", width="252", height="180", class="screenshot" %} +{% Img src="image/BhuKGJaIeLNPW9ehns59NfwqKxF2/hlYsQJPFsF7WBAjJZ6DS.png", +alt="Clicked Disabled extension", width="252", height="180", class="screenshot" %} <figcaption> Disabled extension. </figcaption> </figure> -## Provide the extension icons - -An extension requires at least one icon to represent it. Provide icons in PNG format for the best -visual results, although any raster format supported by Chrome is accepted. This includes BMP, -GIF, ICO, and JPEG. - -{% Aside 'caution' %} - -SVG files are not supported for any icons declared in the manifest. - -{% endAside %} - -Ensure your icon follows the [extension icon best practices][docs-icon-guidelines]. - -### Designate action icons {: #icons } - -Icons specific to the toolbar are registered in the `"default_icon"` field under -[`"action"`][api-action] in the manifest. Including multiple sizes is encouraged to scale for the -16-dip space. At minimum, 16x16 and 32x32 sizes are recommended. - -{% Label %}manifest.json:{% endLabel %} - -```json -{ - "name": "My Awesome Extension", - ... - "action": { - "default_icon": { - "16": "extension_toolbar_icon16.png", - "32": "extension_toolbar_icon32.png" - } - } - ... -} -``` - -All icons should be square or they may be distorted. If no icons are supplied, Chrome will add a -generic one to the toolbar with the first letter of the extension name. - -### Create and register additional icons {: #icon_size } - -Include additional icons in the following sizes for uses outside of the toolbar. +### Respond to the action {: #click} -| Icon Size | Icon Use | -|-----------|--------------------------------------------------------| -| 16x16 | Favicon on the extension's pages and context menu icon.| -| 32x32 | Windows computers often require this size. | -| 48x48 | Displays on the extension management page. | -| 128x128 | Displays on installation and in the Chrome Web Store. | - - -Register icons in the manifest under the `"icons"` field. +It's possible to register an [`OnClicked` handler][action-onclicked] for when the user clicks the action +item. However, this won't fire if the action has a popup (default or otherwise). -{% Label %}manifest.json:{% endLabel %} +{% Label %}service-worker.js:{% endLabel %} -```json -{ - "name": "My Awesome Extension", - ... - "icons": { - "16": "extension_icon16.png", - "32": "extension_icon32.png", - "48": "extension_icon48.png", - "128": "extension_icon128.png" - } - ... -} +```js +chrome.action.onClicked.addListener((tab) => { + chrome.action.setTitle({tabId: tab.id, title: `You are on tab: ${tab.id}`}); +}); ``` -## Additional user interface features {: #additional_features } - ### Action badge {: #badge } Badges display a colored banner on top of the action icon. They can only be used when the `"action"` -is declared in the manifest. +is declared in the manifest. Use badges to indicate the state of the extension. The [Drink Water][sample-drink] sample extension displays a badge with "ON" to show the user they have successfully set an alarm and displays nothing when @@ -175,7 +117,7 @@ the extension is idle. Badges can contain up to 4 characters. <figure> {% Img src="image/BrQidfK9jaQyIHwdw91aVpkPiib2/nXwAHSWLBEgT8099ITT0.png", alt="Badge On", - height="72", width="72" %} + height="72", width="72" %} <figcaption> An action icon with a badge. </figcaption> @@ -185,11 +127,11 @@ the extension is idle. Badges can contain up to 4 characters. {% endColumn %} -{% Column %} +{% Column %} <figure> {% Img src="image/BrQidfK9jaQyIHwdw91aVpkPiib2/pNz8UgfTBMmcf7fE9wja.png", alt="Badge Off", - height="72", width="72" %} + height="72", width="72" %} <figcaption> An action icon without a badge. </figcaption> @@ -212,6 +154,29 @@ chrome.action.setBadgeText({text: 'ON'}); chrome.action.setBadgeBackgroundColor({color: '#4688F1'}); ``` +### Designate action icons {: #icons } + +Icons specific to the toolbar are registered in the `"default_icon"` field under +[`"action"`][api-action] in the manifest. Including multiple sizes is encouraged to scale for the +16-dip space. At minimum, 16x16 and 32x32 sizes are recommended. + +{% Label %}manifest.json:{% endLabel %} + +```json +{ + "name": "My Awesome Extension", + ... + "action": { + "default_icon": { + "16": "extension_toolbar_icon16.png", + "32": "extension_toolbar_icon32.png" + } + } + ... +} +``` + + ### Popup {: #popup } A popup is an HTML file that is displayed in a special window when the user clicks the action icon. @@ -222,7 +187,7 @@ The [Drink Water Event][sample-drink] example popup displays available timer opt alarm by clicking one of the provided buttons. <figure> -{% Img src="image/BrQidfK9jaQyIHwdw91aVpkPiib2/JVduBMXnyUorfNjFZmue.png", alt="The Drink Water popup", height="361", width="213", class="screenshot" %} +{% Img src="image/BrQidfK9jaQyIHwdw91aVpkPiib2/JVduBMXnyUorfNjFZmue.png", alt="The Drink Water popup", height="361", width="213", class="screenshot" %} <figcaption> The Drink Water popup. </figcaption> @@ -275,7 +240,68 @@ chrome.storage.local.get('signed_in', (data) => { }); ``` -### Side panel {: #side-panel } +### Tooltip {: #tooltip } + +Use a tooltip to give short descriptions or instructions to users when they hover over the action +icon. By default, the tootip displays the name of the extension. + +<figure> + {% Img src="image/BrQidfK9jaQyIHwdw91aVpkPiib2/Go8aQg0vd0f2hkOFElLK.png", alt="An +example tooltip", height="157", width="419", class="screenshot" %} + <figcaption> + An example tooltip. + </figcaption> +</figure> + +## Provide the extension icons + +An extension requires at least one icon to represent it. Provide icons in PNG format for the best +visual results, although any raster format supported by Chrome is accepted. This includes BMP, +GIF, ICO, and JPEG. + +{% Aside 'caution' %} + +SVG files are not supported for any icons declared in the manifest. + +{% endAside %} + +Ensure your icon follows the [extension icon best practices][docs-icon-guidelines]. + + +All icons should be square or they may be distorted. If no icons are supplied, Chrome will add a +generic one to the toolbar with the first letter of the extension name. + +Include additional icons in the following sizes for uses outside of the toolbar. {: #icon_size } + +| Icon Size | Icon Use | +|-----------|--------------------------------------------------------| +| 16x16 | Favicon on the extension's pages and context menu icon.| +| 32x32 | Windows computers often require this size. | +| 48x48 | Displays on the extension management page. | +| 128x128 | Displays on installation and in the Chrome Web Store. | + + +Register icons in the manifest under the `"icons"` field. + +{% Label %}manifest.json:{% endLabel %} + +```json +{ + "name": "My Awesome Extension", + ... + "icons": { + "16": "extension_icon16.png", + "32": "extension_icon32.png", + "48": "extension_icon48.png", + "128": "extension_icon128.png" + } + ... +} +``` + +## Additional user interface features {: #additional_features } + +### Side panel {: #side-panel } An extension side panel is an HTML file that provides additional functionality alongside the main content of a web page. The [Dictionary side panel][sample-dictionary-sidepanel] example allows users to right-click on a word and see the definition in the side panel. @@ -295,19 +321,6 @@ An extension side panel is an HTML file that provides additional functionality a For more samples and use cases, see the [Side Panel API][api-sidepanel] reference page. -### Tooltip {: #tooltip } - -Use a tooltip to give short descriptions or instructions to users when they hover over the action -icon. By default, the tootip displays the name of the extension. - -<figure> - {% Img src="image/BrQidfK9jaQyIHwdw91aVpkPiib2/Go8aQg0vd0f2hkOFElLK.png", alt="An -example tooltip", height="157", width="419", class="screenshot" %} - <figcaption> - An example tooltip. - </figcaption> -</figure> - Tooltips are registered in the `"default_title"` field under the `"action"` key in the manifest. {% Label %}manifest.json:{% endLabel %} @@ -325,19 +338,6 @@ Tooltips are registered in the `"default_title"` field under the `"action"` key Tooltips can also be set or updated by calling [`action.setTitle()`][action-settitle]. -### Click Event {: #click} - -It's possible to register an [`OnClicked` handler][action-onclicked] for when the user clicks the action -item. However, this won't fire if the action has a popup (default or otherwise). - -{% Label %}service-worker.js:{% endLabel %} - -```js -chrome.action.onClicked.addListener((tab) => { - chrome.action.setTitle({tabId: tab.id, title: `You are on tab: ${tab.id}`}); -}); -``` - ### Omnibox {: #omnibox } Users can invoke extension functionality through the [Omnibox API][api-omnibox]. Include the `"omnibox"` @@ -575,7 +575,7 @@ permission in the manifest. {% Label %}manifest.json:{% endLabel %} ```json/5 -{ +{ "name": "Drink Water Event Popup", ... "permissions": [ @@ -608,7 +608,7 @@ function showStayHydratedNotification() { ``` <figure> -{% Img src="image/BhuKGJaIeLNPW9ehns59NfwqKxF2/e5S112AtwfnA5o64JrGg.png", +{% Img src="image/BhuKGJaIeLNPW9ehns59NfwqKxF2/e5S112AtwfnA5o64JrGg.png", alt="Mac OS notification", width="500", height="150", class="screenshot" %} <figcaption> Notification on macOS. From 605132d2c6cff2f0459e93ea5c47c019516e3b33 Mon Sep 17 00:00:00 2001 From: Joe Medley <jmedley@google.com> Date: Thu, 5 Oct 2023 16:48:50 -0700 Subject: [PATCH 852/982] Update for per-item privacy policy. (#7446) * Update for per-item privacy policy. * Update site/en/docs/webstore/cws-dashboard-privacy/index.md * Update site/en/docs/webstore/publish/index.md --- .../webstore/cws-dashboard-privacy/index.md | 9 +++++- site/en/docs/webstore/publish/index.md | 28 +++++++++++-------- .../en/docs/webstore/troubleshooting/index.md | 9 +++--- 3 files changed, 29 insertions(+), 17 deletions(-) diff --git a/site/en/docs/webstore/cws-dashboard-privacy/index.md b/site/en/docs/webstore/cws-dashboard-privacy/index.md index febc42877..54d79a776 100644 --- a/site/en/docs/webstore/cws-dashboard-privacy/index.md +++ b/site/en/docs/webstore/cws-dashboard-privacy/index.md @@ -2,7 +2,7 @@ layout: "layouts/doc-post.njk" title: Fill out the privacy fields date: 2020-06-12 -updated: 2023-05-01 +updated: 2023-10-06 description: > Use the privacy practices tab to help the Chrome Web Store team review your extension as quickly as possible. @@ -83,6 +83,12 @@ group of checkboxes to certify that you comply with each of the disclosure state {% Img src="image/SHhb2PDKzXTggPGAYpv8JgR81pX2/PwmNuP356TsVi80bxWAj.png", alt="Screenshot of data use certification fields", width="800", height="495" %} +## Set a privacy policy {: #set-privacy-policy } + +Add a link to the privacy policy for your extension. The policy should include how data is collected, used, and disclosed. See the [User Data FAQ][user-data] for details. + +{% Img src="image/sQ51XsLqKMgSQMCZjIN0B7hlBO02/BB2ziYwins4YpyJ7aETj.png", alt="Screenshot of the privacy policy box", width="674", height="178" %} + ## You are almost ready to publish this item! If you haven't done so yet, complete your listing by @@ -96,3 +102,4 @@ If you haven't done so yet, complete your listing by [remote-code]: /docs/extensions/mv3/intro/mv3-overview/#remotely-hosted-code [setup-account]: /docs/webstore/publish#setup-a-developer-account [upload-item]: /docs/webstore/publish/#upload-your-item +[user-data]: /docs/webstore/user_data/ diff --git a/site/en/docs/webstore/publish/index.md b/site/en/docs/webstore/publish/index.md index ac9f18f1e..42de34838 100644 --- a/site/en/docs/webstore/publish/index.md +++ b/site/en/docs/webstore/publish/index.md @@ -2,7 +2,7 @@ layout: "layouts/doc-post.njk" title: "Publish in the Chrome Web Store" date: 2014-02-28 -updated: 2023-05-01 +updated: 2023-10-06 description: > How to publish a new extension or theme to the Chrome Web Store. --- @@ -33,7 +33,7 @@ We'll go into detail about each step below. ## Create your item's zip file {: #create-your-items-zip-file } -To upload your item, you need to create a ZIP file that contains the +To upload your item, you need to create a ZIP file that contains the manifest file located in the **root directory** and the files for your extension. The manifest file must specify at least the following fields: - `"name":`—This [name][name] appears in the Chrome Web Store and in the Chrome browser @@ -65,17 +65,21 @@ If you already host your item in Google Play and you want your Chrome Web Store After registering, finish setting up your developer account on the Account page. (To access the Account page click the link in the left menu. -{% Img src="image/BhuKGJaIeLNPW9ehns59NfwqKxF2/lBcTQm6QF1FBzOmLEfG1.png", alt="Chrome Web Store Account page", width="800", height="404" %} +{% Img src="image/sQ51XsLqKMgSQMCZjIN0B7hlBO02/3TbrDEevyQgXd6sgvf9Y.png", alt="Chrome Web Store Account page", width="800", height="274" %} -Here you can provide your developer profile information, configure management settings and enable email notifications, among other things. The page itself provides instruction; however, there a few fields worth calling out. +Here you can provide your developer profile information, configure management settings and enable email notifications, among other things. The page itself provides instruction; however, there a few fields worth calling out. -| Field | Description | -| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| **Publisher name** | (Required) Appears under the title of each of your extensions. If you are a [verified publisher][verified-publisher], you can display an official publisher URL instead. | -| **Add email** | (Required) Only displayed under your extensions' contact information. Any notifications will be sent to your Chrome Web Store developer account email. | -| **Privacy policy** | (Required) A link to the privacy policy for all your extensions. The policy should include how data is collected, used, and disclosed. See the [User Data FAQ][user-data] for more details. | -| **Physical address** | (Required) Only items that offer functionality to purchase items, additional features, or subscriptions must include a physical address. | -| **Trusted tester accounts** | (Optional) A comma-separated list of individuals' email addresses to make your extension available to them for testing. | +Publisher name (Required) +: Appears under the title of each of your extensions. If you are a [verified publisher][verified-publisher], you can display an official publisher URL instead. + +Add email (Required) +: Only displayed under your extensions' contact information. Any notifications will be sent to your Chrome Web Store developer account email. + +Physical address (Required in some circumstances) +: Only items that offer functionality to purchase items, additional features, or subscriptions must include a physical address. + +Trusted tester accounts (Optional) +: A comma-separated list of individuals' email addresses to make your extension available to them for testing. {% Aside 'important' %} The Trusted tester accounts field does *not* support using group email addresses such as those used for posting to Google groups or other forums. If you need to test with a group, do so using the item level visibility setting. Click **Items** in the menu at left. Scroll to **Visibility**. Then select **Private** and **Only trusted testers from the current publisher settings**. @@ -173,7 +177,7 @@ if you simply want to change your rollout time. Once the review is complete, you will have up to **30 days** to publish. After that period expires, the staged submission will revert to a draft which will have to be submitted again for -review. You can check when your staged submission will expire under the status of your item. +review. You can check when your staged submission will expire under the status of your item. {% Img src="image/BhuKGJaIeLNPW9ehns59NfwqKxF2/sYCH3lvreW0bUWznlOsE.png", alt="Chrome Web Store staged item diff --git a/site/en/docs/webstore/troubleshooting/index.md b/site/en/docs/webstore/troubleshooting/index.md index fc2e803de..1a563bc3a 100644 --- a/site/en/docs/webstore/troubleshooting/index.md +++ b/site/en/docs/webstore/troubleshooting/index.md @@ -2,7 +2,7 @@ layout: "layouts/doc-post.njk" title: "Troubleshooting Chrome Web Store violations" date: 2020-11-16 -updated: 2023-08-08 +updated: 2023-10-06 description: > Guidelines for understanding why an item was rejected or removed from the Chrome Web Store and how to fix the problem. @@ -350,8 +350,9 @@ that users are aware of what data is collected, and how it is collected, used, a - Add a valid, working and accessible link to your privacy policy [in the designated field][docs-publish-setup]. - - Visit the Chrome Web Store item listing for your extension to verify that a privacy policy - link appears in the "Additional Information" box and that the link works as expected. + - Visit the Privacy tab for your extension to verify that a privacy policy link appears + in the "Privacy Policy" box (located at the bottom of the Privacy tab) and that the + link works as expected. - Ensure the privacy policy talks about data collection, usage, handling, and sharing. - If you have done the above but are still encountering review issues, [contact developer support][dev-support] to request clarification or appeal the verdict. @@ -1309,7 +1310,7 @@ Store [docs-override-page]: /docs/extensions/mv3/override/ [docs-override-settings]: /docs/extensions/mv3/settings_override/ [docs-pack-extension]: /docs/extensions/mv3/linux_hosting/#create -[docs-publish-setup]: /docs/webstore/publish/#setup-a-developer-account +[docs-publish-setup]: /docs/webstore/cws-dashboard-privacy/#set-privacy-policy [docs-service-workers]: /docs/extensions/mv3/service_workers/ [docs-single-purpose-faq]: /docs/extensions/mv3/single_purpose/ [lie-fi]: https://web.dev/performance-poor-connectivity/#what-is-lie-fi From 59986fb442176b0b0f4ab68fbd781eb1b7237da7 Mon Sep 17 00:00:00 2001 From: Joe Medley <jmedley@google.com> Date: Thu, 5 Oct 2023 19:12:43 -0700 Subject: [PATCH 853/982] Fix dates on privacy policy updates (#7447) * Fix date on privacy updates * Fix dates on privacy updates. --- site/en/docs/webstore/cws-dashboard-privacy/index.md | 2 +- site/en/docs/webstore/publish/index.md | 2 +- site/en/docs/webstore/troubleshooting/index.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/site/en/docs/webstore/cws-dashboard-privacy/index.md b/site/en/docs/webstore/cws-dashboard-privacy/index.md index 54d79a776..c352914ba 100644 --- a/site/en/docs/webstore/cws-dashboard-privacy/index.md +++ b/site/en/docs/webstore/cws-dashboard-privacy/index.md @@ -2,7 +2,7 @@ layout: "layouts/doc-post.njk" title: Fill out the privacy fields date: 2020-06-12 -updated: 2023-10-06 +updated: 2023-10-05 description: > Use the privacy practices tab to help the Chrome Web Store team review your extension as quickly as possible. diff --git a/site/en/docs/webstore/publish/index.md b/site/en/docs/webstore/publish/index.md index 42de34838..df808609c 100644 --- a/site/en/docs/webstore/publish/index.md +++ b/site/en/docs/webstore/publish/index.md @@ -2,7 +2,7 @@ layout: "layouts/doc-post.njk" title: "Publish in the Chrome Web Store" date: 2014-02-28 -updated: 2023-10-06 +updated: 2023-10-05 description: > How to publish a new extension or theme to the Chrome Web Store. --- diff --git a/site/en/docs/webstore/troubleshooting/index.md b/site/en/docs/webstore/troubleshooting/index.md index 1a563bc3a..2c4fc18f2 100644 --- a/site/en/docs/webstore/troubleshooting/index.md +++ b/site/en/docs/webstore/troubleshooting/index.md @@ -2,7 +2,7 @@ layout: "layouts/doc-post.njk" title: "Troubleshooting Chrome Web Store violations" date: 2020-11-16 -updated: 2023-10-06 +updated: 2023-10-05 description: > Guidelines for understanding why an item was rejected or removed from the Chrome Web Store and how to fix the problem. From 74b32d44b32ff23cdec647713e51fea70e192e43 Mon Sep 17 00:00:00 2001 From: ilyaspiridonov <spiridonov.ilya@gmail.com> Date: Fri, 6 Oct 2023 12:58:15 +0300 Subject: [PATCH 854/982] [JA] Privacy Sandbox translations (#7448) * Translate index.md via GitLocalize * Translate index.md via GitLocalize * Translate index.md via GitLocalize * Update index.md fm * Update index.md * Update index.md --------- Co-authored-by: mt-gitlocalize <mt@gitlocalize.com> Co-authored-by: Nozomi Kugita <nozomi@nozygatos.com> --- .../privacy-sandbox/chrome-testing/index.md | 94 ++++++++++- site/ja/docs/privacy-sandbox/videos/index.md | 157 ++++++++++++++++++ 2 files changed, 244 insertions(+), 7 deletions(-) create mode 100644 site/ja/docs/privacy-sandbox/videos/index.md diff --git a/site/ja/docs/privacy-sandbox/chrome-testing/index.md b/site/ja/docs/privacy-sandbox/chrome-testing/index.md index 57a3e5fd4..857c30fff 100644 --- a/site/ja/docs/privacy-sandbox/chrome-testing/index.md +++ b/site/ja/docs/privacy-sandbox/chrome-testing/index.md @@ -4,29 +4,42 @@ title: Chrome を利用したテスト subhead: サードパーティ Cookie を無効にしてサイトをテストします。 description: サードパーティ Cookie を無効にしてサイトをテストします。 date: 2023-05-18 +updated: 2023-09-01 authors: - alexandrawhite - rowan_m --- -広告関連 API の[一般提供](/blog/shipping-privacy-sandbox/)を準備する中で、サードパーティ Cookie のない世界でサイトがどのように動作するかを有意義にプレビューできるように、Chrome を利用したテストを提供する予定です。これにより、より効果的な API テストを実行できるようになり、エコシステム内でサードパーティ Cookie の段階的廃止への対応に確信をもてるようになります。 +サードパーティ Cookie の廃止に備え、サイトがサードパーティ Cookie を使用せずにサイトがどのように動作し機能するかをプレビューできるテストモードを Chrome で提供する予定です。この記事では、Chrome が提供する予定のテストモードの概要と、実験グループのラベルにアクセスする方法について説明します。 -Google は CMA との連携により、これらのテストモードが *[Google のプライバシーサンドボックステクノロジーの定量的テスト](https://assets.publishing.service.gov.uk/media/6363b00de90e0705a8c3544d/CMA_Experiments_note.pdf)* に関するメモに記載されているサードパーティ向けのテストフレームワーク(およびタイムライン)と一致していることを確認してきました。その結果、CMA は、これらのモードでのテストの結果がプライバシーサンドボックスの評価に使用できると考えています。 +{% Aside %} + +このテストは、次のプライバシーサンドボックス広告関連 API(PS R&M API)のパフォーマンスの測定に焦点を当てています: アトリビューション レポート、保護されたオーディエンス、トピック、プライベート集計、共有ストレージ、および Fenced Frames。 + +{% endAside %} + +Google は CMA との連携により、これらのテストモードが[業界テストに関するガイダンス](https://www.gov.uk/cma-cases/investigation-into-googles-privacy-sandbox-browser-changes#industry-testing)に記載されているサードパーティ向けのテストフレームワーク(およびタイムライン)に準じていることを確認してきました。そのため、CMA は、これらのモードでのテストの結果がプライバシーサンドボックスの評価に使用できると考えています。 Chrome を利用したテストには 2 つのモードを用意する予定です。 - **モード A**: アドテックは、トラフィックの一部でコントロールラベルと実験ラベルを受け取り、これらを使用してテストと実験を実施できます。 - **モード B**: Chrome は、全 Chrome ユーザーの一部に対してサードパーティ Cookie をグローバルに無効にします。 -これらの詳細は最終的なものではなく、2023 年第 3 四半期の進捗に合わせてさらなる実装ガイダンスを公開する予定です。現在の提案は次のとおりです。 +{% Aside %} + +ラベルは、HTTP ヘッダーまたは JavaScript API 経由でアクセスできる一時的な cookie-deprecation 値を介して利用可能になります。実装の詳細については、後の[「cookie-deprecation 値を介したラベルへのアクセス」](#cookie-deprecation-value)セクションをご覧ください。 + +{% endAside %} + +モード内のグループの構成とサイズに関する一部の詳細は正確で最終的なものではありませんが、それらは CMA のテストガイダンスで定義されている処置と制御のグループに一致する予定であり、2023 年第 3 四半期にさらなる実装ガイダンスを公開する予定です。現在の提案は以下のとおりです。 ## モード A: オプトインテスト {: #mode-a } -アドテックは、Chrome トラフィックの一部について実験ラベルを受け取ることができます。アドテックは、他のアドテックと連携して、たとえば、一貫した実験グループに対してサードパーティ Cookie を使用せずに [Protected Audience](/docs/privacy-sandbox/fledge/) オークションを実行することを選択できます。アドテックは、これらのラベルを独自の実験やテストに使用することもできます。 +アドテックは、Chrome トラフィックの一部について実験的な処置と制御グループのラベルを受け取ることができます。アドテックは、他のアドテックと連携して、たとえば、一貫した実験グループに対してサードパーティ Cookie を使用せずに [Protected Audience](/docs/privacy-sandbox/protected-audience/) オークションを実行することを選択できます。アドテックは、これらのラベルを独自の実験やテストに使用することもできます。 Chrome は、モード A のユーザーのサードパーティ Cookie の状態を変更しません。Chrome は、アドテックが一貫したコントロールグループと実験グループを使用して実験できるように、ラベルを提供するだけです。つまり、アドテックパートナーが実験に参加している場合でも、サイト運営者自身が使用する目的でサイト運営者のサイトがサードパーティ Cookie データを受け取る可能性があるということになります。 -これにより、関係するすべてのサイトとサービスが連携して、プロセス内のどの時点でもサードパーティ Cookie が使用されないようにすることができる、有意義な実験が可能になると期待しています。新しいリクエストヘッダーと低エントロピーのクライアント ヒントを介して、最大 10% の Chrome ブラウザにラベルが提供される予定です。テストに関心のある方は、ラベルへのアクセス方法とラベルの粒度についてエコシステムからの[フィードバック](https://github.com/GoogleChromeLabs/privacy-sandbox-dev-support/issues)を提供することをお勧めします。 +これにより、関係するすべてのサイトとサービスが連携して、プロセス内のどの時点でもサードパーティ Cookie が使用されないようにすることができる、有意義な実験が可能になると期待しています。最大 9% の Chrome ブラウザにラベルが提供される予定です。テストに興味がある方は、ラベルへのアクセス方法とラベルの粒度についてエコシステムから[フィードバック](https://github.com/GoogleChromeLabs/privacy-sandbox-dev-support/issues)を提供することをお勧めします。 オプトインテストモードは 2023 年第 4 四半期から利用可能になる予定で、サードパーティ Cookie が廃止されるまでこのモードは継続されます。 @@ -42,12 +55,79 @@ Chrome は最大 1% のブラウザに対してサードパーティ Cookie を 私たちは、この段階でユーザーエクスペリエンスに影響を与えるイシューを検出し、対処し、サイト所有者に積極的に警告するための緩和策に取り組んでいます。 -さらに、プライバシーサンドボックスの広告関連 API が無効になっているモード B 内のトラフィックのごく一部を提供する予定です。First-Party Sets、CHIPS、FedCM などの他の API は無効になりません。この組み合わせは、サードパーティ Cookie を使用しないパフォーマンスのベースラインを確立するのに役立つと予想されており、このサブセットのテストに充てるトラフィックの適切な部分に関する[フィードバック](https://github.com/GoogleChromeLabs/privacy-sandbox-dev-support/labels/chrome-testing)を求めています。 +さらに、プライバシーサンドボックス広告関連 API が無効になっているモード B 内のトラフィックのごく一部を提供する予定です。First-Party Sets、CHIPS、FedCM などの他の API は無効になりません。この組み合わせは、サードパーティ Cookie を使用しないパフォーマンスのベースラインを確立するのに役立つと予想されており、このサブセットのテストに充てるトラフィックの適切な割合に関する[フィードバック](https://github.com/GoogleChromeLabs/privacy-sandbox-dev-support/labels/chrome-testing)を求めています。 2024 年第 1 四半期にサードパーティ Cookie の 1% を廃止する予定であり、廃止範囲を拡大するためのさらなる措置を講じる前に CMA と緊密に連携します。 -## 貢献とフィードバックの共有 +## `Cookie-Deprecation` 値を介したラベルへのアクセス {: #cookie-deprecation-value} + +モード A とモード B の期間中、オプトイン HTTP ヘッダーと JavaScript API 経由でアクセスできる一時的な `Cookie-Deprecation` 値を導入します。これにより、いずれかに該当する場合に、ブラウザの該当するモード A または B の実験グループ(上述の割合で定義)用のラベルが提供されます。実験が終了したら、この値は削除されます。 + +ラベルへのアクセスには、ユーザーのデバイスに保存されている情報へのアクセスが含まれます。一部の法域(EU や英国など)では、このアクティビティは Cookie の使用に類似しているため、ラベルにアクセスするにはエンド ユーザーの同意が必要になる可能性があると理解しています。ラベルのリクエストを開始する前に、この同意義務があなたに適用されるかどうかについて法的なアドバイスを求めることをお勧めします。 + +{% Aside %} + +Chromium で出荷されるすべての機能と同様に、[Blink 開発プロセスの一環として Intent to Prototype を送信](/docs/privacy-sandbox/proposal-lifecycle/)します。以下の実装の詳細は Google が提案しているものですが、Chrome 安定版で**機能を出荷する前に変更される可能性があります**。このドキュメントの更新は継続して行われる予定です。また、この Intent が [blink-dev メーリングリスト](https://groups.google.com/a/chromium.org/g/blink-dev)に投稿されたら、公開ディスカッションをフォローすることもできます。 + +{% endAside %} + +### `Sec-Cookie-Deprecation` HTTP ヘッダーへのアクセス + +`Sec-Cookie-Deprecation` リクエストヘッダーを受信するには、サイトはまず、`receive-cookie-deprecation` Cookie を設定する必要があります。この Cookie は <code>[Partitioned attribute](/docs/privacy-sandbox/chips/)</code> を使用する必要があります。つまり、ヘッダーを受信するためのオプトインをトップレベルサイトごとに行う必要があるということです。 + +たとえば、`3p-example.site` が `example.com` に埋め込まれたリソースで `Sec-Cookie-Deprecation` ヘッダーを受信したい場合、`3p-example.site` はそのコンテキストで次の Cookie を設定する必要があります。 + +```text +Set-Cookie: receive-cookie-deprecation=1; Secure; HttpOnly; Path=/; SameSite=None; Partitioned; +``` + +`Secure`、`HttpOnly`、`Path`、`SameSite`、および `Partitioned` Cookie 属性は必須です。他の属性の `Domain`、`Expires`、および `Max-Age` はニースに応じて適切に設定できます。 + +ブラウザが `example_label_1 group` に属していると仮定すると、この Cookie を含む後続のリクエストには `Sec-Cookie-Deprecation` ヘッダーも含まれます。 + +```text +Sec-Cookie-Deprecation: example_label_1 +``` + +ブラウザがグループに属していない場合、ヘッダーは送信されません。 + +ラベルは Cookie の存在に関連付けられているため、Cookie が削除されるとラベルも送信されなくなります。`Partitioned` 属性は、サードパーティ Cookie が完全に廃止になった後も継続して使用することを目的としているため、サードパーティ Cookie がブロックされるときに `Partitioned` Cookie が設定される可能性があります。 + +### cookieDeprecationLabel JavaScript API へのアクセス + +`Cookie-Deprecation` 値には、`navigator.cookieDeprecationLabel.getValue()` JavaScript API を介してアクセスすることもできます。これにより、該当するグループラベルを含む文字列に解決される Promise が返されます。たとえば、ブラウザが `example_label_1` グループに属していた場合、以下のようになります。 + +```js +// Feature detect temporary API first +if ('cookieDeprecationLabel' in navigator) { + // Request value and resolve promise + navigator.cookieDeprecationLabel.getValue().then((label) => { + console.log(label); + // Expected output: "example_label_1" + }); +} +``` + +ブラウザがグループの一部ではない場合、値は `null` になります。 + +JavaScript API は `receive-cookie-deprecation` Cookie の存在に関係なく呼び出すことができます。 + +## フィードバック ウェブエコシステム全体の多様な関係者からのフィードバックは、プライバシーサンドボックスイニシアチブにとって非常に重要です。専用の[フィードバックセクション](/docs/privacy-sandbox/feedback/)には、フォローしたりディスカッションに参加したりできる既存の公開チャンネルの概要と、いつでも Chrome チームに直接連絡できるフィードバックフォームが用意されています。 +質問を管理するために、GitHub の開発者サポートリポジトリでは ["chrome-testing"](https://github.com/GoogleChromeLabs/privacy-sandbox-dev-support/labels/chrome-testing) ラベルを使用しています。以下の最初の質問に関するフィードバックやディスカッションをお待ちしています。 + +- [テストにはモード A とモード B のいずれか、または両方を使用していますか?](https://github.com/GoogleChromeLabs/privacy-sandbox-dev-support/issues/112) +- [Chrome が提供するテストのラベルサイズの選択](https://github.com/GoogleChromeLabs/privacy-sandbox-dev-support/issues/113) +- [Chrome が提供するテストでのクライアントヒントの使用](https://github.com/GoogleChromeLabs/privacy-sandbox-dev-support/issues/114) + +「Chrome-facilitated testing」テンプレートを使用して、リポジトリ内に[新しい質問やディスカッションを作成](https://github.com/GoogleChromeLabs/privacy-sandbox-dev-support/issues/new/choose)することもできます。 + +{% Aside %} + +英国の [Competition and Markets Authority](https://www.gov.uk/government/organisations/competition-and-markets-authority)(CMA)は、タイムライン、テスト方法、および次のステップに関する関連情報を記載した[プライバシーサンドボックス API のテストに関するガイダンス](https://www.gov.uk/cma-cases/investigation-into-googles-privacy-sandbox-browser-changes#industry-testing)を公開しました。 + +{% endAside %} + 開発者は、GitHub の [Privacy Sandbox Developer Support リポジトリ](https://github.com/GoogleChromeLabs/privacy-sandbox-dev-support)で質問したり、ディスカッションに参加したりできます。 diff --git a/site/ja/docs/privacy-sandbox/videos/index.md b/site/ja/docs/privacy-sandbox/videos/index.md new file mode 100644 index 000000000..20ef6b4da --- /dev/null +++ b/site/ja/docs/privacy-sandbox/videos/index.md @@ -0,0 +1,157 @@ +--- +layout: layouts/doc-post.njk +title: プライバシー サンドボックス関連動画ライブラリ +subhead: これらのプライバシーサンドボックス関連動画で、概要、チュートリアル、概念上のディスカッションをご覧ください。 +description: プライバシーサンドボックス関連動画ライブラリ +date: 2023-06-26 +authors: + - nmichell +--- + +以下の動画は、Google I/O などのさまざまなイベントやプライバシーサンドボックスの公開オフィスアワーで録画された講演とウォークスルーです。プライバシーサンドボックス API の概要と、詳細な技術的な説明が提供されています。今後のオフィスアワーやイベントについては、[イベントページ](/docs/privacy-sandbox/events/)でご確認ください。 + +{% Aside %} これらの動画で説明されている概念は依然として適切なものではありますが、技術的な詳細とコードの一部が変更されていることに注意してください。 + +最新の詳細については、リンク先のドキュメントをご覧ください。 {% endAside %} + +## プライバシーサンドボックスとは? + +{% Columns %} {% Column %} {% YouTube id='NKz5oT6kXI4' %} 最新の詳細については、ドキュメントをご覧ください: <a href="/docs/privacy-sandbox/overview/">プライバシーサンドボックスとは?</a> + +{% endColumn %} {% Column %} <strong>2023 年 5 月 12 日。再生時間: 23 分 43 秒</strong> + +この講演では、プライバシーサンドボックスチームのメンバーがよくある質問に答えます。視聴すると、Chrome と Android の実装の類似点や相違点など、長期的なビジョンをよりよく理解できるようになります。 {% endColumn %} {% endColumns %} + +{% Columns %} {% Column %} {% YouTube id='gm8O8-b2B8c' %} 最新の詳細については、ドキュメントをご覧ください: <a href="/docs/privacy-sandbox/overview/">プライバシーサンドボックスとは?</a> {% endColumn %} {% Column %} <strong>2023 年 5 月 10 日。再生時間: 15 分 52 秒</strong> + +Chrome はサードパーティ Cookie を段階的に廃止する方向に向かっています。CHIPS や First-Party Sets などの Cookie 関連機能の更新により、サイト上のクロスサイト Cookie をより安全かつプライベートな方法で制限できるようになります。これらがどのように役立つかを学びましょう。{% endColumn %} {% endColumns %} + +{% Details %} {% DetailsSummary %} + +### その他のプライバシーサンドボックス関連動画 + +{% endDetailsSummary %} {% Columns %} {% Column %} {% YouTube id='VVgtGkRtVPU' %} 最新の詳細については、ドキュメントをご覧ください: <a href="/docs/privacy-sandbox/overview/">プライバシーサンドボックスとは?</a> {% endColumn %} {% Column %} <strong>2022 年 5 月 12 日。再生時間: 16 分 16 秒</strong> + +<strong>最新のドキュメント:</strong> [プライバシーサンドボックスとは?](/docs/privacy-sandbox/overview/) + +Google I/O 2022 において、Chrome チームの [Rowan Merewood](/authors/rowan_m/) が、プライバシーサンドボックス、サードパーティコンテンツの長所と短所、およびプライバシーサンドボックスがこれらの問題にどのように対処するかについて講演しました。 {% endColumn %} {% endColumns %} + +{% Columns %} {% Column %} {% YouTube id='7AQFDm7STmw' %} 最新の詳細については、ドキュメントをご覧ください: <a href="/docs/privacy-sandbox/topics/">Topics API</a>、<a href="/docs/privacy-sandbox/protected-audience/">Protected Audience API</a>、<a href="/docs/privacy-sandbox/attribution-reporting/">アトリビューション レポート</a> {% endColumn %} {% Column %} <strong>2023 年 2 月。再生時間: 11 分 08 秒</strong> + +プロダクトパートナーシップチームの [Danny Rojas](/authors/darojas/) が、プライバシーサンドボックス広告 API の概要を説明します。[Topics API](/docs/privacy-sandbox/topics/)、[Protected Audience API](/docs/privacy-sandbox/protected-audience/)(旧 FLEDGE)、および[アトリビューション レポート](/docs/privacy-sandbox/attribution-reporting/)について、いくつかの一般的な使用例とともに簡単に説明されています。{% endColumn %} {% endColumns %} + +{% Columns %} {% Column %} {% YouTube id='wb-2i7Sk7c' %} {% endColumn %} {% Column %} <strong>2023 年 3 月 3 日。再生時間: 11 分 58 秒</strong> + +この動画では、[Jeremy Ney](/authors/jney/) が、ウェブサイトがユーザー向けの重要な機能を保持し、不正行為に対抗するために役立つプライバシーサンドボックス内の新しいテクノロジーについて説明します。 {% endColumn %} {% endColumns %} {% endDetails %} + +## アトリビューション レポート + +{% Columns %} {% Column %} {% YouTube id='mYVi3yL-GNI' %} 最新の詳細については、ドキュメントをご覧ください: <a href="/docs/privacy-sandbox/attribution-reporting/">アトリビューション レポート</a>{% endColumn %} {% Column %} <strong>2023 年 5 月 10 日。再生時間: 19 分 51 秒</strong> + +Chrome と Android にわたるアトリビューション レポートについての詳細を交えたプライバシーサンドボックスへの取り組みについて学び、その取り組みへの関わり方やソリューションを実装し始める方法についてご覧ください。 {% endColumn %} {% endColumns %} + +{% Details %} {% DetailsSummary %} + +### その他のアトリビューション レポート関連動画 + +{% endDetailsSummary %} {% Columns %} {% Column %} {% YouTube id='UGA74CIcom8' %} 最新の詳細については、ドキュメントをご覧ください: <a href="/docs/privacy-sandbox/attribution-reporting/">アトリビューション レポート</a>{% endColumn %} {% Column %} <strong>2021 年 8 月 25 日。再生時間: 6 分 15 秒</strong> + +Chrome チームの [Sam Dutton](/authors/samdutton/) が、Attribution Reporting API に関する概要を説明します。API のイベントレベルレポートと要約レポートの 2 種類のレポートについて、および報告されるデータとその方法がカバーされています。 {% endColumn %} {% endColumns %} + +{% Columns %} {% Column %} + +<iframe src="https://drive.google.com/file/d/18RGEx_mrhDJuMsLUK1BZ0cK5FSZRAAqh/preview" allow="autoplay" width="336" height="187"></iframe> 最新の詳細については、ドキュメントをご覧ください: <a href="/docs/privacy-sandbox/attribution-reporting/">アトリビューション レポート</a> + +{% endColumn %} {% Column %} <strong>2022 年 8 月 11 日。再生時間: 43 分 58 秒。パート1。</strong> + +2022 年 8 月のプライバシーサンドボックス関連オフィスアワーで、Chrome チームの [Maud Nalpas](/authors/maudn/) が Attribution Reporting API について説明します。Maud が、要約レポートのウォークスルーを紹介し、ブラウザで集計可能なレポートを生成する方法について説明しています。ノイズと、要約レポートのセットアップ方法と取得方法について触れています。 {% endColumn %} {% endColumns %} + +{% Columns %} {% Column %} + +<iframe src="https://drive.google.com/file/d/1hmHoM3xyU4eLTJ1dM7_E8x-u6nZgim1O/preview" width="336" height="187" allow="autoplay"></iframe> + +最新の詳細については、ドキュメントをご覧ください: <a href="/docs/privacy-sandbox/attribution-reporting/system-overview/">アトリビューション レポート: 完全なシステム概要</a> + +{% endColumn %} {% Column %} <strong>2022 年 8 月 11 日。再生時間: 29 分 34 秒。パート2。</strong> + +2022 年 8 月に開催されたプライバシーサンドボックス関連オフィスアワーのパート 2 では、Robert Kubis がアトリビューション レポートのサーバー側について説明します。ブラウザから集計可能なレポートを収集する方法、レポートをグループ化して要約レポートを生成する方法、デバッグレポートを生成する方法、および集計サービスでレポートを生成する方法を示します。 {% endColumn %} {% endColumns %} + +{% Columns %} {% Column %} + +<iframe src="https://drive.google.com/file/d/1EVCw6MTz3JIdkno2lICN6q7gNrmZBYGf/preview" width="336" height="187" allow="autoplay"></iframe> 最新の詳細については、ドキュメントをご覧ください: <a href="/docs/privacy-sandbox/attribution-reporting/">アトリビューション レポート</a> + +{% endColumn %} {% Column %} <strong>2022 年 6 月 30 日。再生時間: 23 分 29 秒</strong> + +Chrome チームが、Attribution Reporting API の概要と、今後のサードパーティ Cookie の廃止に伴い Attribution Reporting API が重要となる理由を説明しています。 {% endColumn %} {% endColumns %} {% endDetails %} + +## Protected Audience API + +{% Columns %} {% Column %} {% YouTube id='HkvmYKqnytw' %} 最新の詳細については、ドキュメントをご覧ください: <a href="/docs/privacy-sandbox/protected-audience/">Protected Audience API</a> {% endColumn %} {% Column %} <strong>2021 年 9 月 8 日。再生時間: 5 分 51 秒</strong> + +Chrome チームの [Sam Dutton](/authors/samdutton/) が、Protected Audience API(旧 FLEDGE)がリマーケティング関連ユースケース向けのソリューションをどのように提供するのか、またサードパーティがこの API を使ってサイト間でのユーザーのブラウジング行動を追跡できないようにするためにどのように設計されているかについて説明します。{% endColumn %} {% endColumns %} + +{% Columns %} {% Column %} {% YouTube id='znDD0gkdJyM' %} 最新の詳細については、ドキュメントをご覧ください: <a href="/docs/privacy-sandbox/protected-audience/">Protected Audience API</a>。 + +{% endColumn %} {% Column %} <strong>2022 年 3 月 18 日。再生時間: 6 分 15 秒</strong> Protected Audience API(旧 FLEDGE)は、リマーケティングおよびカスタムオーディエンスに対応するためのプライバシーサンドボックスの提案であり、サードパーティがサイトをまたいでユーザーのブラウジング行動を追跡できないように設計されています。 + +Chrome チームの [Sam Dutton](/authors/samdutton/) が、API に提供されているデモのチュートリアルを提供します。{% endColumn %} {% endColumns %} + +## Topics API + +{% Columns %} {% Column %} + +<iframe src="https://drive.google.com/file/d/1831_uKSlTwnSzYNjpp9pkDEniDA_Q9lF/preview?t=1m03s" width="336" height="187" allow="autoplay"></iframe> + +最新の詳細については、ドキュメントをご覧ください: <a href="/docs/privacy-sandbox/topics/">Topics API の概要</a> + +{% endColumn %} {% Column %} <strong>2022 年 9 月 6 日。再生時間: 14 分 31 秒</strong><br> + +Topics API PM の Leeron Israel が、高レベルのユースケースから API の仕組みの概要まで、API の技術概要を紹介します。トピックの分類法、観察の定義、およびその他の重要な詳細について説明されています。{% endColumn %} {% endColumns %} + +{% Columns %} {% Column %} + +<iframe src="https://drive.google.com/file/d/1dmpMKLJcGNe56M6ECRdRYhuITTv9YUDV/preview" width="336" height="187" allow="autoplay"></iframe> 最新の詳細については、ドキュメントをご覧ください: <a href="/docs/privacy-sandbox/topics/">Topics API の概要</a> + +{% endColumn %} {% Column %} <strong>2022 年 9 月 6 日。再生時間: 21 分 01 秒</strong> + +[Sam Dutton](/authors/samdutton/) が Topics API のデモを実行します。フラグを使用してコマンドラインから Chrome を実行する方法、Chrome の構成を確認する方法、機能の検出方法を示し、API の機能を示します。 {% endColumn %} {% endColumns %} + +{% Columns %} {% Column %} {% YouTube id='hEBzWuXjeTQ' %} 動画で説明されている<a href="https://topics-demo.glitch.me/">デモ</a>をご覧ください。{% endColumn %} {% Column %} <strong>2022 年 11 月。再生時間: 13 分 22 秒</strong> + +Chrome チームの [Sam Dutton](/authors/samdutton/) が、トピックの分類法について説明し、トピック API のデモを実行し、API の実際の動作を示します。最新の詳細およびさらに詳しい情報については、<a href="/docs/privacy-sandbox/topics/">Topics API</a> をご覧ください。 {% endColumn %} {% endColumns %} + +## First-Party Sets + +{% Columns %} {% Column %} {% YouTube id='cNJ8mZ-J3F8' %} 最新の詳細については、ドキュメントをご覧ください: <a href="/docs/privacy-sandbox/first-party-sets/">First-Party Sets</a> + +{% endColumn %} {% Column %} <strong>2021 年 8 月 11 日。再生時間: 5 分 47 秒</strong> + +First-Party Sets は、同じエンティティが所有し運営する関連ドメインが、同じファーストパーティに属するものとして宣言できる提案です。{% endColumn %} {% endColumns %} + +{% Columns %} {% Column %} + +<iframe src="https://drive.google.com/file/d/1riGrGwP5cyz3q4IcDjV5kulOK48OJV2S/preview" width="336" height="187" allow="autoplay"></iframe> + +最新の詳細については、ドキュメントをご覧ください: <a href="/docs/privacy-sandbox/first-party-sets/">First-party Sets</a> + +{% endColumn %} + +{% Column %} <strong>2022 年 12 月 15 日。再生時間: 26 分 48 秒</strong> + +プライバシーサンドボックス関連オフィスアワーで、[Helen Cho](/authors/helencho/) が API の仕組みを説明し、[Rowan Merewood](/authors/rowan_m/) がデモと API のテスト方法を説明しています。 {% endColumn %} {% endColumns %} + +## オリジントライアル + +{% Columns %} {% Column %} {% YouTube id='v_gI8wcsPUA' %} 最新の詳細については、ドキュメントをご覧ください: <a href="/docs/privacy-sandbox/unified-origin-trial/">広告関連の統一オリジントライアル</a> + +{% endColumn %} {% Column %} <strong>2022 年 8 月 17 日。再生時間: 6 分 19 秒</strong> + +オリジントライアルは、ウェブプラットフォーム関連の新機能と実験的機能をテストするための手法です。埋め込みコンテンツのプロバイダーは、サードパーティのオリジントライアルに参加して複数のサイトで新機能を試すことができます。 {% endColumn %} {% endColumns %} + +## プライベートステートトークン + +{% Columns %} {% Column %} + +{% YouTube id='bXB1Iwq6Eq4' %} 最新の詳細についてはドキュメントをご覧ください: <a href="/docs/privacy-sandbox/private-state-tokens/">プライベートステートトークン</a> {% endColumn %} {% Column %} <strong>2021 年 7 月 28 日。再生時間: 8 分 17 秒</strong> + +プライベートステートトークン(旧トラストトークン)は、パッシブトラッキングを使わずに不正行為に対抗し、ボットと本物の人間を区別するのに役立つ新しい API です。この動画では、ウェブにプライベートステートトークンが必要な理由とその仕組みについて学びます。 {% endColumn %} {% endColumns %} From 8d375e9c97f0efe281ac9d95ffb8891b6b064233 Mon Sep 17 00:00:00 2001 From: aplio <ryo.091219@gmail.com> Date: Fri, 6 Oct 2023 19:08:38 +0900 Subject: [PATCH 855/982] [JA] Fix ja localized content for bounce tracking mitigations doc (#7332) * [JA] use template for timeline in bounce-tracking * [JA] use privacycg/nav-track.. for github link. moved in this commit https://github.com/wanderview/bounce-tracking-mitigations/commit/5851e1c9f07e83f7ca1eb6a2cc5fd7d6ce983346 * [JA] Align ja nav-tracking doc w/ en. remove browser impl part --- .../privacy-sandbox/timeline/bounce-tracking.md | 3 +-- .../bounce-tracking-mitigations/index.md | 14 +++++++------- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/site/ja/_partials/privacy-sandbox/timeline/bounce-tracking.md b/site/ja/_partials/privacy-sandbox/timeline/bounce-tracking.md index 04958eb11..cfc85e179 100644 --- a/site/ja/_partials/privacy-sandbox/timeline/bounce-tracking.md +++ b/site/ja/_partials/privacy-sandbox/timeline/bounce-tracking.md @@ -1,3 +1,2 @@ -- [バウンストラッキング対策の提案](https://github.com/wanderview/bounce-tracking-mitigations/blob/main/explainer.md)の[公開ディスカッション](https://github.com/wanderview/bounce-tracking-mitigations/issues)が開始しました。 +- [バウンストラッキング対策の提案](https://github.com/privacycg/nav-tracking-mitigations/blob/main/bounce-tracking-explainer.md)の[公開ディスカッション](https://github.com/privacycg/nav-tracking-mitigations/issues/)が開始しました。 - [Chrome プラットフォームのステータス](https://chromestatus.com/feature/5705149616488448?context=myfeatures)。 -- この提案はどのブラウザにも実装されていません。 diff --git a/site/ja/docs/privacy-sandbox/bounce-tracking-mitigations/index.md b/site/ja/docs/privacy-sandbox/bounce-tracking-mitigations/index.md index 21c42e4ae..b31b916de 100644 --- a/site/ja/docs/privacy-sandbox/bounce-tracking-mitigations/index.md +++ b/site/ja/docs/privacy-sandbox/bounce-tracking-mitigations/index.md @@ -12,10 +12,10 @@ authors: ## 実装ステータス {: #status} -このドキュメントでは、[バウンストラッキング対策に関する新しい提案](https://github.com/wanderview/bounce-tracking-mitigations)の概要を説明します。 +このドキュメントでは、[バウンストラッキング対策に関する新しい提案](https://github.com/privacycg/nav-tracking-mitigations/blob/main/bounce-tracking-explainer.md)の概要を説明します。 + +{% Partial 'privacy-sandbox/timeline/bounce-tracking.njk' %} -- [バウンス トラッキング対策の提案](https://github.com/wanderview/bounce-tracking-mitigations/blob/main/explainer.md)が[公開ディスカッション](https://github.com/wanderview/bounce-tracking-mitigations/issues)に進みました。 -- この提案は[どのブラウザにも実装されていません](https://chromestatus.com/feature/5705149616488448?context=myfeatures)。 - [プライバシーサンドボックスのタイムライン](http://privacysandbox.com/timeline)には、バウンストラッキング対策やその他のプライバシーサンドボックスの提案の実装タイミングに関する情報が提供されています。 ## この提案が必要とされる理由 {: #proposal-reason} @@ -41,7 +41,7 @@ authors: ### 範囲外のユースケース -範囲外のリダイレクトフローには、ID 連携認証、SSO、および決済が含まれます。これは、こういったフローはバウンストラッキングのシナリオに似ているものの、直接的なユーザー操作を伴うものであるためです。[詳細については、Explainer を参照](https://github.com/wanderview/bounce-tracking-mitigations/blob/main/explainer.md)してください。 +範囲外のリダイレクトフローには、ID 連携認証、SSO、および決済が含まれます。これは、こういったフローはバウンストラッキングのシナリオに似ているものの、直接的なユーザー操作を伴うものであるためです。[詳細については、Explainer を参照](https://github.com/privacycg/nav-tracking-mitigations/blob/main/bounce-tracking-explainer.md)してください。 - **ID 連携認証**: [ID 連携認証](/docs/privacy-sandbox/fedcm/)は、ユーザーがウェブで **ID プロバイダーでログイン**(Facebook、GitHub、Google など)ボタンをクリックすると発生します。 - **シングル サインオン**: サイトでシングル サインオン(SSO)が使用されている場合、ユーザーは、ID プロバイダーで 1 回ログインしておけば、他のサイトへのすべてのアクセスでも自動的にログインされることを期待しています。 @@ -58,11 +58,11 @@ authors: これらの定義を明確にすることが、バウンストラッキング対策の取り組みにおいて重要となります。 -バウンストラッキング対策の実施については、まだ[議論中](https://github.com/wanderview/bounce-tracking-mitigations/issues)です。 +バウンストラッキング対策の実施については、まだ[議論中](https://github.com/privacycg/nav-tracking-mitigations/issues)です。 ### セキュリティに関する考慮事項 -[この提案には、バウンストラッキング対策の Explainer で概説されているセキュリティ上の考慮事項](https://github.com/wanderview/bounce-tracking-mitigations/blob/main/explainer.md#privacy-and-security-considerations)がいくつかあります。 +[この提案には、バウンストラッキング対策の Explainer で概説されているセキュリティ上の考慮事項](https://github.com/privacycg/nav-tracking-mitigations/blob/main/bounce-tracking-explainer.md#privacy-and-security-considerations)がいくつかあります。 ## バウンス トラッキング対策の公開時期 {: #availability} @@ -72,5 +72,5 @@ authors: バウンストラッキング対策の提案は現在も検討中であるため、今後変更される可能性があります。フィードバックがある場合は、ぜひお聞かせください。 -- **GitHub**: [提案](https://github.com/wanderview/bounce-tracking-mitigations)を読み、[質問を投稿したり、ディスカッションに参加](https://github.com/wanderview/bounce-tracking-mitigations/issues)したりできます。 +- **GitHub**: [提案](https://github.com/privacycg/nav-tracking-mitigations/blob/main/bounce-tracking-explainer.md)を読み、[質問を投稿したり、ディスカッションに参加](https://github.com/privacycg/proposals/issues/6)したりできます。 - **開発者サポート**: [Privacy Sandbox Developer Support リポジトリ](https://github.com/GoogleChromeLabs/privacy-sandbox-dev-support)では、質問したり、ディスカッションに参加したりできます。 From df214d6842db45630fd9eaad8e21786cfba91732 Mon Sep 17 00:00:00 2001 From: Saurabh Rajpal <41784323+rajpalsaurabh@users.noreply.github.com> Date: Fri, 6 Oct 2023 20:42:09 +0530 Subject: [PATCH 856/982] Update index.md (#7450) Removing the extra '"' from the testimonial sections of redBus and PolicyBazaar. --- site/en/blog/view-transitions-case-studies/index.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/site/en/blog/view-transitions-case-studies/index.md b/site/en/blog/view-transitions-case-studies/index.md index 339451d77..dc4e755e7 100644 --- a/site/en/blog/view-transitions-case-studies/index.md +++ b/site/en/blog/view-transitions-case-studies/index.md @@ -93,7 +93,7 @@ In the following CSS, `slide-to-right`, `slide-to-left`, `slide-from-right`, and redBus chose to implement view transitions along with INP improvement efforts across their site, which led to [7% more sales](https://web.dev/redbus-inp/). [Amit Kumar](https://amitkumar-v.medium.com/), Senior Engineering Manager at redBus, said that view transitions are really awesome for those who genuinely want better user experience and desire less maintenance overhead. -<blockquote><p>"We have conducted comprehensive user feedback sessions, incorporating valuable insights from a diverse group of users. Our deep understanding of our user base (bus and rail) and their needs, combined with our expertise, has led us to believe that this feature will provide significant value right from the start, without the need for A/B testing. View transitions are a step towards bridging the gap between app and web with a smooth navigation experience."</p> +<blockquote><p>We have conducted comprehensive user feedback sessions, incorporating valuable insights from a diverse group of users. Our deep understanding of our user base (bus and rail) and their needs, combined with our expertise, has led us to believe that this feature will provide significant value right from the start, without the need for A/B testing. View transitions are a step towards bridging the gap between app and web with a smooth navigation experience.</p> <cite>Anoop Menon, CTO redBus</cite> </blockquote> @@ -374,7 +374,7 @@ toggleWidgetAnimation() { Rishabh Mehrotra, their head of Design (Life BU), said that view transitions played a significant role in enhancing the website experience for their users by improving usability, engagement, and overall satisfaction. It helped in providing smooth navigation, guided interaction, reduced cognitive load, modern aesthetics and much more. -<blockquote><p>Elevating the web experience stands as a paramount objective for PB, and VT has proven to be an instrumental tool in achieving this with remarkable seamlessness. Its widespread appeal among both our developer community and user base has imbued our team with a sense of enthusiasm. As we contemplate its integration across diverse PODs, we anticipate a far-reaching positive impact on satisfaction levels and operational excellence."</p> +<blockquote><p>Elevating the web experience stands as a paramount objective for PB, and VT has proven to be an instrumental tool in achieving this with remarkable seamlessness. Its widespread appeal among both our developer community and user base has imbued our team with a sense of enthusiasm. As we contemplate its integration across diverse PODs, we anticipate a far-reaching positive impact on satisfaction levels and operational excellence.</p> <cite>Saurabh Tiwari (CTO, PolicyBazaar)</cite> </blockquote> From d9efb9c27af82d3548b262f3c18f8eccb825c37d Mon Sep 17 00:00:00 2001 From: Ewa <devnook@gmail.com> Date: Fri, 6 Oct 2023 17:40:55 +0200 Subject: [PATCH 857/982] Remove tweets embded pipeline (#7453) * Remove tweets embded pipeline * Add other languages homepages --- external/build/tweets.js | 46 ------ site/_data/tweets.js | 150 ------------------ site/_includes/layouts/home.njk | 108 ------------- .../macros/cards/featured-tweet-card.njk | 31 ---- site/es/index.md | 2 +- site/ja/index.md | 2 +- site/ko/index.md | 2 +- site/pt/index.md | 2 +- site/ru/index.md | 2 +- site/zh/index.md | 2 +- 10 files changed, 6 insertions(+), 341 deletions(-) delete mode 100644 external/build/tweets.js delete mode 100644 site/_data/tweets.js delete mode 100644 site/_includes/layouts/home.njk delete mode 100644 site/_includes/macros/cards/featured-tweet-card.njk diff --git a/external/build/tweets.js b/external/build/tweets.js deleted file mode 100644 index 63d217c53..000000000 --- a/external/build/tweets.js +++ /dev/null @@ -1,46 +0,0 @@ -/** - * @fileoverview Fetches the most recent tweet from ChromiumDev and writes to storage. - */ - -require('dotenv').config(); - -const {default: fetch} = require('node-fetch'); -const fs = require('fs'); -const path = require('path'); - -const tweetCount = 1; -const url = `https://api.twitter.com/1.1/statuses/user_timeline.json?user_id=113713261&count=${tweetCount}&include_rts=false&exclude_replies=true&tweet_mode=extended&include_ext_alt_text=true`; - -async function run() { - // Temporarily disable Twitter feeds fetch. - return; - // eslint-disable-next-line no-unreachable - if (!process.env.TWITTER_BEARER) { - if (process.env.CI) { - return; // do nothing, the fallback data will win - } - throw new Error('No `TWITTER_BEARER` environment var for production'); - } - - const r = await fetch(url, { - headers: { - Authorization: `Bearer ${process.env.TWITTER_BEARER}`, - }, - }); - - if (!r.ok) { - throw new Error(`Could not fetch tweets, status: ${r.status}`); - } - - const json = await r.json(); - - if (json['errors']) { - const error = json['errors'][0]; - throw new Error(`${error.code}: ${error.message}`); - } - - const targetFile = path.join(__dirname, '../data/tweets.json'); - fs.writeFileSync(targetFile, JSON.stringify(json)); -} - -run(); diff --git a/site/_data/tweets.js b/site/_data/tweets.js deleted file mode 100644 index 24751ce2a..000000000 --- a/site/_data/tweets.js +++ /dev/null @@ -1,150 +0,0 @@ -const escapeStringRegexp = require('escape-string-regexp'); -const fs = require('fs'); -const path = require('path'); - -/** - * Insert media (images/videos) into a tweet. - * Currently only supports a single image. - * @param {TwitterTweet} tweet - */ -const formatMedia = tweet => { - const {media} = tweet.extended_entities || []; - - if (!media || !media.length) { - return; - } - - for (const item of media) { - // For any piece of media in a tweet, twitter will add a placeholder url - // which just redirects back to the tweet itself. - // - // For example, a tweet that looks like: - // "Hello World!" - // "[foo.jpg]" - // - // Will get turned into: - // "Hello World!" - // "https://t.co/8p5w09RLK3" - // - // We can use this url placeholder to insert an image or video - // at the correct location in the tweet string. - const pattern = escapeStringRegexp(`${item.url}`); - const re = new RegExp(pattern, 'g'); - - if (item.type === 'photo') { - const dimensions = item.sizes.small; - tweet.formatted_text = tweet.formatted_text.replace( - re, - `<img class="gap-top-300 rounded-100" src="${item.media_url_https}?name=small" width="${dimensions.w}" height="${dimensions.h}" alt="${item.ext_alt_text}" />` - ); - // Break after the first photo. We don't want to try to emulate twitter's - // multi-photo mosaic layout. - break; - } - } -}; - -/** - * Turn mention strings into links. - * @param {TwitterTweet} tweet - */ -const formatMentions = tweet => { - const {user_mentions: mentions} = tweet.entities || []; - - if (!mentions || !mentions.length) { - return; - } - - for (const mention of mentions) { - const pattern = escapeStringRegexp(`@${mention.screen_name}`); - const re = new RegExp(pattern, 'g'); - tweet.formatted_text = tweet.formatted_text.replace( - re, - `<a class="link no-visited decoration-none" href="https://twitter.com/${mention.screen_name}">${pattern}</a>` - ); - } -}; - -/** - * Turn url strings into links. - * @param {TwitterTweet} tweet - */ -const formatUrls = tweet => { - const {urls} = tweet.entities || []; - - if (!urls || !urls.length) { - return; - } - - for (const url of urls) { - const pattern = escapeStringRegexp(url.url); - const re = new RegExp(pattern, 'g'); - tweet.formatted_text = tweet.formatted_text.replace( - re, - `<a class="link no-visited decoration-none" href="${url.url}">${url.display_url}</a>` - ); - } -}; - -/** - * Turn hashtag strings into links. - * @param {TwitterTweet} tweet - */ -const formatHashtags = tweet => { - const {hashtags} = tweet.entities || []; - - if (!hashtags || !hashtags.length) { - return; - } - - for (const hashtag of hashtags) { - const pattern = escapeStringRegexp(`#${hashtag.text}`); - const re = new RegExp(pattern, 'g'); - tweet.formatted_text = tweet.formatted_text.replace( - re, - `<a class="link no-visited decoration-none" href="https://twitter.com/hashtag/${hashtag.text}">${pattern}</a>` - ); - } -}; - -/** - * - * @param {TwitterTweet} tweet - */ -const formatEntities = tweet => { - tweet.tweet_url = `https://twitter.com/ChromiumDev/status/${tweet.id_str}`; - // Make a copy of the full_text for us to work with. - // Use the same snake case style as the rest of the tweet object. - // !!! Important !!! - // The text is displayed with whitespace: pre-wrap so adding or - // removing any whitespace will affect how the tweet is rendered. - tweet.formatted_text = tweet.full_text; - formatHashtags(tweet); - formatUrls(tweet); - formatMentions(tweet); - formatMedia(tweet); -}; - -/** - * @return {Promise<TwitterTweet[]>} - */ -module.exports = async () => { - let tweets = []; - try { - const tweetsFile = path.join(__dirname, '../../external/data/tweets.json'); - tweets = /** @type {TwitterTweet[]} */ ( - JSON.parse(fs.readFileSync(tweetsFile, 'utf-8')) - ); - } catch (e) { - console.warn( - 'Error reading tweets.json. Maybe it does not exist? See https://github.com/GoogleChrome/developer.chrome.com/pull/6384' - ); - } - - // Remove polls - tweets = tweets.filter(tweet => !tweet.entities.polls); - - // Format tweet entities such as hashtags, mentions, photos, etc. - tweets.forEach(formatEntities); - return tweets; -}; diff --git a/site/_includes/layouts/home.njk b/site/_includes/layouts/home.njk deleted file mode 100644 index d9f57286f..000000000 --- a/site/_includes/layouts/home.njk +++ /dev/null @@ -1,108 +0,0 @@ -{% extends "layouts/base.njk" %} - -{% block css %} -{% InlineCss '/css/home.css' %} -{% endblock %} - -{% from 'macros/cards/hero-card.njk' import heroCard with context %} -{% from 'macros/cards/featured-post-card.njk' import featuredPostCard with context %} -{% from 'macros/cards/featured-docs-card.njk' import featuredDocsCard with context %} -{% from 'macros/cards/featured-tweet-card.njk' import featuredTweetCard with context %} -{% from 'macros/cards/releases-card.njk' import releasesCard with context %} - -{% block content %} - <div class="home-container width-full center-margin pad-400"> - - {# {{ heroCard( - 'Welcome!', - "This is Chrome's official site to help you build Extensions, publish on the Chrome Web Store, optimize your website, and more.", - "Start building", - "/docs/", - "image/QMjXarRXcMarxQddwrEdPvHVM242/uyy9OtWHTcxH5sK5VuRA.png", - "Construction crane lifting a resource into a Chrome tab" - ) }} #} - {# Temporary IO styles #} - <style> - .hero-card { - background-color: rgb(32,33,37); - background-image: url(https://wd.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/9vEv78Fi4j2VBL19yCZL.svg); - background-repeat: no-repeat; - background-position: 90% 50%; - background-size: contain; - color: #fff; - } - .hero-card h1 { - color: #fff; - font-size: 2em; - } - .hero-card .material-button { - color: #000; - background-color: #ccc; - } - - @media screen and (max-width: 859px) { - .hero-card { - background-position: top center; - background-size: 80%; - } - - .hero-card .hero-card__inner div:first-child:before { - content: ""; - display: block; - width: 100%; - padding-top: 80%; - } - } - </style> - {{ heroCard( - "Thank you for tuning in to Google I/O.", - "Check out the top web things that we are investing in to help you work smarter, ship faster, and stay inspired.", - "Watch now", - "https://www.youtube.com/watch?v=gkAYHomO5Hg&list=PLOU2XLYxmsIJGxIV8Lt8gF_79Z334LQ6h", - null, - "A colorful Google propeller hat." - ) }} - <div class="gap-top-500 grid-gap-500 display-flex direction-column masonry:direction-row align-center masonry:align-start"> - <div class="display-flex direction-column grid-gap-500"> - {% set post = helpers.findByUrl(collections.all, '/blog/chrome-at-io23', 'en') %} - {% if post %} - {{ featuredPostCard(post, { - icon: 'star', - actionText: 'Discover', - actionUrl: '/blog/chrome-at-io23/' - }) }} - {% endif %} - {% set blog = 'blog-' + locale %} - {{ featuredPostCard(collections[blog][0], { - title: 'i18n.nav.side_nav.blog' | i18n(locale), - actionText: 'i18n.common.see_all_articles' | i18n(locale), - actionUrl: '/blog' - }) }} - {{ releasesCard() }} - - {% set meetTheTeam = helpers.findByUrl(collections.all, '/meet-the-team', 'en') %} - - {% if meetTheTeam %} - {{ - featuredPostCard(meetTheTeam, { - icon: 'calendar', - title: 'i18n.events.meet_the_team_card.tag' | i18n(locale), - actionText: 'i18n.events.meet_the_team_card.cta' | i18n(locale), - actionUrl: '/meet-the-team/', - class: 'featured-card--bg-yellow rounded-lg width-full' - }) - }} - {% endif %} - </div> - <div class="display-flex direction-column grid-gap-500"> - {{ featuredDocsCard(featuredProjects) }} - {% if tweets and tweets.length %} - {{ featuredTweetCard() }} - {% endif %} - {% include 'partials/featured-gdg-card.njk' %} - {% include 'partials/report-a-bug.njk' %} - </div> - </div> - - </div> -{% endblock %} diff --git a/site/_includes/macros/cards/featured-tweet-card.njk b/site/_includes/macros/cards/featured-tweet-card.njk deleted file mode 100644 index a855aaea8..000000000 --- a/site/_includes/macros/cards/featured-tweet-card.njk +++ /dev/null @@ -1,31 +0,0 @@ -{% from 'macros/icon.njk' import icon with context %} - -{% macro featuredTweetCard() %} -{% set tweet = tweets[0] %} -{% if tweet %} - <div class="featured-card tweet-card hairline rounded-lg width-full"> - <div class="card-title-bar color-blue-medium"> - {{ icon('twitter', {hidden: true}) }} - <span class="gap-left-300 flex-1 user-select-none">Twitter</span> - </div> - - <a href="{{ tweet.tweet_url }}" class="link decoration-none no-visited display-inline-flex type--small gap-top-300"> - {{ helpers.formatDateShort(tweet.created_at, locale) }} - </a> - - {# - The .tweet-card__text element uses whitespace: pre-wrap so we can't let - the html minifier touch it or it will mess up the formatting of the tweet. - #} - <!-- htmlmin:ignore --> - <p class="tweet-card__text gap-top-300">{{ tweet.formatted_text | safe }}</p> - <!-- htmlmin:ignore --> - - <div class="gap-top-400"> - <a href="https://twitter.com/chromiumdev" class="material-button button-text display-inline-flex color-primary"> - {{ 'i18n.common.follow' | i18n(locale) }} @ChromiumDev - </a> - </div> - </div> -{% endif %} -{% endmacro %} diff --git a/site/es/index.md b/site/es/index.md index 6de2f182a..69a708e8f 100644 --- a/site/es/index.md +++ b/site/es/index.md @@ -1,4 +1,4 @@ --- title: Chrome Developers -layout: 'layouts/home.njk' +layout: 'layouts/devsite-home.njk' --- diff --git a/site/ja/index.md b/site/ja/index.md index 6de2f182a..69a708e8f 100644 --- a/site/ja/index.md +++ b/site/ja/index.md @@ -1,4 +1,4 @@ --- title: Chrome Developers -layout: 'layouts/home.njk' +layout: 'layouts/devsite-home.njk' --- diff --git a/site/ko/index.md b/site/ko/index.md index 6de2f182a..69a708e8f 100644 --- a/site/ko/index.md +++ b/site/ko/index.md @@ -1,4 +1,4 @@ --- title: Chrome Developers -layout: 'layouts/home.njk' +layout: 'layouts/devsite-home.njk' --- diff --git a/site/pt/index.md b/site/pt/index.md index 6de2f182a..69a708e8f 100644 --- a/site/pt/index.md +++ b/site/pt/index.md @@ -1,4 +1,4 @@ --- title: Chrome Developers -layout: 'layouts/home.njk' +layout: 'layouts/devsite-home.njk' --- diff --git a/site/ru/index.md b/site/ru/index.md index 6de2f182a..69a708e8f 100644 --- a/site/ru/index.md +++ b/site/ru/index.md @@ -1,4 +1,4 @@ --- title: Chrome Developers -layout: 'layouts/home.njk' +layout: 'layouts/devsite-home.njk' --- diff --git a/site/zh/index.md b/site/zh/index.md index 6de2f182a..69a708e8f 100644 --- a/site/zh/index.md +++ b/site/zh/index.md @@ -1,4 +1,4 @@ --- title: Chrome Developers -layout: 'layouts/home.njk' +layout: 'layouts/devsite-home.njk' --- From 127afbcb2f0b626658a0f7ba67f0839e8add0352 Mon Sep 17 00:00:00 2001 From: wizardofdocs <83661258+wizardofdocs@users.noreply.github.com> Date: Fri, 6 Oct 2023 09:16:17 -0700 Subject: [PATCH 858/982] Updated Offscreen page (#7397) * Updated Offscreen page Cleaned up phrasing and removed an unnecessary table. Questions in comments. * Updated Offscreen page * Updated manifest boilerplate in Offscreen reference * Update site/en/docs/extensions/reference/offscreen/index.md Updated phrasing Co-authored-by: Joe Medley <jmedley@google.com> * Update site/en/docs/extensions/reference/offscreen/index.md Updated phrasing Co-authored-by: Joe Medley <jmedley@google.com> * Update site/en/docs/extensions/reference/offscreen/index.md Updated phrasing Co-authored-by: Joe Medley <jmedley@google.com> * Update site/en/docs/extensions/reference/offscreen/index.md Updated phrasing Co-authored-by: Joe Medley <jmedley@google.com> * Updated phrasing in Offscreen reference * Updated code sample in Offscreen reference * Update site/en/docs/extensions/reference/offscreen/index.md --------- Co-authored-by: Joe Medley <jmedley@google.com> --- .../extensions/reference/offscreen/index.md | 74 ++++++++++++------- 1 file changed, 48 insertions(+), 26 deletions(-) diff --git a/site/en/docs/extensions/reference/offscreen/index.md b/site/en/docs/extensions/reference/offscreen/index.md index a568279f6..d4ea8f652 100644 --- a/site/en/docs/extensions/reference/offscreen/index.md +++ b/site/en/docs/extensions/reference/offscreen/index.md @@ -2,11 +2,15 @@ api: offscreen --- -Service workers do not have DOM access, and many websites have content security policies that limit the functionality of content scripts. This API allows the extension to use DOM APIs in a hidden document without obtrusively opening new windows or tabs that interrupt the user experience. Offscreen documents do not support other Chrome APIs. +Service workers don't have DOM access, and many websites have content security policies that +limit the functionality of content scripts. The Offscreen API allows the extension to use DOM +APIs in a hidden document without interrupting the user experience by opening new windows or +tabs. The [`runtime`](/docs/extensions/reference/runtime/) API is the only extensions API +supported by offscreen documents. ## Manifest -You must declare the `"offscreen"` permission in the [extension manifest][doc-manifest] to use the Offscreen API. For example: +To use the Offscreen API, declare the `"offscreen"` permission in the [extension manifest][doc-manifest]. For example: ```json { @@ -21,14 +25,25 @@ You must declare the `"offscreen"` permission in the [extension manifest][doc-ma ## Usage -Pages loaded as offscreen documents are handled differently from other types of extension pages. The extension's permissions carry over to offscreen documents, but extension API access is heavily limited. Currently, an offscreen document can only use the [`chrome.runtime`][api-runtime] APIs to send and receive messages; all other extension APIs are not exposed. Other notable differences between offscreen documents and normal pages are as follows: +Pages loaded as offscreen documents are handled differently from other types of extension pages. +The extension's permissions carry over to offscreen documents, but with limits on extension API +access. For example, because the [`chrome.runtime`][api-runtime] API is the only +extensions API supported by offscreen documents, messaging must be handled +using members of that API. + +The following are other ways offscreen documents behave differently from normal pages: * An offscreen document's URL must be a static HTML file bundled with the extension. -* Offscreen documents cannot be focused. -* Offscreen documents cannot have their `opener` property set using the [`chrome.windows` API][api-windows] method `windows.setSelfAsOpener()`. -* An extension can only have one offscreen document open at a time. If the extension is running in split mode with an active incognito profile, both the normal and incognito profiles can each have one offscreen document. +* Offscreen documents can't be focused. +* An offscreen document is an instance of [`window`](https://developer.mozilla.org/docs/Web/API/Window), but the value of its `opener` property is always `null`. +* Though an extension package can contain multiple offscreen documents, an installed extension can only + have one open at a time. If the extension is running + in split mode with an active incognito profile, the normal and incognito profiles can each + have one offscreen document. -Use [`chrome.offscreen.createDocument()`](#method-createDocument) and [`chrome.offscreen.closeDocument()`](#method-closeDocument) for creating and closing an offscreen document. Only a single Document can be open at a time. `createDocument()` requires the document's `url`, a reason, and a justification: +Use [`chrome.offscreen.createDocument()`](#method-createDocument) and +[`chrome.offscreen.closeDocument()`](#method-closeDocument) to create and close an offscreen +document. `createDocument()` requires the document's `url`, a reason, and a justification: ```js chrome.offscreen.createDocument({ @@ -40,17 +55,17 @@ chrome.offscreen.createDocument({ ### Reasons -Find all valid reasons listed [below][offscreen-reason]. Reasons are set on document creation to determine the document's lifespan: - +For a list of valid reasons, see the [Reasons][offscreen-reason] section. Reasons are set during +document creation to determine the document's lifespan. The `AUDIO_PLAYBACK` reason sets the +document to close after 30 seconds without audio playing. All other reasons don't set lifetime limits. -| Reason | Offscreen Document Lifetime | -|-------------------|------------------------------------------------| -| AUDIO_PLAYBACK | Closed after 30 seconds without audio playing. | -| All other reasons | Not currently limited | +## Examples -## Example: maintaining the lifecycle of an offscreen document +### Maintain the lifecycle of an offscreen document -The following example shows how to ensure that the offscreen document has already been created. The `setupOffscreenDocument()` function calls [`runtime.getContexts()`][runtime-get-contexts] to find the existing offscreen document or creates it if it doesn't already exist. Note that an extension can only have one offscreen document. +The following example shows how to ensure that an offscreen document exists. The +`setupOffscreenDocument()` function calls [`runtime.getContexts()`][runtime-get-contexts] to find +an existing offscreen document, or creates the document if it doesn't already exist. ```js let creating; // A global promise to avoid concurrency issues @@ -82,7 +97,8 @@ async function setupOffscreenDocument(path) { } ``` -Before sending a message to an offscreen document, call `setupOffscreenDocument()` to make sure that there is an existing offscreen document, as demonstrated in the following example. +Before sending a message to an offscreen document, call `setupOffscreenDocument()` to make sure +the document exists, as demonstrated in the following example. ```js chrome.action.onClicked.addListener(async () => { @@ -97,23 +113,29 @@ chrome.action.onClicked.addListener(async () => { }); ``` -For complete examples, see the [offscreen-clipboard][gh-offscreen-clipboard] and [offscreen-dom][gh-offscreen-dom] demos on GitHub. +For complete examples, see the [offscreen-clipboard][gh-offscreen-clipboard] and +[offscreen-dom][gh-offscreen-dom] demos on GitHub. ### Before Chrome 116: check if an offscreen document is open [`runtime.getContexts()`][runtime-get-contexts] was added in Chrome 116. In earlier versions of -Chrome, you can check for the existence of the offscreen document using [`clients.matchAll()`](https://developer.mozilla.org/docs/Web/API/Clients/matchAll): +Chrome, use [`clients.matchAll()`](https://developer.mozilla.org/docs/Web/API/Clients/matchAll) +to check for an existing offscreen document: ```js -async function hasOffscreenDocument(offscreenUrl) { +async function hasOffscreenDocument() { + if (chrome.runtime.getContexts) { + const contexts = await chrome.runtime.getContexts({ + contextTypes: ['OFFSCREEN_DOCUMENT'], + documentUrls: [OFFSCREEN_DOCUMENT_PATH] + }); + return Boolean(contexts.length); + } else { const matchedClients = await clients.matchAll(); - - for (const client of matchedClients) { - if (client.url === offscreenUrl) { - return true; - } - } - return false; + return await matchedClients.some(client => { + client.url.includes(chrome.runtime.id); + }); + } } ``` From 95f656fb723d5c6340c205a2800b3ec0a8e1287b Mon Sep 17 00:00:00 2001 From: Joe Medley <jmedley@google.com> Date: Fri, 6 Oct 2023 11:50:11 -0700 Subject: [PATCH 859/982] Make download link more prominent (#7456) --- .../extensions/mv3/getstarted/development-basics/index.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/site/en/docs/extensions/mv3/getstarted/development-basics/index.md b/site/en/docs/extensions/mv3/getstarted/development-basics/index.md index 5e77b20e0..c661ddc07 100644 --- a/site/en/docs/extensions/mv3/getstarted/development-basics/index.md +++ b/site/en/docs/extensions/mv3/getstarted/development-basics/index.md @@ -28,7 +28,10 @@ alt="Hello extension", width="206", height="130", class="screenshot" %} Start by creating a new directory to store extension files. If you prefer, you can download the full source code from [GitHub][sample-hello-world]. -Next, create a new file in this directory called `manifest.json` and add the following code: +Next, create a new file in this directory called `manifest.json`. This JSON object describes the extension's +capabilities and configuration. For example, most manifest files contain an `"action"` key which declares +the image Chrome should use as the extension's action icon and the HTML page to show in a popup when the +extension's action icon is clicked. ```json { @@ -43,8 +46,7 @@ Next, create a new file in this directory called `manifest.json` and add the fol } ``` -This JSON object describes the extension's capabilities and configuration. For example, the `"action"` key -declares the image Chrome should use as the extension's action icon and the HTML page to show in a popup when the extension's action icon is clicked. [Download the icon][hello-icon] to your directory, and be sure to change its name to match what's in the `"default_icon"` key. +[Download the icon][hello-icon] to your directory, and be sure to change its name to match what's in the `"default_icon"` key. For the popup, create a file named `hello.html`, and add the following code: From 57538ffbe428398d150c514d823f2b89850f6318 Mon Sep 17 00:00:00 2001 From: Joe Medley <jmedley@google.com> Date: Fri, 6 Oct 2023 11:51:21 -0700 Subject: [PATCH 860/982] Fix naming and linking issues surrounding single purpose policy. (#7452) --- redirects.yaml | 5 +- site/_data/docs/extensions/toc.yml | 2 +- .../blog/extension-side-panel-launch/index.md | 6 +- .../mv3/getstarted/extensions-101/index.md | 16 ++--- .../mv3/permission_warnings/index.md | 20 +++--- .../index.md | 62 +++++++++++-------- site/en/docs/webstore/best_practices/index.md | 1 - .../docs/webstore/program-policies/index.njk | 2 +- .../quality-guidelines/index.md | 4 +- .../en/docs/webstore/troubleshooting/index.md | 2 +- 10 files changed, 65 insertions(+), 55 deletions(-) rename site/en/docs/extensions/mv3/{single_purpose => quality_guidelines}/index.md (84%) diff --git a/redirects.yaml b/redirects.yaml index a14601d18..b83f09f7e 100644 --- a/redirects.yaml +++ b/redirects.yaml @@ -480,7 +480,7 @@ redirects: # MV2 docs that have been removed, but their MV3 version still exists - from: /docs/extensions/mv2/single_purpose - to: /docs/extensions/mv3/single_purpose/ + to: /docs/extensions/mv3/quality_guidelines/ # Group redirects @@ -774,6 +774,9 @@ redirects: - from: /docs/privacy-sandbox/fledge/... to: /docs/privacy-sandbox/protected-audience/... +- from: docs/extensions/mv3/single_purpose/ + to: docs/extensions/mv3/quality_guidelines/ + # DO NOT REMOVE. This seems pointless but we rewrite "." to "_" inside our server's code, so if the # URL is fine for all but incorrect syntax, we'll fix it up. - from: /... diff --git a/site/_data/docs/extensions/toc.yml b/site/_data/docs/extensions/toc.yml index d108c6180..92bed1258 100644 --- a/site/_data/docs/extensions/toc.yml +++ b/site/_data/docs/extensions/toc.yml @@ -19,7 +19,7 @@ sections: - url: /docs/extensions/mv3/themes - url: /docs/extensions/mv3/faq - - url: /docs/extensions/mv3/single_purpose + - url: /docs/extensions/mv3/quality_guidelines - title: i18n.docs.extensions.migrating sections: - url: /docs/extensions/migrating/ diff --git a/site/en/blog/extension-side-panel-launch/index.md b/site/en/blog/extension-side-panel-launch/index.md index b30e7d4ce..7f077f4c2 100644 --- a/site/en/blog/extension-side-panel-launch/index.md +++ b/site/en/blog/extension-side-panel-launch/index.md @@ -1,6 +1,6 @@ --- title: "Design a superior user experience with the new Side Panel API" -description: "Introducing the new Side Panel API for Chrome extensions." +description: "Introducing the new Side Panel API for Chrome extensions." layout: "layouts/blog-post.njk" authors: - oliverdunk @@ -119,7 +119,7 @@ You can keep up with Chrome extension news by visiting our [What's new page][wha --- _Photo by [Vardan Papikyan][unsplash-vardan] on [Unsplash][unsplash]_ - + [api-sidepanel]: /docs/extensions/reference/sidepanel [chromium-groups]: https://groups.google.com/a/chromium.org/g/chromium-extensions [cws-best-practices]: /docs/webstore/program-policies/best-practices/ @@ -130,7 +130,7 @@ _Photo by [Vardan Papikyan][unsplash-vardan] on [Unsplash][unsplash]_ [gh-sidepanel-dictionary]: https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/functional-samples/sample.sidepanel-dictionary [gh-sidepanel-samples]: https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/functional-samples/ [manifest-icon]: /docs/extensions/mv3/manifest/icons/ -[policy-single-purpose]: /docs/extensions/mv3/single_purpose/ +[policy-single-purpose]: /docs/extensions/mv3/quality_guidelines#single-purpose [sp-by-site]: https://developer.chrome.com/docs/extensions/reference/sidePanel/#by-site [unsplash-vardan]: https://unsplash.com/@timberfoster?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText [unsplash]: https://unsplash.com/photos/lSegRSDBMLw?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText diff --git a/site/en/docs/extensions/mv3/getstarted/extensions-101/index.md b/site/en/docs/extensions/mv3/getstarted/extensions-101/index.md index 888370c14..32efc94ce 100644 --- a/site/en/docs/extensions/mv3/getstarted/extensions-101/index.md +++ b/site/en/docs/extensions/mv3/getstarted/extensions-101/index.md @@ -39,7 +39,7 @@ Extensions can use all the [JavaScript APIs](https://developer.mozilla.org/docs/ browser provides. What makes extensions more powerful than a web app is their access to [Chrome APIs][doc-apis]. The following are just a few examples of what extensions can do: -- Change the functionality or behavior of a website. +- Change the functionality or behavior of a website. - Allow users to collect and organize information across websites. - Add features to Chrome DevTools. @@ -50,25 +50,25 @@ See [Extension development overview][doc-dev-overview] for a complete list of AP Extensions contain different files, depending on the functionality provided. The following are some of the most frequently used files: -The manifest +The manifest : The extension's [manifest][doc-manifest] is the only required file that **must** have a specific file name: `manifest.json` . It also has to be located in the extension's root directory. The manifest records important metadata, defines resources, declares permissions, and identifies which files to run in the background and on the page. -The service worker +The service worker : The extension [service worker][doc-service-worker] handles and listens for browser events. There are many types of events, such as navigating to a new page, removing a bookmark, or closing a tab. It can use all the [Chrome APIs][doc-apis], but it cannot interact directly with the content of web pages; that’s the job of content scripts. -Content scripts +Content scripts : [Content scripts][doc-content-scripts] execute Javascript in the context of a web page. They can also read and modify the [DOM][mdn-dom] of the pages they're injected into. Content Scripts can only use a subset of the [Chrome APIs][doc-reference] but can indirectly access the rest by exchanging messages with the extension service worker. -The popup and other pages +The popup and other pages : An extension can include various HTML files, such as a [popup][doc-popup], an [options page][doc-options], and [other HTML pages][doc-ext-pages]. All these pages have access to [Chrome APIs][doc-apis]. @@ -135,7 +135,7 @@ See [Publish in the Chrome Web Store][doc-cws-publish] to learn how to distribut -{% Details %} +{% Details %} {% DetailsSummary %} **What if I only want to distribute the extension within my organization?** @@ -151,7 +151,7 @@ Read about both in [Enterprise publishing options][doc-cws-enterprise]. ## 🚀 Ready to start building? {: #building } -Choose any of the following tutorials to begin your extension learning journey. +Choose any of the following tutorials to begin your extension learning journey. | Extension | What you will learn | |----------------------------------|------------------------------------------------------------------------| @@ -182,7 +182,7 @@ extension and Chrome Web store documentation: [doc-popup]: /docs/extensions/mv3/user_interface/#popup [doc-reference]: /docs/extensions/reference/ [doc-service-worker]: /docs/extensions/mv3/service_workers/ -[doc-single-purpose]: /docs/extensions/mv3/single_purpose/ +[doc-single-purpose]: /docs/extensions/mv3/quality_guidelines/ [doc-ui]: /docs/extensions/mv3/user_interface/ [js-apis]: /docs/extensions/api_other/ [mdn-dom]: https://developer.mozilla.org/docs/Web/API/Document_Object_Model diff --git a/site/en/docs/extensions/mv3/permission_warnings/index.md b/site/en/docs/extensions/mv3/permission_warnings/index.md index 9239fcd4e..63964a77c 100644 --- a/site/en/docs/extensions/mv3/permission_warnings/index.md +++ b/site/en/docs/extensions/mv3/permission_warnings/index.md @@ -15,20 +15,20 @@ anchorRedirects: Chrome extensions enhance the user's browser experience. To do this extensions use [Chrome APIs][doc-apis] that require certain permissions. Some permissions are less intrusive and do not -display a warning. Other permissions trigger a warning that users have to allow. +display a warning. Other permissions trigger a warning that users have to allow. <figure> - {% Img src="image/BhuKGJaIeLNPW9ehns59NfwqKxF2/NcPZYfAhQMtpW78sT26K.png", - alt="Example of permission warnings are displayed when the user adds a new extension", + {% Img src="image/BhuKGJaIeLNPW9ehns59NfwqKxF2/NcPZYfAhQMtpW78sT26K.png", + alt="Example of permission warnings are displayed when the user adds a new extension", width="333", height="179", class='screenshot'%} <figcaption> - Permission warnings dialog displayed on installation. + Permission warnings dialog displayed on installation. </figcaption> </figure> When a new permission that [triggers a warning](#permissions_with_warnings) is added, the extension will be disabled until the user accepts the new permission. See [Updating -permissions](#update_permissions) to learn how to test this behavior. +permissions](#update_permissions) to learn how to test this behavior. <figure> {% Img src="image/BhuKGJaIeLNPW9ehns59NfwqKxF2/tQgKKMKbzmCzwBEAoatX.gif", alt="Example of an extension that is disabled until the user accepts the new permission.", width="396", height="288" %} @@ -48,7 +48,7 @@ harder to understand than others. Users are more likely to install extensions th guidelines: Request relevant permissions -: Extensions are required to fulfill a [single purpose](/docs/extensions/mv3/single_purpose/) and +: Extensions are required to fulfill a [single purpose](/docs/extensions/mv3/quality_guidelines#single-purpose) and comply with the [Use of permissions](/docs/webstore/program-policies/permissions/) policy. Ensure you only request permissions that support the extension's main functionality. @@ -103,7 +103,7 @@ To view an extension's permission warnings, you have the following options: <figure> {% Img src="image/BhuKGJaIeLNPW9ehns59NfwqKxF2/u6HOe2mbOK4O133iLrlP.png", alt="Pack extension", width="800", height="589", class='screenshot' %} <figcaption> - Developer mode enabled in the Extension management page + Developer mode enabled in the Extension management page </figcaption> </figure> 4. Specify the path to the extension's folder in the extension root directory field. Ignore the **Private key** field for a first-time package. @@ -121,7 +121,7 @@ To view an extension's permission warnings, you have the following options: <figure> {% Img src="image/BrQidfK9jaQyIHwdw91aVpkPiib2/GLrVd51VTUF86K8gUxu8.png", - alt="Packaged Extension Files", height="288", width="521" %} + alt="Packaged Extension Files", height="288", width="521" %} <figcaption> Packaged Extension Files </figcaption> @@ -193,7 +193,7 @@ These steps assume you followed the [Using the Extension Update Testing Tool](#v 1. Go to `chrome://extensions`. **Do not remove the previously installed package**. 1. Pack the extension again, but this time add the pem file in the second input. <figure> - {% Img src="image/BhuKGJaIeLNPW9ehns59NfwqKxF2/Z9V6Q2TOabWTEUTEI6bo.png", + {% Img src="image/BhuKGJaIeLNPW9ehns59NfwqKxF2/Z9V6Q2TOabWTEUTEI6bo.png", alt="Pem file added when packing extension", width="800", height="456", class='screenshot' %} <figcaption> Packing extension dialog with pem file included. @@ -204,7 +204,7 @@ These steps assume you followed the [Using the Extension Update Testing Tool](#v <figure> {% Img src="image/BrQidfK9jaQyIHwdw91aVpkPiib2/usZSh31pGiJxhhuKmM8B.png", alt="Extension has been disabled", height="398", width="297" %} - + <figcaption> Disabled extension warning </figcaption> diff --git a/site/en/docs/extensions/mv3/single_purpose/index.md b/site/en/docs/extensions/mv3/quality_guidelines/index.md similarity index 84% rename from site/en/docs/extensions/mv3/single_purpose/index.md rename to site/en/docs/extensions/mv3/quality_guidelines/index.md index acf7c5ada..84c857d3f 100644 --- a/site/en/docs/extensions/mv3/single_purpose/index.md +++ b/site/en/docs/extensions/mv3/quality_guidelines/index.md @@ -3,7 +3,7 @@ title: "Extensions quality guidelines FAQ" layout: "layouts/doc-post.njk" seoTitle: "Chrome Extensions quality guidelines FAQ" date: 2014-05-09 -updated: 2021-07-22 +updated: 2023-10-06 description: Frequently asked questions about the single purpose policy. --- @@ -17,7 +17,9 @@ With the July 2014 release of Chrome, [we introduced][3] the Settings Overrides extensions to manage important Chrome settings on Windows. Most recently, with the January 2017 release of Chrome, [we enabled][4] the Settings Overrides API on Mac. -## 1) Why did Google launch a "single purpose" Chrome extensions policy? {: #one } +## Single purpose policy {: #single-purpose } + +### Why did Google launch a "single purpose" Chrome extensions policy? {: #one } To maintain the quality of the Chrome user experience, we require Chrome extensions to have a single purpose. For an overview of the policy announcement, please read this [Chromium blog post][5]. @@ -29,19 +31,19 @@ Also, unexpected changes to browser functionality and settings have become the n complaint for Chrome users, and this policy helps minimize the problem by ensuring that users understand what extensions are doing. -## 2) Where can I find the "single purpose" policy? {: #two } +### Where can I find the "single purpose" policy? {: #two } Please refer to the [Extensions Quality Guidelines][6] section of the Chrome Web Store Developer Program Policies. -## 3) What does "single purpose" actually mean? {: #three } +### What does "single purpose" actually mean? {: #three } "Single purpose" can refer to one of two aspects of an extension: 1. An extension can have a single purpose limited to a narrow **focus area or subject matter** (for example, "news headlines", "weather", "comparison shopping"). If the extension has a narrow focus area or subject matter, then it can offer various functions related to that focus area or subject - matter. For example, a shopping extension could have a browser action button that allows users to + matter. For example, a shopping extension could have an action button that allows users to see recent deals and have host access to find coupons for a store the user is currently browsing. 2. Or, an extension can have a single purpose limited to a narrow **browser function** (for example, @@ -54,7 +56,7 @@ Be conscious of your extension's permissions. We assume your extension utilizes permissions it requests. Excessive permissions unrelated to your extension's single purpose will be viewed as enabling unrelated functionalities, resulting in a policy violation. -## 4) Will this policy affect my extension? {: #four } +### Will this policy affect my extension? {: #four } It depends. Particularly if your extension offers multiple features, please make sure that it has a single purpose. Ask yourself these questions: @@ -70,7 +72,7 @@ single purpose. Ask yourself these questions: If you're unsure, you may want to post a question to the [chromium-extensions][crx-group] Google Group to get feedback from other extension developers. -## 5) What will happen if I don't make my extension compliant with this policy? {: #five } +### What will happen if I don't make my extension compliant with this policy? {: #five } If you created your extension after December 19, 2013, your extension will not be permitted in the Chrome Web Store. If you created your extension prior to December 19, 2013, your extension may be @@ -82,7 +84,9 @@ before it can be restored. In order to minimize disruption for users, we recommend that you take a moment to carefully review your extensions and make necessary updates as soon as possible. -## 6) Can my extension make changes to the start page, home page, and new tab settings? {: #six } +## Chrome changes {: #chrome-changes } + +### Can my extension make changes to the start page, home page, and new tab settings? {: #six } Yes. If the purpose of your extension is to modify one narrow function of the browser (either the start page, home page or new tab page, for example), and it does only that, then it would be @@ -105,7 +109,7 @@ created by the entity that controls those domains. For example, you could distri that changes the home page to wikipedia.org if the Wikimedia Foundation originally created and published the extension in the Chrome Web Store, and gave you the right to distribute it. -## 7) Can my extension make changes to the default search settings? {: #seven } +### Can my extension make changes to the default search settings? {: #seven } Yes. If the only purpose of the extension is to change the default search settings, then it would be compliant with the single purpose policy. @@ -114,7 +118,7 @@ The only supported way to change the web search settings using an extension is v Overrides API. Extensions that change the web search experience in any form, without using the [Settings Overrides API][16], are subject to removal from the Chrome Web Store. -## 8) My extension makes programmatic changes to Chrome user settings, but does not use one of the available APIs. What is the deadline to make changes to my extension? {: #eight } +### My extension makes programmatic changes to Chrome user settings, but does not use one of the available APIs. What is the deadline to make changes to my extension? {: #eight } If your extension makes programmatic changes to user settings within Chrome on Mac, make sure you begin adjusting your code to use the Settings Overrides API. Extensions for Chrome on Windows have @@ -123,7 +127,9 @@ until July 1, 2017 to make the appropriate changes and resubmit their extensions extensions that make programmatic changes to any Chrome user settings without an API, will be subject to removal from the Web Store. -## 9) How will users be notified of settings changes in new versions of Chrome? {: #nine } +## Settings {: #settings } + +### How will users be notified of settings changes in new versions of Chrome? {: #nine } If an extension changes Chrome settings via the Settings Override API, the user will be notified of the settings changes prior to installation, when they encounter the settings change for the first @@ -131,23 +137,25 @@ time, and via an indicator next to each changed setting on the Chrome settings p notifications, users will have the option to reverse the settings changes by disabling the extension. -## 10) What happens to settings when an extension is disabled? {: #ten } +### What happens to settings when an extension is disabled? {: #ten } All Chrome settings changed by an extension will be reverted when that extension is disabled. -## 11) Will users' existing home page, search provider or startup pages be affected by the introduction of the Settings Override API? {: #eleven } +### Will users' existing home page, search provider or startup pages be affected by the introduction of the Settings Override API? {: #eleven } No. A user's existing home page, search provider or startup settings will remain unchanged by the introduction of Settings Override API. Following the launch of the Settings Override API, only extensions can programmatically change these settings and only through the Settings Override API. -## 12) Does this policy apply to Chrome apps too? {: #twelve } +### Does this policy apply to Chrome apps too? {: #twelve } At this time, Chrome apps (as distinguished from extensions) are not required to be distributed through the Chrome Web Store, or to have a single purpose. Chrome apps are currently not capable of changing Chrome settings. -## 13) Can I bundle ad injection with some other type of functionality? {: #thirteen } +## Other {: #other } + +### Can I bundle ad injection with some other type of functionality? {: #thirteen } No. This violates the single purpose policy. However, if injecting ads is the single purpose of the extension and the extension is otherwise compliant with Chrome policies, then it would be @@ -156,16 +164,16 @@ related to a page the user is visiting would be compliant with the single purpos has a single purpose limited to a narrow function of the browser. You also might want to explore the other monetization options described [here][10]. -## 14) Are toolbars permitted under this policy? {: #fourteen } +### Are toolbars permitted under this policy? {: #fourteen } -It depends on what the toolbar does. As described in [answer #3][11], it must adhere to the narrow +It depends on what the toolbar does. As [described above #3][11], it must adhere to the narrow single purpose of the extension. Broad, multi-purpose toolbars are not allowed and toolbars that are implemented using content scripts to inject UI into every page are not recommended because they slow down every page load, clutter the UI, and can lead to security problems for users. Instead, consider using an [action popup][12], which was designed to solve this very problem. It's a better user experience, with no performance or security downsides. -## 15) What will happen to non-compliant extensions that were already installed by users? {: #fifteen } +### What will happen to non-compliant extensions that were already installed by users? {: #fifteen } All extensions must comply with the Extension Quality Guidelines. If a user installed a non-compliant extension, then you will need to update them to a compliant extension that is hosted @@ -174,7 +182,7 @@ Chrome Web Store, then the extension will be automatically disabled. As noted ab behaviours controlled by the extension, including any settings controlled by the Settings Override API, will be reverted when the extension is disabled. You can find more information [here][13]. -## 16) If my extension is rejected from the Chrome Web Store because it doesn't comply with the single purpose policy, what will happen after the requirement to host extensions in the Chrome Web Store comes into effect? {: #sixteen } +### If my extension is rejected from the Chrome Web Store because it doesn't comply with the single purpose policy, what will happen after the requirement to host extensions in the Chrome Web Store comes into effect? {: #sixteen } If your extension is rejected from the Chrome Web Store, you will need to make changes or appeal the decision. After the requirement to host extensions in the Chrome Web Store comes into effect for @@ -182,31 +190,31 @@ Windows in late May 2014, your extension must be hosted in the Chrome Web Store automatically disabled from the users' browsers. The same will occur for Mac extensions that are not hosted on the Chrome Web Store prior to the release of 44 in July 2015. -## 17) If my extension gets flagged for review under the single purpose policy, what will happen? {: #seventeen } +### If my extension gets flagged for review under the single purpose policy, what will happen? {: #seventeen } Our team will review it, and it may be removed from the Chrome Web Store. You'll have a chance to make changes and appeal the decision. As noted above, if you created your extension before we announced the policy on December 19, 2013, you have until July 22, 2014 to make changes. If your extension was created after the policy was announced, it needs to be compliant now. -## 18) If my extension's single purpose is to change the new tab page, can I use the browser/page action button? {: #eighteen } +### If my extension's single purpose is to change the new tab page, can I use the action button? {: #eighteen } -The addition of a page or browser action button under the new Chrome UI (Chrome 49 and later), will +The addition of an action button under the new Chrome UI (Chrome 49 and later), will not trigger a single purpose policy violation if the button only serves as a shortcut to the extension's main functionality. For example, if an extension's single purpose is changing the new -tab page, clicking the toolbar icon can open a new tab page. The page or browser action button +tab page, clicking the toolbar icon can open a new tab page. The action button button, however, cannot introduce any additional functionality or content. If an extension's single -purpose is a narrow subject matter or focus area, then the functionality and content of the browser +purpose is a narrow subject matter or focus area, then the functionality and content of the action button must likewise fall within that narrow purpose. -## 19) Why does Chrome display a confirmation prompt for some extensions? {: #nineteen } +### Why does Chrome display a confirmation prompt for some extensions? {: #nineteen } Chrome makes it easy for users to retain agency over their preferred search settings. Modifying search settings should be a purpose on its own, and when bundled with other functionalities, users may experience an unpleasant surprise. For these reasons, search extensions that stretch their functionality beyond a clear single purpose will trigger a confirmation dialog. Search extensions that are limited to the single purpose of overriding search settings will not trigger a confirmation -dialog. +dialog. {# A former section #nineteen has been removed #} @@ -243,7 +251,7 @@ to the narrow subject matter of search. [9]: /docs/extensions/mv3/override [10]: /docs/webstore/money [11]: #three -[12]: /docs/extensions/browserAction +[12]: /docs/extensions/action [13]: http://blog.chromium.org/2014/02/make-sure-to-get-your-extension-in.html [16]: /docs/extensions/mv3/settings_override/#others diff --git a/site/en/docs/webstore/best_practices/index.md b/site/en/docs/webstore/best_practices/index.md index ddd807330..2314dd7b7 100644 --- a/site/en/docs/webstore/best_practices/index.md +++ b/site/en/docs/webstore/best_practices/index.md @@ -172,7 +172,6 @@ Social & Communications [privacy-tab]: /docs/webstore/cws-dashboard-privacy/#certify-your-data-use-practices [program-policies]: /docs/webstore/program-policies/ [puppeteer]: https://pptr.dev/guides/chrome-extensions -[single-purpose]: /docs/extensions/mv3/single_purpose/ [stay-secure]: /docs/extensions/mv3/security/ [supplying-images]: /docs/webstore/images/ [user-data]: /docs/webstore/user_data/ diff --git a/site/en/docs/webstore/program-policies/index.njk b/site/en/docs/webstore/program-policies/index.njk index f5a253821..a9ae89e0e 100644 --- a/site/en/docs/webstore/program-policies/index.njk +++ b/site/en/docs/webstore/program-policies/index.njk @@ -53,7 +53,7 @@ sections: title: Product Ranking Info - url: /webstore/spam-faq/ title: Spam policy FAQ - - url: /docs/extensions/mv3/single_purpose/ + - url: /docs/extensions/mv3/quality_guidelines title: Extensions quality guidelines FAQ tech_reqs: - url: /docs/webstore/program-policies/code-readability/ diff --git a/site/en/docs/webstore/program-policies/quality-guidelines/index.md b/site/en/docs/webstore/program-policies/quality-guidelines/index.md index cf93bd714..d38fedaf3 100644 --- a/site/en/docs/webstore/program-policies/quality-guidelines/index.md +++ b/site/en/docs/webstore/program-policies/quality-guidelines/index.md @@ -17,10 +17,10 @@ updated: 2023-05-30 2. When designing an extension, it's important to ensure it functions as a helpful companion to users' browsing experiences by providing complementary functionality. If utilizing a persistent user interface, extensions should actively enhance the user's current task while causing minimal distractions. Some common violations include: - 1. Side panel extensions which hijack a user’s browsing or search experience. + 1. Side panel extensions which hijack a user’s browsing or search experience. 1. Extensions with the primary purpose of serving ads. See [this FAQ][faq] for more information. -[faq]: /docs/extensions/mv2/single_purpose/ \ No newline at end of file +[faq]: /docs/extensions/mv3/quality_guidelines \ No newline at end of file diff --git a/site/en/docs/webstore/troubleshooting/index.md b/site/en/docs/webstore/troubleshooting/index.md index 2c4fc18f2..9a4911b59 100644 --- a/site/en/docs/webstore/troubleshooting/index.md +++ b/site/en/docs/webstore/troubleshooting/index.md @@ -1312,7 +1312,7 @@ Store [docs-pack-extension]: /docs/extensions/mv3/linux_hosting/#create [docs-publish-setup]: /docs/webstore/cws-dashboard-privacy/#set-privacy-policy [docs-service-workers]: /docs/extensions/mv3/service_workers/ -[docs-single-purpose-faq]: /docs/extensions/mv3/single_purpose/ +[docs-single-purpose-faq]: /docs/extensions/mv3/quality_guidelines#single-purpose [lie-fi]: https://web.dev/performance-poor-connectivity/#what-is-lie-fi [mature-content]: /docs/webstore/cws-dashboard-listing/#mature-content [mdn-cookie-store]: https://developer.mozilla.org/docs/Web/API/Cookie_Store_API From cf4c60537a608e84e9ee6ddc4fd6e347becc6d8f Mon Sep 17 00:00:00 2001 From: Rachel Andrew <rachelandrew@google.com> Date: Sat, 7 Oct 2023 06:54:55 +0300 Subject: [PATCH 861/982] post (#7463) --- site/en/blog/chrome-119-beta/index.md | 156 ++++++++++++++++++++++++++ 1 file changed, 156 insertions(+) create mode 100644 site/en/blog/chrome-119-beta/index.md diff --git a/site/en/blog/chrome-119-beta/index.md b/site/en/blog/chrome-119-beta/index.md new file mode 100644 index 000000000..96cbc7399 --- /dev/null +++ b/site/en/blog/chrome-119-beta/index.md @@ -0,0 +1,156 @@ +--- +title: Chrome 119 beta +description: > + Chrome 119 beta brings you CSS relative color syntax, new pseudo-classes, and much more. +subhead: > + Chrome 119 beta brings you CSS relative color syntax, new pseudo-classes, and much more. +layout: 'layouts/blog-post.njk' +date: 2023-10-06 +hero: 'image/kheDArv5csY6rvQUJDbWRscckLr1/5N68Pe8N9DKjNi5F0YP6.png' +alt: > + Chrome 119 beta hero logo +tags: + - beta + - chrome-119 +--- + +Unless otherwise noted, changes described below apply to the newest Chrome beta channel release for Android, ChromeOS, Linux, macOS, and Windows. Learn more about the features listed here through the provided links or from the list on ChromeStatus.com. Chrome 119 is beta as of October 4, 2023. You can download the latest on [Google.com](https://www.google.com/chrome/beta/) for desktop or on Google Play Store on Android. + +## CSS + +This release adds four new CSS features. + +### :user-valid and :user-invalid CSS pseudo-classes + +The `:user-invalid` and `:user-valid` pseudo-classes represent an element with incorrect or correct input, respectively, but only after the user has significantly interacted with it. This is similar to `:valid` and `:invalid`, but with the added constraint that these pseudo-classes only match after the user has interacted with the element. + +### CSS Relative Color Syntax (RCS) + +The [relative color syntax](https://www.w3.org/TR/css-color-5/#relative-colors) allows developers to define colors by modifying the parameters of other colors. + +For example: `oklab(from magenta calc(l * 0.8) a b);` results in an oklab magenta that is 80% lighter. + +### CSS clip-path geometry-box values + +The CSS `clip-path` property now supports `<geometry-box>` values to control the clip's reference box, making `clip-path` easier to use. These box values can be used alongside basic shapes (for example, `clip-path: circle(50%) margin-box`), or they can be used alone to clip to the specified box (for example, `clip-path: content-box`). + +### CSS clip-path xywh() and rect() values + +Chrome now supports the `xywh()` and `rect()` values of the `clip-path` property, which make it easier to specify rectangular or rounded-rectangular clips. + +## Web APIs + +### Cookie Expires/Max-Age attribute upper limit for prior storage + +Since Chrome 104 newly created cookies or those updated with an expiration date have had that date capped at no more than 400 days in the future. This same limit will now be retroactively applied to cookies already in storage. The expiration dates of these cookies will be capped at no more than 400 days after the first time Chrome 119+ starts up and does a one time database migration. The impact of this change will not be felt by users until at least 400 days after Chrome 119 is released, and then only for existing cookies that have not been updated in that period. + +### DisplayMediaStreamOptions monitorTypeSurfaces + +When `getDisplayMedia()` is called, the browser offers the user a choice of display surfaces: tabs, windows, or monitors. Using the [`monitorTypeSurfaces`](/docs/web-platform/screen-sharing-controls/#monitorTypeSurfaces ) option, the web application may now hint to the browser if it prefers to include display surfaces whose type is monitor among the choices offered to the user. + +### Fenced Frames functionality updates + +Chrome 119 includes the following improvements to Fenced Frames. + +There is an additional format option for Protected Audience ad size macros In the Protected Audience API within the Privacy Sandbox. An opt-in feature allows you to macro the size of the ad that wins the auction into the ad’s url, for example: + +`https://ad.com?width={/%AD_WIDTH%}&height={/%AD_HEIGHT%}` + +To be more consistent with other types of macros in Protected Audience, like those used by `deprecatedReplaceInURN` and `registerAdMacro`, in Chrome 119 we’re adding the ability to use `${AD_WIDTH}` and `${AD_HEIGHT}` as the format for the macros in addition to the current format. + +Automatic beacons will now send to all registered URLs. Previously, only destinations specified when calling `setReportEventDataForAutomaticBeacons()` receive automatic beacons, even if that destination called `registerAdBeacon()` for `"reserved.top_navigation"` in their worklet. Now, any destination that called `registerAdBeacon()` for `"reserved.top_navigation"` will get an automatic beacon, but only destinations specified in `setReportEventDataForAutomaticBeacons()` will get automatic beacon data along with the beacon. The `"once"` parameter in `setReportEventDataForAutomaticBeacons()` will now determine whether the data is sent out once, rather than determine if the entire beacon is sent once. + +### Intersection Observer scroll margin + +The Intersection Observer `scrollMargin` property allows developers to observe targets inside nested scroll containers that are currently clipped away by the scroll containers. This is achieved by expanding the container's clipping rect by the `scrollMargin` when calculating the intersection. + +### Keyboard-focusable scroll containers + +This feature improves accessibility by making scroll containers focusable using sequential focus navigation. Previously, the tab key didn't focus scrollers unless tabIndex was explicitly set to 0 or more. By making scrollers focusable by default, users who can't (or don't want to) use a mouse will be able to focus clipped content using a keyboard's tab and arrow keys. This behavior is enabled only if the scroller does not contain any keyboard focusable children. + +### Private Network Access restrictions for automotive + +Enforce (instead of just warn) Private Network Access restrictions on Chrome for Android Automotive (if `BuildInfo::is_automotive`). This includes Private Network Access preflight requests for subresources, and Private Network Access for Workers. + +### Read Chrome device attributes + +Device Attributes Web API is a subset of the Managed Device Web API, that provides web applications the capability to query device information. For example, device ID, serial number, and location. + +### Replace dangling markup in target name to `_blank` + +This change replaces the navigable target name (which is usually set by target attribute) to `_blank`, if it contains a dangling markup (for example, `\n` and `<`). Which fixes a bypass in the dangling markup injection mitigation. + +### Sec-CH-Prefers-Reduced-Transparency user preference media features Client Hints header + +The [user preference media features Client Hints header](https://web.dev/user-preference-media-features-headers/) defines a set of HTTP Client Hints headers around user preference media features as defined by Media Queries Level 5. If used as Critical Client Hints, these headers allow servers to make smart choices regarding, for example, CSS inlining. `Sec-CH-Prefers-Reduced-Transparency` reflects the user's `prefers-reduced-transparency` preference, and is available from Chrome 119. + +### Standard compliant URL host punctuation characters + +Make Chrome's handling of URL host punctuation characters compliant with the [URL standard](https://url.spec.whatwg.org/#host-writing). For example: + +Before: + +```bash +> const url = new URL("http://exa(mple.com";); +> url.href +'http://exa%28mple.com/' +``` + +`(` is a forbidden character, however, Chrome permits it wrongly. + +After: + +```bash +> const url = new URL("http://exa(mple.com";); +> => throws TypeError: Invalid URL. +``` + +### WebCodecs AudioEncoder bitrateMode + +Some audio codecs support specifying the audio encoder bitrate modes. This feature adds a `"bitrateMode"` flag with a default value of `"variable"` to WebCodec's `AudioEncoderConfig`, which mirrors the config option and default already present for `VideoEncoderConfig`. + +This flag will allow developers to choose between encoding audio with a variable bitrate or a constant bitrate. Specific codec encoder implementations might have slightly different terminology (for example, `CBR` vs `VBR` for Opus), but all of them should map to the general concept of "constant" versus "variable" bitrate. + +The two options have the following effects: + +- **variable**: allows an audio encoder to increase or lower its bitrate according to the content of the audio it is encoding, in order to preserve bandwidth/binary-size, while still maintaining a target quality. For example, an encoder might lower its bitrate when encoding silence, and revert to a full bitrate when encoding speech. +- **constant** : forces an audio encoder to maintain the same bitrate, regardless of the audio content. This can be useful when a predictable bandwidth consumption is preferable. + +As of Chrome 119, this flag will affect two codecs on Chromium: Opus and AAC. + +### X25519Kyber768 key encapsulation for TLS + +[Protect current Chrome TLS traffic](https://blog.chromium.org/2023/08/protecting-chrome-traffic-with-hybrid.html) against future quantum cryptanalysis by deploying the Kyber768 quantum-resistant key agreement algorithm. This is a hybrid X25519 + Kyber768 key agreement based on an IETF standard. This specification and launch is outside the scope of W3C. This key agreement will be launched as a TLS cipher, and should be transparent to users. + +## Origin trials in progress + +In Chrome 119 you can opt into the following new [origin trial](/docs/web-platform/origin-trials/). + +### Open popups as fullscreen windows + +This feature adds a `fullscreen` windowFeatures parameter to the `window.open()` JavaScript API. This allows the caller to open a popup directly to full-screen on the display that would contain the popup (based on screenX and screenY). This eliminates the need for the developer to manually transition a popup into full-screen, which could require a new user activation signal. + +## Deprecations and removals + +This version of Chrome introduces the deprecations and removals listed below. Visit ChromeStatus.com for lists of planned deprecations, current deprecations and previous removals. + +This release of Chrome removes four features. + +### Remove Web SQL + +We previously announced the [deprecation and removal of WebSQL](/blog/deprecating-web-sql/). The feature is fully removed as of Chrome 119. [A reverse origin trial](/origintrials/#/view_trial/494270059103911937) allows developers to continue to use WebSQL until Chrome 123. + +### Remove Sanitizer API + +The Sanitizer API aims to build an easy-to-use, always secure, browser-maintained HTML sanitizer into the platform. Chrome shipped an initial version in Chrome 105, based on the then-current specification draft. However, the discussion has meanwhile moved on and the proposed API shape has changed substantially. + +In order to prevent the current API from becoming entrenched we are removing the current implementation. We expect to re-implement the Sanitizer API when the proposed specification stabilizes again. + +### Remove data: URL in SVGUseElement + +Assigning a `data: URL` in `SVGUseElement` can cause XSS. And this also led to a Trusted Types bypass. Therefore, we plan to deprecate and remove support for it. + + +### Remove non-standard `shadowroot` attribute for declarative shadow DOM + +The standards-track `shadowrootmode` attribute, which enables declarative Shadow DOM, was shipped in Chrome 111. The older, non-standard `shadowroot` attribute is being removed in Chrome 119. There is a straightforward migration path: replace `shadowroot` with `shadowrootmode`. From 65970ca2f29992f28584785bfa4d1d0a369bb3fc Mon Sep 17 00:00:00 2001 From: Sam Dutton <samdutton@users.noreply.github.com> Date: Sat, 7 Oct 2023 10:38:50 +0100 Subject: [PATCH 862/982] Add error handling to Protected Audience example (#7455) --- .../protected-audience-api/ad-auction/index.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/site/en/docs/privacy-sandbox/protected-audience-api/ad-auction/index.md b/site/en/docs/privacy-sandbox/protected-audience-api/ad-auction/index.md index e81bef476..32145e098 100644 --- a/site/en/docs/privacy-sandbox/protected-audience-api/ad-auction/index.md +++ b/site/en/docs/privacy-sandbox/protected-audience-api/ad-auction/index.md @@ -142,7 +142,11 @@ const auctionConfig = { ] }; -const auctionResultPromise = navigator.runAdAuction(auctionConfig); +try { + const auctionResultPromise = navigator.runAdAuction(auctionConfig); +} catch (error) { + // Handle error. +} ``` `runAdAuction()` returns a promise that resolves to a [URN](https://developer.mozilla.org/docs/Web/HTTP/Basics_of_HTTP/Identifying_resources_on_the_Web#urns) (`urn:uuid:<something>`) that represents the From 6003c46f64c9d229b7583538e40afe76c9862d00 Mon Sep 17 00:00:00 2001 From: Sam Dutton <samdutton@users.noreply.github.com> Date: Sat, 7 Oct 2023 10:39:03 +0100 Subject: [PATCH 863/982] Add error handling to Topics example (#7454) --- site/en/docs/privacy-sandbox/topics/index.md | 39 +++++++++++--------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/site/en/docs/privacy-sandbox/topics/index.md b/site/en/docs/privacy-sandbox/topics/index.md index dcd33fd81..00ae7401d 100644 --- a/site/en/docs/privacy-sandbox/topics/index.md +++ b/site/en/docs/privacy-sandbox/topics/index.md @@ -58,25 +58,30 @@ Feature support on the current page isn't a guarantee that an API is usable: the ### Access topics with the JavaScript API {: #access-topics} -Here is a basic example of possible API usage to access topics for the current user. To keep it simple, there's no error handling. +Here is a basic example of possible API usage to access topics for the current user. ```javascript -// Get the array of top topics for this user. -const topics = await document.browsingTopics(); - -// Request an ad creative. -const response = await fetch('https://ads.example/get-creative', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify(topics) -}) - -// Get the JSON from the response. -const creative = await response.json(); - -// Display ad. +try { + // Get the array of top topics for this user. + const topics = await document.browsingTopics(); + + // Request an ad creative. + const response = await fetch('https://ads.example/get-creative', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(topics) + }) + + // Get the JSON from the response. + const creative = await response.json(); + + // Display ad. + +} catch (error) { + // Handle error. +} ``` ### Access topics without modifying state {: #skipobservation} From 2c72733cc6eea040776d5e0873638f0f3cde8565 Mon Sep 17 00:00:00 2001 From: Oliver Dunk <oliverdunk@google.com> Date: Mon, 9 Oct 2023 09:56:58 +0100 Subject: [PATCH 864/982] Update date on storage and cookies article (#7407) * Update date on storage and cookies article * Update site/en/docs/extensions/mv3/storage-and-cookies/index.md Co-authored-by: Joe Medley <jmedley@google.com> --------- Co-authored-by: Joe Medley <jmedley@google.com> --- site/en/docs/extensions/mv3/storage-and-cookies/index.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/site/en/docs/extensions/mv3/storage-and-cookies/index.md b/site/en/docs/extensions/mv3/storage-and-cookies/index.md index 46f0a2683..b20bb2d0e 100644 --- a/site/en/docs/extensions/mv3/storage-and-cookies/index.md +++ b/site/en/docs/extensions/mv3/storage-and-cookies/index.md @@ -2,7 +2,7 @@ layout: "layouts/doc-post.njk" title: "Storage and cookies" seoTitle: "Chrome extensions storage and cookies" -date: 2023-08-01 +date: 2023-09-28 description: Overview of how web storage APIs and cookies work in extensions. --- @@ -87,7 +87,7 @@ When an extension embeds a third-party site, that site will use the extension or Cookies set on chrome-extension:// pages always use [`SameSite=Lax`][same-site]. Consequently, they can never be accessed in iframes and partitioning is not relevant. -When an extension embeds a third-party website inside of a chrome://extension page, the behavior +When an extension embeds a third-party website inside one of its pages, the behavior depends on the choices on Chrome's Privacy and security settings page: - If third-party cookies are enabled, the site can access cookies from a partition keyed based on From 8b8b475ac0e322922884a735a0c31f5723119fbc Mon Sep 17 00:00:00 2001 From: Thomas Steiner <steiner.thomas@gmail.com> Date: Mon, 9 Oct 2023 11:17:14 +0200 Subject: [PATCH 865/982] Add fullscreen popup OT article (#7374) * Add fullscreen popup OT article * Fix lint errors * Update site/en/blog/fullscreen-popups-origin-trial/index.md * Address feedback from Chat * Update site/en/blog/fullscreen-popups-origin-trial/index.md * Update site/en/blog/fullscreen-popups-origin-trial/index.md * Update index.md * Add OT link * Link relative --- .../fullscreen-popups-origin-trial/index.md | 122 ++++++++++++++++++ 1 file changed, 122 insertions(+) create mode 100644 site/en/blog/fullscreen-popups-origin-trial/index.md diff --git a/site/en/blog/fullscreen-popups-origin-trial/index.md b/site/en/blog/fullscreen-popups-origin-trial/index.md new file mode 100644 index 000000000..1ad21c2de --- /dev/null +++ b/site/en/blog/fullscreen-popups-origin-trial/index.md @@ -0,0 +1,122 @@ +--- +title: 'New origin trial for fullscreen popup windows' +description: > + There's now a new origin trial available for opening popup windows in fullscreen mode with just one step. +authors: + - thomassteiner +layout: 'layouts/blog-post.njk' +date: 2023-10-09 +tags: + - capabilities +--- + +Imagine you want to open a popup window in fullscreen mode. Until now, opening a +fullscreen popup window consisted of two steps: + +1. From the main app window, calling the + [`window.open()`](https://developer.mozilla.org/docs/Web/API/Window/open) + method that requires a user gesture like the click on an **Open popup + window** button. +1. From the popup window, calling the + [`Element.requestFullscreen()`](https://developer.mozilla.org/es/docs/Web/API/Element/requestFullscreen) + method, which likewise requires a user gesture like the click on an **Enter + fullscreen mode** button. + +There's now a new +[origin trial](/docs/web-platform/origin-trials/) +available running from Chrome 119 (stable date): {% ChromeDate 119 %} to Chrome +122 (stable date): {% ChromeDate 122 %} for opening popup windows in fullscreen +mode with just one step. Click **Register** on the +[Open popups as fullscreen windows](/origintrials/#/view_trial/106960491150049281) +origin trial landing page to sign up. +Apart from the origin trial, you can also test locally +by setting the `chrome://flags/#fullscreen-popup-windows` flag to **Enabled**. + +## Opening fullscreen popup windows on the current screen + +This new feature is gated behind the +[`window-management`](/articles/window-management/#the-window-management-permission) +permission. Once the user has granted the permission, you can open a fullscreen +popup window as in the following example. + +```js +document.querySelector('.fullscreen-popoup-button').addEventListener('click', async (e) => { + if ((await navigator.permissions.query({name: 'window-management'})).state !== 'granted') { + // Permission not granted. Call `window.getScreenDetails()` to prompt. + await window.getScreenDetails(); + } + // Permission granted. Open the fullscreen popup window. + window.open('https://example.com/popup.html', '_blank', 'popup,fullscreen'); +}); +``` + +In the last line of the code sample, the first parameter is the +[`url`](https://developer.mozilla.org/docs/Web/API/Window/open#url) to +open in the popup window. The second parameter is the +[`target`](https://developer.mozilla.org/docs/Web/API/Window/open#target), +with the special value of +[`_blank`](https://developer.mozilla.org/docs/Web/HTML/Element/a#target). +The third parameter is for the +[`windowFeatures`](https://developer.mozilla.org/docs/Web/API/Window/open#windowfeatures), +a comma-separated string with the value +[`popup`](https://developer.mozilla.org/docs/Web/API/Window/open) for +opening a popup window and the new value `fullscreen` for opening the popup +window in fullscreen mode. This works with just one user gesture, therefore can +be activated with a single click on a button. + +## Opening fullscreen popup windows on other screens + +This feature really shines in combination with the +[Window Management API](/articles/window-management/) +which lets you obtain information about all the screens the user has connected +to their computer. For example, to open a fullscreen popup window on another +screen than the user's current screen, you need to first +[find the other screen](/articles/window-management/#the-getscreendetails-method) +and then pass its `availLeft`, `availTop`, `availWidth`, and `availHeight` +values to the corresponding `left`, `top`, `width`, and `height` values of the +`windowFeatures` string. + +```js +document.querySelector('.fullscreen-popoup-button-other-screen').addEventListener('click', async (e) => { + const screenDetails = await window.getScreenDetails(); + ​​const otherScreen = screenDetails.screens.find(s => s !== screenDetails.currentScreen); + window.open('https://example.com/popup.html', '_blank', `left=${otherScreen.availLeft},` + + `top=${otherScreen.availTop},` + + `width=${otherScreen.availWidth},` + + `height=${otherScreen.availHeight},` + + `fullscreen`); +}); +``` + +{% Aside %} +​​It's not required to add `popup` in the `windowFeatures` strings here, as it's +implicitly assumed when any of `left`, `top`, `width`, or `height` is defined. +{%endAside %} + +## Demo + +Try fullscreen popup windows in the +[demo](https://michaelwasserman.github.io/window-placement-demo/) and +[view the source code](https://github.com/michaelwasserman/window-placement-demo/). +Be sure to check the **fullscreen** checkbox and the **Fullscreen popup** button, and, +if you have the opportunity, play with the demo with multiple screens attached to +your device. + +<iframe src="https://michaelwasserman.github.io/window-placement-demo/" style="width: 100%; height: 800px;" allow="window-management;fullscreen"></iframe> + +## Related links + +- [Public explainer](https://github.com/w3c/window-management/blob/main/EXPLAINER_fullscreen_popups.md) +- [ChromeStatus entry](https://chromestatus.com/feature/6002307972464640) +- [Chromium bug](https://bugs.chromium.org/p/chromium/issues/detail?id=1142516) +- [TAG review](https://github.com/w3ctag/design-reviews/issues/840) +- [Mozilla standards position](https://github.com/mozilla/standards-positions/issues/714) +- [WebKit standards position](https://github.com/WebKit/standards-positions/issues/101) + +## Acknowledgements + +This article was reviewed by [Brad +Triebwasser](https://www.linkedin.com/in/bradtriebwasser), [Hakan +Isbiliroglu](https://www.linkedin.com/in/hakan-isbiliroglu), +[Mike Wasserman](https://www.linkedin.com/in/mike-wasserman), and [Rachel +Andrew](https://rachelandrew.co.uk/). From a7c55808c122a16b6deb915c166f1a8a075f05bb Mon Sep 17 00:00:00 2001 From: Jack J <jxck@google.com> Date: Mon, 9 Oct 2023 21:16:02 +0900 Subject: [PATCH 866/982] Update index.md (#7457) Updating `Referer` header and `Origin` headers. For fixing https://github.com/GoogleChromeLabs/privacy-sandbox-dev-support/issues/152#issuecomment-1731458883 --- site/ja/docs/privacy-sandbox/fedcm/index.md | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/site/ja/docs/privacy-sandbox/fedcm/index.md b/site/ja/docs/privacy-sandbox/fedcm/index.md index 0333fc02e..8dc98341f 100644 --- a/site/ja/docs/privacy-sandbox/fedcm/index.md +++ b/site/ja/docs/privacy-sandbox/fedcm/index.md @@ -208,7 +208,7 @@ const credential = await navigator.credentials.get({ const { token } = credential; ``` -IdP 設定ファイルの場所の完全な URL を `configURL` として指定します。[`navigator.credentials.get()` が RP で呼び出される](#sign-into-rp)と、ブラウザは `Referer` ヘッダーなしで `GET` リクエストを使用して設定ファイルをフェッチします。リクエストには Cookie がなく、リダイレクトに従いません。これにより、誰がリクエストを行い、どの RP が接続を試みているかを IdP が知ることを効果的に防ぎます。次に例を示します。 +IdP 設定ファイルの場所の完全な URL を `configURL` として指定します。[`navigator.credentials.get()` が RP で呼び出される](#sign-into-rp)と、ブラウザは `Origin` ヘッダーや `Referer` ヘッダーなしで `GET` リクエストを使用して設定ファイルをフェッチします。リクエストには Cookie がなく、リダイレクトに従いません。これにより、誰がリクエストを行い、どの RP が接続を試みているかを IdP が知ることを効果的に防ぎます。次に例を示します。 ```http GET /config.json HTTP/1.1 @@ -310,7 +310,7 @@ RP が[Content Security Policy(CSP)](https://developer.mozilla.org/docs/Web/ IdP のアカウントリストエンドポイントは、ユーザーが現在 IdP にサインインしているアカウントのリストを返します。 IdP が複数のアカウントをサポートしている場合、このエンドポイントはサインインしているすべてのアカウントを返します。 -ブラウザは、cookie を含む `GET` リクエストを送信しますが、`client_id`パラメーターまたは `Referer` ヘッダーは使用しません。これにより、ユーザーがサインインしようとしている RP を IdP が知ることを効果的に防止します。次に例を示します。 +ブラウザは、cookie を含む `GET` リクエストを送信しますが、`client_id`パラメーター、 `Origin` ヘッダーや `Referer` ヘッダーは使用しません。これにより、ユーザーがサインインしようとしている RP を IdP が知ることを効果的に防止します。次に例を示します。 ```http GET /accounts.php HTTP/1.1 @@ -396,7 +396,7 @@ IdP のクライアントメタデータエンドポイントは、RP のプラ ```http GET /client_metadata.php?client_id=1234 HTTP/1.1 Host: accounts.idp.example -Referer: https://rp.example/ +Origin: https://rp.example/ Accept: application/json Sec-Fetch-Dest: webidentity ``` @@ -471,21 +471,22 @@ HTTP ヘッダーの例: ```http POST /assertion.php HTTP/1.1 Host: accounts.idp.example -Referer: https://rp.example/ +Origin: https://rp.example/ Content-Type: application/x-www-form-urlencoded Cookie: 0x23223 Sec-Fetch-Dest: webidentity + account_id=123&client_id=client1234&nonce=Ct60bD&disclosure_text_shown=true ``` サーバー上で、IdP は次のことを確認する必要があります。 1. 要求されたアカウント ID が、既にサインインしているアカウントの ID と一致していること。 -2. `Referer` ヘッダーが、所定のクライアント ID に対して事前に登録された RP のオリジンと一致すること。 +2. `Origin` ヘッダーが、所定のクライアント ID に対して事前に登録された RP のオリジンと一致すること。 {% Aside 'warning' %} -OAuth または OpenID Connect でのドメイン検証はブラウザのリダイレクトに依存しているため、FedCM では、 `Referer` ヘッダー値が RP の登録済みオリジンと一致することを IdP サーバーがチェックすることが重要です。 +OAuth または OpenID Connect でのドメイン検証はブラウザのリダイレクトに依存しているため、FedCM では、 `Origin` ヘッダー値が RP の登録済みオリジンと一致することを IdP サーバーがチェックすることが重要です。 {% endAside %} From c74f0cfa0b3588ab82509cb56cc53f8805a32f92 Mon Sep 17 00:00:00 2001 From: Alexandra White <alexandrawhite@google.com> Date: Mon, 9 Oct 2023 08:24:38 -0400 Subject: [PATCH 867/982] Update DevTools Overview panel images (#7445) * Updated image * upd img --------- Co-authored-by: Sofia Emelianova <42939855+sofiayem@users.noreply.github.com> --- site/en/docs/devtools/overview/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/en/docs/devtools/overview/index.md b/site/en/docs/devtools/overview/index.md index 43bd841ec..391b81344 100644 --- a/site/en/docs/devtools/overview/index.md +++ b/site/en/docs/devtools/overview/index.md @@ -146,7 +146,7 @@ Find ways to improve load and runtime performance. ### Application panel {: #application } -{% Img src="image/BrQidfK9jaQyIHwdw91aVpkPiib2/zVZBef8kCIP6uEm9em9y.png", alt="Application Panel", width="800", height="500" %} +{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/Mt5cwUg90P4CkF8i3w3V.png", alt="The Application panel with the Service workers section opened.", width="800", height="630" %} Inspect all resources that are loaded, including IndexedDB or Web SQL databases, local and session storage, cookies, Application Cache, images, fonts, and stylesheets. From 2d5a56ac9f6b8a66ab24698daecabd18afc1d2c6 Mon Sep 17 00:00:00 2001 From: Thomas Steiner <steiner.thomas@gmail.com> Date: Mon, 9 Oct 2023 14:31:50 +0200 Subject: [PATCH 868/982] Add file locking article (#7476) * Add article * Lint * Update site/en/blog/new-dev-trial-for-multiple-readers-and-writers/index.md --- .../index.md | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 site/en/blog/new-dev-trial-for-multiple-readers-and-writers/index.md diff --git a/site/en/blog/new-dev-trial-for-multiple-readers-and-writers/index.md b/site/en/blog/new-dev-trial-for-multiple-readers-and-writers/index.md new file mode 100644 index 000000000..cefba6a2c --- /dev/null +++ b/site/en/blog/new-dev-trial-for-multiple-readers-and-writers/index.md @@ -0,0 +1,53 @@ +--- +layout: 'layouts/blog-post.njk' +title: API Improvements for working with files in the browser +subhead: > + New dev trial for multiple readers and writers for FileSystemSyncAccessHandle and exclusive writer for FileSystemWritableFileStream. +date: 2023-10-09 +updated: 2023-10-09 +authors: + - thomassteiner +tags: + - capabilities +--- + +## Multiple readers and writers for FileSystemSyncAccessHandle + +The [origin private file system](https://web.dev/opfs) (sometimes also referred to as the bucket file system) allows developers to access files that are optimized for maximum reading and writing performance. This happens via [`FileSystemSyncAccessHandle`](https://developer.mozilla.org/docs/Web/API/FileSystemSyncAccessHandle) objects. Currently, trying to open multiple `FileSystemSyncAccessHandle` objects for the same file entry fails with a `NoModificationAllowedError`. Since there are use cases where this constraint is limiting, the new origin trial introduces a new `mode` parameter for the [`FileSystemFileHandle.createSyncAccessHandle()`](https://developer.mozilla.org/docs/Web/API/FileSystemFileHandle/createSyncAccessHandle) method with the following allowed string values: + +- `"readwrite"`: This is the current default. Once open, any methods on `FileSystemSyncAccessHandle` are allowed. Only one instance of `FileSystemSyncAccessHandle` is allowed. +- `"read-only"` : Allows multiple readers. Once open, only read-like methods on `FileSystemSyncAccessHandle` are allowed: `read()`, `getSize()`, and `close()`. Multiple instances of `FileSystemSyncAccessHandle` may be created as long as all of them are in read-only mode. +- `"readwrite-unsafe"`: Allows multiple writers. Once open, any methods on `FileSystemSyncAccessHandle` are allowed. Multiple instances of `FileSystemSyncAccessHandle` may be created as long as all of them are in readwrite-unsafe mode. + +The current behavior is preserved by keeping the `"readwrite"` option as the default, which only allows one instance at a time. If a site needs to open multiple `FileSystemSyncAccessHandle` objects but does not need to perform writes, then the `"read-only"` option should be used. Finally, the last option `"readwrite-unsafe"` allows multiple instances as well as both read and write. In this case, writes can be racy if performed from multiple tabs, and sites would need to provide their own locking scheme. + +```js +const handle1 = await handle.createSyncAccessHandle({mode: 'readwrite-unsafe'}); +// This will succeed: +const handle2 = await handle.createSyncAccessHandle({mode: 'readwrite-unsafe'}); +``` + +## Exclusive writer for FileSystemWritableFileStream + +Unlike with `FileSystemSyncAccessHandle`, multiple instances of [`FileSystemWritableFileStream`](https://developer.mozilla.org/docs/Web/API/FileSystemWritableFileStream) can be created per file entry today. What's missing is a way to provide an option for an exclusive writer. The new dev trial adds an optional `mode` parameter to the [`FileSystemAccessFileHandle.createWritable()`](https://developer.mozilla.org/docs/Web/API/FileSystemFileHandle/createWritable) method that has the following values: + +- `"exclusive"` mode: Only one writer can exist at a time. +- `"siloed"` mode: This is the current default. Each created writer will have its own swap file. + +```js +const writable1 = await handle.createWritable({mode: 'exclusive'}); +// This will fail: +const writable2 = await handle.createWritable(); +``` + +## Enter the dev trial + +To enter the dev trial, set the `#file-system-access-locking-scheme` flag in `chrome://flags` to **Enabled**. This will allow you to test the feature locally on your machine. + +## Providing feedback + +Please let us know what you think, especially if the proposed designs for both features do not work for you. The best way is by [filing a new Issue](https://github.com/whatwg/fs/issues) on the File System Standard repository on GitHub. + +## Acknowledgements + +This article was reviewed by [Daseul Lee](https://www.linkedin.com/in/daseul-lee-8297314b), [Nathan Memmott](https://www.linkedin.com/in/nathan-memmott/), and [Rachel Andrew](https://rachelandrew.co.uk/). From 4558b8aa9378310abfac273b0a0d25de21b4b2d7 Mon Sep 17 00:00:00 2001 From: Bramus <bramus@bram.us> Date: Mon, 9 Oct 2023 14:53:24 +0200 Subject: [PATCH 869/982] Scope article: Fix className (#7475) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It’s `card__content`, not `content` --- site/en/articles/at-scope/index.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/site/en/articles/at-scope/index.md b/site/en/articles/at-scope/index.md index a2746a2e6..05d97cf83 100644 --- a/site/en/articles/at-scope/index.md +++ b/site/en/articles/at-scope/index.md @@ -63,14 +63,14 @@ The scoped style rule `img { … }` can effectively only select `<img>` elements To prevent the `<img>` elements inside the card’s content area (`.card__content`) from being selected you could make the `img` selector more specific. Another way to do this is to use the fact that the `@scope` at-rule also accepts a _scoping limit_ which determines the lower boundary. ```css -@scope (.card) to (.content) { +@scope (.card) to (.card__content) { img { border-color: green; } } ``` -This scoped style rule only targets `<img>` elements that are placed between `.card` and `.content` elements in the ancestor tree. This type of scoping–with an upper and lower boundary–is often referred to as a _donut scope_ +This scoped style rule only targets `<img>` elements that are placed between `.card` and `.card__content` elements in the ancestor tree. This type of scoping–with an upper and lower boundary–is often referred to as a _donut scope_ {% Codepen { user: 'web-dot-dev', From e88f93b663ff150d4ec2b1b12f5585cdc435cd98 Mon Sep 17 00:00:00 2001 From: Joe Medley <jmedley@google.com> Date: Mon, 9 Oct 2023 06:39:28 -0700 Subject: [PATCH 870/982] Use standard heading grammer (#7458) Also makes the titles shorter. --- .../mv3/getstarted/development-basics/index.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/site/en/docs/extensions/mv3/getstarted/development-basics/index.md b/site/en/docs/extensions/mv3/getstarted/development-basics/index.md index c661ddc07..9a16b1640 100644 --- a/site/en/docs/extensions/mv3/getstarted/development-basics/index.md +++ b/site/en/docs/extensions/mv3/getstarted/development-basics/index.md @@ -61,7 +61,7 @@ For the popup, create a file named `hello.html`, and add the following code: The extension now displays a popup when the extension's action icon (toolbar icon) is clicked. Let's test it in Chrome by loading it locally. Ensure all files are saved. -## Loading an unpacked extension {: #load-unpacked } +## Load an unpacked extension {: #load-unpacked } To load an unpacked extension in developer mode: @@ -82,7 +82,7 @@ To load an unpacked extension in developer mode: Ta-da! The extension has been successfully installed. If no extension icons were included in the manifest, a generic icon will be created for the extension. -## Pinning the extension {: #pin } +## Pin the extension {: #pin } By default, when you load your extension locally, it will appear in the extensions menu {% Img src="image/BhuKGJaIeLNPW9ehns59NfwqKxF2/f5i7AgfauCfoQJxnn3kU.png", alt="Puzzle", width="24", @@ -107,7 +107,7 @@ alt="hello world extension", width="206", height="130", class="screenshot" %} </figcaption> </figure> -## Reloading the extension {: #reload } +## Reload the extension {: #reload } Let’s go back to the code and change the name of the extension to "Hello Extensions of the world!" in the manifest. @@ -142,7 +142,7 @@ Not all components need to be reloaded to see changes made, as shown in the foll {% endDetails %} -## Finding console logs and errors {: #logs } +## Find console logs and errors {: #logs } ### Console logs {: #console } @@ -206,14 +206,14 @@ alt="Extension error details", width="400", height="281", class="screenshot" %} To learn more about debugging the service worker, options page, and content scripts, see [Debugging extensions][doc-debug]. -## Structuring an extension project {: #structure } +## Structure an extension project {: #structure } There are many ways to structure an extension project; however, you must place the manifest.json file in the extension's **root directory**. The following is a structure example: {% Img src="image/BhuKGJaIeLNPW9ehns59NfwqKxF2/hjccQNanPjTDpIajkhPU.png", alt="The contents of an extension folder: manifest.json, background.js, scripts folder, popup folder, and images folder.", width="700", height="468" %} -## Using TypeScript {: #types } +## Use TypeScript {: #types } If you are developing using a [code editor][mdn-ide] such as VSCode or Atom, you can use the npm package [chrome-types][npm-chrome-types] to take advantage of auto-completion for the [Chrome From 99e1ca1015ab6696db22f3fa651304c412f379b0 Mon Sep 17 00:00:00 2001 From: Joe Medley <jmedley@google.com> Date: Mon, 9 Oct 2023 06:40:04 -0700 Subject: [PATCH 871/982] Make this tutorial consistent with others. (#7459) --- site/en/docs/extensions/mv3/getstarted/tut-tabs-manager/index.md | 1 + 1 file changed, 1 insertion(+) diff --git a/site/en/docs/extensions/mv3/getstarted/tut-tabs-manager/index.md b/site/en/docs/extensions/mv3/getstarted/tut-tabs-manager/index.md index fa7384dfb..b945ae766 100644 --- a/site/en/docs/extensions/mv3/getstarted/tut-tabs-manager/index.md +++ b/site/en/docs/extensions/mv3/getstarted/tut-tabs-manager/index.md @@ -1,6 +1,7 @@ --- layout: 'layouts/doc-post.njk' title: 'Manage tabs' +seoTitle: 'Chrome Extensions Tutorial: Manage tabs' subhead: 'Build your first tabs manager.' description: 'Learn how to programmatically organize tabs using tab groups.' date: 2022-10-04 From 9263d1ce42b62c5658ae0a227b67c08b31159cb7 Mon Sep 17 00:00:00 2001 From: Thomas Steiner <steiner.thomas@gmail.com> Date: Mon, 9 Oct 2023 17:41:45 +0200 Subject: [PATCH 872/982] [Chrome beta 119] Add OT link (#7477) * Add OT link * Lint --- site/en/blog/chrome-119-beta/index.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/site/en/blog/chrome-119-beta/index.md b/site/en/blog/chrome-119-beta/index.md index 96cbc7399..b5795c3fa 100644 --- a/site/en/blog/chrome-119-beta/index.md +++ b/site/en/blog/chrome-119-beta/index.md @@ -128,7 +128,7 @@ In Chrome 119 you can opt into the following new [origin trial](/docs/web-platfo ### Open popups as fullscreen windows -This feature adds a `fullscreen` windowFeatures parameter to the `window.open()` JavaScript API. This allows the caller to open a popup directly to full-screen on the display that would contain the popup (based on screenX and screenY). This eliminates the need for the developer to manually transition a popup into full-screen, which could require a new user activation signal. +This [new origin trial](/origintrials/#/view_trial/106960491150049281) adds a `fullscreen` windowFeatures parameter to the `window.open()` JavaScript API. This allows the caller to open a popup directly to full-screen on the display that would contain the popup (based on screenX and screenY). This eliminates the need for the developer to manually transition a popup into full-screen, which could require a new user activation signal. ## Deprecations and removals @@ -138,7 +138,7 @@ This release of Chrome removes four features. ### Remove Web SQL -We previously announced the [deprecation and removal of WebSQL](/blog/deprecating-web-sql/). The feature is fully removed as of Chrome 119. [A reverse origin trial](/origintrials/#/view_trial/494270059103911937) allows developers to continue to use WebSQL until Chrome 123. +We previously announced the [deprecation and removal of Web SQL](/blog/deprecating-web-sql/). The feature is fully removed as of Chrome 119. [A reverse origin trial](/origintrials/#/view_trial/494270059103911937) allows developers to continue to use WebSQL until Chrome 123. ### Remove Sanitizer API From 5e07a800a207341ce29b1b2669fc96278604b93b Mon Sep 17 00:00:00 2001 From: Oliver Dunk <oliverdunk@google.com> Date: Tue, 10 Oct 2023 02:28:03 +0100 Subject: [PATCH 873/982] Add Storage and Cookies doc to What's New (#7423) * Add Storage and Cookies doc to What's New * Update site/en/docs/extensions/whatsnew/index.md Co-authored-by: Joe Medley <jmedley@google.com> * Update site/en/docs/extensions/whatsnew/index.md Co-authored-by: Joe Medley <jmedley@google.com> * Update site/en/docs/extensions/whatsnew/index.md Co-authored-by: Joe Medley <jmedley@google.com> * Address feedback * Update site/en/docs/extensions/whatsnew/index.md Co-authored-by: Joe Medley <jmedley@google.com> * Update site/en/docs/extensions/whatsnew/index.md Co-authored-by: Joe Medley <jmedley@google.com> * Update site/en/docs/extensions/whatsnew/index.md --------- Co-authored-by: Joe Medley <jmedley@google.com> --- site/en/docs/extensions/whatsnew/index.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/site/en/docs/extensions/whatsnew/index.md b/site/en/docs/extensions/whatsnew/index.md index 9411057b2..d5e62be6d 100644 --- a/site/en/docs/extensions/whatsnew/index.md +++ b/site/en/docs/extensions/whatsnew/index.md @@ -3,7 +3,7 @@ layout: 'layouts/doc-post.njk' title: What's new in Chrome extensions description: 'Recent changes to the Chrome extensions platform, documentation, and policy' date: 2021-02-25 -updated: 2023-09-29 +updated: 2023-10-09 tags: - extensions-news @@ -15,6 +15,15 @@ tags: Check this page often to learn about changes to Chrome extensions, extensions documentation, or related policy or other changes. You'll find other notices posted on the [Extensions Google Group](https://groups.google.com/a/chromium.org/g/chromium-extensions). The [Extensions News](/tags/extensions-news/) tag lists articles about some of the topics listed here. (It even has [an RSS feed](/feeds/extensions-news.xml).) The [Chrome schedule](https://chromiumdash.appspot.com/schedule) lists stable and beta release dates. +### Documentation on cookies and web storage APIs {: #storage-and-cookies-guide } + +<p class="color-secondary-text type--caption">Posted on <time>October 9, 2023</time></p> + +We published a new guide on [how cookies and web storage APIs work in Chrome extensions](/docs/extensions/mv3/storage-and-cookies/). +It includes details on cookie and storage partitioning changes in +[Privacy Sandbox](/docs/privacy-sandbox/), an ongoing project to deprecate third-party cookies +through the creation of a series of new web platform APIs, and details on how they work in extensions. + ### Extension samples now searchable {: #extension-samples-searchable } <p class="color-secondary-text type--caption">Posted on <time>September 29, 2023</time></p> From b33e408f2f94ec7f869a250ee21497a450c98290 Mon Sep 17 00:00:00 2001 From: Rowan Merewood <rowan@merewood.org> Date: Tue, 10 Oct 2023 10:41:22 +0100 Subject: [PATCH 874/982] Oct 2023 Chrome-facilitated testing updates (#7485) Chrome-facilitated testing details for Mode A/B populations --------- Co-authored-by: Anusmita <anusmitaray@google.com> --- .../privacy-sandbox/chrome-testing/index.md | 201 +++++++++++------- 1 file changed, 120 insertions(+), 81 deletions(-) diff --git a/site/en/docs/privacy-sandbox/chrome-testing/index.md b/site/en/docs/privacy-sandbox/chrome-testing/index.md index 783a5b94b..52e82a0d5 100644 --- a/site/en/docs/privacy-sandbox/chrome-testing/index.md +++ b/site/en/docs/privacy-sandbox/chrome-testing/index.md @@ -6,13 +6,13 @@ subhead: > description: > Test your sites with third-party cookies disabled. date: 2023-05-18 -updated: 2023-09-01 +updated: 2023-10-09 authors: - alexandrawhite - rowan_m --- -To prepare for third-party cookie deprecation, we will be providing Chrome-facilitated testing modes that allow sites to preview how site behavior and functionality works without third-party cookies. This post provides an overview of the testing modes Chrome plans to provide and how to access experiment group labels. +To prepare for third-party cookie deprecation, we will be providing Chrome-facilitated testing modes that allow sites to preview how site behavior and functionality works without third-party cookies. This guide provides an overview of the testing modes Chrome plans to provide and how to access experiment group labels. {% Aside %} @@ -20,18 +20,14 @@ This testing focuses on measuring the performance of the Privacy Sandbox relevan {% endAside %} -We have worked with the CMA to ensure these testing modes align with the -testing framework (and timeline) for third parties laid out in its -[guidance on industry testing](https://www.gov.uk/cma-cases/investigation-into-googles-privacy-sandbox-browser-changes#industry-testing). -As a result, the CMA anticipates that the results from testing in these modes -can be used in its assessment of the Privacy Sandbox. +We will offer two distinct modes: -We plan to have two modes of Chrome-facilitated testing: +* **Mode A:** In Q4 2023 organizations testing the PS R&M APIs can opt in to receive consistent labels on a subset of Chrome browsers to allow for coordinated testing across different testers. +* **Mode B:** In Q1 2024 Chrome will globally disable third-party cookies for a portion of Chrome browsers. -* **Mode A**: Ad techs can receive control and experiment labels on a portion - of traffic and use these to conduct testing and experiments. -* **Mode B**: Chrome globally disables third-party cookies for some portion of - all Chrome users. +Both modes will continue through to at least Q2 2024. Where third-party cookies are disabled in Mode B, they will remain disabled through the full phase out of third-party cookies. + +We have worked with the [CMA](https://www.gov.uk/government/organisations/competition-and-markets-authority) to ensure that these testing modes align with the testing framework (and timeline) for third parties as laid out in its [guidance on industry testing](https://www.gov.uk/cma-cases/investigation-into-googles-privacy-sandbox-browser-changes#industry-testing). As a result, the CMA anticipates that the results from testing in these modes can be used in its assessment of the Privacy Sandbox. {% Aside %} @@ -39,82 +35,131 @@ Labels will be available via the temporary cookie-deprecation value which can be {% endAside %} -Some of the precise details of the composition and size of the groups within the modes are not final, however they will be in line with the treatment and control groups defined in the CMA’s testing guidance and we will publish further implementation guidance in Q3 2023. The current proposals are as follows. - -## Mode A: Opt-in testing {: #mode-a } - -Ad techs will be able to receive labels for experimental treatment and control groups for a portion of Chrome -traffic. An ad tech can choose to coordinate with other ad techs, for example, -to run [Protected Audience](/docs/privacy-sandbox/protected-audience/) auctions without -third-party cookies for a consistent experiment group. Ad techs can also use -these labels for their own independent experiments and testing. - -Chrome will not modify the state of third-party cookies for users in Mode A. -Chrome only provides the labels, as to ensure that ad techs can experiment with -consistent control and experiment groups. This means that a publisher's site -could still receive third-party cookie data for the publisher's own usage, even -if their ad tech partners are participating in the experiment. - -We expect this to allow for meaningful experimentation, where all involved -sites and services can coordinate to ensure third-party cookies are not used at -any point within the process. We anticipate providing labels for up to 9% of -Chrome browsers. We -encourage anyone interested in testing to provide -[feedback](https://github.com/GoogleChromeLabs/privacy-sandbox-dev-support/issues) -from the ecosystem on the method for accessing labels and the granularity of -labels. +We will also be sending this proposal through the usual [Blink development process](/docs/privacy-sandbox/proposal-lifecycle/), where the technical design and the Chrome release milestone will be finalized. While this is the implementation we would like to ship, additional discussion and approval means these details are still subject to change. We will continue to update this page as the plans progress, and you can continue to [provide feedback or questions](#feedback). + + +## Mode A: Labeled browser groups {: #mode-a } + +Organizations participating in testing will be able to opt in to receiving a persistent set of labels for a subset of Chrome browsers, allowing for coordinated experiments across different ad techs on the same set of browsers. If a browser falls into the `label_only_3` group (as shown in the following table) then all participating ad techs would be able to see the same `label_only_3` label and coordinate accordingly, i.e. use the PS R&M APIs, but refrain from using third-party cookies. We expect participants in the page to ensure labels are forwarded to other participants to allow for a consistent experiment across the entire process. + +For example, this allows multiple participants to run [Protected Audience](/docs/privacy-sandbox/fledge/) auctions without third-party cookies across a consistent group of browsers. The auction seller participants would forward the observed label to buyers to facilitate coordinated testing. + +The labels do not affect any functionality in those instances of Chrome, including the availability of third-party cookies. The labels provide the grouping for independent, coordinated experiments, but it's down to the participating parties to enforce the relevant parameters for the experiment. If you're testing the effect of removing third-party cookies, then each participant is responsible for excluding third-party cookie data for browsers with that label. + +The aim is to have groups that are representative of normal Chrome traffic. That means both third-party cookies and the PS R&M APIs should be available, though some portion of users may have changed or disabled functionality via settings or extensions. + +Labels will generally be persistent throughout browsing, and across Chrome sessions, however this is not guaranteed as there are rare scenarios where entirely resetting the browser may also reset the current label. + +We are planning to use 8.5% of Chrome Stable browsers for Mode A, and our initial proposal divides that population into nine groups. The smaller subgroups are intended to allow ad techs flexibility in combining labels to create their own experiments of varying sizes. Groups do not overlap. + +Note that the `control_1.*` labels are intended to be used as "Control 1" as outlined in the CMA’s [guidance on industry testing](https://www.gov.uk/cma-cases/investigation-into-googles-privacy-sandbox-browser-changes#industry-testing), so testing participants should not use Topics API or run Protected Audiences auctions for this traffic. As the labels do not affect functionality, participants should not pass observed topics or run Protected Audience auctions when they detect the `control_1.*` group labels. + +We welcome [feedback](#feedback) as to whether this selection of groups meets the needs of participating organizations. + +<table> + <tr> + <th scope="col" style="text-align: left;">Label</th> + <th scope="col" style="text-align: left;">% of Stable traffic</th> + </tr> + <tr> + <td><code>control_1.1</code></td> + <td style="font-variant-numeric: tabular-nums;">0.25</td> + </tr> + <tr> + <td><code>control_1.2</code></td> + <td style="font-variant-numeric: tabular-nums;">0.25</td> + </tr> + <tr> + <td><code>control_1.3</code></td> + <td style="font-variant-numeric: tabular-nums;">0.25</td> + </tr> + <tr> + <td><code>control_1.4</code></td> + <td style="font-variant-numeric: tabular-nums;">0.25</td> + </tr> + <tr> + <td><code>label_only_1</code></td> + <td style="font-variant-numeric: tabular-nums;">1.5</td> + </tr> + <tr> + <td><code>label_only_2</code></td> + <td style="font-variant-numeric: tabular-nums;">1.5</td> + </tr> + <tr> + <td><code>label_only_3</code></td> + <td style="font-variant-numeric: tabular-nums;">1.5</td> + </tr> + <tr> + <td><code>label_only_4</code></td> + <td style="font-variant-numeric: tabular-nums;">1.5</td> + </tr> + <tr> + <td><code>label_only_5</code></td> + <td style="font-variant-numeric: tabular-nums;">1.5</td> + </tr> +</table> + +We plan to make the labeled browser groups mode available starting in Q4 2023, and continue sending them through to the third-party cookie phase out in Q3 2024. -We plan to make the opt-in testing mode available starting in Q4 2023, and -we'll continue this mode until third-party cookie deprecation. ## Mode B: 1% third-party cookie deprecation {: #mode-b } -Chrome will deprecate third-party cookies for up to 1% of browsers. There is no -opt-in for this mode, as it will be applied globally. There is, of -course, the possibility that some site features may be impacted if the site -hasn't yet adopted an alternative solution, such as -[CHIPS](/docs/privacy-sandbox/chips/) or -[Related Website Sets](/docs/privacy-sandbox/related-website-sets/). +We will disable third-party cookies for approximately 1% of Chrome Stable browsers at the beginning of Q1 2024 (and also in Dev, Canary, and Beta browsers during Q4 2023). Organizations testing the PS R&M APIs do not need to opt in for this mode, as it will be applied uniformly across the entire browser population. There is, of course, the possibility that some site features may be impacted if the site hasn't yet adopted an alternative solution, such as [CHIPS](/docs/privacy-sandbox/chips/) or [Related Website Sets](/docs/privacy-sandbox/first-party-sets/). {% Aside %} -If you rely on third-party cookie data for site functionality, read our -[guide to prepare for third-party cookie phase-out](/docs/privacy-sandbox/third-party-cookie-phase-out/) -to understand if CHIPS or Related Website Sets can address your needs. We've -launched a [public issue tracker](https://goo.gle/report-3pc-broken), where you -can report site issues resulting from third-party cookie deprecation. +If you rely on third-party cookie data for site functionality, read our [guide to prepare for third-party cookie phase-out](/docs/privacy-sandbox/third-party-cookie-phase-out/) to understand if CHIPS or Related Website Sets can address your needs. We've launched a [public issue tracker](https://goo.gle/report-3pc-broken), where you can report site issues resulting from third-party cookie deprecation. We're working on mitigations to detect, address, and proactively alert site owners of issues that impact user experience during this phase. {% endAside %} -We're working on mitigations to detect, address, and proactively alert site -owners of issues that impact user experience during this phase. +Additionally, we plan to provide a small fraction of traffic within Mode B that has PS R&M APIs disabled. Other APIs, such as Related Website Sets, CHIPS, and FedCM, will not be disabled. We anticipate that this combination will be helpful to establish a baseline of performance without third-party cookies or the PS R&M APIs. -Additionally, we plan to provide a small fraction of traffic within Mode B that also -has Privacy Sandbox relevance and measurement APIs disabled. Other APIs, like -Related Website Sets, CHIPS, FedCM, and so on, will not be disabled. We anticipate -that this combination will be helpful to establish a baseline of -performance without third-party cookies, and we're seeking -[feedback](https://github.com/GoogleChromeLabs/privacy-sandbox-dev-support/labels/chrome-testing) on -an appropriate fraction of traffic to devote to this subset of testing. +As part of Mode B we will also provide labels for the affected browsers. The labels will be available at the same time as the APIs are disabled. We're proposing to divide the population into three `treatment_1.*` groups where third-party cookies are disabled, but PS R&M APIs are available, and one `control_2` group where **both** third-party cookies and the PS R&M APIs are disabled. -We plan to deprecate 1% of third party cookies in Q1 2024, and we'll work -closely with the CMA before taking further steps to expand deprecation. +Mode A continues to run and these groups are distinct from the Mode A groups, as in a user will either be in Mode A, Mode B, or neither. Testing participants should use the `control_1.*` traffic as a control group representing the status quo with third party cookies. -## Accessing labels via the `Cookie-Deprecation` value {: #cookie-deprecation-value} +<table> + <tr> + <th scope="col" style="text-align: left;">Label</th> + <th scope="col" style="text-align: left;">% of Stable traffic</th> + </tr> + <tr> + <td><code>treatment_1.1</code></td> + <td style="font-variant-numeric: tabular-nums;">0.25</td> + </tr> + <tr> + <td><code>treatment_1.2</code></td> + <td style="font-variant-numeric: tabular-nums;">0.25</td> + </tr> + <tr> + <td><code>treatment_1.3</code></td> + <td style="font-variant-numeric: tabular-nums;">0.25</td> + </tr> + <tr> + <td><code>control_2</code></td> + <td style="font-variant-numeric: tabular-nums;">0.25</td> + </tr> +</table> -For the duration of Mode A and Mode B we will be introducing a temporary `Cookie-Deprecation` value accessible via an opt-in HTTP header and JavaScript API, which will provide the label for the browser's applicable Mode A or B experiment group (as defined by the percentages above), if it falls into one. We will remove this value when the experiment ends. +As with Mode A, the PS R&M APIs are not guaranteed to be available, as users can disable them from the Chrome **Privacy and security** settings. -Accessing labels involves accessing information stored on the user’s device. In some jurisdictions (for example, the EU and UK), we understand that this activity is analogous to the use of cookies and thus accessing labels likely requires end user consent. Before you begin requesting labels, we recommend that you seek legal advice as to whether this consent obligation applies to you. + +## Accessing labels via the Cookie-Deprecation value {: #cookie-deprecation-value} + +For the duration of Mode A and Mode B we will be introducing a temporary `Cookie-Deprecation` value accessible via an opt-in HTTP header and JavaScript AP, which willI provide the label for the browser's applicable Mode A or B experiment group (as defined by the percentages above), if it falls into one. We will remove this value when the experiment ends. + +Accessing labels involves accessing information stored on the user’s device. In some jurisdictions (e.g., the EU and UK), we understand that this activity is analogous to the use of cookies and thus accessing labels likely requires end user consent. Before you begin requesting labels, we recommend that you seek legal advice as to whether this consent obligation applies to you. {% Aside %} -As with all features we ship in Chromium, we will send an [Intent to Prototype as part of the Blink development process](/docs/privacy-sandbox/proposal-lifecycle/). The implementation details below are what we are proposing, but these **may change before we ship the feature** in Chrome Stable. We will continue to update this documentation and you can also follow the public discussion when the Intents are posted to the [blink-dev mailing list](https://groups.google.com/a/chromium.org/g/blink-dev). +As with all features we ship in Chromium, we have sent an [Intent to Prototype (I2P)](https://groups.google.com/a/chromium.org/g/blink-dev/c/8mlWTOcEzcA/) as part of [the Blink development process](/docs/privacy-sandbox/proposal-lifecycle/). The implementation details below are what we are proposing, but these **may change before we ship the feature** in Chrome Stable. We will continue to update this documentation and you can also follow the public discussion when the Intents are posted to the [blink-dev mailing list](https://groups.google.com/a/chromium.org/g/blink-dev). {% endAside %} -### Accessing the `Sec-Cookie-Deprecation` HTTP header -To receive the `Sec-Cookie-Deprecation` request header, the site must first set the `receive-cookie-deprecation` cookie. This cookie must use the <code>[Partitioned attribute](/docs/privacy-sandbox/chips/)</code>, which means that opt-in for receiving the header must be done per top-level site. +### Accessing the Sec-Cookie-Deprecation HTTP header {: #cookie-deprecation-header} + +To receive the Sec-`Cookie-Deprecation` request header, a site must first set the `receive-cookie-deprecation` cookie. This cookie must use the [`Partitioned` attribute](/docs/privacy-sandbox/chips/), which means that opt-in for receiving the header must be done per top-level site. For example, if `3p-example.site` wants to receive the `Sec-Cookie-Deprecation` header on its resources embedded on `example.com`, then `3p-example.site` must set the following cookie in that context. @@ -122,20 +167,21 @@ For example, if `3p-example.site` wants to receive the `Sec-Cookie-Deprecation` Set-Cookie: receive-cookie-deprecation=1; Secure; HttpOnly; Path=/; SameSite=None; Partitioned; ``` -The `Secure`, `HttpOnly`, `Path`, `SameSite`, and `Partitioned` cookie attributes are mandatory. The other attributes: `Domain`, `Expires`, and `Max-Age` may be set as best suits your needs. +The `Secure`, `HttpOnly`, `SameSite`, and `Partitioned` cookie attributes are mandatory. The other attributes: `Domain`, Path (though Path=/ is a good default), `Expires`, and `Max-Age` may be set as best suits your needs. Assuming the browser was in the `example_label_1 group`, subsequent requests which include this cookie would also include the `Sec-Cookie-Deprecation` header. + ```text Sec-Cookie-Deprecation: example_label_1 ``` If the browser is not part of a group, no header will be sent. -As labels are tied to the presence of the cookie, if the cookie is deleted, labels will also no longer be sent. As the `Partitioned` attribute is intended for continued use after third-party cookies are fully deprecated, this means `Partitioned` cookies may be set when third-party cookies are blocked. +Labels are tied to the presence of the cookie, so if the cookie is deleted, blocked entirely, or blocked for the specific site, then labels will not be sent. As the `Partitioned` attribute is intended for continued use after third-party cookies are fully deprecated, this means `Partitioned` cookies may be set when third-party cookies are blocked. -### Accessing the cookieDeprecationLabel JavaScript API +### Accessing the cookieDeprecationLabel JavaScript API {: #cookie-deprecation-js} The `Cookie-Deprecation` value can also be accessed via the `navigator.cookieDeprecationLabel.getValue()` JavaScript API. This will return a promise which resolves to a string containing the applicable group label. For example, if the browser was in the `example_label_1` group: @@ -150,13 +196,14 @@ if ('cookieDeprecationLabel' in navigator) { } ``` -If the browser is not part of a group, then the value will be `null`. +If the browser is not part of a group, the API will either not be available or the value will be an empty string, so ensure you do feature detection. -The JavaScript API may be called regardless of the presence of the `receive-cookie-deprecation` cookie. +The JavaScript API may be called regardless of the presence of the `receive-cookie-deprecation` cookie. However, if cookies are blocked completely or specifically for the site, the API will again either not be available or return an empty string. + +As with any client provided value, ensure that you sanitize and validate the value from the header or the JavaScript API before use. -## Feedback -Feedback from a diverse set of stakeholders across the web ecosystem is critical to the Privacy Sandbox initiative. The dedicated [feedback section](/docs/privacy-sandbox/feedback/) provides an overview of the existing public channels, where you can follow or contribute to discussion, along with a feedback form to ensure you can always reach the Chrome team directly. +## Feedback We use the ["chrome-testing"](https://github.com/GoogleChromeLabs/privacy-sandbox-dev-support/labels/chrome-testing) label in the developer support repo on GitHub to manage questions. We welcome your feedback and discussion on the initial questions: @@ -165,11 +212,3 @@ We use the ["chrome-testing"](https://github.com/GoogleChromeLabs/privacy-sandbo * [Use of Client Hints for Chrome-facilitated testing](https://github.com/GoogleChromeLabs/privacy-sandbox-dev-support/issues/114) You can also [raise new questions or discussions](https://github.com/GoogleChromeLabs/privacy-sandbox-dev-support/issues/new/choose) in the repo using the "Chrome-facilitated testing" template. - -{% Aside %} - -The [Competition and Markets Authority (CMA)](https://www.gov.uk/government/organisations/competition-and-markets-authority) has published their [guidance on testing Privacy Sandbox APIs](https://www.gov.uk/cma-cases/investigation-into-googles-privacy-sandbox-browser-changes#industry-testing) with relevant information on timelines, approaches to testing, and next steps. - -{% endAside %} - -If you're a developer, you can ask questions and join discussions in the [Privacy Sandbox Developer Support repository](https://github.com/GoogleChromeLabs/privacy-sandbox-dev-support) on GitHub. From 4fa4d2bc740bde21ccef308c8797085534901127 Mon Sep 17 00:00:00 2001 From: Rowan Merewood <rowan@merewood.org> Date: Tue, 10 Oct 2023 11:13:51 +0100 Subject: [PATCH 875/982] Update author entry for rowan_m (#7493) --- site/_data/i18n/authors.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/_data/i18n/authors.yaml b/site/_data/i18n/authors.yaml index 19e7e8a82..56a185973 100644 --- a/site/_data/i18n/authors.yaml +++ b/site/_data/i18n/authors.yaml @@ -692,7 +692,7 @@ rowan_m: title: en: 'Rowan Merewood' description: - en: 'Rowan is a Staff Developer Relations Engineer at Chrome.' + en: 'Developer Relations for Privacy Sandbox.' danielcheng: title: en: 'Daniel Cheng' From b8468a12a99074bd4a6fd3e374067b3425ab18fa Mon Sep 17 00:00:00 2001 From: Sofia Emelianova <42939855+sofiayem@users.noreply.github.com> Date: Tue, 10 Oct 2023 11:20:03 +0100 Subject: [PATCH 876/982] DevTools 118: @property, overrides, search, and workspace (#7337) * @property * overrides 1 * overrides * typo * search * workspace refresh * mention sources panes reorder --- site/en/docs/devtools/css/reference/index.md | 10 ++- site/en/docs/devtools/customize/index.md | 3 +- .../docs/devtools/network/reference/index.md | 3 + site/en/docs/devtools/overrides/index.md | 8 ++- site/en/docs/devtools/search/index.md | 7 +- site/en/docs/devtools/workspaces/index.md | 68 +++++++++---------- 6 files changed, 59 insertions(+), 40 deletions(-) diff --git a/site/en/docs/devtools/css/reference/index.md b/site/en/docs/devtools/css/reference/index.md index 53197cd06..b420900c4 100644 --- a/site/en/docs/devtools/css/reference/index.md +++ b/site/en/docs/devtools/css/reference/index.md @@ -6,7 +6,7 @@ authors: - jecelynyeen - sofiayem date: 2017-06-09 -updated: 2022-06-21 +updated: 2023-09-20 description: "Discover new workflows for viewing and changing CSS in Chrome DevTools." tags: - css @@ -127,6 +127,14 @@ Alternatively, scroll down the **Styles** pane and find sections named `Inherite {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/TuWZmbeQlHR6Qp6pUHVP.png", alt="View the Inherited from... section of the Styles pane.", width="800", height="361" %} +### View `@property` at-rules {: #property } + +The [`@property` CSS at-rule](https://web.dev/at-property/) lets you define [CSS custom properties](https://developer.mozilla.org/docs/Web/CSS/--*) explicitly and register them in a stylesheet without running any JavaScript. + +Hover over the name of such property in the **Styles** pane, to see a tooltip with the property's value, descriptors, and a link to its registration in the collapsible `@property` section at the bottom of the **Styles** pane. + +{% Video src="video/NJdAV9UgKuN8AhoaPBquL7giZQo1/vDfXTULIyNIJXVw6lKvf.mp4", width="800", height="511", autoplay="false", loop="true", muted="true", controls="true", class="screenshot" %} + ### View `@supports` at-rules {: #supports } The **Styles** pane shows you the `@supports` CSS at-rules if they are applied to an element. For example, inspect the following element: diff --git a/site/en/docs/devtools/customize/index.md b/site/en/docs/devtools/customize/index.md index 6ab0f9d0b..d47ef0a40 100644 --- a/site/en/docs/devtools/customize/index.md +++ b/site/en/docs/devtools/customize/index.md @@ -76,7 +76,8 @@ To toggle **Restore last dock position** with a keyboard shortcut, press: To change ordering, click and drag left or right any of the following: - Panels at the top of DevTools. -- Panes in the **Elements** panel such as **Styles**, **Computed**, or **Layout**. +- Panes in the **Elements** panel such as **Styles**, **Computed**, **Layout**, and others. +- Panes in the **Sources** panel such as **Page**, **Workspace**, **Overrides**, and others. - **Drawer** tabs at the bottom of DevTools. Additionally, you can [move panels and tabs up and down](/blog/new-in-devtools-87/#moveable-tools) to and from the **Drawer**. To do this, right-click the panel or tab and select **Move to top** or **Move to bottom** from the drop-down menu. diff --git a/site/en/docs/devtools/network/reference/index.md b/site/en/docs/devtools/network/reference/index.md index 53b2ceda0..3efd84a82 100644 --- a/site/en/docs/devtools/network/reference/index.md +++ b/site/en/docs/devtools/network/reference/index.md @@ -196,6 +196,7 @@ Below is a complete list of supported properties. to include multiple domains. For example, `*.com` displays resources from all domain names ending in `.com`. DevTools shows a populates the autocomplete drop-down menu with all of the domains it has encountered. +- `has-overrides`. Show requests that have overridden `content`, `headers`, any overrides (`yes`), or no overrides (`no`). You can add the corresponding [**Has overrides** column](#columns) to the request table. - `has-response-header`. Show the resources that contain the specified HTTP response header. DevTools populates the autocomplete drop-down with all of the response headers that it has encountered. @@ -365,6 +366,8 @@ displayed options have check marks next to them. {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/zgkV5JsQ7MDYgkWL889O.png", alt="Adding a column to the Requests table.", width="800", height="684" %} +You can add or remove the following additional columns: **Path**, URL, Method, Protocol, Scheme, Domain, Remote address, Remote address space, Initiator address space, Cookies, Set cookies, Priority, Connection ID, and Has overrides. + #### Add custom columns {: #custom-columns } To add a custom column to the **Requests** table: diff --git a/site/en/docs/devtools/overrides/index.md b/site/en/docs/devtools/overrides/index.md index 23f786695..150b01879 100644 --- a/site/en/docs/devtools/overrides/index.md +++ b/site/en/docs/devtools/overrides/index.md @@ -4,7 +4,7 @@ title: "Override web content and HTTP response headers locally" authors: - sofiayem date: 2023-04-12 -updated: 2023-08-21 +updated: 2023-09-20 description: "Use local overrides to mock remote resources and keep the changes you make in DevTools across page loads." tags: - prototype-fixes @@ -52,6 +52,8 @@ You can override web content or response headers right away in the **Network** p To temporarily disable local overrides or delete all the override files, navigate to **Sources** > **Overrides** and clear the {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/ZtDyFg7cjkxacORB3GQn.svg", alt="Empty checkbox.", width="24", height="24" %} **Enable Local Overrides** checkbox or click {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/mMGdymtMmpYX2j3PRSfa.svg", alt="Clear.", width="24", height="24" %} **Clear** respectively. +To delete a single override file or all overrides in a folder, right-click the file or folder in **Sources** > **Overrides**, select **Delete**, then click **OK** in the dialog. This action can't be undone and you will have to manually recreate the deleted overrides. + To quickly see all overrides, in the **Network** panel, right-click a request and select **Show all overrides**. DevTools will take you to **Sources** > **Overrides**. ## Override web content {: #make-changes } @@ -60,6 +62,10 @@ To override web content: 1. [Set up local overrides](#set-up). 1. Make changes to files and save them in DevTools. +{% Aside 'note' %} +You can't override [source-mapped](/docs/devtools/javascript/source-maps/) files. If you right-click a request in the **Network** panel and select **Override content** DevTools shows you a dialog that takes you to the original source files instead. +{% endAside %} + For example, you can edit [files in **Sources**](/docs/devtools/javascript/reference/#edit) or [CSS in **Elements** > **Styles**](/docs/devtools/css/reference/#change-declaration), unless the CSS lives in [HTML files](#limitations). DevTools saves the modified files, lists them in **Sources** > **Overrides**, and shows you the {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/s81rU6SgdmbseeBDGbPl.png", alt="Saved.", width="17", height="20" %} icon next to the overridden files in the relevant panels and panes: **Elements** > **Styles**, **Network**, and **Sources** > **Overrides**. diff --git a/site/en/docs/devtools/search/index.md b/site/en/docs/devtools/search/index.md index 4fe021e08..2bfb00c3b 100644 --- a/site/en/docs/devtools/search/index.md +++ b/site/en/docs/devtools/search/index.md @@ -28,9 +28,10 @@ You can open the **Search** tab in several ways. First, [open DevTools](/docs/de To search for text across all loaded resources, in the search bar on the **Search** tab, type your query and press <kbd>Enter</kbd>. -<figure> - {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/D3YatkHJm3NkOEPMcxzg.png", alt="Search results.", width="800", height="626" %} -</figure> +{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/JmJIkPCr8dHmTNJ9zP9Z.png", alt="Search results.", width="800", height="683" %} + +When DevTools finds several matches in a single line, the search results list all of them with the same line number. +Click a search result and DevTools opens the line in **Sources** and scrolls the match into view. To make your query case-sensitive, toggle the {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/egjnpBbgTvj6FDiIbfoc.png", alt="Match case.", width="25", height="20" %} **Match Case** button. diff --git a/site/en/docs/devtools/workspaces/index.md b/site/en/docs/devtools/workspaces/index.md index 2f94e07ff..e53e1c575 100644 --- a/site/en/docs/devtools/workspaces/index.md +++ b/site/en/docs/devtools/workspaces/index.md @@ -5,7 +5,7 @@ authors: - kaycebasques - sofiayem date: 2018-04-10 -updated: 2022-10-31 +updated: 2023-09-20 description: "Learn how to save changes made within DevTools to your source files." tags: - prototype-fixes @@ -53,12 +53,13 @@ maps][4]. The DevTools community works to support the capabilities provided by source maps across a [variety of frameworks and tools](/docs/devtools/javascript/source-maps/#use_a_supported_preprocessor). If you run into issues while using a workspace with your framework of choice, or you get it working -after some custom configuration, please [start a thread in the mailing list][5] or [ask a question +after some custom configuration, [start a thread in the mailing list][5] or [ask a question on Stack Overflow][6] to share your knowledge with the rest of the DevTools community. ## Related feature: Local Overrides {: #overrides } -[Local overrides][7] is another DevTools feature that is similar to workspace. Use local overrides +[Local overrides][7] is another DevTools feature that is similar to workspace. +Use local overrides to mock web content or request headers without waiting for backend changes or when you want to experiment with changes to a page, and you need to see those changes across page loads, but you don't care about mapping your changes to the page's source code. @@ -68,48 +69,47 @@ Complete this tutorial to get hands-on experience with a workspace. ### Set up the demo {: #demo } -1. [Open the demo][8]. In the bottom-left of the editor, click the button labelled **Tools**. -3. Under **Tools**, select **Import / Export** > **Download Project**. -4. Close the tab. -5. Unzip the source code and move the unzipped `app` directory to your desktop. For the rest of - this tutorial this directory will be referred to as `~/Desktop/app`. -6. Start a local web server in `~/Desktop/app`. Below is some sample code for starting up +1. Clone this [demo repository](https://github.com/sofiayem/devtools-workspace-demo) to some directory on your computer. For example, to `~/Desktop`. +1. Start a local web server in `~/Desktop/devtools-workspace-demo`. Below is some sample code for starting up `SimpleHTTPServer`, but you can use whatever server you prefer. ```bash - cd ~/Desktop/app + cd ~/Desktop/devtools-workspace-demo # If your Python version is 3.X # On Windows, try "python -m http.server" or "py -3 -m http.server" python3 -m http.server # If your Python version is 2.X python -m SimpleHTTPServer ``` - -7. Open a tab in Google Chrome and go to locally-hosted version of the site. You should be able to + For the rest of this tutorial this directory will be referred to as `/devtools-workspace-demo`. +1. Open a tab in Google Chrome and go to locally-hosted version of the site. You should be able to access it via a URL like `localhost:8000`. The exact [port number][9] may be different. - {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/gDXphnuEPJLv62W8MFri.png", alt="The locally-hosted demo page opened in Chrome.", width="800", height="486" %} + {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/l9G12rEKEiiD9b50TOnu.png", alt="The locally-hosted demo page opened in Chrome.", width="800", height="491" %} ### Set up DevTools {: #devtools } 1. [Open DevTools](/docs/devtools/open/) on the locally-hosted demo page. -2. Navigate to the **Sources** > **Filesystem** tab and click {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/YihNsXarRhDgEi9rOT4H.svg", alt="Add.", width="22", height="22" %} **Add folder to workspace**. +1. Navigate to **Sources** > **Workspace** and set up a workspace in the `devtools-workspace-demo` folder that you cloned. You can do that in several ways: + + - Drag and drop the folder into the **Editor** in **Sources**. + - Click the **select folder** link and select the folder. + - Click {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/YihNsXarRhDgEi9rOT4H.svg", alt="Add.", width="22", height="22" %} **Add folder** and select the folder. - {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/74PqTOnc9AsmZ5uc6tlJ.png", alt="The Filesystem tab.", width="800", height="494" %} + {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/bfZVMkr26xHrXzwcBvav.png", alt="The Sources > Workspace tab.", width="800", height="492" %} -5. Select the `~/Desktop/app` folder you downloaded and unpacked in the previous step. -6. In the prompt at the top, click **Allow** to give DevTools permission to read and write to the directory. +1. In the prompt at the top, click **Allow** to give DevTools permission to read and write to the directory. - {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/P46nSsDzgX5ypexrHf7h.png", alt="The Allow button in the prompt.", width="800", height="420" %} + {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/AUXgZ4Sqh9mBM41nVXkx.png", alt="The Allow button in the prompt.", width="800", height="492" %} -In the **Filesystem** tab, there is now a green dot next to `index.html`, `script.js`, and `styles.css`. These green dots mean that DevTools has established a mapping between the network resources of the page, and the files in `~/Desktop/app`. +In the **Workspace** tab, there is now a green dot next to `index.html`, `script.js`, and `styles.css`. These green dots mean that DevTools has established a mapping between the network resources of the page, and the files in `devtools-workspace-demo`. -{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/hIACerOOovvni75V55rt.png", alt="The Filesystem tab now shows a mapping between the local files and the network ones.", width="800", height="420" %} +{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/Vrm9DJM8rBmKhp992Nlg.png", alt="The Workspace tab now shows a mapping between the local files and the network ones.", width="800", height="492" %} ## Step 2: Save a CSS change to disk {: #css } -1. Open `~/Desktop/app/styles.css` in a text editor. Notice how the `color` property of `h1` +1. Open `/devtools-workspace-demo/styles.css` in a text editor. Notice how the `color` property of `h1` elements is set to `fuchsia`. {% Img src="image/admin/aYtE6OhxyFc6D6Ur0eXY.png", alt="Viewing styles.css in a text editor.", width="800", height="551" %} @@ -121,14 +121,14 @@ In the **Filesystem** tab, there is now a green dot next to `index.html`, `scrip 1. Click the `<h1>` element in the **DOM Tree**. 1. In the **Styles** pane, find the `h1 { color: fuchsia }` CSS rule and change the color to your favorite. In this example, the color is set to green. - {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/0x7L1W3PrlYbpoSB03Xx.png", alt="Setting the color property of the h1 element to green.", width="800", height="500" %} + {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/hcX5yGjSy71cuYDdXdkl.png", alt="Setting the color property of the h1 element to green.", width="800", height="545" %} - The green dot {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/juauf8mjfnBBWVxNsQnV.png", alt="The green dot.", width="22", height="28" %} next to `styles.css:1` in the **Styles** pane means that any change you make is mapped to `~/Desktop/app/styles.css`. + The green dot {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/juauf8mjfnBBWVxNsQnV.png", alt="The green dot.", width="22", height="28" %} next to `styles.css:1` in the **Styles** pane means that any change you make is mapped to `/devtools-workspace-demo/styles.css`. -5. Open `~/Desktop/app/styles.css` in a text editor again. The `color` property is now set to your +5. Open `/devtools-workspace-demo/styles.css` in a text editor again. The `color` property is now set to your favorite color. 6. {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/sX65QEDYhwBFHCM24BtV.svg", alt="Reload.", width="22", height="22" %} Reload the page. The color of the `<h1>` element is still set to your favorite color. This works - because when you made the change, DevTools saved the change to disk. And then, when you reloaded + because when you made the change and DevTools saved the change to disk. And then, when you reloaded the page, your local server served the modified copy of the file from disk. ## Step 3: Save an HTML change to disk {: #html } @@ -146,9 +146,9 @@ don't waste time later trying to figure out why it's not working. 2. Double click the text content of the `h1` element, which says `Workspaces Demo`, and replace it with `I ❤️ Cake`. - {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/CUzulgirliDxvZkOJ8Hb.png", alt="Attempting to change HTML from the DOM Tree of the Elements panel.", width="800", height="500" %} + {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/3bfthvibhivwCcXxpzWn.png", alt="Attempting to change HTML from the DOM Tree of the Elements panel.", width="800", height="545" %} -3. Open `~/Desktop/app/index.html` in a text editor. The change that you just made isn't there. +3. Open `/devtools-workspace-demo/index.html` in a text editor. The change that you just made isn't there. 4. {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/sX65QEDYhwBFHCM24BtV.svg", alt="Reload.", width="22", height="22" %} Reload the page. The page reverts to its original title. #### Optional: Why it doesn't work {: #why } @@ -183,9 +183,9 @@ If you want to save a change to the page's HTML, do it via the **Sources** panel 5. Press <kbd>Command</kbd>+<kbd>S</kbd> (Mac) or <kbd>Control</kbd>+<kbd>S</kbd> (Windows, Linux, ChromeOS) to save the change. 6. {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/sX65QEDYhwBFHCM24BtV.svg", alt="Reload.", width="22", height="22" %} Reload the page. The `<h1>` element is still displaying the new text. - {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/wuvTZyzSgykLYFcuiIjo.png", alt="Changing HTML from the Sources panel.", width="800", height="492" %} + {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/mT1pHymBAkdJDjK6pSBZ.png", alt="Changing HTML from the Sources panel.", width="800", height="416" %} -7. Open `~/Desktop/app/index.html`. The `<h1>` element contains the new text. +7. Open `/devtools-workspace-demo/index.html`. The `<h1>` element contains the new text. ## Step 4: Save a JavaScript change to disk {: #js } @@ -199,7 +199,7 @@ to your site. There's a way to have the **Sources** panel open alongside other p 3. Type `QS`, then select **Show Quick Source**. At the bottom of your DevTools window there is now a **Quick Source** tab. - {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/W7Y2Y4sENDGbMcrBXPIe.png", alt="Opening the Quick Source tab via Command Menu.", width="800", height="462" %} + {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/QrRbZtkRkyiMSAdj73Bd.png", alt="Opening the Quick Source tab via Command Menu.", width="800", height="481" %} The tab is displaying the contents of `index.html`, which is the last file you edited in the **Sources** panel. The **Quick Source** tab gives you the editor from the @@ -207,11 +207,11 @@ to your site. There's a way to have the **Sources** panel open alongside other p 4. Press <kbd>Command</kbd>+<kbd>P</kbd> (Mac) or <kbd>Control</kbd>+<kbd>P</kbd> (Windows, Linux, ChromeOS) to open the **Open File** dialog. -5. Type `script`, then select **app/script.js**. +5. Type `script`, then select **devtools-workspace-demo/script.js**. - {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/6fAqf85los5PkCG8mpKb.png", alt="Opening script.js via the Open File dialog.", width="800", height="561" %} + {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/wpiLwWgnLo3uUFlHnZqg.png", alt="Opening script.js via the Open File dialog.", width="800", height="508" %} -6. Notice the `Save Changes To Disk With Workspaces` link in the demo. It's styled regularly. +6. Notice the `Edit and save files in a workspace` link in the demo. It's styled regularly. 7. Add the following code to the bottom of **script.js** via the **Quick Source** tab. ```js @@ -221,7 +221,7 @@ to your site. There's a way to have the **Sources** panel open alongside other p 8. Press <kbd>Command</kbd>+<kbd>S</kbd> (Mac) or <kbd>Control</kbd>+<kbd>S</kbd> (Windows, Linux, ChromeOS) to save the change. 9. {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/sX65QEDYhwBFHCM24BtV.svg", alt="Reload.", width="22", height="22" %} Reload the page. The link on the page is now italic. -{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/gij4b7QfoipdLJI0uMXP.png", alt="The link on the page is now italic.", width="800", height="473" %} +{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/oc74syCBiABs0I2KFY6v.png", alt="The link on the page is now italic.", width="800", height="457" %} ## Next steps {: #next-steps } From abd6117118c041170d7912a332baf1ac2310fefb Mon Sep 17 00:00:00 2001 From: Sofia Emelianova <42939855+sofiayem@users.noreply.github.com> Date: Tue, 10 Oct 2023 11:20:27 +0100 Subject: [PATCH 877/982] prefers-reduced-transparency (#7383) --- .../devtools/rendering/emulate-css/index.md | 22 +++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/site/en/docs/devtools/rendering/emulate-css/index.md b/site/en/docs/devtools/rendering/emulate-css/index.md index 247863f88..c08e496bb 100644 --- a/site/en/docs/devtools/rendering/emulate-css/index.md +++ b/site/en/docs/devtools/rendering/emulate-css/index.md @@ -26,7 +26,7 @@ The [`prefers-color-scheme` CSS media feature][7] indicates if the user prefers To emulate this condition: 1. On the [prefers-color-scheme](https://web.dev/prefers-color-scheme/) page, [open the **Rendering** tab](/docs/devtools/rendering#open-rendering). -1. Under the **Emulate CSS media feature `prefers-color-scheme`**, select one of the following from the dropdown list: +1. Under the **Emulate CSS media feature `prefers-color-scheme`**, select one of the following from the drop-down list: - No emulation - `prefers-color-scheme:light` @@ -55,7 +55,7 @@ The [`forced-colors` CSS media feature][5] indicates if the user agent enabled a To emulate this condition: 1. [Open the **Rendering** tab](/docs/devtools/rendering#open-rendering). -1. Under the **Emulate CSS media feature `forced-colors`**, select one of the following from the dropdown list: +1. Under the **Emulate CSS media feature `forced-colors`**, select one of the following from the drop-down list: - No emulation - `forced-colors:active` @@ -72,7 +72,7 @@ The [`prefers-contrast` CSS media feature][6] indicates if the user requested th To emulate this condition: 1. [Open the **Rendering** tab](/docs/devtools/rendering#open-rendering). -1. Under the **Emulate CSS media feature `prefers-contrast`**, select one of the following from the dropdown list: +1. Under the **Emulate CSS media feature `prefers-contrast`**, select one of the following from the drop-down list: - No emulation - `prefers-contrast:more` @@ -89,6 +89,20 @@ To emulate this condition: 1. Under the **Emulate CSS media feature `prefers-reduced-motion`**, select `prefers-reduced-motion:reduce`. 1. Try scrolling again. +## Emulate CSS media feature `prefers-reduced-transparency` {: #reduced-transparency } + +The [`prefers-reduced-transparency` CSS media feature](https://developer.mozilla.org/docs/Web/CSS/@media/prefers-reduced-transparency) indicates if the user requested to reduce the transparent or translucent layer effects used on the device. + +The `prefers-reduced-transparency` feature is [available from Chrome 118](/blog/chrome-118-beta/#media-queries-prefers-reduced-transparency-feature) and lets you adapt web content to user-selected preference for reduced transparency in the OS, such as the **Reduce transparency** setting on macOS. + +To emulate this condition: + +1. [Open the **Rendering** tab](/docs/devtools/rendering#open-rendering). +1. Under the **Emulate CSS media feature `prefers-reduced-transparency`**, select `prefers-reduced-transparency: reduce`. +1. Check if your page displays correctly. + +{% Video src="video/NJdAV9UgKuN8AhoaPBquL7giZQo1/Xh60t9y0KnAIdwoUnbX5.mp4", autoplay="false", loop="true", muted="true", controls="true", class="screenshot", width="800", height="533" %} + ## Emulate CSS media feature `color-gamut` The [`color-gamut` CSS media feature][9] indicates which range of colors the user agent and the output device support. @@ -96,7 +110,7 @@ The [`color-gamut` CSS media feature][9] indicates which range of colors the use To emulate this condition: 1. [Open the **Rendering** tab](/docs/devtools/rendering#open-rendering). -1. Under the **Emulate CSS media feature `color-gamut`**, select one of the following from the dropdown list: +1. Under the **Emulate CSS media feature `color-gamut`**, select one of the following from the drop-down list: - No emulation - `color-gamut:srgb`—approximately [sRGB](https://en.wikipedia.org/wiki/SRGB) gamut or more From 5f9d6bd5d16d0ff8ec60b87f999a14ed50835bbc Mon Sep 17 00:00:00 2001 From: Barry Pollard <barrypollard@google.com> Date: Tue, 10 Oct 2023 15:21:16 +0100 Subject: [PATCH 878/982] October 2023 CrUX Release (for September data) (#7484) * October 2023 CrUX Release (for September data) * Final tweaks --- site/en/docs/crux/release-notes/index.md | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/site/en/docs/crux/release-notes/index.md b/site/en/docs/crux/release-notes/index.md index 46c8e083d..79d64df30 100644 --- a/site/en/docs/crux/release-notes/index.md +++ b/site/en/docs/crux/release-notes/index.md @@ -21,7 +21,7 @@ date: 2017-10-01 # Optional # Include an updated date when you update your post -updated: 2023-09-12 +updated: 2023-10-09 # Optional # How to add a new author @@ -43,6 +43,23 @@ The CrUX dataset on BigQuery is generally updated on the second Tuesday of every In the list below, we've curated some release notes for each monthly dataset. Subscribe to our [CrUX Announce](https://groups.google.com/a/chromium.org/forum/#!forum/chrome-ux-report-announce) mailing list or follow [@ChromeUXReport](https://twitter.com/ChromeUXReport) on Twitter for release Announcements. +## 202309 + +[Announcement](https://groups.google.com/a/chromium.org/g/chrome-ux-report-announce/c/w48sCWw8IfA) + +Publication date + : October 10, 2023 + +What's new + : - We're again seeing continual improvements across most of the metrics despite the fact that FCP and TTFB actually had slight downturns. This suggests that the [front end improvements to LCP mentioned last month](#202308) which were still rolling out during September, likely more than counter acted these downturns. + : - One thing not mentioned last month until we saw the impact, was that WordPress had [a number of improvements](https://make.wordpress.org/core/2023/08/07/wordpress-6-3-performance-improvements/) in the latest release, in particular [for LCP images](https://make.wordpress.org/core/2023/07/13/image-performance-enhancements-in-wordpress-6-3/). This looks to have resulted in a [measurable boost for WordPress sites compared to the web as a whole](https://lookerstudio.google.com/reporting/55bc8fad-44c2-4280-aa0b-5f3f0cd3d2be/page/M6ZPC?params=%7B%22df33%22:%22include%25EE%2580%25800%25EE%2580%2580IN%25EE%2580%2580ALL%22,%22df46%22:%22include%25EE%2580%25800%25EE%2580%2580IN%25EE%2580%2580mobile%22%7D) and, given it is used on about a third of the sites in the CrUX dataset, also would help explain the further improvement in LCP. + : - While on the subject of LCP, Chrome 117 had [a bug whereby LCP may have been incorrect for some SPA applications when observed via Web APIs](https://chromium.googlesource.com/chromium/src/+/refs/heads/main/docs/speed/metrics_changelog/2023_10_lcp.md). This bug did not affect CrUX, nor Google Search Console data which is fed from CrUX. It has been fixed for Chrome 118 which started rolling out last week. If you noticed a large increase in LCP in your RUM solutions then this may have been the reason why. + +Notable stats + : - 18,405,462 origins + : - 45.7% of origins have good [Core Web Vitals](https://web.dev/vitals/#core-web-vitals) + : - 42.1% of origins have good Core Web Vitals when [using INP in place of FID as will happen from March 2024](https://web.dev/inp-cwv/). + ## 202308 [Announcement](https://groups.google.com/a/chromium.org/g/chrome-ux-report-announce/c/CJT8_DbO9DU) From 98a36ab7b5069349a4a5a3456a95c6c72132aef3 Mon Sep 17 00:00:00 2001 From: Adriana Jara <32825533+tropicadri@users.noreply.github.com> Date: Tue, 10 Oct 2023 11:15:52 -0700 Subject: [PATCH 879/982] New in Chrome 118 posts (#7460) * New in Chrome 118 posts * New in Chrome 118 video * New in Chrome 118 temporary thumnail * Update site/en/blog/new-in-chrome-118/index.md Co-authored-by: Rachel Andrew <rachelandrew@google.com> * Update site/en/blog/new-in-chrome-118/index.md Co-authored-by: Rachel Andrew <rachelandrew@google.com> * Update site/en/blog/new-in-chrome-118/index.md Co-authored-by: Rachel Andrew <rachelandrew@google.com> * Update site/en/blog/new-in-chrome-118/index.md Co-authored-by: Rachel Andrew <rachelandrew@google.com> * Update site/es/blog/new-in-chrome-118/index.md Co-authored-by: Rachel Andrew <rachelandrew@google.com> * Update site/es/blog/new-in-chrome-118/index.md Co-authored-by: Rachel Andrew <rachelandrew@google.com> * Update site/es/blog/new-in-chrome-118/index.md Co-authored-by: Rachel Andrew <rachelandrew@google.com> * Update site/es/blog/new-in-chrome-118/index.md Co-authored-by: Rachel Andrew <rachelandrew@google.com> --------- Co-authored-by: Rachel Andrew <rachelandrew@google.com> --- site/en/blog/new-in-chrome-118/index.md | 238 +++++++++++++++++++++++ site/es/blog/new-in-chrome-118/index.md | 244 ++++++++++++++++++++++++ 2 files changed, 482 insertions(+) create mode 100644 site/en/blog/new-in-chrome-118/index.md create mode 100644 site/es/blog/new-in-chrome-118/index.md diff --git a/site/en/blog/new-in-chrome-118/index.md b/site/en/blog/new-in-chrome-118/index.md new file mode 100644 index 000000000..c7f2e56f7 --- /dev/null +++ b/site/en/blog/new-in-chrome-118/index.md @@ -0,0 +1,238 @@ +--- +title: New in Chrome 118 +description: > + Chrome 118 is rolling out now! Declare specific styles within a component with the @scope css rule. Use new media features: scripting and prefers-reduced-transparency. DevTools has improvements in the Sources panel and there's plenty more. +layout: 'layouts/blog-post.njk' +date: 2023-10-10 +authors: + - ajara +hero: 'image/SeARmcA1EicLXagFnVOe0ou9cqK2/My3ZVJzsSh1BmVasr2sZ.png' +alt: > + New in Chrome hero logo +tags: + - new-in-chrome + - chrome-118 +--- + +{% YouTube id='zx8OZtKe6hA' %} + +Here's what you need to know: + +* Declare specific styles within a component with the [`@scope` css rule](#css-scope). +* There are two new media features: [`scripting` and `prefers-reduced-transparency`](#new-media-queries). +* DevTools has improvements in the [**Sources** panel](#sources-panel-devtools). + +* And there's plenty [more](#more). + +I'm Adriana Jara. Let's dive in and see what's new for developers in Chrome 118. + +## CSS `@scope` rule. {: #css-scope} + +The `@scope` at-rule allows developers to scope style rules to a given scoping root, and style elements according to the proximity of that scoping root. + +With `@scope` you can override styles based on proximity, which is different from the usual CSS styles that are applied relying only on source order and specificity. In the following example, there are two themes. + +```html +<div class="lightpink-theme"> + <a href="#">I'm lightpink!</a> + <div class="pink-theme"> + <a href="#">Different pink!</a> + </div> +</div> +``` +without scope, the style applied is the last one declared. + +{% Compare 'worse', 'Without @scope' %} +```css +.pink-theme a { color: hotpink; } +.lightpink-theme a { color: lightpink; } +``` +{% endCompare %} + +{% Img src="image/SeARmcA1EicLXagFnVOe0ou9cqK2/N1ZbDIild8BHXJ3GjIey.jpg", alt="Two links, the first one reads ' I'm lightpink!' the second one reads 'Different pink', both links are actually light pink, under the links text reads sources order declaration style.", width="800", height="700" %} + +With scope you can have nested elements and the style that applies is the one for the nearest ancestor. + +{% Compare 'better', 'With @scope' %} +```css +@scope (.pink-theme) { + a { + color: hotpink; + } +} + +@scope (.lightpink-theme){ + a { + color: lightpink; + } +} +``` +{% endCompare %} + +{% Img src="image/SeARmcA1EicLXagFnVOe0ou9cqK2/9svylwmK9QHQJUgAMNkj.jpg", alt="Two links, the first one reads ''I''m lightpink!'' the second one reads 'Different pink', second link is a darker pink, under the links text nearest ancestor style and has a green checkmark next to it.", width="800", height="694" %} + +Scope also saves you from writing long, convoluted class names, and makes it easy to manage larger projects and avoid naming conflicts. + +{% Compare 'worse', 'Without @scope' %} +```html +<div class="first-container"> + <h1 class="first-container__main-title"> I'm the main title</h1> +</div> +<div class="second-container"> + <h1 class="second-container__main-title"> I'm the main title, but somewhere else</h1> +</div> +``` + +```css +.first-container__main-title { + color: grey; +} + +.second-container__main-title { + color: mediumturquoise; +} +``` +{% endCompare %} + + +{% Compare 'better', 'With @scope' %} +```html +<div class="first-container"> + <h1 class="main-title"> I'm the main title</h1> +</div> +<div class="second-container"> + <h1 class="main-title"> I'm the main title, but somewhere else</h1> +</div> +``` + +```css +@scope(.first-container){ + .main-title { + color: grey; + } +} +@scope(.second-container){ + .main-title { + color: mediumturquoise; + } +} +``` +{% endCompare %} + + +With scope you can also style a component without styling certain things that are nested within. In a way you can have “holes” where the scoped style doesn't apply. + +Like in the following example, we could apply style to the text and exclude controls or vice versa. + +{% Img src="image/SeARmcA1EicLXagFnVOe0ou9cqK2/2OcZt7BEhhMH2dW9earg.jpg", alt="representation of the html above, with the words in scope next to the first and third div and the word excluded next to the second and fourth div.", width="800", height="648" %} + +```html +<div class="component"> + <div class="purple"> + <h1>Drink water</h1> + <p class="purple">hydration is important</p> + </div> + <div class="click-here"> + <p>not in scope</p> + <button>click here</button> + </div> + + <div class="purple"> + <h1 class="purple">Exercise</h1> + <p class="purple">move it move it</p> + </div> + + <div class="link-here"> + <p>Excluded from scope</p> + <a href="#"> link here </a> + </div> +</div> +``` + +```css +@scope (.component) to (.click-here, .link-here) { + div { + color: purple; + text-align: center; + font-family: sans-serif; + } +} +``` + +Checkout the [`@scope` documentation](https://developer.mozilla.org/docs/Web/CSS/:scope) for more information. + +## `scripting` and `prefers-reduced-transparency` media features {: #new-media-queries } + +We use media queries to provide user experiences that adapt to the user's preferences and device conditions. This Chrome version adds two new values that can be used to adapt user experience: `scripting` and `prefers-reduced-transparency`. + +We may take for granted the presence of scripting when our users access the web, however scripting is not always enabled, now using the `scripting` media feature you can detect if scripting is available and apply particular styles for each case, the available values are: `enabled`,` initial-only` or `none` + +```css +@media (scripting: none) { + .script-none { + color: red; + } +} +``` + +Another value you can test with media queries is `prefers-reduced-transparency` which lets developers adapt web content to user-selected preference for reduced transparency in the OS, such as the Reduce transparency setting on macOS. Valid options are `reduce` or `no-preference`. + +```css +.translucent { + opacity: 0.4; +} + +@media (prefers-reduced-transparency) { + .translucent { + opacity: 0.8; + } +} +``` + +And, you can check how it looks with DevTools: + +{% Video src="video/NJdAV9UgKuN8AhoaPBquL7giZQo1/Xh60t9y0KnAIdwoUnbX5.mp4", autoplay="false", loop="true", muted="true", controls="true", class="screenshot", width="800", height="533" %} + +For more information checkout the [scripting](https://developer.mozilla.org/docs/Web/CSS/@media/scripting) and [prefers-reduced-transparency](https://developer.mozilla.org/docs/Web/CSS/@media/prefers-reduced-transparency) documentation. + +## Sources panel improvements in DevTools {: #sources-panel-devtools } + +DevTools has the following improvements in the **Sources** panel: the [workspace](/docs/devtools/workspaces/) feature improved consistency, most notably, by renaming the **Sources** > **Filesystem** pane to **Workspace** along with other UI text, the [**Sources** > **Workspace**](/docs/devtools/workspaces/) also lets you sync changes you make in DevTools directly to your source files. + +{% Video src="video/NJdAV9UgKuN8AhoaPBquL7giZQo1/1T78X6ldgLhiH6iJgAMk.mp4", width="800", height="436", autoplay="false", loop="true", muted="true", controls="true", class="screenshot" %} + +Also, you can now reorder panes on the left side of the **Sources** panel by dragging and dropping, and the **Sources** panel can now pretty-print inline JavaScript within the following script types: [`module`](https://developer.mozilla.org/docs/Web/JavaScript/Guide/Modules), [`importmap`](https://developer.mozilla.org/docs/Web/HTML/Element/script/type/importmap), [`speculationrules`](/blog/debugging-speculation-rules/) and highlight the syntax of `importmap` and `speculationrules` script types, both of which hold JSON. + +{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/yZYe1CF5ObuLu7zVjcot.png", alt="Before and after pretty-printing and syntax highlighting of speculation rules script type.", width="800", height="395" %} + +Checkout [What's New in DevTools](/blog/new-in-devtools-118/) for more on Chrome 118 DevTools updates. + +## And more! {: #more } + +Of course there's plenty more. + +* [WebUSB API](/articles/usb/) is now exposed to [Service Workers registered by browser extensions](docs/extensions/mv3/service_workers/) allowing developers to use the API when responding to extension events. + +* To help developers reduce friction in Payment Request flows, we are removing the user activation requirement in `Payment Request` and `Secure Payment Confirmation`. + +* [Chrome's release cycle is becoming shorter](/blog/faster-chrome-releases-round2/), stable versions will be released every three weeks, starting with Chrome 119 that will be here in three weeks. + +## Further reading + +This covers only some key highlights. Check the links below for +additional changes in Chrome 118. + +* [What's new in Chrome DevTools (118)](/blog/new-in-devtools-118/) +* [Chrome 118 deprecations and removals](/blog/deps-rems-118/) +* [ChromeStatus.com updates for Chrome 118](https://chromestatus.com/features#milestone%3D118) +* [Chromium source repository change list](https://chromium.googlesource.com/chromium/src/+log/116.0.5845.171..118.0.5938.57) +* [Chrome release calendar](https://chromiumdash.appspot.com/schedule) + +## Subscribe + +To stay up to date, [subscribe](https://goo.gl/6FP1a5) to the +[Chrome Developers YouTube channel](https://www.youtube.com/user/ChromeDevelopers/), +and you'll get an email notification whenever we launch a new video. + +Yo soy Adriana Jara, and as soon as Chrome 119 is released, I'll be right here to +tell you what's new in Chrome! \ No newline at end of file diff --git a/site/es/blog/new-in-chrome-118/index.md b/site/es/blog/new-in-chrome-118/index.md new file mode 100644 index 000000000..cca2f9bab --- /dev/null +++ b/site/es/blog/new-in-chrome-118/index.md @@ -0,0 +1,244 @@ +--- +title: Nuevo en Chrome +description: > + ¡Chrome 118 ya está disponible! Declara estilos específicos dentro de un componente con la regla css @scope. Utiliza nuevas funciones de medios: scripting y prefers-reduced-transparency. DevTools tiene mejoras en el panel Fuentes y mucho más. +layout: 'layouts/blog-post.njk' +date: 2023-10-10 +authors: + - ajara +hero: 'image/SeARmcA1EicLXagFnVOe0ou9cqK2/My3ZVJzsSh1BmVasr2sZ.png' +alt: > + New in Chrome hero logo +tags: + - new-in-chrome + - chrome-118 +--- + +{% YouTube id='zx8OZtKe6hA' %} + +Esto es lo que necesitas saber: + +* Declarar estilos específicos dentro de un componente con la [regla css `@scope`](#css-scope). +* Hay dos nuevas funciones de medios: [`scripting` y `prefers-reduced-transparency`](#new-media-queries). +* DevTools tiene mejoras en el [panel **Fuentes**](#sources-panel-devtools). + +* Y hay mucho [más](#more). + +Yo soy Adriana Jara. Profundicemos y veamos las novedades para los desarrolladores en Chrome 118. + +## Regla CSS `@scope`. {: #css-scope} + +La regla `@scope` te permite aplicar reglas de estilo a una raíz de` @scope` determinada y diseñar elementos de acuerdo con la proximidad de esa raíz de `@scope`. + +Con `@scope` puedes sobrescribir estilos basados ​​en la proximidad, lo cual es diferente de los estilos CSS habituales que se aplican basándose únicamente en el orden y la especificidad del origen. En el siguiente ejemplo, hay dos temas. + +```html +<div class="lightpink-theme"> + <a href="#">Soy rosado claro!</a> + <div class="pink-theme"> + <a href="#">Un rosado diferente!</a> + </div> +</div> +``` + +sin`@scope`, el estilo aplicado es el último declarado. + +{% Compare 'worse', 'Sin @scope' %} +```css +.pink-theme a { color: hotpink; } +.lightpink-theme a { color: lightpink; } +``` +{% endCompare %} + +{% Img src="image/SeARmcA1EicLXagFnVOe0ou9cqK2/N1ZbDIild8BHXJ3GjIey.jpg", alt="Dos enlaces, el primero dice '¡Soy rosa claro!', el segundo dice 'Rosa diferente', ambos enlaces son en realidad rosa claro, debajo del el texto del enlace lee las fuentes estilo aplicadas según el orden de declaración (en inglés).", width="800", height="700" %} + +Con `@scope` puedes tener elementos anidados y el estilo que se aplica es el del ancestro más cercano. + +{% Compare 'better', 'Con @scope' %} +```css +@scope (.pink-theme) { + a { + color: hotpink; + } +} + +@scope (.lightpink-theme){ + a { + color: lightpink; + } +} +``` +{% endCompare %} + +{% Img src="image/SeARmcA1EicLXagFnVOe0ou9cqK2/9svylwmK9QHQJUgAMNkj.jpg", alt="Dos enlaces, el primero dice '¡Soy rosa claro!', el segundo dice 'Rosa diferente', el segundo enlace es de un rosa más oscuro, debajo de los vinculos hay texto que dice con el estilo ancestro más cercano y tiene una marca de verificación verde al lado (en inglés).", width="800", height="694" %} + +Scope también le evita tener que escribir nombres de clases largos y complicados, y facilita la gestión de proyectos más grandes al evitar conflictos de nombres. + +{% Compare 'worse', 'Sin @scope' %} +```html +<div class="first-container"> + <h1 class="first-container__main-title"> I'm the main title</h1> +</div> +<div class="second-container"> + <h1 class="second-container__main-title"> I'm the main title, but somewhere else</h1> +</div> +``` + +```css +.first-container__main-title { + color: grey; +} + +.second-container__main-title { + color: mediumturquoise; +} +``` +{% endCompare %} + + + +{% Compare 'better', 'Con @scope' %} +```html +<div class="first-container"> + <h1 class="main-title"> I'm the main title</h1> +</div> +<div class="second-container"> + <h1 class="main-title"> I'm the main title, but somewhere else</h1> +</div> +``` + +```css +@scope(.first-container){ + .main-title { + color: grey; + } +} +@scope(.second-container){ + .main-title { + color: mediumturquoise; + } +} +``` +{% endCompare %} + + + +Con `@scope` también puedes diseñar un componente sin aplicar el estilo a ciertas cosas que están anidadas en su interior. En cierto modo, puede tener "agujeros" donde no se aplica el estilo del scope. + +Como en el siguiente ejemplo, podríamos aplicar estilo al texto y excluir controles o viceversa. + +{% Img src="image/SeARmcA1EicLXagFnVOe0ou9cqK2/2OcZt7BEhhMH2dW9earg.jpg", alt="representación del html anterior, con las palabras dentro del scope junto al primer y tercer div y la palabra excluida junto al segundo y cuarto div.", width="800", height="648" %} + +```html +<div class="component"> + <div class="purple"> + <h1>Drink water</h1> + <p class="purple">hydration is important</p> + </div> + <div class="click-here"> + <p>not in scope</p> + <button>click here</button> + </div> + + <div class="purple"> + <h1 class="purple">Exercise</h1> + <p class="purple">move it move it</p> + </div> + + <div class="link-here"> + <p>Excluded from scope</p> + <a href="#"> link here </a> + </div> +</div> +``` + +```css +@scope (.component) to (.click-here, .link-here) { + div { + color: purple; + text-align: center; + font-family: sans-serif; + } +} +``` + +Consulte la documentación de [`@scope`](https://developer.mozilla.org/docs/Web/CSS/:scope) para obtener más información. + +## Funciones de medios `scripting` y `prefers-reduced-transparency` {: #new-media-queries } + +Utilizamos consultas de medios (media queries) para proporcionar experiencias de usuario que se adapten a las preferencias del usuario y a las condiciones del dispositivo. Esta versión de Chrome agrega dos nuevos valores que se pueden usar para adaptar la experiencia del usuario: `scripting` y `prefers-reduced-transparency` + +Podemos dar por sentada la presencia de scripting cuando nuestros usuarios acceden a la web, sin embargo, el scripting no siempre está habilitado. Ahora, utilizando la función `scripting`, puedes detectar si las secuencias de comandos están disponibles y aplicar estilos particulares para cada caso, los valores disponibles son : `enabled`,` initial-only` o `none` + + +```css +@media (scripting: none) { + .script-none { + color: red; + } +} +``` + +Otro valor que puede probar con consultas de medios es "prefiere transparencia reducida", que permite a los desarrolladores adaptar el contenido web a las preferencias seleccionadas por el usuario para una transparencia reducida en el sistema operativo, como la configuración Reducir transparencia en macOS. Las opciones válidas son `reduce` o `no-preference`. + +```css +.translucent { + opacity: 0.4; +} + +@media (prefers-reduced-transparency) { + .translucent { + opacity: 0.8; + } +} +``` + +Y puedes comprobar cómo se ve con DevTools: + +{% Video src="video/NJdAV9UgKuN8AhoaPBquL7giZQo1/Xh60t9y0KnAIdwoUnbX5.mp4", autoplay="false", loop="true", muted="true", controls="true", class="screenshot", width="800", height="533" %} + +Para obtener más información, consulte la documentación de [scripting](https://developer.mozilla.org/docs/Web/CSS/@media/scripting) y [prefers-reduced-transparency](https://developer.mozilla.org/docs /Web/CSS/@media/prefers-reduced-transparency). + +## Mejoras en el panel de Fuentes en DevTools {: #sources-panel-devtools } + +DevTools tiene las siguientes mejoras en el panel **Fuentes**: la característica [espacio de trabajo (workspace)](/docs/devtools/workspaces/) mejoró la coherencia, en particular al cambiar el nombre del panel **Fuentes** > **Sistema de archivos** a **Espacio de trabajo(workspace)** junto con otros textos de la interfaz de usuario, [**Fuentes** > **Espacio de trabajo**](/docs/devtools/workspaces/) también le permite sincronizar los cambios que realiza en DevTools directamente con sus archivos fuente. + +{% Video src="video/NJdAV9UgKuN8AhoaPBquL7giZQo1/1T78X6ldgLhiH6iJgAMk.mp4", width="800", height="436", autoplay="false", loop="true", muted="true", controls="true", class="screenshot" %} + +Además, ahora puede reordenar los paneles en el lado izquierdo del panel **Fuentes** arrastrando y soltando, y el panel **Fuentes** ahora puede imprimir JavaScript en línea dentro de los siguientes tipos de secuencias de comandos: [`module`] (https://developer.mozilla.org/docs/Web/JavaScript/Guide/Modules), [`importmap`](https://developer.mozilla.org/docs/Web/HTML/Element/script/type/ importmap), [`speculationrules`](/blog/debugging-speculation-rules/) y resalta la sintaxis de los tipos de script `importmap` y `speculationrules`, los cuales contienen JSON. + + +{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/yZYe1CF5ObuLu7zVjcot.png", alt="Antes y después de la impresión bonita y resaltado de sintaxis del tipo de script de reglas de especulación. +", width="800", height="395" %} + +Consulte [Novedades de DevTools](/blog/new-in-devtools-118/) para obtener más información sobre las actualizaciones de Chrome 118 DevTools. + +## ¡Y más! {: #more } + +Por supuesto que hay mucho más. + +* [WebUSB API](/articles/usb/) ahora está expuesta a [Service Workers registrados por extensiones del navegador](/docs/extensions/mv3/service_workers/) lo que permite a los desarrolladores usar la API al responder a eventos de extensiones. + +* Para ayudar a los desarrolladores a reducir la fricción en los flujos de solicitudes de pago, estamos eliminando el requisito de activación del usuario en "Solicitud de pago" y "Confirmación de pago seguro". + +* [El ciclo de lanzamiento de Chrome se está acortando](/blog/faster-chrome-releases-round2/), las versiones estables se lanzarán cada tres semanas, comenzando con Chrome 119 que estará aquí en tres semanas. + +## Otras lecturas + +Esto cubre sólo algunos aspectos destacados clave. Consulte los enlaces a continuación para +cambios adicionales en Chrome 118. + +* [Novedades de Chrome DevTools (118)](/blog/new-in-devtools-118/) +* [Deprecations y eliminaciones de Chrome 118](/blog/deps-rems-118/) +* [Actualizaciones de ChromeStatus.com para Chrome 118](https://chromestatus.com/features#milestone%3D118) +* [Lista de cambios del repositorio fuente de Chromium](https://chromium.googlesource.com/chromium/src/+log/116.0.5845.171..118.0.5938.57) +* [Calendario de lanzamientos de Chrome](https://chromiumdash.appspot.com/schedule) + +## Suscríbete + +Para mantenerse actualizado, [suscríbase](https://goo.gl/6FP1a5) al +[Canal de YouTube para desarrolladores de Chrome](https://www.youtube.com/user/ChromeDevelopers/), +y recibirás una notificación por correo electrónico cada vez que lancemos un nuevo vídeo. + +Yo soy Adriana Jara, y tan pronto como se lance Chrome 119, estaré aquí para +contarles que hay de nuevo en Chrome! \ No newline at end of file From 4265a43bed727cefaccfae98ab624003812f4bf0 Mon Sep 17 00:00:00 2001 From: Sofia Emelianova <42939855+sofiayem@users.noreply.github.com> Date: Wed, 11 Oct 2023 09:52:10 +0100 Subject: [PATCH 880/982] What's new in DevTools 119 (#7492) * skeleton * property imrovements * device list * sources: pretty inline json * private fields in console * lighthouse * a11y and web sql deprecation * misc * minor * app > manifest > aspect ratio * add issue num * edits * minor edits * upd partials * upd hero and alt * upd previous hero and date --- site/en/_partials/devtools/whats-new.md | 14 ++ site/en/blog/new-in-devtools-118/index.md | 2 +- site/en/blog/new-in-devtools-119/index.md | 151 ++++++++++++++++++++++ 3 files changed, 166 insertions(+), 1 deletion(-) create mode 100644 site/en/blog/new-in-devtools-119/index.md diff --git a/site/en/_partials/devtools/whats-new.md b/site/en/_partials/devtools/whats-new.md index 3d26011f0..921963d72 100644 --- a/site/en/_partials/devtools/whats-new.md +++ b/site/en/_partials/devtools/whats-new.md @@ -4,6 +4,20 @@ A list of everything that has been covered in the [What's New In DevTools](/tags {# $content #} +### Chrome 119 {: #chrome119 } + +* [Improved @property section in Elements > Styles](/blog/new-in-devtools-119/#css) +* [Editable @property rule](/blog/new-in-devtools-119/#edit-property) +* [Issues with invalid @property rules are reported](/blog/new-in-devtools-119/#property-issues) +* [Updated list of devices to emulate](/blog/new-in-devtools-119/#devices) +* [Pretty-print inline JSON in script tags in Sources](/blog/new-in-devtools-119/#sources) +* [Autocomplete private fields in Console](/blog/new-in-devtools-119/#autocomplete-console) +* [Lighthouse 11.1.0](/blog/new-in-devtools-119/#lighthouse) +* [Accessibility improvements](/blog/new-in-devtools-119/#accessibility) +* [Web SQL deprecation](/blog/new-in-devtools-119/#web-sql) +* [Screenshot aspect ratio validation in Application > Manifest](/blog/new-in-devtools-119/#manifest-aspect-ratio) +* [Miscellaneous highlights](/blog/new-in-devtools-119/#misc) + ### Chrome 118 {: #chrome118 } * [New section for custom properties in Elements > Styles](/blog/new-in-devtools-118/#css) diff --git a/site/en/blog/new-in-devtools-118/index.md b/site/en/blog/new-in-devtools-118/index.md index 200ea17e5..33110ce5f 100644 --- a/site/en/blog/new-in-devtools-118/index.md +++ b/site/en/blog/new-in-devtools-118/index.md @@ -5,7 +5,7 @@ authors: - sofiayem date: 2023-09-15 description: "New section for custom properties in Elements > Styles, more local overrides improvements, enhanced search, streamlined workspace in Sources, and more." -hero: 'image/NJdAV9UgKuN8AhoaPBquL7giZQo1/r8TZKv9wtqFJvjYbyBeb.png' +hero: 'image/NJdAV9UgKuN8AhoaPBquL7giZQo1/U10xEiELqdXKVetm7feV.png' alt: 'New section for custom properties in Elements > Styles, more local overrides improvements, enhanced search, streamlined workspace in Sources, and more.' tags: - new-in-devtools diff --git a/site/en/blog/new-in-devtools-119/index.md b/site/en/blog/new-in-devtools-119/index.md new file mode 100644 index 000000000..6a60be1d7 --- /dev/null +++ b/site/en/blog/new-in-devtools-119/index.md @@ -0,0 +1,151 @@ +--- +layout: 'layouts/blog-post.njk' +title: "What's New in DevTools (Chrome 119)" +authors: + - sofiayem +date: 2023-10-10 +description: "Improved @property section in Styles, updated devices list, enhanced pretty-printing in Sources and autocompletion in the Console." +hero: 'image/NJdAV9UgKuN8AhoaPBquL7giZQo1/C5z0hHEPjBwgsXg2WG0t.png' +alt: 'Improved @property section in Styles, updated devices list, enhanced pretty-printing in Sources and autocompletion in the Console.' +tags: + - new-in-devtools + - devtools + - chrome-119 +--- +<!--image/dPDCek3EhZgLQPGtEG3y0fTn4v82/gctGASDKBFTUtOQqVq2H.png --> + +{% Partial 'devtools/banner.md' %} + +<!-- $contentStart --> + +## Improved `@property` section in Elements > Styles {: #css } + +### Editable `@property` rule {: #edit-property } + +You can now edit the [`@property` CSS at-rule](https://web.dev/at-property/) in the corresponding section in the **Elements** > **Styles** pane. + +{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/J6OXQJK3RRuCvAR1Yai9.png", alt="The before and after making the property rule editable.", width="800", height="526" %} + +{% Aside 'note' %} +Note that DevTools shows [non-editable](/docs/devtools/css/issues/#non-editable) rules in *italic text*. +{% endAside %} + +{# https://chromium.googlesource.com/devtools/devtools-frontend/+/0226cbddd5437e869c924569fe342fcb9e89b466 #} +{# https://chromium.googlesource.com/chromium/src/+/15245f8b594e93fa4aeb2f3d321364eaf2ed8438 #} + +Chromium issue: [1471123](https://crbug.com/1471123). + +### Issues with invalid `@property` rules are reported {: #property-issues } + +The **Issues** tab now reports issues with invalid declarations in `@property` rules. + +{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/sd2Fh479paZoIzukHrCO.png", alt="An issues with the property rule reported in the Issues tab.", width="800", height="639" %} + +{# https://chromium.googlesource.com/devtools/devtools-frontend/+/499d13e8ad395b9a55aadf7eaaafe487ebed2cbb #} +{# https://chromium.googlesource.com/chromium/src/+/b0b317506822855ec4757d5962671f5fe666aac0 #} + +Chromium issue: [1473283](https://crbug.com/1473283). + +## Updated list of devices to emulate {: #devices } + +The user agent strings in {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/9gzXiTYY0nZzBxGI6KrV.svg", alt="Settings.", width="24", height="24" %} [**Settings** > **Devices**](/docs/devtools/settings/devices/) has been updated to reflect the average usage of browsers and operating systems. You can now emulate more of the up-to-date devices in [device mode](/docs/devtools/device-mode/). + +{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/EaLfaHSw1q7wGH5C1HQ6.png", alt="The before and after updating the device list.", width="800", height="503" %} + +{# https://chromium.googlesource.com/devtools/devtools-frontend/+/d86bfdc7c2178324e2717afe5b19d2ba1cd8744d #} + +Chromium issue: [1479733](https://crbug.com/1479733). + +## Pretty-print inline JSON in script tags in Sources {: #sources } + +The **Sources** panel now supports pretty-printing inline JSON in `<script>` HTML tags for easier debugging. + +{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/EdE39X771gyHJLTGmPj8.png", alt="The before and after pretty-printing inline JSON in the script tag.", width="800", height="648" %} + +{# https://chromium.googlesource.com/devtools/devtools-frontend/+/84ca000f76aa74165674247374b0e0802c3f8a89 #} + +Chromium issues: [406900](https://crbug.com/406900), [1473875](https://crbug.com/1473875). + +## Autocomplete private fields in Console {: #autocomplete-console } + +You can now autocomplete [private class fields](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Classes/Public_class_fields) when evaluating them outside the class scope in the **Console**. + +{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/5yG7PmRn2TmVGOz0N1ne.png", alt="The before and after supporting autocompletion for private class field outside of class scope.", width="800", height="408" %} + +{# https://chromium.googlesource.com/devtools/devtools-frontend/+/7eb2770f7ff2395c817725e77df1ca07d48fe872 #} + +Chromium issues: [1483848](https://crbug.com/1483848), [1381806](https://crbug.com/1381806). + +## Lighthouse 11.1.0 {: #lighthouse } + +The **Lighthouse** panel now runs Lighthouse 11.1.0. See the [full list of changes](https://github.com/GoogleChrome/lighthouse/releases/tag/v11.1.0). + +To learn the basics of using the **Lighthouse** panel in DevTools, see [Lighthouse: Optimize website speed](/docs/devtools/lighthouse/). + +{# https://chromium.googlesource.com/devtools/devtools-frontend/+/65643d2c71a7fa41038525f125eeff743964af59 #} + +Chromium issues: [772558](https://crbug.com/772558). + +## Accessibility improvements {: #accessibility } + +Screen readers will now read out the following: + +- Warnings and errors in the **Console**. +- The text in the **Do you trust this code?** dialog when pasting code to **Console** or **Sources**. + +Additionally, the **Application** panel fixed contrast issues with links in high contrast mode. + +{# https://chromium.googlesource.com/devtools/devtools-frontend/+/7fa46cca30a1d164c60e359b10cd97b1be541d4e #} +{# https://chromium.googlesource.com/devtools/devtools-frontend/+/6f843ded7a69f3a2b5817c8b1e01ab828e178c8e #} +{# https://chromium.googlesource.com/devtools/devtools-frontend/+/85a958fb910c0c2c0e5c1b206d52e3708b30bebe #} + +Chromium issues: [1485257](https://crbug.com/1485257), [1486643](https://crbug.com/1486643), [1485263](https://crbug.com/1485263). + +## Web SQL deprecation {: #web-sql } + +The **Application** > **Web SQL** section will be removed in Chrome 123 because the [Web SQL Database API](https://www.w3.org/TR/webdatabase/) [isn't maintained](https://www.w3.org/TR/webdatabase/#status-of-this-document) anymore. This version adds a warning to the section about the upcoming removal. + +{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/NuJgh7FznQ2jlgG0pq9w.png", alt="The Web SQL deprecation warning.", width="800", height="472" %} + +For more information, see [Deprecating and removing Web SQL](/blog/deprecating-web-sql/). + +{# https://chromium.googlesource.com/devtools/devtools-frontend/+/087d06b98e6fdd264fde7d16895a1c3cec4d0766 #} +{# https://chromium.googlesource.com/devtools/devtools-frontend/+/712c7996d8c9a492e073f75b26d92ae76f959719 #} + +Chromium issues: [1485966](https://crbug.com/1485966). + +## Screenshot aspect ratio validation in Application > Manifest {: #manifest-aspect-ratio } + +The **Application** > **Manifest** section now checks if your web app's [screenshots](https://web.dev/add-manifest/#screenshots) with the same form factor (`wide` or `narrow`) have the same aspect ratio. + +{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/krHlVOBrMa0p4SvlhGOJ.png", alt="A warning on the incorrect aspect ratio of screenshots with the same form factor.", width="800", height="370" %} + +For more information, see [Debug Progressive Web Apps](/docs/devtools/progressive-web-apps/) and [Add a web app manifest](https://web.dev/add-manifest/). + +The DevTools team expresses gratitude to [Alexey Rodionov](https://chromium.googlesource.com/devtools/devtools-frontend/+/f95f715656086cbd9daef3302b7691403bed12c6) for landing this change and other [manifest warning improvements](https://chromium.googlesource.com/devtools/devtools-frontend/+/ead65e6c528a1a8efe7808a51e3f3db06406b9f7) in the previous version. + +{# https://chromium.googlesource.com/devtools/devtools-frontend/+/f95f715656086cbd9daef3302b7691403bed12c6 #} + +Chromium issue: [1476656](https://crbug.com/1476656). + +## Miscellaneous highlights {: #misc } + +These are some noteworthy fixes and improvements in this release: + +- **Elements**: + - Animation timing function swatches are not shown for longhand CSS properties under the [expandable shorthand](/docs/devtools/css/issues/#shorthand) ones ([1149182](https://crbug.com/1149182)). + - The autocomplete for `contain-intrinsic-*` now doesn't provide the incorrect single `auto` value because it should be `auto <length>` ([1480415](https://crbug.com/1480415)). + - Support for deprecated and invalid `-webkit-*` properties has been removed ([1086089](https://crbug.com/1086089), [1030765](https://crbug.com/1030765)). +- **Breakpoints**: Fixed the bug with disappearing breakpoint editing dialog when the breakpoint type is changed ([1485782](https://crbug.com/1485782)). +- **Performance**: + - The color parsing error during performance recording has been fixed ([1480205](https://crbug.com/1480205)). + - Fixed the bug with [LCP](https://web.dev/lcp/) not showing in the **Timings** track ([1487136](https://crbug.com/1487136)). +- **Network**: The **Set cookies** column now shows the correct number of cookies that are set, excluding blocked ([1486903](https://crbug.com/1486903)). +- DevTools extensions now load after navigation to a non-blocked host ([1476264](https://crbug.com/1476264)). +- Fixed the bug with incorrect script execution context for extensions ([1275331](https://crbug.com/1275331)). + +<!-- $contentEnd --> + +{% Partial 'devtools/reach-out.md' %} +{% Partial 'devtools/whats-new.md' %} + From 647b72b35281cad46b85f69c2cc59634497bf23f Mon Sep 17 00:00:00 2001 From: Wolfgang Beyer <woolfi.b@gmail.com> Date: Wed, 11 Oct 2023 15:00:25 +0200 Subject: [PATCH 881/982] Fix typos in cdp-command-editor blog post (#7222) --- site/en/blog/cdp-command-editor/index.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/site/en/blog/cdp-command-editor/index.md b/site/en/blog/cdp-command-editor/index.md index f9f2431b2..a75e3af03 100644 --- a/site/en/blog/cdp-command-editor/index.md +++ b/site/en/blog/cdp-command-editor/index.md @@ -62,7 +62,7 @@ An auto completion feature now powers the command input bar. It helps you write With this new editor, you can now easily edit the values of primitive parameters. To open the editor, click the {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/H4duJWlMkdd1903sC0Bw.svg", alt="Open left panel.", width="20", height="20" %} icon next to the command input. -Once you enter the command name, the editor shows you the corresponding parameters automatically. You don't have to look up documentation to know what parameters go with what commands. Furthermore, the editor displays the parameters in a given order: the mandatory one first (in red) and the optional ones next (in blue). +Once you enter the command name, the editor shows you the corresponding parameters automatically. You don't have to look up documentation to know what parameters go with what commands. Furthermore, the editor displays the parameters in a given order: the mandatory ones first (in red) and the optional ones next (in blue). To add a value to an optional parameter, hover over its name and click the `+` button. To reset the parameter to undefined, click the **Reset to default value** button. @@ -86,7 +86,7 @@ To delete array items one by one, click the bin button next to the items. You ca ## Object parameters -When you enter a command that accepts object parameters, the editor lists the keys of this object and you can edit their values directly. This works for every type of nested parameters. +When you enter a command that accepts object parameters, the editor lists the keys of this object and you can edit their values directly. This works for all types of nested parameters. {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/O9VSKDH9ENYv9aWW1igP.png", alt="Nested parameters.", width="800", height="564" %} From e262dd234c039ab14e4ad7c3451153d7636ac12d Mon Sep 17 00:00:00 2001 From: Sofia Emelianova <42939855+sofiayem@users.noreply.github.com> Date: Wed, 11 Oct 2023 14:12:26 +0100 Subject: [PATCH 882/982] queueing vs stalled clarification (#7507) --- site/en/docs/devtools/network/reference/index.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/site/en/docs/devtools/network/reference/index.md b/site/en/docs/devtools/network/reference/index.md index 3efd84a82..174e99d37 100644 --- a/site/en/docs/devtools/network/reference/index.md +++ b/site/en/docs/devtools/network/reference/index.md @@ -538,12 +538,12 @@ hovering. Here's more information about each of the phases you may see in the **Timing** tab: -- **Queueing**. The browser queues requests when: +- **Queueing**. The browser queues requests before connection start and when: - There are higher priority requests. - There are already six TCP connections open for this origin, which is the limit. Applies to HTTP/1.0 and HTTP/1.1 only. - - The browser is briefly allocating space in the disk cache -- **Stalled**. The request could be stalled for any of the reasons described in **Queueing**. + - The browser is briefly allocating space in the disk cache. +- **Stalled**. The request could be stalled after connection start for any of the reasons described in **Queueing**. - **DNS Lookup**. The browser is resolving the request's IP address. - **Initial connection**. The browser is establishing a connection, including TCP handshakes/retries and negotiating an SSL. From b537dc27e88766036de9be6cce5888adfd72545d Mon Sep 17 00:00:00 2001 From: Oliver Dunk <oliverdunk@google.com> Date: Wed, 11 Oct 2023 14:50:06 +0100 Subject: [PATCH 883/982] Add isUrlFilterCaseSensitive change to What's New (#7482) * Add isUrlFilterCaseSensitive change to What's New * Update site/en/docs/extensions/whatsnew/index.md Co-authored-by: amysteamdev <37001393+AmySteam@users.noreply.github.com> * Apply suggestions from code review --------- Co-authored-by: amysteamdev <37001393+AmySteam@users.noreply.github.com> --- site/en/docs/extensions/whatsnew/index.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/site/en/docs/extensions/whatsnew/index.md b/site/en/docs/extensions/whatsnew/index.md index d5e62be6d..76f26265d 100644 --- a/site/en/docs/extensions/whatsnew/index.md +++ b/site/en/docs/extensions/whatsnew/index.md @@ -15,6 +15,18 @@ tags: Check this page often to learn about changes to Chrome extensions, extensions documentation, or related policy or other changes. You'll find other notices posted on the [Extensions Google Group](https://groups.google.com/a/chromium.org/g/chromium-extensions). The [Extensions News](/tags/extensions-news/) tag lists articles about some of the topics listed here. (It even has [an RSS feed](/feeds/extensions-news.xml).) The [Chrome schedule](https://chromiumdash.appspot.com/schedule) lists stable and beta release dates. +### Chrome 118: isUrlFilterCaseSensitive now defaults to false {: #118-url-filter-case-sensitive } + +<p class="color-secondary-text type--caption">Posted on <time>October 11, 2023</time></p> + +Starting in Chrome 118, the [`isUrlFilterCaseSensitive`](/docs/extensions/reference/declarativeNetRequest/#property-RuleCondition-isUrlFilterCaseSensitive) +property in the [chrome.declarativeNetRequest](/docs/extensions/reference/declarativeNetRequest/) +API has been changed to default to `false`. If you wish to keep the old behavior, you can explicitly set `isUrlFilterCaseSensitive` to `true` in +your declarativeNetRequest rules. + +This follows [discussions](https://github.com/w3c/webextensions/issues/269) in the Web Extensions +Community Group. Firefox and Safari have already implemented a similar change. + ### Documentation on cookies and web storage APIs {: #storage-and-cookies-guide } <p class="color-secondary-text type--caption">Posted on <time>October 9, 2023</time></p> From 0d3eb467c7ae06cdc020c5a665e799a6451353d9 Mon Sep 17 00:00:00 2001 From: "Kevin K. Lee" <kevinkiklee@google.com> Date: Wed, 11 Oct 2023 10:09:47 -0400 Subject: [PATCH 884/982] Protected Audience worklet caching (#7392) * Add PA worklet caching information * Update site/en/docs/privacy-sandbox/protected-audience-api/index.md Co-authored-by: Anusmita <anusmitaray@google.com> * Update worklet list --------- Co-authored-by: Anusmita <anusmitaray@google.com> --- .../docs/privacy-sandbox/protected-audience-api/index.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/site/en/docs/privacy-sandbox/protected-audience-api/index.md b/site/en/docs/privacy-sandbox/protected-audience-api/index.md index 27377c8e6..03d4c01cc 100644 --- a/site/en/docs/privacy-sandbox/protected-audience-api/index.md +++ b/site/en/docs/privacy-sandbox/protected-audience-api/index.md @@ -486,6 +486,14 @@ and membership is removed when users clear their site data. {% endDetails %} +{% Details %} +{% DetailsSummary %} +### Are the Protected Audience worklets cached by the browser? +{% endDetailsSummary %} + +The resources that contain the Protected Audience worklets—the buyer's bid generation and reporting worklets, and seller's ad scoring and reporting worklets—are cached by the browser. You can use the `Cache-Control` header to control the caching behavior. +{% endDetails %} + {: #engage} ## Engage and share feedback From 06f806fdac21b4156f13a660fdd15b2b7eeffb7e Mon Sep 17 00:00:00 2001 From: Rowan Merewood <rowan@merewood.org> Date: Wed, 11 Oct 2023 15:49:53 +0100 Subject: [PATCH 885/982] Blog post "Preparing for the end of third-party cookies" (#7509) Co-authored-by: Anusmita <anusmitaray@google.com> --- site/_data/i18n/tags.yml | 3 + site/_data/supportedTags.json | 3 + .../en/blog/cookie-countdown-2023oct/index.md | 174 ++++++++++++++++++ .../third-party-cookie-phase-out/index.md | 162 ++++++++++------ 4 files changed, 284 insertions(+), 58 deletions(-) create mode 100644 site/en/blog/cookie-countdown-2023oct/index.md diff --git a/site/_data/i18n/tags.yml b/site/_data/i18n/tags.yml index da4fb53d5..f2ac6cadc 100644 --- a/site/_data/i18n/tags.yml +++ b/site/_data/i18n/tags.yml @@ -93,6 +93,9 @@ cws: cookies: en: Cookies +cookie-countdown: + en: Cookie Countdown + deprecations-removals: en: Deprecations and Removals diff --git a/site/_data/supportedTags.json b/site/_data/supportedTags.json index 46933c245..d5732680f 100644 --- a/site/_data/supportedTags.json +++ b/site/_data/supportedTags.json @@ -29,6 +29,9 @@ "cookies": { "title": "i18n.tags.cookies" }, + "cookie-countdown": { + "title": "i18n.tags.cookie-countdown" + }, "deprecations-removals": { "title": "i18n.tags.deprecations-removals" }, diff --git a/site/en/blog/cookie-countdown-2023oct/index.md b/site/en/blog/cookie-countdown-2023oct/index.md new file mode 100644 index 000000000..523402676 --- /dev/null +++ b/site/en/blog/cookie-countdown-2023oct/index.md @@ -0,0 +1,174 @@ +--- +layout: 'layouts/blog-post.njk' +title: 'Preparing for the end of third-party cookies' +authors: + - rowan_m +description: > + If your site uses third-party cookies it's time to take action as we approach their deprecation. Chrome plans to disable third-party cookies for 1% of users from Q1 2024 to facilitate testing and then ramp up to 100% of users from Q3 2024. In this Cookie Countdown series, we'll guide you through the timeline and immediate actions you can take to ensure your sites are prepared. +date: 2023-10-11 +thumbnail: 'image/VWw0b3pM7jdugTkwI6Y81n6f5Yc2/XeTqWn3za0aUZVGb2kUM.jpg' +alt: > + Preparing for the end of third-party cookies +tags: + - privacy + - cookie-countdown +--- + +If your site uses third-party cookies it's time to take action as we approach their deprecation. Chrome plans to disable third-party cookies for 1% of users from Q1 2024 to facilitate testing, and then ramp up to 100% of users from Q3 2024. The ramp up to 100% of users is subject to addressing any remaining competition concerns of the [UK’s Competition and Markets Authority (CMA)](https://www.gov.uk/cma-cases/investigation-into-googles-privacy-sandbox-browser-changes). + +Our goal with the Privacy Sandbox is to reduce cross-site tracking while still enabling the functionality that keeps online content and services freely accessible by everyone. Deprecating and removing third-party cookies encapsulates the challenge, as they enable critical functionality across sign-in, fraud protection, advertising, and generally the ability to embed rich, third-party content in your sites—but at the same time they're also the key enablers of cross-site tracking. + +In our previous major milestone, we launched a range of APIs providing a privacy-focused alternative to today’s status quo for use cases like identity, advertising, and fraud detection. With alternatives in place, we can now move on to begin phasing out third-party cookies. + +In this [Cookie Countdown series](/tags/cookie-countdown/) we will take you through the timeline and immediate actions you can take to ensure your sites are prepared. + + +## 1% third-party cookie deprecation and Chrome-facilitated testing {: #chrome-testing } + +On the [privacysandbox.com timeline](https://privacysandbox.com/open-web/#the-privacy-sandbox-timeline) you can see two milestones approaching in Q4 2023 and Q1 2024 as part of [Chrome-facilitated testing](/docs/privacy-sandbox/chrome-testing/) modes. This testing is primarily for organizations testing the Privacy Sandbox relevance and measurement APIs, however as part of this we will be disabling third-party cookies for 1% of Chrome Stable users. + +{% Img src="image/VWw0b3pM7jdugTkwI6Y81n6f5Yc2/Fl3J3HIW22U710lVSgtu.png", alt="Timeline for third-party cookie depraction. As part of Chrome-facilitated testing, the opt-in testing with labels mode starts in Q4 2023 and the 1% 3PC deprecation mode starts in Q1 2024. Both continue through to mid-Q3 2024 when the third-party cookie phaseout starts.", width="800", height="276" %} + +This means that from the start of 2024, you can expect to see an increased portion of Chrome users on your site with third-party cookies disabled even if you are not actively participating in the Chrome-facilitated testing. This testing period continues through to Q3 2024 when, after [consultation with the CMA](https://www.gov.uk/cma-cases/investigation-into-googles-privacy-sandbox-browser-changes) and subject to resolving any competition concerns, we plan to begin disabling third-party cookies for all Chrome users + +## Prepare for the third-party cookie phase out + +We've broken the process down into these key steps, with detail below, to ensure you're prepared for your site to run without third-party cookies: + +1. [Audit your third-party cookie usage](#audit). +2. [Test for breakage](#test). +3. For cross-site cookies which store data on a per site basis, like an embed, consider [`Partitioned` with CHIPS](#partitioned). +4. For cross-site cookies across a small group of meaningfully linked sites, consider [Related Website Sets](#rws). +5. For other third-party cookie use cases, [migrate to the relevant web APIs](#migrate). + + +## 1. Audit your third-party cookie usage {: #audit} + +Third-party cookies can be identified by their `SameSite=None` value. You should search your code to look for instances where you set the `SameSite` attribute to this value. If you previously made changes to add `SameSite=None` to your cookies around 2020, then those changes may provide a good starting point. + +The Chrome DevTools Network panel shows cookies set and sent on requests. In the Application panel you can see the Cookies heading under Storage. You can browse the cookies stored for each site accessed as part of the page load. You can sort by the `SameSite` column to group all the `None` cookies. + +{% Img src="image/VWw0b3pM7jdugTkwI6Y81n6f5Yc2/xYNwixxMkPfMmlMmKY4L.png", alt="DevTools Issues tab showing a warning for SameSite=None cookies.", width="800", height="403" %} + +From Chrome 118, the [DevTools Issues tab](/docs/devtools/issues/) shows the breaking change issue, "Cookie sent in cross-site context will be blocked in future Chrome versions." The issue lists potentially affected cookies for the current page. + +{% Aside %} + +We are building a DevTools extension to facilitate analysis of cookie usage during browsing sessions. This will provide debugging pathways for cookies, and Privacy Sandbox features, with access points to learn and understand the different aspects of the Privacy Sandbox initiative. +**Look out for our preview launch in November 2023!** + +{% endAside %} + +If you identify cookies set by third parties, you should check with those providers to see if they have plans for the third-party cookie phase out. For instance, you may need to upgrade a version of a library you are using, change a configuration option in the service, or take no action if the third party is handling the necessary changes themselves. + + +## 2. Test for breakage {: #test } + +You can launch Chrome using the `--test-third-party-cookie-phaseout` [command-line flag](/docs/web-platform/chrome-flags) or from Chrome 118, enable `chrome://flags/#test-third-party-cookie-phaseout`. This will set Chrome to block third-party cookies and ensure that new functionality and mitigations are active in order to best simulate the state after the phase out. + +You can also try browsing with third-party cookies blocked via `chrome://settings/cookies`, but be aware that the flag ensures the new and updated functionality is also enabled. Blocking third-party cookies is a good approach to detect issues, but not necessarily validate you have fixed them. + +If you maintain an active test suite for your sites, then you should do two side-by-side runs: one with Chrome on the usual settings and one with the same version of Chrome launched with the `--test-third-party-cookie-phaseout` flag. Any test failures in the second run and not in the first are good candidates to investigate for third-party cookie dependencies. Make sure you [report the issues](#report-issues) you find. + +Once you have identified the cookies with issues and understand the use cases for them, you can work through the following options to pick the necessary solution. + + +## 3. Use `Partitioned` cookies with CHIPS {: #partitioned } + +Where your third-party cookie is being used in a 1:1 embedded context with the top-level site, then you may consider using the `Partitioned` attribute as part of Cookies Having Independent Partitioned State (CHIPS) to allow cross-site access with a separate cookie used per site. + +{% Img src="image/VWw0b3pM7jdugTkwI6Y81n6f5Yc2/5JLh0cCChr0bKOzp6XxP.png", alt="The Partitioned attribute enables a seperate fav_store cookie to be set per top-level site.", width="800", height="359" %} + +To implement CHIPS, you add the `Partitioned` attribute to your `Set-Cookie` header: + +By setting `Partitioned`, the site opts in to storing the cookie in a separate cookie jar partitioned by top-level site. In the example above, the cookie comes from `store-finder.site` which hosts a map of stores that enables a user to save their favorite store. By using CHIPS, when `brand-a.site` embeds `store-finder.site`, the value of the `fav_store` cookie is `123`. Then when `brand-b.site` also embeds `store-finder.site` they will set and send their own partitioned instance of the `fav_store` cookie, for example with value `456`. + +This means embedded services can still save state, but do not have shared cross-site storage that would allow cross-site tracking. + +**Potential use cases:** third-party chat embeds, third-party map embeds, third-party payment embeds, subresource CDN load balancing, headless CMS providers, sandbox domains for serving untrusted user content, third-party CDNs using cookies for access control, third-party API calls that require cookies on requests, embedded ads with state scoped per publisher. + +**[Learn more about CHIPS](/docs/privacy-sandbox/chips/)** + + +## 4. Use Related Website Sets {: #rws } + +Where your third-party cookie is only used across a small number of related sites, then you may consider using [Related Website Sets](/en/blog/related-website-sets/) (RWS) to allow cross-site access for that cookie within the context of those defined sites. + +To implement RWS, you will need to [define and submit](https://github.com/GoogleChrome/first-party-sets/blob/main/RWS-Submission_Guidelines.md) the group of sites for the set. To ensure that the sites are meaningfully related, the policy for a valid set requires grouping those sites by: associated sites with a visible relation to each other (e.g. variants of a company’s product offering), service domains (e.g. APIs, CDNs), or country-code domains (e.g. \*.uk, \*.jp). + +{% Img src="image/VWw0b3pM7jdugTkwI6Y81n6f5Yc2/es7ld9MfMP8sowe7PZzC.png", alt="Related Website Sets allows cookie access within the context of the declared sites, but not across other third-party sites.", width="800", height="359" %} + +Sites can use the Storage Access API to either request cross-site cookie access using `requestStorageAccess()` or delegate access using `requestStorageAccessFor()`. When sites are within the same set, the browser will automatically grant access and cross-site cookies will be available. + +This means that groups of related sites can still make use of cross-site cookies in a limited context, but do not risk sharing third-party cookies across unrelated sites in a way that would allow cross-site tracking. + +**Potential use cases:** app-specific domains, brand-specific domains, country-specific domains, sandbox domains for serving untrusted user content, service domains for APIs, CDNs. + +**[Learn more about RWS](/blog/related-website-sets/)** + + +## 5. Migrate to the relevant web APIs {: #migrate } + +CHIPS and RWS enable specific types of cross-site cookie access while retaining user privacy, however the other use cases for third-party cookies must migrate to privacy-focused alternatives. + +The Privacy Sandbox provides a range of purpose-built APIs for specific use cases without a need for third-party cookies: + +* **[Federated Credential Management (FedCM)](/docs/privacy-sandbox/fedcm/)** enables federated identity services allowing users to sign in to sites and services. +* **[Private State Tokens](/docs/privacy-sandbox/private-state-tokens/)** enable anti-fraud and anti-spam by exchanging limited, non-identifying information across sites. +* **[Topics](/docs/privacy-sandbox/topics/overview/)** enables interest-based advertising and content personalization. +* **[Protected Audience](/docs/privacy-sandbox/protected-audience/)** enables remarketing and custom audiences. +* **[Attribution Reporting](/docs/privacy-sandbox/attribution-reporting/)** enables measurement of ad impressions and conversions. + +Additionally, Chrome supports the **[Storage Access API](https://developer.mozilla.org/docs/Web/API/Storage_Access_API/Using)** (SAA) for usage in iframes with user interaction. SAA is already [supported across Edge, Firefox, and Safari](https://developer.mozilla.org/docs/Web/API/Storage_Access_API#browser_compatibility). We believe it strikes a good balance to maintain user privacy while still enabling critical cross-site functionality with the benefit of cross-browser compatibility. + +Note that the Storage Access API will surface a browser permission prompt to users. To provide an optimal user experience, we will only prompt the user if the site calling `requestStorageAccess()` has interacted with the embedded page and has previously visited the third-party site in a top-level context. A successful grant will allow cross-site cookie access for that site for 30 days. Potential use cases are authenticated cross-site embeds such as social network commenting widgets, payment providers, subscribed video services. + +If you still have third-party cookie use cases that are not covered by these options, you should [report the issue to us](#report-issues) and consider if there are alternative implementations that do not depend on functionality that can enable cross-site tracking. + + +## Enterprise support + +Enterprise-managed Chrome always has unique requirements compared to general web usage and we will be ensuring that enterprise administrators have appropriate controls over the deprecation of third-party cookies in their browsers. + +As with the majority of Chrome experiments, most enterprise end users will be excluded from the 1% third-party cookie deprecation automatically. For the few that may be affected, enterprise administrators can set the [BlockThirdPartyCookies policy](https://chromeenterprise.google/policies/#BlockThirdPartyCookies) to `false` to opt out their managed browsers ahead of the experiment and allow time to make necessary changes to not rely on this policy or third-party cookies. You can read more in the [Chrome Enterprise release notes](https://support.google.com/chrome/a/answer/7679408?sjid=16745203858910744446-EU#upChromeBrsrBB117). + +We also intend to provide further reporting and tooling to help identify third-party cookie usage on enterprise sites. We have less visibility of enterprise browsers in Chrome's usage metrics which means it is especially important for enterprises to [test for breakage](#test) and [report issues to us](#report-issues). + +Enterprise SaaS integrations will be able to use the third-party deprecation trial described below. + + +## Request additional time with the third-party deprecation trial for non-advertising use cases + +As with many previous deprecations on the web, we understand there are cases where sites need extra time to make the necessary changes. When it comes to privacy-related changes like this, we also have to balance that against the best interests of people using the web. + +We plan to offer a [deprecation trial](/docs/web-platform/origin-trials/#deprecation-trials) to provide a way for sites or services used in a cross-site context to register for continued access to third-party cookies for a limited period of time. + +{% Aside 'key-term' %} + +Deprecation trials are a type of [origin trial](/docs/web-platform/origin-trials/#deprecation-trials) that allow a feature to be temporarily re-enabled. + +{% endAside %} + +We will share more details as plans progress, but we are starting with a few key principles: + +* It will be a [third-party](/docs/web-platform/third-party-origin-trials/) deprecation trial allowing third-party embeds to opt in to temporarily continue using third-party cookies. +* Registering will require a review process to ensure the deprecation trial is only used for functions that greatly affect critical user journeys and registrations will be considered on a case by case basis. +* It will not interfere with the [advertising testing planned for the start of 2024, as described by the CMA](https://www.gov.uk/cma-cases/investigation-into-googles-privacy-sandbox-browser-changes#industry-testing). As such, this means advertising use cases will not be considered for the deprecation trial. + +**Next step:** We will publish an [Intent](https://goo.gle/blink-intents) to the [blink-dev mailing list](https://groups.google.com/a/chromium.org/g/blink-dev) with further details this month and continue to update documentation here. + + +## Preserving critical user experiences + +Cross-site cookies have been a critical part of the web for over a quarter of a century. This makes any change, especially a breaking change, a complex process that requires a coordinated and incremental approach. While the additional cookie attributes and new privacy-focused APIs account for the majority of use cases, there are specific scenarios where we want to ensure we do not break the experience for people using those sites. + +Primarily these are authentication or payment flows where a top-level site either opens a pop-up window or redirects to a third-party site for an operation and then returns to the top-level site, making use of a cookie either on that return journey or in the embedded context. We intend to provide a temporary set of heuristics to identify these scenarios and allow third-party cookies for a limited amount of time, giving sites a longer window to implement the necessary changes. + +**Next step:** We will publish an Intent to the blink-dev mailing list with further details in this month and continue to update documentation here. + + +## Reporting issues with third-party cookies and getting help + +We want to ensure we are capturing the various scenarios where sites break without third-party cookies to ensure that we have provided guidance, tooling, and functionality to allow sites to migrate away from their third-party cookie dependencies. If your site or a service you depend on is breaking with third-party cookies disabled, you can submit it to our breakage tracker at [goo.gle/report-3pc-broken](https://goo.gle/report-3pc-broken). + +If you have questions around the deprecation process and Chrome's plan, you can [raise a new issue using the "third-party cookie deprecation" tag](https://github.com/GoogleChromeLabs/privacy-sandbox-dev-support/issues/new/choose) in our developer support repo. diff --git a/site/en/docs/privacy-sandbox/third-party-cookie-phase-out/index.md b/site/en/docs/privacy-sandbox/third-party-cookie-phase-out/index.md index c20491e85..32763fa91 100644 --- a/site/en/docs/privacy-sandbox/third-party-cookie-phase-out/index.md +++ b/site/en/docs/privacy-sandbox/third-party-cookie-phase-out/index.md @@ -6,7 +6,7 @@ subhead: > description: > Learn how to audit your code to look for third-party cookies and what action you can take to ensure you're all set for the end of third-party cookies. date: 2023-05-17 -updated: 2023-08-30 +updated: 2023-10-11 authors: - mihajlija --- @@ -17,20 +17,37 @@ As part of the [Privacy Sandbox](https://privacysandbox.com/) project, Chrome is To get ready for the future without cross-site tracking, audit your use of cookies and plan the actions needed if your site is impacted. -## Overview +## Prepare for the third-party cookie phase out -1. [Identify first-party and third-party cookies](#identify) in your code. Cookies that contain `SameSite=None` will require updates. -1. If you use third-party cookies in a fully contained, embedded context, investigate [partitioned cookies](#partitioned-cookies). -1. If you need third-party cookies across multiple sites that form one cohesive group, investigate [First-Party Sets](#first-party-sets). -1. If you're not covered by either of these options, [investigate other Privacy Sandbox APIs](#other-apis) for individual use cases that don't rely on cross-site tracking. +We've broken the process down into these key steps, with detail below, to ensure you're prepared for your site to run without third-party cookies: -## Identify your first-party and third-party cookies {: #identify } +1. [Audit your third-party cookie usage](#audit). +2. [Test for breakage](#test). +3. For cross-site cookies which store data on a per site basis, like an embed, consider [`Partitioned` with CHIPS](#partitioned). +4. For cross-site cookies across a small group of meaningfully linked sites, consider [Related Website Sets](#rws). +5. For other third-party cookie use cases, [migrate to the relevant web APIs](#migrate). -Cookies can be first-party or third-party relative to the user's context; depending on which site the user is on at the time. This distinction between first-party and third-party context on the web isn't always obvious and the effect it has on different resources can vary. -Cookies are associated with the site that set them and they can be sent on HTTP requests or accessed by JavaScript. If the site in the browser's location bar matches the site associated with the cookie request, then that's a first-party cookie. If the site is different, it's a third-party cookie. +## 1. Audit your third-party cookie usage {: #audit} -### First-party cookies +Third-party cookies can be identified by their `SameSite=None` value. You should search your code to look for instances where you set the `SameSite` attribute to this value. If you previously made changes to add `SameSite=None` to your cookies around 2020, then those changes may provide a good starting point. + +The Chrome DevTools Network panel shows cookies set and sent on requests. In the Application panel you can see the Cookies heading under Storage. You can browse the cookies stored for each site accessed as part of the page load. You can sort by the `SameSite` column to group all the `None` cookies. + +{% Img src="image/VWw0b3pM7jdugTkwI6Y81n6f5Yc2/xYNwixxMkPfMmlMmKY4L.png", alt="DevTools Issues tab showing a warning for SameSite=None cookies.", width="800", height="403" %} + +From Chrome 118, the [DevTools Issues tab](/docs/devtools/issues/) shows the breaking change issue, "Cookie sent in cross-site context will be blocked in future Chrome versions." The issue lists potentially affected cookies for the current page. + +{% Aside %} + +We are building a DevTools extension to facilitate analysis of cookie usage during browsing sessions. This will provide debugging pathways for cookies, and Privacy Sandbox features, with access points to learn and understand the different aspects of the Privacy Sandbox initiative. +**Look out for our preview launch in November 2023!** + +{% endAside %} + +If you identify cookies set by third parties, you should check with those providers to see if they have plans for the third-party cookie phase out. For instance, you may need to upgrade a version of a library you are using, change a configuration option in the service, or take no action if the third party is handling the necessary changes themselves. + +### Improve your first-party cookies If your cookie is never used on a third-party site, for example if you set a cookie to manage the session on your site and it's never used in a cross-site iframe, that cookie is always used in a first-party context. {% Img src="image/vgdbNJBYHma2o62ZqYmcnkq3j0o1/ArhVqaVr6O2X0mE0YYxp.png", alt="Diagram showing a first-party cookie.", width="800", height="653" %} @@ -63,7 +80,7 @@ SameSite=Lax For more details, check out [Recipes for first-party cookies](https://web.dev/first-party-cookie-recipes). -### Third-party cookies +### Understand your third-party cookies Cookies that are sent in cross-site contexts, like iframes or subresource requests, are generally referred to as third-party cookies. {% Img src="image/vgdbNJBYHma2o62ZqYmcnkq3j0o1/NJLl1qG9AN8tD9GwR2jp.png", alt="Diagram showing a third-party cookie.", width="800", height="646" %} @@ -84,84 +101,113 @@ Set-Cookie: cookie-name=value; SameSite=None; Secure Make sure to review your cookies and have a list of those set with the `SameSite=None`. These are the cookies for which you will need to take action to ensure they keep functioning properly. {% endAside %} -## Debugging cookies +## 2. Test for breakage {: #test } -One way to identify third-party cookies in your code base is to search for cookies containing `SameSite=None`. +You can launch Chrome using the `--test-third-party-cookie-phaseout` [command-line flag](/docs/web-platform/chrome-flags) or from Chrome 118, enable `chrome://flags/#test-third-party-cookie-phaseout`. This will set Chrome to block third-party cookies and ensure that new functionality and mitigations are active in order to best simulate the state after the phase out. -Another option is to browse through your site with third-party cookies blocked on your machine and use DevTools to investigate any potential breakage. +You can also try browsing with third-party cookies blocked via `chrome://settings/cookies`, but be aware that the flag ensures the new and updated functionality is also enabled. Blocking third-party cookies is a good approach to detect issues, but not necessarily validate you have fixed them. -To learn more about DevTools features you can use to investigate third-party cookies check out [the instructions on chromium.org](https://www.chromium.org/Home/chromium-privacy/privacy-sandbox/third-party-cookie-phaseout/). +If you maintain an active test suite for your sites, then you should do two side-by-side runs: one with Chrome on the usual settings and one with the same version of Chrome launched with the `--test-third-party-cookie-phaseout` flag. Any test failures in the second run and not in the first are good candidates to investigate for third-party cookie dependencies. Make sure you [report the issues](#report-issues) you find. -In Chrome version 115 or higher, you can test the browser behavior after third-party cookie phase out by [running Chrome from the command line](https://www.chromium.org/developers/how-tos/run-chromium-with-flags/) with the flag `--test-third-party-cookie-phaseout`. This will block third-party cookies, enable [third-party storage partitioning](/docs/privacy-sandbox/storage-partitioning) and [FedCM](/docs/privacy-sandbox/fedcm), and enable Chrome UI settings for [First-Party Sets](docs/privacy-sandbox/first-party-sets-integration) (["Allow related sites to see your activity in the group"](https://support.google.com/chrome/answer/95647?hl=EN#zippy=%2Callow-related-sites-to-access-your-activity)). +Once you have identified the cookies with issues and understand the use cases for them, you can work through the following options to pick the necessary solution. -If your site breaks when third-party cookies are blocked, you can report the issue to [Chrome's cookie breakage tracker](https://goo.gle/report-3pc-broken). -{% Aside %} -This article was updated on 30 August 2023 to correct a typing mistake in the testing flag `--test-third-party-cookie-phaseout`. -{% endAside %} +## 3. Use `Partitioned` cookies with CHIPS {: #partitioned } -## Partitioned cookies +Where your third-party cookie is being used in a 1:1 embedded context with the top-level site, then you may consider using the `Partitioned` attribute as part of Cookies Having Independent Partitioned State (CHIPS) to allow cross-site access with a separate cookie used per site. -[CHIPS (Cookies Having Independent Partitioned State)](/docs/privacy-sandbox/chips/) is a web platform mechanism that enables opting-in to having third-party cookies partitioned by top-level site using a new cookie attribute `Partitioned`. +{% Img src="image/VWw0b3pM7jdugTkwI6Y81n6f5Yc2/5JLh0cCChr0bKOzp6XxP.png", alt="The Partitioned attribute enables a seperate fav_store cookie to be set per top-level site.", width="800", height="359" %} -If you have a service that is used as a component on another site, any cookies it sets are in a cross-site context. The way cookies currently work, the same cookie that service C sets on site A, can be read when service C is embedded on site B. +To implement CHIPS, you add the `Partitioned` attribute to your `Set-Cookie` header: -{% Img src="image/vgdbNJBYHma2o62ZqYmcnkq3j0o1/4eKoilhldt8qdmiEvEDo.jpg", alt="Diagram showing sites and storage with unpartitioned cookies.", width="800", height="450" %} +By setting `Partitioned`, the site opts in to storing the cookie in a separate cookie jar partitioned by top-level site. In the example above, the cookie comes from `store-finder.site` which hosts a map of stores that enables a user to save their favorite store. By using CHIPS, when `brand-a.site` embeds `store-finder.site`, the value of the `fav_store` cookie is `123`. Then when `brand-b.site` also embeds `store-finder.site` they will set and send their own partitioned instance of the `fav_store` cookie, for example with value `456`. -If your service and the sites using it have a 1:1 relationship, those cookies are only ever needed on the site where they were set and not used across multiple sites. [Examples](/docs/privacy-sandbox/chips/#use-cases) include saving preferences for a widget or sharing a session cookie for an API. +This means embedded services can still save state, but do not have shared cross-site storage that would allow cross-site tracking. -In this case, having cookies partitioned by top-level site is an improvement as it reduces the complexity and risk of cross-site data leaks. Third-party cookies can still be used across sites, however, you will see different cookies when the browser is on different top-level sites. +**Potential use cases:** third-party chat embeds, third-party map embeds, third-party payment embeds, subresource CDN load balancing, headless CMS providers, sandbox domains for serving untrusted user content, third-party CDNs using cookies for access control, third-party API calls that require cookies on requests, embedded ads with state scoped per publisher. -{% Img src="image/vgdbNJBYHma2o62ZqYmcnkq3j0o1/Myb2Km4gEVROgCi5NZFQ.png", alt="Diagram showing sites and paritioned storage with cookies.", width="800", height="393" %} +**[Learn more about CHIPS](/docs/privacy-sandbox/chips/)** -```text -Set-Cookie: __Host-cookie=value; SameSite=None; Secure; Path=/; Partitioned; -``` -### Learn more -For more details about technical design, use cases, and testing, check out [CHIPS documentation](/docs/privacy-sandbox/chips/). +## 4. Use Related Website Sets {: #rws } -## First-Party Sets +Where your third-party cookie is only used across a small number of related sites, then you may consider using [Related Website Sets](/en/blog/related-website-sets/) (RWS) to allow cross-site access for that cookie within the context of those defined sites. -[First-Party Sets (FPS)](/docs/privacy-sandbox/first-party-sets/) is a web platform mechanism for developers to declare relationships among sites, so that browsers can use this information to enable limited cross-site cookie access for specific, user-facing purposes. Chrome will use these declared relationships to decide when to allow or deny a site access to their cookies when in a third-party context. +To implement RWS, you will need to [define and submit](https://github.com/GoogleChrome/first-party-sets/blob/main/RWS-Submission_Guidelines.md) the group of sites for the set. To ensure that the sites are meaningfully related, the policy for a valid set requires grouping those sites by: associated sites with a visible relation to each other (e.g. variants of a company’s product offering), service domains (e.g. APIs, CDNs), or country-code domains (e.g. \*.uk, \*.jp). -{% Img src="image/vgdbNJBYHma2o62ZqYmcnkq3j0o1/NIUl4xLnUCe3yYP7TblC.png", alt="Diagram showing three sites accessing each other's cookies.", width="800", height="446" %} +{% Img src="image/VWw0b3pM7jdugTkwI6Y81n6f5Yc2/es7ld9MfMP8sowe7PZzC.png", alt="Related Website Sets allows cookie access within the context of the declared sites, but not across other third-party sites.", width="800", height="359" %} -If a cookie is used across multiple related sites, blocking cross-site cookies or partitioning by top-level site would prevent [use cases](/blog/first-party-sets-sameparty/#usecases) such as single sign-on or a shared shopping cart. +Sites can use the Storage Access API to either request cross-site cookie access using `requestStorageAccess()` or delegate access using `requestStorageAccessFor()`. When sites are within the same set, the browser will automatically grant access and cross-site cookies will be available. -Declaring your sites as part of a First-Party Set will allow you to use [Storage Access API (SAA)](/docs/privacy-sandbox/first-party-sets-integration/#storage-access-api) and the [requestStorageAccessFor API](/docs/privacy-sandbox/first-party-sets-integration/#requeststorageaccessfor-in-chrome) to request access to those cookies. +This means that groups of related sites can still make use of cross-site cookies in a limited context, but do not risk sharing third-party cookies across unrelated sites in a way that would allow cross-site tracking. -{% Img src="image/vgdbNJBYHma2o62ZqYmcnkq3j0o1/zbeLi9FbtJVhLXiCiRig.png", alt="Diagram showing only sites within the same First-Party Set accessing each other's cookies, while the third site is denied access.", width="800", height="452" %} +**Potential use cases:** app-specific domains, brand-specific domains, country-specific domains, sandbox domains for serving untrusted user content, service domains for APIs, CDNs. -The sets are declared in JSON format–in the example below, the primary domain is `travel.site`, and `air-travel.site` is in the list of associated sites. +**[Learn more about RWS](/blog/related-website-sets/)** -```json -{ - "primary": "https://travel.site", - "associatedSites": ["https://air-travel.site"] -} -``` -Top-level sites can request storage access on behalf of specific origins with [`Document.requestStorageAccessFor()`](https://privacycg.github.io/requestStorageAccessFor/) (rSAFor). +## 5. Migrate to the relevant web APIs {: #migrate } -```js -document.requestStorageAccessFor('https://target.site') -``` +CHIPS and RWS enable specific types of cross-site cookie access while retaining user privacy, however the other use cases for third-party cookies must migrate to privacy-focused alternatives. + +The Privacy Sandbox provides a range of purpose-built APIs for specific use cases without a need for third-party cookies: + +* **[Federated Credential Management (FedCM)](/docs/privacy-sandbox/fedcm/)** enables federated identity services allowing users to sign in to sites and services. +* **[Private State Tokens](/docs/privacy-sandbox/private-state-tokens/)** enable anti-fraud and anti-spam by exchanging limited, non-identifying information across sites. +* **[Topics](/docs/privacy-sandbox/topics/overview/)** enables interest-based advertising and content personalization. +* **[Protected Audience](/docs/privacy-sandbox/protected-audience/)** enables remarketing and custom audiences. +* **[Attribution Reporting](/docs/privacy-sandbox/attribution-reporting/)** enables measurement of ad impressions and conversions. + +Additionally, Chrome supports the **[Storage Access API](https://developer.mozilla.org/docs/Web/API/Storage_Access_API/Using)** (SAA) for usage in iframes with user interaction. SAA is already [supported across Edge, Firefox, and Safari](https://developer.mozilla.org/docs/Web/API/Storage_Access_API#browser_compatibility). We believe it strikes a good balance to maintain user privacy while still enabling critical cross-site functionality with the benefit of cross-browser compatibility. + +Note that the Storage Access API will surface a browser permission prompt to users. To provide an optimal user experience, we will only prompt the user if the site calling `requestStorageAccess()` has interacted with the embedded page and has previously visited the third-party site in a top-level context. A successful grant will allow cross-site cookie access for that site for 30 days. Potential use cases are authenticated cross-site embeds such as social network commenting widgets, payment providers, subscribed video services. + +If you still have third-party cookie use cases that are not covered by these options, you should [report the issue to us](#report-issues) and consider if there are alternative implementations that do not depend on functionality that can enable cross-site tracking. + + +## Enterprise support + +Enterprise-managed Chrome always has unique requirements compared to general web usage and we will be ensuring that enterprise administrators have appropriate controls over the deprecation of third-party cookies in their browsers. + +As with the majority of Chrome experiments, most enterprise end users will be excluded from the 1% third-party cookie deprecation automatically. For the few that may be affected, enterprise administrators can set the [BlockThirdPartyCookies policy](https://chromeenterprise.google/policies/#BlockThirdPartyCookies) to `false` to opt out their managed browsers ahead of the experiment and allow time to make necessary changes to not rely on this policy or third-party cookies. You can read more in the [Chrome Enterprise release notes](https://support.google.com/chrome/a/answer/7679408?sjid=16745203858910744446-EU#upChromeBrsrBB117). + +We also intend to provide further reporting and tooling to help identify third-party cookie usage on enterprise sites. We have less visibility of enterprise browsers in Chrome's usage metrics which means it is especially important for enterprises to [test for breakage](#test) and [report issues to us](#report-issues). + +Enterprise SaaS integrations will be able to use the third-party deprecation trial described below. + + +## Request additional time with the third-party deprecation trial for non-advertising use cases + +As with many previous deprecations on the web, we understand there are cases where sites need extra time to make the necessary changes. When it comes to privacy-related changes like this, we also have to balance that against the best interests of people using the web. + +We plan to offer a [deprecation trial](/docs/web-platform/origin-trials/#deprecation-trials) to provide a way for sites or services used in a cross-site context to register for continued access to third-party cookies for a limited period of time. + +{% Aside 'key-term' %} + +Deprecation trials are a type of [origin trial](/docs/web-platform/origin-trials/#deprecation-trials) that allow a feature to be temporarily re-enabled. + +{% endAside %} + +We will share more details as plans progress, but we are starting with a few key principles: + +* It will be a [third-party](/docs/web-platform/third-party-origin-trials/) deprecation trial allowing third-party embeds to opt in to temporarily continue using third-party cookies. +* Registering will require a review process to ensure the deprecation trial is only used for functions that greatly affect critical user journeys and registrations will be considered on a case by case basis. +* It will not interfere with the [advertising testing planned for the start of 2024, as described by the CMA](https://www.gov.uk/cma-cases/investigation-into-googles-privacy-sandbox-browser-changes#industry-testing). As such, this means advertising use cases will not be considered for the deprecation trial. + +**Next step:** We will publish an [Intent](https://goo.gle/blink-intents) to the [blink-dev mailing list](https://groups.google.com/a/chromium.org/g/blink-dev) with further details this month and continue to update documentation here. -### Learn more -For more details about technical design, use cases, and set submission process, check out [First-Party Sets developer documentation](/docs/privacy-sandbox/first-party-sets-integration/). +## Preserving critical user experiences -## Privacy Sandbox APIs replacing the need for cookies {: #other-apis } +Cross-site cookies have been a critical part of the web for over a quarter of a century. This makes any change, especially a breaking change, a complex process that requires a coordinated and incremental approach. While the additional cookie attributes and new privacy-focused APIs account for the majority of use cases, there are specific scenarios where we want to ensure we do not break the experience for people using those sites. -CHIPS and First-Party Sets cover use cases that can continue to rely on cross-site cookies in a privacy-preserving way. +Primarily these are authentication or payment flows where a top-level site either opens a pop-up window or redirects to a third-party site for an operation and then returns to the top-level site, making use of a cookie either on that return journey or in the embedded context. We intend to provide a temporary set of heuristics to identify these scenarios and allow third-party cookies for a limited amount of time, giving sites a longer window to implement the necessary changes. -If neither meets your needs, there is a wider set of Privacy Sandbox proposals for new APIs for specific use cases, replacing the need for cookies. Some of the new APIs are focused on identity, fraud detection, and more, while others cover advertising. +**Next step:** We will publish an [Intent](https://goo.gle/blink-intents) to the [blink-dev mailing list](https://groups.google.com/a/chromium.org/g/blink-dev) with further details in this month and continue to update documentation here. -[Federated Credential Management (FedCM)](/docs/privacy-sandbox/fedcm/) enables privacy-preserving approach to federated identity services so users can log into sites without sharing their personal information with a third-party service or website. -[Private State Tokens](/docs/privacy-sandbox/private-state-tokens/) convey a limited amount of information from one browsing context to another (for example, across sites) to help combat fraud, without passive tracking. +## Reporting issues with third-party cookies and getting help -A suite of APIs is available to cover [ad relevance](/docs/privacy-sandbox/#show-relevant-content) and [measurement](/docs/privacy-sandbox/#measure-digital-ads) use cases such as interest-based advertising, on-device auctions for custom audiences, cross-site content selection, ad conversion measurement and attribution, and more. +We want to ensure we are capturing the various scenarios where sites break without third-party cookies to ensure that we have provided guidance, tooling, and functionality to allow sites to migrate away from their third-party cookie dependencies. If your site or a service you depend on is breaking with third-party cookies disabled, you can submit it to our breakage tracker at [goo.gle/report-3pc-broken](https://goo.gle/report-3pc-broken). -To learn more about how new APIs might serve use cases that are not covered in this post, explore the [Privacy Sandbox documentation](/docs/privacy-sandbox/). \ No newline at end of file +If you have questions around the deprecation process and Chrome's plan, you can [raise a new issue using the "third-party cookie deprecation" tag](https://github.com/GoogleChromeLabs/privacy-sandbox-dev-support/issues/new/choose) in our developer support repo. From b24e519110ad72748642af2705994df3466eec3c Mon Sep 17 00:00:00 2001 From: Oliver Dunk <oliverdunk@google.com> Date: Wed, 11 Oct 2023 16:20:15 +0100 Subject: [PATCH 886/982] Add callout about percentage rollout and new users (#7508) --- site/en/docs/extensions/migrating/publish-mv3/index.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/site/en/docs/extensions/migrating/publish-mv3/index.md b/site/en/docs/extensions/migrating/publish-mv3/index.md index 245b62b49..9486ba080 100644 --- a/site/en/docs/extensions/migrating/publish-mv3/index.md +++ b/site/en/docs/extensions/migrating/publish-mv3/index.md @@ -4,7 +4,7 @@ title: Publish your extension seoTitle: Publishing a new Manifest V3 Chrome extension. description: 'Guidance for publishing a new Manifest V3 extension' date: 2023-09-04 -# updated: 2023-05-10 +updated: 2023-09-11 --- After [converting your extension][migration-checklist] to Manifest Version 3, the next step is to @@ -84,6 +84,11 @@ To ensure that any unexpected problems will have minimal impact, you can roll ou 2. Go to the **Distribution** tab. 3. Enter a percentage in **Percentage rollout** field. +{% Aside %} +Percentage rollout only applies to existing users of your extension. New users will always receive +the new version. +{% endAside %} + <figure> {% Img src="image/BrQidfK9jaQyIHwdw91aVpkPiib2/oZxWW5oMsh7fUSzwvRNp.png", alt="Screenshot of the Chrome Web Store fractional rollout field", height="488", width="800", class='screenshot' %} <figcaption> From 4f949d3019f0ff744884c75d7d902c86b547339a Mon Sep 17 00:00:00 2001 From: Adam Argyle <argyle@google.com> Date: Wed, 11 Oct 2023 08:21:35 -0700 Subject: [PATCH 887/982] `new post` - CSS relative color syntax (#7483) * port * adds gui challenge video * Update date --- .../blog/css-relative-color-syntax/index.md | 741 ++++++++++++++++++ 1 file changed, 741 insertions(+) create mode 100644 site/en/blog/css-relative-color-syntax/index.md diff --git a/site/en/blog/css-relative-color-syntax/index.md b/site/en/blog/css-relative-color-syntax/index.md new file mode 100644 index 000000000..2fe21b8c1 --- /dev/null +++ b/site/en/blog/css-relative-color-syntax/index.md @@ -0,0 +1,741 @@ +--- +layout: layouts/blog-post.njk +title: CSS relative color syntax +description: > + Create new colors based on another color's channels and values. +subhead: > + Create new colors based on another color's channels and values. +date: 2023-10-11 +authors: + - argyle +tags: + - css +hero: image/vS06HQ1YTsbMKSFTIPl2iogUQP73/NJussb4uxzLcabHjaQ2m.png +thumb: image/vS06HQ1YTsbMKSFTIPl2iogUQP73/W7QVCQJLdkO69EqtdRC3.png +alt: > + A corridor of multi-colors frames, creating a rainbow hallway, is well lit and the light is blending colors inside the corridor. +--- + +In Chrome 119 is a very powerful color feature from [CSS Color Level +4](https://www.w3.org/TR/css-color-5/#relative-colors). Relative color syntax +creates a smooth path for color manipulation within CSS, offering ways for +authors and designers to: + + +- [Lighten](#lighten-a-color) +- [Darken](#darken-a-color) +- [Saturate](#saturate-a-color) +- [Desaturate](#desaturate-a-color) +- [Chroma boost](#chroma-boost-a-color) +- [Adjust opacity](#adjust-opacity-a-color) +- [Invert](#invert-a-color) +- [Compliment](#compliment-a-color) +- [Convert](#color-conversion) +- [Contrast](#contrast-a-color) +- [Color palettes](#color-palettes) + - [Monochromatic](#monochromatic-palettes) + - [Analogous](#analogous-palettes) + - [Triadic](#triadic-palettes) + - [Tetradic](#tetradic-palettes) + - [Monochromatic with hue rotation](#monochromatic-with-a-slight-hue-rotation) + +**Before** relative color syntax, to modify the opacity of a color, you need to +create custom properties for the channels of a color, usually HSL, and assemble +them into a final color and final variant color. This means managing a lot of +color pieces, which can quickly become burdensome. + +```css +:root { + --brand-hue: 300deg; + --brand-saturation: 75%; + --brand-lightness: 50%; + + --brand-hsl: + var(--brand-hue) + var(--brand-saturation) + var(--brand-lightness); + + --brand-color: hsl(var(--brand-hsl)); + + /* all this work just so I can set the opacity to 50% in a variant */ + --brand-color-variant: hsl(var(--brand-hsl) / 50%); +} +``` + +**After** relative color syntax, you can create a brand color with any color space +or syntax you need, and create a half opacity variant with much less code. It's +also much easier to read the intent of the styles and system. + +```css +:root { + --brand-color: hsl(300deg 75% 50%); + --brand-color-variant: hsl(from var(--brand-color) h s l / 50%); +} +``` + +This post will help you [learn the syntax](#syntax-overview) and [demonstrate +common color manipulations](#use-cases-and-demonstrations). + +If you prefer video, nearly all of the following article is covered in this GUI Challenge. + +{% YouTube "1z_ViBjdnSw" %} + +## Syntax overview + +The goal of relative color syntax is to allow deriving a color from another +color. The base color is called the originating color, this is the color that +comes after the new [`from`](#the-from-keyword) keyword. The browser will +[convert](#color-conversion) and break this originating color apart and offer +the parts as variables for use in the new color definition. + +{% Img src="image/vS06HQ1YTsbMKSFTIPl2iogUQP73/fcj6GoebbLUlujPUwtlO.png", alt="A +diagram of the syntax rgb(from green r g b / alpha) is shown, with an arrow +leaving the top of green and arching into the rgb beginning of the function, +this arrow splits into 4 arrows that then point to their relevant variable. The +4 arrows are red, green, blue and alpha. Red and blue have a value of 0, green +is 128 and alpha is 100%.", width="800", height="530" %} + +The preceding diagram shows the originating color `green` being converted to the +new color's [color +space](/articles/high-definition-css-color-guide/#a-review-of-the-classic-color-spaces), +turned into individual numbers represented as `r`, `g`, `b`, and `alpha` +variables, which are then directly used as a new `rgb()` color's values. + +While this image shows the breakdown, process and variables, it's also not +changing the color. The variables are put back into the color unchanged, thus +resulting in a green color still. + +{% Aside %} For a review on specifying colors, visit the [high definition color +guide](/articles/high-definition-css-color-guide/) for all the information you +need about web color. This post assumes familiarity with functional color +notation, color spaces like OKLCH and color gamuts. {% endAside %} + +### The `from` keyword + +The first part of the syntax to learn is the part `from <color>` addition to +specifying a color. It goes right before you specify the values. Here's a code +example where all that has been added is `from green`, right before the values +for `rgb()` are specified. + +```css +.syntax-introduction_same-colors { + color: green; + color: rgb(0 128 0); + color: rgb(from green r g b); /* result = rgb(0 128 0) */ +} +``` + +That `from` keyword, when seen as the first parameter in functional notation, +turns the color definition into a relative color! After the `from` keyword, CSS +expects a color, **a color that will inspire the next color**. + +### Color conversion + +In simpler terms, it converts green to r g and b channels for use in a new +color. + +```css +rgb(from green r g b) /* r=0 g=128 b=0 */ +rgb(from rgb(0 128 0) r g b); /* r=0 g=128 b=0 */ +``` + +### Colors from custom properties + +Reading `rgb from green` is very clear and easy to understand. This is why +custom properties and relative color syntax make such a great match, because you +can take the mystery out of the `from` color. You also don't generally need to +know the color format of the custom property color, as you're creating a new +color in a format of your choice. + +```css +rgb(from rgb(255 105 180) r g b) /* ????? */ +rgb(from var(--hotpink) r g b) /* clear */ +``` + +### Work in your preferred color space + +You can choose the color space with your choice of functional color notation. + +```css +rgb(from hsl(120 100% 25%) r g b) /* r=0 g=128 b=0 */ +hsl(from hsl(120 100% 25%) h s l) /* h=120 s=100% l=25% */ +hwb(from hsl(120 100% 25%) h w b) /* h=120 w=0% b=50% */ +lch(from hsl(120 100% 25%) l c h) /* l=46 c=68 h=134 */ +``` + +The relative color syntax has that conversion step; the color after `from` is +converted into the color space as specified at the beginning of the relative +color. The input and output don't need to match, which is very liberating. + +The ability to choose a color space is also empowering, as choosing a color +space tends to be more focused around the type of color alternation than it is a +preference. The preference is in the results, not the color format or channel +types. This will become much clearer in the sections demonstrating use cases, as +different color spaces excel at different tasks. + +### Mix, match, omit and repeat the variables + +Something strange but exciting about this syntax, the variables don't have to be +put back in order and can be repeated. + +```css +rgb(from green g g g) /* rgb(128 128 128) */ +rgb(from green b r g) /* rgb(0 0 128) */ +rgb(from green 0 0 g) /* rgb(0 0 128) */ +``` + +### Opacity as a variable + +The syntax also provides the opacity as a variable named `alpha`. It's optional, +and goes after the `/` in the functional color notation. + +```css +rgb(from #00800080 r g b / alpha) /* alpha=50% */ +rgb(from rgba(0,128,0,.5) r g b / alpha) /* alpha=50% */ +rgb(from rgb(0 128 0 / 50%) r g b / alpha) /* alpha=50% */ +``` + +### Use calc() or other CSS functions on the variables + +So far we've been creating the color green over and over again. Learning the +syntax, getting familiar with the conversion and destructuring steps. Now is +time to modify the variables, alter the output so it's not the same as the +input. + +```css +green /* h=120 s=100% l=25% */ +hsl(from green calc(h * 2) s l) /* h=240 s=100% l=25% */ +``` + +It's navy now! The hue was doubled, taking a hue of `120` and turning it into +`240`, completely altering the color. This rotated the hue along the color +wheel, a neat trick made very simple with [cylindrical color +spaces](https://en.wikipedia.org/wiki/Color_model#Cylindrical-coordinate_color_models) +like [HSL](/articles/high-definition-css-color-guide/#hsl), +[HWB](/articles/high-definition-css-color-guide/#hwb), +[LCH](/articles/high-definition-css-color-guide/#lch), and +[OKLCH](/articles/high-definition-css-color-guide/#oklch). + +### Check for browser support + +```css +@supports (color: rgb(from white r g b)) { + /* safe to use relative color syntax */ +} +``` + +## Use cases and demonstrations + +The following examples and use cases have many alternative syntaxes to achieve +similar or the same results. The variations come from the color spaces and the +channels they offer. + +Also, many examples will show color adjustments with the verbiage of `by` and +`to`. A color changed `by` is a relative color change; a change that uses the +value of the variable and makes an adjustment based on its current value. A +color changed `to` is an absolute color change; a change that does not use the +value of the variable and instead specifies a completely new value. + +All demo's can be found in this [Codepen +collection](https://codepen.io/collection/eJPQjM). + +### Lighten a color + +The OKLCH, [OKLAB](/articles/high-definition-css-color-guide/#oklab), +[XYZ](/articles/high-definition-css-color-guide/#xyz-xyz-d50-xyz-d65) or +[sRGB](/articles/high-definition-css-color-guide/) color spaces provide the most +predictable results when lightening colors. + +{% Aside %} Learn more about predictable results for gradients in this +[episode](https://www.youtube.com/watch?v=w_vk1j8aYmU) of the CSS podcast. {% +endAside %} + +#### Lighten by an amount + +The following example `.lighten-by-25` takes the color `blue` and converts it to +OKLCH, then lightens the blue by increasing the `l` (lightness) channel by 25. +This pushes the blue color towards white by 25%. + +```css +.lighten-by-25 { + background: oklch(from blue calc(l + 25) c h); +} +``` + +{% Codepen { + user: 'web-dot-dev', + id: 'NWeoqmV', + tab: 'result' +} %} + +#### Lighten to a specific value + +The following example `.lighten-to-75` doesn't utilize the `l` channel to +lighten `blue`, it instead completely replaces the value with `75%`. + +```css +.lighten-to-75 { + background: oklch(from blue 75% c h); +} +``` + +{% Codepen { + user: 'web-dot-dev', + id: 'bGOzVNP', + tab: 'result' +} %} + +### Darken a color + +The same color spaces effective at lightening a color, are also great for +darkening color. + +#### Darken by an amount + +The following example `.darken-by-25` takes the color blue and converts it to +OKLCH, then darkens the blue by decreasing the `l` (lightness) channel by 25. +This pushes the blue color towards black by 25%. + +```css +.darken-by-25 { + background: oklch(from blue calc(l - 25) c h); +} +``` + +{% Codepen { + user: 'web-dot-dev', + id: 'jOXdbbP', + tab: 'result' +} %} + +#### Darken to a specified value + +The following example `.darken-to-25` doesn't utilize the `l` channel to darken +`blue`, it instead completely replaces the value with `25%`. + +```css +.darken-to-25 { + background: oklch(from blue 25% c h); +} +``` + +{% Codepen { + user: 'web-dot-dev', + id: 'RwEvWWe', + tab: 'result' +} %} + +### Saturate a color + +#### Saturate by an amount + +The following example `.saturate-by-25` uses the `s` from `hsl()` to increase +`orchid`'s vibrance by `25%`. + +```css +.saturate-by-25 { + background: hsl(from orchid h calc(s + .25) l); +} +``` + +{% Codepen { + user: 'web-dot-dev', + id: 'GRPzpoP', + tab: 'result' +} %} + +#### Saturate to a specific amount + +The following example `.saturate-to-100` doesn't utilize the `s` channel from +`hsl()`, it instead specifies a desired saturation value. In this example, +saturation is raised to `100%`. + +```css +.saturate-to-100 { + background: hsl(from orchid h 100% l); +} +``` + +{% Codepen { + user: 'web-dot-dev', + id: 'xxmMwVP', + tab: 'result' +} %} + +### Desaturate a color + +#### Desaturate by an amount + +The following example `.desaturate-by-50` uses the `s` from `hsl()` to decrease +the saturation of `indigo` by 50%, essentially cutting it in half. This could +have also been done with division like `calc(s / 2)`. + +```css +.desaturate-by-50 { + background: hsl(from indigo h calc(s - .5) l); +} +``` + +{% Codepen { + user: 'web-dot-dev', + id: 'VwqgvjB', + tab: 'result' +} %} + +#### Desaturate to a specific value + +Rather than desaturate by an amount, you can desaturate to a specific desired +value. The following example `.desaturate-to-25` creates a new color based on +`indigo` but sets the saturation to 25%. + +```css +.desaturate-to-25 { + background: hsl(from indigo h 25% l); +} +``` + +{% Codepen { + user: 'web-dot-dev', + id: 'KKbJdgV', + tab: 'result' +} %} + +### Chroma boost a color + +This effect is similar to saturating a color but is different in a couple of +ways. Firstly, it's a `chroma` change and not a `saturation` change, and this is +because the color spaces that can boost into high dynamic range don't use +saturation. The color spaces which feature `chroma` are high dynamic range +capable, allowing authors to boost color vibrance further than saturation is +even capable of. + +```css +.increase-chroma { + background: oklch(from orange l calc(c + .1) h); +} +``` + +{% Codepen { + user: 'web-dot-dev', + id: 'MWZLabj', + tab: 'result' +} %} + +### Adjust opacity a color + +Making a semi-transparent variant of a color is one of the most common color +adjustments done in design systems. See the example in the introduction of this +article if you missed it, it outlines the problem space really well. + +#### Adjust opacity by an amount + +```css +.decrease-opacity-by-25 { + background: rgb(from lime r g b / calc(alpha - .25)); +} +``` + +{% Codepen { + user: 'web-dot-dev', + id: 'abPaJKJ', + tab: 'result' +} %} + +#### Adjust opacity to a specific value + +```css +.decrease-opacity-to-25 { + background: rgb(from lime r g b / 25%); +} +``` + +{% Codepen { + user: 'web-dot-dev', + id: 'ZEVwbeL', + tab: 'result' +} %} + +### Invert a color + +Color inversion is a common color adjustment function found in color libraries. +One way to accomplish this is to convert a color to RGB then subtract each +channel's value from 1. + +```css +.invert-each-rgb-channel { + background: rgb(from yellow calc(1 - r) calc(1 - g) calc(1 - b)); +} +``` + +{% Codepen { + user: 'web-dot-dev', + id: 'xxmaqQL', + tab: 'result' +} %} + +### Compliment a color + +If your goal wasn't to invert a color but rather complement it, then hue +rotation is likely what you're looking for. Pick a color space which offers the +hue as an angle, then use `calc()` to rotate the hue by an amount you want. +Finding a color's complement is done by rotating by half a turn, in this case +you can add or subtract from the `h` channel by `180` to achieve the result. + +```css +.complimentary-color { + background: hsl(from blue calc(h + 180) s l); +} +``` + +{% Codepen { + user: 'web-dot-dev', + id: 'bGOzVRN', + tab: 'result' +} %} + +### Contrast a color + +As a method of achieving accessible color contrast ratios, consider L* (Lstar). +This uses the (approximately) perceptually uniform lightness (L) channel from +LCH and OKLCH, in a `calc()`. Depending if you are targeting low, medium or high +contrast, the L* delta is around ~40, ~50, or ~60. + +{% Codepen { + user: 'web-dot-dev', + id: 'xxmMZOM', + tab: 'result' +} %} + +This technique works well across any hue in LCH or OKLCH. + +#### Contrast a darker color + +The `.well-contrasting-darker-color` class demonstrates L* with a delta of 60. +Since the originating color is a dark color (low value lightness), 60 is added +to the lightness channel. This technique is used to find a well contrasting, +same hue, dark text color on a light background. + +```css +.well-contrasting-darker-color { + background: darkred; + color: oklch(from darkred calc(l + 60) c h); +} +``` + +{% Codepen { + user: 'web-dot-dev', + id: 'jOXdbLq', + tab: 'result' +} %} + +#### Contrast a lighter color + +The `.well-contrasting-lighter-color` class demonstrates L* with a delta of 60 +also. Since the originating color is a light color (high value lightness), 60 is +subtract from the lightness channel. + +```css +.well-contrasting-lighter-color { + background: lightpink; + color: oklch(from lightpink calc(l - 60) c h); +} +``` + +{% Codepen { + user: 'web-dot-dev', + id: 'mdavVRV', + tab: 'result' +} %} + +### Color palettes + +Relative color syntax is very good at creating color palettes. It's especially +useful and powerful due to the number of color spaces available. The following +examples all use OKLCH because the lightness channel is reliable and the hue +channel can be rotated without side effects. The final example demonstrates a +combination of lightness and hue rotation adjustments for a more interesting +result! + +Open the example source code for these and try changing the `--base-color`, to +see just how dynamic these palettes are. It's fun! + +If you like video, I give in depth information about [building color palettes in +CSS with OKLCH on YouTube](https://www.youtube.com/watch?v=6aCsAMgwnjE). + +{% YouTube "6aCsAMgwnjE" %} + +#### Monochromatic palettes + +To create a monochromatic palette is to make a palette all from the same hue but +with variations in lightness and darkness. The middle color is the source color +for the palette, where two lighter and two darker variants are put on either +side. + +```css +:root { + --base-color: deeppink; + + --color-0: oklch(from var(--base-color) calc(l + 20) c h); /* lightest */ + --color-1: oklch(from var(--base-color) calc(l + 10) c h); + --color-2: var(--base-color); + --color-3: oklch(from var(--base-color) calc(l - 10) c h); + --color-4: oklch(from var(--base-color) calc(l - 20) c h); /* darkest */ +} +``` + +{% Codepen { + user: 'web-dot-dev', + id: 'eYbxpeR', + tab: 'result' +} %} + +##### Try out a bunch of palettes made with relative color syntax and OKLCH + +[Open Props](https://open-props.style), a library of free CSS variables, offers +color palettes built with this strategy and makes them easily usable with an +import. They're also all built off of a color you can customize, you just give +it a color and it spits out a palette! + +{% Codepen { + user: 'web-dot-dev', + id: 'yLGZYpg', + tab: 'result' +} %} + +#### Analogous palettes + +Since hue rotation is so easy with OKLCH and HSL, it's trivial to create an +[analogous color palette](https://en.wikipedia.org/wiki/Analogous_colors). +Rotate the hue by an amount you like the results of and change the base color, +and watch new palettes get built by the browser. + +```css +:root { + --base-color: blue; + + --primary: var(--base-color); + --secondary: oklch(from var(--base-color) l c calc(h - 45)); + --tertiary: oklch(from var(--base-color) l c calc(h + 45)); +} +``` + +{% Codepen { + user: 'web-dot-dev', + id: 'ZEVwbry', + tab: 'result' +} %} + +#### Triadic palettes + +Similar to complimentary colors, [triadic color +palettes](https://www.studiobinder.com/blog/what-is-a-triadic-color-scheme-definition/) +are opposing but harmonious hue rotations given a base color. Where a +complementary color is on the opposite side of a color, like a straight line +drawn through the middle of the color wheel, triadic palettes are like a +triangle of lines, finding 2 colors equally rotated from a base color. +Accomplish this by rotating the hue `120deg`. + +This is a slight simplification of the color theory, but it's enough to kick +start you into the more complex triadic palettes if you're interested. + +```css +:root { + --base-color: yellow; + --triad-1: oklch(from var(--base-color) l c calc(h - 120)); + --triad-2: oklch(from var(--base-color) l c calc(h + 120)); +} +``` + +{% Codepen { + user: 'web-dot-dev', + id: 'KKbJdoN', + tab: 'result' +} %} + +#### Tetradic palettes + +Tetradic palettes are four colors evenly divided around the color wheel, making +a palette with no clear dominant value. You could think of it too, like two +pairs of complementary colors. Used wisely, it can be very meaningful. + +This is a slight simplification of the color theory, but it's enough to kick +start you into the more complex tetradic palettes if you're interested. + +```css +:root { + --base-color: lime; + + --color-1: var(--base-color); + --color-2: oklch(from var(--base-color) l c calc(h + 90)); + --color-3: oklch(from var(--base-color) l c calc(h + 180)); + --color-4: oklch(from var(--base-color) l c calc(h + 270)); +} +``` + +{% Codepen { + user: 'web-dot-dev', + id: 'WNLPQJw', + tab: 'result' +} %} + +#### Monochromatic with a slight hue rotation + +Many color experts keep this trick up their sleeve. The problem is, a +monochromatic color scale can be quite boring. The solution is to add either a +minor or major hue rotation to each new color as the lightness is changed. + +The following example decreases lightness by 10% each swatch and also rotates +the hue by 10 degrees. The result, a hotpink to indigo palette that seems to +seamlessly blend like a gradient might. + +```css +:root { + --base-color: deeppink; + + --color-1: var(--base-color); + --color-2: oklch(from var(--base-color) calc(l - 10) c calc(h - 10)); + --color-3: oklch(from var(--base-color) calc(l - 20) c calc(h - 20)); + --color-4: oklch(from var(--base-color) calc(l - 30) c calc(h - 30)); + --color-5: oklch(from var(--base-color) calc(l - 40) c calc(h - 40)); +} +``` + +{% Codepen { + user: 'web-dot-dev', + id: 'PoXVPaY', + tab: 'result' +} %} + +##### Try out this leaderboard built with OKLCH and hue rotation + +The following leaderboard interface uses this hue rotation strategy. Each list +item tracks its index in the document as a variable called `--i`. This index is +then used to adjust chroma, lightness and hue. The adjustment is only by 5% or +5deg, much more subtle than the above example with deeppink, and so it takes a +keen eye to notice the reason this leaderboard can be in any hue with such +elegance. + +Be sure to change the hue in the slider underneath the leaderboard, and see +relative color syntax create beautiful color moments. + +```css +li { + --_bg: oklch( + /* decrease lightness as list grows */ + calc(75% - (var(--i) * 5%)) + + /* decrease chroma as list grows */ + calc(.2 - (var(--i) * .01)) + + /* lightly rotate the hue as the list grows */ + calc(var(--hue) - (var(--i) + 5)) + ); +} +``` + +{% Codepen { + user: 'web-dot-dev', + id: 'YzdByvg', + height: 600, + tab: 'result' +} %} From 9b10eebc19697daad2c03080ccf80a23880f7f95 Mon Sep 17 00:00:00 2001 From: Barry Pollard <barrypollard@google.com> Date: Wed, 11 Oct 2023 16:45:08 +0100 Subject: [PATCH 888/982] Misc updates to 103 early hints article (#7510) --- site/en/blog/early-hints/index.md | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/site/en/blog/early-hints/index.md b/site/en/blog/early-hints/index.md index 68d6155f7..23a240189 100644 --- a/site/en/blog/early-hints/index.md +++ b/site/en/blog/early-hints/index.md @@ -7,7 +7,7 @@ description: > subhead: > Find out how your server can send hints to the browser about critical sub-resources. date: 2022-06-23 -updated: 2023-08-02 +updated: 2023-10-11 authors: - kenjibaheux - tunetheweb @@ -39,7 +39,7 @@ Early Hints is an HTTP status code (`103 Early Hints`) used to send a preliminar <figcaption>With Early Hints: the server can serve a partial response with resource hints while it determines the final response</figcaption> </figure> -In some cases, the performance improvement to the [Largest Contentful Paint](http://web.dev/lcp) can go from several hundred milliseconds, as observed by [Shopify](https://twitter.com/colinbendell/status/1539322190541295616) and [by Cloudflare](http://blog.cloudflare.com/early-hints-performance), and up to a second faster, as seen in this before/after comparison: +In some cases, the performance improvement to the [Largest Contentful Paint](http://web.dev/articles/lcp) can go from several hundred milliseconds, as observed by [Shopify](https://twitter.com/colinbendell/status/1539322190541295616) and [by Cloudflare](http://blog.cloudflare.com/early-hints-performance), and up to a second faster, as seen in this before/after comparison: <figure> @@ -52,20 +52,22 @@ In some cases, the performance improvement to the [Largest Contentful Paint](htt {% BrowserCompat 'http.status.103' %} -Early Hints is available from Chrome version 103, as a response to navigation requests, or user interactions that change the url in the status bar, with support for both preconnect and preload hints. Other browsers are adding support for preconnect. +Early Hints is available from Chrome version 103, as a response to navigation requests, or user interactions that change the url in the status bar, with support for both preconnect and preload hints. Safari has support for preconnect hints from Safari 17, and Firefox is working on support for preconnect. Before going deep into the topic, please note that Early Hints are not useful if your server can send a 200 (or other final responses) right away. Instead, consider using the regular `link rel=preload` or `link rel=preconnect` on the main response ([Link rel HTTP header](https://developer.mozilla.org/docs/Web/HTTP/Headers/Link)), or in the main response (`<link>` elements), in such situations. For the cases where your server needs a little time to generate the main response, read on! The first step to take advantage of Early Hints consists of identifying the top landing pages, that is, the pages where your users typically start when they visit your website. This could be the homepage, or popular product listing pages if you have lots of users coming from other websites. The reason these entry points matter more than other pages is because Early Hints' usefulness decreases as the user navigates around your website (that is, the browser is more likely to have all the sub-resources it needs on the second or third subsequent navigation). It's also always a good idea to deliver a great first impression! -Now that you have this prioritized list of landing pages, the next step consists of identifying which origins or sub-resources would be good candidates for [preconnect](https://web.dev/uses-rel-preconnect) or [preload](https://web.dev/preload-critical-assets/) hints, as a first approximation. Typically, those would be origins and sub-resources that contribute the most to key user metrics such as [Largest Contentful Paint](https://web.dev/lcp/), or [First Contentful Paint](https://web.dev/first-contentful-paint/). More concretely, look for render-blocking sub-resources such as synchronous JavaScript, stylesheets, or even web fonts. Similarly, look for origins that host sub-resources that contribute a lot to key user metrics. Note: if your main resources are already using `<link rel=preconnect>` or `<link rel=preload>`, you may consider these origins or resources among the candidates for Early Hints. See [this article](https://web.dev/lcp/#how-to-improve-lcp) for more details. +Now that you have this prioritized list of landing pages, the next step consists of identifying which origins or sub-resources would be good candidates for [preconnect](https://web.dev/articles/uses-rel-preconnect) or [preload](https://web.dev/articles/preload-critical-assets) hints, as a first approximation. Typically, those would be origins and sub-resources that contribute the most to key user metrics such as [Largest Contentful Paint](https://web.dev/articles/lcp), or [First Contentful Paint](https://web.dev/articles/fcp). More concretely, look for render-blocking sub-resources such as synchronous JavaScript, stylesheets, or even web fonts. Similarly, look for origins that host sub-resources that contribute a lot to key user metrics. Note: if your main resources are already using `<link rel=preconnect>` or `<link rel=preload>`, you may consider these origins or resources among the candidates for Early Hints. See [this article](https://web.dev/articles/lcp/#how-to-improve-lcp) for more details. {% Aside 'important' %} What you decide to `preconnect` or `preload` as Early Hints may differ from what you have traditionally used these directives for in your HTML. -When using these in HTML you typically want to `preconnect` or `preload` resources that the [Preload Scanner](https://web.dev/preload-scanner/) will not discover in the HTML—for example, fonts, or background images that would otherwise be discovered late. For Early Hints you will not have the HTML and so you may want to instead `preconnect` to critical domains or `preload` critical resources that perhaps _would_ otherwise be discovered early in the HTML—for example, preloading `main.css` or `app.js`. +When using these in HTML you typically want to `preconnect` or `preload` resources that the [Preload Scanner](https://web.dev/articles/preload-scanner) will not discover in the HTML—for example, fonts, or background images that would otherwise be discovered late. For Early Hints you will not have the HTML and so you may want to instead `preconnect` to critical domains or `preload` critical resources that perhaps _would_ otherwise be discovered early in the HTML—for example, preloading `main.css` or `app.js`. Niavely copying the `preconnect` and `preload` directives from HTML to Early Hints [may not be optimal](https://www.youtube.com/watch?v=0kKdMqIhvZs&t=2285s). + +Additionally only Chrome supports `preload` for Early Hints. {% endAside %} The second step consists of minimizing the risk of using Early Hints on resources or origins that might be obsolete, or no longer used by the main resource. For instance, resources that are frequently updated and versioned (for example, `example.com/css/main.fa231e9c.css`) may not be the best choice. Note that this concern isn't specific to Early Hints, it applies to any link `rel=preload` or `rel=preconnect` wherever they might be present. This is the sort of detail that's best dealt with automation or templating (for example, a manual process is more likely to lead to mismatched hash or version urls between `link rel=preload` and the actual HTML tag using the resource). @@ -154,6 +156,7 @@ If you are using one of the following CDNs or platforms, you may not need to man - [Early Hints at Cloudflare](https://developers.cloudflare.com/cache/about/early-hints/) - [Early Hints at Fastly](https://www.fastly.com/blog/beyond-server-push-experimenting-with-the-103-early-hints-status-code#:~:text=about%20this%20feature.-,Sending%20103%20Early%20Hints,in%20VCL%2C%20like%20this%3A). +- [Early Hints at Akamai](https://www.akamai.com/blog/performance/akamai-103-early-hints-prototype-the-results-are-in). ## Avoiding issues for clients that do not support Early Hints @@ -177,6 +180,8 @@ Here are the limitations of Early Hints as implemented in Chrome 103 and future - Only supports preconnect and preload (that is, prefetch isn't supported). - Early Hint followed by a cross-origin redirect on the final response will result in Chrome dropping the resources and connections it obtained via Early Hints. +Other browsers have similar limitations, and further restrict 103 early hints to preconnect only. + ## What's next? Depending on interest from the community, we may augment our implementation of Early Hints with the following capabilities: From e6f895ab0d9292a2cb1f56376596babd4594c178 Mon Sep 17 00:00:00 2001 From: Barry Pollard <barrypollard@google.com> Date: Wed, 11 Oct 2023 19:56:11 +0100 Subject: [PATCH 889/982] Update web.dev links to new format (#7513) * Update web.dev links to new format * More fixes --- .../attribution-reporting/index.md | 6 +- .../privacy-sandbox/first-party-sets/index.md | 2 +- site/de/docs/privacy-sandbox/floc/index.md | 2 +- .../de/docs/privacy-sandbox/glossary/index.md | 2 +- .../de/docs/privacy-sandbox/overview/index.md | 10 +- site/de/docs/privacy-sandbox/status/index.md | 16 +-- .../privacy-sandbox/trust-tokens/index.md | 6 +- .../lighthouse-performance/js-perf.md | 8 +- .../glossary-entries/origin-trial.md | 4 +- .../timeline/first-party-sets.md | 2 +- .../timeline/private-state-tokens.md | 4 +- site/en/articles/at-scope/index.md | 4 +- .../index.md | 6 +- site/en/articles/browser-fs-access/index.md | 2 +- .../en/articles/content-indexing-api/index.md | 10 +- .../articles/cors-rfc1918-feedback/index.md | 2 +- .../css-linear-easing-function/index.md | 2 +- site/en/articles/css-nesting/index.md | 8 +- site/en/articles/css-nth-child-of-s/index.md | 2 +- .../articles/declarative-shadow-dom/index.md | 6 +- site/en/articles/display-override/index.md | 2 +- .../fetch-streaming-requests/index.md | 2 +- site/en/articles/file-handling/index.md | 10 +- site/en/articles/generic-sensor/index.md | 2 +- site/en/articles/hidden-until-found/index.md | 4 +- site/en/articles/inp-in-frameworks/index.md | 12 +- site/en/articles/isinputpending/index.md | 4 +- site/en/articles/local-fonts/index.md | 2 +- .../articles/long-animation-frames/index.md | 16 +-- .../index.md | 2 +- site/en/articles/page-lifecycle-api/index.md | 2 +- .../periodic-background-sync/index.md | 4 +- .../renderingng-architecture/index.md | 4 +- .../renderingng-data-structures/index.md | 4 +- site/en/articles/renderingng/index.md | 8 +- site/en/articles/reporting-api/index.md | 4 +- .../scroll-driven-animations/index.md | 2 +- .../articles/user-agent-client-hints/index.md | 2 +- site/en/articles/wake-lock/index.md | 2 +- site/en/articles/web-otp/index.md | 6 +- site/en/articles/web-share-target/index.md | 6 +- .../en/articles/x-google-ignore-list/index.md | 10 +- .../blog/300ms-tap-delay-gone-away/index.md | 2 +- .../index.md | 2 +- site/en/blog/a2hs-updates/index.md | 12 +- .../advanced-web-apps-fund-oct-22/index.md | 2 +- site/en/blog/advanced-web-apps-fund/index.md | 2 +- site/en/blog/angular-image-directive/index.md | 22 ++-- site/en/blog/animated-blur/index.md | 6 +- .../index.md | 14 +- .../anonymous-iframe-origin-trial/index.md | 16 +-- .../blog/app-install-banners-native/index.md | 2 +- site/en/blog/app-shell/index.md | 2 +- site/en/blog/ar-for-the-web/index.md | 10 +- .../audio-worklet-design-pattern/index.md | 2 +- .../en/blog/aurora-resource-inlining/index.md | 6 +- site/en/blog/aurora-update-2023/index.md | 24 ++-- .../index.md | 8 +- site/en/blog/avoid-not-secure-warn/index.md | 2 +- site/en/blog/background-fetch/index.md | 8 +- site/en/blog/background_tabs/index.md | 2 +- site/en/blog/beyond-spa/index.md | 8 +- site/en/blog/browser-flags/index.md | 2 +- site/en/blog/canvas2d/index.md | 4 +- site/en/blog/capabilities/index.md | 2 +- site/en/blog/cascade-layers/index.md | 2 +- site/en/blog/chrome-107-beta/index.md | 26 ++-- site/en/blog/chrome-108-beta/index.md | 24 ++-- site/en/blog/chrome-110-beta/index.md | 30 ++--- site/en/blog/chrome-111-beta/index.md | 24 ++-- site/en/blog/chrome-115-beta/index.md | 22 ++-- site/en/blog/chrome-119-beta/index.md | 32 ++--- site/en/blog/chrome-84-deps-rems/index.md | 12 +- site/en/blog/chrome-85-deps-rems/index.md | 12 +- .../chrome-dev-summit-mobile-summary/index.md | 2 +- site/en/blog/chrome-ux-report-api/index.md | 8 +- .../chrome-ux-report-history-api/index.md | 4 +- .../index.md | 8 +- .../index.md | 2 +- .../coep-credentialless-origin-trial/index.md | 14 +- site/en/blog/conformance/index.md | 2 +- .../en/blog/coop-restrict-properties/index.md | 24 ++-- site/en/blog/cq-polyfill/index.md | 8 +- .../blog/credential-management-api/index.md | 2 +- .../credential-management-updates/index.md | 8 +- site/en/blog/cross-device-webotp/index.md | 2 +- .../cross-origin-isolated-hr-timers/index.md | 4 +- site/en/blog/cross-origin-prefetch/index.md | 14 +- site/en/blog/crux-rank-magnitude/index.md | 2 +- site/en/blog/csp-issues/index.md | 4 +- site/en/blog/css-grid-tooling/index.md | 4 +- site/en/blog/css-in-js/index.md | 4 +- site/en/blog/css-update-media-query/index.md | 2 +- site/en/blog/cvd/index.md | 6 +- .../blog/debugging-speculation-rules/index.md | 4 +- site/en/blog/default-offline/index.md | 2 +- site/en/blog/deprecating-unload/index.md | 6 +- site/en/blog/deprecating-web-sql/index.md | 2 +- site/en/blog/deps-rems-100/index.md | 4 +- site/en/blog/deps-rems-99/index.md | 2 +- site/en/blog/devtools-autofill/index.md | 2 +- site/en/blog/devtools-tips-10/index.md | 2 +- site/en/blog/devtools-tips-17/index.md | 6 +- site/en/blog/devtools-tips-18/index.md | 4 +- site/en/blog/devtools-tips-20/index.md | 6 +- site/en/blog/devtools-tips-23/index.md | 4 +- site/en/blog/devtools-tips-24/index.md | 4 +- site/en/blog/devtools-tips-5/index.md | 6 +- site/en/blog/devtools-tips-6/index.md | 2 +- site/en/blog/devtools-tips-8/index.md | 6 +- site/en/blog/devtools-tips-9/index.md | 2 +- .../index.md | 14 +- site/en/blog/early-hints/index.md | 2 +- site/en/blog/embed-content/index.md | 20 +-- .../enabling-shared-array-buffer/index.md | 16 +-- .../index.md | 2 +- site/en/blog/extension-instantnav/index.md | 4 +- site/en/blog/fedcm-auto-reauthn/index.md | 94 +++++++------- .../blog/first-input-delay-in-crux/index.md | 4 +- .../blog/first-party-sets-sameparty/index.md | 90 ++++++------- site/en/blog/fledge-api/index.md | 12 +- site/en/blog/floc/index.md | 120 +++++++++--------- site/en/blog/framework-fund-2022/index.md | 2 +- .../framework-tools-font-fallback/index.md | 30 ++--- site/en/blog/fresher-sw/index.md | 2 +- site/en/blog/fugu-status/index.md | 6 +- .../index.md | 2 +- site/en/blog/getting-started-pwa/index.md | 2 +- site/en/blog/heavy-ad-interventions/index.md | 4 +- site/en/blog/help-css-nesting/index.md | 2 +- site/en/blog/hotpath-with-wasm/index.md | 6 +- .../index.md | 8 +- .../index.md | 2 +- .../index.md | 2 +- site/en/blog/http-cache-partitioning/index.md | 8 +- site/en/blog/iframe-credentialless/index.md | 22 ++-- site/en/blog/image-component/index.md | 20 +-- .../blog/immutable-document-domain/index.md | 10 +- .../improved-pwa-offline-detection/index.md | 2 +- site/en/blog/inp-tools-2022/index.md | 12 +- .../index.md | 10 +- site/en/blog/insider-april-2022/index.md | 32 ++--- site/en/blog/insider-dec-22/index.md | 12 +- site/en/blog/insider-july-2022/index.md | 26 ++-- site/en/blog/insider-oct-2022/index.md | 26 ++-- site/en/blog/introducing-aurora/index.md | 2 +- .../index.md | 8 +- site/en/blog/is-project-fugu-done/index.md | 12 +- .../index.md | 2 +- site/en/blog/lighthouse-10-0/index.md | 8 +- site/en/blog/lighthouse-11-0/index.md | 2 +- site/en/blog/lighthouse-8-4/index.md | 8 +- site/en/blog/lighthouse-9-0/index.md | 6 +- .../blog/lighthouse-load-performance/index.md | 8 +- .../en/blog/media-query-range-syntax/index.md | 4 +- .../memory-and-energy-saver-mode/index.md | 2 +- site/en/blog/mini-infobar-update/index.md | 2 +- .../index.md | 4 +- site/en/blog/new-in-chrome-101/index.md | 4 +- site/en/blog/new-in-chrome-102/index.md | 2 +- site/en/blog/new-in-chrome-103/index.md | 2 +- site/en/blog/new-in-chrome-107/index.md | 4 +- site/en/blog/new-in-chrome-108/index.md | 6 +- site/en/blog/new-in-chrome-109/index.md | 2 +- site/en/blog/new-in-chrome-113/index.md | 22 ++-- site/en/blog/new-in-chrome-76/index.md | 2 +- site/en/blog/new-in-chrome-80/index.md | 12 +- site/en/blog/new-in-chrome-84/index.md | 16 +-- site/en/blog/new-in-chrome-85/index.md | 12 +- site/en/blog/new-in-chrome-86/index.md | 2 +- site/en/blog/new-in-chrome-88/index.md | 2 +- site/en/blog/new-in-chrome-89/index.md | 10 +- site/en/blog/new-in-chrome-96/index.md | 2 +- site/en/blog/new-in-devtools-101/index.md | 10 +- site/en/blog/new-in-devtools-102/index.md | 18 +-- site/en/blog/new-in-devtools-104/index.md | 2 +- site/en/blog/new-in-devtools-105/index.md | 10 +- site/en/blog/new-in-devtools-106/index.md | 4 +- site/en/blog/new-in-devtools-112/index.md | 10 +- site/en/blog/new-in-devtools-113/index.md | 2 +- site/en/blog/new-in-devtools-114/index.md | 4 +- site/en/blog/new-in-devtools-117/index.md | 2 +- site/en/blog/new-in-devtools-118/index.md | 2 +- site/en/blog/new-in-devtools-119/index.md | 6 +- site/en/blog/new-in-devtools-89/index.md | 4 +- site/en/blog/new-in-devtools-91/index.md | 20 +-- site/en/blog/new-in-devtools-92/index.md | 2 +- site/en/blog/new-in-devtools-93/index.md | 6 +- site/en/blog/new-in-devtools-96/index.md | 20 +-- site/en/blog/new-in-devtools-98/index.md | 42 +++--- site/en/blog/new-in-devtools-99/index.md | 8 +- site/en/blog/no-spooky-cookies/index.md | 4 +- .../index.md | 10 +- .../blog/passkeys-on-icloud-keychain/index.md | 4 +- .../index.md | 12 +- .../payment-handler-csp-connect-src/index.md | 8 +- site/en/blog/permissions-chip/index.md | 2 +- site/en/blog/prerender-pages/index.md | 8 +- .../blog/privacy-sandbox-participate/index.md | 26 ++-- .../privacy-sandbox-update-2021-jan/index.md | 34 ++--- .../private-network-access-preflight/index.md | 8 +- .../private-network-access-update/index.md | 20 +-- .../index.md | 4 +- .../index.md | 2 +- .../index.md | 2 +- .../index.md | 6 +- .../index.md | 20 +-- site/en/blog/removing-document-write/index.md | 4 +- site/en/blog/removing-push/index.md | 2 +- .../blog/richer-install-ui-desktop/index.md | 2 +- site/en/blog/richer-pwa-installation/index.md | 2 +- site/en/blog/script-component/index.md | 16 +-- site/en/blog/search-ads-speed/index.md | 18 +-- site/en/blog/site-affiliation/index.md | 74 +++++------ .../blog/soft-navigations-experiment/index.md | 14 +- site/en/blog/sxg-desktop/index.md | 20 +-- .../sync-methods-for-accesshandles/index.md | 2 +- site/en/blog/tablesng/index.md | 20 +-- .../index.md | 2 +- site/en/blog/third-party-scripts/index.md | 14 +- .../timer-throttling-in-chrome-88/index.md | 8 +- site/en/blog/top-layer-devtools/index.md | 18 +-- .../index.md | 6 +- .../index.md | 6 +- .../index.md | 8 +- .../index.md | 16 +-- .../view-transitions-case-studies/index.md | 42 +++--- .../en/blog/viewport-resize-behavior/index.md | 10 +- .../index.md | 6 +- .../we-are-chrome-for-developers/index.md | 30 ++--- .../en/blog/web-animations-resources/index.md | 2 +- .../index.md | 2 +- site/en/blog/web-push-encryption/index.md | 2 +- site/en/blog/webauthn-conditional-ui/index.md | 12 +- site/en/blog/whats-new-css-ui-2023/index.md | 58 ++++----- .../index.md | 40 +++--- .../play-billing/index.md | 2 +- .../receive-payments-play-billing/index.md | 6 +- site/en/docs/crux/about/index.md | 2 +- site/en/docs/crux/bigquery/index.md | 2 +- site/en/docs/crux/dashboard/index.md | 6 +- site/en/docs/crux/methodology/index.md | 14 +- site/en/docs/crux/release-notes/index.md | 90 ++++++------- .../devtools/accessibility/contrast/index.md | 4 +- .../devtools/accessibility/reference/index.md | 4 +- .../application/back-forward-cache/index.md | 10 +- site/en/docs/devtools/css/color/index.md | 6 +- .../devtools/css/container-queries/index.md | 4 +- site/en/docs/devtools/css/reference/index.md | 2 +- .../en/docs/devtools/elements/badges/index.md | 6 +- .../javascript/background-services/index.md | 8 +- .../devtools/javascript/breakpoints/index.md | 2 +- .../devtools/javascript/source-maps/index.md | 2 +- site/en/docs/devtools/lighthouse/index.md | 6 +- site/en/docs/devtools/overrides/index.md | 6 +- .../devtools/performance-insights/index.md | 48 +++---- .../devtools/performance/reference/index.md | 8 +- .../devtools/progressive-web-apps/index.md | 14 +- .../devtools/rendering/apply-effects/index.md | 10 +- .../devtools/rendering/emulate-css/index.md | 2 +- .../devtools/rendering/performance/index.md | 10 +- .../docs/devtools/settings/devices/index.md | 2 +- .../storage/applicationcache/index.md | 4 +- .../migrating/to-service-workers/index.md | 16 +-- .../mv2/cross-origin-isolation/index.md | 2 +- .../mv3/cross-origin-isolation/index.md | 2 +- site/en/docs/extensions/whatsnew/index.md | 2 +- site/en/docs/handbook/components/index.md | 4 +- .../how-to/add-a-landing-page/index.md | 8 +- .../docs/handbook/how-to/add-media/index.md | 2 +- .../custom-control-roles/index.md | 8 +- .../custom-controls-labels/index.md | 6 +- .../accessibility/focus-traps/index.md | 4 +- .../accessibility/focusable-controls/index.md | 12 +- .../interactive-element-affordance/index.md | 4 +- .../accessibility/logical-tab-order/index.md | 2 +- .../offscreen-content-hidden/index.md | 2 +- .../visual-order-follows-dom/index.md | 4 +- .../best-practices/csp-xss/index.md | 6 +- .../index.md | 4 +- .../image-aspect-ratio/index.md | 8 +- .../notification-on-start/index.md | 4 +- .../best-practices/uses-http2/index.md | 2 +- .../lighthouse/performance/bf-cache/index.md | 2 +- .../performance/bootup-time/index.md | 2 +- .../critical-request-chains/index.md | 10 +- .../lighthouse/performance/dom-size/index.md | 8 +- .../efficient-animated-content/index.md | 6 +- .../estimated-input-latency/index.md | 10 +- .../first-contentful-paint/index.md | 4 +- .../first-meaningful-paint/index.md | 8 +- .../performance/font-display/index.md | 14 +- .../performance/interactive/index.md | 14 +- .../index.md | 4 +- .../lighthouse-max-potential-fid/index.md | 4 +- .../lighthouse-total-blocking-time/index.md | 2 +- .../mainthread-work-breakdown/index.md | 26 ++-- .../non-composited-animations/index.md | 2 +- .../performance/offscreen-images/index.md | 2 +- .../performance/performance-scoring/index.md | 2 +- .../lighthouse/performance/redirects/index.md | 4 +- .../render-blocking-resources/index.md | 14 +- .../performance/resource-summary/index.md | 2 +- .../performance/server-response-time/index.md | 10 +- .../performance/third-party-facades/index.md | 4 +- .../performance/third-party-summary/index.md | 8 +- .../performance/total-byte-weight/index.md | 14 +- .../performance/unminified-css/index.md | 6 +- .../performance/unused-css-rules/index.md | 4 +- .../performance/unused-javascript/index.md | 4 +- .../performance/user-timings/index.md | 4 +- .../performance/uses-long-cache-ttl/index.md | 4 +- .../uses-optimized-images/index.md | 14 +- .../performance/uses-rel-preconnect/index.md | 2 +- .../performance/uses-rel-preload/index.md | 4 +- .../uses-responsive-images/index.md | 8 +- .../uses-text-compression/index.md | 2 +- .../performance/uses-webp-images/index.md | 4 +- .../lighthouse/pwa/apple-touch-icon/index.md | 2 +- .../lighthouse/pwa/content-width/index.md | 4 +- .../pwa/installable-manifest/index.md | 12 +- .../docs/lighthouse/pwa/is-on-https/index.md | 14 +- .../pwa/load-fast-enough-for-pwa/index.md | 8 +- .../pwa/maskable-icon-audit/index.md | 2 +- .../lighthouse/pwa/offline-start-url/index.md | 8 +- .../lighthouse/pwa/pwa-cross-browser/index.md | 4 +- .../pwa/pwa-each-page-has-url/index.md | 2 +- .../pwa/pwa-page-transitions/index.md | 2 +- .../lighthouse/pwa/service-worker/index.md | 16 +-- .../lighthouse/pwa/splash-screen/index.md | 6 +- .../lighthouse/pwa/themed-omnibox/index.md | 8 +- .../pwa/without-javascript/index.md | 2 +- .../lighthouse/pwa/works-offline/index.md | 4 +- .../en/docs/lighthouse/seo/canonical/index.md | 2 +- .../docs/lighthouse/seo/tap-targets/index.md | 2 +- .../register-attribution-trigger/index.md | 36 +++--- .../privacy-sandbox/cds21-update/index.md | 16 +-- site/en/docs/privacy-sandbox/chips/index.md | 26 ++-- .../fedcm-developer-guide/index.md | 76 +++++------ .../privacy-sandbox/fenced-frame/index.md | 24 ++-- site/en/docs/privacy-sandbox/floc/index.md | 58 ++++----- .../permissions-policy/index.md | 98 +++++++------- .../private-state-tokens/index.md | 6 +- .../interest-groups/index.md | 16 +-- .../related-website-sets/index.md | 2 +- .../storage-partitioning/index.md | 62 ++++----- .../third-party-cookie-phase-out/index.md | 6 +- .../docs/privacy-sandbox/user-agent/index.md | 24 ++-- site/en/docs/puppeteer/ssr/index.md | 6 +- .../bfcache-notrestoredreasons/index.md | 22 ++-- .../docs/web-platform/navigation-api/index.md | 2 +- .../docs/web-platform/origin-trials/index.md | 20 +-- .../web-platform/storage-foundation/index.md | 2 +- .../web-platform/view-transitions/index.md | 2 +- .../en/docs/web-platform/web-bundles/index.md | 2 +- .../workbox/different-architectures/index.md | 2 +- .../index.md | 6 +- .../forcing-a-network-timeout/index.md | 4 +- .../workbox/framework-integrations/index.md | 2 +- .../workbox-navigation-preload/index.md | 2 +- .../workbox/modules/workbox-recipes/index.md | 2 +- .../workbox/modules/workbox-routing/index.md | 2 +- .../modules/workbox-strategies/index.md | 12 +- .../workbox/modules/workbox-window/index.md | 12 +- .../docs/workbox/navigation-preload/index.md | 4 +- .../remove-buggy-service-workers/index.md | 2 +- .../service-worker-deployment/index.md | 6 +- .../workbox/service-worker-lifecycle/index.md | 6 +- .../docs/workbox/the-ways-of-workbox/index.md | 4 +- .../understanding-storage-quota/index.md | 2 +- .../workbox/using-workbox-window/index.md | 8 +- .../using-workbox-without-precaching/index.md | 2 +- site/es/articles/browser-fs-access/index.md | 4 +- site/es/articles/file-handling/index.md | 10 +- .../index.md | 6 +- site/es/blog/new-in-chrome-116/index.md | 4 +- site/es/blog/new-in-devtools-101/index.md | 8 +- site/es/blog/new-in-devtools-102/index.md | 8 +- site/es/blog/new-in-devtools-104/index.md | 4 +- site/es/blog/new-in-devtools-105/index.md | 20 +-- site/es/blog/new-in-devtools-106/index.md | 6 +- site/es/blog/new-in-devtools-112/index.md | 2 +- site/es/blog/new-in-devtools-92/index.md | 4 +- site/es/blog/new-in-devtools-93/index.md | 4 +- site/es/blog/new-in-devtools-96/index.md | 10 +- site/es/blog/new-in-devtools-98/index.md | 12 +- site/es/blog/new-in-devtools-99/index.md | 14 +- .../index.md | 4 +- .../image-aspect-ratio/index.md | 6 +- .../performance/bootup-time/index.md | 2 +- .../critical-request-chains/index.md | 2 +- .../lighthouse/performance/dom-size/index.md | 4 +- .../efficient-animated-content/index.md | 4 +- .../first-meaningful-paint/index.md | 10 +- .../performance/font-display/index.md | 14 +- .../performance/interactive/index.md | 12 +- .../lighthouse-total-blocking-time/index.md | 18 +-- .../non-composited-animations/index.md | 6 +- .../performance/offscreen-images/index.md | 4 +- .../performance/server-response-time/index.md | 2 +- .../performance/third-party-facades/index.md | 2 +- .../performance/total-byte-weight/index.md | 14 +- .../performance/unminified-css/index.md | 6 +- .../performance/unused-css-rules/index.md | 2 +- .../performance/unused-javascript/index.md | 4 +- .../performance/uses-long-cache-ttl/index.md | 2 +- .../uses-optimized-images/index.md | 14 +- .../performance/uses-rel-preconnect/index.md | 2 +- .../performance/uses-rel-preload/index.md | 4 +- .../uses-text-compression/index.md | 2 +- .../lighthouse/pwa/apple-touch-icon/index.md | 2 +- .../pwa/installable-manifest/index.md | 8 +- .../docs/lighthouse/pwa/is-on-https/index.md | 2 +- .../pwa/load-fast-enough-for-pwa/index.md | 2 +- .../pwa/maskable-icon-audit/index.md | 10 +- .../lighthouse/pwa/offline-start-url/index.md | 8 +- .../lighthouse/pwa/service-worker/index.md | 12 +- .../lighthouse/pwa/splash-screen/index.md | 2 +- .../lighthouse/pwa/themed-omnibox/index.md | 6 +- .../attribution-reporting/index.md | 6 +- .../privacy-sandbox/first-party-sets/index.md | 2 +- site/es/docs/privacy-sandbox/floc/index.md | 2 +- .../es/docs/privacy-sandbox/glossary/index.md | 2 +- .../es/docs/privacy-sandbox/overview/index.md | 10 +- site/es/docs/privacy-sandbox/status/index.md | 16 +-- .../privacy-sandbox/trust-tokens/index.md | 6 +- .../attribution-reporting/index.md | 6 +- .../privacy-sandbox/first-party-sets/index.md | 2 +- site/fr/docs/privacy-sandbox/floc/index.md | 2 +- .../fr/docs/privacy-sandbox/glossary/index.md | 2 +- .../fr/docs/privacy-sandbox/overview/index.md | 10 +- site/fr/docs/privacy-sandbox/status/index.md | 16 +-- .../privacy-sandbox/trust-tokens/index.md | 6 +- .../glossary-entries/origin-trial.md | 2 +- .../timeline/first-party-sets.md | 2 +- .../timeline/private-state-tokens.md | 2 +- .../index.md | 2 +- .../index.md | 6 +- .../index.md | 2 +- .../blog/first-party-sets-sameparty/index.md | 4 +- site/ja/blog/fledge-api/index.md | 2 +- site/ja/blog/http-cache-partitioning/index.md | 2 +- site/ja/blog/new-in-devtools-101/index.md | 10 +- site/ja/blog/new-in-devtools-102/index.md | 10 +- site/ja/blog/new-in-devtools-104/index.md | 4 +- site/ja/blog/new-in-devtools-105/index.md | 20 +-- site/ja/blog/new-in-devtools-106/index.md | 6 +- site/ja/blog/new-in-devtools-112/index.md | 4 +- site/ja/blog/new-in-devtools-93/index.md | 8 +- site/ja/blog/new-in-devtools-96/index.md | 16 +-- site/ja/blog/new-in-devtools-98/index.md | 32 ++--- site/ja/blog/new-in-devtools-99/index.md | 16 +-- .../index.md | 4 +- .../index.md | 2 +- .../index.md | 4 +- .../index.md | 4 +- .../performance/bootup-time/index.md | 2 +- .../critical-request-chains/index.md | 2 +- .../lighthouse/performance/dom-size/index.md | 4 +- .../lighthouse-total-blocking-time/index.md | 18 +-- .../non-composited-animations/index.md | 6 +- .../performance/third-party-facades/index.md | 2 +- .../uses-optimized-images/index.md | 14 +- .../performance/uses-rel-preconnect/index.md | 2 +- .../uses-text-compression/index.md | 2 +- .../pwa/installable-manifest/index.md | 10 +- .../pwa/load-fast-enough-for-pwa/index.md | 2 +- .../pwa/maskable-icon-audit/index.md | 10 +- .../lighthouse/pwa/service-worker/index.md | 14 +- .../lighthouse/pwa/themed-omnibox/index.md | 8 +- site/ja/docs/privacy-sandbox/chips/index.md | 2 +- site/ja/docs/privacy-sandbox/fedcm/index.md | 2 +- .../privacy-sandbox/first-party-sets/index.md | 2 +- site/ja/docs/privacy-sandbox/floc/index.md | 2 +- .../permissions-policy/index.md | 8 +- .../proposal-lifecycle/index.md | 2 +- .../storage-partitioning/index.md | 8 +- .../third-party-cookie-phase-out/index.md | 4 +- .../privacy-sandbox/trust-tokens/index.md | 4 +- .../docs/privacy-sandbox/user-agent/index.md | 12 +- .../docs/web-platform/origin-trials/index.md | 4 +- site/ko/articles/file-handling/index.md | 12 +- .../index.md | 6 +- site/ko/blog/new-in-devtools-101/index.md | 8 +- site/ko/blog/new-in-devtools-102/index.md | 18 +-- site/ko/blog/new-in-devtools-104/index.md | 48 +++---- site/ko/blog/new-in-devtools-105/index.md | 22 ++-- site/ko/blog/new-in-devtools-106/index.md | 2 +- site/ko/blog/new-in-devtools-93/index.md | 4 +- site/ko/blog/new-in-devtools-96/index.md | 18 +-- site/ko/blog/new-in-devtools-98/index.md | 38 +++--- site/ko/blog/new-in-devtools-99/index.md | 8 +- .../index.md | 4 +- .../image-aspect-ratio/index.md | 6 +- .../performance/bootup-time/index.md | 2 +- .../critical-request-chains/index.md | 2 +- .../lighthouse/performance/dom-size/index.md | 4 +- .../first-meaningful-paint/index.md | 10 +- .../performance/font-display/index.md | 14 +- .../performance/interactive/index.md | 8 +- .../lighthouse-total-blocking-time/index.md | 18 +-- .../non-composited-animations/index.md | 6 +- .../performance/offscreen-images/index.md | 4 +- .../performance/performance-scoring/index.md | 2 +- .../performance/server-response-time/index.md | 2 +- .../performance/third-party-facades/index.md | 2 +- .../performance/total-byte-weight/index.md | 14 +- .../performance/uses-long-cache-ttl/index.md | 2 +- .../uses-optimized-images/index.md | 14 +- .../performance/uses-rel-preconnect/index.md | 2 +- .../performance/uses-rel-preload/index.md | 4 +- .../uses-responsive-images/index.md | 8 +- .../uses-text-compression/index.md | 2 +- .../lighthouse/pwa/apple-touch-icon/index.md | 6 +- .../pwa/installable-manifest/index.md | 16 +-- .../pwa/load-fast-enough-for-pwa/index.md | 2 +- .../pwa/maskable-icon-audit/index.md | 10 +- .../lighthouse/pwa/service-worker/index.md | 14 +- .../lighthouse/pwa/splash-screen/index.md | 4 +- .../lighthouse/pwa/themed-omnibox/index.md | 8 +- .../attribution-reporting/index.md | 6 +- .../privacy-sandbox/first-party-sets/index.md | 2 +- site/ko/docs/privacy-sandbox/floc/index.md | 2 +- .../ko/docs/privacy-sandbox/glossary/index.md | 2 +- .../ko/docs/privacy-sandbox/overview/index.md | 10 +- site/ko/docs/privacy-sandbox/status/index.md | 16 +-- .../privacy-sandbox/trust-tokens/index.md | 6 +- site/pt/articles/browser-fs-access/index.md | 4 +- site/pt/articles/file-handling/index.md | 12 +- .../index.md | 6 +- site/pt/blog/new-in-devtools-101/index.md | 8 +- site/pt/blog/new-in-devtools-102/index.md | 10 +- site/pt/blog/new-in-devtools-104/index.md | 4 +- site/pt/blog/new-in-devtools-105/index.md | 20 +-- site/pt/blog/new-in-devtools-106/index.md | 6 +- site/pt/blog/new-in-devtools-112/index.md | 18 +-- site/pt/blog/new-in-devtools-93/index.md | 4 +- site/pt/blog/new-in-devtools-96/index.md | 22 ++-- site/pt/blog/new-in-devtools-98/index.md | 32 ++--- site/pt/blog/new-in-devtools-99/index.md | 16 +-- .../image-aspect-ratio/index.md | 6 +- .../performance/bootup-time/index.md | 2 +- .../critical-request-chains/index.md | 2 +- .../lighthouse/performance/dom-size/index.md | 4 +- .../efficient-animated-content/index.md | 4 +- .../first-meaningful-paint/index.md | 10 +- .../performance/font-display/index.md | 14 +- .../performance/interactive/index.md | 8 +- .../lighthouse-total-blocking-time/index.md | 20 +-- .../mainthread-work-breakdown/index.md | 16 +-- .../non-composited-animations/index.md | 6 +- .../performance/offscreen-images/index.md | 4 +- .../performance/performance-scoring/index.md | 2 +- .../performance/server-response-time/index.md | 2 +- .../performance/speed-index/index.md | 2 +- .../performance/third-party-facades/index.md | 2 +- .../performance/total-byte-weight/index.md | 14 +- .../performance/unminified-css/index.md | 6 +- .../performance/unused-css-rules/index.md | 2 +- .../performance/uses-long-cache-ttl/index.md | 2 +- .../uses-optimized-images/index.md | 14 +- .../performance/uses-rel-preconnect/index.md | 2 +- .../performance/uses-rel-preload/index.md | 4 +- .../uses-responsive-images/index.md | 8 +- .../performance/uses-webp-images/index.md | 2 +- .../lighthouse/pwa/apple-touch-icon/index.md | 6 +- .../pwa/installable-manifest/index.md | 16 +-- .../docs/lighthouse/pwa/is-on-https/index.md | 4 +- .../pwa/load-fast-enough-for-pwa/index.md | 2 +- .../pwa/maskable-icon-audit/index.md | 10 +- .../lighthouse/pwa/offline-start-url/index.md | 8 +- .../lighthouse/pwa/service-worker/index.md | 14 +- .../lighthouse/pwa/splash-screen/index.md | 4 +- .../lighthouse/pwa/themed-omnibox/index.md | 8 +- .../attribution-reporting/index.md | 6 +- .../privacy-sandbox/first-party-sets/index.md | 2 +- site/pt/docs/privacy-sandbox/floc/index.md | 2 +- .../pt/docs/privacy-sandbox/glossary/index.md | 2 +- .../pt/docs/privacy-sandbox/overview/index.md | 10 +- site/pt/docs/privacy-sandbox/status/index.md | 16 +-- .../privacy-sandbox/trust-tokens/index.md | 6 +- .../index.md | 6 +- site/ru/blog/new-in-devtools-101/index.md | 12 +- site/ru/blog/new-in-devtools-102/index.md | 14 +- site/ru/blog/new-in-devtools-104/index.md | 4 +- site/ru/blog/new-in-devtools-105/index.md | 20 +-- site/ru/blog/new-in-devtools-106/index.md | 8 +- site/ru/blog/new-in-devtools-112/index.md | 2 +- site/ru/blog/new-in-devtools-93/index.md | 4 +- site/ru/blog/new-in-devtools-96/index.md | 22 ++-- site/ru/blog/new-in-devtools-98/index.md | 46 +++---- site/ru/blog/new-in-devtools-99/index.md | 16 +-- .../index.md | 4 +- .../performance/bootup-time/index.md | 2 +- .../critical-request-chains/index.md | 2 +- .../lighthouse/performance/dom-size/index.md | 4 +- .../first-contentful-paint/index.md | 6 +- .../performance/font-display/index.md | 14 +- .../performance/interactive/index.md | 8 +- .../index.md | 4 +- .../lighthouse-total-blocking-time/index.md | 20 +-- .../mainthread-work-breakdown/index.md | 16 +-- .../non-composited-animations/index.md | 6 +- .../performance/offscreen-images/index.md | 4 +- .../performance/performance-scoring/index.md | 2 +- .../render-blocking-resources/index.md | 8 +- .../performance/server-response-time/index.md | 2 +- .../performance/speed-index/index.md | 2 +- .../performance/third-party-facades/index.md | 2 +- .../performance/total-byte-weight/index.md | 14 +- .../performance/unused-css-rules/index.md | 2 +- .../performance/unused-javascript/index.md | 4 +- .../performance/uses-long-cache-ttl/index.md | 2 +- .../uses-optimized-images/index.md | 14 +- .../performance/uses-rel-preconnect/index.md | 2 +- .../performance/uses-rel-preload/index.md | 4 +- .../uses-responsive-images/index.md | 8 +- .../uses-text-compression/index.md | 2 +- .../performance/uses-webp-images/index.md | 2 +- .../pwa/installable-manifest/index.md | 16 +-- .../pwa/load-fast-enough-for-pwa/index.md | 2 +- .../pwa/maskable-icon-audit/index.md | 10 +- .../lighthouse/pwa/service-worker/index.md | 14 +- .../lighthouse/pwa/themed-omnibox/index.md | 8 +- .../attribution-reporting/index.md | 6 +- .../privacy-sandbox/first-party-sets/index.md | 2 +- site/ru/docs/privacy-sandbox/floc/index.md | 2 +- .../ru/docs/privacy-sandbox/glossary/index.md | 2 +- .../ru/docs/privacy-sandbox/overview/index.md | 10 +- site/ru/docs/privacy-sandbox/status/index.md | 16 +-- .../privacy-sandbox/trust-tokens/index.md | 6 +- site/zh/articles/file-sharing/index.md | 10 +- .../index.md | 6 +- site/zh/blog/new-in-devtools-101/index.md | 8 +- site/zh/blog/new-in-devtools-102/index.md | 12 +- site/zh/blog/new-in-devtools-104/index.md | 116 ++++++++--------- site/zh/blog/new-in-devtools-105/index.md | 20 +-- site/zh/blog/new-in-devtools-106/index.md | 6 +- site/zh/blog/new-in-devtools-112/index.md | 6 +- site/zh/blog/new-in-devtools-92/index.md | 8 +- site/zh/blog/new-in-devtools-93/index.md | 4 +- site/zh/blog/new-in-devtools-96/index.md | 12 +- site/zh/blog/new-in-devtools-98/index.md | 26 ++-- site/zh/blog/new-in-devtools-99/index.md | 16 +-- .../index.md | 4 +- .../image-aspect-ratio/index.md | 6 +- .../performance/bootup-time/index.md | 2 +- .../critical-request-chains/index.md | 2 +- .../lighthouse/performance/dom-size/index.md | 4 +- .../lighthouse-total-blocking-time/index.md | 20 +-- .../non-composited-animations/index.md | 6 +- .../performance/third-party-facades/index.md | 2 +- .../performance/total-byte-weight/index.md | 14 +- .../performance/unused-css-rules/index.md | 2 +- .../uses-optimized-images/index.md | 14 +- .../performance/uses-rel-preconnect/index.md | 2 +- .../uses-text-compression/index.md | 2 +- .../pwa/installable-manifest/index.md | 16 +-- .../pwa/load-fast-enough-for-pwa/index.md | 2 +- .../pwa/maskable-icon-audit/index.md | 10 +- .../lighthouse/pwa/service-worker/index.md | 14 +- .../lighthouse/pwa/splash-screen/index.md | 4 +- .../lighthouse/pwa/themed-omnibox/index.md | 8 +- .../attribution-reporting/index.md | 6 +- .../privacy-sandbox/first-party-sets/index.md | 2 +- site/zh/docs/privacy-sandbox/floc/index.md | 2 +- .../zh/docs/privacy-sandbox/glossary/index.md | 2 +- .../zh/docs/privacy-sandbox/overview/index.md | 10 +- site/zh/docs/privacy-sandbox/status/index.md | 16 +-- .../privacy-sandbox/trust-tokens/index.md | 6 +- 670 files changed, 3015 insertions(+), 3015 deletions(-) diff --git a/site/de/docs/privacy-sandbox/attribution-reporting/index.md b/site/de/docs/privacy-sandbox/attribution-reporting/index.md index 86ee17448..4fe72fdf2 100644 --- a/site/de/docs/privacy-sandbox/attribution-reporting/index.md +++ b/site/de/docs/privacy-sandbox/attribution-reporting/index.md @@ -50,7 +50,7 @@ Heutzutage wird bei Werbung für die Conversion-Messung häufig auf [Drittanbiet Das Attribution Reporting API ermöglicht die Messung zweier miteinander verknüpfter Ereignisse: einem Ereignis auf einer Betreiberwebsite (beispielsweise eine Anzeigenansicht oder ein Anzeigenklick) mit einer anschließenden Conversion auf einer Betreiberwebsite. -Dieses API unterstützt die Messung der Click-through-Conversion-Attribution (verfügbar in der ersten Implementierung dieses, sich derzeit in einer [Origin-Trial](https://web.dev/conversion-measurement/#browser-support) befindenden APIs) sowie die View-through-Attributionsmessung ([siehe öffentliche Erläuterung](https://github.com/WICG/conversion-measurement-api/blob/main/event_attribution_reporting_views.md)). +Dieses API unterstützt die Messung der Click-through-Conversion-Attribution (verfügbar in der ersten Implementierung dieses, sich derzeit in einer [Origin-Trial](/docs/privacy-sandbox/attribution-reporting/#browser-support) befindenden APIs) sowie die View-through-Attributionsmessung ([siehe öffentliche Erläuterung](https://github.com/WICG/conversion-measurement-api/blob/main/event_attribution_reporting_views.md)). Das API bietet zwei Arten von Attributionsberichten, die sich für verschiedene Anwendungsfälle anbieten: @@ -69,8 +69,8 @@ Das API bietet zwei Arten von Attributionsberichten, die sich für verschiedene - [Einführung in die Attributionsberichterstattung (Conversion-Messung)](/docs/privacy-sandbox/attribution-reporting-introduction) - [Technische Erläuterungen zum API](https://github.com/WICG/conversion-measurement-api/) -- (⚠️ veraltet) [Eine datenschutzfreundlichere Methode zur Messung von Conversions, die auf Anzeigen zurückzuführen sind](https://web.dev/conversion-measurement/): Überblick über die erste Iteration dieses APIs für Webentwickler +- (⚠️ veraltet) [Eine datenschutzfreundlichere Methode zur Messung von Conversions, die auf Anzeigen zurückzuführen sind](/docs/privacy-sandbox/attribution-reporting/): Überblick über die erste Iteration dieses APIs für Webentwickler - (⚠️ veraltet) [Eine datenschutzfreundlichere Methode zur Messung von auf Anzeigen zurückzuführender Conversions – Video](https://www.youtube.com/watch?v=jcDfOoWwZcM): Demo der ersten Iteration dieses APIs (nur Klicks) -- (⚠️ veraltet) [Verwenden des Event Conversion Measurement APIs](https://web.dev/using-conversion-measurement/): Wie man mit der ersten Iteration dieses APIs für Webentwickler experimentieren kann +- (⚠️ veraltet) [Verwenden des Event Conversion Measurement APIs](/docs/privacy-sandbox/attribution-reporting/): Wie man mit der ersten Iteration dieses APIs für Webentwickler experimentieren kann - [Mehr über die Privacy Sandbox erfahren](https://web.dev/digging-into-the-privacy-sandbox) - Debuggen Sie das API mit den Chrome-Entwicklertools diff --git a/site/de/docs/privacy-sandbox/first-party-sets/index.md b/site/de/docs/privacy-sandbox/first-party-sets/index.md index 882143cee..8741d0ba7 100644 --- a/site/de/docs/privacy-sandbox/first-party-sets/index.md +++ b/site/de/docs/privacy-sandbox/first-party-sets/index.md @@ -13,7 +13,7 @@ authors: ## Implementierungsstatus -- [In der Origin-Trial](https://web.dev/origin-trials/) für Chrome 89 bis 93. +- [In der Origin-Trial](/docs/web-platform/origin-trials/) für Chrome 89 bis 93. - [Registrieren Sie sich für die Origin-Trial](/origintrials/#/view_trial/988540118207823873). - [Chrome-Plattformstatus](https://chromestatus.com/feature/5640066519007232). - [Chromium-Projekte](https://www.chromium.org/updates/first-party-sets). diff --git a/site/de/docs/privacy-sandbox/floc/index.md b/site/de/docs/privacy-sandbox/floc/index.md index f63780fe4..dd9d407fe 100644 --- a/site/de/docs/privacy-sandbox/floc/index.md +++ b/site/de/docs/privacy-sandbox/floc/index.md @@ -39,7 +39,7 @@ Anschließend kann die Werbeplattform diese Daten verwenden, um relevante Anzeig ## Wie funktioniert FLoC? -„[Was ist FLoC?](https://web.dev/floc/#how-does-floc-work)“ bietet eine einfache Schritt-für-Schritt-Erklärung für die Funktionsweise von FLoC. +„[Was ist FLoC?](https://web.dev/articles/floc#how_does_floc_work)“ bietet eine einfache Schritt-für-Schritt-Erklärung für die Funktionsweise von FLoC. Das folgende Diagramm zeigt ein Beispiel für die verschiedenen Rollen bei der Auswahl und Bereitstellung einer relevanten Anzeige mittels FLoC. diff --git a/site/de/docs/privacy-sandbox/glossary/index.md b/site/de/docs/privacy-sandbox/glossary/index.md index 803dce568..c54267cc5 100644 --- a/site/de/docs/privacy-sandbox/glossary/index.md +++ b/site/de/docs/privacy-sandbox/glossary/index.md @@ -120,7 +120,7 @@ Die Origin (der Ausgangspunkt) einer Anfrage, einschließlich Schema und Servern ## Origin-Trials {: #origin-trial} -Origin-Trials bieten Zugriff auf neue oder experimentelle Funktionen und machen es möglich bestimmte Funktionalität temporär für einige Benutzer bereitzustellen, bevor sie für alle verfügbar gemacht wird. Wenn Chrome eine Origin-Trial für eine Funktion anbietet, kann ein [Ausgangspunkt](#origin) (eine Origin) für die Trial registriert werden, um die Funktion für alle Benutzer dieses Ausgangspunktes zu aktivieren, ohne dass Benutzer Flags umschalten oder zu einem alternativen Chrome-Build wechseln müssen (obwohl sie möglicherweise upgraden müssen). Origin-Trials ermöglichen es Entwicklern, Demos und Prototypen mit neuen Funktionen zu erstellen. Diese Trials helfen den Chrome-Ingenieuren unter anderem zu verstehen, wie neue Funktionen verwendet werden und wie sie mit anderen Webtechnologien interagieren können. Weitere Informationen: [Erste Schritte mit den Origin-Trials von Chrome](https://web.dev/origin-trials/). +Origin-Trials bieten Zugriff auf neue oder experimentelle Funktionen und machen es möglich bestimmte Funktionalität temporär für einige Benutzer bereitzustellen, bevor sie für alle verfügbar gemacht wird. Wenn Chrome eine Origin-Trial für eine Funktion anbietet, kann ein [Ausgangspunkt](#origin) (eine Origin) für die Trial registriert werden, um die Funktion für alle Benutzer dieses Ausgangspunktes zu aktivieren, ohne dass Benutzer Flags umschalten oder zu einem alternativen Chrome-Build wechseln müssen (obwohl sie möglicherweise upgraden müssen). Origin-Trials ermöglichen es Entwicklern, Demos und Prototypen mit neuen Funktionen zu erstellen. Diese Trials helfen den Chrome-Ingenieuren unter anderem zu verstehen, wie neue Funktionen verwendet werden und wie sie mit anderen Webtechnologien interagieren können. Weitere Informationen: [Erste Schritte mit den Origin-Trials von Chrome](/docs/web-platform/origin-trials/). ## Passive Oberfläche {: #passive-surface } diff --git a/site/de/docs/privacy-sandbox/overview/index.md b/site/de/docs/privacy-sandbox/overview/index.md index 06bdb7603..75613d3c6 100644 --- a/site/de/docs/privacy-sandbox/overview/index.md +++ b/site/de/docs/privacy-sandbox/overview/index.md @@ -35,7 +35,7 @@ Die wichtigsten Vorschläge des Chrome-Teams sind unten aufgeführt. ### Erstanbieterschutz -- [**SameSite-Cookie-Änderungen**](https://web.dev/samesite-cookies-explained/): Sichern Sie Websites ab, indem Sie explizit Ihre Cross-Site-Cookies markieren. +- [**SameSite-Cookie-Änderungen**](https://web.dev/articles/samesite-cookies-explained): Sichern Sie Websites ab, indem Sie explizit Ihre Cross-Site-Cookies markieren. - [**Erstanbietersets**](/docs/privacy-sandbox/first-party-sets): Erlauben Sie verwandten Domainnamen, die zur selben Organisation gehören, sich als zu einem Erstanbieter gehörend zu erklären. ### Betrugserkennung @@ -45,7 +45,7 @@ Die wichtigsten Vorschläge des Chrome-Teams sind unten aufgeführt. ### Einschränkung der Datensammlung - [**Datenschutzbudget**](https://www.youtube.com/watch?v=0STgfjSA6T8): Erlaubt Websites, Informationen über den Browser oder das Gerät eines Benutzers abzurufen, ermöglicht es dem Browser jedoch, ein Kontingent für die Gesamtmenge an Informationen festzulegen, auf die eine Website zugreifen kann, sodass ein Benutzer nicht identifiziert werden kann. -- [**User-Agent-Client-Hinweise**](https://web.dev/user-agent-client-hints/): Der [User-Agent](https://developer.mozilla.org/docs/Web/HTTP/Headers/User-Agent)-String (UA) bietet eine signifikante Oberfläche für passives [Fingerprinting](https://w3c.github.io/fingerprinting-guidance/#passive) und lässt sich dazu noch schwer verarbeiten. Client-Hinweise (Client Hints) ermöglichen es Entwicklern, aktiv nur die Informationen anzufordern, die sie über das Gerät oder die Anforderungen des Benutzers benötigen, anstatt diese Daten aus dem User-Agent-String parsen zu müssen. +- [**User-Agent-Client-Hinweise**](https://web.dev/articles/user-agent-client-hints): Der [User-Agent](https://developer.mozilla.org/docs/Web/HTTP/Headers/User-Agent)-String (UA) bietet eine signifikante Oberfläche für passives [Fingerprinting](https://w3c.github.io/fingerprinting-guidance/#passive) und lässt sich dazu noch schwer verarbeiten. Client-Hinweise (Client Hints) ermöglichen es Entwicklern, aktiv nur die Informationen anzufordern, die sie über das Gerät oder die Anforderungen des Benutzers benötigen, anstatt diese Daten aus dem User-Agent-String parsen zu müssen. - [**Gnatcatcher**](https://github.com/bslassey/ip-blindness): Beschränken Sie die Möglichkeit, einzelne Benutzer durch Zugriff auf ihre IP-Adresse zu identifizieren. Der Vorschlag besteht aus zwei Teilen: [**Willful IP Blindness**](https://github.com/bslassey/ip-blindness/blob/master/willful_ip_blindness.md) bietet Websites die Möglichkeit, Browsern mitzuteilen, dass die Website IP-Adressen nicht mit Benutzern verknüpft werden, und [**Near-Path-NAT**](https://github.com/bslassey/ip-blindness/blob/master/near_path_nat.md) ermöglicht es Benutzergruppen, ihren Datenverkehr über denselben privatisierenden Server zu senden, um so effektiv ihre IP-Adressen vor einem Site-Host zu verstecken. Gnatcatcher stellt ebenfalls sicher, dass Websites, die für legitime Zwecke wie die Missbrauchsprävention Zugriff auf IP-Adressen benötigen, dies vorbehaltlich einer Zertifizierung und Prüfung tun können. ### Identität @@ -90,10 +90,10 @@ Für die Erläuterungen zu API-Vorschlägen wird Feedback benötigt, insbesonder ### Artikel und Videos für Webentwickler - [Mehr über die Privacy Sandbox erfahren](https://web.dev/digging-into-the-privacy-sandbox) -- [SameSite-Cookies erklärt](https://web.dev/samesite-cookies-explained/) +- [SameSite-Cookies erklärt](https://web.dev/articles/samesite-cookies-explained) - [Erste Schritte mit Vertrauenstoken](https://web.dev/trust-tokens) -- [Eine privatere Methode zur Messung von auf Anzeigen zurückzuführende Conversions](https://web.dev/conversion-measurement/) -- [Was ist FLoC?](https://web.dev/floc/) +- [Eine privatere Methode zur Messung von auf Anzeigen zurückzuführende Conversions](/docs/privacy-sandbox/attribution-reporting/) +- [Was ist FLoC?](https://web.dev/articles/floc) - [Einführung des Datenschutzbudgets](https://www.youtube.com/watch?v=0STgfjSA6T8) ### Prinzipien und Konzepte hinter den Vorschlägen diff --git a/site/de/docs/privacy-sandbox/status/index.md b/site/de/docs/privacy-sandbox/status/index.md index 6ae6585a9..767a99166 100644 --- a/site/de/docs/privacy-sandbox/status/index.md +++ b/site/de/docs/privacy-sandbox/status/index.md @@ -15,7 +15,7 @@ authors: *Früher bekannt als Conversion-Messung.* -- [Aktuelle Origin-Trial](https://web.dev/origin-trials/): seit Chrome 86, [jetzt ausgeweitet](https://groups.google.com/u/1/a/chromium.org/g/attribution-reporting-api-dev/c/ZKf9T8sRqAM) bis auf Chrome 93. +- [Aktuelle Origin-Trial](/docs/web-platform/origin-trials/): seit Chrome 86, [jetzt ausgeweitet](https://groups.google.com/u/1/a/chromium.org/g/attribution-reporting-api-dev/c/ZKf9T8sRqAM) bis auf Chrome 93. - [Registrieren Sie sich für die Origin-Trial](/origintrials/#/view_trial/3411476717733150721). - [Demo](https://goo.gle/demo-event-level-conversion-measurement-api). - [Chrome-Plattformstatus](https://www.chromestatus.com/features/6412002824028160). @@ -31,25 +31,25 @@ Siehe [Status](/docs/privacy-sandbox/attribution-reporting-introduction/#status) - [Attributionsberichte (Konversionsmessung)](/docs/privacy-sandbox/attribution-reporting) - [Einführung in Attributionsberichte (Konversionsmessung)](/docs/privacy-sandbox/attribution-reporting-introduction) - [Technische API-Erklärer](https://github.com/WICG/conversion-measurement-api/) -- (⚠️ veraltet) [Eine datenschutzfreundlichere Methode zur Messung von Werbekonversionen](https://web.dev/conversion-measurement/): Überblick über die erste Iteration dieses APIs für Webentwickler +- (⚠️ veraltet) [Eine datenschutzfreundlichere Methode zur Messung von Werbekonversionen](/docs/privacy-sandbox/attribution-reporting/): Überblick über die erste Iteration dieses APIs für Webentwickler - (⚠️ veraltet) [Eine datenschutzfreundlichere Methode zur Messung von Werbekonversionen – Video](https://www.youtube.com/watch?v=jcDfOoWwZcM): Demo der ersten Iteration dieses APIs (nur Klicks) -- (⚠️ veraltet) [Verwenden des Event Conversion Measurement APIs](https://web.dev/using-conversion-measurement/): Wie experimentiert man mit der ersten Iteration dieses APIs für Webentwickler +- (⚠️ veraltet) [Verwenden des Event Conversion Measurement APIs](/docs/privacy-sandbox/attribution-reporting/): Wie experimentiert man mit der ersten Iteration dieses APIs für Webentwickler - [Mehr über die Privacy Sandbox erfahren](https://web.dev/digging-into-the-privacy-sandbox) ## Vertrauenstoken (Trust Tokens) -- [Aktuelle Origin-Trial](https://web.dev/origin-trials/): seit Chrome 84, [jetzt ausgeweitet](https://groups.google.com/a/chromium.org/g/blink-dev/c/-W90wVkS0Ks/m/Jfh5-ZWpAQAJ) bis auf Chrome 94. +- [Aktuelle Origin-Trial](/docs/web-platform/origin-trials/): seit Chrome 84, [jetzt ausgeweitet](https://groups.google.com/a/chromium.org/g/blink-dev/c/-W90wVkS0Ks/m/Jfh5-ZWpAQAJ) bis auf Chrome 94. - [Registrieren Sie sich für die Origin-Trial](/origintrials/#/view_trial/2479231594867458049). - [Demo](https://trust-token-demo.glitch.me/). - [Chrome-Plattformstatus](https://www.chromestatus.com/feature/5078049450098688). - [Blink-Status](https://groups.google.com/a/chromium.org/g/blink-dev/search?q=trust%tokens). - [GitHub](https://github.com/WICG/trust-token-api): siehe [Issues](https://github.com/WICG/trust-token-api/issues) für Fragen und Diskussionen zum API - [Chrome-Entwicklertools-Integration](https://developers.google.com/web/updates/2021/01/devtools?utm_source=devtools#trust-token). -- Erfahren Sie mehr: [Erste Schritte mit Vertrauenstoken](https://web.dev/trust-tokens/) +- Erfahren Sie mehr: [Erste Schritte mit Vertrauenstoken](https://web.dev/articles/trust-tokens) ## Erstanbieter-Sets -- [Aktuelle Origin-Trial](https://web.dev/origin-trials/): Chrome 89 bis 93. +- [Aktuelle Origin-Trial](/docs/web-platform/origin-trials/): Chrome 89 bis 93. - [Registrieren Sie sich für die Origin-Trial](/origintrials/#/view_trial/988540118207823873). - [Chrome-Plattformstatus](https://chromestatus.com/feature/5640066519007232). - [Blink-Status](https://groups.google.com/a/chromium.org/g/blink-dev/search?q=first-party%20sets). @@ -64,7 +64,7 @@ Siehe [Status](/docs/privacy-sandbox/attribution-reporting-introduction/#status) - [Der API-Vorschlag](https://github.com/WICG/floc) wird derzeit von der [WICG](https://www.w3.org/community/wicg/) und Interessengruppen erörtert. - [GitHub](https://github.com/WICG/floc): siehe [Issues](https://github.com/WICG/floc/issues) für Fragen und Diskussionen zum API - [Chrome-Plattformstatus](https://www.chromestatus.com/features/5710139774468096). -- Erfahren Sie mehr: [Was ist FLoC?](https://web.dev/floc/) +- Erfahren Sie mehr: [Was ist FLoC?](https://web.dev/articles/floc) ## FLEDGE @@ -91,7 +91,7 @@ Nachfolger von [TURTLEDOVE](https://github.com/WICG/turtledove). ### Origin-Trials -- [Erste Schritte für Origin-Trials mit Chrome](https://web.dev/origin-trials/) +- [Erste Schritte für Origin-Trials mit Chrome](/docs/web-platform/origin-trials/) - [Was sind von Dritten durchgeführte Origin-Trials?](https://web.dev/third-party-origin-trials) - [Fehlerbehebung bei mit Chrome durchgeführten Origin-Trials](/blog/origin-trial-troubleshooting/) - [Origin-Trial-Ratgeber für Webentwickler](https://github.com/GoogleChrome/OriginTrials/blob/gh-pages/developer-guide.md) diff --git a/site/de/docs/privacy-sandbox/trust-tokens/index.md b/site/de/docs/privacy-sandbox/trust-tokens/index.md index 296933cc7..7bf43aee8 100644 --- a/site/de/docs/privacy-sandbox/trust-tokens/index.md +++ b/site/de/docs/privacy-sandbox/trust-tokens/index.md @@ -11,7 +11,7 @@ authors: ## Implementierungsstatus -- [In der Origin-Trial](https://web.dev/origin-trials/) von Chrome 84 bis 94. +- [In der Origin-Trial](/docs/web-platform/origin-trials/) von Chrome 84 bis 94. - [Registrieren Sie sich für die Origin-Trial](/origintrials/#/view_trial/2479231594867458049). - [Demo](https://trust-token-demo.glitch.me/). - [Chrome-Entwicklertools-Integration](https://developers.google.com/web/updates/2021/01/devtools?utm_source=devtools#trust-token). @@ -62,7 +62,7 @@ In diesem Beispiel möchte eine Betreiberwebsite vor dem Schalten einer Werbeanz 12. Die Betreibersite zeigt die Anzeige an. 13. Eine Anzeigenaufrufsimpression wird gezählt. -{% Aside %} Weitere Informationen zu den JavaScript-Aufrufen in diesem Beispiel finden Sie unter [Beispiel für die API-Verwendung](https://web.dev/trust-tokens/#sample-api-usage). {% endAside %} +{% Aside %} Weitere Informationen zu den JavaScript-Aufrufen in diesem Beispiel finden Sie unter [Beispiel für die API-Verwendung](https://web.dev/articles/trust-tokens#sample_api_usage). {% endAside %} --- @@ -78,6 +78,6 @@ In diesem Beispiel möchte eine Betreiberwebsite vor dem Schalten einer Werbeanz ## Erfahren Sie mehr - [Technische Erläuterung zum Vertrauenstoken-API](https://github.com/dvorak42/trust-token-api) -- [Erste Schritte mit Vertrauenstoken](https://web.dev/trust-tokens/): ein Überblick für Webentwickler +- [Erste Schritte mit Vertrauenstoken](https://web.dev/articles/trust-tokens): ein Überblick für Webentwickler - [Erste Schritte mit Origin-Trials von Chrome](https://web.dev/origin-trials) - [Mehr über die Privacy Sandbox erfahren](https://web.dev/digging-into-the-privacy-sandbox) diff --git a/site/en/_partials/lighthouse-performance/js-perf.md b/site/en/_partials/lighthouse-performance/js-perf.md index 7b4f875f4..21c1ca972 100644 --- a/site/en/_partials/lighthouse-performance/js-perf.md +++ b/site/en/_partials/lighthouse-performance/js-perf.md @@ -1,7 +1,7 @@ -- [Only send the code that your users need by implementing code splitting](https://web.dev/reduce-javascript-payloads-with-code-splitting/). -- [Minify and compress your code](https://web.dev/reduce-network-payloads-using-text-compression/). -- [Remove unused code](https://web.dev/remove-unused-code/). -- [Reduce network trips by caching your code with the PRPL pattern](https://web.dev/apply-instant-loading-with-prpl/). +- [Only send the code that your users need by implementing code splitting](https://web.dev/articles/reduce-javascript-payloads-with-code-splitting). +- [Minify and compress your code](https://web.dev/articles/reduce-network-payloads-using-text-compression). +- [Remove unused code](https://web.dev/articles/remove-unused-code). +- [Reduce network trips by caching your code with the PRPL pattern](https://web.dev/articles/apply-instant-loading-with-prpl). For other ways to improve page load, check out the [Performance audits landing page](/docs/lighthouse/performance/). diff --git a/site/en/_partials/privacy-sandbox/glossary-entries/origin-trial.md b/site/en/_partials/privacy-sandbox/glossary-entries/origin-trial.md index 2dd3b8ce1..2aed8734b 100644 --- a/site/en/_partials/privacy-sandbox/glossary-entries/origin-trial.md +++ b/site/en/_partials/privacy-sandbox/glossary-entries/origin-trial.md @@ -8,5 +8,5 @@ Chrome (though they may need to upgrade). Origin trials allow developers to build demos and prototypes using new features. The trials help Chrome engineers understand how new features are used, and how they may interact with other web technologies. -Find out more: -[Getting started with Chrome's origin trials](https://web.dev/origin-trials/). \ No newline at end of file +Find out more: +[Getting started with Chrome's origin trials](/docs/web-platform/origin-trials/). diff --git a/site/en/_partials/privacy-sandbox/timeline/first-party-sets.md b/site/en/_partials/privacy-sandbox/timeline/first-party-sets.md index 230e3a58c..d81826b52 100644 --- a/site/en/_partials/privacy-sandbox/timeline/first-party-sets.md +++ b/site/en/_partials/privacy-sandbox/timeline/first-party-sets.md @@ -1,5 +1,5 @@ * First-Party Sets is in incubation in [WICG](https://github.com/WICG/first-party-sets/issues) -* The first [origin trial](https://web.dev/origin-trials/) ran from Chrome 89 to 93. +* The first [origin trial](/docs/web-platform/origin-trials/) ran from Chrome 89 to 93. * [Chrome Platform Status](https://chromestatus.com/feature/5640066519007232). * [Blink status](https://groups.google.com/a/chromium.org/g/blink-dev/search?q=first-party%20sets). * [Chromium Projects](https://www.chromium.org/updates/first-party-sets) diff --git a/site/en/_partials/privacy-sandbox/timeline/private-state-tokens.md b/site/en/_partials/privacy-sandbox/timeline/private-state-tokens.md index 5e9eb2257..c0fcffae2 100644 --- a/site/en/_partials/privacy-sandbox/timeline/private-state-tokens.md +++ b/site/en/_partials/privacy-sandbox/timeline/private-state-tokens.md @@ -1,4 +1,4 @@ * [Chrome Platform Status](https://www.chromestatus.com/feature/5078049450098688). -* [In origin trial](https://web.dev/origin-trials/) Chrome 84 to 101: [now closed](/origintrials/#/view_trial/2479231594867458049). +* [In origin trial](/docs/web-platform/origin-trials/) Chrome 84 to 101: [now closed](/origintrials/#/view_trial/2479231594867458049). * [Demo](https://private-state-token-demo.glitch.me/). -* [Chrome DevTools integration](/blog/new-in-devtools-89/#trust-token). \ No newline at end of file +* [Chrome DevTools integration](/blog/new-in-devtools-89/#trust-token). diff --git a/site/en/articles/at-scope/index.md b/site/en/articles/at-scope/index.md index 05d97cf83..b434c8af4 100644 --- a/site/en/articles/at-scope/index.md +++ b/site/en/articles/at-scope/index.md @@ -23,7 +23,7 @@ When writing selectors you may find yourself torn between two worlds. On the one For example, when you want to select “the hero image in the content area of the card component”–which is a rather specific element selection–you most likely don’t want to write a selector like `.card > .content > img.hero`. -- This selector has a pretty high [specificity](https://web.dev/learn/css/specificity/) of `(0,3,1)` which makes it hard to override as your code grows. +- This selector has a pretty high [specificity](https://web.dev/learn/css/specificity) of `(0,3,1)` which makes it hard to override as your code grows. - By relying on the direct child combinator it is tightly coupled to the DOM structure. Should the markup ever change, you need to change your CSS as well. But, you also don’t want to write just `img` as the selector for that element, as that would select all image elements across your page. @@ -222,7 +222,7 @@ In the example above, the scoped rules only target elements inside the `div` wit ## @scope in the cascade -Inside of the [CSS Cascade](https://web.dev/learn/css/the-cascade/), `@scope` also adds a new criterion: _scoping proximity_. The step comes after specificity but before order of appearance. +Inside of the [CSS Cascade](https://web.dev/learn/css/the-cascade), `@scope` also adds a new criterion: _scoping proximity_. The step comes after specificity but before order of appearance. {% Img src="image/AeNB0cHNDkYPUYzDuv8gInYA9rY2/SqOlwVfRjOpeRzzbz9L7.svg", alt="Visualization of the CSS Cascade.", width="1920", height="1080" %} diff --git a/site/en/articles/authenticate-secure-payment-confirmation/index.md b/site/en/articles/authenticate-secure-payment-confirmation/index.md index 79050e00e..d5af39843 100644 --- a/site/en/articles/authenticate-secure-payment-confirmation/index.md +++ b/site/en/articles/authenticate-secure-payment-confirmation/index.md @@ -44,7 +44,7 @@ Let's walk through the authentication flow: authentication flow. 4. The merchant invokes SPC. The browser displays a confirmation dialog. * If there are no credential IDs passed from the RP, fall back to the - existing authentication flow. + existing authentication flow. After a successful authentication, **consider using [SPC registration](/articles/register-secure-payment-confirmation) to streamline future authentications**. 5. The user confirms and authenticates the amount and the destination of the @@ -70,7 +70,7 @@ aspects of the API. ## Feature detection To detect whether SPC is supported on the browser, you can send a fake call to -[`canMakePayment()`](https://web.dev/how-payment-request-api-works/#check-whether-the-payment-method-is-available). +[`canMakePayment()`](https://web.dev/articles/how-payment-request-api-works#check_whether_the_payment_method_is_available). Copy and paste the following code to feature detect SPC on a merchant's website. @@ -132,7 +132,7 @@ isSecurePaymentConfirmationSupported().then(result => { ## Authenticate the user To authenticate the user, invoke the `PaymentRequest.show()` method with -`secure-payment-confirmation` and WebAuthn parameters: +`secure-payment-confirmation` and WebAuthn parameters: * [`PublicKeyCredentialRequestOptions`](https://w3c.github.io/webauthn/#dictdef-publickeycredentialrequestoptions) * Other [payment specific parameters](https://w3c.github.io/secure-payment-confirmation/#sctn-securepaymentconfirmationrequest-dictionary) on the merchant's platform. diff --git a/site/en/articles/browser-fs-access/index.md b/site/en/articles/browser-fs-access/index.md index 039c63728..9a0de7e90 100644 --- a/site/en/articles/browser-fs-access/index.md +++ b/site/en/articles/browser-fs-access/index.md @@ -242,7 +242,7 @@ the demo cannot be embedded in this article. ## The browser-fs-access library in the wild In my free time, I contribute a tiny bit to an -[installable PWA](https://web.dev/progressive-web-apps/#make-it-installable) +[installable PWA](https://web.dev/explore/progressive-web-apps#make-it-installable) called [Excalidraw](https://excalidraw.com/), a whiteboard tool that lets you easily sketch diagrams with a hand-drawn feel. It is fully responsive and works well on a range of devices from small mobile phones to computers with large screens. diff --git a/site/en/articles/content-indexing-api/index.md b/site/en/articles/content-indexing-api/index.md index c00b0c934..e2e7f4554 100644 --- a/site/en/articles/content-indexing-api/index.md +++ b/site/en/articles/content-indexing-api/index.md @@ -26,12 +26,12 @@ launched in Chrome 84 for Android. ## What is the Content Indexing API? {: #what } Using a [progressive web -app](https://web.dev/progressive-web-apps/) means having access +app](https://web.dev/explore/progressive-web-apps) means having access to information people care about—images, videos, articles, and more—regardless of the current state of your network connection. Technologies like [service workers](/docs/workbox/service-worker-overview/), the [Cache Storage -API](https://web.dev/cache-api-quick-guide/), +API](https://web.dev/articles/cache-api-quick-guide), and [IndexedDB](https://developer.mozilla.org/docs/Web/API/IndexedDB_API) provide you with the building blocks for storing and serving data when folks interact directly with a PWA. But building a high-quality, offline-first PWA is @@ -123,7 +123,7 @@ underlying media URL as a query parameter and then display the contents of the file, potentially with additional controls or content on the page. Web apps can only add URLs to the content index that are under the -[scope](https://web.dev/learn/pwa/service-workers/) +[scope](https://web.dev/learn/pwa/service-workers) of the current service worker. In other words, a web app could not add a URL belonging to a completely different domain into the content index. @@ -190,7 +190,7 @@ await registration.index.add({ ``` Adding an entry only affects the content index; it does not add anything to the -[cache](https://web.dev/cache-api-quick-guide/). +[cache](https://web.dev/articles/cache-api-quick-guide). #### Edge case: Call `add()` from `window` context if your icons rely on a `fetch` handler @@ -231,7 +231,7 @@ await registration.index.delete('article-123'); ``` Calling `delete()` only affects the index. It does not delete anything from the -[cache](https://web.dev/cache-api-quick-guide/). +[cache](https://web.dev/articles/cache-api-quick-guide). {% Aside 'warning' %} Once indexed, entries do not automatically expire. It's diff --git a/site/en/articles/cors-rfc1918-feedback/index.md b/site/en/articles/cors-rfc1918-feedback/index.md index a8c5b0314..d402e3722 100644 --- a/site/en/articles/cors-rfc1918-feedback/index.md +++ b/site/en/articles/cors-rfc1918-feedback/index.md @@ -59,7 +59,7 @@ Browsers that implement CORS check with target resources whether they are okay being loaded from a different origin. This is accomplished either with extra headers inline describing the access or by using a mechanism called preflight requests, depending on the complexity. Read [Cross -Origin Resource Sharing](https://web.dev/cross-origin-resource-sharing/) +Origin Resource Sharing](https://web.dev/articles/cross-origin-resource-sharing) to learn more. With [CORS-RFC1918](https://wicg.github.io/cors-rfc1918/) the browser will block diff --git a/site/en/articles/css-linear-easing-function/index.md b/site/en/articles/css-linear-easing-function/index.md index b3d31335e..4539b92bb 100644 --- a/site/en/articles/css-linear-easing-function/index.md +++ b/site/en/articles/css-linear-easing-function/index.md @@ -31,7 +31,7 @@ There are several keywords available as presets in CSS, namely `linear`, `ease`, tab: 'result' } %} -{%Aside%}Learn more about these easing keywords and functions in [Learn CSS: Animations](https://web.dev/learn/css/animations/#animation-timing-function).{%endAside%} +{%Aside%}Learn more about these easing keywords and functions in [Learn CSS: Animations](https://web.dev/learn/css/animations#animation_timing_function).{%endAside%} When used appropriately, easings give an animated element a sense of weight as it appears to gather momentum. diff --git a/site/en/articles/css-nesting/index.md b/site/en/articles/css-nesting/index.md index c5e578a27..965f29213 100644 --- a/site/en/articles/css-nesting/index.md +++ b/site/en/articles/css-nesting/index.md @@ -121,7 +121,7 @@ another selector. ``` In this example, the `.child` [class -selector](https://web.dev/learn/css/selectors/#class-selector) is nested within +selector](https://web.dev/learn/css/selectors#class_selector) is nested within the `.parent` class selector. This means that the nested `.child` selector will only apply to elements that are children of elements with a `.parent` class. @@ -201,7 +201,7 @@ blurred out and nearly invisible: #### Selecting any triangles and squares This task requires selecting multiple nested elements, also called a [group -selector](https://web.dev/learn/css/selectors/#grouping-selectors). +selector](https://web.dev/learn/css/selectors#grouping_selectors). **Without nesting**, CSS today, there are two ways: @@ -276,7 +276,7 @@ Both nesting options will use `:is()` under the hood as follows. #### Selecting large triangles and circles This task requires a [compound -selector](https://web.dev/learn/css/selectors/#compound-selectors), where +selector](https://web.dev/learn/css/selectors#compound_selectors), where elements must have both classes present in order to be selected. **Without nesting**, CSS today: @@ -362,7 +362,7 @@ While a valid way to nest, the results won't match the elements you may expect. The reason is that without `&` to specify the desired outcome of `.lg.triangle, .lg.circle` compounded together, the actual result would be `.lg .triangle, .lg .circle`; [descendant -selectors](https://web.dev/learn/css/selectors/#descendant-combinator). +selectors](https://web.dev/learn/css/selectors#descendant_combinator). {% Aside 'key-term' %} Nesting classes without `&` will always result in descendant selectors. diff --git a/site/en/articles/css-nth-child-of-s/index.md b/site/en/articles/css-nth-child-of-s/index.md index fe4ec0cea..e561e2c02 100644 --- a/site/en/articles/css-nth-child-of-s/index.md +++ b/site/en/articles/css-nth-child-of-s/index.md @@ -17,7 +17,7 @@ tags: ## The `:nth-child()` and `:nth-last-child()` pseudo-class selectors -With [the `:nth-child()` pseudo-class selector](https://web.dev/learn/css/pseudo-classes/#nth-child-and-nth-of-type) it is possible to select Elements in the DOM by their index. Using the [`An+B` microsyntax](https://www.w3.org/TR/css-syntax-3/#anb-microsyntax) you get fine control over which elements you want to select. +With [the `:nth-child()` pseudo-class selector](https://web.dev/learn/css/pseudo-classes#nth_child_and_nth_of_type) it is possible to select Elements in the DOM by their index. Using the [`An+B` microsyntax](https://www.w3.org/TR/css-syntax-3/#anb-microsyntax) you get fine control over which elements you want to select. - `:nth-child(2)`: Select the 2nd child. - `:nth-child(2n)`: Select all even children _(2nd, 4th, 6th, 8th, and so on)_. diff --git a/site/en/articles/declarative-shadow-dom/index.md b/site/en/articles/declarative-shadow-dom/index.md index 19e9e89b2..f1f48bbd2 100644 --- a/site/en/articles/declarative-shadow-dom/index.md +++ b/site/en/articles/declarative-shadow-dom/index.md @@ -28,7 +28,7 @@ Declarative Shadow DOM has been available since Chrome 90 and Edge 91, but it us `shadowroot` instead of the standardized `shadowrootmode` attribute. {% endAside %} -[Shadow DOM](https://web.dev/shadowdom-v1/) is one of the three Web Components standards, rounded out by [HTML templates](https://developer.mozilla.org/docs/Web/Web_Components/Using_templates_and_slots) +[Shadow DOM](https://web.dev/articles/shadowdom-v1) is one of the three Web Components standards, rounded out by [HTML templates](https://developer.mozilla.org/docs/Web/Web_Components/Using_templates_and_slots) and [Custom Elements](https://developer.mozilla.org/docs/Web/Web_Components/Using_custom_elements). Shadow DOM provides a way to scope CSS styles to a specific DOM subtree and isolate that subtree from the rest of the document. The `<slot>` element gives us a way to control where the children of a Custom Element should be inserted within its Shadow Tree. These features @@ -48,7 +48,7 @@ also create their Shadow Roots and set their content. However, many web applicat static HTML at build time. This can be an important part of delivering a reasonable experience to visitors who may not be capable of running JavaScript. -The justifications for [Server-Side Rendering](https://web.dev/rendering-on-the-web/) (SSR) vary from project to project. Some +The justifications for [Server-Side Rendering](https://web.dev/articles/rendering-on-the-web) (SSR) vary from project to project. Some websites must provide fully functional server-rendered HTML in order to meet accessibility guidelines, others choose to deliver a baseline no-JavaScript experience as a way to guarantee good performance on slow connections or devices. @@ -286,7 +286,7 @@ Styles specified this way are also highly optimized: if the same stylesheet is p it is only loaded and parsed once. The browser uses a single backing `CSSStyleSheet` that is shared by all of the shadow roots, eliminating duplicate memory overhead. -[Constructable Stylesheets](https://web.dev/constructable-stylesheets/) are not supported in Declarative Shadow DOM. This +[Constructable Stylesheets](https://web.dev/articles/constructable-stylesheets) are not supported in Declarative Shadow DOM. This is because there is currently no way to serialize constructable stylesheets in HTML, and no way to refer to them when populating `adoptedStyleSheets`. diff --git a/site/en/articles/display-override/index.md b/site/en/articles/display-override/index.md index 369db6236..884d83b0f 100644 --- a/site/en/articles/display-override/index.md +++ b/site/en/articles/display-override/index.md @@ -15,7 +15,7 @@ tags: - web-app-manifest --- -A [web app manifest](https://web.dev/add-manifest/) is a JSON file that tells the browser about your Progressive +A [web app manifest](https://web.dev/articles/add-manifest) is a JSON file that tells the browser about your Progressive Web App and how it should behave when installed on the user's desktop or mobile device. Via the [`display`](https://web.dev/add-manifest/#display) property, you can customize what browser UI is shown when your app is launched. For example, you can hide the address bar and browser chrome. Games can even be made to launch full screen. diff --git a/site/en/articles/fetch-streaming-requests/index.md b/site/en/articles/fetch-streaming-requests/index.md index cab3fc041..456244a72 100644 --- a/site/en/articles/fetch-streaming-requests/index.md +++ b/site/en/articles/fetch-streaming-requests/index.md @@ -172,7 +172,7 @@ This is because, according to HTTP/1.1 rules, request and response bodies either Chunked encoding is pretty common when it comes to HTTP/1.1 _responses_, but very rare when it comes to _requests_, so it's too much of a compatibility risk. {% Aside %} -This isn't an issue for HTTP/2 or 3, as data is always 'chunked', although it calls the chunks [frames](https://web.dev/performance-http2/#streams,-messages,-and-frames). +This isn't an issue for HTTP/2 or 3, as data is always 'chunked', although it calls the chunks [frames](https://web.dev/articles/performance-http2#streams,-messages,-and-frames). {% endAside %} ## Potential issues diff --git a/site/en/articles/file-handling/index.md b/site/en/articles/file-handling/index.md index 0b88be88f..0966f01e4 100644 --- a/site/en/articles/file-handling/index.md +++ b/site/en/articles/file-handling/index.md @@ -13,7 +13,7 @@ hero: image/admin/tf0sUZX6G7AM8PvU1t0B.jpg alt: Binders in many colors. --- -Now that web apps are [capable of reading and writing files](https://web.dev/file-system-access/), the next logical +Now that web apps are [capable of reading and writing files](https://web.dev/articles/file-system-access), the next logical step is to let developers declare these very web apps as file handlers for the files their apps can create and process. The File Handling API allows you to do exactly this. After registering a text editor app as a file handler and after installing it, you can right-click a `.txt` file on macOS and @@ -38,7 +38,7 @@ app, however, can be achieved through two other means: - The [Web Share Target API](/articles/web-share-target/) lets developers specify their app as a share target so files can be opened from the operating system's share sheet. -- The [File System Access API](https://web.dev/file-system-access/) can be integrated with file drag and drop, so +- The [File System Access API](https://web.dev/articles/file-system-access) can be integrated with file drag and drop, so developers can handle dropped files in the already opened app. ### Browser support @@ -59,7 +59,7 @@ if ('launchQueue' in window && 'files' in LaunchParams.prototype) { ### The declarative part of the File Handling API -As a first step, web apps need to declaratively describe in their [web app manifest](https://web.dev/add-manifest/) +As a first step, web apps need to declaratively describe in their [web app manifest](https://web.dev/articles/add-manifest) what kind of files they can handle. The File Handling API extends web app manifest with a new property called `"file_handlers"` that accepts an array of, well, file handlers. A file handler is an object with these properties: @@ -138,7 +138,7 @@ in a single client, the last one in multiple clients if multiple files are being {% Aside %} For this declaration to have any effect, the application must be installed. You can learn more in an article series on this very site on -[making your app installable](https://web.dev/progressive-web-apps/#make-it-installable). {% endAside %} +[making your app installable](https://web.dev/explore/progressive-web-apps#make-it-installable). {% endAside %} ### The imperative part of the File Handling API @@ -215,7 +215,7 @@ will be reset. There is a large category of attack vectors that are opened by allowing websites access to files. These are outlined in the -[article on the File System Access API](https://web.dev/file-system-access/#security-considerations). The +[article on the File System Access API](https://web.dev/articles/file-system-access#security_considerations). The additional security-pertinent capability that the File Handling API provides over the File System Access API is the ability to grant access to certain files through the operating system's built-in UI, as opposed to through a file picker shown by a web application. diff --git a/site/en/articles/generic-sensor/index.md b/site/en/articles/generic-sensor/index.md index 211b2398c..8c8342e46 100644 --- a/site/en/articles/generic-sensor/index.md +++ b/site/en/articles/generic-sensor/index.md @@ -438,7 +438,7 @@ API, so let's briefly list them. Because Generic Sensor API is a powerful feature, the browser only allows it on secure contexts. In practice it means that to use Generic Sensor API you'll need to access your page through HTTPS. During development you can do so via [http://localhost](http://localhost) but for production you'll -need to have HTTPS on your server. See the [Safe and secure](https://web.dev/secure/) collection for best practices +need to have HTTPS on your server. See the [Safe and secure](https://web.dev/articles/secure) collection for best practices and guidelines. ### Permissions Policy integration diff --git a/site/en/articles/hidden-until-found/index.md b/site/en/articles/hidden-until-found/index.md index 7ad1f7f8d..24703c1fc 100644 --- a/site/en/articles/hidden-until-found/index.md +++ b/site/en/articles/hidden-until-found/index.md @@ -1,7 +1,7 @@ --- title: 'Making collapsed content accessible with hidden=until-found' description: > - How this new attribute value can ensure that content within accordion sections can be found and linked to. + How this new attribute value can ensure that content within accordion sections can be found and linked to. layout: 'layouts/blog-post.njk' date: 2022-04-28 @@ -14,7 +14,7 @@ tags: - html --- -Collapsing content sections, sometimes described as [an accordion](https://www.smashingmagazine.com/2017/06/designing-perfect-accordion-checklist/), are a common UI pattern. However, content hidden in the collapsed sections becomes impossible to search using a find-in-page search. Also, it isn't possible to link to [text fragments](https://web.dev/text-fragments/) inside collapsed regions. +Collapsing content sections, sometimes described as [an accordion](https://www.smashingmagazine.com/2017/06/designing-perfect-accordion-checklist/), are a common UI pattern. However, content hidden in the collapsed sections becomes impossible to search using a find-in-page search. Also, it isn't possible to link to [text fragments](https://web.dev/articles/text-fragments) inside collapsed regions. The `hidden=until-found` HTML attribute and `beforematch` event can solve these problems. By adding `hidden=until-found` to the container for your hidden content, you make it possible for the browser to search text in that hidden region, and reveal the section if a match is found. diff --git a/site/en/articles/inp-in-frameworks/index.md b/site/en/articles/inp-in-frameworks/index.md index dc8f5e296..70b1dadde 100644 --- a/site/en/articles/inp-in-frameworks/index.md +++ b/site/en/articles/inp-in-frameworks/index.md @@ -17,12 +17,12 @@ tags: - performance --- -Chrome recently introduced a new [experimental responsiveness metric](https://groups.google.com/a/chromium.org/g/chrome-ux-report-announce/c/F7S4_emZkcw) in the [Chrome UX Report](/docs/crux/) report. This metric, which we now know as [Interaction to Next Paint (INP)](https://web.dev/inp/) measures overall responsiveness to user interactions on the page. Today we want to share insights on where websites built using modern JavaScript frameworks stand in relation to this metric. We want to discuss why INP is relevant to frameworks and how [Aurora](/blog/introducing-aurora/) and frameworks are working to optimize responsiveness. +Chrome recently introduced a new [experimental responsiveness metric](https://groups.google.com/a/chromium.org/g/chrome-ux-report-announce/c/F7S4_emZkcw) in the [Chrome UX Report](/docs/crux/) report. This metric, which we now know as [Interaction to Next Paint (INP)](https://web.dev/articles/inp) measures overall responsiveness to user interactions on the page. Today we want to share insights on where websites built using modern JavaScript frameworks stand in relation to this metric. We want to discuss why INP is relevant to frameworks and how [Aurora](/blog/introducing-aurora/) and frameworks are working to optimize responsiveness. ## Background -Chrome uses First Input Delay ([FID](https://web.dev/fid/#why-only-consider-the-input-delay)) as part of Core Web Vitals ([CWV](https://web.dev/learn-web-vitals/)) to measure the [load responsiveness](https://web.dev/user-centric-performance-metrics/#types-of-metrics) of websites. FID measures the waiting time from the first user interaction to the moment the browser is able to process the event handlers connected to the interaction. It does not include the time to process the event handlers, process subsequent interactions on the same page, or paint the next frame after the event callbacks run. However, responsiveness is crucial to the user experience throughout the page lifecycle because users spend roughly 90% of the time on a page after it loads. +Chrome uses First Input Delay ([FID](https://web.dev/articles/fid#why_only_consider_the_input_delay)) as part of Core Web Vitals ([CWV](https://web.dev/articles/learn-web-vitals)) to measure the [load responsiveness](https://web.dev/articles/user-centric-performance-metrics#types_of_metrics) of websites. FID measures the waiting time from the first user interaction to the moment the browser is able to process the event handlers connected to the interaction. It does not include the time to process the event handlers, process subsequent interactions on the same page, or paint the next frame after the event callbacks run. However, responsiveness is crucial to the user experience throughout the page lifecycle because users spend roughly 90% of the time on a page after it loads. [INP](https://web.dev/inp) measures the time it takes a web page to respond to user interactions from when the user starts the interaction until the moment the next frame is painted on the screen. With INP, we hope to enable an aggregate measure for the perceived latency of all interactions in the page's lifecycle. We believe that INP will provide a more accurate estimate of web pages' load and runtime responsiveness. @@ -178,9 +178,9 @@ The table shows the percentage of origins on each framework with a good responsi INP values in the field correlate well with the Total Blocking Time (TBT) observed in the lab. This could imply that any script that blocks the main thread for a long duration would be bad for INP. Heavy JavaScript execution after any interaction could block the main thread for an extended period and delay the response to that interaction. Some of the common causes that lead to blocking scripts are: -* **Unoptimized JavaScript:** Redundant code or poor code-splitting and loading strategies can cause JavaScript bloat and block the main thread for long periods. Code-splitting, progressive loading, and [breaking up long tasks](https://web.dev/long-tasks-devtools/) can improve response times considerably. +* **Unoptimized JavaScript:** Redundant code or poor code-splitting and loading strategies can cause JavaScript bloat and block the main thread for long periods. Code-splitting, progressive loading, and [breaking up long tasks](https://web.dev/articles/long-tasks-devtools) can improve response times considerably. -* **Third-party scripts:** [Third-party scripts](https://web.dev/optimizing-content-efficiency-loading-third-party-javascript/), which are sometimes not required to process an interaction (for example, ad scripts), can block the main thread and cause unnecessary delays. Prioritizing essential scripts can help to reduce the negative impact of third-party scripts. +* **Third-party scripts:** [Third-party scripts](https://web.dev/articles/optimizing-content-efficiency-loading-third-party-javascript), which are sometimes not required to process an interaction (for example, ad scripts), can block the main thread and cause unnecessary delays. Prioritizing essential scripts can help to reduce the negative impact of third-party scripts. * **Multiple event handlers:** Multiple event handlers associated with every interaction, each running a different script, could interfere with each other and add up to cause long delays. Some of these tasks may be non-essential and could be scheduled on a web worker or when the browser is idle. @@ -197,7 +197,7 @@ From now on, for a good INP score, developers will have to focus on reviewing th Aurora works with frameworks by incorporating best practices to provide baked-in solutions to common problems. We have worked with Next.js, Nuxt.js, Gatsby, and Angular on [solutions](/blog/introducing-aurora/#what-has-our-work-unlocked-so-far) that offer strong defaults within the framework to optimize performance. Following are the highlights of our work in this context: -* **React and Next.js:** The [Next.js Script component](/blog/script-component/) helps to address issues caused due to inefficient loading of third-party scripts. [Granular chunking](https://web.dev/granular-chunking-nextjs/) was introduced in Next.js to allow for smaller-sized chunks for shared code. This helps to reduce the amount of unused common code that is downloaded on all pages. We are also working with Next.js to make INP data available as part of their [Analytics](https://nextjs.org/analytics) service. +* **React and Next.js:** The [Next.js Script component](/blog/script-component/) helps to address issues caused due to inefficient loading of third-party scripts. [Granular chunking](https://web.dev/articles/granular-chunking-nextjs) was introduced in Next.js to allow for smaller-sized chunks for shared code. This helps to reduce the amount of unused common code that is downloaded on all pages. We are also working with Next.js to make INP data available as part of their [Analytics](https://nextjs.org/analytics) service. * **Angular:** Aurora is [partnering with the Angular](https://angular.io/guide/roadmap#explore-hydration-and-server-side-rendering-usability-improvements) team to explore server-side rendering and hydration improvements. We also plan to look into refinements in event handling and change detection to improve INP. @@ -231,7 +231,7 @@ Through these enhancements, we can address different issues that lead to poor re ## Conclusion -We expect the INP score to provide a better compass for websites to improve responsiveness and performance in the future. We will build on our [existing INP guide](https://web.dev/optimize-inp/) to provide more actionable tips for framework developers in 2023. We hope to achieve this by: +We expect the INP score to provide a better compass for websites to improve responsiveness and performance in the future. We will build on our [existing INP guide](https://web.dev/articles/optimize-inp) to provide more actionable tips for framework developers in 2023. We hope to achieve this by: * Creating channels for easy access to field data on INP for frameworks and web developers. * Work with frameworks to build features that will improve INP by default. diff --git a/site/en/articles/isinputpending/index.md b/site/en/articles/isinputpending/index.md index c54f6f009..ed943ce27 100644 --- a/site/en/articles/isinputpending/index.md +++ b/site/en/articles/isinputpending/index.md @@ -117,7 +117,7 @@ that wants control of the event loop, or get up to an extra `QUANTUM` millisecon of event latency. {% Aside %} -A good value for `QUANTUM` (under the [RAIL model](https://web.dev/rail/)) is <50ms, +A good value for `QUANTUM` (under the [RAIL model](https://web.dev/articles/rail)) is <50ms, depending on the type of work being done. This value is primarily what dictates the tradeoff between throughput and latency. {% endAside %} @@ -191,7 +191,7 @@ API](https://www.w3.org/TR/page-visibility-2/). We encourage you to use `isInputPending()` with discretion. If there isn't user-blocking work to be done, then be kind to others on the event loop by yielding more frequently. [Long tasks can be -harmful](https://web.dev/long-tasks-devtools/). +harmful](https://web.dev/articles/long-tasks-devtools). ## Feedback diff --git a/site/en/articles/local-fonts/index.md b/site/en/articles/local-fonts/index.md index 44179a960..a1dc708fb 100644 --- a/site/en/articles/local-fonts/index.md +++ b/site/en/articles/local-fonts/index.md @@ -50,7 +50,7 @@ body { The days where web safe fonts really mattered are long gone. Today, we have [web fonts](https://developer.mozilla.org/docs/Learn/CSS/Styling_text/Web_fonts), some of which are -even [variable fonts](https://web.dev/variable-fonts/) that we can tweak further by changing the values for the +even [variable fonts](https://web.dev/articles/variable-fonts) that we can tweak further by changing the values for the various exposed axes. You can use web fonts by declaring an [`@font-face`](https://developer.mozilla.org/docs/Web/CSS/@font-face) block at the start of the CSS, which specifies the font file(s) to download: diff --git a/site/en/articles/long-animation-frames/index.md b/site/en/articles/long-animation-frames/index.md index ac46e3716..1d538554c 100644 --- a/site/en/articles/long-animation-frames/index.md +++ b/site/en/articles/long-animation-frames/index.md @@ -17,7 +17,7 @@ tags: - chrome-116 --- -The [Long Animation Frames API](https://github.com/w3c/longtasks/blob/main/loaf-explainer.md) (LoAF - pronounced Lo-Af) is a new proposal from the Chrome team to update the [Long Tasks API](https://w3c.github.io/longtasks/) to provide a better understanding of slow user interface (UI) updates. This can be useful to identify slow animation frames which are likely to affect the pending [Interaction to Next Paint (INP)](https://web.dev/inp/) Core Web Vital metric which measures responsiveness, or to identify other UI jank which affects [smoothness](https://web.dev/smoothness/). +The [Long Animation Frames API](https://github.com/w3c/longtasks/blob/main/loaf-explainer.md) (LoAF - pronounced Lo-Af) is a new proposal from the Chrome team to update the [Long Tasks API](https://w3c.github.io/longtasks/) to provide a better understanding of slow user interface (UI) updates. This can be useful to identify slow animation frames which are likely to affect the pending [Interaction to Next Paint (INP)](https://web.dev/articles/inp) Core Web Vital metric which measures responsiveness, or to identify other UI jank which affects [smoothness](https://web.dev/articles/smoothness). The LoAF API is available as [an origin trial from Chrome 116](/origintrials/#/view_trial/3935020174414970881) for developers to experiment with and provide feedback on. @@ -33,13 +33,13 @@ const observer = new PerformanceObserver((list) => { observer.observe({ type: 'longtask', buffered: true }); ``` -Long tasks are likely to cause responsiveness issues. If a user tries to interact with a page—for example, click a button, or open a menu—but the main thread is already dealing with a long task, then the [user's interaction is delayed](https://web.dev/optimize-input-delay/#what-is-input-delay) waiting for that task to be completed. +Long tasks are likely to cause responsiveness issues. If a user tries to interact with a page—for example, click a button, or open a menu—but the main thread is already dealing with a long task, then the [user's interaction is delayed](https://web.dev/articles/optimize-input-delay#what_is_input_delay) waiting for that task to be completed. -To improve responsiveness, it is often advised to [break up long tasks](https://web.dev/optimize-long-tasks/). If each long task is instead broken up into a series of multiple, smaller tasks, it may allow more important tasks to be executed in between them to avoid significant delays in responding to interactions. +To improve responsiveness, it is often advised to [break up long tasks](https://web.dev/articles/optimize-long-tasks). If each long task is instead broken up into a series of multiple, smaller tasks, it may allow more important tasks to be executed in between them to avoid significant delays in responding to interactions. -So when trying to improve responsiveness, the first effort is often to run a performance trace and look at long tasks. This could be through a lab-based auditing tool like Lighthouse (which has an **Avoid long main-thread tasks** audit), or by [looking at long tasks in Chrome DevTools](https://web.dev/long-tasks-devtools/). +So when trying to improve responsiveness, the first effort is often to run a performance trace and look at long tasks. This could be through a lab-based auditing tool like Lighthouse (which has an **Avoid long main-thread tasks** audit), or by [looking at long tasks in Chrome DevTools](https://web.dev/articles/long-tasks-devtools). -Lab-based testing is [often a poor starting place for identifying responsiveness issues](https://web.dev/diagnose-slow-interactions-in-the-lab/), as these tools may not include interactions—when they do, they are a small subset of likely interactions. Ideally, you would measure causes of slow interactions in the field. +Lab-based testing is [often a poor starting place for identifying responsiveness issues](https://web.dev/articles/diagnose-slow-interactions-in-the-lab), as these tools may not include interactions—when they do, they are a small subset of likely interactions. Ideally, you would measure causes of slow interactions in the field. ### Shortcomings of the Long Tasks API @@ -76,7 +76,7 @@ The final issue is that measuring long tasks only reports on individual tasks th The [Long Animation Frames API](https://github.com/w3c/longtasks/blob/main/loaf-explainer.md) (LoAF) is a new API that seeks to address some of the shortcomings of the Long Tasks API to enable developers to get more actionable insights to help address responsiveness problems and improve INP. -Good responsiveness means that a page responds quickly to interactions made with it. That involves being able to paint any updates needed by the user in a timely manner, and avoiding blocking these updates from happening. For INP, [it is recommended to respond in 200 milliseconds or less](https://web.dev/inp/#what-is-a-good-inp-score), but for other updates (for example, animations) even that may be too long. +Good responsiveness means that a page responds quickly to interactions made with it. That involves being able to paint any updates needed by the user in a timely manner, and avoiding blocking these updates from happening. For INP, [it is recommended to respond in 200 milliseconds or less](https://web.dev/articles/inp#what_is_a_good_inp_score), but for other updates (for example, animations) even that may be too long. The Long Animation Frames API is an alternative approach to measuring blocking work. Rather than measuring the individual _tasks_, the Long Animation Frames API—as its name suggests—measures _long animation frames_. A long animation frame is when a rendering update is delayed beyond 50 milliseconds (the same as the Long Tasks API's threshold). @@ -172,7 +172,7 @@ The `long-animation-frame` entry type includes better attribution data of each s - `startTime`: time the entry function was invoked. - `executionStart`: the time after compilation. - `duration`: the duration between `startTime` and when the subsequent microtask queue has finished processing. - - `forcedStyleAndLayoutDuration`: the total time spent processing forced layout/style inside this function (see [thrashing](https://web.dev/avoid-large-complex-layouts-and-layout-thrashing/#avoid-layout-thrashing)). + - `forcedStyleAndLayoutDuration`: the total time spent processing forced layout/style inside this function (see [thrashing](https://web.dev/articles/avoid-large-complex-layouts-and-layout-thrashing#avoid_layout_thrashing)). - `desiredExecutionStart`: the time when the callback was queued. - `sourceLocation`: the script resource name and character position. - `windowAttribution`: the container (the top-level document, or an `<iframe>`) the long animation frame occurred in. @@ -372,7 +372,7 @@ If this API proves useful in the long term, it will likely be incorporated into ### Using long animation frames data in other developer tooling -The [Web Vitals extension has shown the value in logging summary debug information](https://web.dev/debug-cwvs-with-web-vitals-extension/) to diagnose performance issues. Should this proposal prove useful and the API is launched, tools like that could more easily surface data to help make developers aware of where to concentrate their efforts. Similarly, this could be added to the [web vitals JavaScript library](https://github.com/GoogleChrome/web-vitals) in the future. +The [Web Vitals extension has shown the value in logging summary debug information](https://web.dev/articles/debug-cwvs-with-web-vitals-extension) to diagnose performance issues. Should this proposal prove useful and the API is launched, tools like that could more easily surface data to help make developers aware of where to concentrate their efforts. Similarly, this could be added to the [web vitals JavaScript library](https://github.com/GoogleChrome/web-vitals) in the future. ### Using long animation frames data in automated testing tools diff --git a/site/en/articles/mediastreamtrack-insertable-media-processing/index.md b/site/en/articles/mediastreamtrack-insertable-media-processing/index.md index 314c644d4..35e47a329 100644 --- a/site/en/articles/mediastreamtrack-insertable-media-processing/index.md +++ b/site/en/articles/mediastreamtrack-insertable-media-processing/index.md @@ -30,7 +30,7 @@ stereo audio track. ## What is insertable streams for `MediaStreamTrack`? The core idea behind insertable streams for `MediaStreamTrack` is to expose the content of a -`MediaStreamTrack` as a collection of [streams](https://web.dev/streams/) (as defined by the WHATWG +`MediaStreamTrack` as a collection of [streams](https://web.dev/articles/streams) (as defined by the WHATWG [Streams API](https://streams.spec.whatwg.org/)). These streams can be manipulated to introduce new components. diff --git a/site/en/articles/page-lifecycle-api/index.md b/site/en/articles/page-lifecycle-api/index.md index be66f5f42..4cb3efe3e 100644 --- a/site/en/articles/page-lifecycle-api/index.md +++ b/site/en/articles/page-lifecycle-api/index.md @@ -931,7 +931,7 @@ freeze or discard the page but still show changes to the tab title or favicon. <strong id="back-forward-cache">What is the back/forward cache?<strong> -The [back/forward cache](https://web.dev/bfcache/) is a term used to describe a +The [back/forward cache](https://web.dev/articles/bfcache) is a term used to describe a navigation optimization some browsers implement that makes using the back and forward buttons faster. diff --git a/site/en/articles/periodic-background-sync/index.md b/site/en/articles/periodic-background-sync/index.md index 6cffb84b0..d1afb51c6 100644 --- a/site/en/articles/periodic-background-sync/index.md +++ b/site/en/articles/periodic-background-sync/index.md @@ -47,7 +47,7 @@ Before using it, make sure that: * You're using Chrome 80 or later. * You - [install](https://web.dev/customize-install/) + [install](https://web.dev/articles/customize-install) the web app before enabling periodic background sync. ## Concepts and usage @@ -140,7 +140,7 @@ consideration and download different amounts of data in response. You can use the following resources to help: * [Network Information API](https://developer.mozilla.org/docs/Web/API/Network_Information_API) -* [Detecting data saver mode](https://web.dev/optimizing-content-efficiency-save-data/#detecting-the-save-data-setting) +* [Detecting data saver mode](https://web.dev/articles/optimizing-content-efficiency-save-data#detecting_the_save_data_setting) * [Estimating available storage](/blog/estimating-available-storage-space/) ### Permissions diff --git a/site/en/articles/renderingng-architecture/index.md b/site/en/articles/renderingng-architecture/index.md index 2778d55db..878520bb1 100644 --- a/site/en/articles/renderingng-architecture/index.md +++ b/site/en/articles/renderingng-architecture/index.md @@ -144,7 +144,7 @@ There is exactly one browser process. plus the browser process. It rasters and draws using the GPU. There is exactly one Viz process. -Different [sites](https://web.dev/same-site-same-origin/) always end up in different render processes. +Different [sites](https://web.dev/articles/same-site-same-origin) always end up in different render processes. (In reality, [always on desktop; when possible on mobile](https://blog.chromium.org/2019/10/recent-site-isolation-improvements.html). I'll write "always" below, @@ -163,7 +163,7 @@ From the perspective of rendering, the important advantage of multiple render processes is that cross-site iframes and tabs achieve [performance isolation](/blog/renderingng/#performance-isolation) from each other. -In addition, origins can opt into [even more isolation](https://web.dev/origin-agent-cluster/). +In addition, origins can opt into [even more isolation](https://web.dev/articles/origin-agent-cluster). There is exactly one Viz process for all of Chromium. After all, there is usually only one GPU and screen to draw to. diff --git a/site/en/articles/renderingng-data-structures/index.md b/site/en/articles/renderingng-data-structures/index.md index 987f4cba3..2f856ec0c 100644 --- a/site/en/articles/renderingng-data-structures/index.md +++ b/site/en/articles/renderingng-data-structures/index.md @@ -319,8 +319,8 @@ geometry. - Avoiding work for offscreen elements and GPU texture tiles. - Efficiently and accurately invalidating paint and raster. - Measuring -[layout shift](https://web.dev/cls/) and -[largest contentful paint](https://web.dev/lcp/) in Core Web Vitals. +[layout shift](https://web.dev/articles/cls) and +[largest contentful paint](https://web.dev/articles/lcp) in Core Web Vitals. Every web document has four separate property trees: transform, clip, effect, and scroll.(*) The transform tree represents CSS transforms and scrolling. diff --git a/site/en/articles/renderingng/index.md b/site/en/articles/renderingng/index.md index 8c64f423f..9e0f616e6 100644 --- a/site/en/articles/renderingng/index.md +++ b/site/en/articles/renderingng/index.md @@ -270,7 +270,7 @@ All of them were developed with open specifications and collaboration with open partners—engineers at other browsers, experts, and web developers. In subsequent blog posts, we will dive into each of these and explain how RenderingNG makes them possible. -- [content-visibility](https://web.dev/content-visibility/): +- [content-visibility](https://web.dev/articles/content-visibility): allows sites to easily avoid rendering work for offscreen content, and cache rendering for not-currently-shown single page application views. - [OffscreenCanvas](/web/updates/2018/08/offscreen-canvas): allows canvas rendering @@ -278,10 +278,10 @@ and cache rendering for not-currently-shown single page application views. This project is also another major milestone for the web—it's the very first web API that allows JavaScript (or WebAssembly!) to render a single web page document from multiple threads. -- [Container queries](https://web.dev/new-responsive/): allows a single component to responsively lay itself out, +- [Container queries](https://web.dev/articles/new-responsive): allows a single component to responsively lay itself out, unblocking a whole universe of plug-and-play components (currently an experimental implementation). -- [Origin isolation](https://web.dev/origin-agent-cluster/): allows sites to opt into more performance isolation between iframes. -- Off-main-thread [paint worklets](https://web.dev/houdini-how/): gives developers a way to extend how elements are painted, +- [Origin isolation](https://web.dev/articles/origin-agent-cluster): allows sites to opt into more performance isolation between iframes. +- Off-main-thread [paint worklets](https://web.dev/articles/houdini-how): gives developers a way to extend how elements are painted, with code that runs on the compositor thread. In addition to explicit web APIs, diff --git a/site/en/articles/reporting-api/index.md b/site/en/articles/reporting-api/index.md index 4e38ddebf..a5e42b947 100644 --- a/site/en/articles/reporting-api/index.md +++ b/site/en/articles/reporting-api/index.md @@ -307,7 +307,7 @@ Here's the data you can find in each of these reports: #### Credentialed reports -Reporting endpoints that have the [same origin](https://web.dev/same-site-same-origin/#same-origin-and-cross-origin) as the page that generates the report receive the credentials +Reporting endpoints that have the [same origin](https://web.dev/articles/same-site-same-origin#same_origin_and_cross_origin) as the page that generates the report receive the credentials (cookies) in the requests that contain the reports. Credentials may give useful additional context about the report; for @@ -315,7 +315,7 @@ example, whether a given user’s account is triggering errors consistently, or of actions taken on other pages is triggering a report on this page. {% Aside %} -[Cross-origin](https://web.dev/same-site-same-origin/#same-origin-and-cross-origin) endpoints +[Cross-origin](https://web.dev/articles/same-site-same-origin#same_origin_and_cross_origin) endpoints don't receive credentials. This is a security measure and can't be changed. {% endAside %} diff --git a/site/en/articles/scroll-driven-animations/index.md b/site/en/articles/scroll-driven-animations/index.md index 870be1912..e1cf579a5 100644 --- a/site/en/articles/scroll-driven-animations/index.md +++ b/site/en/articles/scroll-driven-animations/index.md @@ -73,7 +73,7 @@ For example, here’s an animation that scales up an element on the X-axis while } ``` -{% Aside %} To learn more about CSS Animations, visit [Learn CSS Animations](https://web.dev/learn/css/animations/) {% endAside %} +{% Aside %} To learn more about CSS Animations, visit [Learn CSS Animations](https://web.dev/learn/css/animations) {% endAside %} ### Animations on the web with JavaScript diff --git a/site/en/articles/user-agent-client-hints/index.md b/site/en/articles/user-agent-client-hints/index.md index 06bc6e65f..b1f773af0 100644 --- a/site/en/articles/user-agent-client-hints/index.md +++ b/site/en/articles/user-agent-client-hints/index.md @@ -147,7 +147,7 @@ then dive into the [full proposal](https://wicg.github.io/ua-client-hints/). {% Aside %} Client Hints are **only sent over secure connections**, so make sure you have -[migrated your site to HTTPS](https://web.dev/why-https-matters/). +[migrated your site to HTTPS](https://web.dev/articles/why-https-matters). {% endAside %} ## User-Agent Client Hints from Chromium 89 diff --git a/site/en/articles/wake-lock/index.md b/site/en/articles/wake-lock/index.md index 59e53db3d..45dd01bcc 100644 --- a/site/en/articles/wake-lock/index.md +++ b/site/en/articles/wake-lock/index.md @@ -66,7 +66,7 @@ Of course, there are plenty of other use cases: After implementing the Screen Wake Lock API, *Betty Crocker*, a major cooking site in the US, saw a 300% increase in purchase intent indicators for their users. -Read more in the 🍰 [Betty Crocker case study](https://web.dev/betty-crocker/). +Read more in the 🍰 [Betty Crocker case study](https://web.dev/articles/betty-crocker). {% endAside %} ## Current status {: #status } diff --git a/site/en/articles/web-otp/index.md b/site/en/articles/web-otp/index.md index 73617a219..a0f09dd7e 100644 --- a/site/en/articles/web-otp/index.md +++ b/site/en/articles/web-otp/index.md @@ -523,9 +523,9 @@ Find more questions at [the FAQ section in the explainer](https://github.com/WIC ## Resources {: #resources } -* [SMS OTP form best practices](https://web.dev/sms-otp-form/) +* [SMS OTP form best practices](https://web.dev/articles/sms-otp-form) * [Verify a phone number on desktop using WebOTP API](/blog/cross-device-webotp/) -* [Fill OTP forms within cross-origin iframes with WebOTP API](https://web.dev/web-otp-iframe/) +* [Fill OTP forms within cross-origin iframes with WebOTP API](https://web.dev/articles/web-otp-iframe) * [Yahoo! JAPAN's password-free authentication reduced inquiries by 25%, sped up - sign-in time by 2.6x](https://web.dev/yahoo-japan-identity-case-study/) + sign-in time by 2.6x](https://web.dev/articles/yahoo-japan-identity-case-study) diff --git a/site/en/articles/web-share-target/index.md b/site/en/articles/web-share-target/index.md index 16887ad21..4a90c4cb1 100644 --- a/site/en/articles/web-share-target/index.md +++ b/site/en/articles/web-share-target/index.md @@ -33,7 +33,7 @@ as a share target to receive shared content. {% Aside %} The Web Share Target API is only half of the magic. Web apps can share data, files, links, or text using the Web Share API. See -[Web Share API](https://web.dev/web-share/) for details. +[Web Share API](https://web.dev/articles/web-share) for details. {% endAside %} <figure data-float="right"> @@ -205,10 +205,10 @@ window.addEventListener('DOMContentLoaded', () => { }); ``` -Be sure to use a service worker to [precache](https://web.dev/learn/pwa/caching/) the `action` +Be sure to use a service worker to [precache](https://web.dev/learn/pwa/caching) the `action` page so that it loads quickly and works reliably, even if the user is offline. [Workbox](/docs/workbox/) is a tool that can help you -[implement precaching](https://web.dev/precache-with-workbox/) in your service worker. +[implement precaching](https://web.dev/articles/precache-with-workbox) in your service worker. ### Processing POST shares diff --git a/site/en/articles/x-google-ignore-list/index.md b/site/en/articles/x-google-ignore-list/index.md index a435266b1..2eb1afc10 100644 --- a/site/en/articles/x-google-ignore-list/index.md +++ b/site/en/articles/x-google-ignore-list/index.md @@ -19,7 +19,7 @@ alt: > {% YouTube id='FIYkjjFYvoI', startTime='256' %} -Chrome DevTools parses the `x_google_ignoreList` field in [source maps](https://web.dev/source-maps/) to help improve developer debugging experience. Take a look at the following stack trace in the **Console**. DevTools automatically hides all the third party frames, and shows only the frames that are relevant to your code. +Chrome DevTools parses the `x_google_ignoreList` field in [source maps](https://web.dev/articles/source-maps) to help improve developer debugging experience. Take a look at the following stack trace in the **Console**. DevTools automatically hides all the third party frames, and shows only the frames that are relevant to your code. <figure> {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/4Q6lH52avZS6Om6UV3Dl.png", alt="A comparison of stack trace results.", width="800", height="439" %} @@ -39,7 +39,7 @@ Chrome DevTools uses the `x_google_ignoreList` field (if provided), to filter ou { "version": 3, - "mappings": "AAAAA, ..." + "mappings": "AAAAA, ..." "sources": [ "app.js", "components/Button.ts", @@ -54,7 +54,7 @@ Chrome DevTools uses the `x_google_ignoreList` field (if provided), to filter ou The `sources` field shows a list of original sources used by the `mappings` entry. Watch [What are source maps?](https://youtu.be/FIYkjjFYvoI) to learn how the mappings work. -Given that the two files `node_modules/…/frameworks.js` and `node_modules/.../library.js` are third party scripts, you can specify the `x_google_ignoreList` field to indicate their positions in the `sources` field. Chrome DevTools will apply this information to hide frames from those ignored files. +Given that the two files `node_modules/…/frameworks.js` and `node_modules/.../library.js` are third party scripts, you can specify the `x_google_ignoreList` field to indicate their positions in the `sources` field. Chrome DevTools will apply this information to hide frames from those ignored files. <figure> {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/yw7xc5vBlBrCloYwFioA.png", alt="A comparison of collapsed and expanded stack trace.", width="800", height="467" %} @@ -63,7 +63,7 @@ Given that the two files `node_modules/…/frameworks.js` and `node_modules/.../ </figcaption> </figure> -This also applies to the [**Call Stack**](/docs/devtools/javascript/reference/#show-ignore-listed-frames) in the **Sources** panel during breakpoint debugging. +This also applies to the [**Call Stack**](/docs/devtools/javascript/reference/#show-ignore-listed-frames) in the **Sources** panel during breakpoint debugging. Behind the scenes, DevTools has an extra setting enabled by default: [Automatically add known third-party scripts to ignore list](/docs/devtools/settings/ignore-list/#skip-third-party). You can find it in DevTools > **Settings** > **Ignore List**. @@ -79,7 +79,7 @@ On the other hand, build tools like [Vite](https://vitejs.dev/config/server-opti If you are a framework or library maintainer, it's essential to understand how to implement these settings to improve your users debugging experience. See the following section to see how Angular and Nuxt did it behind the scenes. -### What if your favorite framework and build tool doesn’t support it yet? +### What if your favorite framework and build tool doesn’t support it yet? We actively work with frameworks and build tools to land these new settings. You can also help by notifying maintainers about this feature. For example, you can file an issue in their repository. diff --git a/site/en/blog/300ms-tap-delay-gone-away/index.md b/site/en/blog/300ms-tap-delay-gone-away/index.md index 504d25182..b3f5ca8f8 100644 --- a/site/en/blog/300ms-tap-delay-gone-away/index.md +++ b/site/en/blog/300ms-tap-delay-gone-away/index.md @@ -19,7 +19,7 @@ Ever since the first release of Chrome for Android, this delay was removed if pi The performance difference is huge! -Having a UI that responds instantly means the user can quickly press each button with confidence, rather than pausing and waiting for a response. Find out more about the impact of human reaction times and web performance in our [introduction to RAIL](https://web.dev/rail/). +Having a UI that responds instantly means the user can quickly press each button with confidence, rather than pausing and waiting for a response. Find out more about the impact of human reaction times and web performance in our [introduction to RAIL](https://web.dev/articles/rail). To remove the 300-350ms tap delay, all you need is the following in the `<head>` of your page: diff --git a/site/en/blog/a-new-home-for-the-project-fugu-api-showcase/index.md b/site/en/blog/a-new-home-for-the-project-fugu-api-showcase/index.md index c2cd2e0ac..fe5ae7fda 100644 --- a/site/en/blog/a-new-home-for-the-project-fugu-api-showcase/index.md +++ b/site/en/blog/a-new-home-for-the-project-fugu-api-showcase/index.md @@ -13,7 +13,7 @@ tags: - capabilities --- -The cross-company Capabilities Project (code name [Project Fugu](/capabilities/)) at Google has the objective of making it possible for web apps to do anything platform-specific apps can. Apart from Google, project partners include Microsoft, Intel, Samsung, and others. The project enables amazing web applications like [Photoshop](https://web.dev/ps-on-the-web/) by exposing the capabilities of the underlying operating systems to the web platform, while maintaining user security, privacy, trust, and other core tenets of the web. +The cross-company Capabilities Project (code name [Project Fugu](/capabilities/)) at Google has the objective of making it possible for web apps to do anything platform-specific apps can. Apart from Google, project partners include Microsoft, Intel, Samsung, and others. The project enables amazing web applications like [Photoshop](https://web.dev/articles/ps-on-the-web) by exposing the capabilities of the underlying operating systems to the web platform, while maintaining user security, privacy, trust, and other core tenets of the web. But what are examples of apps that make use of these capabilities? Our answer to this question is the [Project Fugu API Showcase](/fugu-showcase/). It is sourced by community submissions, and contains a filterable list of apps that make use of one or more of the Fugu APIs. diff --git a/site/en/blog/a2hs-updates/index.md b/site/en/blog/a2hs-updates/index.md index 3b28d5a12..66938e248 100644 --- a/site/en/blog/a2hs-updates/index.md +++ b/site/en/blog/a2hs-updates/index.md @@ -18,7 +18,7 @@ that goal. {% Aside %} Chrome 68 is out of beta. See the -[Add to Home Screen](https://web.dev/customize-install/) docs for the +[Add to Home Screen](https://web.dev/articles/customize-install) docs for the current behavior. {% endAside %} @@ -27,7 +27,7 @@ current behavior. Starting in Chrome 68 on Android (Stable in July 2018), Chrome will no longer show the add to home screen banner. If the site meets the -[add to home screen criteria](https://web.dev/install-criteria/), +[add to home screen criteria](https://web.dev/articles/install-criteria), Chrome will show the mini-infobar. Then, if the user clicks on the mini-infobar, or you call `prompt()` on the `beforeinstallprompt` event from within a user gesture, Chrome will show a modal add to home screen dialog. @@ -116,7 +116,7 @@ The mini-infobar is a Chrome UI component and is not controllable by the site, but can be easily dismissed by the user. Once dismissed by the user, it will not appear again until a sufficient amount of time has passed (currently 3 months). The mini-infobar will appear when the site meets the -[add to home screen criteria](https://web.dev/install-criteria/), +[add to home screen criteria](https://web.dev/articles/install-criteria), regardless of whether you `preventDefault()` on the `beforeinstallprompt` event or not. @@ -156,7 +156,7 @@ tomorrow, or whenever they’re ready to install. ### Listening for the `beforeinstallprompt` event If your site meets the -[add to home screen criteria](https://web.dev/install-criteria/), +[add to home screen criteria](https://web.dev/articles/install-criteria), Chrome will fire a `beforeinstallprompt` event, save a reference to the event, and update your user interface to indicate that the user can add your app to their home screen. @@ -176,13 +176,13 @@ window.addEventListener('beforeinstallprompt', event => { {% Aside %} Your site must meet the -[add to home screen criteria](https://web.dev/install-criteria/) +[add to home screen criteria](https://web.dev/articles/install-criteria) in order for the `beforeinstallprompt` event to be fired and your app installed. {% endAside %} The `beforeinstallprompt` event will not be fired if the app is already installed (see the -[add to home screen criteria](https://web.dev/install-criteria/)). +[add to home screen criteria](https://web.dev/articles/install-criteria)). But if the user later uninstalls the app, the `beforeinstallprompt` event will again be fired on each page navigation. diff --git a/site/en/blog/advanced-web-apps-fund-oct-22/index.md b/site/en/blog/advanced-web-apps-fund-oct-22/index.md index 81a372bcb..1fa0743b8 100644 --- a/site/en/blog/advanced-web-apps-fund-oct-22/index.md +++ b/site/en/blog/advanced-web-apps-fund-oct-22/index.md @@ -60,7 +60,7 @@ interested in submitting ideas for our next round, check out the via our [submission form](https://forms.gle/GnTuCvDW3YhzSnBQ8). As a reminder, we recently also expanded Chrome's sponsorship efforts to -include a new [CSS & UI Fund](https://web.dev/ui-fund/) and the +include a new [CSS & UI Fund](https://web.dev/articles/ui-fund) and the [Web Frameworks and Tools Performance Fund](https://blog.opencollective.com/chromes-framework-of-open-source-investment/). If you are interested in submitting sponsorship requests to these efforts, they are still open to reviewing entries. diff --git a/site/en/blog/advanced-web-apps-fund/index.md b/site/en/blog/advanced-web-apps-fund/index.md index c16a9bf3e..39e39e5b6 100644 --- a/site/en/blog/advanced-web-apps-fund/index.md +++ b/site/en/blog/advanced-web-apps-fund/index.md @@ -25,7 +25,7 @@ open through the end of 2022, so submit your ideas via our submission form. {% endAside %} -Over the years, Chrome has been adding new capabilities to the web, such as [File System Access](https://developer.mozilla.org/docs/Web/API/File_System_Access_API) and [WebTransport](https://web.dev/webtransport/), and has made further investments in technologies like WebAssembly. The web is now more capable than ever, enabling developers to bring to the web highly capable applications such as [Photoshop](https://web.dev/ps-on-the-web). +Over the years, Chrome has been adding new capabilities to the web, such as [File System Access](https://developer.mozilla.org/docs/Web/API/File_System_Access_API) and [WebTransport](https://web.dev/articles/webtransport), and has made further investments in technologies like WebAssembly. The web is now more capable than ever, enabling developers to bring to the web highly capable applications such as [Photoshop](https://web.dev/ps-on-the-web). Though the Chrome team has been working hard to build new capabilities, we're responsible for only a small fraction of the work. Web app developers depend on countless others in the community who have built a strong ecosystem of APIs, tools, demonstration apps, and other materials. To help recognize the importance of this work and to enable more people to spend time on these projects, we're thrilled to announce today the launch of the Advanced Web Apps Fund: a new fund to support the web as a platform for advanced apps. diff --git a/site/en/blog/angular-image-directive/index.md b/site/en/blog/angular-image-directive/index.md index c509c4ff2..261092f06 100644 --- a/site/en/blog/angular-image-directive/index.md +++ b/site/en/blog/angular-image-directive/index.md @@ -16,16 +16,16 @@ tags: - aurora-project --- -In May 2022, the [Aurora](https://web.dev/introducing-aurora/) and Angular teams announced that they would collaborate on an [image directive](https://angular.io/guide/roadmap#improve-image-performance) for Angular. The directive was recently released for developer preview as part of Angular v14.2. This post talks about how the new image directive, `NgOptimizedImage`, supports image optimization in Angular. +In May 2022, the [Aurora](https://web.dev/articles/introducing-aurora) and Angular teams announced that they would collaborate on an [image directive](https://angular.io/guide/roadmap#improve-image-performance) for Angular. The directive was recently released for developer preview as part of Angular v14.2. This post talks about how the new image directive, `NgOptimizedImage`, supports image optimization in Angular. ## Background Images are a common and crucial component of web user experience, with [99.9%](https://almanac.httparchive.org/en/2021/media#images) of web pages generating requests for one or more images. Images are also the most significant contributors to page weight, constituting a median of [982 kilobytes](https://almanac.httparchive.org/en/2021/page-weight#fig-2) per page. -Due to their growing number and size, images can hinder the performance of web pages and affect [Core Web Vitals](https://web.dev/vitals/) metrics. For [79.4% of desktop pages](https://almanac.httparchive.org/en/2021/media#fig-4), an image was the Largest Contentful Paint ([LCP](https://web.dev/lcp/)) element in 2021. The pursuit of optimized images has thus become a constant endeavor for many of us. +Due to their growing number and size, images can hinder the performance of web pages and affect [Core Web Vitals](https://web.dev/articles/vitals) metrics. For [79.4% of desktop pages](https://almanac.httparchive.org/en/2021/media#fig-4), an image was the Largest Contentful Paint ([LCP](https://web.dev/articles/lcp)) element in 2021. The pursuit of optimized images has thus become a constant endeavor for many of us. -The Aurora team believes in leveraging the power of frameworks to provide baked-in solutions to common developer challenges. Their first foray into the image optimization space was the [Next.js image component](https://web.dev/image-component/). They considered this component to be a testing ground for whether improving the developer experience (DX) of image optimization could lead to performance wins for more apps using frameworks. +The Aurora team believes in leveraging the power of frameworks to provide baked-in solutions to common developer challenges. Their first foray into the image optimization space was the [Next.js image component](https://web.dev/articles/image-component). They considered this component to be a testing ground for whether improving the developer experience (DX) of image optimization could lead to performance wins for more apps using frameworks. The first set of results from Next.js user [Leboncoin](https://medium.com/leboncoin-engineering-blog/how-we-are-improving-our-web-performance-9f850d59d810) was encouraging. Leboncoin saw a significant LCP improvement (from 2.4s to 1.7s) after they started using `next/image`. The subsequent adoption of `next/image` in the community played a role in the increase of Next.js origins meeting LCP thresholds. Soon there were [requests](https://github.com/angular/angular/issues/42765) for similar features in other frameworks, one of them being [Angular](https://angular.io/). @@ -58,19 +58,19 @@ The highlights of the design are as follows: 1. **Intelligent lazy loading** - Images that are invisible to the user on page load (for example, below-the-fold images or hidden carousel images) should ideally be [lazy-loaded](https://web.dev/lazy-loading-images/). Lazy loading frees up browser resources to load other critical text, media, or scripts. Most images are non-critical and should be lazy-loaded, but only [7.8% of pages](https://almanac.httparchive.org/en/2021/resource-hints#fig-16) used native lazy loading in 2021. + Images that are invisible to the user on page load (for example, below-the-fold images or hidden carousel images) should ideally be [lazy-loaded](https://web.dev/articles/lazy-loading-images). Lazy loading frees up browser resources to load other critical text, media, or scripts. Most images are non-critical and should be lazy-loaded, but only [7.8% of pages](https://almanac.httparchive.org/en/2021/resource-hints#fig-16) used native lazy loading in 2021. The Angular image directive lazy loads non-critical images by default and only eagerly loads images specially marked as `priority`. This ensures that most images exhibit optimal loading behavior. 2. **Prioritization of critical images** - Adding resource hints (e.g., <code>[preload](https://web.dev/preload-critical-assets/)</code> or <code>[preconnect](https://web.dev/uses-rel-preconnect/)</code>) to prioritize the loading of critical images is a [recommended best practice](https://web.dev/preload-critical-assets/). However, most apps are not using them. According to the 2021 Web Almanac, only [12.7% of mobile pages](https://almanac.httparchive.org/en/2021/resource-hints#fig-2) use preconnect hints and [only 22.1% of mobile pages](https://almanac.httparchive.org/en/2021/resource-hints#fig-2) use preload hints. + Adding resource hints (e.g., <code>[preload](https://web.dev/articles/preload-critical-assets)</code> or <code>[preconnect](https://web.dev/articles/uses-rel-preconnect)</code>) to prioritize the loading of critical images is a [recommended best practice](https://web.dev/articles/preload-critical-assets). However, most apps are not using them. According to the 2021 Web Almanac, only [12.7% of mobile pages](https://almanac.httparchive.org/en/2021/resource-hints#fig-2) use preconnect hints and [only 22.1% of mobile pages](https://almanac.httparchive.org/en/2021/resource-hints#fig-2) use preload hints. The image directive acts on two fronts when images are marked as priority. - * It sets the [fetchpriority](https://web.dev/fetch-priority/#increase-the-priority-of-the-lcp-image) of the image to `"high"` so that the browser knows that it should download the image with a high priority. + * It sets the [fetchpriority](https://web.dev/articles/fetch-priority#increase_the_priority_of_the_lcp_image) of the image to `"high"` so that the browser knows that it should download the image with a high priority. * In development mode, a runtime check confirms that a `preconnect` resource hint has been included corresponding to the image's origin. In development mode, the directive also uses the [PerformanceObserver API](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceObserver) to verify that the [LCP image](https://developer.mozilla.org/en-US/docs/Web/API/LargestContentfulPaint/element) has been marked `priority` as expected. If it's not marked `priority`, an error is thrown, instructing the developer to add the `priority` attribute to the LCP image. @@ -81,7 +81,7 @@ The highlights of the design are as follows: 3. **Optimized configuration for popular image tooling** - It's recommended that Angular applications [use image CDNs](https://web.dev/image-cdns/), which often provide optimization services by default. + It's recommended that Angular applications [use image CDNs](https://web.dev/articles/image-cdns), which often provide optimization services by default. The directive encourages using image CDNs by providing an especially appealing developer experience (DX) to configure them in the app. It supports a loader API that allows you to define the CDN provider and your base URL in your configuration. Once configured, you only have to define the asset name in the markup. For example, @@ -110,7 +110,7 @@ The highlights of the design are as follows: In addition to the above built-in optimizations, the directive also has built-in checks to ensure that developers have followed the recommended best practices in the image markup. The image directive performs the following checks. - 1. **Unsized images:** The image directive throws an error if the image markup does not have defined an explicit width and height. Unsized images can cause [layout shifts](https://web.dev/optimize-cls/#images-without-dimensions), affecting the page's Cumulative Layout Shift ([CLS](https://web.dev/cls/)) metric. The recommended best practice to prevent this is that images should have `width` and `height` attributes specified. + 1. **Unsized images:** The image directive throws an error if the image markup does not have defined an explicit width and height. Unsized images can cause [layout shifts](https://web.dev/articles/optimize-cls#images_without_dimensions), affecting the page's Cumulative Layout Shift ([CLS](https://web.dev/articles/cls)) metric. The recommended best practice to prevent this is that images should have `width` and `height` attributes specified. 2. **Aspect ratio:** The image directive throws an error to let developers know if the aspect ratio of the `width`:`height` defined in the HTML is not close to the actual aspect ratio of the rendered image. This can cause the image to look distorted on screen. This can happen if 1. You have defined the wrong dimensions (width or height) by mistake or @@ -131,7 +131,7 @@ Some of the challenges encountered are as follows: 1. **Supporting resource hints** - [Preloading critical assets](https://web.dev/preload-critical-assets/) helps the browser discover them earlier. However, including resource hints in Angular apps is complicated because: + [Preloading critical assets](https://web.dev/articles/preload-critical-assets) helps the browser discover them earlier. However, including resource hints in Angular apps is complicated because: **Manual Addition**: It's difficult for developers to add the `preload` resource hint manually. Angular uses one shared index.html file for the entire project or for all routes in the website. Thus, the `<head>` of the document is the same for every route (at least at serve time). Adding any `preload` hint to the `<head>` would mean that the resource would be preloaded for all routes even where it is not required. Thus, the manual addition of `preload` hints is not recommended. @@ -144,7 +144,7 @@ Some of the challenges encountered are as follows: 2. **Optimizing image size and format on the server** - As Angular apps are typically client-side rendered, images on the file system cannot be compressed at request time and are served as is. For this reason, using image CDNs is recommended to compress images and convert them into [modern formats like WebP](https://web.dev/serve-images-webp/) or AVIF on demand. + As Angular apps are typically client-side rendered, images on the file system cannot be compressed at request time and are served as is. For this reason, using image CDNs is recommended to compress images and convert them into [modern formats like WebP](https://web.dev/articles/serve-images-webp) or AVIF on demand. While the directive does not enforce the use of image CDN’s, it's strongly encouraged to use them with the directive and its built-in loaders ensure that the correct configuration options are used. @@ -177,7 +177,7 @@ One of these partners was [Land's End](https://www.landsend.com/). It was expect [Lighthouse lab testing](https://philipwalton.com/articles/my-challenge-to-the-web-performance-community/) was performed on their QA environment before and after using the image directive. On desktop, their median LCP decreased from 12.0s to 3.0s, a 75% improvement in LCP. On mobile, the median LCP decreased from 20.2s to 12.0s (40.6% improvement). {% Aside %} -It's important to note that the lab testing above is only intended as a general demonstration of the potential of the directive. [Field data](https://web.dev/lab-and-field-data-differences/#field-data) is much preferred to validate performance impact. The Aurora team is currently working with a few production partners to attain this data, and the blog post will be updated as soon as it's available. +It's important to note that the lab testing above is only intended as a general demonstration of the potential of the directive. [Field data](https://web.dev/articles/lab-and-field-data-differences#field_data) is much preferred to validate performance impact. The Aurora team is currently working with a few production partners to attain this data, and the blog post will be updated as soon as it's available. {% endAside %} diff --git a/site/en/blog/animated-blur/index.md b/site/en/blog/animated-blur/index.md index 5090a19ed..72740f17e 100644 --- a/site/en/blog/animated-blur/index.md +++ b/site/en/blog/animated-blur/index.md @@ -151,9 +151,9 @@ with the author's CSS styles or even their JavaScript. You are right. Enter Shadow DOM! While most people think about [Shadow -DOM](https://web.dev/shadowdom-v1/) as a way to attach "internal" +DOM](https://web.dev/articles/shadowdom-v1) as a way to attach "internal" elements to their [Custom -Elements](https://web.dev/custom-elements-v1/), it is also an +Elements](https://web.dev/articles/custom-elements-v1), it is also an isolation and performance primitive! JavaScript and CSS cannot pierce Shadow DOM boundaries which allows us to duplicate content without interfering with the developer's styles or application logic. We already have a `<div>` element for @@ -166,7 +166,7 @@ copies are styled the same way as the original. {% Aside %} In most cases — especially when writing custom elements — we advise against using closed `ShadowRoots`. Find out more in [Eric's -article](https://web.dev/shadowdom-v1/#creating-closed-shadow-roots-should-avoid). +article](https://web.dev/articles/shadowdom-v1#creating_closed_shadow_roots_should_avoid). {% endAside %} diff --git a/site/en/blog/announce-enrollment-privacy-sandbox/index.md b/site/en/blog/announce-enrollment-privacy-sandbox/index.md index 5968ebf46..690aa6ed5 100644 --- a/site/en/blog/announce-enrollment-privacy-sandbox/index.md +++ b/site/en/blog/announce-enrollment-privacy-sandbox/index.md @@ -18,7 +18,7 @@ tags: - privacy --- -As we make plans for general availability of the Privacy Sandbox relevance and measurement APIs, including Attribution Reporting, FLEDGE, Topics, Private Aggregation and Shared Storage, we want to make sure these technologies are used as intended and with transparency. Today, we are announcing a new Developer Enrollment process for Privacy Sandbox relevance and measurement APIs, across Chrome and Android. This will replace the current Privacy Sandbox Android enrollment process. +As we make plans for general availability of the Privacy Sandbox relevance and measurement APIs, including Attribution Reporting, FLEDGE, Topics, Private Aggregation and Shared Storage, we want to make sure these technologies are used as intended and with transparency. Today, we are announcing a new Developer Enrollment process for Privacy Sandbox relevance and measurement APIs, across Chrome and Android. This will replace the current Privacy Sandbox Android enrollment process. The enrollment process will verify the entities calling the APIs, and gather data needed to properly configure and use these APIs. @@ -32,11 +32,11 @@ the new enrollment process goes live in June 2023. ## Why are we asking you to enroll? -It is of paramount importance to the Privacy Sandbox that we protect user privacy. This enrollment process adds an additional layer of protections on top of the structural restrictions enforced within each API, by adding transparency to who is collecting data, and mitigating attempts to misuse the APIs to gather more data than intended. +It is of paramount importance to the Privacy Sandbox that we protect user privacy. This enrollment process adds an additional layer of protections on top of the structural restrictions enforced within each API, by adding transparency to who is collecting data, and mitigating attempts to misuse the APIs to gather more data than intended. -To provide auditable transparency, enrollment information about the company will be made public. We will provide further details in a later update on how the public will be able to access this information. +To provide auditable transparency, enrollment information about the company will be made public. We will provide further details in a later update on how the public will be able to access this information. -To limit how much data an API caller can receive, we've already incorporated rate limits for each developer into the relevance and measurement APIs. Enrollment allows us to better enforce those rate limits by using an independent, third party verification service. We will use Dun & Bradstreet to verify your corporate identity and any potential corporate linkages. +To limit how much data an API caller can receive, we've already incorporated rate limits for each developer into the relevance and measurement APIs. Enrollment allows us to better enforce those rate limits by using an independent, third party verification service. We will use Dun & Bradstreet to verify your corporate identity and any potential corporate linkages. This verification process will also help ensure that one developer can't impersonate another developer and limit their usage of the APIs. Lastly, this effort brings the Privacy Sandbox Chrome and Android ecosystems to a shared enrollment process, which ensures you won't have to duplicate verification efforts across platforms. @@ -53,12 +53,12 @@ To enroll, we will ask you to provide the following information: * Other inputs necessary for API or server configurations (such as sites and/or SDKs used to call the APIs, etc.) * List of requested APIs -We intend for this process to be lightweight, so that developers can easily set up and begin testing the Privacy Sandbox APIs. Extra assistance in transitioning to the new enrollment process will be provided for currently enrolled Android testers, and Google support channels will be available to address any enrollment related questions. +We intend for this process to be lightweight, so that developers can easily set up and begin testing the Privacy Sandbox APIs. Extra assistance in transitioning to the new enrollment process will be provided for currently enrolled Android testers, and Google support channels will be available to address any enrollment related questions. ### Site-based enrollment All API callers will need to enroll their -[site](https://web.dev/same-site-same-origin/#public-suffix-list-and-etld). A +[site](https://web.dev/articles/same-site-same-origin#public_suffix_list_and_etld). A site provides a boundary that informs the Privacy Sandbox API's privacy protections. @@ -81,7 +81,7 @@ tracking. Additionally, attestations help improve public transparency on data collected and used with the Privacy Sandbox APIs. The attestations will be written to be understandable by users, focused on outcomes rather than implementation -details. +details. We'll provide details about the attestations before the unified enrollment period is available so developers can review the full process. Developers will diff --git a/site/en/blog/anonymous-iframe-origin-trial/index.md b/site/en/blog/anonymous-iframe-origin-trial/index.md index ab8ed22f6..2947b285b 100644 --- a/site/en/blog/anonymous-iframe-origin-trial/index.md +++ b/site/en/blog/anonymous-iframe-origin-trial/index.md @@ -17,7 +17,7 @@ tags: {% Aside %} Anonymous iframe has been renamed to iframe credentialless. It is enabled by default starting from Chrome version 110. You can see the [announcement](/blog/iframe-credentialless) for further details. - + `<iframe anonymous></iframe>` is renamed `<iframe credentialless></iframe>`. `window.isAnonymouslyFramed` is renamed `window.credentialless`. {% endAside %} @@ -27,11 +27,11 @@ You can see the [announcement](/blog/iframe-credentialless) for further details. Some web APIs increase the risk of side-channel attacks such as [Spectre](https://en.wikipedia.org/wiki/Spectre_(security_vulnerability)). To mitigate that risk, browsers offer an opt-in-based isolated environment called -[cross-origin isolation](https://web.dev/coop-coep/), which, among other things, +[cross-origin isolation](https://web.dev/articles/coop-coep), which, among other things, requires deploying COEP. This allows websites to use privileged features including [`SharedArrayBuffer`](/blog/enabling-shared-array-buffer/), -[`performance.measureUserAgentSpecificMemory()`](https://web.dev/monitor-total-page-memory-usage/), +[`performance.measureUserAgentSpecificMemory()`](https://web.dev/articles/monitor-total-page-memory-usage), and [high-precision timers with better resolution](/blog/cross-origin-isolated-hr-timers/). @@ -54,7 +54,7 @@ Cross-Origin-Opener-Policy: same-origin While cross-origin isolation brings webpages better security and the ability to enable powerful features, deploying COEP can be -[difficult](https://web.dev/cross-origin-isolation-guide/). One of the biggest +[difficult](https://web.dev/articles/cross-origin-isolation-guide). One of the biggest challenges is that all cross-origin iframes must also deploy COEP and CORP. Iframes without those headers will not be loaded by the browser. @@ -105,7 +105,7 @@ iframes: 1. [Request a token](/origintrials/#/view_trial/2518638091606949889) for your origin. 1. Use the token in one of the following ways: - - In your HTML: + - In your HTML: ```html <meta http-equiv="Origin-Trial" content="TOKEN_GOES_HERE"> ``` @@ -161,8 +161,8 @@ anonymous iframe. ## Resources -- [Making your website "cross-origin isolated" using COOP and COEP](https://web.dev/coop-coep/) -- [Why you need "cross-origin isolated" for powerful features](https://web.dev/why-coop-coep/) -- [A guide to enable cross-origin isolation](https://web.dev/cross-origin-isolation-guide/) +- [Making your website "cross-origin isolated" using COOP and COEP](https://web.dev/articles/coop-coep) +- [Why you need "cross-origin isolated" for powerful features](https://web.dev/articles/why-coop-coep) +- [A guide to enable cross-origin isolation](https://web.dev/articles/cross-origin-isolation-guide) - [SharedArrayBuffer updates in Android Chrome 88 and Desktop Chrome 92](/blog/enabling-shared-array-buffer/) - [Load cross-origin resources without CORP headers using `COEP: credentialless`](/blog/coep-credentialless-origin-trial/) diff --git a/site/en/blog/app-install-banners-native/index.md b/site/en/blog/app-install-banners-native/index.md index 81c543f22..e4f524a78 100644 --- a/site/en/blog/app-install-banners-native/index.md +++ b/site/en/blog/app-install-banners-native/index.md @@ -154,7 +154,7 @@ the next page navigation. ## Special considerations for when using content security policy -If your site has a restrictive [Content Security Policy](https://web.dev/csp/), +If your site has a restrictive [Content Security Policy](https://web.dev/articles/csp), make sure to add `*.googleusercontent.com` to the `img-src` directive so Chrome can download the icon associated with your app from the Play Store. diff --git a/site/en/blog/app-shell/index.md b/site/en/blog/app-shell/index.md index d98e4d1c6..a2133ecd8 100644 --- a/site/en/blog/app-shell/index.md +++ b/site/en/blog/app-shell/index.md @@ -116,7 +116,7 @@ The application shell architecture makes the most sense for apps and sites that ## Are there any production apps using this pattern yet? -The application shell architecture is possible with just a few changes to your overall application’s UI and has worked well for large-scale sites such as Google’s [I/O 2015 Progressive Web App](https://web.dev/service-workers-iowa/) and Google’s Inbox. +The application shell architecture is possible with just a few changes to your overall application’s UI and has worked well for large-scale sites such as Google’s [I/O 2015 Progressive Web App](https://web.dev/articles/service-workers-iowa) and Google’s Inbox. <figure> {% Img src="image/T4FyVKpzu4WKF1kBNvXepbi08t52/VrI0pv3eihgLe7qMF3Hs.png", alt="Image of Google Inbox loading. Illustrates Inbox using service worker.", width="800", height="618" %} diff --git a/site/en/blog/ar-for-the-web/index.md b/site/en/blog/ar-for-the-web/index.md index 2e2deeaa6..a6b824c21 100644 --- a/site/en/blog/ar-for-the-web/index.md +++ b/site/en/blog/ar-for-the-web/index.md @@ -10,7 +10,7 @@ updated: 2018-07-30 --- In Chrome 67, -[we announced](https://web.dev/welcome-to-immersive/) +[we announced](https://web.dev/articles/welcome-to-immersive) the WebXR Device API for both augmented reality (AR) and virtual reality (VR), though only the VR features were enabled. VR is an experience based purely on what's in a computing device. AR on the other hand allows you to render virtual @@ -62,7 +62,7 @@ turned on. Please excuse our construction debris. At Google IO this year, we demonstrated augmented reality with an early build of Chrome. I said something repeatedly to developers and non-developers alike during those three days that I wish I had known to put in my -[immersive web article](https://web.dev/welcome-to-immersive/): +[immersive web article](https://web.dev/articles/welcome-to-immersive): "It's just the web." {% YouTube id="1t1gBVykneA" %} @@ -120,7 +120,7 @@ will look next to your other furniture. A key problem to solve when implementing augmented reality is how to place objects in a real-world view. The method for doing this is called _ray casting_. Ray casting means calculating the intersection between the -[pointer ray](https://web.dev/welcome-to-immersive/#the-input-device-and-the-pointer-ray) +[pointer ray](https://web.dev/articles/welcome-to-immersive#the_input_device_and_the_pointer_ray) and a surface in the real world. That intersection is called a _hit_ and determining whether a hit has occurred is a _hit test_. @@ -160,10 +160,10 @@ helping you understand what's going on. The basics of entering an AR session and running a render loop are the same for AR as they are for VR. You can read -[my previous article](https://web.dev/welcome-to-immersive/) +[my previous article](https://web.dev/articles/welcome-to-immersive) if you're unfamiliar. To be more specific, entering and running an AR session looks almost exactly like -[entering a VR magic window session](https://web.dev/welcome-to-immersive/#starting-and-running-an-app). +[entering a VR magic window session](https://web.dev/articles/welcome-to-immersive#starting_and_running_an_app). As with a magic window, the session type must be non-immersive and the frame of reference type must be `'eye-level'`. diff --git a/site/en/blog/audio-worklet-design-pattern/index.md b/site/en/blog/audio-worklet-design-pattern/index.md index cd12013b4..94ba0bbc7 100644 --- a/site/en/blog/audio-worklet-design-pattern/index.md +++ b/site/en/blog/audio-worklet-design-pattern/index.md @@ -79,7 +79,7 @@ the accompanied code example can be found [here](https://googlechromelabs.github.io/web-audio-samples/audio-worklet/design-pattern/wasm/). For the basic tutorial on how to use Emscripten and WebAssembly (especially the Emscripten glue code), please take a look at -[this article](https://web.dev/emscripting-a-c-library/). +[this article](https://web.dev/articles/emscripting-a-c-library). #### Setting Up diff --git a/site/en/blog/aurora-resource-inlining/index.md b/site/en/blog/aurora-resource-inlining/index.md index 8214a9075..421d9793a 100644 --- a/site/en/blog/aurora-resource-inlining/index.md +++ b/site/en/blog/aurora-resource-inlining/index.md @@ -106,7 +106,7 @@ context of Angular](https://www.youtube.com/watch?v=yOpy9UMQG-Y). Another enhancement involves improving the [First Contentful Paint (FCP)](https://web.dev/fcp) and [Largest Contentful Paint (LCP)](https://web.dev/lcp) metrics by inlining critical CSS. The critical CSS of a page includes all of the styles used at its initial rendering. To learn more about the topic, check out -[Defer non-critical CSS](https://web.dev/defer-non-critical-css/). +[Defer non-critical CSS](https://web.dev/articles/defer-non-critical-css). We observed that many applications are loading styles synchronously, which blocks application rendering. A quick fix is to load the styles asynchronously. Rather than loading the scripts with @@ -139,9 +139,9 @@ updating the `media` attribute to `all`, and applies the styles to the DOM. During the time between rendering the HTML and applying the styles the page is partially unstyled. When the browser uses the styles, we see flickering, which is a bad user experience and results in -regressions in [Cumulative Layout Shift (CLS)](https://web.dev/cls/). +regressions in [Cumulative Layout Shift (CLS)](https://web.dev/articles/cls). -[Critical CSS inlining](https://web.dev/extract-critical-css/), along with asynchronous style loading, can improve +[Critical CSS inlining](https://web.dev/articles/extract-critical-css), along with asynchronous style loading, can improve the loading behavior. The [critters](http://npmjs.com/package/critters) tool finds which styles are used on the page, by looking at the selectors in a stylesheet and matching them against the HTML. When it finds a match, it considers the corresponding styles as part of the critical CSS, and diff --git a/site/en/blog/aurora-update-2023/index.md b/site/en/blog/aurora-update-2023/index.md index 2393bc62d..39e1edac4 100644 --- a/site/en/blog/aurora-update-2023/index.md +++ b/site/en/blog/aurora-update-2023/index.md @@ -15,11 +15,11 @@ alt: > Chrome's Aurora initiative is a collaboration between Chrome and open-source Javascript frameworks and tooling to improve user experience on the web. If Aurora is new to you, take a look at our [introduction post](/blog/introducing-aurora/) to learn more about our mission and methodology. -Given that we haven't published a roadmap since 2021, we'd like to share what we've been up to and some exciting projects we have in store for 2023. +Given that we haven't published a roadmap since 2021, we'd like to share what we've been up to and some exciting projects we have in store for 2023. ## Recent project highlights -For the past few years, we've been partnering with frameworks like Next.js, Angular, and Nuxt to optimize [Core Web Vitals](https://web.dev/vitals/). Here are some highlights since our last update. +For the past few years, we've been partnering with frameworks like Next.js, Angular, and Nuxt to optimize [Core Web Vitals](https://web.dev/articles/vitals). Here are some highlights since our last update. ### Images @@ -27,9 +27,9 @@ Images are often a source of performance issues. The following are some of the m #### Angular image directive -We published a [stable image directive](https://angular.io/guide/image-directive) for the Angular framework, available in Angular 15 and specially backported to 13.4 and 14.3. This directive enables [native lazy loading](https://web.dev/browser-level-image-lazy-loading/) by default, adds [`fetchpriority` hints](https://web.dev/fetch-priority/) to priority images, and automatically generates appropriate `srcset` attributes for responsive images. +We published a [stable image directive](https://angular.io/guide/image-directive) for the Angular framework, available in Angular 15 and specially backported to 13.4 and 14.3. This directive enables [native lazy loading](https://web.dev/articles/browser-level-image-lazy-loading) by default, adds [`fetchpriority` hints](https://web.dev/articles/fetch-priority) to priority images, and automatically generates appropriate `srcset` attributes for responsive images. -**The impact**: [Lighthouse lab testing](https://philipwalton.com/articles/my-challenge-to-the-web-performance-community/) was performed on [Land's End's](https://www.landsend.com/) QA environment before and after using the image directive. On desktop, their median [Largest Contentful Paint (LCP)](https://web.dev/lcp/) decreased from 12.0s to 3.0s, a 75% improvement in LCP. +**The impact**: [Lighthouse lab testing](https://philipwalton.com/articles/my-challenge-to-the-web-performance-community/) was performed on [Land's End's](https://www.landsend.com/) QA environment before and after using the image directive. On desktop, their median [Largest Contentful Paint (LCP)](https://web.dev/articles/lcp) decreased from 12.0s to 3.0s, a 75% improvement in LCP. <figure> {% Img src="image/IypihH3o5cSpEMVp5i08dp69otp2/Jc3mkO2gYZGOPul8Dpgk.png", alt="Filmstrip comparison: Website One with native image tags versus Website Two with the Angular image directive.", width="800", height="391" %} @@ -39,13 +39,13 @@ Read more about the directive in our blog post, [Optimizing Images with the Angu #### Revamped `next/image` -We also worked with the Next.js team to update the [image component](https://nextjs.org/docs/app/building-your-application/optimizing/images) to use new browser features like native lazy loading and `fetchpriority` HTML attribute. The new version is available by default from Next 13. +We also worked with the Next.js team to update the [image component](https://nextjs.org/docs/app/building-your-application/optimizing/images) to use new browser features like native lazy loading and `fetchpriority` HTML attribute. The new version is available by default from Next 13. **The impact** : Our partner [Leboncoin](https://www.leboncoin.fr/) was able to improve the LCP of some pages by up to 60% by switching to the new version of `next/image`. ### Web fonts -Web font optimization can be tricky to get right, as there's more involved than reducing the transfer size of font resources. Web fonts can also contribute significantly to a page's [Cumulative Layout Shift (CLS)](https://web.dev/cls/) metric, and minimizing layout shifts due to font swaps requires considerable effort. Fortunately, we partnered with frameworks to make this task even easier for web developers. +Web font optimization can be tricky to get right, as there's more involved than reducing the transfer size of font resources. Web fonts can also contribute significantly to a page's [Cumulative Layout Shift (CLS)](https://web.dev/articles/cls) metric, and minimizing layout shifts due to font swaps requires considerable effort. Fortunately, we partnered with frameworks to make this task even easier for web developers. #### Tooling for improved font fallbacks in Next.js, Nuxt, and Vite @@ -57,11 +57,11 @@ Read more in our blog posts about [generating improved font fallbacks](/blog/fon #### `nuxtjs/google-fonts` module -We partnered with the Nuxt team to release a [module](https://google-fonts.nuxtjs.org/) to optimize Google Font performance. The module automatically downloads and self-hosts Google fonts to avoid an extra server round trip and also supports font inlining options. +We partnered with the Nuxt team to release a [module](https://google-fonts.nuxtjs.org/) to optimize Google Font performance. The module automatically downloads and self-hosts Google fonts to avoid an extra server round trip and also supports font inlining options. ### Third-party scripts -Third-party JavaScript is a potential source of performance issues, and may affect metrics such as [Interaction to Next Paint (INP)](https://web.dev/inp/), as the work these scripts schedule may delay user interactions from running. +Third-party JavaScript is a potential source of performance issues, and may affect metrics such as [Interaction to Next Paint (INP)](https://web.dev/articles/inp), as the work these scripts schedule may delay user interactions from running. #### `next/script` component for third-party scripts @@ -87,19 +87,19 @@ Read more in our blog post, [Inside the Container Query Polyfill](/blog/inside-t ## What's next for Aurora? -In 2023-2024, we have a number of exciting projects coming down the pipeline to optimize Core Web Vitals for framework developers. +In 2023-2024, we have a number of exciting projects coming down the pipeline to optimize Core Web Vitals for framework developers. In the coming year, we will be focused on the following: -* **Third-party wrapper components for Next.js and Nuxt**: Wrapper components can facilitate loading popular 3P libraries in an optimal way for LCP and INP. Drop a component tag into the DOM to load your 3P instead of a script tag and the framework will select the best loading strategy. See [the RFC](https://github.com/vercel/next.js/discussions/48256) for more details. +* **Third-party wrapper components for Next.js and Nuxt**: Wrapper components can facilitate loading popular 3P libraries in an optimal way for LCP and INP. Drop a component tag into the DOM to load your 3P instead of a script tag and the framework will select the best loading strategy. See [the RFC](https://github.com/vercel/next.js/discussions/48256) for more details. * **Angular SSR and hydration developer experience**: We have been working closely with the Angular team on the [SSR and hydration project](https://angular.io/guide/hydration). Our focus has been to upgrade the developer experience of using SSR, allowing more applications to take advantage of the LCP benefits. Stay tuned for an official RFC around SSR DOM manipulation features. * **Angular image directive and `nuxt/image` features**: We have a number of exciting features planned for Angular, such as automatic preconnect hint generation, migration tools to aid the transition from basic `<img>` elements, `<picture>` element support, and placeholders. We will also be consulting with the Nuxt team on a number of new features for `nuxt/image`. -* **INP research (cross-framework)**: As [Interaction to Next Paint (INP)](https://web.dev/inp/) will be replacing [First Input Delay (FID)](https://web.dev/fid/) in 2024, we are ramping up support for improving INP in frameworks. This will involve analysis of the root causes for INP issues in frameworks and creating built-in solutions for framework users where possible. +* **INP research (cross-framework)**: As [Interaction to Next Paint (INP)](https://web.dev/articles/inp) will be replacing [First Input Delay (FID)](https://web.dev/articles/fid) in 2024, we are ramping up support for improving INP in frameworks. This will involve analysis of the root causes for INP issues in frameworks and creating built-in solutions for framework users where possible. -* **Speedometer 3**: We are also helping to implement the next generation of the benchmarking tool [Speedometer](https://browserbench.org/Speedometer2.0/) to represent the modern web framework landscape of 2023. +* **Speedometer 3**: We are also helping to implement the next generation of the benchmarking tool [Speedometer](https://browserbench.org/Speedometer2.0/) to represent the modern web framework landscape of 2023. ## Stay up to date diff --git a/site/en/blog/automating-resource-selection-with-client-hints/index.md b/site/en/blog/automating-resource-selection-with-client-hints/index.md index 8e040c684..6418e447a 100644 --- a/site/en/blog/automating-resource-selection-with-client-hints/index.md +++ b/site/en/blog/automating-resource-selection-with-client-hints/index.md @@ -13,12 +13,12 @@ Building for the web gives you unparalleled reach. Your web application is a click away and available on almost every connected device-smartphone, tablet, laptop and desktop, TV, and more-regardless of the brand or the platform. To deliver the best experience you've built a -[responsive site](https://web.dev/responsive-web-design-basics/) that +[responsive site](https://web.dev/articles/responsive-web-design-basics) that adapts the presentation and functionality for each form-factor, and now you're running down your performance checklist to ensure that the application loads as quickly as possible: you've optimized your -[critical rendering path](https://web.dev/critical-rendering-path/), -you've [compressed and cached](https://web.dev/performance-optimizing-content-efficiency/) +[critical rendering path](https://web.dev/articles/critical-rendering-path), +you've [compressed and cached](https://web.dev/articles/performance-optimizing-content-efficiency) your text resources, and now you're looking at your image resources, which often account for the majority of transferred bytes. Problem is, **image optimization is hard**: @@ -31,7 +31,7 @@ is hard**: * ... * Account for user's network type, speed, and preferences -Individually, these are [well-understood problems](https://web.dev/fast/#optimize-your-images). +Individually, these are [well-understood problems](https://web.dev/articles/fast#optimize_your_images). Collectively, they create a large optimization space that we (the developers) often overlook or neglect. Humans do a poor job of exploring the same search space repetitively, especially when many steps diff --git a/site/en/blog/avoid-not-secure-warn/index.md b/site/en/blog/avoid-not-secure-warn/index.md index 282b816b8..0b5ae2c04 100644 --- a/site/en/blog/avoid-not-secure-warn/index.md +++ b/site/en/blog/avoid-not-secure-warn/index.md @@ -46,7 +46,7 @@ has been added to the URL bar.` To ensure that the Not Secure warning is not displayed for your pages, you must ensure that all forms containing `<input type=password>` elements and any inputs detected as [credit card -fields](https://web.dev/learn/forms/autofill/#help-users-fill-in-their-credit-card-information) are present _only_ +fields](https://web.dev/learn/forms/autofill#help_users_fill_in_their_credit_card_information) are present _only_ on secure origins. This means that the top-level page must be HTTPS and, if the `input` is in an iframe, that iframe must also be served over HTTPS. diff --git a/site/en/blog/background-fetch/index.md b/site/en/blog/background-fetch/index.md index 39b269d90..a5b23b42b 100644 --- a/site/en/blog/background-fetch/index.md +++ b/site/en/blog/background-fetch/index.md @@ -27,7 +27,7 @@ updated: 2022-07-28 # How to add a new tag # https://developer.chrome.com/docs/handbook/how-to/add-a-tag/ #tags: - + --- @@ -42,7 +42,7 @@ too long the browser will kill the service worker, otherwise it's a risk to the battery. So, what if you need to download something that might take a long time, like a movie, podcasts, or -levels of a game. That's what [Background Fetch](https://developer.mozilla.org/docs/Web/API/Background_Fetch_API) is for. +levels of a game. That's what [Background Fetch](https://developer.mozilla.org/docs/Web/API/Background_Fetch_API) is for. Background Fetch is available by default since Chrome 74. @@ -52,7 +52,7 @@ Here's a quick two minute demo showing the traditional state of things, vs using [Try the demo yourself](https://bgfetch-http203.glitch.me/) and [browse the -code](https://glitch.com/edit/#!/bgfetch-http203?path=public/client.js). +code](https://glitch.com/edit/#!/bgfetch-http203?path=public/client.js). ## How it works @@ -108,7 +108,7 @@ navigator.serviceWorker.ready.then(async (swReg) => { {% Aside %} Many examples in this article use async functions. If you aren't familiar with them, [check -out the guide](https://web.dev/async-functions/). +out the guide](https://web.dev/articles/async-functions). {% endAside %} `backgroundFetch.fetch` takes three arguments: diff --git a/site/en/blog/background_tabs/index.md b/site/en/blog/background_tabs/index.md index c7c265fcb..7c0934a02 100644 --- a/site/en/blog/background_tabs/index.md +++ b/site/en/blog/background_tabs/index.md @@ -92,7 +92,7 @@ long time. Finally, remember that if you are using long tasks in the background, your application can be throttled for a very long period of time (up to 100 times the duration of your task). Split your work in to chunks of 50ms or less per -[the performance guidelines](https://web.dev/rail/) +[the performance guidelines](https://web.dev/articles/rail) and use the `visibilityChange` listener to avoid doing unnecessary work in background. ### Opt-outs diff --git a/site/en/blog/beyond-spa/index.md b/site/en/blog/beyond-spa/index.md index f4cb7f496..d1255d78c 100644 --- a/site/en/blog/beyond-spa/index.md +++ b/site/en/blog/beyond-spa/index.md @@ -75,7 +75,7 @@ the context of a multi-page app. You've heard me (and countless others) use the phrase "progressive web app", or PWA. You might already be familiar with some of the background material, [elsewhere on this -site](https://web.dev/progressive-web-apps/). +site](https://web.dev/explore/progressive-web-apps). You can think of a PWA as a web app that provides a first-class user experience, and that truly earns a place on the user's home screen. The acronym "**FIRE**", @@ -107,7 +107,7 @@ PWAs introduce a high bar for speed and resilience. Fortunately, the web platform offers some building blocks to make that type of performance a reality. I'm referring to [service workers](/docs/workbox/service-worker-overview) and the [Cache Storage -API](https://web.dev/cache-api-quick-guide/). +API](https://web.dev/articles/cache-api-quick-guide). You can build a service worker that listens for incoming requests, passing some on to the network, and storing a copy of the response for future use, via the @@ -352,8 +352,8 @@ and just like my server did, it uses a combination of routing and templating logic to figure out how to respond. The approach is the same as before, but with different low-level primitives, -like [`fetch()`](https://web.dev/introduction-to-fetch/) and the [Cache -Storage API](https://web.dev/cache-api-quick-guide/). I use +like [`fetch()`](https://web.dev/articles/introduction-to-fetch) and the [Cache +Storage API](https://web.dev/articles/cache-api-quick-guide). I use those data sources to construct the HTML response, which the service worker passes back to the web app. diff --git a/site/en/blog/browser-flags/index.md b/site/en/blog/browser-flags/index.md index d50b9db7b..821b2b6db 100644 --- a/site/en/blog/browser-flags/index.md +++ b/site/en/blog/browser-flags/index.md @@ -33,7 +33,7 @@ browser-internal settings or features. You can see the full list by putting ## Setting browser flags -For some [new APIs](https://web.dev/tags/capabilities/) in Chromium, you need to set a browser +For some [new APIs](https://web.dev/articles/tags/capabilities) in Chromium, you need to set a browser flag for experimentation. You guessed it, `chrome://flags` is where this happens. The most popular flag we ask you to set is `chrome://flags/#enable-experimental-web-platform-features`, which, as the name suggests, enables experimental web platform features. diff --git a/site/en/blog/canvas2d/index.md b/site/en/blog/canvas2d/index.md index 2add39256..f093d192f 100644 --- a/site/en/blog/canvas2d/index.md +++ b/site/en/blog/canvas2d/index.md @@ -179,7 +179,7 @@ ctx.clearRect(0, 0, canvas.width, canvas.height); <div style="border:solid 1px #ccc;"> {% Img src="image/kheDArv5csY6rvQUJDbWRscckLr1/ddoRhRRV8AuTy1Z82yEj.png", alt="A blank canvas.", width="500", height="500" %} -</div> +</div> Perfect! A nice blank canvas. Now let's start drawing a nice horizontal line: @@ -267,7 +267,7 @@ Easy as pie! Try it and play with the parameters {% Aside %} The app [SVGcode](https://svgco.de/), a PWA for converting raster images to SVGs, uses a dynamically created <code>CanvasFilter</code> for the task of posterization (more background in the -[accompanying article](https://web.dev/svgcode/)). Be sure to check out the app and the related +[accompanying article](https://web.dev/articles/svgcode)). Be sure to check out the app and the related [source code](https://github.com/tomayac/SVGcode/blob/ef037e33d05b17f43b32cfb2cf039145aeee6104/src/js/preprocessworker.js#L89-L113). {% endAside %} diff --git a/site/en/blog/capabilities/index.md b/site/en/blog/capabilities/index.md index c6ff5a86f..3f6edb9fd 100644 --- a/site/en/blog/capabilities/index.md +++ b/site/en/blog/capabilities/index.md @@ -35,7 +35,7 @@ trust, and other core tenets of the web. {% Aside %} To see a list of all the APIs that are currently in development, check -out [https://web.dev/fugu-status/](https://web.dev/fugu-status/) +out [https://web.dev/articles/fugu-status/](https://web.dev/fugu-status) {% endAside %} ## How will we design & implement these new capabilities? diff --git a/site/en/blog/cascade-layers/index.md b/site/en/blog/cascade-layers/index.md index 3977e7991..2d2f0feb2 100644 --- a/site/en/blog/cascade-layers/index.md +++ b/site/en/blog/cascade-layers/index.md @@ -19,7 +19,7 @@ Layering your CSS in a clear way prevents unexpected style overrides and promote ## CSS specificity and the cascade -[CSS specificity](https://web.dev/learn/css/specificity/) is how CSS decides which styles to apply to which elements. The different selectors you can use determine the specificity of any style rule. For example, elements are less specific than classes or attributes, which are in turn less specific than IDs. This is an elemental part of learning CSS. +[CSS specificity](https://web.dev/learn/css/specificity) is how CSS decides which styles to apply to which elements. The different selectors you can use determine the specificity of any style rule. For example, elements are less specific than classes or attributes, which are in turn less specific than IDs. This is an elemental part of learning CSS. Folks turn to CSS naming conventions like BEM to prevent overriding specificity unintentionally. By giving everything a single classname, everything is placed on the same specificity plane. However, it’s not always possible to maintain such organized styles, especially when working with third-party code and design systems. diff --git a/site/en/blog/chrome-107-beta/index.md b/site/en/blog/chrome-107-beta/index.md index 0277ca1bd..05e05892c 100644 --- a/site/en/blog/chrome-107-beta/index.md +++ b/site/en/blog/chrome-107-beta/index.md @@ -18,31 +18,31 @@ Unless otherwise noted, changes described below apply to the newest Chrome beta ## CSS `grid-template` properties interpolation -In CSS Grid, the `grid-template-columns` and `grid-template-rows` properties allow developers to define line names and track sizing of grid columns and rows, respectively. Thanks to our contributors at Microsoft, we now [support interpolation](https://www.chromestatus.com/feature/6037871692611584) for these properties. Grid layouts can now smoothly transition between states, instead of snapping at the halfway point of an animation or transition. +In CSS Grid, the `grid-template-columns` and `grid-template-rows` properties allow developers to define line names and track sizing of grid columns and rows, respectively. Thanks to our contributors at Microsoft, we now [support interpolation](https://www.chromestatus.com/feature/6037871692611584) for these properties. Grid layouts can now smoothly transition between states, instead of snapping at the halfway point of an animation or transition. ## Privacy preserving screen sharing controls The [Screen Capture API](https://w3c.github.io/mediacapture-screen-share/) introduces additions to the existing Media Capture and Streams API to let the user select a screen or portion of a screen (such as a window) to capture as a media stream. This stream can then be recorded or shared with others over the network. In this beta some new features are added to this API. -{% Aside %} -Learn more about the Screen Capture API in the MDN guide to [Using the Screen Capture API](https://developer.mozilla.org/docs/Web/API/Screen_Capture_API/Using_Screen_Capture). +{% Aside %} +Learn more about the Screen Capture API in the MDN guide to [Using the Screen Capture API](https://developer.mozilla.org/docs/Web/API/Screen_Capture_API/Using_Screen_Capture). {% endAside %} ### DisplayMediaStreamConstraints.selfBrowserSurface -Hint allowing Web applications to instruct the browser whether, upon calling `getDisplayMedia()`, the current tab should be excluded from the list of tabs offered to the user. +Hint allowing Web applications to instruct the browser whether, upon calling `getDisplayMedia()`, the current tab should be excluded from the list of tabs offered to the user. This helps prevent accidental self-capture, when users accidentally choose the tab in which the app is running, a Hall-of-Mirrors effect is produced, confusing users and derailing discussions with remote users. ### DisplayMediaStreamConstraints.surfaceSwitching -Adds an option to programmatically control whether Chrome shows a button for switching tabs while screen-shared. This option will be passed to `navigator.mediaDevices.getDisplayMedia()`. +Adds an option to programmatically control whether Chrome shows a button for switching tabs while screen-shared. This option will be passed to `navigator.mediaDevices.getDisplayMedia()`. -The Share this tab instead button allows users to seamlessly switch which tab they're sharing, without having to select the video-conferencing tab again, click a button to initiate `getDisplayMedia()` again, or selecting a new tab out of a long list of tabs. This behavior is exposed conditionally because not all Web applications are able to handle this behavior. +The Share this tab instead button allows users to seamlessly switch which tab they're sharing, without having to select the video-conferencing tab again, click a button to initiate `getDisplayMedia()` again, or selecting a new tab out of a long list of tabs. This behavior is exposed conditionally because not all Web applications are able to handle this behavior. ### MediaTrackConstraintSet.displaySurface -When `getDisplayMedia()` is called, the browser offers the user a choice of display surfaces: tabs, windows, or monitors. Using the displaySurface constraint, the Web application may now hint to the browser if it prefers that a certain surface type be more prominently offered to the user. +When `getDisplayMedia()` is called, the browser offers the user a choice of display surfaces: tabs, windows, or monitors. Using the displaySurface constraint, the Web application may now hint to the browser if it prefers that a certain surface type be more prominently offered to the user. [Find out more about how these features will help to avoid accidental oversharing.](/blog/avoiding-oversharing-when-screen-sharing/) @@ -52,16 +52,16 @@ Adds a field to [`PerfomanceResourceTiming`](https://developer.mozilla.org/docs/ ## Wildcards in permissions policy origins -This feature adds support for wildcards in permissions policy structured like `SCHEME://*.HOST:PORT` (for example, https://*.foo.com/) where a valid Origin could be constructed from `SCHEME://HOST:PORT` (for example, https://foo.com/). This requires that HOST is at least eTLD+1 (a registrable domain). This means that `https://*.bar.foo.com/` works but `https://*.com/` won't. Wildcards in the scheme and port section will be unsupported and `https://*.foo.com/` does not delegate to `https://foo.com/`. Before, a permissions policy might need to look like: +This feature adds support for wildcards in permissions policy structured like `SCHEME://*.HOST:PORT` (for example, https://*.foo.com/) where a valid Origin could be constructed from `SCHEME://HOST:PORT` (for example, https://foo.com/). This requires that HOST is at least eTLD+1 (a registrable domain). This means that `https://*.bar.foo.com/` works but `https://*.com/` won't. Wildcards in the scheme and port section will be unsupported and `https://*.foo.com/` does not delegate to `https://foo.com/`. Before, a permissions policy might need to look like: ```txt -permissions-policy: ch-ua-platform-version=(self "https://foo.com" "https://cdn1.foo.com" "https://cdn2.foo.com") +permissions-policy: ch-ua-platform-version=(self "https://foo.com" "https://cdn1.foo.com" "https://cdn2.foo.com") ``` -With this feature, you can use: +With this feature, you can use: -```txt -permissions-policy: ch-ua-platform-version=(self "https://foo.com" "https://*.foo.com") +```txt +permissions-policy: ch-ua-platform-version=(self "https://foo.com" "https://*.foo.com") ``` ## Support the `rel` attribute on `<form>` elements @@ -80,7 +80,7 @@ This trial is expected to run until Chrome 109. [Register for the trial here](/o ### Permissions-Policy: unload -This feature allows pages to disable the running of unload event handlers. The goal is to allow sites that have removed all unload handlers to ensure they do not accidentally add new ones. This will help sites migrate off unload event handlers and thereby [improve BFCache hit-rate](https://web.dev/bfcache/#never-use-the-unload-event). +This feature allows pages to disable the running of unload event handlers. The goal is to allow sites that have removed all unload handlers to ensure they do not accidentally add new ones. This will help sites migrate off unload event handlers and thereby [improve BFCache hit-rate](https://web.dev/articles/bfcache#never_use_the_unload_event). This trial is expected to run until Chrome 109. [Register for the trial here](/origintrials/#/view_trial/1012184016251518977). diff --git a/site/en/blog/chrome-108-beta/index.md b/site/en/blog/chrome-108-beta/index.md index 6098f7e17..874efefd2 100644 --- a/site/en/blog/chrome-108-beta/index.md +++ b/site/en/blog/chrome-108-beta/index.md @@ -22,7 +22,7 @@ Chrome 108 includes a number of new CSS features. ### CSS Overflow for replaced elements -Chrome will start to roll out a change that allows developers to use the existing `overflow` property with replaced elements that paint outside the content-box. Paired with `object-view-box` this can be used to create an image with a custom glow or shadow applied, with proper ink-overflow behavior like a CSS shadow would have. +Chrome will start to roll out a change that allows developers to use the existing `overflow` property with replaced elements that paint outside the content-box. Paired with `object-view-box` this can be used to create an image with a custom glow or shadow applied, with proper ink-overflow behavior like a CSS shadow would have. This is a potential breaking change, find out more in [A change to overflow on replaced elements](/blog/overflow-replaced-elements/). @@ -44,10 +44,10 @@ This feature has been added due to Chrome 108 adding support for LayoutNG printi ### Last baseline item alignment -This feature allows developers to align items within either flex or grid layout by their last baseline, instead of their first. This is done via the following properties: +This feature allows developers to align items within either flex or grid layout by their last baseline, instead of their first. This is done via the following properties: - `align-items: last baseline;` -- `justify-items: last baseline;` +- `justify-items: last baseline;` - `align-self: last baseline;` - `justify-self: last baseline;` @@ -65,21 +65,21 @@ The Federated Credential Management API allows users to bring their federated id ### Media Source Extensions in workers -Enables Media Source Extensions (MSE) API usage from DedicatedWorker contexts to enable improved performance of buffering media for playback by an HTMLMediaElement on the main Window context. By creating a MediaSource object on a DedicatedWorker context, an application may then obtain a MediaSourceHandle from it and transfer that handle to the main thread for use in attaching to an HTMLMediaElement. The context that created the MediaSource object may then use it to buffer media. +Enables Media Source Extensions (MSE) API usage from DedicatedWorker contexts to enable improved performance of buffering media for playback by an HTMLMediaElement on the main Window context. By creating a MediaSource object on a DedicatedWorker context, an application may then obtain a MediaSourceHandle from it and transfer that handle to the main thread for use in attaching to an HTMLMediaElement. The context that created the MediaSource object may then use it to buffer media. ### `Sec-CH-Prefers-Reduced-Motion` User Preference Media Features Client Hints Header -[User Preference Media Features Client Hints Headers](https://web.dev/user-preference-media-features-headers/) defines a set of HTTP Client Hints headers around user preference media features as defined by Media Queries Level 5. If used as Critical Client Hints, these headers allow servers to make smart choices regarding, for example, CSS inlining. `Sec-CH-Prefers-Reduced-Motion` reflects the user's `prefers-reduced-motion` preference. +[User Preference Media Features Client Hints Headers](https://web.dev/articles/user-preference-media-features-headers) defines a set of HTTP Client Hints headers around user preference media features as defined by Media Queries Level 5. If used as Critical Client Hints, these headers allow servers to make smart choices regarding, for example, CSS inlining. `Sec-CH-Prefers-Reduced-Motion` reflects the user's `prefers-reduced-motion` preference. ### WebTransport BYOB readers -Supports BYOB(bring-your-own-buffer) readers for WebTransport to allow reading into a developer-supplied buffer. BYOB readers can minimize buffer copies, and reduce memory allocations. +Supports BYOB(bring-your-own-buffer) readers for WebTransport to allow reading into a developer-supplied buffer. BYOB readers can minimize buffer copies, and reduce memory allocations. ### Wildcards in Permissions Policy Origins The Permissions Policy specification defines a mechanism that allows developers to selectively enable and disable use of various browser features and APIs. One capability of this mechanism allows features to be enabled only on explicitly enumerated origins (for example, `https://foo.com/`). This mechanism is not flexible enough for the design of some CDNs, which deliver content via an origin that might be hosted on one of several hundred possible subdomains. -Therefore, this feature adds support for wildcards in permissions policy structured like `SCHEME://*.HOST:PORT` (for example, `https://*.foo.com/`) where a valid Origin could be constructed from `SCHEME://HOST:PORT` (for example, `https://foo.com/`). This requires that HOST is a registrable domain. This means that `https://*.bar.foo.com/` works but `https://*.com/` won’t (if you want to allow all domains to use the feature, you should just delegate to `*`). +Therefore, this feature adds support for wildcards in permissions policy structured like `SCHEME://*.HOST:PORT` (for example, `https://*.foo.com/`) where a valid Origin could be constructed from `SCHEME://HOST:PORT` (for example, `https://foo.com/`). This requires that HOST is a registrable domain. This means that `https://*.bar.foo.com/` works but `https://*.com/` won’t (if you want to allow all domains to use the feature, you should just delegate to `*`). ### Sync methods for AccessHandles in File System Access API @@ -90,7 +90,7 @@ This is a potential breaking change, you can read more in [Breaking change: sync ### WebAuthn conditional UI -[Conditional UI](https://web.dev/passkey-form-autofill/) for WebAuthn is supported on Windows 22H2 or later, macOS, and Android P or later. The WebAuthn UI on desktop platforms has also been refreshed. +[Conditional UI](https://web.dev/articles/passkey-form-autofill) for WebAuthn is supported on Windows 22H2 or later, macOS, and Android P or later. The WebAuthn UI on desktop platforms has also been refreshed. ## Variable COLRv1 fonts and font feature detection @@ -158,18 +158,18 @@ The feature has no observable effects in primary use cases, but may constrain im #### Remove `navigateEvent.restoreScroll()` -`restoreScroll()` is being replaced by `navigateEvent.scroll()`. `scroll()` works identically except that it allows the developer to control scroll timing for non-traverse navigations (`scroll()` works when the scroll is not a restore, hence the name change along with the behavior change). +`restoreScroll()` is being replaced by `navigateEvent.scroll()`. `scroll()` works identically except that it allows the developer to control scroll timing for non-traverse navigations (`scroll()` works when the scroll is not a restore, hence the name change along with the behavior change). #### Remove `navigateEvent.transitionWhile()` -`transitionWhile()` is being replaced by `navigateEvent.intercept()` due to design flaws reported by developers. intercept() behaves nearly identically to transitionWhile(), but instead of taking a mandatory Promise parameter, it takes an optional handler function that returns a Promise. This allows the browser to control when the handler executes, which is later and more intuitive than for `transitionWhile()`. +`transitionWhile()` is being replaced by `navigateEvent.intercept()` due to design flaws reported by developers. intercept() behaves nearly identically to transitionWhile(), but instead of taking a mandatory Promise parameter, it takes an optional handler function that returns a Promise. This allows the browser to control when the handler executes, which is later and more intuitive than for `transitionWhile()`. #### Remove WebRTC mediaConstraint's `googIPv6` -`"googIPv6: false"` can be used to disable IPv6 support in WebRTC, as in the following example. +`"googIPv6: false"` can be used to disable IPv6 support in WebRTC, as in the following example. ```js new RTCPeerConnection({}, {mandatory:{googIPv6:false}}); ``` -IPv6 has been enabled by default for many years and we should not be able to disable it. This is a legacy API that does not exist in the spec. +IPv6 has been enabled by default for many years and we should not be able to disable it. This is a legacy API that does not exist in the spec. diff --git a/site/en/blog/chrome-110-beta/index.md b/site/en/blog/chrome-110-beta/index.md index 2518cb654..3291b83c5 100644 --- a/site/en/blog/chrome-110-beta/index.md +++ b/site/en/blog/chrome-110-beta/index.md @@ -36,7 +36,7 @@ Initial letters are large, decorative letters that have been used to start new s The [`:picture-in-picture`](https://developer.mozilla.org/docs/Web/CSS/:picture-in-picture) pseudo-class helps web developers customize the media player when videos enter and exit [Picture-in-Picture](https://developer.mozilla.org/docs/Web/API/Picture-in-Picture_API). -[Try a demo of the :picture-in-picture pseudo-class](https://googlechrome.github.io/samples/picture-in-picture/css-pseudo-class). +[Try a demo of the :picture-in-picture pseudo-class](https://googlechrome.github.io/samples/picture-in-picture/css-pseudo-class). ## Web APIs @@ -52,13 +52,13 @@ Adds cross-origin iframe support for the FedCM API via a permissions policy. It ### IFrame credentialless -[IFrame credentialless](https://developer.mozilla.org/docs/Web/Security/IFrame_credentialless) gives developers a way to load documents in third party iframes using new and ephemeral contexts. Iframe credentialless are a generalization of [COEP](https://developer.mozilla.org/docs/Web/HTTP/Headers/Cross-Origin-Embedder-Policy) credentialless to support third-party iframes that may not deploy COEP. This removes the constraint that third-party iframes must support COEP in order to be embedded in a COEP page and will unblock developers looking to adopt cross-origin-isolation. +[IFrame credentialless](https://developer.mozilla.org/docs/Web/Security/IFrame_credentialless) gives developers a way to load documents in third party iframes using new and ephemeral contexts. Iframe credentialless are a generalization of [COEP](https://developer.mozilla.org/docs/Web/HTTP/Headers/Cross-Origin-Embedder-Policy) credentialless to support third-party iframes that may not deploy COEP. This removes the constraint that third-party iframes must support COEP in order to be embedded in a COEP page and will unblock developers looking to adopt cross-origin-isolation. Learn more about [iframe credentialless](/blog/iframe-credentialless). ### `FileSystemHandle::remove()` method -The [`remove()`](/articles/file-system-access/#deleting-a-file-or-folder-directly) method of `FileSystemHandle` enables the common use case where you obtain a file handle from `showSaveFilePicker()`, but then decide you don't want to save after all, and delete the file. Before the addition of this method it was impossible to remove a file or directory given its handle. You had to obtain the handle of the parent directory and call [`FileSystemDirectoryHandle::removeEntry()`](/articles/file-system-access/#deleting-files-and-folders-in-a-directory). +The [`remove()`](/articles/file-system-access/#deleting-a-file-or-folder-directly) method of `FileSystemHandle` enables the common use case where you obtain a file handle from `showSaveFilePicker()`, but then decide you don't want to save after all, and delete the file. Before the addition of this method it was impossible to remove a file or directory given its handle. You had to obtain the handle of the parent directory and call [`FileSystemDirectoryHandle::removeEntry()`](/articles/file-system-access/#deleting-files-and-folders-in-a-directory). ### Prefetching triggered by the speculation rules API @@ -70,25 +70,25 @@ Enable IDNA 2008 in Non-Transitional Mode for URL processing, aligning Chrome's ### Web app launch handler -Add a [`launch_handler`](/docs/web-platform/launch-handler/) web app manifest member that enables web apps to customize their launch behavior across all types of app launch triggers. For example, the following will cause all launches of the Example app to focus an existing app window and navigate it (if it exists) instead of always launching a new app window. +Add a [`launch_handler`](/docs/web-platform/launch-handler/) web app manifest member that enables web apps to customize their launch behavior across all types of app launch triggers. For example, the following will cause all launches of the Example app to focus an existing app window and navigate it (if it exists) instead of always launching a new app window. ```js -{ - "name": "Example app", - "start_url": "/index.html", +{ + "name": "Example app", + "start_url": "/index.html", "launch_handler": { - "client_mode": "navigate-existing" - } -} + "client_mode": "navigate-existing" + } +} ``` ### web-share permission policy -Controls access to [`navigator.share()`](https://web.dev/web-share/). By default, third-party iframes do not have permission to use the Web Share API. +Controls access to [`navigator.share()`](https://web.dev/articles/web-share). By default, third-party iframes do not have permission to use the Web Share API. ## Origin trials in progress -In Chrome 110 you can opt into the following new [origin trials](/docs/web-platform/origin-trials/). +In Chrome 110 you can opt into the following new [origin trials](/docs/web-platform/origin-trials/). ### No-Vary-Search support in navigation prefetch cache @@ -98,7 +98,7 @@ Enables prefetch to match even if URL query parameters change. The `No-Vary-Sear ### PerformanceResourceTiming.deliveryType -Expose information about how a resource was delivered. For example, resources which were delivered from the cache (currently exposed through `transferSize`) and navigations which were prefetched by the previous page are useful to identify. +Expose information about how a resource was delivered. For example, resources which were delivered from the cache (currently exposed through `transferSize`) and navigations which were prefetched by the previous page are useful to identify. ### SoftNavigation performance entry @@ -108,7 +108,7 @@ Exposes the (experimental) [soft navigation heuristics](https://github.com/WICG/ ### Speculation rules: delivery via Speculation-Rules header -Currently developers can only specify speculation rules using inline script tags. The proposed feature provides an alternative through the "Speculation-Rules" header. Its value must be a URL to a text resource with `application/speculationrules+json` MIME type. The resource's rules will be added to the document's rule set. +Currently developers can only specify speculation rules using inline script tags. The proposed feature provides an alternative through the "Speculation-Rules" header. Its value must be a URL to a text resource with `application/speculationrules+json` MIME type. The resource's rules will be added to the document's rule set. ### Speculation rules: document-sourced rules @@ -116,7 +116,7 @@ An extension to speculation rules syntax that lets the browser obtain URLs for s ### X-Requested-With in WebView -Deprecation trial to retain legacy behavior of the `X-Requested-Header` on Android WebView. This header is currently set with the package name of the embedding app as the value, but this behavior will be removed in a slow roll-out. During the deprecation this trial will allow site owners to continue to receive the header while migrating away from using it. +Deprecation trial to retain legacy behavior of the `X-Requested-Header` on Android WebView. This header is currently set with the package name of the embedding app as the value, but this behavior will be removed in a slow roll-out. During the deprecation this trial will allow site owners to continue to receive the header while migrating away from using it. More information about this deprecation will follow in a separate blog post. [Register for the X-Requested-With deprecation trial here](/origintrials/#/view_trial/1390486384950640641). diff --git a/site/en/blog/chrome-111-beta/index.md b/site/en/blog/chrome-111-beta/index.md index a1182e56a..d41b9748e 100644 --- a/site/en/blog/chrome-111-beta/index.md +++ b/site/en/blog/chrome-111-beta/index.md @@ -1,6 +1,6 @@ --- title: Chrome 111 beta -description: > +description: > New CSS color types and color spaces, CSS trigonometric functions, and the View Transitions API. subhead: > New CSS color types and color spaces, CSS trigonometric functions, and the View Transitions API. @@ -21,7 +21,7 @@ Unless otherwise noted, the following changes apply to the newest Chrome beta ch ### New CSS color types and spaces -All features described in [CSS Color Level 4](https://www.w3.org/TR/css-color-4/) are now enabled. This includes four device-independent color types (lab, Oklab, lch and Oklch), the [`color()`](https://developer.mozilla.org/docs/Web/CSS/color_value/color) function, and user-defined color spaces for gradients and animations. +All features described in [CSS Color Level 4](https://www.w3.org/TR/css-color-4/) are now enabled. This includes four device-independent color types (lab, Oklab, lch and Oklch), the [`color()`](https://developer.mozilla.org/docs/Web/CSS/color_value/color) function, and user-defined color spaces for gradients and animations. Read the [High definition CSS color guide](/articles/high-definition-css-color-guide/) to learn about these new color types and spaces. @@ -45,11 +45,11 @@ Adds root font units: `rex`, `rch`, `ric`, and `rlh` to the existing root font ### CSS trigonometric functions -The [trigonometric functions](https://developer.mozilla.org/docs/Web/CSS/CSS_Functions#trigonometric_functions) `sin()`, `cos()`, `tan()`, `asin()`, `acos()`, `atan()`, `atan2()` have been added to CSS math expressions. +The [trigonometric functions](https://developer.mozilla.org/docs/Web/CSS/CSS_Functions#trigonometric_functions) `sin()`, `cos()`, `tan()`, `asin()`, `acos()`, `atan()`, `atan2()` have been added to CSS math expressions. ### Style Container Queries for CSS Custom Properties -Adds the `style()` function to `@container` rules to make it possible to apply styles based on the computed values of custom properties of an ancestor element. +Adds the `style()` function to `@container` rules to make it possible to apply styles based on the computed values of custom properties of an ancestor element. ### The `baseline-source` property @@ -59,15 +59,15 @@ The `baseline-source` property allows web developers to specify if an inline-lev ### The `window-management` permission and permission policy string -Chrome 111 adds `window-management` as an alias for `window-placement` permission and permission-policy strings. This is part of a larger effort to rename the strings by eventually deprecating and removing `window-placement`. The terminology change improves the longevity of the descriptor as the Window Management API evolves over time. +Chrome 111 adds `window-management` as an alias for `window-placement` permission and permission-policy strings. This is part of a larger effort to rename the strings by eventually deprecating and removing `window-placement`. The terminology change improves the longevity of the descriptor as the Window Management API evolves over time. ### Media Session API: Presenting slides actions -Adds `previousslide` and `nextslide` actions to the existing Media Session API. +Adds `previousslide` and `nextslide` actions to the existing Media Session API. ### Resizable `ArrayBuffer` and growable `SharedArrayBuffer` -Extend the `ArrayBuffer` constructors to take an additional maximum length that allows in-place growth and shrinking of buffers. Similarly, `SharedArrayBuffer` is extended to take an additional maximum length that allows in-place growth. +Extend the `ArrayBuffer` constructors to take an additional maximum length that allows in-place growth and shrinking of buffers. Similarly, `SharedArrayBuffer` is extended to take an additional maximum length that allows in-place growth. ### Speculation rules: referrer policy key @@ -81,7 +81,7 @@ This adds support for streaming, by attaching the shadow root on the opening, ra Enables the creation of polished transitions in Single-Page Applications (SPAs) by snapshotting views and allowing the DOM to change without any overlap between states. Use View Transitions to build custom transitions, or use a simple crossfade default to improve user experience. -Check out the [Chrome Developers article](/docs/web-platform/view-transitions/) for more information and example transitions to help you get started. +Check out the [Chrome Developers article](/docs/web-platform/view-transitions/) for more information and example transitions to help you get started. ### WebRTC Scalable Video Coding extensions @@ -89,16 +89,16 @@ This extension defines a standard method for picking between possible Scalable V ### WebXR `enabledFeatures` attribute -Returns the set of features that were enabled for this `XRSession` as specified by `XRSessionInit` and the Implied Features required by the spec for the given mode and features. For a granted Session, this will contain all `requiredFeatures`, but may be a subset of `optionalFeatures`. Most features have alternate ways to detect if they were granted; however, for some features the signal of whether or not a feature was enabled may tie closely with data for a feature just not being available right now, rather than data not being available ever. By querying `enabledFeatures`, you can determine if any helpful hints (for example, to improve or start tracking) should be shown, or if a feature will never be supported in the current session. +Returns the set of features that were enabled for this `XRSession` as specified by `XRSessionInit` and the Implied Features required by the spec for the given mode and features. For a granted Session, this will contain all `requiredFeatures`, but may be a subset of `optionalFeatures`. Most features have alternate ways to detect if they were granted; however, for some features the signal of whether or not a feature was enabled may tie closely with data for a feature just not being available right now, rather than data not being available ever. By querying `enabledFeatures`, you can determine if any helpful hints (for example, to improve or start tracking) should be shown, or if a feature will never be supported in the current session. ## Origin trials in progress -In Chrome 111 you can opt into the following new [origin trials](/docs/web-platform/origin-trials/). +In Chrome 111 you can opt into the following new [origin trials](/docs/web-platform/origin-trials/). ### Deprecation trial for removal of the `connect-src` CSP bypass in Web Payment API -Deprecate the ability for Web Payment API to bypass the connect-src CSP policy when fetching the manifest. After this deprecation, a site's connect-src CSP policy will need to allow for the payment method URL specified in a PaymentRequest call, as well as any other URLs that the method chains to fetch its manifest. +Deprecate the ability for Web Payment API to bypass the connect-src CSP policy when fetching the manifest. After this deprecation, a site's connect-src CSP policy will need to allow for the payment method URL specified in a PaymentRequest call, as well as any other URLs that the method chains to fetch its manifest. This bypass ability is removed in Chrome 111 with a reverse origin trial from 111 to 113 for those developers that need to temporarily re-enable the bypass. To opt into this, register for the [reverse deprecation trial for the `connect-src` CSP bypass](/origintrials/#/register_trial/3804415785221226497). @@ -118,7 +118,7 @@ This release of Chrome removes three features. ### Remove PaymentInstruments -PaymentInstruments is the Web API that backs non-JIT install of payment apps (see https://w3c.github.io/payment-handler/). It was designed with the assumption that the browser would store the actual payment instrument details, which has not turned out to be true, and has some privacy leaks. It also has not shipped on any other browser, not have we seen any interest from other browser vendors. As such, [this API has been deprecated and removed](https://web.dev/registering-a-web-based-payment-app/). +PaymentInstruments is the Web API that backs non-JIT install of payment apps (see https://w3c.github.io/payment-handler/). It was designed with the assumption that the browser would store the actual payment instrument details, which has not turned out to be true, and has some privacy leaks. It also has not shipped on any other browser, not have we seen any interest from other browser vendors. As such, [this API has been deprecated and removed](https://web.dev/articles/registering-a-web-based-payment-app). ### Remove `connect-src` CSP bypass in Web Payment API diff --git a/site/en/blog/chrome-115-beta/index.md b/site/en/blog/chrome-115-beta/index.md index 8d2eafd44..f723fc008 100644 --- a/site/en/blog/chrome-115-beta/index.md +++ b/site/en/blog/chrome-115-beta/index.md @@ -49,11 +49,11 @@ The [WebAssembly.Module()](https://developer.mozilla.org/docs/WebAssembly/JavaSc ### FedCM: Support credential management mediation requirements for auto re-authentication -Supports [Credential Management Mediation Requirements](https://w3c.github.io/webappsec-credential-management/#mediation-requirements) to provide streamlined re-authentication UX for users who have created federated accounts on websites with the FedCM API. +Supports [Credential Management Mediation Requirements](https://w3c.github.io/webappsec-credential-management/#mediation-requirements) to provide streamlined re-authentication UX for users who have created federated accounts on websites with the FedCM API. ### HTTPS upgrades -Automatically and optimistically upgrade all main-frame navigations to HTTPS, with fast fallback to HTTP. +Automatically and optimistically upgrade all main-frame navigations to HTTPS, with fast fallback to HTTP. ### Partitioning the Storage, Service Worker, and Communication APIs @@ -62,28 +62,28 @@ To prevent certain types of side-channel cross-site tracking, Chrome is partitio ### Resource Timing: Expose interim response times -Expose `PerformanceResourceTiming.firstInterimResponseStart` in cases where a navigation or subresource fetch encounters an interim 1xx response. For example with 100 continue or 103 early hints, `firstInterimResponseStart` now corresponds to the time of that first interim response, while `responseStart` corresponds to the final response, for example with 200 status. +Expose `PerformanceResourceTiming.firstInterimResponseStart` in cases where a navigation or subresource fetch encounters an interim 1xx response. For example with 100 continue or 103 early hints, `firstInterimResponseStart` now corresponds to the time of that first interim response, while `responseStart` corresponds to the final response, for example with 200 status. ### Update of "xml" prefix handling in `lookupNamespaceURI()` and `createNSResolver()` -`Node.lookupNamespaceURI()` supports "xml" and "xmlns" prefixes by default. The function returns fixed namespace strings for them. `Document.createNSResolver()` and `XPathEvaluator.createNSResolver()` stops to wrap the specified node to add "xml" prefix handling. They return the specified node as is. Web developers can now use an element as an `XPathNSResolver` without wrapping it with `createNSResolver()`. +`Node.lookupNamespaceURI()` supports "xml" and "xmlns" prefixes by default. The function returns fixed namespace strings for them. `Document.createNSResolver()` and `XPathEvaluator.createNSResolver()` stops to wrap the specified node to add "xml" prefix handling. They return the specified node as is. Web developers can now use an element as an `XPathNSResolver` without wrapping it with `createNSResolver()`. ### VisibilityStateEntry -Exposes visibility state (visible or hidden) in the performance timeline. The timeline will always have an entry with a `startTime` of 0 and the initial visibility state, plus entries corresponding to any visibility state change. +Exposes visibility state (visible or hidden) in the performance timeline. The timeline will always have an entry with a `startTime` of 0 and the initial visibility state, plus entries corresponding to any visibility state change. ### WGSLLanguageFeatures for WebGPU -Adds the `wgslLanguageFeatures` getter on the GPU object for WebGPU, and its corresponding `WGSLLanguageFeatures` type. +Adds the `wgslLanguageFeatures` getter on the GPU object for WebGPU, and its corresponding `WGSLLanguageFeatures` type. ### WebDriver commands for interacting with FedCM dialogs -This exposes several WebDriver commands to enable browser automation, such as automated testing, to interact with FedCM dialogs. +This exposes several WebDriver commands to enable browser automation, such as automated testing, to interact with FedCM dialogs. ## Origin trials in progress -In Chrome 115 you can opt into the following new [origin trials](/docs/web-platform/origin-trials/). +In Chrome 115 you can opt into the following new [origin trials](/docs/web-platform/origin-trials/). ### Compute Pressure @@ -99,13 +99,13 @@ Allow attaching information about which functions should be eager parsed and com ### Long Animation Frames API -This is an extension of the [Long Tasks API](https://developer.mozilla.org/docs/Web/API/PerformanceLongTaskTiming). It measures the task together with its subsequent rendering update, adding information such as long running scripts, rendering time, and time spent in forced layout and style known as layout thrashing. Developers can use this as a diagnostic for "sluggishness", which is measured by [Interaction to Next Paint (INP)](https://web.dev/inp/), by finding the causes for main-thread congestion which is often the cause for bad INP. +This is an extension of the [Long Tasks API](https://developer.mozilla.org/docs/Web/API/PerformanceLongTaskTiming). It measures the task together with its subsequent rendering update, adding information such as long running scripts, rendering time, and time spent in forced layout and style known as layout thrashing. Developers can use this as a diagnostic for "sluggishness", which is measured by [Interaction to Next Paint (INP)](https://web.dev/articles/inp), by finding the causes for main-thread congestion which is often the cause for bad INP. [Register for the Long Animation Frames origin trial](/origintrials/#/view_trial/3935020174414970881). ### Storage Buckets API -Storage Buckets allows sites the ability to create multiple storage buckets to organize their data, allowing user agents to delete each bucket independently of other buckets. Each storage bucket can store data associated with established storage APIs such as IndexedDB and CacheStorage. +Storage Buckets allows sites the ability to create multiple storage buckets to organize their data, allowing user agents to delete each bucket independently of other buckets. Each storage bucket can store data associated with established storage APIs such as IndexedDB and CacheStorage. [Register for the Storage Buckets API origin trial](/origintrials/#/register_trial/2674012278751232001). ## Deprecations and removals @@ -116,7 +116,7 @@ This release of Chrome deprecates two features. ### Deprecate the `document.domain` setter -The `document.domain` setter is being deprecated because it allows developers to relax the same-origin policy—and as such it complicates the fundamental security boundary we aim to maintain, and puts roadblocks in the way of post-Spectre changes to Chromium's process model. +The `document.domain` setter is being deprecated because it allows developers to relax the same-origin policy—and as such it complicates the fundamental security boundary we aim to maintain, and puts roadblocks in the way of post-Spectre changes to Chromium's process model. Visit [Chrome disables modifying document.domain](/blog/document-domain-setter-deprecation/) for alternatives to using document.domain. In most use cases, cross-origin `postMessage()` or Channel Messaging API can replace document.domain. As a last resort, you can opt into document-domain via [Origin-keyed agent clusters](https://chromestatus.com/features/5683766104162304). The setter will remain, but the origin remains unchanged. ### Deprecate mutation events diff --git a/site/en/blog/chrome-119-beta/index.md b/site/en/blog/chrome-119-beta/index.md index b5795c3fa..f1d0aabb2 100644 --- a/site/en/blog/chrome-119-beta/index.md +++ b/site/en/blog/chrome-119-beta/index.md @@ -22,17 +22,17 @@ This release adds four new CSS features. ### :user-valid and :user-invalid CSS pseudo-classes -The `:user-invalid` and `:user-valid` pseudo-classes represent an element with incorrect or correct input, respectively, but only after the user has significantly interacted with it. This is similar to `:valid` and `:invalid`, but with the added constraint that these pseudo-classes only match after the user has interacted with the element. +The `:user-invalid` and `:user-valid` pseudo-classes represent an element with incorrect or correct input, respectively, but only after the user has significantly interacted with it. This is similar to `:valid` and `:invalid`, but with the added constraint that these pseudo-classes only match after the user has interacted with the element. ### CSS Relative Color Syntax (RCS) -The [relative color syntax](https://www.w3.org/TR/css-color-5/#relative-colors) allows developers to define colors by modifying the parameters of other colors. +The [relative color syntax](https://www.w3.org/TR/css-color-5/#relative-colors) allows developers to define colors by modifying the parameters of other colors. -For example: `oklab(from magenta calc(l * 0.8) a b);` results in an oklab magenta that is 80% lighter. +For example: `oklab(from magenta calc(l * 0.8) a b);` results in an oklab magenta that is 80% lighter. ### CSS clip-path geometry-box values -The CSS `clip-path` property now supports `<geometry-box>` values to control the clip's reference box, making `clip-path` easier to use. These box values can be used alongside basic shapes (for example, `clip-path: circle(50%) margin-box`), or they can be used alone to clip to the specified box (for example, `clip-path: content-box`). +The CSS `clip-path` property now supports `<geometry-box>` values to control the clip's reference box, making `clip-path` easier to use. These box values can be used alongside basic shapes (for example, `clip-path: circle(50%) margin-box`), or they can be used alone to clip to the specified box (for example, `clip-path: content-box`). ### CSS clip-path xywh() and rect() values @@ -52,11 +52,11 @@ When `getDisplayMedia()` is called, the browser offers the user a choice of disp Chrome 119 includes the following improvements to Fenced Frames. -There is an additional format option for Protected Audience ad size macros In the Protected Audience API within the Privacy Sandbox. An opt-in feature allows you to macro the size of the ad that wins the auction into the ad’s url, for example: +There is an additional format option for Protected Audience ad size macros In the Protected Audience API within the Privacy Sandbox. An opt-in feature allows you to macro the size of the ad that wins the auction into the ad’s url, for example: -`https://ad.com?width={/%AD_WIDTH%}&height={/%AD_HEIGHT%}` +`https://ad.com?width={/%AD_WIDTH%}&height={/%AD_HEIGHT%}` -To be more consistent with other types of macros in Protected Audience, like those used by `deprecatedReplaceInURN` and `registerAdMacro`, in Chrome 119 we’re adding the ability to use `${AD_WIDTH}` and `${AD_HEIGHT}` as the format for the macros in addition to the current format. +To be more consistent with other types of macros in Protected Audience, like those used by `deprecatedReplaceInURN` and `registerAdMacro`, in Chrome 119 we’re adding the ability to use `${AD_WIDTH}` and `${AD_HEIGHT}` as the format for the macros in addition to the current format. Automatic beacons will now send to all registered URLs. Previously, only destinations specified when calling `setReportEventDataForAutomaticBeacons()` receive automatic beacons, even if that destination called `registerAdBeacon()` for `"reserved.top_navigation"` in their worklet. Now, any destination that called `registerAdBeacon()` for `"reserved.top_navigation"` will get an automatic beacon, but only destinations specified in `setReportEventDataForAutomaticBeacons()` will get automatic beacon data along with the beacon. The `"once"` parameter in `setReportEventDataForAutomaticBeacons()` will now determine whether the data is sent out once, rather than determine if the entire beacon is sent once. @@ -66,11 +66,11 @@ The Intersection Observer `scrollMargin` property allows developers to observe t ### Keyboard-focusable scroll containers -This feature improves accessibility by making scroll containers focusable using sequential focus navigation. Previously, the tab key didn't focus scrollers unless tabIndex was explicitly set to 0 or more. By making scrollers focusable by default, users who can't (or don't want to) use a mouse will be able to focus clipped content using a keyboard's tab and arrow keys. This behavior is enabled only if the scroller does not contain any keyboard focusable children. +This feature improves accessibility by making scroll containers focusable using sequential focus navigation. Previously, the tab key didn't focus scrollers unless tabIndex was explicitly set to 0 or more. By making scrollers focusable by default, users who can't (or don't want to) use a mouse will be able to focus clipped content using a keyboard's tab and arrow keys. This behavior is enabled only if the scroller does not contain any keyboard focusable children. ### Private Network Access restrictions for automotive -Enforce (instead of just warn) Private Network Access restrictions on Chrome for Android Automotive (if `BuildInfo::is_automotive`). This includes Private Network Access preflight requests for subresources, and Private Network Access for Workers. +Enforce (instead of just warn) Private Network Access restrictions on Chrome for Android Automotive (if `BuildInfo::is_automotive`). This includes Private Network Access preflight requests for subresources, and Private Network Access for Workers. ### Read Chrome device attributes @@ -78,11 +78,11 @@ Device Attributes Web API is a subset of the Managed Device Web API, that provid ### Replace dangling markup in target name to `_blank` -This change replaces the navigable target name (which is usually set by target attribute) to `_blank`, if it contains a dangling markup (for example, `\n` and `<`). Which fixes a bypass in the dangling markup injection mitigation. +This change replaces the navigable target name (which is usually set by target attribute) to `_blank`, if it contains a dangling markup (for example, `\n` and `<`). Which fixes a bypass in the dangling markup injection mitigation. ### Sec-CH-Prefers-Reduced-Transparency user preference media features Client Hints header -The [user preference media features Client Hints header](https://web.dev/user-preference-media-features-headers/) defines a set of HTTP Client Hints headers around user preference media features as defined by Media Queries Level 5. If used as Critical Client Hints, these headers allow servers to make smart choices regarding, for example, CSS inlining. `Sec-CH-Prefers-Reduced-Transparency` reflects the user's `prefers-reduced-transparency` preference, and is available from Chrome 119. +The [user preference media features Client Hints header](https://web.dev/articles/user-preference-media-features-headers) defines a set of HTTP Client Hints headers around user preference media features as defined by Media Queries Level 5. If used as Critical Client Hints, these headers allow servers to make smart choices regarding, for example, CSS inlining. `Sec-CH-Prefers-Reduced-Transparency` reflects the user's `prefers-reduced-transparency` preference, and is available from Chrome 119. ### Standard compliant URL host punctuation characters @@ -124,11 +124,11 @@ As of Chrome 119, this flag will affect two codecs on Chromium: Opus and AAC. ## Origin trials in progress -In Chrome 119 you can opt into the following new [origin trial](/docs/web-platform/origin-trials/). +In Chrome 119 you can opt into the following new [origin trial](/docs/web-platform/origin-trials/). ### Open popups as fullscreen windows -This [new origin trial](/origintrials/#/view_trial/106960491150049281) adds a `fullscreen` windowFeatures parameter to the `window.open()` JavaScript API. This allows the caller to open a popup directly to full-screen on the display that would contain the popup (based on screenX and screenY). This eliminates the need for the developer to manually transition a popup into full-screen, which could require a new user activation signal. +This [new origin trial](/origintrials/#/view_trial/106960491150049281) adds a `fullscreen` windowFeatures parameter to the `window.open()` JavaScript API. This allows the caller to open a popup directly to full-screen on the display that would contain the popup (based on screenX and screenY). This eliminates the need for the developer to manually transition a popup into full-screen, which could require a new user activation signal. ## Deprecations and removals @@ -142,13 +142,13 @@ We previously announced the [deprecation and removal of Web SQL](/blog/deprecati ### Remove Sanitizer API -The Sanitizer API aims to build an easy-to-use, always secure, browser-maintained HTML sanitizer into the platform. Chrome shipped an initial version in Chrome 105, based on the then-current specification draft. However, the discussion has meanwhile moved on and the proposed API shape has changed substantially. +The Sanitizer API aims to build an easy-to-use, always secure, browser-maintained HTML sanitizer into the platform. Chrome shipped an initial version in Chrome 105, based on the then-current specification draft. However, the discussion has meanwhile moved on and the proposed API shape has changed substantially. -In order to prevent the current API from becoming entrenched we are removing the current implementation. We expect to re-implement the Sanitizer API when the proposed specification stabilizes again. +In order to prevent the current API from becoming entrenched we are removing the current implementation. We expect to re-implement the Sanitizer API when the proposed specification stabilizes again. ### Remove data: URL in SVGUseElement -Assigning a `data: URL` in `SVGUseElement` can cause XSS. And this also led to a Trusted Types bypass. Therefore, we plan to deprecate and remove support for it. +Assigning a `data: URL` in `SVGUseElement` can cause XSS. And this also led to a Trusted Types bypass. Therefore, we plan to deprecate and remove support for it. ### Remove non-standard `shadowroot` attribute for declarative shadow DOM diff --git a/site/en/blog/chrome-84-deps-rems/index.md b/site/en/blog/chrome-84-deps-rems/index.md index 3e53c4495..42b480842 100644 --- a/site/en/blog/chrome-84-deps-rems/index.md +++ b/site/en/blog/chrome-84-deps-rems/index.md @@ -16,7 +16,7 @@ authors: - joemedley # Required -date: 2020-05-27 +date: 2020-05-27 # Optional # Include an updated date when you update your post @@ -34,18 +34,18 @@ tags: --- {% Aside %} -Visit ChromeStatus.com for lists of +Visit ChromeStatus.com for lists of <a href="https://www.chromestatus.com/features#browsers.chrome.status%3A%22Deprecated%22">current deprecations</a> -and <a href="https://www.chromestatus.com/features#browsers.chrome.status:%22Removed%22">previous removals</a>. +and <a href="https://www.chromestatus.com/features#browsers.chrome.status:%22Removed%22">previous removals</a>. {% endAside %} {% Aside %} Chrome expects to start the spec-mandated turn down of AppCache in Chrome 85. For details and instructions for managing the transition gracefully, see -[Preparing for AppCache removal](https://web.dev/appcache-removal/). For +[Preparing for AppCache removal](https://web.dev/articles/appcache-removal). For information on a feature that will help you identify uses of this and other deprecated APIs, see [Know your code -health](https://web.dev/reporting-observer/) +health](https://web.dev/articles/reporting-observer) {% endAside %} ## @import rules in CSSStyleSheet.replace() removed @@ -109,7 +109,7 @@ Chrome currently has a <a href="http://www.chromium.org/blink#TOC-Launch-Process - Announce on the <a href="https://groups.google.com/a/chromium.org/forum/#!forum/blink-dev">blink-dev</a> mailing list. - Set warnings and give time scales in the Chrome DevTools Console when usage is detected on the page. - Wait, monitor, and then remove the feature as usage drops. - + You can find a list of all deprecated features on chromestatus.com using the <a href="https://www.chromestatus.com/features#deprecated"> deprecated filter </a> and removed features by applying the <a href="https://www.chromestatus.com/features#removed">removed filter</a>. We will also try to summarize some of the changes, reasoning, and migration paths in these posts. diff --git a/site/en/blog/chrome-85-deps-rems/index.md b/site/en/blog/chrome-85-deps-rems/index.md index 0229f35a8..abaeaf091 100644 --- a/site/en/blog/chrome-85-deps-rems/index.md +++ b/site/en/blog/chrome-85-deps-rems/index.md @@ -16,7 +16,7 @@ authors: - joemedley # Required -date: 2020-07-22 +date: 2020-07-22 # Optional # Include an updated date when you update your post @@ -34,18 +34,18 @@ tags: --- {% Aside %} -Visit ChromeStatus.com for lists of +Visit ChromeStatus.com for lists of <a href="https://www.chromestatus.com/features#browsers.chrome.status%3A%22Deprecated%22">current deprecations</a> -and <a href="https://www.chromestatus.com/features#browsers.chrome.status:%22Removed%22">previous removals</a>. +and <a href="https://www.chromestatus.com/features#browsers.chrome.status:%22Removed%22">previous removals</a>. {% endAside %} ## AppCache Removal Begins Chrome 85 starts a spec-mandated turn down of AppCache in Chrome. For details and instructions for managing the transition gracefully, see [Preparing for -AppCache removal](https://web.dev/appcache-removal/). For information on a +AppCache removal](https://web.dev/articles/appcache-removal). For information on a feature that will help you identify uses of this and other deprecated APIs, see -[Know your code health](https://web.dev/reporting-observer/) +[Know your code health](https://web.dev/articles/reporting-observer) [Intent to Remove](https://groups.google.com/a/chromium.org/g/blink-dev/c/FvM-qo7BfkI/m/0daqyD8kCQAJ) | [Chrome Platform Status](https://www.chromestatus.com/features/6192449487634432) | @@ -94,7 +94,7 @@ Chrome currently has a <a href="http://www.chromium.org/blink#TOC-Launch-Process - Announce on the <a href="https://groups.google.com/a/chromium.org/forum/#!forum/blink-dev">blink-dev</a> mailing list. - Set warnings and give time scales in the Chrome DevTools Console when usage is detected on the page. - Wait, monitor, and then remove the feature as usage drops. - + You can find a list of all deprecated features on chromestatus.com using the <a href="https://www.chromestatus.com/features#deprecated"> deprecated filter </a> and removed features by applying the <a href="https://www.chromestatus.com/features#removed">removed filter</a>. We will also try to summarize some of the changes, reasoning, and migration paths in these posts. diff --git a/site/en/blog/chrome-dev-summit-mobile-summary/index.md b/site/en/blog/chrome-dev-summit-mobile-summary/index.md index 158dcbdfa..0ef29b0c4 100644 --- a/site/en/blog/chrome-dev-summit-mobile-summary/index.md +++ b/site/en/blog/chrome-dev-summit-mobile-summary/index.md @@ -30,7 +30,7 @@ After an analysis of the mobile-friendliness of the top 1000 sites we found some + Size and space out tap targets appropriately + Use the semantic types for input elements -PageSpeed Insights just launched a [UX analysis for determining how mobile-friendly](https://web.dev/whats-new-pagespeed-insights/) your site is. It will help you [find common problems](https://developers.google.com/speed/pagespeed/insights/?url=http%3A%2F%2Fnews.google.com) with your sites mobile UX. Try it out! +PageSpeed Insights just launched a [UX analysis for determining how mobile-friendly](https://web.dev/articles/whats-new-pagespeed-insights) your site is. It will help you [find common problems](https://developers.google.com/speed/pagespeed/insights/?url=http%3A%2F%2Fnews.google.com) with your sites mobile UX. Try it out! [Slides: Best UX patterns for mobile web apps](http://mobile-ux.appspot.com/) diff --git a/site/en/blog/chrome-ux-report-api/index.md b/site/en/blog/chrome-ux-report-api/index.md index 95ea6d3aa..ec79efd30 100644 --- a/site/en/blog/chrome-ux-report-api/index.md +++ b/site/en/blog/chrome-ux-report-api/index.md @@ -23,9 +23,9 @@ tags: The [Chrome UX Report](/docs/crux/) (CrUX) dataset represents how real-world Chrome users experience popular destinations on the web. Since 2017, when the queryable dataset was first released on [BigQuery](./chrome-ux-report-bigquery/), field data from CrUX has been integrated into developer tools like [PageSpeed Insights](./chrome-ux-report-pagespeed-insights/), the [CrUX Dashboard](./chrome-ux-report-looker-studio-dashboard/), and Search Console's [Core Web Vitals report](https://support.google.com/webmasters/answer/9205520), enabling developers to easily measure and monitor real-user experiences. The piece that has been missing all this time has been a tool that provides free and RESTful access to CrUX data programmatically. To help bridge that gap, we're excited to announce the release of the all new [Chrome UX Report API](/docs/crux/api/)! -This API has been built with the goal of providing developers with simple, fast, and comprehensive access to CrUX data. The CrUX API only reports [_field_](https://web.dev/how-to-measure-speed/#lab-data-vs-field-data) user experience data, unlike the existing [PageSpeed Insights API](https://developers.google.com/speed/docs/insights/v5/get-started), which also reports _lab_ data from the Lighthouse performance audits. The CrUX API is streamlined and can quickly serve user experience data, making it ideally suited for real-time auditing applications. +This API has been built with the goal of providing developers with simple, fast, and comprehensive access to CrUX data. The CrUX API only reports [_field_](https://web.dev/articles/how-to-measure-speed#lab_data_vs_field_data) user experience data, unlike the existing [PageSpeed Insights API](https://developers.google.com/speed/docs/insights/v5/get-started), which also reports _lab_ data from the Lighthouse performance audits. The CrUX API is streamlined and can quickly serve user experience data, making it ideally suited for real-time auditing applications. -To ensure that developers have access to all of the metrics that matter the most—the [Core Web Vitals](https://web.dev/vitals/#core-web-vitals)—the CrUX API audits and monitors [Largest Contentful Paint](https://web.dev/lcp/) (LCP), [First Input Delay](https://web.dev/fid/) (FID), and [Cumulative Layout Shift](https://web.dev/cls/) (CLS) at both the origin and URL level. +To ensure that developers have access to all of the metrics that matter the most—the [Core Web Vitals](https://web.dev/articles/vitals#core_web_vitals)—the CrUX API audits and monitors [Largest Contentful Paint](https://web.dev/articles/lcp) (LCP), [First Input Delay](https://web.dev/articles/fid) (FID), and [Cumulative Layout Shift](https://web.dev/articles/cls) (CLS) at both the origin and URL level. So let's dive in and see how to use it! @@ -121,7 +121,7 @@ If data exists for this origin, the API response is a JSON-encoded object contai } ``` -The `start` and `end` properties of the `histogram` object represent the range of values users experience for the given metric. The `density` property represents the proportion of user experiences within that range. In this example, 79% of LCP user experiences across all web.dev pages are under 2,500 milliseconds, which is the "[good](https://web.dev/lcp/#what-is-lcp)" LCP threshold. The `percentiles.p75` value means that 75% of user experiences in this distribution are less than 2,216 milliseconds. Learn more about the response structure in the [response body](/docs/crux/api/#response-body) documentation. +The `start` and `end` properties of the `histogram` object represent the range of values users experience for the given metric. The `density` property represents the proportion of user experiences within that range. In this example, 79% of LCP user experiences across all web.dev pages are under 2,500 milliseconds, which is the "[good](https://web.dev/articles/lcp#what_is_lcp)" LCP threshold. The `percentiles.p75` value means that 75% of user experiences in this distribution are less than 2,216 milliseconds. Learn more about the response structure in the [response body](/docs/crux/api/#response-body) documentation. ### Errors @@ -320,7 +320,7 @@ Recall from the previous section that 85% of user experiences on this page had " ## Assessing Core Web Vitals performance -The [Core Web Vitals](https://web.dev/vitals/#core-web-vitals) program defines targets that help determine whether a user experience or a distribution of experiences can be considered "good". In the following example, we use the CrUX API and the [`CrUXApiUtil.query`](#crux-api-util) function to assess whether a web page's distribution of Core Web Vitals metrics (LCP, FID, CLS) are "good". +The [Core Web Vitals](https://web.dev/articles/vitals#core_web_vitals) program defines targets that help determine whether a user experience or a distribution of experiences can be considered "good". In the following example, we use the CrUX API and the [`CrUXApiUtil.query`](#crux-api-util) function to assess whether a web page's distribution of Core Web Vitals metrics (LCP, FID, CLS) are "good". ```js/1 CrUXApiUtil.query({ diff --git a/site/en/blog/chrome-ux-report-history-api/index.md b/site/en/blog/chrome-ux-report-history-api/index.md index 20109ff01..58f7fe5e3 100644 --- a/site/en/blog/chrome-ux-report-history-api/index.md +++ b/site/en/blog/chrome-ux-report-history-api/index.md @@ -125,7 +125,7 @@ The overall shape of a response is similar—but there is a lot more data! Inste } ``` -In this example, the `densities` time series for the 0 to 2500 ms bucket of the [Largest Contentful Paint (LCP)](https://web.dev/lcp/) metric is `[0.9190, 0.9203, 0.9194, 0.9195, 0.9183, 0.9187].` Each of these densities was observed during the corresponding `collectionPeriods` entry. For example, the fifth density, 0.9183, was the density for the fifth collection period, ending on September 3rd, 2022, and 0.9187 was the density in the period ending the week after that. +In this example, the `densities` time series for the 0 to 2500 ms bucket of the [Largest Contentful Paint (LCP)](https://web.dev/articles/lcp) metric is `[0.9190, 0.9203, 0.9194, 0.9195, 0.9183, 0.9187].` Each of these densities was observed during the corresponding `collectionPeriods` entry. For example, the fifth density, 0.9183, was the density for the fifth collection period, ending on September 3rd, 2022, and 0.9187 was the density in the period ending the week after that. In other words, interpreting the last time series entries in the example for [https://web.dev](https://web.dev), it was found that from August 14, 2022 until September 10, 2022, 91.87% of page loads had LCP values smaller than 2500ms, 5.27% had values between 2500ms and 4000ms, and 2.85% had values greater than 4000ms. @@ -156,7 +156,7 @@ Page-level (and origin-level) historical data is subject to [the same eligibilit ## Visualizing the data -So, you may ask, why is the data shaped in this way? It was found that this makes it easy to plot graphs. For example, here is a graph for the p75 values for [Interaction To Next Paint (INP)](https://web.dev/inp/) for [https://web.dev](https://web.dev): +So, you may ask, why is the data shaped in this way? It was found that this makes it easy to plot graphs. For example, here is a graph for the p75 values for [Interaction To Next Paint (INP)](https://web.dev/articles/inp) for [https://web.dev](https://web.dev): {% Img src="image/kd0zRXNeKScEzrwMmhY1NNvIzeM2/fgLRTt2WB2Yd67bL3mMc.png", alt="Time series graph of p75 value showing a regression around November 2022", width="512", height="339" %} diff --git a/site/en/blog/chrome-ux-report-looker-studio-dashboard/index.md b/site/en/blog/chrome-ux-report-looker-studio-dashboard/index.md index f5d470714..e33c9b745 100644 --- a/site/en/blog/chrome-ux-report-looker-studio-dashboard/index.md +++ b/site/en/blog/chrome-ux-report-looker-studio-dashboard/index.md @@ -26,7 +26,7 @@ The CrUX Dashboard is built with a Looker Studio feature called [Community Conne ## Using the default CrUX dashboard -CrUX has a [default dashboard](/docs/crux/dashboard/), which is maintained by the CrUX team. New metrics (for example [INP](https://web.dev/inp/)) are added by the team and available the next time the dashboard is loaded. +CrUX has a [default dashboard](/docs/crux/dashboard/), which is maintained by the CrUX team. New metrics (for example [INP](https://web.dev/articles/inp)) are added by the team and available the next time the dashboard is loaded. The default dashboard is recommended as a quick, no maintaince way of visualizing a site's CrUX data. However, some users may wish to customize the dashboard. @@ -76,7 +76,7 @@ The monthly datasets are released on the second Tuesday of every month. For exam ### Core Web Vitals overview -The first page is an overview of the origin's monthly [Core Web Vitals](https://web.dev/vitals/) performance. These are the most important UX metrics that Google recommends you focus on. +The first page is an overview of the origin's monthly [Core Web Vitals](https://web.dev/articles/vitals) performance. These are the most important UX metrics that Google recommends you focus on. {% Img src="image/admin/h8iCTgvmG4DS2zScvatc.png", alt="CrUX Dashboard Core Web Vitals overview", width="800", height="906" %} @@ -94,7 +94,7 @@ After the Core Web Vitals page, you'll find standalone pages for all [metrics](/ Atop each page is the **Device** filter, which you can use to restrict the form factors included in the experience data. For example, you can drill down specifically into phone experiences. This setting persists across pages. -The primary visualizations on these pages are the monthly distributions of experiences categorized as "Good", "Needs Improvement", and "Poor". The color-coded legend below the chart indicates the range of experiences included in the category. For example, in the screenshot above, you can see the percent of "good" [Largest Contentful Paint](https://web.dev/lcp/#what-is-a-good-lcp-score) (LCP) experiences fluctuating and getting slightly worse in recent months. +The primary visualizations on these pages are the monthly distributions of experiences categorized as "Good", "Needs Improvement", and "Poor". The color-coded legend below the chart indicates the range of experiences included in the category. For example, in the screenshot above, you can see the percent of "good" [Largest Contentful Paint](https://web.dev/articles/lcp#what_is_a_good_lcp_score) (LCP) experiences fluctuating and getting slightly worse in recent months. The most recent month's percentages of "good" and "poor" experiences are shown above the chart along with an indicator of the percent difference from the previous month. For this origin, "good" LCP experiences fell by 3.2% to 56.04% month-over-month. @@ -127,7 +127,7 @@ Effective connection types are considered _effective_ because they're based on b {% endAside %} The distributions for these dimensions are calculated using segments of the -[First Contentful Paint](https://web.dev/fcp/) (FCP) histogram data. +[First Contentful Paint](https://web.dev/articles/fcp) (FCP) histogram data. ## FAQ diff --git a/site/en/blog/chrome-ux-report-pagespeed-insights/index.md b/site/en/blog/chrome-ux-report-pagespeed-insights/index.md index c586aa661..0e671bb52 100644 --- a/site/en/blog/chrome-ux-report-pagespeed-insights/index.md +++ b/site/en/blog/chrome-ux-report-pagespeed-insights/index.md @@ -29,7 +29,7 @@ audits will be performed and you will see sections with data from CrUX ("Discove {% Img src="image/W3z1f5ZkBJSgL1V1IfloTIctbIF3/jZSP6YZQHE8vBOJIMhCH.png", alt="Field data from CrUX in PageSpeed Insights", width="800", height="491" %} -In the real-user experiences section, metrics are grouped by [Core Web Vitals](https://web.dev/vitals/#core-web-vitals) and [other notable metrics](https://web.dev/vitals/#other-web-vitals). The three Core Web Vitals metrics are listed first: [Largest Contentful Paint](https://web.dev/lcp/) (LCP), [First Input Delay](https://web.dev/fid/) (FID), and [Cumulative Layout Shift](https://web.dev/cls/). These are followed by the other notable metrics: [First Contentful Paint](https://web.dev/fcp/) (FCP), [Interaction to Next Paint](https://web.dev/inp/) (INP), and [Time to First Byte](https://web.dev/ttfb/) (TTFB). +In the real-user experiences section, metrics are grouped by [Core Web Vitals](https://web.dev/articles/vitals#core_web_vitals) and [other notable metrics](https://web.dev/articles/vitals#other_web_vitals). The three Core Web Vitals metrics are listed first: [Largest Contentful Paint](https://web.dev/articles/lcp) (LCP), [First Input Delay](https://web.dev/articles/fid) (FID), and [Cumulative Layout Shift](https://web.dev/articles/cls). These are followed by the other notable metrics: [First Contentful Paint](https://web.dev/articles/fcp) (FCP), [Interaction to Next Paint](https://web.dev/articles/inp) (INP), and [Time to First Byte](https://web.dev/articles/ttfb) (TTFB). ### Core Web Vitals diff --git a/site/en/blog/coep-credentialless-origin-trial/index.md b/site/en/blog/coep-credentialless-origin-trial/index.md index ffe52e092..e93b54721 100644 --- a/site/en/blog/coep-credentialless-origin-trial/index.md +++ b/site/en/blog/coep-credentialless-origin-trial/index.md @@ -6,7 +6,7 @@ description: > subhead: > Cross-origin resources served by third-parties often do not include adequate CORP headers. If they can be requested without credentials, now you can enable cross-origin - isolation by marking them as such. + isolation by marking them as such. date: 2021-07-29 updated: 2022-05-13 authors: @@ -38,10 +38,10 @@ isolation more easily. Some web APIs increase the risk of side-channel attacks such as [Spectre](https://en.wikipedia.org/wiki/Spectre_(security_vulnerability)). To mitigate that risk, browsers offer an opt-in-based isolated environment called -[cross-origin isolation](https://web.dev/coop-coep/). With a cross-origin +[cross-origin isolation](https://web.dev/articles/coop-coep). With a cross-origin isolated state, the webpage can use privileged features including [`SharedArrayBuffer`](/blog/enabling-shared-array-buffer/), -[`performance.measureUserAgentSpecificMemory()`](https://web.dev/monitor-total-page-memory-usage/) +[`performance.measureUserAgentSpecificMemory()`](https://web.dev/articles/monitor-total-page-memory-usage) and [high-precision timers with better resolution](/blog/cross-origin-isolated-hr-timers/) while isolating the origin from others unless they are opted in. @@ -63,7 +63,7 @@ alt="", width="800", height="372" %} While cross-origin isolation brings webpages better security and the ability to enable powerful features, deploying it can be -[difficult](https://web.dev/cross-origin-isolation-guide/). One of the biggest +[difficult](https://web.dev/articles/cross-origin-isolation-guide). One of the biggest challenges is the requirement to enable CORS or CORP for all cross-origin resources. Resources without those headers will not be loaded by the browser on a cross-origin isolated page. @@ -170,11 +170,11 @@ postpone this to Chrome 106. ## Resources * [Making your website "cross-origin isolated" using COOP and - COEP](https://web.dev/coop-coep/) + COEP](https://web.dev/articles/coop-coep) * [Why you need "cross-origin isolated" for powerful - features](https://web.dev/why-coop-coep/) + features](https://web.dev/articles/why-coop-coep) * [A guide to enable cross-origin - isolation](https://web.dev/cross-origin-isolation-guide/) + isolation](https://web.dev/articles/cross-origin-isolation-guide) * [SharedArrayBuffer updates in Android Chrome 88 and Desktop Chrome 92](/blog/enabling-shared-array-buffer/) diff --git a/site/en/blog/conformance/index.md b/site/en/blog/conformance/index.md index 633ccc63a..eb9e0b6c8 100644 --- a/site/en/blog/conformance/index.md +++ b/site/en/blog/conformance/index.md @@ -46,7 +46,7 @@ enforced at **authoring time**. This breaks down into the following 3 principles {% Aside %} Conformance in this article focuses on coding best practices to achieve predictable loading -performance & [Core Web Vital](https://web.dev/vitals/) scores, but the principles apply equally to +performance & [Core Web Vital](https://web.dev/articles/vitals) scores, but the principles apply equally to other aspects such as security, accessibility, and so forth. {% endAside %} diff --git a/site/en/blog/coop-restrict-properties/index.md b/site/en/blog/coop-restrict-properties/index.md index 0e2bbec04..c7dc4bbdf 100644 --- a/site/en/blog/coop-restrict-properties/index.md +++ b/site/en/blog/coop-restrict-properties/index.md @@ -4,7 +4,7 @@ title: "Secure popup interactions with `restrict-properties`" subhead: > Get cross-origin isolation and cross-site leaks protection while interacting with popups. description: > - Get cross-origin isolation and cross-site leaks protection while interacting with popups. + Get cross-origin isolation and cross-site leaks protection while interacting with popups. date: 2023-08-09 origin_trial: url: /origintrials/#/view_trial/1827335548805578753 @@ -22,7 +22,7 @@ tags: A new value for [Cross-Origin Opener Policy (COOP)](https://developer.mozilla.org/docs/Web/HTTP/Headers/Cross-Origin-Opener-Policy) is available: `restrict-properties`. It brings in security benefits and makes -it easier to adopt [cross-origin isolation](https://web.dev/coop-coep/) while +it easier to adopt [cross-origin isolation](https://web.dev/articles/coop-coep) while allowing your site to interact with third-party popups for payments, authentication, or other use cases. @@ -31,10 +31,10 @@ trial](#origin-trial) starting in [Chrome 116](https://chromiumdash.appspot.com/ ## Why use `restrict-properties` -`restrict-properties` has two main use cases: +`restrict-properties` has two main use cases: - Preventing [cross-site leaks](https://xsleaks.dev/) without breakage. -- Making your site [cross-origin isolated](https://web.dev/why-coop-coep/). +- Making your site [cross-origin isolated](https://web.dev/articles/why-coop-coep). ### Prevent cross-site leaks without breakage @@ -47,7 +47,7 @@ To mitigate this risk, you can use the `Cross-Origin-Opener-Policy` (COOP) heade Up until now, your options for `Cross-Origin-Opener-Policy` were limited. You could either: -* Set `same-origin,` which blocks all cross-origin interactions with popups. +* Set `same-origin,` which blocks all cross-origin interactions with popups. * Set `same-origin-allow-popups`, which blocks all cross-origin interactions that open your site in a popup. * Set `unsafe-none`, which allows all cross-origin interactions with popups. @@ -81,10 +81,10 @@ granted. Some web APIs increase the risk of side-channel attacks like [Spectre](https://en.wikipedia.org/wiki/Spectre_(security_vulnerability)). To mitigate that risk, browsers offer an opt-in-based isolated environment called -[cross-origin isolation](https://web.dev/coop-coep/). With a cross-origin +[cross-origin isolation](https://web.dev/articles/coop-coep). With a cross-origin isolated state, the webpage can use privileged features including [SharedArrayBuffer](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer), -[performance.measureUserAgentSpecificMemory()](https://web.dev/monitor-total-page-memory-usage/) +[performance.measureUserAgentSpecificMemory()](https://web.dev/articles/monitor-total-page-memory-usage) and [high-precision timers](/blog/cross-origin-isolated-hr-timers/) with better resolution, while isolating the origin from others unless they are @@ -128,7 +128,7 @@ To experiment with `Cross-Origin-Opener-Policy: restrict-properties`, opt into the [origin trial](/origintrials/#/view_trial/1827335548805578753). -{% Aside %} +{% Aside %} Review [instructions](/docs/web-platform/origin-trials/#take-part-in-an-origin-trial) on how to participate in an origin trial. @@ -150,7 +150,7 @@ page will prevent any access to properties other than `postMessage` and `closed` across the opener, even if they are same-origin. ### Is the set of allowed properties fixed? -Based on the feedback so far, `window.postMessage` and `window.closed` are suspected +Based on the feedback so far, `window.postMessage` and `window.closed` are suspected to be enough for the majority of workflows, but we're still considering opening it to other properties. If you have a use case that cannot be solved using only `postMessage` and `closed` leave your feedback @@ -158,9 +158,9 @@ be solved using only `postMessage` and `closed` leave your feedback ## Resources -- [Making your website "cross-origin isolated" using COOP and COEP](https://web.dev/coop-coep/) -- [Why you need "cross-origin isolated" for powerful features](https://web.dev/why-coop-coep/) -- [A guide to enable cross-origin isolation](https://web.dev/cross-origin-isolation-guide/) +- [Making your website "cross-origin isolated" using COOP and COEP](https://web.dev/articles/coop-coep) +- [Why you need "cross-origin isolated" for powerful features](https://web.dev/articles/why-coop-coep) +- [A guide to enable cross-origin isolation](https://web.dev/articles/cross-origin-isolation-guide) - [SharedArrayBuffer updates in Android Chrome 88 and Desktop Chrome 92](/blog/enabling-shared-array-buffer/) - [Load cross-origin resources without CORP headers using `COEP: credentialless` - Chrome Developers](/blog/coep-credentialless-origin-trial/) - [Anonymous iframe origin trial: Easily embed iframes in COEP environments - Chrome Developers](/blog/anonymous-iframe-origin-trial/) diff --git a/site/en/blog/cq-polyfill/index.md b/site/en/blog/cq-polyfill/index.md index 237374c9a..e33e3c3a5 100644 --- a/site/en/blog/cq-polyfill/index.md +++ b/site/en/blog/cq-polyfill/index.md @@ -24,7 +24,7 @@ Container queries are a part of the [css-contain-3 specification](https://www.w3 {% endAside %} ## What are container queries? -[Container queries](https://www.youtube.com/watch?v=gCNMyYr7F6w) are a CSS feature which enables you to write styling logic that targets features of a parent element to style its children. You can create truly component-based responsive design by querying for a parent’s size. This is much more granular and useful information than something like [media queries](https://web.dev/learn/design/media-queries/) that only provide size information about the viewport. +[Container queries](https://www.youtube.com/watch?v=gCNMyYr7F6w) are a CSS feature which enables you to write styling logic that targets features of a parent element to style its children. You can create truly component-based responsive design by querying for a parent’s size. This is much more granular and useful information than something like [media queries](https://web.dev/learn/design/media-queries) that only provide size information about the viewport. {% Img src="image/HodOHWjMnbNw56hvNASHWSgZyAf2/Sw2dY4cpYjc8GBJVmCrK.png", alt="ALT_TEXT_HERE", width="800", height="372" %} @@ -99,7 +99,7 @@ To make container queries even more useful, you can use container-based unit val <table><thead><tr><th>unit</th><th>relative to</th></tr></thead><tbody><tr><td><code>cqw</code></td><td>1% of a query container’s width</td></tr><tr><td><code>cqh</code></td><td>1% of a query container’s height</td></tr><tr><td><code>cqi</code></td><td>1% of a query container’s inline size</td></tr><tr><td><code>cqb</code></td><td>1% of a query container’s block size</td></tr><tr><td><code>cqmin</code></td><td>The smaller value of cqi or cqb</td></tr><tr><td><code>cqmax</code></td><td>The larger value of cqi or cqb</td></tr></tbody></table> -One example for how you would use container-based units is responsive typography. The viewport-based units (such as `vh`, `vb`, `vw`, and `vi`) can be used to size any element on the screen. +One example for how you would use container-based units is responsive typography. The viewport-based units (such as `vh`, `vb`, `vw`, and `vi`) can be used to size any element on the screen. ```css .card h2 { @@ -178,7 +178,7 @@ For the best user experience, it's recommended that you initially only use the p On sufficiently fast networks and devices, or devices that natively support container queries, this loading indicator will never be displayed. {% Aside %} -Keep in mind that this technique effectively trades off [LCP](https://web.dev/lcp/) for less jank during initial load, so you may see regressions in the former as a result, particularly on low end devices. +Keep in mind that this technique effectively trades off [LCP](https://web.dev/articles/lcp) for less jank during initial load, so you may see regressions in the former as a result, particularly on low end devices. {% endAside %} ## New Polyfill Features @@ -219,7 +219,7 @@ If you are using the container query polyfill, there are a few missing features ### Warnings -- To prevent impacting [FID](https://web.dev/fid/) and [CLS](https://web.dev/cls/), the polyfill makes no guarantees about when the first layout will occur, even if it’s loaded synchronously, except that it will attempt to avoid unreasonably delaying LCP. In other words, you should never rely on it for first paint. +- To prevent impacting [FID](https://web.dev/articles/fid) and [CLS](https://web.dev/articles/cls), the polyfill makes no guarantees about when the first layout will occur, even if it’s loaded synchronously, except that it will attempt to avoid unreasonably delaying LCP. In other words, you should never rely on it for first paint. - Generates `ResizeObserver Loop Errors`. The original polyfill does this too, but it’s worth calling out. This occurs because the block-size of a `container-type: inline-size` will likely change after evaluating a query, but `ResizeObserver` has no way to tell it that we don’t care about block-size changes. - This polyfill is tested against Web Platform Tests and reached 70% passing since certain features like JavaScript APIs are not polyfilled, and so the pass rate is intentionally closer to 70%. - The `:where()` [workaround](https://github.com/GoogleChromeLabs/container-query-polyfill#supporting-browsers-without-where) is required for the 2.23% users of browsers older than: diff --git a/site/en/blog/credential-management-api/index.md b/site/en/blog/credential-management-api/index.md index ce47e206c..939d41bd1 100644 --- a/site/en/blog/credential-management-api/index.md +++ b/site/en/blog/credential-management-api/index.md @@ -27,7 +27,7 @@ a browser's credential manager and helps users sign in more easily. {% Aside 'warning' %} This API has been drastically updated and sample codes in this article won't work any longer. Checkout [the updated integration -guide](https://web.dev/security-credential-management/) or [the update +guide](https://web.dev/articles/security-credential-management) or [the update summary](/blog/credential-management-updates/). {% endAside %} diff --git a/site/en/blog/credential-management-updates/index.md b/site/en/blog/credential-management-updates/index.md index 411bd7562..4fd0f339b 100644 --- a/site/en/blog/credential-management-updates/index.md +++ b/site/en/blog/credential-management-updates/index.md @@ -18,12 +18,12 @@ Some of the updates described here are explained in the Google I/O session, ## Chrome 57 Chrome 57 introduced this important change to the -[Credential Management API](https://web.dev/security-credential-management/). +[Credential Management API](https://web.dev/articles/security-credential-management). ### Credentials can be shared from a different subdomain Chrome can now retrieve a credential stored in a different subdomain using the -[Credential Management API](https://web.dev/security-credential-management/). +[Credential Management API](https://web.dev/articles/security-credential-management). For example, if a password is stored in `login.example.com`, a script on `www.example.com` can show it as one of account items in account chooser dialog. @@ -48,7 +48,7 @@ is visible to `m.aliexpress.com` and available for the user to choose from: ## Chrome 60 Chrome 60 introduces several important changes to the -[Credential Management API](https://web.dev/security-credential-management/): +[Credential Management API](https://web.dev/articles/security-credential-management): * [`PasswordCredential` object now includes a password.](#password) @@ -81,7 +81,7 @@ website on browsers supporting [WebAuthn](https://www.w3.org/TR/webauthn/)(PublicKeyCredential) but not all credential types (`PasswordCredential` and `FederatedCredential`) defined by the Credential Management API. [Learn -more](https://web.dev/webauthn-credential-management/). +more](https://web.dev/articles/webauthn-credential-management). ### `PasswordCredential` object now includes password {: #password} diff --git a/site/en/blog/cross-device-webotp/index.md b/site/en/blog/cross-device-webotp/index.md index d7db32461..3e88bf416 100644 --- a/site/en/blog/cross-device-webotp/index.md +++ b/site/en/blog/cross-device-webotp/index.md @@ -124,7 +124,7 @@ browser automatically forwards the OTP to the site and resolves the the verification process. Learn more at [Verify phone numbers on the web with the WebOTP -API](https://web.dev/web-otp/). +API](https://web.dev/articles/web-otp). {% Aside 'gotchas' %} diff --git a/site/en/blog/cross-origin-isolated-hr-timers/index.md b/site/en/blog/cross-origin-isolated-hr-timers/index.md index 8a07bc031..3d795dcb1 100644 --- a/site/en/blog/cross-origin-isolated-hr-timers/index.md +++ b/site/en/blog/cross-origin-isolated-hr-timers/index.md @@ -20,7 +20,7 @@ Starting from version 91, following a [specification change](https://github.com/ Chrome will be restricting the resolution of explicit [timers](https://www.w3.org/TR/hr-time/) (`performance.now()`, `performance.timeOrigin`, and other performance APIs that expose `DOMHighResTimestamps`) to 100 microseconds across platforms. -By enabling [cross-origin isolation](https://web.dev/coop-coep/), +By enabling [cross-origin isolation](https://web.dev/articles/coop-coep), websites can relax the restriction to 5 microseconds regardless of platform. {% Aside %} @@ -73,7 +73,7 @@ we can now allow pages to access high-resolution timers, and other APIs that are unsafe to expose in processes that can read arbitrary cross-origin data. To learn more about the background behind this change, read -[Why you need "cross-origin isolated" for powerful features](https://web.dev/why-coop-coep/). +[Why you need "cross-origin isolated" for powerful features](https://web.dev/articles/why-coop-coep). Cover photo by [Linda Perez Johannessen](https://unsplash.com/@linper?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/stopwatch?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText). diff --git a/site/en/blog/cross-origin-prefetch/index.md b/site/en/blog/cross-origin-prefetch/index.md index befdcf3d6..d7c0abdb6 100644 --- a/site/en/blog/cross-origin-prefetch/index.md +++ b/site/en/blog/cross-origin-prefetch/index.md @@ -24,16 +24,16 @@ Most users routinely identify slow page loads as a major source of frustration ( ## Speeding up Largest Contentful Paint (LCP) -As the saying goes, you can't improve what you don't measure. For user experiences on the web, we believe that [Core Web Vitals](https://web.dev/vitals/#core-web-vitals) constitute a solid set of user-centric metrics designed to capture fundamental aspects of the user experience. In particular, [Largest Contentful Paint (LCP)](https://web.dev/lcp/) measures your pages' loading performance by reporting the time it takes to display the largest text or image block that the user sees. To provide a good user experience, LCP should occur within 2.5 seconds of when the page first starts loading (namely, the good LCP threshold). +As the saying goes, you can't improve what you don't measure. For user experiences on the web, we believe that [Core Web Vitals](https://web.dev/articles/vitals#core_web_vitals) constitute a solid set of user-centric metrics designed to capture fundamental aspects of the user experience. In particular, [Largest Contentful Paint (LCP)](https://web.dev/articles/lcp) measures your pages' loading performance by reporting the time it takes to display the largest text or image block that the user sees. To provide a good user experience, LCP should occur within 2.5 seconds of when the page first starts loading (namely, the good LCP threshold). -Let's look at what contributes to the LCP of a typical page. +Let's look at what contributes to the LCP of a typical page. <figure> {% Img src="image/kheDArv5csY6rvQUJDbWRscckLr1/v5Fl8GPalSO3brhBWGds.png", alt="Page loading waterfall.", width="800", height="450" %} <figcaption>A typical waterfall required to load a web page</figcaption> </figure> -When a user visits a page, the browser requests the HTML from the server. The server responds with the HTML, which gives the browser more hints on what to fetch next, including CSS, JavaScript, fonts, and images. As these responses come back, the browser must also do some work to evaluate them, and eventually lay out and paint components on the page. But the majority of time is spent waiting for those packets to travel from the device to the server and then back to the device. In fact, our data (Chrome for Android; median) show that about 40% of user-visible latency is typically spent by the browser waiting for [the very first byte](https://web.dev/ttfb/) to come back from the server. +When a user visits a page, the browser requests the HTML from the server. The server responds with the HTML, which gives the browser more hints on what to fetch next, including CSS, JavaScript, fonts, and images. As these responses come back, the browser must also do some work to evaluate them, and eventually lay out and paint components on the page. But the majority of time is spent waiting for those packets to travel from the device to the server and then back to the device. In fact, our data (Chrome for Android; median) show that about 40% of user-visible latency is typically spent by the browser waiting for [the very first byte](https://web.dev/articles/ttfb) to come back from the server. ## The power of prefetching @@ -44,11 +44,11 @@ If one could prefetch all these files—that is, fetch them before the user visi <figcaption>With all resources preloaded, the waterfall is perfectly streamlined.</figcaption> </figure> -Given the data shared earlier, one could also just prefetch the main resource and still achieve a significantly faster page load. In the same-site case, this type of technique is readily available with primitives such as [`rel=prefetch`](https://web.dev/link-prefetch/). However, with cross-site scenarios, it's not as straightforward. +Given the data shared earlier, one could also just prefetch the main resource and still achieve a significantly faster page load. In the same-site case, this type of technique is readily available with primitives such as [`rel=prefetch`](https://web.dev/articles/link-prefetch). However, with cross-site scenarios, it's not as straightforward. ## Cross-site navigations -While prefetching has been around for a while, an additional consideration is warranted when prefetching pages from one site while the user is on another. +While prefetching has been around for a while, an additional consideration is warranted when prefetching pages from one site while the user is on another. Suppose that a referrer site were to instruct the browser to prefetch a page from a different site. Obviously, when the user clicks on the link to this prefetched page, they would enjoy a better user experience with a much faster page load. However, what if the user never clicks on this link? They wouldn't expect a linked website to learn that they might have been interested in a topic while they were browsing for it on the referrer site. And, yet this is a substantial risk because the prefetching requests would carry the user's IP address, and cookies if any, as any other regular request. @@ -65,7 +65,7 @@ While Private Prefetch Proxy and Signed Exchange solve the same use case, each t Cross-site prefetching is easy to enable for users who visit your site for the first time. For repeat visitors, it depends on how much personalization goes on your site. This comes down to the fact that cross-site prefetch requests can't include cookies for privacy reasons. - For first-time visitors, this restriction does not introduce any challenge because these visitors have no cookies to begin with. Consequently, you can enable cross-site prefetching for these users without any changes to your site. -- If you'd like to enable cross-site prefetching for repeat visitors and your site is personalized based on cookies, you will need to lazy-load these personalized elements after the user navigates. This works because upon navigation, the restriction on cookies is no longer needed since the user explicitly chose to visit your website. So, at navigation time, your site has access to its cookies as usual. For concrete guidance, see these [best practices for lazy-loading](https://web.dev/lazy-loading/). +- If you'd like to enable cross-site prefetching for repeat visitors and your site is personalized based on cookies, you will need to lazy-load these personalized elements after the user navigates. This works because upon navigation, the restriction on cookies is no longer needed since the user explicitly chose to visit your website. So, at navigation time, your site has access to its cookies as usual. For concrete guidance, see these [best practices for lazy-loading](https://web.dev/articles/lazy-loading). - If you currently encode personalization directly into your HTML, you can still continue to do so when cookies are present, and use lazy-loading as a fallback strategy for prefetched pages. - If your site is not personalized based on cookies, or if the personalization isn't critical, you can choose to serve the same content to your repeat visitors as you would to first-time visitors. @@ -87,4 +87,4 @@ These technologies have been integrated on Google Search so that sites may begin While these technologies both solve the same use case, they offer different trade-offs on the key considerations explained earlier. You may even decide to start with one technology and graduate to the other as your needs, or appreciation of the benefits, evolve. See these deep dives to find out which technology is the best path forward for your particular situation: - [Deep dive on Private Prefetch Proxy](/blog/private-prefetch-proxy) -- [Deep dive on Signed Exchange](http://goo.gle/sxg-info) \ No newline at end of file +- [Deep dive on Signed Exchange](http://goo.gle/sxg-info) diff --git a/site/en/blog/crux-rank-magnitude/index.md b/site/en/blog/crux-rank-magnitude/index.md index e6a6750ab..117679bec 100644 --- a/site/en/blog/crux-rank-magnitude/index.md +++ b/site/en/blog/crux-rank-magnitude/index.md @@ -105,7 +105,7 @@ WHERE experimental.popularity.rank <= 10000 To touch on the potential of our new popularity metric, let’s see how popularity segments of the web differ with respect to the [first contentful paint metric -(FCP)](https://web.dev/first-contentful-paint/). For the purpose of this query, +(FCP)](https://web.dev/articles/first-contentful-paint). For the purpose of this query, we consider 1 second a fast user experience. ```sql diff --git a/site/en/blog/csp-issues/index.md b/site/en/blog/csp-issues/index.md index a370f5357..7e22433b1 100644 --- a/site/en/blog/csp-issues/index.md +++ b/site/en/blog/csp-issues/index.md @@ -24,9 +24,9 @@ The implementation work was done in the course of 2 internships: ## What is a Content Security Policy? -[Content Security Policy (CSP)]( https://web.dev/strict-csp/) allows to restrict certain behaviors in a website to increase security. For example, CSP can be used to disallow inline scripts or to disallow [`eval`](https://tc39.es/ecma262/#sec-eval-x), both of which reduce the attack surface for [Cross-Site Scripting (XSS)](https://owasp.org/www-community/attacks/xss/) attacks. For a detailed introduction to CSP, read [here](https://web.dev/csp/). +[Content Security Policy (CSP)]( https://web.dev/articles/strict-csp) allows to restrict certain behaviors in a website to increase security. For example, CSP can be used to disallow inline scripts or to disallow [`eval`](https://tc39.es/ecma262/#sec-eval-x), both of which reduce the attack surface for [Cross-Site Scripting (XSS)](https://owasp.org/www-community/attacks/xss/) attacks. For a detailed introduction to CSP, read [here](https://web.dev/articles/csp). -A particularly new CSP is the [Trusted Types(TT)](https://web.dev/trusted-types/) policy, which enables a dynamic analysis that can systematically prevent a large class of injection attacks on websites. To achieve this, TT supports a website in policing its JavaScript code to only allow certain types of things to be assigned to DOM sinks such as innerHTML. +A particularly new CSP is the [Trusted Types(TT)](https://web.dev/articles/trusted-types) policy, which enables a dynamic analysis that can systematically prevent a large class of injection attacks on websites. To achieve this, TT supports a website in policing its JavaScript code to only allow certain types of things to be assigned to DOM sinks such as innerHTML. A website can activate a content security policy by including a particular HTTP header. For example, the header `content-security-policy: require-trusted-types-for 'script'; trusted-types default` diff --git a/site/en/blog/css-grid-tooling/index.md b/site/en/blog/css-grid-tooling/index.md index 0dd8c1048..9ae764909 100644 --- a/site/en/blog/css-grid-tooling/index.md +++ b/site/en/blog/css-grid-tooling/index.md @@ -19,7 +19,7 @@ tags: ## Why did we make CSS Grid Tooling? -[CSS Grid](https://web.dev/learn/css/grid/) is a very powerful CSS layout system that allows web developers to build a complex two-dimensional layout and set out rules about how each and every child item in a grid is sized, aligned, and ordered. CSS Grid was introduced after [Flexbox](https://web.dev/learn/css/flexbox/) became popular, and together, they can help developers achieve better responsive design without complicated alignment hacks or JavaScript-assisted layout. +[CSS Grid](https://web.dev/learn/css/grid) is a very powerful CSS layout system that allows web developers to build a complex two-dimensional layout and set out rules about how each and every child item in a grid is sized, aligned, and ordered. CSS Grid was introduced after [Flexbox](https://web.dev/learn/css/flexbox) became popular, and together, they can help developers achieve better responsive design without complicated alignment hacks or JavaScript-assisted layout. As a relatively new layout system, CSS Grid is also hard to get right. Its syntax is quite versatile (just search *grid cheatsheet*), there are many ways to achieve the same layout, and flexible sizing and implicit tracks make it harder to reason about why the layout *is* or *isn’t* behaving as it should. This is why we set out to provide dedicated CSS Grid tooling in DevTools, so that developers can have a better understanding of what their CSS code is doing, and how to get to the right layout. @@ -156,4 +156,4 @@ This enables DevTools frontend to get a list of CSS Grid containers in a page, p CSS Grid tooling was one of the first DevTools design tooling projects to support a Web Platform feature. It debuted many fundamental toolings in DevTools, e.g. persistent overlays, DOM Tree badges, and the **Layout** pane, and paved the way for future layout toolings in Chrome DevTools like Flexbox and Container queries. It also laid the foundation for Grid and Flexbox editors, which allow developers to change Grid and Flexbox alignments in an interactive way. We'll go through them in the future. {% Partial 'devtools/reach-out.md' %} -{% Partial 'devtools/engineering-blog.md' %} \ No newline at end of file +{% Partial 'devtools/engineering-blog.md' %} diff --git a/site/en/blog/css-in-js/index.md b/site/en/blog/css-in-js/index.md index 8e7cc01c8..bade52344 100644 --- a/site/en/blog/css-in-js/index.md +++ b/site/en/blog/css-in-js/index.md @@ -35,7 +35,7 @@ stylesheet.replaceSync('.some { color: blue; }'); stylesheet.insertRule('.some { color: green; }'); ``` -You can [create a completely new stylesheet](https://web.dev/constructable-stylesheets/) as well: +You can [create a completely new stylesheet](https://web.dev/articles/constructable-stylesheets) as well: ```js // Create a completely new stylesheet @@ -53,7 +53,7 @@ In DevTools, the most commonly used feature when dealing with CSS is the **Style {% Video src="video/dPDCek3EhZgLQPGtEG3y0fTn4v82/Jy8q9gPbQknRturLyCsq.mp4", autoplay="true", muted="true", loop="true" %} -Before last year, the support for CSS rules modified using CSSOM APIs was rather limited: **you could only see the applied rules but could not edit them.** The main goal we had last year was to allow editing of CSS-in-JS rules using the Styles pane. Sometimes we also call CSS-in-JS styles ["constructed"](https://web.dev/constructable-stylesheets/) to indicate that they were constructed using Web APIs. +Before last year, the support for CSS rules modified using CSSOM APIs was rather limited: **you could only see the applied rules but could not edit them.** The main goal we had last year was to allow editing of CSS-in-JS rules using the Styles pane. Sometimes we also call CSS-in-JS styles ["constructed"](https://web.dev/articles/constructable-stylesheets) to indicate that they were constructed using Web APIs. Let's dive into the details of Styles editing works in DevTools. diff --git a/site/en/blog/css-update-media-query/index.md b/site/en/blog/css-update-media-query/index.md index 8443df6e1..e96da3f25 100644 --- a/site/en/blog/css-update-media-query/index.md +++ b/site/en/blog/css-update-media-query/index.md @@ -12,7 +12,7 @@ tags: - css --- -CSS [media queries](https://web.dev/learn/design/media-queries/) are a powerful +CSS [media queries](https://web.dev/learn/design/media-queries) are a powerful tool that allow you to control the appearance of your website or web app based on the device it is being viewed on. With media queries, you can create different layouts for different screen sizes, orientations, and other factors. diff --git a/site/en/blog/cvd/index.md b/site/en/blog/cvd/index.md index f007347df..fb4d44d6e 100644 --- a/site/en/blog/cvd/index.md +++ b/site/en/blog/cvd/index.md @@ -41,7 +41,7 @@ Chrome DevTools can help developers and designers to improve contrast and to pic - The Inspect Mode tooltip that appears on top of the web page [shows the contrast ratio](/blog/new-in-devtools-84#a11y) for text elements. - The DevTools color picker [calls out bad contrast ratios](/blog/new-in-devtools-65#contrast) for text elements, [shows the recommended contrast line](/blog/new-in-devtools-73#AAA) to help manually select better colors, and can even [suggest accessible colors](/blog/new-in-devtools-86#accessible-color). -- Both [the CSS Overview panel](/blog/new-in-devtools-87#css-overview) and [the Lighthouse Accessibility audit report](https://web.dev/color-contrast/) lists low-contrast text elements as found on your page. +- Both [the CSS Overview panel](/blog/new-in-devtools-87#css-overview) and [the Lighthouse Accessibility audit report](https://web.dev/articles/color-contrast) lists low-contrast text elements as found on your page. {% YouTube id='Mje2wYgPYP0' %} @@ -285,7 +285,7 @@ AtomicString CreateVisionDeficiencyFilterUrl(VisionDeficiency vision_deficiency) Note that this technique gives us access to the full power of SVG filters without having to re-implement anything or re-invent any wheels. We’re implementing a Blink Renderer feature, but we’re doing so by leveraging the Web Platform. -Okay, so we’ve figured out how to construct SVG filters and turn them into data URLs that we can use within our CSS `filter` property value. Can you think of a problem with this technique? It turns out, we can’t actually _rely_ on the data URL being loaded in all cases, since the target page might have [a `Content-Security-Policy`](https://web.dev/strict-csp/) that blocks data URLs. Our final Blink-level implementation takes special care to bypass CSP for these “internal” data URLs during loading. +Okay, so we’ve figured out how to construct SVG filters and turn them into data URLs that we can use within our CSS `filter` property value. Can you think of a problem with this technique? It turns out, we can’t actually _rely_ on the data URL being loaded in all cases, since the target page might have [a `Content-Security-Policy`](https://web.dev/articles/strict-csp) that blocks data URLs. Our final Blink-level implementation takes special care to bypass CSP for these “internal” data URLs during loading. Edge cases aside, we’ve made some good progress. Because we no longer depend on inline `<svg>` being present in the same document, we’ve effectively reduced our solution to just a single self-contained CSS `filter` property definition. Great! Now let’s get rid of that too. @@ -341,4 +341,4 @@ What’s unique about this implementation is that our HTML/CSS/SVG prototype end For more background, check out [our design proposal](https://goo.gle/devtools-cvd) or [the Chromium tracking bug](https://bugs.chromium.org/p/chromium/issues/detail?id=1003700) which references all related patches. {% Partial 'devtools/reach-out.md' %} -{% Partial 'devtools/engineering-blog.md' %} \ No newline at end of file +{% Partial 'devtools/engineering-blog.md' %} diff --git a/site/en/blog/debugging-speculation-rules/index.md b/site/en/blog/debugging-speculation-rules/index.md index 93b212767..59595a3d4 100644 --- a/site/en/blog/debugging-speculation-rules/index.md +++ b/site/en/blog/debugging-speculation-rules/index.md @@ -16,7 +16,7 @@ tags: - chrome-117 --- -Speculation rules can be used to prefetch and prerender next page navigations as detailed in [the previous blog post](/blog/prerender-pages/). This can allow for much quicker—or even instant—page loads, greatly improving [Core Web Vitals](https://web.dev/vitals/) for these additional page navigations. +Speculation rules can be used to prefetch and prerender next page navigations as detailed in [the previous blog post](/blog/prerender-pages/). This can allow for much quicker—or even instant—page loads, greatly improving [Core Web Vitals](https://web.dev/articles/vitals) for these additional page navigations. Debugging speculation rules can be tricky. This is particularly true for prerendered pages, as these pages are rendered in a separate renderer—kind of like a hidden background tab that replaces the current tab when activated. Therefore, the usual DevTools options cannot always be used to debug issues. @@ -29,7 +29,7 @@ There's a lot of "pre-" terms that are easily confused, so let's start with an e - **Prefetch**: fetching a resource or document in advance to improve future performance. This post covers prefetching documents using the Speculation Rules API, rather than the similar, but older `<link rel="prefetch">` option often used for prefetching subresources. - **Prerender**: this goes a step beyond prefetching and actually renders the whole page as if the user had navigated to it, but keeps it in a hidden background renderer process ready to be used if the user actually navigates there. Again, this document is concerned with the newer Speculation Rules API version of this, rather than the older `<link rel="prerender">` option (which [no longer does a full prerender](/blog/nostate-prefetch/)). - **Navigational preloading**: the collective term for the new prefetch and prerender options triggered by speculation rules. -- **Preloading**: an overloaded term that can refer to a number of technologies and processes including `<link rel="preload">`, the [preload scanner](https://web.dev/preload-scanner/), and [service worker navigation preloads](https://web.dev/navigation-preload/). These items will not be covered here, but the term is included to clearly differentiate those from the "navigational preloading" term above. +- **Preloading**: an overloaded term that can refer to a number of technologies and processes including `<link rel="preload">`, the [preload scanner](https://web.dev/articles/preload-scanner), and [service worker navigation preloads](https://web.dev/articles/navigation-preload). These items will not be covered here, but the term is included to clearly differentiate those from the "navigational preloading" term above. {% Aside %} For more details see [this preloading tech landscape](https://docs.google.com/document/d/1FNLyXW0Q5Fi5-kEOtjfOdmtoDxRtUR_wX4dl5Fz9c7o/edit) document. diff --git a/site/en/blog/default-offline/index.md b/site/en/blog/default-offline/index.md index f0c82792b..d1d3ddd88 100644 --- a/site/en/blog/default-offline/index.md +++ b/site/en/blog/default-offline/index.md @@ -16,7 +16,7 @@ tags: Installed platform apps can be launched even when offline. In this situation they often include a page letting the user know internet access is not available. Some developers even create a full set of features that can be used while offline. -With web apps, the capability to work offline is more recent; it became possible with the launch of the [Service Worker API](/docs/workbox/service-worker-overview/). Also, when websites became installable, PWA added a [requirement](https://web.dev/install-criteria/) to register a service worker and implement its `fetch()` method in order for a web app to be installable. +With web apps, the capability to work offline is more recent; it became possible with the launch of the [Service Worker API](/docs/workbox/service-worker-overview/). Also, when websites became installable, PWA added a [requirement](https://web.dev/articles/install-criteria) to register a service worker and implement its `fetch()` method in order for a web app to be installable. The idea was to incentivize developers to provide their users at least a notice that the app couldn’t be used at the moment. Now developers won’t need to do anything to get a default offline page. From Chrome 109 on Android, the browser will automatically generate a page that lets the user know when they are offline. diff --git a/site/en/blog/deprecating-unload/index.md b/site/en/blog/deprecating-unload/index.md index 43a7cbaff..1345859b9 100644 --- a/site/en/blog/deprecating-unload/index.md +++ b/site/en/blog/deprecating-unload/index.md @@ -35,7 +35,7 @@ Scenarios where this event was most commonly used include: However the `unload` event [is extremely unreliable](/articles/page-lifecycle-api/#the-unload-event). -On desktop Chrome and Firefox, `unload` is reasonably reliable but it has a negative impact on a site's performance by preventing the usage of [bfcache (back/forward cache)](https://web.dev/bfcache/#never-use-the-unload-event). +On desktop Chrome and Firefox, `unload` is reasonably reliable but it has a negative impact on a site's performance by preventing the usage of [bfcache (back/forward cache)](https://web.dev/articles/bfcache#never_use_the_unload_event). On mobile browsers `unload` often doesn't run as tabs are frequently backgrounded and then killed. For this reason browsers choose to prioritize the bfcache on mobile over `unload`, making them even more unreliable. Safari also uses this behaviour on desktop. @@ -96,7 +96,7 @@ For more details see [usUsing Reporting API to find unloads](https://github.com/ ### Bfcache `notRestoredReasons` API -The [`notRestoredReasons` property](/docs/web-platform/bfcache-notrestoredreasons/)—added to the [`PerformanceNavigationTiming`](https://developer.mozilla.org/docs/Web/API/PerformanceNavigationTiming) class—reports information on whether documents were blocked from using the [bfcache](https://web.dev/bfcache/) on navigation, and why. Usage instructions can be found [here](/docs/web-platform/bfcache-notrestoredreasons/). This is an example of how the response object warning of an existing `unload` listener looks like: +The [`notRestoredReasons` property](/docs/web-platform/bfcache-notrestoredreasons/)—added to the [`PerformanceNavigationTiming`](https://developer.mozilla.org/docs/Web/API/PerformanceNavigationTiming) class—reports information on whether documents were blocked from using the [bfcache](https://web.dev/articles/bfcache) on navigation, and why. Usage instructions can be found [here](/docs/web-platform/bfcache-notrestoredreasons/). This is an example of how the response object warning of an existing `unload` listener looks like: ```js { @@ -181,7 +181,7 @@ The following table summarizes the different uses of the options discussed previ ## Conclusion -`unload` handlers are being deprecated. They have been unreliable for a long time and are not guaranteed to be fired on all cases where a document gets destroyed. Additionally, `unload` handlers are incompatible with [bfcache](https://web.dev/bfcache/). +`unload` handlers are being deprecated. They have been unreliable for a long time and are not guaranteed to be fired on all cases where a document gets destroyed. Additionally, `unload` handlers are incompatible with [bfcache](https://web.dev/articles/bfcache). Sites that currently make use of `unload` handlers should prepare for this upcoming deprecation by testing for any existing `unload` handlers, removing or migrating them or, as a last resort, delaying the deprecation if more time is needed. diff --git a/site/en/blog/deprecating-web-sql/index.md b/site/en/blog/deprecating-web-sql/index.md index 8a8f2049b..2206ec77c 100644 --- a/site/en/blog/deprecating-web-sql/index.md +++ b/site/en/blog/deprecating-web-sql/index.md @@ -118,7 +118,7 @@ own database to the web. What's more, we're hoping that this example will help a new ecosystem of open-source databases to flourish! The release of -[file system access handles](https://web.dev/file-system-access/#accessing-files-optimized-for-performance-from-the-origin-private-file-system) +[file system access handles](https://web.dev/articles/file-system-access#accessing_files_optimized_for_performance_from_the_origin_private_file_system) finally provides the new primitive on which custom storage solutions can be built. diff --git a/site/en/blog/deps-rems-100/index.md b/site/en/blog/deps-rems-100/index.md index 9ea6e614d..701c11d7a 100644 --- a/site/en/blog/deps-rems-100/index.md +++ b/site/en/blog/deps-rems-100/index.md @@ -19,9 +19,9 @@ stable version in late March, 2022. ## Last Version for Unreduced User-Agent String -Chromium 100 will be the last version to support an unreduced User-Agent string by default (as well as the related `navigator.userAgent`, `navigator.appVersion`, and `navigator.platform` DOM APIs). The origin trial that [allowed sites to test the fully reduced User-Agent](/origintrials/#/view_trial/-7123568710593282047) will end on April 19, 2022. After that date, the User-Agent String will be gradually reduced. To review the whole schedule, see [Chromium Blog: User-Agent Reduction Origin Trial and Dates](https://blog.chromium.org/2021/09/user-agent-reduction-origin-trial-and-dates.html). Sites that need more time to test or [migrate to User-Agent Client Hints](https://web.dev/migrate-to-ua-ch/) can enroll in the deprecation origin trial [scheduled from Chrome 100 to 113](/origintrials/#/view_trial/2608710084154359809), inclusive. In contrast to the first origin trial, which previews the fully reduced User-Agent string, the deprecation trial maintains the legacy User-Agent. The deprecation trial is expected to end in late May of 2023. +Chromium 100 will be the last version to support an unreduced User-Agent string by default (as well as the related `navigator.userAgent`, `navigator.appVersion`, and `navigator.platform` DOM APIs). The origin trial that [allowed sites to test the fully reduced User-Agent](/origintrials/#/view_trial/-7123568710593282047) will end on April 19, 2022. After that date, the User-Agent String will be gradually reduced. To review the whole schedule, see [Chromium Blog: User-Agent Reduction Origin Trial and Dates](https://blog.chromium.org/2021/09/user-agent-reduction-origin-trial-and-dates.html). Sites that need more time to test or [migrate to User-Agent Client Hints](https://web.dev/articles/migrate-to-ua-ch) can enroll in the deprecation origin trial [scheduled from Chrome 100 to 113](/origintrials/#/view_trial/2608710084154359809), inclusive. In contrast to the first origin trial, which previews the fully reduced User-Agent string, the deprecation trial maintains the legacy User-Agent. The deprecation trial is expected to end in late May of 2023. This is part of a strategy to replace use of the User-Agent string with the -new User-Agent Client Hints API. To learn about User-Agent Client Hints, see [Migrate to User-Agent Client Hints](https://web.dev/migrate-to-ua-ch/) and [Improving user privacy and developer experience with User-Agent Client Hints](https://web.dev/user-agent-client-hints/). +new User-Agent Client Hints API. To learn about User-Agent Client Hints, see [Migrate to User-Agent Client Hints](https://web.dev/articles/migrate-to-ua-ch) and [Improving user privacy and developer experience with User-Agent Client Hints](https://web.dev/articles/user-agent-client-hints). {% Partial 'deprecations-policy.md' %} diff --git a/site/en/blog/deps-rems-99/index.md b/site/en/blog/deps-rems-99/index.md index d41212282..63c86a34e 100644 --- a/site/en/blog/deps-rems-99/index.md +++ b/site/en/blog/deps-rems-99/index.md @@ -44,7 +44,7 @@ method now returns an array of [instead of a GamepadList](https://www.chromestatus.com/feature/5693119438782464). `GamepadList` is no longer supported in Chrome. This brings Chrome in line with specification and with Gecko and Webkit. For information on Gamepads generally, see [Play -the Chrome dino game with your gamepad](https://web.dev/gamepad/). +the Chrome dino game with your gamepad](https://web.dev/articles/gamepad). ## Update WebCodecs to match the specification diff --git a/site/en/blog/devtools-autofill/index.md b/site/en/blog/devtools-autofill/index.md index db6d26421..44608941c 100644 --- a/site/en/blog/devtools-autofill/index.md +++ b/site/en/blog/devtools-autofill/index.md @@ -188,5 +188,5 @@ related to DevTools: * [Learn Forms](https://web.dev/learn/forms): A course about HTML forms to help you improve your web developer expertise. Ideal for anyone new to forms and Autofill. -* [web.dev/tags/forms](https://web.dev/tags/forms/): Guidance, best practice and codelabs, for +* [web.dev/tags/forms](https://web.dev/articles/tags/forms): Guidance, best practice and codelabs, for payment, login, and address forms. diff --git a/site/en/blog/devtools-tips-10/index.md b/site/en/blog/devtools-tips-10/index.md index 8c3c32108..966682b6c 100644 --- a/site/en/blog/devtools-tips-10/index.md +++ b/site/en/blog/devtools-tips-10/index.md @@ -16,7 +16,7 @@ tags: - devtools-tips --- -[User preference media features](https://web.dev/new-responsive/#responsive-to-the-user) give you the ability to style web experiences that align with the user's own specific preferences and needs. In other words, preference media features allow you to adapt your user experiences to your user's expectations. +[User preference media features](https://web.dev/articles/new-responsive#responsive_to_the_user) give you the ability to style web experiences that align with the user's own specific preferences and needs. In other words, preference media features allow you to adapt your user experiences to your user's expectations. {% YouTube id='gOkM1L6azEI' %} diff --git a/site/en/blog/devtools-tips-17/index.md b/site/en/blog/devtools-tips-17/index.md index 9ede4b958..b30566e88 100644 --- a/site/en/blog/devtools-tips-17/index.md +++ b/site/en/blog/devtools-tips-17/index.md @@ -30,10 +30,10 @@ With DevTools you can: - Test tokens for [origin trials](/docs/web-platform/origin-trials/). - Explore the Origin Private File System (OPFS) of a web application with a [DevTools extension](https://chrome.google.com/webstore/detail/opfs-explorer/acndjpgkpaclldomagafnognkcgjignd). -To learn more, see the following: +To learn more, see the following: - [Get started with origin trials](/docs/web-platform/origin-trials/) -- [Learn Progressive Web Apps](https://web.dev/learn/pwa/) and [Debug Progressive Web Apps](/docs/devtools/progressive-web-apps/) +- [Learn Progressive Web Apps](https://web.dev/learn/pwa) and [Debug Progressive Web Apps](/docs/devtools/progressive-web-apps/) - [Emulate device sensors](/docs/devtools/sensors/) - [URL protocol handler registration for PWAs](/articles/url-protocol-handler/) -- [The File System Access API](/articles/file-system-access/) \ No newline at end of file +- [The File System Access API](/articles/file-system-access/) diff --git a/site/en/blog/devtools-tips-18/index.md b/site/en/blog/devtools-tips-18/index.md index c2e5b7bbc..5dd6b6ec1 100644 --- a/site/en/blog/devtools-tips-18/index.md +++ b/site/en/blog/devtools-tips-18/index.md @@ -37,6 +37,6 @@ With DevTools, you can: To learn more, see: - [Debug Progressive Web Apps](/docs/devtools/progressive-web-apps/) -- [Learn PWA](https://web.dev/learn/pwa/) +- [Learn PWA](https://web.dev/learn/pwa) - [Unpacking the Workbox](https://www.youtube.com/playlist?list=PLNYkxOF6rcIC3BwCw--jvZNN7obH4QUlH) video series -- [The service worker lifecycle](https://web.dev/service-worker-lifecycle/) \ No newline at end of file +- [The service worker lifecycle](https://web.dev/articles/service-worker-lifecycle) diff --git a/site/en/blog/devtools-tips-20/index.md b/site/en/blog/devtools-tips-20/index.md index b188ce598..d47acf30b 100644 --- a/site/en/blog/devtools-tips-20/index.md +++ b/site/en/blog/devtools-tips-20/index.md @@ -43,7 +43,7 @@ Watch the video to learn how the **Elements** > **Styles** pane highlights vario - *Non-editable property* - <s><em>Overridden non-editable property</em></s> -More debugging tips: +More debugging tips: - Use the filter in the **Styles** pane to focus on the one property that interests you. - Use the **Computed** pane to see all the [Cascade](https://developer.mozilla.org/docs/Web/CSS/Cascade) winners and their computed values. @@ -51,6 +51,6 @@ More debugging tips: To learn more about all the ways DevTools highlights CSS issues, see [Find invalid, overridden, inactive, and other CSS](/docs/devtools/css/issues/). -To level up your CSS expertise, see [Learn CSS](https://web.dev/learn/css/). +To level up your CSS expertise, see [Learn CSS](https://web.dev/learn/css). -To learn how to create websites that look great and work well for everyone, see [Learn Responsive Design](https://web.dev/learn/design/). +To learn how to create websites that look great and work well for everyone, see [Learn Responsive Design](https://web.dev/learn/design). diff --git a/site/en/blog/devtools-tips-23/index.md b/site/en/blog/devtools-tips-23/index.md index c99e5b29c..489e832ee 100644 --- a/site/en/blog/devtools-tips-23/index.md +++ b/site/en/blog/devtools-tips-23/index.md @@ -15,7 +15,7 @@ tags: - devtools-tips --- -[Source maps](https://web.dev/source-maps/) let you keep your code readable and debuggable even after you've combined and minified it, without impacting performance. +[Source maps](https://web.dev/articles/source-maps) let you keep your code readable and debuggable even after you've combined and minified it, without impacting performance. {% YouTube id='FIYkjjFYvoI' %} @@ -38,5 +38,5 @@ Additionally, source maps can have [extensions](https://sourcemaps.info/spec.htm To learn more, see: - [Introduction to JavaScript Source Maps](/blog/sourcemaps/) -- [What are source maps?](https://web.dev/source-maps/) +- [What are source maps?](https://web.dev/articles/source-maps) - [Debug your original code instead of deployed with source maps](/docs/devtools/javascript/source-maps/) diff --git a/site/en/blog/devtools-tips-24/index.md b/site/en/blog/devtools-tips-24/index.md index 51c220b0e..07c41e4d9 100644 --- a/site/en/blog/devtools-tips-24/index.md +++ b/site/en/blog/devtools-tips-24/index.md @@ -15,7 +15,7 @@ tags: - devtools-tips --- -[Source maps](https://web.dev/source-maps/) let you keep your code readable and debuggable even after you've combined and minified it, without impacting performance. To learn how source maps work, see the [previous DevTools Tips video](https://www.youtube.com/watch?v=FIYkjjFYvoI). +[Source maps](https://web.dev/articles/source-maps) let you keep your code readable and debuggable even after you've combined and minified it, without impacting performance. To learn how source maps work, see the [previous DevTools Tips video](https://www.youtube.com/watch?v=FIYkjjFYvoI). {% YouTube id='SkUcO4ML5U0' %} @@ -29,6 +29,6 @@ Watch this video to learn how to work with source maps in DevTools: To learn more, see: -- [What are source maps?](https://web.dev/source-maps/) +- [What are source maps?](https://web.dev/articles/source-maps) - [Debug your original code instead of deployed with source maps](/docs/devtools/javascript/source-maps/) - [Developer Resources: View and manually load source maps](/docs/devtools/developer-resources/) diff --git a/site/en/blog/devtools-tips-5/index.md b/site/en/blog/devtools-tips-5/index.md index f8287fd2d..3b940b8ba 100644 --- a/site/en/blog/devtools-tips-5/index.md +++ b/site/en/blog/devtools-tips-5/index.md @@ -44,7 +44,7 @@ For a more hands-on learning experience, see the [Make your website more readabl To learn more, see: -- [Color and contrast accessibility](https://web.dev/color-and-contrast-accessibility/) +- [Color and contrast accessibility](https://web.dev/articles/color-and-contrast-accessibility) - [WebAIM guidelines](https://webaim.org/standards/wcag/) -- [Learn Accessibility's color and contrast module](https://web.dev/learn/accessibility/color-contrast/) -- [Learn Accessibility](https://web.dev/learn/accessibility/) in general +- [Learn Accessibility's color and contrast module](https://web.dev/learn/accessibility/color-contrast) +- [Learn Accessibility](https://web.dev/learn/accessibility) in general diff --git a/site/en/blog/devtools-tips-6/index.md b/site/en/blog/devtools-tips-6/index.md index 55d951b4e..66ac48d41 100644 --- a/site/en/blog/devtools-tips-6/index.md +++ b/site/en/blog/devtools-tips-6/index.md @@ -26,6 +26,6 @@ Watch the video to learn how to: - Toggle the flexbox overlay in the viewport to see the changes you make right away. - Use the **Elements** > **Layout** > **Flexbox** section to see a list of all elements and locate them in the DOM tree. Additionally, you can customize the overlay colors here. -To learn more about CSS flexbox in general, see [Learn CSS > Flexbox](https://web.dev/learn/css/flexbox/). +To learn more about CSS flexbox in general, see [Learn CSS > Flexbox](https://web.dev/learn/css/flexbox). For a more hands-on debugging experience in DevTools, follow the [Inspect and debug CSS flexbox layouts](/docs/devtools/css/flexbox/) tutorial. diff --git a/site/en/blog/devtools-tips-8/index.md b/site/en/blog/devtools-tips-8/index.md index 5fe46d0f5..2b7d5b715 100644 --- a/site/en/blog/devtools-tips-8/index.md +++ b/site/en/blog/devtools-tips-8/index.md @@ -21,12 +21,12 @@ tags: The new **Performance insights** panel in DevTools is an experiment that addresses your pain points when analysing the performance of your website. {% Aside %} -This is a preview feature from Chrome 102. Our team is actively working on this feature and we are looking for your [feedback](https://goo.gle/perf-insights-feedback) for further enhancements. +This is a preview feature from Chrome 102. Our team is actively working on this feature and we are looking for your [feedback](https://goo.gle/perf-insights-feedback) for further enhancements. {% endAside %} The new **Performance insights** panel does the following: -- Streamlines performance data and focuses on three key metrics: [Core Web Vitals](https://web.dev/vitals/). +- Streamlines performance data and focuses on three key metrics: [Core Web Vitals](https://web.dev/articles/vitals). - Supports use-case-driven analysis. - Identifies issues and suggests actionable insights. - Doesn't require deep browser expertise to use. @@ -39,6 +39,6 @@ With the **Performance insights** panel, boost the performance of your website i Watch the video above to learn how to record the performance, navigate the overview, and get insights. -To understand the three key metrics, see [Core Web Vitals](https://web.dev/vitals/). +To understand the three key metrics, see [Core Web Vitals](https://web.dev/articles/vitals). For a more hands-on learning experience, follow the [Get actionable insights on your website's performance](/docs/devtools/performance-insights/) tutorial. diff --git a/site/en/blog/devtools-tips-9/index.md b/site/en/blog/devtools-tips-9/index.md index 329ea6be1..0edbf2805 100644 --- a/site/en/blog/devtools-tips-9/index.md +++ b/site/en/blog/devtools-tips-9/index.md @@ -16,7 +16,7 @@ tags: - devtools-tips --- -[CSS container queries](https://web.dev/new-responsive/#responsive-to-the-container) is the new CSS feature that web developers are excited about. It may trigger a revolution in web design—from page-based responsive design to container-based [responsive design](https://web.dev/new-responsive/#responsive-to-the-container). +[CSS container queries](https://web.dev/articles/new-responsive#responsive_to_the_container) is the new CSS feature that web developers are excited about. It may trigger a revolution in web design—from page-based responsive design to container-based [responsive design](https://web.dev/articles/new-responsive#responsive_to_the_container). {% YouTube id='X4TYXlvbb2E' %} diff --git a/site/en/blog/document-domain-setter-deprecation/index.md b/site/en/blog/document-domain-setter-deprecation/index.md index 47c7ec8e8..4acb3b682 100644 --- a/site/en/blog/document-domain-setter-deprecation/index.md +++ b/site/en/blog/document-domain-setter-deprecation/index.md @@ -45,7 +45,7 @@ We expect other browsers to eventually deprecate and remove this functionality. [`document.domain`](https://developer.mozilla.org/docs/Web/API/Document/domain) was designed to get or set the origin's hostname. Many websites set `document.domain` to allow communication between [same-site but -cross-origin](https://web.dev/same-site-same-origin/) pages. +cross-origin](https://web.dev/articles/same-site-same-origin) pages. While this is a convenient technique, it introduces a security risk, because it @@ -61,7 +61,7 @@ specification that [warns users to avoid using it](https://html.spec.whatwg.org/ #### How `document.domain` is used today Many websites set `document.domain` to allow communication between [same-site -but cross-origin](https://web.dev/same-site-same-origin/) pages. +but cross-origin](https://web.dev/articles/same-site-same-origin) pages. Same-site but cross-origin sites have the same [eTLD+1](https://web.dev/same-site-same-origin/#:~:text=the%20whole%20site%20name%20is%20known%20as%20the%20etld%2B1) @@ -137,7 +137,7 @@ read the ["Document.domain" page on MDN](https://developer.mozilla.org/docs/Web/ {% Aside 'warning' %} -Note that starting in Chrome 115, using the `document.domain` setter will not throw an exception, as per the [specification](https://html.spec.whatwg.org/multipage/browsers.html#dom-document-domain). It will only cease to have an effect. +Note that starting in Chrome 115, using the `document.domain` setter will not throw an exception, as per the [specification](https://html.spec.whatwg.org/multipage/browsers.html#dom-document-domain). It will only cease to have an effect. {% endAside %} @@ -147,11 +147,11 @@ Notice the yellow flag in the upper right of DevTools. {% Img src="image/O2RNUyVSLubjvENAT3e7JSdqSOx1/HIqzEZLIDAIPgY9y39X1.png", alt="Screenshot of the issue warning in DevTools", width="800", height="255" %} -You can also run your site through the [LightHouse deprecated API audit](https://web.dev/deprecations/) to find all APIs that are scheduled to be removed from Chrome. +You can also run your site through the [LightHouse deprecated API audit](https://web.dev/articles/deprecations) to find all APIs that are scheduled to be removed from Chrome. If you have set up the Reporting API, Chrome has sent you deprecation reports to notify you of this upcoming deprecation. Learn more about [how to use the -Reporting API](https://web.dev/reporting-api/) with either existing report +Reporting API](https://web.dev/articles/reporting-api) with either existing report collection services or by building your own in-house solution. ## How do I see this change in action? @@ -173,7 +173,7 @@ cross-origin accesses. ### Use `postMessage()` or Channel Messaging API instead of `document.domain` -In most use cases, cross-origin +In most use cases, cross-origin [`postMessage()`](https://developer.mozilla.org/docs/Web/API/Window/postMessage) or [Channel Messaging API](https://developer.mozilla.org/docs/Web/API/Channel_Messaging_API) can replace `document.domain`. @@ -237,7 +237,7 @@ Origin-Agent-Cluster: ?0 The `Origin-Agent-Cluster` header instructs the browser whether the document should be handled by the origin-keyed agent cluster or not. To learn more about `Origin-Agent-Cluster`, read [Requesting performance isolation with the -`Origin-Agent-Cluster` header](https://web.dev/origin-agent-cluster/). +`Origin-Agent-Cluster` header](https://web.dev/articles/origin-agent-cluster). When you send this header, your document can continue to set `document.domain` even after it becomes immutable by default. diff --git a/site/en/blog/early-hints/index.md b/site/en/blog/early-hints/index.md index 23a240189..8993fb702 100644 --- a/site/en/blog/early-hints/index.md +++ b/site/en/blog/early-hints/index.md @@ -58,7 +58,7 @@ Before going deep into the topic, please note that Early Hints are not useful if The first step to take advantage of Early Hints consists of identifying the top landing pages, that is, the pages where your users typically start when they visit your website. This could be the homepage, or popular product listing pages if you have lots of users coming from other websites. The reason these entry points matter more than other pages is because Early Hints' usefulness decreases as the user navigates around your website (that is, the browser is more likely to have all the sub-resources it needs on the second or third subsequent navigation). It's also always a good idea to deliver a great first impression! -Now that you have this prioritized list of landing pages, the next step consists of identifying which origins or sub-resources would be good candidates for [preconnect](https://web.dev/articles/uses-rel-preconnect) or [preload](https://web.dev/articles/preload-critical-assets) hints, as a first approximation. Typically, those would be origins and sub-resources that contribute the most to key user metrics such as [Largest Contentful Paint](https://web.dev/articles/lcp), or [First Contentful Paint](https://web.dev/articles/fcp). More concretely, look for render-blocking sub-resources such as synchronous JavaScript, stylesheets, or even web fonts. Similarly, look for origins that host sub-resources that contribute a lot to key user metrics. Note: if your main resources are already using `<link rel=preconnect>` or `<link rel=preload>`, you may consider these origins or resources among the candidates for Early Hints. See [this article](https://web.dev/articles/lcp/#how-to-improve-lcp) for more details. +Now that you have this prioritized list of landing pages, the next step consists of identifying which origins or sub-resources would be good candidates for [preconnect](https://web.dev/articles/uses-rel-preconnect) or [preload](https://web.dev/articles/preload-critical-assets) hints, as a first approximation. Typically, those would be origins and sub-resources that contribute the most to key user metrics such as [Largest Contentful Paint](https://web.dev/articles/lcp), or [First Contentful Paint](https://web.dev/articles/fcp). More concretely, look for render-blocking sub-resources such as synchronous JavaScript, stylesheets, or even web fonts. Similarly, look for origins that host sub-resources that contribute a lot to key user metrics. Note: if your main resources are already using `<link rel=preconnect>` or `<link rel=preload>`, you may consider these origins or resources among the candidates for Early Hints. See [this article](https://web.dev/articles/articles/lcp#how_to_improve_lcp) for more details. {% Aside 'important' %} What you decide to `preconnect` or `preload` as Early Hints may differ from what you have traditionally used these directives for in your HTML. diff --git a/site/en/blog/embed-content/index.md b/site/en/blog/embed-content/index.md index 8c0607b06..cf612516a 100644 --- a/site/en/blog/embed-content/index.md +++ b/site/en/blog/embed-content/index.md @@ -27,7 +27,7 @@ content. There are several ways developers can embed content on a website. The most common technique is to use an -[`<iframe>`](https://developer.mozilla.org/docs/Web/HTML/Element/iframe), +[`<iframe>`](https://developer.mozilla.org/docs/Web/HTML/Element/iframe), which allows you to embed any content onto your site with just a URL. It's already possible to add the `sandbox` attribute to make an iframe more secure. @@ -141,7 +141,7 @@ different top-level partitions needs to be displayed on the same page. ## Embed with portals {: #portal } -[Portal](https://web.dev/hands-on-portals/) (`<portal>`) is a proposed HTML +[Portal](https://web.dev/articles/hands-on-portals) (`<portal>`) is a proposed HTML element with an independent browsing context, which could improve the page transition experience. Portals embed content like iframe, but the user cannot access the portal's code. A portal is view-only and cannot be interacted with by @@ -162,32 +162,32 @@ early stages of development. Throughout web history, there have been a number of HTML elements proposed and APIs created to embed content. For a while, it was common to create sites with -multiple [`<frame>`](https://developer.mozilla.org/docs/Web/HTML/Element/frame) +multiple [`<frame>`](https://developer.mozilla.org/docs/Web/HTML/Element/frame) and a [`<frameset>`](https://developer.mozilla.org/docs/Web/HTML/Element/frameset) elements. Sites with several `<frameset>` elements displayed the URL of the parent page in the address bar, regardless of the source of the many individual frames. This made it difficult to share links to content within the site. These -APIs have since been deprecated. +APIs have since been deprecated. There was also a time when plugin technologies, such as the Java `<applet>` element, were used to cover other use cases. This was later replaced by the `<object>` element. Both of these elements were commonly used to display Flash plugins, but were also used to display other HTML elements (similar to iframes). Other elements, such as `<canvas>`, `<audio>`, `<video>`, and `<svg>`, have -rendered both the `<object>` and `<applet>` elements obsolete. +rendered both the `<object>` and `<applet>` elements obsolete. Although `<object>` and `<embed>` are not officially deprecated yet, it's best to avoid them, especially since they have some [strange behaviors](https://github.com/whatwg/html/issues?q=is%3Aopen+is%3Aissue+label%3A%22topic%3A+embed+and+object%22). `<applet>` was [removed from the HTML -specification](https://github.com/whatwg/html/pull/1399) in 2017. +specification](https://github.com/whatwg/html/pull/1399) in 2017. ## Conclusion -You can securely embed content onto any website, using the existing iframe -specification. More HTML elements, including `<fencedframe>` and `<portal>` have -been proposed for security and style improvements. We'll continue to share the -progress on the [Fenced Frames proposal](/docs/privacy-sandbox/fenced-frame/) as +You can securely embed content onto any website, using the existing iframe +specification. More HTML elements, including `<fencedframe>` and `<portal>` have +been proposed for security and style improvements. We'll continue to share the +progress on the [Fenced Frames proposal](/docs/privacy-sandbox/fenced-frame/) as it progresses. _Hero image by [Jackson So](https://unsplash.com/@jacksonsophat)._ diff --git a/site/en/blog/enabling-shared-array-buffer/index.md b/site/en/blog/enabling-shared-array-buffer/index.md index a5ca8c9b5..86c073a24 100644 --- a/site/en/blog/enabling-shared-array-buffer/index.md +++ b/site/en/blog/enabling-shared-array-buffer/index.md @@ -23,19 +23,19 @@ alt: A collection of padlocks. To secure more time to reliably relax the requirement to enable cross-origin isolation, the deprecation trial of `SharedArrayBuffer` -on desktop will be extended until Chrome 121. +on desktop will be extended until Chrome 121. **Update, Nov 2022** To secure more time to reliably relax the requirement to enable cross-origin isolation, the deprecation trial of `SharedArrayBuffer` -on desktop will be extended until Chrome 113. +on desktop will be extended until Chrome 113. **Update, Aug 2022** To secure more time to reliably relax the requirement to enable cross-origin isolation, the deprecation trial of `SharedArrayBuffer` -on desktop will be extended until Chrome 109. +on desktop will be extended until Chrome 109. **Update, May 2022** @@ -63,7 +63,7 @@ web, but things are settling down. Here's what you need to know: `SharedArrayBuffer` evaluate the impact this will have on other cross-origin elements on your website, such as ad placements. Check if `SharedArrayBuffer` is used by any of your third-party resources to understand impact and - guidance. + guidance. ## Cross-origin isolation overview {: #cross-origin-isolation } @@ -82,7 +82,7 @@ header or [CORS](https://developer.mozilla.org/docs/Web/HTTP/CORS) headers (`Access-Control-Allow-*` and so forth). There's also a [reporting -API](https://web.dev/coop-coep/#observe-issues-using-the-reporting-api), so you +API](https://web.dev/articles/coop-coep#observe_issues_using_the_reporting_api), so you can gather data on requests that failed as a result of `Cross-Origin-Embedder-Policy` and `Cross-Origin-Opener-Policy`. @@ -184,7 +184,7 @@ contain private data. Web standards folks got together to come up with a more complete cross-browser solution. The solution was to give pages a way to say "I hereby relinquish my ability to bring other-origin content into this process without their opt-in". -This declaration is done via [COOP and COEP headers](https://web.dev/coop-coep/) +This declaration is done via [COOP and COEP headers](https://web.dev/articles/coop-coep) served with the page. The browser enforces that, and in exchange the page gains access to `SharedArrayBuffer` and other APIs with similar powers. Other origins can opt-in to content embedding via @@ -215,8 +215,8 @@ Chrome. - [A guide to enable cross-origin isolation](https://web.dev/cross-origin-isolation-guide) -- [How to cross-origin isolate your pages](https://web.dev/coop-coep/) -- [Why cross-origin isolation is needed](https://web.dev/why-coop-coep/) +- [How to cross-origin isolate your pages](https://web.dev/articles/coop-coep) +- [Why cross-origin isolation is needed](https://web.dev/articles/why-coop-coep) Banner photo by <a href="https://unsplash.com/@yeeeeeeha?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Daniel diff --git a/site/en/blog/expanding-privacy-sandbox-testing/index.md b/site/en/blog/expanding-privacy-sandbox-testing/index.md index 67ad9cdfc..2fb9a0418 100644 --- a/site/en/blog/expanding-privacy-sandbox-testing/index.md +++ b/site/en/blog/expanding-privacy-sandbox-testing/index.md @@ -216,7 +216,7 @@ The **changes to the string are intended to be backwards-compatible**, so if you do not need those specific values then you will not be affected. However, if you do parse the user-agent string to extract the browser minor/build version, OS/platform version, or device model then you will need to [migrate to -User-Agent Client Hints](https://web.dev/migrate-to-ua-ch/). +User-Agent Client Hints](https://web.dev/articles/migrate-to-ua-ch). ## Storage partitioning diff --git a/site/en/blog/extension-instantnav/index.md b/site/en/blog/extension-instantnav/index.md index e243770ba..efc9bb651 100644 --- a/site/en/blog/extension-instantnav/index.md +++ b/site/en/blog/extension-instantnav/index.md @@ -17,7 +17,7 @@ TL;DR: The Extensions API has been updated to support back/forward cache, preloading navigations. See below for details. Chrome has been working hard at making navigation fast. Instant Navigation -technologies such as [Back/Forward Cache](https://web.dev/bfcache/) +technologies such as [Back/Forward Cache](https://web.dev/articles/bfcache) ([shipped](https://chromestatus.com/feature/6279906713403392) on desktop in Chrome 96) and [Speculation Rules](/blog/prerender-pages/) ([shipped](https://chromestatus.com/feature/5740655424831488) in Chrome 103) improve both the going back and going forward @@ -123,7 +123,7 @@ frame. However, for prerendered frames the `frameId` will be non-zero for the outermost frame. So using `frameId == 0` as a signal for determining if it is the outermost frame is incorrect. -To help with this, we introduced a new type called +To help with this, we introduced a new type called [`FrameType`](/docs/extensions/reference/extensionTypes/#type-FrameType) so determining if the frame is indeed the outermost frame is now easy. `FrameType` has the following values: diff --git a/site/en/blog/fedcm-auto-reauthn/index.md b/site/en/blog/fedcm-auto-reauthn/index.md index 1af990eeb..66203538d 100644 --- a/site/en/blog/fedcm-auto-reauthn/index.md +++ b/site/en/blog/fedcm-auto-reauthn/index.md @@ -21,13 +21,13 @@ web API for privacy-preserving identity federation. With identity federation, an RP (relying party) relies on an IdP (identity provider) to provide the user an account without requiring a new username and password. -FedCM allows the browser to understand the context in which the RP and IdP -exchange information. It informs the user about the information and privilege -levels being shared and prevents unintended abuse. FedCM has been available in +FedCM allows the browser to understand the context in which the RP and IdP +exchange information. It informs the user about the information and privilege +levels being shared and prevents unintended abuse. FedCM has been available in Chrome since version 108. -In Chrome 115, FedCM is getting support for auto-reauthentication which improves -the user experiences and enables a more streamlined reauthentication to the RP +In Chrome 115, FedCM is getting support for auto-reauthentication which improves +the user experiences and enables a more streamlined reauthentication to the RP after the initial consent. ## Auto-reauthentication {: #auto-reauthn } @@ -38,21 +38,21 @@ visit the website they need to go through the same steps in the user interface. That means the user will need to explicitly and manually re-confirm to reauthenticate and proceed with the sign-in flow. -While the explicit user experience makes sense before the user has created the -federated account to prevent tracking (which is one of the main goals of FedCM), -it is unnecessarily cumbersome after the user has gone through it once: after -the user grants permission to allow communication between the RP and the IdP, -there's no privacy or security benefit for enforcing another explicit user -confirmation for something that they have already previously acknowledged. -That's why we are introducing a more streamlined UX that RPs can choose for +While the explicit user experience makes sense before the user has created the +federated account to prevent tracking (which is one of the main goals of FedCM), +it is unnecessarily cumbersome after the user has gone through it once: after +the user grants permission to allow communication between the RP and the IdP, +there's no privacy or security benefit for enforcing another explicit user +confirmation for something that they have already previously acknowledged. +That's why we are introducing a more streamlined UX that RPs can choose for their returning users. -[FedCM -](https://github.com/fedidcg/FedCM/issues/429)[auto-reauthentication](https://github.com/fedidcg/FedCM/issues/429) -("auto-reauthn" in short) can let users reauthenticate automatically, when they -come back after their initial authentication using FedCM. "The initial -authentication" here means the user creates an account or signs into the RP's -website by tapping on the **"Continue as..."** button on FedCM's sign-in dialog +[FedCM +](https://github.com/fedidcg/FedCM/issues/429)[auto-reauthentication](https://github.com/fedidcg/FedCM/issues/429) +("auto-reauthn" in short) can let users reauthenticate automatically, when they +come back after their initial authentication using FedCM. "The initial +authentication" here means the user creates an account or signs into the RP's +website by tapping on the **"Continue as..."** button on FedCM's sign-in dialog for the first time on the same browser instance. <figure style="width: 300px; margin: auto; margin-top: 2em;"> @@ -67,10 +67,10 @@ for the first time on the same browser instance. ## Choose an option for auto-reauthn {: #mediation-options } -While we are introducing auto-reauthn to provide better UX and to align with the -specification, the default user experience will be different without any code -change. With auto-reauthn available, the browser changes its behavior depending -on the option you select in the `mediation` option developers provide with +While we are introducing auto-reauthn to provide better UX and to align with the +specification, the default user experience will be different without any code +change. With auto-reauthn available, the browser changes its behavior depending +on the option you select in the `mediation` option developers provide with `navigator.credentials.get()`. ```js @@ -85,22 +85,22 @@ const cred = await navigator.credentials.get({ }); ``` -The `mediation` is [a property in the Credential Management -API](https://developer.mozilla.org/docs/Web/API/CredentialsContainer/get#:~:text=mediation), -it behaves in [the same -way](https://web.dev/security-credential-management-retrieve-credentials/) as it -does for -[PasswordCredential](https://developer.mozilla.org/docs/Web/API/PasswordCredential) -and -[FederatedCredential](https://developer.mozilla.org/docs/Web/API/FederatedCredential) -and it's partially supported by -[PublicKeyCredential](https://developer.mozilla.org/docs/Web/API/PublicKeyCredential) +The `mediation` is [a property in the Credential Management +API](https://developer.mozilla.org/docs/Web/API/CredentialsContainer/get#:~:text=mediation), +it behaves in [the same +way](https://web.dev/articles/security-credential-management-retrieve-credentials) as it +does for +[PasswordCredential](https://developer.mozilla.org/docs/Web/API/PasswordCredential) +and +[FederatedCredential](https://developer.mozilla.org/docs/Web/API/FederatedCredential) +and it's partially supported by +[PublicKeyCredential](https://developer.mozilla.org/docs/Web/API/PublicKeyCredential) as well. The property accepts the following four values: -* `'required'`: Always requires a mediation to proceed, for example, clicking the - "Continue" button on the UI. Choose this option if your users are expected to +* `'required'`: Always requires a mediation to proceed, for example, clicking the + "Continue" button on the UI. Choose this option if your users are expected to grant permission explicitly every time they need to be authenticated. -* `'optional'`(default): Auto-reauthn if possible, requires a mediation if not. We +* `'optional'`(default): Auto-reauthn if possible, requires a mediation if not. We recommend choosing this option on the sign-in page. * `'silent'`: Auto-reauthn if possible, silently fail without requiring a mediation if not. We recommend choosing this option on the pages other than @@ -111,9 +111,9 @@ as well. The property accepts the following four values: With this call, auto-reauthn happens under the following conditions: -* FedCM is available to use. For example, the user has not [disabled FedCM +* FedCM is available to use. For example, the user has not [disabled FedCM either globally](#settings) or for the RP in the settings. -* The user used only one account with FedCM API to sign into the website on this +* The user used only one account with FedCM API to sign into the website on this browser. * The user is signed into the IdP with that account. * The auto-reauthn didn't happen within the last 10 minutes. @@ -135,12 +135,12 @@ the user starts as soon as the FedCM `navigator.credentials.get()` is invoked. ## Enforce mediation with `preventSilentAccess()` {: #prevent-silent-access } -Auto-reauthenticating users immediately after they sign out would not make for a -very good user experience. That's why FedCM has a 10-minute quiet period after -an auto-reauthn to prevent this behavior. This means that auto-reauthn happens -at most once in every 10-minutes unless the user signs back in within -10-minutes. The RP should call navigator.credentials.preventSilentAccess() to -explicitly request the browser to disable auto-reauthn when a user signs out of +Auto-reauthenticating users immediately after they sign out would not make for a +very good user experience. That's why FedCM has a 10-minute quiet period after +an auto-reauthn to prevent this behavior. This means that auto-reauthn happens +at most once in every 10-minutes unless the user signs back in within +10-minutes. The RP should call navigator.credentials.preventSilentAccess() to +explicitly request the browser to disable auto-reauthn when a user signs out of the RP explicitly, for example, by clicking a sign-out button. ```js @@ -156,12 +156,12 @@ Users can opt-out from auto-reauth from the settings menu: * On desktop Chrome, go to `chrome://password-manager/settings` > Sign in automatically. -* On Android Chrome, open **Settings** > **Password Manager** > Tap on a +* On Android Chrome, open **Settings** > **Password Manager** > Tap on a cog at the top right corner > Auto sign-in. -By disabling the toggle, the user can opt-out from auto-reauthn behavior all -together. This setting is stored and synchronized across devices, if the user is -signed into a Google account on the Chrome instance and synchronization is +By disabling the toggle, the user can opt-out from auto-reauthn behavior all +together. This setting is stored and synchronized across devices, if the user is +signed into a Google account on the Chrome instance and synchronization is enabled. {% Aside %} diff --git a/site/en/blog/first-input-delay-in-crux/index.md b/site/en/blog/first-input-delay-in-crux/index.md index 86367f355..ce8825bbf 100644 --- a/site/en/blog/first-input-delay-in-crux/index.md +++ b/site/en/blog/first-input-delay-in-crux/index.md @@ -32,7 +32,7 @@ origin trial within a separate "experimental" namespace. ## How FID is measured So what exactly is FID? Here’s how it’s defined in the -[First Input Delay](https://web.dev/fid/) +[First Input Delay](https://web.dev/articles/fid) announcement blog post: > First Input Delay (FID) measures the time from when a user first interacts @@ -63,7 +63,7 @@ demonstrate how to extract these insights from the Chrome UX Report on BigQuery. Let’s start by querying for the percent of fast FID experiences for [developers.google.com](/). We can define a fast experience as one in which FID is less than 100 ms. -Per [RAIL recommendations](https://web.dev/rail/#focus-on-the-user), +Per [RAIL recommendations](https://web.dev/articles/rail#focus_on_the_user), if the delay is 100 ms or better, it should feel instantaneous to the user. ```sql diff --git a/site/en/blog/first-party-sets-sameparty/index.md b/site/en/blog/first-party-sets-sameparty/index.md index c7477d89b..90dbdf658 100644 --- a/site/en/blog/first-party-sets-sameparty/index.md +++ b/site/en/blog/first-party-sets-sameparty/index.md @@ -4,14 +4,14 @@ title: "[OUTDATED] First-Party Sets and the SameParty attribute" description: > First-Party Sets can allow related domain names that are owned and operated by the same entity to be treated as first-party in situations where first party and - third party are otherwise treated differently. + third party are otherwise treated differently. date: 2021-08-26 updated: 2022-11-30 thumbnail: 'image/vgdbNJBYHma2o62ZqYmcnkq3j0o1/JL7L7S2qKI53pTWACfcv.jpg' alt: A diagram showing First-Party Sets. One set contains domains example.com, example.rs, and example.co.uk. The other set containts brandx.site, fly-brandx.site, and drive-brandx.site. -tags: +tags: - privacy is_outdated: true authors: @@ -26,13 +26,13 @@ First-Party Sets proposal has been updated and this article is no longer up to d Many organizations have related sites with different domain names, such as `brandx.site` and `fly-brandx.site`—or domains for different countries such as -`example.com`, `example.rs`, `example.co.uk` and so on. +`example.com`, `example.rs`, `example.co.uk` and so on. Browsers are moving towards [making third-party cookies obsolete](https://blog.google/products/ads-commerce/a-more-privacy-first-web/) to improve privacy on the web, but sites like these often rely on cookies for functionalities that require maintaining and accessing state across domains -(such as single sign-on and consent management). +(such as single sign-on and consent management). {% Img src="image/vgdbNJBYHma2o62ZqYmcnkq3j0o1/JNtmMZl7o44LwUk7mE5G.png", alt="", width="800", height="316" %} @@ -42,22 +42,22 @@ third party are otherwise treated differently. The domain names within a first-party set are considered _same-party_ and they can label which cookies are intended to be set or sent in the same-party context. The aim is to find a balance between preventing cross-site tracking by third-parties while still -maintaining a path that doesn't break valid use-cases. +maintaining a path that doesn't break valid use-cases. The First-Party Sets proposal is currently [in the testing phase](https://privacysandbox.com/timeline/), read on to find out how it works and how you can try it out. -## What is the difference between first-party and third-party cookies? +## What is the difference between first-party and third-party cookies? Cookies are not inherently first-party or third-party, it depends on the current context where the cookie is included. That's either on a request in the -``cookie`` header or via ``document.cookie`` in JavaScript. +``cookie`` header or via ``document.cookie`` in JavaScript. If for example, `video.site` has a `theme=dark` cookie, when you're browsing `video.site` and a request is made to `video.site`, that's a [same-site -context](https://web.dev/same-site-same-origin/#same-site-cross-site) and the -included cookie is _first-party_. +context](https://web.dev/articles/same-site-same-origin#same_site_cross_site) and the +included cookie is _first-party_. However, if you're on ``my-blog.site`` which embeds an iframe player for ``video.site``, when the request is made from `my-blog.site` to `video.site` @@ -68,7 +68,7 @@ that's cross-site context and the ``theme`` cookie is _third-party_. Cookie inclusion is determined by the cookie's ``SameSite`` attribute: + [**Same-site - context**](https://web.dev/same-site-same-origin/#same-site-cross-site) with + context**](https://web.dev/articles/same-site-same-origin#same_site_cross_site) with ``SameSite=Lax``, ``Strict``, or ``None`` makes the cookie **first-party**. + **Cross-site context** with ``SameSite=None`` makes the cookie **third-party**. @@ -80,11 +80,11 @@ go between these sites to select their different options—they expect their manages the user's session with a ``SameSite=None`` cookie to allow it in cross-site contexts. The downside though is now the cookie has no Cross Site Request Forgery (CSRF) protection. If ``evil.site`` includes a request to -``brandx.site`` then it would include that cookie! +``brandx.site`` then it would include that cookie! The cookie is cross-site, but all those sites are owned and operated by the same organization. Visitors also understand it's the same organization and want the -same session, in other words—a shared identity, across them. +same session, in other words—a shared identity, across them. {% Aside %} With First-Party Sets there's a route to define the situations where a @@ -100,12 +100,12 @@ within the first-party set and excluded in third-party contexts. method for **explicitly defining this relationship across multiple sites that are owned and operated by the same party**. This would enable ``brandx.site`` to define its first-party relationship with ``fly-brandx.site``, -``drive-brandx.site``, and so on. +``drive-brandx.site``, and so on. The [Privacy Model](https://github.com/michaelkleber/privacy-model) that drives the various Privacy Sandbox proposals is based on the concept of partitioning identity to prevent cross-site tracking—drawing a boundary between sites that -limits access to any information that can be used to identify users. +limits access to any information that can be used to identify users. {% Img src="image/vgdbNJBYHma2o62ZqYmcnkq3j0o1/bTGzUkmiyY1d0ZssO8Jq.png", alt="Diagram showing the unpartitioned state where the same third-party cookie is accessible in multiple cross-site contexts in contrast to a partitioned model where each top-level context has a separate instance of the cross-site cookie preventing linking activity across those sites.", width="800", height="305" %} @@ -120,21 +120,21 @@ across browsers prevents abuse or misuse. For example, First-Party Sets must not enable the exchange of user information across unrelated sites, or the grouping of sites that are not owned by the same entity. The idea is to ensure that a First-Party Set maps to something a person understands as a first-party and is -not used as a way of sharing identity across different parties. +not used as a way of sharing identity across different parties. One possible way for a site to register a first-party set could be for the site to submit their proposed group of domains to a public tracker (such as a dedicated GitHub repository) along with information needed to satisfy browser -policy. +policy. {% Aside %} The acceptance process for a new first-party set is under discussion with the W3C and one of the considered options is for verification to be handled by an -independent entity, not a browser company. +independent entity, not a browser company. {% endAside %} Once the first-party set assertion has been verified as per policy, browsers may -then fetch lists of sets via an update process. +then fetch lists of sets via an update process. The origin trial has a defined policy which is not final, but the principles are likely to remain the same: @@ -153,14 +153,14 @@ Sets](https://github.com/privacycg/first-party-sets/blob/main/ua_policy_proposal Once you identify the members and the owner of your organization's first-party set, a crucial step will be to submit your proposed set for approval. The exact -process is still under discussion. +process is still under discussion. {% Aside 'caution' %} A first-party set is _not_ meant to be an exhaustive list of sites that belong to the same organization. You _only_ need to create a set between sites if you explicitly need a cross-site cookie allowed across them. Make sure you check out [What use cases are right for the First-Party Sets -Origin Trial?](#usecases) below. +Origin Trial?](#usecases) below. {% endAside %} To declare a first-party set, static JSON resources that list members and owners @@ -168,7 +168,7 @@ should be hosted at `/.well-known/first-party-set` at the top-level of each included domain. In the example of the `brandx` first-party set, the owner-domain hosts the -following at +following at ``https://brandx.site/.well-known/first-party-set``: ```text @@ -180,7 +180,7 @@ following at ``` Each member of the set also hosts a static JSON resource pointing back to the -owner of the set. +owner of the set. At ``https://fly-brandx.site/.well-known/first-party-set`` we have: ```text @@ -213,7 +213,7 @@ affiliated sites. The matching ingredient for cookies is the proposed [``SameParty`` attribute](https://github.com/cfredric/sameparty). Specifying ``SameParty`` tells the browser to include the cookie when its context is part of the same -first-party set as the top-level context. +first-party set as the top-level context. That means that if ``brandx.site`` sets this cookie: @@ -222,7 +222,7 @@ Set-Cookie: session=123; Secure; SameSite=Lax; SameParty ``` Then when the visitor is on ``fly-brandx.site`` and a request goes to -``brandx.site`` then the ``session`` cookie will be included on that request. +``brandx.site`` then the ``session`` cookie will be included on that request. If some other site which is not a part of the first-party set, for example `hotel.xyz`, sends a request to `brandx.site`, the cookie would not be included. @@ -248,7 +248,7 @@ There are some additional requirements: ``Secure`` is mandated as this is still cross-site and you should mitigate those risks by ensuring secure (HTTPS) connections. Likewise, because this is a cross-site relationship, ``SameSite=Strict`` is invalid as it still allows for -tightly site-based CSRF protection within a set. +tightly site-based CSRF protection within a set. {% Aside 'gotchas' %} The ``SameParty`` attribute is only affecting the contexts where a @@ -266,12 +266,12 @@ that cookies are directly shared. First-Party Sets are a good match for cases when an organization needs a form of shared identity across different top-level sites. Shared identity in this case means anything from a full single sign-on solution to just needing a shared -preference across sites. +preference across sites. {% Aside %} You can identify possible candidates for these use cases because they will be instances where you have already marked a cookie as ``SameSite=None`` even -though it's only for cross-site contexts where you own all the sites involved. +though it's only for cross-site contexts where you own all the sites involved. {% endAside %} Your organization may have different top-level domains for: @@ -297,11 +297,11 @@ the discussion on the two proposals: During the testing phase, you can try the functionality using the `--use-first-party-set` command line flag and providing a comma separated list -of sites. +of sites. You can try this on the demo site at [https://fps-member1.glitch.me/](https://fps-member1.glitch.me/) after starting -Chrome with the following flag: +Chrome with the following flag: ```text --use-first-party-set=https://fps-member1.glitch.me,https://fps-member2.glitch.me,https://fps-member3.glitch.me @@ -309,12 +309,12 @@ Chrome with the following flag: This is helpful if you want to test in your development environment, or want to try adding the `SameParty` attribute in a live environment to see how a -first-party set would affect the cookies. +first-party set would affect the cookies. If you have the bandwidth for experimentation and feedback, you can also sign up for the [Origin Trial for First Party Sets and SameParty](/origintrials/#/view_trial/988540118207823873) -which is available in Chrome from version 89 to 93. +which is available in Chrome from version 89 to 93. {% Aside 'key-term' %} Origin trials are Chrome's way of enabling external developers to test @@ -327,46 +327,46 @@ trials](/blog/origin-trials/). ## How to update cookies for the origin trial If you are joining the origin trial and testing the `SameParty` attribute on -your cookies, here are two patterns to consider. +your cookies, here are two patterns to consider. ### Option 1 First, where you have cookies that you have labelled as `SameSite=None` but you would like to restrict to first-party contexts, you can add the `SameParty` attribute to them. In browsers where the origin trial is active, the cookie will -not be sent in cross-site contexts outside the set. +not be sent in cross-site contexts outside the set. However, for the majority of browsers outside of the origin trial the cookie will continue to be sent -cross-site as usual. Consider this as a progressive enhancement approach. +cross-site as usual. Consider this as a progressive enhancement approach. -**Before:** -`set-cookie: cname=cval; SameSite=None; Secure` +**Before:** +`set-cookie: cname=cval; SameSite=None; Secure` -**After:** -`set-cookie: cname=cval; SameSite=None; Secure; SameParty` +**After:** +`set-cookie: cname=cval; SameSite=None; Secure; SameParty` ### Option 2 The second option is more work, but allows you to fully separate the origin trial from existing functionality and specifically allows testing of the -`SameSite=Lax; SameParty` combination. +`SameSite=Lax; SameParty` combination. -**Before:** -`set-cookie: cname=cval; SameSite=None; Secure` +**Before:** +`set-cookie: cname=cval; SameSite=None; Secure` -**After:** +**After:** ```text set-cookie: cname=cval; SameSite=None; Secure -set-cookie: cname-fps=cval; SameSite=Lax; Secure; SameParty +set-cookie: cname-fps=cval; SameSite=Lax; Secure; SameParty ``` When checking for the cookie on incoming requests, you should only expect to see the `cname-fps` cookie on a cross-site request if the sites involved are in the set and the browser is in the origin trial. Consider this approach like a concurrent launch of an updated feature before turning down the previous -version. +version. ## Why might you not need a first-party set? @@ -394,4 +394,4 @@ a set: smoother sign-in experience for users. It's a valid use case, but it's not suitable for First-Party Sets as there's a clear difference in organizations. Early proposals like [WebID](https://github.com/WICG/WebID) are - exploring ways to enable these use cases. + exploring ways to enable these use cases. diff --git a/site/en/blog/fledge-api/index.md b/site/en/blog/fledge-api/index.md index aa3560655..db47994d0 100644 --- a/site/en/blog/fledge-api/index.md +++ b/site/en/blog/fledge-api/index.md @@ -5,7 +5,7 @@ authors: - samdutton - kevinkiklee description: > - Protected Audience API is a Privacy Sandbox proposal to serve remarketing and custom audience use cases, designed so it cannot be used by third parties to track user browsing behavior across sites. + Protected Audience API is a Privacy Sandbox proposal to serve remarketing and custom audience use cases, designed so it cannot be used by third parties to track user browsing behavior across sites. date: 2022-01-27 updated: 2022-08-24 thumbnail: image/80mq7dk16vVEg8BBhsVe42n6zn82/UiyBX61nCLHExFoy0eEn.jpg @@ -68,7 +68,7 @@ The diagram below provides an overview of the FLEDGE lifecycle: A walkthrough of a basic Protected Audience deployment across advertiser and publisher sites is available at [protected-audience-demo.web.app](https://protected-audience-demo.web.app/). - + The [demo video](https://www.youtube.com/watch?v=znDD0gkdJyM&list=PLNYkxOF6rcICntazGfSVKSj5EwuR9w5Nv) explains how the demo code works, and shows how to use Chrome DevTools for Protected Audience debugging. @@ -204,9 +204,9 @@ As part of a Protected Audience ad auction, the browser can access a that returns simple key-value pairs to provide information to an ad buyer, such as remaining campaign budget. The Protected Audience proposal [mandates](https://github.com/WICG/turtledove/blob/main/FLEDGE.md#design-elements) that this server "performs no event-level logging and has no other side effects based on these -requests". +requests". -The Protected Audience Key/Value service code is now available in a [Privacy Sandbox GitHub repository](https://github.com/privacysandbox/fledge-key-value-service). This service can be used by Chrome and Android developers. Check out the [announcement blog post](/blog/open-sourcing-fledge-key-value-service/) for the status update. Learn more about the Protected Audience Key/Value service from the [API explainer](https://github.com/WICG/turtledove/blob/main/FLEDGE_Key_Value_Server_API.md) and the [trust model explainer](https://github.com/privacysandbox/fledge-docs/blob/main/key_value_service_trust_model.md). +The Protected Audience Key/Value service code is now available in a [Privacy Sandbox GitHub repository](https://github.com/privacysandbox/fledge-key-value-service). This service can be used by Chrome and Android developers. Check out the [announcement blog post](/blog/open-sourcing-fledge-key-value-service/) for the status update. Learn more about the Protected Audience Key/Value service from the [API explainer](https://github.com/WICG/turtledove/blob/main/FLEDGE_Key_Value_Server_API.md) and the [trust model explainer](https://github.com/privacysandbox/fledge-docs/blob/main/key_value_service_trust_model.md). For initial testing, ["Bring Your Own Server"](https://github.com/WICG/turtledove/blob/main/FLEDGE.md#3-buyers-provide-ads-and-bidding-functions-byos-for-now) model is used. In the long-term, adtechs will need to use the open-source Protected Audience Key/Value services running in [trusted execution environments](https://github.com/privacysandbox/fledge-docs/blob/main/trusted_services_overview.md#trusted-execution-environment) for retrieving real-time data. @@ -465,7 +465,7 @@ days. Successive calls overwrite previously stored values. {% Aside 'gotchas' %} All URLs used as parameters for Protected Audience API methods must be from secure origins: all resources must -be served over HTTPS URLs. [How to use HTTPS for local development](https://web.dev/how-to-use-local-https/) +be served over HTTPS URLs. [How to use HTTPS for local development](https://web.dev/articles/how-to-use-local-https) explains how to do this when running Protected Audience locally. In addition, `biddingLogicUrl`, `decisionLogicUrl`, and `trustedBiddingSignals` all require an @@ -1303,5 +1303,5 @@ explains the demo code, and shows how to use Chrome DevTools for Protected Audie - [Intent to prototype](https://groups.google.com/a/chromium.org/g/blink-dev/c/w9hm8eQCmNI) <hr> - + Photo by [Ray Hennessy](https://unsplash.com/@rayhennessy) on [Unsplash](https://unsplash.com/photos/GL6ORxDMswI). diff --git a/site/en/blog/floc/index.md b/site/en/blog/floc/index.md index f7ca1f359..4cee25f44 100644 --- a/site/en/blog/floc/index.md +++ b/site/en/blog/floc/index.md @@ -15,30 +15,30 @@ tags: --- {% Aside 'warning' %} -The origin trial for the initial version of FLoC ran from Chrome 89 to 91 and +The origin trial for the initial version of FLoC ran from Chrome 89 to 91 and [is now closed](/origintrials/#/view_trial/213920982300098561). -This post refers to the API implemented in Chrome for the first origin trial of FLoC. +This post refers to the API implemented in Chrome for the first origin trial of FLoC. -Future iterations of an API to enable interest-based advertising without third-party cookies +Future iterations of an API to enable interest-based advertising without third-party cookies or other cross-site tracking mechanisms are currently in development. {% endAside %} -Federated Learning of Cohorts (FLoC) provides a privacy-preserving mechanism for interest-based ad -selection. As a user moves around the web, their browser uses the FLoC algorithm to work out its -"interest cohort", which will be the same for thousands of browsers with a similar recent browsing -history. The user's browser is associated with one interest cohort at a time and recalculates its -cohort periodically (currently once every seven days during this initial origin trial) on -the user's device, without sharing individual browsing data with the browser vendor or anyone else. +Federated Learning of Cohorts (FLoC) provides a privacy-preserving mechanism for interest-based ad +selection. As a user moves around the web, their browser uses the FLoC algorithm to work out its +"interest cohort", which will be the same for thousands of browsers with a similar recent browsing +history. The user's browser is associated with one interest cohort at a time and recalculates its +cohort periodically (currently once every seven days during this initial origin trial) on +the user's device, without sharing individual browsing data with the browser vendor or anyone else. {% Aside %} -During the initial FLoC trial, a page visit was only included in the browser's FLoC computation -for one of two reasons: -* The FLoC API (`document.interestCohort()`) is used on the page. -* Chrome detects that the page [loads ads or ads-related resources](https://github.com/WICG/floc/issues/82). +During the initial FLoC trial, a page visit was only included in the browser's FLoC computation +for one of two reasons: +* The FLoC API (`document.interestCohort()`) is used on the page. +* Chrome detects that the page [loads ads or ads-related resources](https://github.com/WICG/floc/issues/82). -For other clustering algorithms, a trial might experiment with different inclusion criteria: that's +For other clustering algorithms, a trial might experiment with different inclusion criteria: that's part of the origin trial experiment process. {% endAside %} @@ -46,12 +46,12 @@ To find out more about FLoC, see [What is Federated Learning of Cohorts?](https: ## Take part in a FLoC origin trial -An origin trial for FLoC started in Chrome 89, and has been made available as a [third-party origin trial](https://web.dev/third-party-origin-trials/). +An origin trial for FLoC started in Chrome 89, and has been made available as a [third-party origin trial](https://web.dev/articles/third-party-origin-trials). To take part, you will need to [register](/origintrials/#/view_trial/213920982300098561) for a FLoC origin trial token. {% Aside %} -The initial testing of FLoC is taking place with a [small percentage of users](https://blog.google/products/chrome/privacy-sustainability-and-the-importance-of-and/#jump-content:~:text=The%20initial%20testing%20of%20FLoC%20is%20taking%20place%20with%20a%20small%20percentage%20of%20users), and FLoC is subject to [origin trial usage limits](https://github.com/GoogleChrome/OriginTrials/blob/gh-pages/developer-guide.md#19-are-there-any-usage-limits-on-experimental-features). This means that initially during the +The initial testing of FLoC is taking place with a [small percentage of users](https://blog.google/products/chrome/privacy-sustainability-and-the-importance-of-and/#jump-content:~:text=The%20initial%20testing%20of%20FLoC%20is%20taking%20place%20with%20a%20small%20percentage%20of%20users), and FLoC is subject to [origin trial usage limits](https://github.com/GoogleChrome/OriginTrials/blob/gh-pages/developer-guide.md#19-are-there-any-usage-limits-on-experimental-features). This means that initially during the current trial you will only be able to access the user's cohort (with `document.interestCohort()`) for a small proportion of visits to pages on your site that include your origin trial token. Alternatively, you can test the FLoC API locally by [setting browser flags](#enable-floc-with-browser-flags). {% endAside %} @@ -60,34 +60,34 @@ current trial you will only be able to access the user's cohort (with `document. To access interest cohort data on your own site(s), add the origin trial token to your web pages, using one of the following methods: -+ As a meta tag in the <head> of each page served: - ++ As a meta tag in the <head> of each page served: + `<meta http-equiv="origin-trial" content="TOKEN_GOES_HERE">` -+ As an HTTP header: - ++ As an HTTP header: + `Origin-Trial: TOKEN_GOES_HERE` With this in place, you can try out FLoC in a first-party context: for example, to observe cohorts for visitors to your site(s). ### Third-party context -You will need to inject the origin trial token in a meta tag in order to test the FLoC API in your code on third-party sites. [Origin Trials Guide for Web Developers](https://github.com/GoogleChrome/OriginTrials/blob/gh-pages/developer-guide.md#16-can-i-provide-tokens-by-running-script) explains how to do this. +You will need to inject the origin trial token in a meta tag in order to test the FLoC API in your code on third-party sites. [Origin Trials Guide for Web Developers](https://github.com/GoogleChrome/OriginTrials/blob/gh-pages/developer-guide.md#16-can-i-provide-tokens-by-running-script) explains how to do this. ### Submit feedback -Do this through Chrome's [origin trial site](/origintrials/#/trials/active). This feedback is not public and is available only to a limited group of people on the Chrome team. +Do this through Chrome's [origin trial site](/origintrials/#/trials/active). This feedback is not public and is available only to a limited group of people on the Chrome team. When your token expires, you will get an email with a renewal link. Before renewing the token, you are again asked to submit feedback. ## Try out FLoC as a web developer -There are two ways to try out FLoC: +There are two ways to try out FLoC: * Enable FLoC for your browser by setting browser flags. * Use a browser that is included in the origin trial. ### Enable FLoC with browser flags -The FLoC API is very simple: just a single method that returns a promise which resolves to an object providing the cohort `id` and `version`: +The FLoC API is very simple: just a single method that returns a promise which resolves to an object providing the cohort `id` and `version`: ``` js document.interestCohort() @@ -102,25 +102,25 @@ The cohort data made available looks like this: } ``` -The FLoC API is available in Chrome 89 and above, but if your browser is not included in the origin -trial, you will need to run Chrome with flags in order to try out the API. [Run Chromium with flags](http://www.chromium.org/developers/how-tos/run-chromium-with-flags) explains how to do this for different operating systems. +The FLoC API is available in Chrome 89 and above, but if your browser is not included in the origin +trial, you will need to run Chrome with flags in order to try out the API. [Run Chromium with flags](http://www.chromium.org/developers/how-tos/run-chromium-with-flags) explains how to do this for different operating systems. -1. Start Chrome with the following flags. Make sure to copy all the text!<br> <br> +1. Start Chrome with the following flags. Make sure to copy all the text!<br> <br> ``` text - --enable-blink-features=InterestCohortAPI + --enable-blink-features=InterestCohortAPI --enable-features="FederatedLearningOfCohorts:update_interval/10s/minimum_history_domain_size_required/1,FlocIdSortingLshBasedComputation,InterestCohortFeaturePolicy" ``` <br> - The `FlocPagesWithAdResourcesDefaultIncludedInFlocComputation` flag can also be included, to - re-create the FLoC algorithm from the initial origin trial (the default value otherwise is + The `FlocPagesWithAdResourcesDefaultIncludedInFlocComputation` flag can also be included, to + re-create the FLoC algorithm from the initial origin trial (the default value otherwise is `false`). - + <br> 1. Check that third-party cookies are not blocked and that no ad blocker is running. -1. View the demo at [floc.glitch.me](https://floc.glitch.me/) or run the following code from the +1. View the demo at [floc.glitch.me](https://floc.glitch.me/) or run the following code from the DevTools console:<br><br> ``` js @@ -130,15 +130,15 @@ DevTools console:<br><br> #### What do the experimental flags mean? * `InterestCohortAPI` enables FLoC. -* `update_interval/10s` sets the cohort to be recalculated every 10 seconds. This is only to enable +* `update_interval/10s` sets the cohort to be recalculated every 10 seconds. This is only to enable testing; the cohort recalculation interval currently defaults otherwise to every seven days. -* `minimum_history_domain_size_required/1` specifies the minimum number of domains that must be -available in order for the cohort to be computed. The value here is for testing only and normally +* `minimum_history_domain_size_required/1` specifies the minimum number of domains that must be +available in order for the cohort to be computed. The value here is for testing only and normally would be higher. * `FlocIdSortingLshBasedComputation` sets the clustering algorithm used by FLoC. * `InterestCohortFeaturePolicy` enables the availability of the [Permissions-Policy header for FLoC](#how-can-websites-opt-out-of-the-floc-computation). -* It is also possible to [set the FLoC version](https://github.com/WICG/floc/issues/90#issuecomment-814389410) -by using a value such as `"FederatedLearningOfCohorts:finch_config_version/2"`. +* It is also possible to [set the FLoC version](https://github.com/WICG/floc/issues/90#issuecomment-814389410) +by using a value such as `"FederatedLearningOfCohorts:finch_config_version/2"`. You can view FLoC flag code in [Chromium Code Search](https://source.chromium.org/chromium/chromium/src/+/master:components/federated_learning/features/features.cc?q=minimum_history_domain_size_required&ss=chromium). @@ -150,17 +150,17 @@ The codebase for Chrome has two different lists of features: You have to use the correct flag depending on which list your feature is in (though some are in both!) -[Blink features](https://source.chromium.org/chromium/chromium/src/+/master:third_party/blink/renderer/platform/runtime_enabled_features.json5;l=108?q=runtime_enabled_features.json5%20&ss=chromium) with `status=experimental` -can also be enabled by using the Experimental Web Platform features flag in Chrome: +[Blink features](https://source.chromium.org/chromium/chromium/src/+/master:third_party/blink/renderer/platform/runtime_enabled_features.json5;l=108?q=runtime_enabled_features.json5%20&ss=chromium) with `status=experimental` +can also be enabled by using the Experimental Web Platform features flag in Chrome: chrome://flags/#enable-experimental-web-platform-features. {% endAside %} ### Check if your browser is included in the origin trial -During the origin trial, FLoC is enabled by default for [a small percentage of browsers](https://blog.google/products/chrome/privacy-sustainability-and-the-importance-of-and/#jump-content:~:text=The%20initial%20testing%20of%20FLoC). -For these browsers, the FLoC API is made available without requiring flags to be set. You can check -if your browser is included in the trial by trying out one of the two demos below. Each of these +During the origin trial, FLoC is enabled by default for [a small percentage of browsers](https://blog.google/products/chrome/privacy-sustainability-and-the-importance-of-and/#jump-content:~:text=The%20initial%20testing%20of%20FLoC). +For these browsers, the FLoC API is made available without requiring flags to be set. You can check +if your browser is included in the trial by trying out one of the two demos below. Each of these uses a different method to provide an origin trial token. * Meta tag: [floc-ot-meta.glitch.me](https://floc-ot-meta.glitch.me) @@ -169,14 +169,14 @@ uses a different method to provide an origin trial token. ## Try out FLoC as a publisher, advertiser or adtech platform -The [FLoC API explainer](https://github.com/WICG/floc) suggests use cases, but does not define how the API should be used. Different sites and services will have different constraints and requirements for using FLoC to provide relevant content and ads. - -If you manage your own technology for content recommendations, advertising or marketing services then you could apply your FLoC insights to tailor content or marketing messages to specific cohorts. If you rely on third party companies to provide these services then it might make more sense for them to join the origin trial and run experiments including your site and other sites. - +The [FLoC API explainer](https://github.com/WICG/floc) suggests use cases, but does not define how the API should be used. Different sites and services will have different constraints and requirements for using FLoC to provide relevant content and ads. + +If you manage your own technology for content recommendations, advertising or marketing services then you could apply your FLoC insights to tailor content or marketing messages to specific cohorts. If you rely on third party companies to provide these services then it might make more sense for them to join the origin trial and run experiments including your site and other sites. + As an example, for a publisher finding ways to select relevant content, the process of trying out FLoC during the origin trial might work something like this: 1. Collect data about site usage and cohort IDs. -1. Analyze the data for correlations. Use the data to select relevant content. +1. Analyze the data for correlations. Use the data to select relevant content. 1. Compare the FLoC approach against other mechanisms. Did it work the way you expect it? 1. Adjust the use of FLoC to select content. 1. Provide origin trial feedback. @@ -185,37 +185,37 @@ As an example, for a publisher finding ways to select relevant content, the proc ## How can websites opt out of the FLoC computation? -A site should be able to declare that it does not want to be included in the user's list of sites for cohort calculation. A new `interest-cohort` [permissions policy](/docs/privacy-sandbox/permissions-policy/) enables this. The policy will be `allow` by default. +A site should be able to declare that it does not want to be included in the user's list of sites for cohort calculation. A new `interest-cohort` [permissions policy](/docs/privacy-sandbox/permissions-policy/) enables this. The policy will be `allow` by default. -For any frame that is _not_ allowed `interest-cohort` permission, the promise returned when it calls `document.interestCohort()` will reject. If the main frame does not have `interest-cohort` permission then the page visit will not be included in interest cohort calculation. +For any frame that is _not_ allowed `interest-cohort` permission, the promise returned when it calls `document.interestCohort()` will reject. If the main frame does not have `interest-cohort` permission then the page visit will not be included in interest cohort calculation. -For example, a site can opt out of all FLoC cohort calculation by sending the HTTP response header: +For example, a site can opt out of all FLoC cohort calculation by sending the HTTP response header: ``` text Permissions-Policy: interest-cohort=() -``` +``` -During the FLoC origin trial, pages on websites that don't opt out will be included in the FLoC -calculation if Chrome detects that they load [ads-related resources](https://chromium.googlesource.com/chromium/src/+/master/docs/ad_tagging.md) or if they use `document.interestCohort()`. Pages served from private IP addresses, +During the FLoC origin trial, pages on websites that don't opt out will be included in the FLoC +calculation if Chrome detects that they load [ads-related resources](https://chromium.googlesource.com/chromium/src/+/master/docs/ad_tagging.md) or if they use `document.interestCohort()`. Pages served from private IP addresses, such as intranet pages, won't be part of the FLoC computation. -{% Aside %} -[Ad Tagging in Chromium](https://chromium.googlesource.com/chromium/src/+/master/docs/ad_tagging.md) explains how Chrome's ad detection mechanism works. +{% Aside %} +[Ad Tagging in Chromium](https://chromium.googlesource.com/chromium/src/+/master/docs/ad_tagging.md) explains how Chrome's ad detection mechanism works. {% endAside %} ### Why are pages that have ads or ads-related resources included in FLoC cohort computation during the initial origin trial? -Origin trials give developers a chance to see what a new API proposal would be like *if* it were -launched. For FLoC, how can we enable the API to be evaluated realistically before it has wide -adoption? For the small-scale origin trial experiment, Chrome chose to make the assumption that -every page which uses ads would use FLoC. This is unlikely to be completely realistic, but is the +Origin trials give developers a chance to see what a new API proposal would be like *if* it were +launched. For FLoC, how can we enable the API to be evaluated realistically before it has wide +adoption? For the small-scale origin trial experiment, Chrome chose to make the assumption that +every page which uses ads would use FLoC. This is unlikely to be completely realistic, but is the most plausible heuristic available. ## Find out more + [What is Federated Learning of Cohorts (FLoC)?](web.dev/floc) -+ [Getting started with Chrome's origin trials](https://web.dev/origin-trials/): a basic overview. ++ [Getting started with Chrome's origin trials](/docs/web-platform/origin-trials/): a basic overview. + [Origin trials guide for web developers](https://github.com/GoogleChrome/OriginTrials/blob/gh-pages/developer-guide.md): additional technical detail and an extensive FAQ. + [Origin trial explainer](https://github.com/GoogleChrome/OriginTrials/blob/gh-pages/explainer.md): motivations and design for origin trial provision, with an extensive FAQ. + [Running an origin trial](https://www.chromium.org/blink/origin-trials/running-an-origin-trial): technical detail from a Chrome and Chromium perspective. diff --git a/site/en/blog/framework-fund-2022/index.md b/site/en/blog/framework-fund-2022/index.md index 8f7b2d315..058110b0c 100644 --- a/site/en/blog/framework-fund-2022/index.md +++ b/site/en/blog/framework-fund-2022/index.md @@ -58,6 +58,6 @@ Sponsoring these projects not only help support their mission to enable develope As always, we remain open to considering sponsoring more efforts towards the fund's goals in the future. If you are interested in submitting ideas for future funding, feel free to send over your ideas via our [submission form](https://forms.gle/BbshCNVaDFK7NJoU6) and we'll consider them. -As a reminder, we recently also expanded Chrome's sponsorship efforts to include a new [CSS & UI Fund](https://web.dev/ui-fund/) and an [Advanced Web Apps fund](/blog/advanced-web-apps-fund/) If you are interested in submitting sponsorship requests to these efforts, they are still open to reviewing entries. +As a reminder, we recently also expanded Chrome's sponsorship efforts to include a new [CSS & UI Fund](https://web.dev/articles/ui-fund) and an [Advanced Web Apps fund](/blog/advanced-web-apps-fund/) If you are interested in submitting sponsorship requests to these efforts, they are still open to reviewing entries. Thanks once again to the projects receiving sponsorship for everything they do to move the web forward! diff --git a/site/en/blog/framework-tools-font-fallback/index.md b/site/en/blog/framework-tools-font-fallback/index.md index 26767b9ee..0d2af0c2d 100644 --- a/site/en/blog/framework-tools-font-fallback/index.md +++ b/site/en/blog/framework-tools-font-fallback/index.md @@ -1,7 +1,7 @@ --- layout: 'layouts/blog-post.njk' title: Framework tools for font fallbacks -description: +description: Learn how Next.js, Nuxt.js, and other libraries help to generate fallback font CSS without CLS. date: 2023-02-27 authors: @@ -14,18 +14,18 @@ tags: - aurora-project --- -Sites that load fonts with _font-display: swap_ often suffer from a layout shift ([CLS](https://web.dev/cls/)) when the web font loads and is swapped with the fallback font. +Sites that load fonts with _font-display: swap_ often suffer from a layout shift ([CLS](https://web.dev/articles/cls)) when the web font loads and is swapped with the fallback font. You can prevent CLS by adjusting the dimensions of the fallback font to match that of the primary font. Properties such as `size-adjust`, `ascent-override`, `descent-override`, and `line-gap-override` in the [`@font-face`](https://developer.mozilla.org/docs/Web/CSS/@font-face) rule can help override the metrics of a fallback font allowing developers more control over how fonts are displayed. You can read more about font-fallbacks and the override properties in this [post](/blog/font-fallbacks/). You can also see a working implementation of this technique in this [demo](https://cultured-rightful-check.glitch.me). -This article explores how font size adjustments are implemented in the Next.js and Nuxt.js frameworks to generate the fallback font CSS and reduce the CLS. It also demonstrates how you can generate fallback fonts using cross-cutting tools such as Fontaine and Capsize. +This article explores how font size adjustments are implemented in the Next.js and Nuxt.js frameworks to generate the fallback font CSS and reduce the CLS. It also demonstrates how you can generate fallback fonts using cross-cutting tools such as Fontaine and Capsize. ## Background _[font-display: swap](/blog/font-display/#swap)_ is generally used to prevent FOIT (Flash of invisible text) and to display contents faster on the screen. The value of `swap` tells the browser that text using the font should be displayed immediately using a system font and to replace the system font only when the custom font is ready. -The biggest issue with `swap` is the jarring effect, where the difference in character sizes of the two fonts results in screen content shifting around. This leads to poor CLS scores, especially for text-heavy websites. +The biggest issue with `swap` is the jarring effect, where the difference in character sizes of the two fonts results in screen content shifting around. This leads to poor CLS scores, especially for text-heavy websites. The following images show an example of the issue. The first image uses `font-display: swap` with no attempt to adjust the size of the fallback font. The second shows how adjusting the size using the CSS `@font-face` rule improves the loading experience. @@ -66,14 +66,14 @@ body { </figure> -Adjusting the size of the fallback font can be an effective strategy for preventing font loading layout shift, but implementing the logic from scratch can be tricky, as described in [this post about font fallbacks](/blog/font-fallbacks/). Fortunately, several tooling options are already available to make this easier while developing apps. +Adjusting the size of the fallback font can be an effective strategy for preventing font loading layout shift, but implementing the logic from scratch can be tricky, as described in [this post about font fallbacks](/blog/font-fallbacks/). Fortunately, several tooling options are already available to make this easier while developing apps. ## How to optimize font fallbacks with Next.js Next.js provides a built-in way to enable fallback font optimization. This feature is enabled by default when you load fonts using the [@next/font](https://nextjs.org/docs/api-reference/next/font) component. -The [@next/font](https://nextjs.org/docs/api-reference/next/font) component was introduced in Next.js version 13. The component provides an API to import Google Fonts or custom fonts into your pages and includes built-in automatic self-hosting of font files. +The [@next/font](https://nextjs.org/docs/api-reference/next/font) component was introduced in Next.js version 13. The component provides an API to import Google Fonts or custom fonts into your pages and includes built-in automatic self-hosting of font files. When used, the fallback font metrics are automatically calculated and injected into the CSS file. @@ -94,7 +94,7 @@ body { To migrate to next/font: -1. Move the Roboto font declaration into your Javascript by importing the 'Roboto' function from 'next/font'. The function’s return value will be a class name you can leverage in your component template. +1. Move the Roboto font declaration into your Javascript by importing the 'Roboto' function from 'next/font'. The function’s return value will be a class name you can leverage in your component template. Remember to add `display: swap` to the configuration object to enable the feature. ```javascript @@ -107,7 +107,7 @@ Remember to add `display: swap` to the configuration object to enable the featur }) ``` -2. In your component, use the generated class name: +2. In your component, use the generated class name: ```javascript export default function RootLayout({ children }: { children: React.ReactNode; @@ -153,7 +153,7 @@ module.exports = { **Note**: There is no plan to support this feature with the newly introduced `app` dir. In the long term, it’s ideal to use `next/font`. -## How to adjust font fallbacks with Nuxt +## How to adjust font fallbacks with Nuxt [@nuxtjs/fontaine](https://github.com/nuxt-modules/fontaine) is a module for the Nuxt.js framework that automatically calculates the fallback font metric values and generates the fallback `@font-face` CSS. @@ -215,7 +215,7 @@ You can now use `Roboto override` as the fallback font in your CSS, as shown in ## Generating the CSS yourself -Standalone libraries can also help you generate the CSS for fallback font size adjustments. +Standalone libraries can also help you generate the CSS for fallback font size adjustments. ### Using Fontaine library @@ -246,7 +246,7 @@ const options = { } ``` -If you're using Vite, add the plugin like this: +If you're using Vite, add the plugin like this: ```javascript // Vite export default { @@ -308,13 +308,13 @@ Consider the following example: The desired web font is Lobster, falling back to -1. Import createFontStack from the core package: +1. Import createFontStack from the core package: ```javascript import { createFontStack } from '@capsizecss/core'; ``` -2. Import the font metrics for each of the desired fonts (see Font Metrics above): +2. Import the font metrics for each of the desired fonts (see Font Metrics above): ```javascript import lobster from '@capsizecss/metrics/lobster'; import helveticaNeue from '@capsizecss/metrics/helveticaNeue'; @@ -322,9 +322,9 @@ Consider the following example: The desired web font is Lobster, falling back to ``` -3. Create your font stack, passing the metrics as an array, using the same order as you would via the font-family CSS property. +3. Create your font stack, passing the metrics as an array, using the same order as you would via the font-family CSS property. ```javascript - const { fontFamily, fontFaces } = createFontStack([ + const { fontFamily, fontFaces } = createFontStack([ lobster, helveticaNeue, arial, diff --git a/site/en/blog/fresher-sw/index.md b/site/en/blog/fresher-sw/index.md index c74e85361..8c6528b27 100644 --- a/site/en/blog/fresher-sw/index.md +++ b/site/en/blog/fresher-sw/index.md @@ -19,7 +19,7 @@ scripts starting in Chrome 78. ## tl;dr Starting in Chrome 68, HTTP requests that check for updates to the service worker script will no -longer be fulfilled by the [HTTP cache](https://web.dev/http-cache/) +longer be fulfilled by the [HTTP cache](https://web.dev/articles/http-cache) by default. This works around a [common developer pain point](https://developers.google.com/web/tools/workbox/guides/service-worker-checklist#cache-control_of_your_service_worker_file), in which setting an inadvertent `Cache-Control` header on your service worker script could lead to delayed updates. diff --git a/site/en/blog/fugu-status/index.md b/site/en/blog/fugu-status/index.md index a655c144e..520a82c5b 100644 --- a/site/en/blog/fugu-status/index.md +++ b/site/en/blog/fugu-status/index.md @@ -21,9 +21,9 @@ capabilities of these platforms to the web platform, while maintaining user security, privacy, trust, and other core tenets of the web. This work, among many other examples, allowed -[Adobe to bring Photoshop to the web](https://web.dev/ps-on-the-web/), -[Excalidraw to deprecate their Electron app](https://web.dev/deprecating-excalidraw-electron/), and -[Betty Crocker to increase purchase intent indicators by 300%](https://web.dev/betty-crocker/). +[Adobe to bring Photoshop to the web](https://web.dev/articles/ps-on-the-web), +[Excalidraw to deprecate their Electron app](https://web.dev/articles/deprecating-excalidraw-electron), and +[Betty Crocker to increase purchase intent indicators by 300%](https://web.dev/articles/betty-crocker). {% Aside %} Be sure to try out some of the apps the community has built with Fugu APIs diff --git a/site/en/blog/getting-gmail-to-handle-all-mailto-links-with-registerprotocolhandler/index.md b/site/en/blog/getting-gmail-to-handle-all-mailto-links-with-registerprotocolhandler/index.md index 39ce1ca5b..19a6e40a2 100644 --- a/site/en/blog/getting-gmail-to-handle-all-mailto-links-with-registerprotocolhandler/index.md +++ b/site/en/blog/getting-gmail-to-handle-all-mailto-links-with-registerprotocolhandler/index.md @@ -12,7 +12,7 @@ updated: 2019-02-01 If you use Gmail you may become frustrated when you click a `mailto:` link by accident and now your desktop client of Outlook or Mail starts up. -Thanks to `navigator.registerProtocolHandler()` ([which we've covered here before](https://web.dev/registering-a-custom-protocol-handler/)) you can wire up Gmail as your default mail client for all `mailto:` links in Chrome and Firefox. +Thanks to `navigator.registerProtocolHandler()` ([which we've covered here before](https://web.dev/articles/registering-a-custom-protocol-handler)) you can wire up Gmail as your default mail client for all `mailto:` links in Chrome and Firefox. <figure> {% Img src="image/T4FyVKpzu4WKF1kBNvXepbi08t52/klFjlPW7hK25xwqKofQR.jpg", alt="Use Gmail popup screenshot", width="640", height="185" %} diff --git a/site/en/blog/getting-started-pwa/index.md b/site/en/blog/getting-started-pwa/index.md index 964bd97ed..82865da3b 100644 --- a/site/en/blog/getting-started-pwa/index.md +++ b/site/en/blog/getting-started-pwa/index.md @@ -81,7 +81,7 @@ The Manifest for Web applications is a simple JSON file that gives you, the deve The manifest enables your web app to have a more native-like presence on the user's home screen. It allows the app to be launched in full-screen mode (without a URL bar being present), provides control over the screen orientation and in recent -versions of Chrome on Android supports defining a [Splash Screen](https://web.dev/add-manifest/#splash-screen) and +versions of Chrome on Android supports defining a [Splash Screen](https://web.dev/articles/add-manifest#splash_screen) and [theme color](/blog/support-for-theme-color-in-chrome-39-for-android) for the address bar. It is also used to define a set of icons by size and density used for the aforementioned Splash screen and home screen icon. diff --git a/site/en/blog/heavy-ad-interventions/index.md b/site/en/blog/heavy-ad-interventions/index.md index 135f1a6ff..88aa64a7a 100644 --- a/site/en/blog/heavy-ad-interventions/index.md +++ b/site/en/blog/heavy-ad-interventions/index.md @@ -214,7 +214,7 @@ is only best-effort by the browser not a guarantee. {% Aside 'caution' %} [**Do not use** the `unload` and `beforeunload` -events](https://web.dev/bfcache/#never-use-the-unload-event) here. This will +events](https://web.dev/articles/bfcache#never_use_the_unload_event) here. This will actively hurt your page caching and performance across multiple browsers. {% endAside %} @@ -243,7 +243,7 @@ request: Ad content is just web content, so make use of tools like [Lighthouse](/docs/lighthouse/overview/) to audit the overall performance of your content. The resulting audits provide inline guidance on improvements. You can -also refer to the [web.dev/fast](https://web.dev/fast/) collection. +also refer to the [web.dev/fast](https://web.dev/articles/fast) collection. You may find it helpful to test your ad in a more isolated context. You can use the custom URL option on https://heavy-ads.glitch.me to test this with a diff --git a/site/en/blog/help-css-nesting/index.md b/site/en/blog/help-css-nesting/index.md index 38ff24d14..3eed74d4e 100644 --- a/site/en/blog/help-css-nesting/index.md +++ b/site/en/blog/help-css-nesting/index.md @@ -81,7 +81,7 @@ nesting workflows. This would be disruptive and inconsiderate to those ecosystems and communities. <br> -1. <b>Waiting for [`:is()`](https://web.dev/css-is-and-where/)</b> +1. <b>Waiting for [`:is()`](https://web.dev/articles/css-is-and-where)</b> <br> Basic nesting doesn't need `:is()` but more complex nesting does. See [Example #3](#example-3-selector-lists-and-nesting) for a light introduction to selector diff --git a/site/en/blog/hotpath-with-wasm/index.md b/site/en/blog/hotpath-with-wasm/index.md index 1decb2425..97edda340 100644 --- a/site/en/blog/hotpath-with-wasm/index.md +++ b/site/en/blog/hotpath-with-wasm/index.md @@ -11,8 +11,8 @@ updated: 2020-07-24 ## It's consistently fast, yo -In my [previous](https://web.dev/emscripting-a-c-library/) -[articles](https://web.dev/emscripten-npm/) I talked about how WebAssembly +In my [previous](https://web.dev/articles/emscripting-a-c-library) +[articles](https://web.dev/articles/emscripten-npm) I talked about how WebAssembly allows you to bring the library ecosystem of C/C++ to the web. One app that makes extensive use of C/C++ libraries is [squoosh](https://squoosh.app/), our web app that allows you compress images with a variety of codecs that have been @@ -270,7 +270,7 @@ allowing us to write code that doesn't comply with that model. {% Aside %} This is not a best practice. In our experience it is usually worth it to -use binding mechanisms like [embind in Emscripten](https://web.dev/embind/) +use binding mechanisms like [embind in Emscripten](https://web.dev/articles/embind) or [wasm-bindgen](https://rustwasm.github.io/wasm-bindgen/) for Rust to work at a higher level. {% endAside %} diff --git a/site/en/blog/how-fugu-is-my-browser-and-how-fugu-is-the-web/index.md b/site/en/blog/how-fugu-is-my-browser-and-how-fugu-is-the-web/index.md index 644f0606b..49d1003cb 100644 --- a/site/en/blog/how-fugu-is-my-browser-and-how-fugu-is-the-web/index.md +++ b/site/en/blog/how-fugu-is-my-browser-and-how-fugu-is-the-web/index.md @@ -24,7 +24,7 @@ support? What web applications make use of these APIs? Let's find out! Project Fugu APIs such as [File Handling](/articles/file-handling/), [File System Access](/articles/file-system-access/), -[Async Clipboard](https://web.dev/async-clipboard/), and [Web Share](https://web.dev/web-share/) +[Async Clipboard](https://web.dev/articles/async-clipboard), and [Web Share](https://web.dev/articles/web-share) have brought capabilities to the web that you might expect only to be possible in platform-specific apps. For example, you can now double-click an image file so it opens in an associated PWA, make modifications, save the changes back to the file, and then copy the image contents over into another @@ -65,9 +65,9 @@ Project Fugu APIs. These are: 1. [CacheStorage](https://developer.mozilla.org/docs/Web/API/CacheStorage) 1. [Service Worker](https://developer.mozilla.org/docs/Web/API/Service_Worker_API) -1. [Web Share](https://web.dev/web-share/) -1. [Async Clipboard](https://web.dev/async-clipboard/) -1. [Async Clipboard (Images)](https://web.dev/async-clipboard/) +1. [Web Share](https://web.dev/articles/web-share) +1. [Async Clipboard](https://web.dev/articles/async-clipboard) +1. [Async Clipboard (Images)](https://web.dev/articles/async-clipboard) 1. [File System Access](/articles/file-system-access/) 1. [Web Share Target](/articles/web-share-target/) 1. [Web Share Target (Files)](/articles/web-share-target/) diff --git a/site/en/blog/how-photopea-uses-the-file-handling-api/index.md b/site/en/blog/how-photopea-uses-the-file-handling-api/index.md index 41845e2bc..d8b807993 100644 --- a/site/en/blog/how-photopea-uses-the-file-handling-api/index.md +++ b/site/en/blog/how-photopea-uses-the-file-handling-api/index.md @@ -28,7 +28,7 @@ tags: ## File handling in Photopea -As an [installable PWA](https://web.dev/install-criteria/), Photopea runs in a standalone window when the user chooses to install the app. Doing so unlocks a PWA super power, which Photopea makes heavy use of: [file handling](/articles/file-handling/). +As an [installable PWA](https://web.dev/articles/install-criteria), Photopea runs in a standalone window when the user chooses to install the app. Doing so unlocks a PWA super power, which Photopea makes heavy use of: [file handling](/articles/file-handling/). ### The declarative part of the File Handling API diff --git a/site/en/blog/how-photoshop-solved-working-with-files-larger-than-can-fit-into-memory/index.md b/site/en/blog/how-photoshop-solved-working-with-files-larger-than-can-fit-into-memory/index.md index 762760823..99790b315 100644 --- a/site/en/blog/how-photoshop-solved-working-with-files-larger-than-can-fit-into-memory/index.md +++ b/site/en/blog/how-photoshop-solved-working-with-files-larger-than-can-fit-into-memory/index.md @@ -23,7 +23,7 @@ tags: {% YouTube id="Y40vMQap9fs", startTime="695" %} -In 2021, Adobe, together with Chrome engineering, [brought a version of Photoshop to the web](https://web.dev/ps-on-the-web/). The software makes innovative use of WebAssembly with features like [SIMD](https://v8.dev/features/simd), high performance storage in the [origin private file system](/articles/file-system-access/#accessing-the-origin-private-file-system), the [P3 color space](https://developer.mozilla.org/docs/Web/API/HTMLCanvasElement/getContext#colorspace) for canvas, and Web Components with [Lit](https://lit.dev/). In this article, we want to focus on how Adobe Photoshop engineering solved working with files larger than can fit into memory. And, in the case of WebAssembly, how Photoshop works with files larger than the 32-bit address space of wasm32. +In 2021, Adobe, together with Chrome engineering, [brought a version of Photoshop to the web](https://web.dev/articles/ps-on-the-web). The software makes innovative use of WebAssembly with features like [SIMD](https://v8.dev/features/simd), high performance storage in the [origin private file system](/articles/file-system-access/#accessing-the-origin-private-file-system), the [P3 color space](https://developer.mozilla.org/docs/Web/API/HTMLCanvasElement/getContext#colorspace) for canvas, and Web Components with [Lit](https://lit.dev/). In this article, we want to focus on how Adobe Photoshop engineering solved working with files larger than can fit into memory. And, in the case of WebAssembly, how Photoshop works with files larger than the 32-bit address space of wasm32. {% Img src="image/8WbTDNrhLsU0El80frMBGE4eMCD3/O6HxMybFxb42HZEdcc7Q.png", alt="The Photoshop app while editing an image of the Project Fugu logo.", width="800", height="568" %} diff --git a/site/en/blog/http-cache-partitioning/index.md b/site/en/blog/http-cache-partitioning/index.md index cc2126b8b..18263f6f1 100644 --- a/site/en/blog/http-cache-partitioning/index.md +++ b/site/en/blog/http-cache-partitioning/index.md @@ -67,7 +67,7 @@ cached using `https://x.example/doge.png` as the key. </figure> The same user visits another page (`https://b.example`), which requests the same -image (`https://x.example/doge.png`). +image (`https://x.example/doge.png`). The browser checks its HTTP Cache to see if it already has this resource cached, using the image URL as the key. The browser finds a match in its Cache, so it uses the cached version of the @@ -113,11 +113,11 @@ Isolation Key" in addition to the resource URL. The Network Isolation Key is composed of the top-level site and the current-frame site. {% Aside %} -The "site" is recognized using "[scheme://eTLD+1](https://web.dev/same-site-same-origin/)" so if requests are from +The "site" is recognized using "[scheme://eTLD+1](https://web.dev/articles/same-site-same-origin)" so if requests are from different pages, but they have the same scheme and effective top-level domain+1 they will use the same cache partition. To learn more about this, read [Understanding "same-site" and -"same-origin"](https://web.dev/same-site-same-origin/). +"same-origin"](https://web.dev/articles/same-site-same-origin). {% endAside %} Look again at the previous example to see how cache partitioning works in @@ -227,7 +227,7 @@ already supports it: 3. Browse the web on Chrome for a minute. 4. Go back to `chrome://net-export/` and press **Stop Logging**. 5. Go to `https://netlog-viewer.appspot.com/#import`. -6. Press **Choose File** and pass the log file you saved. +6. Press **Choose File** and pass the log file you saved. You will see the output of the log file. diff --git a/site/en/blog/iframe-credentialless/index.md b/site/en/blog/iframe-credentialless/index.md index 6da1da478..2999db7bb 100644 --- a/site/en/blog/iframe-credentialless/index.md +++ b/site/en/blog/iframe-credentialless/index.md @@ -2,7 +2,7 @@ layout: 'layouts/blog-post.njk' title: "Iframe credentialless: Easily embed iframes in COEP environments" description: > - Iframe credentialless is implemented in Chrome 110. It provides developers a way to load documents in third-party iframes using a new and ephemeral context. In return, they are no longer subject to the COEP embedding rules. + Iframe credentialless is implemented in Chrome 110. It provides developers a way to load documents in third-party iframes using a new and ephemeral context. In return, they are no longer subject to the COEP embedding rules. Developers using COEP can now embed third party iframes that do not use COEP themselves. subhead: > Developers using COEP can now embed third party iframes that do not use COEP themselves. @@ -10,7 +10,7 @@ date: 2023-01-12 authors: - arthursonzogni hero: image/udVScdcCFAdRjZwFdLk2jWAFQyr1/unmhfaD1hmGZfa8DF04f.jpg -alt: A photo of a person sitting on a bench. +alt: A photo of a person sitting on a bench. tags: - privacy - security @@ -18,16 +18,16 @@ tags: Iframe credentialless is enabled by default from Chrome version 110. It solves the most common complaint developers working with [Cross-Origin-Embedder-Policy (COEP)](https://web.dev/security-headers/#coep) have: embedding third-party iframes that do not set COEP. -{% Aside %} +{% Aside %} It was previously available as an origin trial from version 106 to 108, and known as [anonymous iframe](/blog/anonymous-iframe-origin-trial/). {% endAside %} ## Why we need COEP -Some web APIs increase the risk of side-channel attacks such as [Spectre](https://en.wikipedia.org/wiki/Spectre_(security_vulnerability)). To mitigate that risk, browsers offer an opt-in-based isolated environment called [cross-origin isolation](https://web.dev/coop-coep/), which requires deploying COEP. [Cross-origin isolation](https://web.dev/coop-coep/) allows websites to use privileged features including [`SharedArrayBuffer`](/blog/enabling-shared-array-buffer/), [`performance.measureUserAgentSpecificMemory()`](https://web.dev/monitor-total-page-memory-usage/), and [high-precision timers with better resolution](/blog/cross-origin-isolated-hr-timers/). +Some web APIs increase the risk of side-channel attacks such as [Spectre](https://en.wikipedia.org/wiki/Spectre_(security_vulnerability)). To mitigate that risk, browsers offer an opt-in-based isolated environment called [cross-origin isolation](https://web.dev/articles/coop-coep), which requires deploying COEP. [Cross-origin isolation](https://web.dev/articles/coop-coep) allows websites to use privileged features including [`SharedArrayBuffer`](/blog/enabling-shared-array-buffer/), [`performance.measureUserAgentSpecificMemory()`](https://web.dev/articles/monitor-total-page-memory-usage), and [high-precision timers with better resolution](/blog/cross-origin-isolated-hr-timers/). + +To enable cross-origin isolation, websites must send the following HTTP headers: -To enable cross-origin isolation, websites must send the following HTTP headers: - ```http Cross-Origin-Embedder-Policy: require-corp Cross-Origin-Opener-Policy: same-origin @@ -37,13 +37,13 @@ Cross-Origin-Opener-Policy: same-origin ## Challenges with enabling COEP -While cross-origin isolation brings webpages better security and the ability to enable powerful features, deploying COEP can be [difficult](https://web.dev/cross-origin-isolation-guide/). One of the biggest challenges is that all cross-origin iframes must deploy COEP and [CORP](https://web.dev/security-headers/#corp). Iframes without those headers will not be loaded by the browser. +While cross-origin isolation brings webpages better security and the ability to enable powerful features, deploying COEP can be [difficult](https://web.dev/articles/cross-origin-isolation-guide). One of the biggest challenges is that all cross-origin iframes must deploy COEP and [CORP](https://web.dev/security-headers/#corp). Iframes without those headers will not be loaded by the browser. ## Iframe credentialless to the rescue We're introducing `<iframe credentialless>` to help embed third-party iframes that don't set COEP. By adding the `credentialless` attribute to the `<iframe>` element, the iframe is loaded from a different, empty context. In particular, it is loaded without cookies. This allows for removing the COEP restriction. -Example: +Example: ```html <iframe credentialless src="https://example.com"> @@ -79,9 +79,9 @@ Pop-ups are opened as if `noopener` was set. They are created in a new regular t ## Resources -- [Making your website "cross-origin isolated" using COOP and COEP](https://web.dev/coop-coep/) -- [Why you need "cross-origin isolated" for powerful features](https://web.dev/why-coop-coep/) -- [A guide to enable cross-origin isolation](https://web.dev/cross-origin-isolation-guide/) +- [Making your website "cross-origin isolated" using COOP and COEP](https://web.dev/articles/coop-coep) +- [Why you need "cross-origin isolated" for powerful features](https://web.dev/articles/why-coop-coep) +- [A guide to enable cross-origin isolation](https://web.dev/articles/cross-origin-isolation-guide) - [SharedArrayBuffer updates in Android Chrome 88 and Desktop Chrome 92](/blog/enabling-shared-array-buffer/) - [Load cross-origin resources without CORP headers using `COEP: credentialless`](/blog/coep-credentialless-origin-trial/) - [IFrame credentialless - Web security | MDN](https://developer.mozilla.org/docs/Web/Security/IFrame_credentialless) diff --git a/site/en/blog/image-component/index.md b/site/en/blog/image-component/index.md index 78c7b26c1..e4a64bad5 100644 --- a/site/en/blog/image-component/index.md +++ b/site/en/blog/image-component/index.md @@ -24,31 +24,31 @@ The [Aurora](/blog/introducing-aurora/) team worked with [Next.js](https://nextj ## Image optimization issues and opportunities -Images not only affect performance, but also business. The number of images on a page was the second [greatest predictor of conversions](https://almanac.httparchive.org/en/2019/page-weight#bigger-complex-pages-can-be-bad-for-your-business) of users visiting websites. Sessions in which users converted had 38% fewer images than sessions where they did not convert. Lighthouse lists multiple [opportunities](https://web.dev/fast/#optimize-your-images) to optimize images and improve [web vitals](https://web.dev/vitals/) as part of its best practices audit. Some of the common areas where images can affect core web vitals, and user experience are as follows. +Images not only affect performance, but also business. The number of images on a page was the second [greatest predictor of conversions](https://almanac.httparchive.org/en/2019/page-weight#bigger-complex-pages-can-be-bad-for-your-business) of users visiting websites. Sessions in which users converted had 38% fewer images than sessions where they did not convert. Lighthouse lists multiple [opportunities](https://web.dev/articles/fast#optimize_your_images) to optimize images and improve [web vitals](https://web.dev/articles/vitals) as part of its best practices audit. Some of the common areas where images can affect core web vitals, and user experience are as follows. ### Unsized images hurt CLS -Images served without their size specified can cause layout instability and contribute to a high Cumulative Layout Shift ([CLS](https://web.dev/cls/)). Setting the `width` and `height` attributes on [img](https://web.dev/patterns/web-vitals-patterns/images/img-tag/) elements can help to prevent layout shifts. For example: +Images served without their size specified can cause layout instability and contribute to a high Cumulative Layout Shift ([CLS](https://web.dev/articles/cls)). Setting the `width` and `height` attributes on [img](https://web.dev/articles/patterns/web-vitals-patterns/images/img-tag) elements can help to prevent layout shifts. For example: ```html <img src="flower.jpg" width="360" height="240"> ``` -The width and height should be set such that the aspect ratio of the rendered image is close to its natural aspect ratio. A significant [difference in the aspect ratio](https://web.dev/image-aspect-ratio/) can result in the image looking distorted. A relatively new property that allows you to specify [aspect-ratio in CSS](https://web.dev/aspect-ratio/) can help to size images responsively while preventing CLS. +The width and height should be set such that the aspect ratio of the rendered image is close to its natural aspect ratio. A significant [difference in the aspect ratio](https://web.dev/articles/image-aspect-ratio) can result in the image looking distorted. A relatively new property that allows you to specify [aspect-ratio in CSS](https://web.dev/articles/aspect-ratio) can help to size images responsively while preventing CLS. ### Large images can hurt LCP -The larger the file size of an image, the longer it will take to download. A large image could be the "hero" image for the page or the most significant element in the viewport responsible for triggering the Largest Contentful Paint ([LCP](https://web.dev/lcp/)). An image that is part of the critical content and takes a long time to download will delay the LCP. +The larger the file size of an image, the longer it will take to download. A large image could be the "hero" image for the page or the most significant element in the viewport responsible for triggering the Largest Contentful Paint ([LCP](https://web.dev/articles/lcp)). An image that is part of the critical content and takes a long time to download will delay the LCP. In many cases, developers can reduce image sizes through better compression and the use of [responsive](https://developer.mozilla.org/docs/Learn/HTML/Multimedia_and_embedding/Responsive_images#how_do_you_create_responsive_images) images. The `srcset` and `sizes` attributes of the `<img>` element help to provide image files with different sizes. The browser can then choose the right one depending on the screen size and resolution. ### Poor image compression can hurt LCP -Modern image formats like [AVIF](https://web.dev/compress-images-avif/) or [WebP](https://web.dev/serve-images-webp/) can provide better compression than commonly used JPEG and PNG formats. Better compression reduces the file size by 25% to 50% in some cases for the same quality of the image. This reduction leads to faster downloads with less data consumption. The app should [serve modern image formats](https://web.dev/uses-webp-images/) to browsers that support these formats. +Modern image formats like [AVIF](https://web.dev/articles/compress-images-avif) or [WebP](https://web.dev/articles/serve-images-webp) can provide better compression than commonly used JPEG and PNG formats. Better compression reduces the file size by 25% to 50% in some cases for the same quality of the image. This reduction leads to faster downloads with less data consumption. The app should [serve modern image formats](https://web.dev/articles/uses-webp-images) to browsers that support these formats. ### Loading unnecessary images hurts LCP -Images below the fold or not in the viewport are not displayed to the user when the page is loaded. They can be deferred so that they do not contribute to the LCP and delay it. [Lazy-loading](https://web.dev/lazy-loading-images/) can be used to load such images later as the user scrolls towards them. +Images below the fold or not in the viewport are not displayed to the user when the page is loaded. They can be deferred so that they do not contribute to the LCP and delay it. [Lazy-loading](https://web.dev/articles/lazy-loading-images) can be used to load such images later as the user scrolls towards them. ## Optimization challenges @@ -60,7 +60,7 @@ Teams can evaluate the performance cost due to the issues listed previously and - **Markup overload**: Solutions for including the image size or `srcset` for different sizes require additional markup for every image, which can be tedious. The `srcset` attribute was introduced in 2014 but is [used by only 26.5%](https://almanac.httparchive.org/en/2020/media#srcset) of the websites today. When using `srcset`, developers have to create images in various sizes. Tools such as [just-gimme-an-img](https://just-gimme-an-img.vercel.app/) can help but have to be used manually for every image. - **Browser support**: Modern image formats like AVIF and WebP create smaller image files but need special handling on browsers that don't support them. Developers have to use strategies like [content negotiation](https://developer.mozilla.org/docs/Web/HTTP/Content_negotiation) or the [`<picture`>](https://developer.mozilla.org/docs/Web/HTML/Element/picture) element so that images are served to all browsers. - **Lazy loading complications**: There are multiple techniques and libraries available to implement lazy-loading for below-the-fold images. Picking the best one can be a challenge. Developers may also not know the best distance from the "fold" to load deferred images. Different viewport sizes on devices can further complicate this. -- **Changing landscape**: As browsers start supporting new HTML or CSS features to enhance performance, it may be difficult for developers to evaluate each of them. For example, Chrome is introducing the [Fetch Priority](https://web.dev/fetch-priority/) feature as an [Origin Trial](/blog/origin-trials/). It can be used to boost the priority of specific images on the page. Overall, developers would find it easier if such enhancements were evaluated and implemented at the component level. +- **Changing landscape**: As browsers start supporting new HTML or CSS features to enhance performance, it may be difficult for developers to evaluate each of them. For example, Chrome is introducing the [Fetch Priority](https://web.dev/articles/fetch-priority) feature as an [Origin Trial](/blog/origin-trials/). It can be used to boost the priority of specific images on the page. Overall, developers would find it easier if such enhancements were evaluated and implemented at the component level. ## Image component as a solution @@ -192,7 +192,7 @@ In the Next.js Image component, loading is set to `"lazy"` by default. Lazy load ### Preload important images -Quite often, LCP elements are images, and large images can delay LCP. It is a good idea to [preload critical images](https://web.dev/preload-critical-assets/) so the browser can discover that image sooner. When using an `<img>` element, a preload hint may be included in the HTML head as follows. +Quite often, LCP elements are images, and large images can delay LCP. It is a good idea to [preload critical images](https://web.dev/articles/preload-critical-assets) so the browser can discover that image sooner. When using an `<img>` element, a preload hint may be included in the HTML head as follows. ```html <link rel="preload" as="image" href="important.png"> @@ -208,7 +208,7 @@ Adding a `priority` attribute simplifies markup and is more convenient to use. I ### Encourage high-performance image hosting -[Image CDNs](https://web.dev/image-cdns/) are recommended for automating image optimization, and they also support [modern image formats](https://web.dev/uses-webp-images/) like WebP and AVIF. The Next.js Image component uses an image CDN by default using a [loader architecture](https://nextjs.org/docs/api-reference/next/image#loader). The following example shows that the loader allows for configuration of the CDN in the Next.js config file. +[Image CDNs](https://web.dev/articles/image-cdns) are recommended for automating image optimization, and they also support [modern image formats](https://web.dev/articles/uses-webp-images) like WebP and AVIF. The Next.js Image component uses an image CDN by default using a [loader architecture](https://nextjs.org/docs/api-reference/next/image#loader). The following example shows that the loader allows for configuration of the CDN in the Next.js config file. ```js module.exports = { @@ -229,7 +229,7 @@ There may be situations where websites cannot use image CDNs. In such cases, an Progressive loading is a technique used to hold users' interest by displaying a placeholder image usually of significantly lower quality while the actual image loads. It improves perceived performance and enhances the user experience. It can be used in combination with lazy loading for below-the-fold images or for above-the-fold images. -The Next.js Image component supports progressive loading for the image through the [placeholder](https://nextjs.org/docs/api-reference/next/image#placeholder) property. This can be used as an [LQIP](https://web.dev/lazy-loading-best-practices/#wrong-layout-shifting) (Low-quality image placeholder) for displaying a low-quality or blurred image while the actual image loads. +The Next.js Image component supports progressive loading for the image through the [placeholder](https://nextjs.org/docs/api-reference/next/image#placeholder) property. This can be used as an [LQIP](https://web.dev/articles/lazy-loading-best-practices#wrong_layout_shifting) (Low-quality image placeholder) for displaying a low-quality or blurred image while the actual image loads. ## Impact diff --git a/site/en/blog/immutable-document-domain/index.md b/site/en/blog/immutable-document-domain/index.md index fc9fa94d0..9def7e4bd 100644 --- a/site/en/blog/immutable-document-domain/index.md +++ b/site/en/blog/immutable-document-domain/index.md @@ -65,7 +65,7 @@ header, as will all other documents that require that behavior (note that ## Why make `document.domain` immutable? Many websites set `document.domain` to allow communication between [same-site -but cross-origin](https://web.dev/same-site-same-origin/) pages. +but cross-origin](https://web.dev/articles/same-site-same-origin) pages. {% Aside 'key-term' %} @@ -150,11 +150,11 @@ panel.", width="800", height="472" %} If you have a reporting endpoint set up, you will also be sent deprecation reports. Learn more about [how to use the Reporting -API](https://web.dev/reporting-api/) with either existing report collection +API](https://web.dev/articles/reporting-api) with either existing report collection services or by building your own in-house solution. You can run your site through the [LightHouse deprecated API -audit](https://web.dev/deprecations/) to find all APIs that are scheduled to +audit](https://web.dev/articles/deprecations) to find all APIs that are scheduled to be removed from Chrome. ## Alternative cross-origin communication @@ -163,7 +163,7 @@ At this time, you have three options to replace `document.domain` for your websi ### Use `postMessage()` or Channel Messaging API -In most use cases, cross-origin +In most use cases, cross-origin [`postMessage()`](https://developer.mozilla.org/docs/Web/API/Window/postMessage) or [Channel Messaging API](https://developer.mozilla.org/docs/Web/API/Channel_Messaging_API) can replace `document.domain`. @@ -227,7 +227,7 @@ Origin-Agent-Cluster: ?0 The `Origin-Agent-Cluster` header instructs the browser whether the document should be handled by the origin-keyed agent cluster or not. To learn more about `Origin-Agent-Cluster`, read [Requesting performance isolation with the -`Origin-Agent-Cluster` header](https://web.dev/origin-agent-cluster/). +`Origin-Agent-Cluster` header](https://web.dev/articles/origin-agent-cluster). When you send this header, your document can continue to set `document.domain` even after it becomes immutable by default. diff --git a/site/en/blog/improved-pwa-offline-detection/index.md b/site/en/blog/improved-pwa-offline-detection/index.md index d0c72c0de..192c9a66f 100644 --- a/site/en/blog/improved-pwa-offline-detection/index.md +++ b/site/en/blog/improved-pwa-offline-detection/index.md @@ -24,7 +24,7 @@ decided to put those plans on hold**. We strongly believe providing a valid page when the user is offline is critical to providing a good user experience. {% endAside %} -[Progressive Web Apps (PWAs)](https://web.dev/pwa/) are a pattern for +[Progressive Web Apps (PWAs)](https://web.dev/articles/pwa) are a pattern for building modern, installable applications using web technology for mobile and desktop devices. diff --git a/site/en/blog/inp-tools-2022/index.md b/site/en/blog/inp-tools-2022/index.md index 9bcc8ac29..ab3915470 100644 --- a/site/en/blog/inp-tools-2022/index.md +++ b/site/en/blog/inp-tools-2022/index.md @@ -16,16 +16,16 @@ tags: - devtools --- -We are thrilled to have the first round of tooling support for the new [pending responsiveness metric](https://web.dev/vitals/#pending), Interaction to Next Paint (INP). To learn about the metric itself, check out [the official INP metric guide](https://web.dev/inp/). +We are thrilled to have the first round of tooling support for the new [pending responsiveness metric](https://web.dev/vitals/#pending), Interaction to Next Paint (INP). To learn about the metric itself, check out [the official INP metric guide](https://web.dev/articles/inp). ## Suggested measurement -The goal of measuring INP is to understand how fast your page responds to user input. The only way to get realistic data is to measure how your page is responding for real users visiting your site using [data from the field](https://web.dev/lab-and-field-data-differences/#field-data). +The goal of measuring INP is to understand how fast your page responds to user input. The only way to get realistic data is to measure how your page is responding for real users visiting your site using [data from the field](https://web.dev/articles/lab-and-field-data-differences#field_data). -Measuring INP [in the lab](https://web.dev/lab-and-field-data-differences/#lab-data) then helps to better understand event timings and where optimizations need to happen. Lab tools won't automatically interact with the page, so they either need manual input while they measure, or they need to be scripted with an automation tool like Puppeteer. When key interactions are identified from typical user journeys, they can be tried out to identify issues or scripted, and put in CI tests to prevent regressions. +Measuring INP [in the lab](https://web.dev/articles/lab-and-field-data-differences#lab_data) then helps to better understand event timings and where optimizations need to happen. Lab tools won't automatically interact with the page, so they either need manual input while they measure, or they need to be scripted with an automation tool like Puppeteer. When key interactions are identified from typical user journeys, they can be tried out to identify issues or scripted, and put in CI tests to prevent regressions. {% Aside %} -To learn more about how to leverage both lab and field data, read about [why lab and field data can be different (and what to do about it)](https://web.dev/lab-and-field-data-differences/). +To learn more about how to leverage both lab and field data, read about [why lab and field data can be different (and what to do about it)](https://web.dev/articles/lab-and-field-data-differences). {% endAside %} ## Discover what your real users are experiencing (field data) @@ -53,7 +53,7 @@ onINP(({value}) => { }); ``` -Read [more about `web-vitals` and how to measure in the DevTools console](https://web.dev/inp/#measure-inp-in-javascript). +Read [more about `web-vitals` and how to measure in the DevTools console](https://web.dev/articles/inp#measure_inp_in_javascript). ### Web Vitals Chrome extension @@ -75,7 +75,7 @@ The new timespan mode in the Lighthouse Panel in DevTools lets you start Lightho {% Video src="video/MtjnObpuceYe3ijODN3a79WrxLU2/GioMntCgOope1zSUmT7s.mov", controls="true"%} </figure> -The same series of interactions can be automated by using [Lighthouse user flows](https://web.dev/lighthouse-user-flows/). INP is available in user flows as of Lighthouse 9.6. +The same series of interactions can be automated by using [Lighthouse user flows](https://web.dev/articles/lighthouse-user-flows). INP is available in user flows as of Lighthouse 9.6. ### Tool availability details diff --git a/site/en/blog/inside-the-container-query-polyfill/index.md b/site/en/blog/inside-the-container-query-polyfill/index.md index c428ca735..c5d73cca3 100644 --- a/site/en/blog/inside-the-container-query-polyfill/index.md +++ b/site/en/blog/inside-the-container-query-polyfill/index.md @@ -91,7 +91,7 @@ However, the `:where(...)` pseudo-class is [fairly new](https://caniuse.com/mdn- color: blue; } } - + .card { color: red; } @@ -105,7 +105,7 @@ However, the `:where(...)` pseudo-class is [fairly new](https://caniuse.com/mdn- color: blue; } } - + .card { color: red; } @@ -269,9 +269,9 @@ During the initial load, there is a lot that needs to happen before the polyfill * The polyfill needs to be loaded and initialized. * Stylesheets need to be parsed and transpiled. Since there aren’t any APIs to access the raw source of an external stylesheet, it may need to be asynchronously re-fetched, though ideally just from the browser cache. -If these concerns aren’t carefully addressed by the polyfill, it could potentially regress your [Core Web Vitals](https://web.dev/vitals/). +If these concerns aren’t carefully addressed by the polyfill, it could potentially regress your [Core Web Vitals](https://web.dev/articles/vitals). -To make it easier for you to give your visitors a pleasant experience, the polyfill was designed to prioritize [First Input Delay (FID)](https://web.dev/fid/) and [Cumulative Layout Shift (CLS)](https://web.dev/cls/), potentially at the expense of [Largest Contentful Paint (LCP)](https://web.dev/lcp/). Concretely, _the polyfill makes no guarantee that your container queries will be evaluated before the first paint_. This means that for the best user experience, you **must** ensure that any content whose size or position would be affected by using container queries are hidden until after the polyfill has loaded and transpiled your CSS. One way to accomplish this is by using an `@supports` rule: +To make it easier for you to give your visitors a pleasant experience, the polyfill was designed to prioritize [First Input Delay (FID)](https://web.dev/articles/fid) and [Cumulative Layout Shift (CLS)](https://web.dev/articles/cls), potentially at the expense of [Largest Contentful Paint (LCP)](https://web.dev/articles/lcp). Concretely, _the polyfill makes no guarantee that your container queries will be evaluated before the first paint_. This means that for the best user experience, you **must** ensure that any content whose size or position would be affected by using container queries are hidden until after the polyfill has loaded and transpiled your CSS. One way to accomplish this is by using an `@supports` rule: ```css @supports not (container-type: inline-size) { @@ -299,4 +299,4 @@ We can't wait to see and experience the amazing things you will build with it. ## Acknowledgements -Hero image by [Dan Cristian Pădureț](https://unsplash.com/@dancristianpaduret) on [Unsplash](https://unsplash.com/photos/XC7lc8biINg). \ No newline at end of file +Hero image by [Dan Cristian Pădureț](https://unsplash.com/@dancristianpaduret) on [Unsplash](https://unsplash.com/photos/XC7lc8biINg). diff --git a/site/en/blog/insider-april-2022/index.md b/site/en/blog/insider-april-2022/index.md index 9468f182b..cd0178c91 100644 --- a/site/en/blog/insider-april-2022/index.md +++ b/site/en/blog/insider-april-2022/index.md @@ -13,7 +13,7 @@ authors: tags: - insider - + hero: 'image/C8ys09lNbQOJLokQMhRtN2A0YU12/RPMWTGEBXQXVHozgFlIG.png' thumbnail: 'image/kheDArv5csY6rvQUJDbWRscckLr1/Hfx3C2heobFhRJJejstK.png' @@ -23,30 +23,30 @@ alt: > --- -Developers often tell us that it’s difficult to keep up with changes on the web and understand why these changes are happening. Today, we’re kicking off a new series called _Chrome Dev Insider_ where we’ll share (1) What’s cool and newsworthy, (2) An insight into how we made a decision on a key topic (for example [changing FLOC](https://blog.google/products/chrome/get-know-new-topics-api-privacy-sandbox/)) or approach our work with the ecosystem (for example [Interop 2022](https://web.dev/interop-2022/)), and (3) any really important things that you need to know about (for example [changes in user agent strings](https://web.dev/chrome-firefox-100/)). +Developers often tell us that it’s difficult to keep up with changes on the web and understand why these changes are happening. Today, we’re kicking off a new series called _Chrome Dev Insider_ where we’ll share (1) What’s cool and newsworthy, (2) An insight into how we made a decision on a key topic (for example [changing FLOC](https://blog.google/products/chrome/get-know-new-topics-api-privacy-sandbox/)) or approach our work with the ecosystem (for example [Interop 2022](https://web.dev/blog/interop-2022)), and (3) any really important things that you need to know about (for example [changes in user agent strings](https://web.dev/articles/chrome-firefox-100)). As we share what we are working on, it will be in the context of our four priorities for 2022: * **Enabling delightful user experiences:** make things intuitive for users; whether it’s performance, transactions, identity or transitions. -* **Advancing the web’s capabilities:** support the web's evolving role from being a content consumption platform, to the platform for a wide range of experiences including those that need deep OS and hardware level integrations. +* **Advancing the web’s capabilities:** support the web's evolving role from being a content consumption platform, to the platform for a wide range of experiences including those that need deep OS and hardware level integrations. * **Simplifying web development:** make decision making easier and improve developer productivity. -* **Improving the privacy of the web:** serve web users' expectation for better data privacy protections in the face of ever-increasing developer sophistication in tracking and targeting. +* **Improving the privacy of the web:** serve web users' expectation for better data privacy protections in the face of ever-increasing developer sophistication in tracking and targeting. ## In the news: Interop 2022 -As we plan our roadmaps, we look at [developer feedback](https://insights.developer.mozilla.org/) to understand web developers’ top pain points and needs, amongst other things. A key theme that repeatedly shows up is _browser compatibility_, making an experience work the same across browsers. Over the past year, we’ve been working with the ecosystem to address this theme as part of our priority to "simplify web development". +As we plan our roadmaps, we look at [developer feedback](https://insights.developer.mozilla.org/) to understand web developers’ top pain points and needs, amongst other things. A key theme that repeatedly shows up is _browser compatibility_, making an experience work the same across browsers. Over the past year, we’ve been working with the ecosystem to address this theme as part of our priority to "simplify web development". -Last year, Microsoft, Chrome and ecosystem players announced [Compat 2021](https://web.dev/compat2021/) that resulted in all popular browser engines (Chromium, Gecko and Webkit) achieving a 90+% score in the [five key focus areas](https://web.dev/compat2021-holiday-update/#css-flexbox) identified for the year. Among other things, Compat 2021 led to creating a solid foundation for powerful features such as [CSS Grid](https://wpt.fyi/compat2021?feature=css-grid) ([12% usage and steadily growing](https://chromestatus.com/metrics/feature/timeline/popularity/1693)) and [CSS Flexbox](https://wpt.fyi/compat2021?feature=css-flexbox) ([77% usage](https://chromestatus.com/metrics/feature/timeline/popularity/1692)). +Last year, Microsoft, Chrome and ecosystem players announced [Compat 2021](https://web.dev/blog/compat2021) that resulted in all popular browser engines (Chromium, Gecko and Webkit) achieving a 90+% score in the [five key focus areas](https://web.dev/articles/compat2021-holiday-update#css_flexbox) identified for the year. Among other things, Compat 2021 led to creating a solid foundation for powerful features such as [CSS Grid](https://wpt.fyi/compat2021?feature=css-grid) ([12% usage and steadily growing](https://chromestatus.com/metrics/feature/timeline/popularity/1693)) and [CSS Flexbox](https://wpt.fyi/compat2021?feature=css-flexbox) ([77% usage](https://chromestatus.com/metrics/feature/timeline/popularity/1692)). -And last month, Apple, Bocoup, Google, Igalia, Microsoft, and Mozilla came together as [supporters](https://github.com/web-platform-tests/interop-2022/blob/main/supporters.md) to solve the top browsers compatibility issues identified by web developers and agree on a common benchmark. The result is [Interop 2022](https://web.dev/interop-2022), a project with the goal of bringing more homogeneity to the platform. The benchmark focuses on [15 priority areas](https://web.dev/interop-2022/#the-15-areas-of-focus) identified by developers as key to improving their productivity. +And last month, Apple, Bocoup, Google, Igalia, Microsoft, and Mozilla came together as [supporters](https://github.com/web-platform-tests/interop-2022/blob/main/supporters.md) to solve the top browsers compatibility issues identified by web developers and agree on a common benchmark. The result is [Interop 2022](https://web.dev/interop-2022), a project with the goal of bringing more homogeneity to the platform. The benchmark focuses on [15 priority areas](https://web.dev/articles/interop-2022#the_15_areas_of_focus) identified by developers as key to improving their productivity. ## Insider scoop: Working with our browser peers -With Interop 2022 top of mind, I sat down with [Robert Nyman](https://twitter.com/robertnyman) and [Philip Jägenstedt](https://twitter.com/foolip) who have been involved in these conversations to get the inside story. Here’s the editor’s cut of how it came together. +With Interop 2022 top of mind, I sat down with [Robert Nyman](https://twitter.com/robertnyman) and [Philip Jägenstedt](https://twitter.com/foolip) who have been involved in these conversations to get the inside story. Here’s the editor’s cut of how it came together. _What’s the genesis of this initiative?_ @@ -70,12 +70,12 @@ I think it's important to recognize that there are limits to this consensus-base _Coming back to Interop 2022, do we see non-design or layout features coming into the pipeline at some point?_ -**Philip:** Absolutely! Interop 2022 was not limited to styling and layout features, but it did end up leaning very heavily towards CSS. Partly because State of CSS 2021 was fresh, but also because web developers have told us that this is where they have the most trouble with differences between browsers. Multiple focus areas, like form and dialog elements, go beyond CSS, and we also have some [investigation efforts](https://web.dev/interop-2022/#investigation-efforts) around editing APIs and pointer and mouse events. I hope that for Interop 2023, we will have more fresh data on developer needs across the web, and include more such features in the effort. +**Philip:** Absolutely! Interop 2022 was not limited to styling and layout features, but it did end up leaning very heavily towards CSS. Partly because State of CSS 2021 was fresh, but also because web developers have told us that this is where they have the most trouble with differences between browsers. Multiple focus areas, like form and dialog elements, go beyond CSS, and we also have some [investigation efforts](https://web.dev/articles/interop-2022#investigation_efforts) around editing APIs and pointer and mouse events. I hope that for Interop 2023, we will have more fresh data on developer needs across the web, and include more such features in the effort. ## Key upcoming changes -One of the intents of this series is to give developers a heads up on upcoming key changes; things that are important for improving user experience and the platform's capabilities. +One of the intents of this series is to give developers a heads up on upcoming key changes; things that are important for improving user experience and the platform's capabilities. The timelines mentioned below are when we expect these changes to happen. However, it is possible release versions for features may change. @@ -83,31 +83,31 @@ The timelines mentioned below are when we expect these changes to happen. Howeve -The [User-Agent](https://developer.mozilla.org/docs/Web/HTTP/Headers/User-Agent) header—and its associated JS interfaces—transmits not only useful browser and device information, but also carries with it a legacy of lineage and inaccurate information. More problematic than the near endless supply of UA string parsing bugs is the fact that it's _passively_ sent to servers for all navigation and sub-resource requests. This represents approximately 10 bits of entropy that servers can use to build stable tracking identifiers as users navigate the web. +The [User-Agent](https://developer.mozilla.org/docs/Web/HTTP/Headers/User-Agent) header—and its associated JS interfaces—transmits not only useful browser and device information, but also carries with it a legacy of lineage and inaccurate information. More problematic than the near endless supply of UA string parsing bugs is the fact that it's _passively_ sent to servers for all navigation and sub-resource requests. This represents approximately 10 bits of entropy that servers can use to build stable tracking identifiers as users navigate the web. -Our current plan is to reduce the existing UA string by continuing to ship low-entropy browser major version, platform name, and _mobileness_, freezing the [high entropy info](https://www.chromium.org/updates/ua-reduction/#token-reference). For use cases that require additional information than contained in the header, we've been shipping the [User-Agent Client Hints](https://web.dev/user-agent-client-hints/) API since Chrome 89. +Our current plan is to reduce the existing UA string by continuing to ship low-entropy browser major version, platform name, and _mobileness_, freezing the [high entropy info](https://www.chromium.org/updates/ua-reduction/#token-reference). For use cases that require additional information than contained in the header, we've been shipping the [User-Agent Client Hints](https://web.dev/articles/user-agent-client-hints) API since Chrome 89. We [ran an Origin Trial for 6 months](/blog/user-agent-reduction-origin-trial/) for experimentation and feedback and were happy to have received no feedback related to breakage despite having more than 200 participants. * **Timeline:** In Chrome 101, [we're moving forward](https://groups.google.com/a/chromium.org/g/blink-dev/c/dcTStiBZVoQ/m/KyomPLOnAwAJ) with what we call Phase 4: reducing the `MINOR.BUILD.PATCH` information in the UA string to `0.0.0`. And we’ll continue to give sites a heads up and time to [prepare for phases 5 and beyond.](https://blog.chromium.org/2021/09/user-agent-reduction-origin-trial-and-dates.html#:~:text=the%20deprecation%20trial.-,Phase%205%3A%20Chrome%20107,-CTA%3A%20Ensure%20your) We've also [created enterprise policies](https://bugs.chromium.org/p/chromium/issues/detail?id=1261837) to opt out of these changes, and will be running a [deprecation trial until Chrome 113 to give sites more time](/blog/user-agent-reduction-deprecation-trial/) to be ready for these changes. -* **Call to action:** [Migrate your site to UA Client Hints](https://web.dev/migrate-to-ua-ch/) or [participate in the deprecation trial](/blog/user-agent-reduction-deprecation-trial/). +* **Call to action:** [Migrate your site to UA Client Hints](https://web.dev/articles/migrate-to-ua-ch) or [participate in the deprecation trial](/blog/user-agent-reduction-deprecation-trial/). ### Local Fonts Access API -Chrome is launching the Local Font Access API. Though sites have long been able to use local fonts, this API enumerates the list of local fonts and gives access to the font data itself. This functionality gives users the ability to use all of their fonts with web-based design and other applications. +Chrome is launching the Local Font Access API. Though sites have long been able to use local fonts, this API enumerates the list of local fonts and gives access to the font data itself. This functionality gives users the ability to use all of their fonts with web-based design and other applications. Local fonts have long been known as a fingerprinting vector. Though this new API doesn’t increase the ability to use fonts for fingerprinting, Chrome requires that a user grant a new `"local-fonts"` permission for a site before it can use the new Local Font Access API. In the future, we plan to require that the same "local-fonts" permission be granted before using any other API that provides access to local fonts. * **Timeline:** Targeting Chrome 103 (June'22) -* **Call to action:** [Learn more](https://web.dev/local-fonts/) about the API and [how to use](https://web.dev/local-fonts/#how-to-use-the-local-font-access-api) it to start implementing. +* **Call to action:** [Learn more](https://web.dev/articles/local-fonts) about the API and [how to use](https://web.dev/articles/local-fonts#how_to_use_the_local_font_access_api) it to start implementing. ### Making BFCache work with `Cache-control: no-store` -We have identified a significant opportunity to improve how often the [Back/Forward cache](https://web.dev/bfcache/) can deliver instant back/forward navigations. This requires a change in how BFCache behaves on pages served with the [Cache-control: no-store HTTP header](https://developer.mozilla.org/docs/Web/HTTP/Headers/Cache-Control#:~:text=shared%20caches%20only.-,no%2Dstore,-The%20no%2Dstore). We have a public proposal designed to prevent significant surprises by monitoring various signals (for example evicting pages from the BFCache whenever an HTTP-only cookie changes), and carve-outs (for example group policy for Enterprise/Edu customers) for unique contexts. This is a complex but exciting opportunity, and we’d love additional scrutiny and feedback! +We have identified a significant opportunity to improve how often the [Back/Forward cache](https://web.dev/articles/bfcache) can deliver instant back/forward navigations. This requires a change in how BFCache behaves on pages served with the [Cache-control: no-store HTTP header](https://developer.mozilla.org/docs/Web/HTTP/Headers/Cache-Control#:~:text=shared%20caches%20only.-,no%2Dstore,-The%20no%2Dstore). We have a public proposal designed to prevent significant surprises by monitoring various signals (for example evicting pages from the BFCache whenever an HTTP-only cookie changes), and carve-outs (for example group policy for Enterprise/Edu customers) for unique contexts. This is a complex but exciting opportunity, and we’d love additional scrutiny and feedback! * **Timeline:** Targeting Chrome 104 (July'22), assuming no major surprises. * **Call to action:** See [the proposal](https://docs.google.com/document/d/1qX1w6L6laTzpFTh78dvT7wwC1060Z3he2Azp4BAwsUE/edit) for further details, including how to enable a work-in-progress implementation, and ways to share feedback such as actual scenarios in which our approach would create new hurdles. diff --git a/site/en/blog/insider-dec-22/index.md b/site/en/blog/insider-dec-22/index.md index efb301fc1..3fccf0ac1 100644 --- a/site/en/blog/insider-dec-22/index.md +++ b/site/en/blog/insider-dec-22/index.md @@ -13,7 +13,7 @@ authors: tags: - insider - + hero: 'image/kheDArv5csY6rvQUJDbWRscckLr1/8d0zCSMHxpgkFZTmXCGk.jpg' thumbnail: 'image/kheDArv5csY6rvQUJDbWRscckLr1/kn68o6p4dsShB0tAI3Jc.png' @@ -26,9 +26,9 @@ We started the [Chrome Dev Insider](/insider/) series this year to bring you clo I couldn't think of a better person to talk about this than [Parisa Tabriz](https://twitter.com/laparisa), our VP of Engineering and Product. Parisa took the reins of our work on both the browser and the open web platform, earlier this year. I hope you enjoy this interview as much as I did. -_**Let's start with your self-appointed "Security Princess" tag. What's the story?**_ +_**Let's start with your self-appointed "Security Princess" tag. What's the story?**_ -**Parisa:** I actually started my career in cybersecurity because a web application I built in college got hacked and defaced by spammers, and I was curious about what happened. (What happened was SQL injection since I hadn't sanitized untrusted input!) I joined a security-focused student club to learn more and ended up getting more experience with practical hacking and system security, while also meeting fellow students that became close friends. +**Parisa:** I actually started my career in cybersecurity because a web application I built in college got hacked and defaced by spammers, and I was curious about what happened. (What happened was SQL injection since I hadn't sanitized untrusted input!) I joined a security-focused student club to learn more and ended up getting more experience with practical hacking and system security, while also meeting fellow students that became close friends. I joined Google back in 2007 as a "hired hacker" to apply some of my security experience on software products like Search, Gmail, and Youtube. I adopted the self-appointed "Security Princess" title and put it on a business card before going to an industry conference in Tokyo, Japan, and it stuck! @@ -46,7 +46,7 @@ Figuring all this out will require close collaboration with designers, researche _**Talking about developers, how do you see your team's role in 2023 and beyond, particularly for developers and the web ecosystem?**_ -**Parisa:** As someone that got into tech via web development over 20 years ago, it's amazing to see how the platform has advanced and what the web enables today. The web has always been a great community of passionate developers and creators, so I'm excited to see how deeply our platform teams continue to connect with and support the developer community. +**Parisa:** As someone that got into tech via web development over 20 years ago, it's amazing to see how the platform has advanced and what the web enables today. The web has always been a great community of passionate developers and creators, so I'm excited to see how deeply our platform teams continue to connect with and support the developer community. I talked about the opportunity to deliver personalized and private experiences to users and Chrome; a user agent should provide developers with the platform and tools to achieve that. Developers from around the world have been building Chrome Extensions that make browsing easier, more productive, and more personalized, and I continue to be amazed at what our extension developer community creates. We're committed to continually working with and listening to developers to improve our extension platform and ecosystem, so users and enterprises can install extensions with confidence. We're currently working on a major migration to [Manifest v3](/docs/extensions/mv3/intro/), which increases the security, privacy, and performance of extensions, and represents one of the most significant shifts in the extensions platform since it launched a decade ago. @@ -54,11 +54,11 @@ In the open web, we've continued to be strong believers and active participants _**I'm very excited about projects like Compat, Interop and Project Aurora that are having a great impact on developer productivity. Ok, let's end on a high. What were the biggest highlights of 2022 for you?**_ -**Parisa:** Yes! For me, projects like [Interop](https://wpt.fyi/interop-2022) are critical in making the web the easiest platform to build on. Our partnerships with ecosystem players like Igalia and other major browser vendors have been the most meaningful in the past couple years, and I'm very excited about the direction we're all collectively taking to reduce development friction for web developers. +**Parisa:** Yes! For me, projects like [Interop](https://wpt.fyi/interop-2022) are critical in making the web the easiest platform to build on. Our partnerships with ecosystem players like Igalia and other major browser vendors have been the most meaningful in the past couple years, and I'm very excited about the direction we're all collectively taking to reduce development friction for web developers. I'm also particularly excited about us by improving the browser's capabilities across speed, safety and stability. From improving [Chrome's speed](https://blog.chromium.org/search/label/the%20fast%20and%20the%20curious), to working with the community on solutions like [FedCM](/en/docs/privacy-sandbox/fedcm/) and [Passkeys](https://blog.google/technology/safety-security/one-step-closer-to-a-passwordless-future/) for better, safer identity management, there's so much great stuff happening all around and our hope is that we enable developers to achieve more by doing less. -Finally, I'm amazed at the pace of innovation happening in computing generally, and am particularly excited about Chrome using [on-device machine learning](https://blog.google/products/chrome/building-a-more-helpful-browser-with-machine-learning) in new ways to create a smarter, more adaptive browsing experience that keeps users safer, translates web pages instantly, and finds information more quickly, and what we can enable for developers by bringing [GPU Compute to the web](https://web.dev/gpu-compute/). +Finally, I'm amazed at the pace of innovation happening in computing generally, and am particularly excited about Chrome using [on-device machine learning](https://blog.google/products/chrome/building-a-more-helpful-browser-with-machine-learning) in new ways to create a smarter, more adaptive browsing experience that keeps users safer, translates web pages instantly, and finds information more quickly, and what we can enable for developers by bringing [GPU Compute to the web](https://web.dev/articles/gpu-compute). Our focus in 2022 was to **make the web work better for everyone**. And for me, it's going to be our mission for the years to come. diff --git a/site/en/blog/insider-july-2022/index.md b/site/en/blog/insider-july-2022/index.md index a4f644aa7..1418212a2 100644 --- a/site/en/blog/insider-july-2022/index.md +++ b/site/en/blog/insider-july-2022/index.md @@ -13,7 +13,7 @@ authors: tags: - insider - + hero: 'image/kheDArv5csY6rvQUJDbWRscckLr1/5pfwyFL3CsjaWdvjG7DM.png' thumbnail: 'image/kheDArv5csY6rvQUJDbWRscckLr1/FEhZwqV3W5kVUciPDV29.png' @@ -24,15 +24,15 @@ alt: > Welcome to the second edition of Chrome Dev Insider where we share updates on what's new and exciting in the community and here at Chrome. This is a new episode of insider stories on how we approach our work, and a quick glance at some of the most important updates that you should pay attention to. -I'm Rachel Andrew, the Content Lead for [web.dev](https://web.dev) and [developer.chrome.com](/), as part of the Chrome Developer Relations team. I've been working on the web for over twenty years, with a focus on open web standards and CSS, and am a member of the CSS Working Group. +I'm Rachel Andrew, the Content Lead for [web.dev](https://web.dev) and [developer.chrome.com](/), as part of the Chrome Developer Relations team. I've been working on the web for over twenty years, with a focus on open web standards and CSS, and am a member of the CSS Working Group. Two months ago, we wrapped up [Google I/O](https://io.google/2022/products/web/) where we [shared](https://www.youtube.com/watch?v=qBkyU1TJKDg&t=1452s) some of the most important updates about how we're supporting developers in making the web faster and more powerful while keeping user information safe and private. -One of the things that stood out (and we're glad that the [community took notice](https://twitter.com/marvinhagemeist/status/1525798010587865088)!) is the huge amount of work the team is doing to support more [CSS and UI features](https://web.dev/state-of-css-2022/) on the web. In this edition of Chrome Dev Insider, we will take you behind the scenes on who's behind this work, how we work towards supporting CSS and UI developers and what lies ahead. That's why I'm thrilled to be hosting this edition of the Insider. +One of the things that stood out (and we're glad that the [community took notice](https://twitter.com/marvinhagemeist/status/1525798010587865088)!) is the huge amount of work the team is doing to support more [CSS and UI features](https://web.dev/articles/state-of-css-2022) on the web. In this edition of Chrome Dev Insider, we will take you behind the scenes on who's behind this work, how we work towards supporting CSS and UI developers and what lies ahead. That's why I'm thrilled to be hosting this edition of the Insider. ## In the news -In the first [Chrome Dev Insider](/blog/insider-april-2022/), we shared some updates on [Compat 2021](https://web.dev/compat2021/) and [Interop 2022](https://github.com/web-platform-tests/interop-2022/) initiatives where browser vendors and ecosystem players have been partnering to bring more features to the web that are supported across all browsers. The initiative has a strong focus on CSS because [browser incompatibility is one of the biggest challenges for CSS developers](https://2021.stateofcss.com/en-US/opinions/#css_pain_points_wins). +In the first [Chrome Dev Insider](/blog/insider-april-2022/), we shared some updates on [Compat 2021](https://web.dev/blog/compat2021) and [Interop 2022](https://github.com/web-platform-tests/interop-2022/) initiatives where browser vendors and ecosystem players have been partnering to bring more features to the web that are supported across all browsers. The initiative has a strong focus on CSS because [browser incompatibility is one of the biggest challenges for CSS developers](https://2021.stateofcss.com/en-US/opinions/#css_pain_points_wins). While this may not be news to most, it's exciting to see the progress we've already made across browsers. @@ -56,21 +56,21 @@ While this may not be news to most, it's exciting to see the progress we've alre {% endColumns %} -Earlier last month, we saw Safari [announce a bumper release](https://webkit.org/blog/12824/news-from-wwdc-webkit-features-in-safari-16-beta/) with Safari 16.0 Beta that includes exciting features like [Container Queries](https://developer.mozilla.org/docs/Web/CSS/CSS_Container_Queries), [subgrid](https://developer.mozilla.org/docs/Web/CSS/CSS_Grid_Layout/Subgrid), and a [flexbox inspector](https://webkit.org/blog/12824/news-from-wwdc-webkit-features-in-safari-16-beta/#flexbox-inspector). Recent releases of Firefox and Chrome have included a number of exciting features and fixes—I'm covering the key things in stable and beta browsers each month in my [new to the web platform](https://web.dev/tags/new-to-the-web/) series of posts. +Earlier last month, we saw Safari [announce a bumper release](https://webkit.org/blog/12824/news-from-wwdc-webkit-features-in-safari-16-beta/) with Safari 16.0 Beta that includes exciting features like [Container Queries](https://developer.mozilla.org/docs/Web/CSS/CSS_Container_Queries), [subgrid](https://developer.mozilla.org/docs/Web/CSS/CSS_Grid_Layout/Subgrid), and a [flexbox inspector](https://webkit.org/blog/12824/news-from-wwdc-webkit-features-in-safari-16-beta/#flexbox-inspector). Recent releases of Firefox and Chrome have included a number of exciting features and fixes—I'm covering the key things in stable and beta browsers each month in my [new to the web platform](https://web.dev/articles/tags/new-to-the-web) series of posts. ## Insider scoop: Supporting CSS and UI developers -With 2022 turning out to be an exciting year for CSS features, we thought it a good time to take you behind the scenes. I sat down with [Una Kravets,](https://twitter.com/Una) DevRel lead for Web UI and Devtools and [Nicole Sullivan](https://twitter.com/stubbornella), our Product Manager for Web UI who focuses on CSS and HTML APIs, to talk about Chrome's journey to supporting UI developers. +With 2022 turning out to be an exciting year for CSS features, we thought it a good time to take you behind the scenes. I sat down with [Una Kravets,](https://twitter.com/Una) DevRel lead for Web UI and Devtools and [Nicole Sullivan](https://twitter.com/stubbornella), our Product Manager for Web UI who focuses on CSS and HTML APIs, to talk about Chrome's journey to supporting UI developers. _Let's start with you both. Tell us a bit more about yourselves?_ -**Nicole:** I'm the product manager for Web UI on Chrome. I focus specifically on new CSS and HTML APIs and on developers and designers who build UI. It's an exciting space with some really important APIs coming out like [Container Queries](https://web.dev/new-responsive/#responsive-to-the-container), [Scope](https://developer.mozilla.org/docs/Web/CSS/:scope), and (hopefully!) [vertical rhythm](https://developer.mozilla.org/docs/Learn/CSS/Styling_text/Styling_lists#handling_list_spacing). +**Nicole:** I'm the product manager for Web UI on Chrome. I focus specifically on new CSS and HTML APIs and on developers and designers who build UI. It's an exciting space with some really important APIs coming out like [Container Queries](https://web.dev/articles/new-responsive#responsive_to_the_container), [Scope](https://developer.mozilla.org/docs/Web/CSS/:scope), and (hopefully!) [vertical rhythm](https://developer.mozilla.org/docs/Learn/CSS/Styling_text/Styling_lists#handling_list_spacing). **Una:** I lead the Web UI and DevTools DevRel teams. We focus on supporting UI engineers on the web platform and make sure they have the tools they need to be successful. This includes CSS APIs and HTML components along with DevTools features to see active changes and feedback. _Chrome's support for UI developers has gathered pace in the last few years. Why do you think it took so long to get here? What were the biggest challenges?_ -**Una:** We needed to do some work to demonstrate how important this work was, and why it should be a priority. We started with the [MDN DNA survey in 2019](https://insights.developer.mozilla.org/), which identified UI as some of the top pain points on the platform. And since then, we've continued to use data as our guide through the MDN and our own internal developer satisfaction surveys. The result of all this is we were able to get deeper leadership buy-in and were able to prioritize engineering work around some of the most highly requested developer features in the UI space that also form the majority of the focus for initiatives like [Compat 2021](https://web.dev/compat2021/) and [Interop 2022](https://github.com/web-platform-tests/interop-2022/). +**Una:** We needed to do some work to demonstrate how important this work was, and why it should be a priority. We started with the [MDN DNA survey in 2019](https://insights.developer.mozilla.org/), which identified UI as some of the top pain points on the platform. And since then, we've continued to use data as our guide through the MDN and our own internal developer satisfaction surveys. The result of all this is we were able to get deeper leadership buy-in and were able to prioritize engineering work around some of the most highly requested developer features in the UI space that also form the majority of the focus for initiatives like [Compat 2021](https://web.dev/blog/compat2021) and [Interop 2022](https://github.com/web-platform-tests/interop-2022/). **Nicole:** In addition to getting leadership buy-in, we had to also find the right way to get these APIs to developers. When I first joined Chrome, I messed this up in a project called [Layered APIs](https://github.com/drufball/layered-apis) (or LAPIs for short). LAPIs aimed to give developers a drop-in component experience. I still think this was a great outcome to shoot for, but we made a lot of mistakes! We focused first on [Toast Notifications](https://developer.android.com/guide/topics/ui/notifiers/toasts) and a [Virtual List](https://groups.google.com/a/chromium.org/g/blink-dev/c/5411pauM9e8/m/aX4K4wz6DgAJ). Toasts are nearly impossible to make accessible and a virtual list is one of the hardest components to get right. Our intentions were good but it wasn't helping developers, so we sunsetted the project. It's difficult to learn the hard way, but every mistake is fueling the renaissance for CSS and HTML that is happening now. @@ -94,13 +94,13 @@ _Speaking of cross-browser support, initiatives like Interop 2022 and Open UI se _Working with the ecosystem has proven to be critical to any success we've had in making developers' lives easier. I know that your team has been doing a lot of work there. Care to share some details?_ -**Nicole:** First, I'm constantly in awe of the projects developers build on the web. From the tiniest library to full on frameworks, developers are building amazing things. It's a fantastic community of makers. And Chrome is taking a bunch of steps to be more connected to these projects. +**Nicole:** First, I'm constantly in awe of the projects developers build on the web. From the tiniest library to full on frameworks, developers are building amazing things. It's a fantastic community of makers. And Chrome is taking a bunch of steps to be more connected to these projects. For instance, a few years ago we started working with JavaScript Frameworks such as React and Angular. And metaframeworks—for example Next, Nuxt, and Gatsby. Last year, we started to do the same with UI tools and frameworks such as Sass, Bootstrap, and Material. I hope this coming year we can collaborate with GreenSock and other tools that make developers' lives easier. I just saw Cassie Evans from GreenSock speak at Smashing Conference and it got me really excited about working with folks in the animation space. _So where do we see the biggest opportunity for the Web UI ecosystem?_ -**Una:** In terms of big opportunities, I feel like we're just scratching the surface of what's possible for customizable web experiences. New APIs such as [container queries](https://web.dev/new-responsive/#responsive-to-the-container) and the CSS [user preference media features](https://web.dev/user-preference-media-features-headers/) are redefining the way that developers view responsive design. I'm also excited about the collaborative design experiences that are enabling developers and designers to be able to work in unison with the users that visit their websites. +**Una:** In terms of big opportunities, I feel like we're just scratching the surface of what's possible for customizable web experiences. New APIs such as [container queries](https://web.dev/articles/new-responsive#responsive_to_the_container) and the CSS [user preference media features](https://web.dev/articles/user-preference-media-features-headers) are redefining the way that developers view responsive design. I'm also excited about the collaborative design experiences that are enabling developers and designers to be able to work in unison with the users that visit their websites. _And Nicole, what's next on the roadmap for your team?_ @@ -108,11 +108,11 @@ _And Nicole, what's next on the roadmap for your team?_ Una touched on the first thing, we're enabling responsive, component-based design. It includes tools for designing color systems so designers can respond to user preferences like dark mode. For example, [OKLCH](https://developer.mozilla.org/docs/Web/CSS/color_value/oklch) color space keeps brightness consistent across hues. Designers can move from choosing colors to designing relationships between colors, without ending up with muddy-looking palettes! -We're also working on some of the most requested APIs, like [container queries](https://web.dev/new-responsive/#responsive-to-the-container), [cascade layers](/blog/cascade-layers/), parent selector ([:has](https://developer.mozilla.org/docs/Web/CSS/:has)), [scoped styles](https://css-tricks.com/saving-the-day-with-scoped-css/), and [nesting](https://css-tricks.com/css-nesting-specificity-and-you/). Developers need these so they can build flexible design systems full of reusable components. +We're also working on some of the most requested APIs, like [container queries](https://web.dev/articles/new-responsive#responsive_to_the_container), [cascade layers](/blog/cascade-layers/), parent selector ([:has](https://developer.mozilla.org/docs/Web/CSS/:has)), [scoped styles](https://css-tricks.com/saving-the-day-with-scoped-css/), and [nesting](https://css-tricks.com/css-nesting-specificity-and-you/). Developers need these so they can build flexible design systems full of reusable components. Scroll linked animations is another fun area. I really like Steve Gardner's [demo](https://codepen.io/ste-vg/pen/GRooLza). He has buttery smooth scrolling and cool airplane animations triggered on scroll. While these are fun, it can be tricky to get them right, especially with accessibility in mind. So we're running user testing for accessibility on the feature now. -The thing I'm personally most excited about is built-in web UI controls. Developers keep building the same tabset over and over again, I think the browser can help. Over at [Open UI](https://open-ui.org/), we're working on components like selectmenu, popup, tooltip, tabs, nav, accordion, and toggle. We are exploring what it would look like to bake accessibility into these browser primitives so the web could, over time, become accessible by default. Developers can then focus on the more complex and nuanced problems, while the basics such as how do tabs tab, can be supported by the browser. This probably needs its own post, so I'll stop there for now! +The thing I'm personally most excited about is built-in web UI controls. Developers keep building the same tabset over and over again, I think the browser can help. Over at [Open UI](https://open-ui.org/), we're working on components like selectmenu, popup, tooltip, tabs, nav, accordion, and toggle. We are exploring what it would look like to bake accessibility into these browser primitives so the web could, over time, become accessible by default. Developers can then focus on the more complex and nuanced problems, while the basics such as how do tabs tab, can be supported by the browser. This probably needs its own post, so I'll stop there for now! Finally, we'll continue to invest in **interop** between browsers. It's been great working with folks at WebKit and Gecko to bring consistency to the developer experience. We heard developers loud and clear that they want this! @@ -122,7 +122,7 @@ We might, if standards go well, even look at vertical rhythm this year! We're ab _Thanks both. I'm sure the whole community, like us, is excited to see the renewed pace of improvements and features coming to the Web UI world. There's still a lot to grok, so where would you say one should start their journey?_ -**Una:** Our [What's new for the web platform](https://www.youtube.com/watch?v=5b4YcLB4DVI&t=38s) session at I/O covers the highlights of many of the features landing this year. Adam Argyle also wrote up a [great article](https://web.dev/state-of-css-2022/) on all the new and upcoming CSS landings. On an ongoing basis, I would focus on stable releases for now and just be aware of the other work coming down the pipeline. Your awesome [New to the web platform](https://web.dev/tags/new-to-the-web/) series is a great one to follow for that. Subscribing for the web.dev newsletter will also bring this content to developers' inbox. And for developers looking to get involved and help with all of this, [joining Open UI](https://open-ui.org/get-involved#getting-involved) is one of the best ways you can support this work. +**Una:** Our [What's new for the web platform](https://www.youtube.com/watch?v=5b4YcLB4DVI&t=38s) session at I/O covers the highlights of many of the features landing this year. Adam Argyle also wrote up a [great article](https://web.dev/articles/state-of-css-2022) on all the new and upcoming CSS landings. On an ongoing basis, I would focus on stable releases for now and just be aware of the other work coming down the pipeline. Your awesome [New to the web platform](https://web.dev/articles/tags/new-to-the-web) series is a great one to follow for that. Subscribing for the web.dev newsletter will also bring this content to developers' inbox. And for developers looking to get involved and help with all of this, [joining Open UI](https://open-ui.org/get-involved#getting-involved) is one of the best ways you can support this work. ## Key upcoming updates diff --git a/site/en/blog/insider-oct-2022/index.md b/site/en/blog/insider-oct-2022/index.md index e2a9e70b1..4071fcc1b 100644 --- a/site/en/blog/insider-oct-2022/index.md +++ b/site/en/blog/insider-oct-2022/index.md @@ -13,7 +13,7 @@ authors: tags: - insider - + hero: 'image/kheDArv5csY6rvQUJDbWRscckLr1/5pfwyFL3CsjaWdvjG7DM.png' thumbnail: 'image/kheDArv5csY6rvQUJDbWRscckLr1/FEhZwqV3W5kVUciPDV29.png' @@ -30,7 +30,7 @@ A small team here at Chrome has been working on a project called [Aurora](/blog/ For the third edition of the Chrome Dev Insider, I spoke with [Addy Osmani](https://twitter.com/addyosmani), [Kara Erickson](https://twitter.com/karaforthewin), and [Houssein Djirdeh](https://twitter.com/hdjirdeh) from the Project Aurora team to learn more about how they've been approaching this project and what lies ahead for them. -## Insider scoop: Working with third party frameworks +## Insider scoop: Working with third party frameworks _**Let's start with the genesis of this project. How did it come about?**_ @@ -50,15 +50,15 @@ So our thinking is if developers have limited time to devote to performance, let **If I understand correctly, you're a team of what, six engineers? I bet you can't work with every possible framework or library. So how do you pick who to work with? And who are they?** -**Addy:** The web is in many ways like the wild wild west. You can choose pretty much whatever framework, bundler, libraries, and third-parties you want. This introduces several layers of complexity that can contribute to good or poor performance. One of the best ways to move the needle on performance is to find those layers comfortable being opinionated and adding more opinions to them. +**Addy:** The web is in many ways like the wild wild west. You can choose pretty much whatever framework, bundler, libraries, and third-parties you want. This introduces several layers of complexity that can contribute to good or poor performance. One of the best ways to move the needle on performance is to find those layers comfortable being opinionated and adding more opinions to them. -For example, web frameworks (Next.js, Nuxt.js, and to an extent Angular) try to bake in more opinions and defaults than a more hand-rolled solution. This is one reason we love working with them! Having stronger defaults for how to load images, fonts and scripts for better Core Web Vitals makes sense in these models. +For example, web frameworks (Next.js, Nuxt.js, and to an extent Angular) try to bake in more opinions and defaults than a more hand-rolled solution. This is one reason we love working with them! Having stronger defaults for how to load images, fonts and scripts for better Core Web Vitals makes sense in these models. It also serves as a nice way to confirm where modern best-practices work or may need a rethink and can help inform the whole ecosystem about how to approach solving optimization problems. -**Kara:** Realistically, we also have to consider popularity. If we want to have the largest possible impact on the web, working with frameworks and libraries that have a large existing community of developers is ideal. We can reach more developers and more apps that way. But it can't be just popularity. Ultimately, it's an intersection of popularity, how opinionated a library is, and the available feature set we can work with. +**Kara:** Realistically, we also have to consider popularity. If we want to have the largest possible impact on the web, working with frameworks and libraries that have a large existing community of developers is ideal. We can reach more developers and more apps that way. But it can't be just popularity. Ultimately, it's an intersection of popularity, how opinionated a library is, and the available feature set we can work with. -For example, if we look at popularity alone, React, Vue, and Angular are the "big three" to consider. But we work with Next.js, Nuxt, and Angular the most. This is because view libraries like React and Vue mostly focus on rendering, so it's impossible to build all the features we want into them directly. So we work more closely with opinionated meta-frameworks built on top of them: Next.js and Nuxt. At this level of abstraction, we can create built-in components. They also have built-in servers, so we can include server-side optimizations. +For example, if we look at popularity alone, React, Vue, and Angular are the "big three" to consider. But we work with Next.js, Nuxt, and Angular the most. This is because view libraries like React and Vue mostly focus on rendering, so it's impossible to build all the features we want into them directly. So we work more closely with opinionated meta-frameworks built on top of them: Next.js and Nuxt. At this level of abstraction, we can create built-in components. They also have built-in servers, so we can include server-side optimizations. You might notice that Angular was on that list of deep partnerships, but it's not a meta-framework. Angular is somewhat of a special case because it's quite popular, but doesn't have a complementary meta-framework the way React and Vue do. So we work with them directly and contribute features through their CLI where possible. @@ -72,13 +72,13 @@ It's really important to us to validate that the performance impact is what we p **All this can't be as easy as you're making it sound. What were some of the challenges or learnings that you've had so far?** -**Houssein:** One important thing we try to navigate to the best of our ability is contributing to popular open-source repositories that have many competing priorities. Just because we're a Google team doesn't necessarily mean that our features will get prioritized, so we try our best to align with the typical process of proposing and shipping new features without stepping on anyone's toes. We've been very fortunate to work with receptive maintainers in the Next.js, Nuxt, and Angular ecosystems. We're grateful that they have been open to listening to our concerns about the web ecosystem and willing to collaborate with us in more ways than one. - -With many of the frameworks that we work with, our overall mission is the same; how can developers get an improved user experience out of the box while also enjoying a great developer experience? We're aware and respect that there are hundreds, if not thousands, of community contributors and framework maintainers each working on different projects that intersect with each other. +**Houssein:** One important thing we try to navigate to the best of our ability is contributing to popular open-source repositories that have many competing priorities. Just because we're a Google team doesn't necessarily mean that our features will get prioritized, so we try our best to align with the typical process of proposing and shipping new features without stepping on anyone's toes. We've been very fortunate to work with receptive maintainers in the Next.js, Nuxt, and Angular ecosystems. We're grateful that they have been open to listening to our concerns about the web ecosystem and willing to collaborate with us in more ways than one. + +With many of the frameworks that we work with, our overall mission is the same; how can developers get an improved user experience out of the box while also enjoying a great developer experience? We're aware and respect that there are hundreds, if not thousands, of community contributors and framework maintainers each working on different projects that intersect with each other. **Kara:** Additionally, because we care about validating performance impact and acting based on data, the process takes a bit more time. We're in uncharted territory, so sometimes we'll experiment with an optimization that doesn't pan out and we don't end up building a planned feature. Even when a feature does pan out, those few extra steps to vet performance take time and extend timelines. -Finding production partners to test our features can also be challenging. As previously mentioned, they are businesses and have their own priorities, so it can be challenging for them to fit in new initiatives if they don't align well with existing projects which have to come first. In addition, the companies most interested in helping tend to be already taking the time to invest in performance, so they're not really our target audience. We're trying to collect feedback from the large swath of the community that *can't* invest in performance, but they're the least likely to reach out to us. +Finding production partners to test our features can also be challenging. As previously mentioned, they are businesses and have their own priorities, so it can be challenging for them to fit in new initiatives if they don't align well with existing projects which have to come first. In addition, the companies most interested in helping tend to be already taking the time to invest in performance, so they're not really our target audience. We're trying to collect feedback from the large swath of the community that *can't* invest in performance, but they're the least likely to reach out to us. **Moving on, what kind of optimizations have you been focusing on?** @@ -101,7 +101,7 @@ Our work has inspired other frameworks and tools to implement similar optimizati **Can you share some positive outcomes of your work with some of these players?** -**Houssein:** Many sites have seen performance improvements due to the optimizations we've shipped. One of my favorite examples is [Leboncoin](https://www.leboncoin.fr/), who [reduced their LCP](https://medium.com/leboncoin-engineering-blog/how-we-are-improving-our-web-performance-9f850d59d810) from 2.4s to 1.7s after they switched to the Next.js image component. There are many more currently in experimentation and testing phases and we'll continue to share learnings and wins from those [here](http://developer.chrome.com/tags/aurora-project/). +**Houssein:** Many sites have seen performance improvements due to the optimizations we've shipped. One of my favorite examples is [Leboncoin](https://www.leboncoin.fr/), who [reduced their LCP](https://medium.com/leboncoin-engineering-blog/how-we-are-improving-our-web-performance-9f850d59d810) from 2.4s to 1.7s after they switched to the Next.js image component. There are many more currently in experimentation and testing phases and we'll continue to share learnings and wins from those [here](http://developer.chrome.com/tags/aurora-project/). **Ok, I get that your focus is on those that have the most popularity, but are there ways that other frameworks or libraries who you aren't working with proactively also benefit?** @@ -116,7 +116,7 @@ At the same time, we understand that not every framework will have the bandwidth **Kara:** We have a lot of exciting projects coming up! Some highlights: - **Reducing font-related CLS:** It's fairly common to see layout shifts when a web font is loaded and replaces the fallback font. We're exploring using font metric overrides and the "size-adjust" property to reduce font-related CLS by default in Next.js. We've also been consulting with the Nuxt team on this and plan to extend this idea to more frameworks next year. -- **Debugging INP:** Now that the [Interaction to Next Paint (INP)](https://web.dev/inp/) metric has been released, we're working with frameworks to investigate the most common root causes of INP issues for their communities and suggest fixes. We've been partnering closely with Angular on this and hope to have some results to share soon! +- **Debugging INP:** Now that the [Interaction to Next Paint (INP)](https://web.dev/articles/inp) metric has been released, we're working with frameworks to investigate the most common root causes of INP issues for their communities and suggest fixes. We've been partnering closely with Angular on this and hope to have some results to share soon! - **Optimizing common 3P scripts:** Loading third-party scripts at the wrong time can have a substantial negative impact on performance. Since there are a few 3Ps that are very common, we are looking into whether we can offer some wrappers for these to ensure they are loaded optimally with frameworks and don't block the main thread. We are using the Next.js script component we built as a starting point for this investigation. Developers can follow our progress on [this site](/tags/aurora-project/). @@ -131,6 +131,6 @@ And, of course, there's also a TON of amazing things happening in the community. I get genuinely excited seeing the ecosystem coming together, pushing what's possible in the browser and helping developers build products that work for everyone. It's an exciting time to be a web developer. -Until the next Insider, Hwyl fawr. +Until the next Insider, Hwyl fawr. _What did you think of this edition of The Chrome Dev Insider? [Share your feedback](https://docs.google.com/forms/d/e/1FAIpQLSeyAnJV9rVb4PdaHD8Q2lHLnPQO2UOv7fYAX6hnetXSnF6wEg/viewform)._ diff --git a/site/en/blog/introducing-aurora/index.md b/site/en/blog/introducing-aurora/index.md index 69819b5ea..1c88a44b9 100644 --- a/site/en/blog/introducing-aurora/index.md +++ b/site/en/blog/introducing-aurora/index.md @@ -176,7 +176,7 @@ defaults of multiple frameworks, including: [Next.js](https://nextjs.org/docs/advanced-features/measuring-performance) to allow easier insight into page performance through web vitals and other custom metrics. -- [Granular chunking](https://web.dev/granular-chunking-nextjs/) shipped in Next.js and Gatsby, +- [Granular chunking](https://web.dev/articles/granular-chunking-nextjs) shipped in Next.js and Gatsby, resulting in 30 to 70 percent reduction in bundle sizes while improving caching performance. This has become the default in Webpack 5. - A separate [polyfill diff --git a/site/en/blog/introducing-scheduler-yield-origin-trial/index.md b/site/en/blog/introducing-scheduler-yield-origin-trial/index.md index ae4ac4664..f7627d044 100644 --- a/site/en/blog/introducing-scheduler-yield-origin-trial/index.md +++ b/site/en/blog/introducing-scheduler-yield-origin-trial/index.md @@ -16,15 +16,15 @@ tags: - javascript --- -Building websites that respond quickly to user input has been one of the most challenging aspects of web performance—one that the Chrome Team has been working hard to help web developers meet. Just this year, [it was announced](https://web.dev/inp-cwv/) that the [Interaction to Next Paint (INP) metric](https://web.dev/inp/) would graduate from experimental to pending status. It is now poised to replace [First Input Delay (FID)](https://web.dev/fid/) as a Core Web Vital in March of 2024. +Building websites that respond quickly to user input has been one of the most challenging aspects of web performance—one that the Chrome Team has been working hard to help web developers meet. Just this year, [it was announced](https://web.dev/articles/inp-cwv) that the [Interaction to Next Paint (INP) metric](https://web.dev/articles/inp) would graduate from experimental to pending status. It is now poised to replace [First Input Delay (FID)](https://web.dev/articles/fid) as a Core Web Vital in March of 2024. -In a continued effort to deliver new APIs that help web developers make their websites as snappy as they can be, the Chrome Team is currently running an [origin trial for `scheduler.yield`](/origintrials/#/view_trial/836543630784069633) starting in version 115 of Chrome. `scheduler.yield` is a proposed new addition to the scheduler API that allows for both an easier and better way to yield control back to the main thread than [the methods that have been traditionally relied upon](https://web.dev/optimize-long-tasks/#manually-defer-code-execution). +In a continued effort to deliver new APIs that help web developers make their websites as snappy as they can be, the Chrome Team is currently running an [origin trial for `scheduler.yield`](/origintrials/#/view_trial/836543630784069633) starting in version 115 of Chrome. `scheduler.yield` is a proposed new addition to the scheduler API that allows for both an easier and better way to yield control back to the main thread than [the methods that have been traditionally relied upon](https://web.dev/articles/optimize-long-tasks#manually_defer_code_execution). ## On yielding JavaScript uses the run-to-completion model to deal with tasks. This means that, when a task runs on the main thread, that task runs as long as necessary in order to complete. Upon a task's completion, control is _yielded_ back to the main thread, which allows the main thread to process the next task in the queue. -Aside from extreme cases when a task never finishes—such as an infinite loop, for example—yielding is an inevitable aspect of JavaScript's task scheduling logic. It _will_ happen, it's just a matter of _when_, and sooner is better than later. When tasks take too long to run—greater than 50 milliseconds, to be exact—they are considered to be [long tasks](https://web.dev/long-tasks-devtools/#what-are-long-tasks). +Aside from extreme cases when a task never finishes—such as an infinite loop, for example—yielding is an inevitable aspect of JavaScript's task scheduling logic. It _will_ happen, it's just a matter of _when_, and sooner is better than later. When tasks take too long to run—greater than 50 milliseconds, to be exact—they are considered to be [long tasks](https://web.dev/articles/long-tasks-devtools#what_are_long_tasks). Long tasks are a source of poor page responsiveness, because they delay the browser's ability to respond to user input. The more often long tasks occur—and the longer they run—the more likely it is that users may get the impression that the page is sluggish, or even feel that it's altogether broken. @@ -45,7 +45,7 @@ When you explicitly yield, you're telling the browser "hey, I understand that th If you're already familiar with current yielding methods—such as using `setTimeout`—you can jump [straight to the section about `scheduler.yield`](#enter-scheduleryield). {% endAside %} -A common method of yielding [uses `setTimeout` with a timeout value of `0`](https://web.dev/optimize-long-tasks/#use-asyncawait-to-create-yield-points). This works because the callback passed to `setTimeout` will move the remaining work to a separate task that will be queued for subsequent execution. Rather than waiting for the browser to yield on its own, you're saying "let's break this big chunk of work up into smaller bits". +A common method of yielding [uses `setTimeout` with a timeout value of `0`](https://web.dev/articles/optimize-long-tasks#use_asyncawait_to_create_yield_points). This works because the callback passed to `setTimeout` will move the remaining work to a separate task that will be queued for subsequent execution. Rather than waiting for the browser to yield on its own, you're saying "let's break this big chunk of work up into smaller bits". However, yielding with `setTimeout` carries a potentially undesirable side effect: the work that comes _after_ the yield point will go to the back of the task queue. Tasks scheduled by user interactions will still go to the front of the queue as they should—but the remaining work you wanted to do after explicitly yielding could end up being further delayed by other tasks from competing sources that were queued ahead of it. diff --git a/site/en/blog/is-project-fugu-done/index.md b/site/en/blog/is-project-fugu-done/index.md index 058219ea7..166964583 100644 --- a/site/en/blog/is-project-fugu-done/index.md +++ b/site/en/blog/is-project-fugu-done/index.md @@ -110,7 +110,7 @@ of the [`navigator.storage.getDirectory()`](https://fs.spec.whatwg.org/#dom-storagemanager-getdirectory) method, used as an entry point to the origin private file system (OPFS). This method is used, for example, for -[Photoshop's high performance storage](https://web.dev/ps-on-the-web/#high-performance-storage) +[Photoshop's high performance storage](https://web.dev/articles/ps-on-the-web#high_performance_storage) needs, and which the storage community is [highly interested in](/blog/deprecating-web-sql/#rationale-for-leaving-storage-to-web-developers) since the started deprecation of Web SQL and even before. @@ -125,9 +125,9 @@ a Wasm context, and since this is happening in a worker, the main thread can't b ## Privacy improvements for the hardware APIs -Another example are the [hardware APIs](https://web.dev/tags/devices/) that allow you to connect to -[HID](https://web.dev/hid/), [serial](https://web.dev/serial/), [USB](https://web.dev/usb/), -[Bluetooth](https://web.dev/bluetooth/), and [NFC](https://web.dev/nfc/) devices. While some of +Another example are the [hardware APIs](https://web.dev/articles/tags/devices) that allow you to connect to +[HID](https://web.dev/articles/hid), [serial](https://web.dev/articles/serial), [USB](https://web.dev/articles/usb), +[Bluetooth](https://web.dev/articles/bluetooth), and [NFC](https://web.dev/articles/nfc) devices. While some of these APIs have been around for a while, until recently there was no way to forget a device that you had previously connected to. Now there is thanks to the [`forget()`](https://wicg.github.io/serial/#forget-method) methods for some of the APIs. For @@ -144,7 +144,7 @@ await port.forget(); ## Refinements for the Multi-Screen Window Placement API A final example is the -[Multi-Screen Window Placement API](https://web.dev/multi-screen-window-placement/), where, based on +[Multi-Screen Window Placement API](https://web.dev/articles/multi-screen-window-placement), where, based on developer feedback, the previously generic screen labels like `"Internal Display 1"` were replaced with more meaningful labels like `"Built-in Retina Display"` so users can more easily associate these labels with the screens of their multi-screen setup. @@ -160,7 +160,7 @@ as you can and provide simple instructions for reproducing. And, if you are concerned about browser support, many Fugu APIs make for great progressive enhancements. See my article -[SVGcode: a PWA to convert raster images to SVG vector graphics](https://web.dev/svgcode/) for +[SVGcode: a PWA to convert raster images to SVG vector graphics](https://web.dev/articles/svgcode) for inspiration. We also don't consider our job done until these APIs are interoperable, and we will continue to push for further standardization, testing, and adoption by other browsers. diff --git a/site/en/blog/lets-build-some-apps-with-polymer/index.md b/site/en/blog/lets-build-some-apps-with-polymer/index.md index f481af6ae..103fabda8 100644 --- a/site/en/blog/lets-build-some-apps-with-polymer/index.md +++ b/site/en/blog/lets-build-some-apps-with-polymer/index.md @@ -117,7 +117,7 @@ Vulcanize will concatenate your imports into a single bundle, *significantly* re But just building a performant app doesn't solve the dilemma of a user with little or no connectivity. In other words, if your app doesn't work offline, then it's not really a mobile app. Today you can use [the much maligned application cache](https://alistapart.com/article/application-cache-is-a-douchebag) to offline your resources, but looking to the future, [Service Worker](https://developers.google.com/web/fundamentals/getting-started/primers/service-workers) should soon make the offline development experience much nicer. -Jake Archibald has recently published an amazing [cookbook of service worker patterns](https://web.dev/offline-cookbook/) but I'll give you the quick start to get you going: +Jake Archibald has recently published an amazing [cookbook of service worker patterns](https://web.dev/articles/offline-cookbook) but I'll give you the quick start to get you going: Installing a service worker is quit easy. Create a `worker.js` file, and register it when your application boots up. diff --git a/site/en/blog/lighthouse-10-0/index.md b/site/en/blog/lighthouse-10-0/index.md index fac3da276..7122de767 100644 --- a/site/en/blog/lighthouse-10-0/index.md +++ b/site/en/blog/lighthouse-10-0/index.md @@ -20,9 +20,9 @@ Lighthouse 10 is available immediately on the [command line through npm](https:/ ## Scoring changes -The venerable [Time To Interactive (TTI)](https://web.dev/tti/) metric is being removed in Lighthouse 10, concluding the [deprecation process started in Lighthouse 8](https://github.com/GoogleChrome/lighthouse/blob/main/docs/v8-perf-faq.md#whats-the-story-with-tti). TTI's 10% score weight is shifting to [Cumulative Layout Shift (CLS)](https://web.dev/cls/), which will now account for 25% of the [overall performance score](/docs/lighthouse/performance/performance-scoring/#lighthouse-10). +The venerable [Time To Interactive (TTI)](https://web.dev/articles/tti) metric is being removed in Lighthouse 10, concluding the [deprecation process started in Lighthouse 8](https://github.com/GoogleChrome/lighthouse/blob/main/docs/v8-perf-faq.md#whats-the-story-with-tti). TTI's 10% score weight is shifting to [Cumulative Layout Shift (CLS)](https://web.dev/articles/cls), which will now account for 25% of the [overall performance score](/docs/lighthouse/performance/performance-scoring/#lighthouse-10). -TTI marks a point in time, but the way it's defined makes it overly sensitive to outlier network requests and long tasks. [Largest Contentful Paint (LCP)](/docs/lighthouse/performance/lighthouse-largest-contentful-paint/) and [Speed Index](/docs/lighthouse/performance/speed-index/) are usually better heuristics for a page's contents feeling loaded than a count of active network requests. [Total Blocking Time (TBT)](/docs/lighthouse/performance/lighthouse-total-blocking-time/) meanwhile handles long tasks and main-thread availability more robustly, and while not a direct proxy, tends to correlate better with [Core Web Vitals](https://web.dev/vitals/#core-web-vitals) as measured in the field. +TTI marks a point in time, but the way it's defined makes it overly sensitive to outlier network requests and long tasks. [Largest Contentful Paint (LCP)](/docs/lighthouse/performance/lighthouse-largest-contentful-paint/) and [Speed Index](/docs/lighthouse/performance/speed-index/) are usually better heuristics for a page's contents feeling loaded than a count of active network requests. [Total Blocking Time (TBT)](/docs/lighthouse/performance/lighthouse-total-blocking-time/) meanwhile handles long tasks and main-thread availability more robustly, and while not a direct proxy, tends to correlate better with [Core Web Vitals](https://web.dev/articles/vitals#core_web_vitals) as measured in the field. CLS's increased weight is incidental to TTI's removal, but better reflects its importance as a Core Web Vital and will ideally increase focus for sites that still make unnecessary layout shifts. @@ -40,7 +40,7 @@ Lighthouse 10 brings a brand new performance audit and a significant change to a ### Back/forward cache {: #bfcache } -The [back/forward cache (bfcache)](https://web.dev/bfcache/) is one of the most powerful tools available for improving a page's performance for real users. Beyond the normal browser cache, a page loaded from the bfcache will restore page layout and execution state nearly instantly, largely skipping all page load activity and getting your page in front of your users immediately as they navigate backward and forward through their history. +The [back/forward cache (bfcache)](https://web.dev/articles/bfcache) is one of the most powerful tools available for improving a page's performance for real users. Beyond the normal browser cache, a page loaded from the bfcache will restore page layout and execution state nearly instantly, largely skipping all page load activity and getting your page in front of your users immediately as they navigate backward and forward through their history. There are a few ways that a page can prevent the browser from restoring a page from the bfcache, however. This new Lighthouse audit actually navigates away from the test page and back again to test if it's bfcache-able, and lists the reasons if it fails. @@ -60,7 +60,7 @@ The new audit is now ["Allows users to paste into input fields" (`paste-preventi If you use Lighthouse as a Node library, there are a few programmatic breaking changes in this release you may need to account for. See the [10.0 changelog](https://github.com/GoogleChrome/lighthouse/releases/tag/v10.0.0) for full details. -Lighthouse 10 also ships with full TypeScript type declarations! Anything imported from `lighthouse` should now be typed, which should be particularly helpful if you're scripting [Lighthouse user flows](https://web.dev/lighthouse-user-flows/). +Lighthouse 10 also ships with full TypeScript type declarations! Anything imported from `lighthouse` should now be typed, which should be particularly helpful if you're scripting [Lighthouse user flows](https://web.dev/articles/lighthouse-user-flows). <figure> {% Img src="image/MtjnObpuceYe3ijODN3a79WrxLU2/VlPiDhDRI96PCBWyPm7x.png", alt="A Node script importing Lighthouse as a function, demonstrating that the options object passed into the function is now type checked by TypeScript", width="562", height="199" %} diff --git a/site/en/blog/lighthouse-11-0/index.md b/site/en/blog/lighthouse-11-0/index.md index b906ddb7e..594973ef6 100644 --- a/site/en/blog/lighthouse-11-0/index.md +++ b/site/en/blog/lighthouse-11-0/index.md @@ -57,7 +57,7 @@ This emphasizes that passing all the automated audits and scoring a 100 in acces ### Interaction to Next Paint (INP) -INP is [no longer experimental](https://web.dev/inp-cwv/), so the metric has been moved from `experimental-interaction-to-next-paint` to `interaction-to-next-paint`. +INP is [no longer experimental](https://web.dev/articles/inp-cwv), so the metric has been moved from `experimental-interaction-to-next-paint` to `interaction-to-next-paint`. ### Service workers diff --git a/site/en/blog/lighthouse-8-4/index.md b/site/en/blog/lighthouse-8-4/index.md index cf363f965..d11df2deb 100644 --- a/site/en/blog/lighthouse-8-4/index.md +++ b/site/en/blog/lighthouse-8-4/index.md @@ -11,10 +11,10 @@ tags: - lighthouse - chrome-95 --- -Lighthouse is an automated website auditing tool that helps developers with opportunities and diagnostics to improve the user experience of their sites. It's available in Chrome DevTools, npm (as a Node module and a CLI), or as a browser extension (in [Chrome](https://chrome.google.com/webstore/detail/lighthouse/blipmdconlkpinefehnmjammfjpmpbjk) and [Firefox](https://addons.mozilla.org/en-US/firefox/addon/google-lighthouse/)). It powers many Google services, including [web.dev/measure](https://web.dev/measure/) and [PageSpeed Insights](https://developers.google.com/speed/pagespeed/insights). +Lighthouse is an automated website auditing tool that helps developers with opportunities and diagnostics to improve the user experience of their sites. It's available in Chrome DevTools, npm (as a Node module and a CLI), or as a browser extension (in [Chrome](https://chrome.google.com/webstore/detail/lighthouse/blipmdconlkpinefehnmjammfjpmpbjk) and [Firefox](https://addons.mozilla.org/en-US/firefox/addon/google-lighthouse/)). It powers many Google services, including [web.dev/measure](https://web.dev/articles/measure) and [PageSpeed Insights](https://developers.google.com/speed/pagespeed/insights). Lighthouse 8.4 is available immediately on the command line and in [Chrome Canary](https://www.google.com/chrome/canary/). -It will land in Chrome Stable in Chrome 95 and be available in [PageSpeed Insights](https://web.dev/whats-new-pagespeed-insights/) within a week. +It will land in Chrome Stable in Chrome 95 and be available in [PageSpeed Insights](https://web.dev/articles/whats-new-pagespeed-insights) within a week. To try the Lighthouse Node CLI, use the following commands: @@ -31,7 +31,7 @@ See the full list of changes in the [8.4 changelog](https://github.com/GoogleChr Lazy-loading images can be an effective way to defer offscreen images so they don't interfere with loading the content that is [above the fold](https://web-dev.imgix.net/image/admin/t3Kkvh265zi6naTBga41.png?auto=format&w=845). -However, if a page's [LCP](https://web.dev/lcp/) element is an image, lazy-loading it can have a significant negative effect on the LCP. The browser may put the image in the queue and fetch other resources first, instead of prioritizing the image for immediate download. A [recent study of lazy-loading in WordPress](https://web.dev/lcp-lazy-loading/) found that LCP can improve by as much as 15% for some sites if images in the initial viewport are not lazy-loaded. +However, if a page's [LCP](https://web.dev/articles/lcp) element is an image, lazy-loading it can have a significant negative effect on the LCP. The browser may put the image in the queue and fetch other resources first, instead of prioritizing the image for immediate download. A [recent study of lazy-loading in WordPress](https://web.dev/articles/lcp-lazy-loading) found that LCP can improve by as much as 15% for some sites if images in the initial viewport are not lazy-loaded. {% Img src="image/MtjnObpuceYe3ijODN3a79WrxLU2/u9nepJj3wgpMgoNxSaDZ.png", alt="The lazy-loaded LCP audit in a Lighthouse report", width="800", height="502", class="screenshot" %} @@ -43,7 +43,7 @@ For more information, see the [initial proposal](https://github.com/GoogleChrome The `viewport` audit has been a part of the Best Practices category for years, but 8.4 welcomes this advice to the Performance category as well. -Many mobile browsers support "double tap to zoom" to allow users to easily magnify content not designed for a mobile screen, that is, content without an explicit mobile `<meta name="viewport">`. In practice, this means the browser [needs to wait as much as 300 ms after a user tap](https://developers.google.com/web/updates/2013/12/300ms-tap-delay-gone-away) to see if a second tap will follow, and during that time the page can't respond to the initial tap. This translates to a [failing FID](https://web.dev/fid/) of several hundred milliseconds. +Many mobile browsers support "double tap to zoom" to allow users to easily magnify content not designed for a mobile screen, that is, content without an explicit mobile `<meta name="viewport">`. In practice, this means the browser [needs to wait as much as 300 ms after a user tap](https://developers.google.com/web/updates/2013/12/300ms-tap-delay-gone-away) to see if a second tap will follow, and during that time the page can't respond to the initial tap. This translates to a [failing FID](https://web.dev/articles/fid) of several hundred milliseconds. {% Img src="image/MtjnObpuceYe3ijODN3a79WrxLU2/FN6XOPqkFfZ8Ii9fIQOm.png", alt="The mobile-viewport audit in a Lighthouse report", width="800", height="344", class="screenshot" %} diff --git a/site/en/blog/lighthouse-9-0/index.md b/site/en/blog/lighthouse-9-0/index.md index bfdfb9c62..83066d34a 100644 --- a/site/en/blog/lighthouse-9-0/index.md +++ b/site/en/blog/lighthouse-9-0/index.md @@ -32,7 +32,7 @@ Puppeteer is used to script page loads and trigger synthetic user interactions, {% Img src="image/MtjnObpuceYe3ijODN3a79WrxLU2/SpZcfNnbmKnbub3l8FWe.png", alt="A Lighthouse user-flow report, which includes multiple steps of loading and interacting with a website, and Lighthouse audit results for each step", width="800", height="450", class="screenshot" %} -For more information, see the [Lighthouse user flows tutorial and code samples](https://web.dev/lighthouse-user-flows/). +For more information, see the [Lighthouse user flows tutorial and code samples](https://web.dev/articles/lighthouse-user-flows). ## Report refresh {: #report-refresh } @@ -50,7 +50,7 @@ To see the new report in action, try out Lighthouse 9.0 or visit this [example r ## Related accessibility elements {: #related-accessibility-elements } -A common accessibility problem is when things that are supposed to be unique in a page are not, for instance if the id referenced in a `aria-labelledby` attribute is [used on multiple elements](https://web.dev/duplicate-id-aria/). +A common accessibility problem is when things that are supposed to be unique in a page are not, for instance if the id referenced in a `aria-labelledby` attribute is [used on multiple elements](https://web.dev/articles/duplicate-id-aria). Lighthouse has always warned about this situation, but would only list the _first_ instance of an element with a repeated ID, which often caused confusion because some users would assume it was showing _all_ elements causing an issue. Since Lighthouse was only showing a single element, they'd assume it was a bug that the single element was being flagged as a duplicate. @@ -64,7 +64,7 @@ For more information, see the [issue collecting user reports](https://github.com ## Running Lighthouse {: #running-lighthouse } -Lighthouse is available in Chrome DevTools, [npm](https://www.npmjs.com/package/lighthouse) (as a Node module and a CLI), and as a browser extension (in [Chrome](https://chrome.google.com/webstore/detail/lighthouse/blipmdconlkpinefehnmjammfjpmpbjk) and [Firefox](https://addons.mozilla.org/en-US/firefox/addon/google-lighthouse/)). It powers many Google services, including [web.dev/measure](https://web.dev/measure/) and [PageSpeed Insights](https://developers.google.com/speed/pagespeed/insights). +Lighthouse is available in Chrome DevTools, [npm](https://www.npmjs.com/package/lighthouse) (as a Node module and a CLI), and as a browser extension (in [Chrome](https://chrome.google.com/webstore/detail/lighthouse/blipmdconlkpinefehnmjammfjpmpbjk) and [Firefox](https://addons.mozilla.org/en-US/firefox/addon/google-lighthouse/)). It powers many Google services, including [web.dev/measure](https://web.dev/articles/measure) and [PageSpeed Insights](https://developers.google.com/speed/pagespeed/insights). To try the Lighthouse Node CLI, use the following commands: diff --git a/site/en/blog/lighthouse-load-performance/index.md b/site/en/blog/lighthouse-load-performance/index.md index e407f17be..477f0d33b 100644 --- a/site/en/blog/lighthouse-load-performance/index.md +++ b/site/en/blog/lighthouse-load-performance/index.md @@ -99,7 +99,7 @@ evaluation, parsing, and compiling time for scripts on a page.</figcaption> </figure> When you run this audit, you can also [enable third party badges in the network -panel](https://web.dev/optimizing-content-efficiency-loading-third-party-javascript/#chrome-devtools-third-party-script-badging) +panel](https://web.dev/articles/optimizing-content-efficiency-loading-third-party-javascript#chrome_devtools_third_party_script_badging) and filter the list to identify third party script resources. With the data from this audit, you'll be better equipped to find sources of excessive JavaScript activity that turn pages from snappy to laggy. For scripts specific to your @@ -170,7 +170,7 @@ the `lighthouse:full` configuration profile. While much performance advice tends to focus on boosting the speed of a website for first time users, it's also important to [use -caching](https://web.dev/http-cache/) +caching](https://web.dev/articles/http-cache) to improve loading performance for returning users. [**The Uses Inefficient Cache Policy on Static Assets**](/docs/lighthouse/performance/uses-long-cache-ttl) audit inspects caching headers for network resources, and notifies you if cache @@ -253,7 +253,7 @@ If Lighthouse finds web fonts in your application that are delaying text rendering, there's a few potential remedies. You can control text rendering with the [`font-display` CSS property](https://css-tricks.com/font-display-masses/), and/or [the Font Loading -API](https://web.dev/fast/#optimize-webfonts). +API](https://web.dev/articles/fast#optimize_webfonts). If you want to dig deeper, consider reading [_A Comprehensive Guide to Font Loading Strategies_](https://www.zachleat.com/web/comprehensive-webfonts/), an excellent guide by [Zach Leatherman](https://www.zachleat.com/web/) which is an @@ -261,7 +261,7 @@ excellent resource for optimal font loading. ## Unminified CSS & JavaScript -[Minification](https://web.dev/decrease-frontend-size/#enable-minification) +[Minification](https://web.dev/articles/decrease-frontend-size#enable_minification) has been a suggested technique since web performance has been a thing, and for good reason. It significantly reduces the size of text-based resources, which in turn is good for loading performance. However, it's easy to overlook this diff --git a/site/en/blog/media-query-range-syntax/index.md b/site/en/blog/media-query-range-syntax/index.md index 84befe3dc..2b2cc9052 100644 --- a/site/en/blog/media-query-range-syntax/index.md +++ b/site/en/blog/media-query-range-syntax/index.md @@ -15,11 +15,11 @@ hero: 'image/kheDArv5csY6rvQUJDbWRscckLr1/iEJSP53ORdmspFCpJBIJ.jpg' alt: > Three measures. --- -Media Queries enabled [responsive design](https://web.dev/learn/design/), and the range features that enable testing the minimum and maximum size of the viewport are used [by around 80% of sites](https://almanac.httparchive.org/en/2021/css#media-features-in-use) that use media queries. The Media Queries Level 4 specification includes a new syntax for these range queries. +Media Queries enabled [responsive design](https://web.dev/learn/design), and the range features that enable testing the minimum and maximum size of the viewport are used [by around 80% of sites](https://almanac.httparchive.org/en/2021/css#media-features-in-use) that use media queries. The Media Queries Level 4 specification includes a new syntax for these range queries. {% BrowserCompat 'css.at-rules.media.range_syntax' %} -The new syntax has been available in Firefox since Firefox 63, and will be available in Chrome from 104. Let’s take a look at how it can streamline your queries. +The new syntax has been available in Firefox since Firefox 63, and will be available in Chrome from 104. Let’s take a look at how it can streamline your queries. A typical media query testing for a minimum viewport width, would be written as follows: diff --git a/site/en/blog/memory-and-energy-saver-mode/index.md b/site/en/blog/memory-and-energy-saver-mode/index.md index d5d6a77f8..bbc12dde6 100644 --- a/site/en/blog/memory-and-energy-saver-mode/index.md +++ b/site/en/blog/memory-and-energy-saver-mode/index.md @@ -140,7 +140,7 @@ The main scenario where this mode _could_ be problematic is if your site uses Ja For example, if your site uses `requestAnimationFrame()` loops and assumes that exactly 16.67 milliseconds will have elapsed between callbacks, your animations will run twice as slow when Energy Saver mode is enabled. -Note that it has [always been problematic](https://web.dev/speed-rendering/#timing-is-everything-requestanimationframe) for developers to assume a default refresh rate of 60 Hz for all users, since that is not true for many current devices. +Note that it has [always been problematic](https://web.dev/articles/speed-rendering#timing_is_everything_requestanimationframe) for developers to assume a default refresh rate of 60 Hz for all users, since that is not true for many current devices. ### Measuring display refresh rate diff --git a/site/en/blog/mini-infobar-update/index.md b/site/en/blog/mini-infobar-update/index.md index 0bb98e96a..8b4ac4ab6 100644 --- a/site/en/blog/mini-infobar-update/index.md +++ b/site/en/blog/mini-infobar-update/index.md @@ -18,7 +18,7 @@ updated: 2019-07-25 ## Background on Progressive Web Apps and the mini-infobar -[Progressive Web Apps (PWA)](https://web.dev/progressive-web-apps/) are a pattern for +[Progressive Web Apps (PWA)](https://web.dev/explore/progressive-web-apps) are a pattern for creating app-like, instant loading, reliable and installable websites. When your PWA passes the diff --git a/site/en/blog/modernising-css-infra-in-devtools/index.md b/site/en/blog/modernising-css-infra-in-devtools/index.md index 767134715..0244a0a14 100644 --- a/site/en/blog/modernising-css-infra-in-devtools/index.md +++ b/site/en/blog/modernising-css-infra-in-devtools/index.md @@ -28,7 +28,7 @@ DevTools implemented CSS in two different ways: one for CSS files used in the [l The CSS implementation in DevTools was defined many years ago and is now outdated. DevTools has stuck to using the [`module.json` pattern](/blog/migrating-to-js-modules/#beginning ) and there has been a huge effort in removing these files. The last blocker for removal of these files is the `resources` section, which is used to load in CSS files. -We wanted to spend time exploring different potential solutions that could eventually morph into [CSS Module Scripts](https://web.dev/css-module-scripts/). The aim was to remove technical debt caused by the legacy system but also make the migration process to CSS Module Scripts easier. +We wanted to spend time exploring different potential solutions that could eventually morph into [CSS Module Scripts](https://web.dev/articles/css-module-scripts). The aim was to remove technical debt caused by the legacy system but also make the migration process to CSS Module Scripts easier. Any CSS files that were in DevTools were considered to be ‘legacy’ as they were loaded using a `module.json` file, which is in the process of being removed. All CSS files had to be listed under `resources` in a `module.json` file in the same directory as the CSS file. @@ -107,7 +107,7 @@ const output = LitHtml.html` ``` Potential solutions using `@import` or `<link>`. -Instead we opted to find a way to import the CSS file as a [`CSSStyleSheet`](https://developer.mozilla.org/docs/Web/API/CSSStyleSheet) object so that we can add it to the [Shadow Dom](https://web.dev/shadowdom-v1) (DevTools uses Shadow DOM for a couple of years now) using its [`adoptedStyleSheets`](https://web.dev/constructable-stylesheets/#using-constructed-stylesheets) property. +Instead we opted to find a way to import the CSS file as a [`CSSStyleSheet`](https://developer.mozilla.org/docs/Web/API/CSSStyleSheet) object so that we can add it to the [Shadow Dom](https://web.dev/shadowdom-v1) (DevTools uses Shadow DOM for a couple of years now) using its [`adoptedStyleSheets`](https://web.dev/articles/constructable-stylesheets#using_constructed_stylesheets) property. ### Bundler options {: #bundler-options } diff --git a/site/en/blog/new-in-chrome-101/index.md b/site/en/blog/new-in-chrome-101/index.md index 44280a2cb..56eebe27b 100644 --- a/site/en/blog/new-in-chrome-101/index.md +++ b/site/en/blog/new-in-chrome-101/index.md @@ -49,12 +49,12 @@ In the example below, a low priority image is indicated with `fetchpriority="low <img src="/images/in_viewport_but_not_important.svg" fetchpriority="low" alt="I'm an unimportant image!"> ``` -Read more about the various use cases in [Optimize resource loading with the Fetch Priority API](https://web.dev/fetch-priority/). +Read more about the various use cases in [Optimize resource loading with the Fetch Priority API](https://web.dev/articles/fetch-priority). ### Also in this release There is a new method of [`forget()`]( -https://web.dev/usb/#revoke-access) for [`USBDevice`](https://developer.mozilla.org/docs/Web/API/USBDevice) objects. This enables the forgetting of a device that previously had permission granted. For example, if this is an application used on a shared computer with many devices. +https://web.dev/articles/usb#revoke_access) for [`USBDevice`](https://developer.mozilla.org/docs/Web/API/USBDevice) objects. This enables the forgetting of a device that previously had permission granted. For example, if this is an application used on a shared computer with many devices. Also for Web USB, a fix to support [`SameObject`] for related attributes within `USBDevice`. The specification change can be found [in a PR to the draft spec](https://github.com/WICG/webusb/pull/212). diff --git a/site/en/blog/new-in-chrome-102/index.md b/site/en/blog/new-in-chrome-102/index.md index 765aee36c..422384259 100644 --- a/site/en/blog/new-in-chrome-102/index.md +++ b/site/en/blog/new-in-chrome-102/index.md @@ -78,7 +78,7 @@ launchQueue.setConsumer((launchParams) => { }); ``` -Check out [Let installed web applications be file handlers](https://web.dev/file-handling/) +Check out [Let installed web applications be file handlers](https://web.dev/articles/file-handling) for all the details. ## The `inert` property {: #inert } diff --git a/site/en/blog/new-in-chrome-103/index.md b/site/en/blog/new-in-chrome-103/index.md index 37e5bdc23..9c8523a69 100644 --- a/site/en/blog/new-in-chrome-103/index.md +++ b/site/en/blog/new-in-chrome-103/index.md @@ -126,7 +126,7 @@ const opts = { const pickedFonts = await self.queryLocalFonts(opts); ``` -Check out Tom's article [Use advanced typography with local fonts](https://web.dev/local-fonts/) +Check out Tom's article [Use advanced typography with local fonts](https://web.dev/articles/local-fonts) on web.dev for complete details. ## Easier Timeouts with AbortSignal.timeout() {: #abort-timeout } diff --git a/site/en/blog/new-in-chrome-107/index.md b/site/en/blog/new-in-chrome-107/index.md index 51a966fd4..ae5fe6762 100644 --- a/site/en/blog/new-in-chrome-107/index.md +++ b/site/en/blog/new-in-chrome-107/index.md @@ -80,7 +80,7 @@ const blocking = res.filter(({renderBlockingStatus}) => renderBlockingStatus === 'blocking'); ``` -Optimizing how you load your resources helps with [Core Web Vitals](https://web.dev/vitals/) and with providing a better user experience, Check out the MDN documentation to learn more about the [Performance API](https://developer.mozilla.org/docs/Web/API/Performance_API), look for those render blocking resources and optimize away. +Optimizing how you load your resources helps with [Core Web Vitals](https://web.dev/articles/vitals) and with providing a better user experience, Check out the MDN documentation to learn more about the [Performance API](https://developer.mozilla.org/docs/Web/API/Performance_API), look for those render blocking resources and optimize away. ## PendingBeacon API origin trial {: #pending-beacon } @@ -99,7 +99,7 @@ Of course there’s plenty more. * The `expect-ct` http header is deprecated. * The `rel` attribute is now supported on `<form>` elements. -* Last time I mentioned [`grid-template` interpolation](https://web.dev/css-animated-grid-layouts/), this time it should be included. +* Last time I mentioned [`grid-template` interpolation](https://web.dev/articles/css-animated-grid-layouts), this time it should be included. ## Further reading diff --git a/site/en/blog/new-in-chrome-108/index.md b/site/en/blog/new-in-chrome-108/index.md index 3ac0a1d4a..c82485e73 100644 --- a/site/en/blog/new-in-chrome-108/index.md +++ b/site/en/blog/new-in-chrome-108/index.md @@ -39,7 +39,7 @@ The value will be anything within the limits of the large unit (the maximum) and {% Img src="image/RYmV5NPuMZRoF3PVwIXTUpdYeQ23/JUvvIgXen1zmHFH53CBS.png", alt="The different parts of the viewport for each type of viewport unit.", width="800", height="664" %} -Check out [this article](https://web.dev/viewport-units/) for more details. Also checkout the change on [Android viewport resizing behavior](/blog/viewport-resize-behavior/) to handle your viewport appropriately . +Check out [this article](https://web.dev/articles/viewport-units) for more details. Also checkout the change on [Android viewport resizing behavior](/blog/viewport-resize-behavior/) to handle your viewport appropriately . ## Variable fonts now supported in COLRv1. {: #colrv1-support } @@ -82,7 +82,7 @@ Of course there’s plenty more. * A change [in the behavior for `overflow`](/blog/overflow-replaced-elements/) on replaced elements is being rolled out. * If you are an identity provider check out the [Federated Credential Management API](/docs/privacy-sandbox/fedcm/). -* The [Media Source Extensions API](https://web.dev/media-mse-basics/) is now available in the worker context. +* The [Media Source Extensions API](https://web.dev/articles/media-mse-basics) is now available in the worker context. ## Further reading @@ -102,4 +102,4 @@ To stay up to date, [subscribe](https://goo.gl/6FP1a5) to the and you'll get an email notification whenever we launch a new video. I’m Adriana Jara, and as soon as Chrome 109 is released, I'll be right here to -tell you what's new in Chrome! \ No newline at end of file +tell you what's new in Chrome! diff --git a/site/en/blog/new-in-chrome-109/index.md b/site/en/blog/new-in-chrome-109/index.md index f8fbad331..09f6436c2 100644 --- a/site/en/blog/new-in-chrome-109/index.md +++ b/site/en/blog/new-in-chrome-109/index.md @@ -43,7 +43,7 @@ Now a few new CSS features, starting with a new length unit: `lh`. The `lh` CSS unit is equal to the computed value of the line-height property on the element on which it is used. This allows a `textarea` to be given a height that is the same as the number of lines of expected text. -Also the CSS Working Group added a new value of `auto` for the descriptors: `font-weight`, `font-style`, and `font-stretch` inside the `@font-face` rule. `auto` is now the initial value. These descriptors in [variable fonts](https://web.dev/variable-fonts/) provide users the ability to choose how heavy or slanted or wide the typeface should be. +Also the CSS Working Group added a new value of `auto` for the descriptors: `font-weight`, `font-style`, and `font-stretch` inside the `@font-face` rule. `auto` is now the initial value. These descriptors in [variable fonts](https://web.dev/articles/variable-fonts) provide users the ability to choose how heavy or slanted or wide the typeface should be. To provide better control over web typography, the [`hyphenate-limit-chars`](https://developer.mozilla.org/docs/Web/CSS/hyphenate-limit-chars#:~:text=The%20hyphenate%2Dlimit%2Dchars%20CSS,control%20over%20hyphenation%20in%20text.) property specifies the minimum number of characters in a hyphenated word. diff --git a/site/en/blog/new-in-chrome-113/index.md b/site/en/blog/new-in-chrome-113/index.md index 6f216b01a..4270d09fd 100644 --- a/site/en/blog/new-in-chrome-113/index.md +++ b/site/en/blog/new-in-chrome-113/index.md @@ -1,7 +1,7 @@ --- title: New in Chrome 113 -description: > - Chrome 113 is rolling out now! WebGPU is here, it allows high-performance 3D graphics and data-parallel computation on the web, devtools can now override network response headers, First Party Sets, part of the Privacy Sandbox, that allows organizations to declare related sites is starting to roll out, and there's plenty more. +description: > + Chrome 113 is rolling out now! WebGPU is here, it allows high-performance 3D graphics and data-parallel computation on the web, devtools can now override network response headers, First Party Sets, part of the Privacy Sandbox, that allows organizations to declare related sites is starting to roll out, and there's plenty more. layout: 'layouts/blog-post.njk' date: 2023-05-03 authors: @@ -18,21 +18,21 @@ tags: Here's what you need to know: -* [WebGPU](#webgpu) is here, it allows high-performance 3D graphics and data-parallel computation on the web. +* [WebGPU](#webgpu) is here, it allows high-performance 3D graphics and data-parallel computation on the web. * Devtools can now override network [response headers](#override-headers). * [First Party Sets](#first-party-sets), part of the [Privacy Sandbox](https://privacysandbox.com/), that allows organizations to declare related sites is starting to roll out. * And there's plenty [more](#more). I'm Adriana Jara. Let's dive in and see what's new for developers in Chrome 113. ## WebGPU is here. {: #webgpu} -[WebGPU is a new API](/blog/webgpu-release/) for the web, which exposes modern hardware capabilities and allows rendering and computation operations on a GPU, similar to [Direct3D 12](https://learn.microsoft.com/en-us/windows/win32/direct3d12/what-is-directx-12-), [Metal](https://developer.apple.com/metal/), and [Vulkan](https://developer.nvidia.com/vulkan). +[WebGPU is a new API](/blog/webgpu-release/) for the web, which exposes modern hardware capabilities and allows rendering and computation operations on a GPU, similar to [Direct3D 12](https://learn.microsoft.com/en-us/windows/win32/direct3d12/what-is-directx-12-), [Metal](https://developer.apple.com/metal/), and [Vulkan](https://developer.nvidia.com/vulkan). -Unlike the [WebGL](https://www.khronos.org/webgl/wiki/Getting_Started) family of APIs, WebGPU offers access to more advanced GPU features and provides first-class support for general computations on the GPU. +Unlike the [WebGL](https://www.khronos.org/webgl/wiki/Getting_Started) family of APIs, WebGPU offers access to more advanced GPU features and provides first-class support for general computations on the GPU. The API is designed with the web platform in mind. It features: -An idiomatic JavaScript API. -Integration with promises. -Support for importing videos. +An idiomatic JavaScript API. +Integration with promises. +Support for importing videos. A polished developer experience with great error messages. Many widely used WebGL libraries are already working on implementing WebGPU support or have already done so. This means that using WebGPU may only require making a single line change, for example: @@ -55,7 +55,7 @@ With response header overrides, you can locally prototype fixes for various head - [Cross-Origin Resource Sharing (CORS) Headers](https://developer.mozilla.org/docs/Web/HTTP/CORS) - [Permissions-Policy Headers](https://developer.mozilla.org/docs/Web/HTTP/Headers/Permissions-Policy) -- [Cross-Origin Isolation Headers](https://web.dev/coop-coep/) +- [Cross-Origin Isolation Headers](https://web.dev/articles/coop-coep) To override a header, navigate to **Network** > **Headers** > **Response Headers**, hover over a header's value, click **Edit** and edit it. @@ -79,8 +79,8 @@ Check out [this article](/blog/new-in-devtools-113/) for instructions on how to {% Img src="image/vgdbNJBYHma2o62ZqYmcnkq3j0o1/OLx3AXkweLjAiDzoDslb.png", alt="Diagram showing brandx.com, fly-brandx.com and drive-brandx.com as one group and example.com, example.rs, example.co.uk as another group.", width="800", height="348" %} As part of the work on First-Party Sets, Chrome is implementing and extending the Storage Access API allowing a site to request access to their cookies in a third-party context. -With it, organizations with related sites (for example, using different domain names, or country-specific domains) can still provide services like single sign-on or shared sessions. -Remember! This API will be rolled out slowly to users over a number of weeks to enable testing and evaluation. +With it, organizations with related sites (for example, using different domain names, or country-specific domains) can still provide services like single sign-on or shared sessions. +Remember! This API will be rolled out slowly to users over a number of weeks to enable testing and evaluation. ## And more! {: #more } diff --git a/site/en/blog/new-in-chrome-76/index.md b/site/en/blog/new-in-chrome-76/index.md index 7d34d11ca..eb983d75d 100644 --- a/site/en/blog/new-in-chrome-76/index.md +++ b/site/en/blog/new-in-chrome-76/index.md @@ -134,7 +134,7 @@ of your site to match the user's preferred mode. ``` Tom has a great article [Hello darkness, my old friend][dark-article] on -[web.dev](https://web.dev/blog/) with everything you need to know, plus tips +[web.dev](https://web.dev/articles/blog) with everything you need to know, plus tips for architecting your style sheets to support both a light, and a dark mode. diff --git a/site/en/blog/new-in-chrome-80/index.md b/site/en/blog/new-in-chrome-80/index.md index f2f5f7bf1..336d83738 100644 --- a/site/en/blog/new-in-chrome-80/index.md +++ b/site/en/blog/new-in-chrome-80/index.md @@ -50,7 +50,7 @@ const worker = new Worker('worker.js', { Moving to JavaScript modules, also enables the use of dynamic import for lazy-loading code, without blocking the execution of the worker. Check out Jason's post -[Threading the web with module workers](https://web.dev/module-workers/) on +[Threading the web with module workers](https://web.dev/articles/module-workers) on web.dev for more details. ## Optional chaining {: #opt-chaining } @@ -93,13 +93,13 @@ allowing them to be used by any site, without a token. ### Periodic background sync -First up, is [periodic background sync](https://web.dev/periodic-background-sync/), +First up, is [periodic background sync](https://web.dev/articles/periodic-background-sync), it periodically synchronizes data in the background, so that when a user opens your installed PWA, they always have the freshest data. ### Contact picker -Next up, is the [Contact Picker API](https://web.dev/contact-picker/), an +Next up, is the [Contact Picker API](https://web.dev/articles/contact-picker), an on-demand API that allows users to select entries from their contact list and share limited details of the selected entries with a website. @@ -108,7 +108,7 @@ easier for users to reach and connect with their friends and family. ### Get installed related apps -And finally, the [Get Installed Related Apps](https://web.dev/get-installed-related-apps/) +And finally, the [Get Installed Related Apps](https://web.dev/articles/get-installed-related-apps) method allows your web app to check if your native app is installed on a user's device. @@ -148,7 +148,7 @@ then call `index.add`, and provide metadata about the content. Once the index is populated, it's shown in a dedicated area of Chrome for Android's Downloads page. Check out Jeff's post [Indexing your offline-capable -pages with the Content Indexing API](https://web.dev/content-indexing-api/) +pages with the Content Indexing API](https://web.dev/articles/content-indexing-api) on web.dev for complete details. ### Notification triggers @@ -178,7 +178,7 @@ registration. In the notification options, add a `showTrigger` property with a notification. The origin trial is planned to run through Chrome 83, so check out Tom's -[Notification Triggers](https://web.dev/notification-triggers/) post on web.dev +[Notification Triggers](https://web.dev/articles/notification-triggers) post on web.dev for complete details. ### Other origin trials diff --git a/site/en/blog/new-in-chrome-84/index.md b/site/en/blog/new-in-chrome-84/index.md index 69f51de10..51517a661 100644 --- a/site/en/blog/new-in-chrome-84/index.md +++ b/site/en/blog/new-in-chrome-84/index.md @@ -73,7 +73,7 @@ app manifest, describe the shortcut, and add your icons. ] ``` -Check out [Getting things done quickly with app shortcuts](https://web.dev/app-shortcuts/) +Check out [Getting things done quickly with app shortcuts](https://web.dev/articles/app-shortcuts) for complete details. ## Web animations API {: #web-animations } @@ -89,7 +89,7 @@ Animations API. I simply **can't** do justice to all the improvements or offer good examples here, so check out -[Web Animations API improvements in Chromium 84](https://web.dev/web-animations/) +[Web Animations API improvements in Chromium 84](https://web.dev/articles/web-animations) for complete details. ## Content indexing API {: #content-indexing } @@ -143,7 +143,7 @@ for (const entry of entries) { ``` See -[Indexing your offline-capable pages with the Content Indexing API](https://web.dev/content-indexing-api/) +[Indexing your offline-capable pages with the Content Indexing API](https://web.dev/articles/content-indexing-api) for complete details. ## Wake lock API {: #wake-lock } @@ -161,7 +161,7 @@ from its origin trial in Chrome 84, sites can request a wake lock to prevent the screen from dimming and locking. In fact, the Betty Crocker website is using this today, and published a -[case study](https://web.dev/betty-crocker/) on web.dev showing a 300% +[case study](https://web.dev/articles/betty-crocker) on web.dev showing a 300% increase in purchase intent indicators. To get a wake lock, call `navigator.wakeLock.request()`, it returns a @@ -178,14 +178,14 @@ wl.release(); ``` Of course, there's a little more to it then that, so check out -[Stay awake with the Screen Wake Lock API](https://web.dev/wakelock/), but at +[Stay awake with the Screen Wake Lock API](https://web.dev/articles/wakelock), but at least my screen won't be covered in flour any more! ## Origin trials There are two new origin trials I want to call out. If you're new to origin trials, check out -[Getting started with Chrome's origin trials](https://web.dev/origin-trials/). +[Getting started with Chrome's origin trials](/docs/web-platform/origin-trials/). ### Idle detection {: #idle-detection } @@ -212,7 +212,7 @@ await idleDetector.start({ }); ``` -See [Detect inactive users with the Idle Detection API](https://web.dev/idle-detection/) +See [Detect inactive users with the Idle Detection API](https://web.dev/articles/idle-detection) to learn more about the API, and how you can start experimenting with it today. ### Web Assembly SIMD {: #wasm-simd } @@ -238,7 +238,7 @@ out. * We're resuming the gradual rollout of [SameSite cookie changes][cr-blog-sscookie]. * Sites with abusive permission requests, or abusive notifications, will automatically be enrolled in our [quieter notifications UI][cr-blog-quieter]. -* There's a new origin trial for [QuicTransport](https://web.dev/quictransport/). +* There's a new origin trial for [QuicTransport](https://web.dev/articles/quictransport). ## Further reading diff --git a/site/en/blog/new-in-chrome-85/index.md b/site/en/blog/new-in-chrome-85/index.md index 4e57674de..edc1b1d4a 100644 --- a/site/en/blog/new-in-chrome-85/index.md +++ b/site/en/blog/new-in-chrome-85/index.md @@ -71,7 +71,7 @@ that have children with contained layouts of their own. By chunking content and adding `content-visibility: auto;`, this page went from a rendering time of 232ms to only 30ms. -Check out the [content visibility](https://web.dev/content-visibility/) to see +Check out the [content visibility](https://web.dev/articles/content-visibility) to see how you can use it to improve your rendering performance. ## `@property` and CSS variables {: #css-properties } @@ -95,7 +95,7 @@ semantic meaning, fallback values, and even enables CSS testing. ``` Una has a great post -[`@property`: giving superpowers to CSS variables](https://web.dev/at-property/) +[`@property`: giving superpowers to CSS variables](https://web.dev/articles/at-property) that shows you how you can use them. ## Get installed related apps {: #gira } @@ -121,7 +121,7 @@ relatedApps.forEach((app) => { ``` Check out my article -[Is your app installed? `getInstalledRelatedApps()` will tell you!](https://web.dev/get-installed-related-apps/) +[Is your app installed? `getInstalledRelatedApps()` will tell you!](https://web.dev/articles/get-installed-related-apps) on web.dev to see how it works, and how to sign your apps to prove they're yours. @@ -155,7 +155,7 @@ both Chrome and Edge. ] ``` -Check out the [App Icon Shortcuts](https://web.dev/app-shortcuts/) article on +Check out the [App Icon Shortcuts](https://web.dev/articles/app-shortcuts) article on web.dev for complete details, and I'm sorry for the confusion I caused. ## Origin Trial: Streaming requests with `fetch()` {: #fetch-stream } @@ -178,7 +178,7 @@ For example, use it to warm up the server, or stream audio or video as it's captured from the microphone or camera. Jake has an in-depth look in -[Streaming requests with the fetch API](https://web.dev/fetch-upload-streaming/) +[Streaming requests with the fetch API](https://web.dev/articles/fetch-upload-streaming) on web.dev, and also covered it in the latest [HTTP203 - Streaming requests with fetch](https://www.youtube.com/watch?v=G9PpImUEeUA) video. @@ -217,7 +217,7 @@ compression gains vs. JPEG and WebP, with a recent [Netflix study](https://netflixtechblog.com/avif-for-next-generation-image-coding-b1d75675fe4) showing 50% savings vs. standard JPEG and > 60% savings on 4:4:4 content. -And [AppCache removal has begun](https://web.dev/appcache-removal/). +And [AppCache removal has begun](https://web.dev/articles/appcache-removal). ## Further reading diff --git a/site/en/blog/new-in-chrome-86/index.md b/site/en/blog/new-in-chrome-86/index.md index 68e670aae..b30f3bba3 100644 --- a/site/en/blog/new-in-chrome-86/index.md +++ b/site/en/blog/new-in-chrome-86/index.md @@ -134,7 +134,7 @@ speakers, to start or end calls, mute the audio, and more. Of course, powerful APIs like this, can only interact with devices when the user explicitly chooses to allow it. -Check out [Connecting to uncommon HID devices](https://web.dev/hid/) +Check out [Connecting to uncommon HID devices](https://web.dev/articles/hid) for more details, examples, how you can get started, and a cool demo. <br style="clear:both;"> diff --git a/site/en/blog/new-in-chrome-88/index.md b/site/en/blog/new-in-chrome-88/index.md index 5544006b9..8fe277ab9 100644 --- a/site/en/blog/new-in-chrome-88/index.md +++ b/site/en/blog/new-in-chrome-88/index.md @@ -153,7 +153,7 @@ And of course there's plenty more. tab-napping attacks. * Most operating systems enable mouse acceleration by default, but that can be a problem for some games. In Chrome 88, the Pointer Lock API allows you to - [disable mouse acceleration](https://web.dev/disable-mouse-acceleration/). + [disable mouse acceleration](https://web.dev/articles/disable-mouse-acceleration). That means the same physical motion, slow or fast, results in the same rotation, providing a better gaming experience and higher accuracy. * And [`addEventListener` now takes an Abort Signal as an option](https://www.chromestatus.com/feature/5658622220566528). diff --git a/site/en/blog/new-in-chrome-89/index.md b/site/en/blog/new-in-chrome-89/index.md index 0c27245f8..05cc58b6c 100644 --- a/site/en/blog/new-in-chrome-89/index.md +++ b/site/en/blog/new-in-chrome-89/index.md @@ -68,9 +68,9 @@ that can interact with lots of sites, users win because they don't need to install special drivers, or software. You can learn more about some of the devices you can connect to at -[web.dev/devices](https://web.dev/devices/), or check out the getting started -guides for [WebHID](https://web.dev/hid/), [WebNFC](https://web.dev/nfc/), -and [Web Serial](https://web.dev/serial/). +[web.dev/devices](https://web.dev/explore/devices), or check out the getting started +guides for [WebHID](https://web.dev/articles/hid), [WebNFC](https://web.dev/articles/nfc), +and [Web Serial](https://web.dev/articles/serial). ## PWA installability criteria changes {: #installability } @@ -163,9 +163,9 @@ you'll want to use the Web Share Target API. ``` Check -[Integrate with the OS sharing UI with the Web Share API](https://web.dev/web-share/) +[Integrate with the OS sharing UI with the Web Share API](https://web.dev/articles/web-share) and -[Receiving shared data with the Web Share Target API](https://web.dev/web-share-target/) +[Receiving shared data with the Web Share Target API](https://web.dev/articles/web-share-target) for getting started guides. ## And more {: #more } diff --git a/site/en/blog/new-in-chrome-96/index.md b/site/en/blog/new-in-chrome-96/index.md index cae21db26..1897a04e9 100644 --- a/site/en/blog/new-in-chrome-96/index.md +++ b/site/en/blog/new-in-chrome-96/index.md @@ -134,7 +134,7 @@ Web Vitals. The `importance` attribute allows you to specify the priority for resource types such as CSS, fonts, scripts, images, and iframes. {% Aside 'warning' %} -The `importance` attribute has been renamed `fetchpriority`. Read [Optimizing resource loading with the Fetch Priority API](https://web.dev/fetch-priority/) for the latest on this feature. +The `importance` attribute has been renamed `fetchpriority`. Read [Optimizing resource loading with the Fetch Priority API](https://web.dev/articles/fetch-priority) for the latest on this feature. {% endAside %} ```html diff --git a/site/en/blog/new-in-devtools-101/index.md b/site/en/blog/new-in-devtools-101/index.md index fdfdb5aaf..11a0aeb99 100644 --- a/site/en/blog/new-in-devtools-101/index.md +++ b/site/en/blog/new-in-devtools-101/index.md @@ -29,7 +29,7 @@ For example, download this [JSON file](https://storage.googleapis.com/web-dev-up Apart from that, you can export the recording as well. After [recording a user flow](/docs/devtools/recorder/#record), click on the export button. There are 3 export options: - **Export as a JSON file**. Download the recording as a JSON file. -- **Export as a @puppeteer/replay script**. Download the recording as a [Puppeteer Replay](https://github.com/puppeteer/replay) script. +- **Export as a @puppeteer/replay script**. Download the recording as a [Puppeteer Replay](https://github.com/puppeteer/replay) script. - **Export as a Puppeteer script** . Download the recording as [Puppeteer](https://pptr.dev/) script. Consult [the documentation](/docs/devtools/recorder/#export-flows) to learn more about the differences between these options. @@ -45,7 +45,7 @@ Chromium issue: [1257499](https://crbug.com/1257499) In this [example](https://jec.fish/demo/cascade-layer), there are 3 cascade layers defined: `page`, `component` and `base`. In the **Styles** pane, you can view each layer and its styles. -Click on the layer name to view the layer order. The `page` layer has the highest specificity, therefore the `box` background is green. +Click on the layer name to view the layer order. The `page` layer has the highest specificity, therefore the `box` background is green. {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/A0yHsGUcqVCIO3fzKhEz.png", alt="View cascade layers in the Styles pane", width="800", height="490" %} @@ -82,13 +82,13 @@ Chromium issues: [1296855](https://crbug.com/1296855), [https://crbug.com/130340 These are some noteworthy fixes in this release: -- The [Back/forward cache](/blog/new-in-devtools-98/#bfcache) now displays the extension ID which blocked [bfcache](https://web.dev/bfcache/) when present.( [1284548](https://crbug.com/1284548)) +- The [Back/forward cache](/blog/new-in-devtools-98/#bfcache) now displays the extension ID which blocked [bfcache](https://web.dev/articles/bfcache) when present.( [1284548](https://crbug.com/1284548)) - Fixed autocompletion support for array-like objects, CSS class names, `map.get` and HTML tags. ([1297101](https://crbug.com/1297101), [1297491](https://crbug.com/1297491), [1293807](https://crbug.com/1293807), [1296983](https://crbug.com/1296983)) - Fixed incorrect highlights when double-clicking on words and undoing autocomplete. ([1298437](https://crbug.com/1298437), [1298667](https://crbug.com/1298667)) - Fixed comment keyboard shortcut in the **Sources** panel. ([1296535](https://crbug.com/1296535)) - Re-enable support for using **Alt** (Options) key for multi selection in the **Sources** panel. ([1304070](https://crbug.com/1304070)) - + ## [Experimental] New timespan and snapshot mode in the Lighthouse panel {: #lighthouse } {% Aside %} @@ -97,7 +97,7 @@ To enable the experiment, enable the **Use Lighthouse panel with timespan and sn Apart from the existing **navigation** mode, the **Lighthouse** panel now support two more modes on measuring user flows - **timespan** and **snapshot**. -For example, you can use the **timespan** reports to analyze user interactions. Open this [demo](https://coffee-cart.netlify.app/) page. Select the **Timespan** mode and click on **Start timespan**. On the page, click on a coffee and end the timespan. Read the report to find out the [Total Blocking Time](https://web.dev/tbt/) and [Cumulative Layout Shift](https://web.dev/cls/) that were caused by the interaction. +For example, you can use the **timespan** reports to analyze user interactions. Open this [demo](https://coffee-cart.netlify.app/) page. Select the **Timespan** mode and click on **Start timespan**. On the page, click on a coffee and end the timespan. Read the report to find out the [Total Blocking Time](https://web.dev/articles/tbt) and [Cumulative Layout Shift](https://web.dev/articles/cls) that were caused by the interaction. Each mode has its own unique use cases, benefits, and limitations. Please refer to the [Lighthouse documentation](https://github.com/GoogleChrome/lighthouse/blob/master/docs/user-flows.md) for more information. diff --git a/site/en/blog/new-in-devtools-102/index.md b/site/en/blog/new-in-devtools-102/index.md index 6bab56c70..3d4948407 100644 --- a/site/en/blog/new-in-devtools-102/index.md +++ b/site/en/blog/new-in-devtools-102/index.md @@ -26,9 +26,9 @@ Use the **Performance insights** panel to get actionable and use-case-driven ins {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/EjgH5CD6FHnzoEhDEWxu.png", alt="New Performance insights panel", width="800", height="585" %} -Once the recording is complete, you get the performance insights on the **Insights** pane. Click on each insight item (for example, Render blocking request, layout shift) to understand the issue and potential fixes. +Once the recording is complete, you get the performance insights on the **Insights** pane. Click on each insight item (for example, Render blocking request, layout shift) to understand the issue and potential fixes. -Go to the **Performance insights** panel [documentation](/docs/devtools/performance-insights/) to learn more with the step-by-step tutorial. +Go to the **Performance insights** panel [documentation](/docs/devtools/performance-insights/) to learn more with the step-by-step tutorial. This is a preview feature to help web developers (especially non-performance experts) to identify and fix potential performance issues. Our team is actively working on this feature and we are looking for your [feedback](https://crbug.com/1270700) for further enhancements. @@ -37,9 +37,9 @@ Chromium issue: [1270700](https://crbug.com/1270700) ## New shortcuts to emulate light and dark themes {: #emulation } -You can now emulate the light and dark themes quicker (CSS media feature [prefers-color-scheme](https://web.dev/prefers-color-scheme/#the-prefers-color-scheme-media-query)) with the new shortcuts in the **Styles** pane. +You can now emulate the light and dark themes quicker (CSS media feature [prefers-color-scheme](https://web.dev/articles/prefers-color-scheme#the_prefers_color_scheme_media_query)) with the new shortcuts in the **Styles** pane. -Previously, it took more steps to [emulate themes](/docs/devtools/rendering/emulate-css/) in the **Rendering** tab. +Previously, it took more steps to [emulate themes](/docs/devtools/rendering/emulate-css/) in the **Rendering** tab. {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/dCbNHwE5ICGNXRUws1zz.png", alt="New shortcuts to emulate light and dark themes", width="800", height="488" %} @@ -52,7 +52,7 @@ Chromium issue: [1314299](https://crbug.com/1314299) DevTools now apply the Content Security Policy (CSP) in the **Preview** tab in the **Network** panel. -For example, the first screenshot shows a page that contains [mixed content](https://web.dev/what-is-mixed-content/). The page loads over a secure HTTPS connection, but the stylesheet loads over an insecure HTTP connection. +For example, the first screenshot shows a page that contains [mixed content](https://web.dev/articles/what-is-mixed-content). The page loads over a secure HTTPS connection, but the stylesheet loads over an insecure HTTP connection. The browser blocked the stylesheet request by default. However, when you opened the page via the **Preview** tab in the **Network** panel, the stylesheet was not blocked previously (hence the background turned into red). It is now blocked as you would expect (second screenshot). @@ -67,7 +67,7 @@ Chromium issue: [833147](https://crbug.com/833147) The debugger now terminates script execution when reloading at breakpoint. -For example, the script got into an endless loop previously when setting and reloading at the `ReactDOM` breakpoint in this [React demo](https://react-stuck.glitch.me/). The **Sources** panel broke due to the endless loop. +For example, the script got into an endless loop previously when setting and reloading at the `ReactDOM` breakpoint in this [React demo](https://react-stuck.glitch.me/). The **Sources** panel broke due to the endless loop. Continuing to execute JavaScript is causing a lot of trouble for developers and might leave the renderer in a broken state. This change aligns the debugging behavior with other browsers like Firefox. @@ -93,7 +93,7 @@ Chromium issue: [1295750](https://crbug.com/1295750) ### Commit live expression with Enter {: #live-expression } -Once you finish typing a [live expression](/blog/new-in-devtools-70/#watch), you can click `Enter` to commit it. Previously, hitting Enter resulted in adding new lines. This is inconsistent with other parts of the DevTools. +Once you finish typing a [live expression](/blog/new-in-devtools-70/#watch), you can click `Enter` to commit it. Previously, hitting Enter resulted in adding new lines. This is inconsistent with other parts of the DevTools. To add a new line in the **live expression** editor, use `Shift` + `Enter` instead. @@ -162,7 +162,7 @@ A new **Copy** button is added to the [Changes](/docs/devtools/changes/) tab as {# https://chromium.googlesource.com/devtools/devtools-frontend/+/afe5698f1cd20304d2763574ef8e9faf6a4a6db1 #} {# ​​https://chromium.googlesource.com/devtools/devtools-frontend/+/5de1d6140cad945783f3ca54055134f4a7db42a1 #} -{# https://chromium.googlesource.com/devtools/devtools-frontend/+/573dfc1cca09e49177ece3898c9ba9619c386f06 #} +{# https://chromium.googlesource.com/devtools/devtools-frontend/+/573dfc1cca09e49177ece3898c9ba9619c386f06 #} Chromium issue: [1268754](https://crbug.com/1268754) @@ -175,7 +175,7 @@ To enable the experiment, check **Enable color picking outside the browser windo Enable this experiment to pick a color outside of the browser with the color picker. Previously, you could only pick a color within the browser. -In the **Styles** pane, click on any color preview to open the color picker. Use the eyedropper to pick color from anywhere. +In the **Styles** pane, click on any color preview to open the color picker. Use the eyedropper to pick color from anywhere. {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/h3xLPNl1QdvyuzZpNuqW.png", alt="Picking color outside of browser", width="800", height="450" %} diff --git a/site/en/blog/new-in-devtools-104/index.md b/site/en/blog/new-in-devtools-104/index.md index 7ab43b6b7..0dca3a6e1 100644 --- a/site/en/blog/new-in-devtools-104/index.md +++ b/site/en/blog/new-in-devtools-104/index.md @@ -75,7 +75,7 @@ Chromium issue: [960909](https://crbug.com/960909) Visualize `performance.measure()` marks in your recording with the new **User Timings** track in the **Performance insights** panel. -For example, this [web page](https://jec.fish/demo/perf-measure) uses the [`performance.measure()`](https://web.dev/usertiming/#calculating-measurements-with-measure()) method to calculate the elapsed time of text loading. +For example, this [web page](https://jec.fish/demo/perf-measure) uses the [`performance.measure()`](https://web.dev/articles/usertiming#calculating_measurements_with_measure()) method to calculate the elapsed time of text loading. When you start [measuring the page load](/docs/devtools/performance-insights/#record), the **User Timings** track shows in the recording. Click on the timings item to view its details on the side pane. diff --git a/site/en/blog/new-in-devtools-105/index.md b/site/en/blog/new-in-devtools-105/index.md index d9b9e5a17..7bd71fa5b 100644 --- a/site/en/blog/new-in-devtools-105/index.md +++ b/site/en/blog/new-in-devtools-105/index.md @@ -48,7 +48,7 @@ Chromium issue: [1257499](https://crbug.com/1257499) ## Largest Contentful Paint (LCP) in the Performance insights panel {: #lcp } -LCP is an important, user-centric metric for measuring [perceived load speed](https://web.dev/user-centric-performance-metrics/#types-of-metrics). You can now find out the critical paths and root causes of a [Largest Contentful Paint (LCP)](https://web.dev/lcp/). +LCP is an important, user-centric metric for measuring [perceived load speed](https://web.dev/articles/user-centric-performance-metrics#types_of_metrics). You can now find out the critical paths and root causes of a [Largest Contentful Paint (LCP)](https://web.dev/articles/lcp). In a [performance recording](/docs/devtools/performance-insights/#record), click on the LCP badge in the **Timeline**. In the **Details** pane, you can view the LCP score, learn how to fix resources that slow down the LCP and see the critical path for the LCP resource. @@ -61,11 +61,11 @@ Chromium issue: [1326481](https://crbug.com/1326481) ## Identify flashes of text (FOIT, FOUT) as potential root causes for layout shifts {: #foit-fout } -The **Performance insights** panel now detects [flash of invisible text (FOIT) and flash of unstyled text (FOUT)](https://web.dev/preload-optional-fonts/#font-rendering) as potential root causes for layout shifts. +The **Performance insights** panel now detects [flash of invisible text (FOIT) and flash of unstyled text (FOUT)](https://web.dev/articles/preload-optional-fonts#font_rendering) as potential root causes for layout shifts. To view the potential root causes of a layout shift, click on a screenshot in the **Layout shifts** track. -See [Optimize WebFont loading and rendering](https://web.dev/optimize-webfont-loading/) to learn the technique to prevent layout shifts. +See [Optimize WebFont loading and rendering](https://web.dev/articles/optimize-webfont-loading) to learn the technique to prevent layout shifts. {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/AMN5oD5hlKhPhnq98sIB.png", alt="FOUT in the Performance insights panel", width="800", height="497" %} @@ -74,7 +74,7 @@ Chromium issues: [1334628](https://crbug.com/1334628), [1328873](https://crbug.c ## Protocol handlers in the Manifest pane {: #manifest } -You can now use DevTools to test the [URL protocol handler registration](https://web.dev/url-protocol-handler/) for [Progressive Web Apps (PWA)](https://web.dev/learn/pwa/). +You can now use DevTools to test the [URL protocol handler registration](https://web.dev/articles/url-protocol-handler) for [Progressive Web Apps (PWA)](https://web.dev/learn/pwa). The URL protocol handler registration lets installed PWAs handle links that use a specific protocol (e.g. [`magnet`](https://wikipedia.org/wiki/Magnet_URI_scheme), `web+example`) for a more integrated experience. @@ -94,7 +94,7 @@ Chromium issues: [1300613](https://crbug.com/1300613) Use the [top layer badge](/blog/top-layer-devtools/#top-layer-support-design-in-devtools) to understand the concept of the top layer and visualize how the top layer content changes. -The [`<dialog>` element](https://web.dev/building-a-dialog-component/) has recently become stable across browsers. When you open a dialog, it is put into a [top layer](/blog/top-layer-devtools/). Top level content renders on top of all the other content. +The [`<dialog>` element](https://web.dev/articles/building-a-dialog-component) has recently become stable across browsers. When you open a dialog, it is put into a [top layer](/blog/top-layer-devtools/). Top level content renders on top of all the other content. In this [demo](https://jec.fish/demo/dialog), click **Open dialog**. diff --git a/site/en/blog/new-in-devtools-106/index.md b/site/en/blog/new-in-devtools-106/index.md index 4c5265fdc..797c708f3 100644 --- a/site/en/blog/new-in-devtools-106/index.md +++ b/site/en/blog/new-in-devtools-106/index.md @@ -138,7 +138,7 @@ Chromium bug: [1347390](https://crbug.com/1347390) ## LCP timings breakdown in the Performance Insights panel {: #insights } -The **Performance Insights** panel now shows the [timings breakdown](https://web.dev/optimize-lcp/#lcp-breakdown) of the [Largest Contentful Paint (LCP)](/docs/devtools/performance-insights/#largest-contentful-paint). Use these timings information to understand and identify an opportunity to improve LCP performance. +The **Performance Insights** panel now shows the [timings breakdown](https://web.dev/articles/optimize-lcp#lcp_breakdown) of the [Largest Contentful Paint (LCP)](/docs/devtools/performance-insights/#largest-contentful-paint). Use these timings information to understand and identify an opportunity to improve LCP performance. {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/hU6RmoRjFskL8P2ZAB9l.png", alt="LCP timings breakdown in the Performance Insights panel", width="800", height="523" %} @@ -162,7 +162,7 @@ Chromium bug: [1351383](https://crbug.com/1351383) - Previously, [Recorder extensions](/docs/devtools/recorder/reference/#extension-troubleshooting) don’t show up in the **Recorder** panel from time to time. ([1351416](https://crbug.com/1351416)) - The **Styles** pane now displays a color picker for the [SVG `<stop>`](https://developer.mozilla.org/docs/Web/SVG/Element/stop) element’s `stop-color` property. ([1351096](https://crbug.com/1351096)) -- Identify scripts causing [layout thrashing](https://web.dev/avoid-large-complex-layouts-and-layout-thrashing/) as the potential root causes for layout shifts in the **Performance Insights** panel. ([1343019](https://crbug.com/1343019)) +- Identify scripts causing [layout thrashing](https://web.dev/articles/avoid-large-complex-layouts-and-layout-thrashing) as the potential root causes for layout shifts in the **Performance Insights** panel. ([1343019](https://crbug.com/1343019)) - Display critical path for LCP web fonts in the **Performance Insights** panel. ([1350390](https://crbug.com/1350390)) {# https://chromium.googlesource.com/devtools/devtools-frontend/+/50a84ca8e5b556e27bb285477f21a99f0ccb7050 #} diff --git a/site/en/blog/new-in-devtools-112/index.md b/site/en/blog/new-in-devtools-112/index.md index d7e46fb38..0238d84e1 100644 --- a/site/en/blog/new-in-devtools-112/index.md +++ b/site/en/blog/new-in-devtools-112/index.md @@ -40,7 +40,7 @@ Chromium issue: [1400243](https://crbug.com/1400243). In addition to [custom, CSS, ARIA, text, and XPath selectors](/docs/devtools/recorder/reference/#selector), you can now record using [pierce selectors](https://pptr.dev/guides/query-selectors#pierce-selectors-pierce). These selectors behave like CSS ones but can also pierce through shadow roots. -Start a new recording on a page with [shadow DOM](https://web.dev/shadowdom-v1/) and check {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/hmp8j3HiLMCcqPArD9yt.svg", alt="Checkbox.", width="22", height="22" %} **Pierce** in **Selector types to record**. Record your interaction with elements in the shadow DOM and inspect the corresponding step. +Start a new recording on a page with [shadow DOM](https://web.dev/articles/shadowdom-v1) and check {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/hmp8j3HiLMCcqPArD9yt.svg", alt="Checkbox.", width="22", height="22" %} **Pierce** in **Selector types to record**. Record your interaction with elements in the shadow DOM and inspect the corresponding step. {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/Spqbf2DG3Fr0D2sc1kgC.png", alt="Setting the Recorder to use pierce selectors; Pierce selector in action.", width="800", height="534" %} @@ -135,7 +135,7 @@ Chromium issue: [1027458](https://crbug.com/1027458). To help you focus on the most important parts of your code, you can now add irrelevant scripts to the **Ignore List** right from the file tree on the **Sources** > **Page** pane. -Right-click any script or folder and select one of the ignore-related options. You may see options to add or remove the script or folder to and from the list. The [Debugger ignores scripts](/docs/devtools/javascript/reference/#show-ignore-listed-frames) added to the list and omits them in the call stack. +Right-click any script or folder and select one of the ignore-related options. You may see options to add or remove the script or folder to and from the list. The [Debugger ignores scripts](/docs/devtools/javascript/reference/#show-ignore-listed-frames) added to the list and omits them in the call stack. {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/RrL7ZmzMjfhtH4gUW3ST.png", alt="Context menus of a folder and script with ignore-related options.", width="800", height="521" %} @@ -143,7 +143,7 @@ All ignore-listed scripts and folders are grayed out in the file tree. {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/DRI11RoakrLnwLZPOJPO.png", alt="Ignore-listed scripts and folders are grayed out, you can hide them with an experimental option in the More options drop-down menu.", width="800", height="542" %} -If you select an ignored script, the **Configure** button takes you to +If you select an ignored script, the **Configure** button takes you to {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/9gzXiTYY0nZzBxGI6KrV.svg", alt="Settings.", width="24", height="24" %} [**Settings** > **Ignore List**](/docs/devtools/settings/ignore-list/). You can also hide ignored sources from the file tree with {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/N5Lkpdwpaz4YqRGFr2Ks.svg", alt="Three-dot menu.", width="24", height="24" %} > [**Hide ignore-listed sources**](/docs/devtools/javascript/reference/#hide-ignore-listed) {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/XfSWf04g2cwpnFcmp40m.svg", alt="Experimental.", width="20", height="20" %}. {# https://chromium.googlesource.com/devtools/devtools-frontend/+/e95d2f3fd27301945a1a095bae4bbcad57326cd8 #} @@ -162,7 +162,7 @@ This DevTools version (112) starts the [four-phase **JavaScript Profiler** depre Instead of the **Profiler**, use the [**Performance**](/docs/devtools/performance/reference/#main) panel to profile CPU. -Learn more and provide feedback in the corresponding [RFC](https://github.com/ChromeDevTools/rfcs/discussions/2) and [crbug.com/1354548](https://crbug.com/1354548). +Learn more and provide feedback in the corresponding [RFC](https://github.com/ChromeDevTools/rfcs/discussions/2) and [crbug.com/1354548](https://crbug.com/1354548). {# https://chromium.googlesource.com/devtools/devtools-frontend/+/71244f613a27289936b979fe515346137d0190f8 #} @@ -206,7 +206,7 @@ Chromium issue: [772558](https://crbug.com/772558). ## A Console warning to remove your no-op service worker fetch handler {: #no-op-fetch-warning } -Chrome 112 [skips no-op (no operation) service worker fetch handlers](/blog/chrome-112-beta/#skip-service-worker-no-op-fetch-handler) because they may slow down navigation but don't serve a purpose. Such handlers are no longer required for your website to quialify as a [Progressive Web App](https://web.dev/learn/pwa/). +Chrome 112 [skips no-op (no operation) service worker fetch handlers](/blog/chrome-112-beta/#skip-service-worker-no-op-fetch-handler) because they may slow down navigation but don't serve a purpose. Such handlers are no longer required for your website to quialify as a [Progressive Web App](https://web.dev/learn/pwa). The **Console** now shows a warning if it finds a no-op fetch handler on your website. Consider removing it. diff --git a/site/en/blog/new-in-devtools-113/index.md b/site/en/blog/new-in-devtools-113/index.md index 696edec20..54f2e42c4 100644 --- a/site/en/blog/new-in-devtools-113/index.md +++ b/site/en/blog/new-in-devtools-113/index.md @@ -28,7 +28,7 @@ With response header overrides, you can locally prototype fixes for various head - [Cross-Origin Resource Sharing (CORS) Headers](https://developer.mozilla.org/docs/Web/HTTP/CORS) - [Permissions-Policy Headers](https://developer.mozilla.org/docs/Web/HTTP/Headers/Permissions-Policy) -- [Cross-Origin Isolation Headers](https://web.dev/coop-coep/) +- [Cross-Origin Isolation Headers](https://web.dev/articles/coop-coep) To override a header, navigate to **Network** > **Headers** > **Response Headers**, hover over a header's value, click {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/k3WKQOAItcJ2pliOyD47.svg", alt="Edit.", width="24", height="24" %} and edit it. diff --git a/site/en/blog/new-in-devtools-114/index.md b/site/en/blog/new-in-devtools-114/index.md index a46f13b50..b95a4d458 100644 --- a/site/en/blog/new-in-devtools-114/index.md +++ b/site/en/blog/new-in-devtools-114/index.md @@ -125,7 +125,7 @@ Chromium issue: [1429191](https://crbug.com/1429191). ### Warning for slow user interactions {: #slow-interaction-warning } -User interactions longer than 200 milliseconds get an [Interaction to Next Paint (INP)](https://web.dev/inp/) warning in the **Performance** > **Summary** tab. +User interactions longer than 200 milliseconds get an [Interaction to Next Paint (INP)](https://web.dev/articles/inp) warning in the **Performance** > **Summary** tab. {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/wrFaZ26nYCuprtCSNB5C.png", alt="The INP warning.", width="800", height="685" %} @@ -149,7 +149,7 @@ Both the **Web Vitals** and **Long Tasks** tracks contained information duplicat Additionally, the **Experiences** track was renamed to **Layout Shifts** to more accurately reflect its usage. -Learn more about [Web Vitals](https://web.dev/vitals/). +Learn more about [Web Vitals](https://web.dev/articles/vitals). {# https://chromium.googlesource.com/devtools/devtools-frontend/+/41b7043de413b2a87f6a8dc8a90ac1a744912400 #} {# https://chromium.googlesource.com/devtools/devtools-frontend/+/26306da9622791b255b12c9c0deeac0a0d4a07b8 #} diff --git a/site/en/blog/new-in-devtools-117/index.md b/site/en/blog/new-in-devtools-117/index.md index f5b5f6bd5..f4b8ea2c3 100644 --- a/site/en/blog/new-in-devtools-117/index.md +++ b/site/en/blog/new-in-devtools-117/index.md @@ -101,7 +101,7 @@ Chromium issue: [406900](https://crbug.com/406900). ## Performance: See the changes in fetch priority for network events {: #performance } -The **Performance** panel now shows two priority fields in the **Summary** of an event in the **Network** track: **Initial Priority** and (final) **Priority**, instead of just the singe **Priority**. With this additional field you can now see if the event's fetch priority changes and tweak the order of downloads. For more information, see [Optimizing resource loading with the Fetch Priority API](https://web.dev/fetch-priority/). +The **Performance** panel now shows two priority fields in the **Summary** of an event in the **Network** track: **Initial Priority** and (final) **Priority**, instead of just the singe **Priority**. With this additional field you can now see if the event's fetch priority changes and tweak the order of downloads. For more information, see [Optimizing resource loading with the Fetch Priority API](https://web.dev/articles/fetch-priority). {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/IzdOpZvv0KSQNdtGLfhL.png", alt="Before and after displaying changes in fetch priority.", width="800", height="521" %} diff --git a/site/en/blog/new-in-devtools-118/index.md b/site/en/blog/new-in-devtools-118/index.md index 33110ce5f..e2740b5ae 100644 --- a/site/en/blog/new-in-devtools-118/index.md +++ b/site/en/blog/new-in-devtools-118/index.md @@ -22,7 +22,7 @@ tags: ## New section for custom properties in Elements > Styles {: #css } -The **Elements** panel now supports the [@property CSS at-rule](https://web.dev/at-property/). It lets you define [CSS custom properties](https://developer.mozilla.org/docs/Web/CSS/--*) explicitly and register them in a stylesheet without running any JavaScript. +The **Elements** panel now supports the [@property CSS at-rule](https://web.dev/articles/at-property). It lets you define [CSS custom properties](https://developer.mozilla.org/docs/Web/CSS/--*) explicitly and register them in a stylesheet without running any JavaScript. To inspect your registered custom properties, in **Elements** > **Styles**, hover over the property name and see its descriptors in a tooltip. In the tooltip, click the link to view the registered property in the collapsible `@property` section. diff --git a/site/en/blog/new-in-devtools-119/index.md b/site/en/blog/new-in-devtools-119/index.md index 6a60be1d7..26cfaf200 100644 --- a/site/en/blog/new-in-devtools-119/index.md +++ b/site/en/blog/new-in-devtools-119/index.md @@ -22,7 +22,7 @@ tags: ### Editable `@property` rule {: #edit-property } -You can now edit the [`@property` CSS at-rule](https://web.dev/at-property/) in the corresponding section in the **Elements** > **Styles** pane. +You can now edit the [`@property` CSS at-rule](https://web.dev/articles/at-property) in the corresponding section in the **Elements** > **Styles** pane. {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/J6OXQJK3RRuCvAR1Yai9.png", alt="The before and after making the property rule editable.", width="800", height="526" %} @@ -120,7 +120,7 @@ The **Application** > **Manifest** section now checks if your web app's [screens {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/krHlVOBrMa0p4SvlhGOJ.png", alt="A warning on the incorrect aspect ratio of screenshots with the same form factor.", width="800", height="370" %} -For more information, see [Debug Progressive Web Apps](/docs/devtools/progressive-web-apps/) and [Add a web app manifest](https://web.dev/add-manifest/). +For more information, see [Debug Progressive Web Apps](/docs/devtools/progressive-web-apps/) and [Add a web app manifest](https://web.dev/articles/add-manifest). The DevTools team expresses gratitude to [Alexey Rodionov](https://chromium.googlesource.com/devtools/devtools-frontend/+/f95f715656086cbd9daef3302b7691403bed12c6) for landing this change and other [manifest warning improvements](https://chromium.googlesource.com/devtools/devtools-frontend/+/ead65e6c528a1a8efe7808a51e3f3db06406b9f7) in the previous version. @@ -139,7 +139,7 @@ These are some noteworthy fixes and improvements in this release: - **Breakpoints**: Fixed the bug with disappearing breakpoint editing dialog when the breakpoint type is changed ([1485782](https://crbug.com/1485782)). - **Performance**: - The color parsing error during performance recording has been fixed ([1480205](https://crbug.com/1480205)). - - Fixed the bug with [LCP](https://web.dev/lcp/) not showing in the **Timings** track ([1487136](https://crbug.com/1487136)). + - Fixed the bug with [LCP](https://web.dev/articles/lcp) not showing in the **Timings** track ([1487136](https://crbug.com/1487136)). - **Network**: The **Set cookies** column now shows the correct number of cookies that are set, excluding blocked ([1486903](https://crbug.com/1486903)). - DevTools extensions now load after navigation to a non-blocked host ([1476264](https://crbug.com/1476264)). - Fixed the bug with incorrect script execution context for extensions ([1275331](https://crbug.com/1275331)). diff --git a/site/en/blog/new-in-devtools-89/index.md b/site/en/blog/new-in-devtools-89/index.md index 87a6040f4..dcdd29ff6 100644 --- a/site/en/blog/new-in-devtools-89/index.md +++ b/site/en/blog/new-in-devtools-89/index.md @@ -419,7 +419,7 @@ To enable the experiment, check the **Show CSP Violations view** checkbox under {% endAside %} -View all [Content Security Policy (CSP)](https://web.dev/strict-csp/) violations at a glance in the new **CSP Violations** tab. +View all [Content Security Policy (CSP)](https://web.dev/articles/strict-csp) violations at a glance in the new **CSP Violations** tab. This new tab is an experiment that should make it easier to work with web pages with a large amount of CSP and Trusted Type violations. @@ -447,7 +447,7 @@ background), and context (ambient light, surroundings, intended purpose of the t {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/gYQKfU4hyzKlrK9w7wBr.png", alt="APCA in Color Picker", width="800", height="537" %} -The example show the APCA threshold is **38%**. The contrast ratio must meet or exceed the listed value. This value is calculated based on font weight and size, referring to this [APCA lookup table](https://bugs.chromium.org/p/chromium/issues/attachmentText?aid=486485). +The example show the APCA threshold is **38%**. The contrast ratio must meet or exceed the listed value. This value is calculated based on font weight and size, referring to this [APCA lookup table](https://bugs.chromium.org/p/chromium/issues/attachmentText?aid=486485). Chromium issue: [1121900][50] diff --git a/site/en/blog/new-in-devtools-91/index.md b/site/en/blog/new-in-devtools-91/index.md index af84a7474..0d1567129 100644 --- a/site/en/blog/new-in-devtools-91/index.md +++ b/site/en/blog/new-in-devtools-91/index.md @@ -46,13 +46,13 @@ Chromium issue: [862450](https://crbug.com/862450) ## New Memory inspector {: #memory-inspector } -Use the new **Memory inspector** to inspect an `ArrayBuffer` in JavaScript, as well as the Wasm memory. +Use the new **Memory inspector** to inspect an `ArrayBuffer` in JavaScript, as well as the Wasm memory. Open [this demo page](https://memory-inspector.glitch.me/demo-js.html). In the **Sources** panel, open the **demo-js.js** file, and set a breakpoint at line 18. Refresh the page. Expand the **Scope** section in the right **debugger** pane. Notice the new icon next to the **buffer** value. Click on it to reveal the **Memory Inspector**. -Check out the documentation to learn more about [inspecting JavaScript `ArrayBuffer` and `WebAssembly.Memory`](/docs/devtools/memory-inspector/) with this new Memory inspector. +Check out the documentation to learn more about [inspecting JavaScript `ArrayBuffer` and `WebAssembly.Memory`](/docs/devtools/memory-inspector/) with this new Memory inspector. {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/aDyRZhv31ZQq8X22MkgF.png", alt="Memory inspector", width="800", height="527" %} @@ -61,7 +61,7 @@ Chromium issue: [1166577](https://crbug.com/1166577) ## New badge settings pane in the Elements panel {: #badge-settings } -You can now selectively enable or disable badges via the **Badge settings** in the **Elements** panel. Use this feature to customize and stay focused on the important badges while inspecting web pages. +You can now selectively enable or disable badges via the **Badge settings** in the **Elements** panel. Use this feature to customize and stay focused on the important badges while inspecting web pages. {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/BliSe8qwK8G6lFvNtmTv.png", alt="badge settings pane in the Elements panel", width="800", height="524" %} @@ -73,7 +73,7 @@ Chromium issue: [1066772](https://crbug.com/1066772) ## Enhanced image preview with aspect ratio information {: #image-preview } -Image previews in the **Elements** panel now displays more information on the image - rendered size, rendered aspect ratio, intrinsic size, intrinsic aspect ratio, and file size. +Image previews in the **Elements** panel now displays more information on the image - rendered size, rendered aspect ratio, intrinsic size, intrinsic aspect ratio, and file size. This information helps you better understand your images and apply optimization if you need to. @@ -130,7 +130,7 @@ Chromium issue: [1092093](https://crbug.com/1092093) ## Categorize issue types with colors and icons {: #issue-category } The **Issues** tab now categorize issues into page errors, upcoming breaking changes, and possible improvements for better severity indication. You can open the **Issues** tab by clicking on the **issue count** button in the **Console**. -- **Page errors (red)**. Issues that have immediate impact for page functionality, such as not setting correct [CORS](https://web.dev/cross-origin-resource-sharing/) headers, etc. +- **Page errors (red)**. Issues that have immediate impact for page functionality, such as not setting correct [CORS](https://web.dev/articles/cross-origin-resource-sharing) headers, etc. - **Upcoming breaking changes (yellow)**. Issues that inform about an upcoming, incompatible change of the web platform that may result in a loss of page functionality (e.g. warning of upcoming [CORS RFC 1918 changes](https://web.dev/cors-rfc1918-feedback)). - **Possible improvements (blue)**. Potential improvements on the page, but are currently not impairing basic functionality of the page (e.g. accessibility issues) @@ -144,7 +144,7 @@ Chromium issue: [1183241](https://crbug.com/1183241) ## Delete Trust tokens {: #trust-tokens } You can now delete trust tokens with the new delete button in the **Trust tokens** pane, under the **Application** panel. -Trust Token is a new API to help combat fraud and distinguish bots from real humans, without passive tracking. Learn how to [get started with Trust Tokens](https://web.dev/trust-tokens/). +Trust Token is a new API to help combat fraud and distinguish bots from real humans, without passive tracking. Learn how to [get started with Trust Tokens](https://web.dev/articles/trust-tokens). {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/M3WPcQCDFBydw04zETEV.png", alt="Delete Trust tokens", width="800", height="435" %} @@ -164,7 +164,7 @@ Open this [demo](http://permission-policy-demo.glitch.me/) page. Go to the **App {# https://chromium.googlesource.com/devtools/devtools-frontend/+/4751c1c8dcb151c985b1e54cb1c1a05cb83704b8 #} {# https://chromium.googlesource.com/devtools/devtools-frontend/+/89cc8730ade0d0018671f19770bacc93b705b9ff #} - + Chromium issue: [1158827](https://crbug.com/1158827) @@ -191,7 +191,7 @@ Chromium issue: [1186049](https://crbug.com/1186049) ### Support for new JavaScript features {: #javascript } DevTools now support the new [private brand check](https://v8.dev/features/private-brand-checks) JavaScript language feature, a.k.a `#foo in obj`. -This private brand checks feature extends the [in operator](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/in) to support the [private class fields](https://v8.dev/features/class-fields#private-class-fields) testing on any given object. +This private brand checks feature extends the [in operator](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/in) to support the [private class fields](https://v8.dev/features/class-fields#private-class-fields) testing on any given object. Try it out in the **Console** and **Sources** panel. You can inspect the private fields in the **Scope** section under the **debugger** pane as well. @@ -201,7 +201,7 @@ Chromium issue: [11374](https://crbug.com/v8/11374) ### Enhanced support for breakpoints debugging {: #breakpoint } -DevTools now properly set breakpoints in multiple scripts correctly. Modern JavaScript bundlers (e.g. [Webpack](https://webpack.js.org/), [Rollup](https://rollupjs.org/)) support code splitting feature - there are scenarios where one shared component can be included in multiple routes (code splits). +DevTools now properly set breakpoints in multiple scripts correctly. Modern JavaScript bundlers (e.g. [Webpack](https://webpack.js.org/), [Rollup](https://rollupjs.org/)) support code splitting feature - there are scenarios where one shared component can be included in multiple routes (code splits). Previously, DevTools was only able to set breakpoints on one raw location. With this latest improvement, DevTools can set breakpoints in all relevant locations correctly. @@ -221,7 +221,7 @@ Chromium issue: [1178305](https://crbug.com/1178305) ### Improved outline of HTML files {: #html-outline } -DevTools now has better outline support for HTML files. In the **Sources** panel, open a HTML file. You can toggle the code outline with keyboard Cmd + Shift + O in Mac or Ctrl + Shift + O in Windows. +DevTools now has better outline support for HTML files. In the **Sources** panel, open a HTML file. You can toggle the code outline with keyboard Cmd + Shift + O in Mac or Ctrl + Shift + O in Windows. In the example below, DevTools now correctly list all functions in the outline. Previously, DevTools only showed some of the functions. diff --git a/site/en/blog/new-in-devtools-92/index.md b/site/en/blog/new-in-devtools-92/index.md index 40d38bcdb..52a496b2c 100644 --- a/site/en/blog/new-in-devtools-92/index.md +++ b/site/en/blog/new-in-devtools-92/index.md @@ -145,7 +145,7 @@ Chromium issue: [622660](https://crbug.com/622660) ## Include Compute Intersections in the Performance panel {: #computed-intersections } -DevTools now show the **Compute Intersections** in the flame chart. These changes help you to identify the [intersection observers](https://web.dev/intersectionobserver-v2/) events and debug on its potential performance overheads. +DevTools now show the **Compute Intersections** in the flame chart. These changes help you to identify the [intersection observers](https://web.dev/articles/intersectionobserver-v2) events and debug on its potential performance overheads. {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/Nx3K0Lpst0lICGbtpzsW.png", alt="Compute Intersections in the Performance panel", width="800", height="496" %} diff --git a/site/en/blog/new-in-devtools-93/index.md b/site/en/blog/new-in-devtools-93/index.md index c391e321d..78e773179 100644 --- a/site/en/blog/new-in-devtools-93/index.md +++ b/site/en/blog/new-in-devtools-93/index.md @@ -20,7 +20,7 @@ tags: {% YouTube id="1VaPAnUGRz8" %} ## Editable CSS container queries in the Styles pane {: #container-queries } -You can now view and edit [CSS container queries](https://web.dev/new-responsive/#responsive-to-the-container) in the **Styles** pane. +You can now view and edit [CSS container queries](https://web.dev/articles/new-responsive#responsive_to_the_container) in the **Styles** pane. Container queries provide a much more dynamic approach to responsive design. The `@container` at-rule works in a similar way to a media query with `@media`. However, instead of querying the viewport and user agent for information, `@container` queries the ancestor container that matches certain criteria. @@ -38,7 +38,7 @@ Chromium issue: [1146422](https://crbug.com/1146422) ## Web bundle preview in the Network panel {: #web-bundle } -[Web bundle](https://web.dev/web-bundles/) is a file format for encapsulating one or more HTTP resources in a single file. You can now preview the web bundle content in the **Network** panel. +[Web bundle](https://web.dev/articles/web-bundles) is a file format for encapsulating one or more HTTP resources in a single file. You can now preview the web bundle content in the **Network** panel. The web bundle feature is experimental currently. Please enable `#enable-experimental-web-platform-features` flag under `chrome://flags` to test it. @@ -143,4 +143,4 @@ Open a JSON response in the **Network** panel, click on the `{}` icon to pretty- Chromium bug: [998674](https://crbug.com/998674) {% Partial 'devtools/reach-out.md' %} -{% Partial 'devtools/whats-new.md' %} \ No newline at end of file +{% Partial 'devtools/whats-new.md' %} diff --git a/site/en/blog/new-in-devtools-96/index.md b/site/en/blog/new-in-devtools-96/index.md index aacfbd372..026540537 100644 --- a/site/en/blog/new-in-devtools-96/index.md +++ b/site/en/blog/new-in-devtools-96/index.md @@ -55,7 +55,7 @@ You can disable it via the **Settings** > **Experiments** > **Enable CSS length Chromium issues: [1259088](https://crbug.com/1259088), [1172993](https://crbug.com/1172993) -## Rendering tab updates +## Rendering tab updates ### Emulate the CSS prefers-contrast media feature {: #prefers-contrast } {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/47fsHvVLiVC9J0eWY9wD.png", alt="Emulate the CSS prefers-contrast media feature", width="800", height="483" %} @@ -73,7 +73,7 @@ Chromium issue: [1139777](https://crbug.com/1139777) Use DevTools to emulate auto dark theme to easily see how your page looks when Chrome’s [Auto Dark Theme](/blog/auto-dark-theme/) is enabled. -Chrome 96 introduces an [Origin Trial](/blog/origin-trials/) for [Auto Dark Theme](/blog/auto-dark-theme/) on Android. With this feature, the browser applies an automatically generated dark theme to light themed sites, when the user has opted into dark themes in the Operating System. +Chrome 96 introduces an [Origin Trial](/blog/origin-trials/) for [Auto Dark Theme](/blog/auto-dark-theme/) on Android. With this feature, the browser applies an automatically generated dark theme to light themed sites, when the user has opted into dark themes in the Operating System. Open the [Command Menu](/docs/devtools/command-menu/), run the **Show Rendering** command, and then set the **Emulate auto dark mode** dropdown. @@ -120,7 +120,7 @@ Together with the **Properties** pane [enhancements](/blog/new-in-devtools-95/#p {# https://chromium.googlesource.com/devtools/devtools-frontend/+/f1574e9b550317c481a943fec059d84bfb863564 #} -Chromium issue: [1226262](https://crbug.com/1226262) +Chromium issue: [1226262](https://crbug.com/1226262) ## Console updates @@ -150,7 +150,7 @@ Chromium issue: [1073804](https://crbug.com/1073804) ### Consistent async stack traces {: #async } -The Console now reports `async` stack traces for `async` functions to be consistent with other async tasks, and consistent with what's shown in the Call Stack.. +The Console now reports `async` stack traces for `async` functions to be consistent with other async tasks, and consistent with what's shown in the Call Stack.. {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/wuKo84nrDzbhwCnIVU2n.png", alt="async stack traces", width="800", height="427" %} @@ -174,11 +174,11 @@ Chromium issues: [1232937](https://crbug.com/1232937), [1255586](https://crbug.c ## Deprecated Application cache pane in the Application panel {: #app-cache } -The [Application cache](/docs/devtools/storage/applicationcache/) pane in the Application panel is now removed as the support for [AppCache](https://web.dev/appcache-removal/) is removed from Chrome and other Chromium-based browsers. +The [Application cache](/docs/devtools/storage/applicationcache/) pane in the Application panel is now removed as the support for [AppCache](https://web.dev/articles/appcache-removal) is removed from Chrome and other Chromium-based browsers. {# https://chromium.googlesource.com/devtools/devtools-frontend/+/de4d15e955d6145674e3885cde8a5a70f1269b79 #} -Chromium issue: [1084190](https://crbug.com/1084190) +Chromium issue: [1084190](https://crbug.com/1084190) ## [Experimental] New Reporting API pane in the Application panel {: #reporting-api } @@ -187,13 +187,13 @@ Chromium issue: [1084190](https://crbug.com/1084190) To enable the experiment, check the **Enable Reporting API panel in the Application panel** checkbox under **Settings** > **Experiments**. {% endAside %} -The [Reporting API](https://web.dev/reporting-api/) is designed to help you monitor security violations of your page, deprecated API calls, and more. +The [Reporting API](https://web.dev/articles/reporting-api) is designed to help you monitor security violations of your page, deprecated API calls, and more. -With this experiment enabled, you can now view the reports status in the new **Reporting API** pane in the **Application** panel. +With this experiment enabled, you can now view the reports status in the new **Reporting API** pane in the **Application** panel. -Please note that the **Endpoints** section is currently still under active development (showing no reporting endpoints for now). +Please note that the **Endpoints** section is currently still under active development (showing no reporting endpoints for now). -Learn more about the **Reporting API** with [this article](https://web.dev/reporting-api/). +Learn more about the **Reporting API** with [this article](https://web.dev/articles/reporting-api). {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/hbwFqi9aNDOj70FhLXsn.png", alt="Reporting API pane in the Application panel", width="800", height="476" %} diff --git a/site/en/blog/new-in-devtools-98/index.md b/site/en/blog/new-in-devtools-98/index.md index 2466acf35..9e9d0a4e5 100644 --- a/site/en/blog/new-in-devtools-98/index.md +++ b/site/en/blog/new-in-devtools-98/index.md @@ -21,7 +21,7 @@ tags: ## Preview feature: Full-page accessibility tree {: #a11y-tree } -The new **Full-page accessibility tree** makes it easier for you to get an overview of the full-page [accessibility tree](/blog/full-accessibility-tree/#what-is-the-accessibility-tree) and help you better understand how your web content is exposed to assistive technology. +The new **Full-page accessibility tree** makes it easier for you to get an overview of the full-page [accessibility tree](/blog/full-accessibility-tree/#what-is-the-accessibility-tree) and help you better understand how your web content is exposed to assistive technology. In the **Elements** panel, open the **Accessibility** pane and select **Enable full-page accessibility tree** checkbox. Then, reload DevTools and you will see a new accessibility button in the **Elements** panel. @@ -40,11 +40,11 @@ Our team is still actively working on this preview feature. We are looking for y Chromium issue: [887173](https://crbug.com/887173) -## More precise changes in the Changes tab {: #changes } +## More precise changes in the Changes tab {: #changes } -The code changes in the **Changes** tab is pretty-printed automatically. +The code changes in the **Changes** tab is pretty-printed automatically. -Previously, it was hard to trace the actual changes of minified source code because all the code is shown in a single line. +Previously, it was hard to trace the actual changes of minified source code because all the code is shown in a single line. {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/aup2bT490dkvuBu3o4DS.png", alt="Changes tab", width="800", height="450" %} @@ -61,8 +61,8 @@ For example, I [recorded a user flow](/docs/devtools/recorder/#record) on this [ We can use the new **Timeout** settings to fix this. Expand the step which we click on the menu item. [Edit the step](/docs/devtools/recorder/#edit-steps) by **Add timeout** and set it to **6000** milliseconds (equal to 6s). -Optionally, you can adjust the **Timeout** in the **Replay settings** for all the steps. Expand the **Replay settings** and edit the **Timeout** value. - +Optionally, you can adjust the **Timeout** in the **Replay settings** for all the steps. Expand the **Replay settings** and edit the **Timeout** value. + {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/y7RDpIp3pd2n6Vnxc5Du.png", alt="timeout settings for user flow recording", width="800", height="530" %} Chromium issue: [1257499](https://crbug.com/1257499) @@ -70,13 +70,13 @@ Chromium issue: [1257499](https://crbug.com/1257499) ## Ensure your pages are cacheable with the Back/forward cache tab {: #bfcache } -[Back/forward cache (or bfcache)](https://web.dev/bfcache/) is a browser optimization that enables instant back and forward navigation. +[Back/forward cache (or bfcache)](https://web.dev/articles/bfcache) is a browser optimization that enables instant back and forward navigation. The new **Back/forward cache** tab can help you test your pages to ensure they're optimized for bfcache, and identify any issues that may be preventing them from being eligible. To test a particular page, navigate to it in Chrome and then in DevTools go to **Application** > **Back-forward Cache**. Next, click the **Test back/forward cache** button and DevTools will attempt to navigate away and back to determine whether the page could be restored from bfcache. -As web developers, it's critical to know how to optimize your pages for bfcache across all browsers because it will significantly improve the browsing experience for users—especially those with slower networks or devices. +As web developers, it's critical to know how to optimize your pages for bfcache across all browsers because it will significantly improve the browsing experience for users—especially those with slower networks or devices. {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/4OrWjuRgG1bB0AupcMmS.png", alt="Back/forward cache tab", width="800", height="516" %} @@ -87,22 +87,22 @@ Chromium issue: [1110752](https://crbug.com/1110752) ## New Properties pane filter {: #properties } -If you want to focus on a specific property in the **Properties** pane, you can now type that property name or value in the new **Filter** textbox. +If you want to focus on a specific property in the **Properties** pane, you can now type that property name or value in the new **Filter** textbox. -By default, properties whose value is `null` or `undefined` are not shown. Enable the **Show all** checkbox to view all properties. +By default, properties whose value is `null` or `undefined` are not shown. Enable the **Show all** checkbox to view all properties. These enhancements allow you to get to the properties you care for quicker and thus improve your productivity! {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/ewmNloO4ohRxlWRNuEW1.png", alt="Properties pane filter", width="800", height="505" %} -{# https://chromium.googlesource.com/devtools/devtools-frontend/+/0980f52facf75b6c03e14472d13fe27968d4732b #} - +{# https://chromium.googlesource.com/devtools/devtools-frontend/+/0980f52facf75b6c03e14472d13fe27968d4732b #} + Chromium issue: [1269674](https://crbug.com/1269674) ## Emulate the CSS forced-colors media feature {: #forced-colors } -The [forced-colors](https://drafts.csswg.org/mediaqueries-5/#forced-colors) CSS media feature is used to detect if the user agent has enabled a forced colors mode (e.g. Windows High Contrast mode) where it enforces a user-chosen limited color palette on the page. +The [forced-colors](https://drafts.csswg.org/mediaqueries-5/#forced-colors) CSS media feature is used to detect if the user agent has enabled a forced colors mode (e.g. Windows High Contrast mode) where it enforces a user-chosen limited color palette on the page. Open the [Command Menu](/docs/devtools/command-menu/), run the **Show Rendering** command, and then set the **Emulate CSS media feature forced-colors** dropdown. @@ -127,7 +127,7 @@ Chromium issue: [1270562](https://crbug.com/1270562) ## Support `row-reverse` and `column-reverse` in the Flexbox editor {: #flexbox-editor } -The [Flexbox editor](/blog/new-in-devtools-90/#flexbox) added two new buttons to support `row-reverse` and `column-reverse` in `flex-direction`. +The [Flexbox editor](/blog/new-in-devtools-90/#flexbox) added two new buttons to support `row-reverse` and `column-reverse` in `flex-direction`. {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/JHI4frP4MqaydXk19sq2.png", alt="Flexbox editor", width="800", height="546" %} @@ -148,7 +148,7 @@ Select a XHR request in the **Network** panel and press **R** on the keyboard to Chromium issue: [1050021](https://crbug.com/1050021) - + ### Keyboard shortcut to expand all search results {: #toggle-search-result } A new shortcut is added in the **Search** tab allowing you to expand and collapse all the search results. Previously, you could only expand and collapse the search results by clicking on one file at a time. @@ -171,7 +171,7 @@ Chromium issue: [1255073](https://crbug.com/1255073) The **Lighthouse** panel is now running Lighthouse 9. Lighthouse will now list all the elements sharing the same id. -Non-unique element id is a common accessibility problem. For instance, the id referenced in an `aria-labelledby` attribute is used on [multiple elements](https://web.dev/duplicate-id-aria/). +Non-unique element id is a common accessibility problem. For instance, the id referenced in an `aria-labelledby` attribute is used on [multiple elements](https://web.dev/articles/duplicate-id-aria). Check out the [What’s new in Lighthouse 9.0](/blog/lighthouse-9-0/) for more details on the updates. @@ -187,11 +187,11 @@ Loads of stability improvements in the **Sources** panel as we upgraded it to us - Significantly faster when opening large files (e.g. WASM, JavaScript) - No more random scrolling when stepping through code -- Improved auto-complete suggestions for editable sources (e.g. snippets, local override) +- Improved auto-complete suggestions for editable sources (e.g. snippets, local override) {# https://chromium.googlesource.com/devtools/devtools-frontend/+/c1ab112d9002d5c3b3bb70cf2839bac182f0cdb5 #} -Chromium issue: [1241848](https://crbug.com/1241848) +Chromium issue: [1241848](https://crbug.com/1241848) ## Miscellaneous highlights {: #misc } @@ -199,7 +199,7 @@ These are some noteworthy fixes in this release: - Properly displaying the waterfall diagram of network requests. Previously, the style was broken. ([1275501](https://crbug.com/1275501)) - The code highlight was broken when searching in documents with very long lines in the **Sources** panel. It’s now fixed. ([1275496](https://crbug.com/1275496)) -- No more duplicate **Payload** tab in network requests. ([1273972](https://crbug.com/1273972)) +- No more duplicate **Payload** tab in network requests. ([1273972](https://crbug.com/1273972)) - Fixed the missing layout shifts details in the **Summary** section of the **Performance** panel. ([1259606](https://crbug.com/1259606)) - Support arbitrary characters (e.g. `,`, `.`), in **Network Search** queries. ([1267196](https://crbug.com/1267196)) @@ -214,11 +214,11 @@ The experimental **Reporting API** pane was introduced in [Chrome 96](/blog/new- The **Endpoints** section is now available. It gives you an overview of all the endpoints configured in the `Reporting-Endpoints` header. -Learn to use the [Reporting API](https://web.dev/reporting-api/) to monitor security violations, deprecated API calls, and more. +Learn to use the [Reporting API](https://web.dev/articles/reporting-api) to monitor security violations, deprecated API calls, and more. {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/D1fUz4zuS1xwDbszgft1.png", alt="Reporting API pane", width="800", height="560" %} -{# https://chromium.googlesource.com/devtools/devtools-frontend/+/a831b26b7ecde579144a42a4faaa7b639789bf3c #} +{# https://chromium.googlesource.com/devtools/devtools-frontend/+/a831b26b7ecde579144a42a4faaa7b639789bf3c #} Chromium issue: [1200732](https://crbug.com/1200732) diff --git a/site/en/blog/new-in-devtools-99/index.md b/site/en/blog/new-in-devtools-99/index.md index b4cd4dcdb..b389b6921 100644 --- a/site/en/blog/new-in-devtools-99/index.md +++ b/site/en/blog/new-in-devtools-99/index.md @@ -33,7 +33,7 @@ Chromium issue: [423246](https://crbug.com/423246) Use the new **Reporting API** pane to monitor the reports generated on your page and their status. -The [Reporting API](https://web.dev/reporting-api/) is designed to help you monitor security violations of your page, deprecated API calls, and more. +The [Reporting API](https://web.dev/articles/reporting-api) is designed to help you monitor security violations of your page, deprecated API calls, and more. Open a page which uses the Reporting API (e.g. [demo page](https://reporting-api-demo.glitch.me/)). In the **Application** panel, scroll down to the **Background services** section and select the **Reporting API** pane. @@ -129,7 +129,7 @@ Chromium issue: [1284737](https://crbug.com/1284737) ### Display worker source files in the Sources panel {: #worker-sourcemap } -[Worker](https://web.dev/workers-overview/) (e.g. web worker, service worker) source files with relative SourceURL are now displayed in the **Source** panel. Previously, worker source files were not handled correctly. +[Worker](https://web.dev/articles/workers-overview) (e.g. web worker, service worker) source files with relative SourceURL are now displayed in the **Source** panel. Previously, worker source files were not handled correctly. {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/apH5n92bqYWINMQn5VXa.png", alt="ALT_TEXT_HERE", width="800", height="509" %} @@ -173,8 +173,8 @@ These are some noteworthy fixes in this release: - Fixed the [edit cookies](/docs/devtools/storage/cookies/#edit) issue in the **Cookies** pane. ([1290196](https://crbug.com/1290196)) - Use `Shift` + `Tab` to select the previous command in the [Command menu](/docs/devtools/command-menu/). ([1278743](https://crbug.com/1278743)) -- Report [CORS preflight request](https://web.dev/cross-origin-resource-sharing/#preflight-requests-for-complex-http-calls) issues in the [Issues](/docs/devtools/issues/) tab. ([1272445](https://crbug.com/1272445)). -- Report [User-Agent Client Hints](https://web.dev/user-agent-client-hints/) issues in the [Issues](/docs/devtools/issues/) tab. ([1219359](https://crbug.com/1219359)). +- Report [CORS preflight request](https://web.dev/articles/cross-origin-resource-sharing#preflight_requests_for_complex_http_calls) issues in the [Issues](/docs/devtools/issues/) tab. ([1272445](https://crbug.com/1272445)). +- Report [User-Agent Client Hints](https://web.dev/articles/user-agent-client-hints) issues in the [Issues](/docs/devtools/issues/) tab. ([1219359](https://crbug.com/1219359)). - Fixed `Shift` + `Delete` and `Page up` / `Page down` behaviors in the **Sources** and **Console** panel. ([1278461](https://crbug.com/1278461), [1285662](https://crbug.com/1285662)) - Close the breakpoint edit dialog on breakpoint removal in the **Sources** panel. (922513) - No reload required when [switching light/dark theme](/docs/devtools/customize/dark-theme/) in DevTools. ([1278738](https://crbug.com/1278738)) diff --git a/site/en/blog/no-spooky-cookies/index.md b/site/en/blog/no-spooky-cookies/index.md index a64770be3..d19561fc8 100644 --- a/site/en/blog/no-spooky-cookies/index.md +++ b/site/en/blog/no-spooky-cookies/index.md @@ -109,7 +109,7 @@ goes stale, and (of course!) is only allowed in same-site contexts. {% Aside %} **Read more:** There's plenty of tweaking you can do to suit your taste and we've got all the details in our [first-party cookie -recipes](https://web.dev/first-party-cookie-recipes/). +recipes](https://web.dev/articles/first-party-cookie-recipes). {% endAside %} ## Cookies taste better with CHIPS! @@ -188,7 +188,7 @@ midway through 2024. There's time to prepare, but you should start planning now. that will require updates. 2. If you don't have any third-party cookies, make sure your same-site cookies are using the best [First-party cookies - recipes](https://web.dev/first-party-cookie-recipes/) + recipes](https://web.dev/articles/first-party-cookie-recipes) 3. If you use those cookies in a fully contained, embedded context then investigate and test the [CHIPS proposal](/docs/privacy-sandbox/chips/). 4. If you need those cookies across multiple sites that form one cohesive group, diff --git a/site/en/blog/optimizing-lcp-using-signed-exchanges/index.md b/site/en/blog/optimizing-lcp-using-signed-exchanges/index.md index 37ad1d544..eb127ed16 100644 --- a/site/en/blog/optimizing-lcp-using-signed-exchanges/index.md +++ b/site/en/blog/optimizing-lcp-using-signed-exchanges/index.md @@ -13,7 +13,7 @@ tags: - performance --- -Signed exchanges (SXGs) are a means to improve your page speed—mainly [Largest Contentful Paint (LCP)](https://web.dev/lcp/). When referring sites (currently Google Search) link to a page, they can [prefetch it](https://developers.google.com/search/docs/advanced/experience/signed-exchange) into the browser cache before the user clicks on the link. +Signed exchanges (SXGs) are a means to improve your page speed—mainly [Largest Contentful Paint (LCP)](https://web.dev/articles/lcp). When referring sites (currently Google Search) link to a page, they can [prefetch it](https://developers.google.com/search/docs/advanced/experience/signed-exchange) into the browser cache before the user clicks on the link. It's possible to make web pages that, when prefetched, require no network on the [critical path to rendering the page](https://developer.mozilla.org/docs/Web/Performance/Critical_rendering_path)! On a 4G connection, this page load [goes from 2.8s to 0.9s](https://www.webpagetest.org/video/compare.php?tests=220422_AiDcJ6_54R-l:Before,220329_BiDc1V_FJG-l:After&medianMetric=LCP) (the remaining 0.9s being mostly by CPU usage): @@ -61,7 +61,7 @@ SXGs are potentially useful for other use cases not covered in this article. For To see the benefit of SXGs, start by using a lab tool to analyze SXG performance in repeatable conditions. You can use [WebPageTest](https://www.webpagetest.org/) to compare waterfalls—and LCP—with and without SXG prefetch. {% Aside 'caution' %} -[Lab results may differ](https://web.dev/lab-and-field-data-differences/) from real user experiences, but they are a useful tool to diagnose where to optimize and to iterate quickly. We'll cover how to measure the resultant real user metrics in the [Measure section](#measure). +[Lab results may differ](https://web.dev/articles/lab-and-field-data-differences) from real user experiences, but they are a useful tool to diagnose where to optimize and to iterate quickly. We'll cover how to measure the resultant real user metrics in the [Measure section](#measure). {% endAside %} Generate a test without SXG as follows: @@ -317,7 +317,7 @@ If it's working, you'll see additional prefetches from Google Search: {% Img src="image/rULxC7pPw3PFS4o9xr7v8isFmCv1/e09y5ZGYE93zgPi2pyFk.png", alt="Google Search results with DevTools Network tab, showing a prefetch of /sub/…/image.jpg", width="800", height="493" %} </figure> -To optimize for LCP, look closely at your waterfall, and figure out which resources are on the critical path to rendering the largest element. If they can't be prefetched, consider if they can be [taken off the critical path](https://web.dev/render-blocking-resources/#how-to-eliminate-render-blocking-scripts). Be on the lookout for scripts that hide the page until they are done loading. +To optimize for LCP, look closely at your waterfall, and figure out which resources are on the critical path to rendering the largest element. If they can't be prefetched, consider if they can be [taken off the critical path](https://web.dev/articles/render-blocking-resources#how_to_eliminate_render_blocking_scripts). Be on the lookout for scripts that hide the page until they are done loading. The Google SXG Cache allows [up to 20](https://github.com/google/webpackager/blob/main/docs/cache_requirements.md#:~:text=There%20may%20be%20no%20more%20than%2020%20rel%3Dpreloads.) subresource preloads and ASX [ensures](https://github.com/google/sxg-rs/blob/33fa49bbd1f156ce92de0e3b6af9e352b1ba8d9f/sxg_rs/src/link.rs#L60) that this limit isn't exceeded. However, there is a risk in adding too many subresource preloads. The browser will only use preloaded subresources [if all of them have finished fetching](https://github.com/WICG/webpackage/blob/main/explainers/signed-exchange-subresource-substitution.md#:~:text=If%20every%20member,their%20original%20URLs.), in order to [prevent cross-site tracking](https://wicg.github.io/webpackage/loading.html#:~:text=This%20is%20intended%20to%20prevent%20the%20referrer%20page%20from%20encoding%20a%20tracking%20ID%20into%20the%20set%20of%20subresources%20it%20prefetches.). The more subresources there are, the less likely all of them will have finished prefetching before the user clicks through to your page. @@ -333,7 +333,7 @@ After optimizing the LCP improvement under WebPageTest, it's useful to measure t ### Server-side metrics -When measuring server-side metrics such as [Time to First Byte (TTFB)](https://web.dev/ttfb/), it's important to note that your site only serves SXGs to crawlers that accept the format. Limit your measurement of TTFB to requests coming from real users, and not bots. You may find that generating SXGs increases the TTFB for crawler requests, but this has no impact on your visitors' experience. +When measuring server-side metrics such as [Time to First Byte (TTFB)](https://web.dev/articles/ttfb), it's important to note that your site only serves SXGs to crawlers that accept the format. Limit your measurement of TTFB to requests coming from real users, and not bots. You may find that generating SXGs increases the TTFB for crawler requests, but this has no impact on your visitors' experience. ### Client-side metrics @@ -468,5 +468,5 @@ Phew! That was a lot. Hopefully it paints a more complete picture of how to test If you have additional advice on how to capture SXG performance, please let us know! [File a bug against developer.chrome.com](https://github.com/GoogleChrome/developer.chrome.com) with your suggested improvements. -For more information on signed exchanges, take a look at the [web.dev documentation](https://web.dev/signed-exchanges/) and the [Google Search documentation](https://developers.google.com/search/docs/advanced/experience/signed-exchange). +For more information on signed exchanges, take a look at the [web.dev documentation](https://web.dev/articles/signed-exchanges) and the [Google Search documentation](https://developers.google.com/search/docs/advanced/experience/signed-exchange). diff --git a/site/en/blog/passkeys-on-icloud-keychain/index.md b/site/en/blog/passkeys-on-icloud-keychain/index.md index a60323154..404728e90 100644 --- a/site/en/blog/passkeys-on-icloud-keychain/index.md +++ b/site/en/blog/passkeys-on-icloud-keychain/index.md @@ -164,9 +164,9 @@ Settings. * [Passwordless login with passkeys | Authentication | Google for Developers](https://developers.google.com/identity/passkeys/) -* [Create a passkey for passwordless logins](https://web.dev/passkey-registration/) +* [Create a passkey for passwordless logins](https://web.dev/articles/passkey-registration) * [Sign in with a passkey through form - autofill](https://web.dev/passkey-form-autofill/) + autofill](https://web.dev/articles/passkey-form-autofill) * [Implement passkeys with form autofill in a web app](https://developers.google.com/codelabs/passkey-form-autofill#0) diff --git a/site/en/blog/payment-handler-canmakepayment-update/index.md b/site/en/blog/payment-handler-canmakepayment-update/index.md index 1214022d1..19e0d1a3e 100644 --- a/site/en/blog/payment-handler-canmakepayment-update/index.md +++ b/site/en/blog/payment-handler-canmakepayment-update/index.md @@ -10,15 +10,15 @@ authors: date: 2022-10-27 updated: 2023-02-07 --- - -[The Payment Handler API](https://web.dev/web-based-payment-apps-overview/) + +[The Payment Handler API](https://web.dev/articles/web-based-payment-apps-overview) allows payment providers to make their custom payment experience available for merchants, along with [the Payment Request -API](https://web.dev/how-payment-request-api-works/). When [the Payment Request -API](https://web.dev/how-payment-request-api-works/) is initialized via the +API](https://web.dev/articles/how-payment-request-api-works). When [the Payment Request +API](https://web.dev/articles/how-payment-request-api-works) is initialized via the `new PaymentRequest()` constructor, it silently fires a `canmakepayment` event with the merchant's origin and arbitrary data to -[a service worker that is registered for the Payment Handler API](https://web.dev/orchestrating-payment-transactions/). +[a service worker that is registered for the Payment Handler API](https://web.dev/articles/orchestrating-payment-transactions). This cross-origin communication does not require a user gesture and does not show any user interface. @@ -69,7 +69,7 @@ To enable the change locally for development purposes: By enabling the flag, the identity fields in the `canmakepayment` event will be emptied-out (and -[the Android `IS_READY_TO_PAY` Intent](https://web.dev/android-payment-apps-developers-guide/#step-2-let-a-merchant-know-if-a-customer-has-an-enrolled-instrument-that-is-ready-to-pay)). +[the Android `IS_READY_TO_PAY` Intent](https://web.dev/articles/android-payment-apps-developers-guide#step_2_let_a_merchant_know_if_a_customer_has_an_enrolled_instrument_that_is_ready_to_pay)). ## Enable the change in production diff --git a/site/en/blog/payment-handler-csp-connect-src/index.md b/site/en/blog/payment-handler-csp-connect-src/index.md index c41db5889..6f7c147f9 100644 --- a/site/en/blog/payment-handler-csp-connect-src/index.md +++ b/site/en/blog/payment-handler-csp-connect-src/index.md @@ -11,15 +11,15 @@ alt: 'Using a ATM - Hand pressing number' date: 2022-09-29 --- -[The Payment Handler API](https://web.dev/web-based-payment-apps-overview/) +[The Payment Handler API](https://web.dev/articles/web-based-payment-apps-overview) allows payment providers to make their custom payment experience available for merchants, along with [the Payment Request -API](https://web.dev/how-payment-request-api-works/). +API](https://web.dev/articles/how-payment-request-api-works). The information on this page only applies to websites that use both [CSP (Content-Security-Policy)](https://developer.mozilla.org/docs/Web/HTTP/Headers/Content-Security-Policy/) and the Payment Request API. If you use neither or only one of the two, then you -can skip these instructions. +can skip these instructions. To check if your payment provider is using the Payment Handler API, contact them and follow their instructions. @@ -35,7 +35,7 @@ your CSP `connect-src` must include `https://example.com` or `https://example.com/pay`: ```http -Content-Security-Policy: connect-src https://example.com/pay +Content-Security-Policy: connect-src https://example.com/pay ``` If `https://example.com/pay` is a cross-origin redirect, then the destination diff --git a/site/en/blog/permissions-chip/index.md b/site/en/blog/permissions-chip/index.md index d6233cd33..1cb56f93f 100644 --- a/site/en/blog/permissions-chip/index.md +++ b/site/en/blog/permissions-chip/index.md @@ -117,7 +117,7 @@ without any interaction. In the short term, and until users get used to the new UI, it is likely that site owners will observe lower grant rates for sites, especially for those that auto-request permissions without priming or -demanding a user gesture (which is considered a [bad practice](https://web.dev/notification-on-start/) anyway). This +demanding a user gesture (which is considered a [bad practice](https://web.dev/articles/notification-on-start) anyway). This acknowledged downside is vastly outweighed by the less interruptive experience. ### Best practices diff --git a/site/en/blog/prerender-pages/index.md b/site/en/blog/prerender-pages/index.md index 59851241c..aaabeff33 100644 --- a/site/en/blog/prerender-pages/index.md +++ b/site/en/blog/prerender-pages/index.md @@ -55,7 +55,7 @@ Prerendering allows a near-instant page load as shown in the Video below when pr %} </figure> -The [web.dev](https://web.dev/) site is already a fast site, but even with this you can see how prerendering improves the user experience. This can therefore also have a direct impact on a site's [Core Web Vitals](https://web.dev/vitals/), with near zero LCP, reduced CLS (since any load CLS happens before the initial view), and improved FID (since the load should be completed before the user interacts). +The [web.dev](https://web.dev/) site is already a fast site, but even with this you can see how prerendering improves the user experience. This can therefore also have a direct impact on a site's [Core Web Vitals](https://web.dev/articles/vitals), with near zero LCP, reduced CLS (since any load CLS happens before the initial view), and improved FID (since the load should be completed before the user interacts). Even when a page activates before it is fully loaded, having a head start to the page load, should improve the loading experience. When a link is activated while prerendering is still happening, the prerendering page will move to the main frame and continue loading. @@ -257,7 +257,7 @@ Removing speculation rules will result in the prerender being cancelled but, by ### Speculation rules and Content Security Policy -As speculation rules use a `<script>` element, even though they only contain JSON, they need to be included in the `script-src` [Content-Security-Policy](https://web.dev/csp/) if the site uses this—either using a hash or nonce. +As speculation rules use a `<script>` element, even though they only contain JSON, they need to be included in the `script-src` [Content-Security-Policy](https://web.dev/articles/csp) if the site uses this—either using a hash or nonce. A new `inline-speculation-rules` can be added to `script-src` allowing `<script type="speculationrules">` elements injected from hash/nonced scripts to be supported. At present, this only supports injected rules and does not [yet support rules includes in the initial HTML](https://bugs.chromium.org/p/chromium/issues/detail?id=1433616). @@ -372,7 +372,7 @@ gtag('set', { 'dimension1': pagePrerendered() }); gtag('config', 'UA-12345678-1'); ``` -This will allow your analytics to show how many navigation are prerendered compared to other types of navigation, and also allow you to correlation any performance metrics or business metrics to these different navigation types. Faster pages means happier users, which can often have real impact on business measures as our [case studies](https://web.dev/tags/case-study/) show. +This will allow your analytics to show how many navigation are prerendered compared to other types of navigation, and also allow you to correlation any performance metrics or business metrics to these different navigation types. Faster pages means happier users, which can often have real impact on business measures as our [case studies](https://web.dev/articles/tags/case-study) show. As you measure the business impact of prerendering pages for instant navigations, you can decide whether it is worth investing more effort in using this technology to allow more navigations to be prerendered, or to investigate why pages are not being prerendered. @@ -388,7 +388,7 @@ The "successful hit rate" can then be approximated by looking at the difference Be aware that some prerendering may be taking place due to the address bar prerendering and not just your speculation rules. You can check the `document.referrer` (which will be blank for address bar navigation including prerendered address bar navigations) if you wish to differentiate these. -Remember to also look at pages which have no prerenders, as that could indicate these pages are not eligible for prerendering, even from the address bar. That may mean you are not benefiting from this performance enhancement. The Chrome team is looking to add extra tooling to test for Prerender eligibility perhaps [similar to the bfcache testing tool](https://web.dev/bfcache/#test-to-ensure-your-pages-are-cacheable), and also potentially add an API to expose why a prerender failed. +Remember to also look at pages which have no prerenders, as that could indicate these pages are not eligible for prerendering, even from the address bar. That may mean you are not benefiting from this performance enhancement. The Chrome team is looking to add extra tooling to test for Prerender eligibility perhaps [similar to the bfcache testing tool](https://web.dev/articles/bfcache#test_to_ensure_your_pages_are_cacheable), and also potentially add an API to expose why a prerender failed. ## Impact on extensions diff --git a/site/en/blog/privacy-sandbox-participate/index.md b/site/en/blog/privacy-sandbox-participate/index.md index 4612e4fac..1a89e4e38 100644 --- a/site/en/blog/privacy-sandbox-participate/index.md +++ b/site/en/blog/privacy-sandbox-participate/index.md @@ -14,24 +14,24 @@ tags: - security --- -[The Privacy Sandbox initiative](https://web.dev/digging-into-the-privacy-sandbox/) proposes a set +[The Privacy Sandbox initiative](https://web.dev/articles/digging-into-the-privacy-sandbox) proposes a set of privacy-preserving APIs to support business models that fund the open web in the absence of tracking mechanisms like third-party cookies. Chrome has invited all stakeholders in the web ecosystem to participate in the incubation, testing -and refinement of these new privacy-preserving web technologies. This post explains how to get +and refinement of these new privacy-preserving web technologies. This post explains how to get involved. ## Monitor overall progress -Chrome will continue to update the ecosystem on the overall progress of the Privacy Sandbox on the -Chromium blog. (See updates from [Aug 2019](https://blog.chromium.org/2019/08/potential-uses-for-privacy-sandbox.html), +Chrome will continue to update the ecosystem on the overall progress of the Privacy Sandbox on the +Chromium blog. (See updates from [Aug 2019](https://blog.chromium.org/2019/08/potential-uses-for-privacy-sandbox.html), [Jan 2020](https://blog.chromium.org/2020/01/building-more-private-web-path-towards.html), [Oct 2020](https://blog.chromium.org/2020/10/progress-on-privacy-sandbox-and.html), Jan 2021.) ## Understand the proposals You can learn more about Chrome's proposals for the Privacy Sandbox on -[web.dev](https://web.dev/digging-into-the-privacy-sandbox/), including direct links to the +[web.dev](https://web.dev/articles/digging-into-the-privacy-sandbox), including direct links to the proposals on GitHub. Links to proposals offered by others in the web community can usually be found in the public resources of the W3C groups where those proposals are being discussed. For example, members of the Improving Web Advertising Business Group created a @@ -43,13 +43,13 @@ advertising use cases and proposals. To participate in conversations with industry representatives, browser vendors and others—for example, to advocate for a particular use case or solution—you can join one or more of the W3C forums where privacy-preserving proposals are being shared and refined. Today most community -discussion is happening in the [Improving Web Advertising Business Group](https://www.w3.org/community/web-adv/), -the [Privacy Community Group](https://privacycg.github.io/) and the +discussion is happening in the [Improving Web Advertising Business Group](https://www.w3.org/community/web-adv/), +the [Privacy Community Group](https://privacycg.github.io/) and the [Web Platform Incubator Community Group](https://www.w3.org/community/wicg/). [Learn more about [W3C Business and Community -Groups](https://www.w3.org/community/about/). However, you don't need to join a W3C forum to share -input. You can also raise questions or share feedback by commenting directly on the proposals on +Groups](https://www.w3.org/community/about/). However, you don't need to join a W3C forum to share +input. You can also raise questions or share feedback by commenting directly on the proposals on GitHub, so that the author and other interested parties can respond and discuss. ## Experimentation and feedback @@ -58,15 +58,15 @@ As proposed solutions move to the early build and test phase, developers are enc experiment and provide feedback. For local testing in Chrome, developers can use feature flags (chrome://flags) to enable an experimental feature in their local browser. To test how new solutions work in live scenarios for real users and sites, developers can register to participate in Chrome -origin trials. You can review the list of [active Chrome origin trials](/origintrials) -and learn [how origin trials work](https://web.dev/origin-trials/). +origin trials. You can review the list of [active Chrome origin trials](/origintrials) +and learn [how origin trials work](/docs/web-platform/origin-trials/). ## Find out more -* [Digging in to the Privacy Sandbox](https://web.dev/digging-into-the-privacy-sandbox/) +* [Digging in to the Privacy Sandbox](https://web.dev/articles/digging-into-the-privacy-sandbox) * [The Privacy Sandbox](https://www.chromium.org/Home/chromium-privacy/privacy-sandbox) * [Progress update on the Privacy Sandbox initiative](/blog/privacy-sandbox-update-2021-jan/) --- -<p>Photo by <a href="https://unsplash.com/@ian_w?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Ian Williams</a> on <a href="https://unsplash.com/?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Unsplash</a></p> \ No newline at end of file +<p>Photo by <a href="https://unsplash.com/@ian_w?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Ian Williams</a> on <a href="https://unsplash.com/?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Unsplash</a></p> diff --git a/site/en/blog/privacy-sandbox-update-2021-jan/index.md b/site/en/blog/privacy-sandbox-update-2021-jan/index.md index 6fb054703..b9d1e97cc 100644 --- a/site/en/blog/privacy-sandbox-update-2021-jan/index.md +++ b/site/en/blog/privacy-sandbox-update-2021-jan/index.md @@ -14,11 +14,11 @@ tags: - security --- -[The Privacy Sandbox initiative](https://web.dev/digging-into-the-privacy-sandbox/) proposes a set +[The Privacy Sandbox initiative](https://web.dev/articles/digging-into-the-privacy-sandbox) proposes a set of privacy-preserving APIs to support business models that fund the open web in the absence of tracking mechanisms like third-party cookies. It was introduced in 2019, and Chrome shared updates on progress in [January](https://blog.chromium.org/2020/01/building-more-private-web-path-towards.html) -and [October](https://blog.chromium.org/2020/10/progress-on-privacy-sandbox-and.html) last year. +and [October](https://blog.chromium.org/2020/10/progress-on-privacy-sandbox-and.html) last year. After a year of incubation, 2021 will be a year of testing with continued [opportunities for the web ecosystem to get involved](/blog/privacy-sandbox-participate). This post @@ -33,12 +33,12 @@ to the user. On today's web, people's interests are often gauged by observing wh they visit, relying on third-party cookies or less-transparent and undesirable mechanisms like device fingerprinting. -In March, with release 89, Chrome will launch an [origin trial](https://web.dev/origin-trials/) for +In March, with release 89, Chrome will launch an [origin trial](/docs/web-platform/origin-trials/) for the [Federated Learning of Cohorts API](https://github.com/WICG/floc) (FLoC). FLoC proposes a new way to reach people with relevant content and ads by clustering large groups of people with similar browsing patterns, hiding individuals "in the crowd" and keeping their web history on their browser. -Today Google Ads is sharing [an update from their tests of the FLoC algorithm](https://blog.google/products/ads-commerce/2021-01-privacy-sandbox), -which show that the proposed API could be similarly effective as third-party cookies in serving +Today Google Ads is sharing [an update from their tests of the FLoC algorithm](https://blog.google/products/ads-commerce/2021-01-privacy-sandbox), +which show that the proposed API could be similarly effective as third-party cookies in serving relevant interest-based ads. ### Building first-party audiences @@ -63,22 +63,22 @@ When a marketer runs an ad campaign, it's important for them to understand how m ad and if this results in an action by the consumer such as a purchase or sign-up. In September 2020, we opened up the [Event Conversion Measurement -API](https://web.dev/conversion-measurement/) for testing in public Chrome origin trials. It +API](/docs/privacy-sandbox/attribution-reporting/) for testing in public Chrome origin trials. It allows marketers to measure conversions without the use of third-party cookies; instead, the browser records clicks and conversions and shares an anonymized report. A future version of this technology will also support "view-through conversions" (when people see an ad but act on it later). To help marketers understand the audience reach of a particular ad campaign, in April 2020 we -published the [Aggregate Measurement API](https://github.com/csharrison/aggregate-reporting-api), -which helps measure how many times unique users viewed an ad across multiple sites, again, without -revealing data that could be used to identify individuals. This is made possible by reporting data -only once it's met a certain threshold for aggregation. We're planning to open up the Aggregate +published the [Aggregate Measurement API](https://github.com/csharrison/aggregate-reporting-api), +which helps measure how many times unique users viewed an ad across multiple sites, again, without +revealing data that could be used to identify individuals. This is made possible by reporting data +only once it's met a certain threshold for aggregation. We're planning to open up the Aggregate Measurement API for testing via public origin trials in the first half of the year. ### Preventing fraud Sites and publishers need to ensure they are able to distinguish spammers, fraudsters and bots from -real users. Last July we opened up the [Trust Tokens API](https://web.dev/trust-tokens/) for +real users. Last July we opened up the [Trust Tokens API](https://web.dev/articles/trust-tokens) for testing. This supports evaluating a user's authenticity to combat fraud without needing to know the user's identity. Chrome 89 introduces an origin trial to support a new type of Trust Token issuer that can improve the detection of fraud originating on mobile devices while still safeguarding user @@ -86,13 +86,13 @@ privacy. ## Cookie security improvements -In 2020, we also improved the safety of current web technology. The [SameSite cookie policy](https://web.dev/samesite-cookies-explained/) has been adopted by Chrome and Edge and is coming to Firefox soon, -treating cookies as first-party, unless the developer indicates that they need to be accessed across -sites. We've also rolled this out for Android webview and expect to enforce the "SameSite=Lax" +In 2020, we also improved the safety of current web technology. The [SameSite cookie policy](https://web.dev/articles/samesite-cookies-explained) has been adopted by Chrome and Edge and is coming to Firefox soon, +treating cookies as first-party, unless the developer indicates that they need to be accessed across +sites. We've also rolled this out for Android webview and expect to enforce the "SameSite=Lax" default treatment beginning in apps targeting Android S. New in this month's Chrome 88 release, we are strengthening this policy by [modifying the definition -of SameSite](https://web.dev/schemeful-samesite/) to prevent some forms of cross-site attacks, +of SameSite](https://web.dev/articles/schemeful-samesite) to prevent some forms of cross-site attacks, including downgrading a connection's security. Now secure and insecure versions of the same host domain, such as [https://site.example](https://site.example) and [http://site.example](http://site.example), are considered as third-party context to each other. @@ -111,7 +111,7 @@ We've also been making progress on changes in Chrome to prevent existing intrusi techniques, and enable mitigating workarounds: + In the coming weeks, we are completing the Chrome stable rollout of the new [User-Agent - Client Hints (UA-CH) API](https://web.dev/user-agent-client-hints/) which enables developers + Client Hints (UA-CH) API](https://web.dev/articles/user-agent-client-hints) which enables developers to request specific information about a user's browser instead of getting it all by default. We encourage developers to begin migrating to the UA-CH API, as Chrome will eventually begin limiting the information available in the traditional User-Agent string which today can be used @@ -133,7 +133,7 @@ techniques, and enable mitigating workarounds: ## Find out more -* [Digging in to the Privacy Sandbox](https://web.dev/digging-into-the-privacy-sandbox/) +* [Digging in to the Privacy Sandbox](https://web.dev/articles/digging-into-the-privacy-sandbox) * [The Privacy Sandbox](https://www.chromium.org/Home/chromium-privacy/privacy-sandbox) * [How to participate in the Privacy Sandbox initiative](/blog/privacy-sandbox-participate/) * [Privacy Sandbox in 2021: Testing a More Private Web](https://blog.chromium.org/) diff --git a/site/en/blog/private-network-access-preflight/index.md b/site/en/blog/private-network-access-preflight/index.md index 7f9ed510f..5dcdd9275 100644 --- a/site/en/blog/private-network-access-preflight/index.md +++ b/site/en/blog/private-network-access-preflight/index.md @@ -91,7 +91,7 @@ The identified issues were fixed for Chrome 104. ## What is Private Network Access (PNA) [Private Network Access](https://wicg.github.io/private-network-access/) -(formerly known as [CORS-RFC1918](https://web.dev/cors-rfc1918-feedback/)) +(formerly known as [CORS-RFC1918](https://web.dev/articles/cors-rfc1918-feedback)) restricts the ability of websites to send requests to servers on private networks. @@ -110,9 +110,9 @@ a request from a public website (`https://example.com`) to a private website (`http://router.local`), or a request from a private website to localhost. {% endAside %} -### How does PNA classify IP addresses and identify a private network +### How does PNA classify IP addresses and identify a private network -The IP addresses are classified into three IP address spaces: +The IP addresses are classified into three IP address spaces: - `public` - `private` - `local` @@ -148,7 +148,7 @@ is considered more private than a public IP address. </figcaption> </figure> -Learn more at [Feedback wanted: CORS for private networks (RFC1918)](https://web.dev/cors-rfc1918-feedback/). +Learn more at [Feedback wanted: CORS for private networks (RFC1918)](https://web.dev/articles/cors-rfc1918-feedback). ## Preflight requests diff --git a/site/en/blog/private-network-access-update/index.md b/site/en/blog/private-network-access-update/index.md index 79d9775df..2a6faa791 100644 --- a/site/en/blog/private-network-access-update/index.md +++ b/site/en/blog/private-network-access-update/index.md @@ -69,7 +69,7 @@ strategies: ## Timeline -* November 2020: [Call for feedback](https://web.dev/cors-rfc1918-feedback/) +* November 2020: [Call for feedback](https://web.dev/articles/cors-rfc1918-feedback) about the upcoming changes. * March 2021: After reviewing feedback and doing outreach, upcoming changes are announced. The specification is renamed from CORS-RFC1918 to Private Network @@ -96,7 +96,7 @@ strategies: * September 2023: Chrome 117 rolls out to Stable, ending the deprecation trial. Chrome blocks all private network requests from public, non-secure contexts. -## What is Private Network Access +## What is Private Network Access [Private Network Access](https://wicg.github.io/private-network-access/) (formerly known as CORS-RFC1918) restricts the ability of websites to send @@ -121,7 +121,7 @@ Access (CORS-RFC1918). ", width="800", height="512" %} </figure> Learn more at [Feedback wanted: CORS for private networks -(RFC1918)](https://web.dev/cors-rfc1918-feedback/). +(RFC1918)](https://web.dev/articles/cors-rfc1918-feedback). ## What's a deprecation trial {: #whats-deprecation-trial} @@ -219,7 +219,7 @@ article](https://support.google.com/chrome/a/answer/9037717). ### Accessing localhost If your website needs to issue requests to localhost, then you just need to -[upgrade your website to HTTPS](https://web.dev/why-https-matters/). +[upgrade your website to HTTPS](https://web.dev/articles/why-https-matters). Requests targeting `http://localhost` (or `http://127.*.*.*`, `http://[::1]`) are not blocked by Mixed Content, even when issued from secure contexts. @@ -255,13 +255,13 @@ infrastructure certificate authorities (PKI CA) only provide TLS certificates to websites with public domain names. To work around this: 1. Register a public domain name (for example, `intranet.example`) and publish - DNS records pointing that domain name to a public server of your choosing. -2. Obtain a TLS certificate for `intranet.example`. + DNS records pointing that domain name to a public server of your choosing. +2. Obtain a TLS certificate for `intranet.example`. 3. Inside your private network, configure DNS to resolve `intranet.example` to - the target server's private IP address. + the target server's private IP address. 4. Configure your private server to use the TLS certificate for `intranet.example`. This allows your users to access the private server at - `https://intranet.example`. + `https://intranet.example`. You can then upgrade the website that initiates the requests to HTTPS and continue making the requests as before. @@ -340,11 +340,11 @@ or localhost. The Private Network Access specification also classifies requests too. This presents a slightly different set of challenges however, as many private websites do not have domain names, complicating the use of deprecation trial tokens. -### CORS preflight requests +### CORS preflight requests The second part of Private Network Access is to gate private network requests initiated from secure contexts with [CORS preflight -requests](https://web.dev/cross-origin-resource-sharing/#preflight-requests-for-complex-http-calls). +requests](https://web.dev/articles/cross-origin-resource-sharing#preflight_requests_for_complex_http_calls). The idea is that even when the request was initiated from a secure context, the target server is asked to provide an explicit grant to the initiator. The request is only sent if the grant is successful. diff --git a/site/en/blog/progress-in-the-privacy-sandbox-2021-08/index.md b/site/en/blog/progress-in-the-privacy-sandbox-2021-08/index.md index 4e76064f6..114d2a2cb 100644 --- a/site/en/blog/progress-in-the-privacy-sandbox-2021-08/index.md +++ b/site/en/blog/progress-in-the-privacy-sandbox-2021-08/index.md @@ -143,9 +143,9 @@ need to make. The origin trial is planned to start **from Chrome 95** and we will announce when it is available for registration. If you require the extended information from the User-Agent, then [**User-Agent -Client Hints (UA-CH)**](https://web.dev/user-agent-client-hints/) provides that +Client Hints (UA-CH)**](https://web.dev/articles/user-agent-client-hints) provides that functionality for both HTTP headers and JavaScript. Check out the [migration -guide](https://web.dev/migrate-to-ua-ch/) for integrating this into your site. +guide](https://web.dev/articles/migrate-to-ua-ch) for integrating this into your site. UA-CH is available by default in Chrome Stable and we are continuing to improve functionality with ecosystem feedback. The Microsoft Edge team is contributing diff --git a/site/en/blog/progress-in-the-privacy-sandbox-2021-09/index.md b/site/en/blog/progress-in-the-privacy-sandbox-2021-09/index.md index fcec54eae..bcd90ee5e 100644 --- a/site/en/blog/progress-in-the-privacy-sandbox-2021-09/index.md +++ b/site/en/blog/progress-in-the-privacy-sandbox-2021-09/index.md @@ -78,7 +78,7 @@ here](https://www.chromium.org/updates/ua-reduction). {% Aside %} If you rely on any of these values, you will need to [migrate to user-agent -client hints](https://web.dev/migrate-to-ua-ch/) to request that additional +client hints](https://web.dev/articles/migrate-to-ua-ch) to request that additional information. {% endAside %} diff --git a/site/en/blog/progress-in-the-privacy-sandbox-2021-10/index.md b/site/en/blog/progress-in-the-privacy-sandbox-2021-10/index.md index 8669f700d..2b43282d4 100644 --- a/site/en/blog/progress-in-the-privacy-sandbox-2021-10/index.md +++ b/site/en/blog/progress-in-the-privacy-sandbox-2021-10/index.md @@ -171,7 +171,7 @@ You can track the full [timeline for reducing Chrome's user-agent](https://blog.chromium.org/2021/09/user-agent-reduction-origin-trial-and-dates.html), with [further examples and details of rollout phases](https://www.chromium.org/updates/ua-reduction). You will also need to -[Migrate to User-Agent Client Hints](https://web.dev/migrate-to-ua-ch/) (UA-CH) +[Migrate to User-Agent Client Hints](https://web.dev/articles/migrate-to-ua-ch) (UA-CH) if you rely on the platform version, device, or full build version information in the current `User-Agent` format. diff --git a/site/en/blog/progress-in-the-privacy-sandbox-2021-12/index.md b/site/en/blog/progress-in-the-privacy-sandbox-2021-12/index.md index 4cb3306ec..5ffe63ab0 100644 --- a/site/en/blog/progress-in-the-privacy-sandbox-2021-12/index.md +++ b/site/en/blog/progress-in-the-privacy-sandbox-2021-12/index.md @@ -120,7 +120,7 @@ To find those areas: * mobile device name 4. These are the values that will be reduced to fixed strings in the future. If you need access to these values, [migrate to User-Agent Client - Hints](https://web.dev/migrate-to-ua-ch/). + Hints](https://web.dev/articles/migrate-to-ua-ch). There is one December update to mention—if you are adopting User-Agent Client Hints, we have sent the **Intent to Ship to [enable delegating hints to other @@ -159,8 +159,8 @@ a healthy number of cookies with quality ingredients. As we continue moving towards the phase out of third-party cookies, you should make sure you know which of your site's cookies will be affected. 2020 provided a headstart as it became necessary to [mark all cookies for cross-site or third-party -use](https://web.dev/samesite-cookies-explained/#samesitenone-must-be-secure) -with `SameSite=None`. +use](https://web.dev/articles/samesite-cookies-explained#samesitenone_must_be_secure) +with `SameSite=None`. Any cookie where you have set the `SameSite` attribute to `None` will need an update. diff --git a/site/en/blog/referrer-policy-new-chrome-default/index.md b/site/en/blog/referrer-policy-new-chrome-default/index.md index e5ee4b09b..341232d44 100644 --- a/site/en/blog/referrer-policy-new-chrome-default/index.md +++ b/site/en/blog/referrer-policy-new-chrome-default/index.md @@ -3,7 +3,7 @@ layout: 'layouts/blog-post.njk' # Required -title: A new default Referrer-Policy for Chrome - strict-origin-when-cross-origin +title: A new default Referrer-Policy for Chrome - strict-origin-when-cross-origin # Required description: > @@ -36,7 +36,7 @@ tags: Before we start: - If you're unsure of the difference between "site" and "origin", check out [Understanding - "same-site" and "same-origin"](https://web.dev/same-site-same-origin/). + "same-site" and "same-origin"](https://web.dev/articles/same-site-same-origin). - The `Referer` header is missing an R, due to an original misspelling in the spec. The `Referrer-Policy` header and `referrer` in JavaScript and the DOM are spelled correctly. @@ -84,7 +84,7 @@ Up until recently, [`no-referrer-when-downgrade`](https://developer.mozilla.org/docs/Web/HTTP/Headers/Referrer-Policy) has been a widespread default policy across browsers. But now many browsers are in some stage of [moving to more privacy-enhancing -defaults](https://web.dev/referrer-best-practices/#default-referrer-policies-in-browsers). +defaults](https://web.dev/articles/referrer-best-practices#default_referrer_policies_in_browsers). Chrome plans to switch its default policy from `no-referrer-when-downgrade` to `strict-origin-when-cross-origin`, [starting in version 85](https://blog.chromium.org/2020/07/chrome-85-upload-streaming-human.html). @@ -96,7 +96,7 @@ this change will only have an effect on websites that have no policy set. {% Aside %} This step to help reduce silent cross-site user tracking is part of a larger initiative: the Privacy Sandbox. Check [Digging into the Privacy -Sandbox](https://web.dev/digging-into-the-privacy-sandbox/) for more details. +Sandbox](https://web.dev/articles/digging-into-the-privacy-sandbox) for more details. {% endAside %} ### What does this change mean? @@ -110,7 +110,7 @@ the path and query string. <figure> {% Img src="image/T4FyVKpzu4WKF1kBNvXepbi08t52/pZd2hVwvPWuPz4gK3uJh.png", alt="Diagram: Referer sent - depending on the policy, for a cross-origin request.", width="800", height="464" %} + depending on the policy, for a cross-origin request.", width="800", height="464" %} <figcaption> <em>Referer sent (and document.referrer) for a cross-origin request, depending on the policy.</em> @@ -130,13 +130,13 @@ https://site-two.example/…: - Like `no-referrer-when-downgrade`, `strict-origin-when-cross-origin` is **secure**: no referrer (`Referer` header and `document.referrer`) is present when the request is made from an HTTPS origin (secure) to an HTTP one (insecure). This way, if your website uses HTTPS ([if not, make it - a priority](https://web.dev/why-https-matters/)), your website's URLs won't leak in non-HTTPS + a priority](https://web.dev/articles/why-https-matters)), your website's URLs won't leak in non-HTTPS requests—because anyone on the network can see these, so this would expose your users to man-in-the-middle-attacks. - Within the same origin, the `Referer` header value is the full URL. For example: -Same-origin request, sent from https://site-one.example/**stuff/detail?tag=red** to +Same-origin request, sent from https://site-one.example/**stuff/detail?tag=red** to https://site-one.example/…: - With `strict-origin-when-cross-origin`: Referer: https://site-one.example/**stuff/detail?tag=red** @@ -202,7 +202,7 @@ have a few options: Note that most browsers are moving in a similar direction when it comes to the referrer (see browser defaults and their evolutions in [Referer and Referrer-Policy: best -practices](https://web.dev/referrer-best-practices/#default-referrer-policies-in-browsers). +practices](https://web.dev/articles/referrer-best-practices#default_referrer_policies_in_browsers). ### Implement an explicit, privacy-enhancing policy across your site @@ -224,7 +224,7 @@ The Chrome enterprise policy [`ForceLegacyDefaultReferrerPolicy`](https://cloud.google.com/docs/chrome-enterprise/policies/?policy=ForceLegacyDefaultReferrerPolicy) is available to IT administrators who would like to force the previous default referrer policy of `no-referrer-when-downgrade` in enterprise environments. This allows enterprises additional time to -test and update their applications. +test and update their applications. This policy will be removed in Chrome 88. @@ -241,7 +241,7 @@ David Van Cleve, Mike West, Sam Dutton, Rowan Merewood, Jxck and Kayce Basques._ ## Resources - [Referer and Referrer-Policy: best practices](web.dev/referrer-best-practices) -- [Understanding "same-site" and "same-origin"](https://web.dev/same-site-same-origin/) +- [Understanding "same-site" and "same-origin"](https://web.dev/articles/same-site-same-origin) - [Chrome status entry](https://www.chromestatus.com/feature/6251880185331712) - [Chrome 85 beta blog post](https://blog.chromium.org/2020/07/chrome-85-upload-streaming-human.html) - [Blink intent to diff --git a/site/en/blog/removing-document-write/index.md b/site/en/blog/removing-document-write/index.md index 99bbf7921..385cdc8c0 100644 --- a/site/en/blog/removing-document-write/index.md +++ b/site/en/blog/removing-document-write/index.md @@ -89,14 +89,14 @@ Specifically Chrome will not execute the `<script>` elements injected via Third party snippets sometimes use `document.write()` to load scripts. Fortunately, most third parties provide -[asynchronous loading alternatives](https://web.dev/efficiently-load-third-party-javascript/#use-async-or-defer), which +[asynchronous loading alternatives](https://web.dev/articles/efficiently-load-third-party-javascript#use_async_or_defer), which allow third party scripts to load without blocking the display of the rest of the content on the page. ## How do I fix this? This simple answer is don't inject scripts using `document.write()`. We -maintain a set of [known services for asynchronous loader support](https://web.dev/async-functions/) +maintain a set of [known services for asynchronous loader support](https://web.dev/articles/async-functions) that we encourage you to keep checking. If your provider is not on the list and does support asynchronous script loading diff --git a/site/en/blog/removing-push/index.md b/site/en/blog/removing-push/index.md index 4004858a9..80dfbc625 100644 --- a/site/en/blog/removing-push/index.md +++ b/site/en/blog/removing-push/index.md @@ -31,7 +31,7 @@ Push was not implemented in many HTTP/3 servers and clients—even though it was [103 Early Hints](/blog/early-hints/) is a much less error-prone alternative with many of the same upsides as Push, and a lot less of the downsides. Rather than the server pushing _resources_, 103 Early Hints sends only _hints_ to the browser of resources that it may benefit from requesting immediately. This leaves the browser in control of deciding whether it needs these or not—for example if it already has those resources in the HTTP cache. -[Preloading critical resources](https://web.dev/preload-critical-assets/) is another alternative that allows the page and the browser to work together to preemptively load critical resources early in the page load. While this does require the page itself to be sent first—so is not quite as fast as either Server Push nor Early Hints—it has the added benefit of not delaying that critical page resource, which can happen with both of those solutions. +[Preloading critical resources](https://web.dev/articles/preload-critical-assets) is another alternative that allows the page and the browser to work together to preemptively load critical resources early in the page load. While this does require the page itself to be sent first—so is not quite as fast as either Server Push nor Early Hints—it has the added benefit of not delaying that critical page resource, which can happen with both of those solutions. {% Aside 'caution' %} All solutions that attempt to load resources early can cause performance degradation and should be used in moderation. The browser is often very good at making the right choices, but sometimes can benefit from a little help in some cases. With emphasis on "little". diff --git a/site/en/blog/richer-install-ui-desktop/index.md b/site/en/blog/richer-install-ui-desktop/index.md index 823610bd3..e71dae5b4 100644 --- a/site/en/blog/richer-install-ui-desktop/index.md +++ b/site/en/blog/richer-install-ui-desktop/index.md @@ -47,7 +47,7 @@ To display the Richer Install UI dialog developers need to add at least one scre For example developers can use the `description` field to highlight the app’s features that incentivize the user to keep it in their devices. With the `screenshots` they can present the look and feel of the web app as a standalone, with all the easy access that platform apps have. -For a detailed specification and a guide to add them to your app visit the [Richer Install UI pattern](https://web.dev/patterns/web-apps/richer-install-ui/). +For a detailed specification and a guide to add them to your app visit the [Richer Install UI pattern](https://web.dev/articles/patterns/web-apps/richer-install-ui). The older style of install prompt provided little information and context. This didn't match users' expectations of what installation means and could leave them confused about what happened. Many declined the install request entirely, which was also bad for the businesses that built them. diff --git a/site/en/blog/richer-pwa-installation/index.md b/site/en/blog/richer-pwa-installation/index.md index 068d9a7b7..b8ea18b51 100644 --- a/site/en/blog/richer-pwa-installation/index.md +++ b/site/en/blog/richer-pwa-installation/index.md @@ -91,7 +91,7 @@ To display the richer install UI dialog developers need to add at least one scre For example developers can use the `description` field to highlight the app’s features that incentivize the user to keep it in their devices, and with the `screenshots` they can present the look and feel of the web app as a standalone, with all the easy access that platform apps have. -For a detailed specification and a guide to add them to your app visit the [Richer Install UI pattern](https://web.dev/patterns/web-apps/richer-install-ui/). +For a detailed specification and a guide to add them to your app visit the [Richer Install UI pattern](https://web.dev/articles/patterns/web-apps/richer-install-ui). ## Feedback diff --git a/site/en/blog/script-component/index.md b/site/en/blog/script-component/index.md index 03b7f3076..1de535362 100644 --- a/site/en/blog/script-component/index.md +++ b/site/en/blog/script-component/index.md @@ -18,7 +18,7 @@ Around [45%](https://almanac.httparchive.org/en/2021/third-parties#fig-3) of req ## Third-party scripts and their impact on performance -[Third-party scripts](https://web.dev/third-party-javascript/) allow web developers to leverage existing solutions to implement common features and reduce development time. But the creators of these scripts typically do not have any incentive to consider the performance impact on the consuming website. These scripts are also a blackbox to developers who use them. +[Third-party scripts](https://web.dev/articles/third-party-javascript) allow web developers to leverage existing solutions to implement common features and reduce development time. But the creators of these scripts typically do not have any incentive to consider the performance impact on the consuming website. These scripts are also a blackbox to developers who use them. Scripts account for a significant number of [third-party bytes](https://almanac.httparchive.org/en/2021/third-parties#fig-11) downloaded by websites across different categories of third-party requests. By default, the browser prioritizes scripts based on where they are in the document which may delay the discovery or execution of scripts critical to user experience. @@ -30,7 +30,7 @@ Third-party libraries required for layout should be loaded early to render the p It's important to consider the resource loading sequence of your page so that critical resources are not delayed and non-critical resources do not block critical resources. -While there are [best practices](https://web.dev/fast/#optimize-your-third-party-resources) to reduce the impact of third parties, not everyone may be aware of how to implement them for every third-party they use. This can be complicated because: +While there are [best practices](https://web.dev/articles/fast#optimize_your_third_party_resources) to reduce the impact of third parties, not everyone may be aware of how to implement them for every third-party they use. This can be complicated because: * On average, websites use [21 to 23 different third parties](https://almanac.httparchive.org/en/2021/third-parties#fig-4)—including scripts—on mobile and desktop. Usage and recommendations may differ for each. * Implementing many third-parties can differ based on whether a particular framework or UI library is used. @@ -39,15 +39,15 @@ While there are [best practices](https://web.dev/fast/#optimize-your-third-party ## Aurora’s focus on third-party scripts -Part of Aurora's [collaboration](/blog/introducing-aurora/#aurora:-a-collaboration-between-chrome-and-open-source-web-frameworks-and-tools) with open source web frameworks and tools is to provide strong defaults and opinionated tooling to help developers improve aspects of the user experience such as performance, accessibility, security, and mobile readiness. In 2021, we were focused on helping framework stacks improve user experience and their [Core Web Vitals](https://web.dev/vitals/) metrics. +Part of Aurora's [collaboration](/blog/introducing-aurora/#aurora:-a-collaboration-between-chrome-and-open-source-web-frameworks-and-tools) with open source web frameworks and tools is to provide strong defaults and opinionated tooling to help developers improve aspects of the user experience such as performance, accessibility, security, and mobile readiness. In 2021, we were focused on helping framework stacks improve user experience and their [Core Web Vitals](https://web.dev/articles/vitals) metrics. -One of the most significant steps towards achieving our goal to improve framework performance involved researching the ideal loading sequence of third-party scripts in Next.js. Frameworks such as Next.js are uniquely positioned to provide useful defaults and features that help developers efficiently load resources, including third-parties. We studied extensive [HTTP Archive](https://httparchive.org/) and Lighthouse [data](https://docs.google.com/spreadsheets/d/1Td-4qFjuBzxp8af_if5iBC0Lkqm_OROb7_2OcbxrU_g/edit?resourcekey=0-ZCfve5cngWxF0-sv5pLRzg#gid=1628564987) to find which third-parties [block rendering](https://web.dev/render-blocking-resources/) the most across different frameworks. +One of the most significant steps towards achieving our goal to improve framework performance involved researching the ideal loading sequence of third-party scripts in Next.js. Frameworks such as Next.js are uniquely positioned to provide useful defaults and features that help developers efficiently load resources, including third-parties. We studied extensive [HTTP Archive](https://httparchive.org/) and Lighthouse [data](https://docs.google.com/spreadsheets/d/1Td-4qFjuBzxp8af_if5iBC0Lkqm_OROb7_2OcbxrU_g/edit?resourcekey=0-ZCfve5cngWxF0-sv5pLRzg#gid=1628564987) to find which third-parties [block rendering](https://web.dev/articles/render-blocking-resources) the most across different frameworks. To address the issue of main-thread blocking third-party scripts used in an application, we built the [Script component](https://nextjs.org/docs/basic-features/script). The component encapsulates sequencing features to provide developers with better controls for third-party script loading. ## Sequencing third-party scripts without a framework component -The [available guidance](https://web.dev/efficiently-load-third-party-javascript/) to reduce the impact of render-blocking scripts provides the following methods for efficiently loading and sequencing third-party scripts: +The [available guidance](https://web.dev/articles/efficiently-load-third-party-javascript) to reduce the impact of render-blocking scripts provides the following methods for efficiently loading and sequencing third-party scripts: 1. Use the `async` or `defer` attribute with `<script>` tags that tell the browser to load non-critical third-party scripts without blocking the document parser. Scripts not required for initial page load or the first user interaction may be considered non-critical. @@ -56,7 +56,7 @@ The [available guidance](https://web.dev/efficiently-load-third-party-javascript <script src="https://example.com/script2.js" async></script> ``` -2. [Establish early connections to required origins](https://web.dev/preconnect-and-dns-prefetch/) using preconnect and dns-prefetch. This allows critical scripts to start downloading earlier. +2. [Establish early connections to required origins](https://web.dev/articles/preconnect-and-dns-prefetch) using preconnect and dns-prefetch. This allows critical scripts to start downloading earlier. ```html <head> @@ -66,7 +66,7 @@ The [available guidance](https://web.dev/efficiently-load-third-party-javascript ``` -3. [Lazy-load](https://web.dev/embed-best-practices/#lazy-loading) third-party resources and embeds after the main page content has finished loading or when the user scrolls down to the part of the page where they are included. +3. [Lazy-load](https://web.dev/articles/embed-best-practices#lazy_loading) third-party resources and embeds after the main page content has finished loading or when the user scrolls down to the part of the page where they are included. ## The Next.js Script component @@ -179,7 +179,7 @@ Third-party scripts were added to the demo blog app as given below. {% Img src="image/IypihH3o5cSpEMVp5i08dp69otp2/BAWQVlyBX1UUJOMyrBJm.gif", alt="Video showing the loading progress for the index page with and without the Script component. There is a 0.5 seconds improvement in FCP with the Script component.", width="800", height="306" %} </figure> -As seen in the video, [First Contentful Paint (FCP)](https://web.dev/fcp/) occurs at 0.9 seconds on the page without the Script component and 0.4 seconds with the Script component. +As seen in the video, [First Contentful Paint (FCP)](https://web.dev/articles/fcp) occurs at 0.9 seconds on the page without the Script component and 0.4 seconds with the Script component. ## What’s next for the Script component diff --git a/site/en/blog/search-ads-speed/index.md b/site/en/blog/search-ads-speed/index.md index f8d7f4fcc..e7800b1fe 100644 --- a/site/en/blog/search-ads-speed/index.md +++ b/site/en/blog/search-ads-speed/index.md @@ -18,9 +18,9 @@ of visits are abandoned if a mobile page takes over [3 seconds to load](https:// Last week, Google Search and Ads teams announced two new speed initiatives to help improve user-experience on the web. Both efforts recommend that site owners and developers pay attention to -[user-centric performance metrics](https://web.dev/user-centric-performance-metrics/) +[user-centric performance metrics](https://web.dev/articles/user-centric-performance-metrics) and use tools such as [Lighthouse](/docs/lighthouse/) and -[PageSpeed Insights](https://web.dev/whats-new-pagespeed-insights/), and real-world field data +[PageSpeed Insights](https://web.dev/articles/whats-new-pagespeed-insights), and real-world field data (e.g. see [Chrome User Experience Report](/docs/crux/)) to diagnose and improve user experiences. @@ -34,11 +34,11 @@ for desktop searches in 2010 and as of this month (July 2018), page [speed will too. If you're a developer working on a site, now is a good time to evaluate your -performance using our [speed tools](https://web.dev/speed-tools/). Think about how -[performance](https://web.dev/rail/) affects the user experience -of your pages and consider measuring a variety of real-world [user-centric performance metrics](https://web.dev/user-centric-performance-metrics/). +performance using our [speed tools](https://web.dev/articles/speed-tools). Think about how +[performance](https://web.dev/articles/rail) affects the user experience +of your pages and consider measuring a variety of real-world [user-centric performance metrics](https://web.dev/articles/user-centric-performance-metrics). -Are you shipping [too much JavaScript](https://web.dev/performance-optimizing-content-efficiency/)? +Are you shipping [too much JavaScript](https://web.dev/articles/performance-optimizing-content-efficiency)? Too many images? Images and JavaScript are the [most significant contributors](https://paulcalvano.com/index.php/2018/07/02/impact-of-page-weight-on-load-time/) to the page weight that affect page load time based on data from [HTTP Archive](https://httparchive.org/) and the [Chrome User Experience Report](/docs/crux/) - our public dataset for key UX metrics as experienced by Chrome users under real-world conditions. @@ -46,7 +46,7 @@ UX metrics as experienced by Chrome users under real-world conditions. To evaluate performance, check: - [PageSpeed Insights](https://pagespeed.web.dev/), an online tool that shows - speed [field data](https://web.dev/speed-tools/#field-data) for + speed [field data](https://web.dev/articles/speed-tools#field_data) for your site, alongside suggestions for common optimizations to improve it. - [Lighthouse](/docs/lighthouse/), [a lab tool](https://web.dev/speed-tools/#lab_data) providing personalized advice on how to improve your website across performance, @@ -85,7 +85,7 @@ Optimized web experiences lead to higher user engagement, conversions, and ROI; performance is a feature and a competitive edge. Looking for tools and tips on which tools and metrics to use, or how to -evaluate and make a business case for performance? Check out our ["How to Think about Speed Tools"](https://web.dev/speed-tools/) guide for a +evaluate and make a business case for performance? Check out our ["How to Think about Speed Tools"](https://web.dev/articles/speed-tools) guide for a hands-on overview. <a href="/https://web.dev/speed-tools/"> @@ -95,6 +95,6 @@ hands-on overview. Looking for tools and tips on which tools and metrics to use, or how to evaluate and make a business case for performance? Check out our -[How to Think about Speed Tools](https://web.dev/speed-tools/) +[How to Think about Speed Tools](https://web.dev/articles/speed-tools) guide for a hands-on overview. Or, if you're looking for a fast-by-default framework for you pages, take a look at [AMP](https://www.ampproject.org/). diff --git a/site/en/blog/site-affiliation/index.md b/site/en/blog/site-affiliation/index.md index 15468b423..789826ff3 100644 --- a/site/en/blog/site-affiliation/index.md +++ b/site/en/blog/site-affiliation/index.md @@ -25,7 +25,7 @@ Chrome's password manager already autofills credentials for sites with saved credentials, as well as in the following two cases: 1. When two sites are in the - [same-site](https://web.dev/same-site-same-origin/) relationship, Chrome + [same-site](https://web.dev/articles/same-site-same-origin) relationship, Chrome will show autofill credentials for the other site if there's at least one credential saved on one site. For example, because `www.example.com` and `m.example.com` are the same-site, Chrome can share saved credentials @@ -72,9 +72,9 @@ at `/.well-known/assetlinks.json` on the respective domains. `https://www.example.com,`can share credentials with `https://www.example.co.uk`, create a file named `assetlinks.json` with the following content: - + <br> - + ```json [{ "relation": ["delegate_permission/common.get_login_creds"], @@ -91,17 +91,17 @@ at `/.well-known/assetlinks.json` on the respective domains. } }] ``` - + <br> - + The `relation` field is an array of one or more strings that describe the relationship between the sites. For sites to share sign-in credentials, - specify the string `delegate_permission/common.get_login_creds`. + specify the string `delegate_permission/common.get_login_creds`. The `target` field is an object that specifies the asset the declaration applies to. The following fields identify a website: - + <br> - + <table> <tr> <td><code>namespace</code></td> @@ -125,7 +125,7 @@ at `/.well-known/assetlinks.json` on the respective domains. <br> In this example, the domain is `www.example.com`, so the JSON file should - be hosted at `https://www.example.com/.well-known/assetlinks.json`. + be hosted at `https://www.example.com/.well-known/assetlinks.json`. <br> @@ -136,10 +136,10 @@ at `/.well-known/assetlinks.json` on the respective domains. {% Aside 'gotchas' %} The request for a DAL file must return an HTTP `200 OK` status code, - otherwise it will be treated as an error. This applies to redirects + otherwise it will be treated as an error. This applies to redirects which return status codes in the `300-399` range. {% endAside %} - + <br> 1. To declare the association in both websites, host the @@ -196,32 +196,32 @@ the Digital Asset Links file. For example, to associate the `example.com`, `https://EXAMPLE_DOMAIN_NAME/.well-known/assetlinks.json`. ```json -[{ - "relation":[ - "delegate_permission/common.get_login_creds" - ], - "target":{ - "site":"https://www.example.com", - "namespace":"web" - } - }, - { - "relation":[ - "delegate_permission/common.get_login_creds" - ], - "target":{ - "site":"https://www.example.co.uk", - "namespace":"web" - } - }, - { - "relation":[ - "delegate_permission/common.get_login_creds" - ], - "target":{ - "site":"https://www.example.co.jp", - "namespace":"web" - } +[{ + "relation":[ + "delegate_permission/common.get_login_creds" + ], + "target":{ + "site":"https://www.example.com", + "namespace":"web" + } + }, + { + "relation":[ + "delegate_permission/common.get_login_creds" + ], + "target":{ + "site":"https://www.example.co.uk", + "namespace":"web" + } + }, + { + "relation":[ + "delegate_permission/common.get_login_creds" + ], + "target":{ + "site":"https://www.example.co.jp", + "namespace":"web" + } }] ``` diff --git a/site/en/blog/soft-navigations-experiment/index.md b/site/en/blog/soft-navigations-experiment/index.md index deae4f946..f00ee8788 100644 --- a/site/en/blog/soft-navigations-experiment/index.md +++ b/site/en/blog/soft-navigations-experiment/index.md @@ -21,9 +21,9 @@ tags: The Soft Navigations origin trial has entered a [second origin trial from Chrome 117](/origintrials/#/view_trial/21392098230009857) after taking feedback on board from the initial trial. {% endAside %} -Since its launch, the [Core Web Vitals initiative](https://web.dev/vitals/) has sought to measure the actual user experience of a website, rather than technical details behind how a website is created or loaded. The three Core Web Vitals metrics were created as [user-centric metrics](https://web.dev/user-centric-performance-metrics/)—an evolution over existing technical metrics such as[`DOMContentLoaded`](https://developer.mozilla.org/docs/Web/API/Document/DOMContentLoaded_event) or [`load`](https://developer.mozilla.org/docs/Web/API/Window/load_event) that measured timings that were often unrelated to how users perceived the performance of the page. Because of this, the technology used to build the site should not impact the scoring providing the site performs well. +Since its launch, the [Core Web Vitals initiative](https://web.dev/articles/vitals) has sought to measure the actual user experience of a website, rather than technical details behind how a website is created or loaded. The three Core Web Vitals metrics were created as [user-centric metrics](https://web.dev/articles/user-centric-performance-metrics)—an evolution over existing technical metrics such as[`DOMContentLoaded`](https://developer.mozilla.org/docs/Web/API/Document/DOMContentLoaded_event) or [`load`](https://developer.mozilla.org/docs/Web/API/Window/load_event) that measured timings that were often unrelated to how users perceived the performance of the page. Because of this, the technology used to build the site should not impact the scoring providing the site performs well. -The reality is always a little trickier than the ideal, and the popular Single Page Application architecture has [never been fully supported by the Core Web Vitals metrics](https://web.dev/vitals-spa-faq/). Rather than loading distinct, individual web pages as the user navigates about the site, these web applications use so-called "soft navigations", where the page content is instead changed by JavaScript. In these applications, the illusion of a traditional webpage architecture is maintained by altering the URL and pushing previous URLs in the browser's history to allow the back and forward buttons to work as the user would expect. +The reality is always a little trickier than the ideal, and the popular Single Page Application architecture has [never been fully supported by the Core Web Vitals metrics](https://web.dev/articles/vitals-spa-faq). Rather than loading distinct, individual web pages as the user navigates about the site, these web applications use so-called "soft navigations", where the page content is instead changed by JavaScript. In these applications, the illusion of a traditional webpage architecture is maintained by altering the URL and pushing previous URLs in the browser's history to allow the back and forward buttons to work as the user would expect. Many JavaScript frameworks use this model, but each in a different way. Since this is outside of what the browser traditionally understands as a "page", measuring this has always been difficult: where is the line to be drawn between an interaction on the _current_ page, versus considering this as a _new_ page? @@ -45,9 +45,9 @@ Once the soft navigation heuristics are enabled (more on this in the next sectio - A `soft-navigation` [`PerformanceTiming`](https://developer.mozilla.org/docs/Web/API/PerformanceTiming) event will be emitted after each soft navigation is detected. - The performance API will provide access to a `soft-navigation` timing entry, as emitted by the above `PerformanceTiming` event. -- The [First Paint (FP)](https://developer.mozilla.org/docs/Glossary/First_paint), [First Contentful Paint (FCP)](https://web.dev/fcp/), [Largest Contentful Paint (LCP)](https://web.dev/lcp/) metrics will be reset, and re-emitted on the next appropriate occurrences of these. (Note: FP, and FCP are not yet implemented.) -- The [First Input Delay (FID)](https://web.dev/fcp/) will be reset, and re-emitted on the first input (note: this is not yet implemented). -- A `navigationId` attribute will be added to each of performance timings (`first-paint`, `first-contentful-paint`, `largest-contentful-paint`, `first-input-delay`, `event`, and `layout-shift`) corresponding to the navigation entry the event was related to, allowing [Cumulative Layout Shift (CLS)](https://web.dev/cls/) and [Interaction to Next Paint (INP)](https://web.dev/inp/) to be calculated. +- The [First Paint (FP)](https://developer.mozilla.org/docs/Glossary/First_paint), [First Contentful Paint (FCP)](https://web.dev/articles/fcp), [Largest Contentful Paint (LCP)](https://web.dev/articles/lcp) metrics will be reset, and re-emitted on the next appropriate occurrences of these. (Note: FP, and FCP are not yet implemented.) +- The [First Input Delay (FID)](https://web.dev/articles/fcp) will be reset, and re-emitted on the first input (note: this is not yet implemented). +- A `navigationId` attribute will be added to each of performance timings (`first-paint`, `first-contentful-paint`, `largest-contentful-paint`, `first-input-delay`, `event`, and `layout-shift`) corresponding to the navigation entry the event was related to, allowing [Cumulative Layout Shift (CLS)](https://web.dev/articles/cls) and [Interaction to Next Paint (INP)](https://web.dev/articles/inp) to be calculated. These changes will allow the Core Web Vitals—and some of the associated diagnostic metrics—to be measured per page navigation, though there are some nuances that need to be considered. @@ -172,11 +172,11 @@ As this example shows, the LCP element for the soft navigation can be reported d ### How to measure TTFB? -[Time to First Byte (TTFB)](https://web.dev/ttfb/) for a traditional page load represents the time that the first bytes of the original request are returned. +[Time to First Byte (TTFB)](https://web.dev/articles/ttfb) for a traditional page load represents the time that the first bytes of the original request are returned. For a soft navigation this is a more tricky question. Should we measure the first request made for the new page? What if all the content already exists in the app and there are no additional requests? What if that request is made in advance with a prefetch? What if a request unrelated to the soft navigation from a user perspective (for example, it's an analytics request)? -A simpler method is to report TTFB of 0 for soft navigations—in a similar manner as we recommend for [back/forward cache](https://web.dev/bfcache/) restores. This is the method the [`web-vitals` library](#using-the-web-vitals-library-to-measure-core-web-vitals-for-soft-navigations) currently uses for soft navigations. +A simpler method is to report TTFB of 0 for soft navigations—in a similar manner as we recommend for [back/forward cache](https://web.dev/articles/bfcache) restores. This is the method the [`web-vitals` library](#using-the-web-vitals-library-to-measure-core-web-vitals-for-soft-navigations) currently uses for soft navigations. In the future, we may support more precise ways of knowing which request is the soft navigation's "navigation request" and will be able to have more precise TTFB measurements. But that's not part of the current experiment. diff --git a/site/en/blog/sxg-desktop/index.md b/site/en/blog/sxg-desktop/index.md index 7b6b19bd1..6d93e0237 100644 --- a/site/en/blog/sxg-desktop/index.md +++ b/site/en/blog/sxg-desktop/index.md @@ -1,6 +1,6 @@ --- layout: 'layouts/blog-post.njk' -title: Signed Exchanges launched for desktop sites +title: Signed Exchanges launched for desktop sites description: > Announcing Signed Exchanges support for Chromium browsers on desktop along with other recent feature launches. date: 2022-07-08 @@ -9,17 +9,17 @@ authors: - twifkak --- -[Signed Exchanges (SXG)](https://web.dev/signed-exchanges/) is a delivery mechanism that can help speed up your site and improve [Largest Contentful Paint (LCP)](https://web.dev/lcp/) by enabling privacy-preserving cross-origin prefetch. At [I/O 2022](https://www.youtube.com/watch?v=bxc-Gc8KmF4), the SXG working group at Google previewed plans to add new SXG features and support site navigations on additional surfaces. Today, we are announcing the first set of these features, with more to come over the next few months: +[Signed Exchanges (SXG)](https://web.dev/articles/signed-exchanges) is a delivery mechanism that can help speed up your site and improve [Largest Contentful Paint (LCP)](https://web.dev/articles/lcp) by enabling privacy-preserving cross-origin prefetch. At [I/O 2022](https://www.youtube.com/watch?v=bxc-Gc8KmF4), the SXG working group at Google previewed plans to add new SXG features and support site navigations on additional surfaces. Today, we are announcing the first set of these features, with more to come over the next few months: -- Support for desktop site navigations -- Google Search support for SXG from Top Stories and News -- Support for server side personalization +- Support for desktop site navigations +- Google Search support for SXG from Top Stories and News +- Support for server side personalization Read on to learn more about these features and how you can leverage them to improve the user experience on your site. ## Support for desktop navigations -With this release, Signed Exchanges will now be available for desktop cross-origin navigations on Chromium browsers. This builds on the existing support for Android mobile and means that now you can use SXG to also cache and prefetch the desktop version of your site. +With this release, Signed Exchanges will now be available for desktop cross-origin navigations on Chromium browsers. This builds on the existing support for Android mobile and means that now you can use SXG to also cache and prefetch the desktop version of your site. We estimate<sup><a href="#footnote-1">1</a></sup> that this release will, on average, double SXG's coverage of your site's visits, enabling improved loading and performance for more users. Today on mobile, this speed improvement is between 300 and 400 ms of LCP reduction on average for navigations from Google Search. @@ -68,7 +68,7 @@ Cloudflare, a leading Content Distribution Network (CDNs), [ran an experiment](h ## Google Search support for Top Stories and News -Google Search is an early adopter of Signed Exchanges' privacy-preserving cross-origin prefetch, which to-date has been available for site navigations from Search's Web Page Results. Starting in July 2022, Search is expanding this support to also include navigations from Top Stories and News. Note that while SXG does not impact ranking or selection criteria on Google Search, it does have the ability to improve your site's [Core Web Vitals](https://web.dev/vitals/), LCP in specific. +Google Search is an early adopter of Signed Exchanges' privacy-preserving cross-origin prefetch, which to-date has been available for site navigations from Search's Web Page Results. Starting in July 2022, Search is expanding this support to also include navigations from Top Stories and News. Note that while SXG does not impact ranking or selection criteria on Google Search, it does have the ability to improve your site's [Core Web Vitals](https://web.dev/articles/vitals), LCP in specific. This feature requires no additional work on your part to enable and will be available automatically to both existing and new adopters. @@ -78,11 +78,11 @@ This feature requires no additional work on your part to enable and will be avai ## Support for server-side personalization -Signed Exchanges uses a cache to prefetch and serve content that has been cryptographically signed by the origin. Cached content can be sent to multiple different users or to the same user multiple times. In the past, this has meant that SXG has not been compatible with sites that use server side personalization—that is, different HTML for logged in users. +Signed Exchanges uses a cache to prefetch and serve content that has been cryptographically signed by the origin. Cached content can be sent to multiple different users or to the same user multiple times. In the past, this has meant that SXG has not been compatible with sites that use server side personalization—that is, different HTML for logged in users. -**Today, we're adding Dynamic SXG**—a new feature that allows you to selectively enable SXG for visits from cookieless users only on Chromium. Logged in navigations, with server-side personalization, will continue to serve non-SXG versions of your site. +**Today, we're adding Dynamic SXG**—a new feature that allows you to selectively enable SXG for visits from cookieless users only on Chromium. Logged in navigations, with server-side personalization, will continue to serve non-SXG versions of your site. -This is especially impactful for sites that dynamically compute a unique web page for each logged-in user and hence often tend to have higher [TTFB](https://web.dev/ttfb/) and LCP stemming from database lookups. Dynamic SXG gives you the option and flexibility to leverage SXG to speed up visits to your site for certain users without impacting your ability to provide a personalized experience to others. +This is especially impactful for sites that dynamically compute a unique web page for each logged-in user and hence often tend to have higher [TTFB](https://web.dev/articles/ttfb) and LCP stemming from database lookups. Dynamic SXG gives you the option and flexibility to leverage SXG to speed up visits to your site for certain users without impacting your ability to provide a personalized experience to others. ### How to enable this feature diff --git a/site/en/blog/sync-methods-for-accesshandles/index.md b/site/en/blog/sync-methods-for-accesshandles/index.md index e4038319b..dbd33d2dd 100644 --- a/site/en/blog/sync-methods-for-accesshandles/index.md +++ b/site/en/blog/sync-methods-for-accesshandles/index.md @@ -18,7 +18,7 @@ tags: --- The -[origin private file system](https://web.dev/file-system-access/#accessing-files-optimized-for-performance-from-the-origin-private-file-system) +[origin private file system](https://web.dev/articles/file-system-access#accessing_files_optimized_for_performance_from_the_origin_private_file_system) provides access to a special kind of file that is highly optimized for performance, for example, by offering in-place and exclusive write access to a file's content. Developers can get access to such files by calling diff --git a/site/en/blog/tablesng/index.md b/site/en/blog/tablesng/index.md index 100c8264a..0f9b97d59 100644 --- a/site/en/blog/tablesng/index.md +++ b/site/en/blog/tablesng/index.md @@ -18,7 +18,7 @@ TablesNG launches in Chromium 91, and fixes a [ton of bugs](https://bugs.chromium.org/p/chromium/issues/list?q=label%3ATarget-TablesNG&can=2) that have been a part of the web platform for years. These updates will improve browser compatibility as a part of the -[#Compat2021](https://web.dev/compat2021/) effort, and improve using tables on +[#Compat2021](https://web.dev/blog/compat2021) effort, and improve using tables on the web platform overall. Some of the most-starred issues include [`position: sticky` in rows](https://bugs.chromium.org/p/chromium/issues/detail?id=702927&q=label%3ATarget-TablesNG&can=2&sort=pri), @@ -32,16 +32,16 @@ and proper TablesNG is a multi-year effort, led by Chrome developer Aleks Totic, to completely re-architect how tables are rendered on the web. Tables are a particular area of friction in web development, in part because of their -history. +history. {% Img src="image/HodOHWjMnbNw56hvNASHWSgZyAf2/bfUfXYeGsTklMOz8J1Kt.png", alt="Parts of a table", width="800", height="420" %} Tables were added to HTML in 1994, then used as the [primary method](https://codeburst.io/a-brief-history-of-trends-in-web-design-845b6acb35bc) -to create complex page layouts for many years. They are still found all over the web, +to create complex page layouts for many years. They are still found all over the web, although modern usage is generally to display tabular data. -However, there are big differences in table behavior across browsers, +However, there are big differences in table behavior across browsers, many of which came about due to the tables specification being incomplete and lacking detail. Tables were also implemented in browsers before many CSS features: orthogonal writing modes, `position:relative`, `box-sizing`, flexbox containers, @@ -83,7 +83,7 @@ was specified well after HTML tables came out. Before this fix, headers with an intended `position: sticky` were just [converted into](https://github.com/w3c/csswg-drafts/issues/3136) `position: static`, but now, you can use `position: sticky` anywhere in the tables: on headers (`<thead>`) or -vertical axis labels. +vertical axis labels. <figure> {% Video src="video/HodOHWjMnbNw56hvNASHWSgZyAf2/SZc6cN9UeFhPZ1q2BRyq.mp4", autoplay="true", muted="true", loop="true" %} @@ -93,7 +93,7 @@ Codepen</a>. </figcaption> </figure> -{% Aside 'warning' %} +{% Aside 'warning' %} If you're using `position: sticky` on a table, make sure it doesn't have borders. Border painting is currently an open cross-browser compatibility issue, as borders belong to the table, not the header row itself. @@ -118,7 +118,7 @@ where the first cell in the table is the top-most. alt="z-index order of tables", width="800", height="434" %} So the issue here is that borders belong to the table, not the cell, in the old -way that tables were painted. Collapsed borders are painted when table paints its foreground. +way that tables were painted. Collapsed borders are painted when table paints its foreground. This means that a single table cell could not have multiple borders: @@ -144,7 +144,7 @@ with TablesNG. Previously, the older engine always rounded graphics values to the pixel. This meant that as you zoom in and out of the page, things would shift, causing alignment problems. TablesNG fixes these alignment issues. -{% Aside 'warning' %} +{% Aside 'warning' %} There is a [known bug](https://bugs.chromium.org/p/chromium/issues/detail?id=1201762) with table zoom and how borders are repainted. If you are testing this out, you may run into that. {% endAside %} @@ -157,12 +157,12 @@ projects that this team has taken on over the past eight years. Others, though not all of the projects, include: - LayoutNG: a ground-up rewrite of all layout algorithms, for greatly improved -reliability and more predictable performance. +reliability and more predictable performance. - BlinkNG: a systematic cleanup and refactoring of the Blink rendering engine into cleanly separated pipeline phases. This allows for better caching, higher reliability, and re-entrant / delayed-rendering features such as [content-visibility](/content-visibility/) -and [container queries](/new-responsive/). +and [container queries](/new-responsive/). - GPU Raster Everywhere: a long-term effort to roll out GPU rasterization on all platforms, whenever possible. - Threaded scrolling and animations: a long-term effort to move all scrolling and diff --git a/site/en/blog/talking-to-the-stadia-controller-with-webhid/index.md b/site/en/blog/talking-to-the-stadia-controller-with-webhid/index.md index 9ae90fc5e..dd488039f 100644 --- a/site/en/blog/talking-to-the-stadia-controller-with-webhid/index.md +++ b/site/en/blog/talking-to-the-stadia-controller-with-webhid/index.md @@ -17,7 +17,7 @@ Since Stadia shut down, many feared that the controller would end up as a useles ## The Stadia controller as a standard gamepad -After flashing, the controller appears as a [standard gamepad](https://w3c.github.io/gamepad/#dfn-standard-gamepad) to the operating system. See the following screenshot for a common button and axis arrangement on a standard gamepad. As defined in the [Gamepad API](https://web.dev/gamepad/) spec, standard gamepads have buttons from 0 to 16, so 17 in total (the d-pad counts as four buttons). If you try the Stadia controller on the [gamepad tester demo](https://gamepad-demo.glitch.me/), you will notice that it works like a charm. +After flashing, the controller appears as a [standard gamepad](https://w3c.github.io/gamepad/#dfn-standard-gamepad) to the operating system. See the following screenshot for a common button and axis arrangement on a standard gamepad. As defined in the [Gamepad API](https://web.dev/articles/gamepad) spec, standard gamepads have buttons from 0 to 16, so 17 in total (the d-pad counts as four buttons). If you try the Stadia controller on the [gamepad tester demo](https://gamepad-demo.glitch.me/), you will notice that it works like a charm. {% Img src="image/8WbTDNrhLsU0El80frMBGE4eMCD3/ujZz8e9qFPk9YVTROqZX.png", alt="A schema of a standard gamepad with the various axes and buttons labeled.", width="800", height="566" %} diff --git a/site/en/blog/third-party-scripts/index.md b/site/en/blog/third-party-scripts/index.md index 2a78fd16b..3832fae4a 100644 --- a/site/en/blog/third-party-scripts/index.md +++ b/site/en/blog/third-party-scripts/index.md @@ -17,7 +17,7 @@ tags: [Third-party](https://almanac.httparchive.org/en/2021/third-parties) resources (such as embeds and scripts) are heavily used across the web today. They provide out-of-the-box solutions for embedding social media, videos, analytics, live chat, advertising, A/B testing, personalization, and others. Third-party embeds are a necessary part of modern websites that allow site owners to focus on their core competencies, while offloading standard but critical functions to external providers. -When both first party and third parties on a web page work in harmony, it is possible for a page to deliver a great user-experience. However, this requires significant effort from both engineering and business teams and is often overlooked, resulting in less than performant web pages and a [negative impact](https://web.dev/third-party-javascript/#performance) to user-centric metrics such as the [Core Web Vitals](https://web.dev/vitals/). This is detrimental to both parties and creates missed opportunities in businesses. Could we do better here? +When both first party and third parties on a web page work in harmony, it is possible for a page to deliver a great user-experience. However, this requires significant effort from both engineering and business teams and is often overlooked, resulting in less than performant web pages and a [negative impact](https://web.dev/third-party-javascript/#performance) to user-centric metrics such as the [Core Web Vitals](https://web.dev/articles/vitals). This is detrimental to both parties and creates missed opportunities in businesses. Could we do better here? We have a future vision of the web where third-party scripts and resources provide the intended business value with minimal regression to the performance or user experience of websites that use them in the browser. This would allow users to ideally experience faster page loads. @@ -134,15 +134,15 @@ These third-party scripts and libraries allow web developers to leverage tried a Ideally, developers of third-parties are subject matter experts for the specific features they provide. Most popular third-parties have undergone several iterations, and one can expect their code to be optimized for their own business goals, which may or may not include the performance of pages using them. However, we do know that even the most well-optimized third-parties [affect performance](https://almanac.httparchive.org/en/2021/third-parties#popular-third-parties-and-their-impact-on-render). Here are the main reasons for this impact: -1. **Size and Script Execution Costs**: Third-parties often aim to provide significant functionality "just" by dropping in a `<script>` or `<iframe>` element into your page. These elements then pull in scripts and resources that are significant in size and take longer to download and execute. Too much JavaScript keeps the main thread busy longer, blocks rendering, and delays user interactions. Some of the top third-parties have been known to block the main thread from [42 ms to 1.6 s](https://almanac.httparchive.org/en/2021/third-parties#fig-14) for more than 50% of the sites analysed. A blocked main thread results in a high [Total Blocking Time (TBT)](https://web.dev/tbt/) which is one of the metrics that affects the performance score for the site. Additionally, it also delays response to user interactions and degrades the [Interaction to Next Paint (INP)](https://web.dev/inp/) metric used to measure the responsiveness of websites. Thus, script execution costs have a significant impact on performance. +1. **Size and Script Execution Costs**: Third-parties often aim to provide significant functionality "just" by dropping in a `<script>` or `<iframe>` element into your page. These elements then pull in scripts and resources that are significant in size and take longer to download and execute. Too much JavaScript keeps the main thread busy longer, blocks rendering, and delays user interactions. Some of the top third-parties have been known to block the main thread from [42 ms to 1.6 s](https://almanac.httparchive.org/en/2021/third-parties#fig-14) for more than 50% of the sites analysed. A blocked main thread results in a high [Total Blocking Time (TBT)](https://web.dev/articles/tbt) which is one of the metrics that affects the performance score for the site. Additionally, it also delays response to user interactions and degrades the [Interaction to Next Paint (INP)](https://web.dev/articles/inp) metric used to measure the responsiveness of websites. Thus, script execution costs have a significant impact on performance. -2. **Number**: On average, websites use around [21 different third-parties](https://almanac.httparchive.org/en/2021/third-parties#fig-4) on mobile and web. Often, third-party tags are added by tag management tools that are not directly controlled by the technical/development teams. Tags which are not required may be added by other teams without a review process and never get removed. These can significantly impact user experience, page weight, or CPU utilisation. Establishing a [governance process](https://web.dev/controlling-third-party-scripts/) can address such situations and allow developers to audit each provider's impact. It would help if developers had ready data available for all third-parties that provide a specific function with their performance impact, benefits, and trade-offs for comparison. Another challenge teams face is that for many sites, their third-party tags only run in production but not in their development environments, making it more challenging for developers to test them. +2. **Number**: On average, websites use around [21 different third-parties](https://almanac.httparchive.org/en/2021/third-parties#fig-4) on mobile and web. Often, third-party tags are added by tag management tools that are not directly controlled by the technical/development teams. Tags which are not required may be added by other teams without a review process and never get removed. These can significantly impact user experience, page weight, or CPU utilisation. Establishing a [governance process](https://web.dev/articles/controlling-third-party-scripts) can address such situations and allow developers to audit each provider's impact. It would help if developers had ready data available for all third-parties that provide a specific function with their performance impact, benefits, and trade-offs for comparison. Another challenge teams face is that for many sites, their third-party tags only run in production but not in their development environments, making it more challenging for developers to test them. 3. **Network**: Since third-parties are hosted on different origins, browsers have to make a larger number of connections to download content from them. The different connections cannot coordinate download based on priority, resulting in network contention. This can further delay the page load if [the proper optimizations](https://web.dev/preconnect-and-dns-prefetch/#:~:text=Adding%20rel%3Dpreconnect%20to%20a,time%20the%20browser%20requests%20them.) are not considered. -4. **Sequencing**: Third-parties can block the main thread and contend with bandwidth for more critical resources. That said, in some cases, third-parties are the critical resources required for rendering the page. Optimal sequencing of the first and third party resources becomes necessary when websites use multiple third-parties. Web developers should be aware of the different [options](https://web.dev/script-component/#sequencing-third-party-scripts-without-a-framework-component) available to optimize sequencing. +4. **Sequencing**: Third-parties can block the main thread and contend with bandwidth for more critical resources. That said, in some cases, third-parties are the critical resources required for rendering the page. Optimal sequencing of the first and third party resources becomes necessary when websites use multiple third-parties. Web developers should be aware of the different [options](https://web.dev/articles/script-component#sequencing_third_party_scripts_without_a_framework_component) available to optimize sequencing. -As a consequence of the above, third-parties can affect any or all components of Core Web Vitals. A majority of third-parties negatively impact [Largest Contentful Paint (LCP)](https://web.dev/lcp/) and [First Input Delay (FID)](https://web.dev/fid/). [YouTube embeds block the main thread](https://almanac.httparchive.org/en/2021/third-parties#fig-15) for 4.5 seconds for 10% of the websites on mobile, and at least 1.6 seconds for 50% of the websites studied. Imagine a user's frustration if they came across a page with 20 such scripts on a slow connection. The following visualization from [thirdpartyweb.today](https://www.thirdpartyweb.today/) shows third-parties with the largest performance impact at present. +As a consequence of the above, third-parties can affect any or all components of Core Web Vitals. A majority of third-parties negatively impact [Largest Contentful Paint (LCP)](https://web.dev/articles/lcp) and [First Input Delay (FID)](https://web.dev/articles/fid). [YouTube embeds block the main thread](https://almanac.httparchive.org/en/2021/third-parties#fig-15) for 4.5 seconds for 10% of the websites on mobile, and at least 1.6 seconds for 50% of the websites studied. Imagine a user's frustration if they came across a page with 20 such scripts on a slow connection. The following visualization from [thirdpartyweb.today](https://www.thirdpartyweb.today/) shows third-parties with the largest performance impact at present. {% Img src="image/1L2RBhCLSnXjCnSlevaDjy3vba73/U26McnxB3ZYKJ2zE0Zp4.png", alt="Third Party Web visualization", width="800", height="500" %} @@ -170,13 +170,13 @@ We propose a three-pronged approach for achieving these outcomes... 1. **Give ***developers*** deeper attribution into per third-party impact via RUM and in Chrome's developer tooling.** - RUM refers to real user metrics data (also known as [field data](https://web.dev/lab-and-field-data-differences/#field-data)) available through [web performance monitoring APIs](https://web.dev/vitals-measurement-getting-started/#collecting-rum-data). Chrome's developer tooling includes Lighthouse, Chrome DevTools and the Chrome User Experience Report. We propose to enhance the available APIs and tools so that site developers understand the impact of every third-party they have used on every page. The tools will also educate them about actions they can take to mitigate the impact (for example, deferring them or using [facades](https://web.dev/third-party-facades/)) and explore other potential solutions (other third-parties or DIY) with trade-offs. For the web performance monitoring APIs, we're exploring ways in which we can expand their coverage of cross-origin resources without compromising our users' privacy and security. + RUM refers to real user metrics data (also known as [field data](https://web.dev/articles/lab-and-field-data-differences#field_data)) available through [web performance monitoring APIs](https://web.dev/articles/vitals-measurement-getting-started#collecting_rum_data). Chrome's developer tooling includes Lighthouse, Chrome DevTools and the Chrome User Experience Report. We propose to enhance the available APIs and tools so that site developers understand the impact of every third-party they have used on every page. The tools will also educate them about actions they can take to mitigate the impact (for example, deferring them or using [facades](https://web.dev/articles/third-party-facades)) and explore other potential solutions (other third-parties or DIY) with trade-offs. For the web performance monitoring APIs, we're exploring ways in which we can expand their coverage of cross-origin resources without compromising our users' privacy and security. 2. **Give ***businesses*** a well-lit path for efficiently loading third-party resources.** We would like to propose new standards that encourage browsers to more intelligently make trade-offs between how first-party and third-party resources are loaded in the name of a better loading experience for users. Later, we'll highlight some of these proposals, such as lazy-loading third-party embeds by default, or applying different resource prioritization to third-party resources that may not be as critical to the initial content users may care about most. These are just a small number of the ideas we're evaluating in this space and would love to collaborate with both web performance experts and the broader community on shaping this work. - We would similarly like to address such problems in JavaScript frameworks and Content Management Systems (CMS) where more appropriate. Projects such as [Aurora](http://web.dev/aurora) and [WordPress Performance Team](https://github.com/WordPress/performance) have taught us the importance of baked-in defaults that resolve known loading issues. Defaults baked into frameworks and CMS guide businesses along a well-lit path. They can also be helpful to the user agent (for example, Chrome) as hints allowing it to apply heuristics to optimize page load and CWV. Such hints can help the user agent decide when and how specific third-parties should load in the page life cycle. (For example, the [Next.js script component](https://web.dev/script-component/#the-next.js-script-component) has a baked-in default to load third-party scripts after the page becomes interactive.) + We would similarly like to address such problems in JavaScript frameworks and Content Management Systems (CMS) where more appropriate. Projects such as [Aurora](http://web.dev/aurora) and [WordPress Performance Team](https://github.com/WordPress/performance) have taught us the importance of baked-in defaults that resolve known loading issues. Defaults baked into frameworks and CMS guide businesses along a well-lit path. They can also be helpful to the user agent (for example, Chrome) as hints allowing it to apply heuristics to optimize page load and CWV. Such hints can help the user agent decide when and how specific third-parties should load in the page life cycle. (For example, the [Next.js script component](https://web.dev/articles/script-component#the_next.js_script_component) has a baked-in default to load third-party scripts after the page becomes interactive.) 3. **Give ***third-parties*** incentives to reduce their performance impact via better transparency efforts.** diff --git a/site/en/blog/timer-throttling-in-chrome-88/index.md b/site/en/blog/timer-throttling-in-chrome-88/index.md index f1018d0de..53919c89b 100644 --- a/site/en/blog/timer-throttling-in-chrome-88/index.md +++ b/site/en/blog/timer-throttling-in-chrome-88/index.md @@ -134,7 +134,7 @@ Some examples: - If you need to know when an element enters in the viewport, use [`IntersectionObserver`](https://developer.mozilla.org/docs/Web/API/Intersection_Observer_API). - If you need to know when an element changes size, use - [`ResizeObserver`](https://web.dev/resize-observer/). + [`ResizeObserver`](https://web.dev/articles/resize-observer). - If you need to know when the DOM changes, use [`MutationObserver`](https://developer.mozilla.org/docs/Web/API/MutationObserver), or maybe [custom element lifecycle @@ -145,14 +145,14 @@ Some examples: events](https://developer.mozilla.org/docs/Web/API/EventSource), [push messages](https://developer.mozilla.org/docs/Web/API/Push_API), or [fetch - streams](https://web.dev/fetch-upload-streaming/#previously-on-the-exciting-adventures-of-fetch-streams). + streams](https://web.dev/articles/fetch-upload-streaming#previously_on_the_exciting_adventures_of_fetch_streams). - If you need to react to stage changes in audio/video, [use events like `timeupdate` and `ended`](https://html.spec.whatwg.org/multipage/media.html#mediaevents), or - [`requestVideoFrameCallback`](https://web.dev/requestvideoframecallback-rvfc/) + [`requestVideoFrameCallback`](https://web.dev/articles/requestvideoframecallback-rvfc) if you need to do something with each frame. -There's also [notification triggers](https://web.dev/notification-triggers/) if +There's also [notification triggers](https://web.dev/articles/notification-triggers) if you want to show a notification at a particular time. ### Animation diff --git a/site/en/blog/top-layer-devtools/index.md b/site/en/blog/top-layer-devtools/index.md index bc5690d97..f1bc02be5 100644 --- a/site/en/blog/top-layer-devtools/index.md +++ b/site/en/blog/top-layer-devtools/index.md @@ -51,7 +51,7 @@ Here is a demo with a couple of dialogs that have styles applied to their backdr Luckily, there is a way to customize the content beneath the top layer element. -Every element in the top layer has a [CSS pseudo-element](https://web.dev/learn/css/pseudo-elements/) called a [backdrop](https://developer.mozilla.org/docs/Web/CSS/::backdrop). +Every element in the top layer has a [CSS pseudo-element](https://web.dev/learn/css/pseudo-elements) called a [backdrop](https://developer.mozilla.org/docs/Web/CSS/::backdrop). The Backdrop is a box the size of the viewport which is rendered immediately beneath any top layer element. The `::backdrop` pseudo-element makes it possible to obscure, style, or completely hide everything located below the element when it's the topmost one in the top layer. @@ -64,7 +64,7 @@ Here is how you style a backdrop: dialog::backdrop { background: rgba(255,0,0,.25); } -``` +``` ### How to show only the first backdrop? @@ -86,7 +86,7 @@ DevTools support for the top layer helps developers understand the concept of th - The element at the top of the stack at any point. Moreover, DevTools top layer support helps to visualize the position of the backdrop pseudo-element in the top layer stack. Even though it is not a tree element, it plays an important role in how the top layer works and can be useful to developers. - + With the top layer support features, you can: 1. Observe which elements are in the top layer stack at any time. The top layer representation stack changes dynamically as elements are added or removed from the top layer. @@ -114,7 +114,7 @@ To jump from the top layer tree element to the link in the top layer container, You can turn off any badge, including the **top-layer** one. To disable the badges, right-click on any badge, choose **Badge settings** and clear the ticks next to badges you want to hide. {% Img src="image/1D9D0Ls1ATa2ZPA9x2ZWrGFyZzT2/FJydb49bYgzMh22sAHHC.gif", alt="Turning the badge off.", width="800", height="438" %} - + {% Aside %} **Note**: The top layer container appears only when the top layer stack contains rendered content. {% endAside %} @@ -139,7 +139,7 @@ In the elements tree, a backdrop element resides before the closing tag of the e ### Changes to the DOM tree -`ElementsTreeElement`, the class responsible for creating and managing individual DOM tree elements in DevTools, was not sufficient to implement a top layer container. +`ElementsTreeElement`, the class responsible for creating and managing individual DOM tree elements in DevTools, was not sufficient to implement a top layer container. To display the **top layer container** as a node in the tree, we added a new class that creates DevTools tree element nodes. Previously, the class responsible for creating DevTools elements tree initialized every `TreeElement` with a `DOMNode`, which is a class with a `backendNodeId` and other backend-related properties. `backendNodeId`, in turn, is assigned on the backend. @@ -178,7 +178,7 @@ To display the current top layer elements, we need a new experimental CDP comman ```diff # Returns NodeIds of the current top layer elements. - # Top layer renders closest to the user within a viewport, therefore, its elements always + # Top layer renders closest to the user within a viewport, therefore, its elements always # appear on top of all other content. experimental command getTopLayerElements returns @@ -188,7 +188,7 @@ To display the current top layer elements, we need a new experimental CDP comman #### CDP: `DOM.topLayerElementsUpdated` event -To get the up-to-date list of the top layer elements, we need every change of the top layer elements to trigger an experimental CDP event. This event informs the frontend of the change that then calls the `DOM.getTopLayerElements` command and receives the new elements list. +To get the up-to-date list of the top layer elements, we need every change of the top layer elements to trigger an experimental CDP event. This event informs the frontend of the change that then calls the `DOM.getTopLayerElements` command and receives the new elements list. The event looks like the following: @@ -199,11 +199,11 @@ The event looks like the following: #### CDP considerations -There were multiple options on how the CDP support of the top layer could be implemented. Another option we considered was making an event that would return the list of the top layer elements instead of just informing the front end about an addition or removal of a top layer element. +There were multiple options on how the CDP support of the top layer could be implemented. Another option we considered was making an event that would return the list of the top layer elements instead of just informing the front end about an addition or removal of a top layer element. Alternatively, we could make two events instead of the command: `topLayerElementAdded` and `topLayerElementRemoved`. In this case, we would be receiving an element and would need to manage the array of the top layer elements on the front end. Currently, a frontend event calls the `getTopLayerElements` command to get a list of updated elements. If we were to send a list of elements or a specific element that caused the change every time an event is triggered, we could avoid one step of calling the command. -However, in this case, the frontend would lose the control over which elements are pushed. +However, in this case, the frontend would lose the control over which elements are pushed. We implemented it in this way because, in our opinion, it's better if the frontend decides when to request top layer nodes. For example, if the top layer is collapsed in the UI or the user is using a DevTools panel that doesn't have the elements tree, there's no need to get the extra nodes that could be deeper into the tree. diff --git a/site/en/blog/user-agent-reduction-android-model-and-version/index.md b/site/en/blog/user-agent-reduction-android-model-and-version/index.md index 20451085a..20da4dce5 100644 --- a/site/en/blog/user-agent-reduction-android-model-and-version/index.md +++ b/site/en/blog/user-agent-reduction-android-model-and-version/index.md @@ -21,7 +21,7 @@ sharing_image: 'image/VWw0b3pM7jdugTkwI6Y81n6f5Yc2/3VrRwYpBizX3JQA93uzg.png' --- {% Aside 'warning'%} -This article is outdated as User-Agent reduction is complete. Learn how to [migrate to User-Agent Client Hints](https://web.dev/migrate-to-ua-ch/) and read about why this change was made in [User-Agent reduction](/docs/privacy-sandbox/user-agent/). +This article is outdated as User-Agent reduction is complete. Learn how to [migrate to User-Agent Client Hints](https://web.dev/articles/migrate-to-ua-ch) and read about why this change was made in [User-Agent reduction](/docs/privacy-sandbox/user-agent/). {% endAside %} Starting in Chrome 110 (February 2023) we are gradually introducing a _fixed value for Android version and device model_—the default value will always be `Android 10` on a model `K`. @@ -136,7 +136,7 @@ navigator.userAgentData ## Cross-origin or initial requests -If you have [cross-origin resources on your page that need these values you can allow access](https://web.dev/migrate-to-ua-ch/#strategy-delegating-hints-to-cross-origin-requests) via the `Permissions-Policy` HTTP header or using the `Delegate-CH` meta tag in your HTML. +If you have [cross-origin resources on your page that need these values you can allow access](https://web.dev/articles/migrate-to-ua-ch#strategy_delegating_hints_to_cross_origin_requests) via the `Permissions-Policy` HTTP header or using the `Delegate-CH` meta tag in your HTML. If it’s necessary for your site to have these sensitive values on the very first top-level request, you can use the [`Critical-CH` HTTP header](/docs/privacy-sandbox/user-agent/#critical-client-hints) which will tell the browser to retry its initial request with those extra hints added. This may be helpful for legacy systems that are hard to update, but ideally you should not be relying on these sensitive values to serve your initial HTML. @@ -153,7 +153,7 @@ If you need more time to prepare, [sign up for the deprecation trial](/origintr To see the reduced user-agent string in action, check out the following: -* See the reduced user-agent string for _your_ device on [goo.gle/reduced-ua-demo](https://goo.gle/reduced-ua-demo) +* See the reduced user-agent string for _your_ device on [goo.gle/reduced-ua-demo](https://goo.gle/reduced-ua-demo) * See all the JavaScript and HTTP header User-Agent Client Hints for _your_ device on [goo.gle/ua-ch-demo](https://goo.gle/ua-ch-demo) * Send the reduced user-agent string in _your_ browser by enabling the `#reduce-user-agent` [Chrome flag](/docs/web-platform/chrome-flags/). diff --git a/site/en/blog/user-agent-reduction-deprecation-trial/index.md b/site/en/blog/user-agent-reduction-deprecation-trial/index.md index c0e490932..8653729b1 100644 --- a/site/en/blog/user-agent-reduction-deprecation-trial/index.md +++ b/site/en/blog/user-agent-reduction-deprecation-trial/index.md @@ -24,12 +24,12 @@ is_outdated: true To replace functionality that relied on the User Agent string, you can implement the [User Agent client hints API](https://developer.mozilla.org/docs/Web/API/User-Agent_Client_Hints_API#browser_compatibility). - The [User-Agent Client Hints page](https://web.dev/migrate-to-ua-ch/) provides some background. + The [User-Agent Client Hints page](https://web.dev/articles/migrate-to-ua-ch) provides some background. The remainder of this blog post should be considered deprecated. {% endAside %} -Starting from Chrome 101, the information available in the User-Agent (UA) string will be reduced [using a phased approach](https://blog.chromium.org/2021/09/user-agent-reduction-origin-trial-and-dates.html). Sites that haven't had time to migrate away from using the reduced User-Agent string and [move toward User-Agent Client Hints](https://web.dev/migrate-to-ua-ch/) can take part in a deprecation trial to continue receiving the full User-Agent string. +Starting from Chrome 101, the information available in the User-Agent (UA) string will be reduced [using a phased approach](https://blog.chromium.org/2021/09/user-agent-reduction-origin-trial-and-dates.html). Sites that haven't had time to migrate away from using the reduced User-Agent string and [move toward User-Agent Client Hints](https://web.dev/articles/migrate-to-ua-ch) can take part in a deprecation trial to continue receiving the full User-Agent string. The registration for the deprecation trial will begin with the [Chrome 100](https://chromiumdash.appspot.com/schedule) Beta. It will allow sites to receive the full User-Agent string ahead of the Chrome 101 release, where the minor version string will be reduced. If you would like to test the origin trial on Chrome 100 Beta before it launches to the stable channel, be sure to register and test before the release date for Chrome 100 ([currently scheduled for March 31st, 2022](https://chromiumdash.appspot.com/schedule)). @@ -44,7 +44,7 @@ By enrolling in the deprecation trial, sites will continue to receive the full U - The `navigator.platform` Javascript getter - The `navigator.appVersion` Javascript getter -Sites should still audit their usage of the User-Agent header and related APIs, and if needed prepare to [migrate to User-Agent Client Hints](https://web.dev/migrate-to-ua-ch/) before the deprecation trial expires. The intent is to expire this deprecation trial once the [User-Agent Reduction rollout](https://blog.chromium.org/2021/09/user-agent-reduction-origin-trial-and-dates.html) is complete. +Sites should still audit their usage of the User-Agent header and related APIs, and if needed prepare to [migrate to User-Agent Client Hints](https://web.dev/articles/migrate-to-ua-ch) before the deprecation trial expires. The intent is to expire this deprecation trial once the [User-Agent Reduction rollout](https://blog.chromium.org/2021/09/user-agent-reduction-origin-trial-and-dates.html) is complete. ## How do I participate in the User-Agent Reduction deprecation trial? diff --git a/site/en/blog/user-agent-reduction-oct-2022-updates/index.md b/site/en/blog/user-agent-reduction-oct-2022-updates/index.md index c7962b3b4..f9ae9a4f4 100644 --- a/site/en/blog/user-agent-reduction-oct-2022-updates/index.md +++ b/site/en/blog/user-agent-reduction-oct-2022-updates/index.md @@ -1,7 +1,7 @@ --- layout: "layouts/blog-post.njk" title: "Prepare for User-Agent Reduction changes in October" -subhead: > +subhead: > What's happening with the User-Agent string, why Chrome is making this change, and what you can do to prepare. description: > In October, Chrome will take the next step in reducing the information @@ -21,7 +21,7 @@ is_outdated: true --- {% Aside 'warning'%} -This article is outdated as User-Agent reduction is complete. Learn how to [migrate to User-Agent Client Hints](https://web.dev/migrate-to-ua-ch/) and read about why this change was made in [User-Agent reduction](/docs/privacy-sandbox/user-agent/). +This article is outdated as User-Agent reduction is complete. Learn how to [migrate to User-Agent Client Hints](https://web.dev/articles/migrate-to-ua-ch) and read about why this change was made in [User-Agent reduction](/docs/privacy-sandbox/user-agent/). {% endAside %} In October, Chrome will take the next step in reducing the information @@ -47,7 +47,7 @@ identify and track a user across the web. And not all websites and services need the information the UA string provides. That's why Chrome is reducing the information shared by default in the UA -string, and introducing [a new API](https://web.dev/user-agent-client-hints/), +string, and introducing [a new API](https://web.dev/articles/user-agent-client-hints), User-Agent Client Hints (UA-CH), that will let sites and services request only the information they need. We first [announced](https://groups.google.com/a/chromium.org/g/blink-dev/c/-2JIRNMWJ7s/m/yHe4tQNLCgAJ) @@ -58,7 +58,7 @@ information in the UA string. ## Phased approach -Chrome began removing parts of the UA string to improve privacy in late April, +Chrome began removing parts of the UA string to improve privacy in late April, beginning with the [minor version](https://chromestatus.com/feature/6311349754789888). This is what we've been calling the diff --git a/site/en/blog/user-agent-reduction-origin-trial/index.md b/site/en/blog/user-agent-reduction-origin-trial/index.md index 84b251222..1cf473075 100644 --- a/site/en/blog/user-agent-reduction-origin-trial/index.md +++ b/site/en/blog/user-agent-reduction-origin-trial/index.md @@ -23,11 +23,11 @@ is_outdated: true To replace functionality that relied on the User Agent string, you can implement the [User Agent client hints API](https://developer.mozilla.org/docs/Web/API/User-Agent_Client_Hints_API#browser_compatibility). - The [User-Agent Client Hints page](https://web.dev/migrate-to-ua-ch/) provides some background. + The [User-Agent Client Hints page](https://web.dev/articles/migrate-to-ua-ch) provides some background. The remainder of this blog post should be considered deprecated. {% endAside %} - + User-Agent Reduction is an effort to reduce passive fingerprinting surfaces by reducing the information in the [User-Agent](https://developer.mozilla.org/docs/Web/HTTP/Headers/User-Agent) @@ -87,14 +87,14 @@ in: To receive more client information than what's shared by the reduced User-Agent, sites will need to migrate to the new User-Agent [Client -Hints](https://web.dev/migrate-to-ua-ch/) API. For more details on migration +Hints](https://web.dev/articles/migrate-to-ua-ch) API. For more details on migration strategies, see [Migrate to User-Agent Client -Hints](https://web.dev/migrate-to-ua-ch/). +Hints](https://web.dev/articles/migrate-to-ua-ch). The User-Agent reduction plans do not currently include iOS and WebView, therefore those platforms will continue to get the full user agent string. The primary reason is that these platforms have not yet implemented User-Agent -[Client Hints](https://web.dev/migrate-to-ua-ch/). +[Client Hints](https://web.dev/articles/migrate-to-ua-ch). ## How does this origin trial work? @@ -124,7 +124,7 @@ provided that the [permissions policy](/docs/privacy-sandbox/permissions-policy/ 1. To register for the origin trial and get a token for your domains, visit the [Trial for User Agent Reduction page](/origintrials/#/view_trial/-7123568710593282047). - + {% Aside %} To register your domains for the trial as a third-party embed, you will [need a separate token](#enroll-third-party). @@ -147,7 +147,7 @@ provided that the [permissions policy](/docs/privacy-sandbox/permissions-policy/ reduced UA string, even if the origins of those requests are not enrolled in the origin trial. 1. Load your website in Chrome M95 (or later) and start receiving the - reduced UA string. + reduced UA string. 1. Submit any issues or feedback to the UA Reduction [GitHub repository](https://github.com/miketaylr/user-agent-reduction/issues). 1. See [https://uar-ot.glitch.me/](https://uar-ot.glitch.me/) for a simple @@ -161,7 +161,7 @@ enrolled. To enroll as a third-party embed: -1. Visit the +1. Visit the [Trial for User Agent Reduction](/origintrials/#/view_trial/-7123568710593282047) and click **Register**. 1. When creating the token, make sure to select the `Third-party matching` checkbox. diff --git a/site/en/blog/view-transitions-case-studies/index.md b/site/en/blog/view-transitions-case-studies/index.md index dc4e755e7..8ac2411e1 100644 --- a/site/en/blog/view-transitions-case-studies/index.md +++ b/site/en/blog/view-transitions-case-studies/index.md @@ -2,7 +2,7 @@ layout: 'layouts/blog-post.njk' title: Seamless navigation made possible with view transitions description: > - An in-depth walkthrough of how and why CyberAgent, RedBus, Nykaa, and PolicyBazaar implemented view transitions. + An in-depth walkthrough of how and why CyberAgent, RedBus, Nykaa, and PolicyBazaar implemented view transitions. hero: image/kheDArv5csY6rvQUJDbWRscckLr1/n1NuTA2jvVGsNzbJdNDv.png thumbnail: image/kheDArv5csY6rvQUJDbWRscckLr1/I0szC9KECv6eSWbggsnh.png alt: '' @@ -20,15 +20,15 @@ Launched in Chrome 111, the [View Transitions API](https://developer.mozilla.org You might wonder, how easy is it to implement? What kind of use cases are there? How are other developers using view transitions? -This article takes you through the implementation of view transitions in 4 different websites: [RedBus](#redbus) (travel), [CyberAgent](#cyberagent) (news/blog publisher), [Nykaa](#nykaa) (eCommerce), and [PolicyBazaar](#policybazaar) (insurance) and how their websites benefited in different ways by using the View Transitions API. +This article takes you through the implementation of view transitions in 4 different websites: [RedBus](#redbus) (travel), [CyberAgent](#cyberagent) (news/blog publisher), [Nykaa](#nykaa) (eCommerce), and [PolicyBazaar](#policybazaar) (insurance) and how their websites benefited in different ways by using the View Transitions API. ## redBus {: #redbus } -redBus, part of MakeMyTrip group, is a bus booking and ticketing website headquartered in Bangalore, India with presence across different geographies globally. It was one of the first websites to implement an experience using the View Transitions API. +redBus, part of MakeMyTrip group, is a bus booking and ticketing website headquartered in Bangalore, India with presence across different geographies globally. It was one of the first websites to implement an experience using the View Transitions API. ### Why did Redbus implement view transitions? -The team at redBus are firm believers in providing a unified, app-like web experience, one that is as close as possible to their native apps. In fact, they had implemented multiple customized solutions over the years. For example, they rolled out customized JavaScript and CSS based animations for the page transitions even before the View Transitions API was developed. However, that meant they had to deal with performance management in lower segments of network and devices, occasionally leading to differential experience with an [adaptive loading](https://web.dev/adaptive-loading-cds-2019/) strategy in place. +The team at redBus are firm believers in providing a unified, app-like web experience, one that is as close as possible to their native apps. In fact, they had implemented multiple customized solutions over the years. For example, they rolled out customized JavaScript and CSS based animations for the page transitions even before the View Transitions API was developed. However, that meant they had to deal with performance management in lower segments of network and devices, occasionally leading to differential experience with an [adaptive loading](https://web.dev/articles/adaptive-loading-cds-2019) strategy in place. redBus used view transitions for multiple user journeys. For example, in their self-help section within their mobile app which opened web pages in Custom Chrome Tabs, and in their bus ticket booking funnel where users go from inventory listing page to payments page. In the latter case, view transitions made page to page navigation smoother and resulted in an increase to their conversion rate. This was a result of a better user experience and better [perceived performance](https://developer.mozilla.org/docs/Learn/Performance/Perceived_performance) while the heavy operations—such as fetching the most updated available inventory—were executed. @@ -91,7 +91,7 @@ In the following CSS, `slide-to-right`, `slide-to-left`, `slide-from-right`, and ## Business impact -redBus chose to implement view transitions along with INP improvement efforts across their site, which led to [7% more sales](https://web.dev/redbus-inp/). [Amit Kumar](https://amitkumar-v.medium.com/), Senior Engineering Manager at redBus, said that view transitions are really awesome for those who genuinely want better user experience and desire less maintenance overhead. +redBus chose to implement view transitions along with INP improvement efforts across their site, which led to [7% more sales](https://web.dev/articles/redbus-inp). [Amit Kumar](https://amitkumar-v.medium.com/), Senior Engineering Manager at redBus, said that view transitions are really awesome for those who genuinely want better user experience and desire less maintenance overhead. <blockquote><p>We have conducted comprehensive user feedback sessions, incorporating valuable insights from a diverse group of users. Our deep understanding of our user base (bus and rail) and their needs, combined with our expertise, has led us to believe that this feature will provide significant value right from the start, without the need for A/B testing. View transitions are a step towards bridging the gap between app and web with a smooth navigation experience.</p> @@ -100,7 +100,7 @@ redBus chose to implement view transitions along with INP improvement efforts ac ## CyberAgent {: #cyberagent } -CyberAgent is a Japan-based IT company that provides many online services, including blog and news publishing. +CyberAgent is a Japan-based IT company that provides many online services, including blog and news publishing. ### Why did CyberAgent implement view transitions? @@ -114,7 +114,7 @@ CyberAgent implemented view transitions between the blog list and the blog page. </div> -They also used media queries to design different animation experiences for different devices. For mobile pages they included element transitions, but this effect had too much movement for desktop. +They also used media queries to design different animation experiences for different devices. For mobile pages they included element transitions, but this effect had too much movement for desktop. ```css @media screen and (min-width: 769px) { @@ -166,7 +166,7 @@ View some more [sample Next.js code](https://github.com/noamr/use-view-transitio ### View Transitions for MPA with prerendering technology -CyberAgent also tried out our new [View Transitions API for Multiple Page Apps (MPA)](https://github.com/WICG/view-transitions/blob/main/cross-doc-explainer.md) (currently under the flag `chrome://flags/#view-transition-on-navigation`) on a service called [Ameba News](https://news.ameba.jp/), which is a news portal site. +CyberAgent also tried out our new [View Transitions API for Multiple Page Apps (MPA)](https://github.com/WICG/view-transitions/blob/main/cross-doc-explainer.md) (currently under the flag `chrome://flags/#view-transition-on-navigation`) on a service called [Ameba News](https://news.ameba.jp/), which is a news portal site. View transitions were used in two places: The first is when changing the categories of the news, shown in the following video. @@ -186,14 +186,14 @@ The interesting point is that they only added animation to the part that will ch </div> -Here's how they did this: they assigned a different `view-transition-name` to the different parts of the page. For example, they assigned one `view-transition-name` to the top part of the article, another for the bottom part, and added no animation to the top part. +Here's how they did this: they assigned a different `view-transition-name` to the different parts of the page. For example, they assigned one `view-transition-name` to the top part of the article, another for the bottom part, and added no animation to the top part. ```css ::view-transition-old(root) { animation: var(--animation-disappear-duration) var(--animation-disappear-easing) both fade-out; } - + ::view-transition-new(root) { animation: var(--animation-appear-in-duration) var(--animation-appear-in-easing) both fade-in; @@ -219,11 +219,11 @@ You can read more about their quicklink implementation from [this article](https ### Testimonial -Kazunari Hara, the Tech Lead of the Ameba service in CyberAgent, said that the view transitions could have significant impact on the business for two reasons. +Kazunari Hara, the Tech Lead of the Ameba service in CyberAgent, said that the view transitions could have significant impact on the business for two reasons. Firstly, they guide users on the page. View transitions make it possible to visually focus users on the most important message, and helps them get the most out of the web page. Also, they enhance and emphasize the brand with animation. CyberAgent has a [designated animation design](https://spindle.ameba.design/styles/animation/) to communicate their brand. With view transitions they are able to implement this branded experience without adding the cost of maintaining external libraries. -<blockquote><p>View Transitions is one of my favorite APIs. The ability to add animations as a standard browser feature makes view transitions easier to implement and maintain compared to other solutions dependent on libraries. We are looking forward to implementing view transitions to more services to communicate our brand.</p> +<blockquote><p>View Transitions is one of my favorite APIs. The ability to add animations as a standard browser feature makes view transitions easier to implement and maintain compared to other solutions dependent on libraries. We are looking forward to implementing view transitions to more services to communicate our brand.</p> <cite>Kazunari Hara, CTO of Ameba</cite> </blockquote> @@ -307,23 +307,23 @@ CSS for side drawer animation: ### Testimonial -[Sunit Jindal](https://github.com/sunitJindal), the head of apps at Nykaa, said that the biggest benefit of the view transition was the "Perception of speed". Nykaa used the [shimmer effects](https://www.geeksforgeeks.org/shimmer-effect-using-css/) to wait for the contents to load from the backend, but found that showing the shimmer effect did not provide the users with how long they would need to wait for the content to load. -With view transitions, the transition itself provided users the sense that "something is about to happen", which made the wait less painful. +[Sunit Jindal](https://github.com/sunitJindal), the head of apps at Nykaa, said that the biggest benefit of the view transition was the "Perception of speed". Nykaa used the [shimmer effects](https://www.geeksforgeeks.org/shimmer-effect-using-css/) to wait for the contents to load from the backend, but found that showing the shimmer effect did not provide the users with how long they would need to wait for the content to load. +With view transitions, the transition itself provided users the sense that "something is about to happen", which made the wait less painful. Nykaa was very excited with the newly enhanced UX of their web page with view transitions, and is ready to implement view transitions on additional pages as well. Here's what their VP of Design said: -<blockquote><p>We are softly-committed to implement view transitions in all the upcoming features where it makes sense. Some areas have already been identified and the team is actively investing in those.</p> +<blockquote><p>We are softly-committed to implement view transitions in all the upcoming features where it makes sense. Some areas have already been identified and the team is actively investing in those.</p> <cite>Krishna R V, VP of Design</cite> </blockquote> ## PolicyBazaar {: #policybazaar } -Headquartered in Gurgaon, PolicyBazaar is India's largest insurance aggregator and multinational financial technology company. +Headquartered in Gurgaon, PolicyBazaar is India's largest insurance aggregator and multinational financial technology company. ### Why did PolicyBazaar implement view transitions? -Being a web-first company, PolicyBazaar team has always aimed at providing the best possible user experience across their critical user journeys. It was common practice to implement custom transitions using JavaScript and CSS even prior to the launch of the View Transitions API, as they enhanced the user experience, created a seamless navigation flow, and improved the overall visual appeal of their websites. +Being a web-first company, PolicyBazaar team has always aimed at providing the best possible user experience across their critical user journeys. It was common practice to implement custom transitions using JavaScript and CSS even prior to the launch of the View Transitions API, as they enhanced the user experience, created a seamless navigation flow, and improved the overall visual appeal of their websites. However, these custom implementations came at a cost of occasional performance-based delays, code maintenance complexities and suboptimal compatibility with the frameworks used. The View Transitions API helped them overcome most of these challenges by providing an easy-to-use interface with performance benefits available natively. @@ -379,11 +379,11 @@ Rishabh Mehrotra, their head of Design (Life BU), said that view transitions pla <cite>Saurabh Tiwari (CTO, PolicyBazaar)</cite> </blockquote> -## Next steps +## Next steps Are you interested in trying out view transitions? Here's are some resources you can follow up to learn more: - [developer.chrome.com documentation for view transitions](/docs/web-platform/view-transitions/) -- [View transitions for MPA explainer](https://github.com/WICG/view-transitions/blob/main/cross-doc-explainer.md) -- [Interop proposals to make view transitions available across browsers](https://github.com/web-platform-tests/interop/issues/437) - +- [View transitions for MPA explainer](https://github.com/WICG/view-transitions/blob/main/cross-doc-explainer.md) +- [Interop proposals to make view transitions available across browsers](https://github.com/web-platform-tests/interop/issues/437) + diff --git a/site/en/blog/viewport-resize-behavior/index.md b/site/en/blog/viewport-resize-behavior/index.md index 354c878c2..c1c11fb31 100644 --- a/site/en/blog/viewport-resize-behavior/index.md +++ b/site/en/blog/viewport-resize-behavior/index.md @@ -86,7 +86,7 @@ Depending on which browser and OS combination a visitor uses, one of the behavio ## Mapping the various resize behaviors -In the [Viewport Investigation Effort](https://github.com/web-platform-tests/interop-2022-viewport)-part of [Interop 2022](https://web.dev/interop-2022/)-various viewport-related aspects were investigated, for every major browser and OS combination. +In the [Viewport Investigation Effort](https://github.com/web-platform-tests/interop-2022-viewport)-part of [Interop 2022](https://web.dev/blog/interop-2022)-various viewport-related aspects were investigated, for every major browser and OS combination. One of the tested aspects is the resize behavior when the OSK is shown. This led to the following classification: @@ -124,13 +124,13 @@ This difference in how the various viewports get resized when the OSK is shown l In the browsers from [group 1](#group-one), with the OSK shown: - - The computed values for [viewport-relative units](https://web.dev/learn/css/sizing/#viewport-relative-units) remain the same. + - The computed values for [viewport-relative units](https://web.dev/learn/css/sizing#viewport_relative_units) remain the same. - Elements that were designed to take up the full visual space keep their size. - Elements that use `position: fixed` remain in place and can be obscured by the OSK. In the browsers from [group 2](#group-two), with the OSK shown: - - The computed values for [viewport-relative units](https://web.dev/learn/css/sizing/#viewport-relative-units) shrink. + - The computed values for [viewport-relative units](https://web.dev/learn/css/sizing#viewport_relative_units) shrink. - Elements that were designed to take up the full visual space shrink. - Elements that use `position: fixed` can end up elsewhere in the layout. @@ -157,7 +157,7 @@ These changes do not affect [WebView](/docs/multidevice/webview/) ## Opting in to a different behavior -If you want your website to use the pre-108 resize behavior, fear not. Also shipping in Chrome 108 is an extension to the [viewport meta tag](https://web.dev/viewport/). +If you want your website to use the pre-108 resize behavior, fear not. Also shipping in Chrome 108 is an extension to the [viewport meta tag](https://web.dev/articles/viewport). Through [the `interactive-widget` key](https://drafts.csswg.org/css-viewport/#interactive-widget-section), you can tell Chrome which resize behavior you want. @@ -194,7 +194,7 @@ Note that this meta tag extension is only supported by Chrome 108 and up at the We expect some minor differences to existing sites, but expect these to be non-blocking as Chrome 108 on Android will now behave similarly to Safari on iOS. Therefore, websites that work fine on Safari on iOS should also work fine on Chrome 108 on Android. -However, we do encourage website authors to actively test their websites in Chrome 108, which is in beta from October 27th 2022. Specifically look out for elements that use `position: fixed` and/or rely on [Viewport-relative units](https://web.dev/learn/css/sizing/#viewport-relative-units). +However, we do encourage website authors to actively test their websites in Chrome 108, which is in beta from October 27th 2022. Specifically look out for elements that use `position: fixed` and/or rely on [Viewport-relative units](https://web.dev/learn/css/sizing#viewport_relative_units). Feedback can be reported over at [crbug.com](https://crbug.com/). Be sure to include “on-screen keyboard” in the report’s title. diff --git a/site/en/blog/wasm-module-sharing-restricted-to-same-origin/index.md b/site/en/blog/wasm-module-sharing-restricted-to-same-origin/index.md index ad2d73dbd..18a99cfee 100644 --- a/site/en/blog/wasm-module-sharing-restricted-to-same-origin/index.md +++ b/site/en/blog/wasm-module-sharing-restricted-to-same-origin/index.md @@ -16,7 +16,7 @@ alt: > --- Sharing a WebAssembly (Wasm) module between [same-site but -cross-origin](https://web.dev/same-site-same-origin/) environments will be +cross-origin](https://web.dev/articles/same-site-same-origin) environments will be deprecated to allow [agent clusters](https://html.spec.whatwg.org/multipage/origin.html#origin-keyed-agent-clusters) to be scoped to origins long term. Developers who are using Wasm modules in such @@ -31,7 +31,7 @@ deployment, loading, and compilation. In the following example code, a Wasm module imported from `https://iframe.site.example` is shared with `https://main.site.example` via `postMessage()`. Notice these domains are [same-site but -cross-origin](https://web.dev/same-site-same-origin/). +cross-origin](https://web.dev/articles/same-site-same-origin). Wasm module on `https://iframe.site.example`: @@ -80,7 +80,7 @@ clusters by default. To learn more about origin-keyed agent clusters, see [Requesting performance isolation with the Origin-Agent-Cluster -header](https://web.dev/origin-agent-cluster/). +header](https://web.dev/articles/origin-agent-cluster). ## Next steps and resources diff --git a/site/en/blog/we-are-chrome-for-developers/index.md b/site/en/blog/we-are-chrome-for-developers/index.md index aec9c2a9d..c8b10c2bc 100644 --- a/site/en/blog/we-are-chrome-for-developers/index.md +++ b/site/en/blog/we-are-chrome-for-developers/index.md @@ -11,49 +11,49 @@ alt: > --- -Chrome is celebrating its 15th anniversary this month. It's hard to believe how much the web has changed in that time and we, the Chrome team, feel privileged to have been able to play a part in its evolution, in partnership with one of the most driven, thriving communities. Most of the web's capabilities and exciting experiences today wouldn't exist without the contributions of engineers across browser vendors, standards bodies, frameworks and libraries, and a multitude of open source contributors as well as the work done by web developers. +Chrome is celebrating its 15th anniversary this month. It's hard to believe how much the web has changed in that time and we, the Chrome team, feel privileged to have been able to play a part in its evolution, in partnership with one of the most driven, thriving communities. Most of the web's capabilities and exciting experiences today wouldn't exist without the contributions of engineers across browser vendors, standards bodies, frameworks and libraries, and a multitude of open source contributors as well as the work done by web developers. When we launched our browser 15 years ago, we also [launched Chromium](https://blog.chromium.org/2008/09/welcome-to-chromium_02.html) as a commitment for our support to the web, evolving our [core values](https://www.chromium.org/blink/guidelines/values/) to meet the changing needs of the web of today to being a responsible user agent, promoting a helpful and innovative web, and partnering to safeguard the openness of the web. ## Being a responsible user agent -With the web's latest capabilities, you can now [stream 3D games](https://www.cocos.com/en/post/ODdxxWGryD6DiM6wPJ3yhPklSzCLCCxE), [unleash your creativity](https://stratechery.com/2023/an-interview-with-adobe-chief-strategy-officer-scott-belsky/#web), and do so much more, all through the browser. As we work together to extend the platform's capabilities, it is also our responsibility to maintain trust on the web by keeping people safe and protecting their data. +With the web's latest capabilities, you can now [stream 3D games](https://www.cocos.com/en/post/ODdxxWGryD6DiM6wPJ3yhPklSzCLCCxE), [unleash your creativity](https://stratechery.com/2023/an-interview-with-adobe-chief-strategy-officer-scott-belsky/#web), and do so much more, all through the browser. As we work together to extend the platform's capabilities, it is also our responsibility to maintain trust on the web by keeping people safe and protecting their data. -We have been focused on providing [more granular control over permissions](/blog/one-time-permissions/) granted to web apps, and using machine learning models to [filter out notifications and permission prompts](https://blog.google/products/chrome/building-a-more-helpful-browser-with-machine-learning/) from apps that are linked to malware and phishing attacks. And, with the [Privacy Sandbox](https://privacysandbox.com/) initiative, we're working closely with the entire ecosystem to improve privacy, while preserving the needs of a thriving digital ecosystem. +We have been focused on providing [more granular control over permissions](/blog/one-time-permissions/) granted to web apps, and using machine learning models to [filter out notifications and permission prompts](https://blog.google/products/chrome/building-a-more-helpful-browser-with-machine-learning/) from apps that are linked to malware and phishing attacks. And, with the [Privacy Sandbox](https://privacysandbox.com/) initiative, we're working closely with the entire ecosystem to improve privacy, while preserving the needs of a thriving digital ecosystem. There are billions of sites serving content today, so it's super important that we do this well to build a web that everyone can trust. ## Promoting a helpful and innovative web -Even after thirty years, the web remains one of the most powerful tools for getting things done. We want to keep extending its capabilities and efficiency. Over the years, we've made many upgrades to make the browser faster, safer, and more accessible for everyone. Over the next few years, we want to build capabilities that enable new experiences, enriched by the power of AI, and create a development environment that significantly increases developer productivity. +Even after thirty years, the web remains one of the most powerful tools for getting things done. We want to keep extending its capabilities and efficiency. Over the years, we've made many upgrades to make the browser faster, safer, and more accessible for everyone. Over the next few years, we want to build capabilities that enable new experiences, enriched by the power of AI, and create a development environment that significantly increases developer productivity. ### Capabilities that enable new experiences -People use Chrome for all sorts of things—whether it's planning trips and researching holiday gifts, watching videos, or editing photos. We think there's so many more ways people can get things done on the web. Our efforts with [Project Fugu](/capabilities/) brought more than [50 APIs to the browser](/blog/is-project-fugu-done/), and helped companies like [LEGO® Education](/blog/lego-education-spike-web-bluetooth-web-serial/) to deliver their SPIKE(TM) kits to millions of students globally. +People use Chrome for all sorts of things—whether it's planning trips and researching holiday gifts, watching videos, or editing photos. We think there's so many more ways people can get things done on the web. Our efforts with [Project Fugu](/capabilities/) brought more than [50 APIs to the browser](/blog/is-project-fugu-done/), and helped companies like [LEGO® Education](/blog/lego-education-spike-web-bluetooth-web-serial/) to deliver their SPIKE(TM) kits to millions of students globally. -Advances in user interface design play an equally important role in making experiences feel modern and intuitive. With [RenderingNG](/articles/renderingng/), we're getting the browser ready for the next generation of high fidelity content. By championing exciting APIs like [View Transitions](/docs/web-platform/view-transitions/) and [Scroll-driven animations](/articles/scroll-driven-animations/#:~:text=A%20scroll%2Ddriven%20animation%20is,which%20move%20as%20you%20scroll.), we're also pushing the platform's ability to deliver slick navigation and non-linear transitions that users only expect in native apps. +Advances in user interface design play an equally important role in making experiences feel modern and intuitive. With [RenderingNG](/articles/renderingng/), we're getting the browser ready for the next generation of high fidelity content. By championing exciting APIs like [View Transitions](/docs/web-platform/view-transitions/) and [Scroll-driven animations](/articles/scroll-driven-animations/#:~:text=A%20scroll%2Ddriven%20animation%20is,which%20move%20as%20you%20scroll.), we're also pushing the platform's ability to deliver slick navigation and non-linear transitions that users only expect in native apps. ### A platform primed for AI enabled experiences -The web has always been the platform of choice for any developer looking to ship their product instantly, and we're seeing the same trend for many new AI products. Chrome Web Store developers offer many [exciting AI powered Chrome Extension experiences](https://chromewebstore.google.com/collection/gen_ai_extensions?hl=en), with over 100 million combined active users across hundreds of extensions that offer services like reading/writing, content summary, voice-to-text, code editing and more. +The web has always been the platform of choice for any developer looking to ship their product instantly, and we're seeing the same trend for many new AI products. Chrome Web Store developers offer many [exciting AI powered Chrome Extension experiences](https://chromewebstore.google.com/collection/gen_ai_extensions?hl=en), with over 100 million combined active users across hundreds of extensions that offer services like reading/writing, content summary, voice-to-text, code editing and more. -With Google pioneering responsible AI, we're committed to bringing the [best of our products and solutions](https://developers.generativeai.google/) to web developers so they can deliver cutting-edge AI experiences to their users without needing to be a machine learning expert. And, by championing APIs like [WebGPU](/blog/webgpu-release/), we are enabling developers to bring their own machine learning models to the web at high speeds. +With Google pioneering responsible AI, we're committed to bringing the [best of our products and solutions](https://developers.generativeai.google/) to web developers so they can deliver cutting-edge AI experiences to their users without needing to be a machine learning expert. And, by championing APIs like [WebGPU](/blog/webgpu-release/), we are enabling developers to bring their own machine learning models to the web at high speeds. -### Solutions to significantly enhance developer productivity +### Solutions to significantly enhance developer productivity -To usher in a more helpful web, it's important to center developers' needs in our work. We want to meet developers where they are—right in their workflows and taking their stack choices into account. -In 2020, we launched [Core Web Vitals](web.dev/web-vitals) that have proven to be a key tool in measuring page quality over the years. With tools like [Chrome DevTools](/docs/devtools/) and [Lighthouse](/docs/lighthouse/overview/#devtools), we made it easier for developers to find opportunities to improve their Web Vitals, right in their workflow. +To usher in a more helpful web, it's important to center developers' needs in our work. We want to meet developers where they are—right in their workflows and taking their stack choices into account. +In 2020, we launched [Core Web Vitals](web.dev/web-vitals) that have proven to be a key tool in measuring page quality over the years. With tools like [Chrome DevTools](/docs/devtools/) and [Lighthouse](/docs/lighthouse/overview/#devtools), we made it easier for developers to find opportunities to improve their Web Vitals, right in their workflow. -We also kicked off [Project Aurora](/aurora/) two years ago, which was an important collaboration between the Chrome team and open source frameworks to bring Core Web Vitals improvements directly to the tools that developers use the most. To help developers debug the code they write and not what gets compiled due to the framework, we launched the [Modern Web Debugging](/blog/devtools-modern-web-debugging/) initiative that has already built in support for many frameworks in Chrome DevTools. +We also kicked off [Project Aurora](/aurora/) two years ago, which was an important collaboration between the Chrome team and open source frameworks to bring Core Web Vitals improvements directly to the tools that developers use the most. To help developers debug the code they write and not what gets compiled due to the framework, we launched the [Modern Web Debugging](/blog/devtools-modern-web-debugging/) initiative that has already built in support for many frameworks in Chrome DevTools. Finally, cross-browser testing and automation is yet another challenge that developers have to tackle. To this end, we launched [Chrome for Testing](/blog/chrome-for-testing/), ensuring developers access to reliable downloads for browser automation. At the ecosystem level, we're actively working with all major browsers on [WebDriver BiDi](/blog/webdriver-bidi-2023/), a new standard that combines the best of the WebDriver Classic and the Chrome DevTools Protocol to make cross-browser automation significantly better for developers. ## Partnering to safeguard the openness of the web -We recognize that an open and thriving web helps drive more innovation. However, we also know that keeping up with platform changes and the inconsistency of features support across browsers remains one of the [top challenges](https://mdn.dev/archives/insights/reports/mdn-web-developer-needs-assessment-2020.html#needs-assessment-ranking-of-all-needs) for developers. -Over the past few years, we've been working in earnest to address this problem. We started with our collaboration on the [MDN DNA Study](https://web.dev/interop-2022/#it-all-started-in-2019) back in 2019–20, which resulted in the [Compat 2021](https://web.dev/compat2021/) initiative. This is now known as Interop, and continues to deliver positive results for the web, including landing much loved features like [Cascade layers](https://web.dev/interop-2022-wrapup/#cascade-layers) and [Container queries](https://web.dev/cq-stable/). And most recently, we've been working closely with the [WebDX Community Group](https://www.w3.org/community/webdx/) and other browser vendors to simplify updates to the web with [Baseline](web.dev/baseline). +We recognize that an open and thriving web helps drive more innovation. However, we also know that keeping up with platform changes and the inconsistency of features support across browsers remains one of the [top challenges](https://mdn.dev/archives/insights/reports/mdn-web-developer-needs-assessment-2020.html#needs-assessment-ranking-of-all-needs) for developers. +Over the past few years, we've been working in earnest to address this problem. We started with our collaboration on the [MDN DNA Study](https://web.dev/articles/interop-2022#it_all_started_in_2019) back in 2019–20, which resulted in the [Compat 2021](https://web.dev/blog/compat2021) initiative. This is now known as Interop, and continues to deliver positive results for the web, including landing much loved features like [Cascade layers](https://web.dev/articles/interop-2022-wrapup#cascade_layers) and [Container queries](https://web.dev/articles/cq-stable). And most recently, we've been working closely with the [WebDX Community Group](https://www.w3.org/community/webdx/) and other browser vendors to simplify updates to the web with [Baseline](web.dev/baseline). -Over the years, we've actively [contributed to](https://blog.chromium.org/2017/10/building-unified-documentation-for-web.html) and [collaborated on](https://web.dev/open-web-docs/) many initiatives with ecosystem partners to build [an open, stable web](https://io.google/2023/program/528a223c-a3d6-46c5-84e4-88af2cf62670/). This work will continue as we move the platform forward. +Over the years, we've actively [contributed to](https://blog.chromium.org/2017/10/building-unified-documentation-for-web.html) and [collaborated on](https://web.dev/articles/open-web-docs) many initiatives with ecosystem partners to build [an open, stable web](https://io.google/2023/program/528a223c-a3d6-46c5-84e4-88af2cf62670/). This work will continue as we move the platform forward. Reflecting back at our journey so far, we find ourselves marveling at the progress the web has made, and the prospect of what's next for Chrome and the web gives us a tingle of excitement. As we continue to play our role in the web ecosystem, we are more motivated than ever to be a trusted, helpful partner in building a powerful web that is made easier for developers. We are _Chrome for Developers_. diff --git a/site/en/blog/web-animations-resources/index.md b/site/en/blog/web-animations-resources/index.md index e4045108d..c71184c2f 100644 --- a/site/en/blog/web-animations-resources/index.md +++ b/site/en/blog/web-animations-resources/index.md @@ -28,7 +28,7 @@ It's [also natively available](http://caniuse.com/#feat=web-animation) in Opera, This is a powerful primitive that deserves a place in your toolbox. {% Aside %} -For a primer on the different approaches to animation on the web, including Web Animations, check out [Modern Animation Fundamentals on YouTube](https://www.youtube.com/watch?v=WaNoqBAp8NI) and [Animations on web.dev](https://web.dev/animations/). +For a primer on the different approaches to animation on the web, including Web Animations, check out [Modern Animation Fundamentals on YouTube](https://www.youtube.com/watch?v=WaNoqBAp8NI) and [Animations on web.dev](https://web.dev/explore/animations). {% endAside%} ## Codelabs diff --git a/site/en/blog/web-custom-formats-for-the-async-clipboard-api/index.md b/site/en/blog/web-custom-formats-for-the-async-clipboard-api/index.md index bd60e915e..5a26d09e9 100644 --- a/site/en/blog/web-custom-formats-for-the-async-clipboard-api/index.md +++ b/site/en/blog/web-custom-formats-for-the-async-clipboard-api/index.md @@ -18,7 +18,7 @@ tags: - capabilities --- -Until now, the [Async Clipboard API](https://web.dev/async-clipboard/) supported a limited set of +Until now, the [Async Clipboard API](https://web.dev/articles/async-clipboard) supported a limited set of MIME types to be copied to and pasted from the system clipboard, specifically: `text/plain`, `text/html`, and `image/png`. The browser typically sanitizes this to, for example, remove embedded `script` elements or `javascript:` links from an HTML string, or to prevent PNG diff --git a/site/en/blog/web-push-encryption/index.md b/site/en/blog/web-push-encryption/index.md index ad073cb22..7fc0936d1 100644 --- a/site/en/blog/web-push-encryption/index.md +++ b/site/en/blog/web-push-encryption/index.md @@ -37,7 +37,7 @@ in transit. ## Client-side changes If you have already -[implemented push notifications without payloads](https://web.dev/notifications/) +[implemented push notifications without payloads](https://web.dev/articles/notifications) then there are only two small changes that you need to make on the client-side. This first is that when you send the subscription information to your backend diff --git a/site/en/blog/webauthn-conditional-ui/index.md b/site/en/blog/webauthn-conditional-ui/index.md index a32ff1c09..86b3f87c7 100644 --- a/site/en/blog/webauthn-conditional-ui/index.md +++ b/site/en/blog/webauthn-conditional-ui/index.md @@ -38,9 +38,9 @@ provide the same experience for both password and passkey users. ## Conditional UI -Allowing websites to make a WebAuthn request without triggering the modal UI is -called "conditional mediation". This autofill integration is often referred to -as a [conditional +Allowing websites to make a WebAuthn request without triggering the modal UI is +called "conditional mediation". This autofill integration is often referred to +as a [conditional UI](https://github.com/w3c/webauthn/wiki/Explainer:-WebAuthn-Conditional-UI). <figure class="screenshot" style="max-width:300px; margin:auto;"> @@ -62,8 +62,8 @@ passkeys](https://developers.google.com/identity/passkeys#security-consideration ### How to use conditional UI -To use the WebAuthn conditional UI, learn how to [Create a passkey for -passwordless logins](https://web.dev/passkey-registration/) and [Sign in with a -passkey through form autofill](https://web.dev/passkey-form-autofill/). +To use the WebAuthn conditional UI, learn how to [Create a passkey for +passwordless logins](https://web.dev/articles/passkey-registration) and [Sign in with a +passkey through form autofill](https://web.dev/articles/passkey-form-autofill). Photo by <a href="https://unsplash.com/@homajob?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Scott Graham</a> on <a href="https://unsplash.com/s/photos/form?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Unsplash</a> diff --git a/site/en/blog/whats-new-css-ui-2023/index.md b/site/en/blog/whats-new-css-ui-2023/index.md index bc6e0566c..110324bbf 100644 --- a/site/en/blog/whats-new-css-ui-2023/index.md +++ b/site/en/blog/whats-new-css-ui-2023/index.md @@ -110,7 +110,7 @@ You can learn more and see more demos in our [blog post on style queries](/blog/ {% BrowserCompat 'css.selectors.has' %} -Speaking of powerful, dynamic features, the [:has() selector](/blog/has-m105/) is one of the most powerful new CSS capabilities landing in modern browsers. With `:has()`, you can apply styles by checking to see if a parent element contains the presence of specific children, or if those children are in a specific state. This means, we essentially now have a parent selector. +Speaking of powerful, dynamic features, the [:has() selector](/blog/has-m105/) is one of the most powerful new CSS capabilities landing in modern browsers. With `:has()`, you can apply styles by checking to see if a parent element contains the presence of specific children, or if those children are in a specific state. This means, we essentially now have a parent selector. Building on the container query example, you can use `:has()` to make the components even more dynamic. In it, an item with a "star" element gets a gray background applied to it, and an item with a checked checkbox a blue background. @@ -145,7 +145,7 @@ Explore this feature further in our [article on nth-of syntax](/articles/css-nth <!-- {% BrowserCompat 'css.??' %} --> -Selectors and style queries aren’t the only places that we can embed logic within our styles; typography is another one. From Chrome 114, you can use text-wrap balancing for headings, using the `text-wrap` property with the value `balance`. +Selectors and style queries aren’t the only places that we can embed logic within our styles; typography is another one. From Chrome 114, you can use text-wrap balancing for headings, using the `text-wrap` property with the value `balance`. <figure> {% Video @@ -182,7 +182,7 @@ To balance the text, the browser effectively performs a binary search for the sm </figure> {% Aside %} -While this is a great progressive enhancement you can try out today, it’s important to note that this API works only up to 4 lines of text, so it’s great for titles and headlines, but likely not what you’re looking for with longer pieces of content. +While this is a great progressive enhancement you can try out today, it’s important to note that this API works only up to 4 lines of text, so it’s great for titles and headlines, but likely not what you’re looking for with longer pieces of content. {% endAside %} Learn more about it in [this article](/blog/css-text-wrap-balance/). @@ -215,7 +215,7 @@ The letter’s block-offset, or “sink”, for where the letter will sit. Learn more about using `intial-letter` [here](/blog/control-your-drop-caps-with-css-initial-letter/). -### Dynamic viewport units +### Dynamic viewport units {% BrowserCompat 'css.types.length.viewport_percentage_units_large' %} @@ -223,21 +223,21 @@ One common problem web developers face today is accurate and consistent full-vie {% Img src="image/HodOHWjMnbNw56hvNASHWSgZyAf2/uhcpJi4cZjgCoyPc9hiF.png", alt="Showing too many scrollbars", width="800", height="488" %} -To resolve this issue, we now have new unit values on the web platform, including: +To resolve this issue, we now have new unit values on the web platform, including: - Small viewport height and width (or `svh` and `svw`), which represent the smallest active viewport size. -- Large viewport height and width (`lvh` and `lvw`), which represent the largest size. +- Large viewport height and width (`lvh` and `lvw`), which represent the largest size. - Dynamic viewport height and width (`dvh` and `dvw`). Dynamic viewport units change in value when the additional dynamic browser toolbars, such as the address at the top or tab bar at the bottom, are visible and when they are not. {% Img src="image/HodOHWjMnbNw56hvNASHWSgZyAf2/nJ8JpRlThr7O631TWmu8.png", alt="New viewport units visualized", width="800", height="315" %} -{% Aside %} -Note that the dynamic viewport units do not take the presence of the Virtual Keyboard into account. From Chrome 108 you can [set a meta-tag to change this behavior](/blog/viewport-resize-behavior/#opting-in-to-a-different-behavior). +{% Aside %} +Note that the dynamic viewport units do not take the presence of the Virtual Keyboard into account. From Chrome 108 you can [set a meta-tag to change this behavior](/blog/viewport-resize-behavior/#opting-in-to-a-different-behavior). {% endAside %} -For more information about these new units, read [The large, small, and dynamic viewport units](https://web.dev/viewport-units/). +For more information about these new units, read [The large, small, and dynamic viewport units](https://web.dev/articles/viewport-units). ### Wide-gamut color spaces @@ -341,12 +341,12 @@ CSS nesting, something folks love from Sass, and one of the top CSS developer re /* can be done with nesting like */ .card { &:hover { - + } } ``` -You can also nest [Media Queries](/learn/design/media-queries/), which also means you can nest [Container Queries](https://web.dev/cq-stable/). In the following example, a card is changed from a portrait layout to a landscape layout if there's enough width in it's container: +You can also nest [Media Queries](/learn/design/media-queries/), which also means you can nest [Container Queries](https://web.dev/articles/cq-stable). In the following example, a card is changed from a portrait layout to a landscape layout if there's enough width in it's container: ```css .card { @@ -363,13 +363,13 @@ The layout adjustment to `flex` occurs when the container has more (or equal to) For more information and examples, check out our post on [CSS nesting](/articles/css-nesting/). -### Cascade layers +### Cascade layers {% BrowserCompat 'css.at-rules.layer' %} Another developer pain point we’ve identified is ensuring consistency in which styles win over others, and one part of resolving this is having better control over the CSS cascade. -[Cascade layers](/blog/cascade-layers/) solve this by giving users control over which layers have a higher precedence than others, meaning more fine-tuned control of when your styles are applied. +[Cascade layers](/blog/cascade-layers/) solve this by giving users control over which layers have a higher precedence than others, meaning more fine-tuned control of when your styles are applied. {% Img src="image/HodOHWjMnbNw56hvNASHWSgZyAf2/jH8ydtcwmHg4rHTfqvRU.png", alt="Cascade Illustration", width="800", height="393" %} @@ -381,18 +381,18 @@ Another developer pain point we’ve identified is ensuring consistency in which Learn more about how to use cascade layers [in this article](/blog/cascade-layers/). -### Scoped CSS +### Scoped CSS {% BrowserCompat 'css.at-rules.scope' %} -CSS scoped styles allow developers to specify the boundaries for which specific styles apply, essentially creating native namespacing in CSS. Before, developers relied on 3rd party scripting to rename classes, or specific naming conventions to prevent style collision, but soon, you can use `@scope`. +CSS scoped styles allow developers to specify the boundaries for which specific styles apply, essentially creating native namespacing in CSS. Before, developers relied on 3rd party scripting to rename classes, or specific naming conventions to prevent style collision, but soon, you can use `@scope`. Here, we’re scoping a `.title` element to a `.card`. This would prevent that title element from conflicting with any other `.title` elements on the page, like a blog post title or other heading. ```css @scope (.card) { - .title { + .title { font-weight: bold; } } @@ -416,9 +416,9 @@ In the demo below, the dots revolve around a central point. Instead of rotating {% Codepen { user: 'web-dot-dev', id: 'ExePgOg', height: 600, theme: 'dark', tab: 'result' } %} -See our [article on trigonometric functions](https://web.dev/css-trig-functions/) for more detailed information on this topic. +See our [article on trigonometric functions](https://web.dev/articles/css-trig-functions) for more detailed information on this topic. -### Individual transform properties +### Individual transform properties {% BrowserCompat 'css.properties.translate' %} @@ -452,7 +452,7 @@ Now, you can have all of this detail in your CSS animations by separating the ty With this, changes in translation, rotation, or scale can happen simultaneously at different rates of change in different times during the animation. -See this [post on individual transform functions](https://web.dev/css-individual-transform-properties/) for more information. +See this [post on individual transform functions](https://web.dev/articles/css-individual-transform-properties) for more information. ## Customizable Components To make sure we’re resolving some of the key developer needs through the web platform, we’re working with the [OpenUI community group](http://open-ui.com/) and have identified three solutions to start with: @@ -480,7 +480,7 @@ The DOM structure for popover is declarative and can be written as clearly as gi <!-- Popover content goes in here -–> </div> -<button popovertarget="event-popup">Create New Event</button> +<button popovertarget="event-popup">Create New Event</button> ``` `popover` is a shorthand for `popover=auto`. An element with `popover=auto` will force-close other popovers when opened, receive focus when opened, and can light-dismiss. Conversely, `popover=manual` elements do not force-close any other element type, do not receive focus immediately, and do not light-dismiss. They close via a toggle or other close action. @@ -488,7 +488,7 @@ The DOM structure for popover is declarative and can be written as clearly as gi {% Codepen { user: 'web-dot-dev', id: 'mdzpGwq', height: 400, tab: 'result' } %} -{% Video +{% Video src="video/HodOHWjMnbNw56hvNASHWSgZyAf2/cgHE50lFjDLze9JSeHtH.mp4", autoplay="true", loop="true", muted="true", @@ -507,7 +507,7 @@ But what happens if the popover doesn’t fit in the viewport based on the way y {% Img src="image/HodOHWjMnbNw56hvNASHWSgZyAf2/wlIsaOjCC0lVKzMp2fCF.png", alt="popover popping out of viewport", width="800", height="544" %} -To solve for this, the anchor positioning API includes fallback positions that you can customize. The following example creates a fallback position called "top-then-bottom". The browser will first try to position the tooltip at the top, and if that doesn’t fit in the viewport, the browser would then position it under the anchoring element, on the bottom. +To solve for this, the anchor positioning API includes fallback positions that you can customize. The following example creates a fallback position called "top-then-bottom". The browser will first try to position the tooltip at the top, and if that doesn’t fit in the viewport, the browser would then position it under the anchoring element, on the bottom. ```css .center-tooltip { @@ -528,7 +528,7 @@ To solve for this, the anchor positioning API includes fallback positions that y } ``` -{% Video +{% Video src="video/HodOHWjMnbNw56hvNASHWSgZyAf2/yZCqhUqmqci63y9V7EFU.mp4", autoplay="true", loop="true", muted="true", @@ -550,7 +550,7 @@ Learn more about anchor positioning [in this blog post](/blog/tether-elements-to ### `<selectmenu>` -With both popover and anchor positioning, you can build fully customizable selectmenus. The OpenUI community group has been investigating the fundamental structure of these menus and looking for ways to allow for the customization of any content within them. Take these visual examples: +With both popover and anchor positioning, you can build fully customizable selectmenus. The OpenUI community group has been investigating the fundamental structure of these menus and looking for ways to allow for the customization of any content within them. Take these visual examples: {% Img src="image/HodOHWjMnbNw56hvNASHWSgZyAf2/4QPcUaz8AXxtwmMNM8J1.png", alt="Examples of selectmenus", width="800", height="458" %} @@ -605,16 +605,16 @@ The following popover demo, animates popovers in and out using `:popover-open` f transform: translateY(20px); opacity: 0; } - + /* 1. open (changed) state */ transform: translateY(0); opacity: 1; } - + /* 2. After-change state */ transform: translateY(-50px); opacity: 0; - + /* enumarate transitioning properties, including display */ transition: transform 0.5s, opacity 0.5s, display 0.5s; } @@ -637,7 +637,7 @@ Which brings us to interactions, the last stop on this tour of web UI features. We already talked about animating discrete properties, but there are also some really exciting APIs landing in Chrome around scroll-driven animations and view transitions -### Scroll-driven animations +### Scroll-driven animations {% BrowserCompat 'css.properties.animation-timeline' %} @@ -654,7 +654,7 @@ These new APIs work in conjunction with existing Web Animations and CSS Animatio For an extensive in-depth guide to how to create these scroll-driven animations, please refer to [this article on scroll-driven animations](/articles/scroll-driven-animations). -### View transitions +### View transitions {% BrowserCompat 'css.properties.view-transition-name' %} diff --git a/site/en/blog/whats-new-in-web-on-android-io2023/index.md b/site/en/blog/whats-new-in-web-on-android-io2023/index.md index b590fc431..2b89c3034 100644 --- a/site/en/blog/whats-new-in-web-on-android-io2023/index.md +++ b/site/en/blog/whats-new-in-web-on-android-io2023/index.md @@ -15,10 +15,10 @@ thumbnail: image/6hHqS5auVgWhN0cQNQztaJx5w4M2/FC4a4vxoHf1XTuMYCvrc.jpg alt: '' --- -There are many reasons for developers to [bring the web to Android](https://developer.android.com/develop/ui/views/layout/webapps): maybe reusing a web widget in an Android app, incorporating first-party or third-party content, even bringing their entire web app to the platform. Whatever the use case, Android has many tools to make it possible. +There are many reasons for developers to [bring the web to Android](https://developer.android.com/develop/ui/views/layout/webapps): maybe reusing a web widget in an Android app, incorporating first-party or third-party content, even bringing their entire web app to the platform. Whatever the use case, Android has many tools to make it possible. Here are the latest updates to these tools. For example: -* Privacy improvements and better support for large screens, such as support for image drag and drop in [WebView](#web-view). +* Privacy improvements and better support for large screens, such as support for image drag and drop in [WebView](#web-view). * [Custom Tabs](#custom-tabs) now supports partial custom tabs. * Integrated features for [PWA](#pwa), like Richer Install UI and Play billing API in [Trusted Web Activities](#twa). @@ -30,7 +30,7 @@ WebView is the most commonly used way to embed web content into Android apps, as ### X-Requested-With header{: #x-requested-with} Let’s start with privacy and the [X-Requested-With header deprecation](https://android-developers.googleblog.com/2023/02/improving-user-privacy-by-requiring-opt-in-to-send-x-requested-wih-header-from-webview.html). When a user installs and runs an application that uses a WebView to embed web content, the WebView will add the X-Requested-With header to every request sent to servers. The value of this header is the application's APK name. This means every request includes specific information about the context in which the user is consuming web content, and leaks the identity of the app to the online service. To protect user privacy, the WebView team started a deprecation trial which removes this header from all WebView requests. -But what if your app relies on X-Requested-With header? Our recommended method is to use the [new opt-in API](https://developer.android.com/jetpack/androidx/releases/webkit#1.6.0-alpha03) that enables you to selectively send the request header to specific origins. This means you get the best of both worlds: you can continue to support existing features built on top of this header, while making sure that the user’s privacy is preserved in all other cases. If you want to keep the existing behavior, you can also sign up for the [X-Requested-With Deprecation](/origintrials/#/view_trial/1390486384950640641) origin trial. +But what if your app relies on X-Requested-With header? Our recommended method is to use the [new opt-in API](https://developer.android.com/jetpack/androidx/releases/webkit#1.6.0-alpha03) that enables you to selectively send the request header to specific origins. This means you get the best of both worlds: you can continue to support existing features built on top of this header, while making sure that the user’s privacy is preserved in all other cases. If you want to keep the existing behavior, you can also sign up for the [X-Requested-With Deprecation](/origintrials/#/view_trial/1390486384950640641) origin trial. ```java WebSettingsCompat.setRequestedWithHeaderOriginAllowList( @@ -41,14 +41,14 @@ WebSettingsCompat.setRequestedWithHeaderOriginAllowList( ### WebView testing{: #webview-testing} The next topic is testing. If you are a web developer, and your websites receive a lot traffic from WebViews, there are two updates for you: -1. WebView now supports [Chrome origin trials](/docs/web-platform/origin-trials/). Origin trials give you access to new or experimental features in Chrome. You can use these to try out a new feature before the feature is made available to everyone. Until now, origin trials have only been available on desktop and mobile Chrome, but starting with Chrome M110, origin trials also work in WebView. +1. WebView now supports [Chrome origin trials](/docs/web-platform/origin-trials/). Origin trials give you access to new or experimental features in Chrome. You can use these to try out a new feature before the feature is made available to everyone. Until now, origin trials have only been available on desktop and mobile Chrome, but starting with Chrome M110, origin trials also work in WebView. 2. It is now much easier to install WebView Beta. We highly recommend testing your website using the WebView Beta channel to make sure that your website works well in upcoming WebView versions. To do this, join the [WebView Beta testing program on the Google Play Store](https://play.google.com/apps/testing/com.google.android.webview), and your device will automatically be enrolled. {% Img src="image/6hHqS5auVgWhN0cQNQztaJx5w4M2/63KraC4Xb1iOtm0hpcm3.png", alt="Screenshot of the website for joining the WebView beta program.", width="393", height="851" %} ### Large screen device support{: #large-screen-device} -Our goal is to make WebView work well on large screen devices. One step in this direction is that WebView now supports image drag and drop. For example, in split screen view mode, you can drag an image from a WebView into a different app. +Our goal is to make WebView work well on large screen devices. One step in this direction is that WebView now supports image drag and drop. For example, in split screen view mode, you can drag an image from a WebView into a different app. {% Video src="video/6hHqS5auVgWhN0cQNQztaJx5w4M2/HMPM2vSc16CupdVuxGH9.mp4", width="800", height="500", autoplay="true", loop="true" %} @@ -73,7 +73,7 @@ Sometimes you might need to run JavaScript in your app without having to display ListenableFuture<JavaScriptSandbox> jsSandboxFuture = JavaScriptSandbox.createConnectedInstanceAsync(JavaScriptEngineActivity.this); JavaScriptIsolate jsIsolate = jsSandboxFuture.get().createIsolate(); -final String code = +final String code = "function sum(a, b) { let r = a + b; return r.toString(); }; sum(3, 4)"; ListenableFuture<String> resultFuture = jsIsolate.evaluateJavaScriptAsync(code); … @@ -83,20 +83,20 @@ ListenableFuture<String> resultFuture = jsIsolate.evaluateJavaScriptAsync(code); {% Img src="image/6hHqS5auVgWhN0cQNQztaJx5w4M2/cRV98kXB7fYtITSTCmlM.png", alt="Android Custom Tab with the default styling.", width="400", height="866" %} -WebView is great for integrating Web UI into your app. But what about letting users browse web content in your app? +WebView is great for integrating Web UI into your app. But what about letting users browse web content in your app? This is a great use case for Custom Tabs. They are a secure and user-friendly way to let users view web content in your app. Their big advantage is that users don't need to re-log in to their favorite websites. This is because they are an instance of the user's default browser and cookies being shared, and they offer all web platform features and APIs supported by the browser powering it. -This also means that if your default browser is Chrome, a custom tab is opened in Chrome; if your default browser is Firefox, a Custom Tab will be opened in Firefox. Most of the major browsers on Android support Custom Tabs, and if the default browser does not support Custom Tabs, the browser app will open instead. +This also means that if your default browser is Chrome, a custom tab is opened in Chrome; if your default browser is Firefox, a Custom Tab will be opened in Firefox. Most of the major browsers on Android support Custom Tabs, and if the default browser does not support Custom Tabs, the browser app will open instead. -What’s great about Custom Tabs is that you can style them to match the look and feel of your app, add custom interactivity via actions, and your own toolbars. +What’s great about Custom Tabs is that you can style them to match the look and feel of your app, add custom interactivity via actions, and your own toolbars. {% Img src="image/6hHqS5auVgWhN0cQNQztaJx5w4M2/th39X3MtXNrt8JfLV6J3.png", alt="Android Custom Tab with custom color theme and toolbars.", width="400", height="866" %} ### Partial Custom Tabs{: #partial-custom-tabs} Custom Tab customizations got a major upgrade with support for [Partial Custom Tabs](/docs/android/custom-tabs/integration-guide/#specify-the-launch-height-of-a-custom-tab). They let users multi-task between apps and the web. Until now, when using Custom Tabs, the browser tab overlay would cover the whole screen. Now you can control the height of the Custom Tab overlay. This way, users can interact with your app and web content at the same time. If your user’s browser does not support Partial Custom Tabs, the user will simply see the supported full-screen Custom Tab. -All you need to do is to connect to the Custom Tabs Service, pass the session to the CustomTabsBuilder, and call setActivityHeight. +All you need to do is to connect to the Custom Tabs Service, pass the session to the CustomTabsBuilder, and call setActivityHeight. ```java CustomTabsSession customTabsSession; @@ -112,7 +112,7 @@ CustomTabsIntent customTabsIntent = new CustomTabsIntent.Builder(customTabsSessi customTabsIntent.launchUrl(context, Uri.parse(url)) ``` -YouTube successfully launched resizable inline Custom Tabs on direct response ads. This way, they’ve been able to implement a new way of interacting with ads and web content without interrupting the organic experience on the app. +YouTube successfully launched resizable inline Custom Tabs on direct response ads. This way, they’ve been able to implement a new way of interacting with ads and web content without interrupting the organic experience on the app. {% Img src="image/6hHqS5auVgWhN0cQNQztaJx5w4M2/9uaSzKcUuo3Z6gNoGpfe.gif", alt="YouTube DirectResponse Ad experience using Partial Custom Tabs.", width="400", height="868" %} @@ -123,14 +123,14 @@ But what about tablets and other large screen devices? The Chrome team is curren ### Measuring engagement signals{: #ct-engagement-signals} The second big update to Custom Tabs is measuring session-specific user engagement. If your app regularly shows content to your users including links, for example, in a news feed, wouldn’t it be great if you could tell which links a user finds valuable and which not? This information can be really helpful when it comes to prioritizing which links to show to your users. -The Chrome team added session-specific metric visibility to Chrome Custom Tabs. In addition to how long a user stays on a page, you can now also get visibility into scroll distance, scroll direction, and overall engagement with web content. +The Chrome team added session-specific metric visibility to Chrome Custom Tabs. In addition to how long a user stays on a page, you can now also get visibility into scroll distance, scroll direction, and overall engagement with web content. Engagement signals are available starting with Chrome 114 and require the `androidx.browser:browser:1.6.0-alpha01` support library or higher. To learn more, check out the engagement signals getting started guide. ## PWA {: #pwa} -There also are updates in PWA— a set of technologies that make it possible to create app-like experiences, built and deployed on the web. +There also are updates in PWA— a set of technologies that make it possible to create app-like experiences, built and deployed on the web. -Using PWA on Android, your web app could be installable: it will live along the other platform apps, on the home screen, launcher, settings, and other surfaces. +Using PWA on Android, your web app could be installable: it will live along the other platform apps, on the home screen, launcher, settings, and other surfaces. PWA features are built based on web standards; they focus on cross-platform compatibility, giving developers the tools to build a web app once, and allowing users to install it on whichever device they choose. Building an installable web app doesn’t mean you can’t or shouldn’t have a native Android app, but it is another option to bring the web to Android. @@ -146,21 +146,21 @@ Of course, the service worker API is still available to build custom offline exp Some other features that can bring a polished web app experience to Android include the [Richer Install UI](/blog/richer-install-ui-desktop/). By adding the fields `description` and `screenshots` to your web manifest, your users will get an install experience that is closer to what app stores show to describe your app. -We also have [shortcuts](https://web.dev/app-shortcuts/). By adding an array called `shortcuts` which describes a set of quick actions that your users frequently make in your app, they will be able to access these actions by long pressing on the app’s icon. +We also have [shortcuts](https://web.dev/articles/app-shortcuts). By adding an array called `shortcuts` which describes a set of quick actions that your users frequently make in your app, they will be able to access these actions by long pressing on the app’s icon. -Using [Web Share](https://web.dev/web-share/) and [Web Share Target](/articles/web-share-target/) APIs, your app can interact with other apps, like any other platform app. Your app will be an option in the sharing sheets, and can share and receive photos, texts, and other files. +Using [Web Share](https://web.dev/articles/web-share) and [Web Share Target](/articles/web-share-target/) APIs, your app can interact with other apps, like any other platform app. Your app will be an option in the sharing sheets, and can share and receive photos, texts, and other files. You can check out the I/O talk “The Web: Your platform for growth” for more information on how businesses are leveraging these technologies. ## Trusted Web Activity{: #twa} -Another way to bring the web to Android is using [Trusted Web Activity (TWA)](/docs/android/trusted-web-activity/). +Another way to bring the web to Android is using [Trusted Web Activity (TWA)](/docs/android/trusted-web-activity/). TWA is the best way to display full screen first-party web content in your app. It is the ideal solution for developers who want to wrap their web app as an Android application, or use their website as part of one. -Note that TWA sounds like it is strictly related to PWA, but it is not. Yes, by using TWA you can publish your installable web app to Google Play, but you could also build a single activity on the web and include it on your Android app. +Note that TWA sounds like it is strictly related to PWA, but it is not. Yes, by using TWA you can publish your installable web app to Google Play, but you could also build a single activity on the web and include it on your Android app. -A Trusted Web Activity is rendered by the user’s browser in exactly the same way as a user would see it in their browser, except they are run full screen and do not display a URL bar. This means that they support all web platform features and APIs supported by the browser powering it. +A Trusted Web Activity is rendered by the user’s browser in exactly the same way as a user would see it in their browser, except they are run full screen and do not display a URL bar. This means that they support all web platform features and APIs supported by the browser powering it. A couple of advantages of wrapping your web app using TWA are: @@ -172,6 +172,6 @@ Check [this article](https://www.thinkwithgoogle.com/intl/it-it/futuro-del-marke ## Conclusion -As you’ve seen, there are many different options available for embedding web content into your app and all these options are continuously being improved. +As you’ve seen, there are many different options available for embedding web content into your app and all these options are continuously being improved. diff --git a/site/en/docs/android/trusted-web-activity/play-billing/index.md b/site/en/docs/android/trusted-web-activity/play-billing/index.md index e17f834e0..b5c8da489 100644 --- a/site/en/docs/android/trusted-web-activity/play-billing/index.md +++ b/site/en/docs/android/trusted-web-activity/play-billing/index.md @@ -131,5 +131,5 @@ application in production. [8]: https://developer.android.com/google/play/billing/terminology [9]: https://github.com/GoogleChromeLabs/bubblewrap [10]: https://github.com/GoogleChromeLabs/bubblewrap/issues/376 -[11]: https://web.dev/origin-trials/ +[11]: https://developer.chrome.com/docs/web-platform/origin-trials/ diff --git a/site/en/docs/android/trusted-web-activity/receive-payments-play-billing/index.md b/site/en/docs/android/trusted-web-activity/receive-payments-play-billing/index.md index a47816bf6..1207ca661 100644 --- a/site/en/docs/android/trusted-web-activity/receive-payments-play-billing/index.md +++ b/site/en/docs/android/trusted-web-activity/receive-payments-play-billing/index.md @@ -107,7 +107,7 @@ if ('getDigitalGoodsService' in window) { const service = await window.getDigitalGoodsService('https://play.google.com/billing'); // Google Play Billing is supported! - + } catch (error) { // Google Play Billing is not available. Use another payment flow. return; @@ -296,7 +296,7 @@ const service = const existingPurchases = await service.listPurchases(); for (const p of existingPurchases) { await verifyOrAcknowledgePurchaseOnBackend(p.purchaseToken, p.itemId); - + // Update the UI with items the user is already entitled to. console.log(`Users has entitlement for ${p.itemId}`); } @@ -352,7 +352,7 @@ by the Digital Goods API, and server-side components. [2]: /docs/android/trusted-web-activity/ [3]: https://developers.google.com/web/fundamentals/payments [4]: https://github.com/WICG/digital-goods/blob/master/explainer.md -[5]: https://web.dev/origin-trials/ +[5]: https://developer.chrome.com/docs/web-platform/origin-trials/ [6]: https://github.com/WICG/digital-goods/issues [7]: https://developer.android.com/distribute/best-practices/earn/in-app-purchases [8]: https://developer.android.com/distribute/best-practices/earn/subscriptions diff --git a/site/en/docs/crux/about/index.md b/site/en/docs/crux/about/index.md index b4f318f34..83f6bbd8d 100644 --- a/site/en/docs/crux/about/index.md +++ b/site/en/docs/crux/about/index.md @@ -37,7 +37,7 @@ tags: - crux --- -CrUX is the official dataset of the [Web Vitals](https://web.dev/vitals/) program. All user-centric Core Web Vitals metrics will be represented in the dataset. +CrUX is the official dataset of the [Web Vitals](https://web.dev/articles/vitals) program. All user-centric Core Web Vitals metrics will be represented in the dataset. CrUX data is collected from real browsers around the world, based on certain browser options which determine [user eligibility](/docs/crux/methodology/#user-eligibility). A set of [dimensions](/docs/crux/methodology/#dimensions) and [metrics](/docs/crux/methodology/#metrics) are collected which allow site owners to determine how users experience their sites. diff --git a/site/en/docs/crux/bigquery/index.md b/site/en/docs/crux/bigquery/index.md index 51d3333a2..01a128d13 100644 --- a/site/en/docs/crux/bigquery/index.md +++ b/site/en/docs/crux/bigquery/index.md @@ -164,7 +164,7 @@ Materialized tables are provided for easy access to summary data by a number of </tbody> </table></div> -This shows that in the 202204 dataset, 90.56% of real-user experiences on `https://example.com` met the criteria for [good LCP](https://web.dev/defining-core-web-vitals-thresholds/#refresher:-core-web-vitals-metrics-and-thresholds), and that the coarse 75th percentile LCP value was 1,600ms. This is slightly slower than previous months. +This shows that in the 202204 dataset, 90.56% of real-user experiences on `https://example.com` met the criteria for [good LCP](https://web.dev/articles/defining-core-web-vitals-thresholds#refresher:_core_web_vitals_metrics_and_thresholds), and that the coarse 75th percentile LCP value was 1,600ms. This is slightly slower than previous months. Four materialized tables are provided: diff --git a/site/en/docs/crux/dashboard/index.md b/site/en/docs/crux/dashboard/index.md index b00c3e0ae..eb21fe4d0 100644 --- a/site/en/docs/crux/dashboard/index.md +++ b/site/en/docs/crux/dashboard/index.md @@ -150,7 +150,7 @@ The monthly datasets are released on the second Tuesday of every month. For exam ### Core Web Vitals overview -The first page is an overview of the origin's monthly [Core Web Vitals](https://web.dev/vitals/) performance. These are the most important UX metrics that Google recommends you focus on. +The first page is an overview of the origin's monthly [Core Web Vitals](https://web.dev/articles/vitals) performance. These are the most important UX metrics that Google recommends you focus on. {% Img src="image/W3z1f5ZkBJSgL1V1IfloTIctbIF3/S9mRhx2J0LD2GQONzfqv.png", alt="CrUX Dashboard Core Web Vitals overview", width="800", height="918" %} @@ -164,7 +164,7 @@ After the Core Web Vitals page, you'll find standalone pages for all [metrics](/ Atop each page is the **Device** filter, which you can use to restrict the form factors included in the experience data. For example, you can drill down specifically into phone experiences. This setting persists across pages. -The primary visualizations on these pages are the monthly distributions of experiences categorized as "Good", "Needs Improvement", and "Poor". The color-coded legend below the chart indicates the range of experiences included in the category. For example, in the screenshot above, you can see the percent of "good" [Largest Contentful Paint](https://web.dev/lcp/#what-is-a-good-lcp-score) (LCP) experiences fluctuating slightly and getting slightly worse in recent months. +The primary visualizations on these pages are the monthly distributions of experiences categorized as "Good", "Needs Improvement", and "Poor". The color-coded legend below the chart indicates the range of experiences included in the category. For example, in the screenshot above, you can see the percent of "good" [Largest Contentful Paint](https://web.dev/articles/lcp#what_is_a_good_lcp_score) (LCP) experiences fluctuating slightly and getting slightly worse in recent months. The most recent month's percentages of "good" and "poor" experiences are shown above the chart along with an indicator of the percent difference from the previous month. For this origin, "good" LCP experiences fell by 0.8% to 83.25% month-over-month, the p75 number had 0 movement and stayed at 1,500 month-over-month, and the "poor" LCP experiences increased by 3.6% (shown in red as an increase here is bad) to 7.42%. Note the percentage movements are actual percentage movements, and not percentage point movements—for example 83.93% to 83.25% is a 0.68 percentage point movement, or 0.8% decrease of the 83.93% previous total. @@ -198,7 +198,7 @@ Similarly, the ECT distribution page shows you the breakdown of 4G, 3G, 2G, slow Effective connection types are considered _effective_ because they're based on bandwidth measurements on users' devices, and don't imply any particular technology used. For example, a desktop user on fast Wi-Fi may be labelled as 4G while a slower mobile connection might be labelled as 2G. {% endAside %} -The distributions for these dimensions are calculated using segments of the [First Contentful Paint](https://web.dev/fcp/) (FCP) histogram data. +The distributions for these dimensions are calculated using segments of the [First Contentful Paint](https://web.dev/articles/fcp) (FCP) histogram data. ## FAQ diff --git a/site/en/docs/crux/methodology/index.md b/site/en/docs/crux/methodology/index.md index 59bdcadbf..f6de9628d 100644 --- a/site/en/docs/crux/methodology/index.md +++ b/site/en/docs/crux/methodology/index.md @@ -70,7 +70,7 @@ An [**origin**](https://developer.mozilla.org/docs/Glossary/Origin) represents a 1. [Publicly discoverable](#discoverability-eligibility) 2. [Sufficiently popular](#popularity-eligibility) -You can verify that your origin is discoverable by running a [Lighthouse audit](https://pagespeed.web.dev/) and looking at the SEO category results. Your site is not discoverable if your root page fails the [_Page is blocked from indexing_](https://web.dev/is-crawable/) or [_Page has unsuccessful HTTP status code_](https://web.dev/http-status-code/) audits. +You can verify that your origin is discoverable by running a [Lighthouse audit](https://pagespeed.web.dev/) and looking at the SEO category results. Your site is not discoverable if your root page fails the [_Page is blocked from indexing_](https://web.dev/articles/is-crawable) or [_Page has unsuccessful HTTP status code_](https://web.dev/articles/http-status-code) audits. If an origin is determined to be publicly discoverable, eligible user experiences on _all_ of that origin's pages are aggregated at the origin-level, regardless of individual page discoverability. All of these experiences count towards the origin's popularity requirement. @@ -83,13 +83,13 @@ The requirements for a **page** to be included in the CrUX dataset are the same 1. [Publicly discoverable](#discoverability-eligibility) 2. [Sufficiently popular](#popularity-eligibility) -You can verify that a page is discoverable by running a [Lighthouse audit](https://pagespeed.web.dev/) and looking at the SEO category results. Your page is not discoverable if it fails the [_Page is blocked from indexing_](https://web.dev/is-crawable/) or [_Page has unsuccessful HTTP status code_](https://web.dev/http-status-code/) audits. +You can verify that a page is discoverable by running a [Lighthouse audit](https://pagespeed.web.dev/) and looking at the SEO category results. Your page is not discoverable if it fails the [_Page is blocked from indexing_](https://web.dev/articles/is-crawable) or [_Page has unsuccessful HTTP status code_](https://web.dev/articles/http-status-code) audits. Pages commonly have additional identifiers in their URL including query string parameters like `?utm_medium=email` and fragments like `#main`. These identifiers are stripped from the URL in the CrUX dataset so that all user experiences on the page are aggregated together. This is useful for pages that would otherwise not meet the popularity threshold if there were many disjointed URL variations for the same page. Note that in rare cases this may unexpectedly group experiences for distinct pages together; for example if parameters `?productID=101` and `?productID=102` represent different pages. Pages in CrUX are measured based on the top-level page. Pages included as iframes are not reported on separately in CrUX, but do contribute to the metrics of the top-level page. For example, if `https://www.example.com/page.html` embeds `https://www.example.com/frame.html` in an iframe, then `page.html` _will be_ represented in CrUX (subject to the other eligibility criteria) but `frame.html` _will not_. And if `frame.html` has poor [CLS](#cls-metric) then the CLS will be included when measuring the CLS for `page.html`. CrUX is the Chrome _User Experience_ Report and a user may not even be aware this is an iframe. Therefore, the experience is measured at the top level page—as per how the user sees this. -A website's architecture may complicate how its data is represented in CrUX. For example, single page apps (SPAs) may use a JavaScript-based _route transition_ scheme to move between pages, as opposed to traditional anchor-based page navigations. These transitions appear as new page views to the user, but to Chrome and the underlying platform APIs the entire experience is attributed to the initial page view. This is a limitation of the native web platform APIs on which CrUX is built, see [How SPA architectures affect Core Web Vitals](https://web.dev/vitals-spa-faq/) on web.dev for more information. +A website's architecture may complicate how its data is represented in CrUX. For example, single page apps (SPAs) may use a JavaScript-based _route transition_ scheme to move between pages, as opposed to traditional anchor-based page navigations. These transitions appear as new page views to the user, but to Chrome and the underlying platform APIs the entire experience is attributed to the initial page view. This is a limitation of the native web platform APIs on which CrUX is built, see [How SPA architectures affect Core Web Vitals](https://web.dev/articles/vitals-spa-faq) on web.dev for more information. ### User {: #user-eligibility} @@ -103,7 +103,7 @@ For a **user** to have their experiences aggregated in the CrUX dataset, they mu The current supported platforms are: - Desktop versions of Chrome including Windows, MacOS, ChromeOS, and Linux operating systems. -- Android versions of Chrome, including native apps using [Custom Tabs](/docs/android/custom-tabs/) and [WebAPKs](https://web.dev/webapks/). +- Android versions of Chrome, including native apps using [Custom Tabs](/docs/android/custom-tabs/) and [WebAPKs](https://web.dev/articles/webapks). There are a few notable exceptions that do not provide data to the CrUX dataset: @@ -226,7 +226,7 @@ The CrUX Dashboard does not support the country dimension, so all global data is The [CrUX API](/docs/crux/api/) provides programmatic access to CrUX data by page or origin, and can be further filtered by form factor, effective connection type and metrics. -The API provides [Web Vitals](https://web.dev/vitals/) metrics both by origin and at page-level and the data is updated daily. The only values provided for metrics are calculated from the previous 28 days as a rolling window. Historical data is available via the separate [History API](#tool-crux-history-api). +The API provides [Web Vitals](https://web.dev/articles/vitals) metrics both by origin and at page-level and the data is updated daily. The only values provided for metrics are calculated from the previous 28 days as a rolling window. Historical data is available via the separate [History API](#tool-crux-history-api). The CrUX API returns more quickly than the [PageSpeed Insights API](#tool-psi-api) but does not include the additional [Lighthouse data](https://developers.google.com/search/blog/2018/11/pagespeed-insights-now-powered-by) provided by PageSpeed Insights. @@ -236,7 +236,7 @@ The CrUX API returns more quickly than the [PageSpeed Insights API](#tool-psi-ap The [CrUX History API](/docs/crux/history-api/) provides programmatic access to CrUX historical data by page or origin, and can be further filtered by form factor, effective connection type and metrics. -The API provides [Web Vitals](https://web.dev/vitals/) metrics both by origin and at page-level and the data is updated weekly. The only values provided for metrics are calculated from the past 25 weekly collection periods of 28 days as a rolling window. +The API provides [Web Vitals](https://web.dev/articles/vitals) metrics both by origin and at page-level and the data is updated weekly. The only values provided for metrics are calculated from the past 25 weekly collection periods of 28 days as a rolling window. [Read more in the History API documentation](/docs/crux/history-api/). @@ -329,7 +329,7 @@ Most metrics are represented as a histogram aggregation, allowing visualization ### Interaction to Next Paint {: #inp-metric} {% Aside %} -"Interaction to Next Paint (INP) is a field metric that assesses [responsiveness](https://web.dev/user-centric-performance-metrics/#types-of-metrics). INP logs the latency of all interactions throughout the entire page lifecycle. The highest value of those interactions—or close to the highest for pages with many interactions—is recorded as the page's INP. A low INP ensures that the page will be reliably responsive at all times." +"Interaction to Next Paint (INP) is a field metric that assesses [responsiveness](https://web.dev/articles/user-centric-performance-metrics#types_of_metrics). INP logs the latency of all interactions throughout the entire page lifecycle. The highest value of those interactions—or close to the highest for pages with many interactions—is recorded as the page's INP. A low INP ensures that the page will be reliably responsive at all times." <cite><a href="https://web.dev/inp/">web.dev/inp/</a></cite> {% endAside %} diff --git a/site/en/docs/crux/release-notes/index.md b/site/en/docs/crux/release-notes/index.md index 79d64df30..b52665d78 100644 --- a/site/en/docs/crux/release-notes/index.md +++ b/site/en/docs/crux/release-notes/index.md @@ -57,8 +57,8 @@ What's new Notable stats : - 18,405,462 origins - : - 45.7% of origins have good [Core Web Vitals](https://web.dev/vitals/#core-web-vitals) - : - 42.1% of origins have good Core Web Vitals when [using INP in place of FID as will happen from March 2024](https://web.dev/inp-cwv/). + : - 45.7% of origins have good [Core Web Vitals](https://web.dev/articles/vitals#core_web_vitals) + : - 42.1% of origins have good Core Web Vitals when [using INP in place of FID as will happen from March 2024](https://web.dev/articles/inp-cwv). ## 202308 @@ -77,8 +77,8 @@ What's new Notable stats : - 18,263,523 origins - : - 45.3% of origins have good [Core Web Vitals](https://web.dev/vitals/#core-web-vitals) - : - 41.6% of origins have good Core Web Vitals when [using INP in place of FID as will happen from March 2024](https://web.dev/inp-cwv/). + : - 45.3% of origins have good [Core Web Vitals](https://web.dev/articles/vitals#core_web_vitals) + : - 41.6% of origins have good Core Web Vitals when [using INP in place of FID as will happen from March 2024](https://web.dev/articles/inp-cwv). ## 202307 @@ -93,7 +93,7 @@ What's new Notable stats : - 17,976,663 origins - : - 44.6% of origins have good [Core Web Vitals](https://web.dev/vitals/#core-web-vitals) + : - 44.6% of origins have good [Core Web Vitals](https://web.dev/articles/vitals#core_web_vitals) ## 202306 @@ -108,7 +108,7 @@ What's new Notable stats : - 18,065,718 origins - : - 44.1% of origins have good [Core Web Vitals](https://web.dev/vitals/#core-web-vitals) + : - 44.1% of origins have good [Core Web Vitals](https://web.dev/articles/vitals#core_web_vitals) ## 202305 @@ -123,7 +123,7 @@ What's new Notable stats : - 18,377,791 origins - : - 43.6% of origins have good [Core Web Vitals](https://web.dev/vitals/#core-web-vitals) + : - 43.6% of origins have good [Core Web Vitals](https://web.dev/articles/vitals#core_web_vitals) ## 202304 @@ -134,12 +134,12 @@ Publication date What's new : - We're seeing a slight decrease in pass rates for the Core Web Vitals, especially for LCP due in part to [a change in LCP to ignore low-entropy images](https://chromium.googlesource.com/chromium/src/+/refs/heads/main/docs/speed/metrics_changelog/2023_04_lcp.md). We also see a decrease in FCP pass rates [due to correction in paint timing](https://chromium.googlesource.com/chromium/src/+/refs/heads/main/docs/speed/metrics_changelog/2023_03_lcp_fcp.md) (which also affects LCP but to a lesser extent). - : - On a more positive note, the [INP](https://web.dev/inp/) pass rate continues to improve with a further increase of 0.2%. This is especially important, as we are [moving this metric from an Experimental metric to a Pending metric](https://web.dev/inp-cwv/), and it will join the reset of the Core Web Vitals next year. + : - On a more positive note, the [INP](https://web.dev/articles/inp) pass rate continues to improve with a further increase of 0.2%. This is especially important, as we are [moving this metric from an Experimental metric to a Pending metric](https://web.dev/articles/inp-cwv), and it will join the reset of the Core Web Vitals next year. : - From this release, the INP metric is available in the [CrUX BigQuery](/docs/crux/bigquery/), [API](/docs/crux/api/), and [History API](/docs/crux/history-api/), both with and without the experimental prefix. We encourage users to move to the non-prefixed field, as the experimental prefix fields should now be considered deprecated and will be removed in 90 days. Notable stats : - 18,406,973 origins - : - 43.5% of origins have good [Core Web Vitals](https://web.dev/vitals/#core-web-vitals) + : - 43.5% of origins have good [Core Web Vitals](https://web.dev/articles/vitals#core_web_vitals) ## 202303 @@ -150,7 +150,7 @@ Publication date Notable stats : - 18,495,210 origins - : - 44.2% of origins have good [Core Web Vitals](https://web.dev/vitals/#core-web-vitals) + : - 44.2% of origins have good [Core Web Vitals](https://web.dev/articles/vitals#core_web_vitals) ## 202302 @@ -164,7 +164,7 @@ What's new Notable stats : - 18,184,396 origins - : - 43.1% of origins have good [Core Web Vitals](https://web.dev/vitals/#core-web-vitals) + : - 43.1% of origins have good [Core Web Vitals](https://web.dev/articles/vitals#core_web_vitals) ## 202301 @@ -179,7 +179,7 @@ What's new Notable stats : - 18,203,637 origins - : - 43.0% of origins have good [Core Web Vitals](https://web.dev/vitals/#core-web-vitals) + : - 43.0% of origins have good [Core Web Vitals](https://web.dev/articles/vitals#core_web_vitals) ## 202212 @@ -193,7 +193,7 @@ What's new Notable stats : - 16,824,271 origins - : - 41.8% of origins have good [Core Web Vitals](https://web.dev/vitals/#core-web-vitals) + : - 41.8% of origins have good [Core Web Vitals](https://web.dev/articles/vitals#core_web_vitals) ## 202211 @@ -207,7 +207,7 @@ What's new Notable stats : - 17,618,944 origins - : - 41.8% of origins have good [Core Web Vitals](https://web.dev/vitals/#core-web-vitals) + : - 41.8% of origins have good [Core Web Vitals](https://web.dev/articles/vitals#core_web_vitals) ## 202210 @@ -221,7 +221,7 @@ What's new Notable stats : - 17,637,195 origins - : - 41.6% of origins have good [Core Web Vitals](https://web.dev/vitals/#core-web-vitals) + : - 41.6% of origins have good [Core Web Vitals](https://web.dev/articles/vitals#core_web_vitals) ## 202209 @@ -250,7 +250,7 @@ What's new Notable stats : - 17,715,277 origins - : - 41.4% of origins have good [Core Web Vitals](https://web.dev/vitals/#core-web-vitals) + : - 41.4% of origins have good [Core Web Vitals](https://web.dev/articles/vitals#core_web_vitals) ## 202208 @@ -261,7 +261,7 @@ Publication date Notable stats : - 16,754,655 origins - : - 40.7% of origins have good [Core Web Vitals](https://web.dev/vitals/#core-web-vitals) + : - 40.7% of origins have good [Core Web Vitals](https://web.dev/articles/vitals#core_web_vitals) ## 202207 @@ -276,7 +276,7 @@ What's new Notable stats : - 16,190,453 origins - : - 40.6% of origins have good [Core Web Vitals](https://web.dev/vitals/#core-web-vitals) + : - 40.6% of origins have good [Core Web Vitals](https://web.dev/articles/vitals#core_web_vitals) ## 202206 @@ -290,7 +290,7 @@ What's new Notable stats : - 16,230,572 origins - : - 41.3% of origins have good [Core Web Vitals](https://web.dev/vitals/#core-web-vitals) + : - 41.3% of origins have good [Core Web Vitals](https://web.dev/articles/vitals#core_web_vitals) ## 202205 @@ -322,7 +322,7 @@ What's new Notable stats : - 8,602,902 origins - : - 41.2% of origins have good [Core Web Vitals](https://web.dev/vitals/#core-web-vitals) + : - 41.2% of origins have good [Core Web Vitals](https://web.dev/articles/vitals#core_web_vitals) ## 202203 @@ -336,7 +336,7 @@ What's new Notable stats : - 8,555,307 origins - : - 39.6% of origins have good [Core Web Vitals](https://web.dev/vitals/#core-web-vitals) + : - 39.6% of origins have good [Core Web Vitals](https://web.dev/articles/vitals#core_web_vitals) ## 202202 @@ -346,11 +346,11 @@ Publication date : March 8, 2022 What's new - : - This release includes `experimental.responsiveness`, our candidate for the new responsiveness metric. See [web.dev/responsiveness/](https://web.dev/responsiveness/) for details. + : - This release includes `experimental.responsiveness`, our candidate for the new responsiveness metric. See [web.dev/responsiveness/](https://web.dev/articles/responsiveness) for details. Notable stats : - 8,764,246 origins - : - 39.0% of origins have good [Core Web Vitals](https://web.dev/vitals/#core-web-vitals) + : - 39.0% of origins have good [Core Web Vitals](https://web.dev/articles/vitals#core_web_vitals) ## 202201 @@ -364,7 +364,7 @@ What's new Notable stats : - 8,934,350 origins - : - 37.6% of origins have good [Core Web Vitals](https://web.dev/vitals/#core-web-vitals) + : - 37.6% of origins have good [Core Web Vitals](https://web.dev/articles/vitals#core_web_vitals) ## 202112 @@ -378,7 +378,7 @@ What's new Notable stats : - 8,398,796 origins - : - 35.0% of origins have good [Core Web Vitals](https://web.dev/vitals/#core-web-vitals) + : - 35.0% of origins have good [Core Web Vitals](https://web.dev/articles/vitals#core_web_vitals) ## 202111 @@ -393,7 +393,7 @@ What's new Notable stats : - 8,733,078 origins - : - 34.8% of origins have good [Core Web Vitals](https://web.dev/vitals/#core-web-vitals) + : - 34.8% of origins have good [Core Web Vitals](https://web.dev/articles/vitals#core_web_vitals) ## 202110 @@ -407,7 +407,7 @@ What's new Notable stats : - 8,784,894 origins - : - 34.1% of origins have good [Core Web Vitals](https://web.dev/vitals/#core-web-vitals) + : - 34.1% of origins have good [Core Web Vitals](https://web.dev/articles/vitals#core_web_vitals) ## 202109 @@ -421,7 +421,7 @@ What's new Notable stats : - 8,660,068 origins - : - 32.8% of origins have good [Core Web Vitals](https://web.dev/vitals/#core-web-vitals) + : - 32.8% of origins have good [Core Web Vitals](https://web.dev/articles/vitals#core_web_vitals) ## 202108 @@ -435,7 +435,7 @@ What's new Notable stats : - 8,431,699 origins - : - 31.3% of origins have good [Core Web Vitals](https://web.dev/vitals/#core-web-vitals) + : - 31.3% of origins have good [Core Web Vitals](https://web.dev/articles/vitals#core_web_vitals) ## 202107 @@ -449,7 +449,7 @@ What's new Notable stats : - 8,174,923 origins - : - 30.4% of origins have good [Core Web Vitals](https://web.dev/vitals/#core-web-vitals) + : - 30.4% of origins have good [Core Web Vitals](https://web.dev/articles/vitals#core_web_vitals) ## 202106 @@ -463,7 +463,7 @@ What's new Notable stats : - 8,416,608 origins - : - 30.6% of origins have good [Core Web Vitals](https://web.dev/vitals/#core-web-vitals) + : - 30.6% of origins have good [Core Web Vitals](https://web.dev/articles/vitals#core_web_vitals) ## 202105 @@ -474,7 +474,7 @@ Publication date Notable stats : - 8,411,670 origins - : - 29.23% of origins have good [Core Web Vitals](https://web.dev/vitals/#core-web-vitals) + : - 29.23% of origins have good [Core Web Vitals](https://web.dev/articles/vitals#core_web_vitals) Notable Changes : - The BigQuery update 202105 includes the same CLS and LCP updates that we released on June 1 for the CrUX API (see below). The previous CLS metric will be available for a limited time as `experimental.uncapped_cumulative_layout_shift`. @@ -483,7 +483,7 @@ API Update : June 1, 2021 Notable Changes - : - The new [Cumulative Layout Shift definition](https://web.dev/evolving-cls/) is now the default metric surfaced as `cumulative_layout_shift`, the previous Cumulative Layout Shift metric will be available for a limited time as it is phased out as `experimental_uncapped_cumulative_layout_shift`. + : - The new [Cumulative Layout Shift definition](https://web.dev/articles/evolving-cls) is now the default metric surfaced as `cumulative_layout_shift`, the previous Cumulative Layout Shift metric will be available for a limited time as it is phased out as `experimental_uncapped_cumulative_layout_shift`. : - [Largest Contentful Paint](https://chromium.googlesource.com/chromium/src/+/refs/heads/main/docs/speed/metrics_changelog/2020_11_lcp_2.md) has undergone adjustments in recent Chrome versions and has been updated similarly in CrUX. : - First Contentful Paint tri-binning thresholds have been updated to be: [0-1.8s], (1.8s-3s), [3s-∞]. @@ -496,7 +496,7 @@ Publication date Notable stats : - 8,423,302 origins - : - 25.83% of origins have good [Core Web Vitals](https://web.dev/vitals/#core-web-vitals) + : - 25.83% of origins have good [Core Web Vitals](https://web.dev/articles/vitals#core_web_vitals) ## 202103 @@ -507,7 +507,7 @@ Publication date Notable stats : - 8,326,310 origins - : - 24.81% of origins have good [Core Web Vitals](https://web.dev/vitals/#core-web-vitals) + : - 24.81% of origins have good [Core Web Vitals](https://web.dev/articles/vitals#core_web_vitals) ## 202102 @@ -522,7 +522,7 @@ What's new Notable stats : - 8,264,371 origins - : - 21.98% of origins have good [Core Web Vitals](https://web.dev/vitals/#core-web-vitals) + : - 21.98% of origins have good [Core Web Vitals](https://web.dev/articles/vitals#core_web_vitals) ## 202101 @@ -533,7 +533,7 @@ Publication date Notable stats : - 8,185,540 origins - : - 23.71% of origins have good [Core Web Vitals](https://web.dev/vitals/#core-web-vitals) + : - 23.71% of origins have good [Core Web Vitals](https://web.dev/articles/vitals#core_web_vitals) ## 202012 @@ -544,7 +544,7 @@ Publication date Notable stats : - 7,629,156 origins - : - 23.4% of origins have good [Core Web Vitals](https://web.dev/vitals/#core-web-vitals) + : - 23.4% of origins have good [Core Web Vitals](https://web.dev/articles/vitals#core_web_vitals) ## 202011 @@ -560,7 +560,7 @@ What's new Notable stats : - 7,942,408 origins - : - 23.5% of origins have good [Core Web Vitals](https://web.dev/vitals/#core-web-vitals) + : - 23.5% of origins have good [Core Web Vitals](https://web.dev/articles/vitals#core_web_vitals) ## 202010 @@ -574,7 +574,7 @@ What's new Notable stats : - 8,050,755 origins - : - 23.7% of origins have good [Core Web Vitals](https://web.dev/vitals/#core-web-vitals) + : - 23.7% of origins have good [Core Web Vitals](https://web.dev/articles/vitals#core_web_vitals) ## 202009 @@ -588,7 +588,7 @@ What's new Notable stats : - 7,937,088 origins - : - 24.6% of origins have good [Core Web Vitals](https://web.dev/vitals/#core-web-vitals) + : - 24.6% of origins have good [Core Web Vitals](https://web.dev/articles/vitals#core_web_vitals) ## 202008 @@ -602,7 +602,7 @@ What's new Notable stats : - 7,773,359 origins - : - 24.9% of origins have good [Core Web Vitals](https://web.dev/vitals/#core-web-vitals) + : - 24.9% of origins have good [Core Web Vitals](https://web.dev/articles/vitals#core_web_vitals) ## 202007 @@ -616,7 +616,7 @@ What's new Notable stats : - 7,527,878 origins - : - 25.2% of origins have good [Core Web Vitals](https://web.dev/vitals/#core-web-vitals) + : - 25.2% of origins have good [Core Web Vitals](https://web.dev/articles/vitals#core_web_vitals) ## 202006 @@ -630,7 +630,7 @@ What's new Notable stats : - 7,501,835 origins - : - 25.34% of origins have good [Core Web Vitals](https://web.dev/vitals/#core-web-vitals) + : - 25.34% of origins have good [Core Web Vitals](https://web.dev/articles/vitals#core_web_vitals) ## 202005 @@ -645,7 +645,7 @@ What's new Notable stats : - 7,103,486 origins - : - 23.77% of origins have good [Core Web Vitals](https://web.dev/vitals/#core-web-vitals) + : - 23.77% of origins have good [Core Web Vitals](https://web.dev/articles/vitals#core_web_vitals) ## 202004 diff --git a/site/en/docs/devtools/accessibility/contrast/index.md b/site/en/docs/devtools/accessibility/contrast/index.md index b68bd4881..3a0763355 100644 --- a/site/en/docs/devtools/accessibility/contrast/index.md +++ b/site/en/docs/devtools/accessibility/contrast/index.md @@ -126,8 +126,8 @@ To save the changes you made in DevTools: Learn more: -- [Learn Accessibility](https://web.dev/learn/accessibility/) in general -- [Color and contrast](https://web.dev/learn/accessibility/color-contrast/) accessibility in particular +- [Learn Accessibility](https://web.dev/learn/accessibility) in general +- [Color and contrast](https://web.dev/learn/accessibility/color-contrast) accessibility in particular [1]: https://web.dev/accessibility/ [2]: /docs/devtools/accessibility/navigation diff --git a/site/en/docs/devtools/accessibility/reference/index.md b/site/en/docs/devtools/accessibility/reference/index.md index 07d09465f..c3e38d6ec 100644 --- a/site/en/docs/devtools/accessibility/reference/index.md +++ b/site/en/docs/devtools/accessibility/reference/index.md @@ -24,7 +24,7 @@ can help you examine a page's accessibility. See [Navigating Chrome DevTools With Assistive Technology][2] if you're looking for help on navigating DevTools with an assistive technology like a screen reader. -See [Learn Accessibility](https://web.dev/learn/accessibility/) if you'd like to learn how to develop accessible websites. +See [Learn Accessibility](https://web.dev/learn/accessibility) if you'd like to learn how to develop accessible websites. ## Overview of accessibility features in Chrome DevTools {: #overview } @@ -167,7 +167,7 @@ To view and debug the source order on your website: 1. [Inspect an element](/docs/devtools/open/#inspect) on the page. 1. In **Elements** > **Accessibility** > **Source Order Viewer**, check {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/hmp8j3HiLMCcqPArD9yt.svg", alt="Checkbox.", width="24", height="24" %} **Show source order**. -In the viewport, DevTools outlines nested elements with borders and marks them with numbers corresponding to their source order. +In the viewport, DevTools outlines nested elements with borders and marks them with numbers corresponding to their source order. {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/sBXqLvOkou3OTfwPzR36.png", alt="Source order option checked.", width="800", height="623" %} diff --git a/site/en/docs/devtools/application/back-forward-cache/index.md b/site/en/docs/devtools/application/back-forward-cache/index.md index 3144d888c..97b959124 100644 --- a/site/en/docs/devtools/application/back-forward-cache/index.md +++ b/site/en/docs/devtools/application/back-forward-cache/index.md @@ -16,7 +16,7 @@ This guide shows you how to use [Chrome DevTools][1] to do the following: - Test if you optimized your page for instant loads when using the browser's back and forward buttons. - Identify issues that may prevent your page from being eligible for this type of caching. -Back/forward cache (or bfcache) is a browser optimization that enables instant back and forward navigation. For more information, see [Back/forward cache](https://web.dev/bfcache/). +Back/forward cache (or bfcache) is a browser optimization that enables instant back and forward navigation. For more information, see [Back/forward cache](https://web.dev/articles/bfcache). {% Aside 'gotchas' %} Back/forward cache differs from browser [cache][2] and [HTTP cache][3]. @@ -34,10 +34,10 @@ To test back/forward cache, follow these steps: {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/s2M01xBJya7X8U1UkqF3.png", alt="Back/forward cache tab.", width="800", height="416" %} -1. Click **Test back/forward cache**. - +1. Click **Test back/forward cache**. + Chrome automatically takes you to `chrome://terms/` and back to your page. - + Alternatively, you can click the browser's back and forward buttons. If the back/forward cache works for your page with no issues, you'll see the following message: @@ -56,7 +56,7 @@ If your page isn't eligible for back/forward caching, the **Back/forward cache** {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/3VKdnWq27QjYWT9ahhvY.png", alt="Not eligible for back/forward cache.", width="800", height="744" %} -- **Actionable**. You can fix these issues to enable caching. For example, [stop using `unload` events](https://web.dev/bfcache/#never-use-the-unload-event). +- **Actionable**. You can fix these issues to enable caching. For example, [stop using `unload` events](https://web.dev/articles/bfcache#never_use_the_unload_event). - **Pending Support**. Chrome doesn't support these features yet, so they prevent caching. However, once supported, Chrome removes these limitations. - **Not Actionable**. You can't fix these issues on this page. Something that is outside the page's control prevents caching. diff --git a/site/en/docs/devtools/css/color/index.md b/site/en/docs/devtools/css/color/index.md index 793ff6cc3..01ff58ce2 100644 --- a/site/en/docs/devtools/css/color/index.md +++ b/site/en/docs/devtools/css/color/index.md @@ -56,7 +56,7 @@ Here's a description of each of the UI elements of the **Color Picker**: 1. **Eyedropper**. See [Sample a color anywhere with the Eyedropper](#eyedropper). 1. **Copy to clipboard**. Copy the **Display value** to your clipboard. 1. **Display value**. Arguments of the chosen color space. -1. **Contrast ratio**. Available only for `color` values. It's the difference between `color` and `background-color`. +1. **Contrast ratio**. Available only for `color` values. It's the difference between `color` and `background-color`. 1. **Color palette**. Click a square to change the color to that of the square. 1. **Gamut boundary**. This line is available only for the new color spaces and the [`color()`](/articles/high-definition-css-color-guide/#the-color-function) function. They can produce both HD and non-HD colors. The line lets you distinguish between HD and non-HD. 1. **Color circle**. Drag this circle across the shades to change the display value. @@ -92,7 +92,7 @@ To choose a color space: - [`rgb(X X X / .X)`](https://developer.mozilla.org/docs/Web/CSS/color_value/rgb). - [`hsl(X X X / X)`](https://developer.mozilla.org/docs/Web/CSS/color_value/hsl). - [`hwb(X X X / .X)`](https://developer.mozilla.org/docs/Web/CSS/color_value/hwb). - + Or one of the new spaces: - [`lch(X X X / .X)`](https://developer.mozilla.org/docs/Web/CSS/color_value/lch) - [`oklch(X X X / .X)`](https://developer.mozilla.org/docs/Web/CSS/color_value/oklch) @@ -131,7 +131,7 @@ To fix a contrast issue for a `color` declaration: {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/1OBcwQNbZivVFL4vbC47.png", alt="The expanded contrast ratio section with WebAIM or APCA guidelines.", width="800", height="518" %} {% Aside %} -By default, the **Color Picker** suggests you to follow the [WebAIM guidelines](https://webaim.org/standards/wcag/). Alternatively, you can set it to suggest values compliant with [APCA](https://web.dev/color-and-contrast-accessibility/#advanced-perceptual-contrast-algorithm-apca): +By default, the **Color Picker** suggests you to follow the [WebAIM guidelines](https://webaim.org/standards/wcag/). Alternatively, you can set it to suggest values compliant with [APCA](https://web.dev/articles/color-and-contrast-accessibility#advanced_perceptual_contrast_algorithm_apca): In {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/9gzXiTYY0nZzBxGI6KrV.svg", alt="Settings.", width="24", height="24" %} [**Settings** > **Experiments**](/docs/devtools/settings/experiments/), check {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/hmp8j3HiLMCcqPArD9yt.svg", alt="Checkbox.", width="22", height="22" %} **Enable new Advanced Perceptual Contrast Algorithm (APCA)...** {% endAside %} diff --git a/site/en/docs/devtools/css/container-queries/index.md b/site/en/docs/devtools/css/container-queries/index.md index cf0ea9aff..0935db9d8 100644 --- a/site/en/docs/devtools/css/container-queries/index.md +++ b/site/en/docs/devtools/css/container-queries/index.md @@ -16,7 +16,7 @@ This guide shows you how to inspect and debug CSS container queries in the **Ele {% YouTube id='X4TYXlvbb2E' %} -[CSS container queries][3] allow you to manipulate the element's styles based on its parent container properties. This capability shifts the concept of [responsive web design][2] from page-based to [container-based](https://web.dev/new-responsive/). +[CSS container queries][3] allow you to manipulate the element's styles based on its parent container properties. This capability shifts the concept of [responsive web design][2] from page-based to [container-based](https://web.dev/articles/new-responsive). The screenshots in this guide are taken from [this demo page](https://jec.fish/demo/css-cq-coffee). @@ -91,7 +91,7 @@ To debug a query, you can modify it as any other CSS declaration in the **Styles {% Video src="video/dPDCek3EhZgLQPGtEG3y0fTn4v82/OdeunIEJzVJ9BSmAyaR0.mp4", autoplay=true, loop=true, class="screenshot" %} -In this example, the container's width is `500px`. The paragraph (`p`) element appears on the page. +In this example, the container's width is `500px`. The paragraph (`p`) element appears on the page. 1. Select the `p` element. In the **Styles** pane. You can see the `@container (inline-size > 400px)` declaration. 2. Change the `inline-size` from `400px` to `520px`. diff --git a/site/en/docs/devtools/css/reference/index.md b/site/en/docs/devtools/css/reference/index.md index b420900c4..73909e377 100644 --- a/site/en/docs/devtools/css/reference/index.md +++ b/site/en/docs/devtools/css/reference/index.md @@ -129,7 +129,7 @@ Alternatively, scroll down the **Styles** pane and find sections named `Inherite ### View `@property` at-rules {: #property } -The [`@property` CSS at-rule](https://web.dev/at-property/) lets you define [CSS custom properties](https://developer.mozilla.org/docs/Web/CSS/--*) explicitly and register them in a stylesheet without running any JavaScript. +The [`@property` CSS at-rule](https://web.dev/articles/at-property) lets you define [CSS custom properties](https://developer.mozilla.org/docs/Web/CSS/--*) explicitly and register them in a stylesheet without running any JavaScript. Hover over the name of such property in the **Styles** pane, to see a tooltip with the property's value, descriptors, and a link to its registration in the collapsible `@property` section at the bottom of the **Styles** pane. diff --git a/site/en/docs/devtools/elements/badges/index.md b/site/en/docs/devtools/elements/badges/index.md index 268d85ab2..78e986d76 100644 --- a/site/en/docs/devtools/elements/badges/index.md +++ b/site/en/docs/devtools/elements/badges/index.md @@ -85,13 +85,13 @@ Toggle the overlay on the following preview: {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/MmkJORNp3sOKHHK1CI4h.png", alt="Flex overlay.", width="800", height="646" %} -The overlay shows child element positions. +The overlay shows child element positions. To learn how to debug flex layouts, see [Inspect and debug CSS flexbox](/docs/devtools/css/flexbox/). ## Ad -DevTools can detect some [ad frames and tag them](https://chromium.googlesource.com/chromium/src/+/master/docs/ad_tagging.md). Such frames have `ad` badges next to them. +DevTools can detect some [ad frames and tag them](https://chromium.googlesource.com/chromium/src/+/master/docs/ad_tagging.md). Such frames have `ad` badges next to them. Discover an ad in the following preview: @@ -185,7 +185,7 @@ Discover the {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/Zml4roc9tWR2DU1Yb9ix ## Top layer -This badge helps you understand the concept of the [top layer](/blog/what-is-the-top-layer/) and visualize it. The top layer renders content on top of all other layers, regardless of [`z-index`][2]. When you open a [`<dialog>` element](https://web.dev/building-a-dialog-component/) using the [`.showModal()` method][3], the browser puts it into the top layer. +This badge helps you understand the concept of the [top layer](/blog/what-is-the-top-layer/) and visualize it. The top layer renders content on top of all other layers, regardless of [`z-index`][2]. When you open a [`<dialog>` element](https://web.dev/articles/building-a-dialog-component) using the [`.showModal()` method][3], the browser puts it into the top layer. To help you visualize top layer elements, the **Elements** panel adds a `#top-layer` container to the DOM tree after the closing `</html>` tag. diff --git a/site/en/docs/devtools/javascript/background-services/index.md b/site/en/docs/devtools/javascript/background-services/index.md index 7f05883e8..4271bd0a3 100644 --- a/site/en/docs/devtools/javascript/background-services/index.md +++ b/site/en/docs/devtools/javascript/background-services/index.md @@ -27,7 +27,7 @@ Chrome DevTools can log fetch, sync, and notification events for three days, eve In addition to background service events, DevTools can: -- Show you [reports](https://web.dev/reporting-api/) that Chrome already sent or is about to send via the [Reporting API][20]. +- Show you [reports](https://web.dev/articles/reporting-api) that Chrome already sent or is about to send via the [Reporting API][20]. - Let you debug and [test back/forward cache](/docs/devtools/application/back-forward-cache/) with a click. ## Background Fetch {: #fetch } @@ -136,9 +136,9 @@ DevTools isn't open: Some errors happen only in production. You never see them locally or during development because real users, networks, and devices change the game. -For example, say your new site relies on third-party software that uses `document.write()` to load critical scripts. New users all over the world open your site but they might have slower connections than you tested with. Unknown to you, your site starts breaking for them because [Chrome intervenes against](https://web.dev/no-document-write/) `document.write()` on slow networks. Alternatively, you might want to keep an eye on deprecated or soon-to-be-deprecated APIs your code base may be using. +For example, say your new site relies on third-party software that uses `document.write()` to load critical scripts. New users all over the world open your site but they might have slower connections than you tested with. Unknown to you, your site starts breaking for them because [Chrome intervenes against](https://web.dev/articles/no-document-write) `document.write()` on slow networks. Alternatively, you might want to keep an eye on deprecated or soon-to-be-deprecated APIs your code base may be using. -The **Reporting API** is designed to help you monitor deprecated API calls, security violations of your page, and more. You can set up reporting as described in [Monitor your web application with the Reporting API](https://web.dev/reporting-api/#using-the-reporting-api). +The **Reporting API** is designed to help you monitor deprecated API calls, security violations of your page, and more. You can set up reporting as described in [Monitor your web application with the Reporting API](https://web.dev/articles/reporting-api#using_the_reporting_api). To view the reports generated by a page: @@ -200,7 +200,7 @@ The **Status** column tells you whether Chrome sent the report successfully, is Reports are removed after a while, whether or not they're successfully sent. -{% Aside 'important' %} The `Queued` status isn't always informative, because it doesn't precisely indicate whether sending has failed or has not been attempted yet. Using [short reporting delays](https://web.dev/reporting-api/#save-time) helps: a report that remains `Queued` in that case likely indicates that sending is failing. {% endAside %} +{% Aside 'important' %} The `Queued` status isn't always informative, because it doesn't precisely indicate whether sending has failed or has not been attempted yet. Using [short reporting delays](https://web.dev/articles/reporting-api#save_time) helps: a report that remains `Queued` in that case likely indicates that sending is failing. {% endAside %} [1]: https://en.wikipedia.org/wiki/Background_process [2]: #fetch diff --git a/site/en/docs/devtools/javascript/breakpoints/index.md b/site/en/docs/devtools/javascript/breakpoints/index.md index 219182921..03cedc6dd 100644 --- a/site/en/docs/devtools/javascript/breakpoints/index.md +++ b/site/en/docs/devtools/javascript/breakpoints/index.md @@ -330,7 +330,7 @@ In the **Breakpoints** pane of the **Sources** tab, go to the **CSP Violation Br In this example, the execution is paused on a policy violation. Trusted Type policies are set up using [`trustedTypes.createPolicy`](https://developer.mozilla.org/docs/Web/API/TrustedTypePolicyFactory/createPolicy). You can find more information about using the API: -- To further your security aims, visit [Prevent DOM-based cross-site scripting vulnerabilities with Trusted Types](https://web.dev/trusted-types/). +- To further your security aims, visit [Prevent DOM-based cross-site scripting vulnerabilities with Trusted Types](https://web.dev/articles/trusted-types). - For debugging, visit [Implementing CSP and Trusted Types debugging in Chrome DevTools](/blog/csp-issues/#debugging-trusted-types-problems). [1]: /docs/devtools/javascript diff --git a/site/en/docs/devtools/javascript/source-maps/index.md b/site/en/docs/devtools/javascript/source-maps/index.md index 0538e2c67..c07a6b78c 100644 --- a/site/en/docs/devtools/javascript/source-maps/index.md +++ b/site/en/docs/devtools/javascript/source-maps/index.md @@ -11,7 +11,7 @@ description: "Keep your client-side code readable and debuggable even after you' --- Keep your client-side code readable and debuggable even after you've combined, minified or compiled -it. Use [source maps](https://web.dev/source-maps/) to map your source code to your compiled code in the **Sources** panel. +it. Use [source maps](https://web.dev/articles/source-maps) to map your source code to your compiled code in the **Sources** panel. {% YouTube id='SkUcO4ML5U0' %} diff --git a/site/en/docs/devtools/lighthouse/index.md b/site/en/docs/devtools/lighthouse/index.md index 11d5f8407..4a9037b85 100644 --- a/site/en/docs/devtools/lighthouse/index.md +++ b/site/en/docs/devtools/lighthouse/index.md @@ -80,7 +80,7 @@ For the rest of the screenshots in this tutorial, DevTools is shown in a [separa The baseline is a record of how the site performed before you made any performance improvements. 1. Open the **Lighthouse** panel. It may be hidden behind {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/V93Xxk8HvmByCBGzMdW4.svg", alt="More panels.", width="20", height="20" %} **More panels**. - + {% Aside %} This panel is powered by its namesake—[**Lighthouse**](/docs/lighthouse), an automated tool for improving the quality of your web apps. {% endAside %} @@ -212,7 +212,7 @@ of lines of code: ```js/2-4 ... const fs = require('fs'); - const compression = require('compression'); + const compression = require('compression'); app.use(compression()); app.use(express.static('build')); @@ -495,7 +495,7 @@ Reduce JavaScript activity by removing the call to `mineBitcoin`: {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/Ug3mIDzuacvZwGSt6StX.png", alt="A Lighthouse report after removing unnecessary JavaScript work.", width="800", height="692" %} -As always, there still are things to do, for example, reduce the [Largest Contentful Paint](/docs/lighthouse/performance/lighthouse-largest-contentful-paint/) and [Cumulative Layout Shift](https://web.dev/cls/) metrics. +As always, there still are things to do, for example, reduce the [Largest Contentful Paint](/docs/lighthouse/performance/lighthouse-largest-contentful-paint/) and [Cumulative Layout Shift](https://web.dev/articles/cls) metrics. {% Aside 'success' %} But it looks like the last change caused a massive jump in performance! diff --git a/site/en/docs/devtools/overrides/index.md b/site/en/docs/devtools/overrides/index.md index 150b01879..22a6aa0a4 100644 --- a/site/en/docs/devtools/overrides/index.md +++ b/site/en/docs/devtools/overrides/index.md @@ -97,7 +97,7 @@ With response header overrides, you can locally prototype fixes for various head - [Cross-Origin Resource Sharing (CORS) Headers](https://developer.mozilla.org/docs/Web/HTTP/CORS) - [Permissions-Policy Headers](https://developer.mozilla.org/docs/Web/HTTP/Headers/Permissions-Policy) -- [Cross-Origin Isolation Headers](https://web.dev/coop-coep/) +- [Cross-Origin Isolation Headers](https://web.dev/articles/coop-coep) To override a response header: @@ -112,7 +112,7 @@ To override a response header: 1. Modify or add a new header. {% Aside %} - This example adds the `Access-Control-Allow-Origin: *` header to get rid of a [CORS error](https://web.dev/cross-origin-resource-sharing/). + This example adds the `Access-Control-Allow-Origin: *` header to get rid of a [CORS error](https://web.dev/articles/cross-origin-resource-sharing). {% endAside %} {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/IhXa4zihNp5Gsi9eBPhN.png", alt="Modifying an existing header value, adding a new one, and removing an override.", width="800", height="653" %} @@ -120,7 +120,7 @@ To override a response header: - To edit a header value, click it. - To add a new header, click {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/eY8MaTQqlXF3oiT6STmy.svg", alt="Add.", width="20", height="20" %} **Add header**. - To remove a header override, click {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/Bg5rfKrzHBaF621Ag9IN.svg", alt="Delete.", width="20", height="20" %} next to it. This removes the headers you added or reverts modified values back to original values. - + DevTools highlights modified headers <span style="background-color:#e9f2ec;">in green</span> and removed overrides <span style="background-color:#ffeff0;text-decoration-line: line-through;">in red</span>. 1. {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/sX65QEDYhwBFHCM24BtV.svg", alt="Refresh.", width="20", height="20" %} Refresh the page to apply the changes. diff --git a/site/en/docs/devtools/performance-insights/index.md b/site/en/docs/devtools/performance-insights/index.md index a9d07a7c3..ab0098331 100644 --- a/site/en/docs/devtools/performance-insights/index.md +++ b/site/en/docs/devtools/performance-insights/index.md @@ -20,11 +20,11 @@ This feature is available only in Chrome, not Chromium. {% YouTube id='5PFmGeCZDvw' %} {% Aside %} -This is a preview feature in Chrome 102. Our team is actively working on this feature and we are looking for your [feedback](https://goo.gle/perf-insights-feedback) for further enhancements. +This is a preview feature in Chrome 102. Our team is actively working on this feature and we are looking for your [feedback](https://goo.gle/perf-insights-feedback) for further enhancements. {% endAside %} -## Why a new panel? +## Why a new panel? The new **Performance insights** panel is an experiment to address these 3 developer pain points when working with the existing **Performance** panel: @@ -58,17 +58,17 @@ The **Performance insights** panel can record general and use-case-driven (for e 2. You can throttle the network and CPU while recording. For this tutorial, check **Disable cache** and set **CPU** to **4x slowdown** in the drop-down menu: {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/ZcatuTY8eettWFRbBxVf.png", alt="Throttling.", width="800", height="489" %} - + {% Aside 'gotchas' %} Throttling is relative to your computer's capabilities. For example, the 4x slowdown option makes your CPU operate 4 times slower than usual. DevTools can't truly simulate the CPUs of mobile devices because the architecture of mobile devices is very different from that of desktops and laptops. - {% endAside %} + {% endAside %} 3. Click {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/sX65QEDYhwBFHCM24BtV.svg", alt="Refresh.", width="20", height="20" %} **Measure page load**. DevTools records performance metrics while the page reloads and then automatically stops the recording a couple seconds after the page load has finished. - + {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/z24Hl8VhBVetZUNHIGms.png", alt="Start options.", width="800", height="489" %} {% Aside 'gotchas' %} - If you want to measure general performance of your web page, use **Start recording**. Interact with the page and click **Stop recording** manually to stop recording. + If you want to measure general performance of your web page, use **Start recording**. Interact with the page and click **Stop recording** manually to stop recording. {% endAside %} @@ -84,13 +84,13 @@ Here is an example of how to do it. - Click {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/gjfZMeLnwzpRfOMfXEMY.svg", alt="Play.", width="20", height="20" %} **Play** to play the recording. - Click {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/E4DiaFpjvozAUMoUQgB1.svg", alt="Pause.", width="20", height="20" %} **Pause** to pause the replay. -- Adjust the **playback speed** with the drop-down. -- Click {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/CoI0VqgWpyBs6ye9WJZ3.svg", alt="Preview.", width="20", height="20" %} **Toggle visual preview** to show or hide the visual preview. +- Adjust the **playback speed** with the drop-down. +- Click {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/CoI0VqgWpyBs6ye9WJZ3.svg", alt="Preview.", width="20", height="20" %} **Toggle visual preview** to show or hide the visual preview. ## Navigate a performance recording {: #navigate } -DevTools automatically zooms out to show the full recording timeline. You can navigate the recording with zoom and move the timeline. +DevTools automatically zooms out to show the full recording timeline. You can navigate the recording with zoom and move the timeline. {% Video src="video/dPDCek3EhZgLQPGtEG3y0fTn4v82/aiNxjBK2fBr76NKHfMoA.mp4", autoplay=true, loop=true, muted="true", class="screenshot" %} @@ -117,13 +117,13 @@ Hover over each of the insights to highlight them on the main tracks. {% Video src="video/dPDCek3EhZgLQPGtEG3y0fTn4v82/FXl6y9hXBJNXsOLgLPft.mp4", controls="true", muted="true", class="screenshot" %} -Click on an insight, for example, the render blocking request, to open it in the **Details** pane. To understand the issue further, examine its **File**, **Issue**, **How to fix** sections, and more. +Click on an insight, for example, the render blocking request, to open it in the **Details** pane. To understand the issue further, examine its **File**, **Issue**, **How to fix** sections, and more. {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/bHHoPGrJHuHPbRYOWWwd.png", alt="Insight details.", width="800", height="489" %} ## View Web Vitals performance metrics {: #vitals } -[Web Vitals](https://web.dev/vitals/) is an initiative by Google to provide unified guidance for quality signals that are essential to delivering a great user experience on the web. +[Web Vitals](https://web.dev/articles/vitals) is an initiative by Google to provide unified guidance for quality signals that are essential to delivering a great user experience on the web. You can view these metrics on the **Timeline** and **Insights** pane. @@ -135,11 +135,11 @@ Hover over the insights on the **Timeline** to learn more about the metrics. ## Discover delays of the largest contentful paint {: #largest-contentful-paint } -[Largest Contentful Paint (LCP)](https://web.dev/lcp/) is one of the [Core Web Vitals](https://web.dev/vitals/#core-web-vitals) metrics. It reports the render time of the largest image or text block visible within the viewport, relative to when the page first started loading. +[Largest Contentful Paint (LCP)](https://web.dev/articles/lcp) is one of the [Core Web Vitals](https://web.dev/articles/vitals#core_web_vitals) metrics. It reports the render time of the largest image or text block visible within the viewport, relative to when the page first started loading. {% Img src="image/tcFciHGuF3MxnTr1y5ue01OGLBn2/elqsdYqQEefWJbUM2qMO.svg", alt="LCP thresholds.", width="800", height="212" %} -A [good LCP score](https://web.dev/lcp/#what-is-a-good-lcp-score?) is 2.5 seconds or less. +A [good LCP score](https://web.dev/articles/lcp#what_is_a_good_lcp_score?) is 2.5 seconds or less. If the largest contentful paint on your page takes longer to render, in the timeline, you will see the LCP badge with a yellow square or red triangle. @@ -149,9 +149,9 @@ To open the **Details** pane, click the LCP badge on the timeline or on the **In {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/Wnl6w6KOnqUQsXSWu0xN.png", alt="The details pane.", width="800", height="627" %} -In this example, a request blocks rendering and you can apply critical styles inline to fix it. To learn more, see [Eliminate render-blocking resources](https://web.dev/render-blocking-resources/). +In this example, a request blocks rendering and you can apply critical styles inline to fix it. To learn more, see [Eliminate render-blocking resources](https://web.dev/articles/render-blocking-resources). -To view the [sub-parts of LCP render time](https://web.dev/optimize-lcp/#lcp-breakdown), scroll down to the **Details** > **Timings breakdown** section. +To view the [sub-parts of LCP render time](https://web.dev/articles/optimize-lcp#lcp_breakdown), scroll down to the **Details** > **Timings breakdown** section. {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/zog6KF5dnfgnGdshcbvH.png", alt="Timings breakdown.", width="800", height="579" %} @@ -188,19 +188,19 @@ If an LCP element doesn't require a resource load to render, the resource load d ## View layout shifts activity {: #layout-shifts } -View layout shifts activity in the **Layout Shifts** track. +View layout shifts activity in the **Layout Shifts** track. {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/ronEnmKW9Xh4h8YLdVWN.png", alt="Layout Shifts track.", width="800", height="491" %} -Layout shifts are grouped in a [session window](https://web.dev/evolving-cls/?utm_source=devtools#why-a-session-window). In the example above, there are two session windows. Session windows have gaps between them. +Layout shifts are grouped in a [session window](https://web.dev/evolving-cls/?utm_source=devtools#why_a_session_window). In the example above, there are two session windows. Session windows have gaps between them. {% Aside 'gotchas' %} -Think about layout shifts like fireworks. There are times where multiple shifts happen at once, then they pause for a while, then multiple shifts happen again. Each set of multiple shifts is a session window. For more information, see [Session window](https://web.dev/evolving-cls/?utm_source=devtools#why-a-session-window). +Think about layout shifts like fireworks. There are times where multiple shifts happen at once, then they pause for a while, then multiple shifts happen again. Each set of multiple shifts is a session window. For more information, see [Session window](https://web.dev/evolving-cls/?utm_source=devtools#why_a_session_window). {% endAside %} {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/7uN8y6gdUU8QdmAREPtJ.png", alt="Session window and gap.", width="800", height="491" %} -[Cumulative Layout Shifts (CLS)](https://web.dev/cls) is one of the [core web vitals](https://web.dev/vitals/#core-web-vitals) metrics. Use the **Layout Shifts** track to identify potential issues and causes of layout shifts. +[Cumulative Layout Shifts (CLS)](https://web.dev/cls) is one of the [core web vitals](https://web.dev/articles/vitals#core_web_vitals) metrics. Use the **Layout Shifts** track to identify potential issues and causes of layout shifts. Always start with the largest session window when improving CLS metric. In our example, session window 1 is the largest window, based on the background color and level. @@ -210,7 +210,7 @@ Click on a screenshot to view the layout shift's details, identify potential roo {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/T7laY8CqS5kMMowwjwOH.png", alt="View the layout shift's details.", width="800", height="523" %} -In our example, the potential root cause is **unsized media**. To learn how to fix it, see [Optimize Cumulative Layout Shift](https://web.dev/optimize-cls/#images-without-dimensions). +In our example, the potential root cause is **unsized media**. To learn how to fix it, see [Optimize Cumulative Layout Shift](https://web.dev/articles/optimize-cls#images_without_dimensions). {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/0eqkyM3nRWQIuWzQACHZ.png", alt="identify potential root causes.", width="800", height="532" %} @@ -254,14 +254,14 @@ View GPU activity in the **GPU** track. The GPU track is hidden by default. To e ## View user timings {: #timings } -To get custom performance measures, you can use [User Timing](https://www.w3.org/TR/user-timing/) and visualize your timings with the **Timing** track. For more information, see the [User timing API](https://web.dev/usertiming/). +To get custom performance measures, you can use [User Timing](https://www.w3.org/TR/user-timing/) and visualize your timings with the **Timing** track. For more information, see the [User timing API](https://web.dev/articles/usertiming). -Check out [this demo page](https://jec.fish/demo/perf-measure) that calculates the elapsed time of text loading. +Check out [this demo page](https://jec.fish/demo/perf-measure) that calculates the elapsed time of text loading. To view user timings: -1. Mark places in your application with [`performance.mark()`](https://web.dev/usertiming/#using-mark()). -1. Measure the elapsed time between marks with [`performance.measure()`](https://web.dev/usertiming/#calculating-measurements-with-measure()). +1. Mark places in your application with [`performance.mark()`](https://web.dev/articles/usertiming#using_mark()). +1. Measure the elapsed time between marks with [`performance.measure()`](https://web.dev/articles/usertiming#calculating_measurements_with_measure()). 1. [Record performance](#record). 1. View the measurements on the **Timings** track. If you can't see the track, check **User timings** in [Settings](#settings). 1. To view details, click the timing on the track. diff --git a/site/en/docs/devtools/performance/reference/index.md b/site/en/docs/devtools/performance/reference/index.md index cf3653713..ad3a8ac73 100644 --- a/site/en/docs/devtools/performance/reference/index.md +++ b/site/en/docs/devtools/performance/reference/index.md @@ -383,8 +383,8 @@ activities from those categories. On the **Timings** track, view important markers such as: - [First Paint (FP)](https://developer.mozilla.org/docs/Glossary/First_paint) -- [First Contentful Paint (FCP)](https://web.dev/fcp/) -- [Largest Contentful Paint (LCP)](https://web.dev/lcp/) +- [First Contentful Paint (FCP)](https://web.dev/articles/fcp) +- [Largest Contentful Paint (LCP)](https://web.dev/articles/lcp) - [DOMContentLoaded Event (DCL)](https://developer.mozilla.org/docs/Web/API/Window/DOMContentLoaded_event) - [Onload Event (L)](https://developer.mozilla.org/docs/Web/API/Window/load_event) - Your custom [`performance.mark()`](https://developer.mozilla.org/docs/Web/API/Performance/mark) calls @@ -408,7 +408,7 @@ To view interactions: In the example above, the **Interactions** track shows two interactions. Both have the same IDs, indicating that the interactions are triggered by the same user action. -The **Interactions** track also shows [Interaction to Next Paint (INP)](https://web.dev/inp/) warnings for interactions longer than 200 milliseconds in the **Summary** tab: +The **Interactions** track also shows [Interaction to Next Paint (INP)](https://web.dev/articles/inp) warnings for interactions longer than 200 milliseconds in the **Summary** tab: {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/wrFaZ26nYCuprtCSNB5C.png", alt="The INP warning.", width="800", height="685" %} @@ -491,7 +491,7 @@ A darker-blue square in the top-left of a request means it's a higher-priority r lighter-blue square means lower-priority. In the example above, the selected request is of high priority, and the blue one above it is highest-priority. -The **Summary** section includes **Initial Priority** and (final) **Priority** fields. If their values differ, the fetch priority of the request has changed during the recording. For more information, see [Optimizing resource loading with the Fetch Priority API](https://web.dev/fetch-priority/). +The **Summary** section includes **Initial Priority** and (final) **Priority** fields. If their values differ, the fetch priority of the request has changed during the recording. For more information, see [Optimizing resource loading with the Fetch Priority API](https://web.dev/articles/fetch-priority). In the example above, the request for `www.google.com` is represented by a line on the left, a bar in the middle with a dark portion and a light portion, and a line on the right. The screenshot below shows the diff --git a/site/en/docs/devtools/progressive-web-apps/index.md b/site/en/docs/devtools/progressive-web-apps/index.md index 8adf2ec84..bd2cfe8b8 100644 --- a/site/en/docs/devtools/progressive-web-apps/index.md +++ b/site/en/docs/devtools/progressive-web-apps/index.md @@ -70,7 +70,7 @@ In addition, if DevTools encounters an error, such as an icon that cannot be loa ### View and check maskable icons {: #icons } -The **Icons** section of the **Manifest** pane displays all the icons of your application. In this section, you can also check safe areas for [maskable icons](https://web.dev/maskable-icon/), the format of icons that adapt to platforms. +The **Icons** section of the **Manifest** pane displays all the icons of your application. In this section, you can also check safe areas for [maskable icons](https://web.dev/articles/maskable-icon), the format of icons that adapt to platforms. To trim the icons so that only the minimum safe area is visible, check {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/hmp8j3HiLMCcqPArD9yt.svg", alt="Checkbox.", width="22", height="22" %} **Show only the minimum safe area for maskable icons**. @@ -108,9 +108,9 @@ DevTools via [remote debugging][6]. To trigger the installation on the connected ### Inspect shortcuts {: #shortcut } -[App shortcuts](https://web.dev/app-shortcuts/) let you to provide quick access to a handful of common actions that users need frequently. +[App shortcuts](https://web.dev/articles/app-shortcuts) let you to provide quick access to a handful of common actions that users need frequently. -To inspect the shortcuts you defined in your [manifest file](https://web.dev/app-shortcuts/#define-app-shortcuts-in-the-web-app-manifest), scroll to the **Shortcut #N** sections of the **Manifest** pane. +To inspect the shortcuts you defined in your [manifest file](https://web.dev/articles/app-shortcuts#define_app_shortcuts_in_the_web_app_manifest), scroll to the **Shortcut #N** sections of the **Manifest** pane. {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/q3uzqiM5Psp7ggEAn3Y0.png", alt="Shortcut section in the Manifest pane.", width="800", height="452" %} @@ -129,7 +129,7 @@ To inspect the screenshots, scroll to the **Screenshot #N** sections of the **Ma ### Test URL protocol handler registration {: #test-protocol-handler } PWAs can handle links that use a specific protocol for a more integrated experience. -To learn how to create a handler, see [URL protocol handler registration for PWAs](https://web.dev/url-protocol-handler/). +To learn how to create a handler, see [URL protocol handler registration for PWAs](https://web.dev/articles/url-protocol-handler). To test your handler: @@ -170,7 +170,7 @@ and debug service workers. - The {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/hmp8j3HiLMCcqPArD9yt.svg", alt="Checkbox.", width="22", height="22" %} **Update on reload** checkbox forces the service worker to update on every page load. - The {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/hmp8j3HiLMCcqPArD9yt.svg", alt="Checkbox.", width="22", height="22" %} **Bypass for network** checkbox bypasses the service worker and forces the browser to go to the network for requested resources. -- The **Network requests** link takes you to the **Network** panel with a list of intercepted requests related to the service worker (`is:service-worker-intercepted` filter). +- The **Network requests** link takes you to the **Network** panel with a list of intercepted requests related to the service worker (`is:service-worker-intercepted` filter). - The **Update** link performs a one-time update of the specified service worker. - The **Push** button emulates a push notification without a payload (also known as a [tickle][10]). - The **Sync** button emulates a background sync event. @@ -195,8 +195,8 @@ and debug service workers. To see the exact timestamp of each activity, click the {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/bJ1ZWs8NN8S0NaZnCHyQ.svg", alt="Expand.", width="20", height="20" %} **Expand** buttons. {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/8Zm0jydouqxuO3erPfBN.png", alt="Activities and their timestamps.", width="400", height="587" %} - - For more information, see [The service worker lifecycle](https://web.dev/service-worker-lifecycle/). + + For more information, see [The service worker lifecycle](https://web.dev/articles/service-worker-lifecycle). If the service worker causes any errors, the **Service Workers** pane shows an {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/99Zk6gIDdtxuEzPABtiy.png", alt="Error.", width="22", height="24" %} **Error** icon with the number of errors next to the **Source** line. The link with the number takes you to the **Console** with all the logged errors. diff --git a/site/en/docs/devtools/rendering/apply-effects/index.md b/site/en/docs/devtools/rendering/apply-effects/index.md index 9e0af179d..38a63b47d 100644 --- a/site/en/docs/devtools/rendering/apply-effects/index.md +++ b/site/en/docs/devtools/rendering/apply-effects/index.md @@ -97,7 +97,7 @@ With [Auto Dark Theme](/blog/auto-dark-theme/) enabled, the [**Emulate CSS media Everyone should be able to access and enjoy the web. [Google is committed to making that a reality](https://www.google.com/accessibility/). -With Chrome DevTools, you can see how people with [vision deficiencies](https://web.dev/learn/accessibility/color-contrast/) see your site, so you can make it better for them. For more information, see [Simulating color vision deficiencies](/blog/cvd/). +With Chrome DevTools, you can see how people with [vision deficiencies](https://web.dev/learn/accessibility/color-contrast) see your site, so you can make it better for them. For more information, see [Simulating color vision deficiencies](/blog/cvd/). To emulate vision deficiencies: @@ -106,7 +106,7 @@ To emulate vision deficiencies: - **No emulation**. - **Blurred vision**. - - **Reduced contrast**. + - **Reduced contrast**. - **Protanopia (no red)**. Low perception of red; confusion of greens, reds, and yellows. - **Deuteranopia (no green)**. Low perception of green; confusion of greens, reds, and yellows. - **Tritanopia (no blue)**. Low perception of blue; confusion of greens and blues. @@ -118,7 +118,7 @@ To emulate vision deficiencies: These emulations make it easier for developers to test different image loading scenarios without having to switch browsers. -Suppose you have the following HTML code to serve an image in [AVIF](https://web.dev/compress-images-avif/) and [WebP](https://web.dev/serve-images-webp/) formats for newer browsers, with a fallback PNG image for older browsers. +Suppose you have the following HTML code to serve an image in [AVIF](https://web.dev/articles/compress-images-avif) and [WebP](https://web.dev/articles/serve-images-webp) formats for newer browsers, with a fallback PNG image for older browsers. ```html <picture> @@ -136,8 +136,8 @@ To disable all AVIF images on a page (or, similarly, WebP images): {% Img src="image/admin/WHyF0XexaaWPCp07vJRj.png", alt="Emulate image types", width="800", height="480" %} -Similarly, you can disable WebP images. +Similarly, you can disable WebP images. {% Aside 'important' %} -These options disable image caching automatically. +These options disable image caching automatically. {% endAside %} diff --git a/site/en/docs/devtools/rendering/emulate-css/index.md b/site/en/docs/devtools/rendering/emulate-css/index.md index c08e496bb..b807fe598 100644 --- a/site/en/docs/devtools/rendering/emulate-css/index.md +++ b/site/en/docs/devtools/rendering/emulate-css/index.md @@ -25,7 +25,7 @@ The [`prefers-color-scheme` CSS media feature][7] indicates if the user prefers To emulate this condition: -1. On the [prefers-color-scheme](https://web.dev/prefers-color-scheme/) page, [open the **Rendering** tab](/docs/devtools/rendering#open-rendering). +1. On the [prefers-color-scheme](https://web.dev/articles/prefers-color-scheme) page, [open the **Rendering** tab](/docs/devtools/rendering#open-rendering). 1. Under the **Emulate CSS media feature `prefers-color-scheme`**, select one of the following from the drop-down list: - No emulation diff --git a/site/en/docs/devtools/rendering/performance/index.md b/site/en/docs/devtools/rendering/performance/index.md index e4c7ad554..1958eac74 100644 --- a/site/en/docs/devtools/rendering/performance/index.md +++ b/site/en/docs/devtools/rendering/performance/index.md @@ -34,7 +34,7 @@ If, on another page, you see the whole screen flash green or areas of the screen ## Highlight layout shift regions {: #layout-shift-regions } -[Layout shifts](https://web.dev/cls/) cause unexpected repaints and can be not only annoying but harmful. +[Layout shifts](https://web.dev/articles/cls) cause unexpected repaints and can be not only annoying but harmful. <figure> <video autoplay controls loop muted @@ -110,16 +110,16 @@ To view the potentially problematic elements: ## View Core Web Vitals -[Web Vitals](https://web.dev/vitals/) is an initiative by Google to provide unified guidance for quality signals that are essential to delivering a great user experience on the web. +[Web Vitals](https://web.dev/articles/vitals) is an initiative by Google to provide unified guidance for quality signals that are essential to delivering a great user experience on the web. Core Web Vitals are the subset of Web Vitals that apply to all web pages. Each of the Core Web Vitals represents a distinct facet of the user experience, is measurable in the field, and reflects the real-world experience of a critical user-centric outcome. The Core Web Vitals are: -- **[Largest Contentful Paint (LCP)](https://web.dev/lcp/)**: measures _loading_ performance. +- **[Largest Contentful Paint (LCP)](https://web.dev/articles/lcp)**: measures _loading_ performance. To provide a good user experience, LCP should occur within **2.5 seconds** of when the page first starts loading. -- **[First Input Delay (FID)](https://web.dev/fid/)**: measures _interactivity_. To provide a +- **[First Input Delay (FID)](https://web.dev/articles/fid)**: measures _interactivity_. To provide a good user experience, pages should have a FID of **100 milliseconds** or less. -- **[Cumulative Layout Shift (CLS)](https://web.dev/cls/)**: measures _visual stability_. To +- **[Cumulative Layout Shift (CLS)](https://web.dev/articles/cls)**: measures _visual stability_. To provide a good user experience, pages should maintain a CLS of **0.1.** or less. diff --git a/site/en/docs/devtools/settings/devices/index.md b/site/en/docs/devtools/settings/devices/index.md index 4c01ce7c5..ebbe172a9 100644 --- a/site/en/docs/devtools/settings/devices/index.md +++ b/site/en/docs/devtools/settings/devices/index.md @@ -30,7 +30,7 @@ If you don't see a device you want to test, add a custom one: {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/saf99v91L29TNeFEAKev.png", alt="Pixel 7 Pro device details.", width="800", height="1039" %} {% Aside 'gotchas' %} - For more information on what to specify, see [User-Agent Client Hints](https://web.dev/user-agent-client-hints/). + For more information on what to specify, see [User-Agent Client Hints](https://web.dev/articles/user-agent-client-hints). {% endAside %} 1. Click **Save**. Your device is enabled by default and you can select it from the **Dimensions** drop-down list in [device mode](/docs/devtools/device-mode/#device). diff --git a/site/en/docs/devtools/storage/applicationcache/index.md b/site/en/docs/devtools/storage/applicationcache/index.md index 9916ab967..ce778ce2e 100644 --- a/site/en/docs/devtools/storage/applicationcache/index.md +++ b/site/en/docs/devtools/storage/applicationcache/index.md @@ -13,7 +13,7 @@ tags: [mdn]: https://developer.mozilla.org/docs/Web/API/Window/applicationCache {% Aside 'warning' %} -Support for [AppCache][mdn] will be removed from Chrome and other Chromium-based browsers. We encourage developers to migrate off of AppCache now, rather than waiting any longer. Read [more](https://web.dev/appcache-removal/). +Support for [AppCache][mdn] will be removed from Chrome and other Chromium-based browsers. We encourage developers to migrate off of AppCache now, rather than waiting any longer. Read [more](https://web.dev/articles/appcache-removal). {% endAside %} This guide shows you how to use [Chrome DevTools](/docs/devtools/) to inspect @@ -47,4 +47,4 @@ can have the following statuses: * **CHECKING**. The manifest is being fetched and checked for updates. * **DOWNLOADING**. Resources are being added to the cache. * **UPDATEREADY**. A new version of the cache is available. -* **OBSOLETE**. The cache is being deleted. \ No newline at end of file +* **OBSOLETE**. The cache is being deleted. diff --git a/site/en/docs/extensions/migrating/to-service-workers/index.md b/site/en/docs/extensions/migrating/to-service-workers/index.md index 66f014473..027f4be64 100644 --- a/site/en/docs/extensions/migrating/to-service-workers/index.md +++ b/site/en/docs/extensions/migrating/to-service-workers/index.md @@ -9,7 +9,7 @@ updated: 2023-05-19 {% Partial 'extensions/mv3-support.md' %} -A service worker replaces the extension's background or event page to ensure that background code stays off the main thread. This enables extensions to run only when needed, saving resources. +A service worker replaces the extension's background or event page to ensure that background code stays off the main thread. This enables extensions to run only when needed, saving resources. Background pages have been a fundamental component of extensions since their introduction. To put it simply, background pages provide an environment that lives independent of any other window or tab. This allows extensions to observe and act in response to events. @@ -40,7 +40,7 @@ This page describes these tasks in detail. ## Update the "background" field in the manifest {: #update-bg-field } -In Manifest V3, background pages are replaced by a *service worker*. The manifest changes are listed below. +In Manifest V3, background pages are replaced by a *service worker*. The manifest changes are listed below. - Replace `"background.scripts"` with `"background.service_worker"` in the `manifest.json`. Note that the `"service_worker"` field takes a string, not an array of strings. - Remove `"background.persistent"` from the `manifest.json`. @@ -80,7 +80,7 @@ Migrating to a service worker (in other words, replacing the `"background.page"` {% endCompare %} </div> -The `"service_worker"` field takes a single string. You will only need the `"type"` field if you use [ES modules](https://web.dev/es-modules-in-sw/#static-imports-only) (using the [`import`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/import) keyword). Its value will always be `"module"`. For more information, see [Extension service worker basics](/docs/extensions/mv3/service_workers/basics/#import-scripts) +The `"service_worker"` field takes a single string. You will only need the `"type"` field if you use [ES modules](https://web.dev/articles/es-modules-in-sw#static_imports_only) (using the [`import`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/import) keyword). Its value will always be `"module"`. For more information, see [Extension service worker basics](/docs/extensions/mv3/service_workers/basics/#import-scripts) ## Move DOM and window calls to an offscreen document {: #move-dom-and-window } @@ -123,7 +123,7 @@ chrome.storage.local.get(["badgeText"], ({ badgeText }) => { chrome.browserAction.setBadgeText({ text: badgeText }); chrome.browserAction.onClicked.addListener(handleActionClick); }); -``` +``` This works with a persistent background page because the page is constantly running and never reinitialized. In Manifest V3, the service worker will be reinitialized when the event is dispatched. This means that when the event fires, the listeners will not be registered (since they are added asynchronously), and the event will be missed. @@ -139,12 +139,12 @@ chrome.storage.local.get(["badgeText"], ({ badgeText }) => { ## Replace XMLHttpRequest() with global fetch() {: #replace-xmlhttprequest } -`XMLHttpRequest()` can't be called from a service worker, extension or otherwise. Replace calls from your background script to `XMLHttpRequest()` with calls to [global `fetch()`](https://developer.mozilla.org/docs/Web/API/fetch). +`XMLHttpRequest()` can't be called from a service worker, extension or otherwise. Replace calls from your background script to `XMLHttpRequest()` with calls to [global `fetch()`](https://developer.mozilla.org/docs/Web/API/fetch). {% Compare 'worse', 'XMLHttpRequest()' %} ```javascript const xhr = new XMLHttpRequest(); -console.log('UNSENT', xhr.readyState); +console.log('UNSENT', xhr.readyState); xhr.open('GET', '/api', true); console.log('OPENED', xhr.readyState); @@ -189,7 +189,7 @@ chrome.browserAction.onClicked.addListener((tab) => { ``` {% endCompare %} -For Manifest V3, replace the global variable with a call to [Storage API](/docs/extensions/reference/storage/). +For Manifest V3, replace the global variable with a call to [Storage API](/docs/extensions/reference/storage/). {% Compare 'better', 'Manifest V3 service worker' %} ```js @@ -213,7 +213,7 @@ It's common to use delayed or periodic operations using the `setTimeout()` or `s {% Compare 'worse', 'Manifest V2 background script' %} ```js // 3 minutes in milliseconds -const TIMEOUT = 3 * 60 * 1000; +const TIMEOUT = 3 * 60 * 1000; setTimeout(() => { chrome.action.setIcon({ path: getRandomIconPath(), diff --git a/site/en/docs/extensions/mv2/cross-origin-isolation/index.md b/site/en/docs/extensions/mv2/cross-origin-isolation/index.md index f946fbd64..08a4b131b 100644 --- a/site/en/docs/extensions/mv2/cross-origin-isolation/index.md +++ b/site/en/docs/extensions/mv2/cross-origin-isolation/index.md @@ -37,7 +37,7 @@ will opt the extension's origin into cross-origin isolation. Opting into cross-origin isolation allows the extension to use powerful APIs like SharedArrayBuffers in its cross-origin isolated contexts. However, it does also come with certain side-effects. See -[Making your website "cross-origin isolated" using COOP and COEP](https://web.dev/coop-coep/) for +[Making your website "cross-origin isolated" using COOP and COEP](https://web.dev/articles/coop-coep) for more information on this. {% Aside 'caution' %} diff --git a/site/en/docs/extensions/mv3/cross-origin-isolation/index.md b/site/en/docs/extensions/mv3/cross-origin-isolation/index.md index a01ddaf9a..9c9d2e3a1 100644 --- a/site/en/docs/extensions/mv3/cross-origin-isolation/index.md +++ b/site/en/docs/extensions/mv3/cross-origin-isolation/index.md @@ -30,7 +30,7 @@ will opt the extension's origin into cross-origin isolation. Opting into cross-origin isolation allows the extension to use powerful APIs like SharedArrayBuffers in its cross-origin isolated contexts. However, it does also come with certain side-effects. See -[Making your website "cross-origin isolated" using COOP and COEP](https://web.dev/coop-coep/) for +[Making your website "cross-origin isolated" using COOP and COEP](https://web.dev/articles/coop-coep) for more information on this. {% Aside 'caution' %} diff --git a/site/en/docs/extensions/whatsnew/index.md b/site/en/docs/extensions/whatsnew/index.md index 76f26265d..52f2c7504 100644 --- a/site/en/docs/extensions/whatsnew/index.md +++ b/site/en/docs/extensions/whatsnew/index.md @@ -586,7 +586,7 @@ at a time. Both [Manifest V2](/docs/extensions/mv2/cross-origin-isolation/) and [Manifest V3](/docs/extensions/mv3/cross-origin-isolation/) extensions can now opt into [cross origin -isolation](https://web.dev/cross-origin-isolation-guide/). This feature limits which cross-origin +isolation](https://web.dev/articles/cross-origin-isolation-guide). This feature limits which cross-origin resources can load an extension's pages and enables the use of low level web platform features like [`SharedArrayBuffer`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer). Opt in will be required starting in Chrome 95. diff --git a/site/en/docs/handbook/components/index.md b/site/en/docs/handbook/components/index.md index e01d87c05..921ccd80f 100644 --- a/site/en/docs/handbook/components/index.md +++ b/site/en/docs/handbook/components/index.md @@ -278,7 +278,7 @@ Use `ChromeDate` when you want to refer to a specific milestone date in the Chro developer.chrome.com uses the same syntax highlighter as web.dev. -See the [Code](https://web.dev/handbook/markup-code/) post for more details. +See the [Code](https://web.dev/articles/handbook/markup-code) post for more details. ## Columns @@ -714,7 +714,7 @@ place the `Img` shortcode snippet inside: ## Labels -Labels can be used to display a filename associated with a [code](https://web.dev/handbook/markup-code/) snippet. +Labels can be used to display a filename associated with a [code](https://web.dev/articles/handbook/markup-code) snippet. ````text {% raw %}{% Label %}filename.js:{% endLabel %}{% endraw %} diff --git a/site/en/docs/handbook/how-to/add-a-landing-page/index.md b/site/en/docs/handbook/how-to/add-a-landing-page/index.md index 188d20a84..ccd79162d 100644 --- a/site/en/docs/handbook/how-to/add-a-landing-page/index.md +++ b/site/en/docs/handbook/how-to/add-a-landing-page/index.md @@ -18,7 +18,7 @@ image to our CDN. Once you've uploaded the image, copy the path out of the shortcode snippet, paste that into this field. - `imgAlt` — the description of the image. You can read more about writing effective alt text over on [the -web.dev handbook](https://web.dev/handbook/inclusion-and-accessibility/#use-inclusive-images). +web.dev handbook](https://web.dev/articles/handbook/inclusion-and-accessibility#use_inclusive_images). - `actionUrl`— an url of the CTA at the bottom of the card. - `actionText`— a text of the CTA at the bottom of the card. @@ -118,7 +118,7 @@ A featured section is a layout of cards on the same plane. The code below is the { postUrl: '/blog/insider-april-2022/', actionUrl: '/blog/insider-april-2022/', actionText: 'Discover' - }, + }, { customPost: { title: '#100CoolWebMoments', description: 'Take a stroll down memory lane and celebrate **#100CoolwebMoments** since Chrome’s first release — _lorem ipsum._', @@ -128,7 +128,7 @@ A featured section is a layout of cards on the same plane. The code below is the actionUrl: '/blog/insider-april-2022/', actionText: 'Discover the timeline' }, - ], utilities: 'grid-cols-1 lg:grid-cols-2') + ], utilities: 'grid-cols-1 lg:grid-cols-2') }} ``` @@ -147,7 +147,7 @@ A featured section is a layout of cards on the same plane. The code below is the { customPost: { title: '#100CoolWebMoments', - description: 'Take a stroll down memory lane and celebrate **#100CoolwebMoments** since Chrome’s first release — _lorem ipsum._', + description: 'Take a stroll down memory lane and celebrate **#100CoolwebMoments** since Chrome’s first release — _lorem ipsum._', imgSrc: 'image/kheDArv5csY6rvQUJDbWRscckLr1/AlyVvShYHBM5I7ikG8vj.jpg', imgAlt: '#100CoolWebMoments' }, diff --git a/site/en/docs/handbook/how-to/add-media/index.md b/site/en/docs/handbook/how-to/add-media/index.md index 507939d3e..8d5368077 100644 --- a/site/en/docs/handbook/how-to/add-media/index.md +++ b/site/en/docs/handbook/how-to/add-media/index.md @@ -42,7 +42,7 @@ Paste the copied code from the previous step into your article. Be sure to replace the text that says "ALT_TEXT_HERE" with your own description of the image. You can read more about writing effective alt text over on [the -web.dev handbook](https://web.dev/handbook/inclusion-and-accessibility/#use-inclusive-images). +web.dev handbook](https://web.dev/articles/handbook/inclusion-and-accessibility#use_inclusive_images). {% Aside %} You may notice that the generated code is using either the diff --git a/site/en/docs/lighthouse/accessibility/custom-control-roles/index.md b/site/en/docs/lighthouse/accessibility/custom-control-roles/index.md index 69172ebb3..65e283009 100644 --- a/site/en/docs/lighthouse/accessibility/custom-control-roles/index.md +++ b/site/en/docs/lighthouse/accessibility/custom-control-roles/index.md @@ -14,7 +14,7 @@ Check that all custom controls have an appropriate `role` and any required ARIA attributes that confer their properties and state. For example, a custom checkbox needs a `role="checkbox"` and `aria-checked="true|false"` to properly convey its state. -See the [Introduction to ARIA](https://web.dev/semantics-aria/) +See the [Introduction to ARIA](https://web.dev/articles/semantics-aria) for a general overview of how ARIA can provide missing semantics for custom controls. ## How to manually test @@ -36,7 +36,7 @@ A `<div>` is just a generic grouping element, so a screen reader only announces the text content of the `<div>`. The `<button>` is announced as a "button," a much stronger signal to the user that it's something they can interact with. -See also [Semantics and screen readers](https://web.dev/semantics-and-screen-readers/). +See also [Semantics and screen readers](https://web.dev/articles/semantics-and-screen-readers). ## How to fix @@ -67,9 +67,9 @@ Using a screen reader first hand will give you a clear understanding of how your content is labeled, and if there are any obstructions to assistive technology navigation. If you're unfamiliar with how semantic markup gets interpreted by assistive technology, -see the [Introduction to Semantics](https://web.dev/semantics-builtin/) for a refresher. +see the [Introduction to Semantics](https://web.dev/articles/semantics-builtin) for a refresher. -See also [How to Do an Accessibility Review](https://web.dev/how-to-review/#try-it-with-a-screen-reader). +See also [How to Do an Accessibility Review](https://web.dev/articles/how-to-review#try_it_with_a_screen_reader). ## Resources diff --git a/site/en/docs/lighthouse/accessibility/custom-controls-labels/index.md b/site/en/docs/lighthouse/accessibility/custom-controls-labels/index.md index 9e671986a..6c0325b40 100644 --- a/site/en/docs/lighthouse/accessibility/custom-controls-labels/index.md +++ b/site/en/docs/lighthouse/accessibility/custom-controls-labels/index.md @@ -14,7 +14,7 @@ Custom interactive controls should be focusable. If you use JavaScript to turn a `<div`> into a fancy dropdown, it won't automatically be inserted into the tab order. You need to manually check that all custom controls are keyboard focusable. -See also [Keyboard access fundamentals](https://web.dev/keyboard-access/). +See also [Keyboard access fundamentals](https://web.dev/articles/keyboard-access). ## How to manually test @@ -29,7 +29,7 @@ press the `TAB` key to navigate through the site: Are you able to reach all of the interactive controls on the page? If not, you may need to use `tabindex` to improve the focusability of those controls. -See also [Control focus with tabindex](https://web.dev/control-focus-with-tabindex/). +See also [Control focus with tabindex](https://web.dev/articles/control-focus-with-tabindex). ## How to fix @@ -48,7 +48,7 @@ keyboard navigation is the primary means of reaching everything on a screen. Good keyboarding experiences depend on a logical tab order and easily discernible focus styles. If a keyboard user can't see what's focused, they have no way of interacting with the page. -Learn more in [How to do an Accessibility Review](https://web.dev/how-to-review/#try-it-with-a-screen-reader). +Learn more in [How to do an Accessibility Review](https://web.dev/articles/how-to-review#try_it_with_a_screen_reader). ## Resources diff --git a/site/en/docs/lighthouse/accessibility/focus-traps/index.md b/site/en/docs/lighthouse/accessibility/focus-traps/index.md index 6e615d684..b67ee2c94 100644 --- a/site/en/docs/lighthouse/accessibility/focus-traps/index.md +++ b/site/en/docs/lighthouse/accessibility/focus-traps/index.md @@ -35,7 +35,7 @@ it makes sense to temporarily trap the user. But you should aim to provide a keyboard-accessible method of escaping the modal as well. Check out [this example on how to create an accessible modal](https://github.com/gdkraus/accessible-modal-dialog). -See also [Modals and Keyboard Traps](https://web.dev/using-tabindex/#modals-and-keyboard-traps). +See also [Modals and Keyboard Traps](https://web.dev/articles/using-tabindex#modals_and_keyboard_traps). In this example, you get the desired behaviors of a modal, without forcing the user to refresh the page to get out of the focus trap. @@ -48,7 +48,7 @@ Good keyboarding experiences depend on a logical tab order and easily discernibl If a keyboard user gets trapped in a particular page element, they have no way of interacting with the page. -Learn more in [How to do an Accessibility Review](https://web.dev/how-to-review/#try-it-with-a-screen-reader). +Learn more in [How to do an Accessibility Review](https://web.dev/articles/how-to-review#try_it_with_a_screen_reader). ## Resources diff --git a/site/en/docs/lighthouse/accessibility/focusable-controls/index.md b/site/en/docs/lighthouse/accessibility/focusable-controls/index.md index ec2145c69..c336dd5c9 100644 --- a/site/en/docs/lighthouse/accessibility/focusable-controls/index.md +++ b/site/en/docs/lighthouse/accessibility/focusable-controls/index.md @@ -14,7 +14,7 @@ Manually check that all custom controls are keyboard focusable and display a focus indicator. The order in which elements are focused should aim to follow the DOM order. If you're unsure which elements should receive focus, -see [Introduction to Focus](https://web.dev/focus/). +see [Introduction to Focus](https://web.dev/articles/focus). ## How to manually test @@ -24,7 +24,7 @@ start by tabbing through your site. Use `TAB` (or `SHIFT + TAB`) to move between controls, and use the arrow keys and `ENTER` and `SPACE` to manipulate their values -(see also [Keyboard access fundamentals](https://web.dev/keyboard-access/)): +(see also [Keyboard access fundamentals](https://web.dev/articles/keyboard-access)): {% Glitch { id: 'interactive-elements', @@ -42,7 +42,7 @@ you may need to use `tabindex` to improve the focusability of those controls. To make a custom control focusable, insert the custom control element into the natural tab order using `tabindex="0"` -(see also [Control focus with tabindex](https://web.dev/control-focus-with-tabindex/)). +(see also [Control focus with tabindex](https://web.dev/articles/control-focus-with-tabindex)). For example: ```html @@ -56,7 +56,7 @@ If you're not seeing a focus indicator, consider using `:focus` to always show a focus indicator. Regardless of whether you use a mouse or a keyboard to tab to it, the button's focus indicator always looks the same -(see also [Style focus](https://web.dev/style-focus/)). +(see also [Style focus](https://web.dev/articles/style-focus)). {% Glitch { id: 'focus-style', @@ -71,10 +71,10 @@ keyboard navigation is the primary means of reaching everything on a screen. Good keyboarding experiences depend on a logical tab order and easily discernible focus styles. If a keyboard user can't see what's focused, they have no way of interacting with the page. -Learn more in [How to do an Accessibility Review](https://web.dev/how-to-review/#try-it-with-a-screen-reader). +Learn more in [How to do an Accessibility Review](https://web.dev/articles/how-to-review#try_it_with_a_screen_reader). ## Resources - [Source code for **Interactive controls are keyboard focusable** audit](https://github.com/GoogleChrome/lighthouse/blob/master/core/audits/accessibility/manual/focusable-controls.js) - [Some elements have a `[tabindex]` value greater than `0`](https://dequeuniversity.com/rules/axe/4.4/tabindex) -- [Use semantic HTML for easy keyboard wins](https://web.dev/use-semantic-html/) +- [Use semantic HTML for easy keyboard wins](https://web.dev/articles/use-semantic-html) diff --git a/site/en/docs/lighthouse/accessibility/interactive-element-affordance/index.md b/site/en/docs/lighthouse/accessibility/interactive-element-affordance/index.md index 7be52b70b..bd255030d 100644 --- a/site/en/docs/lighthouse/accessibility/interactive-element-affordance/index.md +++ b/site/en/docs/lighthouse/accessibility/interactive-element-affordance/index.md @@ -30,7 +30,7 @@ The `:focus` pseudo-class lets you apply a uniform style to an element. That style is applied any time the element is focused, regardless of the input device or method used to focus it. -Learn more in [Style focus](https://web.dev/style-focus/). +Learn more in [Style focus](https://web.dev/articles/style-focus). ## How to manually test with a screen reader @@ -47,7 +47,7 @@ Users of screen readers and other assistive technologies rely on labels to understand the context of that element. Vague labels are common, and they are non-helpful for navigating content. -Learn how to improve [Labels and text alternatives](https://web.dev/labels-and-text-alternatives/). +Learn how to improve [Labels and text alternatives](https://web.dev/articles/labels-and-text-alternatives). ## Why this matters diff --git a/site/en/docs/lighthouse/accessibility/logical-tab-order/index.md b/site/en/docs/lighthouse/accessibility/logical-tab-order/index.md index 6b0d3011b..9ad275e83 100644 --- a/site/en/docs/lighthouse/accessibility/logical-tab-order/index.md +++ b/site/en/docs/lighthouse/accessibility/logical-tab-order/index.md @@ -25,7 +25,7 @@ In general, focus should follow reading order, moving from left to right, from the top to the bottom of your page. -Learn more in [Keyboard access fundamentals](https://web.dev/keyboard-access/). +Learn more in [Keyboard access fundamentals](https://web.dev/articles/keyboard-access). Are you able to reach all of the interactive controls on the page? If not, you may need to use `tabindex` to improve the focusability of those controls. diff --git a/site/en/docs/lighthouse/accessibility/offscreen-content-hidden/index.md b/site/en/docs/lighthouse/accessibility/offscreen-content-hidden/index.md index e5a7a8518..ba07d7d39 100644 --- a/site/en/docs/lighthouse/accessibility/offscreen-content-hidden/index.md +++ b/site/en/docs/lighthouse/accessibility/offscreen-content-hidden/index.md @@ -48,7 +48,7 @@ For example: <button class="remove-me">Can't reach me with the TAB key!</button> ``` -See also [Correctly set the visibility of offscreen content](https://web.dev/keyboard-access/#correctly-set-the-visibility-of-offscreen-content). +See also [Correctly set the visibility of offscreen content](https://web.dev/articles/keyboard-access#correctly_set_the_visibility_of_offscreen_content). ## Resources diff --git a/site/en/docs/lighthouse/accessibility/visual-order-follows-dom/index.md b/site/en/docs/lighthouse/accessibility/visual-order-follows-dom/index.md index 1bd79ff3b..b0f7542a1 100644 --- a/site/en/docs/lighthouse/accessibility/visual-order-follows-dom/index.md +++ b/site/en/docs/lighthouse/accessibility/visual-order-follows-dom/index.md @@ -32,7 +32,7 @@ Notice any jumps in navigation that seem jarring. Also notice any offscreen jumps, where tabbing brings you to content that's not meant to be visible. -Learn more in [Keyboard access fundamentals](https://web.dev/keyboard-access/). +Learn more in [Keyboard access fundamentals](https://web.dev/articles/keyboard-access). ## How to fix @@ -47,7 +47,7 @@ move the element to an earlier position in the DOM. If offscreen content is still accessible to keyboard controls, consider removing it using `tabindex="-1"`. -Learn more in [Control focus with tabindex](https://web.dev/control-focus-with-tabindex/). +Learn more in [Control focus with tabindex](https://web.dev/articles/control-focus-with-tabindex). ## Resources diff --git a/site/en/docs/lighthouse/best-practices/csp-xss/index.md b/site/en/docs/lighthouse/best-practices/csp-xss/index.md index 6594e08ab..530514fe8 100644 --- a/site/en/docs/lighthouse/best-practices/csp-xss/index.md +++ b/site/en/docs/lighthouse/best-practices/csp-xss/index.md @@ -7,7 +7,7 @@ date: 2021-06-16 #updated: 2021-06-02 --- -A Content Security Policy (CSP) helps to ensure any content loaded in the page is trusted by the site owner. CSPs mitigate cross-site scripting (XSS) attacks because they can block unsafe scripts injected by attackers. However, the CSP can easily be bypassed if it is not strict enough. Check out [Mitigate cross-site scripting (XSS) with a strict Content Security Policy (CSP)](https://web.dev/strict-csp/) for more information. Lighthouse collects CSPs enforced on the main document, and reports issues from [CSP Evaluator](https://csp-evaluator.withgoogle.com/) if they can be bypassed. +A Content Security Policy (CSP) helps to ensure any content loaded in the page is trusted by the site owner. CSPs mitigate cross-site scripting (XSS) attacks because they can block unsafe scripts injected by attackers. However, the CSP can easily be bypassed if it is not strict enough. Check out [Mitigate cross-site scripting (XSS) with a strict Content Security Policy (CSP)](https://web.dev/articles/strict-csp) for more information. Lighthouse collects CSPs enforced on the main document, and reports issues from [CSP Evaluator](https://csp-evaluator.withgoogle.com/) if they can be bypassed. <figure> {% Img src="image/9B7J9oWjgsWbuE84mmxDaY37Wpw2/EFTWlPiCrPOn6ETCRiGr.png", @@ -32,7 +32,7 @@ To target XSS, a CSP should include the `script-src`, `object-src`, and `base-ur A CSP that configures an allowlist for `script-src` relies on the assumption that all responses coming from a trusted domain are safe, and can be executed as scripts. However, this assumption does not hold for modern applications; some common, benign patterns such as exposing [JSONP interfaces](https://lcamtuf.blogspot.ch/2011/08/subtle-deadly-problem-with-csp.html) and [hosting copies of the AngularJS library](https://github.com/cure53/XSSChallengeWiki/wiki/H5SC-Minichallenge-3:-%22Sh*t,-it's-CSP!%22) allow attackers to escape the confines of CSP. -In practice, while it may not be obvious to application authors, [the majority of `script-src` allowlists can be circumvented](https://research.google.com/pubs/pub45542.html) by an attacker with an XSS bug, and provide little protection against script injection. In contrast, the [nonce-based and hash-based approaches](https://web.dev/strict-csp/#what-is-a-strict-content-security-policy) do not suffer from these problems and make it easier to adopt and maintain a more secure policy. +In practice, while it may not be obvious to application authors, [the majority of `script-src` allowlists can be circumvented](https://research.google.com/pubs/pub45542.html) by an attacker with an XSS bug, and provide little protection against script injection. In contrast, the [nonce-based and hash-based approaches](https://web.dev/articles/strict-csp#what_is_a_strict_content_security_policy) do not suffer from these problems and make it easier to adopt and maintain a more secure policy. For example, this code uses a JSONP endpoint hosted on a trusted domain to inject an attacker controlled script: @@ -95,6 +95,6 @@ HTML: <script nonce="random123" src="https://trusted.example.com/trusted_script.js"></script> ``` -`random123` would be any base64 string generated server-side every time the page loads. `unsafe-inline` and `https:` are ignored in modern browsers because of the nonce and `strict-dynamic`. For more information about adopting a strict CSP, check out the [Strict CSP guide](https://web.dev/strict-csp/#adopting-a-strict-csp). +`random123` would be any base64 string generated server-side every time the page loads. `unsafe-inline` and `https:` are ignored in modern browsers because of the nonce and `strict-dynamic`. For more information about adopting a strict CSP, check out the [Strict CSP guide](https://web.dev/articles/strict-csp#adopting_a_strict_csp). You can check a CSP for potential bypasses using Lighthouse and [CSP Evaluator](https://csp-evaluator.withgoogle.com/). If you want to test a new CSP without the risk of breaking existing pages, define the CSP in report-only mode by using `Content-Security-Policy-Report-Only` as the header name. This will send CSP violations to any reporting destinations you have configured with `report-to` and `report-uri`, but it will not actually enforce the CSP. diff --git a/site/en/docs/lighthouse/best-practices/external-anchors-use-rel-noopener/index.md b/site/en/docs/lighthouse/best-practices/external-anchors-use-rel-noopener/index.md index 34d63b647..9e0b9a384 100644 --- a/site/en/docs/lighthouse/best-practices/external-anchors-use-rel-noopener/index.md +++ b/site/en/docs/lighthouse/best-practices/external-anchors-use-rel-noopener/index.md @@ -70,11 +70,11 @@ but also prevents the `Referer` header from being sent to the new page. See [Link type "noreferrer"](https://html.spec.whatwg.org/multipage/links.html#link-type-noreferrer). -See the [Share cross-origin resources safely](https://web.dev/cross-origin-resource-sharing/) +See the [Share cross-origin resources safely](https://web.dev/articles/cross-origin-resource-sharing) post for more information. ## Resources - [Source code for **Links to cross-origin destinations are unsafe** audit](https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js) -- [Share cross-origin resources safely](https://web.dev/cross-origin-resource-sharing/) +- [Share cross-origin resources safely](https://web.dev/articles/cross-origin-resource-sharing) - [Site isolation for web developers](/blog/site-isolation/) diff --git a/site/en/docs/lighthouse/best-practices/image-aspect-ratio/index.md b/site/en/docs/lighthouse/best-practices/image-aspect-ratio/index.md index 5c5aa6f5b..135830254 100644 --- a/site/en/docs/lighthouse/best-practices/image-aspect-ratio/index.md +++ b/site/en/docs/lighthouse/best-practices/image-aspect-ratio/index.md @@ -34,8 +34,8 @@ There are two common causes for an incorrect image aspect ratio: ### Use an image CDN An image CDN can make it easier to automate the process of creating different sized -versions of your images. Check out [Use image CDNs to optimize images](https://web.dev/image-cdns/) -for an overview and [How to install the Thumbor image CDN](https://web.dev/install-thumbor/) for a +versions of your images. Check out [Use image CDNs to optimize images](https://web.dev/articles/image-cdns) +for an overview and [How to install the Thumbor image CDN](https://web.dev/articles/install-thumbor) for a hands-on codelab. ### Check the CSS that affects the image's aspect ratio @@ -61,7 +61,7 @@ until you know the viewport dimensions. Consider using the [aspect ratio boxes](https://css-tricks.com/aspect-ratio-boxes/) to help preserve aspect ratios for responsive images. -Finally, check out the [Serve images with correct dimensions](https://web.dev/serve-images-with-correct-dimensions/) +Finally, check out the [Serve images with correct dimensions](https://web.dev/articles/serve-images-with-correct-dimensions) post to learn how to serve images that are the right size for each user's device. ## Resources @@ -69,6 +69,6 @@ post to learn how to serve images that are the right size for each user's device - [Source code for **Displays images with incorrect aspect ratio** audit](https://github.com/GoogleChrome/lighthouse/blob/main/core/audits/image-aspect-ratio.js) - [CSS Aspect Ratio](https://www.npmjs.com/package/css-aspect-ratio) - [Aspect Ratio Boxes](https://css-tricks.com/aspect-ratio-boxes/) -- [Serve images with correct dimensions](https://web.dev/serve-images-with-correct-dimensions/) +- [Serve images with correct dimensions](https://web.dev/articles/serve-images-with-correct-dimensions) [ar]: https://en.wikipedia.org/wiki/Aspect_ratio_(image) diff --git a/site/en/docs/lighthouse/best-practices/notification-on-start/index.md b/site/en/docs/lighthouse/best-practices/notification-on-start/index.md index 45b74511b..93ae89e74 100644 --- a/site/en/docs/lighthouse/best-practices/notification-on-start/index.md +++ b/site/en/docs/lighthouse/best-practices/notification-on-start/index.md @@ -8,7 +8,7 @@ date: 2019-05-02 updated: 2019-08-28 --- -Good notifications are [timely, relevant, and precise](https://web.dev/notifications/). +Good notifications are [timely, relevant, and precise](https://web.dev/articles/notifications). If your page asks for permission to send notifications on page load, those notifications may not be relevant to your users or their needs. @@ -45,4 +45,4 @@ To provide a better user experience: ## Resources - [Source code for **Requests the notification permission on page load** audit](https://github.com/GoogleChrome/lighthouse/blob/main/core/audits/dobetterweb/notification-on-start.js) -- [Web Push Notifications: Timely, Relevant, and Precise](https://web.dev/notifications/) +- [Web Push Notifications: Timely, Relevant, and Precise](https://web.dev/articles/notifications) diff --git a/site/en/docs/lighthouse/best-practices/uses-http2/index.md b/site/en/docs/lighthouse/best-practices/uses-http2/index.md index b12c55627..6260b1242 100644 --- a/site/en/docs/lighthouse/best-practices/uses-http2/index.md +++ b/site/en/docs/lighthouse/best-practices/uses-http2/index.md @@ -37,5 +37,5 @@ see [Setting up HTTP/2](https://dassur.ma/things/h2setup/). ## Resources - [Source code for **Does not use HTTP/2 for all of its resources** audit](https://github.com/GoogleChrome/lighthouse/blob/main/core/audits/dobetterweb/uses-http2.js) -- [Introduction to HTTP/2](https://web.dev/performance-http2/) +- [Introduction to HTTP/2](https://web.dev/articles/performance-http2) - [HTTP/2 Frequently Asked Questions](https://http2.github.io/faq/) diff --git a/site/en/docs/lighthouse/performance/bf-cache/index.md b/site/en/docs/lighthouse/performance/bf-cache/index.md index cc7dd95ee..30f2d76ae 100644 --- a/site/en/docs/lighthouse/performance/bf-cache/index.md +++ b/site/en/docs/lighthouse/performance/bf-cache/index.md @@ -54,7 +54,7 @@ If the page could not be restored from bfcache for any reason, the audit will fa ## Resources - - [Back/forward cache](https://web.dev/bfcache/) + - [Back/forward cache](https://web.dev/articles/bfcache) - [Test bfcache in DevTools](/docs/devtools/application/back-forward-cache/) - [Source code for the bfcache audit](https://github.com/GoogleChrome/lighthouse/blob/main/core/audits/bf-cache.js) diff --git a/site/en/docs/lighthouse/performance/bootup-time/index.md b/site/en/docs/lighthouse/performance/bootup-time/index.md index 32bcc61c2..2ca38fbfa 100644 --- a/site/en/docs/lighthouse/performance/bootup-time/index.md +++ b/site/en/docs/lighthouse/performance/bootup-time/index.md @@ -26,7 +26,7 @@ it slows down your page performance in several ways: JavaScript is also executed on the main thread. If your page runs a lot of code before it's really needed, - that also delays your [Time To Interactive](https://web.dev/tti/), + that also delays your [Time To Interactive](https://web.dev/articles/tti), which is one of the key metrics related to how users perceive your page speed. - **Memory cost** diff --git a/site/en/docs/lighthouse/performance/critical-request-chains/index.md b/site/en/docs/lighthouse/performance/critical-request-chains/index.md index 63771c6bb..42d02e831 100644 --- a/site/en/docs/lighthouse/performance/critical-request-chains/index.md +++ b/site/en/docs/lighthouse/performance/critical-request-chains/index.md @@ -8,7 +8,7 @@ date: 2019-05-02 updated: 2020-04-29 --- -[Critical request chains](https://web.dev/critical-rendering-path/) +[Critical request chains](https://web.dev/articles/critical-rendering-path) are series of dependent network requests important for page rendering. The greater the length of the chains and the larger the download sizes, the more significant the impact on page load performance. @@ -41,10 +41,10 @@ Use the critical request chains audit results to target the resources that have - Optimize the order in which the remaining critical resources are loaded: download all critical assets as early as possible to shorten the critical path length. Learn more about optimizing your -[images](https://web.dev/use-imagemin-to-compress-images/), -[JavaScript](https://web.dev/apply-instant-loading-with-prpl/), -[CSS](https://web.dev/defer-non-critical-css/), and -[web fonts](https://web.dev/avoid-invisible-text/). +[images](https://web.dev/articles/use-imagemin-to-compress-images), +[JavaScript](https://web.dev/articles/apply-instant-loading-with-prpl), +[CSS](https://web.dev/articles/defer-non-critical-css), and +[web fonts](https://web.dev/articles/avoid-invisible-text). ## Stack-specific guidance diff --git a/site/en/docs/lighthouse/performance/dom-size/index.md b/site/en/docs/lighthouse/performance/dom-size/index.md index 574ae23e1..850870e6f 100644 --- a/site/en/docs/lighthouse/performance/dom-size/index.md +++ b/site/en/docs/lighthouse/performance/dom-size/index.md @@ -22,7 +22,7 @@ A large DOM tree can slow down your page performance in multiple ways: As users and scripts interact with your page, the browser must constantly - [recompute the position and styling of nodes](https://web.dev/reduce-the-scope-and-complexity-of-style-calculations/). + [recompute the position and styling of nodes](https://web.dev/articles/reduce-the-scope-and-complexity-of-style-calculations). A large DOM tree in combination with complicated style rules can severely slow down rendering. - **Memory performance** @@ -72,12 +72,12 @@ for more information. ### Angular -If you're rendering large lists, use [virtual scrolling](https://web.dev/virtualize-lists-with-angular-cdk/) with the Component Dev Kit (CDK). +If you're rendering large lists, use [virtual scrolling](https://web.dev/articles/virtualize-lists-with-angular-cdk) with the Component Dev Kit (CDK). ### React - Use a "windowing" library like - [`react-window`](https://web.dev/virtualize-long-lists-react-window/) to minimize the number + [`react-window`](https://web.dev/articles/virtualize-long-lists-react-window) to minimize the number of DOM nodes created if you are rendering many repeated elements on the page. - Minimize unnecessary re-renders using [`shouldComponentUpdate`](https://reactjs.org/docs/optimizing-performance.html#shouldcomponentupdate-in-action), @@ -90,4 +90,4 @@ If you're rendering large lists, use [virtual scrolling](https://web.dev/virtual ## Resources - [Source code for **Avoid an excessive DOM size** audit](https://github.com/GoogleChrome/lighthouse/blob/main/core/audits/dobetterweb/dom-size.js) -- [Reduce the Scope and Complexity of Style Calculations](https://web.dev/reduce-the-scope-and-complexity-of-style-calculations/) +- [Reduce the Scope and Complexity of Style Calculations](https://web.dev/articles/reduce-the-scope-and-complexity-of-style-calculations) diff --git a/site/en/docs/lighthouse/performance/efficient-animated-content/index.md b/site/en/docs/lighthouse/performance/efficient-animated-content/index.md index 79beb7665..8e3cc231b 100644 --- a/site/en/docs/lighthouse/performance/efficient-animated-content/index.md +++ b/site/en/docs/lighthouse/performance/efficient-animated-content/index.md @@ -66,7 +66,7 @@ Luckily, you can recreate these behaviors using the `<video>` element. ## Use a service that converts GIFs to HTML5 videos -Many [image CDNs](https://web.dev/image-cdns/) support GIF to HTML5 video conversion. You upload a +Many [image CDNs](https://web.dev/articles/image-cdns) support GIF to HTML5 video conversion. You upload a GIF to the image CDN, and the image CDN returns an HTML5 video. ## Stack-specific guidance @@ -80,5 +80,5 @@ usage when the content is offscreen. ## Resources - [Source code for **Use video formats for animated content** audit](https://github.com/GoogleChrome/lighthouse/blob/main/core/audits/byte-efficiency/efficient-animated-content.js) -- [Replace animated GIFs with video for faster page loads](https://web.dev/replace-gifs-with-videos/) -- [Replace GIFs with video codelab](https://web.dev/codelab-replace-gifs-with-video/) +- [Replace animated GIFs with video for faster page loads](https://web.dev/articles/replace-gifs-with-videos) +- [Replace GIFs with video codelab](https://web.dev/articles/codelab-replace-gifs-with-video) diff --git a/site/en/docs/lighthouse/performance/estimated-input-latency/index.md b/site/en/docs/lighthouse/performance/estimated-input-latency/index.md index 8412e4b13..c3cc7f62e 100644 --- a/site/en/docs/lighthouse/performance/estimated-input-latency/index.md +++ b/site/en/docs/lighthouse/performance/estimated-input-latency/index.md @@ -30,7 +30,7 @@ to the end of the trace, which is roughly 5 seconds after [Time to Interactive](http://web.dev/tti/). If your latency is higher than 50 ms, users may perceive your app as laggy. -The [RAIL performance model](https://web.dev/rail/) +The [RAIL performance model](https://web.dev/articles/rail) recommends that apps respond to user input within 100 ms, while Lighthouse's Estimated Input Latency target score is 50 ms. Why? Lighthouse uses a proxy metric—availability of the main thread—to measure @@ -49,7 +49,7 @@ Approximately 90% of users will encounter Lighthouse's reported amount of input To make your app respond to user input faster, optimize how your code runs in the browser. Check out the series of techniques outlined on Google's -[Rendering Performance](https://web.dev/rendering-performance/) page. +[Rendering Performance](https://web.dev/articles/rendering-performance) page. These tips range from offloading computation to web workers to free up the main thread, to refactoring your CSS selectors to perform fewer calculations, to using CSS properties that minimize the amount of browser-intensive operations. @@ -68,13 +68,13 @@ See [Do less main thread work](/docs/devtools/lighthouse/#main) for an example of the workflow. The basic idea is to start a recording, perform the user input that you want to measure, stop the recording, and then analyze the flame chart to ensure that -[all stages of the pixel pipeline](https://web.dev/rendering-performance/#the-pixel-pipeline) +[all stages of the pixel pipeline](https://web.dev/articles/rendering-performance#the_pixel_pipeline) are complete within 50 ms. ## Resources - [Source code for **Estimated Input Latency** audit](https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/audits/metrics/estimated-input-latency.js) - [Lighthouse v3 Scoring Guide](/docs/lighthouse/performance/performance-scoring/) -- [Measure Performance with the RAIL Model](https://web.dev/rail/) -- [Rendering Performance](https://web.dev/rendering-performance/) +- [Measure Performance with the RAIL Model](https://web.dev/articles/rail) +- [Rendering Performance](https://web.dev/articles/rendering-performance) - [Optimize Website Speed With Chrome DevTools](/docs/devtools/overview/#start) diff --git a/site/en/docs/lighthouse/performance/first-contentful-paint/index.md b/site/en/docs/lighthouse/performance/first-contentful-paint/index.md index a61c537b5..319bf0df3 100644 --- a/site/en/docs/lighthouse/performance/first-contentful-paint/index.md +++ b/site/en/docs/lighthouse/performance/first-contentful-paint/index.md @@ -80,7 +80,7 @@ see Google's [User-centric Performance Metrics][metrics] page. The [Tracking FP/FCP][tracking] section describes how to programmatically access FCP data and submit it to Google Analytics. -See Google's [Assessing Loading Performance in Real Life with Navigation and Resource Timing](https://web.dev/navigation-and-resource-timing/) +See Google's [Assessing Loading Performance in Real Life with Navigation and Resource Timing](https://web.dev/articles/navigation-and-resource-timing) for more on collecting real-user metrics. {% Partial 'lighthouse-performance/improve.njk' %} @@ -88,7 +88,7 @@ for more on collecting real-user metrics. ## Resources - [Source code for **First Contentful Paint** audit](https://github.com/GoogleChrome/lighthouse/blob/main/core/audits/metrics/first-contentful-paint.js) -- [FCP Metric Guide](https://web.dev/fcp/) +- [FCP Metric Guide](https://web.dev/articles/fcp) - [Lighthouse Scoring Guide](/docs/lighthouse/performance/performance-scoring/) - [Paint Timing specification](https://w3c.github.io/paint-timing) diff --git a/site/en/docs/lighthouse/performance/first-meaningful-paint/index.md b/site/en/docs/lighthouse/performance/first-meaningful-paint/index.md index 03666eefe..bbf685c7e 100644 --- a/site/en/docs/lighthouse/performance/first-meaningful-paint/index.md +++ b/site/en/docs/lighthouse/performance/first-meaningful-paint/index.md @@ -13,7 +13,7 @@ First Meaningful Paint (FMP) is deprecated in Lighthouse 6.0. In practice FMP has been overly sensitive to small differences in the page load, leading to inconsistent (bimodal) results. Additionally, the metric's definition relies on browser-specific implementation details, which means it cannot be standardized nor implemented in all web -browsers. Moving forward, consider using [Largest Contentful Paint](https://web.dev/lcp/) +browsers. Moving forward, consider using [Largest Contentful Paint](https://web.dev/articles/lcp) instead. {% endAside %} @@ -37,7 +37,7 @@ after which the biggest above-the-fold layout change happens. Learn more about the technical details of FMP in Google's [Time to First Meaningful Paint: a layout-based approach](https://docs.google.com/document/d/1BR94tJdZLsin5poeet0XoTW60M0SjvOJQttKT-JK8HI/view). -[First Contentful Paint (FCP)](https://web.dev/fcp/) +[First Contentful Paint (FCP)](https://web.dev/articles/fcp) and FMP are often the same when the first bit of content rendered on the page includes the content above the fold. However, these metrics can differ when, for example, @@ -104,7 +104,7 @@ see Google's [User-centric Performance Metrics][metrics] page. The [Tracking FMP using hero elements][tracking] section describes how to programmatically access FCP data and submit it to Google Analytics. -See Google's [Assessing Loading Performance in Real Life with Navigation and Resource Timing](https://web.dev/navigation-and-resource-timing/) +See Google's [Assessing Loading Performance in Real Life with Navigation and Resource Timing](https://web.dev/articles/navigation-and-resource-timing) for more on collecting real-user metrics. The [User Timing marks and measures Lighthouse audit](/docs/lighthouse/performance/user-timings/) enables you to see User Timing data in your report. @@ -116,7 +116,7 @@ enables you to see User Timing data in your report. - [Source code for **First Meaningful Paint** audit](https://github.com/GoogleChrome/lighthouse/blob/main/core/audits/metrics/first-meaningful-paint.js) - [Lighthouse v3 Scoring Guide](https://developers.google.com/web/tools/lighthouse/v3/scoring) - [Time to First Meaningful Paint: a layout-based approach](https://docs.google.com/document/d/1BR94tJdZLsin5poeet0XoTW60M0SjvOJQttKT-JK8HI/view) -- [Largest Contentful Paint](https://web.dev/lcp/) +- [Largest Contentful Paint](https://web.dev/articles/lcp) [metrics]: https://web.dev/user-centric-performance-metrics/ [tracking]: https://web.dev/user-centric-performance-metrics/ diff --git a/site/en/docs/lighthouse/performance/font-display/index.md b/site/en/docs/lighthouse/performance/font-display/index.md index e83a0b5d5..6ab889ea0 100644 --- a/site/en/docs/lighthouse/performance/font-display/index.md +++ b/site/en/docs/lighthouse/performance/font-display/index.md @@ -10,7 +10,7 @@ updated: 2020-04-29 Fonts are often large files with slow load times. Some browsers hide text until the font loads, -causing a [flash of invisible text (FOIT)](https://web.dev/avoid-invisible-text/). +causing a [flash of invisible text (FOIT)](https://web.dev/articles/avoid-invisible-text). ## How the Lighthouse font-display audit fails @@ -46,15 +46,15 @@ The [font-display API](https://developer.mozilla.org/docs/Web/CSS/@font-face/fon specifies how a font is displayed. `swap` tells the browser that text using the font should be displayed immediately using a system font. Once the custom font is ready, it replaces the system font. -(See the [Avoid invisible text during loading](https://web.dev/avoid-invisible-text/) post +(See the [Avoid invisible text during loading](https://web.dev/articles/avoid-invisible-text) post for more information.) ### Preload web fonts Use `<link rel="preload" as="font">` to fetch your font files earlier. Learn more: -- [Preload web fonts to improve loading speed (codelab)](https://web.dev/codelab-preload-web-fonts/) -- [Prevent layout shifting and flashes of invisibile text (FOIT) by preloading optional fonts](https://web.dev/preload-optional-fonts/) +- [Preload web fonts to improve loading speed (codelab)](https://web.dev/articles/codelab-preload-web-fonts) +- [Prevent layout shifting and flashes of invisibile text (FOIT) by preloading optional fonts](https://web.dev/articles/preload-optional-fonts) ### Google Fonts @@ -90,7 +90,7 @@ Specify `@font-display` when [defining custom fonts](https://devdocs.magento.com ## Resources - [Source code for **Ensure text remains visible during webfont load** audit](https://github.com/GoogleChrome/lighthouse/blob/main/core/audits/font-display.js) -- [Avoid invisible text during loading](https://web.dev/avoid-invisible-text/) +- [Avoid invisible text during loading](https://web.dev/articles/avoid-invisible-text) - [Controlling font performance with font displays](/blog/font-display/) -- [Preload web fonts to improve loading speed (codelab)](https://web.dev/codelab-preload-web-fonts/) -- [Prevent layout shifting and flashes of invisible text (FOIT) by preloading optional fonts](https://web.dev/preload-optional-fonts/) +- [Preload web fonts to improve loading speed (codelab)](https://web.dev/articles/codelab-preload-web-fonts) +- [Prevent layout shifting and flashes of invisible text (FOIT) by preloading optional fonts](https://web.dev/articles/preload-optional-fonts) diff --git a/site/en/docs/lighthouse/performance/interactive/index.md b/site/en/docs/lighthouse/performance/interactive/index.md index 6736603fc..1c2e03e48 100644 --- a/site/en/docs/lighthouse/performance/interactive/index.md +++ b/site/en/docs/lighthouse/performance/interactive/index.md @@ -30,7 +30,7 @@ TTI measures how long it takes a page to become _fully_ interactive. A page is considered fully interactive when: - The page displays useful content, which is measured by the - [First Contentful Paint](https://web.dev/fcp/), + [First Contentful Paint](https://web.dev/articles/fcp), - Event handlers are registered for most visible page elements, and - The page responds to user interactions within 50 milliseconds. @@ -85,9 +85,9 @@ This table shows how to interpret your TTI score: One improvement that can have a particularly big effect on TTI is deferring or removing unnecessary JavaScript work. -Look for opportunities to [optimize your JavaScript](https://web.dev/fast/#optimize-your-javascript). -In particular, consider [reducing JavaScript payloads with code splitting](https://web.dev/reduce-javascript-payloads-with-code-splitting/) -and [applying the PRPL pattern](https://web.dev/apply-instant-loading-with-prpl/). [Optimizing third-party JavaScript][3p] +Look for opportunities to [optimize your JavaScript](https://web.dev/articles/fast#optimize_your_javascript). +In particular, consider [reducing JavaScript payloads with code splitting](https://web.dev/articles/reduce-javascript-payloads-with-code-splitting) +and [applying the PRPL pattern](https://web.dev/articles/apply-instant-loading-with-prpl). [Optimizing third-party JavaScript][3p] also yields significant improvements for some sites. These two Diagnostic audits provide additional opportunities @@ -105,7 +105,7 @@ how to programmatically access TTI data and submit it to Google Analytics. {% Aside %} TTI can be difficult to track in the wild. -Tracking [First Input Delay](https://web.dev/fid/) +Tracking [First Input Delay](https://web.dev/articles/fid) can be a good proxy for TTI. {% endAside %} @@ -116,8 +116,8 @@ can be a good proxy for TTI. - [Source code for **Time to Interactive** audit](https://github.com/GoogleChrome/lighthouse/blob/main/core/audits/metrics/interactive.js) - [Lighthouse Scoring Guide](/docs/lighthouse/performance/performance-scoring/) - [First Interactive And Consistently Interactive](https://docs.google.com/document/d/1GGiI9-7KeY3TPqS3YT271upUVimo-XiL5mwWorDUD4c/edit) -- [JavaScript Start-up Optimization](https://web.dev/optimizing-content-efficiency-javascript-startup-optimization/) -- [Reduce JavaScript Payloads with Tree Shaking](https://web.dev/reduce-javascript-payloads-with-tree-shaking/) +- [JavaScript Start-up Optimization](https://web.dev/articles/optimizing-content-efficiency-javascript-startup-optimization) +- [Reduce JavaScript Payloads with Tree Shaking](https://web.dev/articles/reduce-javascript-payloads-with-tree-shaking) - [Optimize third-party resources][3p] [metrics]: https://web.dev/user-centric-performance-metrics/ diff --git a/site/en/docs/lighthouse/performance/lighthouse-largest-contentful-paint/index.md b/site/en/docs/lighthouse/performance/lighthouse-largest-contentful-paint/index.md index 83b19422a..6616beac6 100644 --- a/site/en/docs/lighthouse/performance/lighthouse-largest-contentful-paint/index.md +++ b/site/en/docs/lighthouse/performance/lighthouse-largest-contentful-paint/index.md @@ -66,7 +66,7 @@ Lighthouse will display the LCP element along with the phase breakdown in the "L | LCP phase | Description | | ------------------------- | ----------- | -| Time to first byte (TTFB) | The time from when the user initiates loading the page until when the browser receives the first byte of the HTML document response. [Learn more about TTFB](https://web.dev/ttfb/). | +| Time to first byte (TTFB) | The time from when the user initiates loading the page until when the browser receives the first byte of the HTML document response. [Learn more about TTFB](https://web.dev/articles/ttfb). | | Load delay | The delta between TTFB and when the browser starts loading the LCP resource. | | Load time | The time it takes to load the LCP resource itself. | | Render delay | The delta between when the LCP resource finishes loading until the LCP element is fully rendered. | @@ -74,7 +74,7 @@ Lighthouse will display the LCP element along with the phase breakdown in the "L ## Resources - [Source code for **Largest Contentful Paint** audit](https://github.com/GoogleChrome/lighthouse/blob/main/core/audits/metrics/largest-contentful-paint.js) -- [Largest Contentful Paint](https://web.dev/lcp/) +- [Largest Contentful Paint](https://web.dev/articles/lcp) - [Largest Contentful Paint API](https://wicg.github.io/largest-contentful-paint/) [definition]: https://web.dev/lcp/#what-is-lcp diff --git a/site/en/docs/lighthouse/performance/lighthouse-max-potential-fid/index.md b/site/en/docs/lighthouse/performance/lighthouse-max-potential-fid/index.md index 59111cb58..707b67eaa 100644 --- a/site/en/docs/lighthouse/performance/lighthouse-max-potential-fid/index.md +++ b/site/en/docs/lighthouse/performance/lighthouse-max-potential-fid/index.md @@ -9,7 +9,7 @@ updated: 2019-10-16 --- {% Aside 'caution' %} -Max Potential First Input Delay was deprecated in Lighthouse 6.0. Moving forward, consider using [Total Blocking Time](https://web.dev/lcp/) in the lab and [First Input Delay](https://web.dev/fid/) and [Interaction to Next Paint](https://web.dev/inp/) in the field. +Max Potential First Input Delay was deprecated in Lighthouse 6.0. Moving forward, consider using [Total Blocking Time](https://web.dev/articles/lcp) in the lab and [First Input Delay](https://web.dev/articles/fid) and [Interaction to Next Paint](https://web.dev/articles/inp) in the field. {% endAside %} Max Potential First Input Delay (FID) is one of the metrics @@ -104,7 +104,7 @@ about how to evaluate the FID data you collect. - [Source code for **Max Potential First Input Delay** audit](https://github.com/GoogleChrome/lighthouse/blob/main/core/audits/metrics/max-potential-fid.js) - [First Input Delay][fid] - [Time to Interactive](http://web.dev/tti/) -- [Are long JavaScript tasks delaying your Time to Interactive?](https://web.dev/long-tasks-devtools/) +- [Are long JavaScript tasks delaying your Time to Interactive?](https://web.dev/articles/long-tasks-devtools) - [First paint and first contentful paint][fcp] - [How To Think About Speed Tools][tools] diff --git a/site/en/docs/lighthouse/performance/lighthouse-total-blocking-time/index.md b/site/en/docs/lighthouse/performance/lighthouse-total-blocking-time/index.md index 601b2a699..311b95352 100644 --- a/site/en/docs/lighthouse/performance/lighthouse-total-blocking-time/index.md +++ b/site/en/docs/lighthouse/performance/lighthouse-total-blocking-time/index.md @@ -63,7 +63,7 @@ This table shows how to interpret your TBT score: ## How to improve your TBT score -See [What is causing my long tasks?](https://web.dev/long-tasks-devtools/#what-is-causing-my-long-tasks) to learn +See [What is causing my long tasks?](https://web.dev/articles/long-tasks-devtools#what_is_causing_my_long_tasks) to learn how to diagnose the root cause of long tasks with the Performance panel of Chrome DevTools. In general, the most common causes of long tasks are: diff --git a/site/en/docs/lighthouse/performance/mainthread-work-breakdown/index.md b/site/en/docs/lighthouse/performance/mainthread-work-breakdown/index.md index 12327bd09..9f699f3c9 100644 --- a/site/en/docs/lighthouse/performance/mainthread-work-breakdown/index.md +++ b/site/en/docs/lighthouse/performance/mainthread-work-breakdown/index.md @@ -48,34 +48,34 @@ as the page loads. ### Script evaluation -- [Optimize third-party JavaScript](https://web.dev/fast/#optimize-your-third-party-resources) -- [Debounce your input handlers](https://web.dev/debounce-your-input-handlers/) -- [Use web workers](https://web.dev/off-main-thread/) +- [Optimize third-party JavaScript](https://web.dev/articles/fast#optimize_your_third_party_resources) +- [Debounce your input handlers](https://web.dev/articles/debounce-your-input-handlers) +- [Use web workers](https://web.dev/articles/off-main-thread) ### Style and layout -- [Reduce the scope and complexity of style calculations](https://web.dev/reduce-the-scope-and-complexity-of-style-calculations/) -- [Avoid large, complex layouts and layout thrashing](https://web.dev/avoid-large-complex-layouts-and-layout-thrashing/) +- [Reduce the scope and complexity of style calculations](https://web.dev/articles/reduce-the-scope-and-complexity-of-style-calculations) +- [Avoid large, complex layouts and layout thrashing](https://web.dev/articles/avoid-large-complex-layouts-and-layout-thrashing) ### Rendering -- [Stick to compositor only properties and manage layer count](https://web.dev/stick-to-compositor-only-properties-and-manage-layer-count/) -- [Simplify paint complexity and reduce paint areas](https://web.dev/simplify-paint-complexity-and-reduce-paint-areas/) +- [Stick to compositor only properties and manage layer count](https://web.dev/articles/stick-to-compositor-only-properties-and-manage-layer-count) +- [Simplify paint complexity and reduce paint areas](https://web.dev/articles/simplify-paint-complexity-and-reduce-paint-areas) ### Parsing HTML and CSS -- [Extract critical CSS](https://web.dev/extract-critical-css/) -- [Minify CSS](https://web.dev/minify-css/) -- [Defer non-critical CSS](https://web.dev/defer-non-critical-css/) +- [Extract critical CSS](https://web.dev/articles/extract-critical-css) +- [Minify CSS](https://web.dev/articles/minify-css) +- [Defer non-critical CSS](https://web.dev/articles/defer-non-critical-css) ### Script parsing and compilation -- [Reduce JavaScript payloads with code splitting](https://web.dev/reduce-javascript-payloads-with-code-splitting/) -- [Remove unused code](https://web.dev/remove-unused-code/) +- [Reduce JavaScript payloads with code splitting](https://web.dev/articles/reduce-javascript-payloads-with-code-splitting) +- [Remove unused code](https://web.dev/articles/remove-unused-code) ### Garbage collection -- [Monitor your web page's total memory usage with `measureMemory()`](https://web.dev/monitor-total-page-memory-usage/) +- [Monitor your web page's total memory usage with `measureMemory()`](https://web.dev/articles/monitor-total-page-memory-usage) ## Resources diff --git a/site/en/docs/lighthouse/performance/non-composited-animations/index.md b/site/en/docs/lighthouse/performance/non-composited-animations/index.md index f66322eb7..f41ad23e6 100644 --- a/site/en/docs/lighthouse/performance/non-composited-animations/index.md +++ b/site/en/docs/lighthouse/performance/non-composited-animations/index.md @@ -7,7 +7,7 @@ date: 2020-08-12 Non-composited animations can appear [janky](https://en.wiktionary.org/wiki/jank) (not smooth) on low-end phones or when performance-heavy tasks are running on the main thread. Janky animations can increase the -[Cumulative Layout Shift](https://web.dev/cls/) (CLS) of your page. Reducing CLS will improve your +[Cumulative Layout Shift](https://web.dev/articles/cls) (CLS) of your page. Reducing CLS will improve your Lighthouse Performance score. ## Background diff --git a/site/en/docs/lighthouse/performance/offscreen-images/index.md b/site/en/docs/lighthouse/performance/offscreen-images/index.md index 03eb96e4a..76eec71f4 100644 --- a/site/en/docs/lighthouse/performance/offscreen-images/index.md +++ b/site/en/docs/lighthouse/performance/offscreen-images/index.md @@ -46,7 +46,7 @@ plugin](https://extensions.joomla.org/instant-search/?jed_live%5Bquery%5D=amp). ### Magento Consider modifying your product and catalog templates to make use of the web -platform's [lazy loading](https://web.dev/browser-level-image-lazy-loading/) feature. +platform's [lazy loading](https://web.dev/articles/browser-level-image-lazy-loading) feature. ### WordPress diff --git a/site/en/docs/lighthouse/performance/performance-scoring/index.md b/site/en/docs/lighthouse/performance/performance-scoring/index.md index 8e9570916..aa286fa5c 100644 --- a/site/en/docs/lighthouse/performance/performance-scoring/index.md +++ b/site/en/docs/lighthouse/performance/performance-scoring/index.md @@ -30,7 +30,7 @@ problems include: Furthermore, even though Lighthouse can provide you a single overall Performance score, it might be more useful to think of your site performance as a distribution of scores, rather than a single number. -See the introduction of [User-Centric Performance Metrics](https://web.dev/user-centric-performance-metrics/) +See the introduction of [User-Centric Performance Metrics](https://web.dev/articles/user-centric-performance-metrics) to understand why. ## How the Performance score is weighted {: #weightings } diff --git a/site/en/docs/lighthouse/performance/redirects/index.md b/site/en/docs/lighthouse/performance/redirects/index.md index c0ff9ca5b..f262b3a9e 100644 --- a/site/en/docs/lighthouse/performance/redirects/index.md +++ b/site/en/docs/lighthouse/performance/redirects/index.md @@ -38,11 +38,11 @@ A page fails this audit when it has two or more redirects. Point links to flagged resources to the resources' current locations. It's especially important to avoid redirects in resources -required for your [Critical Rendering Path](https://web.dev/critical-rendering-path/). +required for your [Critical Rendering Path](https://web.dev/articles/critical-rendering-path). If you're using redirects to divert mobile users to the mobile version of your page, consider redesigning your site to use -[Responsive Design](https://web.dev/responsive-web-design-basics/). +[Responsive Design](https://web.dev/articles/responsive-web-design-basics). ## Stack-specific guidance diff --git a/site/en/docs/lighthouse/performance/render-blocking-resources/index.md b/site/en/docs/lighthouse/performance/render-blocking-resources/index.md index 61afe12f1..506ee0390 100644 --- a/site/en/docs/lighthouse/performance/render-blocking-resources/index.md +++ b/site/en/docs/lighthouse/performance/render-blocking-resources/index.md @@ -66,9 +66,9 @@ When the page loads, it will have what it needs to handle the page's core functi If there's code in a render-blocking URL that's not critical, you can keep it in the URL, and then mark the URL with `async` or `defer` attributes -(see also [Adding Interactivity with JavaScript](https://web.dev/critical-rendering-path-adding-interactivity-with-javascript/)). +(see also [Adding Interactivity with JavaScript](https://web.dev/articles/critical-rendering-path-adding-interactivity-with-javascript)). -Code that isn't being used at all should be removed (see [Remove unused code](https://web.dev/remove-unused-code/)). +Code that isn't being used at all should be removed (see [Remove unused code](https://web.dev/articles/remove-unused-code)). ## How to eliminate render-blocking stylesheets @@ -76,7 +76,7 @@ Similar to inlining code in a `<script>` tag, inline critical styles required for the first paint inside a `<style>` block at the `head` of the HTML page. Then load the rest of the styles asynchronously using the `preload` link -(see [Defer unused CSS](https://web.dev/defer-non-critical-css/)). +(see [Defer unused CSS](https://web.dev/articles/defer-non-critical-css)). Consider automating the process of extracting and inlining "Above the Fold" CSS using the [Critical tool](https://github.com/addyosmani/critical/blob/master/README.md). @@ -86,10 +86,10 @@ to split up those styles into different files, organized by media query. Then add a media attribute to each stylesheet link. When loading a page, the browser only blocks the first paint to retrieve the stylesheets that match the user's device -(see [Render-Blocking CSS](https://web.dev/critical-rendering-path-render-blocking-css/)). +(see [Render-Blocking CSS](https://web.dev/articles/critical-rendering-path-render-blocking-css)). Finally, you'll want to minify your CSS to remove any extra whitespace or -characters (see [Minify CSS](https://web.dev/minify-css/)). +characters (see [Minify CSS](https://web.dev/articles/minify-css)). This ensures that you're sending the smallest possible bundle to your users. ## Stack-specific guidance @@ -122,6 +122,6 @@ resources](https://wordpress.org/plugins/search/defer+css+javascript/). ## Resources - [Source code for **Eliminate render-blocking resources** audit](https://github.com/GoogleChrome/lighthouse/blob/main/core/audits/byte-efficiency/render-blocking-resources.js) -- [Reduce JavaScript payloads with code splitting](https://web.dev/reduce-javascript-payloads-with-code-splitting/) +- [Reduce JavaScript payloads with code splitting](https://web.dev/articles/reduce-javascript-payloads-with-code-splitting) - [Remove unused code codelab](https://web.dev/codelab-remove-unused-code) -- [JavaScript Start-up Optimization](https://web.dev/optimizing-content-efficiency-javascript-startup-optimization/) +- [JavaScript Start-up Optimization](https://web.dev/articles/optimizing-content-efficiency-javascript-startup-optimization) diff --git a/site/en/docs/lighthouse/performance/resource-summary/index.md b/site/en/docs/lighthouse/performance/resource-summary/index.md index 008a741c0..5eb60fdff 100644 --- a/site/en/docs/lighthouse/performance/resource-summary/index.md +++ b/site/en/docs/lighthouse/performance/resource-summary/index.md @@ -79,7 +79,7 @@ Affected metrics: [First Contentful Paint][fcp] ## Use performance budgets to prevent regressions Once you've optimized your code to reduce request counts and transfer sizes, see -[Set performance budgets](https://web.dev/fast/#set-performance-budgets) to learn how to prevent regressions. +[Set performance budgets](https://web.dev/articles/fast#set_performance_budgets) to learn how to prevent regressions. ## Resources diff --git a/site/en/docs/lighthouse/performance/server-response-time/index.md b/site/en/docs/lighthouse/performance/server-response-time/index.md index 3898c7893..d3715d12d 100644 --- a/site/en/docs/lighthouse/performance/server-response-time/index.md +++ b/site/en/docs/lighthouse/performance/server-response-time/index.md @@ -20,9 +20,9 @@ This audit fails when the browser waits more than 600 ms for the server to When users navigate to a URL in their web browser, the browser makes a network request to fetch that content. Your server receives the request and returns the page content. {% Aside 'important' %} -Server response time is only part of the full [Time to First Byte (TTFB)](https://web.dev/ttfb/). As well as including the server response time, TTFB can often include DNS lookups and redirects (for example, if the final slash or the www subdomain or https protocol is omitted then the server might redirect to the correct URL, or for URL shorteners or Ads that redirect via several domains). Many Lighthouse tests will test the end URL, missing the redirect time, but even when this is not the case, the server response time will exclude these parts. +Server response time is only part of the full [Time to First Byte (TTFB)](https://web.dev/articles/ttfb). As well as including the server response time, TTFB can often include DNS lookups and redirects (for example, if the final slash or the www subdomain or https protocol is omitted then the server might redirect to the correct URL, or for URL shorteners or Ads that redirect via several domains). Many Lighthouse tests will test the end URL, missing the redirect time, but even when this is not the case, the server response time will exclude these parts. -For this reason, Lighthouse has a smaller limit (600 ms) to the [Core Web Vitals TTFB recommended time](https://web.dev/ttfb/#what-is-a-good-ttfb-score) (800 ms). +For this reason, Lighthouse has a smaller limit (600 ms) to the [Core Web Vitals TTFB recommended time](https://web.dev/articles/ttfb#what_is_a_good_ttfb_score) (800 ms). {% endAside %} The server may need to do a lot of work in order to return a page with all of the content that users want. For example, if users are looking at their order history, the server needs to fetch each user's history from a database, and then insert that content into the page. Optimizing the server to do work like this as quickly as possible is one way to reduce the time that users spend waiting for pages to load. @@ -41,7 +41,7 @@ There are many possible causes of slow server responses, and therefore many poss Use a CDN to reduce network latency. This is particularly effective if the document can be cached at the CDN edge node. -See the [Optimize TTFB](https://web.dev/optimize-ttfb/) guide for more details. +See the [Optimize TTFB](https://web.dev/articles/optimize-ttfb) guide for more details. ## Stack-specific guidance @@ -64,5 +64,5 @@ Themes, plugins, and server specifications all contribute to server response tim ## Resources - [Source code for **Reduce server response times (TTFB)** audit](https://github.com/GoogleChrome/lighthouse/blob/main/core/audits/server-response-time.js) -- [Time to First Byte documentation](https://web.dev/ttfb/) -- [Optimizing TTFB guide](https://web.dev/optimize-ttfb/) +- [Time to First Byte documentation](https://web.dev/articles/ttfb) +- [Optimizing TTFB guide](https://web.dev/articles/optimize-ttfb) diff --git a/site/en/docs/lighthouse/performance/third-party-facades/index.md b/site/en/docs/lighthouse/performance/third-party-facades/index.md index 43732f2c3..75d542add 100644 --- a/site/en/docs/lighthouse/performance/third-party-facades/index.md +++ b/site/en/docs/lighthouse/performance/third-party-facades/index.md @@ -7,9 +7,9 @@ date: 2020-12-01 #updated: 2020-12-01 --- -[Third-party resources](https://web.dev/third-party-javascript/) are often used for displaying ads or videos and integrating with social media. +[Third-party resources](https://web.dev/articles/third-party-javascript) are often used for displaying ads or videos and integrating with social media. The default approach is to load third-party resources as soon as the page loads, but this can unnecessarily slow the page load. If the third-party -content is not critical, this performance cost can be reduced by [lazy loading](https://web.dev/fast/#lazy-load-images-and-video) it. +content is not critical, this performance cost can be reduced by [lazy loading](https://web.dev/articles/fast#lazy_load_images_and_video) it. This audit highlights third-party embeds which can be lazily loaded on interaction. In that case, a _facade_ is used in place of the third-party content until the user interacts with it. diff --git a/site/en/docs/lighthouse/performance/third-party-summary/index.md b/site/en/docs/lighthouse/performance/third-party-summary/index.md index fe62a387a..266d77cff 100644 --- a/site/en/docs/lighthouse/performance/third-party-summary/index.md +++ b/site/en/docs/lighthouse/performance/third-party-summary/index.md @@ -10,7 +10,7 @@ updated: 2019-10-04 To add an advertising network, social media button, A/B test, or analytics service to your page, you usually need to add a third-party script to your HTML. These [third-party scripts can -significantly affect your page load performance](https://web.dev/third-party-javascript/). +significantly affect your page load performance](https://web.dev/articles/third-party-javascript). ## How the Lighthouse audit for third-party code fails @@ -28,14 +28,14 @@ the audit fails. ## How to reduce the impact of third-party code -See [Identify slow third-party scripts](https://web.dev/identify-slow-third-party-javascript/) to learn how to use +See [Identify slow third-party scripts](https://web.dev/articles/identify-slow-third-party-javascript) to learn how to use Chrome DevTools and other Lighthouse audits to detect problematic third-party code, and -see [Efficiently load third-party JavaScript](https://web.dev/efficiently-load-third-party-javascript/) for +see [Efficiently load third-party JavaScript](https://web.dev/articles/efficiently-load-third-party-javascript) for optimization strategies. ## Resources - [Source code for **Reduce the impact of third-party code** audit](https://github.com/GoogleChrome/lighthouse/blob/main/core/audits/third-party-summary.js) -- [Loading Third-party JavaScript](https://web.dev/optimizing-content-efficiency-loading-third-party-javascript/) +- [Loading Third-party JavaScript](https://web.dev/articles/optimizing-content-efficiency-loading-third-party-javascript) [main thread]: https://developer.mozilla.org/docs/Glossary/Main_thread diff --git a/site/en/docs/lighthouse/performance/total-byte-weight/index.md b/site/en/docs/lighthouse/performance/total-byte-weight/index.md index e24f4c835..53c735815 100644 --- a/site/en/docs/lighthouse/performance/total-byte-weight/index.md +++ b/site/en/docs/lighthouse/performance/total-byte-weight/index.md @@ -47,23 +47,23 @@ while still achieving a [Time to Interactive](http://web.dev/tti/) of 10 se Here are some ways to keep payload size down: - Defer requests until they're needed. - See the [PRPL Pattern](https://web.dev/apply-instant-loading-with-prpl/) for one possible approach. + See the [PRPL Pattern](https://web.dev/articles/apply-instant-loading-with-prpl) for one possible approach. - Optimize requests to be as small as possible. Possible techniques include: - - [Minify and compress network payloads](https://web.dev/reduce-network-payloads-using-text-compression/). - - [Use WebP instead of JPEG or PNG for your images](https://web.dev/serve-images-webp/). - - [Set the compression level of JPEG images to 85](https://web.dev/use-imagemin-to-compress-images/). + - [Minify and compress network payloads](https://web.dev/articles/reduce-network-payloads-using-text-compression). + - [Use WebP instead of JPEG or PNG for your images](https://web.dev/articles/serve-images-webp). + - [Set the compression level of JPEG images to 85](https://web.dev/articles/use-imagemin-to-compress-images). - Cache requests so that the page doesn't re-download the resources - on repeat visits. (See the [Network reliability landing page](https://web.dev/reliable/) + on repeat visits. (See the [Network reliability landing page](https://web.dev/explore/reliable) to learn how caching works and how to implement it.) ## Stack-specific guidance ### Angular -Apply [route-level code splitting](https://web.dev/route-level-code-splitting-in-angular/) to +Apply [route-level code splitting](https://web.dev/articles/route-level-code-splitting-in-angular) to minimize the size of your JavaScript bundles. Also, consider precaching assets with the [Angular service -worker](https://web.dev/precaching-with-the-angular-service-worker/). +worker](https://web.dev/articles/precaching-with-the-angular-service-worker). ### Drupal diff --git a/site/en/docs/lighthouse/performance/unminified-css/index.md b/site/en/docs/lighthouse/performance/unminified-css/index.md index a0a824918..048a3bfaa 100644 --- a/site/en/docs/lighthouse/performance/unminified-css/index.md +++ b/site/en/docs/lighthouse/performance/unminified-css/index.md @@ -76,7 +76,7 @@ you probably want to set up an automated workflow that minifies your CSS automat before you deploy your updated code. This is usually accomplished with a build tool like Gulp or Webpack. -Learn how to minify your CSS code in [Minify CSS](https://web.dev/minify-css/). +Learn how to minify your CSS code in [Minify CSS](https://web.dev/articles/minify-css). ## Stack-specific guidance @@ -119,5 +119,5 @@ to use a build process to do this minification up-front if possible. ## Resources - [Source code for **Minify CSS** audit](https://github.com/GoogleChrome/lighthouse/blob/main/core/audits/byte-efficiency/unminified-css.js) -- [Minify CSS](https://web.dev/minify-css/) -- [Minify and compress network payloads](https://web.dev/reduce-network-payloads-using-text-compression/) +- [Minify CSS](https://web.dev/articles/minify-css) +- [Minify and compress network payloads](https://web.dev/articles/reduce-network-payloads-using-text-compression) diff --git a/site/en/docs/lighthouse/performance/unused-css-rules/index.md b/site/en/docs/lighthouse/performance/unused-css-rules/index.md index c5529d38b..f073b4dd6 100644 --- a/site/en/docs/lighthouse/performance/unused-css-rules/index.md +++ b/site/en/docs/lighthouse/performance/unused-css-rules/index.md @@ -44,7 +44,7 @@ These extra network trips can significantly increase the time that users must wait before they see any content on their screens. Unused CSS also slows down a browser's construction of the -[render tree](https://web.dev/critical-rendering-path-render-tree-construction/). +[render tree](https://web.dev/articles/critical-rendering-path-render-tree-construction). The render tree is like the DOM tree, except that it also includes the styles for each node. To construct the render tree, a browser must walk the entire DOM tree, and check which CSS rules apply to each node. The more unused CSS there is, @@ -75,7 +75,7 @@ Then load the rest of the styles asynchronously using the `preload` link. Consider automating the process of extracting and inlining "Above the Fold" CSS using the [Critical tool](https://github.com/addyosmani/critical/blob/master/README.md). -Learn more in [Defer non-critical CSS](https://web.dev/defer-non-critical-css/). +Learn more in [Defer non-critical CSS](https://web.dev/articles/defer-non-critical-css). ## Stack-specific guidance diff --git a/site/en/docs/lighthouse/performance/unused-javascript/index.md b/site/en/docs/lighthouse/performance/unused-javascript/index.md index edb79c7d9..5629cc629 100644 --- a/site/en/docs/lighthouse/performance/unused-javascript/index.md +++ b/site/en/docs/lighthouse/performance/unused-javascript/index.md @@ -79,7 +79,7 @@ bundling](https://devdocs.magento.com/guides/v2.3/frontend-dev-guide/themes/js-b ### React If you are not server-side rendering, [split your JavaScript -bundles](https://web.dev/code-splitting-suspense/) with `React.lazy()`. +bundles](https://web.dev/articles/code-splitting-suspense) with `React.lazy()`. Otherwise, code-split using a third-party library such as [loadable-components](https://www.smooth-code.com/open-source/loadable-components/docs/getting-started/). @@ -95,7 +95,7 @@ plugins](https://wordpress.org/plugins/) loading unused JavaScript in your page. ## Resources - [Source code for the **Remove unused code** audit](https://github.com/GoogleChrome/lighthouse/blob/main/core/audits/byte-efficiency/unused-javascript.js) -- [Remove unused code](https://web.dev/remove-unused-code/) +- [Remove unused code](https://web.dev/articles/remove-unused-code) - [Adding interactivity with JavaScript][crp] - [Code Splitting][split] - [Dead Code Elimination][eliminate] diff --git a/site/en/docs/lighthouse/performance/user-timings/index.md b/site/en/docs/lighthouse/performance/user-timings/index.md index 5a99aee6f..6101f7987 100644 --- a/site/en/docs/lighthouse/performance/user-timings/index.md +++ b/site/en/docs/lighthouse/performance/user-timings/index.md @@ -20,7 +20,7 @@ extracting detailed timing data that you can use to optimize your code. You can access those data from JavaScript using the API or by viewing them on your [Chrome DevTools Timeline Recordings](/docs/devtools/evaluate-performance/performance-reference/). -Check out the [page about the User Timing API](https://web.dev/usertiming/) +Check out the [page about the User Timing API](https://web.dev/articles/usertiming) for a quick introduction to using it. ## How Lighthouse reports User Timing data @@ -55,4 +55,4 @@ your components. - [Source code for **User Timing marks and measures** audit](https://github.com/GoogleChrome/lighthouse/blob/main/core/audits/user-timings.js) - [User Timing API (MDN)](https://developer.mozilla.org/docs/Web/API/User_Timing_API) -- [User Timing API (web.dev)](https://web.dev/usertiming/) +- [User Timing API (web.dev)](https://web.dev/articles/usertiming) diff --git a/site/en/docs/lighthouse/performance/uses-long-cache-ttl/index.md b/site/en/docs/lighthouse/performance/uses-long-cache-ttl/index.md index 58206aa03..1d5ca2226 100644 --- a/site/en/docs/lighthouse/performance/uses-long-cache-ttl/index.md +++ b/site/en/docs/lighthouse/performance/uses-long-cache-ttl/index.md @@ -91,8 +91,8 @@ it's up to you to decide what the optimal cache duration is for your resources. There are many directives for customizing how the browser caches different resources. Learn more about caching resources in -[The HTTP cache: your first line of defense guide](https://web.dev/http-cache/) -and [Configuring HTTP caching behavior codelab](https://web.dev/codelab-http-cache/). +[The HTTP cache: your first line of defense guide](https://web.dev/articles/http-cache) +and [Configuring HTTP caching behavior codelab](https://web.dev/articles/codelab-http-cache). ## How to verify cached responses in Chrome DevTools diff --git a/site/en/docs/lighthouse/performance/uses-optimized-images/index.md b/site/en/docs/lighthouse/performance/uses-optimized-images/index.md index c645a6cae..223bfd0cb 100644 --- a/site/en/docs/lighthouse/performance/uses-optimized-images/index.md +++ b/site/en/docs/lighthouse/performance/uses-optimized-images/index.md @@ -26,13 +26,13 @@ If the potential savings are 4KiB or greater, Lighthouse flags the image as opti There are many steps you can take to optimize your images, including: -- [Using image CDNs](https://web.dev/image-cdns/) -- [Compressing images](https://web.dev/use-imagemin-to-compress-images/) -- [Replacing animated GIFs with video](https://web.dev/replace-gifs-with-videos/) -- [Lazy loading images](https://web.dev/use-lazysizes-to-lazyload-images/) -- [Serving responsive images](https://web.dev/serve-responsive-images/) -- [Serving images with correct dimensions](https://web.dev/serve-images-with-correct-dimensions/) -- [Using WebP images](https://web.dev/serve-images-webp/) +- [Using image CDNs](https://web.dev/articles/image-cdns) +- [Compressing images](https://web.dev/articles/use-imagemin-to-compress-images) +- [Replacing animated GIFs with video](https://web.dev/articles/replace-gifs-with-videos) +- [Lazy loading images](https://web.dev/articles/use-lazysizes-to-lazyload-images) +- [Serving responsive images](https://web.dev/articles/serve-responsive-images) +- [Serving images with correct dimensions](https://web.dev/articles/serve-images-with-correct-dimensions) +- [Using WebP images](https://web.dev/articles/serve-images-webp) ## Optimize images using GUI tools diff --git a/site/en/docs/lighthouse/performance/uses-rel-preconnect/index.md b/site/en/docs/lighthouse/performance/uses-rel-preconnect/index.md index 3ec0f6afc..0d42b9c96 100644 --- a/site/en/docs/lighthouse/performance/uses-rel-preconnect/index.md +++ b/site/en/docs/lighthouse/performance/uses-rel-preconnect/index.md @@ -83,5 +83,5 @@ and add preconnect or DNS prefetch resource hints. - [Source code for **Preconnect to required origins** audit](https://github.com/GoogleChrome/lighthouse/blob/main/core/audits/uses-rel-preconnect.js) - [Resource Prioritization–Getting the Browser to Help You](https://developers.google.com/web/fundamentals/performance/resource-prioritization#preconnect) -- [Establish network connections early to improve perceived page speed](https://web.dev/preconnect-and-dns-prefetch/) +- [Establish network connections early to improve perceived page speed](https://web.dev/articles/preconnect-and-dns-prefetch) - [Link types: preconnect](https://developer.mozilla.org/docs/Web/HTML/Link_types/preconnect#Browser_compatibility) diff --git a/site/en/docs/lighthouse/performance/uses-rel-preload/index.md b/site/en/docs/lighthouse/performance/uses-rel-preload/index.md index 2bd1c9f62..5369fcb3a 100644 --- a/site/en/docs/lighthouse/performance/uses-rel-preload/index.md +++ b/site/en/docs/lighthouse/performance/uses-rel-preload/index.md @@ -71,7 +71,7 @@ as soon as possible. </figcaption> </figure> -See also [Preload critical assets to improve loading speed](https://web.dev/preload-critical-assets/) +See also [Preload critical assets to improve loading speed](https://web.dev/articles/preload-critical-assets) for more guidance. ### Browser compatibility @@ -89,7 +89,7 @@ page. ### Angular -[Preload routes](https://web.dev/route-preloading-in-angular/) ahead of time to speed up navigation. +[Preload routes](https://web.dev/articles/route-preloading-in-angular) ahead of time to speed up navigation. ### Magento diff --git a/site/en/docs/lighthouse/performance/uses-responsive-images/index.md b/site/en/docs/lighthouse/performance/uses-responsive-images/index.md index f84e0287d..a5bb75037 100644 --- a/site/en/docs/lighthouse/performance/uses-responsive-images/index.md +++ b/site/en/docs/lighthouse/performance/uses-responsive-images/index.md @@ -33,12 +33,12 @@ Anything larger than that just results in wasted bytes and slows down page load The main strategy for serving appropriately sized images is called "responsive images". With responsive images, you generate multiple versions of each image, and then specify which version to use in your HTML or CSS using media queries, viewport dimensions, and so on. Additionally, [RespImageLint](https://ausi.github.io/respimagelint/) is a helpful bookmarklet for identifying the optimal `srcset` and `sizes` values for your images. See [Serve responsive images](https://web.dev/serve-responsive-images) to learn more about these attributes. -[Image CDNs](https://web.dev/image-cdns/) are another main strategy for serving appropriately sized images. +[Image CDNs](https://web.dev/articles/image-cdns) are another main strategy for serving appropriately sized images. You can think of image CDNs like web service APIs for transforming images. Another strategy is to use vector-based image formats, like SVG. With a finite amount of code, an SVG image can scale to any size. -See [Replace complex icons with SVG](https://web.dev/responsive-images/#replace-complex-icons-with-svg) to learn more. +See [Replace complex icons with SVG](https://web.dev/articles/responsive-images#replace_complex_icons_with_svg) to learn more. Tools like [gulp-responsive](https://www.npmjs.com/package/gulp-responsive) or @@ -54,7 +54,7 @@ either when you upload an image, or request it from your page. Use the [`amp-img`](https://amp.dev/documentation/components/amp-img/?format=websites) component's support for -[`srcset`](https://web.dev/use-srcset-to-automatically-choose-the-right-image/) +[`srcset`](https://web.dev/articles/use-srcset-to-automatically-choose-the-right-image) to specify which image assets to use based on the screen size. See also [Responsive images with srcset, sizes & heights](https://amp.dev/documentation/guides-and-tutorials/develop/style_and_layout/art_direction/). @@ -97,4 +97,4 @@ pages](https://wordpress.org/support/article/inserting-images-into-posts-and-pag ## Resources - [Source code for **Properly size images** audit](https://github.com/GoogleChrome/lighthouse/blob/main/core/audits/byte-efficiency/uses-responsive-images.js) -- [Serve images with correct dimensions](https://web.dev/serve-images-with-correct-dimensions/) +- [Serve images with correct dimensions](https://web.dev/articles/serve-images-with-correct-dimensions) diff --git a/site/en/docs/lighthouse/performance/uses-text-compression/index.md b/site/en/docs/lighthouse/performance/uses-text-compression/index.md index 3dc93ff3c..2ed820994 100644 --- a/site/en/docs/lighthouse/performance/uses-text-compression/index.md +++ b/site/en/docs/lighthouse/performance/uses-text-compression/index.md @@ -102,7 +102,7 @@ To compare the compressed and de-compressed sizes of a response: top value is the compressed size. The bottom value is the de-compressed size. -See also [Minify and compress network payloads](https://web.dev/reduce-network-payloads-using-text-compression/). +See also [Minify and compress network payloads](https://web.dev/articles/reduce-network-payloads-using-text-compression). ## Stack-specific guidance diff --git a/site/en/docs/lighthouse/performance/uses-webp-images/index.md b/site/en/docs/lighthouse/performance/uses-webp-images/index.md index b5ffb948f..8d75cec80 100644 --- a/site/en/docs/lighthouse/performance/uses-webp-images/index.md +++ b/site/en/docs/lighthouse/performance/uses-webp-images/index.md @@ -29,7 +29,7 @@ See [A New Image Format For The Web](https://developers.google.com/speed/webp/) for more on WebP. {% Aside 'codelab' %} -[Create WebP Images with the Command Line](https://web.dev/codelab-serve-images-webp/) +[Create WebP Images with the Command Line](https://web.dev/articles/codelab-serve-images-webp) {% endAside %} ## How Lighthouse calculates potential savings @@ -97,6 +97,6 @@ formats. ## Resources - [Source code for **Serve images in modern formats** audit](https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/audits/byte-efficiency/modern-image-formats.js) -- [Use WebP images](https://web.dev/serve-images-webp/) +- [Use WebP images](https://web.dev/articles/serve-images-webp) <!-- https://www.reddit.com/r/webdev/comments/gspjwe/serve_images_in_nextgen_formats/ --> diff --git a/site/en/docs/lighthouse/pwa/apple-touch-icon/index.md b/site/en/docs/lighthouse/pwa/apple-touch-icon/index.md index bee338670..181291960 100644 --- a/site/en/docs/lighthouse/pwa/apple-touch-icon/index.md +++ b/site/en/docs/lighthouse/pwa/apple-touch-icon/index.md @@ -9,7 +9,7 @@ updated: 2023-03-24 is_outdated: true --- -When iOS Safari users add [Progressive Web Apps (PWAs)](https://web.dev/progressive-web-apps/#make-it-installable) to +When iOS Safari users add [Progressive Web Apps (PWAs)](https://web.dev/explore/progressive-web-apps#make-it-installable) to their home screens, the icon that appears is called the *Apple touch icon*. You can specify what icon your app should use by including a `<link rel="apple-touch-icon" href="/example.png">` tag in the `<head>` of your diff --git a/site/en/docs/lighthouse/pwa/content-width/index.md b/site/en/docs/lighthouse/pwa/content-width/index.md index 66bace6af..4ef970e56 100644 --- a/site/en/docs/lighthouse/pwa/content-width/index.md +++ b/site/en/docs/lighthouse/pwa/content-width/index.md @@ -32,7 +32,7 @@ The audit fails if `window.innerWidth` does not equal `window.outerWidth`. This audit is a roundabout way of determining if your page is optimized for mobile devices. See Google's -[Responsive Web Design Basics](https://web.dev/responsive-web-design-basics/) +[Responsive Web Design Basics](https://web.dev/articles/responsive-web-design-basics) for an overview of how to create a mobile-friendly page. You can ignore this audit if: @@ -44,4 +44,4 @@ You can ignore this audit if: ## Resources - [Source code for **Content is not sized correctly for the viewport** audit](https://github.com/GoogleChrome/lighthouse/blob/main/core/audits/content-width.js) -- [Responsive Web Design Basics](https://web.dev/responsive-web-design-basics/) +- [Responsive Web Design Basics](https://web.dev/articles/responsive-web-design-basics) diff --git a/site/en/docs/lighthouse/pwa/installable-manifest/index.md b/site/en/docs/lighthouse/pwa/installable-manifest/index.md index 919efc6ae..b3883e5c0 100644 --- a/site/en/docs/lighthouse/pwa/installable-manifest/index.md +++ b/site/en/docs/lighthouse/pwa/installable-manifest/index.md @@ -9,17 +9,17 @@ date: 2019-05-04 updated: 2022-01-25 --- -Installability is a core requirement of [Progressive Web Apps (PWAs)](https://web.dev/progressive-web-apps/#make-it-installable). +Installability is a core requirement of [Progressive Web Apps (PWAs)](https://web.dev/explore/progressive-web-apps#make-it-installable). By prompting users to install your PWA, you allow them to add it to their home screens. Users who add apps to home screens engage with those apps more frequently. -A [web app manifest](https://web.dev/add-manifest/) includes key pieces of information +A [web app manifest](https://web.dev/articles/add-manifest) includes key pieces of information required to make your app installable. ## How the Lighthouse web app manifest audit fails [Lighthouse](/docs/lighthouse/overview/) -flags pages that don't have a [web app manifest](https://web.dev/add-manifest/) +flags pages that don't have a [web app manifest](https://web.dev/articles/add-manifest) that meets minimum requirements for installability: <figure> @@ -42,7 +42,7 @@ it will fail the audit: A web app manifest is _necessary_ for your app to be installable, but it isn't _sufficient_. To learn how to meet all the requirements for installability, see the -[Discover what it takes to be installable](https://web.dev/progressive-web-apps/#make-it-installable) post. +[Discover what it takes to be installable](https://web.dev/explore/progressive-web-apps#make-it-installable) post. {% endAside %} {% Partial 'lighthouse-pwa/scoring.njk' %} @@ -78,7 +78,7 @@ Check their respective sites for full details: ## Resources - [Source code for **Web app manifest does not meet the installability requirements** audit](https://github.com/GoogleChrome/lighthouse/blob/main/core/audits/installable-manifest.js) -- [Add a web app manifest](https://web.dev/add-manifest/) -- [Discover what it takes to be installable](https://web.dev/progressive-web-apps/#make-it-installable) +- [Add a web app manifest](https://web.dev/articles/add-manifest) +- [Discover what it takes to be installable](https://web.dev/explore/progressive-web-apps#make-it-installable) - [Web App Manifest](https://developer.mozilla.org/docs/Web/Manifest) - [Does not use HTTPS](/docs/lighthouse/pwa/is-on-https/) diff --git a/site/en/docs/lighthouse/pwa/is-on-https/index.md b/site/en/docs/lighthouse/pwa/is-on-https/index.md index 5ec9b9523..cb2ec99c9 100644 --- a/site/en/docs/lighthouse/pwa/is-on-https/index.md +++ b/site/en/docs/lighthouse/pwa/is-on-https/index.md @@ -11,11 +11,11 @@ All websites should be protected with HTTPS, even ones that don't handle sensitive data. HTTPS prevents intruders from tampering with or passively listening in on the communications between your site and your users. -A page can't qualify as a [Progressive Web App (PWA)](https://web.dev/progressive-web-apps/#make-it-installable) if it doesn't run on HTTPS; +A page can't qualify as a [Progressive Web App (PWA)](https://web.dev/explore/progressive-web-apps#make-it-installable) if it doesn't run on HTTPS; many core PWA technologies, such as service workers, require HTTPS. For more information about why all sites should be protected with HTTPS, see -[Why HTTPS Matters](https://web.dev/why-https-matters/). +[Why HTTPS Matters](https://web.dev/articles/why-https-matters). ## How the Lighthouse HTTPS audit fails @@ -37,12 +37,12 @@ If the event isn't heard within 10 seconds, the audit fails. Consider hosting your site on a CDN. Most CDNs are secure by default. To learn how to enable HTTPS on your servers, see Google's -[Enabling HTTPS on Your Servers](https://web.dev/enabling-https-on-your-servers/). +[Enabling HTTPS on Your Servers](https://web.dev/articles/enabling-https-on-your-servers). If you're running your own server and need a cheap and easy way to generate certificates, [Let's Encrypt](https://letsencrypt.org/) is a good option. If your page is already running on HTTPS but you're failing this audit, -you may have problems with [mixed content](https://web.dev/what-is-mixed-content/). +you may have problems with [mixed content](https://web.dev/articles/what-is-mixed-content). A page has mixed content when the page itself is loaded over HTTPS, but it requests an unprotected (HTTP) resource. Check out the following doc on the Chrome DevTools Security panel to learn how to debug these situations: @@ -51,8 +51,8 @@ Chrome DevTools Security panel to learn how to debug these situations: ## Resources - [Source code for **Does not use HTTPS** audit](https://github.com/GoogleChrome/lighthouse/blob/main/core/audits/is-on-https.js) -- [Why You Should Always Use HTTPS](https://web.dev/why-https-matters/) -- [Enabling HTTPS on Your Servers](https://web.dev/enabling-https-on-your-servers/) +- [Why You Should Always Use HTTPS](https://web.dev/articles/why-https-matters) +- [Enabling HTTPS on Your Servers](https://web.dev/articles/enabling-https-on-your-servers) - [Understand Security Issues With Chrome DevTools](/docs/devtools/security/) -- [What Is Mixed Content?](https://web.dev/what-is-mixed-content/) +- [What Is Mixed Content?](https://web.dev/articles/what-is-mixed-content) - [Let's Encrypt](https://letsencrypt.org/) diff --git a/site/en/docs/lighthouse/pwa/load-fast-enough-for-pwa/index.md b/site/en/docs/lighthouse/pwa/load-fast-enough-for-pwa/index.md index 08d8754c4..53aee809b 100644 --- a/site/en/docs/lighthouse/pwa/load-fast-enough-for-pwa/index.md +++ b/site/en/docs/lighthouse/pwa/load-fast-enough-for-pwa/index.md @@ -29,7 +29,7 @@ flags pages that don't load fast enough on mobile: Two main metrics affect how users perceive load time: - [First Meaningful Paint (FMP)](/docs/lighthouse/performance/first-meaningful-paint), which measures when the primary content of the page appears visually complete -- [Time to Interactive (TTI)](https://web.dev/tti/), which measures when the page is fully interactive +- [Time to Interactive (TTI)](https://web.dev/articles/tti), which measures when the page is fully interactive For example, if a page appears visually complete after 1 second, but the user can't interact with it for 10 seconds, @@ -46,8 +46,8 @@ If the time to interactive is more than 10 seconds, the audit fails. - [Source code for **Page load is not fast enough on mobile networks** audit](https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/audits/load-fast-enough-for-pwa.js) - [Baseline Progressive Web App Checklist](https://web.dev/pwa-checklist/#core) -- [Critical Rendering Path](https://web.dev/critical-rendering-path/) +- [Critical Rendering Path](https://web.dev/articles/critical-rendering-path) - [Get Started With Analyzing Runtime Performance](/docs/devtools/evaluate-performance/) - [Record load performance](/docs/devtools/evaluate-performance/reference/#record-load) -- [Optimizing Content Efficiency](https://web.dev/performance-optimizing-content-efficiency/) -- [Rendering Performance](https://web.dev/rendering-performance/) +- [Optimizing Content Efficiency](https://web.dev/articles/performance-optimizing-content-efficiency) +- [Rendering Performance](https://web.dev/articles/rendering-performance) diff --git a/site/en/docs/lighthouse/pwa/maskable-icon-audit/index.md b/site/en/docs/lighthouse/pwa/maskable-icon-audit/index.md index 4623804eb..1190a78c9 100644 --- a/site/en/docs/lighthouse/pwa/maskable-icon-audit/index.md +++ b/site/en/docs/lighthouse/pwa/maskable-icon-audit/index.md @@ -57,7 +57,7 @@ In order to pass the audit: ``` 3. Use Chrome DevTools to verify that the maskable icon is displaying correctly. - See [Are my current icons ready?](https://web.dev/maskable-icon/#are-my-current-icons-ready) + See [Are my current icons ready?](https://web.dev/articles/maskable-icon#are_my_current_icons_ready) ## Resources diff --git a/site/en/docs/lighthouse/pwa/offline-start-url/index.md b/site/en/docs/lighthouse/pwa/offline-start-url/index.md index 24f49ad44..1fe4054e2 100644 --- a/site/en/docs/lighthouse/pwa/offline-start-url/index.md +++ b/site/en/docs/lighthouse/pwa/offline-start-url/index.md @@ -8,7 +8,7 @@ date: 2019-05-04 updated: 2020-04-29 --- -The [manifest](https://web.dev/add-manifest/) for a [Progressive Web App](https://web.dev/what-are-pwas/) (PWA) should include a `start_url`, +The [manifest](https://web.dev/articles/add-manifest) for a [Progressive Web App](https://web.dev/articles/what-are-pwas) (PWA) should include a `start_url`, which indicates the URL to be loaded when the user launches the app. If the browser doesn't receive an @@ -32,7 +32,7 @@ flags web apps whose start URL doesn't respond with a 200 when offline: {% Partial 'reliable/workbox.njk' %} -1. If you don't already have one, [add a web app manifest](https://web.dev/add-manifest/). +1. If you don't already have one, [add a web app manifest](https://web.dev/articles/add-manifest). 1. Check that the `start_url` in your manifest is correct. 1. Add a service worker to your app. 1. Use the service worker to cache files locally. @@ -43,6 +43,6 @@ guide for more information. ## Resources -- [What is network reliability and how do you measure it?](https://web.dev/network-connections-unreliable/) -- [Add a web app manifest](https://web.dev/add-manifest/) +- [What is network reliability and how do you measure it?](https://web.dev/articles/network-connections-unreliable) +- [Add a web app manifest](https://web.dev/articles/add-manifest) - [Workbox: Your high-level service worker toolkit](/docs/workbox/) diff --git a/site/en/docs/lighthouse/pwa/pwa-cross-browser/index.md b/site/en/docs/lighthouse/pwa/pwa-cross-browser/index.md index fb0eb74ae..caadef971 100644 --- a/site/en/docs/lighthouse/pwa/pwa-cross-browser/index.md +++ b/site/en/docs/lighthouse/pwa/pwa-cross-browser/index.md @@ -14,9 +14,9 @@ To reach the most users, sites should work on every major browser. Test your site in Chrome, Edge, Firefox, and Safari, and fix any issues that appear in each browser. -If your page is a [Progressive Web App](https://web.dev/progressive-web-apps/#make-it-installable), +If your page is a [Progressive Web App](https://web.dev/explore/progressive-web-apps#make-it-installable), consider using [Workbox](/docs/workbox/), -a high-level [service worker](https://web.dev/service-workers-cache-storage/) toolkit. +a high-level [service worker](https://web.dev/articles/service-workers-cache-storage) toolkit. Workbox is developed against a cross-browser test suite, and when possible, automatically falls back to alternative implementations of features that are missing from certain browsers: diff --git a/site/en/docs/lighthouse/pwa/pwa-each-page-has-url/index.md b/site/en/docs/lighthouse/pwa/pwa-each-page-has-url/index.md index 965995f32..33d76e55a 100644 --- a/site/en/docs/lighthouse/pwa/pwa-each-page-has-url/index.md +++ b/site/en/docs/lighthouse/pwa/pwa-each-page-has-url/index.md @@ -8,7 +8,7 @@ updated: 2019-09-19 --- Ensure individual pages and views in your -[Progressive Web App (PWA)](https://web.dev/progressive-web-apps/#make-it-installable) +[Progressive Web App (PWA)](https://web.dev/explore/progressive-web-apps#make-it-installable) are deep linkable via URL and that each URL is unique to make them easily shareable on social media. diff --git a/site/en/docs/lighthouse/pwa/pwa-page-transitions/index.md b/site/en/docs/lighthouse/pwa/pwa-page-transitions/index.md index e64ff7bc4..b90348a2e 100644 --- a/site/en/docs/lighthouse/pwa/pwa-page-transitions/index.md +++ b/site/en/docs/lighthouse/pwa/pwa-page-transitions/index.md @@ -9,7 +9,7 @@ updated: 2019-09-19 --- Quick page transitions are key to how users perceive the performance of your -[Progressive Web App (PWA)](https://web.dev/progressive-web-apps/#make-it-installable). +[Progressive Web App (PWA)](https://web.dev/explore/progressive-web-apps#make-it-installable). Transitions should feel snappy, even on a slow network. ## Recommendations diff --git a/site/en/docs/lighthouse/pwa/service-worker/index.md b/site/en/docs/lighthouse/pwa/service-worker/index.md index e233e7ed8..f4810eb32 100644 --- a/site/en/docs/lighthouse/pwa/service-worker/index.md +++ b/site/en/docs/lighthouse/pwa/service-worker/index.md @@ -8,14 +8,14 @@ date: 2019-05-04 updated: 2022-12-03 --- -Registering a [service worker](https://web.dev/service-workers-cache-storage/) -is the first step towards enabling key [Progressive Web App (PWA)](https://web.dev/progressive-web-apps/#make-it-installable) features: +Registering a [service worker](https://web.dev/articles/service-workers-cache-storage) +is the first step towards enabling key [Progressive Web App (PWA)](https://web.dev/explore/progressive-web-apps#make-it-installable) features: - Works offline - Supports push notifications - Can be installed to the device -Learn more in the [Service workers and the Cache Storage API](https://web.dev/service-workers-cache-storage/) post. +Learn more in the [Service workers and the Cache Storage API](https://web.dev/articles/service-workers-cache-storage) post. ## Browser compatibility @@ -46,8 +46,8 @@ is to make it possible to implement one of the PWA features outlined above. Actually implementing those features requires more work: - To learn how to cache files for offline use, see the -[What is network reliability and how do you measure it?](https://web.dev/network-connections-unreliable/) post. -- To learn how to make your app installable, see the [Make it installable](https://web.dev/codelab-make-installable/) codelab. +[What is network reliability and how do you measure it?](https://web.dev/articles/network-connections-unreliable) post. +- To learn how to make your app installable, see the [Make it installable](https://web.dev/articles/codelab-make-installable) codelab. - To learn how to enable push notifications, see Google's [Adding Push Notifications to a Web App](https://codelabs.developers.google.com/codelabs/push-notifications). @@ -55,7 +55,7 @@ Actually implementing those features requires more work: - [Source code for **Does not register a service worker that controls page and `start_url`** audit](https://github.com/GoogleChrome/lighthouse/blob/main/core/audits/service-worker.js) - [Service Workers: an Introduction](/docs/workbox/service-worker-overview/) -- [Service workers and the Cache Storage API](https://web.dev/service-workers-cache-storage/) -- [What is network reliability and how do you measure it?](https://web.dev/network-connections-unreliable/) -- [Make it installable](https://web.dev/codelab-make-installable/) +- [Service workers and the Cache Storage API](https://web.dev/articles/service-workers-cache-storage) +- [What is network reliability and how do you measure it?](https://web.dev/articles/network-connections-unreliable) +- [Make it installable](https://web.dev/articles/codelab-make-installable) - [Adding Push Notifications to a Web App](https://codelabs.developers.google.com/codelabs/push-notifications) diff --git a/site/en/docs/lighthouse/pwa/splash-screen/index.md b/site/en/docs/lighthouse/pwa/splash-screen/index.md index b44379899..e16569bb7 100644 --- a/site/en/docs/lighthouse/pwa/splash-screen/index.md +++ b/site/en/docs/lighthouse/pwa/splash-screen/index.md @@ -7,7 +7,7 @@ date: 2019-05-04 updated: 2023-03-16 --- -A custom splash screen makes your [Progressive Web App (PWA)](https://web.dev/progressive-web-apps/#make-it-installable) feel more like an +A custom splash screen makes your [Progressive Web App (PWA)](https://web.dev/explore/progressive-web-apps#make-it-installable) feel more like an app built for that device. By default, when a user launches your PWA from the home screen, Android displays a white screen until the PWA is ready. The user may see this blank, white screen for up to 200 ms. @@ -29,7 +29,7 @@ flags pages that don't have a custom splash screen: ## How to create a custom splash screen Chrome for Android automatically shows your custom splash screen as long as -you meet the following requirements in your [web app manifest](https://web.dev/add-manifest/): +you meet the following requirements in your [web app manifest](https://web.dev/articles/add-manifest): - The `name` property is set to the name of your PWA. - The `background_color` property is set to a valid CSS color value. @@ -37,7 +37,7 @@ you meet the following requirements in your [web app manifest](https://web.dev/a - The `icons` array specifies an icon that is at least 512x512 px. - The specified icon exists and is a PNG. -See [Adding a Splash Screen for Installed Web Apps in Chrome 47](https://web.dev/add-manifest/#splash-screen) +See [Adding a Splash Screen for Installed Web Apps in Chrome 47](https://web.dev/articles/add-manifest#splash_screen) for more information. {% Aside %} diff --git a/site/en/docs/lighthouse/pwa/themed-omnibox/index.md b/site/en/docs/lighthouse/pwa/themed-omnibox/index.md index 7078d479a..178d85ce9 100644 --- a/site/en/docs/lighthouse/pwa/themed-omnibox/index.md +++ b/site/en/docs/lighthouse/pwa/themed-omnibox/index.md @@ -8,7 +8,7 @@ updated: 2020-12-03 --- Theming the browser's address bar to match the brand colors -of your [Progressive Web App (PWA)](https://web.dev/progressive-web-apps/#make-it-installable) provides a more immersive user experience. +of your [Progressive Web App (PWA)](https://web.dev/explore/progressive-web-apps#make-it-installable) provides a more immersive user experience. ## Browser compatibility @@ -27,7 +27,7 @@ flags pages that don't apply a theme to the address bar: </figure> The audit fails if Lighthouse doesn't find a `theme-color` meta tag in the page's -HTML and a `theme_color` property in the [web app manifest](https://web.dev/add-manifest/). +HTML and a `theme_color` property in the [web app manifest](https://web.dev/articles/add-manifest). Note that Lighthouse doesn't test whether the values are valid CSS color values. @@ -60,7 +60,7 @@ Learn more about the `theme-color` meta tag in Google's The `theme_color` property in your web app manifest ensures that the address bar is branded when a user launches your PWA from the home screen. Unlike the `theme-color` meta tag, you only need -to define this once, in the [manifest](https://web.dev/add-manifest/). +to define this once, in the [manifest](https://web.dev/articles/add-manifest). Set the property to any valid CSS color value: ```html/1 @@ -76,5 +76,5 @@ according to the manifest's `theme_color`. ## Resources - [Source code for **Does not set a theme color for the address bar** audit](https://github.com/GoogleChrome/lighthouse/blob/main/core/audits/themed-omnibox.js) -- [Add a web app manifest](https://web.dev/add-manifest/) +- [Add a web app manifest](https://web.dev/articles/add-manifest) - [Support for `theme-color` in Chrome 39 for Android](/blog/support-for-theme-color-in-chrome-39-for-android/) diff --git a/site/en/docs/lighthouse/pwa/without-javascript/index.md b/site/en/docs/lighthouse/pwa/without-javascript/index.md index 6aaaa9289..c90ba74ed 100644 --- a/site/en/docs/lighthouse/pwa/without-javascript/index.md +++ b/site/en/docs/lighthouse/pwa/without-javascript/index.md @@ -67,5 +67,5 @@ Chrome DevTools' [Disable JavaScript](/docs/devtools/javascript/disable/) featur - [Source code for **Does not provide fallback content when JavaScript is not available** audit](https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/audits/without-javascript.js) - [Progressive Enhancement: What It Is, And How To Use It](https://www.smashingmagazine.com/2009/04/progressive-enhancement-what-it-is-and-how-to-use-it/) -- [Critical Rendering Path](https://web.dev/critical-rendering-path/) +- [Critical Rendering Path](https://web.dev/articles/critical-rendering-path) - [Disable JavaScript With Chrome DevTools](/docs/devtools/javascript/disable/) diff --git a/site/en/docs/lighthouse/pwa/works-offline/index.md b/site/en/docs/lighthouse/pwa/works-offline/index.md index 35fef44a1..5ed87a343 100644 --- a/site/en/docs/lighthouse/pwa/works-offline/index.md +++ b/site/en/docs/lighthouse/pwa/works-offline/index.md @@ -14,7 +14,7 @@ should provide a custom offline page. The [Optimial Progressive Web App checklis says that a PWA should provide an offline experience where the PWA works the same offline as it does online (wherever network connectivity isn't strictly required). -Learn more in the [What is network reliability and how do you measure it?](https://web.dev/network-connections-unreliable/) post. +Learn more in the [What is network reliability and how do you measure it?](https://web.dev/articles/network-connections-unreliable) post. ## How the Lighthouse offline audit fails @@ -48,5 +48,5 @@ with the [Working with service workers](https://web.dev/codelab-service-workers) ## Resources -- [What is network reliability and how do you measure it?](https://web.dev/network-connections-unreliable/) +- [What is network reliability and how do you measure it?](https://web.dev/articles/network-connections-unreliable) - [Service Workers: an Introduction](/docs/workbox/service-worker-overview/) diff --git a/site/en/docs/lighthouse/seo/canonical/index.md b/site/en/docs/lighthouse/seo/canonical/index.md index 6dd2f142c..f9b5a21e9 100644 --- a/site/en/docs/lighthouse/seo/canonical/index.md +++ b/site/en/docs/lighthouse/seo/canonical/index.md @@ -83,7 +83,7 @@ page. ### General guidelines - Make sure that the canonical URL is valid. -- Use secure [HTTPS](https://web.dev/why-https-matters/) canonical URLs rather than HTTP whenever possible. +- Use secure [HTTPS](https://web.dev/articles/why-https-matters) canonical URLs rather than HTTP whenever possible. - If you use [`hreflang` links](/docs/lighthouse/seo/hreflang/) to serve different versions of a page depending on a user's language or country, make sure that the canonical URL points to the proper page for that respective language or country. diff --git a/site/en/docs/lighthouse/seo/tap-targets/index.md b/site/en/docs/lighthouse/seo/tap-targets/index.md index 9a6d30991..2616ef226 100644 --- a/site/en/docs/lighthouse/seo/tap-targets/index.md +++ b/site/en/docs/lighthouse/seo/tap-targets/index.md @@ -70,5 +70,5 @@ but is not always enough spacing to pass the audit especially for very small tar ## Resources -- [Accessible tap targets](https://web.dev/accessible-tap-targets/): more information on how to ensure your tap targets are accessible by all users. +- [Accessible tap targets](https://web.dev/articles/accessible-tap-targets): more information on how to ensure your tap targets are accessible by all users. - [Source code for **Tap targets are not sized appropriately** audit](https://github.com/GoogleChrome/lighthouse/blob/main/core/audits/seo/tap-targets.js) diff --git a/site/en/docs/privacy-sandbox/attribution-reporting/register-attribution-trigger/index.md b/site/en/docs/privacy-sandbox/attribution-reporting/register-attribution-trigger/index.md index e8862ac4f..ab6277be5 100644 --- a/site/en/docs/privacy-sandbox/attribution-reporting/register-attribution-trigger/index.md +++ b/site/en/docs/privacy-sandbox/attribution-reporting/register-attribution-trigger/index.md @@ -36,10 +36,10 @@ Registering a trigger is similar to 1. **Initiate the trigger registration.** Use a pixel or a `fetch()` call to make a request. 1. **Complete the trigger registration** by responding with the trigger - registration header. + registration header. <br><br> - + Upon receiving the pixel request—sent either to the endpoint defined in the usual `src` attribute, or to the endpoint defined in `attributionsrc` if you've chosen to use `attributionsrc` and given it @@ -51,7 +51,7 @@ Registering a trigger is similar to response to a request made from a site that matches the `destination`, sources will be matched. When the header is received, the browser looks for matching sources and schedules a report. - + **Example for event-level reports:** ```json @@ -65,7 +65,7 @@ Registering a trigger is similar to ``` **Example for summary reports:** - + ```json { ... // existing fields, such as "event_trigger_data" @@ -91,7 +91,7 @@ Registering a trigger is similar to {% Aside %} When the browser receives an attribution trigger response from an attributionsrc URL on a given page, a local storage lookup is done to find a source that matches both the attributionsrc origin and that page URL's eTLD+1. <br> - If multiple sources are found, the browser picks the one that was stored most recently—unless sources have different priorities, in which the browser picks the one with the greatest priority. + If multiple sources are found, the browser picks the one that was stored most recently—unless sources have different priorities, in which the browser picks the one with the greatest priority. {% endAside %} ### Dealing with subdomains @@ -113,21 +113,21 @@ required. When `attributionsrc` is **optional**, using it indicates that the request is eligible for Attribution Reporting. If you use `attributionsrc`, the browser sends the `Attribution-Reporting-Eligible` header. It's also useful for app-to-web -measurement: if `attributionsrc` is present, the browser sends the +measurement: if `attributionsrc` is present, the browser sends the `Attribution-Reporting-Support` header. <table> <thead> <tr> <th>Registration method</th> - + <th><strong>Trigger</strong></th> </tr> </thead> <tbody> <tr> <td><code><a></code> tag</td> - <td><em>N/A</em> + <td><em>N/A</em> <em>Anchors cannot register a trigger.</em></td> </tr> <tr> @@ -142,19 +142,19 @@ is sufficient to register a trigger.</td> </tr> <tr> <td><code>fetch</code> call</td> - <td>The <code>attributionReporting</code> option is + <td>The <code>attributionReporting</code> option is <strong>required</strong>.</td> </tr> <tr> <td><code>XMLHttpRequest</code> </td> - <td>The <code>attributionReporting</code> option is + <td>The <code>attributionReporting</code> option is <strong>required</strong>.</td> </tr> <tr> <td><code>window.open()</code> </td> - <td><em>N/A</em> + <td><em>N/A</em> <em><code>window.open</code> cannot register a trigger.</em></td> </tr> </tbody> @@ -172,8 +172,8 @@ You can register a trigger using a pixel (`<img>` tag) or script tag. ``` {% Aside 'important' %} -* The origin for `src` must match the origin that performed the source registration. -* An attribution can only be triggered on a page whose [eTLD+1](https://web.dev/same-site-same-origin/#%22schemeful-same-site%22) matches the site that was provided in destination upon source registration. +* The origin for `src` must match the origin that performed the source registration. +* An attribution can only be triggered on a page whose [eTLD+1](https://web.dev/articles/same-site-same-origin#%22schemeful_same_site%22) matches the site that was provided in destination upon source registration. {% endAside %} #### Using a script tag @@ -190,7 +190,7 @@ const attributionReporting = { }; // Optionally set keepalive to ensure the request outlives the page. -window.fetch("https://adtech.example/attribution_source?my_ad_id=123", +window.fetch("https://adtech.example/attribution_source?my_ad_id=123", { keepalive: true, attributionReporting }); ``` @@ -210,7 +210,7 @@ const req = new XMLHttpRequest(); {% Aside 'important' %} - The origin for <code>src</code> must match the origin that performed -source registration. +source registration. - An attribution can only be triggered on a page whose <a href="https://web.dev/same-site-same-origin/#%22schemeful-same-site%22">eTLD+1</a> matches the site that was provided in <code>destination</code> upon source @@ -229,14 +229,14 @@ You can add `attributionsrc` either with or without a value. <img src="..." width="1" height="1" attributionsrc="https://..."> ``` -If you set a value for `attributionsrc`, it should be a single URL. +If you set a value for `attributionsrc`, it should be a single URL. Using a URL causes the browser to initiate a **separate** keepalive fetch request—one for each URL—which includes the `Attribution-Reporting-Eligible` request header. This is useful if you want to make the source registration by responding to a -request that is separate from the element's main request. +request that is separate from the element's main request. For example, if you need to register sources for clicks on an anchor element, you may not actually be in control of the destination; in this case, you'll want @@ -246,7 +246,7 @@ specifying an explicit value for `attributionsrc`, you're instructing the browser to make that extra request and configuring its destination. -### Step 2: Respond with a header +### Step 2: Respond with a header Upon receiving the browser request, respond and include in your response the `Attribution-Reporting-Register-Trigger` header: diff --git a/site/en/docs/privacy-sandbox/cds21-update/index.md b/site/en/docs/privacy-sandbox/cds21-update/index.md index b7116764d..467b1bf8e 100644 --- a/site/en/docs/privacy-sandbox/cds21-update/index.md +++ b/site/en/docs/privacy-sandbox/cds21-update/index.md @@ -19,7 +19,7 @@ Here's what you need to know: * Monitor and [engage in conversation](#discussion) around [privacy proposals](https://github.com/w3c/web-advertising#ideas-and-proposals-links-outside-this-repo) * [Prepare for User-Agent reduction](https://blog.chromium.org/2021/09/user-agent-reduction-origin-trial-and-dates.html) - and migrate to [UA Client Hints](https://web.dev/migrate-to-ua-ch/) + and migrate to [UA Client Hints](https://web.dev/articles/migrate-to-ua-ch) * Share your feedback with [@ChromiumDev on Twitter](https://twitter.com/ChromiumDev) This update on the Privacy Sandbox was announced at the @@ -71,7 +71,7 @@ width="485", height="659" Many of the common web functions described above weren't built into the web platform, but instead have been layered over it with general-purpose -technologies such as third-party cookies. +technologies such as third-party cookies. When we design APIs for each specific use case, we can ensure appropriate privacy protections, give people more useful controls, and ideally improve each @@ -100,7 +100,7 @@ There have been dozens of [privacy-preserving proposals](https://github.com/w3c/web-advertising#ideas-and-proposals-links-outside-this-repo) offered by Chrome and others over the last couple of years. You can read these proposals, ask questions, offer ideas to improve them and see what others are -saying. +saying. To find conversations where the proposed solutions are being discussed and debated together, there are a number of W3C groups you can join or monitor, @@ -129,7 +129,7 @@ width="800", height="169" %} There have also been more than half a dozen other proposals offered by other companies, in the same solution space. Through continued collaboration, we hope -to define a path forward. +to define a path forward. At the same time, we're starting [developer testing](/docs/privacy-sandbox/protected-audience/) for the initial version of the Protected Audience API behind a flag in Chrome so developers can get their @@ -172,7 +172,7 @@ which has now been added to the API. {% endAside %} We also hope to see companies talking about their approach to testing and how -they expect to use an API. +they expect to use an API. In the origin trial for the first version of [FLoC](https://github.com/WICG/floc) – a proposal to support interest-based advertising and content – @@ -181,7 +181,7 @@ we saw companies like CafeMedia publishing their so that others could review what they'd learned. Chrome tests aren't the only way to explore how new technologies might work. -Some companies are also building simulations based on Privacy Sandbox concepts. +Some companies are also building simulations based on Privacy Sandbox concepts. {% Aside %} Advertising platform Criteo recently @@ -202,7 +202,7 @@ Once an API is tested and ready for general use in Chrome, we'll announce the launch and make sure public documentation is ready for scaled ecosystem adoption. -[User-Agent Client Hints](https://web.dev/user-agent-client-hints/) (UA-CH) +[User-Agent Client Hints](https://web.dev/articles/user-agent-client-hints) (UA-CH) launched in Chrome earlier this year and is now ready to scale. It's part of the Privacy Sandbox work stream to reduce covert tracking such as browser fingerprinting. @@ -221,7 +221,7 @@ width="800", height="464" %} To get this information in the future, you'll need to transition to UA-CH. The User-Agent string will give you some information by default, which may cover most of your use cases, but more detailed information is available only -on request in a straightforward format. +on request in a straightforward format. We were happy to make this ergonomic improvement for developers while moving the majority of UA information from an "available by default" model to an "on diff --git a/site/en/docs/privacy-sandbox/chips/index.md b/site/en/docs/privacy-sandbox/chips/index.md index 194ed1bf6..1ea02d8b8 100644 --- a/site/en/docs/privacy-sandbox/chips/index.md +++ b/site/en/docs/privacy-sandbox/chips/index.md @@ -12,11 +12,11 @@ authors: - mihajlija tags: - cookies - - privacy + - privacy --- ## Changes - + - **June 2022**: Based on feedback, setting cookies with the `Partitioned` attribute no longer requires omitting the `Domain` attribute. This allows subdomains of a third-party site to access cookies within a partition. ## Implementation status @@ -37,7 +37,7 @@ Without partitioning, third-party cookies can enable services to track users and width="800", height="450" %} -CHIPS introduces a new cookie attribute, `Partitioned`, to support cross-site cookies that are partitioned by top-level context. +CHIPS introduces a new cookie attribute, `Partitioned`, to support cross-site cookies that are partitioned by top-level context. Set-Cookie header: @@ -65,11 +65,11 @@ If a user visits site C as a top level website, the partitioned cookie that C se ## Use cases -For example, the site `retail.example` may want to work with a third-party service `support.chat.example` to embed a support chat box on its site. Many embeddable chat services today rely on cookies to save interaction history. +For example, the site `retail.example` may want to work with a third-party service `support.chat.example` to embed a support chat box on its site. Many embeddable chat services today rely on cookies to save interaction history. {% Img src="image/vgdbNJBYHma2o62ZqYmcnkq3j0o1/jsxgCpkMRXwXughPjg7j.png", alt="Top-level site retail.example embedding a third-party service support.chat.example.", width="400", height="310" %} -Without the ability to set a cross-site cookie, `support.chat.example` could instead rely on `retail.example` passing along their first-party session identifier (or some derived value of it). In that case, every website that `support.chat.example` is embedded on would require additional setup to pass along the state. +Without the ability to set a cross-site cookie, `support.chat.example` could instead rely on `retail.example` passing along their first-party session identifier (or some derived value of it). In that case, every website that `support.chat.example` is embedded on would require additional setup to pass along the state. Alternatively, `support.chat.example` may request `retail.example` to embed JavaScript that's hosted on `support.chat.example` on `retail.example` pages. This introduces security risks, because it allows the `support.chat.example` script to have elevated privileges on `retail.example`, such as the ability to access authentication cookies. @@ -102,19 +102,19 @@ While third-party cookies still exist, the `Partitioned` attribute provides an o ### Partitioning model -Today, cookies are keyed on the hostname or domain of the site that set them, that is, their _host key_. +Today, cookies are keyed on the hostname or domain of the site that set them, that is, their _host key_. -For example, for cookies from `https://support.chat.example`, the host key is `("support.chat.example")`. +For example, for cookies from `https://support.chat.example`, the host key is `("support.chat.example")`. -Under CHIPS, cookies that opt into partitioning will be double-keyed on their host key and _partition key_. +Under CHIPS, cookies that opt into partitioning will be double-keyed on their host key and _partition key_. -A _cookie's partition key_ is the site ([scheme and registrable domain](https://web.dev/same-site-same-origin/#%22schemeful-same-site%22)) of the top-level URL the browser was visiting at the start of the request to the endpoint that set the cookie. +A _cookie's partition key_ is the site ([scheme and registrable domain](https://web.dev/articles/same-site-same-origin#%22schemeful_same_site%22)) of the top-level URL the browser was visiting at the start of the request to the endpoint that set the cookie. -In the example above where `https://support.chat.example` is embedded on `https://retail.example`, the top-level URL is `https://retail.example`. +In the example above where `https://support.chat.example` is embedded on `https://retail.example`, the top-level URL is `https://retail.example`. -The partition key in that case is `("https", "retail.example")`. +The partition key in that case is `("https", "retail.example")`. -Likewise, a _request's partition key_ is the site of the top-level URL the browser is visiting at the start of a request. Browsers must only send a cookie with the `Partitioned` attribute in requests with the same partition key as that cookie. +Likewise, a _request's partition key_ is the site of the top-level URL the browser is visiting at the start of a request. Browsers must only send a cookie with the `Partitioned` attribute in requests with the same partition key as that cookie. Here's what the cookie key in the example above looks like before and after CHIPS. @@ -163,7 +163,7 @@ Partitioned cookies must be set with `Secure`. It is recommended to use the `__Host` prefix when setting partitioned cookies to make them bound to the hostname (and not the registrable domain). -Example: +Example: ```text Set-Cookie: __Host-example=34d8g; SameSite=None; Secure; Path=/; Partitioned; diff --git a/site/en/docs/privacy-sandbox/fedcm-developer-guide/index.md b/site/en/docs/privacy-sandbox/fedcm-developer-guide/index.md index 08c0eb0b5..e8c9e781b 100644 --- a/site/en/docs/privacy-sandbox/fedcm-developer-guide/index.md +++ b/site/en/docs/privacy-sandbox/fedcm-developer-guide/index.md @@ -71,7 +71,7 @@ in](#sign-into-rp) with the IdP. To prevent [trackers from abusing the API](https://github.com/fedidcg/FedCM/issues/230), a well-known file must be served from `/.well-known/web-identity` of -[eTLD+1](https://web.dev/same-site-same-origin/#same-site-cross-site) of the +[eTLD+1](https://web.dev/articles/same-site-same-origin#same_site_cross_site) of the IdP. For example, if the IdP endpoints are served under @@ -416,7 +416,7 @@ account_id=123&client_id=client1234&nonce=Ct60bD&disclosure_text_shown=true On the server, the IdP should confirm that: 1. The claimed account ID matches the ID for the account that is already - signed in. + signed in. 2. The `Origin` header matches the origin the RP, registered in advance for the given client ID. @@ -570,19 +570,19 @@ let them sign-in and start a new session. ### Auto-reauthenticate users after the initial consent {: #auto-reauthn } -[FedCM auto-reauthentication](https://github.com/fedidcg/FedCM/issues/429) -("auto-reauthn" in short) can let users reauthenticate automatically, when they -come back after their initial authentication using FedCM. "The initial -authentication" here means the user creates an account or signs into the RP's -website by tapping on the **"Continue as..."** button on FedCM's sign-in dialog +[FedCM auto-reauthentication](https://github.com/fedidcg/FedCM/issues/429) +("auto-reauthn" in short) can let users reauthenticate automatically, when they +come back after their initial authentication using FedCM. "The initial +authentication" here means the user creates an account or signs into the RP's +website by tapping on the **"Continue as..."** button on FedCM's sign-in dialog for the first time on the same browser instance. -While the explicit user experience makes sense before the user has created the -federated account to prevent tracking (which is one of the main goals of FedCM), -it is unnecessarily cumbersome after the user has gone through it once: after -the user grants permission to allow communication between the RP and the IdP, -there's no privacy or security benefit for enforcing another explicit user -confirmation for something that they have already previously acknowledged. +While the explicit user experience makes sense before the user has created the +federated account to prevent tracking (which is one of the main goals of FedCM), +it is unnecessarily cumbersome after the user has gone through it once: after +the user grants permission to allow communication between the RP and the IdP, +there's no privacy or security benefit for enforcing another explicit user +confirmation for something that they have already previously acknowledged. With auto-reauthentication, the browser changes its behavior depending on the option you specify for the `mediation` when calling `navigator.credentials.get()`. @@ -599,22 +599,22 @@ const cred = await navigator.credentials.get({ }); ``` -The `mediation` is [a property in the Credential Management -API](https://developer.mozilla.org/docs/Web/API/CredentialsContainer/get#:~:text=mediation), -it behaves in [the same -way](https://web.dev/security-credential-management-retrieve-credentials/) as it -does for -[PasswordCredential](https://developer.mozilla.org/docs/Web/API/PasswordCredential) -and -[FederatedCredential](https://developer.mozilla.org/docs/Web/API/FederatedCredential) -and it's partially supported by -[PublicKeyCredential](https://developer.mozilla.org/docs/Web/API/PublicKeyCredential) +The `mediation` is [a property in the Credential Management +API](https://developer.mozilla.org/docs/Web/API/CredentialsContainer/get#:~:text=mediation), +it behaves in [the same +way](https://web.dev/articles/security-credential-management-retrieve-credentials) as it +does for +[PasswordCredential](https://developer.mozilla.org/docs/Web/API/PasswordCredential) +and +[FederatedCredential](https://developer.mozilla.org/docs/Web/API/FederatedCredential) +and it's partially supported by +[PublicKeyCredential](https://developer.mozilla.org/docs/Web/API/PublicKeyCredential) as well. The property accepts the following four values: -* `'optional'`(default): Auto-reauthn if possible, requires a mediation if not. We +* `'optional'`(default): Auto-reauthn if possible, requires a mediation if not. We recommend choosing this option on the sign-in page. -* `'required'`: Always requires a mediation to proceed, for example, clicking the - "Continue" button on the UI. Choose this option if your users are expected to +* `'required'`: Always requires a mediation to proceed, for example, clicking the + "Continue" button on the UI. Choose this option if your users are expected to grant permission explicitly every time they need to be authenticated. * `'silent'`: Auto-reauthn if possible, silently fail without requiring a mediation if not. We recommend choosing this option on the pages other than @@ -625,9 +625,9 @@ as well. The property accepts the following four values: With this call, auto-reauthn happens under the following conditions: -* FedCM is available to use. For example, the user has not [disabled FedCM +* FedCM is available to use. For example, the user has not [disabled FedCM either globally](#settings) or for the RP in the settings. -* The user used only one account with FedCM API to sign into the website on this +* The user used only one account with FedCM API to sign into the website on this browser. * The user is signed into the IdP with that account. * The auto-reauthn didn't happen within the last 10 minutes. @@ -649,12 +649,12 @@ the user starts as soon as the FedCM `navigator.credentials.get()` is invoked. #### Enforce mediation with `preventSilentAccess()` {: #prevent-silent-access } -Auto-reauthenticating users immediately after they sign out would not make for a -very good user experience. That's why FedCM has a 10-minute quiet period after -an auto-reauthn to prevent this behavior. This means that auto-reauthn happens -at most once in every 10-minutes unless the user signs back in within -10-minutes. The RP should call `navigator.credentials.preventSilentAccess()` to -explicitly request the browser to disable auto-reauthn when a user signs out of +Auto-reauthenticating users immediately after they sign out would not make for a +very good user experience. That's why FedCM has a 10-minute quiet period after +an auto-reauthn to prevent this behavior. This means that auto-reauthn happens +at most once in every 10-minutes unless the user signs back in within +10-minutes. The RP should call `navigator.credentials.preventSilentAccess()` to +explicitly request the browser to disable auto-reauthn when a user signs out of the RP explicitly, for example, by clicking a sign-out button. ```js @@ -670,12 +670,12 @@ Users can opt-out from auto-reauth from the settings menu: * On desktop Chrome, go to `chrome://password-manager/settings` > Sign in automatically. -* On Android Chrome, open **Settings** > **Password Manager** > Tap on a +* On Android Chrome, open **Settings** > **Password Manager** > Tap on a cog at the top right corner > Auto sign-in. -By disabling the toggle, the user can opt-out from auto-reauthn behavior all -together. This setting is stored and synchronized across devices, if the user is -signed into a Google account on the Chrome instance and synchronization is +By disabling the toggle, the user can opt-out from auto-reauthn behavior all +together. This setting is stored and synchronized across devices, if the user is +signed into a Google account on the Chrome instance and synchronization is enabled. {% Aside %} diff --git a/site/en/docs/privacy-sandbox/fenced-frame/index.md b/site/en/docs/privacy-sandbox/fenced-frame/index.md index 7baff69b8..0b329804b 100644 --- a/site/en/docs/privacy-sandbox/fenced-frame/index.md +++ b/site/en/docs/privacy-sandbox/fenced-frame/index.md @@ -39,12 +39,12 @@ the `shoes.example` ad, and `shoes.example` cannot learn first-party data from ### Strengthen cross-site privacy with storage partitioning -While browsing the web, you've probably looked at products on one site, and then +While browsing the web, you've probably looked at products on one site, and then you've seen them appear again in an ad on a completely different site. -Today, this advertising technique is achieved primarily through tracking -technology that uses third-party cookies to share information across sites. This -is technology which [Chrome has committed to phase +Today, this advertising technique is achieved primarily through tracking +technology that uses third-party cookies to share information across sites. This +is technology which [Chrome has committed to phase out](https://blog.google/products/chrome/updated-timeline-privacy-sandbox-milestones/) and replace with more privacy-preserving variants. @@ -56,7 +56,7 @@ then that value can be read from the `shoes.example` site. When storage has been partitioned, cross-site iframes will no longer share storage, therefore `shoes.example` will not be able to access information stored by the iframe. If the iframe is served from `*.shoes.example` and embedded on -`*.shoes.example`, browser storage will be shared as these are considered [same-site](https://web.dev/same-site-same-origin/). +`*.shoes.example`, browser storage will be shared as these are considered [same-site](https://web.dev/articles/same-site-same-origin). {% Img src="image/hVf1flv5Jdag8OQKYqOcJgWUvtz1/ss7wjBshEJcwdQXcXGov.png", alt="A comparison of before and after state of storage partitinoing.", width="800", height="613" %} @@ -165,7 +165,7 @@ to existing iframe features. <td>Yes (dependent on use case)</td> </tr> </tbody></table> - + Fenced frames support fewer external communication options to preserve privacy. @@ -275,7 +275,7 @@ const frameData = { await window.sharedStorage.worklet.addModule('reporting-worklet.js'); await window.sharedStorage.run('send-report', { - data: { + data: { frameData }, }); @@ -305,7 +305,7 @@ class ReportingOperation { register('send-report', ReportingOperation); ``` -To learn more about the embedder’s context in a fenced frame config object, see the [explainer](https://github.com/WICG/fenced-frame/blob/master/explainer/fenced_frame_config_context.md). +To learn more about the embedder’s context in a fenced frame config object, see the [explainer](https://github.com/WICG/fenced-frame/blob/master/explainer/fenced_frame_config_context.md). ## Try fenced frames @@ -358,15 +358,15 @@ browsers](https://chromestatus.com/feature/5699388062040064#consensus). Fenced Frames are under active discussion and subject to change in the future. If you try this API and have feedback, we'd love to hear it. -* **GitHub**: Read the [explainer](https://github.com/shivanigithub/fenced-frame), - [raise questions, and follow +* **GitHub**: Read the [explainer](https://github.com/shivanigithub/fenced-frame), + [raise questions, and follow discussion](https://github.com/shivanigithub/fenced-frame/issues). * **Developer support**: Ask questions and join discussions on the - [Privacy Sandbox Developer Support + [Privacy Sandbox Developer Support repo](https://github.com/GoogleChromeLabs/privacy-sandbox-dev-support). ## Find out more * [Chrome Platform Status](https://chromestatus.com/feature/5699388062040064) -* [Blink Intent to +* [Blink Intent to Prototype](https://groups.google.com/a/chromium.org/g/blink-dev/c/Ko9UXQYPgUE/m/URRsB-qvAAAJ) diff --git a/site/en/docs/privacy-sandbox/floc/index.md b/site/en/docs/privacy-sandbox/floc/index.md index 1dddf66c3..a36946b41 100644 --- a/site/en/docs/privacy-sandbox/floc/index.md +++ b/site/en/docs/privacy-sandbox/floc/index.md @@ -4,9 +4,9 @@ title: 'FLoC' subhead: > Allow sites to guess your interests without being able to uniquely identify you. description: > - FLoC enables interest-based advertising in a way that preserves privacy. As a user moves around the - web, their browser is assigned to an "interest cohort" along with thousands of others with a - similar browsing history. This is done without sharing individual browsing history with the browser + FLoC enables interest-based advertising in a way that preserves privacy. As a user moves around the + web, their browser is assigned to an "interest cohort" along with thousands of others with a + similar browsing history. This is done without sharing individual browsing history with the browser vendor or anyone else. date: 2021-05-18 updated: 2021-10-29 @@ -17,23 +17,23 @@ authors: ## Implementation status -* Initial [origin trial](https://web.dev/origin-trials) now closed. +* Initial [origin trial](https://web.dev/origin-trials) now closed. * [Demo](https://floc.glitch.me/) of initial version (origin trial now closed). -* [Intent to Experiment](https://groups.google.com/a/chromium.org/g/blink-dev/c/MmijXrmwrJs) in +* [Intent to Experiment](https://groups.google.com/a/chromium.org/g/blink-dev/c/MmijXrmwrJs) in [Blink](https://www.chromium.org/blink). {% Aside %} -This post outlines the API design implemented in Chrome for the first origin trial of FLoC. +This post outlines the API design implemented in Chrome for the first origin trial of FLoC. -Future iterations of an API to enable interest-based advertising without third-party cookies +Future iterations of an API to enable interest-based advertising without third-party cookies or other cross-site tracking mechanisms are currently in development. {% endAside %} ## Why do we need FLoC? -Many people are concerned about the privacy implications of tailored advertising, which currently -relies on techniques such as tracking cookies and device fingerprinting which can reveal your -browsing history across sites to advertisers or ad platforms. The FLoC proposal aims to allow ad +Many people are concerned about the privacy implications of tailored advertising, which currently +relies on techniques such as tracking cookies and device fingerprinting which can reveal your +browsing history across sites to advertisers or ad platforms. The FLoC proposal aims to allow ad selection in a way that better protects privacy. @@ -41,41 +41,41 @@ selection in a way that better protects privacy. FLoC provides a privacy-preserving mechanism for interest-based selection of ads and other content. -As a user moves around the web, their browser uses the FLoC algorithm to work out its -"interest cohort", which will be the same for thousands of browsers with a similar recent browsing -history. The browser recalculates its cohort periodically, on the user's device, without sharing +As a user moves around the web, their browser uses the FLoC algorithm to work out its +"interest cohort", which will be the same for thousands of browsers with a similar recent browsing +history. The browser recalculates its cohort periodically, on the user's device, without sharing individual browsing data with the browser vendor or anyone else. -Advertisers (sites that pay for advertisements) can include code on their own websites to gather and -provide cohort data to their ad tech platforms (companies that provide software and tools to deliver -advertising). For example, an ad tech platform might learn from an online shoe store that browsers -from cohorts 1101 and 1354 seem interested in the store's hiking gear. From other advertisers, the +Advertisers (sites that pay for advertisements) can include code on their own websites to gather and +provide cohort data to their ad tech platforms (companies that provide software and tools to deliver +advertising). For example, an ad tech platform might learn from an online shoe store that browsers +from cohorts 1101 and 1354 seem interested in the store's hiking gear. From other advertisers, the ad tech platform learns about other interests of those cohorts. -Subsequently, the ad platform can use this data to select relevant ads when a browser from one of +Subsequently, the ad platform can use this data to select relevant ads when a browser from one of those cohorts visits a page from a site that displays ads, such as a news website. ## What can FLoC be used for? -* Show ads to people whose browsers belong to a cohort that has been observed to frequently visit an +* Show ads to people whose browsers belong to a cohort that has been observed to frequently visit an advertiser's site or shows interest in relevant topics. -* Use machine learning models to predict the probability a user will convert based on their cohort, +* Use machine learning models to predict the probability a user will convert based on their cohort, in order to inform ad auction bidding behavior. -* Recommend content to users. For example, suppose a news site observes that their sports podcast -page has become especially popular with visitors from cohorts 1234 and 14159. They can recommend +* Recommend content to users. For example, suppose a news site observes that their sports podcast +page has become especially popular with visitors from cohorts 1234 and 14159. They can recommend that content to other visitors from those cohorts. ## How does FLoC work? -[What is FLoC?](https://web.dev/floc/#how-does-floc-work) provides a simple, step-by-step -explanation of how FloC works. +[What is FLoC?](https://web.dev/articles/floc#how_does_floc_work) provides a simple, step-by-step +explanation of how FloC works. -The diagram below shows an example of the different roles in selecting and delivering a relevant ad +The diagram below shows an example of the different roles in selecting and delivering a relevant ad by using FLoC. -{% Img src="image/80mq7dk16vVEg8BBhsVe42n6zn82/oH6SuZegrVJMbkTsl9mq.png", -alt="Diagram showing, step by step, the different roles in selecting and delivering a relevant ad by +{% Img src="image/80mq7dk16vVEg8BBhsVe42n6zn82/oH6SuZegrVJMbkTsl9mq.png", +alt="Diagram showing, step by step, the different roles in selecting and delivering a relevant ad by using FLoC: FLoC service, Browser, Advertisers, Publisher (to observe cohorts), Ad tech, Publisher (to display ads)", width="800", height="359" %} @@ -85,10 +85,10 @@ alt="Diagram showing, step by step, the different roles in selecting and deliver ## Engage and share feedback -* **GitHub**: Read the [proposal](https://github.com/WICG/floc), [raise questions and +* **GitHub**: Read the [proposal](https://github.com/WICG/floc), [raise questions and follow discussion](https://github.com/WICG/floc/issues). * **W3C**: Discuss industry use cases in the [Improving Web Advertising Business Group](https://www.w3.org/community/web-adv/participants). -* **Developer support**: Ask questions and join discussions on the +* **Developer support**: Ask questions and join discussions on the [Privacy Sandbox Developer Support repo](https://github.com/GoogleChromeLabs/privacy-sandbox-dev-support). diff --git a/site/en/docs/privacy-sandbox/permissions-policy/index.md b/site/en/docs/privacy-sandbox/permissions-policy/index.md index cff87bba4..b95f0417f 100644 --- a/site/en/docs/privacy-sandbox/permissions-policy/index.md +++ b/site/en/docs/privacy-sandbox/permissions-policy/index.md @@ -17,19 +17,19 @@ policies are applied to origins provided in a response header origin list. The origin list can contain same-origins and/or cross-origins, and it allows the developer to control first-party and third-party access to browser features. -The user has the final decision to allow access to more powerful features, and needs to provide explicit permission via a prompt. +The user has the final decision to allow access to more powerful features, and needs to provide explicit permission via a prompt. Permissions Policy allows the top-level site to define what it and its third parties intend to use, and removes the burden from the user of determining whether the feature access request is legitimate or not. For example, by blocking the geolocation feature for all third parties via Permissions Policy, the developer can be certain that no third party will gain access to the user's -geolocation. +geolocation. {% Aside %} -[Privacy Sandbox](https://web.dev/digging-into-the-privacy-sandbox/) is a series of proposals and APIs to satisfy third-party use cases without third-party cookies or other tracking mechanisms. +[Privacy Sandbox](https://web.dev/articles/digging-into-the-privacy-sandbox) is a series of proposals and APIs to satisfy third-party use cases without third-party cookies or other tracking mechanisms. -Privacy Sandbox APIs, such as [User-Agent Client Hints](https://web.dev/user-agent-client-hints/) and the [Topics API](/docs/privacy-sandbox/topics/), are managed by Permissions Policy in the same way that features like `geolocation` and `camera` are managed. For a list of web platform APIs that rely on Permissions Policy, see the [feature list](https://github.com/w3c/webappsec-permissions-policy/blob/main/features.md). Note, this list may not be current. +Privacy Sandbox APIs, such as [User-Agent Client Hints](https://web.dev/articles/user-agent-client-hints) and the [Topics API](/docs/privacy-sandbox/topics/), are managed by Permissions Policy in the same way that features like `geolocation` and `camera` are managed. For a list of web platform APIs that rely on Permissions Policy, see the [feature list](https://github.com/w3c/webappsec-permissions-policy/blob/main/features.md). Note, this list may not be current. {% endAside %} @@ -66,38 +66,38 @@ If the response does not contain a Permissions Policy header, the origin list is Therefore, we recommend developers explicitly set the Permissions Policy header in the response, so that cross-origin iframes which aren't listed in the origin list are blocked from accessing this feature, even if `allow` is present. -Feature Policy can still be used after Chrome 88, but it acts as an alias for Permissions Policy. Other than the syntax, there is no difference in logic. If both Permissions Policy and Feature Policy headers are used together, the `Permissions-Policy` header will have higher priority, and will overwrite the value provided by the `Feature-Policy` header. +Feature Policy can still be used after Chrome 88, but it acts as an alias for Permissions Policy. Other than the syntax, there is no difference in logic. If both Permissions Policy and Feature Policy headers are used together, the `Permissions-Policy` header will have higher priority, and will overwrite the value provided by the `Feature-Policy` header. ## How do I use Permissions Policy? {: #usage } ### Quick overview -Before we dive deep, let's take a quick look at a common scenario where you are the owner of a website and you want to control how your site and third-party code use browser features. +Before we dive deep, let's take a quick look at a common scenario where you are the owner of a website and you want to control how your site and third-party code use browser features. * Your site is `https://your-site.example`. -* Your site embeds an iframe from same-origin (`https://your-site.example`). -* Your site embeds an iframe from `https://trusted-site.example` that you trust. -* Your site also displays ads served by `https://ad.example`. -* You want to allow geolocation only for your site and the trusted site, not for the ad. +* Your site embeds an iframe from same-origin (`https://your-site.example`). +* Your site embeds an iframe from `https://trusted-site.example` that you trust. +* Your site also displays ads served by `https://ad.example`. +* You want to allow geolocation only for your site and the trusted site, not for the ad. -In this case, use the following header: +In this case, use the following header: ```text Permissions-Policy: geolocation=(self "https://trusted-site.example") ``` And explicitly set the `allow` attribute to the iframe tag for the trusted site: - + ```html <iframe src="https://trusted-site.example" allow="geolocation"> ``` {% Img src="image/hVf1flv5Jdag8OQKYqOcJgWUvtz1/8mRSZZQAhoAHsa6Tgvyo.png", alt="Quick overview diagram of Permissions Policy usage.", width="700", height="238" %} -In this example, the header origin list lets only your site (`self`) and `trusted-site.example` to use the geolocation feature. `ad.example` is not allowed to use geolocation. +In this example, the header origin list lets only your site (`self`) and `trusted-site.example` to use the geolocation feature. `ad.example` is not allowed to use geolocation. 1. Your site `your-site.example` is allowed to use the geolocation feature with the user's consent. 1. A same-origin iframe (`your-site.example`) is allowed to use the feature without the usage of the `allow` attribute. -1. An iframe served from a different subdomain (`subdomain.your-site-example`) that was not added to the origin list, and has the allow attribute set on the iframe tag, is blocked from using the feature. Different subdomains are considered same-site but cross-origin. +1. An iframe served from a different subdomain (`subdomain.your-site-example`) that was not added to the origin list, and has the allow attribute set on the iframe tag, is blocked from using the feature. Different subdomains are considered same-site but cross-origin. 1. A cross-origin iframe (`trusted-site.example`) that was added to the origin list and has the `allow` attribute set on the iframe tag is allowed to use the feature. 1. A cross-origin iframe (`trusted-site.example`) added to the origin list, without the `allow` attribute, is blocked from using the feature. 1. A cross-origin iframe (`ad.example`) which wasn't added to the origin list is blocked from using the feature, even if the `allow` attribute is included in the iframe tag. @@ -112,11 +112,11 @@ Permissions-Policy: <feature>=(<token>|<origin(s)>) Use a `Permissions-Policy` header in the response from the server to set the allowed origins for a feature. The header value can take a combination of tokens and strings of origins. The [available tokens](https://w3c.github.io/webappsec-permissions-policy/#structured-header-serialization) are `*` for all origins and `self` for same-origin. -If your header is for multiple features, separate the features with a comma. If you list multiple origins, separate each origin in the origin list with a space. For headers which list an origin that's a cross-origin request, the iframe tag must include the `allow` attribute. +If your header is for multiple features, separate the features with a comma. If you list multiple origins, separate each origin in the origin list with a space. For headers which list an origin that's a cross-origin request, the iframe tag must include the `allow` attribute. Here are some example key-value pairs: -* Syntax: `[FEATURE]=*` +* Syntax: `[FEATURE]=*` * Policy applied to all origins * Example: `geolocation=*` * Syntax: `[FEATURE]=(self)` @@ -126,27 +126,27 @@ Here are some example key-value pairs: * Policy applied to same origin and the specified origins * Example: `geolocation=(self "https://a.example" "https://b.example")` * `self` is a shorthand for `https://your-site.example` -* Syntax: `[FEATURE]=([ORIGIN(s)])` +* Syntax: `[FEATURE]=([ORIGIN(s)])` * Policy applied to same origin and the specified origins * Example: `geolocation=("https://your-site.example" "https://a.example" "https://b.example")` * When using this syntax, one of the origins should be the origin of the embedder. If the embedder page itself is not granted the permissions, the iframes embedded in that page will be also blocked even though they are added to the origin list because Permissions Policy delegates permissions. You can also use the `self` token. -* Syntax: `[FEATURE]=()` +* Syntax: `[FEATURE]=()` * Feature blocked for all origins * Example: `geolocation=()` {% Aside 'warning' %} -If the Permission Policy header is not present in the response, the default value `*` token is used. This allows all iframes on the page with an `allow` attribute to use the feature. Therefore, it is strongly recommended that the origin list is explicitly set in the Permissions-Policy header to control access. +If the Permission Policy header is not present in the response, the default value `*` token is used. This allows all iframes on the page with an `allow` attribute to use the feature. Therefore, it is strongly recommended that the origin list is explicitly set in the Permissions-Policy header to control access. {% endAside %} {% Aside 'gotchas' %} -With the change in Permissions Policy from Feature Policy, adding the origin to the header origin list is no longer enough to enable the feature for a cross-origin iframe. The iframe must include the `allow` attribute if it's cross-origin, regardless of what is set in the header origin list. +With the change in Permissions Policy from Feature Policy, adding the origin to the header origin list is no longer enough to enable the feature for a cross-origin iframe. The iframe must include the `allow` attribute if it's cross-origin, regardless of what is set in the header origin list. {% endAside %} #### Different subdomains and paths -Different subdomains, such as `https://your-site.example` and `https://subdomain.your-site.example`, are considered [same-site but cross-origin](https://web.dev/same-site-same-origin/). Therefore, adding a subdomain in the origin list does not allow access to another subdomain of the same site. Every embedded subdomain that wants to use the feature must be added separately to the origin list. For example, if access to the user's browsing topics is allowed to the same-origin only with the header `Permissions-Policy: browsing-topics=(self)`, an iframe from a different subdomain of the same site, `https://subdomain.your-site.example`, will not have access to the topics. +Different subdomains, such as `https://your-site.example` and `https://subdomain.your-site.example`, are considered [same-site but cross-origin](https://web.dev/articles/same-site-same-origin). Therefore, adding a subdomain in the origin list does not allow access to another subdomain of the same site. Every embedded subdomain that wants to use the feature must be added separately to the origin list. For example, if access to the user's browsing topics is allowed to the same-origin only with the header `Permissions-Policy: browsing-topics=(self)`, an iframe from a different subdomain of the same site, `https://subdomain.your-site.example`, will not have access to the topics. -Different paths, such as `https://your-site.example` and `https://your-site.example/embed`, are considered same-origin, and different paths do not have to be listed in the origin list. +Different paths, such as `https://your-site.example` and `https://your-site.example/embed`, are considered same-origin, and different paths do not have to be listed in the origin list. ### Iframe `allow` attribute @@ -163,14 +163,14 @@ For example: ``` {% Aside %} -The syntax `allow="geolocation"` is a shorthand for allow="geolocation 'src'". src is a special token that expands into the origin of the iframe's `src` attribute. -{% endAside %} +The syntax `allow="geolocation"` is a shorthand for allow="geolocation 'src'". src is a special token that expands into the origin of the iframe's `src` attribute. +{% endAside %} #### Handling iframe navigation {% Img src="image/hVf1flv5Jdag8OQKYqOcJgWUvtz1/Y7RGrm7k7ysTtKfLvhO4.png", alt="Iframe navigation setup", width="500", height="283" %} -By default, if an iframe navigates to another origin, the policy is not applied to the origin that the iframe navigates to. By listing the origin that the iframe navigates to in the `allow` attribute, the Permissions Policy that was applied to the original iframe will be applied to the origin the iframe navigates to. +By default, if an iframe navigates to another origin, the policy is not applied to the origin that the iframe navigates to. By listing the origin that the iframe navigates to in the `allow` attribute, the Permissions Policy that was applied to the original iframe will be applied to the origin the iframe navigates to. ```html <iframe src="https://trusted-site.example" allow="geolocation https://trusted-site.example https://trusted-navigated-site.example"> @@ -195,9 +195,9 @@ Permissions-Policy: geolocation=* <iframe src="https://ad.example" allow="geolocation"> ``` -When the origin list is set to the `*` token, the feature is allowed for all origins present on the page, including itself and all iframes. In this example, all code served from `https://your-site.example` and the codes served from `https://trusted-site.example` iframe and `https://ad.example` have access to the geolocation feature in the user's browser. Remember that the allow attribute must also be set on the iframe itself along with adding the origin to the header origin list. +When the origin list is set to the `*` token, the feature is allowed for all origins present on the page, including itself and all iframes. In this example, all code served from `https://your-site.example` and the codes served from `https://trusted-site.example` iframe and `https://ad.example` have access to the geolocation feature in the user's browser. Remember that the allow attribute must also be set on the iframe itself along with adding the origin to the header origin list. -This setup can be seen in the [demo](https://permissions-policy-demo.glitch.me/demo/all-allowed). +This setup can be seen in the [demo](https://permissions-policy-demo.glitch.me/demo/all-allowed). ### Feature allowed on same-origin only @@ -207,9 +207,9 @@ This setup can be seen in the [demo](https://permissions-policy-demo.glitch.me/d Permissions-Policy: geolocation=(self) ``` -Using the `self` token allows geolocation usage to the same-origin only. Cross-origins will not have access to the feature. In this example, only `https://trusted-site.example` (`self`) will have access to geolocation. Utilize this syntax if you want the feature only for your page and no one else. +Using the `self` token allows geolocation usage to the same-origin only. Cross-origins will not have access to the feature. In this example, only `https://trusted-site.example` (`self`) will have access to geolocation. Utilize this syntax if you want the feature only for your page and no one else. -This setup can be seen in the [demo](https://permissions-policy-demo.glitch.me/demo/same-allowed). +This setup can be seen in the [demo](https://permissions-policy-demo.glitch.me/demo/same-allowed). ### Feature allowed on same-origin and specific cross-origins @@ -219,9 +219,9 @@ This setup can be seen in the [demo](https://permissions-policy-demo.glitch.me/d Permissions-Policy: geolocation=(self "https://trusted-site.example") ``` -This syntax allows the usage of geolocation to both self (`https://your-site.example`) and `https://trusted-site.example`. Remember to explicitly add the allow attribute to the iframe tag. If there is another iframe with `<iframe src="https://ad.example" allow="geolocation">`, then `https://ad.example` will not have access to the geolocation feature. Only the original page and `https://trusted-site.example` that is listed in the origin list along with having the allow attribute in the iframe tag will have access to the user's feature. +This syntax allows the usage of geolocation to both self (`https://your-site.example`) and `https://trusted-site.example`. Remember to explicitly add the allow attribute to the iframe tag. If there is another iframe with `<iframe src="https://ad.example" allow="geolocation">`, then `https://ad.example` will not have access to the geolocation feature. Only the original page and `https://trusted-site.example` that is listed in the origin list along with having the allow attribute in the iframe tag will have access to the user's feature. -This setup can be seen in the [demo](https://permissions-policy-demo.glitch.me/demo/some-allowed). +This setup can be seen in the [demo](https://permissions-policy-demo.glitch.me/demo/some-allowed). ### Feature blocked on all origins @@ -231,7 +231,7 @@ This setup can be seen in the [demo](https://permissions-policy-demo.glitch.me/d Permissions-Policy: geolocation=() ``` -With an empty origin list, the feature is blocked for all origins. This setup can be seen in the [demo](https://permissions-policy-demo.glitch.me/demo/none-allowed). +With an empty origin list, the feature is blocked for all origins. This setup can be seen in the [demo](https://permissions-policy-demo.glitch.me/demo/none-allowed). {% Aside 'gotchas' %} It isn't possible to allow the feature for embedded cross-origins if the feature is blocked for same-origin. Since the permissions applied to the parent page are delegated to the embedded iframes, the feature must be enabled for same-origin if the feature is to be allowed for cross-origins. @@ -241,22 +241,22 @@ It isn't possible to allow the feature for embedded cross-origins if the feature The existing JavaScript API of Feature Policy is found as an object on either the document or the element (`document.featurePolicy or element.featurePolicy`). The JavaScript API for Permissions Policy has not been implemented yet. -The Feature Policy API can be used for policies set by Permissions Policy, with some limitations. There are [remaining questions](https://github.com/w3c/webappsec-permissions-policy/issues/401) regarding a JavaScript API implementation, and a [proposal](https://github.com/w3c/webappsec-permissions-policy/issues/401#issuecomment-824878596) has been made to move the logic into the [Permissions API](https://developer.mozilla.org/docs/Web/API/Permissions_API). Join the discussion if you have any thoughts. +The Feature Policy API can be used for policies set by Permissions Policy, with some limitations. There are [remaining questions](https://github.com/w3c/webappsec-permissions-policy/issues/401) regarding a JavaScript API implementation, and a [proposal](https://github.com/w3c/webappsec-permissions-policy/issues/401#issuecomment-824878596) has been made to move the logic into the [Permissions API](https://developer.mozilla.org/docs/Web/API/Permissions_API). Join the discussion if you have any thoughts. ### featurePolicy.allowsFeature(feature) -* Returns `true` if the feature is allowed for the default-origin usage. +* Returns `true` if the feature is allowed for the default-origin usage. * The behavior is the same for both policies set by Permissions Policy and the previous Feature Policy * When `allowsFeature()` is called on an iframe element (`iframeEl.featurePolicy.allowsFeature('geolocation')`), the returned value reflects if the allow attribute is set on the iframe ### featurePolicy.allowsFeature(feature, origin) -* Returns `true` if the feature is allowed for the specified origin. -* If the method is called on `document`, this method no longer tells you whether the feature is allowed for the specified origin like Feature Policy did. Now, this method tells you that it's possible for the feature to be allowed to that origin. You must conduct an additional check of whether the iframe has the `allow` attribute set or not. The developer must conduct an additional check for the `allow` attribute on the iframe element to determine if the feature is allowed for the third-party origin. +* Returns `true` if the feature is allowed for the specified origin. +* If the method is called on `document`, this method no longer tells you whether the feature is allowed for the specified origin like Feature Policy did. Now, this method tells you that it's possible for the feature to be allowed to that origin. You must conduct an additional check of whether the iframe has the `allow` attribute set or not. The developer must conduct an additional check for the `allow` attribute on the iframe element to determine if the feature is allowed for the third-party origin. #### Check for features in an iframe with the `element` object -You can use `element.allowsFeature(feature)` that takes the allow attribute into account unlike `document.allowsFeature(feature, origin)` that does not. +You can use `element.allowsFeature(feature)` that takes the allow attribute into account unlike `document.allowsFeature(feature, origin)` that does not. ```js const someIframeEl = document.getElementById('some-iframe') @@ -282,7 +282,7 @@ Check out how Permissions Policy works in DevTools. 1. [Open Chrome DevTools](/docs/devtools/open/#elements). 2. Open the **Application** panel to check the allowed features and disallowed features of each frame. -3. In the sidebar, select the frame that you want to inspect. You will be presented with a list of features that the selected frame is allowed to use and a list of features that are blocked in that frame. +3. In the sidebar, select the frame that you want to inspect. You will be presented with a list of features that the selected frame is allowed to use and a list of features that are blocked in that frame. ## Migration from Feature-Policy @@ -298,7 +298,7 @@ Feature-Policy: autoplay *; geolocation 'self'; camera 'self' 'https://trusted-site.example'; - fullscreen 'none'; + fullscreen 'none'; ``` {% CompareCaption %} Before with Feature Policy. @@ -307,7 +307,7 @@ Feature-Policy: {% Compare 'better', 'new' %} ```text -Permissions-Policy: +Permissions-Policy: autoplay=*, geolocation=(self), camera=(self "https://trusted-site.example"), @@ -320,11 +320,11 @@ Permissions-Policy: ### Update `document.allowsFeature(feature, origin)` usage -If you are using `document.allowsFeature(feature, origin)` method to check allowed features for iframes, use `allowsFeature(feature)` method attached on the iframe element, and not the containing `document`. The method `element.allowsFeature(feature)` accounts for the allow attribute while `document.allowsFeature(feature, origin)` does not. +If you are using `document.allowsFeature(feature, origin)` method to check allowed features for iframes, use `allowsFeature(feature)` method attached on the iframe element, and not the containing `document`. The method `element.allowsFeature(feature)` accounts for the allow attribute while `document.allowsFeature(feature, origin)` does not. #### Checking feature access with `document` -To continue using `document` as the base node, then you must conduct an additional check for the `allow` attribute on the iframe tag. +To continue using `document` as the base node, then you must conduct an additional check for the `allow` attribute on the iframe tag. ```html <iframe id="some-iframe" src="https://example.com" allow="camera"></iframe> @@ -335,10 +335,10 @@ Permissions-Policy: camera=(self "https://example.com") ``` ```js -const isCameraPolicySet = document.featurePolicy.allowsFeature('camera', 'https://example.com') +const isCameraPolicySet = document.featurePolicy.allowsFeature('camera', 'https://example.com') const someIframeEl = document.getElementById('some-iframe') -const hasCameraAttributeValue = someIframeEl.hasAttribute('allow') +const hasCameraAttributeValue = someIframeEl.hasAttribute('allow') && someIframeEl.getAttribute('allow').includes('camera') const isCameraFeatureAllowed = isCameraPolicySet && hasCameraAttributeValue @@ -348,11 +348,11 @@ Instead of updating the existing code using `document`, it's recommended to call ## Reporting API -The [Reporting API](https://web.dev/reporting-api/) provides a reporting mechanism for web applications in a consistent manner, and Reporting API for Permissions Policy violations is available as an experimental feature. +The [Reporting API](https://web.dev/articles/reporting-api) provides a reporting mechanism for web applications in a consistent manner, and Reporting API for Permissions Policy violations is available as an experimental feature. -If you would like to test the experimental feature, follow the [walkthrough](https://web.dev/reporting-api/#use-devtools) and enable the flag in `chrome://flags/#enable-experimental-web-platform-features`. With the flag enabled, you can observe Permissions Policy violations in DevTools under the Application tab: +If you would like to test the experimental feature, follow the [walkthrough](https://web.dev/articles/reporting-api#use_devtools) and enable the flag in `chrome://flags/#enable-experimental-web-platform-features`. With the flag enabled, you can observe Permissions Policy violations in DevTools under the Application tab: -The following example shows how the Reporting API header may be constructed: +The following example shows how the Reporting API header may be constructed: ```text Reporting-Endpoints: main-endpoint="https://reports.example/main", default="https://reports.example/default" @@ -361,7 +361,7 @@ Content-Security-Policy: script-src 'self'; object-src 'none'; report-to main-en Document-Policy: document-write=?0; report-to=main-endpoint; ``` -In the current implementation, you can receive policy violation reports from any violations occurring within that frame by configuring an endpoint named 'default' like the example above. Subframes will require their own reporting configuration. +In the current implementation, you can receive policy violation reports from any violations occurring within that frame by configuring an endpoint named 'default' like the example above. Subframes will require their own reporting configuration. {% Aside %} If you would like to see Permissions Policy support in the Reporting API by default, [add your support or comments to the discussion](https://github.com/w3c/webappsec-permissions-policy/issues/386). @@ -369,7 +369,7 @@ If you would like to see Permissions Policy support in the Reporting API by defa ## Find out more -For a deeper understanding of Permissions Policy, refer to the following resources: +For a deeper understanding of Permissions Policy, refer to the following resources: * [Permissions Policy specs](https://www.w3.org/TR/permissions-policy-1/) * [Permissions Policy explainer](https://github.com/w3c/webappsec-permissions-policy/blob/main/permissions-policy-explainer.md) diff --git a/site/en/docs/privacy-sandbox/private-state-tokens/index.md b/site/en/docs/privacy-sandbox/private-state-tokens/index.md index 0d3763fad..3358a13df 100644 --- a/site/en/docs/privacy-sandbox/private-state-tokens/index.md +++ b/site/en/docs/privacy-sandbox/private-state-tokens/index.md @@ -106,7 +106,7 @@ that the user is trusted by the issuer to be a real human. 1. An ad view impression is counted. {% Aside %} -For more detail about the JavaScript calls in this example, see [Sample API usage](https://web.dev/trust-tokens/#sample-api-usage). +For more detail about the JavaScript calls in this example, see [Sample API usage](https://web.dev/articles/trust-tokens#sample_api_usage). {% endAside %} ## Is tooling available for Privacy State Tokens? @@ -132,12 +132,12 @@ follow discussion](https://github.com/WICG/trust-token-api/issues). [Privacy Pass working group](https://datatracker.ietf.org/wg/privacypass/about/). * **Developer support**: Ask questions and join discussions on the [Privacy Sandbox Developer Support repo](https://github.com/GoogleChromeLabs/privacy-sandbox-dev-support). -* **Origin trial questions**: [file a Chromium bug](https://bugs.chromium.org/p/chromium/issues/list?q=trust%20tokens) or respond to the feedback form that is sent to you as an origin trial participant. +* **Origin trial questions**: [file a Chromium bug](https://bugs.chromium.org/p/chromium/issues/list?q=trust%20tokens) or respond to the feedback form that is sent to you as an origin trial participant. ## Find out more * [Private State Token API technical explainer](https://github.com/dvorak42/trust-token-api) -* [Getting started with Private State Tokens](https://web.dev/trust-tokens/): an overview for web developers +* [Getting started with Private State Tokens](https://web.dev/articles/trust-tokens): an overview for web developers * [Getting started with Chrome's origin trials](https://web.dev/origin-trials) * [Digging into the Privacy Sandbox](https://web.dev/digging-into-the-privacy-sandbox) diff --git a/site/en/docs/privacy-sandbox/protected-audience-api/interest-groups/index.md b/site/en/docs/privacy-sandbox/protected-audience-api/interest-groups/index.md index 9e7af9f80..ccd6a6198 100644 --- a/site/en/docs/privacy-sandbox/protected-audience-api/interest-groups/index.md +++ b/site/en/docs/privacy-sandbox/protected-audience-api/interest-groups/index.md @@ -46,7 +46,7 @@ Owners of Protected Audience API interest groups can be invited to [bid in Prote The advertiser's demand-side platform (DSP) or the advertiser itself calls `navigator.joinAdInterestGroup()` to ask the browser to add an interest group -to the browser's membership list. +to the browser's membership list. The origin of the calling context for `joinAdInterestGroup()` must match the interest group owner's origin, so `joinAdInterestGroup()` will need to be @@ -128,10 +128,10 @@ previously stored values. {% Aside 'gotchas' %} All URLs used as parameters for Protected Audience API methods must be from secure origins: -all resources must be served over HTTPS URLs. [How to use HTTPS for local development](https://web.dev/how-to-use-local-https/) +all resources must be served over HTTPS URLs. [How to use HTTPS for local development](https://web.dev/articles/how-to-use-local-https) explains how to do this when running the Protected Audience API locally. -In addition, `biddingLogicUrl`, `decisionLogicUrl`, and `trustedBiddingSignals` +In addition, `biddingLogicUrl`, `decisionLogicUrl`, and `trustedBiddingSignals` require an `X-Allow-FLEDGE: true` HTTP response header. {% endAside %} @@ -196,7 +196,7 @@ The remaining properties are optional: <dd>Role: Components for <a href="https://github.com/WICG/turtledove/blob/main/FLEDGE.md#34-ads-composed-of-multiple-pieces">ads composed of multiple pieces</a>.</dd> </dl> - + <caption style="text-align:left"> <p id="first-ref"><sup>1</sup> The `biddingLogicUrl` and `ads` properties are optional, but required to participate in an auction. There may be use cases for creating an interest group without these properties: for example, an interest group owner might want to add a browser to an interest group for a campaign that isn't running yet, or for some other future use, or they may temporarily have run out of advertising budget.</p> @@ -285,7 +285,7 @@ include a `generateBid()` function. When a [seller calls `navigator.runAdAuction()`](/docs/privacy-sandbox/protected-audience-api/ad-auction), the `generateBid()` function is called once for each candidate ad. In other words, it's called for each interest group that the browser is a member -of—if the interest group's owner is invited to bid. +of—if the interest group's owner is invited to bid. The seller provides a `decisionLogicUrl` in the auction configuration parameter passed to `navigator.runAdAuction()`. The code at this @@ -449,9 +449,9 @@ Code for an ad can also call this function for its interest group. ### How do I implement frequency control by click? {% endDetailsSummary %} -For simple frequency control, you can use the `prevWins` field in `browserSignals` inside `generateBid()`. Alternatively, you can call `navigator.leaveAdInterestGroup()` to request that a user's browser leave an interest group when an ad is clicked. This prevents future bidding and acts as a form of frequency capping. +For simple frequency control, you can use the `prevWins` field in `browserSignals` inside `generateBid()`. Alternatively, you can call `navigator.leaveAdInterestGroup()` to request that a user's browser leave an interest group when an ad is clicked. This prevents future bidding and acts as a form of frequency capping. -You can also use a first-party cookie to store click information. When the ad is rendered, overwrite an existing interest group with the click data as user bidding signals. The workflow would look something like: +You can also use a first-party cookie to store click information. When the ad is rendered, overwrite an existing interest group with the click data as user bidding signals. The workflow would look something like: * User visits `advertiser.com/product`. * The advertiser writes "0 clicks" in a first-party cookie and calls `joinAdInterestGroup({ ..., userBiddingSignals: { clicks: [] } })`. @@ -467,7 +467,7 @@ You can also use a first-party cookie to store click information. When the ad is A user's browsing history for the site that called `joinAdInterestGroup()` can be updated in `userBiddingSignals`, which can be used during on-device bidding. See the [product-level TURTLEDOVE](https://github.com/WICG/turtledove/blob/main/PRODUCT_LEVEL.md) original proposal which includes some analysis by RTB House on the impact of core metrics for recommendation use case adoption. -`dailyUpdateUrl` provides a mechanism to periodically update the attributes of the interest group, but this update is not based on the user's browsing history. +`dailyUpdateUrl` provides a mechanism to periodically update the attributes of the interest group, but this update is not based on the user's browsing history. {% endDetails %} {% Details %} diff --git a/site/en/docs/privacy-sandbox/related-website-sets/index.md b/site/en/docs/privacy-sandbox/related-website-sets/index.md index 09147e4f1..ec7780112 100644 --- a/site/en/docs/privacy-sandbox/related-website-sets/index.md +++ b/site/en/docs/privacy-sandbox/related-website-sets/index.md @@ -26,7 +26,7 @@ Related sites like these often rely on cookies to keep you signed in or show you As [Chrome moves towards blocking third-party cookies](https://blog.chromium.org/2020/01/building-more-private-web-path-towards.html) to improve privacy on the web, new mechanisms are needed to enable these experiences to work. {% Aside %} -Cookies set by the site you visit—the one shown in the URL bar—are first-party cookies. A site you visit can embed content from other sites, for example, images, ads, and text. Cookies coming from sites other than the current site are [third-party cookies](https://web.dev/samesite-cookie-recipes/#use-cases-for-cross-site-or-third-party-cookies). +Cookies set by the site you visit—the one shown in the URL bar—are first-party cookies. A site you visit can embed content from other sites, for example, images, ads, and text. Cookies coming from sites other than the current site are [third-party cookies](https://web.dev/articles/samesite-cookie-recipes#use_cases_for_cross_site_or_third_party_cookies). {% endAside %} ## Defining related sites with Related Website Sets diff --git a/site/en/docs/privacy-sandbox/storage-partitioning/index.md b/site/en/docs/privacy-sandbox/storage-partitioning/index.md index 407c6f42a..f1507171b 100644 --- a/site/en/docs/privacy-sandbox/storage-partitioning/index.md +++ b/site/en/docs/privacy-sandbox/storage-partitioning/index.md @@ -13,7 +13,7 @@ updated: 2023-05-16 tags: - privacy --- - + ## Implementation status - Full implementation is available for testing in Chrome Beta 113 and later. @@ -22,14 +22,14 @@ tags: - [Chrome Platform Status](https://chromestatus.com/feature/5723617717387264) -The feature is rolling out to a small percentage of users starting in Chrome 113. +The feature is rolling out to a small percentage of users starting in Chrome 113. Depending on the stability and compatibility, it will be made fully available in Chrome Stable mid-year 2023. Testing third-party storage partitioning now and filing bugs will help uncover any potential issues and resolve them before the full rollout. - + ## What is storage partitioning? - + To prevent certain types of side-channel cross-site tracking, Chrome is partitioning storage and communications APIs in third-party contexts. @@ -40,7 +40,7 @@ about the user in the top-level site using side-channel techniques such as [Timing Attacks](https://dl.acm.org/doi/10.1145/352600.352606), [XS-Leaks](https://github.com/xsleaks/xsleaks), and [COSI](https://arxiv.org/pdf/1908.02204.pdf). - + Historically, storage has been keyed only by origin. This means that if an iframe from `example.com` is embedded on `a.com` and `b.com`, it could learn about your browsing habits for those two sites by storing and successfully @@ -52,7 +52,7 @@ Partitioning generally means that data stored by storage APIs like local storage and IndexedDB by an iframe will no longer be accessible to all contexts in the same origin. Instead, the data will only be available to contexts with the same origin and same top-level site. - + {% Columns %} {% Column %} @@ -70,7 +70,7 @@ the same origin and same top-level site. {% Column %} ### After - + <figure> {% Img src="image/vgdbNJBYHma2o62ZqYmcnkq3j0o1/X8tExxdcoVSE4P1bUKQJ.png", alt="Diagram of storage APIs with partitioning.", width="800", height="553" %} <figcaption> @@ -80,25 +80,25 @@ the same origin and same top-level site. {% endColumn %} {% endColumns %} - + ## How to test storage partitioning - + To try it out: - + 1. Use Chrome Canary version 113 or higher. 1. Visit `chrome://flags/#third-party-storage-partitioning`. 1. Enable the "Experimental Third-party Storage Partitioning" flag. - + Participate in testing and [report bugs](https://bugs.chromium.org/p/chromium/issues/entry?labels=StoragePartitioning-trial-bugs&components=Blink%3EStorage) to help the Chrome team identify and fix any unexpected behavior before the -stable launch. - +stable launch. + ## Updated APIs ### Storage APIs - [Quota system](https://web.dev/storage-for-the-web/#how-much) + [Quota system](https://web.dev/articles/storage-for-the-web#how_much) : The quota system is used to determine how much disk space is allocated for storage. The quota system will manage each partition as a separate bucket to determine how much space is permitted, and when it @@ -118,27 +118,27 @@ stable launch. [Session Storage](https://developer.mozilla.org/docs/Web/API/Window/sessionStorage). They are not currently quota-managed, but will still be partitioned. - [Origin Private File System](https://web.dev/file-system-access/#accessing-the-origin-private-file-system) + [Origin Private File System](https://web.dev/articles/file-system-access#accessing_the_origin_private_file_system) : The [File System Access API](https://web.dev/file-system-access) allows a site to read or save changes directly to files and folders on the device after the user grants access. Origin Private File System allows an origin to store private content to disk that can be easily accessed by the user, and will be partitioned. - + [Storage Bucket API](https://wicg.github.io/storage-buckets/explainer.html) : The Storage Bucket API is being developed for [Storage Standard](https://storage.spec.whatwg.org/) which consolidates various storage APIs such as IndexedDB and localStorage by using a new concept called buckets. The data stored in the buckets and the metadata associated with the buckets will be partitioned. - + [Clear-Site-Data header](https://developer.mozilla.org/docs/Web/HTTP/Headers/Clear-Site-Data) : Including the `Clear-Site-Data` header in the response allows a server to request to clear the data stored in the user's browser. Cache, cookies, and DOM storage can be cleared. Using the header will only clear the storage within one partition. - + [Blob URL](https://developer.mozilla.org/docs/Web/API/URL/createObjectURL) store : A [blob](https://developer.mozilla.org/docs/Web/API/Blob) is an object that contains raw data to be processed, and a blob URL can @@ -148,35 +148,35 @@ stable launch. store might be partitioned by the agent cluster instead of the top-level site. This feature will not be available for testing yet, and the partitioning mechanism may change in the future. - + ### Communication APIs - + Along with storage APIs, communication APIs that allow one context to communicate across origin boundaries are also partitioned. The changes mainly affect APIs that allow the discovery of other contexts via broadcasting or same-origin rendezvous. - + For the following communication APIs, third party iframe will no longer be able to communicate with its same-origin context: - + [Broadcast Channel](/blog/broadcastchannel/) : Broadcast Channel API allows communication between [browsing contexts](https://developer.mozilla.org/docs/Glossary/Browsing_context) (windows, tabs, or iframes) and workers of the same origin. : Cross-site iframe `postMessage()` where the relationship between contexts is clearly defined is not proposed to be changed. - + [SharedWorker](https://developer.mozilla.org/docs/Web/API/SharedWorker) : SharedWorker API provides a worker that can be accessed across browsing contexts of the same origin. - + [Web Locks](https://developer.mozilla.org/docs/Web/API/Web_Locks_API) : The Web Locks API allows code running in one tab or worker of the same origin to acquire a lock for a shared resource while some work is performed. - + ### Service Worker API - + The [Service Worker API](https://developer.mozilla.org/docs/Web/API/Service_Worker_API) provides the interface for conducting tasks in the background. Sites create persistent registrations that create new worker context to respond to events, @@ -187,9 +187,9 @@ potential for cross-site information leaks such as Therefore, Service Workers registered from a third-party context will be partitioned. - + ### Extension APIs - + [Extensions](/docs/extensions/mv3/) are programs that allow users to customize their browsing experience. @@ -204,12 +204,12 @@ interact with the cookies for a given site. This currently operates on cookies f in a way which can be surprising. For more information, see the [extension docs](/docs/extensions/mv3/storage-and-cookies). - + ## Engage and share feedback - + The shared storage proposal is under active discussion and subject to change in the future. If you try these APIs and have feedback, we'd love to hear it. - + - **GitHub**: Read the [proposal](https://github.com/wanderview/quota-storage-partitioning/blob/main/explainer.md), [raise questions and participate in discussion](https://github.com/wanderview/quota-storage-partitioning/issues). diff --git a/site/en/docs/privacy-sandbox/third-party-cookie-phase-out/index.md b/site/en/docs/privacy-sandbox/third-party-cookie-phase-out/index.md index 32763fa91..6de8babe0 100644 --- a/site/en/docs/privacy-sandbox/third-party-cookie-phase-out/index.md +++ b/site/en/docs/privacy-sandbox/third-party-cookie-phase-out/index.md @@ -40,7 +40,7 @@ From Chrome 118, the [DevTools Issues tab](/docs/devtools/issues/) shows the bre {% Aside %} -We are building a DevTools extension to facilitate analysis of cookie usage during browsing sessions. This will provide debugging pathways for cookies, and Privacy Sandbox features, with access points to learn and understand the different aspects of the Privacy Sandbox initiative. +We are building a DevTools extension to facilitate analysis of cookie usage during browsing sessions. This will provide debugging pathways for cookies, and Privacy Sandbox features, with access points to learn and understand the different aspects of the Privacy Sandbox initiative. **Look out for our preview launch in November 2023!** {% endAside %} @@ -84,14 +84,14 @@ For more details, check out [Recipes for first-party cookies](https://web.dev/fi Cookies that are sent in cross-site contexts, like iframes or subresource requests, are generally referred to as third-party cookies. {% Img src="image/vgdbNJBYHma2o62ZqYmcnkq3j0o1/NJLl1qG9AN8tD9GwR2jp.png", alt="Diagram showing a third-party cookie.", width="800", height="646" %} -[Some use cases for third-party cookies](https://web.dev/samesite-cookie-recipes/#use-cases-for-cross-site-or-third-party-cookies) include: +[Some use cases for third-party cookies](https://web.dev/articles/samesite-cookie-recipes#use_cases_for_cross_site_or_third_party_cookies) include: - Embedded content shared from other sites, such as videos, maps, code samples, and social posts. - Widgets from external services such as payments, calendars, booking, and reservation functionality. - Widgets such as social buttons or anti-fraud services. - Remote resources on a page such as `<img>` or `<script>` tags, that rely on cookies to be sent with a request (commonly used for tracking pixels and personalizing content). -[In 2019, browsers changed the cookie behavior, restricting them to first-party access by default](https://web.dev/samesite-cookies-explained/#changes-to-the-default-behavior-without-samesite). Any cookies used in cross-site contexts today must be set with `SameSite=None` attribute. +[In 2019, browsers changed the cookie behavior, restricting them to first-party access by default](https://web.dev/articles/samesite-cookies-explained#changes_to_the_default_behavior_without_samesite). Any cookies used in cross-site contexts today must be set with `SameSite=None` attribute. ```text Set-Cookie: cookie-name=value; SameSite=None; Secure diff --git a/site/en/docs/privacy-sandbox/user-agent/index.md b/site/en/docs/privacy-sandbox/user-agent/index.md index c2e94d5bf..a6d3df7da 100644 --- a/site/en/docs/privacy-sandbox/user-agent/index.md +++ b/site/en/docs/privacy-sandbox/user-agent/index.md @@ -26,7 +26,7 @@ Web developers should review their site code for usage of the User-Agent string. If your site relies on parsing the User-Agent string to read the device model, platform version, or full browser version, you'll need to [implement the User-Agent Client Hints -API](https://web.dev/migrate-to-ua-ch/). +API](https://web.dev/articles/migrate-to-ua-ch). {% Aside 'key-term' %} The [`User-Agent` string](https://developer.mozilla.org/docs/Web/HTTP/Headers/User-Agent) @@ -60,20 +60,20 @@ Reduced UA and UA-CH improve user privacy by sharing only basic information by d The reduced User-Agent includes the browser's brand and a significant version, where the request came from (desktop or mobile), and the platform. To access more data, User-Agent Client Hints allow you to request specific information -about the user's device or conditions. +about the user's device or conditions. Further, over time the `User-Agent` string grew longer and more complex, which led to error-prone string parsing. UA-CH provides structured and reliable data that is easier to interpret. Existing code that parses the UA string shouldn't break (though it will return less data), and you'll need to migrate to UA-CH -if your site [needs specific client +if your site [needs specific client information](https://wicg.github.io/ua-client-hints/#use-cases). ## How does the reduced UA and UA-CH work? Here is a brief example of how the reduced User-Agent string and UA-CH work. For a more in-depth example, review [Improving user privacy and developer -experience with User-Agent Client Hints](https://web.dev/user-agent-client-hints/#example-exchange). +experience with User-Agent Client Hints](https://web.dev/articles/user-agent-client-hints#example_exchange). A user opens the browser and enters `example.com` into the address bar: @@ -159,11 +159,11 @@ the high-entropy `Sec-CH-UA-Model` hint. ## How do I use and test reduced UA? {: #prepare-and-test} To begin, [review your site -code](https://web.dev/migrate-to-ua-ch/#audit-collection-and-use-of-user-agent-data) +code](https://web.dev/articles/migrate-to-ua-ch#audit_collection_and_use_of_user_agent_data) for instances and uses of the User-Agent string. If your site relies on parsing the User-Agent string to read the device model, platform version, or full browser version, you'll need to -[implement the UA-CH API](https://web.dev/migrate-to-ua-ch/). +[implement the UA-CH API](https://web.dev/articles/migrate-to-ua-ch). Once you've updated to the UA-CH API, you should test to ensure you get the data you expect from the User-Agent. There are three ways to test, each @@ -183,11 +183,11 @@ There are a couple of methods to test the reduced User-Agent locally: * Configure an emulated device in DevTools with the right `user-agent` string and client hints. * In the top right of DevTools, click - {% Img src="image/admin/CBHNS0GIpZlOcDkO1D7F.png", alt="", width="28", height="28" %} + {% Img src="image/admin/CBHNS0GIpZlOcDkO1D7F.png", alt="", width="28", height="28" %} **Settings** > **Devices** > **Add custom device...** to configure an emulated device with any combination of `user-agent` string and - User-Agent Client Hints values you need. - * In the top left of DevTools, click + User-Agent Client Hints values you need. + * In the top left of DevTools, click {% Img src="image/admin/9FiBHFCzfPgP8sy6LMx7.png", alt="", width="30", height="32" %} **Toggle Device Toolbar** to open the DevTools UI to emulate a device. * Launch Chrome with the `--user-agent="Custom string here"`. @@ -206,7 +206,7 @@ expressions. ## Support for Client Hints and critical hints -There are three [default Client Hints](https://web.dev/migrate-to-ua-ch/#are-you-only-using-basic-user-agent-data) +There are three [default Client Hints](https://web.dev/articles/migrate-to-ua-ch#are_you_only_using_basic_user_agent_data) returned to the server, including browser name and major version, a boolean that indicates if the browser is on a mobile device, and the operating system name. These are sent after the Transport Layer Security protocol (TLS) handshake. These are already available and @@ -303,9 +303,9 @@ User-Agent string. ## Find out more -* [Improving user privacy and developer experience](https://web.dev/user-agent-client-hints/): +* [Improving user privacy and developer experience](https://web.dev/articles/user-agent-client-hints): an overview for web developers -* [Migrate from UA string to UA-CH](https://web.dev/migrate-to-ua-ch/): a +* [Migrate from UA string to UA-CH](https://web.dev/articles/migrate-to-ua-ch): a tutorial for web developers * [User-Agent snippets](/docs/privacy-sandbox/user-agent/snippets/): code snippets to transform the current User-Agent string to the reduced format for diff --git a/site/en/docs/puppeteer/ssr/index.md b/site/en/docs/puppeteer/ssr/index.md index 3baa43fb3..fb4dac131 100644 --- a/site/en/docs/puppeteer/ssr/index.md +++ b/site/en/docs/puppeteer/ssr/index.md @@ -43,13 +43,13 @@ If [SEO](https://en.wikipedia.org/wiki/Search_engine_optimization) has served me well, you landed on this article for one of two reasons. First, you've built a web app and it's not being indexed the search engines! Your app might be a Single Page Application (SPA), -[PWA](https://web.dev/pwa/), using vanilla JS, or built with +[PWA](https://web.dev/articles/pwa), using vanilla JS, or built with something more complex like a library or framework. To be honest, your tech stack doesn't matter. What matters is that you spent a lot of time building Awesome Web Thing and users are unable to discover it. The other reason you might be here is because some articles out on The Web mentioned that server-side rendering is good for performance. You're here for that quick win to -reduce [JavaScript startup cost](https://web.dev/optimizing-content-efficiency-javascript-startup-optimization/) +reduce [JavaScript startup cost](https://web.dev/articles/optimizing-content-efficiency-javascript-startup-optimization) and improve [first meaningful paint](/docs/lighthouse/audits/first-meaningful-paint). @@ -294,7 +294,7 @@ What about performance numbers? On one of my ([code](https://github.com/ebidel/devwebfeed/blob/master/server.mjs)), headless Chrome takes about 1s to render the page on the server. Once the page is cached, DevTools **3G Slow emulation** puts -[FCP](https://web.dev/user-centric-performance-metrics/) at +[FCP](https://web.dev/articles/user-centric-performance-metrics) at **8.37s faster** than the client-side version. <table> diff --git a/site/en/docs/web-platform/bfcache-notrestoredreasons/index.md b/site/en/docs/web-platform/bfcache-notrestoredreasons/index.md index cc78eefc1..7bfbbb0ce 100644 --- a/site/en/docs/web-platform/bfcache-notrestoredreasons/index.md +++ b/site/en/docs/web-platform/bfcache-notrestoredreasons/index.md @@ -10,7 +10,7 @@ authors: - chrisdavidmills --- -The `notRestoredReasons` property, added to the [`PerformanceNavigationTiming`](https://developer.mozilla.org/docs/Web/API/PerformanceNavigationTiming) class, reports information on whether frames present in the document were blocked from using the [bfcache](https://web.dev/bfcache/) on navigation, and why. Developers can use this information to identify pages that need updates to make them bfcache-compatible, thereby improving site performance. +The `notRestoredReasons` property, added to the [`PerformanceNavigationTiming`](https://developer.mozilla.org/docs/Web/API/PerformanceNavigationTiming) class, reports information on whether frames present in the document were blocked from using the [bfcache](https://web.dev/articles/bfcache) on navigation, and why. Developers can use this information to identify pages that need updates to make them bfcache-compatible, thereby improving site performance. ## Current status @@ -34,14 +34,14 @@ You can try out the bfcache `notRestoredReasons` API by [registering for the ori ## Concepts and usage -Modern browsers provide an optimization feature for history navigation called the [back/forward cache](https://web.dev/bfcache/) (bfcache). This enables an instant loading experience when users go back to a page they have already visited. Pages can be blocked from entering the bfcache or get evicted while in bfcache for different reasons, some required by a specification and some specific to browser implementations. - -Previously, there was no way for developers to find out why their pages were blocked from using the bfcache in the field, though there was a [test in Chrome dev tools](https://web.dev/bfcache/#test-to-ensure-your-pages-are-cacheable). To enable monitoring in the field, the [`PerformanceNavigationTiming`](https://developer.mozilla.org/docs/Web/API/PerformanceNavigationTiming) class has been extended to include a `notRestoredReasons` property. This returns an object containing related information on all frames present in the document: - +Modern browsers provide an optimization feature for history navigation called the [back/forward cache](https://web.dev/articles/bfcache) (bfcache). This enables an instant loading experience when users go back to a page they have already visited. Pages can be blocked from entering the bfcache or get evicted while in bfcache for different reasons, some required by a specification and some specific to browser implementations. + +Previously, there was no way for developers to find out why their pages were blocked from using the bfcache in the field, though there was a [test in Chrome dev tools](https://web.dev/articles/bfcache#test_to_ensure_your_pages_are_cacheable). To enable monitoring in the field, the [`PerformanceNavigationTiming`](https://developer.mozilla.org/docs/Web/API/PerformanceNavigationTiming) class has been extended to include a `notRestoredReasons` property. This returns an object containing related information on all frames present in the document: + * Details such as frame `id` and `name`, to help identify them in the HTML. * Whether they were blocked from using the bfcache. * Reasons why they were blocked from using the bfcache. - + This allows developers to take action to make those pages bfcache-compatible, thereby improving site performance. ## Examples @@ -129,7 +129,7 @@ For example: When a page has cross-origin frames embedded, we limit the amount of information shared about them to avoid leaking cross-origin information. We only include information that the outer page already knows, and whether the cross-origin subtree blocked bfcache or not. We don't include any blocking reasons or information about lower levels of the subtree (even if some sub-levels are same-origin). -For example: +For example: ```js { @@ -174,10 +174,10 @@ As we said earlier, there are many different reasons why blocking could occur. W There are a few major categories of reason that are worth calling out: -* `Circumstantial`: This refers to blocking reasons not directly related to the developer's page code. For example a related component crashed, something went wrong with the loading process, the page is in a temporary state that can't be cached, bfcache disabled due to insufficient memory, or a service worker did something to the page that disqualifies it from being cached. +* `Circumstantial`: This refers to blocking reasons not directly related to the developer's page code. For example a related component crashed, something went wrong with the loading process, the page is in a temporary state that can't be cached, bfcache disabled due to insufficient memory, or a service worker did something to the page that disqualifies it from being cached. * `Extensions`: There are a few different reason messages related to extensions. Generally we combine quite a few different reasons into the "Extensions" reason. We are intentionally vague about extension-related blocking reasons because we don't want to give away too much information about what extensions the user have installed, which ones are active on the page, what they are doing, etc. -* `PageSupportNeeded`: The developer's code is using a web platform feature that is otherwise not bfcache blocking, but it is currently in a state that is bfcache blocking. For example, the page currently has a [BroadcastChannel](https://developer.mozilla.org/docs/Web/API/BroadcastChannel) with registered listeners, or an open [IndexedDB](https://developer.mozilla.org/docs/Web/API/IndexedDB_API) connection. Or the page has registered an [`unload` handler](https://developer.mozilla.org/docs/Web/API/Window/unload_event), which currently [prevents the bfcache being used in some browsers](https://web.dev/bfcache/#never-use-the-unload-event). -* `SupportPending`: The developer's code is using a web platform feature that disqualifies the page from the bfcache, for example the [Web Serial API](https://developer.mozilla.org/docs/Web/API/Web_Serial_API), [Web Authentication API](https://developer.mozilla.org/docs/Web/API/Web_Authentication_API), [File System Access API](https://developer.mozilla.org/docs/Web/API/File_System_Access_API), or [Media Session API](https://developer.mozilla.org/docs/Web/API/Media_Session_API). Or the page is using [`Cache-Control: no-store`](https://developer.mozilla.org/docs/Web/HTTP/Headers/Cache-Control), which currently [prevents the bfcache being used in some browsers](https://web.dev/bfcache/#minimize-use-of-cache-control-no-store). This category is also used to report the presence of a tool outside the page itself that is blocking the bfcache, such as a screenreader or the Chrome password manager. +* `PageSupportNeeded`: The developer's code is using a web platform feature that is otherwise not bfcache blocking, but it is currently in a state that is bfcache blocking. For example, the page currently has a [BroadcastChannel](https://developer.mozilla.org/docs/Web/API/BroadcastChannel) with registered listeners, or an open [IndexedDB](https://developer.mozilla.org/docs/Web/API/IndexedDB_API) connection. Or the page has registered an [`unload` handler](https://developer.mozilla.org/docs/Web/API/Window/unload_event), which currently [prevents the bfcache being used in some browsers](https://web.dev/articles/bfcache#never_use_the_unload_event). +* `SupportPending`: The developer's code is using a web platform feature that disqualifies the page from the bfcache, for example the [Web Serial API](https://developer.mozilla.org/docs/Web/API/Web_Serial_API), [Web Authentication API](https://developer.mozilla.org/docs/Web/API/Web_Authentication_API), [File System Access API](https://developer.mozilla.org/docs/Web/API/File_System_Access_API), or [Media Session API](https://developer.mozilla.org/docs/Web/API/Media_Session_API). Or the page is using [`Cache-Control: no-store`](https://developer.mozilla.org/docs/Web/HTTP/Headers/Cache-Control), which currently [prevents the bfcache being used in some browsers](https://web.dev/articles/bfcache#minimize_use_of_cache_control_no_store). This category is also used to report the presence of a tool outside the page itself that is blocking the bfcache, such as a screenreader or the Chrome password manager. ## Feedback @@ -208,7 +208,7 @@ let us know where and how you are using it. ## Helpful links {: #helpful } -- [Back/forward cache](https://web.dev/bfcache/) +- [Back/forward cache](https://web.dev/articles/bfcache) - [Public explainer][explainer] - [Chromium tracking bug][cr-bug] - [Origin trial for Back/forward cache NotRestoredReason API][ot] diff --git a/site/en/docs/web-platform/navigation-api/index.md b/site/en/docs/web-platform/navigation-api/index.md index a22be3931..05ac825a4 100644 --- a/site/en/docs/web-platform/navigation-api/index.md +++ b/site/en/docs/web-platform/navigation-api/index.md @@ -169,7 +169,7 @@ function shouldNotIntercept(navigationEvent) { When your code calls `intercept({ handler })` from within its `"navigate"` listener, it informs the browser that it's now preparing the page for the new, updated state, and that the navigation may take some time. The browser begins by capturing the scroll position for the current state, so it can be optionally restored later, then it calls your `handler` callback. -If your `handler` returns a promise (which happens automatically with [async functions](https://web.dev/async-functions/)), that promise tells the browser how long the navigation takes, and whether it's successful. +If your `handler` returns a promise (which happens automatically with [async functions](https://web.dev/articles/async-functions)), that promise tells the browser how long the navigation takes, and whether it's successful. ```js navigation.addEventListener('navigate', navigateEvent => { diff --git a/site/en/docs/web-platform/origin-trials/index.md b/site/en/docs/web-platform/origin-trials/index.md index f6f4a3322..57497e92b 100644 --- a/site/en/docs/web-platform/origin-trials/index.md +++ b/site/en/docs/web-platform/origin-trials/index.md @@ -16,13 +16,13 @@ tags: - origin-trials --- -{% YouTube - id='v_gI8wcsPUA' +{% YouTube + id='v_gI8wcsPUA' %} Origin trials give you access to a new or experimental feature, to build functionality your users can try out for a limited time before the feature -is made available to everyone. +is made available to everyone. When Chrome offers an origin trial for a feature, you can register for the trial to enable the feature for all users on your [origin](https://web.dev/same-site-same-origin/#origin), @@ -56,12 +56,12 @@ Find out more: [What are third-party origin trials?](/docs/web-platform/third-pa ## Deprecation trials -Not all origin trials are for testing new APIs. Some trials enable a deprecated feature to be -temporarily re-enabled. These are known as **deprecation trials**, and in some contexts have been +Not all origin trials are for testing new APIs. Some trials enable a deprecated feature to be +temporarily re-enabled. These are known as **deprecation trials**, and in some contexts have been referred to as "reverse" origin trials. -For example, [from Chrome 85](https://web.dev/appcache-removal/#origin-trial) AppCache is no longer -available in Chrome by default. Sites needing extra time to migrate off AppCache could register for +For example, [from Chrome 85](https://web.dev/articles/appcache-removal#origin_trial) AppCache is no longer +available in Chrome by default. Sites needing extra time to migrate off AppCache could register for the [deprecation trial to continue using AppCache](/origintrials/#/view_trial/1776670052997660673) until Chrome 93. @@ -86,9 +86,9 @@ the [deprecation trial to continue using AppCache](/origintrials/#/view_trial/17 {: #multiple} -You can register for the same origin trial multiple times, for different origins, and include -multiple tokens in the same page. This can be useful if you need to provide tokens -that are valid for resources served from different origins, such as code included on multiple +You can register for the same origin trial multiple times, for different origins, and include +multiple tokens in the same page. This can be useful if you need to provide tokens +that are valid for resources served from different origins, such as code included on multiple sites that you own. The origin trials framework looks for the first valid token and then ignores all other tokens. You diff --git a/site/en/docs/web-platform/storage-foundation/index.md b/site/en/docs/web-platform/storage-foundation/index.md index db0431d30..f84cd7334 100644 --- a/site/en/docs/web-platform/storage-foundation/index.md +++ b/site/en/docs/web-platform/storage-foundation/index.md @@ -15,7 +15,7 @@ description: | considering our options, we have decided to continue working on the features proposed by this API in the context of the origin private file system of the File System Access API instead. For more information on present use, read -[Accessing files optimized for performance from the origin private file system](https://web.dev/file-system-access/#accessing-files-optimized-for-performance-from-the-origin-private-file-system). +[Accessing files optimized for performance from the origin private file system](https://web.dev/articles/file-system-access#accessing_files_optimized_for_performance_from_the_origin_private_file_system). {% endAside %} The web platform increasingly offers developers the tools they need to build fined-tuned diff --git a/site/en/docs/web-platform/view-transitions/index.md b/site/en/docs/web-platform/view-transitions/index.md index 526bfde5c..cc33839cf 100644 --- a/site/en/docs/web-platform/view-transitions/index.md +++ b/site/en/docs/web-platform/view-transitions/index.md @@ -621,7 +621,7 @@ You may also want to change which elements you assign a `view-transition-name` d ### Reacting to the 'reduced motion' preference -Users can indicate they prefer reduced motion via their operating system, and that preference is [exposed via CSS](https://web.dev/prefers-reduced-motion/). +Users can indicate they prefer reduced motion via their operating system, and that preference is [exposed via CSS](https://web.dev/articles/prefers-reduced-motion). You could chose to prevent any transitions for these users: diff --git a/site/en/docs/web-platform/web-bundles/index.md b/site/en/docs/web-platform/web-bundles/index.md index 8c5c86a6b..926d8c7b4 100644 --- a/site/en/docs/web-platform/web-bundles/index.md +++ b/site/en/docs/web-platform/web-bundles/index.md @@ -190,7 +190,7 @@ You could also try out other sample web bundles: - [web.dev.wbn](https://storage.googleapis.com/web-dev-assets/web-bundles/web.dev.wbn) is a snapshot of the entire web.dev site, as of 2019 October 15. - [proxx.wbn](https://storage.googleapis.com/web-dev-assets/web-bundles/proxx.wbn): - [PROXX](https://web.dev/proxx-announce/) is a Minesweeper clone that works offline. + [PROXX](https://web.dev/articles/proxx-announce) is a Minesweeper clone that works offline. - [squoosh.wbn](https://storage.googleapis.com/web-dev-assets/web-bundles/squoosh.wbn): [Squoosh](https://squoosh.app) is a convenient and fast image optimization tool that lets you do side-by-side comparisons of various image compression formats, with support for diff --git a/site/en/docs/workbox/different-architectures/index.md b/site/en/docs/workbox/different-architectures/index.md index af06a6990..2247d8bfc 100644 --- a/site/en/docs/workbox/different-architectures/index.md +++ b/site/en/docs/workbox/different-architectures/index.md @@ -9,7 +9,7 @@ description: > When it comes to building for the web, there are a couple of architectural styles to be aware of. -For example, a "traditional" website—also referred to as a _Multi-page Application_ (MPA)—is a collection of pages that users navigate through via traditional [navigation requests](https://web.dev/handling-navigation-requests/). Static sites are a good example of this architectural style, even CMS-powered websites such as blog and marketing websites are examples of the style as well. +For example, a "traditional" website—also referred to as a _Multi-page Application_ (MPA)—is a collection of pages that users navigate through via traditional [navigation requests](https://web.dev/articles/handling-navigation-requests). Static sites are a good example of this architectural style, even CMS-powered websites such as blog and marketing websites are examples of the style as well. Then there's the "modern" _Single Page Application_ (SPA) style, where the only navigation request is the very first one. SPA architectures tend to serve minimal markup on the initial navigation request, which is populated by data provided by server-side APIs. This data is then presented in client-rendered markup provided by a client-side router for every subsequent navigation. diff --git a/site/en/docs/workbox/faster-multipage-applications-with-streams/index.md b/site/en/docs/workbox/faster-multipage-applications-with-streams/index.md index ef4888450..d07196c04 100644 --- a/site/en/docs/workbox/faster-multipage-applications-with-streams/index.md +++ b/site/en/docs/workbox/faster-multipage-applications-with-streams/index.md @@ -373,9 +373,9 @@ Browsers excel when it comes to dealing with responses to navigation requests, e This works to our advantage when we use a streaming service worker pattern. Whenever you respond to a request from the service worker cache from the get-go, the start of the response arrives almost instantaneously. When you stitch together precached header and footer markup with a response from the network, you get some notable performance advantages: -- [Time to First Byte (TTFB)](https://web.dev/ttfb/) will often be greatly reduced, as the first byte of the response to a navigation request is instant. -- [First Contentful Paint (FCP)](https://web.dev/fcp/) will be _very_ fast, as the precached header markup will contain a reference to a cached style sheet, meaning that the page will paint very, very quickly. -- In some cases, [Largest Contentful Paint (LCP)](https://web.dev/lcp/) can be faster as well, particularly if the largest onscreen element is provided by the precached header partial. Even so, just serving _something_ out of the service worker cache as soon as possible in tandem with smaller markup payloads may result in a better LCP. +- [Time to First Byte (TTFB)](https://web.dev/articles/ttfb) will often be greatly reduced, as the first byte of the response to a navigation request is instant. +- [First Contentful Paint (FCP)](https://web.dev/articles/fcp) will be _very_ fast, as the precached header markup will contain a reference to a cached style sheet, meaning that the page will paint very, very quickly. +- In some cases, [Largest Contentful Paint (LCP)](https://web.dev/articles/lcp) can be faster as well, particularly if the largest onscreen element is provided by the precached header partial. Even so, just serving _something_ out of the service worker cache as soon as possible in tandem with smaller markup payloads may result in a better LCP. Streaming multipage architectures can be a bit tricky to set up and iterate on, but the complexity involved is often no more onerous than SPAs in theory. The main benefit is that you're not replacing the browser's default navigation scheme—you're _enhancing_ it. diff --git a/site/en/docs/workbox/forcing-a-network-timeout/index.md b/site/en/docs/workbox/forcing-a-network-timeout/index.md index dc8095f20..a9a26d1d7 100644 --- a/site/en/docs/workbox/forcing-a-network-timeout/index.md +++ b/site/en/docs/workbox/forcing-a-network-timeout/index.md @@ -6,7 +6,7 @@ description: > Learn how to force a network timeout in the presence of a slow network connection, and how to get the timing right. --- -There are times when you have a network connection, but that connection is either too slow, or your connection [is lying to you that you're online](https://web.dev/performance-poor-connectivity/#lie-fi). In such situations where a service worker is in the mix, a network-first caching strategy may take too long to get a response from the network, or the request will hang—and loading spinners will spin endlessly—until you get an error page. +There are times when you have a network connection, but that connection is either too slow, or your connection [is lying to you that you're online](https://web.dev/articles/performance-poor-connectivity#lie_fi). In such situations where a service worker is in the mix, a network-first caching strategy may take too long to get a response from the network, or the request will hang—and loading spinners will spin endlessly—until you get an error page. Whatever the situation is, there are instances in which falling back to the last cached response for an asset or page after a certain period of time would be preferable—yet another problem that Workbox can help with. @@ -77,4 +77,4 @@ When forcing a timeout for requests—particularly navigation requests&mdash The right answer is "it depends". If you're running a site such as a blog and don't update content too often, the right answer is probably to err on the side of not waiting _too_ much, as whatever is in the cache is probably "fresh" enough. However, for more interactive websites and web apps, it may be best to wait a bit longer and avoid serving stale data from the service worker cache too eagerly. -If you're recording metrics [in the field](https://web.dev/how-to-measure-speed/#lab-data-vs-field-data), look at the **75th percentile** of [Time to First Byte (TTFB)](https://web.dev/ttfb/) and [First Contentful Paint (FCP)](https://web.dev/fcp/) scores to get a sense of where longer wait times for navigation requests might be among your user base. That may give you insight as to where to draw the line. +If you're recording metrics [in the field](https://web.dev/articles/how-to-measure-speed#lab_data_vs_field_data), look at the **75th percentile** of [Time to First Byte (TTFB)](https://web.dev/articles/ttfb) and [First Contentful Paint (FCP)](https://web.dev/articles/fcp) scores to get a sense of where longer wait times for navigation requests might be among your user base. That may give you insight as to where to draw the line. diff --git a/site/en/docs/workbox/framework-integrations/index.md b/site/en/docs/workbox/framework-integrations/index.md index afdd7808c..f0c05b882 100644 --- a/site/en/docs/workbox/framework-integrations/index.md +++ b/site/en/docs/workbox/framework-integrations/index.md @@ -10,7 +10,7 @@ Frameworks make web development more enjoyable through an improved developer exp ## React/React-compatible -- [create-react-app](https://web.dev/precache-with-workbox-react/) +- [create-react-app](https://web.dev/articles/precache-with-workbox-react) - [gatsby-plugin-offline](https://www.gatsbyjs.com/plugins/gatsby-plugin-offline/) - [preact-cli](https://preactjs.com/cli/service-worker/) - [next/pwa](https://github.com/shadowwalker/next-pwa) diff --git a/site/en/docs/workbox/modules/workbox-navigation-preload/index.md b/site/en/docs/workbox/modules/workbox-navigation-preload/index.md index eccdeef05..4444e365d 100644 --- a/site/en/docs/workbox/modules/workbox-navigation-preload/index.md +++ b/site/en/docs/workbox/modules/workbox-navigation-preload/index.md @@ -7,7 +7,7 @@ description: > Enable navigation preload, to get a network response for navigation requests faster. --- -"[Speed up Service Worker with Navigation Preloads](https://web.dev/navigation-preload/)" does a +"[Speed up Service Worker with Navigation Preloads](https://web.dev/articles/navigation-preload)" does a great job of explaining what navigation preload is, and the benefits it offers to web apps whose service worker does not explicitly handle [navigation requests](/docs/workbox/caching-strategies-overview/). diff --git a/site/en/docs/workbox/modules/workbox-recipes/index.md b/site/en/docs/workbox/modules/workbox-recipes/index.md index 0c9d635fc..e9f72d1f0 100644 --- a/site/en/docs/workbox/modules/workbox-recipes/index.md +++ b/site/en/docs/workbox/modules/workbox-recipes/index.md @@ -126,7 +126,7 @@ self.addEventListener('install', event => { ### Page cache -The page cache recipe allows your service worker to respond to a request for an HTML page (through URL navigation) with a [network first](/docs/workbox/modules/workbox-strategies/#network-first-network-falling-back-to-cache) caching strategy, optimized to, ideally, allow for the cache fallback to arrive quick enough for for a [largest contentful paint](https://web.dev/vitals/) score of less than 4.0 seconds. +The page cache recipe allows your service worker to respond to a request for an HTML page (through URL navigation) with a [network first](/docs/workbox/modules/workbox-strategies/#network-first-network-falling-back-to-cache) caching strategy, optimized to, ideally, allow for the cache fallback to arrive quick enough for for a [largest contentful paint](https://web.dev/articles/vitals) score of less than 4.0 seconds. This recipe, by default, assumes the network timeout should be 3 seconds and supports [cache warming](#warm-strategy-cache) through the `warmCache` option. See the [page cache options](/docs/workbox/reference/workbox-recipes/#method-pageCache) for a list of all configuration options. diff --git a/site/en/docs/workbox/modules/workbox-routing/index.md b/site/en/docs/workbox/modules/workbox-routing/index.md index c991e1051..4b75c3353 100644 --- a/site/en/docs/workbox/modules/workbox-routing/index.md +++ b/site/en/docs/workbox/modules/workbox-routing/index.md @@ -82,7 +82,7 @@ const handlerCb = async ({url, request, event, params}) => { Your handler must return a promise that resolves to a `Response`. In this example, we're using -[`async` and `await`](https://web.dev/javascript-async-functions/). +[`async` and `await`](https://web.dev/articles/javascript-async-functions). Under the hood, the return `Response` value will be wrapped in a promise. You can register these callbacks like so: diff --git a/site/en/docs/workbox/modules/workbox-strategies/index.md b/site/en/docs/workbox/modules/workbox-strategies/index.md index d3d0f42e7..cf3df90a3 100644 --- a/site/en/docs/workbox/modules/workbox-strategies/index.md +++ b/site/en/docs/workbox/modules/workbox-strategies/index.md @@ -15,7 +15,7 @@ generates a response after receiving a fetch event. apply them in your service worker. We won't go into much detail outside of the strategies supported by Workbox, -but you can [learn more in the Offline Cookbook](https://web.dev/offline-cookbook/). +but you can [learn more in the Offline Cookbook](https://web.dev/articles/offline-cookbook). ## Using Strategies @@ -31,7 +31,7 @@ the caching strategies directly without `workbox-routing`. {% Img src="image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/CjsxJKEDAzC6l9qezYaO.png", alt="Stale While Revalidate Diagram", width="800", height="388" %} -The [stale-while-revalidate](https://web.dev/offline-cookbook/#stale-while-revalidate) +The [stale-while-revalidate](https://web.dev/articles/offline-cookbook#stale_while_revalidate) pattern allows you to respond to the request as quickly as possible with a cached response if available, falling back to the network request if it's not cached. The network request is then used to update the cache. As opposed to @@ -58,7 +58,7 @@ registerRoute( Offline web apps will rely heavily on the cache, but for assets that are non-critical and can be gradually cached, a -[cache first](https://web.dev/offline-cookbook/#cache-falling-back-to-network) +[cache first](https://web.dev/articles/offline-cookbook#cache_falling_back_to_network) is the best option. If there is a Response in the cache, the Request will be fulfilled using the @@ -78,7 +78,7 @@ registerRoute(({request}) => request.destination === 'style', new CacheFirst()); {% Img src="image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/jP2SpragluJprmpiiZYt.png", alt="Network First Diagram", width="800", height="388" %} For requests that are updating frequently, the -[network first](https://web.dev/offline-cookbook/#network-falling-back-to-cache) +[network first](https://web.dev/articles/offline-cookbook#network_falling_back_to_cache) strategy is the ideal solution. By default, it will try to fetch the latest response from the network. If the request is successful, it'll put the response in the cache. If the network fails to return a response, the cached response @@ -99,7 +99,7 @@ registerRoute( {% Img src="image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/lSmhYmQTXgGJKU773wAR.png", alt="Network Only Diagram", width="800", height="272" %} If you require specific requests to be fulfilled from the network, the -[network only](https://web.dev/offline-cookbook/#network-only) +[network only](https://web.dev/articles/offline-cookbook#network_only) is the strategy to use. ```js @@ -113,7 +113,7 @@ registerRoute(({url}) => url.pathname.startsWith('/admin/'), new NetworkOnly()); {% Img src="image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/wQ6arISYebhPxC1qJ7Fp.png", alt="Cache Only Diagram", width="800", height="272" %} -The [cache only](https://web.dev/offline-cookbook/#cache-only) +The [cache only](https://web.dev/articles/offline-cookbook#cache_only) strategy ensures that responses are obtained from a cache. This is less common in workbox, but can be useful if you have your own precaching step. diff --git a/site/en/docs/workbox/modules/workbox-window/index.md b/site/en/docs/workbox/modules/workbox-window/index.md index ddb1364c3..d8885c845 100644 --- a/site/en/docs/workbox/modules/workbox-window/index.md +++ b/site/en/docs/workbox/modules/workbox-window/index.md @@ -269,7 +269,7 @@ you'll need to call its `addCacheListener()` method manually. ## Important service worker lifecycle moments The [service worker -lifecycle](https://web.dev/service-worker-lifecycle/) +lifecycle](https://web.dev/articles/service-worker-lifecycle) is complex and can be a challenge to fully understand. Part of the reason it's so complex is it must handle all the edge cases for all possible usages of service worker (e.g. registering more than one service worker, registering @@ -280,7 +280,7 @@ But most developers implementing service worker should not need to worry about all these edge cases because their usage is quite simple. Most developer register just one service worker per page load, and they [don't change the name of the service -worker](https://web.dev/service-worker-lifecycle/#avoid-url-change) +worker](https://web.dev/articles/service-worker-lifecycle#avoid_url_change) file they deploy to their server. The `Workbox` class embraces this simpler view for the service worker lifecycle @@ -530,7 +530,7 @@ help with debugging why things aren't as you'd expect. In addition, a common mistake developers make when first using service worker is to register a service worker in the -[wrong scope](https://web.dev/learn/pwa/service-workers/#registering-a-service-worker). +[wrong scope](https://web.dev/learn/pwa/service-workers#registering_a_service_worker). To help prevent this from happening, the `Workbox` class will warn you if the page registering the service worker is not in that service worker's scope. It'll @@ -656,7 +656,7 @@ For example, in the code above, if the service worker version returned by that until an update is found (which should happen when you call `register()`). At that point you can either notify the user or an update, or you can manually [skip the waiting -phase](https://web.dev/service-worker-lifecycle/#skip-the-waiting-phase) +phase](https://web.dev/articles/service-worker-lifecycle#skip_the_waiting_phase) to activate the new service worker right away. #### Cache first @@ -668,7 +668,7 @@ to use `messageSW()` right away. However, if an updated version of your service worker is found and activates when your page calls `register()` (i.e. you intentionally [skip the waiting -phase](https://web.dev/service-worker-lifecycle/#skip-the-waiting-phase)), +phase](https://web.dev/articles/service-worker-lifecycle#skip_the_waiting_phase)), it may no longer be safe to send messages to it. One strategy for managing this possibility is to use a versioning scheme that @@ -681,7 +681,7 @@ version of the page, and suggest they reload to get the update. A common use convention for window to service worker messaging is send a `{type: 'SKIP_WAITING'}` message to instruct a service worker that's installed to -[skip the waiting phase](https://web.dev/service-worker-lifecycle/#skip-the-waiting-phase) +[skip the waiting phase](https://web.dev/articles/service-worker-lifecycle#skip_the_waiting_phase) and activate. Starting with Workbox v6, the `messageSkipWaiting()` method can be used to send a diff --git a/site/en/docs/workbox/navigation-preload/index.md b/site/en/docs/workbox/navigation-preload/index.md index 01b40d77a..3449a8d8f 100644 --- a/site/en/docs/workbox/navigation-preload/index.md +++ b/site/en/docs/workbox/navigation-preload/index.md @@ -28,7 +28,7 @@ The best time to use navigation preload is when a website can't precache HTML. T ## Using navigation preload in Workbox -Using navigation preload directly in a service worker not powered by Workbox is tricky. First, [it's not supported in all browsers](https://caniuse.com/mdn-api_navigationpreloadmanager). Secondly, it can be difficult to get right. You can learn how to use it directly in [this great explainer by Jake Archibald](https://web.dev/navigation-preload/). +Using navigation preload directly in a service worker not powered by Workbox is tricky. First, [it's not supported in all browsers](https://caniuse.com/mdn-api_navigationpreloadmanager). Secondly, it can be difficult to get right. You can learn how to use it directly in [this great explainer by Jake Archibald](https://web.dev/articles/navigation-preload). Workbox simplifies using navigation preload, because the `workbox-navigation-preload` module's [`enable` method](/docs/workbox/reference/workbox-navigation-preload/#method-enable) does the necessary feature support checks, as well as creating the `activate` event listener to enable it for you. @@ -93,7 +93,7 @@ In cases like these, it pays to know that preload requests are sent with a `Serv Service-Worker-Navigation-Preload: true ``` -Then, in your application backend of choice, you can check for this header and modify the response to suit your needs. If the header's default value is problematic for any reason, [you can change it in the window context](https://web.dev/navigation-preload/#changing-the-header). Just know that any work you do on the server to read this header is up to you, and outside the scope of Workbox. +Then, in your application backend of choice, you can check for this header and modify the response to suit your needs. If the header's default value is problematic for any reason, [you can change it in the window context](https://web.dev/articles/navigation-preload#changing_the_header). Just know that any work you do on the server to read this header is up to you, and outside the scope of Workbox. ## Conclusion diff --git a/site/en/docs/workbox/remove-buggy-service-workers/index.md b/site/en/docs/workbox/remove-buggy-service-workers/index.md index c9f88f296..e877b4098 100644 --- a/site/en/docs/workbox/remove-buggy-service-workers/index.md +++ b/site/en/docs/workbox/remove-buggy-service-workers/index.md @@ -82,7 +82,7 @@ but additional measures can be taken if necessary. Sometimes a previously installed service worker's URL is unknown. This might be because it is versioned (for example contains a hash in its file name). In this case it can be a challenge to deploy a no-op service worker that matches the URL of each old service worker that might be registered. -[This goes against best practices](https://web.dev/service-worker-lifecycle/#avoid-url-change), +[This goes against best practices](https://web.dev/articles/service-worker-lifecycle#avoid_url_change), as developers likely won't remember every hash for every service worker version that was deployed. Fortunately, a helpful HTTP request header is sent with a request for a service worker script: diff --git a/site/en/docs/workbox/service-worker-deployment/index.md b/site/en/docs/workbox/service-worker-deployment/index.md index 37de65372..b250195c3 100644 --- a/site/en/docs/workbox/service-worker-deployment/index.md +++ b/site/en/docs/workbox/service-worker-deployment/index.md @@ -45,7 +45,7 @@ This means HTML parsers may discover service worker registration code before the This is a problem. A service worker should ideally be performance-neutral in the worst of cases, not make performance worse. Do users a favor and -[register a service worker when the page's `load` event fires](https://web.dev/service-workers-registration/). +[register a service worker when the page's `load` event fires](https://web.dev/articles/service-workers-registration). This reduces the chance that precaching will interfere with loading a page's critical assets, which in turn means the page can get interactive faster without having to contend with network requests for assets that may not be needed until later anyway. @@ -68,12 +68,12 @@ This extra overhead before a request can be handled is small compared to the ben When using strategies that can't serve from the cache, and has to go to the network—in particular when handling -[navigation requests](https://web.dev/handling-navigation-requests/)—[bootup time always adds some delay](https://web.dev/navigation-preload/#the-problem). +[navigation requests](https://web.dev/articles/handling-navigation-requests)—[bootup time always adds some delay](https://web.dev/articles/navigation-preload#the_problem). Depending on device capabilities and/or CPU pressure, a navigation request can experience a noticeable delay due to slow service worker boot-ups. Deploying a service worker without awareness of this delay means that users could experience an unintentional performance hit. -This problem has been solved with [Navigation Preload](https://web.dev/navigation-preload/#the-solution), +This problem has been solved with [Navigation Preload](https://web.dev/articles/navigation-preload#the_solution), but [it isn't supported in all browsers yet](https://caniuse.com/mdn-api_navigationpreloadmanager_enable). However, it's use is worth considering, and it's covered [later in this documentation](/docs/workbox/navigation-preload). diff --git a/site/en/docs/workbox/service-worker-lifecycle/index.md b/site/en/docs/workbox/service-worker-lifecycle/index.md index 97fdf9812..8e51ab362 100644 --- a/site/en/docs/workbox/service-worker-lifecycle/index.md +++ b/site/en/docs/workbox/service-worker-lifecycle/index.md @@ -197,7 +197,7 @@ Browsers will check for updates to a service worker when: - The user navigates to a page within the service worker's scope. - [`navigator.serviceWorker.register()`](https://developer.mozilla.org/docs/Web/API/ServiceWorkerContainer/register) -is called with a URL different from the currently installed service worker—[but don't change a service worker's URL](https://web.dev/service-worker-lifecycle/#avoid-url-change)! +is called with a URL different from the currently installed service worker—[but don't change a service worker's URL](https://web.dev/articles/service-worker-lifecycle#avoid_url_change)! - [`navigator.serviceWorker.register()`](https://developer.mozilla.org/docs/Web/API/ServiceWorkerContainer/register) is called with the same URL as the installed service worker, but with a different scope. @@ -233,7 +233,7 @@ The browser automatically performs update checks when there's a navigation to a Concerning updates, registration logic generally shouldn't change. Yet, one exception might be if sessions on a website are long-lived. This can happen in single page applications where -[navigation requests](https://web.dev/handling-navigation-requests/) are rare, +[navigation requests](https://web.dev/articles/handling-navigation-requests) are rare, since the application typically encounters one navigation request at the start of the application's lifecycle. In such situations, a manual update can be triggered on the main thread: @@ -348,6 +348,6 @@ With that understanding, service worker behaviors should seem more logical than For those interested in a deeper dive into this subject, it's worth checking out -[this article by Jake Archibald](https://web.dev/service-worker-lifecycle/). +[this article by Jake Archibald](https://web.dev/articles/service-worker-lifecycle). There's tons of nuance in how the whole dance around the service lifecycle goes, but it _is_ knowable, and that knowledge will go far when using Workbox. diff --git a/site/en/docs/workbox/the-ways-of-workbox/index.md b/site/en/docs/workbox/the-ways-of-workbox/index.md index a33956a9c..8c2464864 100644 --- a/site/en/docs/workbox/the-ways-of-workbox/index.md +++ b/site/en/docs/workbox/the-ways-of-workbox/index.md @@ -25,7 +25,7 @@ You should use `generateSW` if: On the other hand, you should _not_ use `generateSW` if: -- You want to use other service worker features (such as [Web Push](https://web.dev/push-notifications-overview/)). +- You want to use other service worker features (such as [Web Push](https://web.dev/articles/push-notifications-overview)). - You need additional flexibility to import additional scripts or use specific Workbox modules to fine-tune your service worker to your application's needs. ### When to use `injectManifest` @@ -121,7 +121,7 @@ The options you pass to either `GenerateSW` or `InjectManifest` aren't the same ## Using a framework -Everything covered up this point focuses on using Workbox regardless of one's framework preferences. However, it's possible to use Workbox within a specific framework if it makes development easier. For example, [`create-react-app` ships with Workbox by default](https://web.dev/precache-with-workbox-react/). Different framework integrations with Workbox [are covered later in a later article](/docs/workbox/framework-integrations/). +Everything covered up this point focuses on using Workbox regardless of one's framework preferences. However, it's possible to use Workbox within a specific framework if it makes development easier. For example, [`create-react-app` ships with Workbox by default](https://web.dev/articles/precache-with-workbox-react). Different framework integrations with Workbox [are covered later in a later article](/docs/workbox/framework-integrations/). It's worth noting that these framework-specific integrations of Workbox may restrict your ability to configure Workbox in the way you want. In cases like these, you can always fall back to the methods discussed in this article. diff --git a/site/en/docs/workbox/understanding-storage-quota/index.md b/site/en/docs/workbox/understanding-storage-quota/index.md index 7f5304994..d91115d49 100644 --- a/site/en/docs/workbox/understanding-storage-quota/index.md +++ b/site/en/docs/workbox/understanding-storage-quota/index.md @@ -62,7 +62,7 @@ This option currently defaults to `false`. Runtime caches should, in general, be ## How much data are you allowed to store? -Each browser has [its own upper limits on storage](https://web.dev/storage-for-the-web/#how-much), so there's no single answer. Additionally, some browsers have a dynamic limit which varies based on the amount of storage that's free on a given device, so the effective upper limit might change without notice. +Each browser has [its own upper limits on storage](https://web.dev/articles/storage-for-the-web#how_much), so there's no single answer. Additionally, some browsers have a dynamic limit which varies based on the amount of storage that's free on a given device, so the effective upper limit might change without notice. Some browsers expose an interface for querying the approximate amount of storage that your origin is using, along with the upper limit, via [`navigator.storage.estimate()`](https://developer.mozilla.org/docs/Web/API/StorageManager/estimate). The "[Estimating Available Storage Space](/blog/estimating-available-storage-space/)" article has more information on how you can use that in your own web apps. diff --git a/site/en/docs/workbox/using-workbox-window/index.md b/site/en/docs/workbox/using-workbox-window/index.md index bf8eb2a47..0808031ed 100644 --- a/site/en/docs/workbox/using-workbox-window/index.md +++ b/site/en/docs/workbox/using-workbox-window/index.md @@ -3,7 +3,7 @@ layout: "layouts/doc-post.njk" title: Using workbox-window date: 2021-12-07 description: > - Sometimes users go offline. Learn how to adapt, and help them resume requests when they eventually go back online. + Sometimes users go offline. Learn how to adapt, and help them resume requests when they eventually go back online. --- One Workbox module that hasn't gotten much coverage yet in this documentation is [`workbox-window`](/docs/workbox/reference/workbox-window/), which is a set of modules intended to run in the [`window`](https://developer.mozilla.org/docs/Web/API/Window). The goals of this module are: @@ -41,10 +41,10 @@ if ('serviceWorker' in navigator) { wb.register(); } -</script> +</script> ``` -Though `workbox-window` is quite small, you _could_ split it from your website's core application logic using [dynamic `import`](https://web.dev/reduce-javascript-payloads-with-code-splitting/), which can reduce the size of your page's main bundle: +Though `workbox-window` is quite small, you _could_ split it from your website's core application logic using [dynamic `import`](https://web.dev/articles/reduce-javascript-payloads-with-code-splitting), which can reduce the size of your page's main bundle: ```html <script type="module"> @@ -54,7 +54,7 @@ if ('serviceWorker' in navigator) { const wb = new Workbox('/sw.js'); wb.register(); } -</script> +</script> ``` ### Using the CDN diff --git a/site/en/docs/workbox/using-workbox-without-precaching/index.md b/site/en/docs/workbox/using-workbox-without-precaching/index.md index 823843060..2bdfb7882 100644 --- a/site/en/docs/workbox/using-workbox-without-precaching/index.md +++ b/site/en/docs/workbox/using-workbox-without-precaching/index.md @@ -8,7 +8,7 @@ description: > So far, this documentation has been big on precaching, often touching on the `generateSW` and `injectManifest` build tools. While there are plenty of good reasons to include precaching logic in your service worker, you don't have to use precaching to use Workbox. -Perhaps your project only needs runtime caching, or maybe you want a cleaner way to integrate service worker APIs, such as [web push](https://web.dev/notifications/). These are cases when you won't want to use Workbox's build tools, and that's what is covered in this article. +Perhaps your project only needs runtime caching, or maybe you want a cleaner way to integrate service worker APIs, such as [web push](https://web.dev/articles/notifications). These are cases when you won't want to use Workbox's build tools, and that's what is covered in this article. ## When using a bundler diff --git a/site/es/articles/browser-fs-access/index.md b/site/es/articles/browser-fs-access/index.md index 0752b00f9..6c76f7a24 100644 --- a/site/es/articles/browser-fs-access/index.md +++ b/site/es/articles/browser-fs-access/index.md @@ -66,7 +66,7 @@ Una desventaja masiva del enfoque de *descarga* es que no hay forma de hacer que La API de File System Access hace que ambas operaciones, abrir y guardar, sean mucho más simples. También permite un *verdadero guardado*, es decir, no solo puedes elegir dónde guardar un archivo, sino también sobrescribir un archivo existente. -{% Aside %} Para obtener una introducción más detallada a la API de File System Access, consulta el artículo [La API de File System Access: simplificación del acceso a archivos locales](https://web.dev/file-system-access/). {% endAside %} +{% Aside %} Para obtener una introducción más detallada a la API de File System Access, consulta el artículo [La API de File System Access: simplificación del acceso a archivos locales](https://web.dev/articles/file-system-access). {% endAside %} ### Abrir archivos @@ -168,7 +168,7 @@ Puedes ver el código anterior en acción en una [demostración](https://browser ## La biblioteca browser-fs-access en lo salvaje -En mi tiempo libre, contribuyo un poco a una [PWA instalable](https://web.dev/progressive-web-apps/#installable) llamada [Excalidraw](https://excalidraw.com/), una herramienta de pizarra que te permite dibujar diagramas fácilmente con una sensación de dibujo a mano. Es totalmente responsiva y funciona bien en una variedad de dispositivos, desde pequeños teléfonos móviles hasta computadoras con pantallas grandes. Esto significa que debes manejar archivos en todas las diversas plataformas, ya sea que admitan o no la API de File System Access. Esto la convierte en una gran candidata para la biblioteca browser-fs-access. +En mi tiempo libre, contribuyo un poco a una [PWA instalable](https://web.dev/explore/progressive-web-apps#make-it-installable) llamada [Excalidraw](https://excalidraw.com/), una herramienta de pizarra que te permite dibujar diagramas fácilmente con una sensación de dibujo a mano. Es totalmente responsiva y funciona bien en una variedad de dispositivos, desde pequeños teléfonos móviles hasta computadoras con pantallas grandes. Esto significa que debes manejar archivos en todas las diversas plataformas, ya sea que admitan o no la API de File System Access. Esto la convierte en una gran candidata para la biblioteca browser-fs-access. Puedo, por ejemplo, iniciar un dibujo en mi iPhone, guardarlo (técnicamente: descargarlo, ya que Safari no es compatible con la API de File System Access) en la carpeta Descargas de mi iPhone, abrir el archivo en mi escritorio (después de transferirlo desde mi teléfono), modificar el archivo y sobrescribirlo con mis cambios, o incluso guardarlo como un archivo nuevo. diff --git a/site/es/articles/file-handling/index.md b/site/es/articles/file-handling/index.md index f97d07e5c..2b99f0e2b 100644 --- a/site/es/articles/file-handling/index.md +++ b/site/es/articles/file-handling/index.md @@ -15,7 +15,7 @@ alt: Carpetas de muchos colores. {% Aside %} La API para administrar archivos forma parte del [proyecto funciones](/blog/fugu-status/) y actualmente está en desarrollo. Esta publicación se actualizará conforme avance la implementación. {% endAside %} -Ahora que las aplicaciones web son [capaces de leer y escribir archivos](https://web.dev/file-system-access/), el siguiente paso lógico es permitir que los desarrolladores declaren estas mismas aplicaciones web como administradores de archivos para los archivos que sus aplicaciones pueden crear y procesar. La API de administración de archivos le permite hacer exactamente esto. Después de registrar una aplicación de editor de texto como administrador de archivos y después de instalarla, puede hacer clic con el botón derecho en un archivo `.txt` en macOS y seleccionar "Obtener información" para indicar al sistema operativo que siempre debe abrir los archivos `.txt` con esta aplicación de forma predeterminada. +Ahora que las aplicaciones web son [capaces de leer y escribir archivos](https://web.dev/articles/file-system-access), el siguiente paso lógico es permitir que los desarrolladores declaren estas mismas aplicaciones web como administradores de archivos para los archivos que sus aplicaciones pueden crear y procesar. La API de administración de archivos le permite hacer exactamente esto. Después de registrar una aplicación de editor de texto como administrador de archivos y después de instalarla, puede hacer clic con el botón derecho en un archivo `.txt` en macOS y seleccionar "Obtener información" para indicar al sistema operativo que siempre debe abrir los archivos `.txt` con esta aplicación de forma predeterminada. ## Casos de uso sugeridos para la API de administración de archivos {: #use-cases } @@ -35,8 +35,8 @@ Para experimentar con la API de administración de archivos de forma local, sin La API de administración de archivos por sí misma no puede ser polivalente. Sin embargo, la capacidad de abrir archivos con una aplicación web puede conseguirse por otros dos medios: -- La [API de objetivo compartido web](https://web.dev/web-share-target/) permite a los desarrolladores especificar su aplicación como un objetivo compartido para que los archivos puedan abrirse desde la hoja compartida del sistema operativo. -- La [API de acceso al sistema de archivos](https://web.dev/file-system-access/) puede integrarse con la función de arrastrar y soltar archivos, para que los desarrolladores puedan administrar los archivos soltados en la aplicación que ya está abierta. +- La [API de objetivo compartido web](https://web.dev/articles/web-share-target) permite a los desarrolladores especificar su aplicación como un objetivo compartido para que los archivos puedan abrirse desde la hoja compartida del sistema operativo. +- La [API de acceso al sistema de archivos](https://web.dev/articles/file-system-access) puede integrarse con la función de arrastrar y soltar archivos, para que los desarrolladores puedan administrar los archivos soltados en la aplicación que ya está abierta. ### Detección de funciones @@ -52,7 +52,7 @@ if ('launchQueue' in window && 'files' in LaunchParams.prototype) { ### La parte declarativa de la API de administración de archivos -Como primer paso, las aplicaciones web necesitan describir de forma declarativa en su [manifiesto de aplicación web](https://web.dev/add-manifest/) qué tipo de archivos pueden administrar. La API de administración de archivos amplía el manifiesto de la aplicación web con una nueva propiedad llamada `"file_handlers"` que acepta una serie de, precisamente, administradores de archivos. Un administrador de archivos es un objeto con dos propiedades: +Como primer paso, las aplicaciones web necesitan describir de forma declarativa en su [manifiesto de aplicación web](https://web.dev/articles/add-manifest) qué tipo de archivos pueden administrar. La API de administración de archivos amplía el manifiesto de la aplicación web con una nueva propiedad llamada `"file_handlers"` que acepta una serie de, precisamente, administradores de archivos. Un administrador de archivos es un objeto con dos propiedades: - Una propiedad `"action"` que señala como valor una URL dentro del alcance de la aplicación. - Una propiedad `"accept"` con un objeto de tipos MIME como claves y listas de extensiones de archivos entre sus valores. @@ -109,7 +109,7 @@ El siguiente ejemplo, que muestra solo el fragmento correspondiente del manifies Esto se utiliza para una aplicación hipotética que administra archivos de valores separados por comas (`.csv`) en `/open-csv`, gráficos vectoriales escalables (`. svg`) en `/open-svg`, y un formato de archivo Grafr formado por `.grafr`, `.graf`, o `.graph` como extensión en `/open-graf`. -{% Aside %} Para que esta declaración tenga algún efecto, la aplicación debe estar instalada. Puede obtener más información en una serie de artículos de este mismo sitio sobre [cómo hacer que su aplicación se pueda instalar](https://web.dev/progressive-web-apps/#make-it-installable). {% endAside %} +{% Aside %} Para que esta declaración tenga algún efecto, la aplicación debe estar instalada. Puede obtener más información en una serie de artículos de este mismo sitio sobre [cómo hacer que su aplicación se pueda instalar](https://web.dev/explore/progressive-web-apps#make-it-installable). {% endAside %} ### La parte imperativa de la API de administración de archivos diff --git a/site/es/blog/chrome-ux-report-looker-studio-dashboard/index.md b/site/es/blog/chrome-ux-report-looker-studio-dashboard/index.md index 22dfba34d..279ac43ec 100644 --- a/site/es/blog/chrome-ux-report-looker-studio-dashboard/index.md +++ b/site/es/blog/chrome-ux-report-looker-studio-dashboard/index.md @@ -74,7 +74,7 @@ Los conjuntos de datos mensuales se publican el segundo martes de cada mes. Por ### Descripción general de Core Web Vitals -La primera página es una descripción general del rendimiento [mensual de Core Web Vitals del origen.](https://web.dev/vitals/) Estas son las métricas de UX más importantes, por lo que Google recomienda que se concentre en estas. +La primera página es una descripción general del rendimiento [mensual de Core Web Vitals del origen.](https://web.dev/articles/vitals) Estas son las métricas de UX más importantes, por lo que Google recomienda que se concentre en estas. {% Img src="image/admin/h8iCTgvmG4DS2zScvatc.png", alt="Descripción general del Panel CrUX Core Web Vitals", width="800", height="906" %} @@ -92,7 +92,7 @@ Después de la página Core Web Vitals, encontrará páginas independientes para En la parte superior de cada página se encuentra el filtro **Dispositivos**, que puede usarse para restringir los factores de forma incluidos en los datos de experiencia. Por ejemplo, puede profundizar específicamente en las experiencias telefónicas. Esta configuración persiste en todas las páginas. -Las visualizaciones principales en estas páginas son las distribuciones mensuales de experiencias categorizadas como "Buena", "Necesita mejorar" y "Deficiente". La leyenda codificada por colores debajo del gráfico indica las diversas experiencias incluidas en la categoría. Por ejemplo, en la captura de pantalla anterior, puede ver que el porcentaje de experiencias "buenas" de [Largest Contentful Paint](https://web.dev/lcp/#what-is-a-good-lcp-score) (LCP) fluctúa y empeora ligeramente en los últimos meses. +Las visualizaciones principales en estas páginas son las distribuciones mensuales de experiencias categorizadas como "Buena", "Necesita mejorar" y "Deficiente". La leyenda codificada por colores debajo del gráfico indica las diversas experiencias incluidas en la categoría. Por ejemplo, en la captura de pantalla anterior, puede ver que el porcentaje de experiencias "buenas" de [Largest Contentful Paint](https://web.dev/articles/lcp#what_is_a_good_lcp_score) (LCP) fluctúa y empeora ligeramente en los últimos meses. Los porcentajes de experiencias "buenas" y "malas" del mes más reciente se muestran encima del gráfico junto con un indicador de la diferencia porcentual con respecto al mes anterior. Para este origen, las experiencias "buenas" de LCP cayeron un 3.2% llegando a 56.04% mes a mes. @@ -120,7 +120,7 @@ De manera similar, la página de distribución de ECT muestra el desglose de 4G, {% Aside 'key-term' %} Los tipos de conexión efectivos se consideran *efectivos* porque se basan en mediciones de ancho de banda en los dispositivos de los usuarios y no implican el uso de ninguna tecnología específica. Por ejemplo, un usuario de escritorio con Wi-Fi rápido puede etiquetarse como 4G, mientras que una conexión móvil más lenta puede etiquetarse como 2G. {% endAside %} -Las distribuciones para estas dimensiones se calculan utilizando segmentos de los datos del histograma [First Contentful Paint](https://web.dev/fcp/) (FCP). +Las distribuciones para estas dimensiones se calculan utilizando segmentos de los datos del histograma [First Contentful Paint](https://web.dev/articles/fcp) (FCP). ## Preguntas frecuentes diff --git a/site/es/blog/new-in-chrome-116/index.md b/site/es/blog/new-in-chrome-116/index.md index 14b85201c..75ca839e7 100644 --- a/site/es/blog/new-in-chrome-116/index.md +++ b/site/es/blog/new-in-chrome-116/index.md @@ -69,7 +69,7 @@ Consulte [Picture in Picture para cualquier elemento](/docs/web-platform/documen ## Propiedad `notRestoredReasons`. {: #not-restored-reasons } -Los navegadores modernos proporcionan una función de optimización para la navegación del historial llamada [caché de retroceso/adelante] (https://web.dev/bfcache/) o bfcache. Permite una experiencia de carga instantánea cuando los usuarios regresan a una página que ya han visitado. +Los navegadores modernos proporcionan una función de optimización para la navegación del historial llamada [caché de retroceso/adelante] (https://web.dev/articles/bfcache) o bfcache. Permite una experiencia de carga instantánea cuando los usuarios regresan a una página que ya han visitado. Mire este video de bfcache en acción para comprender la velocidad que puede aportar a las navegaciones: @@ -141,4 +141,4 @@ Para mantenerse actualizado, [suscríbase](https://goo.gl/6FP1a5) al y recibirás una notificación por correo electrónico cada vez que lancemos un nuevo video. Yo soy Adriana Jara, y tan pronto como se lance Chrome 117, estaré aquí para -¡Contarles qué hay de nuevo en Chrome! \ No newline at end of file +¡Contarles qué hay de nuevo en Chrome! diff --git a/site/es/blog/new-in-devtools-101/index.md b/site/es/blog/new-in-devtools-101/index.md index 96d2ac7d3..2ab7b6e73 100644 --- a/site/es/blog/new-in-devtools-101/index.md +++ b/site/es/blog/new-in-devtools-101/index.md @@ -103,8 +103,8 @@ Chromium issues: [1296855](https://crbug.com/1296855), [https://crbug.com/130340 <!-- These are some noteworthy fixes in this release: --> Existen algunas correcciones destacadas en esta versión: -<!-- - The [Back/forward cache](/blog/new-in-devtools-98/#bfcache) now displays the extension ID which blocked [bfcache](https://web.dev/bfcache/) when present.( [1284548](https://crbug.com/1284548)) --> -- La [caché de retroceso/avance](/blog/new-in-devtools-98/#bfcache) ahora muestra el ID de la extensión que bloqueó [bfcache](https://web.dev/bfcache/) cuando está presente. ([1284548](https://crbug.com/1284548)) +<!-- - The [Back/forward cache](/blog/new-in-devtools-98/#bfcache) now displays the extension ID which blocked [bfcache](https://web.dev/articles/bfcache) when present.( [1284548](https://crbug.com/1284548)) --> +- La [caché de retroceso/avance](/blog/new-in-devtools-98/#bfcache) ahora muestra el ID de la extensión que bloqueó [bfcache](https://web.dev/articles/bfcache) cuando está presente. ([1284548](https://crbug.com/1284548)) <!-- - Fixed autocompletion support for array-like objects, CSS class names, `map.get` and HTML tags. ([1297101](https://crbug.com/1297101), [1297491](https://crbug.com/1297491), [1293807](https://crbug.com/1293807), [1296983](https://crbug.com/1296983)) --> - Corregido el soporte de autocompletado para objetos tipo array, nombres de clase CSS, `map.get` y etiquetas HTML. ([1297101](https://crbug.com/1297101), [1297491](https://crbug.com/1297491), [1293807](https://crbug.com/1293807), [1296983](https://crbug.com/1296983)) <!-- - Fixed incorrect highlights when double-clicking on words and undoing autocomplete. ([1298437](https://crbug.com/1298437), [1298667](https://crbug.com/1298667)) --> @@ -126,8 +126,8 @@ Existen algunas correcciones destacadas en esta versión: <!-- Apart from the existing **navigation** mode, the **Lighthouse** panel now support two more modes on measuring user flows - **timespan** and **snapshot**. --> Además del modo de navegación existente, el panel **Lighthouse** ahora soporta dos modos de medida de flujos de usuario - **tiempo de espera** e **instantánea**. -<!-- For example, you can use the **timespan** reports to analyze user interactions. Open this [demo](https://coffee-cart.netlify.app/) page. Select the **Timespan** mode and click on **Start timespan**. On the page, click on a coffee and end the timespan. Read the report to find out the [Total Blocking Time](https://web.dev/tbt/) and [Cumulative Layout Shift](https://web.dev/cls/) that were caused by the interaction. --> -Por ejemplo, puede usar los informes de **tiempo de espera** para analizar las interacciones de usuario. Abra esta página [demo](https://coffee-cart.netlify.app/). Seleccione el modo de **Tiempo de Espera** y haga clic en **Iniciar tiempo de bloqueo**. En la página, haga clic en un café y termine el tiempo de bloqueo. Lea el informe para encontrar el [Tiempo de bloqueo total](https://web.dev/tbt/) y [Desplazamiento acumulado del diseño](https://web.dev/cls/) que fueron causados por la interacción. +<!-- For example, you can use the **timespan** reports to analyze user interactions. Open this [demo](https://coffee-cart.netlify.app/) page. Select the **Timespan** mode and click on **Start timespan**. On the page, click on a coffee and end the timespan. Read the report to find out the [Total Blocking Time](https://web.dev/articles/tbt) and [Cumulative Layout Shift](https://web.dev/articles/cls) that were caused by the interaction. --> +Por ejemplo, puede usar los informes de **tiempo de espera** para analizar las interacciones de usuario. Abra esta página [demo](https://coffee-cart.netlify.app/). Seleccione el modo de **Tiempo de Espera** y haga clic en **Iniciar tiempo de bloqueo**. En la página, haga clic en un café y termine el tiempo de bloqueo. Lea el informe para encontrar el [Tiempo de bloqueo total](https://web.dev/articles/tbt) y [Desplazamiento acumulado del diseño](https://web.dev/articles/cls) que fueron causados por la interacción. <!-- Each mode has its own unique use cases, benefits, and limitations. Please refer to the [Lighthouse documentation](https://github.com/GoogleChrome/lighthouse/blob/master/docs/user-flows.md) for more information. --> Cada modo tiene sus propios casos de uso, beneficios y limitaciones. Por favor, consulte la [documentación de Lighthouse](https://github.com/GoogleChrome/lighthouse/blob/master/docs/user-flows.md) para más información. diff --git a/site/es/blog/new-in-devtools-102/index.md b/site/es/blog/new-in-devtools-102/index.md index a5f4f5a92..0c76ce384 100644 --- a/site/es/blog/new-in-devtools-102/index.md +++ b/site/es/blog/new-in-devtools-102/index.md @@ -61,13 +61,13 @@ Chromium issue: [1270700](https://crbug.com/1270700) <!-- ## New shortcuts to emulate light and dark themes {: #emulation } --> -<!-- You can now emulate the light and dark themes quicker (CSS media feature [prefers-color-scheme](https://web.dev/prefers-color-scheme/#the-prefers-color-scheme-media-query)) with the new shortcuts in the **Styles** pane. --> +<!-- You can now emulate the light and dark themes quicker (CSS media feature [prefers-color-scheme](https://web.dev/articles/prefers-color-scheme#the_prefers_color_scheme_media_query)) with the new shortcuts in the **Styles** pane. --> <!-- Previously, it took more steps to [emulate themes](/docs/devtools/rendering/emulate-css/) in the **Rendering** tab. --> ## Nuevos atajos para emular temas claros y oscuros {: #emulation } -Ahora puede emular los temas claros y oscuros rápidamente (característica multimedia CSS [prefiere-color-scheme](https://web.dev/prefers-color-scheme/#the-prefers-color-scheme-media-query)) con los nuevos accesos directos en el panel **Estilos**. +Ahora puede emular los temas claros y oscuros rápidamente (característica multimedia CSS [prefiere-color-scheme](https://web.dev/articles/prefers-color-scheme#the_prefers_color_scheme_media_query)) con los nuevos accesos directos en el panel **Estilos**. Anteriormente, se necesitaban más pasos para [emular temas](/docs/devtools/rendering/emulate-css/) en la pestaña **Rendering**. @@ -82,7 +82,7 @@ Chromium issue: [1314299](https://crbug.com/1314299) <!-- DevTools now apply the Content Security Policy (CSP) in the **Preview** tab in the **Network** panel. --> -<!-- For example, the first screenshot shows a page that contains [mixed content](https://web.dev/what-is-mixed-content/). The page loads over a secure HTTPS connection, but the stylesheet loads over an insecure HTTP connection. --> +<!-- For example, the first screenshot shows a page that contains [mixed content](https://web.dev/articles/what-is-mixed-content). The page loads over a secure HTTPS connection, but the stylesheet loads over an insecure HTTP connection. --> <!-- The browser blocked the stylesheet request by default. However, when you opened the page via the **Preview** tab in the **Network** panel, the stylesheet was not blocked previously (hence the background turned into red). It is now blocked as you would expect (second screenshot). --> @@ -90,7 +90,7 @@ Chromium issue: [1314299](https://crbug.com/1314299) DevTools ahora aplica la Política de seguridad de contenido (CSP) en la pestaña **Vista previa** en el panel **Red**. -Por ejemplo, la primera captura de pantalla muestra una página que contiene [contenido mixto](https://web.dev/what-is-mixed-content/). La página se carga a través de una conexión HTTPS segura, pero la hoja de estilo se carga a través de una conexión HTTP no segura. +Por ejemplo, la primera captura de pantalla muestra una página que contiene [contenido mixto](https://web.dev/articles/what-is-mixed-content). La página se carga a través de una conexión HTTPS segura, pero la hoja de estilo se carga a través de una conexión HTTP no segura. El navegador bloqueó la solicitud de la hoja de estilo de forma predeterminada. Sin embargo, cuando abrió la página a través de la pestaña **Vista previa** en el panel **Red**, la hoja de estilo no estaba bloqueada previamente (por lo tanto, el fondo se volvió rojo). Este está bloqueado como era de esperar (segunda captura de pantalla). diff --git a/site/es/blog/new-in-devtools-104/index.md b/site/es/blog/new-in-devtools-104/index.md index 8f55fd73b..d56db9cb5 100644 --- a/site/es/blog/new-in-devtools-104/index.md +++ b/site/es/blog/new-in-devtools-104/index.md @@ -106,8 +106,8 @@ Chromium issue: [960909](https://crbug.com/960909) <!-- Visualize `performance.measure()` marks in your recording with the new **User Timings** track in the **Performance insights** panel. --> Visualice las marcas `performance.measure()` en su grabación con la nueva pista **User Timings** en el panel **Performance insights**. -<!-- For example, this [web page](https://jec.fish/demo/perf-measure) uses the [`performance.measure()`](https://web.dev/usertiming/#calculating-measurements-with-measure()) method to calculate the elapsed time of text loading. --> -Por ejemplo, esta [página web](https://jec.fish/demo/perf-measure) utiliza [`performance.measure()`](https://web.dev/usertiming/#calculating-measurements- with-measure()) método para calcular el tiempo transcurrido de carga de texto. +<!-- For example, this [web page](https://jec.fish/demo/perf-measure) uses the [`performance.measure()`](https://web.dev/articles/usertiming#calculating_measurements_with_measure()) method to calculate the elapsed time of text loading. --> +Por ejemplo, esta [página web](https://jec.fish/demo/perf-measure) utiliza [`performance.measure()`](https://web.dev/articles/usertiming#calculating_measurements_ with_measure()) método para calcular el tiempo transcurrido de carga de texto. <!-- When you start [measuring the page load](/docs/devtools/performance-insights/#record), the **User Timings** track shows in the recording. Click on the timings item to view its details on the side pane. --> Cuando comienzas a [medir la carga de la página](/docs/devtools/performance-insights/#record), la pista **Tiempos de usuario** se muestra en la grabación. Haga clic en el elemento de tiempos para ver sus detalles en el panel lateral. diff --git a/site/es/blog/new-in-devtools-105/index.md b/site/es/blog/new-in-devtools-105/index.md index d7ca6f168..c00fefbf8 100644 --- a/site/es/blog/new-in-devtools-105/index.md +++ b/site/es/blog/new-in-devtools-105/index.md @@ -65,8 +65,8 @@ Chromium issue: [1257499](https://crbug.com/1257499) <!-- ## Largest Contentful Paint (LCP) in the Performance insights panel {: #lcp } --> ## Largest Contentful Paint (LCP) en el panel Performance Insights {: #lcp } -<!-- LCP is an important, user-centric metric for measuring [perceived load speed](https://web.dev/user-centric-performance-metrics/#types-of-metrics). You can now find out the critical paths and root causes of a [Largest Contentful Paint (LCP)](https://web.dev/lcp/). --> -LCP es una métrica importante, centrada en el usuario, para medir [velocidad de carga percibida](https://web.dev/user-centric-performance-metrics/#types-of-metrics). Ahora puede conocer los caminos críticos y las causas raíz de un [Largest Contentful Paint (LCP)](https://web.dev/lcp/). +<!-- LCP is an important, user-centric metric for measuring [perceived load speed](https://web.dev/articles/user-centric-performance-metrics#types_of_metrics). You can now find out the critical paths and root causes of a [Largest Contentful Paint (LCP)](https://web.dev/articles/lcp). --> +LCP es una métrica importante, centrada en el usuario, para medir [velocidad de carga percibida](https://web.dev/articles/user-centric-performance-metrics#types_of_metrics). Ahora puede conocer los caminos críticos y las causas raíz de un [Largest Contentful Paint (LCP)](https://web.dev/articles/lcp). <!-- In a [performance recording](/docs/devtools/performance-insights/#record), click on the LCP badge in the **Timeline**. In the **Details** pane, you can view the LCP score, learn how to fix resources that slow down the LCP and see the critical path for the LCP resource. --> En una grabación de rendimiento, haga clic en el sello LCP en la **Línea de tiempo**. En el panel de detalles, puede ver la puntuación del LCP, aprender cómo arreglar recursos que ralentizan el LCP y ver el camino crítico para el recurso LCP. @@ -82,14 +82,14 @@ Chromium issue: [1326481](https://crbug.com/1326481) <!-- ## Identify flashes of text (FOIT, FOUT) as potential root causes for layout shifts {: #foit-fout } --> ## Identificar parpadeos de texto (FOIT, FOUT) como causas potenciales de desplazamientos de diseño {: #foit-fout } -<!-- The **Performance insights** panel now detects [flash of invisible text (FOIT) and flash of unstyled text (FOUT)](https://web.dev/preload-optional-fonts/#font-rendering) as potential root causes for layout shifts. --> -El [panel Performance Insights](/docs/devtools/performance-insights/) ahora detecta [parpadeos de texto invisible (FOIT) y parpadeos de texto sin estilos (FOUT)](https://web.dev/preload-optional-fonts/#font-rendering) como causas potenciales de desplazamientos de diseño. +<!-- The **Performance insights** panel now detects [flash of invisible text (FOIT) and flash of unstyled text (FOUT)](https://web.dev/articles/preload-optional-fonts#font_rendering) as potential root causes for layout shifts. --> +El [panel Performance Insights](/docs/devtools/performance-insights/) ahora detecta [parpadeos de texto invisible (FOIT) y parpadeos de texto sin estilos (FOUT)](https://web.dev/articles/preload-optional-fonts#font_rendering) como causas potenciales de desplazamientos de diseño. <!-- To view the potential root causes of a layout shift, click on a screenshot in the **Layout shifts** track. --> Para ver las causas principales de un desplazamiento de diseño, haga clic en una captura de pantalla en la pista de **Desplazamientos de diseño**. -<!-- See [Optimize WebFont loading and rendering](https://web.dev/optimize-webfont-loading/) to learn the technique to prevent layout shifts. --> -Vea [Optimizar carga de fuentes web y pintado](https://web.dev/optimize-webfont-loading/) para aprender la técnica para evitar desplazamientos de diseño. +<!-- See [Optimize WebFont loading and rendering](https://web.dev/articles/optimize-webfont-loading) to learn the technique to prevent layout shifts. --> +Vea [Optimizar carga de fuentes web y pintado](https://web.dev/articles/optimize-webfont-loading) para aprender la técnica para evitar desplazamientos de diseño. {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/AMN5oD5hlKhPhnq98sIB.png", alt="FOUT en el panel Performance Insights", width="800", height="497" %} @@ -98,8 +98,8 @@ Chromium issues: [1334628](https://crbug.com/1334628), [1328873](https://crbug.c <!-- ## Protocol handlers in the Manifest pane {: #manifest } --> ## Controladores de protocolo en el panel de Manifiesto {: #manifest } -<!-- You can now use DevTools to test the [URL protocol handler registration](https://web.dev/url-protocol-handler/) for [Progressive Web Apps (PWA)](https://web.dev/learn/pwa/). --> -Ahora puede usar DevTools para probar el [registro de controlador de protocolo de URL](https://web.dev/url-protocol-handler/) para [Aplicaciones Web Progresivas (PWA)](https://web.dev/learn/pwa/). +<!-- You can now use DevTools to test the [URL protocol handler registration](https://web.dev/articles/url-protocol-handler) for [Progressive Web Apps (PWA)](https://web.dev/learn/pwa). --> +Ahora puede usar DevTools para probar el [registro de controlador de protocolo de URL](https://web.dev/articles/url-protocol-handler) para [Aplicaciones Web Progresivas (PWA)](https://web.dev/learn/pwa). <!-- The URL protocol handler registration lets installed PWAs handle links that use a specific protocol (e.g. [`magnet`](https://wikipedia.org/wiki/Magnet_URI_scheme), `web+example`) for a more integrated experience. --> El registro de controladores para el protocolo URL permite a las PWAs instaladas manejar enlaces que usen un protocolo específico (por ejemplo, [`magnet`](https://wikipedia.org/wiki/Magnet_URI_scheme), `web+example`) para una experiencia más integrada. @@ -124,8 +124,8 @@ Chromium issues: [1300613](https://crbug.com/1300613) <!-- Use the [top layer badge](/blog/top-layer-devtools/#top-layer-support-design-in-devtools) to understand the concept of the top layer and visualize how the top layer content changes. --> Use la [insignia de capa superior](/blog/top-layer-devtools/#top-layer-support-design-in-devtools) para entender el concepto de la capa superior y visualizar cómo cambia el contenido de la capa superior. -<!-- The [`<dialog>` element](https://web.dev/building-a-dialog-component/) has recently become stable across browsers. When you open a dialog, it is put into a [top layer](/blog/top-layer-devtools/). Top level content renders on top of all the other content. --> -El [elemento `<dialog>`](https://web.dev/building-a-dialog-component/) se volvió estable recientemente en todos los navegadores. Cuando abre un diálogo, se pone en una [capa superior](/blog/top-layer-devtools/). El contenido de nivel superior es pintado encima de todo el contenido. +<!-- The [`<dialog>` element](https://web.dev/articles/building-a-dialog-component) has recently become stable across browsers. When you open a dialog, it is put into a [top layer](/blog/top-layer-devtools/). Top level content renders on top of all the other content. --> +El [elemento `<dialog>`](https://web.dev/articles/building-a-dialog-component) se volvió estable recientemente en todos los navegadores. Cuando abre un diálogo, se pone en una [capa superior](/blog/top-layer-devtools/). El contenido de nivel superior es pintado encima de todo el contenido. <!-- In this [demo](https://jec.fish/demo/dialog), click **Open dialog**. --> En esta [demo](https://jec.fish/demo/dialog), haga clic en **Open dialog**. diff --git a/site/es/blog/new-in-devtools-106/index.md b/site/es/blog/new-in-devtools-106/index.md index 196f682c0..1ef465061 100644 --- a/site/es/blog/new-in-devtools-106/index.md +++ b/site/es/blog/new-in-devtools-106/index.md @@ -188,7 +188,7 @@ Chromium bug: [1347390](https://crbug.com/1347390) <!-- ## LCP timings breakdown in the Performance Insights panel {: #insights } --> ## Desglose de tiempos de LCP en el panel de pespectiva de rendimiento {: #insights } -<!-- The **Performance Insights** panel now shows the [timings breakdown](https://web.dev/optimize-lcp/#lcp-breakdown) of the [Largest Containful Paint (LCP)](/docs/devtools/performance-insights/#largest-contentful-paint). Use these timings information to understand and identify an opportunity to improve LCP performance. --> +<!-- The **Performance Insights** panel now shows the [timings breakdown](https://web.dev/articles/optimize-lcp#lcp_breakdown) of the [Largest Containful Paint (LCP)](/docs/devtools/performance-insights/#largest-contentful-paint). Use these timings information to understand and identify an opportunity to improve LCP performance. --> {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/hU6RmoRjFskL8P2ZAB9l.png", alt="Desglose de tiempos de LCP en el panel Perspectiva de Rendimiento", width="800", height="523" %} @@ -221,8 +221,8 @@ Chromium bug: [1351383](https://crbug.com/1351383) <!-- - The **Styles** pane now displays a color picker for the [SVG `<stop>`](https://developer.mozilla.org/docs/Web/SVG/Element/stop) element’s `stop-color` property. ([1351096](https://crbug.com/1351096)) --> - El panel **Estilos** ahora muestra un selector de color para la propiedad `stop-color` del elemento [SVG `<stop>`](https://developer.mozilla.org/docs/Web/SVG/Element/stop) . ([1351096](https://crbug.com/1351096)) -<!-- - Identify script causing [layout](https://web.dev/avoid-large-complex-layouts-and-layout-thrashing/) as the potential root causes for layout shifts in the **Performance Insights** panel. ([1343019](https://crbug.com/1343019)) --> -- Identifique el script que está provocando la ejecución de [layout](https://web.dev/avoid-large-complex-layouts-and-layout-thrashing/) como una posible causa fundamental de cambios de diseño con el panel **Performance Insights**. ([1343019](https://crbug.com/1343019)) +<!-- - Identify script causing [layout](https://web.dev/articles/avoid-large-complex-layouts-and-layout-thrashing) as the potential root causes for layout shifts in the **Performance Insights** panel. ([1343019](https://crbug.com/1343019)) --> +- Identifique el script que está provocando la ejecución de [layout](https://web.dev/articles/avoid-large-complex-layouts-and-layout-thrashing) como una posible causa fundamental de cambios de diseño con el panel **Performance Insights**. ([1343019](https://crbug.com/1343019)) <!-- - Display critical path for LCP web fonts in the **Performance Insights** panel. ([1350390](https://crbug.com/1350390)) --> - Se muestra la ruta crítica para las fuentes web LCP en el panel **Performance Insights**. ([1350390](https://crbug.com/1350390)) diff --git a/site/es/blog/new-in-devtools-112/index.md b/site/es/blog/new-in-devtools-112/index.md index 09aa4c319..d7c150235 100644 --- a/site/es/blog/new-in-devtools-112/index.md +++ b/site/es/blog/new-in-devtools-112/index.md @@ -48,7 +48,7 @@ Chromium issue: [1400243](https://crbug.com/1400243). <!-- In addition to [custom, CSS, ARIA, text, and XPath selectors](/docs/devtools/recorder/reference/#selector), you can now record using [pierce selectors](https://pptr.dev/guides/query-selectors#pierce-selectors-pierce). These selectors behave like CSS ones but can also pierce through shadow roots. --> -<!-- Start a new recording on a page with [shadow DOM](https://web.dev/shadowdom-v1/) and check {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/hmp8j3HiLMCcqPArD9yt.svg", alt="Checkbox.", width="22", height="22" %} **Pierce** in **Selector types to record**. Record your interaction with elements in the shadow DOM and inspect the corresponding step. --> +<!-- Start a new recording on a page with [shadow DOM](https://web.dev/articles/shadowdom-v1) and check {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/hmp8j3HiLMCcqPArD9yt.svg", alt="Checkbox.", width="22", height="22" %} **Pierce** in **Selector types to record**. Record your interaction with elements in the shadow DOM and inspect the corresponding step. --> {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/Spqbf2DG3Fr0D2sc1kgC.png", alt="Setting the Recorder to use pierce selectors; Pierce selector in action.", width="800", height="534" %} diff --git a/site/es/blog/new-in-devtools-92/index.md b/site/es/blog/new-in-devtools-92/index.md index 1038add0f..88faac8a9 100644 --- a/site/es/blog/new-in-devtools-92/index.md +++ b/site/es/blog/new-in-devtools-92/index.md @@ -150,7 +150,7 @@ Chromium issue: [622660](https://crbug.com/622660) ## Incluye las intersecciones computadas en el panel de Performance {: #computed-intersections } -DevTools ahora te muestra el coste de las **intersecciones computadas** en la pila de JavaScript. Este cambio te puede ayudar a identificar los eventos de [Intersection Observer](https://web.dev/intersectionobserver-v2/) y depurar cualquier problema potencial de rendimiento. +DevTools ahora te muestra el coste de las **intersecciones computadas** en la pila de JavaScript. Este cambio te puede ayudar a identificar los eventos de [Intersection Observer](https://web.dev/articles/intersectionobserver-v2) y depurar cualquier problema potencial de rendimiento. {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/Nx3K0Lpst0lICGbtpzsW.png", alt="Interseciones computadas en el panel de Performance", width="800", height="496" %} @@ -223,4 +223,4 @@ Ten en cuenta que este experimento está en sus primeras etapas de desarrollo. H Chromium issue: [1199787](https://crbug.com/1199787) {% Partial 'devtools/reach-out.md' %} -{% Partial 'devtools/whats-new.md' %} \ No newline at end of file +{% Partial 'devtools/whats-new.md' %} diff --git a/site/es/blog/new-in-devtools-93/index.md b/site/es/blog/new-in-devtools-93/index.md index 5613fcc5a..91b34e451 100644 --- a/site/es/blog/new-in-devtools-93/index.md +++ b/site/es/blog/new-in-devtools-93/index.md @@ -23,7 +23,7 @@ tags: ## Consultas de contenedores CSS editables en el panel de Estilos {: #container-queries } -Ahora puedes ver y editar las [consultas de contenedores CSS](https://web.dev/new-responsive/#responsive-to-the-container) en el panel de **Estilos**. +Ahora puedes ver y editar las [consultas de contenedores CSS](https://web.dev/articles/new-responsive#responsive_to_the_container) en el panel de **Estilos**. Las consultas de contenedor (*container queries*) ofrecen una manera mucho más dinámica de realizar diseños adaptables. La regla `@container` funciona de una forma similar a las consultas de medios (*media queries*). Sin embargo, en lugar de consultar el tamaño de la ventana y la información del agente del usuario, `@container` consulta el contenedor ascendiente que cumple cierto criterio. @@ -43,7 +43,7 @@ Chromium issue: [1146422](https://crbug.com/1146422) ## Previsualización de paquetes Web en el panel de Red {: #web-bundle } -[Un paquete Web](https://web.dev/web-bundles/) es un formato de encapsulación de uno o más recursos HTTP en un sólo fichero. Ahora puedes previsualizar el contenido de tu paquete web en el panel de **Red**. +[Un paquete Web](https://web.dev/articles/web-bundles) es un formato de encapsulación de uno o más recursos HTTP en un sólo fichero. Ahora puedes previsualizar el contenido de tu paquete web en el panel de **Red**. Actualmente la característica de paquete web es experimental. Por favor, activa la opción `#enable-experimental-web-platform-features` en `chrome://flags` para probarlo. diff --git a/site/es/blog/new-in-devtools-96/index.md b/site/es/blog/new-in-devtools-96/index.md index 4c3f65f45..629c4b6e2 100644 --- a/site/es/blog/new-in-devtools-96/index.md +++ b/site/es/blog/new-in-devtools-96/index.md @@ -39,11 +39,11 @@ Lea [este artículo](/docs/devtools/css-overview) para obtener más información Chromium issue: [1254557](https://crbug.com/1254557) -## Recuperada y mejorada las acciones de copiar y editar propiedades CSS con logintud {: #length } +## Recuperada y mejorada las acciones de copiar y editar propiedades CSS con logintud {: #length } Las acciones de **copiar CSS** y **editar como texto** se restauran para las propiedades CSS con longitud. Estas características dejaron de funcionar en la última versión. -{% Video src="video/dPDCek3EhZgLQPGtEG3y0fTn4v82/3zxmVrRNd767L9zPDvU8.mp4", autoplay="true", muted="true", loop="true", class="screenshot" %} +{% Video src="video/dPDCek3EhZgLQPGtEG3y0fTn4v82/3zxmVrRNd767L9zPDvU8.mp4", autoplay="true", muted="true", loop="true", class="screenshot" %} Además, puede arrastrar para ajustar el valor de la unidad y actualizar el tipo de unidad a través del menú desplegable. Esta funcionalidad no debería afectar a la experiencia de usuario en la acción principal editar como texto. @@ -178,7 +178,7 @@ Chromium issues: [1232937](https://crbug.com/1232937), [1255586](https://crbug.c ## Panel de caché de la aplicación en desuso (deprecated) en el panel de la aplicación {: #app-cache } --> -El panel [Caché de la aplicación](/docs/devtools/storage/applicationcache/) en el panel de Aplicación se eliminó pues el soporte para [AppCache](https://web.dev/appcache-removal/) se ha eliminado de Chrome y otros navegadores basados ​​en Chromium. +El panel [Caché de la aplicación](/docs/devtools/storage/applicationcache/) en el panel de Aplicación se eliminó pues el soporte para [AppCache](https://web.dev/articles/appcache-removal) se ha eliminado de Chrome y otros navegadores basados ​​en Chromium. {# https://chromium.googlesource.com/devtools/devtools-frontend/+/de4d15e955d6145674e3885cde8a5a70f1269b79 #} @@ -191,13 +191,13 @@ Chromium issue: [1084190](https://crbug.com/1084190) Para habilitar esta característica experimental, marque la casilla de verificación **Enable Reporting API panel in the Application panel** que encontrará en la siguiente ruta **Configuración** > **Experimentos**. {% endAside %} -La [API de informes](https://web.dev/reporting-api/) está diseñada para ayudarlo a monitorear las violaciones de seguridad de su página, las llamadas a API obsoletas y más. +La [API de informes](https://web.dev/articles/reporting-api) está diseñada para ayudarlo a monitorear las violaciones de seguridad de su página, las llamadas a API obsoletas y más. Con este experimento habilitado, ahora puede ver el estado de los informes en el nuevo panel **API de informes** en el panel **Aplicación**. Tenga en cuenta que la sección **Endpoints** se encuentra actualmente en desarrollo activo (no muestra ningún informe de endpoints por ahora). -Obtenga más información sobre la **API de informes** con [este artículo](https://web.dev/reporting-api/). +Obtenga más información sobre la **API de informes** con [este artículo](https://web.dev/articles/reporting-api). {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/hbwFqi9aNDOj70FhLXsn.png", alt="Panel de la API de informes en el panel de la aplicación", width="800", height="476" %} diff --git a/site/es/blog/new-in-devtools-98/index.md b/site/es/blog/new-in-devtools-98/index.md index b93870ab5..5815e3659 100644 --- a/site/es/blog/new-in-devtools-98/index.md +++ b/site/es/blog/new-in-devtools-98/index.md @@ -105,9 +105,9 @@ Chromium issue: [1257499](https://crbug.com/1257499) ## Asegúrese de que sus páginas se puedan almacenar en caché con la pestaña de caché Atrás/adelante {: #bfcache } -<!-- [Back/forward cache (or bfcache)](https://web.dev/bfcache/) is a browser optimization that enables instant back and forward navigation. --> +<!-- [Back/forward cache (or bfcache)](https://web.dev/articles/bfcache) is a browser optimization that enables instant back and forward navigation. --> -[Caché Atrás/adelante (o bfcache)](https://web.dev/bfcache/) es una optimización del navegador que permite la navegación instantánea hacia atrás y hacia adelante. +[Caché Atrás/adelante (o bfcache)](https://web.dev/articles/bfcache) es una optimización del navegador que permite la navegación instantánea hacia atrás y hacia adelante. <!-- The new **Back/forward cache** tab can help you test your pages to ensure they're optimized for bfcache, and identify any issues that may be preventing them from being eligible. --> @@ -244,9 +244,9 @@ Vaya a los [atajos de teclado](/docs/devtools/shortcuts/) para consultar los ata El panel **Lighthouse** ahora ejecuta Lighthouse 9. Lighthouse ahora enumerará todos los elementos que comparten la misma identificación. -<!-- Non-unique element id is a common accessibility problem. For instance, the id referenced in an `aria-labelledby` attribute is used on [multiple elements](https://web.dev/duplicate-id-aria/). --> +<!-- Non-unique element id is a common accessibility problem. For instance, the id referenced in an `aria-labelledby` attribute is used on [multiple elements](https://web.dev/articles/duplicate-id-aria). --> -La identificación de elemento no único es un problema de accesibilidad común. Por ejemplo, la identificación a la que se hace referencia en un atributo `aria-labelledby` se usa en [múltiples elementos](https://web.dev/duplicate-id-aria/). +La identificación de elemento no único es un problema de accesibilidad común. Por ejemplo, la identificación a la que se hace referencia en un atributo `aria-labelledby` se usa en [múltiples elementos](https://web.dev/articles/duplicate-id-aria). <!-- Check out the [What's new in Lighthouse 9.0](/blog/lighthouse-9-0/) for more details on the updates. --> @@ -314,9 +314,9 @@ El panel experimental **API Reporting** se introdujo en [Chrome 96](/blog/new-in La sección **Endpoints** ya está disponible. Le brinda una descripción general de todos los `endpoints` configurados en el encabezado `Reporting-Endpoints`. -<!-- Learn to use the [Reporting API](https://web.dev/reporting-api/) to monitor security violations, deprecated API calls, and more. --> +<!-- Learn to use the [Reporting API](https://web.dev/articles/reporting-api) to monitor security violations, deprecated API calls, and more. --> -Aprenda a usar la [API de informes](https://web.dev/reporting-api/) para monitorear violaciones de seguridad, llamadas a API obsoletas y más. +Aprenda a usar la [API de informes](https://web.dev/articles/reporting-api) para monitorear violaciones de seguridad, llamadas a API obsoletas y más. {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/D1fUz4zuS1xwDbszgft1.png", alt="Panel de informes de API", width="800", height="560" %} diff --git a/site/es/blog/new-in-devtools-99/index.md b/site/es/blog/new-in-devtools-99/index.md index 5b4904e85..0204314ae 100644 --- a/site/es/blog/new-in-devtools-99/index.md +++ b/site/es/blog/new-in-devtools-99/index.md @@ -37,8 +37,8 @@ Chromium issue: [423246](https://crbug.com/423246) <!-- Use the new **Reporting API** pane to monitor the reports generated on your page and their status. --> Usa el nuevo panel **Reportes API** para monitorizar los reportes generados en tu página y su estado. -<!-- The [Reporting API](https://web.dev/reporting-api/) is designed to help you monitor security violations of your page, deprecated API calls, and more. --> -La [API de Reportes](https://web.dev/reporting-api/) está diseñada para ayudarte a monitorizar las violaciones de seguridad de tu página, llamadas a API obsoletas y más. +<!-- The [Reporting API](https://web.dev/articles/reporting-api) is designed to help you monitor security violations of your page, deprecated API calls, and more. --> +La [API de Reportes](https://web.dev/articles/reporting-api) está diseñada para ayudarte a monitorizar las violaciones de seguridad de tu página, llamadas a API obsoletas y más. <!-- Open a page which uses the Reporting API (e.g. [demo page](https://reporting-api-demo.glitch.me/)). In the **Application** panel, scroll down to the **Background services** section and select the **Reporting API** pane. --> Abra una página que use la API de Reportes (ej. [página de demostración](https://reporting-api-demo.glitch.me/)). En el panel **Aplicación**, desplácese hacia abajo hasta la sección **Servicios en segundo plano** y seleccione el panel **Reportes API**. @@ -156,7 +156,7 @@ Chromium issue: [1284737](https://crbug.com/1284737) <!-- ### Display worker source files in the Sources panel {: #worker-sourcemap } --> ### Muestra los archivos de fuente de Worker en el panel de Fuentes {: #worker-sourcemap } -<!-- [Worker](https://web.dev/workers-overview/) (e.g. web worker, service worker) source files with relative SourceURL are now displayed in the **Source** panel. Previously, worker source files were not handled correctly. --> +<!-- [Worker](https://web.dev/articles/workers-overview) (e.g. web worker, service worker) source files with relative SourceURL are now displayed in the **Source** panel. Previously, worker source files were not handled correctly. --> Los archivos fuente de Worker (ej. web worker, service worker) con SourceURL relativa se muestran ahora en el panel de **Fuentes**. Antes, los archivos de fuente de Worker no se manejaban correctamente. {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/apH5n92bqYWINMQn5VXa.png", alt="Muestra los archivos de fuente de Worker en el panel de Fuentes", width="800", height="509" %} @@ -213,10 +213,10 @@ Estos son algunos arreglos destacados en esta versión: - Arreglado el [problema de edición de cookies](/docs/devtools/storage/cookies/#edit) en el panel **Cookies**. ([1290196](https://crbug.com/1290196)) <!-- - Use `Shift` + `Tab` to select the previous command in the [Command menu](/docs/devtools/command-menu/). ([1278743](https://crbug.com/1278743)) --> - Usa `Mayús` + `Tab` para seleccionar el comando anterior en el [Menú de Comandos](/docs/devtools/command-menu/). ([1278743](https://crbug.com/1278743)) -<!-- - Report [CORS preflight request](https://web.dev/cross-origin-resource-sharing/#preflight-requests-for-complex-http-calls) issues in the [Issues](/docs/devtools/issues/) tab. ([1272445](https://crbug.com/1272445)). --> -- Reporta [problemas de solicitud de preflight](https://web.dev/cross-origin-resource-sharing/#preflight-requests-for-complex-http-calls) en la pestaña [Problemas](/docs/devtools/issues/). ([1272445](https://crbug.com/1272445)). -<!-- - Report [User-Agent Client Hints](https://web.dev/user-agent-client-hints/) issues in the [Issues](/docs/devtools/issues/) tab. ([1219359](https://crbug.com/1219359)). --> -- Reporta [problemas de User-Agent Client Hints](https://web.dev/user-agent-client-hints/) en la pestaña [Problemas](/docs/devtools/issues/). ([1219359](https://crbug.com/1219359)). +<!-- - Report [CORS preflight request](https://web.dev/articles/cross-origin-resource-sharing#preflight_requests_for_complex_http_calls) issues in the [Issues](/docs/devtools/issues/) tab. ([1272445](https://crbug.com/1272445)). --> +- Reporta [problemas de solicitud de preflight](https://web.dev/articles/cross-origin-resource-sharing#preflight_requests_for_complex_http_calls) en la pestaña [Problemas](/docs/devtools/issues/). ([1272445](https://crbug.com/1272445)). +<!-- - Report [User-Agent Client Hints](https://web.dev/articles/user-agent-client-hints) issues in the [Issues](/docs/devtools/issues/) tab. ([1219359](https://crbug.com/1219359)). --> +- Reporta [problemas de User-Agent Client Hints](https://web.dev/articles/user-agent-client-hints) en la pestaña [Problemas](/docs/devtools/issues/). ([1219359](https://crbug.com/1219359)). <!-- - Fixed `Shift` + `Delete` and `Page up` / `Page down` behaviors in the **Sources** and **Console** panel. ([1278461](https://crbug.com/1278461), [1285662](https://crbug.com/1285662)) --> - Arreglado el comportamiento de `Mayús` + `Supr` y `Re Pág` / `Av Pág` en el panel **Fuentes** y **Consola**. ([1278461](https://crbug.com/1278461), [1285662](https://crbug.com/1285662)) <!-- - Close the breakpoint edit dialog on breakpoint removal in the **Sources** panel. (922513) --> diff --git a/site/es/docs/lighthouse/best-practices/external-anchors-use-rel-noopener/index.md b/site/es/docs/lighthouse/best-practices/external-anchors-use-rel-noopener/index.md index ba9d5de78..9be7411eb 100644 --- a/site/es/docs/lighthouse/best-practices/external-anchors-use-rel-noopener/index.md +++ b/site/es/docs/lighthouse/best-practices/external-anchors-use-rel-noopener/index.md @@ -45,10 +45,10 @@ Agregue `rel="noopener"` o `rel="noreferrer"` a cada enlace identificado en su i - `rel="noopener"` evita que la nueva página pueda acceder a la `window.opener` y garantiza que se ejecute en un proceso separado. - `rel="noreferrer"` tiene el mismo efecto, pero también evita que la cabecera `Referer` se envíe a la nueva página. Consulte [Tipo de enlace "noreferrer"](https://html.spec.whatwg.org/multipage/links.html#link-type-noreferrer). -Consulte la publicación [Compartir recursos de origen cruzado de forma segura](https://web.dev/cross-origin-resource-sharing/) para obtener más información. +Consulte la publicación [Compartir recursos de origen cruzado de forma segura](https://web.dev/articles/cross-origin-resource-sharing) para obtener más información. ## Recursos - [Código fuente para la auditoría **Enlaces a destinos de origen cruzado inseguros**](https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js) -- [Comparta recursos de origen cruzado de forma segura](https://web.dev/cross-origin-resource-sharing/) +- [Comparta recursos de origen cruzado de forma segura](https://web.dev/articles/cross-origin-resource-sharing) - [Aislamiento del sitio para desarrolladores web](https://developers.google.com/web/updates/2018/07/site-isolation) diff --git a/site/es/docs/lighthouse/best-practices/image-aspect-ratio/index.md b/site/es/docs/lighthouse/best-practices/image-aspect-ratio/index.md index c5bfb2907..201b58f98 100644 --- a/site/es/docs/lighthouse/best-practices/image-aspect-ratio/index.md +++ b/site/es/docs/lighthouse/best-practices/image-aspect-ratio/index.md @@ -27,7 +27,7 @@ Existen dos causas comunes para una relación de aspecto incorrecta de las imág ### Utilice un CDN de imagen -Un CDN de imagen puede facilitar la automatización del proceso de creación de versiones de diferentes tamaños de sus imágenes. Consulte el documento [Uso de los CDN de imagen para optimizar imágenes](https://web.dev/image-cdns/) para obtener una descripción general, además consulte [Cómo instalar el CDN de imágenes Thumbor](https://web.dev/install-thumbor/) para un laboratorio de código práctico. +Un CDN de imagen puede facilitar la automatización del proceso de creación de versiones de diferentes tamaños de sus imágenes. Consulte el documento [Uso de los CDN de imagen para optimizar imágenes](https://web.dev/articles/image-cdns) para obtener una descripción general, además consulte [Cómo instalar el CDN de imágenes Thumbor](https://web.dev/articles/install-thumbor) para un laboratorio de código práctico. ### Verifique el CSS que afecta la relación de aspecto de la imagen @@ -39,11 +39,11 @@ Cuando sea posible, una práctica recomendable es especificar los atributos `wid Sin embargo, especificar las dimensiones de la imagen en HTML puede ser difícil si se trabaja con imágenes receptivas, porque no hay forma de saber el ancho y la altura hasta que se conozcan las dimensiones de la ventana gráfica. Considere la posibilidad de utilizar la biblioteca [Relación de aspecto CSS](https://www.npmjs.com/package/css-aspect-ratio) o los [cuadros de relación de aspecto](https://css-tricks.com/aspect-ratio-boxes/) para ayudar a conservar las proporciones de las imágenes receptivas. -Por último, consulte la publicación [Suministrar imágenes con las dimensiones correctas](https://web.dev/serve-images-with-correct-dimensions/) para saber cómo suministrar imágenes del tamaño adecuado para el dispositivo de cada usuario. +Por último, consulte la publicación [Suministrar imágenes con las dimensiones correctas](https://web.dev/articles/serve-images-with-correct-dimensions) para saber cómo suministrar imágenes del tamaño adecuado para el dispositivo de cada usuario. ## Recursos - [Código fuente para la auditoría **Mostrar las imágenes con una relación de aspecto incorrecta**](https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/audits/image-aspect-ratio.js) - [Relación de aspecto CSS](https://www.npmjs.com/package/css-aspect-ratio) - [Cajas de relación de aspecto](https://css-tricks.com/aspect-ratio-boxes/) -- [Suministrar imágenes con las dimensiones correctas](https://web.dev/serve-images-with-correct-dimensions/) +- [Suministrar imágenes con las dimensiones correctas](https://web.dev/articles/serve-images-with-correct-dimensions) diff --git a/site/es/docs/lighthouse/performance/bootup-time/index.md b/site/es/docs/lighthouse/performance/bootup-time/index.md index 783f3c35a..a78f22111 100644 --- a/site/es/docs/lighthouse/performance/bootup-time/index.md +++ b/site/es/docs/lighthouse/performance/bootup-time/index.md @@ -22,7 +22,7 @@ Cuando su JavaScript tarda mucho en ejecutarse, ralentiza el rendimiento de su p - **Costo de ejecución** - JavaScript también se ejecuta en el hilo principal. Si su página ejecuta mucho código antes de que sea realmente necesario, eso también retrasa el [Time to Interactive (tiempo de interacción)](https://web.dev/tti/), que es una de las métricas clave relacionadas con la forma en que los usuarios perciben la velocidad de su página. + JavaScript también se ejecuta en el hilo principal. Si su página ejecuta mucho código antes de que sea realmente necesario, eso también retrasa el [Time to Interactive (tiempo de interacción)](https://web.dev/articles/tti), que es una de las métricas clave relacionadas con la forma en que los usuarios perciben la velocidad de su página. - **Costo de memoria** diff --git a/site/es/docs/lighthouse/performance/critical-request-chains/index.md b/site/es/docs/lighthouse/performance/critical-request-chains/index.md index ae4775bf3..9761ba414 100644 --- a/site/es/docs/lighthouse/performance/critical-request-chains/index.md +++ b/site/es/docs/lighthouse/performance/critical-request-chains/index.md @@ -32,7 +32,7 @@ Utilice los resultados de la auditoría de cadenas de solicitudes críticas para - Optimice el número de bytes críticos para reducir el tiempo de descarga (número de viajes de ida y vuelta). - Optimice el orden en el que se cargan los recursos críticos restantes: descargue todos los activos críticos lo antes posible para acortar la longitud de la ruta crítica. -Obtenga más información sobre cómo optimizar sus [imágenes](https://web.dev/use-imagemin-to-compress-images/), [JavaScript](https://web.dev/apply-instant-loading-with-prpl/), [CSS](https://web.dev/defer-non-critical-css/) y [fuentes web](https://web.dev/avoid-invisible-text/). +Obtenga más información sobre cómo optimizar sus [imágenes](https://web.dev/articles/use-imagemin-to-compress-images), [JavaScript](https://web.dev/articles/apply-instant-loading-with-prpl), [CSS](https://web.dev/articles/defer-non-critical-css) y [fuentes web](https://web.dev/articles/avoid-invisible-text). ## Directrices específicas según la pila diff --git a/site/es/docs/lighthouse/performance/dom-size/index.md b/site/es/docs/lighthouse/performance/dom-size/index.md index ecbbe2dce..7830724ca 100644 --- a/site/es/docs/lighthouse/performance/dom-size/index.md +++ b/site/es/docs/lighthouse/performance/dom-size/index.md @@ -49,11 +49,11 @@ Si no puede evitar un árbol DOM grande, otro enfoque para mejorar el rendimient ### Angular -Si renderiza listas grandes, utilice [desplazamiento virtual](https://web.dev/virtualize-lists-with-angular-cdk/) con el Kit de desarrollo de componentes (CDK). +Si renderiza listas grandes, utilice [desplazamiento virtual](https://web.dev/articles/virtualize-lists-with-angular-cdk) con el Kit de desarrollo de componentes (CDK). ### React -- Utilice una biblioteca de "ventanas" como [`react-window`](https://web.dev/virtualize-long-lists-react-window/) para minimizar el número de nodos DOM creados si renderiza muchos elementos repetidos en la página. +- Utilice una biblioteca de "ventanas" como [`react-window`](https://web.dev/articles/virtualize-long-lists-react-window) para minimizar el número de nodos DOM creados si renderiza muchos elementos repetidos en la página. - Minimice las renderizaciones repetititvas innecesarias utilizando [`shouldComponentUpdate`](https://reactjs.org/docs/optimizing-performance.html#shouldcomponentupdate-in-action), [`PureComponent`](https://reactjs.org/docs/react-api.html#reactpurecomponent), o [`React.memo`](https://reactjs.org/docs/react-api.html#reactmemo). - [Omita efectos](https://reactjs.org/docs/hooks-effect.html#tip-optimizing-performance-by-skipping-effects) solo hasta que ciertas dependencias hayan cambiado si utiliza el hook `Effect` para mejorar el rendimiento en el tiempo de ejecución. diff --git a/site/es/docs/lighthouse/performance/efficient-animated-content/index.md b/site/es/docs/lighthouse/performance/efficient-animated-content/index.md index e24abf407..7c1e036d5 100644 --- a/site/es/docs/lighthouse/performance/efficient-animated-content/index.md +++ b/site/es/docs/lighthouse/performance/efficient-animated-content/index.md @@ -53,7 +53,7 @@ Afortunadamente, puede recrear estos comportamientos usando el elemento `<video> ## Utilizar un servicio que convierta GIF en videos HTML5 -Muchas [CDN de imágenes admiten](https://web.dev/image-cdns/) la conversión de video GIF a HTML5. Se sube un GIF a la CDN de imágenes, y esta devuelve un video HTML5. +Muchas [CDN de imágenes admiten](https://web.dev/articles/image-cdns) la conversión de video GIF a HTML5. Se sube un GIF a la CDN de imágenes, y esta devuelve un video HTML5. ## Orientación específica de la pila @@ -64,5 +64,5 @@ Para contenido animado, use [`amp-anim`](https://amp.dev/documentation/component ## Recursos - [Código fuente para la auditoría **Usar formatos de video para contenido animado**](https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/audits/byte-efficiency/efficient-animated-content.js) -- [Reemplazar los GIF animados con video para cargas de página más rápidas](https://web.dev/replace-gifs-with-videos/) +- [Reemplazar los GIF animados con video para cargas de página más rápidas](https://web.dev/articles/replace-gifs-with-videos) - [Laboratorio de código para reemplazar GIF con video](https://web.dev/codelab-replace-gifs-with-video) diff --git a/site/es/docs/lighthouse/performance/first-meaningful-paint/index.md b/site/es/docs/lighthouse/performance/first-meaningful-paint/index.md index 76428e9c9..ddaccb97b 100644 --- a/site/es/docs/lighthouse/performance/first-meaningful-paint/index.md +++ b/site/es/docs/lighthouse/performance/first-meaningful-paint/index.md @@ -6,7 +6,7 @@ date: 2019-05-02 updated: 2019-11-05 --- -{% Aside 'caution' %} El Primer despliegue significativo (FMP) está obsoleto a partir de Lighthouse 6.0. En la práctica, FMP se ha comportado de forma demasiado sensible a las pequeñas diferencias en la carga de la página, lo que ha dado lugar a resultados inconsistentes (bimodales). Además, la definición de la métrica se basa en detalles de implementación específicos del navegador, lo que significa que no se puede estandarizar ni implementar en todos los navegadores. En el futuro, en vez de esta métrica, considere usar [Despliegue del contenido más extenso](https://web.dev/lcp/). {% endAside %} +{% Aside 'caution' %} El Primer despliegue significativo (FMP) está obsoleto a partir de Lighthouse 6.0. En la práctica, FMP se ha comportado de forma demasiado sensible a las pequeñas diferencias en la carga de la página, lo que ha dado lugar a resultados inconsistentes (bimodales). Además, la definición de la métrica se basa en detalles de implementación específicos del navegador, lo que significa que no se puede estandarizar ni implementar en todos los navegadores. En el futuro, en vez de esta métrica, considere usar [Despliegue del contenido más extenso](https://web.dev/articles/lcp). {% endAside %} Primer despliegue significativo (FMP) es una de las seis métricas que se registran en la sección **Rendimiento** del informe Lighthouse. Cada métrica captura algún aspecto de la velocidad de carga de la página. @@ -18,7 +18,7 @@ Lighthouse muestra FMP en segundos: FMP mide cuándo el contenido principal de una página se hace visible para el usuario. La puntuación bruta para FMP es el tiempo en segundos entre el momento en que el usuario inicia la carga de la página y el momento en que la página presenta el contenido principal de la mitad superior de la página. FMP esencialmente muestra el momento del despliegue después del cual ocurre el mayor cambio en el diseño en la parte superior de la página. Obtenga más información sobre los detalles técnicos de FMP en [Hasta el primer despliegue significativo: un enfoque basado en diseño](https://docs.google.com/document/d/1BR94tJdZLsin5poeet0XoTW60M0SjvOJQttKT-JK8HI/view) de Google. -El [Primer despliegue del contenido (FCP)](https://web.dev/fcp/) y el FMP suelen ser iguales cuando el primer fragmento de contenido representado en la página incluye el contenido en la mitad superior de la página. Sin embargo, estas métricas pueden diferir cuando, por ejemplo, existe contenido en la mitad superior de un iframe. FMP registra cuando el contenido dentro del iframe es visible para el usuario, mientras que FCP _no_ incluye contenido de iframe. +El [Primer despliegue del contenido (FCP)](https://web.dev/articles/fcp) y el FMP suelen ser iguales cuando el primer fragmento de contenido representado en la página incluye el contenido en la mitad superior de la página. Sin embargo, estas métricas pueden diferir cuando, por ejemplo, existe contenido en la mitad superior de un iframe. FMP registra cuando el contenido dentro del iframe es visible para el usuario, mientras que FCP _no_ incluye contenido de iframe. ## Cómo Lighthouse determina su puntaje FMP @@ -63,11 +63,11 @@ Esta tabla muestra cómo interpretar su puntuación FMP: ## Cómo mejorar su puntuación FMP -Vea [Cómo mejorar despliegue del contenido más extenso en su sitio](https://web.dev/lcp/#how-to-improve-lcp). Las estrategias para mejorar el FMP son en gran parte las mismas que las estrategias para mejorar el despliegue del contenido más extenso. +Vea [Cómo mejorar despliegue del contenido más extenso en su sitio](https://web.dev/articles/lcp#how_to_improve_lcp). Las estrategias para mejorar el FMP son en gran parte las mismas que las estrategias para mejorar el despliegue del contenido más extenso. ## Seguimiento de FMP en dispositivos de usuarios reales -Para saber cómo medir cuándo ocurre realmente el FMP en los dispositivos de sus usuarios, consulte la página de [métricas de rendimiento centradas en el usuario](https://web.dev/user-centric-performance-metrics/) de Google. La sección [Seguimiento de FMP usando elementos principales](https://developers.google.com/web/fundamentals/performance/user-centric-performance-metrics#tracking_fmp_using_hero_elements) describe cómo acceder a los datos de FCP mediante programación y enviarlos a Google Analytics. +Para saber cómo medir cuándo ocurre realmente el FMP en los dispositivos de sus usuarios, consulte la página de [métricas de rendimiento centradas en el usuario](https://web.dev/articles/user-centric-performance-metrics) de Google. La sección [Seguimiento de FMP usando elementos principales](https://developers.google.com/web/fundamentals/performance/user-centric-performance-metrics#tracking_fmp_using_hero_elements) describe cómo acceder a los datos de FCP mediante programación y enviarlos a Google Analytics. Consulte [Evaluación del rendimiento de carga en la vida real con la navegación y sincronización de recursos](https://developers.google.com/web/fundamentals/performance/navigation-and-resource-timing/) de Google para obtener más información sobre la recopilación de métricas de usuarios reales. La [auditoría de Lighthouse User Timing marks and measures](/docs/lighthouse/performance/user-timings/) le permite ver los datos del tiempo del usuario en su informe. @@ -78,4 +78,4 @@ Consulte [Evaluación del rendimiento de carga en la vida real con la navegació - [Código fuente para la auditoría de **Primer despliegue significativo**](https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/audits/metrics/first-meaningful-paint.js) - [Guía de puntuación de Lighthouse v3](https://developers.google.com/web/tools/lighthouse/v3/scoring) - [Hasta el primer despliegue significativo: un enfoque basado en diseño](https://docs.google.com/document/d/1BR94tJdZLsin5poeet0XoTW60M0SjvOJQttKT-JK8HI/view) -- [Despliegue con contenido más extenso](https://web.dev/lcp/) +- [Despliegue con contenido más extenso](https://web.dev/articles/lcp) diff --git a/site/es/docs/lighthouse/performance/font-display/index.md b/site/es/docs/lighthouse/performance/font-display/index.md index b265f7ff6..f05d37cbf 100644 --- a/site/es/docs/lighthouse/performance/font-display/index.md +++ b/site/es/docs/lighthouse/performance/font-display/index.md @@ -6,7 +6,7 @@ date: 2019-05-02 updated: 2020-04-29 --- -Con frecuencia, las fuentes son archivos grandes que tardan en cargarse. En algunos navegadores se oculta el texto hasta que se carga la fuente, lo que provoca un [destello de texto invisible (FOIT)](https://web.dev/avoid-invisible-text/). +Con frecuencia, las fuentes son archivos grandes que tardan en cargarse. En algunos navegadores se oculta el texto hasta que se carga la fuente, lo que provoca un [destello de texto invisible (FOIT)](https://web.dev/articles/avoid-invisible-text). ## Cómo falla la auditoría de visualización para fuentes de Lighthouse @@ -32,14 +32,14 @@ El modo más sencillo de evitar que se visualice el texto invisible mientras se } ``` -En la [API de visualización de las fuentes](https://developer.mozilla.org/docs/Web/CSS/@font-face/font-display) se especifica cómo se muestra una fuente. `swap` permite que el navegador muestre inmediatamente el texto que utiliza la fuente con una fuente del sistema. Una vez que la fuente personalizada está lista, reemplaza a la fuente del sistema. (Consulte la publicación [Evitar el texto invisible durante la carga](https://web.dev/avoid-invisible-text/) para obtener más información). +En la [API de visualización de las fuentes](https://developer.mozilla.org/docs/Web/CSS/@font-face/font-display) se especifica cómo se muestra una fuente. `swap` permite que el navegador muestre inmediatamente el texto que utiliza la fuente con una fuente del sistema. Una vez que la fuente personalizada está lista, reemplaza a la fuente del sistema. (Consulte la publicación [Evitar el texto invisible durante la carga](https://web.dev/articles/avoid-invisible-text) para obtener más información). ### Precargar fuentes web Utilice `<link rel="preload" as="font">` para recuperar los archivos de sus fuentes con antelación. Obtenga más información: -- [Precargue fuentes web para mejorar la velocidad de carga (codelab)](https://web.dev/codelab-preload-web-fonts/)<a></a> -- [Evite el cambio de diseño y los destellos de texto invisible (FOIT) mediante la precarga de fuentes opcionales](https://web.dev/preload-optional-fonts/) +- [Precargue fuentes web para mejorar la velocidad de carga (codelab)](https://web.dev/articles/codelab-preload-web-fonts)<a></a> +- [Evite el cambio de diseño y los destellos de texto invisible (FOIT) mediante la precarga de fuentes opcionales](https://web.dev/articles/preload-optional-fonts) ### Fuentes de Google @@ -71,7 +71,7 @@ Especifique `@font-display` al [definir fuentes personalizadas](https://devdocs. ## Recursos - [Código fuente para **Asegurar que el texto permanezca visible durante la auditoría de carga para fuentes web**](https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/audits/font-display.js) -- [Evitar el texto invisible durante la carga](https://web.dev/avoid-invisible-text/) +- [Evitar el texto invisible durante la carga](https://web.dev/articles/avoid-invisible-text) - [Controlar el rendimiento de las fuentes con visualizadores para fuentes](https://developers.google.com/web/updates/2016/02/font-display) -- [Precargar fuentes web para mejorar la velocidad de carga (codelab)](https://web.dev/codelab-preload-web-fonts/)<a></a> -- [Evitar el cambio de diseño y los destellos de texto invisible (FOIT) mediante la precarga de fuentes opcionales](https://web.dev/preload-optional-fonts/) +- [Precargar fuentes web para mejorar la velocidad de carga (codelab)](https://web.dev/articles/codelab-preload-web-fonts)<a></a> +- [Evitar el cambio de diseño y los destellos de texto invisible (FOIT) mediante la precarga de fuentes opcionales](https://web.dev/articles/preload-optional-fonts) diff --git a/site/es/docs/lighthouse/performance/interactive/index.md b/site/es/docs/lighthouse/performance/interactive/index.md index aa413b99e..ce4091898 100644 --- a/site/es/docs/lighthouse/performance/interactive/index.md +++ b/site/es/docs/lighthouse/performance/interactive/index.md @@ -20,7 +20,7 @@ Lighthouse muestra el TTI en segundos: El TTI mide el tiempo que tarda una página en volverse _completamente_ interactiva. Una página se considera completamente interactiva cuando: -- La página muestra contenido útil, que se mide con [First Contentful Paint (FCP): Primera pintura con contenido](https://web.dev/fcp/) +- La página muestra contenido útil, que se mide con [First Contentful Paint (FCP): Primera pintura con contenido](https://web.dev/articles/fcp) - Los controladores de eventos están registrados para la mayoría de los elementos visibles de la página - La página responde a las interacciones del usuario en menos de 50 milisegundos @@ -61,16 +61,16 @@ Esta tabla muestra cómo interpretar tu puntaje TTI: ## Cómo mejorar tu puntaje TTI -Una mejora que puede tener un efecto particularmente importante en el TTI es diferir o eliminar el trabajo de JavaScript innecesario. Busca oportunidades para [optimizar tu JavaScript](https://web.dev/fast/#optimize-your-javascript). En particular, considera [la posibilidad de reducir las cargas útiles de JavaScript dividiendo el código](https://web.dev/reduce-javascript-payloads-with-code-splitting/) y [aplicando el patrón PRPL](https://web.dev/apply-instant-loading-with-prpl). [La optimización de JavaScript de terceros](https://web.dev/fast/#optimize-your-third-party-resources) también produce mejoras significativas para algunos sitios. +Una mejora que puede tener un efecto particularmente importante en el TTI es diferir o eliminar el trabajo de JavaScript innecesario. Busca oportunidades para [optimizar tu JavaScript](https://web.dev/articles/fast#optimize_your_javascript). En particular, considera [la posibilidad de reducir las cargas útiles de JavaScript dividiendo el código](https://web.dev/articles/reduce-javascript-payloads-with-code-splitting) y [aplicando el patrón PRPL](https://web.dev/apply-instant-loading-with-prpl). [La optimización de JavaScript de terceros](https://web.dev/articles/fast#optimize_your_third_party_resources) también produce mejoras significativas para algunos sitios. Estas dos auditorías de diagnóstico brindan oportunidades adicionales para reducir el trabajo de JavaScript: -- [Minimizar el trabajo del hilo principal](https://web.dev/mainthread-work-breakdown/) -- [Reducir el tiempo de ejecución de JavaScript](https://web.dev/bootup-time/) +- [Minimizar el trabajo del hilo principal](https://web.dev/articles/mainthread-work-breakdown) +- [Reducir el tiempo de ejecución de JavaScript](https://web.dev/articles/bootup-time) ## Seguimiento del TTI en dispositivos de usuarios reales -Para saber cómo medir cuándo ocurre realmente el TTI en los dispositivos de sus usuarios, consulta la página de [métricas de rendimiento centradas en el usuario](https://web.dev/user-centric-performance-metrics/) de Google. La sección de [seguimiento de TTI](https://developers.google.com/web/fundamentals/performance/user-centric-performance-metrics#tracking_tti) describe cómo acceder, mediante la programación, a los datos de TTI y enviarlos a Google Analytics. +Para saber cómo medir cuándo ocurre realmente el TTI en los dispositivos de sus usuarios, consulta la página de [métricas de rendimiento centradas en el usuario](https://web.dev/articles/user-centric-performance-metrics) de Google. La sección de [seguimiento de TTI](https://developers.google.com/web/fundamentals/performance/user-centric-performance-metrics#tracking_tti) describe cómo acceder, mediante la programación, a los datos de TTI y enviarlos a Google Analytics. {% Aside %} El TTI puede ser difícil de rastrear en un ambiente real. El seguimiento del [First Input Delay (FID): Demora de la primera entrada](https://developers.google.com/web/updates/2018/05/first-input-delay) puede ser un buen indicador directo del TTI. {% endAside %} @@ -83,4 +83,4 @@ Para saber cómo medir cuándo ocurre realmente el TTI en los dispositivos de su - [First Interactive And Consistently Interactive (Primer interactivo y consistentemente interactivo)](https://docs.google.com/document/d/1GGiI9-7KeY3TPqS3YT271upUVimo-XiL5mwWorDUD4c/edit) - [Optimización del JavaScript de arranque](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/javascript-startup-optimization/) - [Reduce las cargas útiles de JavaScript con Tree Shaking](https://developers.google.com/web/fundamentals/performance/optimizing-javascript/tree-shaking/) -- [Optimización de los recursos de terceros](https://web.dev/fast/#optimize-your-third-party-resources) +- [Optimización de los recursos de terceros](https://web.dev/articles/fast#optimize_your_third_party_resources) diff --git a/site/es/docs/lighthouse/performance/lighthouse-total-blocking-time/index.md b/site/es/docs/lighthouse/performance/lighthouse-total-blocking-time/index.md index 27713c900..d3c86ca1b 100644 --- a/site/es/docs/lighthouse/performance/lighthouse-total-blocking-time/index.md +++ b/site/es/docs/lighthouse/performance/lighthouse-total-blocking-time/index.md @@ -16,7 +16,7 @@ El informe Lighthouse muestra el TBT en milisegundos: ## Qué mide la TBT -La TBT mide la cantidad total de tiempo que una página está bloqueada para que no responda a la entrada del usuario, como los clics del ratón, toques de la pantalla o pulsaciones del teclado. La suma se calcula sumando la _parte de bloqueo_ de todas [las tareas largas](https://web.dev/long-tasks-devtools/) entre [First Contentful Paint (primer despliegue de contenido)](https://web.dev/fcp/) y [Time to Interactive (tiempo de interacción)](https://web.dev/tti/). Cualquier tarea que se ejecute durante más de 50 ms es una tarea larga. La cantidad de tiempo después de 50 ms es la parte de bloqueo. Por ejemplo, si Lighthouse detecta una tarea de 70 ms de duración, la porción de bloqueo sería de 20 ms. +La TBT mide la cantidad total de tiempo que una página está bloqueada para que no responda a la entrada del usuario, como los clics del ratón, toques de la pantalla o pulsaciones del teclado. La suma se calcula sumando la _parte de bloqueo_ de todas [las tareas largas](https://web.dev/articles/long-tasks-devtools) entre [First Contentful Paint (primer despliegue de contenido)](https://web.dev/articles/fcp) y [Time to Interactive (tiempo de interacción)](https://web.dev/articles/tti). Cualquier tarea que se ejecute durante más de 50 ms es una tarea larga. La cantidad de tiempo después de 50 ms es la parte de bloqueo. Por ejemplo, si Lighthouse detecta una tarea de 70 ms de duración, la porción de bloqueo sería de 20 ms. ## Cómo determina Lighthouse su puntaje TBT @@ -53,11 +53,11 @@ Esta tabla muestra cómo interpretar su puntaje TBT: ## Cómo mejorar su puntaje TBT -Consulte [¿Qué está causando mis tareas largas?](https://web.dev/long-tasks-devtools/#what-is-causing-my-long-tasks) para aprender a diagnosticar la causa principal de tareas largas con el panel Rendimiento de Chrome DevTools. +Consulte [¿Qué está causando mis tareas largas?](https://web.dev/articles/long-tasks-devtools#what_is_causing_my_long_tasks) para aprender a diagnosticar la causa principal de tareas largas con el panel Rendimiento de Chrome DevTools. En general, las causas más comunes de tareas largas son: -- Carga, análisis o ejecución de JavaScript innecesarios. Al analizar su código en el panel Rendimiento, es posible que descubra que el hilo principal está realizando un trabajo que no es realmente necesario para cargar la página. [Reducir las cargas útiles de JavaScript con la división de código](https://web.dev/reduce-javascript-payloads-with-code-splitting/), [eliminar el código no utilizado](https://web.dev/remove-unused-code/) o [cargar JavaScript de terceros de manera eficiente](https://web.dev/efficiently-load-third-party-javascript/) debería mejorar su puntaje TBT. +- Carga, análisis o ejecución de JavaScript innecesarios. Al analizar su código en el panel Rendimiento, es posible que descubra que el hilo principal está realizando un trabajo que no es realmente necesario para cargar la página. [Reducir las cargas útiles de JavaScript con la división de código](https://web.dev/articles/reduce-javascript-payloads-with-code-splitting), [eliminar el código no utilizado](https://web.dev/articles/remove-unused-code) o [cargar JavaScript de terceros de manera eficiente](https://web.dev/articles/efficiently-load-third-party-javascript) debería mejorar su puntaje TBT. - Declaraciones de JavaScript ineficientes. Por ejemplo, después de analizar su código en el panel Rendimiento, suponga que ve una llamada a `document.querySelectorAll('a')` que devuelve 2000 nodos. Refactorizar su código para usar un selector más específico que solo devuelva 10 nodos debería mejorar su puntaje TBT. {% Aside %} La carga, el análisis o la ejecución innecesarios de JavaScript suelen ser una oportunidad mucho mayor de mejora en la mayoría de los sitios. {% endAside %} @@ -67,10 +67,10 @@ En general, las causas más comunes de tareas largas son: ## Recursos - [Código fuente para la auditoría **Total Blocking Time**](https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/audits/metrics/total-blocking-time.js) -- [¿Las tareas largas de JavaScript están retrasando su Time to Interactive?](https://web.dev/long-tasks-devtools/) +- [¿Las tareas largas de JavaScript están retrasando su Time to Interactive?](https://web.dev/articles/long-tasks-devtools) - [Optimizar la demora de la primera entrada](https://web.dev/optimize-fid) -- [Primer despliegue de contenido](https://web.dev/fcp/) -- [Tiempo de interacción](https://web.dev/tti/) -- [Reducir las cargas útiles de JavaScript con la división de código](https://web.dev/reduce-javascript-payloads-with-code-splitting/) -- [Eliminar el código no utilizado](https://web.dev/remove-unused-code/) -- [Cargar de manera eficiente los recursos de terceros](https://web.dev/efficiently-load-third-party-javascript/) +- [Primer despliegue de contenido](https://web.dev/articles/fcp) +- [Tiempo de interacción](https://web.dev/articles/tti) +- [Reducir las cargas útiles de JavaScript con la división de código](https://web.dev/articles/reduce-javascript-payloads-with-code-splitting) +- [Eliminar el código no utilizado](https://web.dev/articles/remove-unused-code) +- [Cargar de manera eficiente los recursos de terceros](https://web.dev/articles/efficiently-load-third-party-javascript) diff --git a/site/es/docs/lighthouse/performance/non-composited-animations/index.md b/site/es/docs/lighthouse/performance/non-composited-animations/index.md index 211f774ae..a29ad6a6d 100644 --- a/site/es/docs/lighthouse/performance/non-composited-animations/index.md +++ b/site/es/docs/lighthouse/performance/non-composited-animations/index.md @@ -5,7 +5,7 @@ description: Cómo aprobar la auditoría Lighthouse "Evitar animaciones no compu date: 2020-08-12 --- -Las animaciones no compuestas pueden parecer irregulares (es decir, no fluidas) en teléfonos de gama baja o cuando se ejecutan tareas de alto rendimiento en la línea principal. Las animaciones Janky pueden aumentar el [cambio de diseño acumulativo](https://web.dev/cls/) (CLS) de su página. Reducir CLS mejorará su puntuación de rendimiento de Lighthouse. +Las animaciones no compuestas pueden parecer irregulares (es decir, no fluidas) en teléfonos de gama baja o cuando se ejecutan tareas de alto rendimiento en la línea principal. Las animaciones Janky pueden aumentar el [cambio de diseño acumulativo](https://web.dev/articles/cls) (CLS) de su página. Reducir CLS mejorará su puntuación de rendimiento de Lighthouse. ## Antecedentes @@ -27,12 +27,12 @@ Cuando una animación no se puede componer, Chrome informa las razones de la fal ## Cómo asegurarse de que las animaciones estén compuestas -Consulta [Adherirse a las propiedades exclusivas del compositor y administrar el número de capas](https://developers.google.com/web/fundamentals/performance/rendering/stick-to-compositor-only-properties-and-manage-layer-count) y [las animaciones de alto rendimiento](https://web.dev/animations-guide/) . +Consulta [Adherirse a las propiedades exclusivas del compositor y administrar el número de capas](https://developers.google.com/web/fundamentals/performance/rendering/stick-to-compositor-only-properties-and-manage-layer-count) y [las animaciones de alto rendimiento](https://web.dev/articles/animations-guide) . ## Recursos - [Código fuente para la auditoría de _Evitar animaciones no compuestas_](https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/audits/non-composited-animations.js) - [Limítate a las propiedades exclusivas del compositor y gestiona el número de capas](https://developers.google.com/web/fundamentals/performance/rendering/stick-to-compositor-only-properties-and-manage-layer-count) -- [Animaciones de alto rendimiento](https://web.dev/animations-guide/) +- [Animaciones de alto rendimiento](https://web.dev/articles/animations-guide) - [Simplifica la complejidad de la pintura y reduce sus áreas](https://developers.google.com/web/fundamentals/performance/rendering/simplify-paint-complexity-and-reduce-paint-areas) - [Una mirada al interior de los navegadores web modernos (parte 3)](https://developers.google.com/web/updates/2018/09/inside-browser-part3) diff --git a/site/es/docs/lighthouse/performance/offscreen-images/index.md b/site/es/docs/lighthouse/performance/offscreen-images/index.md index 694f9ba53..099cc0708 100644 --- a/site/es/docs/lighthouse/performance/offscreen-images/index.md +++ b/site/es/docs/lighthouse/performance/offscreen-images/index.md @@ -8,7 +8,7 @@ date: 2019-05-02 updated: 2020-05-29 --- -La sección de Oportunidades del informe Lighthouse enumera todas las imágenes ocultas o fuera de la pantalla en tu página junto con los ahorros potenciales en [kibibytes (KiB)](https://en.wikipedia.org/wiki/Kibibyte). Considera la posibilidad de cargar de forma diferida estas imágenes después de que todos los recursos críticos hayan terminado de cargarse para reducir el [Time to Interactive (TTI): Tiempo para interactuar](https://web.dev/tti/): +La sección de Oportunidades del informe Lighthouse enumera todas las imágenes ocultas o fuera de la pantalla en tu página junto con los ahorros potenciales en [kibibytes (KiB)](https://en.wikipedia.org/wiki/Kibibyte). Considera la posibilidad de cargar de forma diferida estas imágenes después de que todos los recursos críticos hayan terminado de cargarse para reducir el [Time to Interactive (TTI): Tiempo para interactuar](https://web.dev/articles/tti): <figure>{% Img src="image/tcFciHGuF3MxnTr1y5ue01OGLBn2/agMyJtIarLruD8iuz0Mt.png", alt="Una captura de pantalla de la auditoría de aplazar imágenes fuera de pantalla de Lighthouse", width="800", height="416" %}</figure> @@ -30,7 +30,7 @@ Instala un [complemento de Joomla de carga diferida](https://extensions.joomla.o ### Magento -Considera modificar las plantillas de tu producto y catálogo para hacer uso de la función de [carga diferida](https://web.dev/browser-level-image-lazy-loading/) de la plataforma web. +Considera modificar las plantillas de tu producto y catálogo para hacer uso de la función de [carga diferida](https://web.dev/articles/browser-level-image-lazy-loading) de la plataforma web. ### WordPress diff --git a/site/es/docs/lighthouse/performance/server-response-time/index.md b/site/es/docs/lighthouse/performance/server-response-time/index.md index 902b538fa..d13d4710d 100644 --- a/site/es/docs/lighthouse/performance/server-response-time/index.md +++ b/site/es/docs/lighthouse/performance/server-response-time/index.md @@ -51,4 +51,4 @@ Tanto los temas, los complementos y las especificaciones del servidor contribuye ## Recursos - [Código fuente para la auditoría de **Reducción de los tiempos de respuesta del servidor (TTFB**](https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/audits/server-response-time.js) -- [Servicio adaptativo con API de Información de red](https://web.dev/adaptive-serving-based-on-network-quality/) +- [Servicio adaptativo con API de Información de red](https://web.dev/articles/adaptive-serving-based-on-network-quality) diff --git a/site/es/docs/lighthouse/performance/third-party-facades/index.md b/site/es/docs/lighthouse/performance/third-party-facades/index.md index b32b3dfa3..2d1c2045f 100644 --- a/site/es/docs/lighthouse/performance/third-party-facades/index.md +++ b/site/es/docs/lighthouse/performance/third-party-facades/index.md @@ -7,7 +7,7 @@ description: |2 date: 2020-12-01 --- -Los [recursos de terceros](https://web.dev/third-party-javascript/) se utilizan a menudo para mostrar anuncios o videos e integrarse con las redes sociales. El enfoque predeterminado es cargar los recursos de terceros tan pronto como se carga la página, pero esto puede ralentizar innecesariamente la carga de la misma. Si el contenido de terceros no es crítico, este costo de rendimiento se puede reducir [al cargarlo de forma diferida](https://web.dev/fast/#lazy-load-images-and-video). +Los [recursos de terceros](https://web.dev/articles/third-party-javascript) se utilizan a menudo para mostrar anuncios o videos e integrarse con las redes sociales. El enfoque predeterminado es cargar los recursos de terceros tan pronto como se carga la página, pero esto puede ralentizar innecesariamente la carga de la misma. Si el contenido de terceros no es crítico, este costo de rendimiento se puede reducir [al cargarlo de forma diferida](https://web.dev/articles/fast#lazy_load_images_and_video). Esta auditoría destaca las incrustaciones de terceros que se pueden cargar de forma diferida durante la interacción. En ese caso, se utiliza una _fachada_ en lugar del contenido de terceros hasta que el usuario interactúe con él. diff --git a/site/es/docs/lighthouse/performance/total-byte-weight/index.md b/site/es/docs/lighthouse/performance/total-byte-weight/index.md index c6444ac90..ca35ea591 100644 --- a/site/es/docs/lighthouse/performance/total-byte-weight/index.md +++ b/site/es/docs/lighthouse/performance/total-byte-weight/index.md @@ -24,22 +24,22 @@ Según los datos de [HTTP Archive](https://httparchive.org/reports/state-of-the- ## Cómo reducir el tamaño de la carga útil -Trata de mantener tu tamaño total de bytes por debajo de los 1,600 KiB. Este objetivo se basa en la cantidad de datos que teóricamente se pueden descargar en una conexión 3G sin dejar de alcanzar un [Time to Interactive (TTI): Tiempo para interactuar](https://web.dev/tti/) de 10 segundos o menos. +Trata de mantener tu tamaño total de bytes por debajo de los 1,600 KiB. Este objetivo se basa en la cantidad de datos que teóricamente se pueden descargar en una conexión 3G sin dejar de alcanzar un [Time to Interactive (TTI): Tiempo para interactuar](https://web.dev/articles/tti) de 10 segundos o menos. A continuación, se muestran algunas formas de reducir el tamaño de la carga útil: -- Aplazar las solicitudes hasta que sean necesarias. Consulta el [patrón PRPL](https://web.dev/apply-instant-loading-with-prpl/) para ver una posible aproximación. +- Aplazar las solicitudes hasta que sean necesarias. Consulta el [patrón PRPL](https://web.dev/articles/apply-instant-loading-with-prpl) para ver una posible aproximación. - Optimiza las consultas para que sean lo más pequeñas posible. Las posibles técnicas incluyen: - - [Minimiza y comprime las cargas útiles de la red](https://web.dev/reduce-network-payloads-using-text-compression/). - - [Utiliza WebP en lugar de JPEG o PNG para tus imágenes](https://web.dev/serve-images-webp/). - - [Establece el nivel de compresión de las imágenes JPEG en 85](https://web.dev/use-imagemin-to-compress-images/). -- Almacena las solicitudes en caché para que la página no vuelva a descargar los recursos en visitas repetidas. (Consulta la [confiabilidad de la página de inicio de la red](https://web.dev/reliable/) para aprender cómo funciona el almacenamiento en caché y cómo implementarlo). + - [Minimiza y comprime las cargas útiles de la red](https://web.dev/articles/reduce-network-payloads-using-text-compression). + - [Utiliza WebP en lugar de JPEG o PNG para tus imágenes](https://web.dev/articles/serve-images-webp). + - [Establece el nivel de compresión de las imágenes JPEG en 85](https://web.dev/articles/use-imagemin-to-compress-images). +- Almacena las solicitudes en caché para que la página no vuelva a descargar los recursos en visitas repetidas. (Consulta la [confiabilidad de la página de inicio de la red](https://web.dev/explore/reliable) para aprender cómo funciona el almacenamiento en caché y cómo implementarlo). ## Orientación de recursos tecnológicos específicos ### Angular -Aplica la [división de código a nivel de ruta](https://web.dev/route-level-code-splitting-in-angular/) para minimizar el tamaño de tus paquetes de JavaScript. Además, considera almacenar en caché los archivos con los [service workers de Angular](https://web.dev/precaching-with-the-angular-service-worker/). +Aplica la [división de código a nivel de ruta](https://web.dev/articles/route-level-code-splitting-in-angular) para minimizar el tamaño de tus paquetes de JavaScript. Además, considera almacenar en caché los archivos con los [service workers de Angular](https://web.dev/articles/precaching-with-the-angular-service-worker). ### Drupal diff --git a/site/es/docs/lighthouse/performance/unminified-css/index.md b/site/es/docs/lighthouse/performance/unminified-css/index.md index 793d7a874..db8a8086c 100644 --- a/site/es/docs/lighthouse/performance/unminified-css/index.md +++ b/site/es/docs/lighthouse/performance/unminified-css/index.md @@ -54,7 +54,7 @@ Para sitios pequeños que no usted actualiza con frecuencia, probablemente pueda Para los desarrolladores profesionales, probablemente desee configurar un flujo de trabajo automatizado que minifique su CSS automáticamente antes de implementar su código actualizado. Esto generalmente se logra con una herramienta de compilación como Gulp o Webpack. -Aprenda a minificar su código CSS en [Minificar CSS](https://web.dev/minify-css/). +Aprenda a minificar su código CSS en [Minificar CSS](https://web.dev/articles/minify-css). ## Orientación específica de la pila @@ -81,5 +81,5 @@ Varios [complementos](https://wordpress.org/plugins/search/minify+css/) de WordP ## Recursos - [Código fuente para la auditoría **Minificar CSS**](https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/audits/byte-efficiency/unminified-css.js) -- [Minificar CSS](https://web.dev/minify-css/) -- [Minifique y comprima las cargas útiles de la red](https://web.dev/reduce-network-payloads-using-text-compression/) +- [Minificar CSS](https://web.dev/articles/minify-css) +- [Minifique y comprima las cargas útiles de la red](https://web.dev/articles/reduce-network-payloads-using-text-compression) diff --git a/site/es/docs/lighthouse/performance/unused-css-rules/index.md b/site/es/docs/lighthouse/performance/unused-css-rules/index.md index 603cd607e..93e299aa3 100644 --- a/site/es/docs/lighthouse/performance/unused-css-rules/index.md +++ b/site/es/docs/lighthouse/performance/unused-css-rules/index.md @@ -46,7 +46,7 @@ Similar al código en línea en una etiqueta de`<script>`, se requieren estilos Considera la posibilidad de automatizar el proceso de extracción e inserción de CSS "Above the Fold" utilizando la [Critical tool (Herramienta critica)](https://github.com/addyosmani/critical/blob/master/README.md). -Obten más información en [Aplazar CSS no crítico](https://web.dev/defer-non-critical-css/). +Obten más información en [Aplazar CSS no crítico](https://web.dev/articles/defer-non-critical-css). ## Orientación de recursos tecnológicos específicos diff --git a/site/es/docs/lighthouse/performance/unused-javascript/index.md b/site/es/docs/lighthouse/performance/unused-javascript/index.md index dd8a3c05b..7451de182 100644 --- a/site/es/docs/lighthouse/performance/unused-javascript/index.md +++ b/site/es/docs/lighthouse/performance/unused-javascript/index.md @@ -56,7 +56,7 @@ Desactive la [compactación de JavaScript](https://devdocs.magento.com/guides/v2 ### React -Si no renderiza el lado del servidor, [divida sus paquetes de JavaScript](https://web.dev/code-splitting-suspense/) con `React.lazy()`. De lo contrario, divida el código mediante una biblioteca de terceros como [loadable-components](https://www.smooth-code.com/open-source/loadable-components/docs/getting-started/). +Si no renderiza el lado del servidor, [divida sus paquetes de JavaScript](https://web.dev/articles/code-splitting-suspense) con `React.lazy()`. De lo contrario, divida el código mediante una biblioteca de terceros como [loadable-components](https://www.smooth-code.com/open-source/loadable-components/docs/getting-started/). ### Vue @@ -69,7 +69,7 @@ Considere la posibilidad de reducir, o cambiar, el número de [complementos de J ## Recursos - [Código fuente para **Eliminar el código que no se utiliza** en la auditoría](https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/audits/byte-efficiency/unused-javascript.js) -- [Eliminar el código que no se utiliza](https://web.dev/remove-unused-code/) +- [Eliminar el código que no se utiliza](https://web.dev/articles/remove-unused-code) - [Agregar interactividad con JavaScript](https://developers.google.com/web/fundamentals/performance/critical-rendering-path/adding-interactivity-with-javascript) - [Dividir el código](https://bundlers.tooling.report/code-splitting/) - [Eliminar códigos inactivos](https://bundlers.tooling.report/transformations/dead-code/) diff --git a/site/es/docs/lighthouse/performance/uses-long-cache-ttl/index.md b/site/es/docs/lighthouse/performance/uses-long-cache-ttl/index.md index 4fa78996a..e145eb80d 100644 --- a/site/es/docs/lighthouse/performance/uses-long-cache-ttl/index.md +++ b/site/es/docs/lighthouse/performance/uses-long-cache-ttl/index.md @@ -63,7 +63,7 @@ No use `no-cache` si el recurso cambia y la actualización es importante, pero s No siempre es bueno que la duración del caché sea por tiempo prolongado. En última instancia, depende de usted decidir cuál será la duración óptima del caché para sus recursos. -Hay muchas directorios por personalizar conforme el caché del navegador almacene diferentes recursos. Obtenga más información sobre el almacenamiento de los recursos en el caché en [El caché HTTP: su guía sobre la primera línea de defensa](https://web.dev/http-cache/) y [Cómo configurar el codelab de comportamiento para el almacenamiento HTTP](https://web.dev/codelab-http-cache). +Hay muchas directorios por personalizar conforme el caché del navegador almacene diferentes recursos. Obtenga más información sobre el almacenamiento de los recursos en el caché en [El caché HTTP: su guía sobre la primera línea de defensa](https://web.dev/articles/http-cache) y [Cómo configurar el codelab de comportamiento para el almacenamiento HTTP](https://web.dev/codelab-http-cache). ## Cómo verificar las respuestas que se almacenan en el caché de Chrome DevTools diff --git a/site/es/docs/lighthouse/performance/uses-optimized-images/index.md b/site/es/docs/lighthouse/performance/uses-optimized-images/index.md index 3994a1a04..d27871abb 100644 --- a/site/es/docs/lighthouse/performance/uses-optimized-images/index.md +++ b/site/es/docs/lighthouse/performance/uses-optimized-images/index.md @@ -18,13 +18,13 @@ Lighthouse recopila todas las imágenes JPEG o BMP de la página, establece el n Hay muchos pasos que puede seguir para optimizar sus imágenes, incluyendo: -- [Usar CDN de imágenes](https://web.dev/image-cdns/) -- [Comprimir imágenes](https://web.dev/use-imagemin-to-compress-images/) -- [Reemplazar de GIF animados con video](https://web.dev/replace-gifs-with-videos/) -- [Carga diferida de imágenes](https://web.dev/use-lazysizes-to-lazyload-images/) -- [Servir imágenes receptivas](https://web.dev/serve-responsive-images/) -- [Servir imágenes con las dimensiones correctas](https://web.dev/serve-images-with-correct-dimensions/) -- [Usar imágenes WebP](https://web.dev/serve-images-webp/) +- [Usar CDN de imágenes](https://web.dev/articles/image-cdns) +- [Comprimir imágenes](https://web.dev/articles/use-imagemin-to-compress-images) +- [Reemplazar de GIF animados con video](https://web.dev/articles/replace-gifs-with-videos) +- [Carga diferida de imágenes](https://web.dev/articles/use-lazysizes-to-lazyload-images) +- [Servir imágenes receptivas](https://web.dev/articles/serve-responsive-images) +- [Servir imágenes con las dimensiones correctas](https://web.dev/articles/serve-images-with-correct-dimensions) +- [Usar imágenes WebP](https://web.dev/articles/serve-images-webp) ## Optimizar imágenes usando herramientas GUI diff --git a/site/es/docs/lighthouse/performance/uses-rel-preconnect/index.md b/site/es/docs/lighthouse/performance/uses-rel-preconnect/index.md index ab98e19be..8bc5db8f6 100644 --- a/site/es/docs/lighthouse/performance/uses-rel-preconnect/index.md +++ b/site/es/docs/lighthouse/performance/uses-rel-preconnect/index.md @@ -59,5 +59,5 @@ Utiliza [un módulo que admite sugerencias de recursos de agentes de usuario](ht - [Código fuente para la auditoría de **preconexión a los orígenes requeridos**](https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/audits/uses-rel-preconnect.js) - [Priorización de recursos: Conseguir que el navegador te ayude](https://developers.google.com/web/fundamentals/performance/resource-prioritization#preconnect) -- [Establece conexiones de red con anticipación para mejorar la velocidad percibida de la página](https://web.dev/preconnect-and-dns-prefetch/) +- [Establece conexiones de red con anticipación para mejorar la velocidad percibida de la página](https://web.dev/articles/preconnect-and-dns-prefetch) - [Tipos de enlace: preconnect](https://developer.mozilla.org/docs/Web/HTML/Link_types/preconnect#Browser_compatibility) diff --git a/site/es/docs/lighthouse/performance/uses-rel-preload/index.md b/site/es/docs/lighthouse/performance/uses-rel-preload/index.md index ffe182474..cd90a0c2e 100644 --- a/site/es/docs/lighthouse/performance/uses-rel-preload/index.md +++ b/site/es/docs/lighthouse/performance/uses-rel-preload/index.md @@ -45,7 +45,7 @@ Declare enlaces de precarga en su HTML para indicar al navegador que descargue l <figure>{% Img src="image/tcFciHGuF3MxnTr1y5ue01OGLBn2/tJLJXH2qXcrDBUfsSAK5.png", alt="Con enlaces de precarga, styles.css y ui.js se solicitan al mismo tiempo que app.js.", width="800", height="478" %} <figcaption> Con los enlaces de precarga, <code>styles.css</code> y <code>ui.js</code> se solicitan al mismo tiempo que <code>app.js</code></figcaption></figure> -Consulte también [Precarga de archivos críticos para mejorar la velocidad de carga](https://web.dev/preload-critical-assets/) para obtener más orientación. +Consulte también [Precarga de archivos críticos para mejorar la velocidad de carga](https://web.dev/articles/preload-critical-assets) para obtener más orientación. ### Compatibilidad del navegador @@ -59,7 +59,7 @@ Consulte la página de [Precargando archivos (Preloading Assets) de Tooling.Repo ### Angular -[Precargue las rutas](https://web.dev/route-preloading-in-angular/) con anticipación para acelerar la navegación. +[Precargue las rutas](https://web.dev/articles/route-preloading-in-angular) con anticipación para acelerar la navegación. ### Magento diff --git a/site/es/docs/lighthouse/performance/uses-text-compression/index.md b/site/es/docs/lighthouse/performance/uses-text-compression/index.md index 9bc521b16..2e3199ad3 100644 --- a/site/es/docs/lighthouse/performance/uses-text-compression/index.md +++ b/site/es/docs/lighthouse/performance/uses-text-compression/index.md @@ -66,7 +66,7 @@ Para comparar los tamaños comprimidos y descomprimidos de una respuesta: 3. Habilite filas de solicitud grandes. Consulte [Usar filas de solicitud grandes](https://developers.google.com/web/tools/chrome-devtools/network/reference#request-rows). 4. Busque en la **columna Tamaño** la respuesta que le interesa. El valor superior es el tamaño comprimido. El valor inferior es el tamaño descomprimido. -Consulte también [Minificar y comprimir cargas útiles de red](https://web.dev/reduce-network-payloads-using-text-compression/). +Consulte también [Minificar y comprimir cargas útiles de red](https://web.dev/articles/reduce-network-payloads-using-text-compression). ## Guía para pilas específicas diff --git a/site/es/docs/lighthouse/pwa/apple-touch-icon/index.md b/site/es/docs/lighthouse/pwa/apple-touch-icon/index.md index c46923614..12a5f6911 100644 --- a/site/es/docs/lighthouse/pwa/apple-touch-icon/index.md +++ b/site/es/docs/lighthouse/pwa/apple-touch-icon/index.md @@ -50,5 +50,5 @@ Para dar una buena experiencia de usuario, asegúrese de que: ## Recursos - [Código fuente para la Auditoría **No proporciona un ícono `apple-touch-icon` válido**](https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/audits/apple-touch-icon.js) -- [Descubra lo que se necesita para ser instalable](https://web.dev/install-criteria/) +- [Descubra lo que se necesita para ser instalable](https://web.dev/articles/install-criteria) - <a href="https://webhint.io/docs/user-guide/hints/hint-apple-touch-icons/" rel="noreferrer">Usar el icono táctil de Apple</a> diff --git a/site/es/docs/lighthouse/pwa/installable-manifest/index.md b/site/es/docs/lighthouse/pwa/installable-manifest/index.md index 0f07f605a..c994e048b 100644 --- a/site/es/docs/lighthouse/pwa/installable-manifest/index.md +++ b/site/es/docs/lighthouse/pwa/installable-manifest/index.md @@ -12,11 +12,11 @@ updated: 2019-09-19 La instalación es un requisito fundamental de las [aplicaciones web progresivas (PWA)](/es/docs/lighthouse/pwa/#instalable). Al pedirles a los usuarios que instalen su PWA, les permite agregarla a sus pantallas de inicio. Los usuarios que agregan aplicaciones a las pantallas de inicio interactúan con esas aplicaciones con más frecuencia. -Un [manifiesto de aplicación web](https://web.dev/add-manifest/) incluye información clave necesaria para que su aplicación se pueda instalar. +Un [manifiesto de aplicación web](https://web.dev/articles/add-manifest) incluye información clave necesaria para que su aplicación se pueda instalar. ## Cómo falla la auditoría Lighthouse del manifiesto de la aplicación web -[Lighthouse](https://developers.google.com/web/tools/lighthouse/) marca las páginas que no tengan un [manifiesto de aplicación web](https://web.dev/add-manifest/) que cumpla con los requisitos mínimos de instalación: +[Lighthouse](https://developers.google.com/web/tools/lighthouse/) marca las páginas que no tengan un [manifiesto de aplicación web](https://web.dev/articles/add-manifest) que cumpla con los requisitos mínimos de instalación: <figure>{% Img src="image/tcFciHGuF3MxnTr1y5ue01OGLBn2/039DlaixA4drrswBzSra.png", alt="Auditoría de Lighthouse que muestra que el usuario no puede instalar la aplicación web desde su pantalla de inicio", width="800", height="98" %}</figure> @@ -34,7 +34,7 @@ Si el manifiesto de una página no incluye las siguientes propiedades, la audito ## Cómo hacer que su PWA sea instalable -Verifique que su aplicación tenga un manifiesto que cumpla con los criterios anteriores. Consulte la colección [instalable](https://web.dev/progressive-web-apps/#haga-que-pueda-instalarse) para obtener más información sobre cómo crear una PWA. +Verifique que su aplicación tenga un manifiesto que cumpla con los criterios anteriores. Consulte la colección [instalable](https://web.dev/articles/progressive-web-apps#haga_que_pueda_instalarse) para obtener más información sobre cómo crear una PWA. ## Cómo comprobar que su PWA es instalable @@ -57,7 +57,7 @@ Otros navegadores tienen diferentes criterios de instalación y para activar el ## Recursos - [El código fuente de la auditoria **El manifiesto de la aplicación web no cumple con los requisitos de instalación**](https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/audits/installable-manifest.js). -- [Agregar un manifiesto de aplicación web](https://web.dev/add-manifest/) +- [Agregar un manifiesto de aplicación web](https://web.dev/articles/add-manifest) - [Descubra lo que se necesita para que sea instalable](/es/docs/lighthouse/pwa/#instalable) - [Manifiesto de la aplicación web](https://developer.mozilla.org/docs/Web/Manifest) - [No usa HTTPS](/es/docs/lighthouse/pwa/is-on-https/) diff --git a/site/es/docs/lighthouse/pwa/is-on-https/index.md b/site/es/docs/lighthouse/pwa/is-on-https/index.md index 0b903db75..bca34da6b 100644 --- a/site/es/docs/lighthouse/pwa/is-on-https/index.md +++ b/site/es/docs/lighthouse/pwa/is-on-https/index.md @@ -12,7 +12,7 @@ Todos los sitios web deben estar protegidos con HTTPS, incluso los que no maneja Una página no puede calificar como una [aplicación web progresiva (PWA)](/es/docs/lighthouse/pwa/#instalable) si no se ejecuta sobre HTTPS; muchas tecnologías centrales de PWA, como los service workers, requieren HTTPS. -Para obtener más información sobre por qué todos los sitios deben protegerse con HTTPS, consulte [Por qué es importante HTTPS](https://web.dev/why-https-matters/). +Para obtener más información sobre por qué todos los sitios deben protegerse con HTTPS, consulte [Por qué es importante HTTPS](https://web.dev/articles/why-https-matters). ## Cómo falla la auditoría Lighthouse para HTTPS diff --git a/site/es/docs/lighthouse/pwa/load-fast-enough-for-pwa/index.md b/site/es/docs/lighthouse/pwa/load-fast-enough-for-pwa/index.md index ce86f174b..709a58fec 100644 --- a/site/es/docs/lighthouse/pwa/load-fast-enough-for-pwa/index.md +++ b/site/es/docs/lighthouse/pwa/load-fast-enough-for-pwa/index.md @@ -21,7 +21,7 @@ Muchos usuarios de su página visitan usando una conexión de red celular lenta. Dos métricas principales afectan la forma en que los usuarios perciben el tiempo de carga: - [First Meaningful Paint: Primer despliegue significativo (FMP)](/docs/lighthouse/performance/first-meaningful-paint/), que mide cuándo el contenido principal de la página aparece visualmente completo -- [Time to Interactive: Tiempo de interacción (TTI)](https://web.dev/tti/), que mide cuándo la página es completamente interactiva +- [Time to Interactive: Tiempo de interacción (TTI)](https://web.dev/articles/tti), que mide cuándo la página es completamente interactiva Por ejemplo, si una página aparece visualmente completa después de 1 segundo, pero el usuario no puede interactuar con ella durante 10 segundos, es probable que los usuarios perciban que el tiempo de carga de la página es de 10 segundos. diff --git a/site/es/docs/lighthouse/pwa/maskable-icon-audit/index.md b/site/es/docs/lighthouse/pwa/maskable-icon-audit/index.md index a75407bf4..fb55c5445 100644 --- a/site/es/docs/lighthouse/pwa/maskable-icon-audit/index.md +++ b/site/es/docs/lighthouse/pwa/maskable-icon-audit/index.md @@ -7,7 +7,7 @@ description: |2- date: 2020-05-06 --- -[Los íconos enmascarables](https://web.dev/maskable-icon/) son un nuevo formato de ícono que garantiza que el ícono de su PWA se vea genial en todos los dispositivos Android. En los dispositivos Android más nuevos, los íconos de PWA que no siguen el formato de ícono enmascarable tienen un fondo blanco. Cuando usted usa un ícono enmascarable, asegura que el ícono ocupe todo el espacio que le proporciona Android. +[Los íconos enmascarables](https://web.dev/articles/maskable-icon) son un nuevo formato de ícono que garantiza que el ícono de su PWA se vea genial en todos los dispositivos Android. En los dispositivos Android más nuevos, los íconos de PWA que no siguen el formato de ícono enmascarable tienen un fondo blanco. Cuando usted usa un ícono enmascarable, asegura que el ícono ocupe todo el espacio que le proporciona Android. ## Cómo falla la auditoría de los íconos enmascarables de Lighthouse @@ -29,7 +29,7 @@ Para aprobar la auditoría: 1. Utilice [Maskable.app Editor](https://maskable.app/editor) para convertir un ícono existente en un ícono enmascarable. -2. Agregue la propiedad `purpose` a uno de los objetos de `icons` en el [manifiesto de su aplicación web](https://web.dev/add-manifest/). Establezca el valor de `purpose` en `maskable` o `any maskable`. Consulte la sección [Valores](https://developer.mozilla.org/docs/Web/Manifest/icons#Values). +2. Agregue la propiedad `purpose` a uno de los objetos de `icons` en el [manifiesto de su aplicación web](https://web.dev/articles/add-manifest). Establezca el valor de `purpose` en `maskable` o `any maskable`. Consulte la sección [Valores](https://developer.mozilla.org/docs/Web/Manifest/icons#Values). ```json/8 { @@ -47,12 +47,12 @@ Para aprobar la auditoría: } ``` -3. Utilice Chrome DevTools para verificar que el ícono enmascarable se muestre correctamente. Consulte [¿Están listos mis íconos actuales?](https://web.dev/maskable-icon/#are-my-current-icons-ready) +3. Utilice Chrome DevTools para verificar que el ícono enmascarable se muestre correctamente. Consulte [¿Están listos mis íconos actuales?](https://web.dev/articles/maskable-icon#are_my_current_icons_ready) ## Recursos - [El código fuente de **El manifiesto no tiene una auditoría de ícono enmascarable**](https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/audits/maskable-icon.js) -- [Soporte de íconos adaptables en PWA con íconos enmascarables](https://web.dev/maskable-icon/) +- [Soporte de íconos adaptables en PWA con íconos enmascarables](https://web.dev/articles/maskable-icon) - [Editor de Maskable.app](https://maskable.app/editor) -- [Agregar un manifiesto de aplicación web](https://web.dev/add-manifest/) +- [Agregar un manifiesto de aplicación web](https://web.dev/articles/add-manifest) - [La propiedad de los `icons` en MDN](https://developer.mozilla.org/docs/Web/Manifest/icons) diff --git a/site/es/docs/lighthouse/pwa/offline-start-url/index.md b/site/es/docs/lighthouse/pwa/offline-start-url/index.md index 7e0614cd7..5afa62272 100644 --- a/site/es/docs/lighthouse/pwa/offline-start-url/index.md +++ b/site/es/docs/lighthouse/pwa/offline-start-url/index.md @@ -6,7 +6,7 @@ date: 2019-05-04 updated: 2020-04-29 --- -El [manifiesto](https://web.dev/add-manifest/) de una [Aplicación web progresiva](https://web.dev/what-are-pwas/) (PWA) debe incluir un `start_url` que indica la URL que se cargará cuando el usuario inicie la aplicación. +El [manifiesto](https://web.dev/articles/add-manifest) de una [Aplicación web progresiva](https://web.dev/articles/what-are-pwas) (PWA) debe incluir un `start_url` que indica la URL que se cargará cuando el usuario inicie la aplicación. Si el navegador no recibe una [respuesta HTTP 200](https://developer.mozilla.org/docs/Web/HTTP/Status#Successful_responses) al acceder a una aplicación desde el `start_url`, la `start_url` no es correcta o la página no es accesible sin conexión. Esto causa problemas a los usuarios que han instalado la aplicación en sus dispositivos. @@ -22,7 +22,7 @@ Si el navegador no recibe una [respuesta HTTP 200](https://developer.mozilla.org {% Partial 'reliable/workbox.njk' %} -1. Si aún no tienes uno, [agrega un manifiesto de aplicación web](https://web.dev/add-manifest/). +1. Si aún no tienes uno, [agrega un manifiesto de aplicación web](https://web.dev/articles/add-manifest). 2. Verifica que el `start_url` en tu manifiesto esté correcto. 3. Agrega un service worker a tu aplicación. 4. Utiliza el service worker para almacenar en caché los archivos localmente. @@ -32,6 +32,6 @@ Consulta [la página actual no responde con un 200 cuando está sin conexión](/ ## Recursos -- [¿Qué es la confiabilidad de la red y cómo se mide?](https://web.dev/network-connections-unreliable/) -- [Agregar un manifiesto de aplicación web](https://web.dev/add-manifest/) +- [¿Qué es la confiabilidad de la red y cómo se mide?](https://web.dev/articles/network-connections-unreliable) +- [Agregar un manifiesto de aplicación web](https://web.dev/articles/add-manifest) - [Workbox: Tu kit de herramientas para service workers de alto nivel](/docs/workbox/) diff --git a/site/es/docs/lighthouse/pwa/service-worker/index.md b/site/es/docs/lighthouse/pwa/service-worker/index.md index 49cb63d8f..f5f30776b 100644 --- a/site/es/docs/lighthouse/pwa/service-worker/index.md +++ b/site/es/docs/lighthouse/pwa/service-worker/index.md @@ -6,13 +6,13 @@ date: 2019-05-04 updated: 2020-06-10 --- -El registro de un [service worker](https://web.dev/service-workers-cache-storage/) es el primer paso para habilitar las funciones clave de la [aplicación web progresiva (PWA)](/es/docs/lighthouse/pwa/#instalable): +El registro de un [service worker](https://web.dev/articles/service-workers-cache-storage) es el primer paso para habilitar las funciones clave de la [aplicación web progresiva (PWA)](/es/docs/lighthouse/pwa/#instalable): - Funcionar sin conexión - Admitir notificaciones emergentes - Se puede instalar en el dispositivo -Obtenga más información en la publicación [Service Workers y API de almacenamiento en caché.](https://web.dev/service-workers-cache-storage/) +Obtenga más información en la publicación [Service Workers y API de almacenamiento en caché.](https://web.dev/articles/service-workers-cache-storage) ## Compatibilidad del navegador @@ -35,14 +35,14 @@ Lighthouse comprueba si el [Protocolo de depuración remota de Chrome](https://g El registro de un trabajador del servicio implica solo unas pocas líneas de código, pero la única razón por la que usaría un service worker es para hacer posible la implementación de una de las características de la PWA descritas anteriormente. La implementación real de esas características requiere más trabajo: - Para saber cómo almacenar archivos en caché para su uso sin conexión, consulte la publicación [¿Qué es la confiabilidad de la red y cómo se mide?](https://web.dev/network-connections-unreliable). -- Para saber cómo hacer que su aplicación sea instalable, consulte el laboratorio de códigos [Hacerlo instalable](https://web.dev/codelab-make-installable/). +- Para saber cómo hacer que su aplicación sea instalable, consulte el laboratorio de códigos [Hacerlo instalable](https://web.dev/articles/codelab-make-installable). - Para saber cómo habilitar las notificaciones emergentes, consulte [Añadir notificaciones emergentes a una página Web](https://codelabs.developers.google.com/codelabs/push-notifications) de Google. ## Recursos - [Código fuente para la auditoría **No registra un service worker que controla la página y el `start_url`**](https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/audits/service-worker.js) - [Service workers: una introducción](https://developers.google.com/web/fundamentals/primers/service-workers) -- [Service workers y la API de almacenamiento en caché](https://web.dev/service-workers-cache-storage/) -- [¿Qué es la confiabilidad de la red y cómo se mide?](https://web.dev/network-connections-unreliable/) -- [Hágalo instalable](https://web.dev/codelab-make-installable/) +- [Service workers y la API de almacenamiento en caché](https://web.dev/articles/service-workers-cache-storage) +- [¿Qué es la confiabilidad de la red y cómo se mide?](https://web.dev/articles/network-connections-unreliable) +- [Hágalo instalable](https://web.dev/articles/codelab-make-installable) - [Agregar notificaciones emergentes a una aplicación web](https://codelabs.developers.google.com/codelabs/push-notifications) diff --git a/site/es/docs/lighthouse/pwa/splash-screen/index.md b/site/es/docs/lighthouse/pwa/splash-screen/index.md index 0003c5c13..16194062e 100644 --- a/site/es/docs/lighthouse/pwa/splash-screen/index.md +++ b/site/es/docs/lighthouse/pwa/splash-screen/index.md @@ -20,7 +20,7 @@ Una pantalla de presentación personalizada hace que su [aplicación web progres ## Cómo crear una pantalla de bienvenida personalizada -Chrome para Android muestra automáticamente su pantalla de presentación personalizada siempre que cumpla con los siguientes requisitos en el [manifiesto de su aplicación web](https://web.dev/add-manifest/): +Chrome para Android muestra automáticamente su pantalla de presentación personalizada siempre que cumpla con los siguientes requisitos en el [manifiesto de su aplicación web](https://web.dev/articles/add-manifest): - La propiedad `name` se configura como el nombre de su PWA. - La propiedad `background_color` se establece en un valor de color CSS válido. diff --git a/site/es/docs/lighthouse/pwa/themed-omnibox/index.md b/site/es/docs/lighthouse/pwa/themed-omnibox/index.md index 6a9c837b0..0e9d51a30 100644 --- a/site/es/docs/lighthouse/pwa/themed-omnibox/index.md +++ b/site/es/docs/lighthouse/pwa/themed-omnibox/index.md @@ -20,7 +20,7 @@ En el momento de redactar este artículo, el uso de temas para la barra de direc <figure>{% Img src="image/tcFciHGuF3MxnTr1y5ue01OGLBn2/YadFSuw8denjl1hhnvFs.png", alt="La auditoría de Lighthouse que muestra que la barra de direcciones no está relacionada con los colores de la página", width="800", height="98" %}</figure> -La auditoría falla si Lighthouse no encuentra una meta tag `theme-color` en el HTML de la página y una propiedad `theme_color` en el [manifiesto de la aplicación web](https://web.dev/add-manifest/). +La auditoría falla si Lighthouse no encuentra una meta tag `theme-color` en el HTML de la página y una propiedad `theme_color` en el [manifiesto de la aplicación web](https://web.dev/articles/add-manifest). Tenga en cuenta que Lighthouse no verifica si los valores son valores de color CSS válidos. @@ -47,7 +47,7 @@ Obtenga más información sobre la meta tag `theme-color` en <a href="https://de ### Paso 2: Agregue la propiedad `theme_color` al manifiesto de su aplicación web -La propiedad `theme_color` en el manifiesto de su aplicación web garantiza que la barra de direcciones presente la marca cuando un usuario inicia su PWA desde la pantalla de inicio. A diferencia de la meta-tag `theme-color`, solo necesita definir esto una vez, en el [manifiesto](https://web.dev/add-manifest/). Establezca la propiedad en cualquier valor de color CSS válido: +La propiedad `theme_color` en el manifiesto de su aplicación web garantiza que la barra de direcciones presente la marca cuando un usuario inicia su PWA desde la pantalla de inicio. A diferencia de la meta-tag `theme-color`, solo necesita definir esto una vez, en el [manifiesto](https://web.dev/articles/add-manifest). Establezca la propiedad en cualquier valor de color CSS válido: ```html/1 { @@ -61,5 +61,5 @@ El navegador establecerá el color de la barra de direcciones de cada página de ## Recursos - [Código fuente para la auditoría **No establece un color de tema para la barra de direcciones**](https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/audits/themed-omnibox.js) -- [Agregar un manifiesto de aplicación web](https://web.dev/add-manifest/) +- [Agregar un manifiesto de aplicación web](https://web.dev/articles/add-manifest) - [Support for <code>theme-color</code> in Chrome 39 for Android](https://developers.google.com/web/updates/2014/11/Support-for-theme-color-in-Chrome-39-for-Android) diff --git a/site/es/docs/privacy-sandbox/attribution-reporting/index.md b/site/es/docs/privacy-sandbox/attribution-reporting/index.md index b0bc5f32b..c57d68cee 100644 --- a/site/es/docs/privacy-sandbox/attribution-reporting/index.md +++ b/site/es/docs/privacy-sandbox/attribution-reporting/index.md @@ -48,7 +48,7 @@ Hoy en día, la evaluación de conversiones publicitarias depende a menudo de la La API de informes de atribuciones permite medir dos eventos que están vinculados entre sí: un evento en el sitio web de un editor, como un usuario que ve o hace clic en un anuncio, con una conversión posterior en el sitio de un anunciante. -Esta API es compatible con la evaluación de atribuciones de conversiones a través de clics (disponible en la primera implementación de esta API, actualmente en la [prueba de origen](https://web.dev/conversion-measurement/#browser-support)) y la evaluación de atribuciones a través de visualizaciones ([consulte explicación pública](https://github.com/WICG/conversion-measurement-api/blob/main/event_attribution_reporting.md)). +Esta API es compatible con la evaluación de atribuciones de conversiones a través de clics (disponible en la primera implementación de esta API, actualmente en la [prueba de origen](/docs/privacy-sandbox/attribution-reporting/#browser-support)) y la evaluación de atribuciones a través de visualizaciones ([consulte explicación pública](https://github.com/WICG/conversion-measurement-api/blob/main/event_attribution_reporting.md)). La API ofrece dos tipos de informes de atribuciones que se pueden utilizar para diferentes casos de uso: @@ -67,8 +67,8 @@ La API ofrece dos tipos de informes de atribuciones que se pueden utilizar para - [Introducción a los Informes de atribuciones (Evaluación de las conversiones)](/docs/privacy-sandbox/attribution-reporting-introduction) - [Explicaciones técnicas sobre la API](https://github.com/WICG/conversion-measurement-api/) -- (⚠️ obsoleto) [Una forma más privada de medir las conversiones de los anuncios](https://web.dev/conversion-measurement/) : descripción general de la primera iteración de esta API para desarrolladores web +- (⚠️ obsoleto) [Una forma más privada de medir las conversiones de los anuncios](/docs/privacy-sandbox/attribution-reporting/) : descripción general de la primera iteración de esta API para desarrolladores web - (⚠️ obsoleto) [Una forma más privada de medir las conversiones de los anuncios - Video](https://www.youtube.com/watch?v=jcDfOoWwZcM): demostración de la primera iteración de esta API (solo clics) -- (⚠️ obsoleto) [Uso de la API para Evaluar conversiones de eventos](https://web.dev/using-conversion-measurement/): cómo experimentar con la primera iteración de esta API para desarrolladores web +- (⚠️ obsoleto) [Uso de la API para Evaluar conversiones de eventos](/docs/privacy-sandbox/attribution-reporting/): cómo experimentar con la primera iteración de esta API para desarrolladores web - [Conociendo a detalle la iniciativa de Google, Privacy Sandbox](https://web.dev/digging-into-the-privacy-sandbox) - [Depurar la API con Chrome DevTools](/blog/new-in-devtools-93/#attribution-reporting) diff --git a/site/es/docs/privacy-sandbox/first-party-sets/index.md b/site/es/docs/privacy-sandbox/first-party-sets/index.md index 404d422bf..fe7d38fc2 100644 --- a/site/es/docs/privacy-sandbox/first-party-sets/index.md +++ b/site/es/docs/privacy-sandbox/first-party-sets/index.md @@ -13,7 +13,7 @@ authors: ## Estado de la implementación -- [En la prueba de origen](https://web.dev/origin-trials/) Chrome 89 a 93. +- [En la prueba de origen](/docs/web-platform/origin-trials/) Chrome 89 a 93. - [Regístrese para la prueba de origen](/origintrials/#/view_trial/988540118207823873). - [Estado de la plataforma Chrome](https://chromestatus.com/feature/5640066519007232). - [Proyectos de Chromium](https://www.chromium.org/updates/first-party-sets). diff --git a/site/es/docs/privacy-sandbox/floc/index.md b/site/es/docs/privacy-sandbox/floc/index.md index 84d41ee53..d81fdaffa 100644 --- a/site/es/docs/privacy-sandbox/floc/index.md +++ b/site/es/docs/privacy-sandbox/floc/index.md @@ -37,7 +37,7 @@ Posteriormente, la plataforma publicitaria puede usar estos datos para seleccion ## ¿Cómo funciona FLoC? -[¿Qué es FLoC?](https://web.dev/floc/#how-does-floc-work) proporciona una explicación simple, paso a paso, de cómo funciona FloC. +[¿Qué es FLoC?](https://web.dev/articles/floc#how_does_floc_work) proporciona una explicación simple, paso a paso, de cómo funciona FloC. En el siguiente diagrama se muestra un ejemplo sobre las diferentes funciones implicadas en la selección y publicación de un anuncio relevante mediante el uso de FLoC. diff --git a/site/es/docs/privacy-sandbox/glossary/index.md b/site/es/docs/privacy-sandbox/glossary/index.md index a646b4f36..42c5ec358 100644 --- a/site/es/docs/privacy-sandbox/glossary/index.md +++ b/site/es/docs/privacy-sandbox/glossary/index.md @@ -124,7 +124,7 @@ Se refiere al origen de una solicitud, incluido el esquema y el nombre del servi ## Prueba de origen {: #origin-trial } -Las pruebas de origen brindan acceso a una función nueva o experimental, esto con el fin de crear funciones que los usuarios pueden probar durante un tiempo limitado antes de que la función esté disponible para todos. Cuando Chrome ofrece una prueba de origen para una función, [es posible registrar un origen](#origin) para la prueba a fin de habilitar la función para todos los usuarios en ese origen, sin requerir que los usuarios cambien ninguna marca o cambien a una versión alternativa de Chrome (aunque es posible que necesiten hacerlo). potenciar). Las pruebas de origen permiten a los desarrolladores crear demostraciones y prototipos utilizando nuevas funciones. Estas pruebas también ayudan a los ingenieros de Chrome a comprender cómo se utilizan las nuevas funciones y cómo pueden interactuar con otras tecnologías web. Para obtener más información, consulta: [Introducción a las pruebas de origen de Chrome](https://web.dev/origin-trials/). +Las pruebas de origen brindan acceso a una función nueva o experimental, esto con el fin de crear funciones que los usuarios pueden probar durante un tiempo limitado antes de que la función esté disponible para todos. Cuando Chrome ofrece una prueba de origen para una función, [es posible registrar un origen](#origin) para la prueba a fin de habilitar la función para todos los usuarios en ese origen, sin requerir que los usuarios cambien ninguna marca o cambien a una versión alternativa de Chrome (aunque es posible que necesiten hacerlo). potenciar). Las pruebas de origen permiten a los desarrolladores crear demostraciones y prototipos utilizando nuevas funciones. Estas pruebas también ayudan a los ingenieros de Chrome a comprender cómo se utilizan las nuevas funciones y cómo pueden interactuar con otras tecnologías web. Para obtener más información, consulta: [Introducción a las pruebas de origen de Chrome](/docs/web-platform/origin-trials/). ## Superficie pasiva {: #passive-surface } diff --git a/site/es/docs/privacy-sandbox/overview/index.md b/site/es/docs/privacy-sandbox/overview/index.md index e2e65a485..fba276764 100644 --- a/site/es/docs/privacy-sandbox/overview/index.md +++ b/site/es/docs/privacy-sandbox/overview/index.md @@ -35,7 +35,7 @@ A continuación se enumeran las principales propuestas desarrolladas por el equi ### Protecciones propias -- [**Cambios en las cookies del mismo sitio**](https://web.dev/samesite-cookies-explained/): aseguran los sitios marcando explícitamente sus cookies entre sitios. +- [**Cambios en las cookies del mismo sitio**](https://web.dev/articles/samesite-cookies-explained): aseguran los sitios marcando explícitamente sus cookies entre sitios. - [**Conjuntos propios**](/docs/privacy-sandbox/first-party-sets): permiten que los nombres de dominio relacionados, propiedad de la misma entidad, se declaren como pertenecientes a la primera parte. ### Detección de fraudes @@ -45,7 +45,7 @@ A continuación se enumeran las principales propuestas desarrolladas por el equi ### Limitar la recopilación de datos - [**Presupuesto de privacidad**](https://www.youtube.com/watch?v=0STgfjSA6T8): permite que los sitios web obtengan información sobre el navegador o el dispositivo de un usuario, pero permite que el navegador establezca una cuota sobre la cantidad total de información a la que puede acceder un sitio, de modo que no se pueda identificar al usuario. -- [**Consejos para el cliente Usuario-agente**](https://web.dev/user-agent-client-hints/): La cadena [Usuario-agente](https://developer.mozilla.org/docs/Web/HTTP/Headers/User-Agent) (UA) es una importante superficie pasiva de [huellas digitales](https://w3c.github.io/fingerprinting-guidance/#passive), además de ser difícil de procesar. Las sugerencias del cliente permiten que los desarrolladores soliciten activamente solo la información que necesitan sobre el dispositivo o las condiciones del usuario, en vez de que necesiten analizar estos datos a partir de la cadena Usuario-agente. +- [**Consejos para el cliente Usuario-agente**](https://web.dev/articles/user-agent-client-hints): La cadena [Usuario-agente](https://developer.mozilla.org/docs/Web/HTTP/Headers/User-Agent) (UA) es una importante superficie pasiva de [huellas digitales](https://w3c.github.io/fingerprinting-guidance/#passive), además de ser difícil de procesar. Las sugerencias del cliente permiten que los desarrolladores soliciten activamente solo la información que necesitan sobre el dispositivo o las condiciones del usuario, en vez de que necesiten analizar estos datos a partir de la cadena Usuario-agente. - [**Gnatcatcher**](https://github.com/bslassey/ip-blindness): Limita la capacidad de identificar usuarios individuales accediendo a su dirección IP. La propuesta tiene dos partes: [<strong data-md="">Willful IP Blindness</strong>](https://github.com/bslassey/ip-blindness/blob/master/willful_ip_blindness.md) proporciona una forma para que los sitios web informen a los navegadores que no están conectando las direcciones IP con los usuarios, y <a href="https://github.com/bslassey/ip-blindness/blob/master/near_path_nat.md" data-md-type=" link "><strong data-md-type=" double_emphasis ">Near-path NAT</strong></a> permite que grupos de usuarios envíen su tráfico a través del mismo servidor privatizador, ocultando de forma efectiva sus direcciones IP del host de un sitio. Gnatcatcher también garantiza que los sitios que necesiten acceder a las direcciones IP con fines legítimos, como la prevención de abusos, puedan hacerlo, sujetos a certificación y auditoría. ### Identidad @@ -90,10 +90,10 @@ La explicación de la propuesta de la API necesitan comentarios, en particular p ### Artículos y videos para desarrolladores web - [Conociendo a detalle la iniciativa de Google, Privacy Sandbox](https://web.dev/digging-into-the-privacy-sandbox) -- [Explicación de las cookies de SameSite](https://web.dev/samesite-cookies-explained/) +- [Explicación de las cookies de SameSite](https://web.dev/articles/samesite-cookies-explained) - [Introducción a los Trust Tokens](https://web.dev/trust-tokens) -- [Una forma más privada de evaluar las conversiones de los anuncios](https://web.dev/conversion-measurement/) -- [¿Qué es FLoC?](https://web.dev/floc/) +- [Una forma más privada de evaluar las conversiones de los anuncios](/docs/privacy-sandbox/attribution-reporting/) +- [¿Qué es FLoC?](https://web.dev/articles/floc) - [Presentación del presupuesto de privacidad](https://www.youtube.com/watch?v=0STgfjSA6T8) ### Principios y conceptos en los que se basan las propuestas diff --git a/site/es/docs/privacy-sandbox/status/index.md b/site/es/docs/privacy-sandbox/status/index.md index 779dfe90a..ee0ebab72 100644 --- a/site/es/docs/privacy-sandbox/status/index.md +++ b/site/es/docs/privacy-sandbox/status/index.md @@ -15,7 +15,7 @@ authors: *Anteriormente conocido como Evaluación de las conversiones.* -- [Prueba de origen actual](https://web.dev/origin-trials/): desde Chrome 86, [ahora ampliado](https://groups.google.com/u/1/a/chromium.org/g/attribution-reporting-api-dev/c/ZKf9T8sRqAM) a Chrome 93. +- [Prueba de origen actual](/docs/web-platform/origin-trials/): desde Chrome 86, [ahora ampliado](https://groups.google.com/u/1/a/chromium.org/g/attribution-reporting-api-dev/c/ZKf9T8sRqAM) a Chrome 93. - [Regístrese para la prueba de origen](/origintrials/#/view_trial/3411476717733150721). - [Demostración](https://goo.gle/demo-event-level-conversion-measurement-api). - [Estado de la plataforma Chrome](https://www.chromestatus.com/features/6412002824028160). @@ -31,25 +31,25 @@ Ver [Estado](/docs/privacy-sandbox/attribution-reporting-introduction/#status). - [Informes de atribuciones (evaluación de las conversiones)](/docs/privacy-sandbox/attribution-reporting) - [Introducción a los Informes de atribuciones (evaluación de las conversiones)](/docs/privacy-sandbox/attribution-reporting-introduction) - [Explicaciones técnicas sobre la API](https://github.com/WICG/conversion-measurement-api/) -- (⚠️ obsoleto) [Una forma más privada de medir las conversiones de los anuncios](https://web.dev/conversion-measurement/): descripción general de la primera iteración de esta API para desarrolladores web +- (⚠️ obsoleto) [Una forma más privada de medir las conversiones de los anuncios](/docs/privacy-sandbox/attribution-reporting/): descripción general de la primera iteración de esta API para desarrolladores web - (⚠️ obsoleto) [Una forma más privada de medir las conversiones de los anuncios - Video](https://www.youtube.com/watch?v=jcDfOoWwZcM): demostración de la primera iteración de esta API (solo clics) -- (⚠️ obsoleto) [Uso de la API para Evaluar conversiones de eventos](https://web.dev/using-conversion-measurement/): cómo experimentar con la primera iteración de esta API para desarrolladores web +- (⚠️ obsoleto) [Uso de la API para Evaluar conversiones de eventos](/docs/privacy-sandbox/attribution-reporting/): cómo experimentar con la primera iteración de esta API para desarrolladores web - [Conociendo a detalle la iniciativa de Google, Privacy Sandbox](https://web.dev/digging-into-the-privacy-sandbox) ## Los Trust Tokens -- [Prueba de origen actual](https://web.dev/origin-trials/): desde Chrome 84, [ahora ampliada](https://groups.google.com/a/chromium.org/g/blink-dev/c/-W90wVkS0Ks/m/Jfh5-ZWpAQAJ) a Chrome 94. +- [Prueba de origen actual](/docs/web-platform/origin-trials/): desde Chrome 84, [ahora ampliada](https://groups.google.com/a/chromium.org/g/blink-dev/c/-W90wVkS0Ks/m/Jfh5-ZWpAQAJ) a Chrome 94. - [Regístrese para la prueba de origen](/origintrials/#/view_trial/2479231594867458049). - [Demostración](https://trust-token-demo.glitch.me/). - [Estado de la plataforma Chrome](https://www.chromestatus.com/feature/5078049450098688). - [El estado de Blink](https://groups.google.com/a/chromium.org/g/blink-dev/search?q=trust%tokens). - [GitHub](https://github.com/WICG/trust-token-api): consulte los [problemas](https://github.com/WICG/trust-token-api/issues) para conocer las preguntas y la discusión sobre la API. - [Integración con las Chrome DevTools](https://developers.google.com/web/updates/2021/01/devtools?utm_source=devtools#trust-token). -- Obtener más información: [Introducción a los Trust Tokens](https://web.dev/trust-tokens/). +- Obtener más información: [Introducción a los Trust Tokens](https://web.dev/articles/trust-tokens). ## Conjuntos propios -- [Prueba de origen actual](https://web.dev/origin-trials/): Chrome 84 a 91. +- [Prueba de origen actual](/docs/web-platform/origin-trials/): Chrome 84 a 91. - [Regístrese para la prueba de origen](/origintrials/#/view_trial/988540118207823873). - [Estado de la plataforma Chrome](https://chromestatus.com/feature/5640066519007232). - [El estado de Blink](https://groups.google.com/a/chromium.org/g/blink-dev/search?q=first-party%20sets). @@ -64,7 +64,7 @@ Ver [Estado](/docs/privacy-sandbox/attribution-reporting-introduction/#status). - Se está examinando la [propuesta de la API](https://github.com/WICG/floc) con [WICG](https://www.w3.org/community/wicg/) y los grupos de interés. - [GitHub](https://github.com/WICG/floc): consulte los [problemas](https://github.com/WICG/floc/issues) para conocer las preguntas y la discusión sobre la API. - [Estado de la plataforma Chrome](https://www.chromestatus.com/features/5710139774468096). -- Obtener más información: [¿Qué es FLoC?](https://web.dev/floc/) +- Obtener más información: [¿Qué es FLoC?](https://web.dev/articles/floc) ## FLEDGE @@ -91,7 +91,7 @@ Es un descendiente de [TURTLEDOVE](https://github.com/WICG/turtledove). ### Pruebas de origen -- [Introducción a las pruebas de origen de Chrome](https://web.dev/origin-trials/) +- [Introducción a las pruebas de origen de Chrome](/docs/web-platform/origin-trials/) - [¿Qué son las pruebas de origen de terceros?](https://web.dev/third-party-origin-trials) - [Diagnóstico de los problemas en las pruebas de origen de Chrome](/blog/origin-trial-troubleshooting/) - [Guía de las pruebas de origen para desarrolladores web](https://github.com/GoogleChrome/OriginTrials/blob/gh-pages/developer-guide.md) diff --git a/site/es/docs/privacy-sandbox/trust-tokens/index.md b/site/es/docs/privacy-sandbox/trust-tokens/index.md index d00e8cdad..b542a4b65 100644 --- a/site/es/docs/privacy-sandbox/trust-tokens/index.md +++ b/site/es/docs/privacy-sandbox/trust-tokens/index.md @@ -11,7 +11,7 @@ authors: ## Estado de la implementación -- [En la prueba de origen](https://web.dev/origin-trials/) Chrome 84 a 94. +- [En la prueba de origen](/docs/web-platform/origin-trials/) Chrome 84 a 94. - [Regístrese para la prueba](/origintrials/#/view_trial/2479231594867458049). - [Demostración](https://trust-token-demo.glitch.me/). - [Integración con las Chrome DevTools](https://developers.google.com/web/updates/2021/01/devtools?utm_source=devtools#trust-token). @@ -62,7 +62,7 @@ En este ejemplo, el sitio web de un editor quiere verificar si un usuario es un 12. El sitio del editor muestra el anuncio. 13. Esto se cuenta como una impresión en la visualización del anuncio. -{% Aside %} Para obtener más detalles sobre las llamadas de JavaScript que se mencionaron en este ejemplo, consulte el [Ejemplo acerca del uso de la API](https://web.dev/trust-tokens/#sample-api-usage). {% endAside %} +{% Aside %} Para obtener más detalles sobre las llamadas de JavaScript que se mencionaron en este ejemplo, consulte el [Ejemplo acerca del uso de la API](https://web.dev/articles/trust-tokens#sample_api_usage). {% endAside %} --- @@ -78,6 +78,6 @@ En este ejemplo, el sitio web de un editor quiere verificar si un usuario es un ## Obtener más información - [Explicación técnica sobre la API Trust Token](https://github.com/dvorak42/trust-token-api) -- [Introducción a los Trust Tokens](https://web.dev/trust-tokens/): descripción general para los desarrolladores web +- [Introducción a los Trust Tokens](https://web.dev/articles/trust-tokens): descripción general para los desarrolladores web - [Introducción a las pruebas de origen de Chrome](https://web.dev/origin-trials) - [Conociendo a detalle la iniciativa de Google, Privacy Sandbox](https://web.dev/digging-into-the-privacy-sandbox) diff --git a/site/fr/docs/privacy-sandbox/attribution-reporting/index.md b/site/fr/docs/privacy-sandbox/attribution-reporting/index.md index 4aadcddf4..bb26ca884 100644 --- a/site/fr/docs/privacy-sandbox/attribution-reporting/index.md +++ b/site/fr/docs/privacy-sandbox/attribution-reporting/index.md @@ -50,7 +50,7 @@ Aujourd'hui, la mesure des conversions publicitaires repose souvent sur des [coo L'API Attribution Reporting permet de mesurer deux événements associés entre eux : un événement sur le site web d'un éditeur, tel qu'un internaute qui consulte ou clique sur une annonce, avec une conversion ultérieure sur le site d'un annonceur. -Cette API prend en charge la mesure de l'attribution des conversions après clic (disponible dans la première implémentation de cette API, actuellement en [phase d'évaluation](https://web.dev/conversion-measurement/#browser-support)) et la mesure de l'attribution après affichage ([voir l'explication publique](https://github.com/WICG/conversion-measurement-api/blob/main/event_attribution_reporting_views.md)). +Cette API prend en charge la mesure de l'attribution des conversions après clic (disponible dans la première implémentation de cette API, actuellement en [phase d'évaluation](/docs/privacy-sandbox/attribution-reporting/#browser-support)) et la mesure de l'attribution après affichage ([voir l'explication publique](https://github.com/WICG/conversion-measurement-api/blob/main/event_attribution_reporting_views.md)). L'API propose deux types de rapports d'attribution pouvant être utilisés pour différents cas d'utilisation : @@ -69,8 +69,8 @@ L'API propose deux types de rapports d'attribution pouvant être utilisés pour - [Introduction à la création de rapports sur l'attribution (mesure des conversions)](/docs/privacy-sandbox/attribution-reporting-introduction) - [Explications techniques de l'API](https://github.com/WICG/conversion-measurement-api/) -- (⚠️ obsolète) [Un moyen plus privé de mesurer les conversions publicitaires](https://web.dev/conversion-measurement/) : aperçu de la première itération de cette API pour les développeurs web +- (⚠️ obsolète) [Un moyen plus privé de mesurer les conversions publicitaires](/docs/privacy-sandbox/attribution-reporting/) : aperçu de la première itération de cette API pour les développeurs web - (⚠️ obsolète) [Un moyen plus privé de mesurer les conversions publicitaires - Vidéo](https://www.youtube.com/watch?v=jcDfOoWwZcM) : démo de la première itération de cette API (clics uniquement) -- (⚠️ obsolète) [Utilisation de l'API Event Conversion Measurement](https://web.dev/using-conversion-measurement/) : comment expérimenter la première itération de cette API pour les développeurs web +- (⚠️ obsolète) [Utilisation de l'API Event Conversion Measurement](/docs/privacy-sandbox/attribution-reporting/) : comment expérimenter la première itération de cette API pour les développeurs web - [Explications détaillées de Privacy Sandbox](https://web.dev/digging-into-the-privacy-sandbox) - [Déboguer l'API avec les outils pour les développeurs Chrome](/blog/new-in-devtools-93/#attribution-reporting) diff --git a/site/fr/docs/privacy-sandbox/first-party-sets/index.md b/site/fr/docs/privacy-sandbox/first-party-sets/index.md index f98e5f284..b439ef486 100644 --- a/site/fr/docs/privacy-sandbox/first-party-sets/index.md +++ b/site/fr/docs/privacy-sandbox/first-party-sets/index.md @@ -13,7 +13,7 @@ authors: ## État de mise en œuvre -- [En essai d'origine](https://web.dev/origin-trials/) Chrome 89 à 93. +- [En essai d'origine](/docs/web-platform/origin-trials/) Chrome 89 à 93. - [S'inscrire à un essai d'origine](/origintrials/#/view_trial/988540118207823873). - [État de la plate-forme Chrome](https://chromestatus.com/feature/5640066519007232). - [Projets Chromium](https://www.chromium.org/updates/first-party-sets). diff --git a/site/fr/docs/privacy-sandbox/floc/index.md b/site/fr/docs/privacy-sandbox/floc/index.md index 54e9a8b4d..34cf7a607 100644 --- a/site/fr/docs/privacy-sandbox/floc/index.md +++ b/site/fr/docs/privacy-sandbox/floc/index.md @@ -37,7 +37,7 @@ Par la suite, la plate-forme publicitaire peut utiliser ces données pour sélec ## Comment fonctionne la méthode FLoC ? -L'article [Qu'est-ce que la méthode FLoC ?](https://web.dev/floc/#how-does-floc-work) fournit une explication simple, étape par étape, de son fonctionnement. +L'article [Qu'est-ce que la méthode FLoC ?](https://web.dev/articles/floc#how_does_floc_work) fournit une explication simple, étape par étape, de son fonctionnement. Le diagramme ci-dessous montre un exemple des différents rôles dans la sélection et la diffusion d'une annonce pertinente à l'aide de la méthode FLoC. diff --git a/site/fr/docs/privacy-sandbox/glossary/index.md b/site/fr/docs/privacy-sandbox/glossary/index.md index 8abd3d239..16aac1fe1 100644 --- a/site/fr/docs/privacy-sandbox/glossary/index.md +++ b/site/fr/docs/privacy-sandbox/glossary/index.md @@ -120,7 +120,7 @@ L'origine d'une requête, y compris le schéma et le nom du serveur, mais aucune ## Essai d'origine {: #origin-trial} -Les essais d'origine donnent accès à une fonctionnalité nouvelle ou expérimentale, afin de créer des fonctionnalités que les utilisateurs peuvent essayer pendant une durée limitée avant qu'elle ne soit mise à la disposition de tous. Lorsque Chrome propose un essai d'origine pour une fonctionnalité, une [origine](#origin) peut être enregistrée pour l'essai afin d'activer la fonctionnalité pour tous les utilisateurs de cette origine, sans les obliger à basculer vers une version alternative de Chrome (bien qu'ils puissent nécessiter une mise à niveau). Les essais d'origine permettent aux développeurs de créer des démos et des prototypes à l'aide de nouvelles fonctionnalités. Les essais aident également les ingénieurs Chrome à comprendre comment les nouvelles fonctionnalités sont utilisées et comment elles peuvent interagir avec d'autres technologies Web. Pour en savoir plus : [Getting started with Chrome's origin trials](https://web.dev/origin-trials/). +Les essais d'origine donnent accès à une fonctionnalité nouvelle ou expérimentale, afin de créer des fonctionnalités que les utilisateurs peuvent essayer pendant une durée limitée avant qu'elle ne soit mise à la disposition de tous. Lorsque Chrome propose un essai d'origine pour une fonctionnalité, une [origine](#origin) peut être enregistrée pour l'essai afin d'activer la fonctionnalité pour tous les utilisateurs de cette origine, sans les obliger à basculer vers une version alternative de Chrome (bien qu'ils puissent nécessiter une mise à niveau). Les essais d'origine permettent aux développeurs de créer des démos et des prototypes à l'aide de nouvelles fonctionnalités. Les essais aident également les ingénieurs Chrome à comprendre comment les nouvelles fonctionnalités sont utilisées et comment elles peuvent interagir avec d'autres technologies Web. Pour en savoir plus : [Getting started with Chrome's origin trials](/docs/web-platform/origin-trials/). ## Surface passive {: #surface-passive } diff --git a/site/fr/docs/privacy-sandbox/overview/index.md b/site/fr/docs/privacy-sandbox/overview/index.md index 0e8f03573..6a0e4509e 100644 --- a/site/fr/docs/privacy-sandbox/overview/index.md +++ b/site/fr/docs/privacy-sandbox/overview/index.md @@ -35,7 +35,7 @@ Les principales propositions développées par l'équipe Chrome sont répertori ### Protections propriétaires -- [**Modifications des cookies SameSite**](https://web.dev/samesite-cookies-explained/) : sécurisez les sites en marquant explicitement vos cookies intersites. +- [**Modifications des cookies SameSite**](https://web.dev/articles/samesite-cookies-explained) : sécurisez les sites en marquant explicitement vos cookies intersites. - [Les **ensembles propriétaires**](/docs/privacy-sandbox/first-party-sets) : permettent aux noms de domaine associés détenus par la même entité de se déclarer comme tels. ### Détection de fraude @@ -45,7 +45,7 @@ Les principales propositions développées par l'équipe Chrome sont répertori ### Limiter la collecte de données - [**Budget de confidentialité**](https://www.youtube.com/watch?v=0STgfjSA6T8) : permet aux sites web d'obtenir des informations sur le navigateur ou l'appareil d'un utilisateur, mais permet au navigateur de définir un quota sur la quantité totale d'informations auxquelles un site peut accéder, afin qu'un utilisateur ne puisse pas être identifié. -- [**User-Agent Client Hints**](https://web.dev/user-agent-client-hints/) : la [chaîne User-Agent](https://developer.mozilla.org/docs/Web/HTTP/Headers/User-Agent) (UA) est une [surface de fingerprinting](https://w3c.github.io/fingerprinting-guidance/#passive) passive importante, tout en étant difficile à traiter. Les Client Hints permettent aux développeurs de demander activement uniquement les informations dont ils ont besoin sur l'appareil de l'utilisateur ou les conditions, plutôt que d'avoir à analyser ces données à partir de la chaîne User-Agent. +- [**User-Agent Client Hints**](https://web.dev/articles/user-agent-client-hints) : la [chaîne User-Agent](https://developer.mozilla.org/docs/Web/HTTP/Headers/User-Agent) (UA) est une [surface de fingerprinting](https://w3c.github.io/fingerprinting-guidance/#passive) passive importante, tout en étant difficile à traiter. Les Client Hints permettent aux développeurs de demander activement uniquement les informations dont ils ont besoin sur l'appareil de l'utilisateur ou les conditions, plutôt que d'avoir à analyser ces données à partir de la chaîne User-Agent. - [**Gnatcatcher**](https://github.com/bslassey/ip-blindness) : limitez la possibilité d'identifier les utilisateurs individuels en accédant à leur adresse IP. Il y a deux parties à la proposition : [**Willful IP Blindness**](https://github.com/bslassey/ip-blindness/blob/master/willful_ip_blindness.md) fournit un moyen pour les sites web d'informer les navigateurs qu'ils ne connectent pas les adresses IP avec les utilisateurs, et [**Near-path NAT**](https://github.com/bslassey/ip-blindness/blob/master/near_path_nat.md) permet à des groupes d'utilisateurs d'envoyer leur trafic via le même serveur de privatisation, cachant efficacement leurs adresses IP à partir d'un hébergeur de site. Gnatcatcher garantit également que les sites nécessitant un accès aux adresses IP à des fins légitimes, telles que la prévention des abus peuvent le faire, sous réserve de certification et d'audit. ### Identité @@ -90,10 +90,10 @@ Il est nécessaire d'obtenir des retours d'information concernant les explicatio ### Articles et vidéos pour les développeurs web - [Explications détaillées de Privacy Sandbox](https://web.dev/digging-into-the-privacy-sandbox) -- [Cookies SameSite expliqués](https://web.dev/samesite-cookies-explained/) +- [Cookies SameSite expliqués](https://web.dev/articles/samesite-cookies-explained) - [Premiers pas avec les jetons de confiance](https://web.dev/trust-tokens) -- [Un moyen plus privé de mesurer les conversions publicitaires](https://web.dev/conversion-measurement/) -- [Qu'est-ce que la méthode FLoC ?](https://web.dev/floc/) +- [Un moyen plus privé de mesurer les conversions publicitaires](/docs/privacy-sandbox/attribution-reporting/) +- [Qu'est-ce que la méthode FLoC ?](https://web.dev/articles/floc) - [Présentation du budget de confidentialité](https://www.youtube.com/watch?v=0STgfjSA6T8) ### Principes et concepts derrière les propositions diff --git a/site/fr/docs/privacy-sandbox/status/index.md b/site/fr/docs/privacy-sandbox/status/index.md index 5bb624b91..dd3a6fe4d 100644 --- a/site/fr/docs/privacy-sandbox/status/index.md +++ b/site/fr/docs/privacy-sandbox/status/index.md @@ -15,7 +15,7 @@ authors: *Anciennement API Conversion Measurement.* -- [Phase d'évaluation actuelle](https://web.dev/origin-trials/) : à partir de Chrome 86, [maintenant étendu](https://groups.google.com/u/1/a/chromium.org/g/attribution-reporting-api-dev/c/ZKf9T8sRqAM) à Chrome 93. +- [Phase d'évaluation actuelle](/docs/web-platform/origin-trials/) : à partir de Chrome 86, [maintenant étendu](https://groups.google.com/u/1/a/chromium.org/g/attribution-reporting-api-dev/c/ZKf9T8sRqAM) à Chrome 93. - [Inscrivez-vous à la phase d'évaluation](/origintrials/#/view_trial/3411476717733150721). - [Démo](https://goo.gle/demo-event-level-conversion-measurement-api). - [État de la plate-forme Chrome](https://www.chromestatus.com/features/6412002824028160). @@ -31,25 +31,25 @@ Consultez [État](/docs/privacy-sandbox/attribution-reporting-introduction/#stat - [Rapports sur l'attribution (mesure des conversions)](/docs/privacy-sandbox/attribution-reporting) - [Introduction à la création de rapports sur l'attribution (mesure des conversions)](/docs/privacy-sandbox/attribution-reporting-introduction) - [Explicateurs techniques API](https://github.com/WICG/conversion-measurement-api/) -- (⚠️ obsolète) [Une façon plus privée de mesurer les conversions publicitaires](https://web.dev/conversion-measurement/) : aperçu de la première itération de cette API pour les développeurs web +- (⚠️ obsolète) [Une façon plus privée de mesurer les conversions publicitaires](/docs/privacy-sandbox/attribution-reporting/) : aperçu de la première itération de cette API pour les développeurs web - (⚠️ obsolète) [Une façon plus privée de mesurer les conversions publicitaires - Vidéo](https://www.youtube.com/watch?v=jcDfOoWwZcM) : démo de la première itération de cette API (clics uniquement) -- (⚠️ obsolète) [Utilisation de l'API Event Conversion Measurement](https://web.dev/using-conversion-measurement/) : comment expérimenter la première itération de cette API pour les développeurs web +- (⚠️ obsolète) [Utilisation de l'API Event Conversion Measurement](/docs/privacy-sandbox/attribution-reporting/) : comment expérimenter la première itération de cette API pour les développeurs web - [Explications détaillées de Privacy Sandbox](https://web.dev/digging-into-the-privacy-sandbox) ## Jetons de confiance (Trust Tokens) -- [Phase d'évaluation actuelle](https://web.dev/origin-trials/) : à partir de Chrome 84, [maintenant étendu](https://groups.google.com/a/chromium.org/g/blink-dev/c/-W90wVkS0Ks/m/Jfh5-ZWpAQAJ) à Chrome 94. +- [Phase d'évaluation actuelle](/docs/web-platform/origin-trials/) : à partir de Chrome 84, [maintenant étendu](https://groups.google.com/a/chromium.org/g/blink-dev/c/-W90wVkS0Ks/m/Jfh5-ZWpAQAJ) à Chrome 94. - [Inscrivez-vous à la phase d'évaluation](/origintrials/#/view_trial/2479231594867458049). - [Démo](https://trust-token-demo.glitch.me/). - [État de la plate-forme Chrome](https://www.chromestatus.com/feature/5078049450098688). - [État Blink](https://groups.google.com/a/chromium.org/g/blink-dev/search?q=trust%tokens). - [GitHub](https://github.com/WICG/trust-token-api) : consultez les [problèmes](https://github.com/WICG/trust-token-api/issues) pour les questions et discussions sur l'API. - [Intégration des outils pour les développeurs Chrome](https://developers.google.com/web/updates/2021/01/devtools?utm_source=devtools#trust-token). -- En savoir plus : [Premiers pas avec les jetons de confiance](https://web.dev/trust-tokens/) +- En savoir plus : [Premiers pas avec les jetons de confiance](https://web.dev/articles/trust-tokens) ## Ensembles propriétaires -- [Phase d'évaluation actuelle](https://web.dev/origin-trials/) : Chrome 89 à 93. +- [Phase d'évaluation actuelle](/docs/web-platform/origin-trials/) : Chrome 89 à 93. - [Inscrivez-vous à la phase d'évaluation](/origintrials/#/view_trial/988540118207823873). - [État de la plate-forme Chrome](https://chromestatus.com/feature/5640066519007232). - [État Blink](https://groups.google.com/a/chromium.org/g/blink-dev/search?q=first-party%20sets). @@ -64,7 +64,7 @@ Consultez [État](/docs/privacy-sandbox/attribution-reporting-introduction/#stat - [La proposition d'API](https://github.com/WICG/floc) fait actuellement l'objet de discussions au sein du [WICG](https://www.w3.org/community/wicg/) et des groupes d'intérêt. - [GitHub](https://github.com/WICG/floc) : consultez les [problèmes](https://github.com/WICG/floc/issues) pour les questions et discussions sur l'API. - [État de la plate-forme Chrome](https://www.chromestatus.com/features/5710139774468096). -- En savoir plus : [Qu'est-ce que la méthode FLoC ?](https://web.dev/floc/) +- En savoir plus : [Qu'est-ce que la méthode FLoC ?](https://web.dev/articles/floc) ## FLEDGE @@ -91,7 +91,7 @@ Descendant de [TURTLEDOVE](https://github.com/WICG/turtledove). ### Phases d'évaluation -- [Premiers pas avec les phases d'évaluation de Chrome](https://web.dev/origin-trials/) +- [Premiers pas avec les phases d'évaluation de Chrome](/docs/web-platform/origin-trials/) - [Que sont les phases d'évaluation tierce ?](https://web.dev/third-party-origin-trials) - [Dépannage des phases d'évaluation de Chrome](/blog/origin-trial-troubleshooting/) - [Guide sur les phases d'évaluation pour les développeurs web](https://github.com/GoogleChrome/OriginTrials/blob/gh-pages/developer-guide.md) diff --git a/site/fr/docs/privacy-sandbox/trust-tokens/index.md b/site/fr/docs/privacy-sandbox/trust-tokens/index.md index 4d39a9412..94ce00273 100644 --- a/site/fr/docs/privacy-sandbox/trust-tokens/index.md +++ b/site/fr/docs/privacy-sandbox/trust-tokens/index.md @@ -11,7 +11,7 @@ authors: ## État d'implémentation -- [En phase d'évaluation](https://web.dev/origin-trials/) Chrome 84 à 94. +- [En phase d'évaluation](/docs/web-platform/origin-trials/) Chrome 84 à 94. - [Inscrivez-vous à la phase d'évaluation](/origintrials/#/view_trial/2479231594867458049). - [Démo](https://trust-token-demo.glitch.me/). - [Intégration des outils pour les développeurs Chrome](https://developers.google.com/web/updates/2021/01/devtools?utm_source=devtools#trust-token). @@ -62,7 +62,7 @@ Dans cet exemple, un site web d'éditeur souhaite vérifier si un utilisateur es 12. Le site d'éditeur affiche l'annonce. 13. Une impression de vue d'annonce est comptabilisée. -{% Aside %} Pour plus de détails sur les appels JavaScript dans cet exemple, consultez [Exemple d'utilisation de l'API](https://web.dev/trust-tokens/#sample-api-usage). {% endAside %} +{% Aside %} Pour plus de détails sur les appels JavaScript dans cet exemple, consultez [Exemple d'utilisation de l'API](https://web.dev/articles/trust-tokens#sample_api_usage). {% endAside %} ## Interagir et donner son avis @@ -77,6 +77,6 @@ Dans cet exemple, un site web d'éditeur souhaite vérifier si un utilisateur es ## En savoir plus - [Explications techniques de l'API Trust Token](https://github.com/dvorak42/trust-token-api) -- [Premiers pas avec les jetons de confiance](https://web.dev/trust-tokens/) : un aperçu pour les développeurs web +- [Premiers pas avec les jetons de confiance](https://web.dev/articles/trust-tokens) : un aperçu pour les développeurs web - [Premiers pas avec les phases d'évaluation de Chrome](https://web.dev/origin-trials) - [Explications détaillées de Privacy Sandbox](https://web.dev/digging-into-the-privacy-sandbox) diff --git a/site/ja/_partials/privacy-sandbox/glossary-entries/origin-trial.md b/site/ja/_partials/privacy-sandbox/glossary-entries/origin-trial.md index e97f17a84..e0b40c78a 100644 --- a/site/ja/_partials/privacy-sandbox/glossary-entries/origin-trial.md +++ b/site/ja/_partials/privacy-sandbox/glossary-entries/origin-trial.md @@ -2,4 +2,4 @@ Chrome が機能のオリジントライアルを提供している場合、トライアルに[オリジン](#origin)を登録すると、そのオリジンのすべてのユーザーはフラグを切り替えたり、Chrome の代替ビルドに切り替えたりすることなく、その機能を使用することができます(Chrome のアップグレードが必要な場合があります)。オリジントライアルを使用することにより、開発者は新しい機能を使用してデモやプロトタイプをビルドすることができます。 このトライアルは、Chrome エンジニアが新機能の使用方法や他のウェブテクノロジーとの相互作用を理解するのに役立ちます。 -詳細は、[Chrome のオリジン トライアルのスタートガイド](https://web.dev/origin-trials/)をご覧ください。 +詳細は、[Chrome のオリジン トライアルのスタートガイド](/docs/web-platform/origin-trials/)をご覧ください。 diff --git a/site/ja/_partials/privacy-sandbox/timeline/first-party-sets.md b/site/ja/_partials/privacy-sandbox/timeline/first-party-sets.md index 563bb8e55..f7a1f2321 100644 --- a/site/ja/_partials/privacy-sandbox/timeline/first-party-sets.md +++ b/site/ja/_partials/privacy-sandbox/timeline/first-party-sets.md @@ -1,5 +1,5 @@ - First-Party Sets は [WICG](https://github.com/WICG/first-party-sets/issues) で検討中です。 -- 最初の[オリジントライアルは](https://web.dev/origin-trials/) Chrome 89 から 93 まで実行されました。 +- 最初の[オリジントライアルは](/docs/web-platform/origin-trials/) Chrome 89 から 93 まで実行されました。 - [Chrome プラットフォームのステータス](https://chromestatus.com/feature/5640066519007232)。 - [Blink のステータス](https://groups.google.com/a/chromium.org/g/blink-dev/search?q=first-party%20sets)。 - [Chromium プロジェクト](https://www.chromium.org/updates/first-party-sets)。 diff --git a/site/ja/_partials/privacy-sandbox/timeline/private-state-tokens.md b/site/ja/_partials/privacy-sandbox/timeline/private-state-tokens.md index 3182ece1e..6e5e7888a 100644 --- a/site/ja/_partials/privacy-sandbox/timeline/private-state-tokens.md +++ b/site/ja/_partials/privacy-sandbox/timeline/private-state-tokens.md @@ -1,4 +1,4 @@ - [Chrome プラットフォームのステータス](https://www.chromestatus.com/feature/5078049450098688)。 -- Chrome 84 から 101 の[オリジントライアル](https://web.dev/origin-trials/): [終了しました](/origintrials/#/view_trial/2479231594867458049)。 +- Chrome 84 から 101 の[オリジントライアル](/docs/web-platform/origin-trials/): [終了しました](/origintrials/#/view_trial/2479231594867458049)。 - [デモ](https://trust-token-demo.glitch.me/): オリジントライアルが終了したため、これは機能しなくなりました。コードは引き続き閲覧できます。 - [Chrome DevTools の統合](/blog/new-in-devtools-89/#trust-token)。 diff --git a/site/ja/blog/announce-enrollment-privacy-sandbox/index.md b/site/ja/blog/announce-enrollment-privacy-sandbox/index.md index 3048d6c43..282245be9 100644 --- a/site/ja/blog/announce-enrollment-privacy-sandbox/index.md +++ b/site/ja/blog/announce-enrollment-privacy-sandbox/index.md @@ -45,7 +45,7 @@ API 呼び出し元が受け取ることができるデータの量を制限す ### サイト単位の登録 -すべての API 呼び出し元は、[サイト](https://web.dev/same-site-same-origin/#public-suffix-list-and-etld)を登録する必要があります。サイトは、プライバシーサンドボックス API のプライバシー保護を通知する境界を提供します。 +すべての API 呼び出し元は、[サイト](https://web.dev/articles/same-site-same-origin#public_suffix_list_and_etld)を登録する必要があります。サイトは、プライバシーサンドボックス API のプライバシー保護を通知する境界を提供します。 {% Aside %} この登録は、1 つ以上のプライバシーサンドボックスの広告関連 API を呼び出す企業にのみ適用されます。アドテックの顧客であるサイト運営者やその他の企業は、登録する必要はありません。 {% endAside %} diff --git a/site/ja/blog/chrome-ux-report-looker-studio-dashboard/index.md b/site/ja/blog/chrome-ux-report-looker-studio-dashboard/index.md index c9a37374f..2b4ff0bea 100644 --- a/site/ja/blog/chrome-ux-report-looker-studio-dashboard/index.md +++ b/site/ja/blog/chrome-ux-report-looker-studio-dashboard/index.md @@ -70,7 +70,7 @@ https://developer.chrome.com/chrome-ux-report-looker-studio-dashboard/ ### Core Web Vitalsの概要 -最初のページは、オリジンの毎月の[Core WebVitals](https://web.dev/vitals/)パフォーマンスの概要です。これらは、Googleが注目するよう勧めている最も重要なUX指標です。 +最初のページは、オリジンの毎月の[Core WebVitals](https://web.dev/articles/vitals)パフォーマンスの概要です。これらは、Googleが注目するよう勧めている最も重要なUX指標です。 {% Img src="image/admin/h8iCTgvmG4DS2zScvatc.png", alt="CrUX DashboardのCore Web Vitalsの概要", width="800", height="906" %} @@ -88,7 +88,7 @@ Core Web Vitalsページの次に、CrUXデータセットのあるあらゆる[ 各ページの上部には**Device**フィルターがあり、エクスペリエンスデータに含まれるフォームファクターを絞り込むために使用できます。たとえば、具体的に携帯電話でのエクスペリエンスに絞り込むことができます。この設定はページ全体に適用されます。 -これらのページの主な可視化は、「Good(良い)」、「Needs Improvement(改善が必要)」、「Poor(悪い)」に分類されたエクスペリエンスの月次分布です。グラフの下の色分けされた凡例は、カテゴリに含まれるエクスペリエンスの範囲を示しています。たとえば、上のスクリーンショットでは、「Good」[Largest Contentful Paint](https://web.dev/lcp/#what-is-a-good-lcp-score)(LCP: 最大視覚コンテンツの表示時間)エクスペリエンスの割合が変動しており、ここ数か月でわずかに悪化していることがわかります。 +これらのページの主な可視化は、「Good(良い)」、「Needs Improvement(改善が必要)」、「Poor(悪い)」に分類されたエクスペリエンスの月次分布です。グラフの下の色分けされた凡例は、カテゴリに含まれるエクスペリエンスの範囲を示しています。たとえば、上のスクリーンショットでは、「Good」[Largest Contentful Paint](https://web.dev/articles/lcp#what_is_a_good_lcp_score)(LCP: 最大視覚コンテンツの表示時間)エクスペリエンスの割合が変動しており、ここ数か月でわずかに悪化していることがわかります。 直近の月には「Good」と「Poor」のエクスペリエンスの割合は、前月との差の指標とともにチャートの上に表示されます。このオリジンでは、「Good」LCPエクスペリエンスは、前月比で3.2%減少して56.04%になっています。 @@ -116,7 +116,7 @@ PageSpeed Insightsなどのツールの対応するP75値は、公開されて {% Aside 'key-term' %}有効な接続タイプは、ユーザーのデバイスの帯域幅測定に基づいており、使用されている特定のテクノロジーについては言及していないため、*有効*とみなされます。たとえば、高速Wi-Fiを使用しているデスクトップユーザーは4Gとラベル付けされますが、低速のモバイル接続は2Gとラベル付けされる場合があります。 {% endAside %} -これらの次元の分布は、[First Contentful Paint](https://web.dev/fcp/)(FCP: 視覚コンテンツの初期表示時間)ヒストグラムデータのセグメントを使って計算されます。 +これらの次元の分布は、[First Contentful Paint](https://web.dev/articles/fcp)(FCP: 視覚コンテンツの初期表示時間)ヒストグラムデータのセグメントを使って計算されます。 ## よくある質問 diff --git a/site/ja/blog/expanding-privacy-sandbox-testing/index.md b/site/ja/blog/expanding-privacy-sandbox-testing/index.md index 0567d2831..0eb802b0d 100644 --- a/site/ja/blog/expanding-privacy-sandbox-testing/index.md +++ b/site/ja/blog/expanding-privacy-sandbox-testing/index.md @@ -94,7 +94,7 @@ First-Party Sets は、異なる国レベルのドメインなどで複数のサ {% endAside %} -**文字列の変更は下位互換性が確保される予定**であるため、これらの特定の値が必要がない場合は、影響を受けません。 ただし、ユーザーエージェント文字列を解析して、ブラウザのマイナー/ビルドバージョン、OS/プラットフォームバージョン、またはデバイスモデルを抽出する場合は、[User-Agent Client Hints](https://web.dev/migrate-to-ua-ch/) に移行する必要があります。 +**文字列の変更は下位互換性が確保される予定**であるため、これらの特定の値が必要がない場合は、影響を受けません。 ただし、ユーザーエージェント文字列を解析して、ブラウザのマイナー/ビルドバージョン、OS/プラットフォームバージョン、またはデバイスモデルを抽出する場合は、[User-Agent Client Hints](https://web.dev/articles/migrate-to-ua-ch) に移行する必要があります。 ## ストレージ分割 diff --git a/site/ja/blog/first-party-sets-sameparty/index.md b/site/ja/blog/first-party-sets-sameparty/index.md index 76ea026b7..d50d362e3 100644 --- a/site/ja/blog/first-party-sets-sameparty/index.md +++ b/site/ja/blog/first-party-sets-sameparty/index.md @@ -31,7 +31,7 @@ First-Party Sets の提案は現在[テスト段階](https://privacysandbox.com/ Cookie は本質的にファーストパーティまたはサードパーティではなく、Cookie が含まれる現在のコンテキストに依存します。これは、`cookie` ヘッダー内、または JavaScript の `document.cookie` を介したリクエストのいずれかです。 -たとえば、 `video.site` に `theme=dark` Cookie がある場合、`video.site` を閲覧中にリクエストが `video.site` に対して行われると、これは [same-site コンテキスト](https://web.dev/same-site-same-origin/#same-site-cross-site)であり、含まれる Cookie は *first-party* となります。 +たとえば、 `video.site` に `theme=dark` Cookie がある場合、`video.site` を閲覧中にリクエストが `video.site` に対して行われると、これは [same-site コンテキスト](https://web.dev/articles/same-site-same-origin#same_site_cross_site)であり、含まれる Cookie は *first-party* となります。 ただし、`video.site` の iframe プレーヤーを埋め込んだ `my-blog.site` を閲覧している場合に `my-blog.site` から `video.site` にリクエストが送信されると、これはクロスサイトコンテキストであり、`theme` Cookie は *third-party* となります。 @@ -39,7 +39,7 @@ Cookie は本質的にファーストパーティまたはサードパーティ Cookie の組み込みは、Cookie の `SameSite` 属性によって決定されます。 -- `SameSite=Lax`、`Strict`、または `None` を指定した [**same-site コンテキスト**](https://web.dev/same-site-same-origin/#same-site-cross-site)では、Cookie は**ファーストパーティ**になります。 +- `SameSite=Lax`、`Strict`、または `None` を指定した [**same-site コンテキスト**](https://web.dev/articles/same-site-same-origin#same_site_cross_site)では、Cookie は**ファーストパーティ**になります。 - `SameSite=None` を指定した **cross-site コンテキスト**では、Cookie は**サードパーティ**になります。 ただし、必ずしも明確ではありません。`brandx.site` が旅行予約サイトで、`fly-brandx.site` と `drive-brandx.site` も併用してフライトとレンタカーのサービスを分けているとします。1 つの旅行を予約する過程で、訪問者はこれらのサイト間を移動してさまざまなオプションを選択し、これらのサイト間で、「ショッピングカート」の中身が維持されることを期待しています。`brandx.site`は、`SameSite=None` Cookie を使用して、cross-site コンテキストを許可することでユーザーのセッションを管理します。ただし欠点があり、Cookie にクロスサイトリクエストフォージェリ(CSRF)保護がありません。`evil.site` が `brandx.site` へのリクエストを含めると、その Cookie が含まれてしまうことになります! diff --git a/site/ja/blog/fledge-api/index.md b/site/ja/blog/fledge-api/index.md index a61a8ea68..96f7bc6df 100644 --- a/site/ja/blog/fledge-api/index.md +++ b/site/ja/blog/fledge-api/index.md @@ -325,7 +325,7 @@ navigator.joinAdInterestGroup(interestGroup, 7 * kSecsPerDay); {% Aside 'gotchas' %} -FLEDGE API メソッドのパラメーターとして使用されるすべての URL は、安全なオリジンからのものである必要があります。すべてのリソースは、HTTPS URL 経由で提供される必要があります。[ローカル開発での HTTPS の使用方法](https://web.dev/how-to-use-local-https/)には、FLEDGE をローカルで実行するときにこれをどのように行うかが説明されています。 +FLEDGE API メソッドのパラメーターとして使用されるすべての URL は、安全なオリジンからのものである必要があります。すべてのリソースは、HTTPS URL 経由で提供される必要があります。[ローカル開発での HTTPS の使用方法](https://web.dev/articles/how-to-use-local-https)には、FLEDGE をローカルで実行するときにこれをどのように行うかが説明されています。 さらに、`biddingLogicUrl`、`decisionLogicUrl`、`trustedBiddingSignals` にはすべて、`X-Allow-FLEDGE: true` HTTP レスポンスヘッダーが必要です。 diff --git a/site/ja/blog/http-cache-partitioning/index.md b/site/ja/blog/http-cache-partitioning/index.md index 3502d000b..770e53991 100644 --- a/site/ja/blog/http-cache-partitioning/index.md +++ b/site/ja/blog/http-cache-partitioning/index.md @@ -42,7 +42,7 @@ Chrome では、キャッシュの仕組みがさまざまな方法で使用さ キャッシュ パーティションでは、キャッシュされたリソースは、リソース URL に加えて新しい「ネットワーク分離キー」を使用するキーとなります。ネットワーク分離キーは、トップレベルサイトと現在のフレームのサイトで構成されます。 -{% Aside %} 「サイト」は「[scheme://eTLD+1](https://web.dev/same-site-same-origin/)」を使用して認識されるため、リクエストが異なるページからのものであっても、同じスキームと有効なトップレベルドメイン+1 を持つ場合、同じキャッシュ分割が使用されます。詳細については、「[「same-site」と「same-origin」を理解する](https://web.dev/same-site-same-origin/)」をご覧ください。 {% endAside %} +{% Aside %} 「サイト」は「[scheme://eTLD+1](https://web.dev/articles/same-site-same-origin)」を使用して認識されるため、リクエストが異なるページからのものであっても、同じスキームと有効なトップレベルドメイン+1 を持つ場合、同じキャッシュ分割が使用されます。詳細については、「[「same-site」と「same-origin」を理解する](https://web.dev/articles/same-site-same-origin)」をご覧ください。 {% endAside %} 前の例をもう一度見て、さまざまなコンテキストでキャッシュ パーティションがどのように機能するかを確認しましょう。 diff --git a/site/ja/blog/new-in-devtools-101/index.md b/site/ja/blog/new-in-devtools-101/index.md index d0104df84..a5ba256b8 100644 --- a/site/ja/blog/new-in-devtools-101/index.md +++ b/site/ja/blog/new-in-devtools-101/index.md @@ -104,8 +104,8 @@ Chromium issues: [1296855](https://crbug.com/1296855), [https://crbug.com/130340 <!-- These are some noteworthy fixes in this release: --> 今回のリリースでは、以下のような注目すべき修正点があります。 -<!-- - The [Back/forward cache](/blog/new-in-devtools-98/#bfcache) now displays the extension ID which blocked [bfcache](https://web.dev/bfcache/) when present.( [1284548](https://crbug.com/1284548)) --> -- [バック/フォワードキャッシュ](/blog/new-in-devtools-98/#bfcache)が存在する場合、 [bfcache](https://web.dev/bfcache/) をブロックした拡張機能のIDを表示するようになりました( [1284548](https://crbug.com/1284548)). +<!-- - The [Back/forward cache](/blog/new-in-devtools-98/#bfcache) now displays the extension ID which blocked [bfcache](https://web.dev/articles/bfcache) when present.( [1284548](https://crbug.com/1284548)) --> +- [バック/フォワードキャッシュ](/blog/new-in-devtools-98/#bfcache)が存在する場合、 [bfcache](https://web.dev/articles/bfcache) をブロックした拡張機能のIDを表示するようになりました( [1284548](https://crbug.com/1284548)). <!-- - Fixed autocompletion support for array-like objects, CSS class names, `map.get` and HTML tags. ([1297101](https://crbug.com/1297101), [1297491](https://crbug.com/1297491), [1293807](https://crbug.com/1293807), [1296983](https://crbug.com/1296983)) --> - array-like オブジェクト、CSSクラス名、 `map.get` 、HTMLタグのオートコンプリートのサポートを修正しました。([1297101](https://crbug.com/1297101), [1297491](https://crbug.com/1297491), [1293807](https://crbug.com/1293807), [1296983](https://crbug.com/1296983)) <!-- - Fixed incorrect highlights when double-clicking on words and undoing autocomplete. ([1298437](https://crbug.com/1298437), [1298667](https://crbug.com/1298667)) --> @@ -115,7 +115,7 @@ Chromium issues: [1296855](https://crbug.com/1296855), [https://crbug.com/130340 <!-- - Re-enable support for using **Alt** (Options) key for multi selection in the **Sources** panel. ([1304070](https://crbug.com/1304070)) --> - **Sources** パネルでの複数選択時に **Alt** (Options) キーを使用するサポートを再び有効化しました。([1304070](https://crbug.com/1304070)) - + <!-- ## [Experimental] New timespan and snapshot mode in the Lighthouse panel {: #lighthouse } --> ## [実験的] Lighthouse パネルに新しいタイムスパンとスナップショットのモードを追加 {: #lighthouse } @@ -127,8 +127,8 @@ Chromium issues: [1296855](https://crbug.com/1296855), [https://crbug.com/130340 <!-- Apart from the existing **navigation** mode, the **Lighthouse** panel now support two more modes on measuring user flows - **timespan** and **snapshot**. --> 従来の **navigation** モードとは別に、 **Lighthouse** パネルは、ユーザーフローを測定するための2つのモード、**タイムスパン**と**スナップショット**をサポートするようになりました。 -<!-- For example, you can use the **timespan** reports to analyze user interactions. Open this [demo](https://coffee-cart.netlify.app/) page. Select the **Timespan** mode and click on **Start timespan**. On the page, click on a coffee and end the timespan. Read the report to find out the [Total Blocking Time](https://web.dev/tbt/) and [Cumulative Layout Shift](https://web.dev/cls/) that were caused by the interaction. --> -例えば、 **タイムスパン** レポートを使用して、ユーザーのインタラクションを分析することができます。この[デモ](https://coffee-cart.netlify.app/)ページを開いてください。 **Timespan** モードを選択し、 **Start timespan** をクリックします。ページ上でコーヒーをクリックし、タイムスパンを終了します。レポートを読んで、インタラクションによって生じた[Total Blocking Time](https://web.dev/tbt/) と [Cumulative Layout Shift](https://web.dev/cls/) を確認します。 +<!-- For example, you can use the **timespan** reports to analyze user interactions. Open this [demo](https://coffee-cart.netlify.app/) page. Select the **Timespan** mode and click on **Start timespan**. On the page, click on a coffee and end the timespan. Read the report to find out the [Total Blocking Time](https://web.dev/articles/tbt) and [Cumulative Layout Shift](https://web.dev/articles/cls) that were caused by the interaction. --> +例えば、 **タイムスパン** レポートを使用して、ユーザーのインタラクションを分析することができます。この[デモ](https://coffee-cart.netlify.app/)ページを開いてください。 **Timespan** モードを選択し、 **Start timespan** をクリックします。ページ上でコーヒーをクリックし、タイムスパンを終了します。レポートを読んで、インタラクションによって生じた[Total Blocking Time](https://web.dev/articles/tbt) と [Cumulative Layout Shift](https://web.dev/articles/cls) を確認します。 <!-- Each mode has its own unique use cases, benefits, and limitations. Please refer to the [Lighthouse documentation](https://github.com/GoogleChrome/lighthouse/blob/master/docs/user-flows.md) for more information. --> それぞれのモードには、独自の使用例、利点、制限があります。詳しくは、[Lighthouse のドキュメント](https://github.com/GoogleChrome/lighthouse/blob/master/docs/user-flows.md)をご参照ください。 diff --git a/site/ja/blog/new-in-devtools-102/index.md b/site/ja/blog/new-in-devtools-102/index.md index 141d5997f..658e8c48b 100644 --- a/site/ja/blog/new-in-devtools-102/index.md +++ b/site/ja/blog/new-in-devtools-102/index.md @@ -54,8 +54,8 @@ Chromium issue: [1270700](https://crbug.com/1270700) <!-- ## New shortcuts to emulate light and dark themes {: #emulation } --> ## ライトテーマとダークテーマをエミュレートする新しいショートカット {: #emulation } -<!-- You can now emulate the light and dark themes quicker (CSS media feature [prefers-color-scheme](https://web.dev/prefers-color-scheme/#the-prefers-color-scheme-media-query)) with the new shortcuts in the **Styles** pane. --> -**Styles** ペインで新しいショートカットを使用して、ライトテーマとダークテーマ(CSSメディア特性の [prefers-color-scheme](https://web.dev/prefers-color-scheme/#the-prefers-color-scheme-media-query))をより素早くエミュレートできるようになりました。 +<!-- You can now emulate the light and dark themes quicker (CSS media feature [prefers-color-scheme](https://web.dev/articles/prefers-color-scheme#the_prefers_color_scheme_media_query)) with the new shortcuts in the **Styles** pane. --> +**Styles** ペインで新しいショートカットを使用して、ライトテーマとダークテーマ(CSSメディア特性の [prefers-color-scheme](https://web.dev/articles/prefers-color-scheme#the_prefers_color_scheme_media_query))をより素早くエミュレートできるようになりました。 <!-- Previously, it took more steps to [emulate themes](/docs/devtools/rendering/emulate-css/) in the **Rendering** tab. --> これまでは **Rendering** タブで[テーマをエミュレートする](/docs/devtools/rendering/emulate-css/)ためにより多くの手順が必要でした。 @@ -74,8 +74,8 @@ Chromium issue: [1314299](https://crbug.com/1314299) <!-- DevTools now apply the Content Security Policy (CSP) in the **Preview** tab in the **Network** panel. --> DevTools は **Network** パネルの **Preview** タブに Content Security Policy(CSP)を適用するようになりました。 -<!-- For example, the first screenshot shows a page that contains [mixed content](https://web.dev/what-is-mixed-content/). The page loads over a secure HTTPS connection, but the stylesheet loads over an insecure HTTP connection. --> -例えば、最初のスクリーンショットは[混合コンテンツ](https://web.dev/what-is-mixed-content/)を含むページを示しています。このページはセキュアな HTTPS 接続を使用して読み込まれますが、スタイルシートはセキュアではない HTTP 接続が使用されています。 +<!-- For example, the first screenshot shows a page that contains [mixed content](https://web.dev/articles/what-is-mixed-content). The page loads over a secure HTTPS connection, but the stylesheet loads over an insecure HTTP connection. --> +例えば、最初のスクリーンショットは[混合コンテンツ](https://web.dev/articles/what-is-mixed-content)を含むページを示しています。このページはセキュアな HTTPS 接続を使用して読み込まれますが、スタイルシートはセキュアではない HTTP 接続が使用されています。 <!-- The browser blocked the stylesheet request by default. However, when you opened the page via the **Preview** tab in the **Network** panel, the stylesheet was not blocked previously (hence the background turned into red). It is now blocked as you would expect (second screenshot). --> デフォルトではブラウザはスタイルシートのリクエストをブロックします。しかし、これまではこのページが **Network** パネルの **Preview** タブで開かれたときには、スタイルシートがブロックされませんでした(そのため背景が赤色に変わります)。これが期待どおりにブロックされるようになります(2枚目のスクリーンショット)。 @@ -220,7 +220,7 @@ CSS の変更を簡単に追跡してコピーできるように、新しい **C {# https://chromium.googlesource.com/devtools/devtools-frontend/+/afe5698f1cd20304d2763574ef8e9faf6a4a6db1 #} {# https://chromium.googlesource.com/devtools/devtools-frontend/+/5de1d6140cad945783f3ca54055134f4a7db42a1 #} -{# https://chromium.googlesource.com/devtools/devtools-frontend/+/573dfc1cca09e49177ece3898c9ba9619c386f06 #} +{# https://chromium.googlesource.com/devtools/devtools-frontend/+/573dfc1cca09e49177ece3898c9ba9619c386f06 #} Chromium issue: [1268754](https://crbug.com/1268754) diff --git a/site/ja/blog/new-in-devtools-104/index.md b/site/ja/blog/new-in-devtools-104/index.md index 0aecb0f45..8cd1f737f 100644 --- a/site/ja/blog/new-in-devtools-104/index.md +++ b/site/ja/blog/new-in-devtools-104/index.md @@ -101,8 +101,8 @@ Chromium issue: [960909](https://crbug.com/960909) <!-- Visualize `performance.measure()` marks in your recording with the new **User Timings** track in the **Performance insights** panel. --> **Performance insights** パネルの新しい **User Timings** トラックで、 計測中の `performance.measure()` マークを視覚化します。 -<!-- For example, this [web page](https://jec.fish/demo/perf-measure) uses the [`performance.measure()`](https://web.dev/usertiming/#calculating-measurements-with-measure()) method to calculate the elapsed time of text loading. --> -たとえば、この [Web ページ](https://jec.fish/demo/perf-measure)では、 [`performance.measure()`](https://web.dev/usertiming/#calculating-measurements-with-measure()) メソッドを用いて、テキストの読み込み経過時間を算出しています。 +<!-- For example, this [web page](https://jec.fish/demo/perf-measure) uses the [`performance.measure()`](https://web.dev/articles/usertiming#calculating_measurements_with_measure()) method to calculate the elapsed time of text loading. --> +たとえば、この [Web ページ](https://jec.fish/demo/perf-measure)では、 [`performance.measure()`](https://web.dev/articles/usertiming#calculating_measurements_with_measure()) メソッドを用いて、テキストの読み込み経過時間を算出しています。 <!-- When you start [measuring the page load](/docs/devtools/performance-insights/#record), the **User Timings** track shows in the recording. Click on the timings item to view its details on the side pane. --> [ページ読み込みの計測](/docs/devtools/performance-insights/#record)を開始すると、 **User Timings** トラックが計測結果に表示されるようになります。タイミング項目をクリックすると、サイドペインにその詳細が表示されます。 diff --git a/site/ja/blog/new-in-devtools-105/index.md b/site/ja/blog/new-in-devtools-105/index.md index c3270eb38..f21b8e863 100644 --- a/site/ja/blog/new-in-devtools-105/index.md +++ b/site/ja/blog/new-in-devtools-105/index.md @@ -71,8 +71,8 @@ Chromium issue: [1257499](https://crbug.com/1257499) <!-- ## Largest Contentful Paint (LCP) in the Performance insights panel {: #lcp } --> ## Performance insight パネルに Largest Contentful Paint (LCP) を追加 {: #lcp } -<!-- LCP is an important, user-centric metric for measuring [perceived load speed](https://web.dev/user-centric-performance-metrics/#types-of-metrics). You can now find out the critical paths and root causes of a [Largest Contentful Paint (LCP)](https://web.dev/lcp/). --> -LCP は[認識される読み込み速度](https://web.dev/user-centric-performance-metrics/#types-of-metrics)を測定する重要なユーザー中心メトリクスのひとつです。これからはクリティカルパスと [Largest Contentful Paint (LCP)](https://web.dev/lcp/) の主な要因を見つけることができます。 +<!-- LCP is an important, user-centric metric for measuring [perceived load speed](https://web.dev/articles/user-centric-performance-metrics#types_of_metrics). You can now find out the critical paths and root causes of a [Largest Contentful Paint (LCP)](https://web.dev/articles/lcp). --> +LCP は[認識される読み込み速度](https://web.dev/articles/user-centric-performance-metrics#types_of_metrics)を測定する重要なユーザー中心メトリクスのひとつです。これからはクリティカルパスと [Largest Contentful Paint (LCP)](https://web.dev/articles/lcp) の主な要因を見つけることができます。 <!-- In a [performance recording](/docs/devtools/performance-insights/#record), click on the LCP badge in the **Timeline**. In the **Details** pane, you can view the LCP score, learn how to fix resources that slow down the LCP and see the critical path for the LCP resource. --> [performance recording](/docs/devtools/performance-insights/#record)で、**Timeline** にある LCP バッジをクリックしてください。**Details** ペインで、LCP スコアを見て、LCP を遅滞させているリソースをどのように修正すればいいかを学び、LCP リソースのクリティカルパスを確認できます。 @@ -89,14 +89,14 @@ Chromium issue: [1326481](https://crbug.com/1326481) <!-- ## Identify flashes of text (FOIT, FOUT) as potential root causes for layout shifts {: #foit-fout } --> ## レイアウトシフトの潜在的な主要因であるテキストのフラッシュ(FOIT、FOUT)を識別 {: #foit-fout } -<!-- The **Performance insights** panel now detects [flash of invisible text (FOIT) and flash of unstyled text (FOUT)](https://web.dev/preload-optional-fonts/#font-rendering) as potential root causes for layout shifts. --> -**Performance insights** パネルはレイアウトシフトの潜在的な主要因として [flash of invisible text (FOIT) と flash of unstyled text (FOUT)](https://web.dev/preload-optional-fonts/#font-rendering) を検出できるようになりました。 +<!-- The **Performance insights** panel now detects [flash of invisible text (FOIT) and flash of unstyled text (FOUT)](https://web.dev/articles/preload-optional-fonts#font_rendering) as potential root causes for layout shifts. --> +**Performance insights** パネルはレイアウトシフトの潜在的な主要因として [flash of invisible text (FOIT) と flash of unstyled text (FOUT)](https://web.dev/articles/preload-optional-fonts#font_rendering) を検出できるようになりました。 <!-- To view the potential root causes of a layout shift, click on a screenshot in the **Layout shifts** track. --> レイアウトシフトの潜在的な主要因を確認するには、**Layout shifts** トラックにあるスクリーンショットをクリックしてください。 -<!-- See [Optimize WebFont loading and rendering](https://web.dev/optimize-webfont-loading/) to learn the technique to prevent layout shifts. --> -レイアウトシフトを避けるテクニックについて学ぶには [Optimize WebFont loading and rendering](https://web.dev/optimize-webfont-loading/) を参照してください。 +<!-- See [Optimize WebFont loading and rendering](https://web.dev/articles/optimize-webfont-loading) to learn the technique to prevent layout shifts. --> +レイアウトシフトを避けるテクニックについて学ぶには [Optimize WebFont loading and rendering](https://web.dev/articles/optimize-webfont-loading) を参照してください。 <!-- {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/AMN5oD5hlKhPhnq98sIB.png", alt="FOUT in the Performance insights panel", width="800", height="497" %} --> {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/AMN5oD5hlKhPhnq98sIB.png", alt="Performance insights パネルの FOUT", width="800", height="497" %} @@ -107,8 +107,8 @@ Chromium issues: [1334628](https://crbug.com/1334628), [1328873](https://crbug.c <!-- ## Protocol handlers in the Manifest pane {: #manifest } --> ## Manifest ペインの Protocol ハンドラ {: #manifest } -<!-- You can now use DevTools to test the [URL protocol handler registration](https://web.dev/url-protocol-handler/) for [Progressive Web Apps (PWA)](https://web.dev/learn/pwa/). --> -DevTools を使用して [Progressive Web Apps (PWA)](https://web.dev/learn/pwa/) のための [URL protocol handler registration](https://web.dev/url-protocol-handler/) をテストできるようになりました。 +<!-- You can now use DevTools to test the [URL protocol handler registration](https://web.dev/articles/url-protocol-handler) for [Progressive Web Apps (PWA)](https://web.dev/learn/pwa). --> +DevTools を使用して [Progressive Web Apps (PWA)](https://web.dev/learn/pwa) のための [URL protocol handler registration](https://web.dev/articles/url-protocol-handler) をテストできるようになりました。 <!-- The URL protocol handler registration lets installed PWAs handle links that use a specific protocol (e.g. [`magnet`](https://wikipedia.org/wiki/Magnet_URI_scheme), `web+example`) for a more integrated experience. --> URL protocol handler registration を使用するとインストールされた PWA が特定のプロトコル(例、[`magnet`](https://wikipedia.org/wiki/Magnet_URI_scheme)、`web+example`)が使用されたリンクを処理して、より統一感のある体験を提供できます。 @@ -134,8 +134,8 @@ Chromium issues: [1300613](https://crbug.com/1300613) <!-- Use the [top layer badge](/blog/top-layer-devtools/#top-layer-support-design-in-devtools) to understand the concept of the top layer and visualize how the top layer content changes. --> トップレイヤのコンセプトと、トップレイヤ内容の変更がどのように可視化されるかを理解するには [top layer badge](/blog/top-layer-devtools/#top-layer-support-design-in-devtools) を確認してください。 -<!-- The [`<dialog>` element](https://web.dev/building-a-dialog-component/) has recently become stable across browsers. When you open a dialog, it is put into a [top layer](/blog/top-layer-devtools/). Top level content renders on top of all the other content. --> -[`<dialog>` 要素](https://web.dev/building-a-dialog-component/)は最近ブラウザで安定版になりました。ダイアログを開くと、その内容が [top layer](/blog/top-layer-devtools/) に配置されます。トップレベルコンテンツはその他すべてのコンテンツの上に描画されます。 +<!-- The [`<dialog>` element](https://web.dev/articles/building-a-dialog-component) has recently become stable across browsers. When you open a dialog, it is put into a [top layer](/blog/top-layer-devtools/). Top level content renders on top of all the other content. --> +[`<dialog>` 要素](https://web.dev/articles/building-a-dialog-component)は最近ブラウザで安定版になりました。ダイアログを開くと、その内容が [top layer](/blog/top-layer-devtools/) に配置されます。トップレベルコンテンツはその他すべてのコンテンツの上に描画されます。 <!-- In this [demo](https://jec.fish/demo/dialog), click **Open dialog**. --> この[デモ](https://jec.fish/demo/dialog)で、**Open dialog** をクリックしてください。 diff --git a/site/ja/blog/new-in-devtools-106/index.md b/site/ja/blog/new-in-devtools-106/index.md index 237ea01a4..ad817b0ca 100644 --- a/site/ja/blog/new-in-devtools-106/index.md +++ b/site/ja/blog/new-in-devtools-106/index.md @@ -174,7 +174,7 @@ Chromium bug: [1347390](https://crbug.com/1347390) <!-- ## LCP timings breakdown in the Performance Insights panel {: #insights } --> ## Performance Insights パネルでの LCP タイミングの内訳 {: #insights } -<!-- The **Performance Insights** panel now shows the [timings breakdown](https://web.dev/optimize-lcp/#lcp-breakdown) of the [Largest Containful Paint (LCP)](/docs/devtools/performance-insights/#largest-contentful-paint). Use these timings information to understand and identify an opportunity to improve LCP performance. --> +<!-- The **Performance Insights** panel now shows the [timings breakdown](https://web.dev/articles/optimize-lcp#lcp_breakdown) of the [Largest Containful Paint (LCP)](/docs/devtools/performance-insights/#largest-contentful-paint). Use these timings information to understand and identify an opportunity to improve LCP performance. --> {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/hU6RmoRjFskL8P2ZAB9l.png", alt="Performance Insights パネルでの LCP タイミングの内訳", width="800", height="523" %} @@ -201,11 +201,11 @@ Chromium bug: [1351383](https://crbug.com/1351383) <!-- - Previously, [Recorder extensions](/docs/devtools/recorder/reference/#extension-troubleshooting) don’t show up in the **Recorder** panel from time to time. ([1351416](https://crbug.com/1351416)) --> <!-- - The **Styles** pane now displays a color picker for the [SVG `<stop>`](https://developer.mozilla.org/docs/Web/SVG/Element/stop) element’s `stop-color` property. ([1351096](https://crbug.com/1351096)) --> -<!-- - Identify script causing [layout](https://web.dev/avoid-large-complex-layouts-and-layout-thrashing/) as the potential root causes for layout shifts in the **Performance Insights** panel. ([1343019](https://crbug.com/1343019)) --> +<!-- - Identify script causing [layout](https://web.dev/articles/avoid-large-complex-layouts-and-layout-thrashing) as the potential root causes for layout shifts in the **Performance Insights** panel. ([1343019](https://crbug.com/1343019)) --> <!-- - Display critical path for LCP web fonts in the **Performance Insights** panel. ([1350390](https://crbug.com/1350390)) --> - 以前は、[Recorder 拡張機能](/docs/devtools/recorder/reference/#extension-troubleshooting) が **Recorder** パネルに時々表示されないことがありました。 ([1351416](https://crbug.com/1351416)) - **Styles** ペインにて、 [SVG `<stop>`](https://developer.mozilla.org/docs/Web/SVG/Element/stop) 要素の `stop-color` プロパティ向けのカラーピッカーが表示されるようになりました。 ([1351096](https://crbug.com/1351096)) -- **Performance Insights** パネルで、レイアウトシフトの潜在的な根本原因として [レイアウト](https://web.dev/avoid-large-complex-layouts-and-layout-thrashing/) を引き起こすスクリプトを特定します。 ([1343019](https://crbug.com/1343019)) +- **Performance Insights** パネルで、レイアウトシフトの潜在的な根本原因として [レイアウト](https://web.dev/articles/avoid-large-complex-layouts-and-layout-thrashing) を引き起こすスクリプトを特定します。 ([1343019](https://crbug.com/1343019)) - **Performance Insights** パネルに LCP Web フォントのクリティカルパスを表示します。 ([1350390](https://crbug.com/1350390)) {# https://chromium.googlesource.com/devtools/devtools-frontend/+/50a84ca8e5b556e27bb285477f21a99f0ccb7050 #} diff --git a/site/ja/blog/new-in-devtools-112/index.md b/site/ja/blog/new-in-devtools-112/index.md index ee3068869..1d86ee6bb 100644 --- a/site/ja/blog/new-in-devtools-112/index.md +++ b/site/ja/blog/new-in-devtools-112/index.md @@ -54,8 +54,8 @@ Chromium issue: [1400243](https://crbug.com/1400243). <!-- In addition to [custom, CSS, ARIA, text, and XPath selectors](/docs/devtools/recorder/reference/#selector), you can now record using [pierce selectors](https://pptr.dev/guides/query-selectors#pierce-selectors-pierce). These selectors behave like CSS ones but can also pierce through shadow roots. --> [カスタム、CSS、ARIA、テキスト、XPathセレクタ](/docs/devtools/recorder/reference/#selector)に加えて、[ピアスセレクタ](https://pptr.dev/guides/query-selectors#pierce-selectors-pierce)を使用して記録できるようになりました。これらのセレクタはCSSのセレクタと同じように振る舞いますが、シャドウルートを貫通することもできます。 -<!-- Start a new recording on a page with [shadow DOM](https://web.dev/shadowdom-v1/) and check {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/hmp8j3HiLMCcqPArD9yt.svg", alt="Checkbox.", width="22", height="22" %} **Pierce** in **Selector types to record**. Record your interaction with elements in the shadow DOM and inspect the corresponding step. --> -[Shadow DOM](https://web.dev/shadowdom-v1/)が含まれるページで新規レコードを開始し、**Selector types to record**で {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/hmp8j3HiLMCcqPArD9yt.svg", alt="Checkbox.", width="22", height="22" %} **Pierce** にチェックをつけます。Shadow DOMの中の要素とのインタラクションを記録し、対応するステップを検査します。 +<!-- Start a new recording on a page with [shadow DOM](https://web.dev/articles/shadowdom-v1) and check {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/hmp8j3HiLMCcqPArD9yt.svg", alt="Checkbox.", width="22", height="22" %} **Pierce** in **Selector types to record**. Record your interaction with elements in the shadow DOM and inspect the corresponding step. --> +[Shadow DOM](https://web.dev/articles/shadowdom-v1)が含まれるページで新規レコードを開始し、**Selector types to record**で {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/hmp8j3HiLMCcqPArD9yt.svg", alt="Checkbox.", width="22", height="22" %} **Pierce** にチェックをつけます。Shadow DOMの中の要素とのインタラクションを記録し、対応するステップを検査します。 {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/Spqbf2DG3Fr0D2sc1kgC.png", alt="ピアスセレクタを使った Recorder の設定; 作動中のピアスセレクタ", width="800", height="534" %} diff --git a/site/ja/blog/new-in-devtools-93/index.md b/site/ja/blog/new-in-devtools-93/index.md index 400d7da82..5d68c4c22 100644 --- a/site/ja/blog/new-in-devtools-93/index.md +++ b/site/ja/blog/new-in-devtools-93/index.md @@ -27,9 +27,9 @@ tags: --> ## Styles ペインで CSS コンテナクエリを編集 {: #container-queries } <!-- -You can now view and edit [CSS container queries](https://web.dev/new-responsive/#responsive-to-the-container) in the **Styles** pane. +You can now view and edit [CSS container queries](https://web.dev/articles/new-responsive#responsive_to_the_container) in the **Styles** pane. --> -**Styles** ペインで[CSS コンテナクエリ](https://web.dev/new-responsive/#responsive-to-the-container)を確認して編集できるようになりました。 +**Styles** ペインで[CSS コンテナクエリ](https://web.dev/articles/new-responsive#responsive_to_the_container)を確認して編集できるようになりました。 <!-- Container queries provide a much more dynamic approach to responsive design. The `@container` at-rule works in a similar way to a media query with `@media`. However, instead of querying the viewport and user agent for information, `@container` queries the ancestor container that matches certain criteria. @@ -60,9 +60,9 @@ Chromium issue: [1146422](https://crbug.com/1146422) --> ## NetworkパネルでWeb Bundleをプレビュー {: #web-bundle } <!-- -[Web bundle](https://web.dev/web-bundles/) is a file format for encapsulating one or more HTTP resources in a single file. You can now preview the web bundle content in the **Network** panel. +[Web bundle](https://web.dev/articles/web-bundles) is a file format for encapsulating one or more HTTP resources in a single file. You can now preview the web bundle content in the **Network** panel. --> -[Web Bundle](https://web.dev/web-bundles/) はひとつ以上の HTTP リソースを単一のファイルにカプセル化するためのファイルフォーマットです。**Network** パネルでこの Web Bundle のコンテンツをプレビューできるようになりました。 +[Web Bundle](https://web.dev/articles/web-bundles) はひとつ以上の HTTP リソースを単一のファイルにカプセル化するためのファイルフォーマットです。**Network** パネルでこの Web Bundle のコンテンツをプレビューできるようになりました。 <!-- The web bundle feature is experimental currently. Please enable `#enable-experimental-web-platform-features` flag under `chrome://flags` to test it. diff --git a/site/ja/blog/new-in-devtools-96/index.md b/site/ja/blog/new-in-devtools-96/index.md index e6257ef19..70fb534e8 100644 --- a/site/ja/blog/new-in-devtools-96/index.md +++ b/site/ja/blog/new-in-devtools-96/index.md @@ -214,7 +214,7 @@ Chromium issue: [1214030](https://crbug.com/1214030) {# https://chromium.googlesource.com/devtools/devtools-frontend/+/f1574e9b550317c481a943fec059d84bfb863564 #} -Chromium issue: [1226262](https://crbug.com/1226262) +Chromium issue: [1226262](https://crbug.com/1226262) <!-- ## Console updates --> @@ -307,13 +307,13 @@ Chromium issues: [1232937](https://crbug.com/1232937), [1255586](https://crbug.c ## Application パネルの Application cache ペインの廃止 {: #app-cache } -<!-- The [Application cache](/docs/devtools/storage/applicationcache/) pane in the Application panel is now removed as the support for [AppCache](https://web.dev/appcache-removal/) is removed from Chrome and other Chromium-based browsers. --> +<!-- The [Application cache](/docs/devtools/storage/applicationcache/) pane in the Application panel is now removed as the support for [AppCache](https://web.dev/articles/appcache-removal) is removed from Chrome and other Chromium-based browsers. --> -Chrome やその他の Chromium ベースのブラウザから [AppCache](https://web.dev/appcache-removal/) のサポートが外れることに伴い、Application パネルの [Application cache](/docs/devtools/storage/applicationcache/) は削除されます。 +Chrome やその他の Chromium ベースのブラウザから [AppCache](https://web.dev/articles/appcache-removal) のサポートが外れることに伴い、Application パネルの [Application cache](/docs/devtools/storage/applicationcache/) は削除されます。 {# https://chromium.googlesource.com/devtools/devtools-frontend/+/de4d15e955d6145674e3885cde8a5a70f1269b79 #} -Chromium issue: [1084190](https://crbug.com/1084190) +Chromium issue: [1084190](https://crbug.com/1084190) <!-- ## [Experimental] New Reporting API pane in the Application panel {: #reporting-api } --> @@ -326,9 +326,9 @@ Chromium issue: [1084190](https://crbug.com/1084190) 実験的な機能を有効にするには、**Settings** > **Experiments** の中の **Enable Reporting API panel in the Application panel** チェックボックスをチェックしてください。 {% endAside %} -<!-- The [Reporting API](https://web.dev/reporting-api/) is designed to help you monitor security violations of your page, deprecated API calls, and more. --> +<!-- The [Reporting API](https://web.dev/articles/reporting-api) is designed to help you monitor security violations of your page, deprecated API calls, and more. --> -[Reporting API](https://web.dev/reporting-api/) はページのセキュリティ違反や廃止されたAPIの利用などの監視を助けるように用意されています。 +[Reporting API](https://web.dev/articles/reporting-api) はページのセキュリティ違反や廃止されたAPIの利用などの監視を助けるように用意されています。 <!-- With this experiment enabled, you can now view the reports status in the new **Reporting API** pane in the **Application** panel. --> @@ -338,9 +338,9 @@ Chromium issue: [1084190](https://crbug.com/1084190) **Endpoints** セクションは現在のところまだ開発が非常に活発であることに注意してください(今はレポーティングのエンドポイントは表示されません)。 -<!-- Learn more about the **Reporting API** with [this article](https://web.dev/reporting-api/). --> +<!-- Learn more about the **Reporting API** with [this article](https://web.dev/articles/reporting-api). --> -**Reporting API** についてより詳しく知るには[この記事](https://web.dev/reporting-api/)を見てください。 +**Reporting API** についてより詳しく知るには[この記事](https://web.dev/articles/reporting-api)を見てください。 <!-- {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/hbwFqi9aNDOj70FhLXsn.png", alt="Reporting API pane in the Application panel", width="800", height="476" %} diff --git a/site/ja/blog/new-in-devtools-98/index.md b/site/ja/blog/new-in-devtools-98/index.md index 2c0cc6dab..5ca120b61 100644 --- a/site/ja/blog/new-in-devtools-98/index.md +++ b/site/ja/blog/new-in-devtools-98/index.md @@ -56,7 +56,7 @@ Chromium issue: [887173](https://crbug.com/887173) <!-- ## More precise changes in the Changes tab {: #changes } --> -## Changes タブで変更点のよりわかりやすい表示 {: #changes } +## Changes タブで変更点のよりわかりやすい表示 {: #changes } <!-- The code changes in the **Changes** tab is pretty-printed automatically. --> **Changes** タブのコード変更点は、自動的にプリティプリントされます。 @@ -86,7 +86,7 @@ Chromium issues: [1238818](https://crbug.com/1238818), [1268754](https://crbug.c <!-- Optionally, you can adjust the **Timeout** in the **Replay settings** for all the steps. Expand the **Replay settings** and edit the **Timeout** value. --> **Replay settings** の中ですべてのステップの **Timeout** を調整することができます。 **Replay settings** を展開し、 **Timeout** の値を編集します。 - + <!-- {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/y7RDpIp3pd2n6Vnxc5Du.png", alt="timeout settings for user flow recording", width="800", height="530" %} --> {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/y7RDpIp3pd2n6Vnxc5Du.png", alt="ユーザーフロー記録のタイムアウト設定", width="800", height="530" %} @@ -96,8 +96,8 @@ Chromium issue: [1257499](https://crbug.com/1257499) <!-- ## Ensure your pages are cacheable with the Back/forward cache tab {: #bfcache } --> ## Back/forward cache タブでページがキャッシュ可能であることを確認する {: #bfcache } -<!-- [Back/forward cache (or bfcache)](https://web.dev/bfcache/) is a browser optimization that enables instant back and forward navigation. --> -[Back/forward cache (または bfcache)](https://web.dev/bfcache/) は、高速な戻る、進むを可能にするブラウザの最適化です。 +<!-- [Back/forward cache (or bfcache)](https://web.dev/articles/bfcache) is a browser optimization that enables instant back and forward navigation. --> +[Back/forward cache (または bfcache)](https://web.dev/articles/bfcache) は、高速な戻る、進むを可能にするブラウザの最適化です。 <!-- The new **Back/forward cache** tab can help you test your pages to ensure they're optimized for bfcache, and identify any issues that may be preventing them from being eligible. --> 新しい **Back/forward cache** タブは、ページが bfcache に最適化されているかどうかをテストし、対象外となる可能性がある問題を特定するのに役立ちます。 @@ -131,8 +131,8 @@ Chromium issue: [1110752](https://crbug.com/1110752) <!-- {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/ewmNloO4ohRxlWRNuEW1.png", alt="Properties pane filter", width="800", height="505" %} --> {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/ewmNloO4ohRxlWRNuEW1.png", alt="Properties ペインフィルター", width="800", height="505" %} -{# https://chromium.googlesource.com/devtools/devtools-frontend/+/0980f52facf75b6c03e14472d13fe27968d4732b #} - +{# https://chromium.googlesource.com/devtools/devtools-frontend/+/0980f52facf75b6c03e14472d13fe27968d4732b #} + Chromium issue: [1269674](https://crbug.com/1269674) @@ -200,7 +200,7 @@ Chromium issue: [1263866](https://crbug.com/1263866) Chromium issue: [1050021](https://crbug.com/1050021) - + <!-- ### Keyboard shortcut to expand all search results {: #toggle-search-result } --> ### 検索結果をすべて展開するキーボードショートカット {: #toggle-search-result } @@ -229,8 +229,8 @@ Chromium issue: [1255073](https://crbug.com/1255073) <!-- The **Lighthouse** panel is now running Lighthouse 9. Lighthouse will now list all the elements sharing the same id. --> **Lighthouse** パネルで Lighthouse 9が動作するようになりました。 Lighthouse は、同じ id を共有するすべての要素をリストアップするようになりました。 -<!-- Non-unique element id is a common accessibility problem. For instance, the id referenced in an `aria-labelledby` attribute is used on [multiple elements](https://web.dev/duplicate-id-aria/). --> -要素の id が一意でないことはよくあるアクセシビリティ上の問題です。例えば、 `aria-labelledby` 属性で参照される id が[複数の要素](https://web.dev/duplicate-id-aria/)で使用されていることがあります。 +<!-- Non-unique element id is a common accessibility problem. For instance, the id referenced in an `aria-labelledby` attribute is used on [multiple elements](https://web.dev/articles/duplicate-id-aria). --> +要素の id が一意でないことはよくあるアクセシビリティ上の問題です。例えば、 `aria-labelledby` 属性で参照される id が[複数の要素](https://web.dev/articles/duplicate-id-aria)で使用されていることがあります。 <!-- Check out the [What’s new in Lighthouse 9.0](/blog/lighthouse-9-0/) for more details on the updates. --> アップデートの詳細は、 [What's new in Lighthouse 9.0](/blog/lighthouse-9-0/) をご確認ください。 @@ -253,11 +253,11 @@ Chromium issue: [772558](https://crbug.com/772558) - Improved auto-complete suggestions for editable sources (e.g. snippets, local override) --> - 大きなファイル(WASM 、 JavaScript など)を開く際の大幅な高速化 - コードを読み進める際のランダムなスクロールを解消 -- 編集可能なソース(スニペット、ローカルオーバーライドなど)に対するオートコンプリートの候補を改善 +- 編集可能なソース(スニペット、ローカルオーバーライドなど)に対するオートコンプリートの候補を改善 {# https://chromium.googlesource.com/devtools/devtools-frontend/+/c1ab112d9002d5c3b3bb70cf2839bac182f0cdb5 #} -Chromium issue: [1241848](https://crbug.com/1241848) +Chromium issue: [1241848](https://crbug.com/1241848) <!-- ## Miscellaneous highlights {: #misc } --> ## その他のハイライト {: #misc } @@ -267,12 +267,12 @@ Chromium issue: [1241848](https://crbug.com/1241848) <!-- - Properly displaying the waterfall diagram of network requests. Previously, the style was broken. ([1275501](https://crbug.com/1275501)) - The code highlight was broken when searching in documents with very long lines in the **Sources** panel. It’s now fixed. ([1275496](https://crbug.com/1275496)) -- No more duplicate **Payload** tab in network requests. ([1273972](https://crbug.com/1273972)) +- No more duplicate **Payload** tab in network requests. ([1273972](https://crbug.com/1273972)) - Fixed the missing layout shifts details in the **Summary** section of the **Performance** panel. ([1259606](https://crbug.com/1259606)) - Support arbitrary characters (e.g. `,`, `.`), in **Network Search** queries. ([1267196](https://crbug.com/1267196)) --> - ネットワークリクエストのウォーターフォール図を正しく表示するようにしました。以前は、スタイルが崩れていました ([1275501](https://crbug.com/1275501)) - **Source** パネルで非常に長い行のドキュメントで検索すると、コードハイライトが壊れていました。これは現在修正されています ([1275496](https://crbug.com/1275496)) -- ネットワークリクエストで、 **Payload** タブが重複しないようになりました ([1273972](https://crbug.com/1273972)) +- ネットワークリクエストで、 **Payload** タブが重複しないようになりました ([1273972](https://crbug.com/1273972)) - **Performance** パネルの **Summary** セクションのレイアウトシフトの詳細が欠落していたのを修正しました ([1259606](https://crbug.com/1259606)) - **Network Search** のクエリで、任意の文字(例:`,`や`.`)をサポートしました ([1267196](https://crbug.com/1267196)) @@ -291,13 +291,13 @@ Chromium issue: [1241848](https://crbug.com/1241848) <!-- The **Endpoints** section is now available. It gives you an overview of all the endpoints configured in the `Reporting-Endpoints` header. --> **Endpoints** セクションが利用可能になりました。これは `Reporting-Endpoints` ヘッダで設定されたすべてのエンドポイントの概要を提供します。 -<!-- Learn to use the [Reporting API](https://web.dev/reporting-api/) to monitor security violations, deprecated API calls, and more. --> -[Reporting API](https://web.dev/reporting-api/) を使用してセキュリティ違反や非推奨の API コールなどを監視する方法を学びましょう。 +<!-- Learn to use the [Reporting API](https://web.dev/articles/reporting-api) to monitor security violations, deprecated API calls, and more. --> +[Reporting API](https://web.dev/articles/reporting-api) を使用してセキュリティ違反や非推奨の API コールなどを監視する方法を学びましょう。 <!-- {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/D1fUz4zuS1xwDbszgft1.png", alt="Reporting API pane", width="800", height="560" %} --> {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/D1fUz4zuS1xwDbszgft1.png", alt="Reporting API ペイン", width="800", height="560" %} -{# https://chromium.googlesource.com/devtools/devtools-frontend/+/a831b26b7ecde579144a42a4faaa7b639789bf3c #} +{# https://chromium.googlesource.com/devtools/devtools-frontend/+/a831b26b7ecde579144a42a4faaa7b639789bf3c #} Chromium issue: [1200732](https://crbug.com/1200732) diff --git a/site/ja/blog/new-in-devtools-99/index.md b/site/ja/blog/new-in-devtools-99/index.md index 387c2ef11..510c79a64 100644 --- a/site/ja/blog/new-in-devtools-99/index.md +++ b/site/ja/blog/new-in-devtools-99/index.md @@ -56,9 +56,9 @@ Chromium issue: [423246](https://crbug.com/423246) 新しく追加された **Reporting API** ペインを使用すると、そのページで生成されるレポートやそれらの状況を監視できます。 -<!-- The [Reporting API](https://web.dev/reporting-api/) is designed to help you monitor security violations of your page, deprecated API calls, and more. --> +<!-- The [Reporting API](https://web.dev/articles/reporting-api) is designed to help you monitor security violations of your page, deprecated API calls, and more. --> -[Reporting API](https://web.dev/reporting-api/) はセキュリティ違反や廃止されるAPIの呼び出しなどを監視できるように設計されています。 +[Reporting API](https://web.dev/articles/reporting-api) はセキュリティ違反や廃止されるAPIの呼び出しなどを監視できるように設計されています。 <!-- Open a page which uses the Reporting API (e.g. [demo page](https://reporting-api-demo.glitch.me/)). In the **Application** panel, scroll down to the **Background services** section and select the **Reporting API** pane. --> @@ -211,9 +211,9 @@ Chromium issue: [1284737](https://crbug.com/1284737) ### Sources パネルにワーカーのソースファイルを表示 {: #worker-sourcemap } -<!-- [Worker](https://web.dev/workers-overview/) (e.g. web worker, service worker) source files with relative SourceURL are now displayed in the **Source** panel. Previously, worker source files were not handled correctly. --> +<!-- [Worker](https://web.dev/articles/workers-overview) (e.g. web worker, service worker) source files with relative SourceURL are now displayed in the **Source** panel. Previously, worker source files were not handled correctly. --> -相対 SourceURL を持つ [Worker](https://web.dev/workers-overview/)(例、Web Worker、Service Worker)のソースファイルが **Source** パネルに表示されるようになりました。これまでは、ワーカーのソースファイルは正しく扱われませんでした。 +相対 SourceURL を持つ [Worker](https://web.dev/articles/workers-overview)(例、Web Worker、Service Worker)のソースファイルが **Source** パネルに表示されるようになりました。これまでは、ワーカーのソースファイルは正しく扱われませんでした。 <!-- {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/apH5n92bqYWINMQn5VXa.png", alt="ALT_TEXT_HERE", width="800", height="509" %} --> @@ -281,10 +281,10 @@ Chromium issues: [1284245](https://crbug.com/1284245), [1284995](https://crbug.c - **Cookies** ペインの [Cookie 編集](/docs/devtools/storage/cookies/#edit)に関する問題が修正されました。 ([1290196](https://crbug.com/1290196)) <!-- - Use `Shift` + `Tab` to select the previous command in the [Command menu](/docs/devtools/command-menu/). ([1278743](https://crbug.com/1278743)) --> - [コマンドメニュー](/docs/devtools/command-menu/)で `Shift` + `Tab` を使用して以前のコマンドを選択できます。 ([1278743](https://crbug.com/1278743)) -<!-- - Report [CORS preflight request](https://web.dev/cross-origin-resource-sharing/#preflight-requests-for-complex-http-calls) issues in the [Issues](/docs/devtools/issues/) tab. ([1272445](https://crbug.com/1272445)). --> -- [CORS プリフライトリクエスト](https://web.dev/cross-origin-resource-sharing/#preflight-requests-for-complex-http-calls)の問題が [Issues](/docs/devtools/issues/) タブでレポートされるようになりました。 ([1272445](https://crbug.com/1272445)). -<!-- - Report [User-Agent Client Hints](https://web.dev/user-agent-client-hints/) issues in the [Issues](/docs/devtools/issues/) tab. ([1219359](https://crbug.com/1219359)). --> -- [User-Agent Client Hints](https://web.dev/user-agent-client-hints/) の問題が [Issues](/docs/devtools/issues/) タブでレポートされるようになりました。 ([1272445](https://crbug.com/1272445)). +<!-- - Report [CORS preflight request](https://web.dev/articles/cross-origin-resource-sharing#preflight_requests_for_complex_http_calls) issues in the [Issues](/docs/devtools/issues/) tab. ([1272445](https://crbug.com/1272445)). --> +- [CORS プリフライトリクエスト](https://web.dev/articles/cross-origin-resource-sharing#preflight_requests_for_complex_http_calls)の問題が [Issues](/docs/devtools/issues/) タブでレポートされるようになりました。 ([1272445](https://crbug.com/1272445)). +<!-- - Report [User-Agent Client Hints](https://web.dev/articles/user-agent-client-hints) issues in the [Issues](/docs/devtools/issues/) tab. ([1219359](https://crbug.com/1219359)). --> +- [User-Agent Client Hints](https://web.dev/articles/user-agent-client-hints) の問題が [Issues](/docs/devtools/issues/) タブでレポートされるようになりました。 ([1272445](https://crbug.com/1272445)). <!-- - Fixed `Shift` + `Delete` and `Page up` / `Page down` behaviors in the **Sources** and **Console** panel. ([1278461](https://crbug.com/1278461), [1285662](https://crbug.com/1285662)) --> - **Sources** パネルと **Console** パネルでの `Shift` + `Delete` と `Page up` / `Page down` の動作が修正されました。 ([1278461](https://crbug.com/1278461), [1285662](https://crbug.com/1285662)) <!-- - Close the breakpoint edit dialog on breakpoint removal in the **Sources** panel. (922513) --> diff --git a/site/ja/blog/user-agent-reduction-deprecation-trial/index.md b/site/ja/blog/user-agent-reduction-deprecation-trial/index.md index a29c46507..f1f6e9429 100644 --- a/site/ja/blog/user-agent-reduction-deprecation-trial/index.md +++ b/site/ja/blog/user-agent-reduction-deprecation-trial/index.md @@ -13,7 +13,7 @@ tags: - chrome-101 --- -Chrome 101 以降、User-Agent(UA)文字列で利用できる情報量は、[段階的なアプローチに沿って](https://blog.chromium.org/2021/09/user-agent-reduction-origin-trial-and-dates.html)削減されます。削減された User-Agent 文字列の使用から [User-Agent Client Hints に移行](https://web.dev/migrate-to-ua-ch/)する時間がないサイトは、デプリケーション トライアルに参加すると、完全な User-Agent 文字列を引き続き受け取ることができます。 +Chrome 101 以降、User-Agent(UA)文字列で利用できる情報量は、[段階的なアプローチに沿って](https://blog.chromium.org/2021/09/user-agent-reduction-origin-trial-and-dates.html)削減されます。削減された User-Agent 文字列の使用から [User-Agent Client Hints に移行](https://web.dev/articles/migrate-to-ua-ch)する時間がないサイトは、デプリケーション トライアルに参加すると、完全な User-Agent 文字列を引き続き受け取ることができます。 デプリケーション トライアルへの登録は、[Chrome 100](https://chromiumdash.appspot.com/schedule) ベータ版から開始されます。これにより、マイナーバージョン文字列が削減される Chrome 101 リリースの前に、サイトは完全な User-Agent 文字列を受け取れるようになります。安定版チャンネルにリリースされる前に Chrome 100 ベータ版でオリジン トライアルをテストしたい場合は、必ず Chrome 100 のリリース日([現時点では 2022 年 3 月 31 日を予定](https://chromiumdash.appspot.com/schedule))までに登録を済ませてテストしてください。 @@ -28,7 +28,7 @@ Chrome 101 以降、User-Agent(UA)文字列で利用できる情報量は、 - `navigator.platform` Javascript ゲッター - `navigator.appVersion` Javascript ゲッター -サイトは引き続き User-Agent ヘッダーと関連する API の使用状況を監査し、必要に応じてデプリケーション トライアルが終了する前に [User-Agent Client Hints に移行](https://web.dev/migrate-to-ua-ch/)する準備をする必要があります。[User-Agent 削減のロールアウト](https://blog.chromium.org/2021/09/user-agent-reduction-origin-trial-and-dates.html)が完了したら、このデプリケーション トライアルを終了することが目的です。 +サイトは引き続き User-Agent ヘッダーと関連する API の使用状況を監査し、必要に応じてデプリケーション トライアルが終了する前に [User-Agent Client Hints に移行](https://web.dev/articles/migrate-to-ua-ch)する準備をする必要があります。[User-Agent 削減のロールアウト](https://blog.chromium.org/2021/09/user-agent-reduction-origin-trial-and-dates.html)が完了したら、このデプリケーション トライアルを終了することが目的です。 ## User-Agent 削減デプリケーション トライアルへの参加方法 diff --git a/site/ja/blog/user-agent-reduction-oct-2022-updates/index.md b/site/ja/blog/user-agent-reduction-oct-2022-updates/index.md index 813b16680..af58c126b 100644 --- a/site/ja/blog/user-agent-reduction-oct-2022-updates/index.md +++ b/site/ja/blog/user-agent-reduction-oct-2022-updates/index.md @@ -22,7 +22,7 @@ User-Agent 文字列には、ブラウザとユーザーが使用しているデ とは言え、UA 文字列は最新の Web プライバシーの期待を満たしていません。デフォルトでは、User-Agent 文字列から、Web 中のユーザーの識別とトラッキングに使用できる情報を得られます。また、すべての Web サイトやサービスが UA 文字列が提供する情報を必要とするわけではありません。 -そのため、Chrome では UA 文字列でデフォルトで共有される情報を削減し、サイトやサービスが必要な情報のみをリクエストできるようにうする User-Agent Client Hints(UA-CH)という[新しい API](https://web.dev/user-agent-client-hints/) を導入しています。この計画を最初に[発表](https://groups.google.com/a/chromium.org/g/blink-dev/c/-2JIRNMWJ7s/m/yHe4tQNLCgAJ)したのは 2020 年 1 月で、 [段階的なロードマップ](https://blog.chromium.org/2021/05/update-on-user-agent-string-reduction.html)を 2021 年 5 月に共有しました。この変更により、UA 文字列の情報の制限において、Chrome と他のブラウザの機能が同調されます。 +そのため、Chrome では UA 文字列でデフォルトで共有される情報を削減し、サイトやサービスが必要な情報のみをリクエストできるようにうする User-Agent Client Hints(UA-CH)という[新しい API](https://web.dev/articles/user-agent-client-hints) を導入しています。この計画を最初に[発表](https://groups.google.com/a/chromium.org/g/blink-dev/c/-2JIRNMWJ7s/m/yHe4tQNLCgAJ)したのは 2020 年 1 月で、 [段階的なロードマップ](https://blog.chromium.org/2021/05/update-on-user-agent-string-reduction.html)を 2021 年 5 月に共有しました。この変更により、UA 文字列の情報の制限において、Chrome と他のブラウザの機能が同調されます。 ## 段階的アプローチ diff --git a/site/ja/blog/user-agent-reduction-origin-trial/index.md b/site/ja/blog/user-agent-reduction-origin-trial/index.md index 9f80b6659..c4d6e1996 100644 --- a/site/ja/blog/user-agent-reduction-origin-trial/index.md +++ b/site/ja/blog/user-agent-reduction-origin-trial/index.md @@ -37,9 +37,9 @@ User-Agent 削減は、Chrome ブラウザのパッシブ フィンガープリ - `navigator.platform` Javascript ゲッター - `navigator.appVersion` Javascript ゲッター -削減された User-Agent によって共有されるものよりも多くのクライアント情報を受け取るには、サイトを新しい User-Agent [Client Hints](https://web.dev/migrate-to-ua-ch/) API に移行する必要があります。移行戦略の詳細については、「[User-Agent Client Hints への移行](https://web.dev/migrate-to-ua-ch/)」をご覧ください。 +削減された User-Agent によって共有されるものよりも多くのクライアント情報を受け取るには、サイトを新しい User-Agent [Client Hints](https://web.dev/articles/migrate-to-ua-ch) API に移行する必要があります。移行戦略の詳細については、「[User-Agent Client Hints への移行](https://web.dev/articles/migrate-to-ua-ch)」をご覧ください。 -現在、User-Agent 削減計画には iOS と WebView が含まれていないため、これらのプラットフォームは引き続き完全な User Agent 文字列を取得します。主に、これらのプラットフォームがまだ User-Agent [Client Hints](https://web.dev/migrate-to-ua-ch/) を実装していないことがその理由です。 +現在、User-Agent 削減計画には iOS と WebView が含まれていないため、これらのプラットフォームは引き続き完全な User Agent 文字列を取得します。主に、これらのプラットフォームがまだ User-Agent [Client Hints](https://web.dev/articles/migrate-to-ua-ch) を実装していないことがその理由です。 ## このオリジントライアルの仕組み diff --git a/site/ja/docs/lighthouse/best-practices/external-anchors-use-rel-noopener/index.md b/site/ja/docs/lighthouse/best-practices/external-anchors-use-rel-noopener/index.md index e9218a896..580ea5e70 100644 --- a/site/ja/docs/lighthouse/best-practices/external-anchors-use-rel-noopener/index.md +++ b/site/ja/docs/lighthouse/best-practices/external-anchors-use-rel-noopener/index.md @@ -45,10 +45,10 @@ Lighthouseレポートで識別された各リンクに`rel="noopener"`または - `rel="noopener"`によって、新しいページは`window.opener`プロパティにアクセスできなくなり、別のプロセスで実行されるようになります。 - `rel="noreferrer"`も同じ効果がありますが、 `Referer`ヘッダーが新しいページに送信されないようにします。「["noreferrer" リンクタイプ](https://html.spec.whatwg.org/multipage/links.html#link-type-noreferrer)」をご覧ください。 -詳細については、「[クロスオリジンリソースを安全に共有する](https://web.dev/cross-origin-resource-sharing/)」をご覧ください。 +詳細については、「[クロスオリジンリソースを安全に共有する](https://web.dev/articles/cross-origin-resource-sharing)」をご覧ください。 ## リソース - [**安全でないクロスオリジン宛先へのリンク**監査のソースコード](https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js) -- [クロスオリジンリソースを安全に共有する](https://web.dev/cross-origin-resource-sharing/) +- [クロスオリジンリソースを安全に共有する](https://web.dev/articles/cross-origin-resource-sharing) - [ウェブ開発者向けのサイト分離](https://developers.google.com/web/updates/2018/07/site-isolation) diff --git a/site/ja/docs/lighthouse/performance/bootup-time/index.md b/site/ja/docs/lighthouse/performance/bootup-time/index.md index 79d5e8bed..1ff3dc39e 100644 --- a/site/ja/docs/lighthouse/performance/bootup-time/index.md +++ b/site/ja/docs/lighthouse/performance/bootup-time/index.md @@ -20,7 +20,7 @@ JavaScriptの実行に時間がかかると、ページのパフォーマンス - **実行コスト** - JavaScriptもまた、メインスレッドで実行されます。ページがその時点ではまだ必要のないコードを数多く実行してしまうと、[Time to Interactive (インタラクティブになるまでの時間)](https://web.dev/tti/) (ユーザーがどのようにページの速度を認識しているかを判断するための主な指標の1つ) も遅延します。 + JavaScriptもまた、メインスレッドで実行されます。ページがその時点ではまだ必要のないコードを数多く実行してしまうと、[Time to Interactive (インタラクティブになるまでの時間)](https://web.dev/articles/tti) (ユーザーがどのようにページの速度を認識しているかを判断するための主な指標の1つ) も遅延します。 - **メモリコスト** diff --git a/site/ja/docs/lighthouse/performance/critical-request-chains/index.md b/site/ja/docs/lighthouse/performance/critical-request-chains/index.md index e1b8d2956..9d1dd6f88 100644 --- a/site/ja/docs/lighthouse/performance/critical-request-chains/index.md +++ b/site/ja/docs/lighthouse/performance/critical-request-chains/index.md @@ -28,7 +28,7 @@ Lighthouseは、レンダリングをブロックする重要なリソースを - 重要なバイト数を最適化して、ダウンロード時間 (ラウンドトリップ数) を減らします。 - 残りの重要なリソースが読み込まれる順序を最適化します。クリティカルパスの長さを短くするために、すべてのクリティカルアセットをできるだけ早くダウンロードします。 -[画像](https://web.dev/use-imagemin-to-compress-images/)、[JavaScript](https://web.dev/apply-instant-loading-with-prpl/)、[CSS](https://web.dev/defer-non-critical-css/)、および[Webフォント](https://web.dev/avoid-invisible-text/)の最適化の詳細をご覧ください。 +[画像](https://web.dev/articles/use-imagemin-to-compress-images)、[JavaScript](https://web.dev/articles/apply-instant-loading-with-prpl)、[CSS](https://web.dev/articles/defer-non-critical-css)、および[Webフォント](https://web.dev/articles/avoid-invisible-text)の最適化の詳細をご覧ください。 ## スタック固有のガイダンス diff --git a/site/ja/docs/lighthouse/performance/dom-size/index.md b/site/ja/docs/lighthouse/performance/dom-size/index.md index 8e35452d0..7061bd236 100644 --- a/site/ja/docs/lighthouse/performance/dom-size/index.md +++ b/site/ja/docs/lighthouse/performance/dom-size/index.md @@ -49,11 +49,11 @@ Lighthouse は DOM ツリーのあるページに以下のようなフラグを ### Angular -大規模なリストをレンダリングする場合は、Component Dev Kit(CDK)の[仮想スクロール](https://web.dev/virtualize-lists-with-angular-cdk/)を使用してください。 +大規模なリストをレンダリングする場合は、Component Dev Kit(CDK)の[仮想スクロール](https://web.dev/articles/virtualize-lists-with-angular-cdk)を使用してください。 ### React -- ページで多数の反復要素をレンダリングしている場合は、[`react-window`](https://web.dev/virtualize-long-lists-react-window/) などの「ウィンドウイング」ライブラリを使用して、作成される DOM の数を最小限に抑えてください。 +- ページで多数の反復要素をレンダリングしている場合は、[`react-window`](https://web.dev/articles/virtualize-long-lists-react-window) などの「ウィンドウイング」ライブラリを使用して、作成される DOM の数を最小限に抑えてください。 - [`shouldComponentUpdate`](https://reactjs.org/docs/optimizing-performance.html#shouldcomponentupdate-in-action)、[`PureComponent`](https://reactjs.org/docs/react-api.html#reactpurecomponent)、または [`React.memo`](https://reactjs.org/docs/react-api.html#reactmemo) を使って、不要な再レンダリングを最小限に抑えてください。 - ランタイムのパフォーマンスを改善するために `Effect` フックを使用している場合は、特定の依存関係が変更するまでのみ[効果をスキップ](https://reactjs.org/docs/hooks-effect.html#tip-optimizing-performance-by-skipping-effects)してください。 diff --git a/site/ja/docs/lighthouse/performance/lighthouse-total-blocking-time/index.md b/site/ja/docs/lighthouse/performance/lighthouse-total-blocking-time/index.md index 90a823835..95af55fc6 100644 --- a/site/ja/docs/lighthouse/performance/lighthouse-total-blocking-time/index.md +++ b/site/ja/docs/lighthouse/performance/lighthouse-total-blocking-time/index.md @@ -16,7 +16,7 @@ Lighthouseのレポートには、TBTがミリ秒単位で表示されます。 ## TBTが測定するもの -TBTは、マウスのクリック、画面のタップ、キーボードの押下といったユーザー入力への応答がブロックされている合計時間を測定します。合計は、[First Contentful Paint (最初のコンテンツ描画にかかるまでの時間)](https://web.dev/fcp/) と [Time to Interactive (インタラクティブになるまでの時間)](https://web.dev/tti/) の間に実行されるすべての[長いタスク](https://web.dev/long-tasks-devtools/)の*ブロック部分*を加算することで算出されます。長いタスクとは、50ミリ秒を超えて実行されるタスクのことです。50msを超えた後の時間がブロック部分です。たとえば、Lighthouseが70ミリ秒の長さのタスクを検出した場合、ブロック部分は20ミリ秒になります。 +TBTは、マウスのクリック、画面のタップ、キーボードの押下といったユーザー入力への応答がブロックされている合計時間を測定します。合計は、[First Contentful Paint (最初のコンテンツ描画にかかるまでの時間)](https://web.dev/articles/fcp) と [Time to Interactive (インタラクティブになるまでの時間)](https://web.dev/articles/tti) の間に実行されるすべての[長いタスク](https://web.dev/articles/long-tasks-devtools)の*ブロック部分*を加算することで算出されます。長いタスクとは、50ミリ秒を超えて実行されるタスクのことです。50msを超えた後の時間がブロック部分です。たとえば、Lighthouseが70ミリ秒の長さのタスクを検出した場合、ブロック部分は20ミリ秒になります。 ## LighthouseがTBTスコアを決定する方法 @@ -53,11 +53,11 @@ TBTは、マウスのクリック、画面のタップ、キーボードの押 ## TBTスコアを改善する方法 -Chrome DevToolsのパフォーマンスパネルを使用して長いタスクの根本原因を診断する方法を[What is causing my long tasks? (長いタスクが発生する原因は何ですか?)](https://web.dev/long-tasks-devtools/#what-is-causing-my-long-tasks)と題した記事に記載していますので、ぜひ参照してください。 +Chrome DevToolsのパフォーマンスパネルを使用して長いタスクの根本原因を診断する方法を[What is causing my long tasks? (長いタスクが発生する原因は何ですか?)](https://web.dev/articles/long-tasks-devtools#what_is_causing_my_long_tasks)と題した記事に記載していますので、ぜひ参照してください。 一般に、長いタスクの最も一般的な原因は次のとおりです。 -- JavaScriptによる不要な読み込み、解析、または実行。パフォーマンスパネルでコードを分析していると、メインスレッドによってページの読み込みには不必要な作業が実行されていることに気付くことがあるかもしれません。[コードを分割してJavaScriptのペイロードを削減する](https://web.dev/reduce-javascript-payloads-with-code-splitting/)、[未使用のコードを除去する](https://web.dev/remove-unused-code/)、または[サードパーティのJavaScriptを効率的に読み込む](https://web.dev/efficiently-load-third-party-javascript/)ことを実践すれば、TBTスコアが向上するはずです。 +- JavaScriptによる不要な読み込み、解析、または実行。パフォーマンスパネルでコードを分析していると、メインスレッドによってページの読み込みには不必要な作業が実行されていることに気付くことがあるかもしれません。[コードを分割してJavaScriptのペイロードを削減する](https://web.dev/articles/reduce-javascript-payloads-with-code-splitting)、[未使用のコードを除去する](https://web.dev/articles/remove-unused-code)、または[サードパーティのJavaScriptを効率的に読み込む](https://web.dev/articles/efficiently-load-third-party-javascript)ことを実践すれば、TBTスコアが向上するはずです。 - JavaScriptの非効率的なステートメント。たとえば、[パフォーマンス]パネルでコードを分析した後、2000個のノードを返す`document.querySelectorAll('a')`の呼び出しがあることに気付くとします。10個のノードのみを返すもっと具体的なセレクタを使用するようにコードをリファクタリングすれば、TBTスコアは向上するはずです。 {% Aside %}JavaScriptによる不要な読み込みや解析、実行を見つければ、多くのサイトでは改善につなげる大きなチャンスとなります。{% endAside %} @@ -68,9 +68,9 @@ Chrome DevToolsのパフォーマンスパネルを使用して長いタスク - [**Total BlockingTime**監査のソースコード](https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/audits/metrics/total-blocking-time.js) - [Are long JavaScript tasks delaying your Time to Interactive? (JavaScriptの長いタスクがインタラクティブになるまでの時間を遅らせていませんか?)](https://web.dev/long-tasks-devtools) -- [Optimize First Input Delay (最初の入力の遅延を最適化する)](https://web.dev/optimize-fid/) -- [First Contentful Paint (最初のコンテンツ描画にかかるまでの時間)](https://web.dev/fcp/) -- [Time to Interactive (インタラクティブになるまでの時間)](https://web.dev/tti/) -- [Reduce JavaScript payloads with code splitting (コードを分割してJavaScriptのペイロードを削減する)](https://web.dev/reduce-javascript-payloads-with-code-splitting/) -- [Remove unused code (未使用のコードを除去うする)](https://web.dev/remove-unused-code/) -- [Efficiently load third-party resources (サードパーティのリソースを効率的に読み込む)](https://web.dev/efficiently-load-third-party-javascript/) +- [Optimize First Input Delay (最初の入力の遅延を最適化する)](https://web.dev/articles/optimize-fid) +- [First Contentful Paint (最初のコンテンツ描画にかかるまでの時間)](https://web.dev/articles/fcp) +- [Time to Interactive (インタラクティブになるまでの時間)](https://web.dev/articles/tti) +- [Reduce JavaScript payloads with code splitting (コードを分割してJavaScriptのペイロードを削減する)](https://web.dev/articles/reduce-javascript-payloads-with-code-splitting) +- [Remove unused code (未使用のコードを除去うする)](https://web.dev/articles/remove-unused-code) +- [Efficiently load third-party resources (サードパーティのリソースを効率的に読み込む)](https://web.dev/articles/efficiently-load-third-party-javascript) diff --git a/site/ja/docs/lighthouse/performance/non-composited-animations/index.md b/site/ja/docs/lighthouse/performance/non-composited-animations/index.md index 865acb96a..41d1f56c6 100644 --- a/site/ja/docs/lighthouse/performance/non-composited-animations/index.md +++ b/site/ja/docs/lighthouse/performance/non-composited-animations/index.md @@ -5,7 +5,7 @@ description: "「合成されていないアニメーションを避ける」灯 date: 2020-08-12 --- -合成されていないアニメーションは、ローエンドの電話で、またはパフォーマンスの高いタスクがメインスレッドで実行されている場合に、ぎくしゃくした(つまりスムーズではない)ように見えることがあります。[ぎこちないアニメーションは、ページの累積レイアウトシフト](https://web.dev/cls/)(CLS)を増やす可能性があります。 CLSを減らすと、LighthousePerformanceスコアが向上します。 +合成されていないアニメーションは、ローエンドの電話で、またはパフォーマンスの高いタスクがメインスレッドで実行されている場合に、ぎくしゃくした(つまりスムーズではない)ように見えることがあります。[ぎこちないアニメーションは、ページの累積レイアウトシフト](https://web.dev/articles/cls)(CLS)を増やす可能性があります。 CLSを減らすと、LighthousePerformanceスコアが向上します。 ## バックグラウンド @@ -27,12 +27,12 @@ HTML、CSS、およびJavaScriptをピクセルに変換するためのブラウ ## アニメーションを確実に合成する方法 -[コンポジターのみのプロパティに固執し、レイヤー数](https://developers.google.com/web/fundamentals/performance/rendering/stick-to-compositor-only-properties-and-manage-layer-count)と[高性能アニメーション](https://web.dev/animations-guide/)を管理するを参照してください。 +[コンポジターのみのプロパティに固執し、レイヤー数](https://developers.google.com/web/fundamentals/performance/rendering/stick-to-compositor-only-properties-and-manage-layer-count)と[高性能アニメーション](https://web.dev/articles/animations-guide)を管理するを参照してください。 ## 資力 - [合成されてい*ないアニメーションを回避する*監査のソースコード](https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/audits/non-composited-animations.js) - [コンポジターのみのプロパティに固執し、レイヤー数を管理します](https://developers.google.com/web/fundamentals/performance/rendering/stick-to-compositor-only-properties-and-manage-layer-count) -- [高性能アニメーション](https://web.dev/animations-guide/) +- [高性能アニメーション](https://web.dev/articles/animations-guide) - [ペイントの複雑さを簡素化し、ペイント領域を減らします](https://developers.google.com/web/fundamentals/performance/rendering/simplify-paint-complexity-and-reduce-paint-areas) - [最新のWebブラウザの内部を見る(パート3)](https://developers.google.com/web/updates/2018/09/inside-browser-part3) diff --git a/site/ja/docs/lighthouse/performance/third-party-facades/index.md b/site/ja/docs/lighthouse/performance/third-party-facades/index.md index aef6702aa..3e11c2367 100644 --- a/site/ja/docs/lighthouse/performance/third-party-facades/index.md +++ b/site/ja/docs/lighthouse/performance/third-party-facades/index.md @@ -5,7 +5,7 @@ description: ファサードを使用してサードパーティのリソース date: 2020-12-01 --- -[サードパーティのリソース](https://web.dev/third-party-javascript/)は、広告や動画の表示やソーシャルメディアとの統合でよく使用されます。デフォルトのアプローチでは、ページが読み込まれるとすぐにサードパーティのリソースが読み込まれますが、これによりページの読み込みが不必要に遅くなる可能性があります。サードパーティのコンテンツが重要でない場合は、[遅延読み込み](https://web.dev/fast/#lazy-load-images-and-video)を行うことで、このパフォーマンスコストを削減できます。 +[サードパーティのリソース](https://web.dev/articles/third-party-javascript)は、広告や動画の表示やソーシャルメディアとの統合でよく使用されます。デフォルトのアプローチでは、ページが読み込まれるとすぐにサードパーティのリソースが読み込まれますが、これによりページの読み込みが不必要に遅くなる可能性があります。サードパーティのコンテンツが重要でない場合は、[遅延読み込み](https://web.dev/articles/fast#lazy_load_images_and_video)を行うことで、このパフォーマンスコストを削減できます。 このレポートでは、操作時に遅延読み込みできるサードパーティの埋め込みに焦点を当てます。その場合、ユーザーが操作するまで、サードパーティのコンテンツの代わりに*ファサード*が使用されます。 diff --git a/site/ja/docs/lighthouse/performance/uses-optimized-images/index.md b/site/ja/docs/lighthouse/performance/uses-optimized-images/index.md index c6e889951..244070e92 100644 --- a/site/ja/docs/lighthouse/performance/uses-optimized-images/index.md +++ b/site/ja/docs/lighthouse/performance/uses-optimized-images/index.md @@ -18,13 +18,13 @@ Lighthouseは、ページ上のすべてのJPEGまたはBMP画像を収集し、 画像を最適化するためのステップは、以下を含め、実践できることがたくさんあります。 -- [画像CDNを使用する](https://web.dev/image-cdns/) -- [画像を圧縮する](https://web.dev/use-imagemin-to-compress-images/) -- [アニメーションGIFを動画に置き換える](https://web.dev/replace-gifs-with-videos/) -- [画像を遅延読みする](https://web.dev/use-lazysizes-to-lazyload-images/) -- [レスポンシブ画像を提供する](https://web.dev/serve-responsive-images/) -- [正しいサイズの画像を提供する](https://web.dev/serve-images-with-correct-dimensions/) -- [WebP画像を使用する](https://web.dev/serve-images-webp/) +- [画像CDNを使用する](https://web.dev/articles/image-cdns) +- [画像を圧縮する](https://web.dev/articles/use-imagemin-to-compress-images) +- [アニメーションGIFを動画に置き換える](https://web.dev/articles/replace-gifs-with-videos) +- [画像を遅延読みする](https://web.dev/articles/use-lazysizes-to-lazyload-images) +- [レスポンシブ画像を提供する](https://web.dev/articles/serve-responsive-images) +- [正しいサイズの画像を提供する](https://web.dev/articles/serve-images-with-correct-dimensions) +- [WebP画像を使用する](https://web.dev/articles/serve-images-webp) ## GUIツールを使用して画像を最適化する diff --git a/site/ja/docs/lighthouse/performance/uses-rel-preconnect/index.md b/site/ja/docs/lighthouse/performance/uses-rel-preconnect/index.md index d5d19f395..b1152bfbd 100644 --- a/site/ja/docs/lighthouse/performance/uses-rel-preconnect/index.md +++ b/site/ja/docs/lighthouse/performance/uses-rel-preconnect/index.md @@ -59,5 +59,5 @@ LighthouseレポートのOpportunitiesセクションには、`<link rel=preconn - [**必要なオリジンへの事前接続**監査のソースコード](https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/audits/uses-rel-preconnect.js) - [リソースの優先順位付け―ブラウザの支援を活用する](https://developers.google.com/web/fundamentals/performance/resource-prioritization#preconnect) -- [ページ速度の感触を改善するために、早期にネットワーク接続を確立する](https://web.dev/preconnect-and-dns-prefetch/) +- [ページ速度の感触を改善するために、早期にネットワーク接続を確立する](https://web.dev/articles/preconnect-and-dns-prefetch) - [Linkタイプ: preconnect](https://developer.mozilla.org/docs/Web/HTML/Link_types/preconnect#Browser_compatibility) diff --git a/site/ja/docs/lighthouse/performance/uses-text-compression/index.md b/site/ja/docs/lighthouse/performance/uses-text-compression/index.md index 0599db937..de76fda20 100644 --- a/site/ja/docs/lighthouse/performance/uses-text-compression/index.md +++ b/site/ja/docs/lighthouse/performance/uses-text-compression/index.md @@ -66,7 +66,7 @@ Content-Encoding: br 3. 大きなリクエスト行を有効にします。[Use large request rows (大きなリクエスト行を使用する)](https://developers.google.com/web/tools/chrome-devtools/network/reference#request-rows)を参照してください。 4. 関心のあるレスポンスの[**Size**]列を見てください。一番上の値は圧縮されたサイズで、一番下の値は圧縮解除されたサイズです。 -[Minify and compress network payloads (ネットワークペイロードの縮小と圧縮)](https://web.dev/reduce-network-payloads-using-text-compression/) も参照してください。 +[Minify and compress network payloads (ネットワークペイロードの縮小と圧縮)](https://web.dev/articles/reduce-network-payloads-using-text-compression) も参照してください。 ## スタック固有のガイダンス diff --git a/site/ja/docs/lighthouse/pwa/installable-manifest/index.md b/site/ja/docs/lighthouse/pwa/installable-manifest/index.md index c0cc7baa3..00c1a3f9f 100644 --- a/site/ja/docs/lighthouse/pwa/installable-manifest/index.md +++ b/site/ja/docs/lighthouse/pwa/installable-manifest/index.md @@ -12,11 +12,11 @@ updated: 2019-09-19 インストール可能性は、[プログレッシブウェブアプリ (PWA)](/docs/lighthouse/pwa/) の基本的な要件です。ユーザーに PWA のインストールを促すことで、ユーザーが PWA をホーム画面に追加できるようにします。ユーザーは、ホーム画面に追加するアプリをそれ以外のアプリよりも頻繁に利用します。 -[ウェブアプリマニフェスト](https://web.dev/add-manifest/)には、アプリをインストール可能にするための重要な情報が含まれています。 +[ウェブアプリマニフェスト](https://web.dev/articles/add-manifest)には、アプリをインストール可能にするための重要な情報が含まれています。 ## Lighthouse によるウェブアプリマニフェスト監査が失敗する原因 -[Lighthouse](https://developers.google.com/web/tools/lighthouse/) は、インストール可能性の最低要件を満たす[ウェブアプリマニフェスト](https://web.dev/add-manifest/)がないページをフラグします。 +[Lighthouse](https://developers.google.com/web/tools/lighthouse/) は、インストール可能性の最低要件を満たす[ウェブアプリマニフェスト](https://web.dev/articles/add-manifest)がないページをフラグします。 <figure>{% Img src="image/tcFciHGuF3MxnTr1y5ue01OGLBn2/039DlaixA4drrswBzSra.png", alt="ユーザーがホーム画面からウェブアプリをインストールできないことを示す Lighthouse 監査", width="800", height="98" %}</figure> @@ -34,7 +34,7 @@ updated: 2019-09-19 ## PWA をインストール可能にする方法 -上述した要件を満たすマニフェストがアプリにあることを確認してください。 PWA の作成について詳しくは、[Installable](https://web.dev/progressive-web-apps/) コレクションを参照してください。 +上述した要件を満たすマニフェストがアプリにあることを確認してください。 PWA の作成について詳しくは、[Installable](https://web.dev/explore/progressive-web-apps) コレクションを参照してください。 ## PWA がインストール可能であることを確認する方法 @@ -42,7 +42,7 @@ updated: 2019-09-19 アプリがインストール可能性の最低要件を満たしている場合、Chrome は`beforeinstallprompt` イベントを発生させます。このイベントを使用して、ユーザーに PWA のインストールを促すことができます。 -{% Aside 'codelab' %} Chrome でアプリをインストール可能にする方法については、コードラボの [Make it installable](https://web.dev/codelab-make-installable/) で紹介されています。{% endAside %} +{% Aside 'codelab' %} Chrome でアプリをインストール可能にする方法については、コードラボの [Make it installable](https://web.dev/articles/codelab-make-installable) で紹介されています。{% endAside %} ### 他のブラウザの場合 @@ -57,7 +57,7 @@ updated: 2019-09-19 ## リソース - [**Web app manifest does not meet the installability requirements (ウェブアプリマニフェストがインストール可能性の要件を満たしていない)** 監査のソースコード](https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/audits/installable-manifest.js) -- [Add a web app manifest (ウェブアプリマニフェストを追加する)](https://web.dev/add-manifest/) +- [Add a web app manifest (ウェブアプリマニフェストを追加する)](https://web.dev/articles/add-manifest) - [Discover what it takes to be installable (インストール可能にする方法について)](/docs/lighthouse/pwa/) - [Web App Manifest (ウェブアプリマニフェスト)](https://developer.mozilla.org/docs/Web/Manifest) - [Does not use HTTPS (HTTPS を使用していない)](/docs/lighthouse/pwa/is-on-https/) diff --git a/site/ja/docs/lighthouse/pwa/load-fast-enough-for-pwa/index.md b/site/ja/docs/lighthouse/pwa/load-fast-enough-for-pwa/index.md index 897f5c26a..408b7a9c1 100644 --- a/site/ja/docs/lighthouse/pwa/load-fast-enough-for-pwa/index.md +++ b/site/ja/docs/lighthouse/pwa/load-fast-enough-for-pwa/index.md @@ -19,7 +19,7 @@ updated: 2020-06-10 下記の2つの主要な指標は、読み込み時間に対するユーザーの知覚に影響します。 - [First Meaningful Paint(FMP)](/docs/lighthouse/performance/first-meaningful-paint)は、ページのメインとなるコンテンツが表示されるまでの時間を測定します -- [Time to Interactive(TTI)](https://web.dev/tti/)は、ページが操作可能になるまでの時間を測定します +- [Time to Interactive(TTI)](https://web.dev/articles/tti)は、ページが操作可能になるまでの時間を測定します たとえば、ページが1秒後に完全に表示されたが、ユーザーが10秒以内でそのページを操作できない場合、ユーザーはページの読み込み時間を10秒と認識するかもしれません。 diff --git a/site/ja/docs/lighthouse/pwa/maskable-icon-audit/index.md b/site/ja/docs/lighthouse/pwa/maskable-icon-audit/index.md index 443b8c492..c50657ad4 100644 --- a/site/ja/docs/lighthouse/pwa/maskable-icon-audit/index.md +++ b/site/ja/docs/lighthouse/pwa/maskable-icon-audit/index.md @@ -5,7 +5,7 @@ description: PWA にマスカブルアイコンのサポートを追加する方 date: 2020-05-06 --- -[マスカブルアイコン](https://web.dev/maskable-icon/)は、すべての Android デバイスにおいて PWA アイコンが適切に表示されることを保証する新しいアイコン形式です。新しい Androidデバイスでは、マスカブルアイコンの形式に従わない PWA アイコンは、背景色が白になります。マスカブルアイコンを使用すると、Android がそのアイコン用に提供するスペース全体にそのアイコンが表示されます。 +[マスカブルアイコン](https://web.dev/articles/maskable-icon)は、すべての Android デバイスにおいて PWA アイコンが適切に表示されることを保証する新しいアイコン形式です。新しい Androidデバイスでは、マスカブルアイコンの形式に従わない PWA アイコンは、背景色が白になります。マスカブルアイコンを使用すると、Android がそのアイコン用に提供するスペース全体にそのアイコンが表示されます。 ## Lighthouse によるマスカブルアイコンの監査が失敗する原因 @@ -27,7 +27,7 @@ date: 2020-05-06 1. [Maskable.app Editor](https://maskable.app/editor) を使用して、既存のアイコンをマスカブルアイコンに変換します。 -2. [ウェブアプリのマニフェスト](https://web.dev/add-manifest/)の `icons` オブジェクトの1つに `purpose` プロパティを追加します。`purpose` の値を `maskable{/code4 } もしくは <code data-md-type="codespan">any maskable` に設定します。[Values](https://developer.mozilla.org/docs/Web/Manifest/icons#Values) (値) を参照してください。 +2. [ウェブアプリのマニフェスト](https://web.dev/articles/add-manifest)の `icons` オブジェクトの1つに `purpose` プロパティを追加します。`purpose` の値を `maskable{/code4 } もしくは <code data-md-type="codespan">any maskable` に設定します。[Values](https://developer.mozilla.org/docs/Web/Manifest/icons#Values) (値) を参照してください。 ```json/8 { @@ -45,12 +45,12 @@ date: 2020-05-06 } ``` -3. Chrome DevTools を使用して、マスカブルアイコンが正しく表示されていることを確認します。[Are my current icons ready? (私の現在のアイコンは使用できるか?)](https://web.dev/maskable-icon/#are-my-current-icons-ready) を参照してください。 +3. Chrome DevTools を使用して、マスカブルアイコンが正しく表示されていることを確認します。[Are my current icons ready? (私の現在のアイコンは使用できるか?)](https://web.dev/articles/maskable-icon#are_my_current_icons_ready) を参照してください。 ## リソース - [**Manifest doesn't have a maskable icon (マニフェストにマスカブルアイコンがない)** 監査のソースコード](https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/audits/maskable-icon.js) -- [Adaptive icon support in PWAs with maskable icons (マスカブルアイコンを使用した PWA におけるアダプティブアイコンサポート)](https://web.dev/maskable-icon/) +- [Adaptive icon support in PWAs with maskable icons (マスカブルアイコンを使用した PWA におけるアダプティブアイコンサポート)](https://web.dev/articles/maskable-icon) - [Maskable.app エディター](https://maskable.app/editor) -- [Add a web app manifest (ウェブアプリのマニフェストを追加する)](https://web.dev/add-manifest/) +- [Add a web app manifest (ウェブアプリのマニフェストを追加する)](https://web.dev/articles/add-manifest) - [MDNの `icons` プロパティ](https://developer.mozilla.org/docs/Web/Manifest/icons) diff --git a/site/ja/docs/lighthouse/pwa/service-worker/index.md b/site/ja/docs/lighthouse/pwa/service-worker/index.md index d19f0f207..5b8164e2b 100644 --- a/site/ja/docs/lighthouse/pwa/service-worker/index.md +++ b/site/ja/docs/lighthouse/pwa/service-worker/index.md @@ -6,13 +6,13 @@ date: 2019-05-04 updated: 2020-06-10 --- -[Service Worker](https://web.dev/service-workers-cache-storage/) の登録は、[Progressive Web App (PWA) (プログレッシブウェブアプリ)](/docs/lighthouse/pwa/) が提供する主な機能を有効化する最初のステップです。 +[Service Worker](https://web.dev/articles/service-workers-cache-storage) の登録は、[Progressive Web App (PWA) (プログレッシブウェブアプリ)](/docs/lighthouse/pwa/) が提供する主な機能を有効化する最初のステップです。 - オフラインで稼働する - プッシュ通知をサポートする - デバイスにインストールできる -詳細は、[Service workers and the Cache Storage API (サービスワーカーと Cache Storage API)](https://web.dev/service-workers-cache-storage/) と題した記事をお読みください。 +詳細は、[Service workers and the Cache Storage API (サービスワーカーと Cache Storage API)](https://web.dev/articles/service-workers-cache-storage) と題した記事をお読みください。 ## ブラウザの互換性 @@ -34,15 +34,15 @@ Lighthouse は、[Chrome Remote Debugging Protocol (Chrome リモートデバッ サービスワーカーは、わずか数行のコードで登録できますが、サービスワーカーを使用する唯一の理由は、上述した PWA の機能の 1 つを実装できるようにするためです。実際にそうした機能を実装するには、さらに多くの作業が必要になります。 -- ファイルをキャッシュしてオフラインで使用する方法は、[What is network reliability and how do you measure it? (ネットワークの信頼性とは、またその評価方法とは?)](https://web.dev/network-connections-unreliable/) と題した記事をお読みください。 -- アプリをインストール可能にする方法については、コードラボ [Make it installable (インストール可能にする)](https://web.dev/codelab-make-installable/) を参照してください。 +- ファイルをキャッシュしてオフラインで使用する方法は、[What is network reliability and how do you measure it? (ネットワークの信頼性とは、またその評価方法とは?)](https://web.dev/articles/network-connections-unreliable) と題した記事をお読みください。 +- アプリをインストール可能にする方法については、コードラボ [Make it installable (インストール可能にする)](https://web.dev/articles/codelab-make-installable) を参照してください。 - プッシュ通知を有効にする方法については、Google の[Adding Push Notifications to a Web App (プッシュ通知のウェブアプリへの追加)](https://codelabs.developers.google.com/codelabs/push-notifications) を参照してください。 ## リソース - [**Does not register a service worker that controls page and `start_url (ページと `start_url` を制御するサービスワーカーが登録されない)`** 監査のソースコード](https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/audits/service-worker.js) - [Service Workers: an Introduction (サービスワーカー: はじめに)](https://developers.google.com/web/fundamentals/primers/service-workers) -- [Service workers and the Cache Storage API (サービスワーカーと Cache Storage API)](https://web.dev/service-workers-cache-storage/) -- [What is network reliability and how do you measure it? (ネットワークの信頼性とは、またその評価方法とは?)](https://web.dev/network-connections-unreliable/) -- [Make it installable (インストール可能にする)](https://web.dev/codelab-make-installable/) +- [Service workers and the Cache Storage API (サービスワーカーと Cache Storage API)](https://web.dev/articles/service-workers-cache-storage) +- [What is network reliability and how do you measure it? (ネットワークの信頼性とは、またその評価方法とは?)](https://web.dev/articles/network-connections-unreliable) +- [Make it installable (インストール可能にする)](https://web.dev/articles/codelab-make-installable) - [Adding Push Notifications to a Web App (プッシュ通知のウェブアプリへの追加)](https://codelabs.developers.google.com/codelabs/push-notifications) diff --git a/site/ja/docs/lighthouse/pwa/themed-omnibox/index.md b/site/ja/docs/lighthouse/pwa/themed-omnibox/index.md index 098cc8448..df370da36 100644 --- a/site/ja/docs/lighthouse/pwa/themed-omnibox/index.md +++ b/site/ja/docs/lighthouse/pwa/themed-omnibox/index.md @@ -8,7 +8,7 @@ date: 2019-05-04 updated: 2020-06-17 --- -[Progressive Web App(PWA)](https://web.dev/discover-installable/)のブランドカラーに一致するようにブラウザのアドレスバーにテーマを設定すると、より没入型のユーザー体験が提供されます。 +[Progressive Web App(PWA)](https://web.dev/articles/discover-installable)のブランドカラーに一致するようにブラウザのアドレスバーにテーマを設定すると、より没入型のユーザー体験が提供されます。 ## ブラウザの互換性 @@ -20,7 +20,7 @@ updated: 2020-06-17 <figure>{% Img src="image/tcFciHGuF3MxnTr1y5ue01OGLBn2/YadFSuw8denjl1hhnvFs.png", alt="Lighthouse 監査はページの色をテーマにしていないアドレスバーを表示します", width="800", height="98" %}</figure> -LighthouseがページのHTMLで`theme-color`メタタグを検出せず、[Webアプリマニフェスト](https://web.dev/add-manifest/)で`theme_color`プロパティを検出しない場合、監査は失敗します。 +LighthouseがページのHTMLで`theme-color`メタタグを検出せず、[Webアプリマニフェスト](https://web.dev/articles/add-manifest)で`theme_color`プロパティを検出しない場合、監査は失敗します。 Lighthouseは、値が有効なCSSカラー値であるかどうかをテストしないことに注意してください。 @@ -47,7 +47,7 @@ Lighthouseは、値が有効なCSSカラー値であるかどうかをテスト ### ステップ2: `theme_color`プロパティをWebアプリマニフェストに追加します -Webアプリマニフェストの`theme_color`プロパティにより、ユーザーがホーム画面からPWAを起動したときに、アドレスバーがブランド化されます。 `theme-color`メタタグとは異なり、[マニフェスト](https://web.dev/add-manifest/)でこれを定義する必要があるのは1回だけです。プロパティを任意の有効なCSSカラー値に設定してください。 +Webアプリマニフェストの`theme_color`プロパティにより、ユーザーがホーム画面からPWAを起動したときに、アドレスバーがブランド化されます。 `theme-color`メタタグとは異なり、[マニフェスト](https://web.dev/articles/add-manifest)でこれを定義する必要があるのは1回だけです。プロパティを任意の有効なCSSカラー値に設定してください。 ```html/1 { @@ -61,5 +61,5 @@ Webアプリマニフェストの`theme_color`プロパティにより、ユー ## リソース - [監査の**アドレスバーのテーマカラーを設定しない**監査用のソースコード](https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/audits/themed-omnibox.js) -- [Webアプリマニフェストを追加する](https://web.dev/add-manifest/) +- [Webアプリマニフェストを追加する](https://web.dev/articles/add-manifest) - [Android向けのChrome 39で`theme-color`用のサポート](https://developers.google.com/web/updates/2014/11/Support-for-theme-color-in-Chrome-39-for-Android) diff --git a/site/ja/docs/privacy-sandbox/chips/index.md b/site/ja/docs/privacy-sandbox/chips/index.md index e1d72525e..b6e98b581 100644 --- a/site/ja/docs/privacy-sandbox/chips/index.md +++ b/site/ja/docs/privacy-sandbox/chips/index.md @@ -97,7 +97,7 @@ Firefox は、ETP Strict モードとプライベート ブラウジングモー CHIPS では、パーティション化にオプトインしている Cookie には、ホストキーと *パーティション キーの 2* つが設定されるようになります。 -Cookie のパーティション キーは、Cookie を設定したエンドポイントへのリクエストの開始時にブラウザがアクセスしていたトップレベル URL のサイト([スキームと登録可能なドメイン](https://web.dev/same-site-same-origin/#%22schemeful-same-site%22))になります。 +Cookie のパーティション キーは、Cookie を設定したエンドポイントへのリクエストの開始時にブラウザがアクセスしていたトップレベル URL のサイト([スキームと登録可能なドメイン](https://web.dev/articles/same-site-same-origin#%22schemeful_same_site%22))になります。 `https://support.chat.example` が `https://retail.example` に埋め込まれた上記の例の場合、トップレベル URL は `https://retail.example` となります。 diff --git a/site/ja/docs/privacy-sandbox/fedcm/index.md b/site/ja/docs/privacy-sandbox/fedcm/index.md index 8dc98341f..ca9a08aff 100644 --- a/site/ja/docs/privacy-sandbox/fedcm/index.md +++ b/site/ja/docs/privacy-sandbox/fedcm/index.md @@ -177,7 +177,7 @@ FedCM を使用するには、Chrome の IdP と RP の両方で安全なコン ### well-known ファイルを作成する {: #well-known-file } -[トラッカーによる API の悪用](https://github.com/fedidcg/FedCM/issues/230)を防ぐには、IdP の [eTLD+1](https://web.dev/same-site-same-origin/#same-site-cross-site) の `/.well-known/web-identity` から well-known ファイルを提供する必要があります。 +[トラッカーによる API の悪用](https://github.com/fedidcg/FedCM/issues/230)を防ぐには、IdP の [eTLD+1](https://web.dev/articles/same-site-same-origin#same_site_cross_site) の `/.well-known/web-identity` から well-known ファイルを提供する必要があります。 たとえば、IdP エンドポイントが `https://accounts.idp.example/` で配信されている場合、`https://idp.example/.well-known/web-identity` の well-known ファイルと [IdP 設定ファイル](#idp-config-file)を配信する必要があります。以下は、well-known ファイルの例です。 diff --git a/site/ja/docs/privacy-sandbox/first-party-sets/index.md b/site/ja/docs/privacy-sandbox/first-party-sets/index.md index a3aa0706e..735c24942 100644 --- a/site/ja/docs/privacy-sandbox/first-party-sets/index.md +++ b/site/ja/docs/privacy-sandbox/first-party-sets/index.md @@ -20,7 +20,7 @@ authors: ウェブのプライバシーを改善するために、[Chrome はサードパーティ Cookie をブロックする方向に転換している](https://blog.chromium.org/2020/01/building-more-private-web-path-towards.html)ため、こういったエクスペリエンスの機能には新しいメカニズムが必要です。 -{% Aside %} アクセスしたサイト(URL バーに表示されるサイト)によって設定される Cookie は、ファースト パーティ Cookie です。アクセスしたサイトには、他のサイトのコンテンツ(画像、広告、テキストなど)を埋め込むことができます。現在のサイト以外のサイトからの Cookie は[サードパーティ Cookie](https://web.dev/samesite-cookie-recipes/#use-cases-for-cross-site-or-third-party-cookies) です。 {% endAside %} +{% Aside %} アクセスしたサイト(URL バーに表示されるサイト)によって設定される Cookie は、ファースト パーティ Cookie です。アクセスしたサイトには、他のサイトのコンテンツ(画像、広告、テキストなど)を埋め込むことができます。現在のサイト以外のサイトからの Cookie は[サードパーティ Cookie](https://web.dev/articles/samesite-cookie-recipes#use_cases_for_cross_site_or_third_party_cookies) です。 {% endAside %} ## First-Party Sets で関連サイトを定義する diff --git a/site/ja/docs/privacy-sandbox/floc/index.md b/site/ja/docs/privacy-sandbox/floc/index.md index 321eff6b4..b56f3d38b 100644 --- a/site/ja/docs/privacy-sandbox/floc/index.md +++ b/site/ja/docs/privacy-sandbox/floc/index.md @@ -37,7 +37,7 @@ FLoC は、興味に基づいて広告やその他のコンテンツを選択す ## FLoC の仕組み -「[FLoC の仕組み](https://web.dev/floc/#how-does-floc-work)」には、FloC の仕組みに関するステップバイステップの説明が記載されています。 +「[FLoC の仕組み](https://web.dev/articles/floc#how_does_floc_work)」には、FloC の仕組みに関するステップバイステップの説明が記載されています。 次の図では、FLoC を使用して関連する広告を選択して配信する際のさまざまな役割の例を示しています。 diff --git a/site/ja/docs/privacy-sandbox/permissions-policy/index.md b/site/ja/docs/privacy-sandbox/permissions-policy/index.md index a2c32718d..452505508 100644 --- a/site/ja/docs/privacy-sandbox/permissions-policy/index.md +++ b/site/ja/docs/privacy-sandbox/permissions-policy/index.md @@ -14,9 +14,9 @@ authors: 権限ポリシーにより、トップレベルサイトは、サイトとそのサードパーティが何を使用する予定であるかを定義できるようになり、機能アクセスリクエストが正当かどうかを判断するユーザーの負担が軽減されます。たとえば、権限ポリシーを使用してすべてのサードパーティの位置情報機能をブロックすることにより、開発者は、サードパーティがユーザーの位置情報にアクセスできないことを確証できます。 -{% Aside %} [プライバシーサンドボックス](https://web.dev/digging-into-the-privacy-sandbox/)は、サードパーティ Cookie やその他の追跡メカニズムを使用せずに、サードパーティのユース ケースを満たすための一連の提案です。 +{% Aside %} [プライバシーサンドボックス](https://web.dev/articles/digging-into-the-privacy-sandbox)は、サードパーティ Cookie やその他の追跡メカニズムを使用せずに、サードパーティのユース ケースを満たすための一連の提案です。 -[User-Agent Client Hints](https://web.dev/user-agent-client-hints/) や [Topics API](/docs/privacy-sandbox/topics/) などのプライバシーサンドボックス API は、 `geolocation` や `camera` などの機能が管理されるのと同じ方法で、権限ポリシーによって管理されます。権限ポリシーに依存するウェブプラットフォーム API のリストについては、[機能リスト](https://github.com/w3c/webappsec-permissions-policy/blob/main/features.md)をご覧ください。このリストは最新のものではない場合があることに注意してください。 {% endAside %} +[User-Agent Client Hints](https://web.dev/articles/user-agent-client-hints) や [Topics API](/docs/privacy-sandbox/topics/) などのプライバシーサンドボックス API は、 `geolocation` や `camera` などの機能が管理されるのと同じ方法で、権限ポリシーによって管理されます。権限ポリシーに依存するウェブプラットフォーム API のリストについては、[機能リスト](https://github.com/w3c/webappsec-permissions-policy/blob/main/features.md)をご覧ください。このリストは最新のものではない場合があることに注意してください。 {% endAside %} ## 権限ポリシーへの変更 @@ -321,9 +321,9 @@ const isCameraFeatureAllowed = isCameraPolicySet && hasCameraAttributeValue ## Reporting API -[Reporting API](https://web.dev/reporting-api/) は Web アプリケーションのレポートメカニズムを一貫した方法で提供します。権限ポリシーの違反に利用できる Reporting API は実験的機能として提供されています。 +[Reporting API](https://web.dev/articles/reporting-api) は Web アプリケーションのレポートメカニズムを一貫した方法で提供します。権限ポリシーの違反に利用できる Reporting API は実験的機能として提供されています。 -この実験的機能をテストするには、[ウォークスルー](https://web.dev/reporting-api/#use-devtools)に従い、`chrome://flags/#enable-experimental-web-platform-features` でフラグを有効にします。 このフラグが有効な場合、DevTools の[アプリケーション]タブで権限ポリシー違反を確認できます。 +この実験的機能をテストするには、[ウォークスルー](https://web.dev/articles/reporting-api#use_devtools)に従い、`chrome://flags/#enable-experimental-web-platform-features` でフラグを有効にします。 このフラグが有効な場合、DevTools の[アプリケーション]タブで権限ポリシー違反を確認できます。 次の例は、Reporting API ヘッダーの構造を示しています。 diff --git a/site/ja/docs/privacy-sandbox/proposal-lifecycle/index.md b/site/ja/docs/privacy-sandbox/proposal-lifecycle/index.md index 22eda868d..aee48d55b 100644 --- a/site/ja/docs/privacy-sandbox/proposal-lifecycle/index.md +++ b/site/ja/docs/privacy-sandbox/proposal-lifecycle/index.md @@ -97,7 +97,7 @@ W3C などの公の場、フィードバックフォーム、またはダイレ API のテストが完了し、Chrome での一般使用の準備ができたら、リリースを発表し、大規模なエコシステム採用に向けた公開ドキュメントが準備されていることを確認します。 -[User-Agent Client Hints](https://web.dev/user-agent-client-hints/)(UA-CH)は、2021 年に Chrome にリリースされました。 これは、プライバシーサンドボックスの取り組みの一環として、ブラウザのフィンガープリンティングなどの隠されたトラッキングを減らします。 +[User-Agent Client Hints](https://web.dev/articles/user-agent-client-hints)(UA-CH)は、2021 年に Chrome にリリースされました。 これは、プライバシーサンドボックスの取り組みの一環として、ブラウザのフィンガープリンティングなどの隠されたトラッキングを減らします。 Cookie と同様に、User-Agent(UA)文字列は初期のウェブ機能です。 デフォルトでは、ユーザーのブラウザとデバイスに関する多くの情報を提供するため、フィンガープリンティングをすぐに利用できるサーフェスとなっています 。 また、解析が非常に面倒になる可能性のあるフォーマットも備わっています。 diff --git a/site/ja/docs/privacy-sandbox/storage-partitioning/index.md b/site/ja/docs/privacy-sandbox/storage-partitioning/index.md index c47db19c5..931ecfdc7 100644 --- a/site/ja/docs/privacy-sandbox/storage-partitioning/index.md +++ b/site/ja/docs/privacy-sandbox/storage-partitioning/index.md @@ -34,14 +34,14 @@ tags: ### パーティション ストレージ有効前 -<figure> {% Img src="image/vgdbNJBYHma2o62ZqYmcnkq3j0o1/wOagNNjLO8LHJUn6p1iM.png", alt="パーティション化のないストレージ API の図。", width="793", height="415" %} <figcaption> ストレージ パーティション有効前は a.com と b.com でデータを共有可能。<br><a href="https://wd.imgix.net/image/vgdbNJBYHma2o62ZqYmcnkq3j0o1/wOagNNjLO8LHJUn6p1iM.png">拡大表示</a>。 </figcaption> </figure> +<figure> {% Img src="image/vgdbNJBYHma2o62ZqYmcnkq3j0o1/wOagNNjLO8LHJUn6p1iM.png", alt="パーティション化のないストレージ API の図。", width="793", height="415" %} <figcaption> ストレージ パーティション有効前は a.com と b.com でデータを共有可能。<br><a href="https://wd.imgix.net/image/vgdbNJBYHma2o62ZqYmcnkq3j0o1/wOagNNjLO8LHJUn6p1iM.png">拡大表示</a>。 </figcaption> </figure> {% endColumn %} {% Column %} ### パーティション ストレージ後 -<figure> {% Img src="image/vgdbNJBYHma2o62ZqYmcnkq3j0o1/X8tExxdcoVSE4P1bUKQJ.png", alt="パーティション化によるストレージ API の図。", width="800", height="553" %} <figcaption> ストレージ パーティション有効後は b.com は a.com のストレージにアクセスできなくなる。<br><a href="https://wd.imgix.net/image/vgdbNJBYHma2o62ZqYmcnkq3j0o1/X8tExxdcoVSE4P1bUKQJ.png">拡大表示</a>。 </figcaption> </figure> +<figure> {% Img src="image/vgdbNJBYHma2o62ZqYmcnkq3j0o1/X8tExxdcoVSE4P1bUKQJ.png", alt="パーティション化によるストレージ API の図。", width="800", height="553" %} <figcaption> ストレージ パーティション有効後は b.com は a.com のストレージにアクセスできなくなる。<br><a href="https://wd.imgix.net/image/vgdbNJBYHma2o62ZqYmcnkq3j0o1/X8tExxdcoVSE4P1bUKQJ.png">拡大表示</a>。 </figcaption> </figure> {% endColumn %} {% endColumns %} @@ -60,11 +60,11 @@ tags: ### ストレージ API -[クォータ システム](https://web.dev/storage-for-the-web/#how-much) : クォータ システムは、ストレージに割り当てられるディスク容量を決定するために使用されます。各パーティションはクォータ システムによって個別のバケットとして管理され、許可される容量と、クリアされる時期が決定されます。 : `navigator.storage.estimate()` はパーティションの情報を返します。`window.webkitStorageInfo` や `navigator.webkitTemporaryStorage` などの Chrome 専用 API は使用廃止になります。 : [IndexedDB](https://developer.mozilla.org/docs/Web/API/IndexedDB_API) と [キャッシュ ストレージ](https://web.dev/cache-api-quick-guide)は、新しいパーティション クォータ システムを使用します。 +[クォータ システム](https://web.dev/articles/storage-for-the-web#how_much) : クォータ システムは、ストレージに割り当てられるディスク容量を決定するために使用されます。各パーティションはクォータ システムによって個別のバケットとして管理され、許可される容量と、クリアされる時期が決定されます。 : `navigator.storage.estimate()` はパーティションの情報を返します。`window.webkitStorageInfo` や `navigator.webkitTemporaryStorage` などの Chrome 専用 API は使用廃止になります。 : [IndexedDB](https://developer.mozilla.org/docs/Web/API/IndexedDB_API) と [キャッシュ ストレージ](https://web.dev/cache-api-quick-guide)は、新しいパーティション クォータ システムを使用します。 [Web Storage API](https://developer.mozilla.org/docs/Web/API/Web_Storage_API) : Web Storage API は、ブラウザがキーと値のペアを保存できる [Local Storage](https://developer.mozilla.org/docs/Web/API/Window/localStorage) と [Session Storage](https://developer.mozilla.org/docs/Web/API/Window/sessionStorage) の 2 つの仕組みを提供します。これらは現在クォータで管理されていませんが、引き続きパーティション化されます。 -[Origin Private File System](https://web.dev/file-system-access/#accessing-the-origin-private-file-system) : [File System Access API](https://web.dev/file-system-access)を使用すると、ユーザーがアクセスを許可した後、サイトはデバイス上のファイルやフォルダの変更を直接読み取ったり保存したりできます。Origin Private File System を使用すると、オリジンは、ユーザーが簡単にアクセスできるディスクに非公開コンテンツを保存でき、パーティション化されます。 +[Origin Private File System](https://web.dev/articles/file-system-access#accessing_the_origin_private_file_system) : [File System Access API](https://web.dev/file-system-access)を使用すると、ユーザーがアクセスを許可した後、サイトはデバイス上のファイルやフォルダの変更を直接読み取ったり保存したりできます。Origin Private File System を使用すると、オリジンは、ユーザーが簡単にアクセスできるディスクに非公開コンテンツを保存でき、パーティション化されます。 [Storage Bucket API](https://wicg.github.io/storage-buckets/explainer.html) : Storage Bucket API は、バケットと呼ばれる新しい概念を使用して、IndexedDB や localStorage などのさまざまなストレージ API を統合する [Storage Standard](https://storage.spec.whatwg.org/) 用に開発されています。バケットに格納されたデータとバケットに関連付けられたメタデータはパーティションされます。 diff --git a/site/ja/docs/privacy-sandbox/third-party-cookie-phase-out/index.md b/site/ja/docs/privacy-sandbox/third-party-cookie-phase-out/index.md index ca5e93e8c..fc778bac1 100644 --- a/site/ja/docs/privacy-sandbox/third-party-cookie-phase-out/index.md +++ b/site/ja/docs/privacy-sandbox/third-party-cookie-phase-out/index.md @@ -59,14 +59,14 @@ SameSite=Lax ### サードパーティ Cookie -iframe やサブリソースリクエストなど、クロスサイトのコンテキストで送信される Cookie は通常、サードパーティ Cookie と呼ばれます。{% Img src="image/vgdbNJBYHma2o62ZqYmcnkq3j0o1/NJLl1qG9AN8tD9GwR2jp.png", alt="サードパーティ Cookie を示す図。", width="800", height="646" %} [サードパーティ Cookie のユースケース](https://web.dev/samesite-cookie-recipes/#use-cases-for-cross-site-or-third-party-cookies)には次のようなものがあります。 +iframe やサブリソースリクエストなど、クロスサイトのコンテキストで送信される Cookie は通常、サードパーティ Cookie と呼ばれます。{% Img src="image/vgdbNJBYHma2o62ZqYmcnkq3j0o1/NJLl1qG9AN8tD9GwR2jp.png", alt="サードパーティ Cookie を示す図。", width="800", height="646" %} [サードパーティ Cookie のユースケース](https://web.dev/articles/samesite-cookie-recipes#use_cases_for_cross_site_or_third_party_cookies)には次のようなものがあります。 - 動画、地図、コードサンプル、ソーシャルメディア投稿など、他のサイトから共有される埋め込みコンテンツ。 - ペイメント、カレンダー、予約、予約機能などの外部サービスのウィジェット。 - ソーシャルボタンや詐欺対策サービスなどのウィジェット。 - リクエストとともに送信される Cookie に依存する `<img>` や `<script>` タグなどのページ上のリモートリソース(通常、ピクセルのトラッキングやコンテンツのパーソナライズに使用されます)。 -[2019 年には、ブラウザの Cookie の動作が変更され、デフォルトでファーストパーティのアクセスに制限されました](https://web.dev/samesite-cookies-explained/#changes-to-the-default-behavior-without-samesite)。現在、クロスサイトコンテキストで使用されるすべての Cookie は、`SameSite=None` 属性で設定されている必要があります。 +[2019 年には、ブラウザの Cookie の動作が変更され、デフォルトでファーストパーティのアクセスに制限されました](https://web.dev/articles/samesite-cookies-explained#changes_to_the_default_behavior_without_samesite)。現在、クロスサイトコンテキストで使用されるすべての Cookie は、`SameSite=None` 属性で設定されている必要があります。 ```text Set-Cookie: cookie-name=value; SameSite=None; Secure diff --git a/site/ja/docs/privacy-sandbox/trust-tokens/index.md b/site/ja/docs/privacy-sandbox/trust-tokens/index.md index e2616e363..f42864675 100644 --- a/site/ja/docs/privacy-sandbox/trust-tokens/index.md +++ b/site/ja/docs/privacy-sandbox/trust-tokens/index.md @@ -62,7 +62,7 @@ Private State Token API を使用すると、ウェブサイトは信頼でき 12. ニュースサイトに広告が表示されます。 13. 広告ビューのインプレッションがカウントされます。 -{% Aside %} この例の JavaScript 呼び出しの詳細については、[API の使用例](https://web.dev/trust-tokens/#sample-api-usage)をご覧ください。 {% endAside %} +{% Aside %} この例の JavaScript 呼び出しの詳細については、[API の使用例](https://web.dev/articles/trust-tokens#sample_api_usage)をご覧ください。 {% endAside %} ## プライバシー状態トークン用のツールはありますか? @@ -89,6 +89,6 @@ Chrome DevTools では、[ネットワーク] タブと [アプリケーショ ## 詳細について - [Private State Token API の技術的 Explainer](https://github.com/dvorak42/trust-token-api) -- [Private State Tokens の基礎](https://web.dev/trust-tokens/): ウェブ開発者向けの概要 +- [Private State Tokens の基礎](https://web.dev/articles/trust-tokens): ウェブ開発者向けの概要 - [Chrome のオリジントライアル入門](https://web.dev/origin-trials) - [プライバシーサンドボックスを掘り下げる](https://web.dev/digging-into-the-privacy-sandbox) diff --git a/site/ja/docs/privacy-sandbox/user-agent/index.md b/site/ja/docs/privacy-sandbox/user-agent/index.md index c720d1219..3259d5944 100644 --- a/site/ja/docs/privacy-sandbox/user-agent/index.md +++ b/site/ja/docs/privacy-sandbox/user-agent/index.md @@ -21,7 +21,7 @@ authors: User-Agent(UA)の情報量削減とは、 [パッシブフィンガープリントに使用される](https://www.w3.org/2001/tag/doc/unsanctioned-tracking/#unsanctioned-tracking-tracking-without-user-control). 可能性のある User-Agent 文字列中の識別情報を最小限に抑える取り組みです。この [変更が展開される](https://blog.chromium.org/2021/09/user-agent-reduction-origin-trial-and-dates.html), と、すべてのリソース リクエストには情報量が削減された `User-Agent` ヘッダーが含まれるようになります。その結果、いくつかの `Navigator` インターフェース `navigator.userAgent`、`navigator.appVersion`、`navigator.platform` など から返される値の情報量が削減されます。 -ウェブ デベロッパーは、サイトのコードの中で User-Agent 文字列のインスタンスや使用に関係する部分を確認し、[User-Agent 文字列の情報量削減に備える](#prepare-and-test) 必要があります。User-Agent 文字列を解析することでデバイスのモデル、プラットフォームのバージョン、ブラウザのフルバージョンの情報を取得しているサイトの場合は、[User-Agent Client Hints API の実装](https://web.dev/migrate-to-ua-ch/) が必要になります。 +ウェブ デベロッパーは、サイトのコードの中で User-Agent 文字列のインスタンスや使用に関係する部分を確認し、[User-Agent 文字列の情報量削減に備える](#prepare-and-test) 必要があります。User-Agent 文字列を解析することでデバイスのモデル、プラットフォームのバージョン、ブラウザのフルバージョンの情報を取得しているサイトの場合は、[User-Agent Client Hints API の実装](https://web.dev/articles/migrate-to-ua-ch) が必要になります。 User-Agent [の情報量削減のスケジュールに関する最新情報をご確認ください](https://www.chromium.org/updates/ua-reduction)。 @@ -48,7 +48,7 @@ User-Agent [の情報量削減のスケジュールに関する最新情報を ## 情報量削減後の UA と UA-CH の機能 -情報量削減後の UA と UA-CH がどのように機能するかについて、簡単な例を次に示します。より詳細な例については、[User-Agent Client Hints によるユーザーのプライバシーとデベロッパーエクスペリエンスの改善](https://web.dev/user-agent-client-hints/#example-exchange) をご覧ください。 +情報量削減後の UA と UA-CH がどのように機能するかについて、簡単な例を次に示します。より詳細な例については、[User-Agent Client Hints によるユーザーのプライバシーとデベロッパーエクスペリエンスの改善](https://web.dev/articles/user-agent-client-hints#example_exchange) をご覧ください。 ユーザーがブラウザを開き、アドレスバーに「`example.com` 」と入力します。 @@ -92,7 +92,7 @@ Critical-CH: Device-Memory ## UA の情報量削減への準備方法 {: #prepare-and-test} -Stable 版 Chrome で情報量削減後の User-Agent が大規模に利用可能になるのに合わせて、User-Agent 文字列のインスタンスや使用に関係する [サイトのコードをご確認ください](https://web.dev/migrate-to-ua-ch/#audit-collection-and-use-of-user-agent-data) 。User-Agent 文字列を解析することでデバイスのモデル、プラットフォームのバージョン、ブラウザのフルバージョンの情報を取得しているサイトの場合は、 [UA-CH API の実装](https://web.dev/migrate-to-ua-ch/)が必要になります。 +Stable 版 Chrome で情報量削減後の User-Agent が大規模に利用可能になるのに合わせて、User-Agent 文字列のインスタンスや使用に関係する [サイトのコードをご確認ください](https://web.dev/articles/migrate-to-ua-ch#audit_collection_and_use_of_user_agent_data) 。User-Agent 文字列を解析することでデバイスのモデル、プラットフォームのバージョン、ブラウザのフルバージョンの情報を取得しているサイトの場合は、 [UA-CH API の実装](https://web.dev/articles/migrate-to-ua-ch)が必要になります。 UA-CH API に更新したら、User-Agent から想定どおりのデータが得られることを確認するためのテストを行います。テスト方法は 3 つありますが、いずれもこれまでより複雑です。 @@ -124,7 +124,7 @@ UA-CH API に更新したら、User-Agent から想定どおりのデータが ## Client Hints と Critical Hints のサポート -サーバーに返される[デフォルトの Client Hints](https://web.dev/migrate-to-ua-ch/#are-you-only-using-basic-user-agent-data) は 3 つあります。これには、ブラウザー名とメジャー バージョン、ブラウザーがモバイル デバイス上にあるかどうかを示すブール値、およびオペレーティング システム名が含まれます。これらは TLS ハンドシェイクの後に送信されます。これらは既に利用可能で、ブラウザでサポートされています。 +サーバーに返される[デフォルトの Client Hints](https://web.dev/articles/migrate-to-ua-ch#are_you_only_using_basic_user_agent_data) は 3 つあります。これには、ブラウザー名とメジャー バージョン、ブラウザーがモバイル デバイス上にあるかどうかを示すブール値、およびオペレーティング システム名が含まれます。これらは TLS ハンドシェイクの後に送信されます。これらは既に利用可能で、ブラウザでサポートされています。 ただし、サイトをレンダリングするために重要な情報を取得する必要がある場合があります。 @@ -155,7 +155,7 @@ Critical Hints を使用する必要がある場合は、 [Critical Hints の信 ## 詳細 -- [ユーザー プライバシーとデベロッパーエクスペリエンスの改善に関するウェブデベロッパー向け概要](https://web.dev/user-agent-client-hints/): に関するウェブデベロッパー向け概要 -- [UA 文字列から UA-CH に移行する](https://web.dev/migrate-to-ua-ch/): ためのウェブデベロッパー向けチュートリアル +- [ユーザー プライバシーとデベロッパーエクスペリエンスの改善に関するウェブデベロッパー向け概要](https://web.dev/articles/user-agent-client-hints): に関するウェブデベロッパー向け概要 +- [UA 文字列から UA-CH に移行する](https://web.dev/articles/migrate-to-ua-ch): ためのウェブデベロッパー向けチュートリアル - [User-Agent の情報量削減スニペット](/docs/privacy-sandbox/user-agent/snippets/): (テストのために現在の User-Agent 文字列を情報量削減後の形式に変換するコード スニペット) - [プライバシーサンドボックスの詳細](https://web.dev/digging-into-the-privacy-sandbox) diff --git a/site/ja/docs/web-platform/origin-trials/index.md b/site/ja/docs/web-platform/origin-trials/index.md index ff09a299e..bc50cee17 100644 --- a/site/ja/docs/web-platform/origin-trials/index.md +++ b/site/ja/docs/web-platform/origin-trials/index.md @@ -61,10 +61,10 @@ temporarily re-enabled. These are known as **deprecation trials**, and in some c referred to as "reverse" origin trials. --> すべてのオリジントライアルが新しい API のテスト向けであるとは限りません。一部のトライアルでは、廃止された機能を一時的に再度有効にすることができます。これらは **デプリケーショントライアル** として知られており、一部のコンテキストでは「リバース」オリジントライアルと呼ばれています。 -<!-- For example, [from Chrome 85](https://web.dev/appcache-removal/#origin-trial) AppCache is no longer +<!-- For example, [from Chrome 85](https://web.dev/articles/appcache-removal#origin_trial) AppCache is no longer available in Chrome by default. Sites needing extra time to migrate off AppCache could register for the [deprecation trial to continue using AppCache](/origintrials/#/view_trial/1776670052997660673) until Chrome 93. --> -例えば、 [Chrome 85 から](https://web.dev/appcache-removal/#origin-trial) AppCache は初期状態で Chrome で使用できなくなりました。 AppCache から移行するために追加の時間が必要なサイトは、Chrome 93 まで [deprecation trial to continue using AppCache](/origintrials/#/view_trial/1776670052997660673) に登録することができました。 +例えば、 [Chrome 85 から](https://web.dev/articles/appcache-removal#origin_trial) AppCache は初期状態で Chrome で使用できなくなりました。 AppCache から移行するために追加の時間が必要なサイトは、Chrome 93 まで [deprecation trial to continue using AppCache](/origintrials/#/view_trial/1776670052997660673) に登録することができました。 <!-- ## How to register for an origin trial --> diff --git a/site/ko/articles/file-handling/index.md b/site/ko/articles/file-handling/index.md index 9a195db1d..e236c5f92 100644 --- a/site/ko/articles/file-handling/index.md +++ b/site/ko/articles/file-handling/index.md @@ -15,7 +15,7 @@ alt: 다양한 색상의 바인더. {% Aside %} 파일 처리 API는 [기능 프로젝트](/blog/fugu-status/)의 일부이며 현재 개발 중입니다. 이 게시물은 구현이 진행되는 대로 업데이트됩니다. {% endAside %} -이제 웹 앱이 [파일을 읽고 쓸 수 있으므로](https://web.dev/file-system-access/) 다음 논리적 단계는 개발자가 이러한 웹 앱을 앱이 만들고 처리할 수 있는 파일에 대한 파일 핸들러로 선언하도록 하는 것입니다. 파일 처리 API를 사용하면 정확히 이 작업을 수행할 수 있습니다. 텍스트 편집기 앱을 파일 핸들러로 등록하고 설치한 후 macOS에서 `.txt` 파일을 마우스 오른쪽 버튼으로 클릭하고 "정보 가져오기"를 선택한 다음 OS에 항상 이 앱을 기본으로 사용하여 `.txt`를 열도록 지시합니다. +이제 웹 앱이 [파일을 읽고 쓸 수 있으므로](https://web.dev/articles/file-system-access) 다음 논리적 단계는 개발자가 이러한 웹 앱을 앱이 만들고 처리할 수 있는 파일에 대한 파일 핸들러로 선언하도록 하는 것입니다. 파일 처리 API를 사용하면 정확히 이 작업을 수행할 수 있습니다. 텍스트 편집기 앱을 파일 핸들러로 등록하고 설치한 후 macOS에서 `.txt` 파일을 마우스 오른쪽 버튼으로 클릭하고 "정보 가져오기"를 선택한 다음 OS에 항상 이 앱을 기본으로 사용하여 `.txt`를 열도록 지시합니다. ## 파일 처리 API {: #use-cases }에 대한 권장 사용 사례 @@ -35,8 +35,8 @@ alt: 다양한 색상의 바인더. 파일 처리 API 자체는 폴리필할 수 없습니다. 그러나 웹 앱으로 파일을 여는 기능은 두 가지 다른 방법을 통해 달성할 수 있습니다. -- [웹 공유 대상 API](https://web.dev/web-share-target/)를 사용하면 개발자가 앱을 공유 대상으로 지정할 수 있으므로 운영 체제의 공유 시트에서 파일을 열 수 있습니다. -- [파일 시스템 액세스 API](https://web.dev/file-system-access/)는 파일 드래그 앤 드롭과 통합될 수 있으므로 개발자는 이미 열려 있는 앱에서 드롭된 파일을 처리할 수 있습니다. +- [웹 공유 대상 API](https://web.dev/articles/web-share-target)를 사용하면 개발자가 앱을 공유 대상으로 지정할 수 있으므로 운영 체제의 공유 시트에서 파일을 열 수 있습니다. +- [파일 시스템 액세스 API](https://web.dev/articles/file-system-access)는 파일 드래그 앤 드롭과 통합될 수 있으므로 개발자는 이미 열려 있는 앱에서 드롭된 파일을 처리할 수 있습니다. ### 기능 감지 @@ -52,7 +52,7 @@ if ('launchQueue' in window && 'files' in LaunchParams.prototype) { ### 파일 처리 API의 선언적 부분 -첫 번째 단계로 웹 앱은 [웹 앱 매니페스트](https://web.dev/add-manifest/)에서 처리할 수 있는 파일의 종류를 선언적으로 설명해야 합니다. 파일 처리 API는 파일 처리기의 배열을 허용하는 `"file_handlers"`라는 새로운 속성으로 웹 앱 매니페스트를 확장합니다. 파일 핸들러는 두 가지 속성을 가진 객체입니다. +첫 번째 단계로 웹 앱은 [웹 앱 매니페스트](https://web.dev/articles/add-manifest)에서 처리할 수 있는 파일의 종류를 선언적으로 설명해야 합니다. 파일 처리 API는 파일 처리기의 배열을 허용하는 `"file_handlers"`라는 새로운 속성으로 웹 앱 매니페스트를 확장합니다. 파일 핸들러는 두 가지 속성을 가진 객체입니다. - 앱 범위 내의 URL을 값으로 가리키는 `"action"` - MIME 유형의 개체를 키로 사용하고 파일 확장자 목록을 값으로 사용하는 `"accept"` @@ -109,7 +109,7 @@ if ('launchQueue' in window && 'files' in LaunchParams.prototype) { 이 예시는 쉼표로 구분된 값을 저장한 파일(`.csv`은 `/open-csv`에서, 스케일러블 벡터 그래픽스 파일(`.svg`)은 (`.svg`)에서, `.grafr`, `.graf`, or `.graph` 중 하나의 확장자를 사용하는 임의로 만들어진 Grafr 파일 형식은 `/open-graf`에서 처리하는 가상의 애플리케이션입니다. -{% Aside %} 이 선언이 적용되려면 애플리케이션이 설치되어 있어야 합니다. [앱을 설치 가능하게 만드는 방법](https://web.dev/progressive-web-apps/#make-it-installable)에 대한 바로 이 사이트의 기사 시리즈에서 자세히 알아볼 수 있습니다. {% endAside %} +{% Aside %} 이 선언이 적용되려면 애플리케이션이 설치되어 있어야 합니다. [앱을 설치 가능하게 만드는 방법](https://web.dev/explore/progressive-web-apps#make-it-installable)에 대한 바로 이 사이트의 기사 시리즈에서 자세히 알아볼 수 있습니다. {% endAside %} ### 파일 처리 API의 필수 부분 @@ -155,7 +155,7 @@ Chrome 팀은 사용자 제어, 투명성, 인체 공학을 포함 [하여 강 ### 파일 관련 고려 사항 -웹사이트가 파일에 액세스할 수 있도록 허용함으로써 열리는 큰 범주의 공격 벡터가 있습니다. 이는 [파일 시스템 액세스 API에 대한 문서](https://web.dev/file-system-access/#security-considerations)에 설명되어 있습니다. 파일 처리 API가 파일 시스템 액세스 API를 통해 제공하는 추가 보안 관련 기능은 웹 애플리케이션에 표시된 파일 선택기를 통하지 않고 운영 체제의 내장 UI를 통해 특정 파일에 대한 액세스 권한을 부여하는 기능입니다. +웹사이트가 파일에 액세스할 수 있도록 허용함으로써 열리는 큰 범주의 공격 벡터가 있습니다. 이는 [파일 시스템 액세스 API에 대한 문서](https://web.dev/articles/file-system-access#security_considerations)에 설명되어 있습니다. 파일 처리 API가 파일 시스템 액세스 API를 통해 제공하는 추가 보안 관련 기능은 웹 애플리케이션에 표시된 파일 선택기를 통하지 않고 운영 체제의 내장 UI를 통해 특정 파일에 대한 액세스 권한을 부여하는 기능입니다. 사용자가 의도하지 않게 파일을 열어 웹 응용 프로그램에 액세스 권한을 부여할 수 있는 위험이 여전히 있습니다. 그러나 일반적으로 파일을 열면 파일을 여는 응용 프로그램에서 해당 파일을 읽거나 조작할 수 있습니다. 따라서 "연결 프로그램…" 컨텍스트 메뉴 등을 통해 사용자가 파일을 설치된 애플리케이션으로 실행하겠다고 명시적으로 선택을 한다면 이는 해당 애플리케이션을 충분히 신뢰하고 있다는 신호로 해석할 수 있습니다. diff --git a/site/ko/blog/chrome-ux-report-looker-studio-dashboard/index.md b/site/ko/blog/chrome-ux-report-looker-studio-dashboard/index.md index 7b7e9ee41..da740157e 100644 --- a/site/ko/blog/chrome-ux-report-looker-studio-dashboard/index.md +++ b/site/ko/blog/chrome-ux-report-looker-studio-dashboard/index.md @@ -70,7 +70,7 @@ https://developer.chrome.com/chrome-ux-report-looker-studio-dashboard/ ### Core Web Vitals 개요 -첫 번째 페이지는 출처의 월간 [Core Web Vitals](https://web.dev/vitals/) 성능에 대한 개요입니다. 이것은 Google에서 집중할 것을 권장하는 가장 중요한 UX 측정 항목입니다. +첫 번째 페이지는 출처의 월간 [Core Web Vitals](https://web.dev/articles/vitals) 성능에 대한 개요입니다. 이것은 Google에서 집중할 것을 권장하는 가장 중요한 UX 측정 항목입니다. {% Img src="image/admin/h8iCTgvmG4DS2zScvatc.png", alt="CrUX 대시보드 Core Web Vitals 개요", width="800", height="906" %} @@ -88,7 +88,7 @@ Core Web Vitals 페이지 다음에 CrUX 데이터 세트의 모든 [메트릭]( 각 페이지 상단에는 경험 데이터에 포함된 폼 팩터를 제한하는 데 사용할 수 있는 **장치 필터**가 있습니다. 예를 들어 전화 경험을 구체적으로 드릴다운할 수 있습니다. 이 설정은 여러 페이지에 걸쳐 유지됩니다. -이 페이지의 기본 시각화는 "좋음", "개선 필요" 및 "나쁨"으로 분류된 경험의 월별 분포입니다. 차트 아래 색상으로 구분된 범례는 범주에 포함된 경험의 범위를 나타냅니다. 예를 들어 위의 스크린샷에서 "좋음" [Largest Contentful Paint](https://web.dev/lcp/#what-is-a-good-lcp-score)(LCP) 경험의 비율이 변동하고 최근 몇 개월 동안 약간 나빠지는 것을 볼 수 있습니다. +이 페이지의 기본 시각화는 "좋음", "개선 필요" 및 "나쁨"으로 분류된 경험의 월별 분포입니다. 차트 아래 색상으로 구분된 범례는 범주에 포함된 경험의 범위를 나타냅니다. 예를 들어 위의 스크린샷에서 "좋음" [Largest Contentful Paint](https://web.dev/articles/lcp#what_is_a_good_lcp_score)(LCP) 경험의 비율이 변동하고 최근 몇 개월 동안 약간 나빠지는 것을 볼 수 있습니다. 가장 최근 달의 "좋음" 및 "나쁨" 경험 비율이 이전달과의 백분율 차이 지표와 함께 차트 위에 표시됩니다. 이 출처의 경우 "좋음" LCP 경험은 전월 대비 3.2% 하락한 56.04%를 기록했습니다. @@ -116,7 +116,7 @@ PageSpeed Insights와 같은 도구의 해당 P75 값은 공개 BigQuery 데이 {% Aside 'key-term' %} 유효 연결 유형은 사용자 기기의 대역폭 측정을 기반으로 하고 사용된 특정 기술을 의미하지 않기 때문에 *효과적인 것*으로 간주됩니다. 예를 들어 빠른 Wi-Fi를 사용하는 데스크탑 사용자는 4G로 레이블이 지정되고 느린 모바일 연결은 2G로 레이블이 지정될 수 있습니다. {% endAside %} -이러한 차원의 분포는 [First Contentful Paint](https://web.dev/fcp/)(FCP) 히스토그램 데이터의 세그먼트를 사용하여 계산됩니다. +이러한 차원의 분포는 [First Contentful Paint](https://web.dev/articles/fcp)(FCP) 히스토그램 데이터의 세그먼트를 사용하여 계산됩니다. ## 자주 묻는 질문 diff --git a/site/ko/blog/new-in-devtools-101/index.md b/site/ko/blog/new-in-devtools-101/index.md index 3ed7844d4..50130db97 100644 --- a/site/ko/blog/new-in-devtools-101/index.md +++ b/site/ko/blog/new-in-devtools-101/index.md @@ -31,7 +31,7 @@ tags: 그 외에도 녹화물을 내보낼 수도 있습니다. [유저 플로우를 녹화](/docs/devtools/recorder/#record) 한 뒤에 export 버튼을 클릭하세요. 다음과 같은 3가지 옵션이 있습니다: - **JSON 파일로 내보내기**. 녹화본을 JSON 파일로 다운로드합니다. -- **@puppeteer/replay 스크립트로 내보내기**. 녹화본을 [Puppeteer 다시보기](https://github.com/puppeteer/replay) 스크립트로 다운로드합니다. +- **@puppeteer/replay 스크립트로 내보내기**. 녹화본을 [Puppeteer 다시보기](https://github.com/puppeteer/replay) 스크립트로 다운로드합니다. - **Puppeteer 스크립트로 내보내기** . 녹화본을 [Puppeteer](https://pptr.dev/) 스크립트로 다운로드합니다. 이러한 옵션들 사이의 차이점에 대해 더 자세히 알고자 한다면 [문서](/docs/devtools/recorder/#export-flows) 를 참고하세요. @@ -84,13 +84,13 @@ Chromium issues: [1296855](https://crbug.com/1296855), [https://crbug.com/130340 이번 릴리스에서 주목할만한 수정 사항들입니다: -- [뒤로/앞으로 캐쉬(혹은 bfcache)](/blog/new-in-devtools-98/#bfcache) 에서 블락된 [bfcache](https://web.dev/bfcache/) 익스텐션 ID를 표시합니다. ( [1284548](https://crbug.com/1284548)) +- [뒤로/앞으로 캐쉬(혹은 bfcache)](/blog/new-in-devtools-98/#bfcache) 에서 블락된 [bfcache](https://web.dev/articles/bfcache) 익스텐션 ID를 표시합니다. ( [1284548](https://crbug.com/1284548)) - 유사 배열 객체, CSS 클래스 이름, `map.get` 과 HTML 태그에 대한 자동 완성 지원이 수정되었습니다. ([1297101](https://crbug.com/1297101), [1297491](https://crbug.com/1297491), [1293807](https://crbug.com/1293807), [1296983](https://crbug.com/1296983)) - 단어를 더블 클릭하거나 자동 완성을 취소할 때 잘못된 하이라이트를 수정하였습니다. ([1298437](https://crbug.com/1298437), [1298667](https://crbug.com/1298667)) - **소스** 패널에서 주석 키보드 단축키를 수정하였습니다. ([1296535](https://crbug.com/1296535)) - **소스** 패널에서 **Alt** (Options) 키를 사용해 여러 곳을 선택하는 기능을 다시 지원합니다. ([1304070](https://crbug.com/1304070)) - + ## [실험실 기능] Lighthouse 패널의 새로운 시간 범위 (timespan) 및 스냅샷 (snapshot) 모드 {: #lighthouse } {% Aside %} @@ -99,7 +99,7 @@ Chromium issues: [1296855](https://crbug.com/1296855), [https://crbug.com/130340 기존 **navigation** 모드와 별개로 **Lighthouse** 패널에서 유저 플로우를 측정하기 위한 **timespan**, **snapshot** 모드를 추가로 지원합니다. -예를 들어, **timespan** 보고서를 유저 인터렉션을 측정하기 위해 사용할 수 있습니다. [데모](https://coffee-cart.netlify.app/) 페이지를 열어 **Timespan** 모드를 선택한 뒤 **Start timespan** 을 클릭하세요. 페이지에서 커피를 선택한 뒤 timespan을 종료하세요. 보고서를 읽어보면 인터렉션으로 인해 발생한 [총 차단 시간](https://web.dev/tbt/)과 [누적 레이아웃 이동](https://web.dev/cls/) 을 찾을 수 있습니다. +예를 들어, **timespan** 보고서를 유저 인터렉션을 측정하기 위해 사용할 수 있습니다. [데모](https://coffee-cart.netlify.app/) 페이지를 열어 **Timespan** 모드를 선택한 뒤 **Start timespan** 을 클릭하세요. 페이지에서 커피를 선택한 뒤 timespan을 종료하세요. 보고서를 읽어보면 인터렉션으로 인해 발생한 [총 차단 시간](https://web.dev/articles/tbt)과 [누적 레이아웃 이동](https://web.dev/articles/cls) 을 찾을 수 있습니다. 각 모드에는 고유한 사용 사례, 이점, 제한 사항이 있습니다. 더 상세한 정보는 [Lighthouse 문서](https://github.com/GoogleChrome/lighthouse/blob/master/docs/user-flows.md) 를 살펴보세요. diff --git a/site/ko/blog/new-in-devtools-102/index.md b/site/ko/blog/new-in-devtools-102/index.md index a198d1447..fd9b3e3f0 100644 --- a/site/ko/blog/new-in-devtools-102/index.md +++ b/site/ko/blog/new-in-devtools-102/index.md @@ -48,8 +48,8 @@ Chromium issue: [1270700](https://crbug.com/1270700) <!-- ## New shortcuts to emulate light and dark themes {: #emulation } --> ## 새 바로가기 메뉴 - 라이트 테마 및 다크 테마 에뮬레이팅하기 {: #emulation } -<!-- You can now emulate the light and dark themes quicker (CSS media feature [prefers-color-scheme](https://web.dev/prefers-color-scheme/#the-prefers-color-scheme-media-query)) with the new shortcuts in the **Styles** pane. --> -여러분은 이제 **스타일** 창의 새 바로가기를 통해 라이트 테마 및 다크 테마를 좀 더 빠르게 에뮬레이트할 수 있습니다. (CSS 미디어 기능 [prefers-color-scheme](https://web.dev/prefers-color-scheme/#the-prefers-color-scheme-media-query)) +<!-- You can now emulate the light and dark themes quicker (CSS media feature [prefers-color-scheme](https://web.dev/articles/prefers-color-scheme#the_prefers_color_scheme_media_query)) with the new shortcuts in the **Styles** pane. --> +여러분은 이제 **스타일** 창의 새 바로가기를 통해 라이트 테마 및 다크 테마를 좀 더 빠르게 에뮬레이트할 수 있습니다. (CSS 미디어 기능 [prefers-color-scheme](https://web.dev/articles/prefers-color-scheme#the_prefers_color_scheme_media_query)) <!-- Previously, it took more steps to [emulate themes](/docs/devtools/rendering/emulate-css/) in the **Rendering** tab. --> 이전에는, **렌더링** 탭에서 [테마 에뮬레이션](/docs/devtools/rendering/emulate-css/) 을 위해 더 많은 단계를 거쳐야 했습니다. {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/dCbNHwE5ICGNXRUws1zz.png", alt="라이트 테마 및 다크 테마를 에뮬레이팅하기 위한 새로운 바로가기", width="800", height="488" %} @@ -63,8 +63,8 @@ Chromium issue: [1314299](https://crbug.com/1314299) ## 네트워크 창의 미리보기 탭 보안 개선 {: #network-preview } <!-- DevTools now apply the Content Security Policy (CSP) in the **Preview** tab in the **Network** panel. --> DevTools의 새로운 기능 중 하나로, **네트워크** 창의 **미리보기** 탭에 콘텐츠 보안 정책(CSP)이 적용되었습니다. -<!-- For example, the first screenshot shows a page that contains [mixed content](https://web.dev/what-is-mixed-content/). The page loads over a secure HTTPS connection, but the stylesheet loads over an insecure HTTP connection. --> -예를 들어, 첫 번째 스크린샷을 보면 이 페이지에는 [혼합 콘텐츠](https://web.dev/what-is-mixed-content/)가 포함되어 있습니다. 이 페이지는 안전한 HTTPS 연결을 통해 로딩되지만, 스타일시트는 로딩을 위해 보안되지 않은 HTTP 연결을 이용합니다. +<!-- For example, the first screenshot shows a page that contains [mixed content](https://web.dev/articles/what-is-mixed-content). The page loads over a secure HTTPS connection, but the stylesheet loads over an insecure HTTP connection. --> +예를 들어, 첫 번째 스크린샷을 보면 이 페이지에는 [혼합 콘텐츠](https://web.dev/articles/what-is-mixed-content)가 포함되어 있습니다. 이 페이지는 안전한 HTTPS 연결을 통해 로딩되지만, 스타일시트는 로딩을 위해 보안되지 않은 HTTP 연결을 이용합니다. <!-- The browser blocked the stylesheet request by default. However, when you opened the page via the **Preview** tab in the **Network** panel, the stylesheet was not blocked previously (hence the background turned into red). It is now blocked as you would expect (second screenshot). --> 브라우저는 스타일시트 요청을 기본적으로 제한합니다. 그러나 이 페이지를 **네트워크** 창의 **미리보기** 탭을 통해 열었을 때, 이전에는 스타일시트의 요청이 제한되지 않았습니다. (따라서 배경이 붉게 바뀝니다.) 그러나 이제는 여러분이 기대하는 것처럼 요청이 받아들여지지 않습니다. {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/jxqxoJYqWXGzj4V9aJaX.png", alt="네트워크 창의 미리 보기 탭 보안 개선", width="800", height="488" %} @@ -94,7 +94,7 @@ Chromium issues: [1014415](https://crbug.com/1014415), [1004038](https://crbug.c <!-- ### Handle script execution errors in the Console {: #errors } --> ### 콘솔에서의 스크립트 실행 오류 다루기 {: #errors } <!-- Errors during script evaluation in the Console now generate proper error events that trigger the `window.onerror` handler and are dispatched as `"error"` events on the window object. --> -콘솔에서의 스크립트 평가 중 발생한 오류는 `window.onerror` 핸들러를 실행시키는 데 적절한 오류 이벤트를 생성하며, 이 이벤트는 윈도우 객체의 `"error"` 이벤트로 전달됩니다. +콘솔에서의 스크립트 평가 중 발생한 오류는 `window.onerror` 핸들러를 실행시키는 데 적절한 오류 이벤트를 생성하며, 이 이벤트는 윈도우 객체의 `"error"` 이벤트로 전달됩니다. {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/gBtY4zD39SPizfcCGJJW.png", alt="콘솔에서의 스크립트 실행 오류 다루기", width="800", height="487" %} @@ -119,7 +119,7 @@ Chromium issue: [1260744](https://crbug.com/1260744) <!-- ## Cancel user flow recording at the start {: #recorder } --> ## 시작 전에 유저 플로우 녹화 취소하기 {: #recorder } <!-- You can cancel the recording during the start of user flow recording. Previously, there was no option to cancel the recording. --> -이전 버전에서는 녹화를 취소할 수 있는 옵션이 없었으나 이제 유저 플로우 녹화 시작 중에도 취소가 가능해졌습니다. +이전 버전에서는 녹화를 취소할 수 있는 옵션이 없었으나 이제 유저 플로우 녹화 시작 중에도 취소가 가능해졌습니다. {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/3vhz3UrjLd9lJKcYw2FU.png", alt="시작 중에 유저 플로우 녹화 취소하기", width="800", height="488" %} @@ -130,7 +130,7 @@ Chromium issue: [1257499](https://crbug.com/1257499) <!-- ## Display inherited highlight pseudo-elements in the Styles pane {: #pseudo } --> ## 스타일 창에 상속된 하이라이트 의사 요소들 표시하기 {: #pseudo } <!-- View the inherited highlight pseudo-elements (e.g. `::selection`, `::spelling-error`, `::grammar-error`, and `::highlight`) in the **Styles** pane. Previously, these rules were not displayed. --> -**스타일** 창에서 상속된 하이라이트 의사 요소들 (예시: `::selection`, `::spelling-error`, `::grammar-error`, `::highlight`)을 보세요. 이전에는 이 규칙들이 표시되지 않았습니다. +**스타일** 창에서 상속된 하이라이트 의사 요소들 (예시: `::selection`, `::spelling-error`, `::grammar-error`, `::highlight`)을 보세요. 이전에는 이 규칙들이 표시되지 않았습니다. <!-- As mentioned in the [specification](https://drafts.csswg.org/css-pseudo-4/#highlight-cascade), when multiple styles conflict, cascade determines the winning style. This new feature helps you understand the inheritance and priority of the rules. --> [스펙 문서](https://drafts.csswg.org/css-pseudo-4/#highlight-cascade)에 언급되었듯이 다중 스타일이 충돌을 일으킬 때, 캐스케이드가 가장 우선시되는 스타일을 결정합니다. 이 새로운 기능은 여러분들로 하여금 상속과 우선되는 규칙을 더 잘 이해할 수 있도록 해 줍니다. {% Aside %} @@ -158,7 +158,7 @@ Chromium issue: [1024156](https://crbug.com/1024156) - **스타일** 창이 오버라이딩된 `@support` 규칙을 취소선으로 적절하게 표시하기 시작했습니다. 이전 버전에서는 취소선이 표시되지 않았습니다. ([1298025](https://crbug.com/1298025)) - **소스** 창에서 CSS를 편집할 떄 여러 개의 빈 줄을 만들던 CSS 포매팅 로직이 현 버전에서 수정되었습니다. - **콘솔**에 있는 객체의 **재귀적으로 확장** 옵션을 최대 100으로 제한하여 원형 개체에 대해 영원히 지속되지 않도록 합니다. ([1272450](https://crbug.com/1272450)) - + {# https://chromium.googlesource.com/devtools/devtools-frontend/+/d4240f8bc96a3ebd2dc2a5b316fd41c24e20fb3c #} {# https://chromium.googlesource.com/devtools/devtools-frontend/+/cf09d1de8a0277dbaa9e2000a8d2fcca69e7128e #} {# https://chromium.googlesource.com/devtools/devtools-frontend/+/6616b9f0cd3e9f1138fb0f409fbe91206d5c8640 #} @@ -183,7 +183,7 @@ Chromium issue: [1024156](https://crbug.com/1024156) {# https://chromium.googlesource.com/devtools/devtools-frontend/+/afe5698f1cd20304d2763574ef8e9faf6a4a6db1 #} {# ​​https://chromium.googlesource.com/devtools/devtools-frontend/+/5de1d6140cad945783f3ca54055134f4a7db42a1 #} -{# https://chromium.googlesource.com/devtools/devtools-frontend/+/573dfc1cca09e49177ece3898c9ba9619c386f06 #} +{# https://chromium.googlesource.com/devtools/devtools-frontend/+/573dfc1cca09e49177ece3898c9ba9619c386f06 #} Chromium issue: [1268754](https://crbug.com/1268754) diff --git a/site/ko/blog/new-in-devtools-104/index.md b/site/ko/blog/new-in-devtools-104/index.md index 9d59d2917..91f3143f2 100644 --- a/site/ko/blog/new-in-devtools-104/index.md +++ b/site/ko/blog/new-in-devtools-104/index.md @@ -60,17 +60,17 @@ Chromium issue: [1325751](https://crbug.com/1325751) 소스 패널에서 **작성자 순/배포 순으로 파일 그룹핑하기** 옵션을 사용하여 파일을 묶을 수 있습니다. 프레임워크 (React, Angular 등)을 이용해 웹 애플리케이션을 개발할 때, 빌드 도구 (Webpack, Vite)를 통해 생성된 압축된 파일들을 소스 파일에서 살펴보기 어려울 수 있기 때문입니다. -이 체크박스를 이용해, 파일을 2가지 카테고리로 그룹하여 빠르게 찾을 수 있습니다. - +이 체크박스를 이용해, 파일을 2가지 카테고리로 그룹하여 빠르게 찾을 수 있습니다. + - **Authored**. IDE에서 보는 것과 비슷하게 소스 파일을 봅니다. DevTools 는 (빌드 도구에서 제공한) 소스맵을 바탕으로 이 파일들을 생성합니다. - **Deployed**. 브라우저에서 읽어들인 실제 파일들입니다. 보통 이 파일들은 경량화되어있습니다. - + 다음 [React 데모](https://reactjs.org/) 에서 한 번 해보세요! {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/5E1qbkl0Gx1REx7FdqEr.png", alt="소스 패널에서 작성자 / 배포 순 그룹하기", width="800", height="521" %} {# https://chromium.googlesource.com/devtools/devtools-frontend/+/6bc65d0595702fc826ca87e2cfe519a134b62d90 #} - + Chromium issue: [960909](https://crbug.com/960909) @@ -78,7 +78,7 @@ Chromium issue: [960909](https://crbug.com/960909) **Performance insights** 패널 안에서 새로운 **User Timings** 트랙을 사용하여 녹화본 내의 `performance.measure()` 마크를 시각화할 수 있습니다. -예를 들어, 다음 [웹 페이지](https://jec.fish/demo/perf-measure) 에서 [`performance.measure()`](https://web.dev/usertiming/#calculating-measurements-with-measure()) 메서드를 텍스트 로딩 경과 시간을 계산하기 위해 사용하고 있습니다. +예를 들어, 다음 [웹 페이지](https://jec.fish/demo/perf-measure) 에서 [`performance.measure()`](https://web.dev/articles/usertiming#calculating_measurements_with_measure()) 메서드를 텍스트 로딩 경과 시간을 계산하기 위해 사용하고 있습니다. [measuring the page load](/docs/devtools/performance-insights/#record) 를 시작하면, 녹화본에서 **User Timings** 트랙이 보일 것입니다. 타이밍 아이템을 클릭하면 사이드 영역에서 상세한 내용을 볼 수 있습니다. @@ -86,7 +86,7 @@ Chromium issue: [960909](https://crbug.com/960909) Chromium issue: [1322808](https://crbug.com/1322808) - + ## 요소의 할당된 슬롯 표시 {: #slot } **요소** 패널에서 슬롯된 요소는 `slot` 뱃지와 함께 보입니다. 레이아웃 문제를 디버깅 할 때 이 기능을 사용하여 노드의 레이아웃에 영향을 미치는 요소를 더 빨리 식별할 수 있습니다. @@ -103,16 +103,16 @@ Chromium issue: [1018906](https://crbug.com/1018906) ## 성능 기록을 위한 하드웨어 동시성 시뮬레이션 {: #simulate } - + **성능** 패널에서 **하드웨어 동시성** 설정을 사용하여 `navigator.hardwareConcurrency` 를 통해 보고된 값을 정의할 수 있습니다. -일부 애플리케이션은 `navigator.hardwareConcurrency`를 사용하여 애플리케이션의 병렬 처리 정도를 제어합니다. +일부 애플리케이션은 `navigator.hardwareConcurrency`를 사용하여 애플리케이션의 병렬 처리 정도를 제어합니다. 예를 들어, Emscripten pthread 풀 사이즈를 제어할 수 있습니다. 이 기능을 통해 개발자는 다양한 코어 수로 애플리케이션 성능을 테스트할 수 있습니다. - + {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/PyykGRv29FZbBKJAwWOW.png", alt="성능 기록을 위한 하드웨어 동시성 시뮬레이션", width="800", height="536" %} {# https://chromium.googlesource.com/devtools/devtools-frontend/+/b26de259d74a45e700d989ad9178c5e3a8b73145 #} - + Chromium issue: [1297439](https://crbug.com/1297439) @@ -126,18 +126,18 @@ CSS 변수를 자동완성할 때, DevTools 는 값이 노드에 어떤 종류 Chromium issue: [1285091](https://crbug.com/1285091) - + ## 뒤로-앞으로 캐시 창에서 차단 프레임 식별 {: #bfcache } **애플리케이션** 패널의 [뒤로-앞으로 캐시](/docs/devtools/application/back-forward-cache/) 창의 새로운 **frames** 섹션에서, 페이지가 bfcache에 적합하지 못하게 하는 차단 프레임을 식별할 수 있습니다. {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/UaRYEoYYoXhjSIn9seYK.png", alt="뒤로-앞으로 캐시 영역에서 차단 프레임 식별", width="800", height="486" %} - + {# https://chromium.googlesource.com/devtools/devtools-frontend/+/897799b24fff0639d483111dd2d957288ba2bd06 #} - -Chromium issue: [1288158](https://crbug.com/1288158) - - + +Chromium issue: [1288158](https://crbug.com/1288158) + + ## 자바스크립트 객체 자동완성 제안 기능 개선 {: #autocomplete } 자바스크립트 객체 속성 자동 완성이 다음 순서대로 노출됩니다. @@ -152,14 +152,14 @@ Chromium issue: [1288158](https://crbug.com/1288158) {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/IvFTcOWrBOTTMRHqn8u4.png", alt="자바스크립트 객체 자동완성 제안 기능 개선", width="800", height="563" %} {# https://chromium.googlesource.com/devtools/devtools-frontend/+/cee5205ae93c95b1dce49e220b9ebfa8c998d5a6 #} - + Chromium issue: [1299241](https://crbug.com/1299241) - + ## 소스맵 개선 {: #sourcemaps } 전반적인 디버깅 경험을 개선하기 위한 소스맵 수정 사항이 있습니다. - + - sourceURL 어노테이션을 이용한 인라인 `<script>` 에서 중단점이 동작합니다. - 디버거가 소스맵을 사용하여 **Scope** 뷰에서 블록 범위 변수를 확인합니다. {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/gv9cGnDMF7OVlXPWntII.png", alt="블록 범위 변수 확인", width="800", height="532" %} @@ -167,17 +167,17 @@ Chromium issue: [1299241](https://crbug.com/1299241) {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/CZk0xjwMQAqknkW5G4Xf.png", alt="함수 내 변수 확인", width="800", height="479" %} Chromium issues: [1329113](https://crbug.com/1329113), [1322115](https://crbug.com/1322115) - - + + ## 기타 하이라이트 {: #misc } - + 이번 릴리스에서 수정된 사항들입니다. - + - **소스** 패널에서 **자동 완성** 설정 수정, 이전에는 설정이 비활성화된 경우에도 자동 완성이 항상 켜져 있었습니다. ([1323286](https://crbug.com/1323286)) - **애플리케이션** 패널 내 **Manifest** 탭에서 최신 색상 스킴 포맷으로 파싱하도록 개선 ([1318305](https://crbug.com/1318305)) - **Performance insights** 패널에서 `<script async>` 렌더링 차단 이슈를 위한 제안을 개선. 이전에는 DevTools가 script가 이미 async 속성을 가지고 있어도 `script 태그에 async 속성을 추가하세요` 라고 제안했습니다. ([1334096](https://crbug.com/1334096)) - **Performance insights** 패널에서 레이아웃 시프트를 유발할 가능성이 있는 iframe을 감지해냅니다. **Details** 창에서 iframe 상세를 볼 수 있습니다. ([1328873](https://crbug.com/1328873)) -- **커맨드 메뉴** 에서 [파일 열기](/docs/devtools/resources/#open) 할 때, 작성된 파일 (소스맵을 통해 생성된 파일)이 비슷한 이름의 배포된 스크립트보다 더 상위에 노출됩니다. ([1312929](https://crbug.com/1312929)) +- **커맨드 메뉴** 에서 [파일 열기](/docs/devtools/resources/#open) 할 때, 작성된 파일 (소스맵을 통해 생성된 파일)이 비슷한 이름의 배포된 스크립트보다 더 상위에 노출됩니다. ([1312929](https://crbug.com/1312929)) {% Partial 'devtools/reach-out.md' %} {% Partial 'devtools/whats-new.md' %} diff --git a/site/ko/blog/new-in-devtools-105/index.md b/site/ko/blog/new-in-devtools-105/index.md index b59d34317..8adc79160 100644 --- a/site/ko/blog/new-in-devtools-105/index.md +++ b/site/ko/blog/new-in-devtools-105/index.md @@ -57,9 +57,9 @@ Chromium issue: [1257499](https://crbug.com/1257499) <!-- ## Largest Contentful Paint (LCP) in the Performance insights panel {: #lcp } --> ## Performance insights 패널의 Largest Contentful Paint (LCP) {: #lcp } -<!-- LCP is an important, user-centric metric for measuring [perceived load speed](https://web.dev/user-centric-performance-metrics/#types-of-metrics). You can now find out the critical paths and root causes of a [Largest Contentful Paint (LCP)](https://web.dev/lcp/). --> -LCP 는 [인지 로드 속도](https://web.dev/user-centric-performance-metrics/#types-of-metrics)를 측정하기 위한 중요한 사용자 중심적 측정 기준입니다. -여러분은 이제 [최대 콘텐츠풀 페인트(LCP)](https://web.dev/lcp/) 의 중요한 경로와 근본적인 원인을 찾을 수 있습니다. +<!-- LCP is an important, user-centric metric for measuring [perceived load speed](https://web.dev/articles/user-centric-performance-metrics#types_of_metrics). You can now find out the critical paths and root causes of a [Largest Contentful Paint (LCP)](https://web.dev/articles/lcp). --> +LCP 는 [인지 로드 속도](https://web.dev/articles/user-centric-performance-metrics#types_of_metrics)를 측정하기 위한 중요한 사용자 중심적 측정 기준입니다. +여러분은 이제 [최대 콘텐츠풀 페인트(LCP)](https://web.dev/articles/lcp) 의 중요한 경로와 근본적인 원인을 찾을 수 있습니다. <!-- In a [performance recording](/docs/devtools/performance-insights/#record), click on the LCP badge in the **Timeline**. In the **Details** pane, you can view the LCP score, learn how to fix resources that slow down the LCP and see the critical path for the LCP resource. --> [performance recording](/docs/devtools/performance-insights/#record) 에서, **타임라인** 의 LCP 배지를 클릭하세요. **Details** 창에서, 여러분은 LCP 점수를 볼 수 있고, LCP를 느리게 만드는 리소스를 어떻게 수정할지를 알 수 있고, LCP 자원의 중요한 경로를 찾을 수 있습니다. <!-- See [Performance Insights](/docs/devtools/performance-insights/) to learn how to get actionable insights and improve your website’s performance with the panel. --> @@ -72,12 +72,12 @@ Chromium issue: [1326481](https://crbug.com/1326481) <!-- ## Identify flashes of text (FOIT, FOUT) as potential root causes for layout shifts {: #foit-fout } --> ## 레이아웃 변경의 잠재적 근본 원인으로서 텍스트 깜박임(FOIT, FOUT) 식별 {: #foit-fout } -<!-- The **Performance insights** panel now detects [flash of invisible text (FOIT) and flash of unstyled text (FOUT)](https://web.dev/preload-optional-fonts/#font-rendering) as potential root causes for layout shifts. --> -이제 **Performance insights** 패널에서, 레이아웃 변경의 잠재적 근본 원인으로서 [보이지 않는 텍스트 깜박임(FOIT)과 스타일이 지정되지 않은 텍스트 깜박임(FOUT)](https://web.dev/preload-optional-fonts/#font-rendering)을 감지할 수 있습니다. +<!-- The **Performance insights** panel now detects [flash of invisible text (FOIT) and flash of unstyled text (FOUT)](https://web.dev/articles/preload-optional-fonts#font_rendering) as potential root causes for layout shifts. --> +이제 **Performance insights** 패널에서, 레이아웃 변경의 잠재적 근본 원인으로서 [보이지 않는 텍스트 깜박임(FOIT)과 스타일이 지정되지 않은 텍스트 깜박임(FOUT)](https://web.dev/articles/preload-optional-fonts#font_rendering)을 감지할 수 있습니다. <!-- To view the potential root causes of a layout shift, click on a screenshot in the **Layout shifts** track. --> 레이아웃 변경의 잠재적 근본 원인을 찾아보기 위해서, **Layout shifts** 트랙 내의 스크린샷을 클릭하세요. -<!-- See [Optimize WebFont loading and rendering](https://web.dev/optimize-webfont-loading/) to learn the technique to prevent layout shifts. --> -[WebFont 로딩 및 렌더링 최적화](https://web.dev/optimize-webfont-loading/)에서 레이아웃 변경을 방지하기 위한 기술들을 배워 보세요. +<!-- See [Optimize WebFont loading and rendering](https://web.dev/articles/optimize-webfont-loading) to learn the technique to prevent layout shifts. --> +[WebFont 로딩 및 렌더링 최적화](https://web.dev/articles/optimize-webfont-loading)에서 레이아웃 변경을 방지하기 위한 기술들을 배워 보세요. {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/AMN5oD5hlKhPhnq98sIB.png", alt="Performance insights 패널에서의 FOUT", width="800", height="497" %} Chromium issues: [1334628](https://crbug.com/1334628), [1328873](https://crbug.com/1328873) @@ -85,8 +85,8 @@ Chromium issues: [1334628](https://crbug.com/1334628), [1328873](https://crbug.c <!-- ## Protocol handlers in the Manifest pane {: #manifest } --> ## 매니페스트 창의 프로토콜 핸들러 {: #manifest } -<!-- You can now use DevTools to test the [URL protocol handler registration](https://web.dev/url-protocol-handler/) for [Progressive Web Apps (PWA)](https://web.dev/learn/pwa/). --> -이제 여러분은 DevTools를 이용하여 [프로그레시브 웹 앱(PWA)](https://web.dev/learn/pwa/)에 대한 [URL 프로토콜 핸들러 등록](https://web.dev/url-protocol-handler/)을 테스트할 수 있습니다. +<!-- You can now use DevTools to test the [URL protocol handler registration](https://web.dev/articles/url-protocol-handler) for [Progressive Web Apps (PWA)](https://web.dev/learn/pwa). --> +이제 여러분은 DevTools를 이용하여 [프로그레시브 웹 앱(PWA)](https://web.dev/learn/pwa)에 대한 [URL 프로토콜 핸들러 등록](https://web.dev/articles/url-protocol-handler)을 테스트할 수 있습니다. <!-- The URL protocol handler registration lets installed PWAs handle links that use a specific protocol (e.g. [`magnet`](https://wikipedia.org/wiki/Magnet_URI_scheme), `web+example`) for a more integrated experience. --> URL 프로토콜 핸들러 등록을 통해, 설치된 PWA(프로그레시브 웹 앱)이 특정한 프로토콜 (예: [`magnet`](https://wikipedia.org/wiki/Magnet_URI_scheme), `web+example`) 핸들링하도록 할 수 있으며, 이는 더욱 통합된 경험을 위해서입니다. @@ -110,8 +110,8 @@ Chromium issues: [1300613](https://crbug.com/1300613) <!-- Use the [top layer badge](/blog/top-layer-devtools/#top-layer-support-design-in-devtools) to understand the concept of the top layer and visualize how the top layer content changes. --> [Top layer badge](/blog/top-layer-devtools/#top-layer-support-design-in-devtools) 를 사용하여, top layer의 개념을 이해할 수 있으며 또한 top layer 의 컨텐츠 변화를 시각화할 수 있습니다. -<!-- The [`<dialog>` element](https://web.dev/building-a-dialog-component/) has recently become stable across browsers. When you open a dialog, it is put into a [top layer](/blog/top-layer-devtools/). Top level content renders on top of all the other content. --> -[`<dialog>` 요소](https://web.dev/building-a-dialog-component/) 가 최근에 웹 브라우저들에 대해 안정화되었습니다. 여러분이 다이얼로그를 열 때, 이는 [top layer](/blog/top-layer-devtools/)에 위치하게 됩니다. 최상위 레벨 컨텐츠는 기타 다른 컨텐츠 위에 렌더링됩니다. +<!-- The [`<dialog>` element](https://web.dev/articles/building-a-dialog-component) has recently become stable across browsers. When you open a dialog, it is put into a [top layer](/blog/top-layer-devtools/). Top level content renders on top of all the other content. --> +[`<dialog>` 요소](https://web.dev/articles/building-a-dialog-component) 가 최근에 웹 브라우저들에 대해 안정화되었습니다. 여러분이 다이얼로그를 열 때, 이는 [top layer](/blog/top-layer-devtools/)에 위치하게 됩니다. 최상위 레벨 컨텐츠는 기타 다른 컨텐츠 위에 렌더링됩니다. <!-- In this [demo](https://jec.fish/demo/dialog), click **Open dialog**. --> 주어진 [데모](https://jec.fish/demo/dialog) 페이지에서 **Open dialog**를 클릭합니다. diff --git a/site/ko/blog/new-in-devtools-106/index.md b/site/ko/blog/new-in-devtools-106/index.md index bb14f4ade..993da0298 100644 --- a/site/ko/blog/new-in-devtools-106/index.md +++ b/site/ko/blog/new-in-devtools-106/index.md @@ -170,7 +170,7 @@ Chromium bug: [1351383](https://crbug.com/1351383) - 이전에는 [기록 확장 프로그램들](/docs/devtools/recorder/reference/#extension-troubleshooting)이 **기록** 패널에서 종종 표시되지 않았습니다. ([1351416](https://crbug.com/1351416)) - **스타일** 창은 이제 [SVG `<stop>`](https://developer.mozilla.org/docs/Web/SVG/Element/stop) 요소의 `stop-color` 속성에 대한 색상 선택기를 표시해줍니다. ([1351096](https://crbug.com/1351096)) -- **Performance Insights** 패널에서 레이아웃 변경의 근본적 잠재원인인 [레이아웃](https://web.dev/avoid-large-complex-layouts-and-layout-thrashing/)을 유발하는 스크립트를 식별합니다. ([1343019](https://crbug.com/1343019)) +- **Performance Insights** 패널에서 레이아웃 변경의 근본적 잠재원인인 [레이아웃](https://web.dev/articles/avoid-large-complex-layouts-and-layout-thrashing)을 유발하는 스크립트를 식별합니다. ([1343019](https://crbug.com/1343019)) - **Performance Insights** 패널에서 LCP 웹 글꼴의 주요 경로를 표시합니다. ([1350390](https://crbug.com/1350390)) {# https://chromium.googlesource.com/devtools/devtools-frontend/+/50a84ca8e5b556e27bb285477f21a99f0ccb7050 #} diff --git a/site/ko/blog/new-in-devtools-93/index.md b/site/ko/blog/new-in-devtools-93/index.md index e5f903b8e..8bcd33817 100644 --- a/site/ko/blog/new-in-devtools-93/index.md +++ b/site/ko/blog/new-in-devtools-93/index.md @@ -22,7 +22,7 @@ tags: {% YouTube id="1VaPAnUGRz8" %} ## Styles 영역에서 CSS 컨테이너 쿼리를 수정할 수 있습니다 {: #container-queries } -이제 **Styles** 영역에서 [CSS 컨테이너 쿼리](https://web.dev/new-responsive/#responsive-to-the-container) 를 보고 수정할 수 있습니다. +이제 **Styles** 영역에서 [CSS 컨테이너 쿼리](https://web.dev/articles/new-responsive#responsive_to_the_container) 를 보고 수정할 수 있습니다. 컨테이너 쿼리는 반응형 디자인을 구현하기 위해 더 다양한 접근 방식을 제공합니다. `@container` 규칙은 `@media` 를 사용한 미디어 쿼리와 비슷한 방식으로 동작합니다. @@ -45,7 +45,7 @@ Chromium issue: [1146422](https://crbug.com/1146422) ## Network 패널에서 Web bundle 미리보기 {: #web-bundle } -[Web bundle](https://web.dev/web-bundles/) 여러개의 HTTP 리소스를 하나의 파일로 묶은 파일 포맷입니다. 이제 **Network** 패널에서 web bundle 의 내용을 미리볼 수 있습니다. +[Web bundle](https://web.dev/articles/web-bundles) 여러개의 HTTP 리소스를 하나의 파일로 묶은 파일 포맷입니다. 이제 **Network** 패널에서 web bundle 의 내용을 미리볼 수 있습니다. web bundle은 현재 실험 기능입니다. `chrome://flags` 에서 `#enable-experimental-web-platform-features` 플래그를 활성화한 상태로 테스트하세요. diff --git a/site/ko/blog/new-in-devtools-96/index.md b/site/ko/blog/new-in-devtools-96/index.md index 3b29f5abe..5f90c240a 100644 --- a/site/ko/blog/new-in-devtools-96/index.md +++ b/site/ko/blog/new-in-devtools-96/index.md @@ -36,7 +36,7 @@ tags: 여러분은 CSS의 정보들을 더욱 깊이 파고들 수 있게 됩니다. 예를 들어, **색상** 섹션의 색상을 클릭해서 동일한 색상이 적용되는 요소들의 리스트를 볼 수 있으며, 하나의 구성요소를 클릭해서 **구성요소** 패널에서 열어 볼 수 있습니다. -**CSS 개요** 패널은 프리뷰 기능입니다. 우리는 이 기능에 계속적인 노력을 기울이고 있으며, 또한 더 많은 개선점을 찾기 위해서 여러분의 [피드백](https://goo.gle/css-overview-feedback)이 필요합니다. +**CSS 개요** 패널은 프리뷰 기능입니다. 우리는 이 기능에 계속적인 노력을 기울이고 있으며, 또한 더 많은 개선점을 찾기 위해서 여러분의 [피드백](https://goo.gle/css-overview-feedback)이 필요합니다. **CSS 개요** 에 대해 좀 더 알고 싶으시다면 [더보기](/docs/devtools/css-overview)를 클릭하여 첨부된 문서를 읽어 보세요. @@ -67,7 +67,7 @@ Chromium issue: [1254557](https://crbug.com/1254557) Chromium issues: [1259088](https://crbug.com/1259088), [1172993](https://crbug.com/1172993) -## 렌더링 탭의 업데이트 +## 렌더링 탭의 업데이트 ### CSS 의 prefers-contrast 미디어 기능 에뮬레이션 {: #prefers-contrast } @@ -135,14 +135,14 @@ Chromium issue: [1214030](https://crbug.com/1214030) {# https://chromium.googlesource.com/devtools/devtools-frontend/+/f1574e9b550317c481a943fec059d84bfb863564 #} -Chromium issue: [1226262](https://crbug.com/1226262) +Chromium issue: [1226262](https://crbug.com/1226262) ## 콘솔 업데이트 ### 콘솔의 CORS 에러 숨김 옵션 {: #hide-cors-errors } -**콘솔** 에서 CORS 오류를 숨길 수 있습니다. CORS 오류들은 현재 이슈 탭에 리포트되고 있으므로, **콘솔** 에서 이들을 숨기는 것은 콘솔 내부에 어지럽게 흩어진 오류들을 줄이는 데 도움을 줄 수 있습니다. +**콘솔** 에서 CORS 오류를 숨길 수 있습니다. CORS 오류들은 현재 이슈 탭에 리포트되고 있으므로, **콘솔** 에서 이들을 숨기는 것은 콘솔 내부에 어지럽게 흩어진 오류들을 줄이는 데 도움을 줄 수 있습니다. **콘솔**에서 **설정** 아이콘을 클릭한 다음 **콘솔에 CORS 오류 표시** 체크박스를 해제합니다. @@ -155,7 +155,7 @@ Chromium issue: [1251176](https://crbug.com/1251176) ### 콘솔에서 적절한 `Intl` 객체 미리보기 및 값 판별 {: #intl } -[Intl](https://tc39.es/ecma402/#intl-object)객체는 적절한 미리보기 기능을 가지고 있고, 또한 콘솔은 이 객체의 모든 값을 괄호닫음 없이 모두 표시합니다. +[Intl](https://tc39.es/ecma402/#intl-object)객체는 적절한 미리보기 기능을 가지고 있고, 또한 콘솔은 이 객체의 모든 값을 괄호닫음 없이 모두 표시합니다. <!-- {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/ZxGQoDdnilseKTFsxdbC.png", alt="Intl objects in the Console", width="800", height="559" %} --> @@ -189,11 +189,11 @@ Chromium issues: [1232937](https://crbug.com/1232937), [1255586](https://crbug.c ## 애플리케이션 패널 내 애플리케이션 캐시 영역 제거 예정 {: #app-cache } -[AppCache](https://web.dev/appcache-removal/)에 대한 지원이 크롬 및 다른 크로미움 기반 브라우저에서 중단됨에 따라, 애플리케이션 패널 내부 [애플리케이션 캐시](/docs/devtools/storage/applicationcache/) 영역이 제거되었습니다. +[AppCache](https://web.dev/articles/appcache-removal)에 대한 지원이 크롬 및 다른 크로미움 기반 브라우저에서 중단됨에 따라, 애플리케이션 패널 내부 [애플리케이션 캐시](/docs/devtools/storage/applicationcache/) 영역이 제거되었습니다. {# https://chromium.googlesource.com/devtools/devtools-frontend/+/de4d15e955d6145674e3885cde8a5a70f1269b79 #} -Chromium issue: [1084190](https://crbug.com/1084190) +Chromium issue: [1084190](https://crbug.com/1084190) ## [실험실 기능] 애플리케이션 패널에 새롭게 추가된 Reporting API 영역 {: #reporting-api } @@ -202,12 +202,12 @@ Chromium issue: [1084190](https://crbug.com/1084190) 이 기능을 활성화하기 위해서, **설정** > **실험** > **Enable Reporting API panel in the Application panel** 체크박스에 체크해 주세요. {% endAside %} -[Reporting API](https://web.dev/reporting-api/)는 개발자들이 웹페이지, 제거된 API 호츨 등에서의 보안수칙 위반을 잘 모니터링할 수 있도록 설계되었습니다. +[Reporting API](https://web.dev/articles/reporting-api)는 개발자들이 웹페이지, 제거된 API 호츨 등에서의 보안수칙 위반을 잘 모니터링할 수 있도록 설계되었습니다. 이 실험을 활성화함으로써, 여러분들은 이제 보고된 상태를 **애플리케이션** 패널의 새로운 **Reporting API** 영역에서 볼 수 있습니다. **Endpoints** 섹션은 현재 개발중임을 염두에 두세요. (따라서 엔드포인트는 현재 보고되지 않습니다.) -[관련문서](https://web.dev/reporting-api/)를 통해 **Reporting API**에 대해 좀더 알아볼 수 있습니다. +[관련문서](https://web.dev/articles/reporting-api)를 통해 **Reporting API**에 대해 좀더 알아볼 수 있습니다. {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/hbwFqi9aNDOj70FhLXsn.png", alt="Reporting API pane in the Application panel", width="800", height="476" %} diff --git a/site/ko/blog/new-in-devtools-98/index.md b/site/ko/blog/new-in-devtools-98/index.md index 2d5445cfc..5e71630de 100644 --- a/site/ko/blog/new-in-devtools-98/index.md +++ b/site/ko/blog/new-in-devtools-98/index.md @@ -43,7 +43,7 @@ tags: 접근성 트리는 **접근성** 패널에서 이용가능했습니다만, 그 뷰 자체는 오직 싱글 노드 및 그 노드의 조상들만을 볼 수 있을 만큼 제한적이었습니다. <!-- Our team is still actively working on this preview feature. We are looking for your [feedback](https://goo.gle/devtools-a11y-tree-feedback) for further enhancements! --> -우리는 아직 이 미리보기 기능 구현에 대해 적극적으로 작업하고 있으며, 앞으로의 개선점에 대한 여러분들의 [의견](https://goo.gle/devtools-a11y-tree-feedback)을 기다리고 있습니다! +우리는 아직 이 미리보기 기능 구현에 대해 적극적으로 작업하고 있으며, 앞으로의 개선점에 대한 여러분들의 [의견](https://goo.gle/devtools-a11y-tree-feedback)을 기다리고 있습니다! {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/o4BY07JabERFd6OieU8b.png", alt="전체 페이지 접근성 트리", width="800", height="505" %} @@ -80,7 +80,7 @@ Chromium issues: [1238818](https://crbug.com/1238818), [1268754](https://crbug.c <!-- Optionally, you can adjust the **Timeout** in the **Replay settings** for all the steps. Expand the **Replay settings** and edit the **Timeout** value. --> 추가적으로, 여러분은 모든 단계에 대한 **타임아웃**을 **Replay settings**에서도 조정할 수 있습니다. **Replay settings**을 확장한 다음 **타임아웃** 값을 수정합니다. - + {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/y7RDpIp3pd2n6Vnxc5Du.png", alt="유저 플로우 녹화를 위한 타임아웃 설정", width="800", height="530" %} Chromium issue: [1257499](https://crbug.com/1257499) @@ -88,8 +88,8 @@ Chromium issue: [1257499](https://crbug.com/1257499) <!-- ## Ensure your pages are cacheable with the Back/forward cache tab {: #bfcache } --> ## 뒤로/앞으로 캐쉬 탭을 이용해 페이지가 캐쉬 가능한지 확인하기 {: #bfcache } -<!-- [Back/forward cache (or bfcache)](https://web.dev/bfcache/) is a browser optimization that enables instant back and forward navigation. --> -[뒤로/앞으로 캐쉬(혹은 bfcache)](https://web.dev/bfcache/)는 브라우저 최적화의 하나로, 즉각적인 앞뒤 내비게이션을 가능하게 해 주는 기능입니다. +<!-- [Back/forward cache (or bfcache)](https://web.dev/articles/bfcache) is a browser optimization that enables instant back and forward navigation. --> +[뒤로/앞으로 캐쉬(혹은 bfcache)](https://web.dev/articles/bfcache)는 브라우저 최적화의 하나로, 즉각적인 앞뒤 내비게이션을 가능하게 해 주는 기능입니다. <!-- The new **Back/forward cache** tab can help you test your pages to ensure they're optimized for bfcache, and identify any issues that may be preventing them from being eligible. --> 새롭게 선보이는 **뒤로/앞으로 캐쉬** 탭을 사용하여, 웹 페이지들이 bfcache에 대해 최적화되었는지를 테스트할 수 있으며, 또한 페이지가 bfcache를 사용하지 못하도록 하는 이슈들을 파악할 수 있습니다. @@ -98,7 +98,7 @@ Chromium issue: [1257499](https://crbug.com/1257499) 특정 페이지를 테스트하기 위해, 크롬에서 해당 페이지로 이동한 다음 DevTools에서 **애플리케이션** > **뒤로-앞으로 캐쉬** 를 선택합니다. 그리고 **뒤로/앞으로 캐쉬 테스트** 버튼을 클릭하여 DevTools가 앞으로 혹은 뒤로 페이지 탐색을 시작하도록 하여, 해당 페이지가 bfcache 로부터 복구 가능한지를 확인할 수 있습니다. <!-- As web developers, it's critical to know how to optimize your pages for bfcache across all browsers because it will significantly improve the browsing experience for users—especially those with slower networks or devices. --> -웹 개발자는 페이지가 모든 브라우저에서 bfcache에 맞게 최적화하는 방법을 이해하는 것이 매우 중요합니다. 이는 특히 느린 네트워크 혹은 기기에서의 사용자 탐색 경험을 크게 향상시킬 수 있기 때문입니다. +웹 개발자는 페이지가 모든 브라우저에서 bfcache에 맞게 최적화하는 방법을 이해하는 것이 매우 중요합니다. 이는 특히 느린 네트워크 혹은 기기에서의 사용자 탐색 경험을 크게 향상시킬 수 있기 때문입니다. {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/4OrWjuRgG1bB0AupcMmS.png", alt="뒤로/앞으로 캐쉬 탭", width="800", height="516" %} @@ -112,7 +112,7 @@ Chromium issue: [1110752](https://crbug.com/1110752) <!-- If you want to focus on a specific property in the **Properties** pane, you can now type that property name or value in the new **Filter** textbox. --> **속성** 창의 특정 속성에 초점을 맞추고 싶으시다면, 배포판에 새로 추가된 **필터** 입력창에 프로퍼티의 이름이나 값을 기입하면 됩니다. -<!-- By default, properties whose value is `null` or `undefined` are not shown. Enable the **Show all** +<!-- By default, properties whose value is `null` or `undefined` are not shown. Enable the **Show all** checkbox to view all properties. --> 기본적으로 `null` 이나 `undefined` 값을 가지는 속성들은 표시되지 않습니다. **모두 보기** 체크박스를 클릭하여 모든 속성을 볼 수 있도록 합니다. @@ -121,8 +121,8 @@ checkbox to view all properties. --> {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/ewmNloO4ohRxlWRNuEW1.png", alt="속성 창 필터", width="800", height="505" %} -{# https://chromium.googlesource.com/devtools/devtools-frontend/+/0980f52facf75b6c03e14472d13fe27968d4732b #} - +{# https://chromium.googlesource.com/devtools/devtools-frontend/+/0980f52facf75b6c03e14472d13fe27968d4732b #} + Chromium issue: [1269674](https://crbug.com/1269674) @@ -145,7 +145,7 @@ Chromium issue: [1130859](https://crbug.com/1130859) ## 마우스를 가져가면 눈금자 표시 {: #show-rulers } <!-- You can now open the [Command Menu](/docs/devtools/command-menu/) and run the **Show rulers on hover** command. The page rulers make it easier to measure the width and height of an element. --> -여러분은 이제 [Command Menu](/docs/devtools/command-menu/) 를 열고 **마우스를 가져가면 눈금자 표시**를 실행할 수 있습니다. 페이지의 눈금 기능을 이용하여 우리는 각 요소의 길이와 넓이를 좀더 쉽게 측정할 수 있습니다. +여러분은 이제 [Command Menu](/docs/devtools/command-menu/) 를 열고 **마우스를 가져가면 눈금자 표시**를 실행할 수 있습니다. 페이지의 눈금 기능을 이용하여 우리는 각 요소의 길이와 넓이를 좀더 쉽게 측정할 수 있습니다. <!-- Previously, you can only enable the page rulers via **Settings** > **Show rulers** checkbox. --> 이전에는 **설정** > **눈금자 표시** 체크박스를 통해 페이지의 눈금 모드를 활성화할 수 있었습니다. @@ -182,7 +182,7 @@ Chromium issue: [1263866](https://crbug.com/1263866) Chromium issue: [1050021](https://crbug.com/1050021) - + <!-- ### Keyboard shortcut to expand all search results {: #toggle-search-result } --> ### 모든 검색 결과 키보드 단축키 {: #toggle-search-result } @@ -210,8 +210,8 @@ Chromium issue: [1255073](https://crbug.com/1255073) <!-- The **Lighthouse** panel is now running Lighthouse 9. Lighthouse will now list all the elements sharing the same id. --> **Lighthouse** 패널은 현재 Lighthouse 9를 구동하고 있습니다. Lighthouse는 곧 같은 아이디를 공유하는 모든 요소들을 나열할 것입니다. -<!-- Non-unique element id is a common accessibility problem. For instance, the id referenced in an `aria-labelledby` attribute is used on [multiple elements](https://web.dev/duplicate-id-aria/). --> -요소들의 비고유한 아이디는 흔히 발생하는 접근성 문제입니다. 예를 들면, `aria-labelledby` 속성이 참조하는 아이디는 [Multiple elements](https://web.dev/duplicate-id-aria/) 에서 사용됩니다. +<!-- Non-unique element id is a common accessibility problem. For instance, the id referenced in an `aria-labelledby` attribute is used on [multiple elements](https://web.dev/articles/duplicate-id-aria). --> +요소들의 비고유한 아이디는 흔히 발생하는 접근성 문제입니다. 예를 들면, `aria-labelledby` 속성이 참조하는 아이디는 [Multiple elements](https://web.dev/articles/duplicate-id-aria) 에서 사용됩니다. <!-- Check out the [What’s new in Lighthouse 9.0](/blog/lighthouse-9-0/) for more details on the updates. --> [What’s new in Lighthouse 9.0](/blog/lighthouse-9-0/) 에서 구체적인 사항들과 업데이트를 확인해 보세요! @@ -234,11 +234,11 @@ Chromium issue: [772558](https://crbug.com/772558) - 대용량 파일들을 열 때의 속도가 향상되었습니다. (예: WASM, JavaScript) - 코드를 단계별로 실행할 때 무작위 스크롤이 더 이상 발생하지 않습니다. -- 편집가능한 소스(예: snippets, local override)에 대한 자동완성 제안이 개선되었습니다. +- 편집가능한 소스(예: snippets, local override)에 대한 자동완성 제안이 개선되었습니다. {# https://chromium.googlesource.com/devtools/devtools-frontend/+/c1ab112d9002d5c3b3bb70cf2839bac182f0cdb5 #} -Chromium issue: [1241848](https://crbug.com/1241848) +Chromium issue: [1241848](https://crbug.com/1241848) <!-- ## Miscellaneous highlights {: #misc } --> ## 기타 하이라이트 {: #misc } @@ -247,12 +247,12 @@ Chromium issue: [1241848](https://crbug.com/1241848) <!-- - Properly displaying the waterfall diagram of network requests. Previously, the style was broken. ([1275501](https://crbug.com/1275501)) - The code highlight was broken when searching in documents with very long lines in the **Sources** panel. It’s now fixed. ([1275496](https://crbug.com/1275496)) -- No more duplicate **Payload** tab in network requests. ([1273972](https://crbug.com/1273972)) +- No more duplicate **Payload** tab in network requests. ([1273972](https://crbug.com/1273972)) - Fixed the missing layout shifts details in the **Summary** section of the **Performance** panel. ([1259606](https://crbug.com/1259606)) - Support arbitrary characters (e.g. `,`, `.`), in **Network Search** queries. ([1267196](https://crbug.com/1267196)) --> - **Sources** 패널에서 너무 긴 문서를 검색할 때 코드 하이라이트가 동작하지 않았던 문제가 수정되었습니다. ([1275496](https://crbug.com/1275496)) -- 네트워크 요청에서 중복된 **페이로드** 탭이 더 이상 없습니다. ([1273972](https://crbug.com/1273972)) +- 네트워크 요청에서 중복된 **페이로드** 탭이 더 이상 없습니다. ([1273972](https://crbug.com/1273972)) - **성능** 패널의 **요약** 섹션에서 누락된 레이아웃 변경 세부정보가 수정되었습니다. ([1259606](https://crbug.com/1259606)) - **네트워크 검색** 쿼리에서 임의의 문자(예: `,`, `.`)를 지원합니다. @@ -270,12 +270,12 @@ Chromium issue: [1241848](https://crbug.com/1241848) <!-- The **Endpoints** section is now available. It gives you an overview of all the endpoints configured in the `Reporting-Endpoints` header. --> 현재 **Endpoints** 섹션이 사용가능해졌으며, 이는 `Reporting-Endpoints` 헤더에 구성된 모든 엔드포인트에 대한 개요를 제공합니다. -<!-- Learn to use the [Reporting API](https://web.dev/reporting-api/) to monitor security violations, deprecated API calls, and more. --> -[Reporting API](https://web.dev/reporting-api/)를 이용하여, 보안수칙 위반, 더 이상 사용되지 않는 API의 호출 등을 모니터링할 수 있게 되었습니다. 이 기능을 어떻게 사용하는지 알아보세요! +<!-- Learn to use the [Reporting API](https://web.dev/articles/reporting-api) to monitor security violations, deprecated API calls, and more. --> +[Reporting API](https://web.dev/articles/reporting-api)를 이용하여, 보안수칙 위반, 더 이상 사용되지 않는 API의 호출 등을 모니터링할 수 있게 되었습니다. 이 기능을 어떻게 사용하는지 알아보세요! {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/D1fUz4zuS1xwDbszgft1.png", alt="Reporting API 창", width="800", height="560" %} -{# https://chromium.googlesource.com/devtools/devtools-frontend/+/a831b26b7ecde579144a42a4faaa7b639789bf3c #} +{# https://chromium.googlesource.com/devtools/devtools-frontend/+/a831b26b7ecde579144a42a4faaa7b639789bf3c #} Chromium issue: [1200732](https://crbug.com/1200732) diff --git a/site/ko/blog/new-in-devtools-99/index.md b/site/ko/blog/new-in-devtools-99/index.md index 1a4be6c34..74b074394 100644 --- a/site/ko/blog/new-in-devtools-99/index.md +++ b/site/ko/blog/new-in-devtools-99/index.md @@ -36,7 +36,7 @@ Chromium 이슈: [423246](https://crbug.com/423246) **Reporting API** 창을 사용하여 페이지에서 생성된 보고서와 그 상태를 모니터링할 수 있습니다. -[Reporting API](https://web.dev/reporting-api/) 는 페이지에 대한 보안 위험도, 더 이상 사용되지 않는 API 호출 등을 모니터링하는 데 도움을 주도록 설계되었습니다. +[Reporting API](https://web.dev/articles/reporting-api) 는 페이지에 대한 보안 위험도, 더 이상 사용되지 않는 API 호출 등을 모니터링하는 데 도움을 주도록 설계되었습니다. Reporting API 를 사용하고자 하는 페이지에 접속하세요 (예시: [demo page](https://reporting-api-demo.glitch.me/)). **애플리케이션** 패널에서 스크롤을 내려 **백그라운드 서비스** 영역의 **Reporting API** 창을 선택하세요. @@ -133,7 +133,7 @@ Chromium 이슈: [1284737](https://crbug.com/1284737) ### 소스 패널에서 워커 소스 파일 표시 {: #worker-sourcemap } -소스 패널에서 [워커](https://web.dev/workers-overview/) (예: 웹 워커, 서비스 워커) 소스 파일 및 연관된 sourceURL이 보입니다. 이전에는 워커 소스 파일이 제대로 제어되지 않았습니다. +소스 패널에서 [워커](https://web.dev/articles/workers-overview) (예: 웹 워커, 서비스 워커) 소스 파일 및 연관된 sourceURL이 보입니다. 이전에는 워커 소스 파일이 제대로 제어되지 않았습니다. {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/apH5n92bqYWINMQn5VXa.png", alt="소스 패널에서 워커 소스 파일 표시", width="800", height="509" %} @@ -181,8 +181,8 @@ Chromium 이슈: [1284245](https://crbug.com/1284245), [1284995](https://crbug.c - **쿠키** 창에서 [edit cookies](/docs/devtools/storage/cookies/#edit) 이슈를 해결하였습니다. ([1290196](https://crbug.com/1290196)) - [Command menu](/docs/devtools/command-menu/) 에서 `Shift` + `Tab` 을 사용해 이전 커맨드를 선택할 수 있습니다. ([1278743](https://crbug.com/1278743)) -- [이슈](/docs/devtools/issues/) 탭에서 [CORS preflight request](https://web.dev/cross-origin-resource-sharing/#preflight-requests-for-complex-http-calls) 이슈가 노출됩니다. ([1272445](https://crbug.com/1272445)). -- [이슈](/docs/devtools/issues/) 탭에서 [User-Agent Client Hints](https://web.dev/user-agent-client-hints/) 이슈가 노출됩니다. ([1219359](https://crbug.com/1219359)). +- [이슈](/docs/devtools/issues/) 탭에서 [CORS preflight request](https://web.dev/articles/cross-origin-resource-sharing#preflight_requests_for_complex_http_calls) 이슈가 노출됩니다. ([1272445](https://crbug.com/1272445)). +- [이슈](/docs/devtools/issues/) 탭에서 [User-Agent Client Hints](https://web.dev/articles/user-agent-client-hints) 이슈가 노출됩니다. ([1219359](https://crbug.com/1219359)). - **소스** 및 **콘솔** 패널에서 `Shift` + `Delete` 및 `Page up` / `Page down` 동작을 수정하였습니다. ([1278461](https://crbug.com/1278461), [1285662](https://crbug.com/1285662)) - **소스** 패널에서 브레이크포인트를 제거하면 브레이크포인트 편집 다이얼로그를 닫습니다. ([922513](https://crbug.com/922513)) - DevTools에서 [라이트 / 다크 테마 선택](/docs/devtools/customize/dark-theme/) 시에 다시 불러올 필요가 없어졌습니다. ([1278738](https://crbug.com/1278738)) diff --git a/site/ko/docs/lighthouse/best-practices/external-anchors-use-rel-noopener/index.md b/site/ko/docs/lighthouse/best-practices/external-anchors-use-rel-noopener/index.md index bd3416bc6..560d7a924 100644 --- a/site/ko/docs/lighthouse/best-practices/external-anchors-use-rel-noopener/index.md +++ b/site/ko/docs/lighthouse/best-practices/external-anchors-use-rel-noopener/index.md @@ -43,10 +43,10 @@ Lighthouse 보고서에서 식별된 각 링크에 `rel="noopener"` 또는 `rel= - `rel="noopener"`는 새 페이지가 `window.opener` 속성에 액세스할 수 없도록 하고 별도의 프로세스에서 실행되도록 합니다. - `rel="noreferrer"`는 동일한 효과를 갖지만 `Referer` 헤더가 새 페이지로 전송되는 것을 방지합니다. [링크 유형 "noreferrer"](https://html.spec.whatwg.org/multipage/links.html#link-type-noreferrer)를 참조하세요. -자세한 내용은 [교차 출처 리소스를 안전하게 공유](https://web.dev/cross-origin-resource-sharing/) 게시물을 참조하세요. +자세한 내용은 [교차 출처 리소스를 안전하게 공유](https://web.dev/articles/cross-origin-resource-sharing) 게시물을 참조하세요. ## 리소스 - [**교차 출처 대상에 대한 링크가 안전하지 않음** 감사의 소스 코드](https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js) -- [교차 출처 리소스를 안전하게 공유](https://web.dev/cross-origin-resource-sharing/) +- [교차 출처 리소스를 안전하게 공유](https://web.dev/articles/cross-origin-resource-sharing) - [웹 개발자를 위한 사이트 격리](https://developers.google.com/web/updates/2018/07/site-isolation) diff --git a/site/ko/docs/lighthouse/best-practices/image-aspect-ratio/index.md b/site/ko/docs/lighthouse/best-practices/image-aspect-ratio/index.md index ca5e37bc1..a529b74d2 100644 --- a/site/ko/docs/lighthouse/best-practices/image-aspect-ratio/index.md +++ b/site/ko/docs/lighthouse/best-practices/image-aspect-ratio/index.md @@ -27,7 +27,7 @@ updated: 2020-04-29 ### 이미지 CDN 사용 -이미지 CDN을 사용하면 다양한 크기의 이미지를 생성하는 프로세스를 더 쉽게 자동화할 수 있습니다. 개요를 보려면 [이미지 CDN을 사용하여 이미지 최적화하기](https://web.dev/image-cdns/)를, 직접 실습을 원한다면 [Thumbor 이미지 CDN을 설치하는 방법](https://web.dev/install-thumbor/)을 확인하십시오. +이미지 CDN을 사용하면 다양한 크기의 이미지를 생성하는 프로세스를 더 쉽게 자동화할 수 있습니다. 개요를 보려면 [이미지 CDN을 사용하여 이미지 최적화하기](https://web.dev/articles/image-cdns)를, 직접 실습을 원한다면 [Thumbor 이미지 CDN을 설치하는 방법](https://web.dev/articles/install-thumbor)을 확인하십시오. ### 이미지의 종횡비에 영향을 미치는 CSS 확인하기 @@ -39,11 +39,11 @@ updated: 2020-04-29 그러나 반응형 이미지로 작업하는 경우 뷰포트 크기를 알 때까지 너비와 높이를 알 수 있는 방법이 없기 때문에 HTML에서 이미지 크기를 지정하는 것이 어려울 수 있습니다. 반응형 이미지의 종횡비를 유지하려면 [CSS 종횡비](https://www.npmjs.com/package/css-aspect-ratio) 라이브러리 또는 [종횡비 박스](https://css-tricks.com/aspect-ratio-boxes/)를 사용하는 것이 좋습니다. -마지막으로 [올바른 크기의 이미지 제공](https://web.dev/serve-images-with-correct-dimensions/) 게시물을 확인하여 각 사용자의 기기에 적합한 크기의 이미지를 제공하는 방법을 알아보세요. +마지막으로 [올바른 크기의 이미지 제공](https://web.dev/articles/serve-images-with-correct-dimensions) 게시물을 확인하여 각 사용자의 기기에 적합한 크기의 이미지를 제공하는 방법을 알아보세요. ## 리소스 - [**이미지가 잘못된 종횡비로 나타납니다** 검사에 대한 소스 코드](https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/audits/image-aspect-ratio.js) - [CSS 종횡비](https://www.npmjs.com/package/css-aspect-ratio) - [종횡비 상자](https://css-tricks.com/aspect-ratio-boxes/) -- [이미지를 올바른 크기로 제공하기](https://web.dev/serve-images-with-correct-dimensions/) +- [이미지를 올바른 크기로 제공하기](https://web.dev/articles/serve-images-with-correct-dimensions) diff --git a/site/ko/docs/lighthouse/performance/bootup-time/index.md b/site/ko/docs/lighthouse/performance/bootup-time/index.md index 4fc371275..145423102 100644 --- a/site/ko/docs/lighthouse/performance/bootup-time/index.md +++ b/site/ko/docs/lighthouse/performance/bootup-time/index.md @@ -20,7 +20,7 @@ JavaScript를 실행하는 데 시간이 오래 걸리면 여러 가지 방법 - **실행 비용** - JavaScript는 기본 스레드에서도 실행됩니다. 페이지에서 실제로 필요로 하기 전에 많은 코드를 실행하면 사용자가 페이지 속도를 인식하는 방식과 관련된 주요 측정 항목 중 하나인 [상호 작용까지의 시간](https://web.dev/tti/)도 지연됩니다. + JavaScript는 기본 스레드에서도 실행됩니다. 페이지에서 실제로 필요로 하기 전에 많은 코드를 실행하면 사용자가 페이지 속도를 인식하는 방식과 관련된 주요 측정 항목 중 하나인 [상호 작용까지의 시간](https://web.dev/articles/tti)도 지연됩니다. - **메모리 비용** diff --git a/site/ko/docs/lighthouse/performance/critical-request-chains/index.md b/site/ko/docs/lighthouse/performance/critical-request-chains/index.md index ac1fa4abd..146bcc009 100644 --- a/site/ko/docs/lighthouse/performance/critical-request-chains/index.md +++ b/site/ko/docs/lighthouse/performance/critical-request-chains/index.md @@ -28,7 +28,7 @@ Lighthouse는 네트워크 우선순위를 프록시로 사용하여 렌더링 - 중요한 바이트의 수를 최적화하여 다운로드 시간(왕복 횟수)을 줄이십시오. - 나머지 중요 리소스가 로드되는 순서를 최적화합니다. 모든 중요 자산을 최대한 빨리 다운로드하여 중요 경로 길이를 단축합니다. -[이미지](https://web.dev/use-imagemin-to-compress-images/), [자바스크립트](https://web.dev/apply-instant-loading-with-prpl/), [CSS](https://web.dev/defer-non-critical-css/), [웹 글꼴](https://web.dev/avoid-invisible-text/) 최적화에 대해 자세히 알아보십시오. +[이미지](https://web.dev/articles/use-imagemin-to-compress-images), [자바스크립트](https://web.dev/articles/apply-instant-loading-with-prpl), [CSS](https://web.dev/articles/defer-non-critical-css), [웹 글꼴](https://web.dev/articles/avoid-invisible-text) 최적화에 대해 자세히 알아보십시오. ## 스택별 지침 diff --git a/site/ko/docs/lighthouse/performance/dom-size/index.md b/site/ko/docs/lighthouse/performance/dom-size/index.md index 6c2a8bf79..ebbbdbea9 100644 --- a/site/ko/docs/lighthouse/performance/dom-size/index.md +++ b/site/ko/docs/lighthouse/performance/dom-size/index.md @@ -51,11 +51,11 @@ Lighthouse는 다음과 같은 DOM 트리가 있는 페이지에 플래그를 ### Angular -큰 목록을 렌더링하는 경우 CDK(구성 요소 개발 키트)와 함께 [가상 스크롤](https://web.dev/virtualize-lists-with-angular-cdk/)을 사용합니다. +큰 목록을 렌더링하는 경우 CDK(구성 요소 개발 키트)와 함께 [가상 스크롤](https://web.dev/articles/virtualize-lists-with-angular-cdk)을 사용합니다. ### React -- 페이지에서 반복되는 많은 요소를 렌더링하는 경우 생성되는 DOM 노드 수를 최소화하려면 [`react-window`](https://web.dev/virtualize-long-lists-react-window/)와 같은 "windowing" 라이브러리를 사용하십시오. +- 페이지에서 반복되는 많은 요소를 렌더링하는 경우 생성되는 DOM 노드 수를 최소화하려면 [`react-window`](https://web.dev/articles/virtualize-long-lists-react-window)와 같은 "windowing" 라이브러리를 사용하십시오. - [`shouldComponentUpdate`](https://reactjs.org/docs/optimizing-performance.html#shouldcomponentupdate-in-action) , [`PureComponent`](https://reactjs.org/docs/react-api.html#reactpurecomponent) 또는 [`React.memo`](https://reactjs.org/docs/react-api.html#reactmemo)를 사용하여 불필요한 재렌더링을 최소화하십시오. - 런타임 성능을 개선하기 위해 `Effect` 후크를 사용하는 경우 특정 종속성이 변경될 때까지만 [효과를 건너뜁니다](https://reactjs.org/docs/hooks-effect.html#tip-optimizing-performance-by-skipping-effects). diff --git a/site/ko/docs/lighthouse/performance/first-meaningful-paint/index.md b/site/ko/docs/lighthouse/performance/first-meaningful-paint/index.md index 6ae15e45d..60f82f9fb 100644 --- a/site/ko/docs/lighthouse/performance/first-meaningful-paint/index.md +++ b/site/ko/docs/lighthouse/performance/first-meaningful-paint/index.md @@ -10,7 +10,7 @@ date: 2019-05-02 updated: 2019-11-05 --- -{% Aside 'caution' %} 첫 번째 의미 있는 페인트(FMP)는 Lighthouse 6.0에서 더 이상 사용되지 않습니다. 실제로 FMP는 페이지 로드의 작은 차이에 지나치게 민감하여 일관성 없는(바이모달) 결과를 초래합니다. 또한 메트릭의 정의는 브라우저별 구현 세부 정보에 의존하므로 모든 웹 브라우저에서 표준화하거나 구현할 수 없습니다. 앞으로는 [가장 큰 콘텐츠가 포함된 페인트](https://web.dev/lcp/)를 대신 사용하는 것이 좋습니다. {% endAside %} +{% Aside 'caution' %} 첫 번째 의미 있는 페인트(FMP)는 Lighthouse 6.0에서 더 이상 사용되지 않습니다. 실제로 FMP는 페이지 로드의 작은 차이에 지나치게 민감하여 일관성 없는(바이모달) 결과를 초래합니다. 또한 메트릭의 정의는 브라우저별 구현 세부 정보에 의존하므로 모든 웹 브라우저에서 표준화하거나 구현할 수 없습니다. 앞으로는 [가장 큰 콘텐츠가 포함된 페인트](https://web.dev/articles/lcp)를 대신 사용하는 것이 좋습니다. {% endAside %} 첫 번째 의미 있는 페인트(FMP)는 Lighthouse 보고서의 **성능** 섹션에서 추적되는 6가지 메트릭 중 하나입니다. 각 메트릭은 페이지 로드 속도의 일부 측면을 캡처합니다. @@ -22,7 +22,7 @@ Lighthouse는 몇 초 만에 FMP를 표시합니다. FMP는 페이지의 주요 콘텐츠가 사용자에게 표시되는 시점을 측정합니다. FMP의 원시 점수는 페이지 로드를 시작한 사용자와 스크롤 없이 볼 수 있는 기본 콘텐츠를 렌더링하는 페이지 사이의 시간(초)입니다. FMP는 기본적으로 가장 큰 스크롤 없이 볼 수 있는 레이아웃 변경이 발생한 후 페인트의 타이밍을 보여줍니다. Google의 [Time to First meaningful Paint: 레이아웃 기반 접근 방식](https://docs.google.com/document/d/1BR94tJdZLsin5poeet0XoTW60M0SjvOJQttKT-JK8HI/view)에서 FMP의 기술적 세부사항에 대해 자세히 알아보세요. -[FCP(First Contentful Paint)](https://web.dev/fcp/)와 FMP는 페이지에 렌더링된 콘텐츠의 첫 번째 비트에 스크롤 없이 볼 수 있는 부분의 콘텐츠가 포함되어 있는 경우가 많습니다. 그러나 이러한 측정항목은 예를 들어 iframe 내 스크롤 없이 볼 수 있는 부분에 콘텐츠가 있는 경우 다를 수 있습니다. FMP는 iframe 내의 콘텐츠가 사용자에게 표시될 때 등록되지만 FCP는 iframe 콘텐츠를 포함 *하지 않습니다.* +[FCP(First Contentful Paint)](https://web.dev/articles/fcp)와 FMP는 페이지에 렌더링된 콘텐츠의 첫 번째 비트에 스크롤 없이 볼 수 있는 부분의 콘텐츠가 포함되어 있는 경우가 많습니다. 그러나 이러한 측정항목은 예를 들어 iframe 내 스크롤 없이 볼 수 있는 부분에 콘텐츠가 있는 경우 다를 수 있습니다. FMP는 iframe 내의 콘텐츠가 사용자에게 표시될 때 등록되지만 FCP는 iframe 콘텐츠를 포함 *하지 않습니다.* ## Lighthouse가 FMP 점수를 결정하는 방법 @@ -67,11 +67,11 @@ FMP와 FCP가 같을 때 점수는 같다. FCP 이후에 FMP가 발생하는 경 ## FMP 점수를 높이는 방법 -[사이트에서 가장 큰 콘텐츠가 포함된 페인트를 개선하는 방법](https://web.dev/lcp/#how-to-improve-lcp)을 참조하십시오. FMP를 개선하기 위한 전략은 Largest Contentful Paint를 개선하기 위한 전략과 대체로 동일합니다. +[사이트에서 가장 큰 콘텐츠가 포함된 페인트를 개선하는 방법](https://web.dev/articles/lcp#how_to_improve_lcp)을 참조하십시오. FMP를 개선하기 위한 전략은 Largest Contentful Paint를 개선하기 위한 전략과 대체로 동일합니다. ## 실제 사용자의 장치에서 FMP 추적 -FMP가 실제로 사용자의 기기에서 발생하는 시점을 측정하는 방법을 알아보려면 Google의 [사용자 중심 성능 메트릭](https://web.dev/user-centric-performance-metrics/) 페이지를 참조하세요. [영웅 요소를 사용하여 FMP 추적](https://developers.google.com/web/fundamentals/performance/user-centric-performance-metrics#tracking_fmp_using_hero_elements) 섹션에서는 프로그래밍 방식으로 FCP 데이터에 액세스하고 이를 Google 애널리틱스에 제출하는 방법을 설명합니다. +FMP가 실제로 사용자의 기기에서 발생하는 시점을 측정하는 방법을 알아보려면 Google의 [사용자 중심 성능 메트릭](https://web.dev/articles/user-centric-performance-metrics) 페이지를 참조하세요. [영웅 요소를 사용하여 FMP 추적](https://developers.google.com/web/fundamentals/performance/user-centric-performance-metrics#tracking_fmp_using_hero_elements) 섹션에서는 프로그래밍 방식으로 FCP 데이터에 액세스하고 이를 Google 애널리틱스에 제출하는 방법을 설명합니다. 실제 사용자 측정항목 수집에 대한 자세한 내용은 [탐색 및 리소스 타이밍을 사용하여 실생활에서 로드 성능 평가](https://developers.google.com/web/fundamentals/performance/navigation-and-resource-timing/)를 참조하세요. [사용자 시간 표시 및 측정 Lighthouse 감사](/docs/lighthouse/performance/user-timings/)를 사용하면 보고서에서 사용자 시간 데이터를 볼 수 있습니다. @@ -82,4 +82,4 @@ FMP가 실제로 사용자의 기기에서 발생하는 시점을 측정하는 - [**첫 번째 의미 있는 페인트** 감사를 위한 소스 코드](https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/audits/metrics/first-meaningful-paint.js) - [Lighthouse v3 스코어링 가이드](https://developers.google.com/web/tools/lighthouse/v3/scoring) - [첫 번째 의미 있는 페인트까지의 시간: 레이아웃 기반 접근 방식](https://docs.google.com/document/d/1BR94tJdZLsin5poeet0XoTW60M0SjvOJQttKT-JK8HI/view) -- [가장 큰 콘텐츠가 포함된 페인트](https://web.dev/lcp/) +- [가장 큰 콘텐츠가 포함된 페인트](https://web.dev/articles/lcp) diff --git a/site/ko/docs/lighthouse/performance/font-display/index.md b/site/ko/docs/lighthouse/performance/font-display/index.md index 18c3f0568..35c96acff 100644 --- a/site/ko/docs/lighthouse/performance/font-display/index.md +++ b/site/ko/docs/lighthouse/performance/font-display/index.md @@ -6,7 +6,7 @@ date: 2019-05-02 updated: 2020-04-29 --- -글꼴은 로드하는 데 시간이 많이 걸리는 대용량 파일인 경우가 많습니다. 일부 브라우저는 글꼴이 로드될 때까지 텍스트를 숨기면서 [보이지 않는 텍스트의 플래시(FOIT)](https://web.dev/avoid-invisible-text/)를 일으킵니다. +글꼴은 로드하는 데 시간이 많이 걸리는 대용량 파일인 경우가 많습니다. 일부 브라우저는 글꼴이 로드될 때까지 텍스트를 숨기면서 [보이지 않는 텍스트의 플래시(FOIT)](https://web.dev/articles/avoid-invisible-text)를 일으킵니다. ## Lighthouse 글꼴 표시 감사가 실패하는 방식 @@ -30,14 +30,14 @@ updated: 2020-04-29 } ``` -[글꼴 표시 API](https://developer.mozilla.org/docs/Web/CSS/@font-face/font-display)는 글꼴이 표시되는 방식을 지정합니다. `swap`은 글꼴을 사용하는 텍스트가 시스템 글꼴을 사용하여 즉시 표시되어야 함을 브라우저에 알립니다. 사용자 정의 글꼴이 준비되면 시스템 글꼴을 대체합니다. (자세한 내용은 [로드 중 보이지 않는 텍스트의 표시 방지](https://web.dev/avoid-invisible-text/) 게시물을 참조하세요.) +[글꼴 표시 API](https://developer.mozilla.org/docs/Web/CSS/@font-face/font-display)는 글꼴이 표시되는 방식을 지정합니다. `swap`은 글꼴을 사용하는 텍스트가 시스템 글꼴을 사용하여 즉시 표시되어야 함을 브라우저에 알립니다. 사용자 정의 글꼴이 준비되면 시스템 글꼴을 대체합니다. (자세한 내용은 [로드 중 보이지 않는 텍스트의 표시 방지](https://web.dev/articles/avoid-invisible-text) 게시물을 참조하세요.) ### 웹 글꼴 미리 로드 글꼴 파일을 더 일찍 가져오려면 `<link rel="preload" as="font">`를 사용하세요. 자세한 정보: -- [로딩 속도 향상을 위해 웹 글꼴 미리 로드(codelab)](https://web.dev/codelab-preload-web-fonts/) -- [선택적 글꼴을 미리 로드하여 레이아웃 이동 및 보이지 않는 텍스트의 플래시(FOIT) 방지](https://web.dev/preload-optional-fonts/) +- [로딩 속도 향상을 위해 웹 글꼴 미리 로드(codelab)](https://web.dev/articles/codelab-preload-web-fonts) +- [선택적 글꼴을 미리 로드하여 레이아웃 이동 및 보이지 않는 텍스트의 플래시(FOIT) 방지](https://web.dev/articles/preload-optional-fonts) ### Google 글꼴 @@ -66,7 +66,7 @@ Google 글꼴 URL 끝에 `&display=swap` [매개변수](https://developer.mozill ## 리소스 - [**웹폰트 로드 중에 텍스트가 계속 표시되도록 하기** 감사에 대한 소스 코드](https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/audits/font-display.js) -- [로딩 중 보이지 않는 텍스트 피하기](https://web.dev/avoid-invisible-text/) +- [로딩 중 보이지 않는 텍스트 피하기](https://web.dev/articles/avoid-invisible-text) - [글꼴 표시로 글꼴 성능 제어](https://developers.google.com/web/updates/2016/02/font-display) -- [로딩 속도 향상을 위해 웹 글꼴 미리 로드(codelab)](https://web.dev/codelab-preload-web-fonts/) -- [선택적 글꼴을 미리 로드하여 레이아웃 이동 및 보이지 않는 텍스트의 플래시(FOIT) 방지](https://web.dev/preload-optional-fonts/) +- [로딩 속도 향상을 위해 웹 글꼴 미리 로드(codelab)](https://web.dev/articles/codelab-preload-web-fonts) +- [선택적 글꼴을 미리 로드하여 레이아웃 이동 및 보이지 않는 텍스트의 플래시(FOIT) 방지](https://web.dev/articles/preload-optional-fonts) diff --git a/site/ko/docs/lighthouse/performance/interactive/index.md b/site/ko/docs/lighthouse/performance/interactive/index.md index 9763d2383..0371314ae 100644 --- a/site/ko/docs/lighthouse/performance/interactive/index.md +++ b/site/ko/docs/lighthouse/performance/interactive/index.md @@ -18,7 +18,7 @@ Lighthouse는 TTI를 초 단위로 표시합니다. TTI는 페이지가 *완전히* 상호 작용 가능하게 되는 데 걸리는 시간을 측정합니다. 다음과 같은 경우에 페이지가 완전한 상호 작용 가능한 것으로 간주됩니다. -- 페이지에 [첫 번째 콘텐츠풀 페인트](https://web.dev/fcp/)에 의해 측정되는 유용한 콘텐츠가 표시됩니다. +- 페이지에 [첫 번째 콘텐츠풀 페인트](https://web.dev/articles/fcp)에 의해 측정되는 유용한 콘텐츠가 표시됩니다. - 가장 많이 보이는 페이지 요소에 이벤트 핸들러가 등록됩니다. - 페이지가 50밀리초 이내에 사용자 상호 작용에 응답합니다. @@ -59,7 +59,7 @@ TTI 점수는 [HTTP 아카이브의 데이터](https://httparchive.org/reports/l ## TTI 점수를 높이는 방법 -TTI에 특히 큰 영향을 미칠 수 있는 한 가지 개선 사항은 불필요한 JavaScript 작업을 연기하거나 제거하는 것입니다. [JavaScript를 최적화](https://web.dev/fast/#optimize-your-javascript)할 수 있는 기회를 찾아보세요. 특히, [코드 분할로 JavaScript 페이로드를 줄이](https://web.dev/apply-instant-loading-with-prpl)고 [PRPL 패턴을 적용](https://web.dev/reduce-javascript-payloads-with-code-splitting)하는 방법을 고려하세요. [타사 JavaScript를 최적화](https://web.dev/fast/#optimize-your-third-party-resources)해도 일부 사이트에서 상당한 개선이 이루어집니다. +TTI에 특히 큰 영향을 미칠 수 있는 한 가지 개선 사항은 불필요한 JavaScript 작업을 연기하거나 제거하는 것입니다. [JavaScript를 최적화](https://web.dev/articles/fast#optimize_your_javascript)할 수 있는 기회를 찾아보세요. 특히, [코드 분할로 JavaScript 페이로드를 줄이](https://web.dev/apply-instant-loading-with-prpl)고 [PRPL 패턴을 적용](https://web.dev/reduce-javascript-payloads-with-code-splitting)하는 방법을 고려하세요. [타사 JavaScript를 최적화](https://web.dev/articles/fast#optimize_your_third_party_resources)해도 일부 사이트에서 상당한 개선이 이루어집니다. 다음 두 가지 진단 감사는 JavaScript 작업을 줄일 수 있는 추가 기회를 제공합니다. @@ -68,7 +68,7 @@ TTI에 특히 큰 영향을 미칠 수 있는 한 가지 개선 사항은 불필 ## 실제 사용자의 장치에서 TTI 추적 -TTI가 실제로 사용자의 기기에서 발생하는 시점을 측정하는 방법을 알아보려면 Google의 [사용자 중심 성능 메트릭](https://web.dev/user-centric-performance-metrics/) 페이지를 참조하세요. [TTI 추적](https://developers.google.com/web/fundamentals/performance/user-centric-performance-metrics#tracking_tti) 섹션에서는 프로그래밍 방식으로 TTI 데이터에 액세스하고 이를 Google Analytics에 제출하는 방법을 설명합니다. +TTI가 실제로 사용자의 기기에서 발생하는 시점을 측정하는 방법을 알아보려면 Google의 [사용자 중심 성능 메트릭](https://web.dev/articles/user-centric-performance-metrics) 페이지를 참조하세요. [TTI 추적](https://developers.google.com/web/fundamentals/performance/user-centric-performance-metrics#tracking_tti) 섹션에서는 프로그래밍 방식으로 TTI 데이터에 액세스하고 이를 Google Analytics에 제출하는 방법을 설명합니다. {% Aside %} TTI는 실제 상황에서 추적하기 어려울 수 있습니다. [첫 번째 입력 지연](https://developers.google.com/web/updates/2018/05/first-input-delay)을 추적하면 TTI를 간접적으로 가늠해볼 수 있습니다. {% endAside %} @@ -81,4 +81,4 @@ TTI가 실제로 사용자의 기기에서 발생하는 시점을 측정하는 - [첫 상호 작용 및 지속적 상호 작용](https://docs.google.com/document/d/1GGiI9-7KeY3TPqS3YT271upUVimo-XiL5mwWorDUD4c/edit) - [JavaScript 시작 최적화](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/javascript-startup-optimization/) - [트리 쉐이킹으로 JavaScript 페이로드 줄이기](https://developers.google.com/web/fundamentals/performance/optimizing-javascript/tree-shaking/) -- [타사 리소스 최적화](https://web.dev/fast/#optimize-your-third-party-resources) +- [타사 리소스 최적화](https://web.dev/articles/fast#optimize_your_third_party_resources) diff --git a/site/ko/docs/lighthouse/performance/lighthouse-total-blocking-time/index.md b/site/ko/docs/lighthouse/performance/lighthouse-total-blocking-time/index.md index a75923e3e..ced76217a 100644 --- a/site/ko/docs/lighthouse/performance/lighthouse-total-blocking-time/index.md +++ b/site/ko/docs/lighthouse/performance/lighthouse-total-blocking-time/index.md @@ -16,7 +16,7 @@ Lighthouse 보고서는 TBT를 밀리초 단위로 표시합니다. ## TBT 측정 항목 -TBT는 마우스 클릭, 화면 탭 또는 키보드 누름과 같은 사용자 입력으로부터 페이지가 응답하지 못하도록 차단된 총 시간을 측정합니다. 합계는 [최초 콘텐츠풀 페인트](https://web.dev/fcp/)와 [상호 작용까지의 시간](https://web.dev/tti/) 사이의 모든 [긴 작업](https://web.dev/long-tasks-devtools/)의 *차단 부분*을 더하여 계산합니다. 50ms 이상 실행되는 모든 작업은 긴 작업입니다. 50ms 이후의 시간이 차단 부분입니다. 예를 들어 Lighthouse가 70ms 길이의 작업을 감지하면 차단 부분은 20ms가 됩니다. +TBT는 마우스 클릭, 화면 탭 또는 키보드 누름과 같은 사용자 입력으로부터 페이지가 응답하지 못하도록 차단된 총 시간을 측정합니다. 합계는 [최초 콘텐츠풀 페인트](https://web.dev/articles/fcp)와 [상호 작용까지의 시간](https://web.dev/articles/tti) 사이의 모든 [긴 작업](https://web.dev/articles/long-tasks-devtools)의 *차단 부분*을 더하여 계산합니다. 50ms 이상 실행되는 모든 작업은 긴 작업입니다. 50ms 이후의 시간이 차단 부분입니다. 예를 들어 Lighthouse가 70ms 길이의 작업을 감지하면 차단 부분은 20ms가 됩니다. ## Lighthouse가 TBT 점수를 산정하는 방법 @@ -53,11 +53,11 @@ TBT 점수는 모바일 장치에 로드되었을 때의 페이지 TBT 시간과 ## TBT 점수를 높이는 방법 -Chrome DevTools의 성능 패널로 긴 작업의 근본 원인을 진단하는 방법을 알아보려면 [긴 작업의 원인은 무엇입니까?](https://web.dev/long-tasks-devtools/#what-is-causing-my-long-tasks) 를 참조하십시오. +Chrome DevTools의 성능 패널로 긴 작업의 근본 원인을 진단하는 방법을 알아보려면 [긴 작업의 원인은 무엇입니까?](https://web.dev/articles/long-tasks-devtools#what_is_causing_my_long_tasks) 를 참조하십시오. 일반적으로 긴 작업의 가장 일반적인 원인은 다음과 같습니다. -- 불필요한 JavaScript 로딩, 구문 분석 또는 실행. 성능 패널에서 코드를 분석하는 동안 기본 스레드가 페이지를 로드하는 데 실제로 필요하지 않은 작업을 수행하고 있음을 발견할 수 있습니다. [코드 분할로 JavaScript 페이로드 줄이기](https://web.dev/remove-unused-code/), [사용하지 않는 코드 제거](https://web.dev/efficiently-load-third-party-javascript/) 또는 [타사 JavaScript를 효율적으로 로드](https://web.dev/reduce-javascript-payloads-with-code-splitting/)하면 TBT 점수가 향상됩니다. +- 불필요한 JavaScript 로딩, 구문 분석 또는 실행. 성능 패널에서 코드를 분석하는 동안 기본 스레드가 페이지를 로드하는 데 실제로 필요하지 않은 작업을 수행하고 있음을 발견할 수 있습니다. [코드 분할로 JavaScript 페이로드 줄이기](https://web.dev/articles/remove-unused-code), [사용하지 않는 코드 제거](https://web.dev/articles/efficiently-load-third-party-javascript) 또는 [타사 JavaScript를 효율적으로 로드](https://web.dev/articles/reduce-javascript-payloads-with-code-splitting)하면 TBT 점수가 향상됩니다. - 비효율적인 JavaScript 문. 예를 들어 성능 패널에서 코드를 분석한 후 2000개의 노드를 반환하는 `document.querySelectorAll('a')`에 대한 호출이 표시된다고 가정합니다. 10개의 노드만 반환하는 등 더 구체적인 선택기를 사용하도록 코드를 리팩토링하면 TBT 점수가 향상됩니다. {% Aside %} 불필요한 JavaScript 로드, 구문 분석 또는 실행은 일반적으로 대부분의 사이트에서 개선할 수 있는 훨씬 더 큰 기회입니다. {% endAside %} @@ -67,10 +67,10 @@ Chrome DevTools의 성능 패널로 긴 작업의 근본 원인을 진단하는 ## 참고 자료 - [**총 차단 시간** 감사에 대한 소스 코드](https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/audits/metrics/total-blocking-time.js) -- [긴 JavaScript 작업으로 인해 상호 작용까지의 시간이 지연됩니까?](https://web.dev/long-tasks-devtools/) +- [긴 JavaScript 작업으로 인해 상호 작용까지의 시간이 지연됩니까?](https://web.dev/articles/long-tasks-devtools) - [첫 번째 입력 지연 최적화](https://web.dev/optimize-fid) -- [최초 콘텐츠풀 페인트](https://web.dev/fcp/) -- [상호 작용까지의 시간](https://web.dev/tti/) -- [코드 분할로 JavaScript 페이로드 줄이기](https://web.dev/reduce-javascript-payloads-with-code-splitting/) -- [사용하지 않는 코드 제거](https://web.dev/remove-unused-code/) -- [타사 리소스를 효율적으로 로드](https://web.dev/efficiently-load-third-party-javascript/) +- [최초 콘텐츠풀 페인트](https://web.dev/articles/fcp) +- [상호 작용까지의 시간](https://web.dev/articles/tti) +- [코드 분할로 JavaScript 페이로드 줄이기](https://web.dev/articles/reduce-javascript-payloads-with-code-splitting) +- [사용하지 않는 코드 제거](https://web.dev/articles/remove-unused-code) +- [타사 리소스를 효율적으로 로드](https://web.dev/articles/efficiently-load-third-party-javascript) diff --git a/site/ko/docs/lighthouse/performance/non-composited-animations/index.md b/site/ko/docs/lighthouse/performance/non-composited-animations/index.md index 93136450e..50bb1d3c8 100644 --- a/site/ko/docs/lighthouse/performance/non-composited-animations/index.md +++ b/site/ko/docs/lighthouse/performance/non-composited-animations/index.md @@ -5,7 +5,7 @@ description: '"합성되지 않은 애니메이션 방지" Lighthouse 감사를 date: 2020-08-12 --- -합성되지 않은 애니메이션은 저가형 휴대폰 또는 성능이 많이 요구되는 작업이 메인 스레드에서 실행될 때 버벅거림(즉, 매끄럽지 않음)으로 나타날 수 있습니다. 버벅거리는 애니메이션은 페이지의 [누적 레이아웃 이동](https://web.dev/cls/)(CLS)을 증가시킬 수 있습니다. CLS를 줄이면 Lighthouse Performance 점수가 향상됩니다. +합성되지 않은 애니메이션은 저가형 휴대폰 또는 성능이 많이 요구되는 작업이 메인 스레드에서 실행될 때 버벅거림(즉, 매끄럽지 않음)으로 나타날 수 있습니다. 버벅거리는 애니메이션은 페이지의 [누적 레이아웃 이동](https://web.dev/articles/cls)(CLS)을 증가시킬 수 있습니다. CLS를 줄이면 Lighthouse Performance 점수가 향상됩니다. ## 배경 @@ -27,12 +27,12 @@ HTML, CSS 및 JavaScript를 픽셀로 변환하기 위한 브라우저의 알고 ## 애니메이션이 합성되었는지 확인하는 방법 -[합성 전용 속성 유지 및 레이어 수 관리](https://developers.google.com/web/fundamentals/performance/rendering/stick-to-compositor-only-properties-and-manage-layer-count) 및 [고성능 애니메이션](https://web.dev/animations-guide/)을 참조하세요. +[합성 전용 속성 유지 및 레이어 수 관리](https://developers.google.com/web/fundamentals/performance/rendering/stick-to-compositor-only-properties-and-manage-layer-count) 및 [고성능 애니메이션](https://web.dev/articles/animations-guide)을 참조하세요. ## 리소스 - [*합성되지 않은 애니메이션 방지* 감사를 위한 소스 코드](https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/audits/non-composited-animations.js) - [합성 전용 속성 유지 및 레이어 수 관리](https://developers.google.com/web/fundamentals/performance/rendering/stick-to-compositor-only-properties-and-manage-layer-count) -- [고성능 애니메이션](https://web.dev/animations-guide/) +- [고성능 애니메이션](https://web.dev/articles/animations-guide) - [페인트 복잡성을 단순화하고 페인트 영역 줄이기](https://developers.google.com/web/fundamentals/performance/rendering/simplify-paint-complexity-and-reduce-paint-areas) - [최신 웹 브라우저 내부 살펴보기(3부)](https://developers.google.com/web/updates/2018/09/inside-browser-part3) diff --git a/site/ko/docs/lighthouse/performance/offscreen-images/index.md b/site/ko/docs/lighthouse/performance/offscreen-images/index.md index fc8f1c818..c1ebeac2f 100644 --- a/site/ko/docs/lighthouse/performance/offscreen-images/index.md +++ b/site/ko/docs/lighthouse/performance/offscreen-images/index.md @@ -6,7 +6,7 @@ date: 2019-05-02 updated: 2020-05-29 --- -Lighthouse 보고서의 기회 섹션에는 페이지의 모든 오프스크린 이미지 또는 숨겨진 이미지와 함께 [KiB 단위](https://en.wikipedia.org/wiki/Kibibyte)의 잠재적 절감 효과가 나열됩니다. [상호 작용까지 시간](https://web.dev/tti/)을 낮추기 위해 모든 중요한 리소스가 로드를 완료한 후에 이러한 이미지를 지연 로드하는 것이 좋습니다. +Lighthouse 보고서의 기회 섹션에는 페이지의 모든 오프스크린 이미지 또는 숨겨진 이미지와 함께 [KiB 단위](https://en.wikipedia.org/wiki/Kibibyte)의 잠재적 절감 효과가 나열됩니다. [상호 작용까지 시간](https://web.dev/articles/tti)을 낮추기 위해 모든 중요한 리소스가 로드를 완료한 후에 이러한 이미지를 지연 로드하는 것이 좋습니다. <figure>{% Img src="image/tcFciHGuF3MxnTr1y5ue01OGLBn2/agMyJtIarLruD8iuz0Mt.png", alt="Lighthouse 오프스크린 이미지 지연 감사를 보여주는 스크린샷", width="800", height="416" %}</figure> @@ -28,7 +28,7 @@ Lighthouse 보고서의 기회 섹션에는 페이지의 모든 오프스크린 ### Magento -웹 플랫폼의 [지연 로드](https://web.dev/browser-level-image-lazy-loading/) 기능을 사용하도록 제품 및 카탈로그 템플릿을 수정하는 것이 좋습니다. +웹 플랫폼의 [지연 로드](https://web.dev/articles/browser-level-image-lazy-loading) 기능을 사용하도록 제품 및 카탈로그 템플릿을 수정하는 것이 좋습니다. ### WordPress diff --git a/site/ko/docs/lighthouse/performance/performance-scoring/index.md b/site/ko/docs/lighthouse/performance/performance-scoring/index.md index ea7b7b636..05ca606cc 100644 --- a/site/ko/docs/lighthouse/performance/performance-scoring/index.md +++ b/site/ko/docs/lighthouse/performance/performance-scoring/index.md @@ -23,7 +23,7 @@ updated: 2021-02-26 [가변성에 대한 Lighthouse 문서](https://github.com/GoogleChrome/lighthouse/blob/master/docs/variability.md)에서 이에 대해 더 자세히 설명합니다. -또한 Lighthouse가 전체 성능 점수를 종합적으로 제공할 수 있지만 사이트 성능을 단일 숫자가 아닌 점수 분포로 생각하는 것이 더 유용할 수 있습니다. 그 이유를 이해하려면 [사용자 중심적 성능 메트릭](https://web.dev/user-centric-performance-metrics/)의 소개 내용을 참조하세요. +또한 Lighthouse가 전체 성능 점수를 종합적으로 제공할 수 있지만 사이트 성능을 단일 숫자가 아닌 점수 분포로 생각하는 것이 더 유용할 수 있습니다. 그 이유를 이해하려면 [사용자 중심적 성능 메트릭](https://web.dev/articles/user-centric-performance-metrics)의 소개 내용을 참조하세요. ## 성능 점수에 가중치가 부여되는 방식 {: #weightings } diff --git a/site/ko/docs/lighthouse/performance/server-response-time/index.md b/site/ko/docs/lighthouse/performance/server-response-time/index.md index 5508344fe..2af4f84f0 100644 --- a/site/ko/docs/lighthouse/performance/server-response-time/index.md +++ b/site/ko/docs/lighthouse/performance/server-response-time/index.md @@ -53,4 +53,4 @@ Magento의 [Varnish 통합](https://devdocs.magento.com/guides/v2.3/config-guide ## 리소스 - [**서버 응답 시간(TTFB) 단축** 감사를 위한 소스 코드](https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/audits/server-response-time.js) -- [네트워크 정보 API를 사용한 적응형 서비스](https://web.dev/adaptive-serving-based-on-network-quality/) +- [네트워크 정보 API를 사용한 적응형 서비스](https://web.dev/articles/adaptive-serving-based-on-network-quality) diff --git a/site/ko/docs/lighthouse/performance/third-party-facades/index.md b/site/ko/docs/lighthouse/performance/third-party-facades/index.md index d28de22d9..f59d967f4 100644 --- a/site/ko/docs/lighthouse/performance/third-party-facades/index.md +++ b/site/ko/docs/lighthouse/performance/third-party-facades/index.md @@ -7,7 +7,7 @@ description: |2 date: 2020-12-01 --- -[타사 리소스](https://web.dev/third-party-javascript/)는 종종 광고 또는 동영상을 표시하고 소셜 미디어와 통합하는 데 사용됩니다. 기본 접근 방식은 페이지가 로드되는 즉시 타사 리소스를 로드하는 것이지만 이렇게 하면 페이지 로드가 불필요하게 느려질 수 있습니다. 타사 콘텐츠가 중요하지 않은 경우 [지연 로드](https://web.dev/fast/#lazy-load-images-and-video)를 통해 이 성능 하락을 줄일 수 있습니다. +[타사 리소스](https://web.dev/articles/third-party-javascript)는 종종 광고 또는 동영상을 표시하고 소셜 미디어와 통합하는 데 사용됩니다. 기본 접근 방식은 페이지가 로드되는 즉시 타사 리소스를 로드하는 것이지만 이렇게 하면 페이지 로드가 불필요하게 느려질 수 있습니다. 타사 콘텐츠가 중요하지 않은 경우 [지연 로드](https://web.dev/articles/fast#lazy_load_images_and_video)를 통해 이 성능 하락을 줄일 수 있습니다. 이 감사는 상호 작용 시 느리게 로드될 수 있는 타사 임베드를 강조합니다. 이 경우 사용자가 상호 작용할 때까지 타사 콘텐츠 대신 *파사드*가 사용됩니다. diff --git a/site/ko/docs/lighthouse/performance/total-byte-weight/index.md b/site/ko/docs/lighthouse/performance/total-byte-weight/index.md index f8b3cd87c..b1d5da99b 100644 --- a/site/ko/docs/lighthouse/performance/total-byte-weight/index.md +++ b/site/ko/docs/lighthouse/performance/total-byte-weight/index.md @@ -22,22 +22,22 @@ updated: 2020-05-29 ## 페이로드 크기를 줄이는 방법 -전체 바이트 크기를 1,600KiB 미만으로 유지하는 것을 목표로 하십시오. 이 목표는 10초 이하의 [Interactive 시간](https://web.dev/tti/)을 달성하면서 이론적으로 3G 연결에서 다운로드할 수 있는 데이터의 양을 기반으로 합니다. +전체 바이트 크기를 1,600KiB 미만으로 유지하는 것을 목표로 하십시오. 이 목표는 10초 이하의 [Interactive 시간](https://web.dev/articles/tti)을 달성하면서 이론적으로 3G 연결에서 다운로드할 수 있는 데이터의 양을 기반으로 합니다. 다음은 페이로드 크기를 줄이는 몇 가지 방법입니다. -- 페이로드가 필요할 때까지 요청을 연기합니다. 한 가지 가능한 접근 방식은 [PRPL 패턴](https://web.dev/apply-instant-loading-with-prpl/)을 참조하십시오. +- 페이로드가 필요할 때까지 요청을 연기합니다. 한 가지 가능한 접근 방식은 [PRPL 패턴](https://web.dev/articles/apply-instant-loading-with-prpl)을 참조하십시오. - 요청을 최대한 작게 최적화합니다. 가능한 기술은 다음과 같습니다. - - [네트워크 페이로드를 최소화하고 압축합니다](https://web.dev/reduce-network-payloads-using-text-compression/). - - [이미지에 대해 JPEG 또는 PNG 대신 WebP를 사용합니다](https://web.dev/serve-images-webp/). - - [JPEG 이미지의 압축 수준을 85로 설정합니다](https://web.dev/use-imagemin-to-compress-images/). -- 페이지가 반복 방문 시 리소스를 다시 다운로드하지 않도록 요청을 캐시합니다. (캐싱의 작동 방식과 구현 방법을 알아 보려면 [네트워크 안정성 랜딩 페이지)](https://web.dev/reliable/)를 참조하십시오. + - [네트워크 페이로드를 최소화하고 압축합니다](https://web.dev/articles/reduce-network-payloads-using-text-compression). + - [이미지에 대해 JPEG 또는 PNG 대신 WebP를 사용합니다](https://web.dev/articles/serve-images-webp). + - [JPEG 이미지의 압축 수준을 85로 설정합니다](https://web.dev/articles/use-imagemin-to-compress-images). +- 페이지가 반복 방문 시 리소스를 다시 다운로드하지 않도록 요청을 캐시합니다. (캐싱의 작동 방식과 구현 방법을 알아 보려면 [네트워크 안정성 랜딩 페이지)](https://web.dev/explore/reliable)를 참조하십시오. ## 스택별 지침 ### Angular -JavaScript 번들 크기를 최소화하려면 [경로 수준 코드 분할](https://web.dev/route-level-code-splitting-in-angular/)을 적용하십시오. 또한 [Angular 서비스 작업자](https://web.dev/precaching-with-the-angular-service-worker/)로 자산을 미리 캐싱하는 것을 고려하십시오. +JavaScript 번들 크기를 최소화하려면 [경로 수준 코드 분할](https://web.dev/articles/route-level-code-splitting-in-angular)을 적용하십시오. 또한 [Angular 서비스 작업자](https://web.dev/articles/precaching-with-the-angular-service-worker)로 자산을 미리 캐싱하는 것을 고려하십시오. ### Drupal diff --git a/site/ko/docs/lighthouse/performance/uses-long-cache-ttl/index.md b/site/ko/docs/lighthouse/performance/uses-long-cache-ttl/index.md index ca26571fb..15df1224e 100644 --- a/site/ko/docs/lighthouse/performance/uses-long-cache-ttl/index.md +++ b/site/ko/docs/lighthouse/performance/uses-long-cache-ttl/index.md @@ -63,7 +63,7 @@ Cache-Control: max-age=31536000 캐시 기간이 길다고 항상 좋은 것은 아닙니다. 궁극적으로 리소스에 대한 최적의 캐시 기간을 결정하는 것은 사용자의 몫입니다. -브라우저가 다양한 리소스를 캐시하는 방식을 사용자 정의하기 위한 많은 지시문이 있습니다. [HTTP 캐시: 첫 방어선 가이드라인](https://web.dev/http-cache/) 및 [HTTP 캐싱 동작 구성 codelab](https://web.dev/codelab-http-cache)에서 리소스 캐싱에 대해 자세히 알아보세요. +브라우저가 다양한 리소스를 캐시하는 방식을 사용자 정의하기 위한 많은 지시문이 있습니다. [HTTP 캐시: 첫 방어선 가이드라인](https://web.dev/articles/http-cache) 및 [HTTP 캐싱 동작 구성 codelab](https://web.dev/codelab-http-cache)에서 리소스 캐싱에 대해 자세히 알아보세요. ## Chrome DevTools에서 캐시된 응답을 확인하는 방법 diff --git a/site/ko/docs/lighthouse/performance/uses-optimized-images/index.md b/site/ko/docs/lighthouse/performance/uses-optimized-images/index.md index dcf7d1efd..6057aa216 100644 --- a/site/ko/docs/lighthouse/performance/uses-optimized-images/index.md +++ b/site/ko/docs/lighthouse/performance/uses-optimized-images/index.md @@ -20,13 +20,13 @@ Lighthouse는 페이지의 모든 JPEG 또는 BMP 이미지를 수집하고 각 다음을 포함하여 이미지를 최적화하기 위해 취할 수 있는 여러 단계가 있습니다. -- [이미지 CDN 사용](https://web.dev/image-cdns/) -- [이미지 압축](https://web.dev/use-imagemin-to-compress-images/) -- [애니메이션 GIF를 비디오로 대체](https://web.dev/replace-gifs-with-videos/) -- [이미지 로딩 지연](https://web.dev/use-lazysizes-to-lazyload-images/) -- [반응형 이미지 제공](https://web.dev/serve-responsive-images/) -- [올바른 크기의 이미지 제공](https://web.dev/serve-images-with-correct-dimensions/) -- [WebP 이미지 사용](https://web.dev/serve-images-webp/) +- [이미지 CDN 사용](https://web.dev/articles/image-cdns) +- [이미지 압축](https://web.dev/articles/use-imagemin-to-compress-images) +- [애니메이션 GIF를 비디오로 대체](https://web.dev/articles/replace-gifs-with-videos) +- [이미지 로딩 지연](https://web.dev/articles/use-lazysizes-to-lazyload-images) +- [반응형 이미지 제공](https://web.dev/articles/serve-responsive-images) +- [올바른 크기의 이미지 제공](https://web.dev/articles/serve-images-with-correct-dimensions) +- [WebP 이미지 사용](https://web.dev/articles/serve-images-webp) ## GUI 도구를 사용하여 이미지 최적화 diff --git a/site/ko/docs/lighthouse/performance/uses-rel-preconnect/index.md b/site/ko/docs/lighthouse/performance/uses-rel-preconnect/index.md index a38f51672..e9f615911 100644 --- a/site/ko/docs/lighthouse/performance/uses-rel-preconnect/index.md +++ b/site/ko/docs/lighthouse/performance/uses-rel-preconnect/index.md @@ -59,5 +59,5 @@ Lighthouse 보고서의 기회 섹션에는 `<link rel=preconnect>`로 아직 - [**필수 원본에 대한 사전 연결** 감사를 위한 소스 코드](https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/audits/uses-rel-preconnect.js) - [리소스 우선 순위 지정 - 브라우저에서 도움 받기](https://developers.google.com/web/fundamentals/performance/resource-prioritization#preconnect) -- [조기에 네트워크 연결을 설정하여 인지된 페이지 속도 개선](https://web.dev/preconnect-and-dns-prefetch/) +- [조기에 네트워크 연결을 설정하여 인지된 페이지 속도 개선](https://web.dev/articles/preconnect-and-dns-prefetch) - [링크 유형: 사전 연결](https://developer.mozilla.org/docs/Web/HTML/Link_types/preconnect#Browser_compatibility) diff --git a/site/ko/docs/lighthouse/performance/uses-rel-preload/index.md b/site/ko/docs/lighthouse/performance/uses-rel-preload/index.md index 911ae79fb..c9fa92b88 100644 --- a/site/ko/docs/lighthouse/performance/uses-rel-preload/index.md +++ b/site/ko/docs/lighthouse/performance/uses-rel-preload/index.md @@ -48,7 +48,7 @@ HTML에 사전 로드 링크를 선언하여 브라우저가 가능한 한 빨 <figure> {% Img src="image/tcFciHGuF3MxnTr1y5ue01OGLBn2/tJLJXH2qXcrDBUfsSAK5.png", alt="사전 로드 링크를 사용하면 style.css 및 ui.js가 app.js와 동시에 요청됩니다.", width="800", height="478" %} <figcaption> 사전 로드 링크를 사용하면 <code>styles.css</code> 및 <code>ui.js</code>가 <code>app.js</code>와 동시에 요청됩니다. </figcaption></figure> -추가 지침은 [중요 자산을 사전 로드하여 로딩 속도 개선하기](https://web.dev/preload-critical-assets/)를 참조하세요. +추가 지침은 [중요 자산을 사전 로드하여 로딩 속도 개선하기](https://web.dev/articles/preload-critical-assets)를 참조하세요. ### 브라우저 호환성 @@ -62,7 +62,7 @@ HTML에 사전 로드 링크를 선언하여 브라우저가 가능한 한 빨 ### Angular -탐색 속도를 높이려면 미리 [경로를 사전 로드](https://web.dev/route-preloading-in-angular/)하세요. +탐색 속도를 높이려면 미리 [경로를 사전 로드](https://web.dev/articles/route-preloading-in-angular)하세요. ### Magento diff --git a/site/ko/docs/lighthouse/performance/uses-responsive-images/index.md b/site/ko/docs/lighthouse/performance/uses-responsive-images/index.md index 01d1c1699..536baeb12 100644 --- a/site/ko/docs/lighthouse/performance/uses-responsive-images/index.md +++ b/site/ko/docs/lighthouse/performance/uses-responsive-images/index.md @@ -20,9 +20,9 @@ Lighthouse 보고서의 '기회' 섹션에는 페이지에서 크기가 적절 이상적으로, 사용자 화면에 렌더링된 버전보다 큰 이미지가 페이지에 제공되어서는 안 됩니다. 그보다 크면 바이트가 낭비되고 페이지 로드 시간이 느려집니다. -적절한 크기의 이미지를 제공하기 위한 주요 전략을 "반응형 이미지"라고 합니다. 반응형 이미지를 사용하면 각 이미지의 여러 버전을 생성한 다음 미디어 쿼리, 뷰포트 크기 등을 사용하여 HTML 또는 CSS에서 사용할 버전을 지정합니다. 자세한 내용은 [반응형 이미지 제공](https://web.dev/serve-responsive-images/)을 참조하세요. +적절한 크기의 이미지를 제공하기 위한 주요 전략을 "반응형 이미지"라고 합니다. 반응형 이미지를 사용하면 각 이미지의 여러 버전을 생성한 다음 미디어 쿼리, 뷰포트 크기 등을 사용하여 HTML 또는 CSS에서 사용할 버전을 지정합니다. 자세한 내용은 [반응형 이미지 제공](https://web.dev/articles/serve-responsive-images)을 참조하세요. -[이미지 CDN](https://web.dev/image-cdns/)은 적절한 크기의 이미지를 제공하기 위한 또 다른 주요 전략입니다. 이미지 변환을 위한 웹 서비스 API와 같은 이미지 CDN을 생각해볼 수 있습니다. +[이미지 CDN](https://web.dev/articles/image-cdns)은 적절한 크기의 이미지를 제공하기 위한 또 다른 주요 전략입니다. 이미지 변환을 위한 웹 서비스 API와 같은 이미지 CDN을 생각해볼 수 있습니다. 또 다른 전략은 SVG와 같은 벡터 기반 이미지 형식을 사용하는 것입니다. SVG 이미지는 한정된 양의 코드를 사용해 어떤 크기로든 확장할 수 있습니다. 자세한 내용은 [복잡한 아이콘을 SVG로 바꾸기](https://developers.google.com/web/fundamentals/design-and-ux/responsive/images#replace_complex_icons_with_svg)를 참조하세요. @@ -32,7 +32,7 @@ Lighthouse 보고서의 '기회' 섹션에는 페이지에서 크기가 적절 ### AMP -[`amp-img`](https://amp.dev/documentation/components/amp-img/?format=websites) 구성 요소의 [`srcset`](https://web.dev/use-srcset-to-automatically-choose-the-right-image/) 지원을 사용하여 화면 크기에 따라 사용할 이미지 자산을 지정합니다. [srcset, 크기 및 높이가 있는 반응형 이미지](https://amp.dev/documentation/guides-and-tutorials/develop/style_and_layout/art_direction/)를 참조하세요. +[`amp-img`](https://amp.dev/documentation/components/amp-img/?format=websites) 구성 요소의 [`srcset`](https://web.dev/articles/use-srcset-to-automatically-choose-the-right-image) 지원을 사용하여 화면 크기에 따라 사용할 이미지 자산을 지정합니다. [srcset, 크기 및 높이가 있는 반응형 이미지](https://amp.dev/documentation/guides-and-tutorials/develop/style_and_layout/art_direction/)를 참조하세요. ### Angular @@ -57,4 +57,4 @@ CDK(Component Dev Kit)의 [`BreakpointObserver` 유틸리티](https://material.a ## 리소스 - [**적절한 크기의 이미지** 감사 소스 코드](https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/audits/byte-efficiency/uses-responsive-images.js) -- [올바른 크기의 이미지 제공](https://web.dev/serve-images-with-correct-dimensions/) +- [올바른 크기의 이미지 제공](https://web.dev/articles/serve-images-with-correct-dimensions) diff --git a/site/ko/docs/lighthouse/performance/uses-text-compression/index.md b/site/ko/docs/lighthouse/performance/uses-text-compression/index.md index 0a1c786b3..265b5292b 100644 --- a/site/ko/docs/lighthouse/performance/uses-text-compression/index.md +++ b/site/ko/docs/lighthouse/performance/uses-text-compression/index.md @@ -66,7 +66,7 @@ Content-Encoding: br 3. 큰 요청 행을 활성화합니다. [큰 요청 행 사용](https://developers.google.com/web/tools/chrome-devtools/network/reference#request-rows)을 참조하십시오. 4. 관심 있는 응답의 **크기** 열을 확인하십시오. 최상위 값은 압축된 크기입니다. 하단 값은 압축 해제된 크기입니다. -[네트워크 페이로드 축소 및 압축](https://web.dev/reduce-network-payloads-using-text-compression/)도 참조하십시오. +[네트워크 페이로드 축소 및 압축](https://web.dev/articles/reduce-network-payloads-using-text-compression)도 참조하십시오. ## 스택별 지침 diff --git a/site/ko/docs/lighthouse/pwa/apple-touch-icon/index.md b/site/ko/docs/lighthouse/pwa/apple-touch-icon/index.md index ab7bc6883..f310acb6c 100644 --- a/site/ko/docs/lighthouse/pwa/apple-touch-icon/index.md +++ b/site/ko/docs/lighthouse/pwa/apple-touch-icon/index.md @@ -8,7 +8,7 @@ updated: 2023-03-24 is_outdated: true --- -iOS Safari 사용자가 홈 화면에 [PWA(Progressive Web App)](https://web.dev/progressive-web-apps/)를 추가하는 경우에 나타나는 아이콘을 *Apple 터치 아이콘*이라고 합니다. 페이지의 `<head>`에 `<link rel="apple-touch-icon" href="/example.png">` 태그를 포함시켜 앱에서 사용해야 하는 아이콘을 지정할 수 있습니다. 페이지에 이 링크 태그가 없으면 iOS가 페이지 콘텐츠의 스크린샷을 찍어 아이콘을 생성합니다. 즉, iOS에 아이콘을 다운로드하도록 지시하면 보다 세련된 사용자 경험을 얻을 수 있습니다. +iOS Safari 사용자가 홈 화면에 [PWA(Progressive Web App)](https://web.dev/explore/progressive-web-apps)를 추가하는 경우에 나타나는 아이콘을 *Apple 터치 아이콘*이라고 합니다. 페이지의 `<head>`에 `<link rel="apple-touch-icon" href="/example.png">` 태그를 포함시켜 앱에서 사용해야 하는 아이콘을 지정할 수 있습니다. 페이지에 이 링크 태그가 없으면 iOS가 페이지 콘텐츠의 스크린샷을 찍어 아이콘을 생성합니다. 즉, iOS에 아이콘을 다운로드하도록 지시하면 보다 세련된 사용자 경험을 얻을 수 있습니다. ## Lighthouse Apple 터치 아이콘 감사에 실패하는 이유 @@ -39,7 +39,7 @@ Lighthouse는 아이콘이 실제로 존재하는지, 또는 아이콘이 올바 2. `/example.png`를 아이콘의 실제 경로로 바꿉니다. -{% Aside 'codelab' %} [Progressive Web App에 Apple 터치 아이콘 추가](https://web.dev/codelab-apple-touch-icon/) 코드랩을 확인하여 Apple 터치 아이콘을 추가하면 사용자 경험이 개선되는 이유를 알아보세요. {% endAside %} +{% Aside 'codelab' %} [Progressive Web App에 Apple 터치 아이콘 추가](https://web.dev/articles/codelab-apple-touch-icon) 코드랩을 확인하여 Apple 터치 아이콘을 추가하면 사용자 경험이 개선되는 이유를 알아보세요. {% endAside %} 개선된 사용자 경험을 제공하려면 다음을 확인하세요. @@ -50,5 +50,5 @@ Lighthouse는 아이콘이 실제로 존재하는지, 또는 아이콘이 올바 ## 리소스 - [**유효한 `apple-touch-icon`을 제공하지 않음** 감사의 소스 코드](https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/audits/apple-touch-icon.js) -- [설치 가능하게 하려면 필요한 사항 알아보기](https://web.dev/install-criteria/) +- [설치 가능하게 하려면 필요한 사항 알아보기](https://web.dev/articles/install-criteria) - <a href="https://webhint.io/docs/user-guide/hints/hint-apple-touch-icons/" rel="noreferrer">Apple 터치 아이콘 사용</a> diff --git a/site/ko/docs/lighthouse/pwa/installable-manifest/index.md b/site/ko/docs/lighthouse/pwa/installable-manifest/index.md index 00e6c55c9..58a98d310 100644 --- a/site/ko/docs/lighthouse/pwa/installable-manifest/index.md +++ b/site/ko/docs/lighthouse/pwa/installable-manifest/index.md @@ -10,13 +10,13 @@ date: 2019-05-04 updated: 2019-09-19 --- -설치 가능성은 [PWA(프로그레시브 웹 앱)](https://web.dev/progressive-web-apps/)의 핵심 요구 사항입니다. 사용자에게 PWA를 설치하라는 메시지를 표시하면 PWA를 홈 화면에 추가할 수 있습니다. 홈 화면에 앱을 추가하는 사용자는 해당 앱을 더 자주 사용합니다. +설치 가능성은 [PWA(프로그레시브 웹 앱)](https://web.dev/explore/progressive-web-apps)의 핵심 요구 사항입니다. 사용자에게 PWA를 설치하라는 메시지를 표시하면 PWA를 홈 화면에 추가할 수 있습니다. 홈 화면에 앱을 추가하는 사용자는 해당 앱을 더 자주 사용합니다. -[웹 앱 매니페스트](https://web.dev/add-manifest/)에는 앱을 설치 가능하게 만드는 데 필요한 주요 정보가 포함되어 있습니다. +[웹 앱 매니페스트](https://web.dev/articles/add-manifest)에는 앱을 설치 가능하게 만드는 데 필요한 주요 정보가 포함되어 있습니다. ## Lighthouse 웹 앱 매니페스트 감사가 실패하는 방법 -[Lighthouse](https://developers.google.com/web/tools/lighthouse/)는 설치 가능성에 대한 최소 요구 사항을 충족하는 [웹 앱 매니페스트](https://web.dev/add-manifest/)가 없는 페이지에 플래그를 지정합니다. +[Lighthouse](https://developers.google.com/web/tools/lighthouse/)는 설치 가능성에 대한 최소 요구 사항을 충족하는 [웹 앱 매니페스트](https://web.dev/articles/add-manifest)가 없는 페이지에 플래그를 지정합니다. <figure>{% Img src="image/tcFciHGuF3MxnTr1y5ue01OGLBn2/039DlaixA4drrswBzSra.png", alt="사용자가 홈 화면에서 웹 앱을 설치할 수 없음을 보여주는 Lighthouse 감사", width="800", height="98" %}</figure> @@ -28,13 +28,13 @@ updated: 2019-09-19 - `fullscreen` , `standalone` 또는 `minimal-ui`로 설정된 [`display`](https://developer.mozilla.org/docs/Web/Manifest/display) - `true` 이외의 값으로 설정되는 [`prefer_related_applications`](https://developers.google.com/web/fundamentals/app-install-banners/native) 속성. -{% Aside 'caution' %} 앱을 설치하려면 웹 앱 매니페스트가 *필요*하지만 *충분*하지 않습니다. 설치 가능성에 대한 모든 요구 사항을 충족하는 방법을 알아보려면 [설치 가능 게시물에 필요한 사항 알아보기](https://web.dev/progressive-web-apps/)를 참조하십시오. {% endAside %} +{% Aside 'caution' %} 앱을 설치하려면 웹 앱 매니페스트가 *필요*하지만 *충분*하지 않습니다. 설치 가능성에 대한 모든 요구 사항을 충족하는 방법을 알아보려면 [설치 가능 게시물에 필요한 사항 알아보기](https://web.dev/explore/progressive-web-apps)를 참조하십시오. {% endAside %} {% Partial 'lighthouse-pwa/scoring.njk' %} ## PWA를 설치 가능하게 만드는 방법 -앱에 위의 기준을 충족하는 매니페스트가 있는지 확인하세요. PWA 생성에 대한 자세한 내용은 [설치 가능](https://web.dev/progressive-web-apps/) 컬렉션을 참조하세요. +앱에 위의 기준을 충족하는 매니페스트가 있는지 확인하세요. PWA 생성에 대한 자세한 내용은 [설치 가능](https://web.dev/explore/progressive-web-apps) 컬렉션을 참조하세요. ## PWA가 설치 가능한지 확인하는 방법 @@ -42,7 +42,7 @@ updated: 2019-09-19 앱이 설치 가능성에 대한 최소 요구 사항을 충족하면 Chrome은 사용자에게 PWA를 설치하라는 메시지를 표시하는 데 사용할 수 있는 `beforeinstallprompt` 이벤트를 실행합니다. -{% Aside 'codelab' %} [설치 가능하게 만들기](https://web.dev/codelab-make-installable/) 코드랩을 사용하여 Chrome에서 앱을 설치할 수 있도록 하는 방법에 대해 배우십시오. {% endAside %} +{% Aside 'codelab' %} [설치 가능하게 만들기](https://web.dev/articles/codelab-make-installable) 코드랩을 사용하여 Chrome에서 앱을 설치할 수 있도록 하는 방법에 대해 배우십시오. {% endAside %} ### 다른 브라우저에서 @@ -57,7 +57,7 @@ updated: 2019-09-19 ## 참고 자료 - [**웹 앱 매니페스트의 소스 코드가 설치 가능성 요구 사항** 감사를 충족하지 않음](https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/audits/installable-manifest.js) -- [웹 앱 매니페스트 추가](https://web.dev/add-manifest/) -- [설치에 필요한 사항 알아보기](https://web.dev/progressive-web-apps/) +- [웹 앱 매니페스트 추가](https://web.dev/articles/add-manifest) +- [설치에 필요한 사항 알아보기](https://web.dev/explore/progressive-web-apps) - [웹 앱 매니페스트](https://developer.mozilla.org/docs/Web/Manifest) - [HTTPS를 사용하지 않음](/docs/lighthouse/pwa/is-on-https/) diff --git a/site/ko/docs/lighthouse/pwa/load-fast-enough-for-pwa/index.md b/site/ko/docs/lighthouse/pwa/load-fast-enough-for-pwa/index.md index 44e1b21e5..3b78c760c 100644 --- a/site/ko/docs/lighthouse/pwa/load-fast-enough-for-pwa/index.md +++ b/site/ko/docs/lighthouse/pwa/load-fast-enough-for-pwa/index.md @@ -22,7 +22,7 @@ updated: 2020-06-10 두 가지 주요 메트릭은 사용자가 로드 시간을 인식하는 방식에 영향을 줍니다. - [첫 번째 의미 있는 페인트(FMP)](/docs/lighthouse/pwa/first-meaningful-paint) , 페이지의 기본 콘텐츠가 시각적으로 완전히 나타나는 시점을 측정합니다. -- [상호 작용까지의 시간(TTI)](https://web.dev/tti/), 페이지가 완전히 상호 작용하는 때를 측정 +- [상호 작용까지의 시간(TTI)](https://web.dev/articles/tti), 페이지가 완전히 상호 작용하는 때를 측정 예를 들어 페이지가 1초 후에 시각적으로 완료된 것처럼 보이지만 사용자가 10초 동안 페이지와 상호 작용할 수 없는 경우 사용자는 페이지 로드 시간을 10초로 인식할 것입니다. diff --git a/site/ko/docs/lighthouse/pwa/maskable-icon-audit/index.md b/site/ko/docs/lighthouse/pwa/maskable-icon-audit/index.md index 660ec0618..db45bcf9a 100644 --- a/site/ko/docs/lighthouse/pwa/maskable-icon-audit/index.md +++ b/site/ko/docs/lighthouse/pwa/maskable-icon-audit/index.md @@ -7,7 +7,7 @@ description: |2- date: 2020-05-06 --- -[마스크 가능 아이콘](https://web.dev/maskable-icon/)은 모든 Android 기기에서 PWA 아이콘이 멋지게 보이도록 하는 새로운 아이콘 형식입니다. 최신 Android 기기에서 마스크 가능한 아이콘 형식을 따르지 않는 PWA 아이콘에는 흰색 배경이 제공됩니다. 마스크 가능한 아이콘을 사용하면 아이콘이 Android에서 제공하는 모든 공간을 차지하게 됩니다. +[마스크 가능 아이콘](https://web.dev/articles/maskable-icon)은 모든 Android 기기에서 PWA 아이콘이 멋지게 보이도록 하는 새로운 아이콘 형식입니다. 최신 Android 기기에서 마스크 가능한 아이콘 형식을 따르지 않는 PWA 아이콘에는 흰색 배경이 제공됩니다. 마스크 가능한 아이콘을 사용하면 아이콘이 Android에서 제공하는 모든 공간을 차지하게 됩니다. ## Lighthouse 마스크 가능 아이콘 감사가 실패하는 방법 @@ -29,7 +29,7 @@ date: 2020-05-06 1. [Maskable.app Editor](https://maskable.app/editor)를 사용하여 기존 아이콘을 마스크 가능 아이콘으로 변환합니다. -2. [웹 앱 매니페스트](https://web.dev/add-manifest/)의 `icons` 개체 중 하나에 `purpose` 속성을 추가합니다. `purpose`의 값을 `maskable` 또는 `any maskable`로 설정하십시오. [값](https://developer.mozilla.org/docs/Web/Manifest/icons#Values)을 참조하십시오. +2. [웹 앱 매니페스트](https://web.dev/articles/add-manifest)의 `icons` 개체 중 하나에 `purpose` 속성을 추가합니다. `purpose`의 값을 `maskable` 또는 `any maskable`로 설정하십시오. [값](https://developer.mozilla.org/docs/Web/Manifest/icons#Values)을 참조하십시오. ```json/8 { @@ -47,12 +47,12 @@ date: 2020-05-06 } ``` -3. Chrome DevTools를 사용하여 마스크 가능 아이콘이 올바르게 표시되는지 확인합니다. [현재 아이콘이 준비되었습니까?](https://web.dev/maskable-icon/#are-my-current-icons-ready)를 참조하십시오. +3. Chrome DevTools를 사용하여 마스크 가능 아이콘이 올바르게 표시되는지 확인합니다. [현재 아이콘이 준비되었습니까?](https://web.dev/articles/maskable-icon#are_my_current_icons_ready)를 참조하십시오. ## 자원 - [**매니페스트의 소스 코드에 마스크 가능 아이콘** 감사 없음](https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/audits/maskable-icon.js) -- [마스크 가능 아이콘이 있는 PWA의 적응형 아이콘 지원](https://web.dev/maskable-icon/) +- [마스크 가능 아이콘이 있는 PWA의 적응형 아이콘 지원](https://web.dev/articles/maskable-icon) - [Maskable.app 편집기](https://maskable.app/editor) -- [웹 앱 매니페스트 추가](https://web.dev/add-manifest/) +- [웹 앱 매니페스트 추가](https://web.dev/articles/add-manifest) - [MDN의 `icons` 속성](https://developer.mozilla.org/docs/Web/Manifest/icons) diff --git a/site/ko/docs/lighthouse/pwa/service-worker/index.md b/site/ko/docs/lighthouse/pwa/service-worker/index.md index 9450f3dff..f077be8ac 100644 --- a/site/ko/docs/lighthouse/pwa/service-worker/index.md +++ b/site/ko/docs/lighthouse/pwa/service-worker/index.md @@ -6,13 +6,13 @@ date: 2019-05-04 updated: 2020-06-10 --- -[서비스 워커를](https://web.dev/service-workers-cache-storage/) 등록하는 것은 주요 [PWA(Progressive Web App)](https://web.dev/progressive-web-apps/) 기능을 활성화하기 위한 첫 번째 단계입니다. +[서비스 워커를](https://web.dev/articles/service-workers-cache-storage) 등록하는 것은 주요 [PWA(Progressive Web App)](https://web.dev/explore/progressive-web-apps) 기능을 활성화하기 위한 첫 번째 단계입니다. - 오프라인에서 작동 - 푸시 알림 지원 - 장치에 설치 가능 -[서비스 워커 및 Cache Storage API](https://web.dev/service-workers-cache-storage/) 게시물에서 자세히 알아보세요. +[서비스 워커 및 Cache Storage API](https://web.dev/articles/service-workers-cache-storage) 게시물에서 자세히 알아보세요. ## 브라우저 호환성 @@ -34,15 +34,15 @@ Lighthouse는 [Chrome 원격 디버깅 프로토콜](https://github.com/ChromeDe 서비스 워커를 등록하는 데는 몇 줄의 코드만 필요하지만 서비스 워커를 사용하는 유일한 이유는 위에 설명된 PWA 기능 중 하나를 구현할 수 있도록 하기 위해서입니다. 실제로 이러한 기능을 구현하려면 더 많은 작업이 필요합니다. -- 오프라인 사용을 위해 파일을 캐시 하는 방법을 알아보려면 [네트워크 안정성이란 무엇이며 어떻게 측정합니까?](https://web.dev/network-connections-unreliable/)게시물을 참조하세요. -- 앱을 설치 가능하게 만드는 방법을 알아보려면 [설치 가능하게 만들기](https://web.dev/codelab-make-installable/) 코드랩을 참조하세요. +- 오프라인 사용을 위해 파일을 캐시 하는 방법을 알아보려면 [네트워크 안정성이란 무엇이며 어떻게 측정합니까?](https://web.dev/articles/network-connections-unreliable)게시물을 참조하세요. +- 앱을 설치 가능하게 만드는 방법을 알아보려면 [설치 가능하게 만들기](https://web.dev/articles/codelab-make-installable) 코드랩을 참조하세요. - 푸시 알림을 활성화하는 방법을 알아보려면 Google의 [웹 앱에 푸시 알림 추가를](https://codelabs.developers.google.com/codelabs/push-notifications) 참조하세요. ## 자원 - [**페이지 및 `start_url`을 제어하는 서비스 작업자를 등록하지 않은** 감사에 대한 소스 코드](https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/audits/service-worker.js) - [서비스 워커: 소개](https://developers.google.com/web/fundamentals/primers/service-workers) -- [서비스 워커와 Cache Storage API](https://web.dev/service-workers-cache-storage/) -- [네트워크 안정성이란 무엇이며 어떻게 측정합니까?](https://web.dev/network-connections-unreliable/) -- [설치 가능하게 만들기](https://web.dev/codelab-make-installable/) +- [서비스 워커와 Cache Storage API](https://web.dev/articles/service-workers-cache-storage) +- [네트워크 안정성이란 무엇이며 어떻게 측정합니까?](https://web.dev/articles/network-connections-unreliable) +- [설치 가능하게 만들기](https://web.dev/articles/codelab-make-installable) - [웹 앱에 푸시 알림 추가](https://codelabs.developers.google.com/codelabs/push-notifications) diff --git a/site/ko/docs/lighthouse/pwa/splash-screen/index.md b/site/ko/docs/lighthouse/pwa/splash-screen/index.md index 9110ca83c..718abe338 100644 --- a/site/ko/docs/lighthouse/pwa/splash-screen/index.md +++ b/site/ko/docs/lighthouse/pwa/splash-screen/index.md @@ -6,7 +6,7 @@ date: 2019-05-04 updated: 2019-09-19 --- -커스텀 스플래시 스크린을 사용하면 [PWA(프로그레시브 웹 앱)](https://web.dev/progressive-web-apps/)가 해당 장치용으로 빌드된 앱처럼 느껴지게 됩니다. 기본적으로 사용자가 홈 화면에서 PWA를 시작하면 Android는 PWA가 준비될 때까지 흰색 화면을 표시합니다. 사용자는 최대 200ms 동안 이 빈 흰색 화면을 볼 수 있습니다. 커스텀 스플래시 스크린을 설정하여 사용자에게 커스텀 배경색과 PWA 아이콘을 표시하여 브랜드화된 매력적인 경험을 제공할 수 있습니다. +커스텀 스플래시 스크린을 사용하면 [PWA(프로그레시브 웹 앱)](https://web.dev/explore/progressive-web-apps)가 해당 장치용으로 빌드된 앱처럼 느껴지게 됩니다. 기본적으로 사용자가 홈 화면에서 PWA를 시작하면 Android는 PWA가 준비될 때까지 흰색 화면을 표시합니다. 사용자는 최대 200ms 동안 이 빈 흰색 화면을 볼 수 있습니다. 커스텀 스플래시 스크린을 설정하여 사용자에게 커스텀 배경색과 PWA 아이콘을 표시하여 브랜드화된 매력적인 경험을 제공할 수 있습니다. ## Lighthouse 스플래시 스크린 감사가 실패하는 이유 @@ -18,7 +18,7 @@ updated: 2019-09-19 ## 커스텀 스플래시 스크린을 만드는 방법 -Android용 Chrome은 [웹 앱 매니페스트](https://web.dev/add-manifest/)에서 다음 요구 사항을 충족하기만 하면 자동으로 커스텀 스플래시 스크린을 표시합니다. +Android용 Chrome은 [웹 앱 매니페스트](https://web.dev/articles/add-manifest)에서 다음 요구 사항을 충족하기만 하면 자동으로 커스텀 스플래시 스크린을 표시합니다. - `name` 속성은 PWA의 이름으로 설정됩니다. - `background_color` 속성은 유효한 CSS 색상 값으로 설정됩니다. diff --git a/site/ko/docs/lighthouse/pwa/themed-omnibox/index.md b/site/ko/docs/lighthouse/pwa/themed-omnibox/index.md index 763e55540..39619a3cf 100644 --- a/site/ko/docs/lighthouse/pwa/themed-omnibox/index.md +++ b/site/ko/docs/lighthouse/pwa/themed-omnibox/index.md @@ -8,7 +8,7 @@ date: 2019-05-04 updated: 2020-06-17 --- -[프로그레시브 웹앱(PWA)](https://web.dev/progressive-web-apps/)의 브랜드 색상과 일치하도록 브라우저의 주소 표시줄 테마를 지정하면 더욱 몰입도 높은 사용자 환경을 제공합니다. +[프로그레시브 웹앱(PWA)](https://web.dev/explore/progressive-web-apps)의 브랜드 색상과 일치하도록 브라우저의 주소 표시줄 테마를 지정하면 더욱 몰입도 높은 사용자 환경을 제공합니다. ## 브라우저 호환성 @@ -20,7 +20,7 @@ updated: 2020-06-17 <figure>{% Img src="image/tcFciHGuF3MxnTr1y5ue01OGLBn2/YadFSuw8denjl1hhnvFs.png", alt="주소 표시줄을 표시하는 Lighthouse 감사는 페이지 색상을 테마로 하지 않습니다.", width="800", height="98" %}</figure> -Lighthouse가 페이지의 HTML에서 `theme-color` 메타 태그를, [웹앱 매니페스트](https://web.dev/add-manifest/)에서 `theme_color` 속성을 찾지 못하면 감사가 실패합니다. +Lighthouse가 페이지의 HTML에서 `theme-color` 메타 태그를, [웹앱 매니페스트](https://web.dev/articles/add-manifest)에서 `theme_color` 속성을 찾지 못하면 감사가 실패합니다. Lighthouse는 값이 유효한 CSS 색상 값인지 테스트하지 않습니다. @@ -47,7 +47,7 @@ Google의 [Android용 Chrome 39의 `theme-color` 지원](https://developers.goog ### 2단계: 웹앱 매니페스트에 `theme_color` 속성 추가 -웹앱 매니페스트의 `theme_color` 속성은 사용자가 홈 화면에서 PWA를 시작할 때 주소 표시줄에 브랜드가 표시되도록 합니다. `theme-color` 메타 태그와는 달리 [매니페스트](https://web.dev/add-manifest/)에서 한 번만 정의하면 됩니다. 속성을 유효한 CSS 색상 값으로 설정합니다. +웹앱 매니페스트의 `theme_color` 속성은 사용자가 홈 화면에서 PWA를 시작할 때 주소 표시줄에 브랜드가 표시되도록 합니다. `theme-color` 메타 태그와는 달리 [매니페스트](https://web.dev/articles/add-manifest)에서 한 번만 정의하면 됩니다. 속성을 유효한 CSS 색상 값으로 설정합니다. ```html/1 { @@ -61,5 +61,5 @@ Google의 [Android용 Chrome 39의 `theme-color` 지원](https://developers.goog ## 참고자료 - [**주소 표시줄의 테마 색상을 설정하지 않음** 감사용 소스 코드](https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/audits/themed-omnibox.js) -- [웹앱 매니페스트 추가](https://web.dev/add-manifest/) +- [웹앱 매니페스트 추가](https://web.dev/articles/add-manifest) - [Android용 Chrome 39의 `theme-color` 지원](https://developers.google.com/web/updates/2014/11/Support-for-theme-color-in-Chrome-39-for-Android) diff --git a/site/ko/docs/privacy-sandbox/attribution-reporting/index.md b/site/ko/docs/privacy-sandbox/attribution-reporting/index.md index cb0346042..b14729f1a 100644 --- a/site/ko/docs/privacy-sandbox/attribution-reporting/index.md +++ b/site/ko/docs/privacy-sandbox/attribution-reporting/index.md @@ -48,7 +48,7 @@ authors: Attribution Reporting API를 사용하면 함께 연결된 두 이벤트, 즉 사용자가 광고를 보거나 클릭하는 것과 같은 게시자 웹사이트의 이벤트와 이후 광고주 사이트에서 전환을 측정할 수 있습니다. -이 API는 클릭 후 전환 기여 측정(현재 [최초 평가판](https://web.dev/conversion-measurement/#browser-support) 상태인 이 API의 첫 구현에서 사용 가능) 및 조회 후 전환 기여 측정([공개 설명자 참조](https://github.com/WICG/conversion-measurement-api/blob/main/event_attribution_reporting.md))을 지원합니다. +이 API는 클릭 후 전환 기여 측정(현재 [최초 평가판](/docs/privacy-sandbox/attribution-reporting/#browser-support) 상태인 이 API의 첫 구현에서 사용 가능) 및 조회 후 전환 기여 측정([공개 설명자 참조](https://github.com/WICG/conversion-measurement-api/blob/main/event_attribution_reporting.md))을 지원합니다. API는 다양한 사용 사례에 사용할 수 있는 두 가지 유형의 기여 보고서를 제공합니다. @@ -67,8 +67,8 @@ API는 다양한 사용 사례에 사용할 수 있는 두 가지 유형의 기 - [기여 보고(전환 측정) 소개](/docs/privacy-sandbox/attribution-reporting-introduction) - [API 기술 설명자](https://github.com/WICG/conversion-measurement-api/) -- (⚠️ 사용되지 않음) [광고 전환을 측정하는 보다 안전한 방법](https://web.dev/conversion-measurement/): 웹 개발자를 위한 이 API의 첫 버전의 개요 +- (⚠️ 사용되지 않음) [광고 전환을 측정하는 보다 안전한 방법](/docs/privacy-sandbox/attribution-reporting/): 웹 개발자를 위한 이 API의 첫 버전의 개요 - (⚠️ 사용되지 않음) [광고 전환을 측정하는 보다 안전한 방법 - 비디오](https://www.youtube.com/watch?v=jcDfOoWwZcM): 이 API 첫 버전의 데모(클릭만) -- (⚠️ 사용되지 않음) [이벤트 전환 측정 API 사용](https://web.dev/using-conversion-measurement/): 웹 개발자가 이 API의 첫 버전으로 실험하는 방법 +- (⚠️ 사용되지 않음) [이벤트 전환 측정 API 사용](/docs/privacy-sandbox/attribution-reporting/): 웹 개발자가 이 API의 첫 버전으로 실험하는 방법 - [개인정보 보호 샌드박스 자세히 알아보기](https://web.dev/digging-into-the-privacy-sandbox) - [Chrome DevTools로 API 디버그](/blog/new-in-devtools-93/#attribution-reporting) diff --git a/site/ko/docs/privacy-sandbox/first-party-sets/index.md b/site/ko/docs/privacy-sandbox/first-party-sets/index.md index e1849df79..a25afd57d 100644 --- a/site/ko/docs/privacy-sandbox/first-party-sets/index.md +++ b/site/ko/docs/privacy-sandbox/first-party-sets/index.md @@ -13,7 +13,7 @@ authors: ## 구현 현황 -- [최초 평가판](https://web.dev/origin-trials/) Chrome 89 ~ 93 +- [최초 평가판](/docs/web-platform/origin-trials/) Chrome 89 ~ 93 - [최초 평가판에 등록](/origintrials/#/view_trial/988540118207823873) - [Chrome 플랫폼 현황](https://chromestatus.com/feature/5640066519007232) - [Chromium 프로젝트](https://www.chromium.org/updates/first-party-sets) diff --git a/site/ko/docs/privacy-sandbox/floc/index.md b/site/ko/docs/privacy-sandbox/floc/index.md index 5cabe4cf5..2e708fa7a 100644 --- a/site/ko/docs/privacy-sandbox/floc/index.md +++ b/site/ko/docs/privacy-sandbox/floc/index.md @@ -37,7 +37,7 @@ FLoC는 관심 기반 광고 및 기타 콘텐츠 선택에서 개인정보 보 ## FLoC는 어떻게 작동합니까? -[FLoC란 무엇입니까?](https://web.dev/floc/#how-does-floc-work)에서 FloC 작동 방식에 대한 간단한 단계별 설명을 제공합니다. +[FLoC란 무엇입니까?](https://web.dev/articles/floc#how_does_floc_work)에서 FloC 작동 방식에 대한 간단한 단계별 설명을 제공합니다. 아래 다이어그램은 FLoC를 사용하여 관련 광고를 선택하고 전달하는 다양한 역할의 예를 보여줍니다. diff --git a/site/ko/docs/privacy-sandbox/glossary/index.md b/site/ko/docs/privacy-sandbox/glossary/index.md index 68a1f4d73..aa936c0e7 100644 --- a/site/ko/docs/privacy-sandbox/glossary/index.md +++ b/site/ko/docs/privacy-sandbox/glossary/index.md @@ -124,7 +124,7 @@ glitch.me ## 최초 평가판 {: #origin-trial } -최초 평가판은 새로운 기능이나 실험적인 기능에 대한 액세스를 제공하여, 모든 사람이 이용할 수 있게 되기 전에 사용자가 제한된 시간 동안 시험해 볼 수 있는 기능을 구축할 수 있는 기회를 줍니다. Chrome에서 기능에 대한 [최초](#origin) 평가판을 제공하면 사용자가 플래그를 토글하거나 Chrome의 대체 빌드로 전환할 필요 없이(필요할 수는 있지만) 해당 평가판에서 모든 사용자가 기능을 이용할 수 있도록 평가판에 [최초 원본](#origin)을 등록할 수 있습니다. 최초 평가판을 통해 개발자는 새로운 기능을 사용하여 데모 및 프로토타입을 구축할 수 있습니다. 평가판은 또한 Chrome 엔지니어가 새로운 기능이 사용되는 방식, 및 다른 웹 기술과 상호 작용하는 방식을 이해하는 데 도움이 됩니다. 자세히 알아보기: [Chrome의 최초 평가판 시작하기](https://web.dev/origin-trials/). +최초 평가판은 새로운 기능이나 실험적인 기능에 대한 액세스를 제공하여, 모든 사람이 이용할 수 있게 되기 전에 사용자가 제한된 시간 동안 시험해 볼 수 있는 기능을 구축할 수 있는 기회를 줍니다. Chrome에서 기능에 대한 [최초](#origin) 평가판을 제공하면 사용자가 플래그를 토글하거나 Chrome의 대체 빌드로 전환할 필요 없이(필요할 수는 있지만) 해당 평가판에서 모든 사용자가 기능을 이용할 수 있도록 평가판에 [최초 원본](#origin)을 등록할 수 있습니다. 최초 평가판을 통해 개발자는 새로운 기능을 사용하여 데모 및 프로토타입을 구축할 수 있습니다. 평가판은 또한 Chrome 엔지니어가 새로운 기능이 사용되는 방식, 및 다른 웹 기술과 상호 작용하는 방식을 이해하는 데 도움이 됩니다. 자세히 알아보기: [Chrome의 최초 평가판 시작하기](/docs/web-platform/origin-trials/). ## 패시브 표면 {: #passive-surface } diff --git a/site/ko/docs/privacy-sandbox/overview/index.md b/site/ko/docs/privacy-sandbox/overview/index.md index 22e2a927d..18cd1cb87 100644 --- a/site/ko/docs/privacy-sandbox/overview/index.md +++ b/site/ko/docs/privacy-sandbox/overview/index.md @@ -35,7 +35,7 @@ Chrome 팀에서 개발한 주요 제안은 다음과 같습니다. ### 자사 보호 -- [**SameSite 쿠키 변경**](https://web.dev/samesite-cookies-explained/): 사이트 간 쿠키를 명시적으로 표시하여 사이트를 보호합니다. +- [**SameSite 쿠키 변경**](https://web.dev/articles/samesite-cookies-explained): 사이트 간 쿠키를 명시적으로 표시하여 사이트를 보호합니다. - [**자사 세트**](/docs/privacy-sandbox/first-party-sets): 동일한 엔터티가 소유한 관련 도메인 이름이 자신을 동일한 자사에 속하는 것으로 선언할 수 있게 합니다. ### 사기 감지 @@ -45,7 +45,7 @@ Chrome 팀에서 개발한 주요 제안은 다음과 같습니다. ### 데이터 수집 제한 - [**개인정보 보호 예산**](https://www.youtube.com/watch?v=0STgfjSA6T8): 웹사이트가 사용자의 브라우저 또는 장치에 대한 정보를 얻을 수 있도록 허용하지만 사이트가 액세스할 수 있는 총 정보량에 대한 할당량을 브라우저에서 설정할 수 있도록 하여 사용자를 식별하지 못하게 합니다. -- [**사용자-에이전트 클라이언트 힌트**](https://web.dev/user-agent-client-hints/): [사용자-에이전트](https://developer.mozilla.org/docs/Web/HTTP/Headers/User-Agent)(UA) 문자열은 중요한 패시브 [핑거프린팅](https://w3c.github.io/fingerprinting-guidance/#passive) 표면이며 처리가 까다롭습니다. 클라이언트 힌트를 사용하면 개발자가 사용자-에이전트 문자열에서 데이터 구문을 분석할 필요 없이 사용자의 장치 또는 조건에 대해 필요한 정보만 능동적으로 요청할 수 있습니다. +- [**사용자-에이전트 클라이언트 힌트**](https://web.dev/articles/user-agent-client-hints): [사용자-에이전트](https://developer.mozilla.org/docs/Web/HTTP/Headers/User-Agent)(UA) 문자열은 중요한 패시브 [핑거프린팅](https://w3c.github.io/fingerprinting-guidance/#passive) 표면이며 처리가 까다롭습니다. 클라이언트 힌트를 사용하면 개발자가 사용자-에이전트 문자열에서 데이터 구문을 분석할 필요 없이 사용자의 장치 또는 조건에 대해 필요한 정보만 능동적으로 요청할 수 있습니다. - [**Gnatcatcher**](https://github.com/bslassey/ip-blindness): 사용자의 IP 주소에 액세스하여 개별 사용자를 식별할 가능성을 제한합니다. 제안에는 두 부분이 있습니다: [<strong data-md="">의도적 IP 가림</strong>](https://github.com/bslassey/ip-blindness/blob/master/willful_ip_blindness.md)은 웹사이트가 브라우저에 사용자와 IP 주소를 연결하지 않음을 알릴 수 있는 방법을 제공하고, [**근접 경로 NAT**](https://github.com/bslassey/ip-blindness/blob/master/near_path_nat.md)는 사용자 그룹이 동일한 비공개 처리 서버를 통해 트래픽을 보낼 수 있게 하여 사이트 호스트로부터 해당 IP 주소를 효과적으로 숨길 수 있는 방법입니다. Gnatcatcher는 또한 남용 방지와 같은 합법적인 목적으로 IP 주소에 액세스해야 하는 사이트가 인증 및 감사를 통해 그렇게 할 수 있도록 합니다. ### 신원 @@ -90,10 +90,10 @@ API 제안 설명자에는 특히 누락된 사용 사례와 목표 달성을 ### 웹 개발자를 위한 기사와 비디오 - [개인정보 보호 샌드박스 자세히 알아보기](https://web.dev/digging-into-the-privacy-sandbox) -- [SameSite 쿠키 설명](https://web.dev/samesite-cookies-explained/) +- [SameSite 쿠키 설명](https://web.dev/articles/samesite-cookies-explained) - [신뢰 토큰 시작하기](https://web.dev/trust-tokens) -- [광고 전환을 측정하는 보다 안전한 방법](https://web.dev/conversion-measurement/) -- [FLoC란 무엇입니까?](https://web.dev/floc/) +- [광고 전환을 측정하는 보다 안전한 방법](/docs/privacy-sandbox/attribution-reporting/) +- [FLoC란 무엇입니까?](https://web.dev/articles/floc) - [개인정보 보호 예산 소개](https://www.youtube.com/watch?v=0STgfjSA6T8) ### 제안의 원칙과 개념 diff --git a/site/ko/docs/privacy-sandbox/status/index.md b/site/ko/docs/privacy-sandbox/status/index.md index e60be0be2..e764cdb21 100644 --- a/site/ko/docs/privacy-sandbox/status/index.md +++ b/site/ko/docs/privacy-sandbox/status/index.md @@ -15,7 +15,7 @@ authors: *이전에는 전환 측정이라고 했습니다.* -- [현재 최초 평가판](https://web.dev/origin-trials/): Chrome 86에서 [이제 Chrome 93으로 확장](https://groups.google.com/u/1/a/chromium.org/g/attribution-reporting-api-dev/c/ZKf9T8sRqAM)되었습니다. +- [현재 최초 평가판](/docs/web-platform/origin-trials/): Chrome 86에서 [이제 Chrome 93으로 확장](https://groups.google.com/u/1/a/chromium.org/g/attribution-reporting-api-dev/c/ZKf9T8sRqAM)되었습니다. - [최초 평가판에 등록](/origintrials/#/view_trial/3411476717733150721) - [데모](https://goo.gle/demo-event-level-conversion-measurement-api) - [Chrome 플랫폼 현황](https://www.chromestatus.com/features/6412002824028160) @@ -31,25 +31,25 @@ authors: - [기여 보고(전환 측정)](/docs/privacy-sandbox/attribution-reporting) - [기여 보고(전환 측정) 소개](/docs/privacy-sandbox/attribution-reporting-introduction) - [API 기술 설명자](https://github.com/WICG/conversion-measurement-api/) -- (⚠️ 사용되지 않음) [광고 전환을 측정하는 보다 안전한 방법](https://web.dev/conversion-measurement/): 웹 개발자를 위한 이 API의 첫 버전의 개요 +- (⚠️ 사용되지 않음) [광고 전환을 측정하는 보다 안전한 방법](/docs/privacy-sandbox/attribution-reporting/): 웹 개발자를 위한 이 API의 첫 버전의 개요 - (⚠️ 사용되지 않음) [광고 전환을 측정하는 보다 안전한 방법 - 비디오](https://www.youtube.com/watch?v=jcDfOoWwZcM): 이 API 첫 버전의 데모(클릭만) -- (⚠️ 사용되지 않음) [이벤트 전환 측정 API 사용](https://web.dev/using-conversion-measurement/): 웹 개발자가 이 API의 첫 버전으로 실험하는 방법 +- (⚠️ 사용되지 않음) [이벤트 전환 측정 API 사용](/docs/privacy-sandbox/attribution-reporting/): 웹 개발자가 이 API의 첫 버전으로 실험하는 방법 - [개인정보 보호 샌드박스 자세히 알아보기](https://web.dev/digging-into-the-privacy-sandbox) ## 신뢰 토큰 -- [현재 최초 평가판](https://web.dev/origin-trials/): Chrome 84에서 [이제 Chrome 94로 확장](https://groups.google.com/a/chromium.org/g/blink-dev/c/-W90wVkS0Ks/m/Jfh5-ZWpAQAJ)되었습니다. +- [현재 최초 평가판](/docs/web-platform/origin-trials/): Chrome 84에서 [이제 Chrome 94로 확장](https://groups.google.com/a/chromium.org/g/blink-dev/c/-W90wVkS0Ks/m/Jfh5-ZWpAQAJ)되었습니다. - [최초 평가판에 등록](/origintrials/#/view_trial/2479231594867458049) - [데모](https://trust-token-demo.glitch.me/) - [Chrome 플랫폼 현황](https://www.chromestatus.com/feature/5078049450098688) - [Blink 상태](https://groups.google.com/a/chromium.org/g/blink-dev/search?q=trust%tokens) - [GitHub](https://github.com/WICG/trust-token-api): API 질문 및 토론에 대한 [이슈](https://github.com/WICG/trust-token-api/issues)를 참조하세요. - [Chrome DevTools 통합](https://developers.google.com/web/updates/2021/01/devtools?utm_source=devtools#trust-token) -- 자세히 알아보기: [신뢰 토큰 시작하기](https://web.dev/trust-tokens/) +- 자세히 알아보기: [신뢰 토큰 시작하기](https://web.dev/articles/trust-tokens) ## 자사 세트 -- [현재 최초 평가판](https://web.dev/origin-trials/) Chrome 89 ~ 93 +- [현재 최초 평가판](/docs/web-platform/origin-trials/) Chrome 89 ~ 93 - [최초 평가판에 등록](/origintrials/#/view_trial/988540118207823873) - [Chrome 플랫폼 현황](https://chromestatus.com/feature/5640066519007232) - [Blink 상태](https://groups.google.com/a/chromium.org/g/blink-dev/search?q=first-party%20sets) @@ -64,7 +64,7 @@ authors: - [API 제안](https://github.com/WICG/floc)이 [WICG](https://www.w3.org/community/wicg/) 및 이익 단체에서 논의 중 - [GitHub](https://github.com/WICG/floc): API 질문 및 토론에 대한 [이슈](https://github.com/WICG/floc/issues)를 참조하세요. - [Chrome 플랫폼 현황](https://www.chromestatus.com/features/5710139774468096) -- 자세히 알아보기: [FLoC란 무엇입니까?](https://web.dev/floc/) +- 자세히 알아보기: [FLoC란 무엇입니까?](https://web.dev/articles/floc) ## FLEDGE @@ -91,7 +91,7 @@ authors: ### 최초 평가판 -- [Chrome의 최초 평가판 시작하기](https://web.dev/origin-trials/) +- [Chrome의 최초 평가판 시작하기](/docs/web-platform/origin-trials/) - [타사 최초 평가판이란 무엇입니까?](https://web.dev/third-party-origin-trials) - [Chrome 최초 평가판 문제 해결](https://github.com/GoogleChrome/OriginTrials/blob/gh-pages/developer-guide.md) - [웹 개발자를 위한 최초 평가판 가이드](https://github.com/GoogleChrome/OriginTrials/blob/gh-pages/developer-guide.md) diff --git a/site/ko/docs/privacy-sandbox/trust-tokens/index.md b/site/ko/docs/privacy-sandbox/trust-tokens/index.md index 22f2526f7..83519b74a 100644 --- a/site/ko/docs/privacy-sandbox/trust-tokens/index.md +++ b/site/ko/docs/privacy-sandbox/trust-tokens/index.md @@ -11,7 +11,7 @@ authors: ## 구현 현황 -- [최초 평가판](https://web.dev/origin-trials/) Chrome 84 ~ 94 +- [최초 평가판](/docs/web-platform/origin-trials/) Chrome 84 ~ 94 - [평가판에 등록](/origintrials/#/view_trial/2479231594867458049) - [데모](https://trust-token-demo.glitch.me/) - [Chrome DevTools 통합](https://developers.google.com/web/updates/2021/01/devtools?utm_source=devtools#trust-token) @@ -62,7 +62,7 @@ Trust Tokens API를 사용하면 웹사이트에서 신뢰하는 사용자에게 12. 게시자 사이트에서 광고를 표시됩니다. 13. 광고 조회 노출이 계산됩니다. -{% Aside %} 이 예제의 JavaScript 호출에 대한 자세한 내용은 [Sample API 사용](https://web.dev/trust-tokens/#sample-api-usage)을 참조하세요. {% endAside %} +{% Aside %} 이 예제의 JavaScript 호출에 대한 자세한 내용은 [Sample API 사용](https://web.dev/articles/trust-tokens#sample_api_usage)을 참조하세요. {% endAside %} --- @@ -78,6 +78,6 @@ Trust Tokens API를 사용하면 웹사이트에서 신뢰하는 사용자에게 ## 더 많은 리소스 찾아보기 - [Trust Token API 기술 설명자](https://github.com/dvorak42/trust-token-api) -- [신뢰 토큰 시작하기](https://web.dev/trust-tokens/): 웹 개발자를 위한 개요 +- [신뢰 토큰 시작하기](https://web.dev/articles/trust-tokens): 웹 개발자를 위한 개요 - [Chrome의 최초 평가판 시작하기](https://web.dev/origin-trials) - [개인정보 보호 샌드박스 자세히 알아보기](https://web.dev/digging-into-the-privacy-sandbox) diff --git a/site/pt/articles/browser-fs-access/index.md b/site/pt/articles/browser-fs-access/index.md index b0dc6a930..c4535eddd 100644 --- a/site/pt/articles/browser-fs-access/index.md +++ b/site/pt/articles/browser-fs-access/index.md @@ -66,7 +66,7 @@ Uma grande desvantagem da *abordagem de download* é que não há como fazer um A API de acesso ao sistema de arquivos torna ambas as operações, abrir e salvar, muito mais simples. Também possibilita *o salvamento real*, ou seja, você não só pode escolher onde salvar um arquivo, mas também sobrescrever um arquivo existente. -{% Aside %} Para obter uma introdução mais completa à API de acesso ao sistema de arquivos, consulte o artigo [A API de acesso ao sistema de arquivos: simplificando o acesso a arquivos locais](https://web.dev/file-system-access/). {% endAside %} +{% Aside %} Para obter uma introdução mais completa à API de acesso ao sistema de arquivos, consulte o artigo [A API de acesso ao sistema de arquivos: simplificando o acesso a arquivos locais](https://web.dev/articles/file-system-access). {% endAside %} ### Abrindo arquivos @@ -168,7 +168,7 @@ Você pode ver o código acima em ação em uma [demonstração](https://browser ## A biblioteca browser-fs-access em liberdade -Em meu tempo livre, contribuo um pouquinho para um [PWA instalável](https://web.dev/progressive-web-apps/#make-it-installable) chamado [Excalidraw](https://excalidraw.com/), uma ferramenta de quadro branco que permite esboçar diagramas facilmente com uma sensação de desenho à mão. É totalmente responsivo e funciona bem em uma variedade de dispositivos, desde pequenos telefones celulares a computadores com telas grandes. Isso significa que ele precisa lidar com arquivos em todas as várias plataformas, independentemente de serem ou não compatíveis com a API de acesso ao sistema de arquivos. Isso o torna um ótimo candidato para a biblioteca browser-fs-access. +Em meu tempo livre, contribuo um pouquinho para um [PWA instalável](https://web.dev/explore/progressive-web-apps#make-it-installable) chamado [Excalidraw](https://excalidraw.com/), uma ferramenta de quadro branco que permite esboçar diagramas facilmente com uma sensação de desenho à mão. É totalmente responsivo e funciona bem em uma variedade de dispositivos, desde pequenos telefones celulares a computadores com telas grandes. Isso significa que ele precisa lidar com arquivos em todas as várias plataformas, independentemente de serem ou não compatíveis com a API de acesso ao sistema de arquivos. Isso o torna um ótimo candidato para a biblioteca browser-fs-access. Posso, por exemplo, iniciar um desenho no meu iPhone, salvá-lo (tecnicamente: baixe-o, pois o Safari não oferece suporte à API de acesso ao sistema de arquivos) na pasta Downloads do meu iPhone, abra o arquivo no meu desktop (após transferi-lo do meu telefone), modifique o arquivo e substitua-o com minhas alterações ou mesmo salve-o como um novo arquivo. diff --git a/site/pt/articles/file-handling/index.md b/site/pt/articles/file-handling/index.md index 4115b24cd..7b54e649e 100644 --- a/site/pt/articles/file-handling/index.md +++ b/site/pt/articles/file-handling/index.md @@ -15,7 +15,7 @@ alt: Fichários em várias cores. {% Aside %} A API de Gerenciamento de Arquivos faz parte do [projeto de recursos](/blog/fugu-status/) e está atualmente em desenvolvimento. Esta postagem será atualizada conforme o andamento da implementação. {% endAside %} -Agora que os aplicativos da web são [capazes de ler e gravar arquivos](https://web.dev/file-system-access/) , a próxima etapa lógica é permitir que os desenvolvedores declarem esses mesmos aplicativos da web como gerenciadores de arquivos para os arquivos que seus aplicativos podem criar e processar. A API de gerenciamento de arquivos permite que você faça exatamente isso. Depois de registrar um aplicativo de editor de texto como um gerenciador de arquivos e depois de instalá-lo, você pode clicar com o botão direito em um arquivo `.txt` no macOS e selecionar "Obter informações" para instruir o sistema operacional de que ele deve sempre abrir arquivos `.txt` com este aplicativo como padrão . +Agora que os aplicativos da web são [capazes de ler e gravar arquivos](https://web.dev/articles/file-system-access) , a próxima etapa lógica é permitir que os desenvolvedores declarem esses mesmos aplicativos da web como gerenciadores de arquivos para os arquivos que seus aplicativos podem criar e processar. A API de gerenciamento de arquivos permite que você faça exatamente isso. Depois de registrar um aplicativo de editor de texto como um gerenciador de arquivos e depois de instalá-lo, você pode clicar com o botão direito em um arquivo `.txt` no macOS e selecionar "Obter informações" para instruir o sistema operacional de que ele deve sempre abrir arquivos `.txt` com este aplicativo como padrão . ## Casos de uso sugeridos para a API de gerenciamento de arquivos {: # use-cases} @@ -35,8 +35,8 @@ Para testar a API de gerenciamento de arquivos localmente, sem um token de teste A API de gerenciamento de arquivos por si só não permite polyfill. A funcionalidade de abrir arquivos com um aplicativo da web, no entanto, pode ser obtida por dois outros meios: -- A [API de destino de compartilhamento da web](https://web.dev/web-share-target/) permite que os desenvolvedores especifiquem seu aplicativo como um destino de compartilhamento para que os arquivos possam ser abertos a partir da planilha de compartilhamento do sistema operacional. -- A [API de acesso ao sistema de arquivos](https://web.dev/file-system-access/) pode ser integrada à função de arrastar e soltar arquivos, para que os desenvolvedores possam processar arquivos soltos no aplicativo já aberto. +- A [API de destino de compartilhamento da web](https://web.dev/articles/web-share-target) permite que os desenvolvedores especifiquem seu aplicativo como um destino de compartilhamento para que os arquivos possam ser abertos a partir da planilha de compartilhamento do sistema operacional. +- A [API de acesso ao sistema de arquivos](https://web.dev/articles/file-system-access) pode ser integrada à função de arrastar e soltar arquivos, para que os desenvolvedores possam processar arquivos soltos no aplicativo já aberto. ### Detecção de recursos @@ -52,7 +52,7 @@ if ('launchQueue' in window && 'files' in LaunchParams.prototype) { ### A parte declarativa da API de gerenciamento de arquivos -Como uma primeira etapa, os aplicativos da web precisam descrever declarativamente em seu [manifesto do aplicativo da web](https://web.dev/add-manifest/) que tipo de arquivos eles podem gerenciar. A API de gerenciamento de arquivos estende o manifesto do aplicativo da web com uma nova propriedade chamada `"file_handlers"` que aceita uma matriz de, bem, gerenciadores de arquivo. Um gerenciador de arquivo é um objeto com duas propriedades: +Como uma primeira etapa, os aplicativos da web precisam descrever declarativamente em seu [manifesto do aplicativo da web](https://web.dev/articles/add-manifest) que tipo de arquivos eles podem gerenciar. A API de gerenciamento de arquivos estende o manifesto do aplicativo da web com uma nova propriedade chamada `"file_handlers"` que aceita uma matriz de, bem, gerenciadores de arquivo. Um gerenciador de arquivo é um objeto com duas propriedades: - Uma propriedade `"action"` que aponta para um URL dentro do escopo do aplicativo como seu valor. - Uma propriedade `"accept"` com um objeto de tipo MIME como chaves e listas de extensões de arquivo como seus valores. @@ -109,7 +109,7 @@ O exemplo abaixo, mostrando apenas o trecho relevante do manifesto do aplicativo Isso é para um aplicativo hipotético que processa arquivos `.csv` de valores separados por vírgula em `/open-csv` , arquivos de gráficos vetoriais escaláveis ( `.svg` em `/open-svg` e um formato de arquivo Grafr inventado com `.grafr` , `.graf` ou `.graph` como a extensão em `/open-graf` . -{% Aside %} Para que esta declaração tenha efeito, o aplicativo deve estar instalado. Você pode aprender mais em uma série de artigos neste mesmo site sobre como [tornar seu aplicativo instalável](https://web.dev/progressive-web-apps/#installable) . {% endAside %} +{% Aside %} Para que esta declaração tenha efeito, o aplicativo deve estar instalado. Você pode aprender mais em uma série de artigos neste mesmo site sobre como [tornar seu aplicativo instalável](https://web.dev/explore/progressive-web-apps#make-it-installable) . {% endAside %} ### A parte fundamental da API de gerenciamento de arquivos @@ -155,7 +155,7 @@ Quando atualizações e mudanças de manifesto na seção `"file_handlers"` fore ### Desafios relacionados a arquivos -Há uma grande categoria de vetores de ataque que se abrem ao permitir que sites acessem arquivos. Eles são descritos no [artigo sobre API de acesso ao sistema de arquivos](https://web.dev/file-system-access/#security-considerations) . O recurso adicional relacionado à segurança que a API de gerenciamento de arquivos proporciona para a API de acesso ao sistema de arquivos é a capacidade de conceder acesso a determinados arquivos por meio da IU integrada do sistema operacional, em vez de por meio de um seletor de arquivos exibido por um aplicativo da web. +Há uma grande categoria de vetores de ataque que se abrem ao permitir que sites acessem arquivos. Eles são descritos no [artigo sobre API de acesso ao sistema de arquivos](https://web.dev/articles/file-system-access#security_considerations) . O recurso adicional relacionado à segurança que a API de gerenciamento de arquivos proporciona para a API de acesso ao sistema de arquivos é a capacidade de conceder acesso a determinados arquivos por meio da IU integrada do sistema operacional, em vez de por meio de um seletor de arquivos exibido por um aplicativo da web. Ainda existe o risco de que os usuários possam conceder acidentalmente o acesso a um aplicativo da Web para um arquivo, ao abri-lo. No entanto, geralmente se entende que a abertura de um arquivo permite que o aplicativo com o qual foi aberto leia e / ou gerencie esse arquivo. Portanto, a escolha explícita do usuário de abrir um arquivo em um aplicativo instalado, como por meio de um menu de contexto "Abrir com …", pode ser lida como um sinal suficiente de confiança no aplicativo. diff --git a/site/pt/blog/chrome-ux-report-looker-studio-dashboard/index.md b/site/pt/blog/chrome-ux-report-looker-studio-dashboard/index.md index 01eb26c63..51cad52e9 100644 --- a/site/pt/blog/chrome-ux-report-looker-studio-dashboard/index.md +++ b/site/pt/blog/chrome-ux-report-looker-studio-dashboard/index.md @@ -70,7 +70,7 @@ Os conjuntos de dados mensais são divulgados na segunda terça-feira de cada m ### Visão geral do Core Web Vitals -A primeira página é uma visão geral do desempenho mensal do [Core Web Vitals](https://web.dev/vitals/) da origem. Essas são as métricas de experiência do usuário mais importantes nas quais o Google recomenda que você se concentre. +A primeira página é uma visão geral do desempenho mensal do [Core Web Vitals](https://web.dev/articles/vitals) da origem. Essas são as métricas de experiência do usuário mais importantes nas quais o Google recomenda que você se concentre. {% Img src="image/admin/h8iCTgvmG4DS2zScvatc.png", alt="Visão geral do Core Web Vitals do Painel CrUX", width="800", height="906" %} @@ -88,7 +88,7 @@ Após a página Core Web Vitals, você encontrará páginas independentes para t No topo de cada página está o filtro **Dispositivo**, que você pode usar para restringir os fatores de forma incluídos nos dados de experiência. Por exemplo, você pode se aprofundar especificamente em experiências de telefone. Essa configuração persiste nas páginas. -As visualizações primárias nessas páginas são as distribuições mensais de experiências categorizadas como "Bom", "Precisa melhorar" e "Insuficiente". A legenda codificada por cores abaixo do gráfico indica a gama de experiências incluídas na categoria. Por exemplo, na captura de tela acima, você pode ver a porcentagem de experiências "boas" de [pintura com maior conteúdo](https://web.dev/lcp/#what-is-a-good-lcp-score) (LCP) flutuando e piorando um pouco nos últimos meses. +As visualizações primárias nessas páginas são as distribuições mensais de experiências categorizadas como "Bom", "Precisa melhorar" e "Insuficiente". A legenda codificada por cores abaixo do gráfico indica a gama de experiências incluídas na categoria. Por exemplo, na captura de tela acima, você pode ver a porcentagem de experiências "boas" de [pintura com maior conteúdo](https://web.dev/articles/lcp#what_is_a_good_lcp_score) (LCP) flutuando e piorando um pouco nos últimos meses. As porcentagens do mês mais recente de experiências "boas" e "ruins" são mostradas acima do gráfico, junto com um indicador da diferença percentual em relação ao mês anterior. Para esta origem, as experiências "boas" de LCP caíram 3,2%, para 56,04% mês a mês. @@ -116,7 +116,7 @@ Da mesma forma, a página de distribuição da ECT mostra a divisão de experiê {% Aside 'key-term' %} Os tipos de conexão eficazes são considerados *eficazes* porque são baseados em medições de largura de banda nos dispositivos dos usuários e não implicam em nenhuma tecnologia específica usada. Por exemplo, um usuário de desktop em Wi-Fi rápido pode ser rotulado como 4G, enquanto uma conexão móvel mais lenta pode ser rotulada como 2G. {% endAside %} -As distribuições para essas dimensões são calculadas usando segmentos dos dados do histograma do [First Contentful Paint](https://web.dev/fcp/) (FCP). +As distribuições para essas dimensões são calculadas usando segmentos dos dados do histograma do [First Contentful Paint](https://web.dev/articles/fcp) (FCP). ## Perguntas frequentes diff --git a/site/pt/blog/new-in-devtools-101/index.md b/site/pt/blog/new-in-devtools-101/index.md index 21cc84452..2c48ecfd1 100644 --- a/site/pt/blog/new-in-devtools-101/index.md +++ b/site/pt/blog/new-in-devtools-101/index.md @@ -91,12 +91,12 @@ Issues relacionadas: [1296855](https://crbug.com/1296855), [https://crbug.com/13 ## Destaques diversos {: #misc } <!-- These are some noteworthy fixes in this release: --> Estas são algumas correções notáveis nesta versão: -<!-- - The [Back/forward cache](/blog/new-in-devtools-98/#bfcache) now displays the extension ID which blocked [bfcache](https://web.dev/bfcache/) when present.( [1284548](https://crbug.com/1284548)) --> +<!-- - The [Back/forward cache](/blog/new-in-devtools-98/#bfcache) now displays the extension ID which blocked [bfcache](https://web.dev/articles/bfcache) when present.( [1284548](https://crbug.com/1284548)) --> <!-- - Fixed autocompletion support for array-like objects, CSS class names, `map.get` and HTML tags. ([1297101](https://crbug.com/1297101), [1297491](https://crbug.com/1297491), [1293807](https://crbug.com/1293807), [1296983](https://crbug.com/1296983)) --> <!-- - Fixed incorrect highlights when double-clicking on words and undoing autocomplete. ([1298437](https://crbug.com/1298437), [1298667](https://crbug.com/1298667)) --> <!-- - Fixed comment keyboard shortcut in the **Sources** panel. ([1296535](https://crbug.com/1296535)) --> <!-- - Re-enable support for using **Alt** (Options) key for multi selection in the **Sources** panel. ([1304070](https://crbug.com/1304070)) --> -- O [cache de retorno/avanço](/blog/new-in-devtools-98/#bfcache) agora exibe o ID da extensão que bloqueou o [bfcache](https://web.dev/bfcache/) quando presente.([1284548](https://crbug.com/1284548)) +- O [cache de retorno/avanço](/blog/new-in-devtools-98/#bfcache) agora exibe o ID da extensão que bloqueou o [bfcache](https://web.dev/articles/bfcache) quando presente.([1284548](https://crbug.com/1284548)) - Corrigido suporte de autocompletar para objetos do tipo array, nomes de classe CSS, `map.get` e tags HTML. ([1297101](https://crbug.com/1297101), [1297491](https://crbug.com/1297491), [1293807](https://crbug.com/1293807), [1296983]( https://crbug.com/1296983)) - Corrigido destaques incorretos ao clicar duas vezes nas palavras e desfazer o preenchimento automático. ([1298437](https://crbug.com/1298437), [1298667](https://crbug.com/1298667)) - Correção do atalho de teclado para comentários no painel **Fontes**. ([1296535](https://crbug.com/1296535)) @@ -112,8 +112,8 @@ Para ativar o experimento, ative a caixa de seleção **Usar painel Lighthouse c <!-- Apart from the existing **navigation** mode, the **Lighthouse** panel now support two more modes on measuring user flows - **timespan** and **snapshot**. --> Além do modo de **navegação** existente, o painel **Lighthouse** agora oferece suporte a mais dois modos de medição de fluxos de usuários - **timespan** e **snapshot**. -<!-- For example, you can use the **timespan** reports to analyze user interactions. Open this [demo](https://coffee-cart.netlify.app/) page. Select the **Timespan** mode and click on **Start timespan**. On the page, click on a coffee and end the timespan. Read the report to find out the [Total Blocking Time](https://web.dev/tbt/) and [Cumulative Layout Shift](https://web.dev/cls/) that were caused by the interaction. --> -Por exemplo, você pode usar os relatórios de **timespan** para analisar as interações do usuário. Abra esta página [demo](https://coffee-cart.netlify.app/). Selecione o modo **Timespan** e clique em **Começar timespan**. Na página, clique em um café e encerre o intervalo de tempo. Leia o relatório para descobrir o [Total Blocking Time](https://web.dev/tbt/) e [Cumulative Layout Shift](https://web.dev/cls/) que foram causados pela interação. +<!-- For example, you can use the **timespan** reports to analyze user interactions. Open this [demo](https://coffee-cart.netlify.app/) page. Select the **Timespan** mode and click on **Start timespan**. On the page, click on a coffee and end the timespan. Read the report to find out the [Total Blocking Time](https://web.dev/articles/tbt) and [Cumulative Layout Shift](https://web.dev/articles/cls) that were caused by the interaction. --> +Por exemplo, você pode usar os relatórios de **timespan** para analisar as interações do usuário. Abra esta página [demo](https://coffee-cart.netlify.app/). Selecione o modo **Timespan** e clique em **Começar timespan**. Na página, clique em um café e encerre o intervalo de tempo. Leia o relatório para descobrir o [Total Blocking Time](https://web.dev/articles/tbt) e [Cumulative Layout Shift](https://web.dev/articles/cls) que foram causados pela interação. <!-- Each mode has its own unique use cases, benefits, and limitations. Please refer to the [Lighthouse documentation](https://github.com/GoogleChrome/lighthouse/blob/master/docs/user-flows.md) for more information. --> Cada modo tem seus próprios casos de uso, benefícios e limitações. Consulte a [documentação do Lighthouse](https://github.com/GoogleChrome/lighthouse/blob/master/docs/user-flows.md) para obter mais informações. diff --git a/site/pt/blog/new-in-devtools-102/index.md b/site/pt/blog/new-in-devtools-102/index.md index f5c67d287..66e1e97ee 100644 --- a/site/pt/blog/new-in-devtools-102/index.md +++ b/site/pt/blog/new-in-devtools-102/index.md @@ -53,8 +53,8 @@ Issue relacionada: [1270700](https://crbug.com/1270700) <!-- ## New shortcuts to emulate light and dark themes {: #emulation } --> ## Novos atalhos para emular temas claros e escuros {: #emulation } -<!-- You can now emulate the light and dark themes quicker (CSS media feature [prefers-color-scheme](https://web.dev/prefers-color-scheme/#the-prefers-color-scheme-media-query)) with the new shortcuts in the **Styles** pane. --> -Você pode agora emular temas claros e escuros mais facilmente (veja a media query CSS chamada [prefers-color-scheme](https://web.dev/prefers-color-scheme/#the-prefers-color-scheme-media-query)) com os novos atalhos no painel **Estilos**. +<!-- You can now emulate the light and dark themes quicker (CSS media feature [prefers-color-scheme](https://web.dev/articles/prefers-color-scheme#the_prefers_color_scheme_media_query)) with the new shortcuts in the **Styles** pane. --> +Você pode agora emular temas claros e escuros mais facilmente (veja a media query CSS chamada [prefers-color-scheme](https://web.dev/articles/prefers-color-scheme#the_prefers_color_scheme_media_query)) com os novos atalhos no painel **Estilos**. <!-- Previously, it took more steps to [emulate themes](/docs/devtools/rendering/emulate-css/) in the **Rendering** tab. --> Anteriormente, eram necessários mais passos para [emular temas](/docs/devtools/rendering/emulate-css/) na aba de **Renderização**. @@ -72,8 +72,8 @@ Issue relacionada: [1314299](https://crbug.com/1314299) <!-- DevTools now apply the Content Security Policy (CSP) in the **Preview** tab in the **Network** panel. --> O DevTools agora aplica o *Content Security Policy (CSP)* na aba **Preview** no painel **Rede** -<!-- For example, the first screenshot shows a page that contains [mixed content](https://web.dev/what-is-mixed-content/). The page loads over a secure HTTPS connection, but the stylesheet loads over an insecure HTTP connection. --> -Por exemplo, a primeira imagem mostra uma página que contém [conteúdo misto](https://web.dev/what-is-mixed-content/). A página carrega em uma conexão HTTPS segura, mas o CSS é lido a partir de uma conexão HTTP insegura. +<!-- For example, the first screenshot shows a page that contains [mixed content](https://web.dev/articles/what-is-mixed-content). The page loads over a secure HTTPS connection, but the stylesheet loads over an insecure HTTP connection. --> +Por exemplo, a primeira imagem mostra uma página que contém [conteúdo misto](https://web.dev/articles/what-is-mixed-content). A página carrega em uma conexão HTTPS segura, mas o CSS é lido a partir de uma conexão HTTP insegura. <!-- The browser blocked the stylesheet request by default. However, when you opened the page via the **Preview** tab in the **Network** panel, the stylesheet was not blocked previously (hence the background turned into red). It is now blocked as you would expect (second screenshot). --> O browser bloqueia essa requisição para o CSS por padrão. No entanto, quando você abria a página através da aba **Preview** no painel **Rede**, o CSS não estava bloqueado antes (por isso o fundo fica vermelho). Agora está bloqueado, como é de se esperar (segunda imagem). @@ -207,7 +207,7 @@ Um novo botão **Copiar** foi adicionado à aba de [Mudanças](/docs/devtools/ch {# https://chromium.googlesource.com/devtools/devtools-frontend/+/afe5698f1cd20304d2763574ef8e9faf6a4a6db1 #} {# ​​https://chromium.googlesource.com/devtools/devtools-frontend/+/5de1d6140cad945783f3ca54055134f4a7db42a1 #} -{# https://chromium.googlesource.com/devtools/devtools-frontend/+/573dfc1cca09e49177ece3898c9ba9619c386f06 #} +{# https://chromium.googlesource.com/devtools/devtools-frontend/+/573dfc1cca09e49177ece3898c9ba9619c386f06 #} Issue relacionada: [1268754](https://crbug.com/1268754) diff --git a/site/pt/blog/new-in-devtools-104/index.md b/site/pt/blog/new-in-devtools-104/index.md index f24eec1b8..fa6fcfb17 100644 --- a/site/pt/blog/new-in-devtools-104/index.md +++ b/site/pt/blog/new-in-devtools-104/index.md @@ -101,8 +101,8 @@ Issue relacionada: [960909](https://crbug.com/960909) <!-- Visualize `performance.measure()` marks in your recording with the new **User Timings** track in the **Performance insights** panel. --> Visualize marcas `performance.measure()` em sua gravação com a nova trilha **Tempos do usuário** no painel **Performance insights**. -<!-- For example, this [web page](https://jec.fish/demo/perf-measure) uses the [`performance.measure()`](https://web.dev/usertiming/#calculating-measurements-with-measure()) method to calculate the elapsed time of text loading. --> -Por exemplo, esta [página da web](https://jec.fish/demo/perf-measure) usa o [`performance.measure()`](https://web.dev/usertiming/#calculating-measurements-with-measure()) para calcular o tempo decorrido do carregamento do texto. +<!-- For example, this [web page](https://jec.fish/demo/perf-measure) uses the [`performance.measure()`](https://web.dev/articles/usertiming#calculating_measurements_with_measure()) method to calculate the elapsed time of text loading. --> +Por exemplo, esta [página da web](https://jec.fish/demo/perf-measure) usa o [`performance.measure()`](https://web.dev/articles/usertiming#calculating_measurements_with_measure()) para calcular o tempo decorrido do carregamento do texto. <!-- When you start [measuring the page load](/docs/devtools/performance-insights/#record), the **User Timings** track shows in the recording. Click on the timings item to view its details on the side pane. --> Quando você começa [medindo o carregamento da página](/docs/devtools/performance-insights/#record), a trilha **User Timings** é exibida na gravação. Clique no item de tempos para ver seus detalhes no painel lateral. diff --git a/site/pt/blog/new-in-devtools-105/index.md b/site/pt/blog/new-in-devtools-105/index.md index 8bfa3ba3d..b8b3df6e0 100644 --- a/site/pt/blog/new-in-devtools-105/index.md +++ b/site/pt/blog/new-in-devtools-105/index.md @@ -59,8 +59,8 @@ Issue relacionada: [1257499](https://crbug.com/1257499) <!-- ## Largest Contentful Paint (LCP) in the Performance insights panel {: #lcp } --> ## Largest Contentful Paint (LCP) no painel de insights de desempenho {: #lcp } -<!-- LCP is an important, user-centric metric for measuring [perceived load speed](https://web.dev/user-centric-performance-metrics/#types-of-metrics). You can now find out the critical paths and root causes of a [Largest Contentful Paint (LCP)](https://web.dev/lcp/). --> -O LCP é uma métrica importante e centrada no usuário para medir a [velocidade de carga percebida](https://web.dev/user-centric-performance-metrics/#types-of-metrics). Agora você pode descobrir os caminhos críticos e as causas-raiz de uma [Largest Contentful Paint (LCP)](https://web.dev/lcp/). +<!-- LCP is an important, user-centric metric for measuring [perceived load speed](https://web.dev/articles/user-centric-performance-metrics#types_of_metrics). You can now find out the critical paths and root causes of a [Largest Contentful Paint (LCP)](https://web.dev/articles/lcp). --> +O LCP é uma métrica importante e centrada no usuário para medir a [velocidade de carga percebida](https://web.dev/articles/user-centric-performance-metrics#types_of_metrics). Agora você pode descobrir os caminhos críticos e as causas-raiz de uma [Largest Contentful Paint (LCP)](https://web.dev/articles/lcp). <!-- In a [performance recording](/docs/devtools/performance-insights/#record), click on the LCP badge in the **Timeline**. In the **Details** pane, you can view the LCP score, learn how to fix resources that slow down the LCP and see the critical path for the LCP resource. --> Em uma [gravação de desempenho](/docs/devtools/performance-insights/#record), clique no selo do LCP na **Linha do tempo**. No painel **Detalhes**, você pode ver a pontuação do LCP, saber como corrigir recursos que tornam o LCP mais lento e ver o caminho crítico para o recurso do LCP. <!-- See [Performance Insights](/docs/devtools/performance-insights/) to learn how to get actionable insights and improve your website’s performance with the panel. --> @@ -72,12 +72,12 @@ Issue relacionada: [1326481](https://crbug.com/1326481) <!-- ## Identify flashes of text (FOIT, FOUT) as potential root causes for layout shifts {: #foit-fout } --> ## Identificação de flashes de texto (FOIT, FOUT) como possíveis causas-raiz para mudanças de layout {: #foit-fout } -<!-- The **Performance insights** panel now detects [flash of invisible text (FOIT) and flash of unstyled text (FOUT)](https://web.dev/preload-optional-fonts/#font-rendering) as potential root causes for layout shifts. --> -O painel **Performance Insights** agora detecta [flash de texto invisível (FOIT) e flash de texto sem estilo (FOUT)](https://web.dev/preload-optional-fonts/#font-rendering) como raiz potencial causas para mudanças de layout. +<!-- The **Performance insights** panel now detects [flash of invisible text (FOIT) and flash of unstyled text (FOUT)](https://web.dev/articles/preload-optional-fonts#font_rendering) as potential root causes for layout shifts. --> +O painel **Performance Insights** agora detecta [flash de texto invisível (FOIT) e flash de texto sem estilo (FOUT)](https://web.dev/articles/preload-optional-fonts#font_rendering) como raiz potencial causas para mudanças de layout. <!-- To view the potential root causes of a layout shift, click on a screenshot in the **Layout shifts** track. --> Para ver as possíveis causas principais de uma mudança de layout, clique em uma captura de tela na faixa **Mudanças de layout**. -<!-- See [Optimize WebFont loading and rendering](https://web.dev/optimize-webfont-loading/) to learn the technique to prevent layout shifts. --> -Consulte [Otimizar carregamento e renderização de WebFont](https://web.dev/optimize-webfont-loading/) para aprender a técnica para evitar mudanças de layout. +<!-- See [Optimize WebFont loading and rendering](https://web.dev/articles/optimize-webfont-loading) to learn the technique to prevent layout shifts. --> +Consulte [Otimizar carregamento e renderização de WebFont](https://web.dev/articles/optimize-webfont-loading) para aprender a técnica para evitar mudanças de layout. {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/AMN5oD5hlKhPhnq98sIB.png", alt="FOUT no painel de insights de desempenho", width="800", height="497" %} @@ -86,8 +86,8 @@ Issue relacionadas: [1334628](https://crbug.com/1334628), [1328873](https://crbu <!-- ## Protocol handlers in the Manifest pane {: #manifest } --> ## Handlers de protocolo no painel Manifesto {: #manifest } -<!-- You can now use DevTools to test the [URL protocol handler registration](https://web.dev/url-protocol-handler/) for [Progressive Web Apps (PWA)](https://web.dev/learn/pwa/). --> -Agora você pode usar o DevTools para testar o [registro do handler do protocolo da URL](https://web.dev/url-protocol-handler/) para [Progressive Web Apps (PWA)](https://web.dev/learn/ pwa/). +<!-- You can now use DevTools to test the [URL protocol handler registration](https://web.dev/articles/url-protocol-handler) for [Progressive Web Apps (PWA)](https://web.dev/learn/pwa). --> +Agora você pode usar o DevTools para testar o [registro do handler do protocolo da URL](https://web.dev/articles/url-protocol-handler) para [Progressive Web Apps (PWA)](https://web.dev/learn/ pwa). <!-- The URL protocol handler registration lets installed PWAs handle links that use a specific protocol (e.g. [`magnet`](https://wikipedia.org/wiki/Magnet_URI_scheme), `web+example`) for a more integrated experience. --> O registro do handler de protocolo de URL permite que os PWAs instalados manipulem links que usam um protocolo específico (por exemplo, [`magnet`](https://wikipedia.org/wiki/Magnet_URI_scheme), `web+example`) para uma experiência mais integrada. <!-- Navigate to the **Protocol Handlers** section via the **Application** > **Manifest** pane. You can view and test all the available protocols here. --> @@ -107,8 +107,8 @@ Issue relacionadas: [1300613](https://crbug.com/1300613) ## Selo da camada superior no painel Elementos {: #top-layer } <!-- Use the [top layer badge](/blog/top-layer-devtools/#top-layer-support-design-in-devtools) to understand the concept of the top layer and visualize how the top layer content changes. --> Use o [emblema da camada superior](/blog/top-layer-devtools/#top-layer-support-design-in-devtools) para entender o conceito da camada superior e visualizar como o conteúdo da camada superior muda. -<!-- The [`<dialog>` element](https://web.dev/building-a-dialog-component/) has recently become stable across browsers. When you open a dialog, it is put into a [top layer](/blog/top-layer-devtools/). Top level content renders on top of all the other content. --> -O elemento [`<dialog>`](https://web.dev/building-a-dialog-component/) tornou-se recentemente estável nos navegadores. Quando você abre uma caixa de diálogo, ela é colocada em uma [camada superior](/blog/top-layer-devtools/). O conteúdo de nível superior é renderizado em cima de todo o outro conteúdo. +<!-- The [`<dialog>` element](https://web.dev/articles/building-a-dialog-component) has recently become stable across browsers. When you open a dialog, it is put into a [top layer](/blog/top-layer-devtools/). Top level content renders on top of all the other content. --> +O elemento [`<dialog>`](https://web.dev/articles/building-a-dialog-component) tornou-se recentemente estável nos navegadores. Quando você abre uma caixa de diálogo, ela é colocada em uma [camada superior](/blog/top-layer-devtools/). O conteúdo de nível superior é renderizado em cima de todo o outro conteúdo. <!-- In this [demo](https://jec.fish/demo/dialog), click **Open dialog**. --> Nesta [demonstração](https://jec.fish/demo/dialog), clique em **Abrir caixa de diálogo**. <!-- To help visualize the top layer elements, DevTools adds a top layer container (`#top-layer`) to the DOM tree. It resides after the closing `</html>` tag. --> diff --git a/site/pt/blog/new-in-devtools-106/index.md b/site/pt/blog/new-in-devtools-106/index.md index 2b5a496d6..6b2110ac1 100644 --- a/site/pt/blog/new-in-devtools-106/index.md +++ b/site/pt/blog/new-in-devtools-106/index.md @@ -180,7 +180,7 @@ Issue do Chromium: [1347390](https://crbug.com/1347390) <!-- ## LCP timings breakdown in the Performance Insights panel {: #insights } --> ## Detalhamento de tempos de LCP no painel de Performance Insights {: #insights } -<!-- The **Performance Insights** panel now shows the [timings breakdown](https://web.dev/optimize-lcp/#lcp-breakdown) of the [Largest Containful Paint (LCP)](/docs/devtools/performance-insights/#largest-contentful-paint). Use these timings information to understand and identify an opportunity to improve LCP performance. --> +<!-- The **Performance Insights** panel now shows the [timings breakdown](https://web.dev/articles/optimize-lcp#lcp_breakdown) of the [Largest Containful Paint (LCP)](/docs/devtools/performance-insights/#largest-contentful-paint). Use these timings information to understand and identify an opportunity to improve LCP performance. --> {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/hU6RmoRjFskL8P2ZAB9l.png", alt="Detalhamento de tempos de LCP no painel de Performance Insights", width="800", height="523" %} @@ -209,8 +209,8 @@ Issue do Chromium: [1351383](https://crbug.com/1351383) - Anteriormente, [Extensões do Gravador](/docs/devtools/recorder/reference/#extension-troubleshooting) não eram mostradas no painel do mesmo de tempos em tempos ([1351416](https://crbug.com/1351416)) <!-- - The **Styles** pane now displays a color picker for the [SVG `<stop>`](https://developer.mozilla.org/docs/Web/SVG/Element/stop) element’s `stop-color` property. ([1351096](https://crbug.com/1351096)) --> - O painel **Estilos** agora mostra um seletor de cores para a propriedade `stop-color` da tag [`<stop>` do SVG](https://developer.mozilla.org/docs/Web/SVG/Element/stop). ([1351096](https://crbug.com/1351096)) -<!-- - Identify script causing [layout](https://web.dev/avoid-large-complex-layouts-and-layout-thrashing/) as the potential root causes for layout shifts in the **Performance Insights** panel. ([1343019](https://crbug.com/1343019)) --> -- Identifique scripts causando [layout thrashing](https://web.dev/avoid-large-complex-layouts-and-layout-thrashing/) como uma potencial causa para mudanças de layout no painel de **Performance Insights**. ([1343019](https://crbug.com/1343019)) +<!-- - Identify script causing [layout](https://web.dev/articles/avoid-large-complex-layouts-and-layout-thrashing) as the potential root causes for layout shifts in the **Performance Insights** panel. ([1343019](https://crbug.com/1343019)) --> +- Identifique scripts causando [layout thrashing](https://web.dev/articles/avoid-large-complex-layouts-and-layout-thrashing) como uma potencial causa para mudanças de layout no painel de **Performance Insights**. ([1343019](https://crbug.com/1343019)) <!-- - Display critical path for LCP web fonts in the **Performance Insights** panel. ([1350390](https://crbug.com/1350390)) --> - O caminho crítico para fontes LCP agora é mostrado no painel **Performance Insights**. ([1350390](https://crbug.com/1350390)) diff --git a/site/pt/blog/new-in-devtools-112/index.md b/site/pt/blog/new-in-devtools-112/index.md index 8dad95e8c..bfb6827e0 100644 --- a/site/pt/blog/new-in-devtools-112/index.md +++ b/site/pt/blog/new-in-devtools-112/index.md @@ -27,7 +27,7 @@ tags: <!-- ## Recorder updates {: #recorder } --> -## Atualizações do Gravador {: #recorder } +## Atualizações do Gravador {: #recorder } <!-- ### Replay extensions support {: #replay-extensions } --> ### Suporte para extensões de replay {: #replay-extensions } <!-- The **Recorder** introduces support for custom replay options that you can embed into DevTools with an extension. --> @@ -50,8 +50,8 @@ Issue relacionada: [1400243](https://crbug.com/1400243). <!-- In addition to [custom, CSS, ARIA, text, and XPath selectors](/docs/devtools/recorder/reference/#selector), you can now record using [pierce selectors](https://pptr.dev/guides/query-selectors#pierce-selectors-pierce). These selectors behave like CSS ones but can also pierce through shadow roots. --> Além dos [seletores personalizados, CSS, ARIA, texto e XPath](/docs/devtools/recorder/reference/#selector), agora você pode gravar usando [seletores pierce](https://pptr.dev/guides/ query-selectors#pierce-selectors-pierce). Esses seletores se comportam como os CSS, mas também podem penetrar shadow roots. -<!-- Start a new recording on a page with [shadow DOM](https://web.dev/shadowdom-v1/) and check {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/hmp8j3HiLMCcqPArD9yt.svg", alt="Checkbox.", width="22", height="22" %} **Pierce** in **Selector types to record**. Record your interaction with elements in the shadow DOM and inspect the corresponding step. --> -Inicie uma nova gravação em uma página com [shadow DOM](https://web.dev/shadowdom-v1/) e marque {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/hmp8j3HiLMCcqPArD9yt.svg", alt="Checkbox.", width="22", height="22" %} **Pierce** em **Selecione o tipo de Gravação**. Registre sua interação com elementos no shadow DOM e inspecione a etapa correspondente. +<!-- Start a new recording on a page with [shadow DOM](https://web.dev/articles/shadowdom-v1) and check {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/hmp8j3HiLMCcqPArD9yt.svg", alt="Checkbox.", width="22", height="22" %} **Pierce** in **Selector types to record**. Record your interaction with elements in the shadow DOM and inspect the corresponding step. --> +Inicie uma nova gravação em uma página com [shadow DOM](https://web.dev/articles/shadowdom-v1) e marque {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/hmp8j3HiLMCcqPArD9yt.svg", alt="Checkbox.", width="22", height="22" %} **Pierce** em **Selecione o tipo de Gravação**. Registre sua interação com elementos no shadow DOM e inspecione a etapa correspondente. {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/Spqbf2DG3Fr0D2sc1kgC.png", alt="Configurando o gravador para usar seletores pierce; Seletor pierce em ação.", width="800", height="534" %} @@ -76,7 +76,7 @@ Abra sua gravação, clique em {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/4d {# https://chrome-internal.googlesource.com/devtools/devtools-internal/+/fcaf72d9134e54140cab41c011b7520dd168a340 #} <!-- ### Get extensions {: #get-extensions } --> -### Obter extensões {: #get-extensions } +### Obter extensões {: #get-extensions } <!-- Explore options to customize your recorder experience, for example, with custom export options. Get extensions for the **Recorder** by clicking the {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/4dU9UXvsinS4zbgjd8rK.svg", alt="Export.", width="20", height="20" %} **Export** > **Get extensions** in a recording. --> Explore as opções para personalizar sua experiência de gravação, por exemplo, com opções de exportação personalizadas. Obtenha extensões para o **Gravador** clicando em {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/4dU9UXvsinS4zbgjd8rK.svg", alt="Export.", width="20", height="20" %} **Exportar** > **Obter extensões** em uma gravação. @@ -129,7 +129,7 @@ O painel **Elementos** > **Estilos** agora reconhece a sintaxe [CSS Nesting](/ar Issue relacionada: [1172985](https://crbug.com/1172985). <!-- ## Marking logpoints and conditional breakpoints in the Console {: #logpoint } --> -## Destaque de logpoints e breakpoints condicionais no Console {: #logpoint } +## Destaque de logpoints e breakpoints condicionais no Console {: #logpoint } <!-- Further improving the [enhanced breakpoint UX](/blog/new-in-devtools-111/#breakpoint-redesign), the **Console** now marks messages triggered by breakpoints: --> Nós melhoramos ainda mais a [UX do breakpoint](/blog/new-in-devtools-111/#breakpoint-redesign), o **Console** agora destaca mensagens acionadas por breakpoints: <!-- - `console.*` calls in [conditional breakpoints](/docs/devtools/javascript/breakpoints/#conditional-loc) with an orange question mark `?` --> @@ -178,7 +178,7 @@ Se você selecionar um script ignorado, o botão **Configurar** o levará para Issue relacionada: [883325](https://crbug.com/883325). <!-- ## JavaScript Profiler deprecation started {: #js-profiler-deprecation } --> -## Início da descontinuação do JavaScript Profiler {: #js-profiler-deprecation } +## Início da descontinuação do JavaScript Profiler {: #js-profiler-deprecation } <!-- As early as [Chrome 58](/blog/devtools-javascript-cpu-profile-migration-2/), the DevTools team planned to eventually deprecate the **JavaScript Profiler** and have Node.js and Deno developers use the **Performance** panel for profiling JavaScript CPU performance. --> Já no [Chrome 58](/blog/devtools-javascript-cpu-profile-migration-2/), a equipe do DevTools planejava eventualmente descontinuar o **JavaScript Profiler** e fazer com que os desenvolvedores Node.js e Deno usassem o Painel **Desempenho** para criação de perfil de desempenho da CPU do JavaScript. <!-- This DevTools version (112) starts the [four-phase **JavaScript Profiler** deprecation](https://github.com/ChromeDevTools/rfcs/discussions/2#discussioncomment-5189668). The **JavaScript Profiler** panel now shows the corresponding warning banner. --> @@ -196,7 +196,7 @@ Saiba mais e forneça feedback no [RFC](https://github.com/ChromeDevTools/rfcs/d Issue relacionada: [1417647](https://crbug.com/1417647). <!-- ## Emulate reduced contrast {: #reduced-contrast } --> -## Emulação de contraste reduzido {: #reduced-contrast } +## Emulação de contraste reduzido {: #reduced-contrast } <!-- The [**Rendering**](/docs/devtools/rendering/#open-rendering) tab adds a new option to the [Emulate vision deficiencies](/docs/devtools/rendering/apply-effects/#emulate-vision-deficiencies) list—**Reduced contrast**. With this option, you can discover how your website looks to people with reduced contrast sensitivity. --> A guia [**Renderização**](/docs/devtools/rendering/#open-rendering) adiciona uma nova opção para a lista de [emulação deficiências de visão](/docs/devtools/rendering/apply-effects/#emulate-vision-deficiencies) — **Contraste reduzido**. Com esta opção, você pode descobrir a aparência do seu site para pessoas com sensibilidade reduzida ao contraste. @@ -213,7 +213,7 @@ Com o DevTools, você pode encontrar e corrigir todos os problemas de contraste Issues relacionadas: [1412719](https://crbug.com/1412719), [1412721](https://crbug.com/1412721). <!-- ## Lighthouse 10 {: #lighthouse } --> -## Lighthouse 10 {: #lighthouse } +## Lighthouse 10 {: #lighthouse } <!-- The **Lighthouse** panel now runs [Lighthouse 10.0.1](/blog/lighthouse-10-0/). For more details, see [What's new in Lighthouse 10.0.1](/blog/lighthouse-10-0/). --> O painel **Lighthouse** agora executa [Lighthouse 10.0.1](/blog/lighthouse-10-0/). Para obter mais detalhes, consulte [O que há de novo no Lighthouse 10.0.1](/blog/lighthouse-10-0/). <!-- **Lighthouse** > {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/9gzXiTYY0nZzBxGI6KrV.svg", alt="Settings.", width="24", height="24" %} > {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/ZtDyFg7cjkxacORB3GQn.svg", alt="Empty checkbox.", width="24", height="24" %} **Legacy navigation** is now disabled by default. This option uses legacy [Lighthouse configuration](https://github.com/GoogleChrome/lighthouse/blob/main/docs/configuration.md) in navigation mode. --> @@ -238,7 +238,7 @@ Issue relacionada: [772558](https://crbug.com/772558). <!-- These are some noteworthy fixes in this release: --> Mais algumas novidades dignas de atenção nessa versão: <!-- - The [**Sources** > **Breakpoints**](/docs/devtools/javascript/breakpoints/#manage-loc) pane now shows differentiating file paths next to ambiguous file names ([1403924](crbug.com/1403924)). --> -- O painel [**Código Fonte** > **Breakpoints**](/docs/devtools/javascript/breakpoints/#manage-loc) agora mostra caminhos de arquivo diferenciados ao lado de nomes de arquivo ambíguos +- O painel [**Código Fonte** > **Breakpoints**](/docs/devtools/javascript/breakpoints/#manage-loc) agora mostra caminhos de arquivo diferenciados ao lado de nomes de arquivo ambíguos ([1403924](crbug.com/1403924)). <!-- - The [**Main** section](/docs/devtools/performance/reference/#main) in the flame chart of the **Performance** panel now designates `CpuProfiler::StartProfiling` as `Profiler Overhead` ([1358602](https://crbug.com/1358602)). --> - A [seção **Principal**](/docs/devtools/performance/reference/#main) no diagrama de chamas do painel **Performance** agora designa `CpuProfiler::StartProfiling` como `Profiler Overhead` ([1358602](https://crbug.com/1358602)). diff --git a/site/pt/blog/new-in-devtools-93/index.md b/site/pt/blog/new-in-devtools-93/index.md index 5627fa478..343c94b64 100644 --- a/site/pt/blog/new-in-devtools-93/index.md +++ b/site/pt/blog/new-in-devtools-93/index.md @@ -23,7 +23,7 @@ tags: ## Consultas de contêiner CSS editáveis no painel Styles {: #container-queries } -Agora você pode visualizar e editar [Consultas de contêiner CSS](https://web.dev/new-responsive/#responsive-to-the-container) no painel **Styles**. +Agora você pode visualizar e editar [Consultas de contêiner CSS](https://web.dev/articles/new-responsive#responsive_to_the_container) no painel **Styles**. As consultas de contêiner fornecem uma abordagem muito mais dinâmica para design responsivo. A regra `@container` funciona de maneira semelhante a uma consulta de mídia com `@media`. No entanto, em vez de consultar a viewport e o agente do usuário em busca de informações, `@container` consulta o container antecessor que corresponde a certos critérios. @@ -41,7 +41,7 @@ Issue relacionada: [1146422](https://crbug.com/1146422) ## Prévia do web-bundle no painel Network {: #web-bundle } -[Web bundle](https://web.dev/web-bundles/) é um formato de arquivo para encapsular um ou mais recursos HTTP em um único arquivo. Agora você pode visualizar o conteúdo do web bundle no painel **Network**. +[Web bundle](https://web.dev/articles/web-bundles) é um formato de arquivo para encapsular um ou mais recursos HTTP em um único arquivo. Agora você pode visualizar o conteúdo do web bundle no painel **Network**. O recurso de web-bundle é atualmente experimental. Habilite a sinalização `#enable-experimental-web-platform-features` em `chrome://flags` para testá-la. diff --git a/site/pt/blog/new-in-devtools-96/index.md b/site/pt/blog/new-in-devtools-96/index.md index 0f60ceb2e..0eaa110db 100644 --- a/site/pt/blog/new-in-devtools-96/index.md +++ b/site/pt/blog/new-in-devtools-96/index.md @@ -109,7 +109,7 @@ Issue relacionada: [1243309](https://crbug.com/1243309) <!-- ## Copy declarations as JavaScript in the Styles pane {: #copy-as-js } --> -## Copie as declarações como JavaScript no painel Estilos {: #copy-as-js } +## Copie as declarações como JavaScript no painel Estilos {: #copy-as-js } <!-- Two new options are added in the context menu for you to easily copy CSS rules as JavaScript properties. These shortcuts options are handy especially for developers who are working with [CSS-in-JS](/blog/css-in-js/#what-is-css-in-js) libraries. --> Duas novas opções foram adicionadas ao menu de contexto para que você copie facilmente as regras CSS como propriedades JavaScript. Essas opções de atalhos são úteis especialmente para desenvolvedores que estão trabalhando com bibliotecas [CSS-in-JS](/blog/css-in-js/#what-is-css-in-js). @@ -127,7 +127,7 @@ Issue relacionada: [1253635](https://crbug.com/1253635) <!-- ## New Payload tab in the Network panel {: #payload } --> -## Nova guia Payload no painel Rede {: #payload } +## Nova guia Payload no painel Rede {: #payload } <!-- Use the new **Payload** tab in the **Network** panel when you inspect a network request with payload. Previously, the payload information is available under the **Headers** tab. --> Use a nova guia **Payload** no painel **Rede** ao inspecionar uma solicitação de rede com payload. Anteriormente, as informações de payload estavam disponíveis na guia **Headers**. @@ -150,7 +150,7 @@ Junto com as [melhorias](/blog/new-in-devtools-95/#properties) do painel **Propr {# https://chromium.googlesource.com/devtools/devtools-frontend/+/f1574e9b550317c481a943fec059d84bfb863564 #} -Issue relacionada: [1226262](https://crbug.com/1226262) +Issue relacionada: [1226262](https://crbug.com/1226262) <!-- ## Console updates --> @@ -196,7 +196,7 @@ Issue relacionada: [1254259](https://crbug.com/1254259) <!-- ### Retain the Console sidebar {: #console-sidebar } --> -### Mantida a barra lateral do console {: #console-sidebar } +### Mantida a barra lateral do console {: #console-sidebar } <!-- The Console sidebar is here to stay. In Chrome 94, we announced the [upcoming deprecation of the Console sidebar](/blog/new-in-devtools-94/#deprecated) and ask developers for feedback and concerns. --> A barra lateral do Console veio para ficar. No Chrome 94, anunciamos a [próxima descontinuação da barra lateral do Console](/blog/new-in-devtools-94/#deprecated) e pedimos feedback e preocupações aos desenvolvedores. <!-- We have now got enough feedback from the deprecation notice and we will work on improving the sidebar rather than removing it. --> @@ -211,12 +211,12 @@ Issues relacionadas: [1232937](https://crbug.com/1232937), [1255586](https://crb <!-- ## Deprecated Application cache pane in the Application panel {: #app-cache } --> ## Obsolescência do Painel de cache no painel do Aplicativo {: #app-cache } -<!-- The [Application cache](/docs/devtools/storage/applicationcache/) pane in the Application panel is now removed as the support for [AppCache](https://web.dev/appcache-removal/) is removed from Chrome and other Chromium-based browsers. --> -O painel [Cache do aplicativo](/docs/devtools/storage/applicationcache/) no painel do aplicativo foi removido pois o suporte para [AppCache](https://web.dev/appcache-removal/) foi removido do Chrome e de outros navegadores baseados em Chromium. +<!-- The [Application cache](/docs/devtools/storage/applicationcache/) pane in the Application panel is now removed as the support for [AppCache](https://web.dev/articles/appcache-removal) is removed from Chrome and other Chromium-based browsers. --> +O painel [Cache do aplicativo](/docs/devtools/storage/applicationcache/) no painel do aplicativo foi removido pois o suporte para [AppCache](https://web.dev/articles/appcache-removal) foi removido do Chrome e de outros navegadores baseados em Chromium. {# https://chromium.googlesource.com/devtools/devtools-frontend/+/de4d15e955d6145674e3885cde8a5a70f1269b79 #} -Issue relacionada: [1084190](https://crbug.com/1084190) +Issue relacionada: [1084190](https://crbug.com/1084190) <!-- ## [Experimental] New Reporting API pane in the Application panel {: #reporting-api } --> @@ -227,15 +227,15 @@ Issue relacionada: [1084190](https://crbug.com/1084190) Para ativar o recurso experimental, marque a caixa de seleção **Ativar painel API de relatórios no painel do aplicativo** em **Configurações** > **Experimentos**. {% endAside %} -<!-- The [Reporting API](https://web.dev/reporting-api/) is designed to help you monitor security violations of your page, deprecated API calls, and more. --> -A [API de relatórios](https://web.dev/reporting-api/) foi projetada para ajudá-lo a monitorar violações de segurança de sua página, chamadas de API obsoletas e muito mais. +<!-- The [Reporting API](https://web.dev/articles/reporting-api) is designed to help you monitor security violations of your page, deprecated API calls, and more. --> +A [API de relatórios](https://web.dev/articles/reporting-api) foi projetada para ajudá-lo a monitorar violações de segurança de sua página, chamadas de API obsoletas e muito mais. <!-- With this experiment enabled, you can now view the reports status in the new **Reporting API** pane in the **Application** panel. --> Com esse experimento habilitado, agora você pode visualizar o status dos relatórios no novo painel **API de relatórios** no painel **Aplicativo**. Observe que a seção **Endpoints** ainda está em desenvolvimento ativo (não mostrando endpoints de relatório por enquanto). -<!-- Learn more about the **Reporting API** with [this article](https://web.dev/reporting-api/). --> -Saiba mais sobre a **API de relatórios** com [este artigo](https://web.dev/reporting-api/). +<!-- Learn more about the **Reporting API** with [this article](https://web.dev/articles/reporting-api). --> +Saiba mais sobre a **API de relatórios** com [este artigo](https://web.dev/articles/reporting-api). {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/hbwFqi9aNDOj70FhLXsn.png", alt="Painel de API de relatórios no painel do aplicativo", width="800", height="476" %} diff --git a/site/pt/blog/new-in-devtools-98/index.md b/site/pt/blog/new-in-devtools-98/index.md index 54493943e..9ea538dac 100644 --- a/site/pt/blog/new-in-devtools-98/index.md +++ b/site/pt/blog/new-in-devtools-98/index.md @@ -30,7 +30,7 @@ tags: <!-- end: translation instructions --> <!-- ## Preview feature: Full-page accessibility tree {: #a11y-tree } --> -## Prévia de funcionalidade: Árvore de acessibilidade da página {: #a11y-tree } +## Prévia de funcionalidade: Árvore de acessibilidade da página {: #a11y-tree } <!-- The new **Full-page accessibility tree** makes it easier for you to get an overview of the full-page [accessibility tree](/blog/full-accessibility-tree/#what-is-the-accessibility-tree) and help you better understand how your web content is exposed to assistive technology. --> A nova **Árvore de acessibilidade da página** facilita a obtenção de uma visão geral da [árvore de acessibilidade](/blog/full-accessibility-tree/#what-is-the-accessibility-tree) da página e irá ajudar a entender melhor como seu conteúdo da web é exposto à tecnologia assistiva. <!-- In the **Elements** panel, open the **Accessibility** pane and select **Enable full-page accessibility tree** checkbox. Then, reload DevTools and you will see a new accessibility button in the **Elements** panel. --> @@ -50,7 +50,7 @@ Issue Relacionada: [887173](https://crbug.com/887173) <!-- ## More precise changes in the Changes tab {: #changes } --> -## Alterações mais precisas na guia Alterações {: #changes } +## Alterações mais precisas na guia Alterações {: #changes } <!-- The code changes in the **Changes** tab is pretty-printed automatically. --> As alterações de código na guia **Alterações** são impressas automaticamente. <!-- Previously, it was hard to trace the actual changes of minified source code because all the code is shown in a single line. --> @@ -79,9 +79,9 @@ Issue Relacionada: [1257499](https://crbug.com/1257499) <!-- ## Ensure your pages are cacheable with the Back/forward cache tab {: #bfcache } --> -## Verifique se suas páginas podem ser armazenadas em cache com a guia Cache Voltar/Avançar {: #bfcache } -<!-- [Back/forward cache (or bfcache)](https://web.dev/bfcache/) is a browser optimization that enables instant back and forward navigation. --> -[Cache de retorno/avanço (ou bfcache)](https://web.dev/bfcache/) é uma otimização do navegador que permite a navegação instantânea de retorno e avanço. +## Verifique se suas páginas podem ser armazenadas em cache com a guia Cache Voltar/Avançar {: #bfcache } +<!-- [Back/forward cache (or bfcache)](https://web.dev/articles/bfcache) is a browser optimization that enables instant back and forward navigation. --> +[Cache de retorno/avanço (ou bfcache)](https://web.dev/articles/bfcache) é uma otimização do navegador que permite a navegação instantânea de retorno e avanço. <!-- The new **Back/forward cache** tab can help you test your pages to ensure they're optimized for bfcache, and identify any issues that may be preventing them from being eligible. --> A nova guia **Cache de retorno/avanço** pode ajudar você a testar suas páginas para garantir que elas sejam otimizadas para bfcache e identificar quaisquer problemas que possam estar impedindo que elas sejam qualificadas. <!-- To test a particular page, navigate to it in Chrome and then in DevTools go to **Application** > **Back-forward Cache**. Next, click the **Test back/forward cache** button and DevTools will attempt to navigate away and back to determine whether the page could be restored from bfcache. --> @@ -107,13 +107,13 @@ Estas melhorias permitem chegar mais rapidamente às propriedades de que está a {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/ewmNloO4ohRxlWRNuEW1.png", alt="Filtro do painel Propriedades", width="800", height="505" %} -{# https://chromium.googlesource.com/devtools/devtools-frontend/+/0980f52facf75b6c03e14472d13fe27968d4732b #} - +{# https://chromium.googlesource.com/devtools/devtools-frontend/+/0980f52facf75b6c03e14472d13fe27968d4732b #} + Issue Relacionada: [1269674](https://crbug.com/1269674) <!-- ## Emulate the CSS forced-colors media feature {: #forced-colors } --> -## Emular o recurso de mídia CSS cores forçadas {: #forced-colors } +## Emular o recurso de mídia CSS cores forçadas {: #forced-colors } <!-- The [forced-colors](https://drafts.csswg.org/mediaqueries-5/#forced-colors) CSS media feature is used to detect if the user agent has enabled a forced colors mode (e.g. Windows High Contrast mode) where it enforces a user-chosen limited color palette on the page. --> O recurso de mídia CSS [cores forçadas](https://drafts.csswg.org/mediaqueries-5/#forced-colors) é usado para detectar se o agente do usuário ativou um modo de cores forçadas (por exemplo, modo de alto contraste do Windows) onde impõe uma paleta de cores limitada escolhida pelo usuário na página. @@ -165,7 +165,7 @@ Selecione uma solicitação de XHR no painel **Rede** e pressione **R** no tecla Issue Relacionada: [1050021](https://crbug.com/1050021) - + <!-- ### Keyboard shortcut to expand all search results {: #toggle-search-result } --> ### Keyboard shortcut to expand all search results {: #toggle-search-result } @@ -192,8 +192,8 @@ Issue Relacionada: [1255073](https://crbug.com/1255073) <!-- The **Lighthouse** panel is now running Lighthouse 9. Lighthouse will now list all the elements sharing the same id. --> O painel **Lighthouse** agora está executando o Lighthouse 9. O Lighthouse agora listará todos os elementos que compartilham o mesmo id. -<!-- Non-unique element id is a common accessibility problem. For instance, the id referenced in an `aria-labelledby` attribute is used on [multiple elements](https://web.dev/duplicate-id-aria/). --> -ID de elemento não exclusivo é um problema de acessibilidade comum. Por exemplo, o id referenciado em um atributo `aria-labelledby` é usado em [vários elementos](https://web.dev/duplicate-id-aria/). +<!-- Non-unique element id is a common accessibility problem. For instance, the id referenced in an `aria-labelledby` attribute is used on [multiple elements](https://web.dev/articles/duplicate-id-aria). --> +ID de elemento não exclusivo é um problema de acessibilidade comum. Por exemplo, o id referenciado em um atributo `aria-labelledby` é usado em [vários elementos](https://web.dev/articles/duplicate-id-aria). <!-- Check out the [What’s new in Lighthouse 9.0](/blog/lighthouse-9-0/) for more details on the updates. --> Confira [O que há de novo no Lighthouse 9.0](/blog/lighthouse-9-0/) para mais detalhes sobre as atualizações. @@ -218,7 +218,7 @@ Muitas melhorias de estabilidade no painel **Sources** conforme atualizamos para {# https://chromium.googlesource.com/devtools/devtools-frontend/+/c1ab112d9002d5c3b3bb70cf2839bac182f0cdb5 #} -Issue Relacionada: [1241848](https://crbug.com/1241848) +Issue Relacionada: [1241848](https://crbug.com/1241848) <!-- ## Miscellaneous highlights {: #misc } --> ## Destaques diversos {: #misc } @@ -226,7 +226,7 @@ Issue Relacionada: [1241848](https://crbug.com/1241848) Estas são algumas correções dignas de nota nesta versão: <!-- - Properly displaying the waterfall diagram of network requests. Previously, the style was broken. ([1275501](https://crbug.com/1275501)) - The code highlight was broken when searching in documents with very long lines in the **Sources** panel. It’s now fixed. ([1275496](https://crbug.com/1275496)) -- No more duplicate **Payload** tab in network requests. ([1273972](https://crbug.com/1273972)) +- No more duplicate **Payload** tab in network requests. ([1273972](https://crbug.com/1273972)) - Fixed the missing layout shifts details in the **Summary** section of the **Performance** panel. ([1259606](https://crbug.com/1259606)) - Support arbitrary characters (e.g. `,`, `.`), in **Network Search** queries. ([1267196](https://crbug.com/1267196)) --> - Exibindo corretamente o diagrama em cascata de solicitações de rede. Anteriormente, o estilo estava quebrado. ([1275501](https://crbug.com/1275501)) @@ -247,12 +247,12 @@ Para ativar a experiência, marque a caixa de seleção **Ativar painel da API d O painel experimental **API de relatórios** foi introduzido no [Chrome 96](/blog/new-in-devtools-96/#reporting-api) para ajudar você a monitorar os relatórios gerados em sua página e o status deles. <!-- The **Endpoints** section is now available. It gives you an overview of all the endpoints configured in the `Reporting-Endpoints` header. --> A seção **Endpoints** já está disponível. Ele fornece uma visão geral de todos os endpoints configurados no cabeçalho `Reporting-Endpoints`. -<!-- Learn to use the [Reporting API](https://web.dev/reporting-api/) to monitor security violations, deprecated API calls, and more. --> -Aprenda a usar a [API de relatórios](https://web.dev/reporting-api/) para monitorar violações de segurança, chamadas de API obsoletas e muito mais. +<!-- Learn to use the [Reporting API](https://web.dev/articles/reporting-api) to monitor security violations, deprecated API calls, and more. --> +Aprenda a usar a [API de relatórios](https://web.dev/articles/reporting-api) para monitorar violações de segurança, chamadas de API obsoletas e muito mais. {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/D1fUz4zuS1xwDbszgft1.png", alt="Painel API de relatórios", width="800", height="560" %} -{# https://chromium.googlesource.com/devtools/devtools-frontend/+/a831b26b7ecde579144a42a4faaa7b639789bf3c #} +{# https://chromium.googlesource.com/devtools/devtools-frontend/+/a831b26b7ecde579144a42a4faaa7b639789bf3c #} Issue Relacionada: [1200732](https://crbug.com/1200732) diff --git a/site/pt/blog/new-in-devtools-99/index.md b/site/pt/blog/new-in-devtools-99/index.md index 6d81b2a53..be2559798 100644 --- a/site/pt/blog/new-in-devtools-99/index.md +++ b/site/pt/blog/new-in-devtools-99/index.md @@ -46,8 +46,8 @@ Issue relacionada: [423246](https://crbug.com/423246) <!-- Use the new **Reporting API** pane to monitor the reports generated on your page and their status. --> Use o novo painel **API de relatórios** para monitorar os relatórios gerados em sua página e o status deles. -<!-- The [Reporting API](https://web.dev/reporting-api/) is designed to help you monitor security violations of your page, deprecated API calls, and more. --> -A [API de relatórios](https://web.dev/reporting-api/) foi desenvolvida para ajudar você a monitorar violações de segurança de sua página, chamadas de API obsoletas e muito mais. +<!-- The [Reporting API](https://web.dev/articles/reporting-api) is designed to help you monitor security violations of your page, deprecated API calls, and more. --> +A [API de relatórios](https://web.dev/articles/reporting-api) foi desenvolvida para ajudar você a monitorar violações de segurança de sua página, chamadas de API obsoletas e muito mais. <!-- Open a page which uses the Reporting API (e.g. [demo page](https://reporting-api-demo.glitch.me/)). In the **Application** panel, scroll down to the **Background services** section and select the **Reporting API** pane. --> Abra uma página que usa a API de relatórios (por exemplo, [página de demonstração](https://reporting-api-demo.glitch.me/)). No painel **Aplicativo**, role para baixo até a seção **Serviços em segundo plano** e selecione o painel **API de relatórios**. <!-- The **Reports** section shows you a list of reports generated on your page and their status. Click on it to view the report’s details. --> @@ -149,8 +149,8 @@ Issue relacionada: [1284737](https://crbug.com/1284737) <!-- ### Display worker source files in the Sources panel {: #worker-sourcemap } --> ### Exibição arquivos fontes de workers no painel Origens {: #worker-sourcemap } -<!-- [Worker](https://web.dev/workers-overview/) (e.g. web worker, service worker) source files with relative SourceURL are now displayed in the **Source** panel. Previously, worker source files were not handled correctly. --> -[Worker](https://web.dev/workers-overview/) (por exemplo, web worker, service worker) arquivos fontes com SourceURL relativo agora são exibidos no painel **Fontes**. Anteriormente, os arquivos fontes do worker não eram tratados corretamente. +<!-- [Worker](https://web.dev/articles/workers-overview) (e.g. web worker, service worker) source files with relative SourceURL are now displayed in the **Source** panel. Previously, worker source files were not handled correctly. --> +[Worker](https://web.dev/articles/workers-overview) (por exemplo, web worker, service worker) arquivos fontes com SourceURL relativo agora são exibidos no painel **Fontes**. Anteriormente, os arquivos fontes do worker não eram tratados corretamente. {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/apH5n92bqYWINMQn5VXa.png", alt="Exibição arquivos fontes de workers no painel Origens", width="800", height="509" %} @@ -199,10 +199,10 @@ Estas são algumas correções dignas de nota nesta versão: - Corrigido o problema de [editar cookies](/docs/devtools/storage/cookies/#edit) no painel **Cookies**. ([1290196](https://crbug.com/1290196)) <!-- - Use `Shift` + `Tab` to select the previous command in the [Command menu](/docs/devtools/command-menu/). ([1278743](https://crbug.com/1278743)) --> - Use `Shift` + `Tab` para selecionar o comando anterior no [menu Comando](/docs/devtools/command-menu/). ([1278743](https://crbug.com/1278743)) -<!-- - Report [CORS preflight request](https://web.dev/cross-origin-resource-sharing/#preflight-requests-for-complex-http-calls) issues in the [Issues](/docs/devtools/issues/) tab. ([1272445](https://crbug.com/1272445)). --> -- Informe os problemas de [solicitação de simulação do CORS](https://web.dev/cross-origin-resource-sharing/#preflight-requests-for-complex-http-calls) na aba [Problemas](/docs/devtools/issues/ ). ([1272445](https://crbug.com/1272445)). -<!-- - Report [User-Agent Client Hints](https://web.dev/user-agent-client-hints/) issues in the [Issues](/docs/devtools/issues/) tab. ([1219359](https://crbug.com/1219359)). --> -- Relate problemas de [User-Agent Client Hints](https://web.dev/user-agent-client-hints/) na guia [Problemas](/docs/devtools/issues/).(https://crbug.com/1219359)). +<!-- - Report [CORS preflight request](https://web.dev/articles/cross-origin-resource-sharing#preflight_requests_for_complex_http_calls) issues in the [Issues](/docs/devtools/issues/) tab. ([1272445](https://crbug.com/1272445)). --> +- Informe os problemas de [solicitação de simulação do CORS](https://web.dev/articles/cross-origin-resource-sharing#preflight_requests_for_complex_http_calls) na aba [Problemas](/docs/devtools/issues/ ). ([1272445](https://crbug.com/1272445)). +<!-- - Report [User-Agent Client Hints](https://web.dev/articles/user-agent-client-hints) issues in the [Issues](/docs/devtools/issues/) tab. ([1219359](https://crbug.com/1219359)). --> +- Relate problemas de [User-Agent Client Hints](https://web.dev/articles/user-agent-client-hints) na guia [Problemas](/docs/devtools/issues/).(https://crbug.com/1219359)). <!-- - Fixed `Shift` + `Delete` and `Page up` / `Page down` behaviors in the **Sources** and **Console** panel. ([1278461](https://crbug.com/1278461), [1285662](https://crbug.com/1285662)) --> - Corrigidos os comportamentos `Shift` + `Delete` e `Page up` / `Page down` no painel **Sources** e **Console**. ([1278461](https://crbug.com/1278461), [1285662](https://crbug.com/1285662)) <!-- - Close the breakpoint edit dialog on breakpoint removal in the **Sources** panel. (922513) --> diff --git a/site/pt/docs/lighthouse/best-practices/image-aspect-ratio/index.md b/site/pt/docs/lighthouse/best-practices/image-aspect-ratio/index.md index f559a3ea5..a5d5cb848 100644 --- a/site/pt/docs/lighthouse/best-practices/image-aspect-ratio/index.md +++ b/site/pt/docs/lighthouse/best-practices/image-aspect-ratio/index.md @@ -27,7 +27,7 @@ Existem duas causas comuns para uma proporção de imagem incorreta: ### Use um CDN de imagem -Um CDN de imagem pode facilitar a automatização do processo de criação de versões de tamanhos diferentes de suas imagens. Confira [Usar CDNs de imagem para otimizar imagens](https://web.dev/image-cdns/) para ter uma visão geral e [Como instalar o CDN de imagem Thumbor](https://web.dev/install-thumbor/) para ver um codelab prático. +Um CDN de imagem pode facilitar a automatização do processo de criação de versões de tamanhos diferentes de suas imagens. Confira [Usar CDNs de imagem para otimizar imagens](https://web.dev/articles/image-cdns) para ter uma visão geral e [Como instalar o CDN de imagem Thumbor](https://web.dev/articles/install-thumbor) para ver um codelab prático. ### Verifique o CSS que afeta a proporção da imagem @@ -39,11 +39,11 @@ Quando possível, é uma boa prática especificar os `width` e `height` de cada No entanto, especificar as dimensões da imagem em HTML pode ser difícil se você estiver trabalhando com imagens responsivas, porque não há como saber a largura e a altura até que você saiba as dimensões da janela de visualização. Considere o uso da biblioteca de [proporções CSS](https://www.npmjs.com/package/css-aspect-ratio) ou [caixas de proporções](https://css-tricks.com/aspect-ratio-boxes/) para ajudar a preservar as proporções das imagens responsivas. -Por fim, confira a postagem [Exibir imagens com dimensões corretas](https://web.dev/serve-images-with-correct-dimensions/) para aprender como exibir imagens com o tamanho certo para o dispositivo de cada usuário. +Por fim, confira a postagem [Exibir imagens com dimensões corretas](https://web.dev/articles/serve-images-with-correct-dimensions) para aprender como exibir imagens com o tamanho certo para o dispositivo de cada usuário. ## Recursos - [Código-fonte para a auditoria **Exibe imagens com proporção incorreta**](https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/audits/image-aspect-ratio.js) - [Proporção CSS](https://www.npmjs.com/package/css-aspect-ratio) - [Caixas de proporção de aspecto](https://css-tricks.com/aspect-ratio-boxes/) -- [Sirva imagens com dimensões corretas](https://web.dev/serve-images-with-correct-dimensions/) +- [Sirva imagens com dimensões corretas](https://web.dev/articles/serve-images-with-correct-dimensions) diff --git a/site/pt/docs/lighthouse/performance/bootup-time/index.md b/site/pt/docs/lighthouse/performance/bootup-time/index.md index 8ef683ca4..84010b561 100644 --- a/site/pt/docs/lighthouse/performance/bootup-time/index.md +++ b/site/pt/docs/lighthouse/performance/bootup-time/index.md @@ -24,7 +24,7 @@ Quando seu JavaScript leva muito tempo para ser executado, ele desacelera o dese - **Custo de execução** - JavaScript também é executado no thread principal. Se sua página executa muitos códigos antes de eles realmente serem necessários, isso também atrasa seu [Time to Interactive](https://web.dev/tti/) (tempo até interativa), que é uma das principais métricas relacionadas a como os usuários percebem a velocidade de sua página. + JavaScript também é executado no thread principal. Se sua página executa muitos códigos antes de eles realmente serem necessários, isso também atrasa seu [Time to Interactive](https://web.dev/articles/tti) (tempo até interativa), que é uma das principais métricas relacionadas a como os usuários percebem a velocidade de sua página. - **Custo de memória** diff --git a/site/pt/docs/lighthouse/performance/critical-request-chains/index.md b/site/pt/docs/lighthouse/performance/critical-request-chains/index.md index 854663bc4..1462cea7e 100644 --- a/site/pt/docs/lighthouse/performance/critical-request-chains/index.md +++ b/site/pt/docs/lighthouse/performance/critical-request-chains/index.md @@ -32,7 +32,7 @@ Use os resultados de auditoria de cadeias de solicitação críticas para direci - Otimize o número de bytes críticos para reduzir o tempo de download (número de viagens de ida e volta). - Otimize a ordem em que os recursos críticos restantes são carregados: baixe todos os ativos críticos o quanto antes para encurtar o comprimento do caminho crítico. -Saiba mais sobre como otimizar suas [imagens](https://web.dev/use-imagemin-to-compress-images/) , [JavaScript](https://web.dev/apply-instant-loading-with-prpl/), [CSS](https://web.dev/defer-non-critical-css/) e [fontes da web](https://web.dev/avoid-invisible-text/) . +Saiba mais sobre como otimizar suas [imagens](https://web.dev/articles/use-imagemin-to-compress-images) , [JavaScript](https://web.dev/articles/apply-instant-loading-with-prpl), [CSS](https://web.dev/articles/defer-non-critical-css) e [fontes da web](https://web.dev/articles/avoid-invisible-text) . ## Orientação específica de pilha diff --git a/site/pt/docs/lighthouse/performance/dom-size/index.md b/site/pt/docs/lighthouse/performance/dom-size/index.md index e5dd749d6..6811d0db9 100644 --- a/site/pt/docs/lighthouse/performance/dom-size/index.md +++ b/site/pt/docs/lighthouse/performance/dom-size/index.md @@ -51,11 +51,11 @@ Se você não puder evitar uma grande árvore DOM, outra abordagem para melhorar ### Angular -Se você estiver renderizando listas grandes, use a [rolagem virtual](https://web.dev/virtualize-lists-with-angular-cdk/) com o Component Dev Kit (CDK). +Se você estiver renderizando listas grandes, use a [rolagem virtual](https://web.dev/articles/virtualize-lists-with-angular-cdk) com o Component Dev Kit (CDK). ### React -- Use uma biblioteca de "janelas", como [`react-window`](https://web.dev/virtualize-long-lists-react-window/), para minimizar o número de nós DOM criados se você estiver renderizando muitos elementos repetidos na página. +- Use uma biblioteca de "janelas", como [`react-window`](https://web.dev/articles/virtualize-long-lists-react-window), para minimizar o número de nós DOM criados se você estiver renderizando muitos elementos repetidos na página. - Minimize a renderização desnecessária usando [`shouldComponentUpdate`](https://reactjs.org/docs/optimizing-performance.html#shouldcomponentupdate-in-action), [`PureComponent`](https://reactjs.org/docs/react-api.html#reactpurecomponent) ou [`React.memo`](https://reactjs.org/docs/react-api.html#reactmemo). - [Ignore os efeitos](https://reactjs.org/docs/hooks-effect.html#tip-optimizing-performance-by-skipping-effects) apenas até que certas dependências tenham mudado se você estiver usando `Effect` para melhorar o desempenho em tempo de execução. diff --git a/site/pt/docs/lighthouse/performance/efficient-animated-content/index.md b/site/pt/docs/lighthouse/performance/efficient-animated-content/index.md index 3d1da29cf..61f270ee7 100644 --- a/site/pt/docs/lighthouse/performance/efficient-animated-content/index.md +++ b/site/pt/docs/lighthouse/performance/efficient-animated-content/index.md @@ -53,7 +53,7 @@ Felizmente, você pode recriar esses comportamentos usando o elemento `<video>` ## Use um serviço que converte GIFs em vídeos HTML5 -Muitos [CDNs de imagem](https://web.dev/image-cdns/) oferecem suporte à conversão de vídeo de GIF para HTML5. Você carrega um GIF para o CDN da imagem, e o CDN da imagem retorna um vídeo HTML5. +Muitos [CDNs de imagem](https://web.dev/articles/image-cdns) oferecem suporte à conversão de vídeo de GIF para HTML5. Você carrega um GIF para o CDN da imagem, e o CDN da imagem retorna um vídeo HTML5. ## Orientação específica para pilhas @@ -64,5 +64,5 @@ Para conteúdo animado, use [`amp-anim`](https://amp.dev/documentation/component ## Recursos - [Código-fonte para a auditoria **Use formatos de vídeo conteúdo animado**](https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/audits/byte-efficiency/efficient-animated-content.js) -- [Substitua GIFs animados por vídeo para carregamentos de página mais rápidos](https://web.dev/replace-gifs-with-videos/) +- [Substitua GIFs animados por vídeo para carregamentos de página mais rápidos](https://web.dev/articles/replace-gifs-with-videos) - [Codelab Substitua GIFs por vídeo](https://web.dev/codelab-replace-gifs-with-video) diff --git a/site/pt/docs/lighthouse/performance/first-meaningful-paint/index.md b/site/pt/docs/lighthouse/performance/first-meaningful-paint/index.md index 1faea4891..7eb28dccb 100644 --- a/site/pt/docs/lighthouse/performance/first-meaningful-paint/index.md +++ b/site/pt/docs/lighthouse/performance/first-meaningful-paint/index.md @@ -8,7 +8,7 @@ date: 2019-05-02 updated: 2019-11-05 --- -{% Aside 'caution' %} A métrica first-meaningful-paint (FMP) foi descontinuada no Lighthouse 6.0. Na prática, a FMP tem sido excessivamente sensível a pequenas diferenças no carregamento da página, levando a resultados inconsistentes (bimodais). Além disso, a definição da métrica depende de detalhes de implementação específicos do navegador, o que significa que não pode ser padronizada nem implementada em todos os navegadores da web. Seguindo em frente, considere usar a [Largest Contentful Paint](https://web.dev/lcp/). {% endAside %} +{% Aside 'caution' %} A métrica first-meaningful-paint (FMP) foi descontinuada no Lighthouse 6.0. Na prática, a FMP tem sido excessivamente sensível a pequenas diferenças no carregamento da página, levando a resultados inconsistentes (bimodais). Além disso, a definição da métrica depende de detalhes de implementação específicos do navegador, o que significa que não pode ser padronizada nem implementada em todos os navegadores da web. Seguindo em frente, considere usar a [Largest Contentful Paint](https://web.dev/articles/lcp). {% endAside %} First Meaningful Paint (FMP) é uma das seis métricas monitoradas na **seção Desempenho** do relatório Lighthouse. Cada métrica captura algum aspecto da velocidade de carregamento da página. @@ -20,7 +20,7 @@ O Lighthouse exibe FMP em segundos: O FMP mede quando o conteúdo principal de uma página está visível para o usuário. A pontuação bruta para FMP é o tempo em segundos entre o usuário iniciar o carregamento da página e a página que renderiza o conteúdo primário acima da dobra. A FMP mostra essencialmente o tempo da pintura após o qual a maior mudança de layout acima da dobra acontece. Saiba mais sobre os detalhes técnicos da FMP em [Time to First Meaningful Paint do Google: uma abordagem baseada em layout](https://docs.google.com/document/d/1BR94tJdZLsin5poeet0XoTW60M0SjvOJQttKT-JK8HI/view). -[First Contentful Paint (FCP)](https://web.dev/fcp/) e FMP são geralmente as mesmas quando o primeiro bit de conteúdo renderizado na página inclui o conteúdo acima da dobra. No entanto, essas métricas podem ser diferentes quando, por exemplo, há conteúdo acima da dobra em um iframe. A FMP registra quando o conteúdo do iframe é visível para o usuário, enquanto a FCP *não* inclui o conteúdo do iframe. +[First Contentful Paint (FCP)](https://web.dev/articles/fcp) e FMP são geralmente as mesmas quando o primeiro bit de conteúdo renderizado na página inclui o conteúdo acima da dobra. No entanto, essas métricas podem ser diferentes quando, por exemplo, há conteúdo acima da dobra em um iframe. A FMP registra quando o conteúdo do iframe é visível para o usuário, enquanto a FCP *não* inclui o conteúdo do iframe. ## Como o Lighthouse determina sua pontuação FMP @@ -65,11 +65,11 @@ Esta tabela mostra como interpretar sua pontuação FMP: ## Como melhorar sua pontuação FMP -Veja [Como melhorar a Largest Contentful Paint em seu site](https://web.dev/lcp/#how-to-improve-lcp). As estratégias para melhorar a FMP são basicamente as mesmas que as estratégias para melhorar a Largest Contentful Paint. +Veja [Como melhorar a Largest Contentful Paint em seu site](https://web.dev/articles/lcp#how_to_improve_lcp). As estratégias para melhorar a FMP são basicamente as mesmas que as estratégias para melhorar a Largest Contentful Paint. ## Rastreando FMP em dispositivos de usuários reais -Para saber como medir quando a FMP realmente ocorre nos dispositivos dos usuários, consulte a página [Métricas de desempenho centradas no usuário do Google.](https://web.dev/user-centric-performance-metrics/) A seção [Acompanhamento de FMP usando elementos hero](https://developers.google.com/web/fundamentals/performance/user-centric-performance-metrics#tracking_fmp_using_hero_elements) descreve como acessar programaticamente os dados da FCP e enviá-los ao Google Analytics. +Para saber como medir quando a FMP realmente ocorre nos dispositivos dos usuários, consulte a página [Métricas de desempenho centradas no usuário do Google.](https://web.dev/articles/user-centric-performance-metrics) A seção [Acompanhamento de FMP usando elementos hero](https://developers.google.com/web/fundamentals/performance/user-centric-performance-metrics#tracking_fmp_using_hero_elements) descreve como acessar programaticamente os dados da FCP e enviá-los ao Google Analytics. Consulte [Avaliação do desempenho de carregamento do Google na vida real com navegação e tempo de recursos](https://developers.google.com/web/fundamentals/performance/navigation-and-resource-timing/) para obter mais informações sobre como coletar métricas de usuários reais. A auditoria [Marcas e medidas de tempo do usuário do Lighthouse](/docs/lighthouse/performance/user-timings/) permite que você veja os dados de tempo do usuário em seu relatório. @@ -80,4 +80,4 @@ Consulte [Avaliação do desempenho de carregamento do Google na vida real com n - [Código-fonte para auditoria da **First Meaningful Paint**](https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/audits/metrics/first-meaningful-paint.js) - [Guia de pontuação do Lighthouse v3](https://developers.google.com/web/tools/lighthouse/v3/scoring) - [Tempo até a First Meaningful Paint: uma abordagem baseada em layout](https://docs.google.com/document/d/1BR94tJdZLsin5poeet0XoTW60M0SjvOJQttKT-JK8HI/view) -- [Largest Contentful Paint](https://web.dev/lcp/) +- [Largest Contentful Paint](https://web.dev/articles/lcp) diff --git a/site/pt/docs/lighthouse/performance/font-display/index.md b/site/pt/docs/lighthouse/performance/font-display/index.md index 9521bdd25..6604f61cd 100644 --- a/site/pt/docs/lighthouse/performance/font-display/index.md +++ b/site/pt/docs/lighthouse/performance/font-display/index.md @@ -6,7 +6,7 @@ date: 2019-05-02 updated: 2020-04-29 --- -As fontes geralmente são arquivos grandes que demoram um pouco para carregar. Alguns navegadores ocultam o texto até que a fonte carregue, causando um [flash de texto invisível (Flash Of Invisible Text - FOIT)](https://web.dev/avoid-invisible-text/) . +As fontes geralmente são arquivos grandes que demoram um pouco para carregar. Alguns navegadores ocultam o texto até que a fonte carregue, causando um [flash de texto invisível (Flash Of Invisible Text - FOIT)](https://web.dev/articles/avoid-invisible-text) . ## Como falha a auditoria de exibição de fontes do Lighthouse @@ -30,14 +30,14 @@ A maneira mais fácil de evitar a exibição de texto invisível durante o carre } ``` -A API [font-display](https://developer.mozilla.org/docs/Web/CSS/@font-face/font-display) especifica como uma fonte é exibida. `swap` informa ao navegador que o texto usando a fonte deve ser exibido imediatamente usando uma fonte do sistema. Assim que a fonte personalizada estiver pronta, ela substituirá a fonte do sistema. (Veja [Evite texto invisível durante o carregamento](https://web.dev/avoid-invisible-text/) para mais informações.) +A API [font-display](https://developer.mozilla.org/docs/Web/CSS/@font-face/font-display) especifica como uma fonte é exibida. `swap` informa ao navegador que o texto usando a fonte deve ser exibido imediatamente usando uma fonte do sistema. Assim que a fonte personalizada estiver pronta, ela substituirá a fonte do sistema. (Veja [Evite texto invisível durante o carregamento](https://web.dev/articles/avoid-invisible-text) para mais informações.) ### Pré-carregue as fontes da web Use `<link rel="preload" as="font">` para baixar seus arquivos de fonte com antecedência. Saiba mais: -- [Pré-carregue fontes da web para melhorar a velocidade de carregamento (codelab)](https://web.dev/codelab-preload-web-fonts/) -- [Evite mudanças de layout e flashes de texto invisível (FOIT) pré-carregando fontes opcionais](https://web.dev/preload-optional-fonts/) +- [Pré-carregue fontes da web para melhorar a velocidade de carregamento (codelab)](https://web.dev/articles/codelab-preload-web-fonts) +- [Evite mudanças de layout e flashes de texto invisível (FOIT) pré-carregando fontes opcionais](https://web.dev/articles/preload-optional-fonts) ### Google Fonts @@ -66,7 +66,7 @@ Especifique `@font-display` ao [definir fontes personalizadas](https://devdocs.m ## Recursos - [Código-fonte para a auditoria **Garanta que o texto permanece visível durante a carga de fontes da web**](https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/audits/font-display.js) -- [Evite texto invisível durante o carregamento](https://web.dev/avoid-invisible-text/) +- [Evite texto invisível durante o carregamento](https://web.dev/articles/avoid-invisible-text) - [Controlando o desempenho da fonte com font-display](https://developers.google.com/web/updates/2016/02/font-display) -- [Pré-carregue fontes da web para melhorar a velocidade de carregamento (codelab)](https://web.dev/codelab-preload-web-fonts/) -- [Evite mudanças de layout e flashes de texto invisível (FOIT) pré-carregando fontes opcionais](https://web.dev/preload-optional-fonts/) +- [Pré-carregue fontes da web para melhorar a velocidade de carregamento (codelab)](https://web.dev/articles/codelab-preload-web-fonts) +- [Evite mudanças de layout e flashes de texto invisível (FOIT) pré-carregando fontes opcionais](https://web.dev/articles/preload-optional-fonts) diff --git a/site/pt/docs/lighthouse/performance/interactive/index.md b/site/pt/docs/lighthouse/performance/interactive/index.md index 049883a62..9e47794b4 100644 --- a/site/pt/docs/lighthouse/performance/interactive/index.md +++ b/site/pt/docs/lighthouse/performance/interactive/index.md @@ -18,7 +18,7 @@ O Lighthouse apresenta a métrica TTI em segundos: O TTI mede quanto tempo leva para uma página se tornar *totalmente* interativa. Uma página é considerada totalmente interativa quando: -- A página exibe conteúdo útil, que é medido pela métrica [First Contentful Paint](https://web.dev/fcp/), +- A página exibe conteúdo útil, que é medido pela métrica [First Contentful Paint](https://web.dev/articles/fcp), - Os handlers de eventos estão registrados para a maioria dos elementos visíveis da página e - A página responde às interações do usuário dentro de 50 milissegundos. @@ -59,7 +59,7 @@ A tabela abaixo mostra como interpretar sua pontuação TTI: ## Como melhorar sua pontuação TTI -Uma melhoria que pode ter um efeito particularmente grande na TTI é adiar ou remover o trabalho desnecessário do JavaScript. Procure oportunidades para [otimizar seu JavaScript](https://web.dev/fast/#optimize-your-javascript). Em particular, considere [reduzir as payloads do JavaScript com divisão de código](https://web.dev/reduce-javascript-payloads-with-code-splitting/) e [aplicação do padrão PRPL](https://web.dev/apply-instant-loading-with-prpl/). [Otimizar o JavaScript de terceiros](https://web.dev/fast/#optimize-your-third-party-resources) também produz melhorias significativas para alguns sites. +Uma melhoria que pode ter um efeito particularmente grande na TTI é adiar ou remover o trabalho desnecessário do JavaScript. Procure oportunidades para [otimizar seu JavaScript](https://web.dev/articles/fast#optimize_your_javascript). Em particular, considere [reduzir as payloads do JavaScript com divisão de código](https://web.dev/articles/reduce-javascript-payloads-with-code-splitting) e [aplicação do padrão PRPL](https://web.dev/articles/apply-instant-loading-with-prpl). [Otimizar o JavaScript de terceiros](https://web.dev/articles/fast#optimize_your_third_party_resources) também produz melhorias significativas para alguns sites. Essas duas auditorias de diagnóstico fornecem oportunidades adicionais para reduzir o trabalho do JavaScript: @@ -68,7 +68,7 @@ Essas duas auditorias de diagnóstico fornecem oportunidades adicionais para red ## Rastreando a TTI em dispositivos de usuários reais -Para saber como medir quando a TTI ocorre nos dispositivos dos seus usuários, consulte a página Google [Métricas de desempenho centradas no usuário](https://web.dev/user-centric-performance-metrics/). A [seção Tracking TTI](https://developers.google.com/web/fundamentals/performance/user-centric-performance-metrics#tracking_tti) descreve como acessar programaticamente os dados do TTI e enviá-los ao Google Analytics. +Para saber como medir quando a TTI ocorre nos dispositivos dos seus usuários, consulte a página Google [Métricas de desempenho centradas no usuário](https://web.dev/articles/user-centric-performance-metrics). A [seção Tracking TTI](https://developers.google.com/web/fundamentals/performance/user-centric-performance-metrics#tracking_tti) descreve como acessar programaticamente os dados do TTI e enviá-los ao Google Analytics. {% Aside %} TTI pode ser difícil de rastrear em campo. Rastrear o [First Input Delay](https://developers.google.com/web/updates/2018/05/first-input-delay) pode ser um bom proxy para TTI. {% endAside %} @@ -81,4 +81,4 @@ Para saber como medir quando a TTI ocorre nos dispositivos dos seus usuários, c - [First Interactive And Consistently Interactive](https://docs.google.com/document/d/1GGiI9-7KeY3TPqS3YT271upUVimo-XiL5mwWorDUD4c/edit) - [Otimização de inicialização de JavaScript](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/javascript-startup-optimization/) - [Reduza payloads JavaScript com tree shaking](https://developers.google.com/web/fundamentals/performance/optimizing-javascript/tree-shaking/) -- [Otimize recursos de terceiros](https://web.dev/fast/#optimize-your-third-party-resources) +- [Otimize recursos de terceiros](https://web.dev/articles/fast#optimize_your_third_party_resources) diff --git a/site/pt/docs/lighthouse/performance/lighthouse-total-blocking-time/index.md b/site/pt/docs/lighthouse/performance/lighthouse-total-blocking-time/index.md index bf571455e..566f6c106 100644 --- a/site/pt/docs/lighthouse/performance/lighthouse-total-blocking-time/index.md +++ b/site/pt/docs/lighthouse/performance/lighthouse-total-blocking-time/index.md @@ -14,7 +14,7 @@ O Lighthouse apresenta a métrica TBT em segundos: ## O que o TBT mede -O TBT mede a quantidade total de tempo que uma página fica bloqueada para responder à entrada do usuário, como cliques do mouse, toques na tela ou pressionar de teclas. A soma é calculada adicionando a *parte* do bloqueio de todas [as tarefas longas](https://web.dev/long-tasks-devtools/) entre [First Contentful Paint](https://web.dev/fcp/), renderização do primeiro conteúdo, e [Time to Interactive](https://web.dev/tti/), tempo até interativa. Qualquer tarefa executada por mais de 50 ms é uma tarefa longa. A quantidade de tempo após 50 ms é a parte do bloqueio. Por exemplo, se o Lighthouse detecta uma tarefa de 70 ms, a porção de bloqueio seria de 20 ms. +O TBT mede a quantidade total de tempo que uma página fica bloqueada para responder à entrada do usuário, como cliques do mouse, toques na tela ou pressionar de teclas. A soma é calculada adicionando a *parte* do bloqueio de todas [as tarefas longas](https://web.dev/articles/long-tasks-devtools) entre [First Contentful Paint](https://web.dev/articles/fcp), renderização do primeiro conteúdo, e [Time to Interactive](https://web.dev/articles/tti), tempo até interativa. Qualquer tarefa executada por mais de 50 ms é uma tarefa longa. A quantidade de tempo após 50 ms é a parte do bloqueio. Por exemplo, se o Lighthouse detecta uma tarefa de 70 ms, a porção de bloqueio seria de 20 ms. ## Como o Lighthouse determina sua pontuação TBT @@ -51,11 +51,11 @@ Esta tabela mostra como interpretar sua pontuação TBT: ## Como melhorar sua pontuação TBT -Veja [O que está causando minhas longas tarefas?](https://web.dev/long-tasks-devtools/#what-is-causing-my-long-tasks) para aprender a diagnosticar a causa raiz de tarefas longas com o painel Desempenho do Chrome DevTools. +Veja [O que está causando minhas longas tarefas?](https://web.dev/articles/long-tasks-devtools#what_is_causing_my_long_tasks) para aprender a diagnosticar a causa raiz de tarefas longas com o painel Desempenho do Chrome DevTools. Em geral, as causas mais comuns das tarefas longas são: -- Carregamento, análise ou execução desnecessária de JavaScript. Ao analisar seu código no painel Desempenho, você pode descobrir que o thread principal está fazendo um trabalho que não é realmente necessário para carregar a página. [Reduzir as cargas úteis do JavaScript com divisão de código](https://web.dev/reduce-javascript-payloads-with-code-splitting/), [remover código não utilizado](https://web.dev/remove-unused-code/) ou [carregar de forma eficiente o JavaScript de terceiros](https://web.dev/efficiently-load-third-party-javascript/) deve melhorar sua pontuação TBT. +- Carregamento, análise ou execução desnecessária de JavaScript. Ao analisar seu código no painel Desempenho, você pode descobrir que o thread principal está fazendo um trabalho que não é realmente necessário para carregar a página. [Reduzir as cargas úteis do JavaScript com divisão de código](https://web.dev/articles/reduce-javascript-payloads-with-code-splitting), [remover código não utilizado](https://web.dev/articles/remove-unused-code) ou [carregar de forma eficiente o JavaScript de terceiros](https://web.dev/articles/efficiently-load-third-party-javascript) deve melhorar sua pontuação TBT. - Declarações de JavaScript ineficientes. Por exemplo, depois de analisar seu código no painel Desempenho, suponha que você veja uma chamada para `document.querySelectorAll('a')` que retorna 2.000 nós. Refatorar seu código para usar um seletor mais específico que retorna apenas 10 nós deve melhorar sua pontuação TBT. {% Aside %} Carregamento, análise ou execução desnecessários de JavaScript costumam ser uma oportunidade muito maior para melhorias na maioria dos sites. {% endAside %} @@ -65,10 +65,10 @@ Em geral, as causas mais comuns das tarefas longas são: ## Recursos - [Código fonte para auditoria de **Total Blocking Time** (tempo total de bloqueio)](https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/audits/metrics/total-blocking-time.js) -- [As longas tarefas de JavaScript estão atrasando seu Time to Interactive (tempo até interativa)?](https://web.dev/long-tasks-devtools/) -- [First Contentful Paint (primeira renderização de conteúdo)](https://web.dev/fcp/) -- [Time to Interactive (tempo até interativa)](https://web.dev/tti/) -- [Reduza os payloads do JavaScript com divisão de código](https://web.dev/reduce-javascript-payloads-with-code-splitting/) -- [Remova o código não utilizado](https://web.dev/remove-unused-code/) -- [Carregue com eficiência recursos de terceiros](https://web.dev/efficiently-load-third-party-javascript/) -- [Carregue com eficiência recursos de terceiros](https://web.dev/efficiently-load-third-party-javascript/) +- [As longas tarefas de JavaScript estão atrasando seu Time to Interactive (tempo até interativa)?](https://web.dev/articles/long-tasks-devtools) +- [First Contentful Paint (primeira renderização de conteúdo)](https://web.dev/articles/fcp) +- [Time to Interactive (tempo até interativa)](https://web.dev/articles/tti) +- [Reduza os payloads do JavaScript com divisão de código](https://web.dev/articles/reduce-javascript-payloads-with-code-splitting) +- [Remova o código não utilizado](https://web.dev/articles/remove-unused-code) +- [Carregue com eficiência recursos de terceiros](https://web.dev/articles/efficiently-load-third-party-javascript) +- [Carregue com eficiência recursos de terceiros](https://web.dev/articles/efficiently-load-third-party-javascript) diff --git a/site/pt/docs/lighthouse/performance/mainthread-work-breakdown/index.md b/site/pt/docs/lighthouse/performance/mainthread-work-breakdown/index.md index 028525a5e..2399f1fa8 100644 --- a/site/pt/docs/lighthouse/performance/mainthread-work-breakdown/index.md +++ b/site/pt/docs/lighthouse/performance/mainthread-work-breakdown/index.md @@ -28,9 +28,9 @@ Veja [Faça menos trabalho no thread principal](https://developers.google.com/we ### Computação de scripts -- [Otimize o JavaScript de terceiros](https://web.dev/fast/#optimize-your-third-party-resources) +- [Otimize o JavaScript de terceiros](https://web.dev/articles/fast#optimize_your_third_party_resources) - [Rode seus handlers de entradas em paralelo](https://developers.google.com/web/fundamentals/performance/rendering/debounce-your-input-handlers) -- [Use web workers](https://web.dev/off-main-thread/) +- [Use web workers](https://web.dev/articles/off-main-thread) ### Estilo e layout @@ -44,18 +44,18 @@ Veja [Faça menos trabalho no thread principal](https://developers.google.com/we ### Processamento de HTML e CSS -- [Extraia o CSS crítico](https://web.dev/extract-critical-css/) -- [Minifique o CSS](https://web.dev/minify-css/) -- [Adie CSS não crítico](https://web.dev/defer-non-critical-css/) +- [Extraia o CSS crítico](https://web.dev/articles/extract-critical-css) +- [Minifique o CSS](https://web.dev/articles/minify-css) +- [Adie CSS não crítico](https://web.dev/articles/defer-non-critical-css) ### Processamento e compilação de scripts -- [Reduza payloads JavaScript com divisão de código](https://web.dev/reduce-javascript-payloads-with-code-splitting/) -- [Remova o código não utilizado](https://web.dev/remove-unused-code/) +- [Reduza payloads JavaScript com divisão de código](https://web.dev/articles/reduce-javascript-payloads-with-code-splitting) +- [Remova o código não utilizado](https://web.dev/articles/remove-unused-code) ### Coleta de lixo -- [Monitore o uso de memória total de sua página da web com `measureMemory()`](https://web.dev/monitor-total-page-memory-usage/) +- [Monitore o uso de memória total de sua página da web com `measureMemory()`](https://web.dev/articles/monitor-total-page-memory-usage) ## Recursos diff --git a/site/pt/docs/lighthouse/performance/non-composited-animations/index.md b/site/pt/docs/lighthouse/performance/non-composited-animations/index.md index b25d24d3a..edde4cad1 100644 --- a/site/pt/docs/lighthouse/performance/non-composited-animations/index.md +++ b/site/pt/docs/lighthouse/performance/non-composited-animations/index.md @@ -5,7 +5,7 @@ description: Como passar na auditoria Lighthouse "Evitar animações não compos date: 2020-08-12 --- -Animações não compostas podem parecer irregulares (ou seja, não suaves) em telefones de baixo custo ou quando tarefas de alto desempenho estiverem sendo executadas no thread principal. As animações Janky podem aumentar o [Cumulative Layout Shift](https://web.dev/cls/) (CLS) da sua página. Reduzir o CLS melhorará sua pontuação de desempenho do Lighthouse. +Animações não compostas podem parecer irregulares (ou seja, não suaves) em telefones de baixo custo ou quando tarefas de alto desempenho estiverem sendo executadas no thread principal. As animações Janky podem aumentar o [Cumulative Layout Shift](https://web.dev/articles/cls) (CLS) da sua página. Reduzir o CLS melhorará sua pontuação de desempenho do Lighthouse. ## Fundo @@ -27,12 +27,12 @@ Quando uma animação não pode ser composta, o Chrome relata os motivos da falh ## Como garantir que as animações sejam compostas -Consulte [Atenha-se às propriedades somente do compositor e gerencie a contagem de camadas](https://developers.google.com/web/fundamentals/performance/rendering/stick-to-compositor-only-properties-and-manage-layer-count) e [animações de alto desempenho](https://web.dev/animations-guide/) . +Consulte [Atenha-se às propriedades somente do compositor e gerencie a contagem de camadas](https://developers.google.com/web/fundamentals/performance/rendering/stick-to-compositor-only-properties-and-manage-layer-count) e [animações de alto desempenho](https://web.dev/articles/animations-guide) . ## Recursos - [Código-fonte para a auditoria de *evitar animações não compostas*](https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/audits/non-composited-animations.js) - [Atenha-se às propriedades somente do compositor e gerencie a contagem de camadas](https://developers.google.com/web/fundamentals/performance/rendering/stick-to-compositor-only-properties-and-manage-layer-count) -- [Animações de alto desempenho](https://web.dev/animations-guide/) +- [Animações de alto desempenho](https://web.dev/articles/animations-guide) - [Simplifique a complexidade da pintura e reduza as áreas de pintura](https://developers.google.com/web/fundamentals/performance/rendering/simplify-paint-complexity-and-reduce-paint-areas) - [Visão interna dos navegadores da web modernos (parte 3)](https://developers.google.com/web/updates/2018/09/inside-browser-part3) diff --git a/site/pt/docs/lighthouse/performance/offscreen-images/index.md b/site/pt/docs/lighthouse/performance/offscreen-images/index.md index cfcf3db69..9e56b8904 100644 --- a/site/pt/docs/lighthouse/performance/offscreen-images/index.md +++ b/site/pt/docs/lighthouse/performance/offscreen-images/index.md @@ -6,7 +6,7 @@ date: 2019-05-02 updated: 2020-05-29 --- -A seção Oportunidades de seu relatório Lighthouse lista todas as imagens offscreen ou ocultas em sua página junto com a economia potencial em [kibibytes (KiB)](https://en.wikipedia.org/wiki/Kibibyte). Considere o carregamento lazy dessas imagens depois que todos os recursos críticos terminarem de carregar para reduzir a métrica [Time to Interactive](https://web.dev/tti/) (tempo até interação): +A seção Oportunidades de seu relatório Lighthouse lista todas as imagens offscreen ou ocultas em sua página junto com a economia potencial em [kibibytes (KiB)](https://en.wikipedia.org/wiki/Kibibyte). Considere o carregamento lazy dessas imagens depois que todos os recursos críticos terminarem de carregar para reduzir a métrica [Time to Interactive](https://web.dev/articles/tti) (tempo até interação): <figure> {% Img src="image/tcFciHGuF3MxnTr1y5ue01OGLBn2/agMyJtIarLruD8iuz0Mt.png", alt="Uma captura de tela da auditoria Lighthouse Defer offscreen images", width="800", height="416" %}</figure> @@ -28,7 +28,7 @@ Instale um [plugin Joomla de carregamento lazy](https://extensions.joomla.org/in ### Magento -Considere modificar seus modelos de produto e catálogo para usar o recurso de [carregamento lazy](https://web.dev/browser-level-image-lazy-loading/) da plataforma web. +Considere modificar seus modelos de produto e catálogo para usar o recurso de [carregamento lazy](https://web.dev/articles/browser-level-image-lazy-loading) da plataforma web. ### WordPress diff --git a/site/pt/docs/lighthouse/performance/performance-scoring/index.md b/site/pt/docs/lighthouse/performance/performance-scoring/index.md index ea05d729a..b59be3ea8 100644 --- a/site/pt/docs/lighthouse/performance/performance-scoring/index.md +++ b/site/pt/docs/lighthouse/performance/performance-scoring/index.md @@ -25,7 +25,7 @@ Grande parte da variabilidade na sua pontuação geral de desempenho e valores d [A documentação do Lighthouse sobre variabilidade](https://github.com/GoogleChrome/lighthouse/blob/master/docs/variability.md) trata disso com mais profundidade. -Além disso, embora o Lighthouse possa fornecer uma pontuação geral de desempenho única, pode ser mais útil pensar no desempenho do seu site como uma distribuição de pontuações, em vez de um único número. Veja a introdução das [Métricas de desempenho centradas no usuário](https://web.dev/user-centric-performance-metrics/) para entender o porquê. +Além disso, embora o Lighthouse possa fornecer uma pontuação geral de desempenho única, pode ser mais útil pensar no desempenho do seu site como uma distribuição de pontuações, em vez de um único número. Veja a introdução das [Métricas de desempenho centradas no usuário](https://web.dev/articles/user-centric-performance-metrics) para entender o porquê. ## Como a pontuação de desempenho é ponderada {: #weightings} diff --git a/site/pt/docs/lighthouse/performance/server-response-time/index.md b/site/pt/docs/lighthouse/performance/server-response-time/index.md index 0deafcebc..fed148b12 100644 --- a/site/pt/docs/lighthouse/performance/server-response-time/index.md +++ b/site/pt/docs/lighthouse/performance/server-response-time/index.md @@ -51,4 +51,4 @@ Temas, plug-ins e especificações de servidor contribuem para o tempo de respos ## Recursos - [Código-fonte da auditoria **Reduza tempos de resposta do servidor (TTFB)**](https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/audits/server-response-time.js) -- [Adaptive Serving com o Network Information API](https://web.dev/adaptive-serving-based-on-network-quality/) +- [Adaptive Serving com o Network Information API](https://web.dev/articles/adaptive-serving-based-on-network-quality) diff --git a/site/pt/docs/lighthouse/performance/speed-index/index.md b/site/pt/docs/lighthouse/performance/speed-index/index.md index 0699b43a0..8c9353e05 100644 --- a/site/pt/docs/lighthouse/performance/speed-index/index.md +++ b/site/pt/docs/lighthouse/performance/speed-index/index.md @@ -57,7 +57,7 @@ Embora qualquer coisa que você faça para melhorar a velocidade de carregamento - [Minimize o trabalho do thread principal](/docs/lighthouse/performance/mainthread-work-breakdown/) - [Reduza o tempo de execução do JavaScript](/docs/lighthouse/performance/bootup-time/) -- [Garanta que o texto permanece visível durante o carregamento das fontes web](https://web.dev/font-display/) +- [Garanta que o texto permanece visível durante o carregamento das fontes web](https://web.dev/articles/font-display) {% Partial 'lighthouse-performance/improve.njk' %} diff --git a/site/pt/docs/lighthouse/performance/third-party-facades/index.md b/site/pt/docs/lighthouse/performance/third-party-facades/index.md index 7d62e32b4..fc0fe394f 100644 --- a/site/pt/docs/lighthouse/performance/third-party-facades/index.md +++ b/site/pt/docs/lighthouse/performance/third-party-facades/index.md @@ -5,7 +5,7 @@ description: Aprenda sobre as oportunidades de carregamento lazy de recursos de date: 2020-12-01 --- -[Recursos de terceiros](https://web.dev/third-party-javascript/) costumam ser usados para exibir anúncios ou vídeos e integrar-se a mídias socias. A abordagem default é carregar recursos de terceiros assim que a página for carregada, mas isto pode retardar desnecessariamente o carregamento da página. Se o conteúdo de terceiros não for crítico, esse custo de desempenho pode ser reduzido usando [carregamento lazy](https://web.dev/fast/#lazy-load-images-and-video). +[Recursos de terceiros](https://web.dev/articles/third-party-javascript) costumam ser usados para exibir anúncios ou vídeos e integrar-se a mídias socias. A abordagem default é carregar recursos de terceiros assim que a página for carregada, mas isto pode retardar desnecessariamente o carregamento da página. Se o conteúdo de terceiros não for crítico, esse custo de desempenho pode ser reduzido usando [carregamento lazy](https://web.dev/articles/fast#lazy_load_images_and_video). Esta auditoria destaca incorporações de terceiros que podem ser carregadas de forma lazy durante a interação. Nesse caso, uma *fachada* é usada no lugar do conteúdo de terceiros até que o usuário interaja com ele. diff --git a/site/pt/docs/lighthouse/performance/total-byte-weight/index.md b/site/pt/docs/lighthouse/performance/total-byte-weight/index.md index 834c02a81..1014b5293 100644 --- a/site/pt/docs/lighthouse/performance/total-byte-weight/index.md +++ b/site/pt/docs/lighthouse/performance/total-byte-weight/index.md @@ -26,22 +26,22 @@ Com base nos [dados do arquivo HTTP](https://httparchive.org/reports/state-of-th ## Como reduzir o tamanho da carga útil -Tente manter o tamanho total de bytes abaixo de 1.600 KiB. Essa meta é baseada na quantidade de dados que podem ser baixados teoricamente em uma conexão 3G enquanto ainda atinge um [tempo de interação](https://web.dev/tti/) de 10 segundos ou menos. +Tente manter o tamanho total de bytes abaixo de 1.600 KiB. Essa meta é baseada na quantidade de dados que podem ser baixados teoricamente em uma conexão 3G enquanto ainda atinge um [tempo de interação](https://web.dev/articles/tti) de 10 segundos ou menos. Aqui estão algumas maneiras de manter o tamanho da carga útil baixo: -- Adie as solicitações até que sejam necessárias. Consulte o [padrão PRPL](https://web.dev/apply-instant-loading-with-prpl/) para uma abordagem possível. +- Adie as solicitações até que sejam necessárias. Consulte o [padrão PRPL](https://web.dev/articles/apply-instant-loading-with-prpl) para uma abordagem possível. - Otimize as solicitações para serem o menor possível. As técnicas possíveis incluem: - - [Minimize e comprima cargas úteis de rede](https://web.dev/reduce-network-payloads-using-text-compression/). - - [Use WebP em vez de JPEG ou PNG para suas imagens](https://web.dev/serve-images-webp/). - - [Defina o nível de compressão de imagens JPEG para 85](https://web.dev/use-imagemin-to-compress-images/). -- Solicitações de cache para que a página não baixe novamente os recursos em visitas repetidas. Consulte a [página inicial de confiabilidade](https://web.dev/reliable/) da rede para saber como o cache funciona e como implementá-lo. + - [Minimize e comprima cargas úteis de rede](https://web.dev/articles/reduce-network-payloads-using-text-compression). + - [Use WebP em vez de JPEG ou PNG para suas imagens](https://web.dev/articles/serve-images-webp). + - [Defina o nível de compressão de imagens JPEG para 85](https://web.dev/articles/use-imagemin-to-compress-images). +- Solicitações de cache para que a página não baixe novamente os recursos em visitas repetidas. Consulte a [página inicial de confiabilidade](https://web.dev/explore/reliable) da rede para saber como o cache funciona e como implementá-lo. ## Orientação específica para pilha ### Angular -Aplique a [divisão de código no nível da rota](https://web.dev/route-level-code-splitting-in-angular/) para minimizar o tamanho de seus pacotes de JavaScript. Além disso, considere pré-armazenar em cache os ativos com o [trabalhador de serviço Angular](https://web.dev/precaching-with-the-angular-service-worker/). +Aplique a [divisão de código no nível da rota](https://web.dev/articles/route-level-code-splitting-in-angular) para minimizar o tamanho de seus pacotes de JavaScript. Além disso, considere pré-armazenar em cache os ativos com o [trabalhador de serviço Angular](https://web.dev/articles/precaching-with-the-angular-service-worker). ### Drupal diff --git a/site/pt/docs/lighthouse/performance/unminified-css/index.md b/site/pt/docs/lighthouse/performance/unminified-css/index.md index 6d6f3a76d..94be53dca 100644 --- a/site/pt/docs/lighthouse/performance/unminified-css/index.md +++ b/site/pt/docs/lighthouse/performance/unminified-css/index.md @@ -46,7 +46,7 @@ Para sites pequenos que você não atualiza com frequência, provavelmente você Para desenvolvedores profissionais, você provavelmente deseja configurar um fluxo de trabalho automatizado que minifica seu CSS automaticamente antes de implantar o código atualizado. Isso geralmente é feito com uma ferramenta de construção como Gulp ou Webpack. -Aprenda como minificar seu código CSS em [Minificar CSS](https://web.dev/minify-css/). +Aprenda como minificar seu código CSS em [Minificar CSS](https://web.dev/articles/minify-css). ## Orientação específica de pilha @@ -73,5 +73,5 @@ Vários [plug-ins do WordPress](https://wordpress.org/plugins/search/minify+css/ ## Recursos - [Código-fonte para auditoria **Minify CSS**](https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/audits/byte-efficiency/unminified-css.js) -- [Minificar CSS](https://web.dev/minify-css/) -- [Minificar e comprimir payloads de rede](https://web.dev/reduce-network-payloads-using-text-compression/) +- [Minificar CSS](https://web.dev/articles/minify-css) +- [Minificar e comprimir payloads de rede](https://web.dev/articles/reduce-network-payloads-using-text-compression) diff --git a/site/pt/docs/lighthouse/performance/unused-css-rules/index.md b/site/pt/docs/lighthouse/performance/unused-css-rules/index.md index 2c9d7e861..f355577e8 100644 --- a/site/pt/docs/lighthouse/performance/unused-css-rules/index.md +++ b/site/pt/docs/lighthouse/performance/unused-css-rules/index.md @@ -44,7 +44,7 @@ De forma semelhante ao código incorporado em `<script>`, insira estilos crític Considere automatizar o processo de extração e incorporação de CSS "Acima da Dobra" usando a [ferramenta crítica](https://github.com/addyosmani/critical/blob/master/README.md). -Saiba mais em [Adie CSS não crítico](https://web.dev/defer-non-critical-css/). +Saiba mais em [Adie CSS não crítico](https://web.dev/articles/defer-non-critical-css). ## Orientações para pilhas específicas diff --git a/site/pt/docs/lighthouse/performance/uses-long-cache-ttl/index.md b/site/pt/docs/lighthouse/performance/uses-long-cache-ttl/index.md index 9f04f7a2a..22a92eadb 100644 --- a/site/pt/docs/lighthouse/performance/uses-long-cache-ttl/index.md +++ b/site/pt/docs/lighthouse/performance/uses-long-cache-ttl/index.md @@ -63,7 +63,7 @@ Use `no-cache` se o recurso mudar e a atualização for importante, mas você ai Uma duração de cache mais longa nem sempre é melhor. Em última análise, cabe a você decidir qual é a duração ideal do cache para seus recursos. -Existem muitas diretivas para personalizar como o navegador armazena em cache diferentes recursos. Saiba mais sobre recursos de cache no guia [Cache HTTP: sua primeira linha de defesa](https://web.dev/http-cache/) e no codelab [Configurando o comportamento de cache em HTTP](https://web.dev/codelab-http-cache/) . +Existem muitas diretivas para personalizar como o navegador armazena em cache diferentes recursos. Saiba mais sobre recursos de cache no guia [Cache HTTP: sua primeira linha de defesa](https://web.dev/articles/http-cache) e no codelab [Configurando o comportamento de cache em HTTP](https://web.dev/articles/codelab-http-cache) . ## Como verificar respostas em cache no Chrome DevTools diff --git a/site/pt/docs/lighthouse/performance/uses-optimized-images/index.md b/site/pt/docs/lighthouse/performance/uses-optimized-images/index.md index 63c35e30b..1f571cf40 100644 --- a/site/pt/docs/lighthouse/performance/uses-optimized-images/index.md +++ b/site/pt/docs/lighthouse/performance/uses-optimized-images/index.md @@ -20,13 +20,13 @@ O Lighthouse coleta todas as imagens JPEG ou BMP da página, define o nível de Existem várias etapas que você pode seguir para otimizar suas imagens, incluindo: -- [Usar CDNs de imagem](https://web.dev/image-cdns/) -- [Compactar imagens](https://web.dev/use-imagemin-to-compress-images/) -- [Substituir GIFs animados por vídeo](https://web.dev/replace-gifs-with-videos/) -- [Remover imagens de carregamento lento](https://web.dev/use-lazysizes-to-lazyload-images/) -- [Veicular imagens responsivas](https://web.dev/serve-responsive-images/) -- [Veicular imagens com dimensões corretas](https://web.dev/serve-images-with-correct-dimensions/) -- [Usar imagens WebP](https://web.dev/serve-images-webp/) +- [Usar CDNs de imagem](https://web.dev/articles/image-cdns) +- [Compactar imagens](https://web.dev/articles/use-imagemin-to-compress-images) +- [Substituir GIFs animados por vídeo](https://web.dev/articles/replace-gifs-with-videos) +- [Remover imagens de carregamento lento](https://web.dev/articles/use-lazysizes-to-lazyload-images) +- [Veicular imagens responsivas](https://web.dev/articles/serve-responsive-images) +- [Veicular imagens com dimensões corretas](https://web.dev/articles/serve-images-with-correct-dimensions) +- [Usar imagens WebP](https://web.dev/articles/serve-images-webp) ## Otimize imagens usando ferramentas de GUI diff --git a/site/pt/docs/lighthouse/performance/uses-rel-preconnect/index.md b/site/pt/docs/lighthouse/performance/uses-rel-preconnect/index.md index db4059a9e..c9de11573 100644 --- a/site/pt/docs/lighthouse/performance/uses-rel-preconnect/index.md +++ b/site/pt/docs/lighthouse/performance/uses-rel-preconnect/index.md @@ -59,5 +59,5 @@ Use [um módulo que ofereça suporte a dicas de recursos do agente do usuário]( - [Código-fonte para **pré-conexão à** auditoria de origens exigida](https://developers.google.com/web/fundamentals/performance/resource-prioritization#preconnect) - [Priorização de recursos - Obtendo o navegador para ajudá-lo](https://developers.google.com/web/fundamentals/performance/resource-prioritization#preconnect) -- [Estabeleça conexões de rede com antecedência para melhorar a velocidade percebida da página](https://web.dev/preconnect-and-dns-prefetch/) +- [Estabeleça conexões de rede com antecedência para melhorar a velocidade percebida da página](https://web.dev/articles/preconnect-and-dns-prefetch) - [Tipos de link: pré-conexão](https://developer.mozilla.org/docs/Web/HTML/Link_types/preconnect#Browser_compatibility) diff --git a/site/pt/docs/lighthouse/performance/uses-rel-preload/index.md b/site/pt/docs/lighthouse/performance/uses-rel-preload/index.md index b0b16d470..c4fe32a03 100644 --- a/site/pt/docs/lighthouse/performance/uses-rel-preload/index.md +++ b/site/pt/docs/lighthouse/performance/uses-rel-preload/index.md @@ -46,7 +46,7 @@ Declare links de pré-carregamento em seu HTML para instruir o navegador a fazer <figure> {% Img src="image/tcFciHGuF3MxnTr1y5ue01OGLBn2/tJLJXH2qXcrDBUfsSAK5.png", alt="Com links de pré-carregamento, styles.css e ui.js são solicitados ao mesmo tempo que app.js.", width="800", height="478" %} <figcaption>Com links de pré-carregamento, <code>styles.css</code> e <code>ui.js</code> são solicitados ao mesmo tempo que <code>app.js</code> </figcaption></figure> -Veja também [Pré-carregue ativos importantes para melhorar a velocidade de carregamento](https://web.dev/preload-critical-assets/) para mais orientações. +Veja também [Pré-carregue ativos importantes para melhorar a velocidade de carregamento](https://web.dev/articles/preload-critical-assets) para mais orientações. ### Compatibilidade de navegadores @@ -60,7 +60,7 @@ Veja a página [Preloading Assets da Tooling.Report](https://bundlers.tooling.re ### Angular -[Pré-carregue as rotas](https://web.dev/route-preloading-in-angular/) com antecedência para acelerar a navegação. +[Pré-carregue as rotas](https://web.dev/articles/route-preloading-in-angular) com antecedência para acelerar a navegação. ### Magento diff --git a/site/pt/docs/lighthouse/performance/uses-responsive-images/index.md b/site/pt/docs/lighthouse/performance/uses-responsive-images/index.md index 2e6c0c72d..12b8f1491 100644 --- a/site/pt/docs/lighthouse/performance/uses-responsive-images/index.md +++ b/site/pt/docs/lighthouse/performance/uses-responsive-images/index.md @@ -18,9 +18,9 @@ Para cada imagem na página, o Lighthouse compara o tamanho da imagem renderizad O ideal é que sua página nunca sirva imagens maiores do que a versão renderizada na tela do usuário. Qualquer coisa maior do que apenas resulta em bytes perdidos e diminui o tempo de carregamento da página. -A principal estratégia para servir imagens de tamanhos adequados é chamada de "imagens responsivas". Com imagens responsivas, você gera várias versões de cada imagem e, a seguir, especifica qual versão usar em seu HTML ou CSS usando media queries, dimensões da viewport e assim por diante. Veja [Sirva imagens responsivas](https://web.dev/serve-responsive-images/) para saber mais. +A principal estratégia para servir imagens de tamanhos adequados é chamada de "imagens responsivas". Com imagens responsivas, você gera várias versões de cada imagem e, a seguir, especifica qual versão usar em seu HTML ou CSS usando media queries, dimensões da viewport e assim por diante. Veja [Sirva imagens responsivas](https://web.dev/articles/serve-responsive-images) para saber mais. -[Os CDNs de imagem](https://web.dev/image-cdns/) são outra boa estratégia para servir imagens de tamanho apropriado. Você pode pensar em CDNs de imagem como APIs de serviços web para transformar imagens. +[Os CDNs de imagem](https://web.dev/articles/image-cdns) são outra boa estratégia para servir imagens de tamanho apropriado. Você pode pensar em CDNs de imagem como APIs de serviços web para transformar imagens. Outra estratégia é usar formatos de imagem vetoriais, como SVG. Com uma quantidade finita de código, uma imagem SVG pode ser redimensionada para qualquer tamanho. Veja [Substitua ícones complexos por SVG](https://developers.google.com/web/fundamentals/design-and-ux/responsive/images#replace_complex_icons_with_svg) para saber mais. @@ -30,7 +30,7 @@ Ferramentas como [gulp-responsive](https://www.npmjs.com/package/gulp-responsive ### AMP -Use o suporte ao componente [`amp-img`](https://amp.dev/documentation/components/amp-img/?format=websites) [`srcset`](https://web.dev/use-srcset-to-automatically-choose-the-right-image/) para especificar quais ativos de imagem usar com base no tamanho da tela. Veja também [Imagens responsivas com srcset, sizes e heights](https://amp.dev/documentation/guides-and-tutorials/develop/style_and_layout/art_direction/) . +Use o suporte ao componente [`amp-img`](https://amp.dev/documentation/components/amp-img/?format=websites) [`srcset`](https://web.dev/articles/use-srcset-to-automatically-choose-the-right-image) para especificar quais ativos de imagem usar com base no tamanho da tela. Veja também [Imagens responsivas com srcset, sizes e heights](https://amp.dev/documentation/guides-and-tutorials/develop/style_and_layout/art_direction/) . ### Angular @@ -55,4 +55,4 @@ Carregue imagens diretamente pela [biblioteca de mídia](https://wordpress.org/s ## Recursos - [Código fonte para a auditoria **Redimensione imagens corretamente**](https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/audits/byte-efficiency/uses-responsive-images.js) -- [Sirva imagens com dimensões corretas](https://web.dev/serve-images-with-correct-dimensions/) +- [Sirva imagens com dimensões corretas](https://web.dev/articles/serve-images-with-correct-dimensions) diff --git a/site/pt/docs/lighthouse/performance/uses-webp-images/index.md b/site/pt/docs/lighthouse/performance/uses-webp-images/index.md index 7d296b455..7275af0a2 100644 --- a/site/pt/docs/lighthouse/performance/uses-webp-images/index.md +++ b/site/pt/docs/lighthouse/performance/uses-webp-images/index.md @@ -62,6 +62,6 @@ Considere o uso de um [plugin](https://wordpress.org/plugins/search/convert+webp ## Recursos - [Código-fonte para a auditoria **Sirva imagens em formatos modernos**](https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/audits/byte-efficiency/modern-image-formats.js) -- [Use imagens WebP](https://web.dev/serve-images-webp/) +- [Use imagens WebP](https://web.dev/articles/serve-images-webp) <!-- https://www.reddit.com/r/webdev/comments/gspjwe/serve_images_in_nextgen_formats/ --> diff --git a/site/pt/docs/lighthouse/pwa/apple-touch-icon/index.md b/site/pt/docs/lighthouse/pwa/apple-touch-icon/index.md index 6ae0b147a..a28ed3a79 100644 --- a/site/pt/docs/lighthouse/pwa/apple-touch-icon/index.md +++ b/site/pt/docs/lighthouse/pwa/apple-touch-icon/index.md @@ -8,7 +8,7 @@ updated: 2023-03-24 is_outdated: true --- -Quando os usuários do Safari do iOS adicionam [Progressive Web Apps (PWAs)](https://web.dev/progressive-web-apps/) à tela inicial, o ícone exibido é chamado de _ícone Apple Touch_ (Apple touch icon). É possível especificar o ícone usado pelo app com a inclusão de uma tag `<link rel="apple-touch-icon" href="/example.png">` no `<head>` da página. Se a página não apresentar essa tag de link, o iOS faz uma captura de tela do conteúdo para gerar um ícone. Em outras palavras, instruir o iOS a fazer o download de um ícone resulta em uma experiência do usuário mais otimizada. +Quando os usuários do Safari do iOS adicionam [Progressive Web Apps (PWAs)](https://web.dev/explore/progressive-web-apps) à tela inicial, o ícone exibido é chamado de _ícone Apple Touch_ (Apple touch icon). É possível especificar o ícone usado pelo app com a inclusão de uma tag `<link rel="apple-touch-icon" href="/example.png">` no `<head>` da página. Se a página não apresentar essa tag de link, o iOS faz uma captura de tela do conteúdo para gerar um ícone. Em outras palavras, instruir o iOS a fazer o download de um ícone resulta em uma experiência do usuário mais otimizada. ## Como a auditoria de ícone Apple Touch do Lighthouse falha @@ -39,7 +39,7 @@ O Lighthouse não verifica se o ícone realmente existe ou se o tamanho dele est 2. Substitua `/example.png` pelo caminho real do ícone. -{% Aside 'codelab' %} Confira o codelab [Como adicionar um ícone Apple Touch ao Progressive Web App](https://web.dev/codelab-apple-touch-icon/) para ver como o ícone oferece uma experiência do usuário mais otimizada. {% endAside %} +{% Aside 'codelab' %} Confira o codelab [Como adicionar um ícone Apple Touch ao Progressive Web App](https://web.dev/articles/codelab-apple-touch-icon) para ver como o ícone oferece uma experiência do usuário mais otimizada. {% endAside %} Para fornecer uma boa experiência do usuário, verifique o seguinte: @@ -50,5 +50,5 @@ Para fornecer uma boa experiência do usuário, verifique o seguinte: ## Recursos - [Código-fonte da auditoria **O `apple-touch-icon` fornecido não é valido**](https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/audits/apple-touch-icon.js) -- [Veja os critérios para a instalação](https://web.dev/install-criteria/) +- [Veja os critérios para a instalação](https://web.dev/articles/install-criteria) - <a href="https://webhint.io/docs/user-guide/hints/hint-apple-touch-icons/" rel="noreferrer">Use o ícone Apple Touch</a> diff --git a/site/pt/docs/lighthouse/pwa/installable-manifest/index.md b/site/pt/docs/lighthouse/pwa/installable-manifest/index.md index a9912746d..8a52a4eb1 100644 --- a/site/pt/docs/lighthouse/pwa/installable-manifest/index.md +++ b/site/pt/docs/lighthouse/pwa/installable-manifest/index.md @@ -10,13 +10,13 @@ date: 2019-05-04 updated: 2019-09-19 --- -A instalabilidade é um requisito básico dos [Progressive Web Apps (PWAs)](https://web.dev/progressive-web-apps/). Ao solicitar aos usuários que instalem seu PWA, você permite que eles o adicionem às telas iniciais. Os usuários que adicionam aplicativos às telas iniciais se envolvem com esses aplicativos com mais frequência. +A instalabilidade é um requisito básico dos [Progressive Web Apps (PWAs)](https://web.dev/explore/progressive-web-apps). Ao solicitar aos usuários que instalem seu PWA, você permite que eles o adicionem às telas iniciais. Os usuários que adicionam aplicativos às telas iniciais se envolvem com esses aplicativos com mais frequência. -Um [manifesto de aplicativo da web](https://web.dev/add-manifest/) inclui informações importantes necessárias para tornar seu aplicativo instalável. +Um [manifesto de aplicativo da web](https://web.dev/articles/add-manifest) inclui informações importantes necessárias para tornar seu aplicativo instalável. ## Como a auditoria de manifesto do aplicativo da web Lighthouse falha -O [Lighthouse](https://developers.google.com/web/tools/lighthouse/) sinaliza páginas que não têm um [manifesto de aplicativo da web](https://web.dev/add-manifest/) que atenda aos requisitos mínimos de instalação: +O [Lighthouse](https://developers.google.com/web/tools/lighthouse/) sinaliza páginas que não têm um [manifesto de aplicativo da web](https://web.dev/articles/add-manifest) que atenda aos requisitos mínimos de instalação: <figure>{% Img src="image/tcFciHGuF3MxnTr1y5ue01OGLBn2/039DlaixA4drrswBzSra.png", alt="Auditoria do farol mostrando que o usuário não pode instalar o aplicativo da web a partir da tela inicial", width="800", height="98" %}</figure> @@ -28,13 +28,13 @@ Se o manifesto de uma página não incluir as seguintes propriedades, ele falhar - Uma propriedade [`display`](https://developer.mozilla.org/docs/Web/Manifest/display) ajustada para `fullscreen`, `standalone` ou `minimal-ui` - Uma propriedade [`prefer_related_applications`](https://developers.google.com/web/fundamentals/app-install-banners/native) definida com um valor diferente de `true`. -{% Aside 'caution' %} Um manifesto de aplicativo da web é _necessário_ para que seu aplicativo seja instalável, mas não é _suficiente_. Para saber como atender a todos os requisitos de instalabilidade, consulte a postagem [Descubra o que é preciso para ser instalável.](https://web.dev/progressive-web-apps/) {% endAside %} +{% Aside 'caution' %} Um manifesto de aplicativo da web é _necessário_ para que seu aplicativo seja instalável, mas não é _suficiente_. Para saber como atender a todos os requisitos de instalabilidade, consulte a postagem [Descubra o que é preciso para ser instalável.](https://web.dev/explore/progressive-web-apps) {% endAside %} {% Partial 'lighthouse-pwa/scoring.njk' %} ## Como tornar seu PWA instalável -Certifique-se de que seu aplicativo tenha um manifesto que atenda aos critérios acima. Consulte a [coleção instalável](https://web.dev/progressive-web-apps/) para obter mais informações sobre como criar um PWA. +Certifique-se de que seu aplicativo tenha um manifesto que atenda aos critérios acima. Consulte a [coleção instalável](https://web.dev/explore/progressive-web-apps) para obter mais informações sobre como criar um PWA. ## Como verificar se o seu PWA pode ser instalado @@ -42,7 +42,7 @@ Certifique-se de que seu aplicativo tenha um manifesto que atenda aos critérios Quando seu aplicativo atende aos requisitos mínimos de instalação, o Chrome dispara um `beforeinstallprompt` que você pode usar para solicitar que o usuário instale seu PWA. -{% Aside 'codelab' %} Saiba como tornar seu aplicativo instalável no Chrome com o codelab [Torná-lo instalável.](https://web.dev/codelab-make-installable/) {% endAside %} +{% Aside 'codelab' %} Saiba como tornar seu aplicativo instalável no Chrome com o codelab [Torná-lo instalável.](https://web.dev/articles/codelab-make-installable) {% endAside %} ### Em outros navegadores @@ -57,7 +57,7 @@ Outros navegadores têm critérios diferentes para instalação e para acionar o ## Recursos - [O código-fonte para auditoria **Manifesto do aplicativo da web não atende aos requisitos de instabilidade**](https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/audits/installable-manifest.js) -- [Adicionar um manifesto de aplicativo da web](https://web.dev/add-manifest/) -- [Descubra o que é necessário para ser instalável](https://web.dev/progressive-web-apps/) +- [Adicionar um manifesto de aplicativo da web](https://web.dev/articles/add-manifest) +- [Descubra o que é necessário para ser instalável](https://web.dev/explore/progressive-web-apps) - [Manifesto de aplicativo da web](https://developer.mozilla.org/docs/Web/Manifest) - [Não usa HTTPS](/pt/docs/lighthouse/pwa/is-on-https/) diff --git a/site/pt/docs/lighthouse/pwa/is-on-https/index.md b/site/pt/docs/lighthouse/pwa/is-on-https/index.md index 0b4fdc0c7..67c270309 100644 --- a/site/pt/docs/lighthouse/pwa/is-on-https/index.md +++ b/site/pt/docs/lighthouse/pwa/is-on-https/index.md @@ -10,9 +10,9 @@ updated: 2020-04-29 Todos os sites devem ser protegidos com HTTPS, mesmo aqueles que não lidam com dados confidenciais. O HTTPS evita que intrusos adulterem ou escutem passivamente as comunicações entre o seu site e seus usuários. -Uma página não pode ser qualificada como um [Progressive Web App (PWA)](https://web.dev/progressive-web-apps/) se não for executada em HTTPS; muitas tecnologias principais de PWA, como service workers, exigem HTTPS. +Uma página não pode ser qualificada como um [Progressive Web App (PWA)](https://web.dev/explore/progressive-web-apps) se não for executada em HTTPS; muitas tecnologias principais de PWA, como service workers, exigem HTTPS. -Para obter mais informações sobre por que todos os sites devem ser protegidos com HTTPS, consulte [Por que o HTTPS é importante](https://web.dev/why-https-matters/). +Para obter mais informações sobre por que todos os sites devem ser protegidos com HTTPS, consulte [Por que o HTTPS é importante](https://web.dev/articles/why-https-matters). ## Como a auditoria Lighthouse HTTPS falha diff --git a/site/pt/docs/lighthouse/pwa/load-fast-enough-for-pwa/index.md b/site/pt/docs/lighthouse/pwa/load-fast-enough-for-pwa/index.md index f3195ca8d..f2763a50a 100644 --- a/site/pt/docs/lighthouse/pwa/load-fast-enough-for-pwa/index.md +++ b/site/pt/docs/lighthouse/pwa/load-fast-enough-for-pwa/index.md @@ -19,7 +19,7 @@ O [Lighthouse](https://developers.google.com/web/tools/lighthouse/) marca págin Duas métricas principais afetam a forma como os usuários percebem o tempo de carregamento: - [First Meaningful Paint - FMP](/docs/lighthouse/performance/first-meaningful-paint/) (primeira renderização significativa), que mede quando o conteúdo principal da página parece visualmente completo -- [Time to Interactive - TTI](https://web.dev/tti/) (tempo até a interatividade), que mede quando a página é totalmente interativa +- [Time to Interactive - TTI](https://web.dev/articles/tti) (tempo até a interatividade), que mede quando a página é totalmente interativa Por exemplo, se uma página parecer visualmente completa depois de um segundo, mas o usuário não puder interagir com ela por 10 segundos, os usuários provavelmente perceberão o tempo de carregamento da página como sendo 10 segundos. diff --git a/site/pt/docs/lighthouse/pwa/maskable-icon-audit/index.md b/site/pt/docs/lighthouse/pwa/maskable-icon-audit/index.md index 02ce2e4b4..c460823ee 100644 --- a/site/pt/docs/lighthouse/pwa/maskable-icon-audit/index.md +++ b/site/pt/docs/lighthouse/pwa/maskable-icon-audit/index.md @@ -7,7 +7,7 @@ description: |2 date: 2020-05-06 --- -Os [ícones mascaráveis](https://web.dev/maskable-icon/) são um novo formato de ícone que garante que seu ícone PWA tenha uma ótima aparência em todos os dispositivos Android. Em dispositivos Android mais recentes, os ícones PWA que não seguem o formato de ícone mascarável recebem um fundo branco. Quando você usa um ícone mascarável, isso garante que o ícone ocupe todo o espaço que o Android fornece para ele. +Os [ícones mascaráveis](https://web.dev/articles/maskable-icon) são um novo formato de ícone que garante que seu ícone PWA tenha uma ótima aparência em todos os dispositivos Android. Em dispositivos Android mais recentes, os ícones PWA que não seguem o formato de ícone mascarável recebem um fundo branco. Quando você usa um ícone mascarável, isso garante que o ícone ocupe todo o espaço que o Android fornece para ele. ## Como a auditoria do ícone mascarável do Lighthouse falha @@ -29,7 +29,7 @@ Para passar na auditoria: 1. Use o [Editor Maskable.app](https://maskable.app/editor) para converter um ícone existente em um ícone mascarável. -2. Adicione a `purpose` a um dos objetos de `icons` [em seu manifesto de aplicativo da web](https://web.dev/add-manifest/) . Defina o valor de `purpose` como `maskable` ou `any maskable`. Veja [valores](https://developer.mozilla.org/docs/Web/Manifest/icons#Values). +2. Adicione a `purpose` a um dos objetos de `icons` [em seu manifesto de aplicativo da web](https://web.dev/articles/add-manifest) . Defina o valor de `purpose` como `maskable` ou `any maskable`. Veja [valores](https://developer.mozilla.org/docs/Web/Manifest/icons#Values). ```json/8 { @@ -47,12 +47,12 @@ Para passar na auditoria: } ``` -3. Use o Chrome DevTools para verificar se o ícone mascarável está sendo exibido corretamente. Consulte [Meus ícones atuais estão prontos?](https://web.dev/maskable-icon/#are-my-current-icons-ready) +3. Use o Chrome DevTools para verificar se o ícone mascarável está sendo exibido corretamente. Consulte [Meus ícones atuais estão prontos?](https://web.dev/articles/maskable-icon#are_my_current_icons_ready) ## Recursos - [O código-fonte para a auditoria **O manifesto não tem um ícone mascarável**](https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/audits/maskable-icon.js) -- [Suporte de ícone adaptável em PWAs com ícones mascaráveis](https://web.dev/maskable-icon/) +- [Suporte de ícone adaptável em PWAs com ícones mascaráveis](https://web.dev/articles/maskable-icon) - [Editor Maskable.app](https://maskable.app/editor) -- [Adicionar um manifesto de aplicativo da web](https://web.dev/add-manifest/) +- [Adicionar um manifesto de aplicativo da web](https://web.dev/articles/add-manifest) - [A propriedade `icons` no MDN](https://developer.mozilla.org/docs/Web/Manifest/icons) diff --git a/site/pt/docs/lighthouse/pwa/offline-start-url/index.md b/site/pt/docs/lighthouse/pwa/offline-start-url/index.md index 4abb1905f..2f3f5c9b7 100644 --- a/site/pt/docs/lighthouse/pwa/offline-start-url/index.md +++ b/site/pt/docs/lighthouse/pwa/offline-start-url/index.md @@ -10,7 +10,7 @@ date: 2019-05-04 updated: 2020-04-29 --- -O [manifesto](https://web.dev/add-manifest/) para um [Progressive Web App](https://web.dev/what-are-pwas/) (PWA) deve incluir um `start_url`, que indica a URL a ser carregada quando o usuário inicia o aplicativo. +O [manifesto](https://web.dev/articles/add-manifest) para um [Progressive Web App](https://web.dev/articles/what-are-pwas) (PWA) deve incluir um `start_url`, que indica a URL a ser carregada quando o usuário inicia o aplicativo. Se o navegador não receber uma [resposta HTTP 200](https://developer.mozilla.org/docs/Web/HTTP/Status#Successful_responses) ao acessar um aplicativo do `start_url`, o `start_url` não está correto ou a página não está acessível offline. Isso causa problemas para os usuários que instalaram o aplicativo em seus dispositivos. @@ -26,7 +26,7 @@ Se o navegador não receber uma [resposta HTTP 200](https://developer.mozilla.or {% Partial 'reliable/workbox.njk' %} -1. Se você ainda não tiver um, [adicione um manifesto de aplicativo da web](https://web.dev/add-manifest/). +1. Se você ainda não tiver um, [adicione um manifesto de aplicativo da web](https://web.dev/articles/add-manifest). 2. Verifique se `start_url` em seu manifesto está correto. 3. Adicione um service worker ao seu aplicativo. 4. Use o service worker para armazenar arquivos em cache localmente. @@ -36,6 +36,6 @@ Consulte a [página atual não responde com um guia 200 quando está off-line](/ ## Recursos -- [O que é confiabilidade de rede e como você a mede?](https://web.dev/network-connections-unreliable/) -- [Adicionar um manifesto de aplicativo da web](https://web.dev/add-manifest/) +- [O que é confiabilidade de rede e como você a mede?](https://web.dev/articles/network-connections-unreliable) +- [Adicionar um manifesto de aplicativo da web](https://web.dev/articles/add-manifest) - [Caixa de trabalho: seu kit de ferramentas de serviço de alto nível](/docs/workbox/) diff --git a/site/pt/docs/lighthouse/pwa/service-worker/index.md b/site/pt/docs/lighthouse/pwa/service-worker/index.md index c6bbfe2fc..71f0cc8f2 100644 --- a/site/pt/docs/lighthouse/pwa/service-worker/index.md +++ b/site/pt/docs/lighthouse/pwa/service-worker/index.md @@ -10,13 +10,13 @@ date: 2019-05-04 updated: 2020-06-10 --- -Registrar um [service worker](https://web.dev/service-workers-cache-storage/) é a primeira etapa para habilitar os principais recursos do [Progressive Web App (PWA)](https://web.dev/progressive-web-apps/): +Registrar um [service worker](https://web.dev/articles/service-workers-cache-storage) é a primeira etapa para habilitar os principais recursos do [Progressive Web App (PWA)](https://web.dev/explore/progressive-web-apps): - Funciona offline - Suporta notificações push - Pode ser instalado no dispositivo -Saiba mais em [Service workers](https://web.dev/service-workers-cache-storage/) e na postagem da API Cache Storage. +Saiba mais em [Service workers](https://web.dev/articles/service-workers-cache-storage) e na postagem da API Cache Storage. ## Compatibilidade do navegador @@ -38,15 +38,15 @@ O Lighthouse verifica se o [protocolo de depuração remota do Chrome](https://g O registro de um service worker envolve apenas algumas linhas de código, mas o único motivo pelo qual você utilizaria um ervice worker é para possibilitar a implementação de um dos recursos do PWA descritos acima. Na verdade, a implementação desses recursos requer mais trabalho: -- Para aprender como armazenar arquivos em cache para uso offline, consulte a publicação [O que é confiabilidade de rede e como você a mede?](https://web.dev/network-connections-unreliable/). -- Para saber como tornar seu aplicativo instalável, consulte o codelab [Torne-o instalável.](https://web.dev/codelab-make-installable/) +- Para aprender como armazenar arquivos em cache para uso offline, consulte a publicação [O que é confiabilidade de rede e como você a mede?](https://web.dev/articles/network-connections-unreliable). +- Para saber como tornar seu aplicativo instalável, consulte o codelab [Torne-o instalável.](https://web.dev/articles/codelab-make-installable) - Para saber como habilitar notificações push, consulte [Adicionando notificações push a um aplicativo da web do Google](https://codelabs.developers.google.com/codelabs/push-notifications) . ## Recursos - [Código fonte para a auditoria **Não registra um service worker que controla a página e `start_url`**](https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/audits/service-worker.js) - [Service workers: uma introdução](https://developers.google.com/web/fundamentals/primers/service-workers) -- [Service workers e a API Cache Storage](https://web.dev/service-workers-cache-storage/) -- [O que é confiabilidade de rede e como você a mede?](https://web.dev/network-connections-unreliable/) -- [Torne-o instalável](https://web.dev/codelab-make-installable/) +- [Service workers e a API Cache Storage](https://web.dev/articles/service-workers-cache-storage) +- [O que é confiabilidade de rede e como você a mede?](https://web.dev/articles/network-connections-unreliable) +- [Torne-o instalável](https://web.dev/articles/codelab-make-installable) - [Adicionando notificações push a um aplicativo da web](https://codelabs.developers.google.com/codelabs/push-notifications) diff --git a/site/pt/docs/lighthouse/pwa/splash-screen/index.md b/site/pt/docs/lighthouse/pwa/splash-screen/index.md index 2c4a16e0d..8a145f0a3 100644 --- a/site/pt/docs/lighthouse/pwa/splash-screen/index.md +++ b/site/pt/docs/lighthouse/pwa/splash-screen/index.md @@ -8,7 +8,7 @@ date: 2019-05-04 updated: 2019-09-19 --- -Uma tela inicial personalizada torna seu [Progressive Web App (PWA)](https://web.dev/progressive-web-apps/) mais parecido com um aplicativo criado para esse dispositivo. Por padrão, quando um usuário inicia seu PWA a partir da tela de início, o Android exibe uma tela branca até que o PWA esteja pronto. O usuário pode ver essa tela em branco por até 200 ms. Ao configurar uma tela inicial personalizada, você pode mostrar aos usuários uma cor de fundo personalizada e o ícone do seu PWA, proporcionando uma experiência de marca e envolvente. +Uma tela inicial personalizada torna seu [Progressive Web App (PWA)](https://web.dev/explore/progressive-web-apps) mais parecido com um aplicativo criado para esse dispositivo. Por padrão, quando um usuário inicia seu PWA a partir da tela de início, o Android exibe uma tela branca até que o PWA esteja pronto. O usuário pode ver essa tela em branco por até 200 ms. Ao configurar uma tela inicial personalizada, você pode mostrar aos usuários uma cor de fundo personalizada e o ícone do seu PWA, proporcionando uma experiência de marca e envolvente. ## Como a auditoria da tela inicial do Lighthouse falha @@ -20,7 +20,7 @@ Uma tela inicial personalizada torna seu [Progressive Web App (PWA)](https://web ## Como criar uma tela inicial personalizada -O Chrome para Android mostra automaticamente sua tela inicial personalizada, desde que você atenda aos seguintes requisitos no [manifesto do seu aplicativo da web:](https://web.dev/add-manifest/) +O Chrome para Android mostra automaticamente sua tela inicial personalizada, desde que você atenda aos seguintes requisitos no [manifesto do seu aplicativo da web:](https://web.dev/articles/add-manifest) - A propriedade `name` é definida como o nome do seu PWA. - A propriedade `background_color` é definida como um valor de cor CSS válido. diff --git a/site/pt/docs/lighthouse/pwa/themed-omnibox/index.md b/site/pt/docs/lighthouse/pwa/themed-omnibox/index.md index ed99738df..7ba8733fa 100644 --- a/site/pt/docs/lighthouse/pwa/themed-omnibox/index.md +++ b/site/pt/docs/lighthouse/pwa/themed-omnibox/index.md @@ -6,7 +6,7 @@ date: 2019-05-04 updated: 2020-06-17 --- -Aplicar um tema na barra de endereço do navegador para corresponder às cores da marca de seu [Progressive Web App (PWA)](https://web.dev/progressive-web-apps/) fornece uma experiência de usuário mais envolvente. +Aplicar um tema na barra de endereço do navegador para corresponder às cores da marca de seu [Progressive Web App (PWA)](https://web.dev/explore/progressive-web-apps) fornece uma experiência de usuário mais envolvente. ## Compatibilidade dos navegadores @@ -18,7 +18,7 @@ O [Lighthouse](https://developers.google.com/web/tools/lighthouse/) marca págin <figure> {% Img src="image/tcFciHGuF3MxnTr1y5ue01OGLBn2/YadFSuw8denjl1hhnvFs.png", alt="Auditoria Lighthouse mostrando barra de endereço que não tem o tema das cores da página", width="800", height="98" %}</figure> -A auditoria falha se o Lighthouse não encontrar uma meta tag `theme-color` no HTML da página e uma propriedade `theme_color` no [manifesto web app](https://web.dev/add-manifest/). +A auditoria falha se o Lighthouse não encontrar uma meta tag `theme-color` no HTML da página e uma propriedade `theme_color` no [manifesto web app](https://web.dev/articles/add-manifest). Observe que o Lighthouse não testa se os valores são valores de cor CSS válidos. @@ -45,7 +45,7 @@ Saiba mais sobre a meta tag `theme-color` no artigo <a href="https://developers. ### Passo 2: adicione a propriedade `theme_color` ao seu manifesto web app -A propriedade `theme_color` em seu manifesto web app garante que a barra de endereço seja marcada quando um usuário iniciar seu PWA a partir da tela inicial. Ao contrário da meta tag `theme-color` do tema, você só precisa defini-la uma vez, no [manifesto](https://web.dev/add-manifest/). Defina a propriedade para qualquer valor de cor CSS válido: +A propriedade `theme_color` em seu manifesto web app garante que a barra de endereço seja marcada quando um usuário iniciar seu PWA a partir da tela inicial. Ao contrário da meta tag `theme-color` do tema, você só precisa defini-la uma vez, no [manifesto](https://web.dev/articles/add-manifest). Defina a propriedade para qualquer valor de cor CSS válido: ```html/1 { @@ -59,5 +59,5 @@ O navegador definirá a cor da barra de endereço de cada página do seu aplicat ## Recursos - [Código fonte para a auditoria**Não define uma cor de tema para a barra de endereço**](https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/audits/themed-omnibox.js) -- [Adicionar um manifesto web app](https://web.dev/add-manifest/) +- [Adicionar um manifesto web app](https://web.dev/articles/add-manifest) - [Suporte a <code>theme-color</code> no Chrome 39 para Android](https://developers.google.com/web/updates/2014/11/Support-for-theme-color-in-Chrome-39-for-Android) diff --git a/site/pt/docs/privacy-sandbox/attribution-reporting/index.md b/site/pt/docs/privacy-sandbox/attribution-reporting/index.md index 6a2b2d3c1..391b7500c 100644 --- a/site/pt/docs/privacy-sandbox/attribution-reporting/index.md +++ b/site/pt/docs/privacy-sandbox/attribution-reporting/index.md @@ -48,7 +48,7 @@ Hoje, a medição de conversão de anúncios geralmente depende de [cookies de t A API Attribution Reporting permite a medição de dois eventos vinculados: um evento no site de um editor, como um usuário visualizando ou clicando num anúncio, com uma conversão subsequente no site de um anunciante. -Esta API suporta a medição de atribuição de conversão do tipo click-through (disponível na primeira implementação desta API, atualmente em [ensaio de origem](https://web.dev/conversion-measurement/#browser-support)) e medição de atribuição do tipo view-through ([veja a explicação pública](https://github.com/WICG/conversion-measurement-api/blob/main/event_attribution_reporting.md)). +Esta API suporta a medição de atribuição de conversão do tipo click-through (disponível na primeira implementação desta API, atualmente em [ensaio de origem](/docs/privacy-sandbox/attribution-reporting/#browser-support)) e medição de atribuição do tipo view-through ([veja a explicação pública](https://github.com/WICG/conversion-measurement-api/blob/main/event_attribution_reporting.md)). A API oferece dois tipos de relatórios de atribuição que podem ser usados para diferentes casos de uso: @@ -67,8 +67,8 @@ A API oferece dois tipos de relatórios de atribuição que podem ser usados par - [Introdução aos relatórios de atribuição (mensuração de conversão)](/docs/privacy-sandbox/attribution-reporting-introduction) - [Explicações técnicas da API](https://github.com/WICG/conversion-measurement-api/) -- (⚠️ obsoleto) [Uma forma de medir as conversões de anúncios com mais privacidade](https://web.dev/conversion-measurement/): visão geral da primeira iteração desta API para desenvolvedores web +- (⚠️ obsoleto) [Uma forma de medir as conversões de anúncios com mais privacidade](/docs/privacy-sandbox/attribution-reporting/): visão geral da primeira iteração desta API para desenvolvedores web - (⚠️ obsoleto) [Uma forma de medir as conversões de anúncios com mais privacidade](https://www.youtube.com/watch?v=jcDfOoWwZcM) - Vídeo: demonstração da primeira iteração desta API (apenas cliques) -- (⚠️ obsoleto) [Usando a API Event Conversion Measurement](https://web.dev/using-conversion-measurement/): como experimentar a primeira iteração desta API para desenvolvedores web +- (⚠️ obsoleto) [Usando a API Event Conversion Measurement](/docs/privacy-sandbox/attribution-reporting/): como experimentar a primeira iteração desta API para desenvolvedores web - [Explorando a Privacy Sandbox](https://web.dev/digging-into-the-privacy-sandbox) - [Depure a API com Chrome DevTools](/blog/new-in-devtools-93/#attribution-reporting) diff --git a/site/pt/docs/privacy-sandbox/first-party-sets/index.md b/site/pt/docs/privacy-sandbox/first-party-sets/index.md index 142f297e4..bd9017068 100644 --- a/site/pt/docs/privacy-sandbox/first-party-sets/index.md +++ b/site/pt/docs/privacy-sandbox/first-party-sets/index.md @@ -13,7 +13,7 @@ authors: ## Status de implementação -- [Em ensaio de origem](https://web.dev/origin-trials/) no Chrome 89 a 93. +- [Em ensaio de origem](/docs/web-platform/origin-trials/) no Chrome 89 a 93. - [Cadastre-se para o ensaio de origem](/origintrials/#/view_trial/988540118207823873). - [Status da plataforma Chrome](https://chromestatus.com/feature/5640066519007232). - [Projetos Chromium](https://www.chromium.org/updates/first-party-sets) . diff --git a/site/pt/docs/privacy-sandbox/floc/index.md b/site/pt/docs/privacy-sandbox/floc/index.md index 548cee3ef..c6d73a5c8 100644 --- a/site/pt/docs/privacy-sandbox/floc/index.md +++ b/site/pt/docs/privacy-sandbox/floc/index.md @@ -39,7 +39,7 @@ Posteriormente, a plataforma de anúncios pode usar esses dados para selecionar ## Como funciona o FLoC? -[O que é FLoC?](https://web.dev/floc/#how-does-floc-work) fornece uma explicação simples e passo a passo de como funciona o FloC. +[O que é FLoC?](https://web.dev/articles/floc#how_does_floc_work) fornece uma explicação simples e passo a passo de como funciona o FloC. O diagrama abaixo mostra um exemplo das diferentes funções na seleção e distribuição de um anúncio relevante usando FLoC. diff --git a/site/pt/docs/privacy-sandbox/glossary/index.md b/site/pt/docs/privacy-sandbox/glossary/index.md index 931ab0dc5..4d287abc5 100644 --- a/site/pt/docs/privacy-sandbox/glossary/index.md +++ b/site/pt/docs/privacy-sandbox/glossary/index.md @@ -124,7 +124,7 @@ A origem de uma solicitação, incluindo o esquema e o nome do servidor, mas nen ## Ensaio de origem {: #origin-trial } -Os ensaios de origem fornecem acesso a um recurso novo ou experimental, para possibilitar a construção de funcionalidades que os usuários poderão experimentar por um tempo limitado antes que o recurso seja disponibilizado para todos. Quando o Chrome oferece um ensaio de origem para um recurso, uma [origem](#origin) pode ser registrada para o ensaio e irá habilitar o recurso para todos os usuários daquela origem, sem exigir que os usuários precisem ativar/desativar quaisquer flags ou mudar para uma versão alternativa do Chrome (embora possam precisar fazer um upgrade). Os ensaios de origem permitem que os desenvolvedores criem demos e protótipos usando novos recursos. Os ensaios também ajudam os engenheiros do Chrome a entender como os novos recursos são usados e como eles podem interagir com outras tecnologias web. Saiba mais: [Introdução aos ensaios de origem do Chrome](https://web.dev/origin-trials/). +Os ensaios de origem fornecem acesso a um recurso novo ou experimental, para possibilitar a construção de funcionalidades que os usuários poderão experimentar por um tempo limitado antes que o recurso seja disponibilizado para todos. Quando o Chrome oferece um ensaio de origem para um recurso, uma [origem](#origin) pode ser registrada para o ensaio e irá habilitar o recurso para todos os usuários daquela origem, sem exigir que os usuários precisem ativar/desativar quaisquer flags ou mudar para uma versão alternativa do Chrome (embora possam precisar fazer um upgrade). Os ensaios de origem permitem que os desenvolvedores criem demos e protótipos usando novos recursos. Os ensaios também ajudam os engenheiros do Chrome a entender como os novos recursos são usados e como eles podem interagir com outras tecnologias web. Saiba mais: [Introdução aos ensaios de origem do Chrome](/docs/web-platform/origin-trials/). ## Superfície passiva {: #passive-surface } diff --git a/site/pt/docs/privacy-sandbox/overview/index.md b/site/pt/docs/privacy-sandbox/overview/index.md index 69e354dba..b44cdc0b1 100644 --- a/site/pt/docs/privacy-sandbox/overview/index.md +++ b/site/pt/docs/privacy-sandbox/overview/index.md @@ -35,7 +35,7 @@ As principais propostas desenvolvidas pela equipe do Chrome estão listadas abai ### Proteções de fontes primárias -- [**Alterações nos cookies SameSite**](https://web.dev/samesite-cookies-explained/): protege sites marcando explicitamente seus cookies cross-site. +- [**Alterações nos cookies SameSite**](https://web.dev/articles/samesite-cookies-explained): protege sites marcando explicitamente seus cookies cross-site. - [**First-Party Sets**](/docs/privacy-sandbox/first-party-sets): permitem que nomes de domínio relacionados pertencentes à mesma entidade se declarem pertencentes à mesma fonte primária. ### Detecção de fraudes @@ -45,7 +45,7 @@ As principais propostas desenvolvidas pela equipe do Chrome estão listadas abai ### Limitação da coleta de dados - [**Privacy Budget**](https://www.youtube.com/watch?v=0STgfjSA6T8): permite que os sites obtenham informações sobre o navegador ou dispositivo de um usuário, mas permite que o navegador defina uma cota na quantidade total de informações que um site pode acessar, de modo que o usuário não possa ser identificado. -- [**User-Agent Client Hints**](https://web.dev/user-agent-client-hints/): A string [User-Agent](https://developer.mozilla.org/docs/Web/HTTP/Headers/User-Agent) (UA) é uma [significativa superfície de](https://w3c.github.io/fingerprinting-guidance/#passive)[fingerprinting](https://w3c.github.io/fingerprinting-guidance/#passive) passiva, além de ser difícil de processar. Client Hints (dicas do cliente) permitem que os desenvolvedores solicitem ativamente apenas as informações de que precisam sobre o dispositivo do usuário ou condições, em vez de precisar processar esses dados na string User-Agent. +- [**User-Agent Client Hints**](https://web.dev/articles/user-agent-client-hints): A string [User-Agent](https://developer.mozilla.org/docs/Web/HTTP/Headers/User-Agent) (UA) é uma [significativa superfície de](https://w3c.github.io/fingerprinting-guidance/#passive)[fingerprinting](https://w3c.github.io/fingerprinting-guidance/#passive) passiva, além de ser difícil de processar. Client Hints (dicas do cliente) permitem que os desenvolvedores solicitem ativamente apenas as informações de que precisam sobre o dispositivo do usuário ou condições, em vez de precisar processar esses dados na string User-Agent. - [**Gnatcatcher**](https://github.com/bslassey/ip-blindness): Limita a capacidade de identificar usuários individuais acessando seus endereços IP. A proposta tem duas partes: [**Willful IP Blindness**](https://github.com/bslassey/ip-blindness/blob/master/willful_ip_blindness.md) fornece uma maneira para os sites informarem aos navegadores que eles não estão conectando endereços IP aos usuários e [**Near-path NAT**](https://github.com/bslassey/ip-blindness/blob/master/near_path_nat.md) permite que grupos de usuários enviem seu tráfego através do mesmo servidor de privatização, efetivamente ocultando seus endereços IP de um host. O Gnatcatcher também garante que os sites que requerem acesso a endereços IP para fins legítimos, como prevenção de abusos, possam fazê-lo, sujeito a certificação e auditoria. ### Identidade @@ -90,10 +90,10 @@ As explicações da proposta da API precisam de feedback, em particular para sug ### Artigos e vídeos para desenvolvedores web - [Explorando a Privacy Sandbox](https://web.dev/digging-into-the-privacy-sandbox) -- [Cookies SameSite explicados](https://web.dev/samesite-cookies-explained/) +- [Cookies SameSite explicados](https://web.dev/articles/samesite-cookies-explained) - [Primeiros passos com os Trust Tokens](https://web.dev/trust-tokens) -- [Uma forma de medir conversões de anúncios com mais privacidade](https://web.dev/conversion-measurement/) -- [O que é FLoC?](https://web.dev/floc/) +- [Uma forma de medir conversões de anúncios com mais privacidade](/docs/privacy-sandbox/attribution-reporting/) +- [O que é FLoC?](https://web.dev/articles/floc) - [Introdução ao Privacy Budget](https://www.youtube.com/watch?v=0STgfjSA6T8) ### Princípios e conceitos por trás das propostas diff --git a/site/pt/docs/privacy-sandbox/status/index.md b/site/pt/docs/privacy-sandbox/status/index.md index cdc00bd40..dfea7278c 100644 --- a/site/pt/docs/privacy-sandbox/status/index.md +++ b/site/pt/docs/privacy-sandbox/status/index.md @@ -15,7 +15,7 @@ authors: *Anteriormente conhecido como Conversion Measurement (mensuração de conversão).* -- [Ensaio de origem atual](https://web.dev/origin-trials/): do Chrome 86, [agora estendido](https://groups.google.com/u/1/a/chromium.org/g/attribution-reporting-api-dev/c/ZKf9T8sRqAM) ao Chrome 93. +- [Ensaio de origem atual](/docs/web-platform/origin-trials/): do Chrome 86, [agora estendido](https://groups.google.com/u/1/a/chromium.org/g/attribution-reporting-api-dev/c/ZKf9T8sRqAM) ao Chrome 93. - [Cadastre-se para o ensaio de origem](/origintrials/#/view_trial/3411476717733150721). - [Demo](https://goo.gle/demo-event-level-conversion-measurement-api). - [Status da plataforma Chrome](https://www.chromestatus.com/features/6412002824028160). @@ -31,25 +31,25 @@ Veja o [status](/docs/privacy-sandbox/attribution-reporting-introduction/#status - [Relatórios de atribuição (medição de conversão)](/docs/privacy-sandbox/attribution-reporting) - [Introdução aos relatórios de atribuição (mensuração de conversão)](/docs/privacy-sandbox/attribution-reporting-introduction) - [Explicações técnicas da API](https://github.com/WICG/conversion-measurement-api/) -- (⚠️ obsoleto) [Uma forma de medir as conversões de anúncios com mais privacidade](https://web.dev/conversion-measurement/): visão geral da primeira iteração desta API para desenvolvedores web +- (⚠️ obsoleto) [Uma forma de medir as conversões de anúncios com mais privacidade](/docs/privacy-sandbox/attribution-reporting/): visão geral da primeira iteração desta API para desenvolvedores web - (⚠️ obsoleto) [Uma forma de medir as conversões de anúncios com mais privacidade](https://www.youtube.com/watch?v=jcDfOoWwZcM) - Vídeo: demonstração da primeira iteração desta API (apenas cliques) -- (⚠️ obsoleto) [Usando a API Event Conversion Measurement](https://web.dev/using-conversion-measurement/): como experimentar a primeira iteração desta API para desenvolvedores web +- (⚠️ obsoleto) [Usando a API Event Conversion Measurement](/docs/privacy-sandbox/attribution-reporting/): como experimentar a primeira iteração desta API para desenvolvedores web - [Explorando a Privacy Sandbox](https://web.dev/digging-into-the-privacy-sandbox) ## Trust Tokens -- [Ensaio de origem atual](https://web.dev/origin-trials/): do Chrome 84, [agora estendido](https://groups.google.com/a/chromium.org/g/blink-dev/c/-W90wVkS0Ks/m/Jfh5-ZWpAQAJ) ao Chrome 94. +- [Ensaio de origem atual](/docs/web-platform/origin-trials/): do Chrome 84, [agora estendido](https://groups.google.com/a/chromium.org/g/blink-dev/c/-W90wVkS0Ks/m/Jfh5-ZWpAQAJ) ao Chrome 94. - [Cadastre-se para o ensaio de origem](/origintrials/#/view_trial/2479231594867458049). - [Demo](https://trust-token-demo.glitch.me/). - [Status da plataforma Chrome](https://www.chromestatus.com/feature/5078049450098688). - [Status do Blink](https://groups.google.com/a/chromium.org/g/blink-dev/search?q=trust%tokens) . - [GitHub](https://github.com/WICG/trust-token-api): veja os [issues](https://github.com/WICG/trust-token-api/issues) para perguntas e discussões sobre a API. - [Integração do Chrome DevTools](https://developers.google.com/web/updates/2021/01/devtools?utm_source=devtools#trust-token). -- Saiba mais: [Primeiros passos com os Trust Tokens](https://web.dev/trust-tokens/) +- Saiba mais: [Primeiros passos com os Trust Tokens](https://web.dev/articles/trust-tokens) ## Conjuntos primários -- [Ensaio de origem atual](https://web.dev/origin-trials/): Chrome 89 a 93. +- [Ensaio de origem atual](/docs/web-platform/origin-trials/): Chrome 89 a 93. - [Cadastre-se para o ensaio de origem](/origintrials/#/view_trial/988540118207823873). - [Status da plataforma Chrome](https://chromestatus.com/feature/5640066519007232). - [Status do Blink](https://groups.google.com/a/chromium.org/g/blink-dev/search?q=first-party%20sets) . @@ -64,7 +64,7 @@ Veja o [status](/docs/privacy-sandbox/attribution-reporting-introduction/#status - [A proposta da API](https://github.com/WICG/floc) está em discussão com o [WICG](https://www.w3.org/community/wicg/) e grupos de interesse. - [GitHub](https://github.com/WICG/floc): veja os [issues](https://github.com/WICG/floc/issues) para perguntas e discussões sobre a API. - [Status da plataforma Chrome](https://www.chromestatus.com/features/5710139774468096). -- Saiba mais: [O que é FLoC?](https://web.dev/floc/) +- Saiba mais: [O que é FLoC?](https://web.dev/articles/floc) ## FLEDGE @@ -91,7 +91,7 @@ Descendente do [TURTLEDOVE](https://github.com/WICG/turtledove) . ### Ensaios de origem -- [Introdução aos ensaios de origem do Chrome](https://web.dev/origin-trials/) +- [Introdução aos ensaios de origem do Chrome](/docs/web-platform/origin-trials/) - [O que são ensaios de origem de terceiros?](https://web.dev/third-party-origin-trials) - [Solução de problemas para ensaios de origem do Chrome](/blog/origin-trial-troubleshooting/) - [Guia de ensaios de origem para desenvolvedores web](https://github.com/GoogleChrome/OriginTrials/blob/gh-pages/developer-guide.md) diff --git a/site/pt/docs/privacy-sandbox/trust-tokens/index.md b/site/pt/docs/privacy-sandbox/trust-tokens/index.md index fe75fa14d..3e7bb828b 100644 --- a/site/pt/docs/privacy-sandbox/trust-tokens/index.md +++ b/site/pt/docs/privacy-sandbox/trust-tokens/index.md @@ -11,7 +11,7 @@ authors: ## Status de implementação -- [Em ensaio de origem](https://web.dev/origin-trials/): Chrome 84 a 94. +- [Em ensaio de origem](/docs/web-platform/origin-trials/): Chrome 84 a 94. - [Cadastre-se para o ensaio](/origintrials/#/view_trial/2479231594867458049). - [Demo](https://trust-token-demo.glitch.me/). - [Integração do Chrome DevTools](https://developers.google.com/web/updates/2021/01/devtools?utm_source=devtools#trust-token). @@ -62,7 +62,7 @@ Neste exemplo, um site de editor deseja verificar se um usuário é um ser human 12. O site do editor exibe o anúncio. 13. Uma impressão de visualização do anúncio é contada. -{% Aside %} Para mais detalhes sobre as chamadas de JavaScript neste exemplo, veja o [Exemplo de uso da API](https://web.dev/trust-tokens/#sample-api-usage). {% endAside %} +{% Aside %} Para mais detalhes sobre as chamadas de JavaScript neste exemplo, veja o [Exemplo de uso da API](https://web.dev/articles/trust-tokens#sample_api_usage). {% endAside %} --- @@ -78,6 +78,6 @@ Neste exemplo, um site de editor deseja verificar se um usuário é um ser human ## Saiba mais - [Explicação técnica do Trust Token](https://github.com/dvorak42/trust-token-api) -- [Getting started with Trust Tokens](https://web.dev/trust-tokens/): an overview for web developers +- [Getting started with Trust Tokens](https://web.dev/articles/trust-tokens): an overview for web developers - [Introdução aos ensaios de origem do Chrome](https://web.dev/origin-trials) - [Explorando a Privacy Sandbox](https://web.dev/digging-into-the-privacy-sandbox) diff --git a/site/ru/blog/chrome-ux-report-looker-studio-dashboard/index.md b/site/ru/blog/chrome-ux-report-looker-studio-dashboard/index.md index 5ab871a2b..db5d7a856 100644 --- a/site/ru/blog/chrome-ux-report-looker-studio-dashboard/index.md +++ b/site/ru/blog/chrome-ux-report-looker-studio-dashboard/index.md @@ -70,7 +70,7 @@ https://developer.chrome.com/chrome-ux-report-looker-studio-dashboard/ ### Обзор Core Web Vitals -На первой странице представлен месячный обзор метрик производительности [Core Web Vitals](https://web.dev/vitals/). Это самые важные показатели UX, на которых Google рекомендует сосредоточиться. +На первой странице представлен месячный обзор метрик производительности [Core Web Vitals](https://web.dev/articles/vitals). Это самые важные показатели UX, на которых Google рекомендует сосредоточиться. {% Img src="image/admin/h8iCTgvmG4DS2zScvatc.png", alt="Обзор Core Web Vitals на панели CrUX Dashboard", width="800", height="906" %} @@ -88,7 +88,7 @@ https://developer.chrome.com/chrome-ux-report-looker-studio-dashboard/ На каждой странице находится фильтр **Device (Устройство)**, который можно использовать для ограничения форм-факторов, включенных в данные о взаимодействии с пользователями. Например, можно детализировать данные для мобильного сектора. Этот параметр сохраняется на всех страницах. -Основными визуализациями на этих страницах являются ежемесячные распределения пользовательских впечатлений, классифицированные как Good (Хорошо), Needs Improvement (Требует улучшения) и Poor (Плохо). На гистограммах с цветовой кодировкой указан процентный диапазон для каждой из категорий. Например, на скриншоте выше видно, что процент «хорошей» метрики [LCP (Скорость загрузки основного контента)](https://web.dev/lcp/#what-is-a-good-lcp-score) колеблется и немного ухудшается в последние месяцы. +Основными визуализациями на этих страницах являются ежемесячные распределения пользовательских впечатлений, классифицированные как Good (Хорошо), Needs Improvement (Требует улучшения) и Poor (Плохо). На гистограммах с цветовой кодировкой указан процентный диапазон для каждой из категорий. Например, на скриншоте выше видно, что процент «хорошей» метрики [LCP (Скорость загрузки основного контента)](https://web.dev/articles/lcp#what_is_a_good_lcp_score) колеблется и немного ухудшается в последние месяцы. Процентное соотношение «хороших» и «плохих» пользовательских впечатлений за последний месяц показано над гистограммой вместе с индикатором процентного различия по сравнению с предыдущим месяцем. Для этого источника «хорошие» впечатления от LCP упали на 3,2% до 56,04% по сравнению с предыдущим месяцем. @@ -116,7 +116,7 @@ https://developer.chrome.com/chrome-ux-report-looker-studio-dashboard/ {% Aside 'key-term' %} Эффективные типы подключения считаются *эффективными*, поскольку они основаны на измерениях пропускной способности на устройствах пользователей и не подразумевают использование какой-либо конкретной технологии. Например, пользователь настольного компьютера с быстрым Wi-Fi может быть обозначен как 4G, а более медленное мобильное соединение может быть обозначено как 2G. {% endAside %} -Распределения для этих факторов рассчитываются с использованием сегментов данных гистограммы [FCP (Первой отрисовки контента)](https://web.dev/fcp/). +Распределения для этих факторов рассчитываются с использованием сегментов данных гистограммы [FCP (Первой отрисовки контента)](https://web.dev/articles/fcp). ## Часто задаваемые вопросы diff --git a/site/ru/blog/new-in-devtools-101/index.md b/site/ru/blog/new-in-devtools-101/index.md index b5c724497..70db9c7f0 100644 --- a/site/ru/blog/new-in-devtools-101/index.md +++ b/site/ru/blog/new-in-devtools-101/index.md @@ -112,8 +112,8 @@ DevTools теперь правильно оценивает и отобража <!-- These are some noteworthy fixes in this release: --> Вот несколько заслуживающих внимания исправлений в этом выпуске: -<!-- - The [Back/forward cache](/blog/new-in-devtools-98/#bfcache) now displays the extension ID which blocked [bfcache](https://web.dev/bfcache/) when present.( [1284548](https://crbug.com/1284548)) --> -- [Возвратный кэш](/blog/new-in-devtools-98/#bfcache) теперь показывает ID расширения, которое блокирует [bfcache](https://web.dev/bfcache/) при наличии. ([1284548](https://crbug.com/1284548)) +<!-- - The [Back/forward cache](/blog/new-in-devtools-98/#bfcache) now displays the extension ID which blocked [bfcache](https://web.dev/articles/bfcache) when present.( [1284548](https://crbug.com/1284548)) --> +- [Возвратный кэш](/blog/new-in-devtools-98/#bfcache) теперь показывает ID расширения, которое блокирует [bfcache](https://web.dev/articles/bfcache) при наличии. ([1284548](https://crbug.com/1284548)) <!-- - Fixed autocompletion support for array-like objects, CSS class names, `map.get` and HTML tags. ([1297101](https://crbug.com/1297101), [1297491](https://crbug.com/1297491), [1293807](https://crbug.com/1293807), [1296983](https://crbug.com/1296983)) --> - Исправлена поддержка автодополнения объектов типа массив, имён CSS-классов, `map.get` и HTML-тегов. ([1297101](https://crbug.com/1297101), [1297491](https://crbug.com/1297491), [1293807](https://crbug.com/1293807), [1296983](https://crbug.com/1296983)) <!-- - Fixed incorrect highlights when double-clicking on words and undoing autocomplete. ([1298437](https://crbug.com/1298437), [1298667](https://crbug.com/1298667)) --> @@ -123,7 +123,7 @@ DevTools теперь правильно оценивает и отобража <!-- - Re-enable support for using **Alt** (Options) key for multi selection in the **Sources** panel. ([1304070](https://crbug.com/1304070)) --> - Вновь включена поддержка клавиш **Alt** (Options) для множественного выбора во вкладке **Источники** (Sources). ([1304070](https://crbug.com/1304070)) - + <!-- ## [Experimental] New timespan and snapshot mode in the Lighthouse panel {: #lighthouse } --> ## [Эксперимент] Новые режимы временного промежутка и сводки во вкладке Lighthouse {: #lighthouse } @@ -135,8 +135,8 @@ DevTools теперь правильно оценивает и отобража <!-- Apart from the existing **navigation** mode, the **Lighthouse** panel now support two more modes on measuring user flows - **timespan** and **snapshot**. --> Помимо существующего режима **навигации**, вкладка **Lighthouse** теперь поддерживает еще два режима измерения пользовательских потоков — **timespan** и **сводка**. -<!-- For example, you can use the **timespan** reports to analyze user interactions. Open this [demo](https://coffee-cart.netlify.app/) page. Select the **Timespan** mode and click on **Start timespan**. On the page, click on a coffee and end the timespan. Read the report to find out the [Total Blocking Time](https://web.dev/tbt/) and [Cumulative Layout Shift](https://web.dev/cls/) that were caused by the interaction. --> -Например, вы можете использовать отчёты в режиме **timespan** для анализа пользовательских действий. Откройте эту [демо-страницу](https://coffee-cart.netlify.app/). Выберите режим **Timespan** и нажмите **Start timespan**. Кликните на кофе на странице и завершите запись. Прочитайте отчёт, чтобы узнать [Total Blocking Time](https://web.dev/tbt/) и [Cumulative Layout Shift](https://web.dev/cls/) обусловленные взаимодействием. +<!-- For example, you can use the **timespan** reports to analyze user interactions. Open this [demo](https://coffee-cart.netlify.app/) page. Select the **Timespan** mode and click on **Start timespan**. On the page, click on a coffee and end the timespan. Read the report to find out the [Total Blocking Time](https://web.dev/articles/tbt) and [Cumulative Layout Shift](https://web.dev/articles/cls) that were caused by the interaction. --> +Например, вы можете использовать отчёты в режиме **timespan** для анализа пользовательских действий. Откройте эту [демо-страницу](https://coffee-cart.netlify.app/). Выберите режим **Timespan** и нажмите **Start timespan**. Кликните на кофе на странице и завершите запись. Прочитайте отчёт, чтобы узнать [Total Blocking Time](https://web.dev/articles/tbt) и [Cumulative Layout Shift](https://web.dev/articles/cls) обусловленные взаимодействием. <!-- Each mode has its own unique use cases, benefits, and limitations. Please refer to the [Lighthouse documentation](https://github.com/GoogleChrome/lighthouse/blob/master/docs/user-flows.md) for more information. --> Каждый режим имеет свои уникальные сценарии использования, преимущества и ограничения. Пожалуйста, обратитесь к [документации по Lighthouse](https://github.com/GoogleChrome/lighthouse/blob/master/docs/user-flows.md) для получения дополнительной информации. @@ -148,4 +148,4 @@ DevTools теперь правильно оценивает и отобража Задача в трекере Chromium: [772558](https://crbug.com/772558) {% Partial 'devtools/reach-out.md' %} -{% Partial 'devtools/whats-new.md' %} \ No newline at end of file +{% Partial 'devtools/whats-new.md' %} diff --git a/site/ru/blog/new-in-devtools-102/index.md b/site/ru/blog/new-in-devtools-102/index.md index 9ade767e3..8c63c951f 100644 --- a/site/ru/blog/new-in-devtools-102/index.md +++ b/site/ru/blog/new-in-devtools-102/index.md @@ -54,8 +54,8 @@ tags: <!-- ## New shortcuts to emulate light and dark themes {: #emulation } --> ## Новые горячие клавиши для эмуляции светлой и тёмной темы {: #emulation } -<!-- You can now emulate the light and dark themes quicker (CSS media feature [prefers-color-scheme](https://web.dev/prefers-color-scheme/#the-prefers-color-scheme-media-query)) with the new shortcuts in the **Styles** pane. --> -Теперь вы можете быстро переключать светлую и тёмную темы (CSS медиафункция [prefers-color-scheme](https://web.dev/prefers-color-scheme/#the-prefers-color-scheme-media-query)) при помощи горячих клавиш в панели **Стили** (Styles). +<!-- You can now emulate the light and dark themes quicker (CSS media feature [prefers-color-scheme](https://web.dev/articles/prefers-color-scheme#the_prefers_color_scheme_media_query)) with the new shortcuts in the **Styles** pane. --> +Теперь вы можете быстро переключать светлую и тёмную темы (CSS медиафункция [prefers-color-scheme](https://web.dev/articles/prefers-color-scheme#the_prefers_color_scheme_media_query)) при помощи горячих клавиш в панели **Стили** (Styles). <!-- Previously, it took more steps to [emulate themes](/docs/devtools/rendering/emulate-css/) in the **Rendering** tab. --> До этого требовалось больше действий для [эмуляции темы](/docs/devtools/rendering/emulate-css/) во вкладке **Отрисовка** (Rendering). @@ -73,8 +73,8 @@ tags: <!-- DevTools now apply the Content Security Policy (CSP) in the **Preview** tab in the **Network** panel. --> DevTools теперь применяет политику безопасности содержимого (CSP) на вкладке **Предварительный просмотр** (Preview) внутри вкладки **Сеть** (Network). -<!-- For example, the first screenshot shows a page that contains [mixed content](https://web.dev/what-is-mixed-content/). The page loads over a secure HTTPS connection, but the stylesheet loads over an insecure HTTP connection. --> -Например, на первом скриншоте показана страница, содержащая [смешанный контент](https://web.dev/what-is-mixed-content/). Страница загружается через безопасное соединение HTTPS, но таблица стилей загружается через небезопасное соединение HTTP. +<!-- For example, the first screenshot shows a page that contains [mixed content](https://web.dev/articles/what-is-mixed-content). The page loads over a secure HTTPS connection, but the stylesheet loads over an insecure HTTP connection. --> +Например, на первом скриншоте показана страница, содержащая [смешанный контент](https://web.dev/articles/what-is-mixed-content). Страница загружается через безопасное соединение HTTPS, но таблица стилей загружается через небезопасное соединение HTTP. <!-- The browser blocked the stylesheet request by default. However, when you opened the page via the **Preview** tab in the **Network** panel, the stylesheet was not blocked previously (hence the background turned into red). It is now blocked as you would expect (second screenshot). --> Браузер по умолчанию блокирует запрос таблицы стилей. Однако, когда вы открывали страницу через вкладку **Предварительный просмотр** (Preview) во вкладке **Сеть** (Network), таблица стилей ранее не блокировалась (поэтому фон становился красным). Теперь запрос блокируется, как и следовало ожидать (второй скриншот). @@ -152,7 +152,7 @@ DevTools теперь применяет политику безопасност ## Отображение наследуемых псевдоэлементов выделения в панели Стили (Styles) {: #pseudo } <!-- View the inherited highlight pseudo-elements (e.g. `::selection`, `::spelling-error`, `::grammar-error`, and `::highlight`) in the **Styles** pane. Previously, these rules were not displayed. --> -Просматривайте наследуемые псевдоэлементы выделения (`::selection`, `::spelling-error`, `::grammar-error` и `::highlight`) в панели **Стили** (Styles). Раньше эти правила не отображались. +Просматривайте наследуемые псевдоэлементы выделения (`::selection`, `::spelling-error`, `::grammar-error` и `::highlight`) в панели **Стили** (Styles). Раньше эти правила не отображались. <!-- As mentioned in the [specification](https://drafts.csswg.org/css-pseudo-4/#highlight-cascade), when multiple styles conflict, cascade determines the winning style. This new feature helps you understand the inheritance and priority of the rules. --> Как указано в [спецификации](https://drafts.csswg.org/css-pseudo-4/#highlight-cascade), когда несколько стилей конфликтуют, каскад определяет победивший стиль. Эта новая функция помогает понять наследование и приоритет правил. @@ -212,7 +212,7 @@ DevTools теперь применяет политику безопасност {# https://chromium.googlesource.com/devtools/devtools-frontend/+/afe5698f1cd20304d2763574ef8e9faf6a4a6db1 #} {# ​​https://chromium.googlesource.com/devtools/devtools-frontend/+/5de1d6140cad945783f3ca54055134f4a7db42a1 #} -{# https://chromium.googlesource.com/devtools/devtools-frontend/+/573dfc1cca09e49177ece3898c9ba9619c386f06 #} +{# https://chromium.googlesource.com/devtools/devtools-frontend/+/573dfc1cca09e49177ece3898c9ba9619c386f06 #} Задача в трекере Chromium: [1268754](https://crbug.com/1268754) @@ -238,4 +238,4 @@ DevTools теперь применяет политику безопасност Задача в трекере Chromium: [1245191](https://crbug.com/1245191) {% Partial 'devtools/reach-out.md' %} -{% Partial 'devtools/whats-new.md' %} \ No newline at end of file +{% Partial 'devtools/whats-new.md' %} diff --git a/site/ru/blog/new-in-devtools-104/index.md b/site/ru/blog/new-in-devtools-104/index.md index ac8ad9b5f..52e16d9e1 100644 --- a/site/ru/blog/new-in-devtools-104/index.md +++ b/site/ru/blog/new-in-devtools-104/index.md @@ -101,8 +101,8 @@ tags: <!-- Visualize `performance.measure()` marks in your recording with the new **User Timings** track in the **Performance insights** panel. --> Визуализируйте метки `performance.measure()` в вашей записи с новым треком **User Timings** во вкладке **Performance insights**. -<!-- For example, this [web page](https://jec.fish/demo/perf-measure) uses the [`performance.measure()`](https://web.dev/usertiming/#calculating-measurements-with-measure()) method to calculate the elapsed time of text loading. --> -Например, на [этой странице](https://jec.fish/demo/perf-measure) используется метод [`performance.measure()`](https://web.dev/usertiming/#calculating-measurements-with-measure()) для подсчёта времени, затраченного на загрузку текста. +<!-- For example, this [web page](https://jec.fish/demo/perf-measure) uses the [`performance.measure()`](https://web.dev/articles/usertiming#calculating_measurements_with_measure()) method to calculate the elapsed time of text loading. --> +Например, на [этой странице](https://jec.fish/demo/perf-measure) используется метод [`performance.measure()`](https://web.dev/articles/usertiming#calculating_measurements_with_measure()) для подсчёта времени, затраченного на загрузку текста. <!-- When you start [measuring the page load](/docs/devtools/performance-insights/#record), the **User Timings** track shows in the recording. Click on the timings item to view its details on the side pane. --> Когда вы запускаете [измерение загрузки страницы](/docs/devtools/performance-insights/#record), трек **User Timings** отображается в записи. Кликните на элемент хронометража, чтообы увидеть подробности о нём в боковой панели. diff --git a/site/ru/blog/new-in-devtools-105/index.md b/site/ru/blog/new-in-devtools-105/index.md index 577610a05..b111ceb7c 100644 --- a/site/ru/blog/new-in-devtools-105/index.md +++ b/site/ru/blog/new-in-devtools-105/index.md @@ -62,8 +62,8 @@ tags: <!-- ## Largest Contentful Paint (LCP) in the Performance insights panel {: #lcp } --> ## Самое крупное существенное отображение (LCP) во вкладке Performance Insights {: #lcp } -<!-- LCP is an important, user-centric metric for measuring [perceived load speed](https://web.dev/user-centric-performance-metrics/#types-of-metrics). You can now find out the critical paths and root causes of a [Largest Contentful Paint (LCP)](https://web.dev/lcp/). --> -LCP – это важная, ориентированная на пользователя метрика, замеряющая [ощущаемую скорость нагрузки](https://web.dev/user-centric-performance-metrics/#types-of-metrics). Теперь вы можете отследить критические моменты и первопричины задержки отрисовки [крупного существенного отображения (LCP)](https://web.dev/lcp/). +<!-- LCP is an important, user-centric metric for measuring [perceived load speed](https://web.dev/articles/user-centric-performance-metrics#types_of_metrics). You can now find out the critical paths and root causes of a [Largest Contentful Paint (LCP)](https://web.dev/articles/lcp). --> +LCP – это важная, ориентированная на пользователя метрика, замеряющая [ощущаемую скорость нагрузки](https://web.dev/articles/user-centric-performance-metrics#types_of_metrics). Теперь вы можете отследить критические моменты и первопричины задержки отрисовки [крупного существенного отображения (LCP)](https://web.dev/articles/lcp). <!-- In a [performance recording](/docs/devtools/performance-insights/#record), click on the LCP badge in the **Timeline**. In the **Details** pane, you can view the LCP score, learn how to fix resources that slow down the LCP and see the critical path for the LCP resource. --> В [записи производительности](/docs/devtools/performance-insights/#record) кликните на значок LPC в **Таймлайне** (Timeline). В панели **Details** вы можете увидеть оценку LCP, узнать как поправить ресурсы, которые замедляют LPC, и посмотреть критический путь для ресурса LCP. @@ -79,14 +79,14 @@ LCP – это важная, ориентированная на пользов <!-- ## Identify flashes of text (FOIT, FOUT) as potential root causes for layout shifts {: #foit-fout } --> ## Определение миганий текста (FOIT, FOUT) как потенциальных первопричин сдвигов раскладки {: #foit-fout } -<!-- The **Performance insights** panel now detects [flash of invisible text (FOIT) and flash of unstyled text (FOUT)](https://web.dev/preload-optional-fonts/#font-rendering) as potential root causes for layout shifts. --> -Во вкладке **Performance Insights** теперь распознаются [мигания невидимого текста (FOIT) и мигания нестилизованного текста (FOUT)](https://web.dev/preload-optional-fonts/#font-rendering) как потенциальные причины сдвига раскладки. +<!-- The **Performance insights** panel now detects [flash of invisible text (FOIT) and flash of unstyled text (FOUT)](https://web.dev/articles/preload-optional-fonts#font_rendering) as potential root causes for layout shifts. --> +Во вкладке **Performance Insights** теперь распознаются [мигания невидимого текста (FOIT) и мигания нестилизованного текста (FOUT)](https://web.dev/articles/preload-optional-fonts#font_rendering) как потенциальные причины сдвига раскладки. <!-- To view the potential root causes of a layout shift, click on a screenshot in the **Layout shifts** track. --> Чтобы увидеть потенциальные причины сдвига раскладки кликните на скриншот в **Layout shifts**. -<!-- See [Optimize WebFont loading and rendering](https://web.dev/optimize-webfont-loading/) to learn the technique to prevent layout shifts. --> -Изучите статью [Optimize WebFont loading and rendering](https://web.dev/optimize-webfont-loading/), чтобы узнать о техниках предотвращения сдвига раскладки. +<!-- See [Optimize WebFont loading and rendering](https://web.dev/articles/optimize-webfont-loading) to learn the technique to prevent layout shifts. --> +Изучите статью [Optimize WebFont loading and rendering](https://web.dev/articles/optimize-webfont-loading), чтобы узнать о техниках предотвращения сдвига раскладки. {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/AMN5oD5hlKhPhnq98sIB.png", alt="FOUT во вкладке Performance insights", width="800", height="497" %} @@ -96,8 +96,8 @@ LCP – это важная, ориентированная на пользов <!-- ## Protocol handlers in the Manifest pane {: #manifest } --> ## Обработчики протоколов в панели Манифест {: #manifest } -<!-- You can now use DevTools to test the [URL protocol handler registration](https://web.dev/url-protocol-handler/) for [Progressive Web Apps (PWA)](https://web.dev/learn/pwa/). --> -Теперь вы можете использовать DevTools для тестирования [регистрации обработчика протокола URL](https://web.dev/url-protocol-handler/) для [прогрессивных веб-приложений (PWA)](https://web.dev/learn/pwa/). +<!-- You can now use DevTools to test the [URL protocol handler registration](https://web.dev/articles/url-protocol-handler) for [Progressive Web Apps (PWA)](https://web.dev/learn/pwa). --> +Теперь вы можете использовать DevTools для тестирования [регистрации обработчика протокола URL](https://web.dev/articles/url-protocol-handler) для [прогрессивных веб-приложений (PWA)](https://web.dev/learn/pwa). <!-- The URL protocol handler registration lets installed PWAs handle links that use a specific protocol (e.g. [`magnet`](https://wikipedia.org/wiki/Magnet_URI_scheme), `web+example`) for a more integrated experience. --> Регистрация обработчика протокола URL позволяет установленным PWA обрабатывать ссылки, использующие определённый протокол (например [`magnet`](https://wikipedia.org/wiki/Magnet_URI_scheme), `web+example`), для более полноценного опыта использования. @@ -122,8 +122,8 @@ LCP – это важная, ориентированная на пользов <!-- Use the [top layer badge](/blog/top-layer-devtools/#top-layer-support-design-in-devtools) to understand the concept of the top layer and visualize how the top layer content changes. --> Используйте [значок верхнего слоя](/blog/top-layer-devtools/#top-layer-support-design-in-devtools), чтобы понять концепцию верхнего слоя и визуализировать, как меняется его контент. -<!-- The [`<dialog>` element](https://web.dev/building-a-dialog-component/) has recently become stable across browsers. When you open a dialog, it is put into a [top layer](/blog/top-layer-devtools/). Top level content renders on top of all the other content. --> -Элемент [`<dialog>`](https://web.dev/building-a-dialog-component/) недавно стал стабилен во всех браузерах. Когда вы открываете диалог, он помещается в [верхний слой](/blog/top-layer-devtools/). Контент верхнего уровня отображается поверх всего остального контента. +<!-- The [`<dialog>` element](https://web.dev/articles/building-a-dialog-component) has recently become stable across browsers. When you open a dialog, it is put into a [top layer](/blog/top-layer-devtools/). Top level content renders on top of all the other content. --> +Элемент [`<dialog>`](https://web.dev/articles/building-a-dialog-component) недавно стал стабилен во всех браузерах. Когда вы открываете диалог, он помещается в [верхний слой](/blog/top-layer-devtools/). Контент верхнего уровня отображается поверх всего остального контента. <!-- In this [demo](https://jec.fish/demo/dialog), click **Open dialog**. --> В этом [демо](https://jec.fish/demo/dialog) кликните на **Open dialog**. diff --git a/site/ru/blog/new-in-devtools-106/index.md b/site/ru/blog/new-in-devtools-106/index.md index 8fa73f7ee..e8693e79d 100644 --- a/site/ru/blog/new-in-devtools-106/index.md +++ b/site/ru/blog/new-in-devtools-106/index.md @@ -174,8 +174,8 @@ async increment() { <!-- ## LCP timings breakdown in the Performance Insights panel {: #insights } --> ## Разбивка по времени LCP во вкладке Performance Insights {: #insights } -<!-- The **Performance Insights** panel now shows the [timings breakdown](https://web.dev/optimize-lcp/#lcp-breakdown) of the [Largest Containful Paint (LCP)](/docs/devtools/performance-insights/#largest-contentful-paint). Use these timings information to understand and identify an opportunity to improve LCP performance. --> -Вкладка **Performance Insights** теперь показывает [разбивку по времени](https://web.dev/optimize-lcp/#lcp-breakdown) для [самого крупного существенного отображения (LCP)](/docs/devtools/performance-insights/#largest-contentful-paint). Используйте информацию о тайминге для понимания и определения возможностей для улучшения LCP. +<!-- The **Performance Insights** panel now shows the [timings breakdown](https://web.dev/articles/optimize-lcp#lcp_breakdown) of the [Largest Containful Paint (LCP)](/docs/devtools/performance-insights/#largest-contentful-paint). Use these timings information to understand and identify an opportunity to improve LCP performance. --> +Вкладка **Performance Insights** теперь показывает [разбивку по времени](https://web.dev/articles/optimize-lcp#lcp_breakdown) для [самого крупного существенного отображения (LCP)](/docs/devtools/performance-insights/#largest-contentful-paint). Используйте информацию о тайминге для понимания и определения возможностей для улучшения LCP. {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/hU6RmoRjFskL8P2ZAB9l.png", alt="Разбивка по времени LCP во вкладке Performance Insights", width="800", height="523" %} @@ -204,8 +204,8 @@ async increment() { - Ранее [расширение Recorder](/docs/devtools/recorder/reference/#extension-troubleshooting) во вкладке **Recorder** периодически не показывалось. ([1351416](https://crbug.com/1351416)) <!-- - The **Styles** pane now displays a color picker for the [SVG `<stop>`](https://developer.mozilla.org/docs/Web/SVG/Element/stop) element’s `stop-color` property. ([1351096](https://crbug.com/1351096)) --> - Во вкладке **Стили** (Styles) теперь показывается предпросмотр цвета для элемента [`<stop>` в SVG](https://developer.mozilla.org/docs/Web/SVG/Element/stop) в свойстве `stop-color`. ([1351096](https://crbug.com/1351096)) -<!-- - Identify script causing [layout](https://web.dev/avoid-large-complex-layouts-and-layout-thrashing/) as the potential root causes for layout shifts in the **Performance Insights** panel. ([1343019](https://crbug.com/1343019)) --> -- Определение вызова скрипта [отрисовки](https://web.dev/avoid-large-complex-layouts-and-layout-thrashing/) как потенциальной причины для сдвигов раскладки во вкладке **Performance Insights**. ([1343019](https://crbug.com/1343019)) +<!-- - Identify script causing [layout](https://web.dev/articles/avoid-large-complex-layouts-and-layout-thrashing) as the potential root causes for layout shifts in the **Performance Insights** panel. ([1343019](https://crbug.com/1343019)) --> +- Определение вызова скрипта [отрисовки](https://web.dev/articles/avoid-large-complex-layouts-and-layout-thrashing) как потенциальной причины для сдвигов раскладки во вкладке **Performance Insights**. ([1343019](https://crbug.com/1343019)) <!-- - Display critical path for LCP web fonts in the **Performance Insights** panel. ([1350390](https://crbug.com/1350390)) --> - Отображение критического для LCP пути до веб-шрифтов во вкладке **Performance Insights**. ([1350390](https://crbug.com/1350390)) diff --git a/site/ru/blog/new-in-devtools-112/index.md b/site/ru/blog/new-in-devtools-112/index.md index c99199abc..d02e913d9 100644 --- a/site/ru/blog/new-in-devtools-112/index.md +++ b/site/ru/blog/new-in-devtools-112/index.md @@ -48,7 +48,7 @@ Chromium issue: [1400243](https://crbug.com/1400243). <!-- In addition to [custom, CSS, ARIA, text, and XPath selectors](/docs/devtools/recorder/reference/#selector), you can now record using [pierce selectors](https://pptr.dev/guides/query-selectors#pierce-selectors-pierce). These selectors behave like CSS ones but can also pierce through shadow roots. --> -<!-- Start a new recording on a page with [shadow DOM](https://web.dev/shadowdom-v1/) and check {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/hmp8j3HiLMCcqPArD9yt.svg", alt="Checkbox.", width="22", height="22" %} **Pierce** in **Selector types to record**. Record your interaction with elements in the shadow DOM and inspect the corresponding step. --> +<!-- Start a new recording on a page with [shadow DOM](https://web.dev/articles/shadowdom-v1) and check {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/hmp8j3HiLMCcqPArD9yt.svg", alt="Checkbox.", width="22", height="22" %} **Pierce** in **Selector types to record**. Record your interaction with elements in the shadow DOM and inspect the corresponding step. --> {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/Spqbf2DG3Fr0D2sc1kgC.png", alt="Setting the Recorder to use pierce selectors; Pierce selector in action.", width="800", height="534" %} diff --git a/site/ru/blog/new-in-devtools-93/index.md b/site/ru/blog/new-in-devtools-93/index.md index 71f090748..d707ac66a 100644 --- a/site/ru/blog/new-in-devtools-93/index.md +++ b/site/ru/blog/new-in-devtools-93/index.md @@ -26,7 +26,7 @@ tags: ## Редактируемые выражения от контейнера в панели Styles {: #container-queries } Теперь вы можете просматривать и редактировать [выражения от -контейнера](https://web.dev/new-responsive/#responsive-to-the-container) в +контейнера](https://web.dev/articles/new-responsive#responsive_to_the_container) в панели **Styles**. @@ -63,7 +63,7 @@ https://chromium.googlesource.com/devtools/devtools-frontend/+/ef157dab2ccf32194 ## Предварительный просмотр веб-бандлов во вкладке Network {: #web-bundle } -[Веб-бандлы](https://web.dev/web-bundles/) — это способ инкапсуляции одного или +[Веб-бандлы](https://web.dev/articles/web-bundles) — это способ инкапсуляции одного или нескольких HTTP-ресурсов в один файл. Теперь вы можете просмотреть содержимое веб-бандла во вкладке **Network**. diff --git a/site/ru/blog/new-in-devtools-96/index.md b/site/ru/blog/new-in-devtools-96/index.md index b2a61c441..dfadedd44 100644 --- a/site/ru/blog/new-in-devtools-96/index.md +++ b/site/ru/blog/new-in-devtools-96/index.md @@ -166,7 +166,7 @@ Chrome 96 включает [origin trial](/blog/origin-trials/) функции [ {# https://chromium.googlesource.com/devtools/devtools-frontend/+/f1574e9b550317c481a943fec059d84bfb863564 #} -Задача в трекере Chromium: [1226262](https://crbug.com/1226262) +Задача в трекере Chromium: [1226262](https://crbug.com/1226262) <!-- ## Console updates --> @@ -206,7 +206,7 @@ Chrome 96 включает [origin trial](/blog/origin-trials/) функции [ ### Консистентные асинхронные трассировки стека {: #async } <!-- DevTools now reports `async` stack traces for `async` functions to be consistent with other async tasks. --> -DevTools теперь отображает стек трассировки `async` для асинхронных функций, чтобы они соответствовали другим задачам async. +DevTools теперь отображает стек трассировки `async` для асинхронных функций, чтобы они соответствовали другим задачам async. {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/wuKo84nrDzbhwCnIVU2n.png", alt="Стек трассировки async", width="800", height="427" %} @@ -234,12 +234,12 @@ DevTools теперь отображает стек трассировки `asyn <!-- ## Deprecated Application cache pane in the Application panel {: #app-cache } --> ## Устаревшая панель Кэш приложения на вкладке Приложение {: #app-cache } -<!-- The [Application cache](/docs/devtools/storage/applicationcache/) pane in the Application panel is now removed as the support for [AppCache](https://web.dev/appcache-removal/) is removed from Chrome and other Chromium-based browsers. --> -Панель [Кеш приложений](/docs/devtools/storage/applicationcache/) (Application cache) на вкладке Приложение (Application) удалена, поскольку [AppCache](https://web.dev/appcache-removal/) больше не поддерживается в Chrome и других браузерах на основе Chromium. +<!-- The [Application cache](/docs/devtools/storage/applicationcache/) pane in the Application panel is now removed as the support for [AppCache](https://web.dev/articles/appcache-removal) is removed from Chrome and other Chromium-based browsers. --> +Панель [Кеш приложений](/docs/devtools/storage/applicationcache/) (Application cache) на вкладке Приложение (Application) удалена, поскольку [AppCache](https://web.dev/articles/appcache-removal) больше не поддерживается в Chrome и других браузерах на основе Chromium. {# https://chromium.googlesource.com/devtools/devtools-frontend/+/de4d15e955d6145674e3885cde8a5a70f1269b79 #} -Задача в трекере Chromium: [1084190](https://crbug.com/1084190) +Задача в трекере Chromium: [1084190](https://crbug.com/1084190) <!-- ## [Experimental] New Reporting API pane in the Application panel {: #reporting-api } --> @@ -250,17 +250,17 @@ DevTools теперь отображает стек трассировки `asyn Чтобы включить эксперимент, поставьте галочку в чекбоксе напротив пункта **Enable Reporting API panel in the Application panel** во вкладке **Настройки** (Settings) > **Экспериментальные функции** (Experiments). {% endAside %} -<!-- The [Reporting API](https://web.dev/reporting-api/) is designed to help you monitor security violations of your page, deprecated API calls, and more. --> -[Reporting API](https://web.dev/reporting-api/) призван помочь вам отслеживать нарушения безопасности вашей страницы, устаревшие вызовы API и многое другое. +<!-- The [Reporting API](https://web.dev/articles/reporting-api) is designed to help you monitor security violations of your page, deprecated API calls, and more. --> +[Reporting API](https://web.dev/articles/reporting-api) призван помочь вам отслеживать нарушения безопасности вашей страницы, устаревшие вызовы API и многое другое. <!-- With this experiment enabled, you can now view the reports status in the new **Reporting API** pane in the **Application** panel. --> -С включенным экспериментом вы теперь можете просматривать статус отчётов в панели **Reporting API** во вкладке **Приложение** (Application). +С включенным экспериментом вы теперь можете просматривать статус отчётов в панели **Reporting API** во вкладке **Приложение** (Application). <!-- Please note that the **Endpoints** section is currently still under active development (showing no reporting endpoints for now). --> -Пожалуйста, обратите внимание что секция **Endpoints** пока находится в активной разработке (пока не показывает конечные точки отчетности). +Пожалуйста, обратите внимание что секция **Endpoints** пока находится в активной разработке (пока не показывает конечные точки отчетности). -<!-- Learn more about the **Reporting API** with [this article](https://web.dev/reporting-api/). --> -Читайте больше о **Reporting API** в [этой статье](https://web.dev/reporting-api/). +<!-- Learn more about the **Reporting API** with [this article](https://web.dev/articles/reporting-api). --> +Читайте больше о **Reporting API** в [этой статье](https://web.dev/articles/reporting-api). {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/hbwFqi9aNDOj70FhLXsn.png", alt="Панель Reporting API на вкладке Приложение", width="800", height="476" %} diff --git a/site/ru/blog/new-in-devtools-98/index.md b/site/ru/blog/new-in-devtools-98/index.md index 8bda2bc2f..e196d331e 100644 --- a/site/ru/blog/new-in-devtools-98/index.md +++ b/site/ru/blog/new-in-devtools-98/index.md @@ -33,7 +33,7 @@ tags: ## Ранний доступ: дерево доступности на всю страницу (Full-page accessibility tree) {: #a11y-tree } <!-- The new **Full-page accessibility tree** makes it easier for you to get an overview of the full-page [accessibility tree](/blog/full-accessibility-tree/#what-is-the-accessibility-tree) and help you better understand how your web content is exposed to assistive technology. --> -Новая функция **Дерево доступности на всю страницу** (Full-page accessibility tree) облегчает обзор полностраничного [дерева доступности](/blog/full-accessibility-tree/#what-is-the-accessibility-tree) и помогает лучше понять, как ваш веб-контент работает со вспомогательными технологиями. +Новая функция **Дерево доступности на всю страницу** (Full-page accessibility tree) облегчает обзор полностраничного [дерева доступности](/blog/full-accessibility-tree/#what-is-the-accessibility-tree) и помогает лучше понять, как ваш веб-контент работает со вспомогательными технологиями. <!-- In the **Elements** panel, open the **Accessibility** pane and select **Enable full-page accessibility tree** checkbox. Then, reload DevTools and you will see a new accessibility button in the **Elements** panel. --> @@ -59,13 +59,13 @@ tags: <!-- ## More precise changes in the Changes tab {: #changes } --> -## Явное отображение изменений на вкладке Изменения (Changes) {: #changes } +## Явное отображение изменений на вкладке Изменения (Changes) {: #changes } <!-- The code changes in the **Changes** tab is pretty-printed automatically. --> -Изменения кода на вкладке **Изменения** (Changes) автоматически форматируются. +Изменения кода на вкладке **Изменения** (Changes) автоматически форматируются. <!-- Previously, it was hard to trace the actual changes of minified source code because all the code is shown in a single line. --> -Раньше было сложно отследить фактические изменения в минифицированных файлах, поскольку весь код отображался в одну строку. +Раньше было сложно отследить фактические изменения в минифицированных файлах, поскольку весь код отображался в одну строку. {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/aup2bT490dkvuBu3o4DS.png", alt="Вкладка Изменения", width="800", height="450" %} @@ -87,8 +87,8 @@ tags: Мы можем использовать новую настройку **Timeout** чтобы исправить это. Откройте детали шага, в котором мы нажимаем на пункт меню. [Редактируйте шаг](/docs/devtools/recorder/#edit-steps), нажав кнопку **Add timeout** и установите значение **6000** миллисекунд (равно 6 секундам). <!-- Optionally, you can adjust the **Timeout** in the **Replay settings** for all the steps. Expand the **Replay settings** and edit the **Timeout** value. --> -По желанию вы можете настроить **Timeout** для всех шагов в меню **Replay settings**. Раскройте настройки **Replay settings** и измените значение **Timeout**. - +По желанию вы можете настроить **Timeout** для всех шагов в меню **Replay settings**. Раскройте настройки **Replay settings** и измените значение **Timeout**. + {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/y7RDpIp3pd2n6Vnxc5Du.png", alt="Настройка тайм-аута для записи поведения пользователя", width="800", height="530" %} Задача в трекере Chromium: [1257499](https://crbug.com/1257499) @@ -97,8 +97,8 @@ tags: <!-- ## Ensure your pages are cacheable with the Back/forward cache tab {: #bfcache } --> ## Убедитесь, что ваши страницы кешируются с помощью вкладки Возвратный кеш (Back/forward cache) {: #bfcache } -<!-- [Back/forward cache (or bfcache)](https://web.dev/bfcache/) is a browser optimization that enables instant back and forward navigation. --> -[Возвратный кеш (или bfcache)](https://web.dev/bfcache/) это оптимизация браузера, которая обеспечивает мгновенную навигацию назад и вперед. +<!-- [Back/forward cache (or bfcache)](https://web.dev/articles/bfcache) is a browser optimization that enables instant back and forward navigation. --> +[Возвратный кеш (или bfcache)](https://web.dev/articles/bfcache) это оптимизация браузера, которая обеспечивает мгновенную навигацию назад и вперед. <!-- The new **Back/forward cache** tab can help you test your pages to ensure they're optimized for bfcache, and identify any issues that may be preventing them from being eligible. --> Новая вкладка **Возвратный кеш** (Back/forward cache) поможет протестировать ваши страницы, чтобы убедиться, что они оптимизированы для возвратного кеша, или выявить проблемы, которые этому препятствуют. @@ -107,7 +107,7 @@ tags: Чтобы протестировать конкретную страницу, перейдите на неё в Chrome и затем в DevTools откройте **Приложение** (Application) > **Возвратный кеш** (Back-forward Cache). Далее, нажмите кнопку **Test back/forward cache**, и DevTools попытается произвести переход на предыдущую страницу и обратно, чтобы проверить, может ли страница быть восстановлена из кеша. <!-- As web developers, it's critical to know how to optimize your pages for bfcache across all browsers because it will significantly improve the browsing experience for users—especially those with slower networks or devices. --> -Для веб-разработчиков очень важно знать, как оптимизировать страницы для возвратного кеша во всех браузерах, поскольку это значительно улучшит качество просмотра для пользователей. Особенно для тех, у кого медленные сети или устройства. +Для веб-разработчиков очень важно знать, как оптимизировать страницы для возвратного кеша во всех браузерах, поскольку это значительно улучшит качество просмотра для пользователей. Особенно для тех, у кого медленные сети или устройства. {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/4OrWjuRgG1bB0AupcMmS.png", alt="Вкладка Возвратный кеш", width="800", height="516" %} @@ -123,15 +123,15 @@ tags: Если вы хотите сфокусироваться на конкретном свойстве в панели **Свойства** (Properties), вы теперь можете ввести название нужного свойства или его значение в новом текстовом поле **Фильтр** (Filter). <!-- By default, properties whose value is `null` or `undefined` are not shown. Enable the **Show all** checkbox to view all properties. --> -По умолчанию свойства, чьи значения равны `null` или `undefined`, не отображаются. Поставьте галочку в чекбоксе **Показывать все** (Show all), чтобы увидеть все свойства. +По умолчанию свойства, чьи значения равны `null` или `undefined`, не отображаются. Поставьте галочку в чекбоксе **Показывать все** (Show all), чтобы увидеть все свойства. <!-- These enhancements allow you to get to the properties you care for quicker and thus improve your productivity! --> Эти нововведения позволят вам быстрее добраться до объектов, которые вам интересны, и тем самым повысить вашу продуктивность! {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/ewmNloO4ohRxlWRNuEW1.png", alt="Фильтр во вкладке Свойства", width="800", height="505" %} -{# https://chromium.googlesource.com/devtools/devtools-frontend/+/0980f52facf75b6c03e14472d13fe27968d4732b #} - +{# https://chromium.googlesource.com/devtools/devtools-frontend/+/0980f52facf75b6c03e14472d13fe27968d4732b #} + Задача в трекере Chromium: [1269674](https://crbug.com/1269674) @@ -170,7 +170,7 @@ tags: ## Поддержка значений `row-reverse` и `column-reverse` в редакторе флексбоксов {: #flexbox-editor } <!-- The [Flexbox editor](/blog/new-in-devtools-90/#flexbox) added two new buttons to support `row-reverse` and `column-reverse` in `flex-direction`. --> -В [редактор флексбоксов](/blog/new-in-devtools-90/#flexbox) добавлены две новые кнопки для поддержки значений `row-reverse` и `column-reverse` в свойстве `flex-direction`. +В [редактор флексбоксов](/blog/new-in-devtools-90/#flexbox) добавлены две новые кнопки для поддержки значений `row-reverse` и `column-reverse` в свойстве `flex-direction`. {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/JHI4frP4MqaydXk19sq2.png", alt="Редактор флексбоксов", width="800", height="546" %} @@ -194,7 +194,7 @@ tags: Задача в трекере Chromium: [1050021](https://crbug.com/1050021) - + <!-- ### Keyboard shortcut to expand all search results {: #toggle-search-result } --> ### Шорткат для расширение всех результатов поиска {: #toggle-search-result } @@ -223,8 +223,8 @@ tags: <!-- The **Lighthouse** panel is now running Lighthouse 9. Lighthouse will now list all the elements sharing the same id. --> Во вкладке **Lighthouse** теперь запускается Lighthouse 9. Lighthouse теперь перечисляет все элементы, имеющие одинаковый идентификатор. -<!-- Non-unique element id is a common accessibility problem. For instance, the id referenced in an `aria-labelledby` attribute is used on [multiple elements](https://web.dev/duplicate-id-aria/). --> -Неуникальный идентификатор элемента — распространенная проблема доступности. Например, id, на который ссылается атрибут `aria-labelledby`, используется на [нескольких элементах] (https://web.dev/duplicate-id-aria/). +<!-- Non-unique element id is a common accessibility problem. For instance, the id referenced in an `aria-labelledby` attribute is used on [multiple elements](https://web.dev/articles/duplicate-id-aria). --> +Неуникальный идентификатор элемента — распространенная проблема доступности. Например, id, на который ссылается атрибут `aria-labelledby`, используется на [нескольких элементах] (https://web.dev/articles/duplicate-id-aria). <!-- Check out the [What’s new in Lighthouse 9.0](/blog/lighthouse-9-0/) for more details on the updates. --> Перейдите на страницу [What’s new in Lighthouse 9.0](/blog/lighthouse-9-0/) для получения более подробной информации об обновлении. @@ -246,11 +246,11 @@ tags: - Improved auto-complete suggestions for editable sources (e.g. snippets, local override) --> - Значительно ускорилось открытие больших файлов (например, WASM, JavaScript) - Больше никакой случайной прокрутки при пошаговом выполнении кода -- Улучшены предложения автозаполнения для редактируемых источников (например, сниппеты, локальное переопределение) +- Улучшены предложения автозаполнения для редактируемых источников (например, сниппеты, локальное переопределение) {# https://chromium.googlesource.com/devtools/devtools-frontend/+/c1ab112d9002d5c3b3bb70cf2839bac182f0cdb5 #} -Задача в трекере Chromium: [1241848](https://crbug.com/1241848) +Задача в трекере Chromium: [1241848](https://crbug.com/1241848) <!-- ## Miscellaneous highlights {: #misc } --> ## Другие важные моменты {: #misc } @@ -260,12 +260,12 @@ tags: <!-- - Properly displaying the waterfall diagram of network requests. Previously, the style was broken. ([1275501](https://crbug.com/1275501)) - The code highlight was broken when searching in documents with very long lines in the **Sources** panel. It’s now fixed. ([1275496](https://crbug.com/1275496)) -- No more duplicate **Payload** tab in network requests. ([1273972](https://crbug.com/1273972)) +- No more duplicate **Payload** tab in network requests. ([1273972](https://crbug.com/1273972)) - Fixed the missing layout shifts details in the **Summary** section of the **Performance** panel. ([1259606](https://crbug.com/1259606)) - Support arbitrary characters (e.g. `,`, `.`), in **Network Search** queries. ([1267196](https://crbug.com/1267196)) --> - Правильное отображение графика водопада сетевых запросов. Ранее стили был некорректны. ([1275501](https://crbug.com/1275501)) - Выделение кода было неисправно при поиске в документах с очень длинными строками во вкладке **Источники** (Sources). Теперь это исправлено. ([1275496](https://crbug.com/1275496)) -- Больше не дублируется вкладка **Полезная нагрузка** (Payload) в сетевых запросах. ([1273972](https://crbug.com/1273972)) +- Больше не дублируется вкладка **Полезная нагрузка** (Payload) в сетевых запросах. ([1273972](https://crbug.com/1273972)) - Исправлено отсутствие деталей сдвига макета в разделе **Сводка** (Summary) во вкладке **Производительность** (Performance). ([1259606](https://crbug.com/1259606)) - Поддержка произвольных символов (например, `,`, `.`) в запросах поиска на вкладке **Сеть**. ([1267196](https://crbug.com/1267196)) @@ -286,12 +286,12 @@ tags: <!-- The **Endpoints** section is now available. It gives you an overview of all the endpoints configured in the `Reporting-Endpoints` header. --> Секция **Endpoints** теперь доступна. Она показывает все эндпоинты, настроенные в заголовке `Reporting-Endpoints`. -<!-- Learn to use the [Reporting API](https://web.dev/reporting-api/) to monitor security violations, deprecated API calls, and more. --> -Научитесь пользоваться [Reporting API](https://web.dev/reporting-api/) для отслеживания проблем безопасности, устаревших вызовов API и т.д. +<!-- Learn to use the [Reporting API](https://web.dev/articles/reporting-api) to monitor security violations, deprecated API calls, and more. --> +Научитесь пользоваться [Reporting API](https://web.dev/articles/reporting-api) для отслеживания проблем безопасности, устаревших вызовов API и т.д. {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/D1fUz4zuS1xwDbszgft1.png", alt="Панель Reporting API", width="800", height="560" %} -{# https://chromium.googlesource.com/devtools/devtools-frontend/+/a831b26b7ecde579144a42a4faaa7b639789bf3c #} +{# https://chromium.googlesource.com/devtools/devtools-frontend/+/a831b26b7ecde579144a42a4faaa7b639789bf3c #} Задача в трекере Chromium: [1200732](https://crbug.com/1200732) diff --git a/site/ru/blog/new-in-devtools-99/index.md b/site/ru/blog/new-in-devtools-99/index.md index 5438b4f3e..45abe582f 100644 --- a/site/ru/blog/new-in-devtools-99/index.md +++ b/site/ru/blog/new-in-devtools-99/index.md @@ -49,8 +49,8 @@ tags: <!-- Use the new **Reporting API** pane to monitor the reports generated on your page and their status. --> Используйте новую панель **Reporting API**, чтобы отслеживать созданные на вашей страницы отчёты и их статус. -<!-- The [Reporting API](https://web.dev/reporting-api/) is designed to help you monitor security violations of your page, deprecated API calls, and more. --> -[Reporting API](https://web.dev/reporting-api/) помогает отслеживать нарушения безопасности на вашем сайте, устаревшие запросы API и многое другое. +<!-- The [Reporting API](https://web.dev/articles/reporting-api) is designed to help you monitor security violations of your page, deprecated API calls, and more. --> +[Reporting API](https://web.dev/articles/reporting-api) помогает отслеживать нарушения безопасности на вашем сайте, устаревшие запросы API и многое другое. <!-- Open a page which uses the Reporting API (e.g. [demo page](https://reporting-api-demo.glitch.me/)). In the **Application** panel, scroll down to the **Background services** section and select the **Reporting API** pane. --> Откроейте страницу, которая использует Reporting API (например, [демо страница](https://reporting-api-demo.glitch.me/)). Во вкладке **Приложение** (Application) проскрольте до раздела **Фоновые службы** (Background services) и выберите панель **Reporting API**. @@ -170,8 +170,8 @@ tags: <!-- ### Display worker source files in the Sources panel {: #worker-sourcemap } --> ### Отображение исходных файлов воркеров во вкладке Источники (Sources) {: #worker-sourcemap } -<!-- [Worker](https://web.dev/workers-overview/) (e.g. web worker, service worker) source files with relative SourceURL are now displayed in the **Source** panel. Previously, worker source files were not handled correctly. --> -Исходные файлы [воркера](https://web.dev/workers-overview/) (веб-воркера, сервис-воркера) с относительным SourceURL теперь отображаются во вкладке **Источники** (Sources). Ранее исходные файлы воркеров обрабатывались неправильно. +<!-- [Worker](https://web.dev/articles/workers-overview) (e.g. web worker, service worker) source files with relative SourceURL are now displayed in the **Source** panel. Previously, worker source files were not handled correctly. --> +Исходные файлы [воркера](https://web.dev/articles/workers-overview) (веб-воркера, сервис-воркера) с относительным SourceURL теперь отображаются во вкладке **Источники** (Sources). Ранее исходные файлы воркеров обрабатывались неправильно. {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/apH5n92bqYWINMQn5VXa.png", alt="Исходный файл сервис-вордекра во вкладке Источники", width="800", height="509" %} @@ -228,10 +228,10 @@ Chrome 96 анонсировал [ранний доступ](/blog/origin-trials - Исправлены неполадки с [редактированием cookies](/docs/devtools/storage/cookies/#edit) в панели **Файлы cookie** (Cookies). ([1290196](https://crbug.com/1290196)) <!-- - Use `Shift` + `Tab` to select the previous command in the [Command menu](/docs/devtools/command-menu/). ([1278743](https://crbug.com/1278743)) --> - Использование `Shift` + `Tab` для выбора предыдущей команды в [Командном меню (Command menu)](/docs/devtools/command-menu/). ([1278743](https://crbug.com/1278743)) -<!-- - Report [CORS preflight request](https://web.dev/cross-origin-resource-sharing/#preflight-requests-for-complex-http-calls) issues in the [Issues](/docs/devtools/issues/) tab. ([1272445](https://crbug.com/1272445)). --> -- Вывод сообщений о проблемах с [предварительным запросом CORS](https://web.dev/cross-origin-resource-sharing/#preflight-requests-for-complex-http-calls) во вкладке [Проблемы (Issues)](/docs/devtools/issues/). ([1272445](https://crbug.com/1272445)) -<!-- - Report [User-Agent Client Hints](https://web.dev/user-agent-client-hints/) issues in the [Issues](/docs/devtools/issues/) tab. ([1219359](https://crbug.com/1219359)). --> -- Вывод сообщений о проблемах с [User-Agent Client Hints](https://web.dev/user-agent-client-hints/) во вкладке [Проблемы (Issues)](/docs/devtools/issues/). ([1219359](https://crbug.com/1219359)) +<!-- - Report [CORS preflight request](https://web.dev/articles/cross-origin-resource-sharing#preflight_requests_for_complex_http_calls) issues in the [Issues](/docs/devtools/issues/) tab. ([1272445](https://crbug.com/1272445)). --> +- Вывод сообщений о проблемах с [предварительным запросом CORS](https://web.dev/articles/cross-origin-resource-sharing#preflight_requests_for_complex_http_calls) во вкладке [Проблемы (Issues)](/docs/devtools/issues/). ([1272445](https://crbug.com/1272445)) +<!-- - Report [User-Agent Client Hints](https://web.dev/articles/user-agent-client-hints) issues in the [Issues](/docs/devtools/issues/) tab. ([1219359](https://crbug.com/1219359)). --> +- Вывод сообщений о проблемах с [User-Agent Client Hints](https://web.dev/articles/user-agent-client-hints) во вкладке [Проблемы (Issues)](/docs/devtools/issues/). ([1219359](https://crbug.com/1219359)) <!-- - Fixed `Shift` + `Delete` and `Page up` / `Page down` behaviors in the **Sources** and **Console** panel. ([1278461](https://crbug.com/1278461), [1285662](https://crbug.com/1285662)) --> - Исправлено поведение `Shift` + `Delete` и `Page up` / `Page down` во вкладках **Источники** (Sources) и **Консоль** (Console). ([1278461](https://crbug.com/1278461), [1285662](https://crbug.com/1285662)) <!-- - Close the breakpoint edit dialog on breakpoint removal in the **Sources** panel. (922513) --> diff --git a/site/ru/docs/lighthouse/best-practices/external-anchors-use-rel-noopener/index.md b/site/ru/docs/lighthouse/best-practices/external-anchors-use-rel-noopener/index.md index 8214ec6e6..022c07b54 100644 --- a/site/ru/docs/lighthouse/best-practices/external-anchors-use-rel-noopener/index.md +++ b/site/ru/docs/lighthouse/best-practices/external-anchors-use-rel-noopener/index.md @@ -45,10 +45,10 @@ Lighthouse использует следующий процесс для опр - `rel="noopener"` предотвращает доступ новой страницы к свойству `window.opener` и обеспечивает ее запуск в отдельном процессе. - `rel="noreferrer"` имеет тот же эффект, но также предотвращает перенаправление заголовка `Referer` на новую страницу. См. [Тип ссылки "noreferrer"](https://html.spec.whatwg.org/multipage/links.html#link-type-noreferrer). -Дополнительную информацию см. в публикации «[Безопасный общий доступ к ресурсам из разных источников](https://web.dev/cross-origin-resource-sharing/)». +Дополнительную информацию см. в публикации «[Безопасный общий доступ к ресурсам из разных источников](https://web.dev/articles/cross-origin-resource-sharing)». ## Ресурсы - [Исходный код для аудита «**Небезопасные ссылки на пункты назначения из разных источников**»](https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js) -- [Безопасный общий доступ к ресурсам из разных источников](https://web.dev/cross-origin-resource-sharing/) +- [Безопасный общий доступ к ресурсам из разных источников](https://web.dev/articles/cross-origin-resource-sharing) - [Изоляция сайта для веб-разработчиков](https://developers.google.com/web/updates/2018/07/site-isolation) diff --git a/site/ru/docs/lighthouse/performance/bootup-time/index.md b/site/ru/docs/lighthouse/performance/bootup-time/index.md index cafff4484..42344d216 100644 --- a/site/ru/docs/lighthouse/performance/bootup-time/index.md +++ b/site/ru/docs/lighthouse/performance/bootup-time/index.md @@ -20,7 +20,7 @@ tags: - **Затраты на выполнение** - JavaScript-код выполняется в основном потоке. Кроме того, преждевременное выполнение на странице большого количества кода приводит к увеличению [времени до интерактивности (TTI)](https://web.dev/tti/), которое является одним из ключевых показателей, влияющих на субъективную скорость работы страницы. + JavaScript-код выполняется в основном потоке. Кроме того, преждевременное выполнение на странице большого количества кода приводит к увеличению [времени до интерактивности (TTI)](https://web.dev/articles/tti), которое является одним из ключевых показателей, влияющих на субъективную скорость работы страницы. - **Расход памяти** diff --git a/site/ru/docs/lighthouse/performance/critical-request-chains/index.md b/site/ru/docs/lighthouse/performance/critical-request-chains/index.md index 89210356f..df86d464d 100644 --- a/site/ru/docs/lighthouse/performance/critical-request-chains/index.md +++ b/site/ru/docs/lighthouse/performance/critical-request-chains/index.md @@ -28,7 +28,7 @@ Lighthouse использует сетевой приоритет в качес - Сократите объем критических ресурсов в байтах, чтобы уменьшить время их загрузки (количество циклов обмена). - Оптимизируйте порядок загрузки оставшихся критических ресурсов: загружайте все критические ресурсы как можно раньше, чтобы сократить длину критического пути. -Читайте подробнее об оптимизации [изображений](https://web.dev/use-imagemin-to-compress-images/), [JavaScript](https://web.dev/apply-instant-loading-with-prpl/), [CSS](https://web.dev/defer-non-critical-css/) и [веб-шрифтов](https://web.dev/avoid-invisible-text/). +Читайте подробнее об оптимизации [изображений](https://web.dev/articles/use-imagemin-to-compress-images), [JavaScript](https://web.dev/articles/apply-instant-loading-with-prpl), [CSS](https://web.dev/articles/defer-non-critical-css) и [веб-шрифтов](https://web.dev/articles/avoid-invisible-text). ## Рекомендации по стекам diff --git a/site/ru/docs/lighthouse/performance/dom-size/index.md b/site/ru/docs/lighthouse/performance/dom-size/index.md index 406b8ee81..c13537874 100644 --- a/site/ru/docs/lighthouse/performance/dom-size/index.md +++ b/site/ru/docs/lighthouse/performance/dom-size/index.md @@ -51,11 +51,11 @@ Lighthouse отмечает страницы со следующими дере ### Angular -Если вы визуализируете большие списки, используйте [виртуальную прокрутку](https://web.dev/virtualize-lists-with-angular-cdk/) с помощью Component Dev Kit (CDK). +Если вы визуализируете большие списки, используйте [виртуальную прокрутку](https://web.dev/articles/virtualize-lists-with-angular-cdk) с помощью Component Dev Kit (CDK). ### React -- Используйте «оконную» библиотеку, такую как [`react-window`](https://web.dev/virtualize-long-lists-react-window/), чтобы минимизировать количество создаваемых узлов DOM, если вы визуализируете много повторяющихся элементов на странице. +- Используйте «оконную» библиотеку, такую как [`react-window`](https://web.dev/articles/virtualize-long-lists-react-window), чтобы минимизировать количество создаваемых узлов DOM, если вы визуализируете много повторяющихся элементов на странице. - Сведите к минимуму ненужный повторный рендеринг, используя [`shouldComponentUpdate`](https://reactjs.org/docs/optimizing-performance.html#shouldcomponentupdate-in-action), [`PureComponent`](https://reactjs.org/docs/react-api.html#reactpurecomponent) или [`React.memo`](https://reactjs.org/docs/react-api.html#reactmemo). - Если вы используете хук `Effect` для повышения производительности во время выполнения, [пропускайте эффекты](https://reactjs.org/docs/hooks-effect.html#tip-optimizing-performance-by-skipping-effects) только до тех пор, пока не изменятся определенные зависимости. diff --git a/site/ru/docs/lighthouse/performance/first-contentful-paint/index.md b/site/ru/docs/lighthouse/performance/first-contentful-paint/index.md index d1e1ca0ef..ed918b6af 100644 --- a/site/ru/docs/lighthouse/performance/first-contentful-paint/index.md +++ b/site/ru/docs/lighthouse/performance/first-contentful-paint/index.md @@ -55,7 +55,7 @@ FCP измеряет, сколько времени требуется брау ## Отслеживайте FCP на устройствах реальных пользователей -Чтобы узнать, как измерять FCP на реальных устройствах пользователей, см. статью [Google «Ориентированные на пользователя показатели производительности».](https://web.dev/user-centric-performance-metrics/) В разделе [«Отслеживание FP/FCP»](https://developers.google.com/web/fundamentals/performance/user-centric-performance-metrics#tracking_fpfcp) описывается, как программно получить доступ к данным FCP и отправить их в Google Analytics. +Чтобы узнать, как измерять FCP на реальных устройствах пользователей, см. статью [Google «Ориентированные на пользователя показатели производительности».](https://web.dev/articles/user-centric-performance-metrics) В разделе [«Отслеживание FP/FCP»](https://developers.google.com/web/fundamentals/performance/user-centric-performance-metrics#tracking_fpfcp) описывается, как программно получить доступ к данным FCP и отправить их в Google Analytics. См. статью Google [«Оценка производительности загрузки в реальных условиях с помощью API Navigation Timing и API Resource Timing»](https://developers.google.com/web/fundamentals/performance/navigation-and-resource-timing/), чтобы узнать больше о сборе метрик реальных пользователей. @@ -64,6 +64,6 @@ FCP измеряет, сколько времени требуется брау ## Ресурсы - [Исходный код проверки **FCP**](https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/audits/metrics/first-contentful-paint.js). -- [Руководство по метрике FCP](https://web.dev/fcp/). -- [Руководство по оценке производительности в Lighthouse](https://web.dev/performance-scoring//). +- [Руководство по метрике FCP](https://web.dev/articles/fcp). +- [Руководство по оценке производительности в Lighthouse](https://web.dev/articles/performance-scoring/). - [Спецификация Paint Timing](https://w3c.github.io/paint-timing). diff --git a/site/ru/docs/lighthouse/performance/font-display/index.md b/site/ru/docs/lighthouse/performance/font-display/index.md index 40febda47..2a7d9c0e1 100644 --- a/site/ru/docs/lighthouse/performance/font-display/index.md +++ b/site/ru/docs/lighthouse/performance/font-display/index.md @@ -6,7 +6,7 @@ date: 2019-05-02 updated: 2020-04-29 --- -Шрифты часто представляют собой большие файлы, загрузка которых требует времени. Некоторые браузеры скрывают текст до загрузки шрифта, вызывая побочный эффект, известный как [мигание невидимого текста (FOIT)](https://web.dev/avoid-invisible-text/). +Шрифты часто представляют собой большие файлы, загрузка которых требует времени. Некоторые браузеры скрывают текст до загрузки шрифта, вызывая побочный эффект, известный как [мигание невидимого текста (FOIT)](https://web.dev/articles/avoid-invisible-text). ## Причины плохих результатов проверки отображения шрифтов в Lighthouse @@ -30,14 +30,14 @@ updated: 2020-04-29 } ``` -[API font-display](https://developer.mozilla.org/docs/Web/CSS/@font-face/font-display) определяет способ отображения шрифта. `swap` сообщает браузеру, что текст, использующий шрифт, должен немедленно отображаться с использованием системного шрифта. Когда пользовательский шрифт готов, он заменяет системный шрифт. (Для получения дополнительной информации см. статью [«Избегайте невидимого текста во время загрузки шрифта».)](https://web.dev/avoid-invisible-text/) +[API font-display](https://developer.mozilla.org/docs/Web/CSS/@font-face/font-display) определяет способ отображения шрифта. `swap` сообщает браузеру, что текст, использующий шрифт, должен немедленно отображаться с использованием системного шрифта. Когда пользовательский шрифт готов, он заменяет системный шрифт. (Для получения дополнительной информации см. статью [«Избегайте невидимого текста во время загрузки шрифта».)](https://web.dev/articles/avoid-invisible-text) ### Предварительно загрузите веб-шрифты Используйте `<link rel="preload" as="font">`, чтобы получить файлы шрифтов раньше. Дополнительные материалы: -- [Предварительная загрузка веб-шрифтов для повышения скорости загрузки (codelab)](https://web.dev/codelab-preload-web-fonts/). -- [Предотвращение смещения макета и мигания невидимого текста (FOIT) путем предварительной загрузки дополнительных шрифтов](https://web.dev/preload-optional-fonts/). +- [Предварительная загрузка веб-шрифтов для повышения скорости загрузки (codelab)](https://web.dev/articles/codelab-preload-web-fonts). +- [Предотвращение смещения макета и мигания невидимого текста (FOIT) путем предварительной загрузки дополнительных шрифтов](https://web.dev/articles/preload-optional-fonts). ### Шрифты Google @@ -66,7 +66,7 @@ updated: 2020-04-29 ## Ресурсы - [Исходный код проверки **Ensure text remains visible during webfont** (Убедитесь, что текст остается видимым во время загрузки веб-шрифтов)](https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/audits/font-display.js). -- [Избегайте невидимого текста во время загрузки шрифта](https://web.dev/avoid-invisible-text/). +- [Избегайте невидимого текста во время загрузки шрифта](https://web.dev/articles/avoid-invisible-text). - [Управление производительностью шрифтов с помощью отображения шрифтов](https://developers.google.com/web/updates/2016/02/font-display). -- [Предварительная загрузка веб-шрифтов для повышения скорости загрузки (codelab)](https://web.dev/codelab-preload-web-fonts/). -- [Предотвращение смещения макета и мигания невидимого текста (FOIT) путем предварительной загрузки дополнительных шрифтов](https://web.dev/preload-optional-fonts/). +- [Предварительная загрузка веб-шрифтов для повышения скорости загрузки (codelab)](https://web.dev/articles/codelab-preload-web-fonts). +- [Предотвращение смещения макета и мигания невидимого текста (FOIT) путем предварительной загрузки дополнительных шрифтов](https://web.dev/articles/preload-optional-fonts). diff --git a/site/ru/docs/lighthouse/performance/interactive/index.md b/site/ru/docs/lighthouse/performance/interactive/index.md index e47546ef4..8ca6d0ea5 100644 --- a/site/ru/docs/lighthouse/performance/interactive/index.md +++ b/site/ru/docs/lighthouse/performance/interactive/index.md @@ -22,7 +22,7 @@ Lighthouse отображает TTI в секундах: TTI измеряет, сколько времени требуется странице, чтобы стать *полностью* интерактивной. Страница считается полностью интерактивной, если: -- На странице отображается полезный контент, который измеряется с помощью показателя [First Contentful Paint](https://web.dev/fcp/), +- На странице отображается полезный контент, который измеряется с помощью показателя [First Contentful Paint](https://web.dev/articles/fcp), - Обработчики событий регистрируются для наиболее видимых элементов страницы, и - Страница реагирует на действия пользователя в течение 50 миллисекунд. @@ -63,7 +63,7 @@ TTI измеряет, сколько времени требуется стра ## Как улучшить оценку TTI -Одним из улучшений, которое может особенно сильно повлиять на TTI, является отсрочка или удаление ненужной работы JavaScript. Ищите возможности для [оптимизации вашего JavaScript](https://web.dev/fast/#optimize-your-javascript). В частности, рассмотрите возможность [уменьшения полезной нагрузки JavaScript за счет разделения кода](https://web.dev/reduce-javascript-payloads-with-code-splitting/) и [применения шаблона PRPL](https://web.dev/apply-instant-loading-with-prpl/). [Оптимизация стороннего JavaScript](https://web.dev/fast/#optimize-your-third-party-resources/) также дает значительные улучшения для некоторых сайтов. +Одним из улучшений, которое может особенно сильно повлиять на TTI, является отсрочка или удаление ненужной работы JavaScript. Ищите возможности для [оптимизации вашего JavaScript](https://web.dev/articles/fast#optimize_your_javascript). В частности, рассмотрите возможность [уменьшения полезной нагрузки JavaScript за счет разделения кода](https://web.dev/articles/reduce-javascript-payloads-with-code-splitting) и [применения шаблона PRPL](https://web.dev/articles/apply-instant-loading-with-prpl). [Оптимизация стороннего JavaScript](https://web.dev/articles/articles/fast#optimize_your_third_party_resources) также дает значительные улучшения для некоторых сайтов. Эти два диагностических аудита предоставляют дополнительные возможности для сокращения объема работы JavaScript: @@ -72,7 +72,7 @@ TTI измеряет, сколько времени требуется стра ## Отслеживание TTI на устройствах реальных пользователей -Чтобы узнать, как измерить реальное значение TTI на устройствах ваших пользователей, см. страницу Google [с показателями производительности, ориентированными на пользователя](https://web.dev/user-centric-performance-metrics/). В разделе [«Отслеживание TTI»](https://developers.google.com/web/fundamentals/performance/user-centric-performance-metrics#tracking_tti) описывается, как программно получить доступ к данным TTI и отправить их в Google Analytics. +Чтобы узнать, как измерить реальное значение TTI на устройствах ваших пользователей, см. страницу Google [с показателями производительности, ориентированными на пользователя](https://web.dev/articles/user-centric-performance-metrics). В разделе [«Отслеживание TTI»](https://developers.google.com/web/fundamentals/performance/user-centric-performance-metrics#tracking_tti) описывается, как программно получить доступ к данным TTI и отправить их в Google Analytics. {% Aside %} TTI может быть сложно отследить в естественных условиях. Отслеживая показатель [First Input Delay (задержка первого ввода)](https://developers.google.com/web/updates/2018/05/first-input-delay), можно получить достаточно близкое к TTI значение. {% endAside %} @@ -85,4 +85,4 @@ TTI измеряет, сколько времени требуется стра - [Первая интерактивность и полная интерактивность](https://docs.google.com/document/d/1GGiI9-7KeY3TPqS3YT271upUVimo-XiL5mwWorDUD4c/edit) - [Оптимизация запуска JavaScript](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/javascript-startup-optimization/) - [Уменьшение полезной нагрузки JavaScript с помощью Tree Shaking](https://developers.google.com/web/fundamentals/performance/optimizing-javascript/tree-shaking/) -- [Оптимизация сторонних ресурсов](https://web.dev/fast/#optimize-your-third-party-resources) +- [Оптимизация сторонних ресурсов](https://web.dev/articles/fast#optimize_your_third_party_resources) diff --git a/site/ru/docs/lighthouse/performance/lighthouse-largest-contentful-paint/index.md b/site/ru/docs/lighthouse/performance/lighthouse-largest-contentful-paint/index.md index 0e5d3fc02..502311de6 100644 --- a/site/ru/docs/lighthouse/performance/lighthouse-largest-contentful-paint/index.md +++ b/site/ru/docs/lighthouse/performance/lighthouse-largest-contentful-paint/index.md @@ -14,7 +14,7 @@ Lighthouse отображает LCP в секундах: ## Что измеряет LCP -LCP измеряет время до вывода на экран самого большого элемента контента в области просмотра. Это время примерно соответствует моменту, когда основное содержимое страницы становится видимым для пользователей. См. статью [«Скорость загрузки основного контента (LCP)»](https://web.dev/lcp/#what-is-lcp) для получения дополнительных сведений о том, как определяется LCP. +LCP измеряет время до вывода на экран самого большого элемента контента в области просмотра. Это время примерно соответствует моменту, когда основное содержимое страницы становится видимым для пользователей. См. статью [«Скорость загрузки основного контента (LCP)»](https://web.dev/articles/lcp#what_is_lcp) для получения дополнительных сведений о том, как определяется LCP. ## Как Lighthouse определяет LCP @@ -51,7 +51,7 @@ LCP измеряет время до вывода на экран самого ## Как улучшить свою оценку LCP -Ознакомьтесь с этой статьей [«Скорость загрузки основного контента (LCP)»](https://web.dev/lcp/#how-to-improve-lcp), чтобы узнать, как улучшить LCP для вашего сайта. +Ознакомьтесь с этой статьей [«Скорость загрузки основного контента (LCP)»](https://web.dev/articles/lcp#how_to_improve_lcp), чтобы узнать, как улучшить LCP для вашего сайта. ## Ресурсы diff --git a/site/ru/docs/lighthouse/performance/lighthouse-total-blocking-time/index.md b/site/ru/docs/lighthouse/performance/lighthouse-total-blocking-time/index.md index 951f83ced..6fb619130 100644 --- a/site/ru/docs/lighthouse/performance/lighthouse-total-blocking-time/index.md +++ b/site/ru/docs/lighthouse/performance/lighthouse-total-blocking-time/index.md @@ -14,7 +14,7 @@ updated: 2021-06-04 ## Что такое TBT -TBT — это общее время, в течение которого страница не может отвечать на пользовательский ввод, такой как щелчки мыши, касания экрана или нажатия на клавиатуру. Сумма рассчитывается путем сложения *блокирующей части* всех [длительных задач](https://web.dev/long-tasks-devtools/) в промежутке между [первой отрисовкой контента (FCP)](https://web.dev/fcp/) и [временем до интерактивности (TTI)](https://web.dev/tti/). Длительной задачей считается любая задача, которая выполняется более 50 мс. Время свыше 50 мс считается блокирующей частью. Например, если Lighthouse обнаруживает задачу длительностью в 70 мс, блокирующая часть будет составлять 20 мс. +TBT — это общее время, в течение которого страница не может отвечать на пользовательский ввод, такой как щелчки мыши, касания экрана или нажатия на клавиатуру. Сумма рассчитывается путем сложения *блокирующей части* всех [длительных задач](https://web.dev/articles/long-tasks-devtools) в промежутке между [первой отрисовкой контента (FCP)](https://web.dev/articles/fcp) и [временем до интерактивности (TTI)](https://web.dev/articles/tti). Длительной задачей считается любая задача, которая выполняется более 50 мс. Время свыше 50 мс считается блокирующей частью. Например, если Lighthouse обнаруживает задачу длительностью в 70 мс, блокирующая часть будет составлять 20 мс. ## Как Lighthouse рассчитывает оценку вашего TBT @@ -51,11 +51,11 @@ TBT — это общее время, в течение которого стр ## Как улучшить оценку TBT -Чтобы узнать, как при помощи панели «Производительность» в Chrome DevTools диагностировать основную причину появления длительных задач, см. статью [В чем причина появления длительных задач?](https://web.dev/long-tasks-devtools/#what-is-causing-my-long-tasks). +Чтобы узнать, как при помощи панели «Производительность» в Chrome DevTools диагностировать основную причину появления длительных задач, см. статью [В чем причина появления длительных задач?](https://web.dev/articles/long-tasks-devtools#what_is_causing_my_long_tasks). Вот наиболее распространенные причины появления длительных задач: -- Загрузка, обработка или выполнение ненужного JavaScript-кода. В ходе анализа кода при помощи панели «Производительность» может выясниться, что основной поток выполняет работу, которая на самом деле не требуется для загрузки страницы. Улучшить оценку TBT можно посредством [сокращения полезной нагрузки JavaScript с помощью разделения кода](https://web.dev/reduce-javascript-payloads-with-code-splitting/), [удаления неиспользуемого кода](https://web.dev/remove-unused-code/) или [эффективной загрузки стороннего JavaScript](https://web.dev/efficiently-load-third-party-javascript/). +- Загрузка, обработка или выполнение ненужного JavaScript-кода. В ходе анализа кода при помощи панели «Производительность» может выясниться, что основной поток выполняет работу, которая на самом деле не требуется для загрузки страницы. Улучшить оценку TBT можно посредством [сокращения полезной нагрузки JavaScript с помощью разделения кода](https://web.dev/articles/reduce-javascript-payloads-with-code-splitting), [удаления неиспользуемого кода](https://web.dev/articles/remove-unused-code) или [эффективной загрузки стороннего JavaScript](https://web.dev/articles/efficiently-load-third-party-javascript). - Неэффективные JavaScript-инструкции. Например, предположим, что в ходе анализа кода при помощи панели «Производительность» вы обнаружили вызов `document.querySelectorAll('a')`, возвращающий 2000 узлов. Чтобы улучшить оценку TBT, можно перестроить код, заменив селектор на более избирательный, возвращающий только 10 узлов. {% Aside %} На большинстве сайтов устранение загрузки, обработки или выполнения ненужного JavaScript-кода обычно позволяет добиться гораздо более серьезных улучшений. {% endAside %} @@ -65,10 +65,10 @@ TBT — это общее время, в течение которого стр ## Ресурсы - [Исходный код проверки **Total Blocking Time (общее время блокировки)**](https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/audits/metrics/total-blocking-time.js) -- [Увеличено ли у вас время до интерактивности (TTI) из-за длительных JavaScript-задач?](https://web.dev/long-tasks-devtools/) -- [Оптимизация времени ожидания до первого взаимодействия с контентом (FID)](https://web.dev/optimize-fid/) -- [Первая отрисовка контента (FCP)](https://web.dev/fcp/) -- [Время до интерактивности (TTI)](https://web.dev/tti/) -- [Сокращение размера полезной нагрузки JavaScript за счет разделения кода](https://web.dev/reduce-javascript-payloads-with-code-splitting/) -- [Удаление неиспользуемого кода](https://web.dev/remove-unused-code/) -- [Эффективная загрузка сторонних ресурсов](https://web.dev/efficiently-load-third-party-javascript/) +- [Увеличено ли у вас время до интерактивности (TTI) из-за длительных JavaScript-задач?](https://web.dev/articles/long-tasks-devtools) +- [Оптимизация времени ожидания до первого взаимодействия с контентом (FID)](https://web.dev/articles/optimize-fid) +- [Первая отрисовка контента (FCP)](https://web.dev/articles/fcp) +- [Время до интерактивности (TTI)](https://web.dev/articles/tti) +- [Сокращение размера полезной нагрузки JavaScript за счет разделения кода](https://web.dev/articles/reduce-javascript-payloads-with-code-splitting) +- [Удаление неиспользуемого кода](https://web.dev/articles/remove-unused-code) +- [Эффективная загрузка сторонних ресурсов](https://web.dev/articles/efficiently-load-third-party-javascript) diff --git a/site/ru/docs/lighthouse/performance/mainthread-work-breakdown/index.md b/site/ru/docs/lighthouse/performance/mainthread-work-breakdown/index.md index ad75f8791..4427b5c3e 100644 --- a/site/ru/docs/lighthouse/performance/mainthread-work-breakdown/index.md +++ b/site/ru/docs/lighthouse/performance/mainthread-work-breakdown/index.md @@ -32,9 +32,9 @@ updated: 2019-10-04 ### Оценка скриптов -- [Оптимизация стороннего JavaScript](https://web.dev/fast/#optimize-your-third-party-resources) +- [Оптимизация стороннего JavaScript](https://web.dev/articles/fast#optimize_your_third_party_resources) - [Устранение обработчиков ввода](https://developers.google.com/web/fundamentals/performance/rendering/debounce-your-input-handlers) -- [Использование веб-воркеров](https://web.dev/off-main-thread/) +- [Использование веб-воркеров](https://web.dev/articles/off-main-thread) ### Стили и верстка @@ -48,18 +48,18 @@ updated: 2019-10-04 ### Анализ HTML и CSS -- [Извлечение критического CSS](https://web.dev/extract-critical-css/) -- [Минимизация CSS](https://web.dev/minify-css/) -- [Откладывание некритического CSS](https://web.dev/defer-non-critical-css/) +- [Извлечение критического CSS](https://web.dev/articles/extract-critical-css) +- [Минимизация CSS](https://web.dev/articles/minify-css) +- [Откладывание некритического CSS](https://web.dev/articles/defer-non-critical-css) ### Анализ и компиляция скрипта -- [Уменьшение полезной нагрузки JavaScript за счет разделения кода](https://web.dev/reduce-javascript-payloads-with-code-splitting/) -- [Удаление неиспользуемого кода](https://web.dev/remove-unused-code/) +- [Уменьшение полезной нагрузки JavaScript за счет разделения кода](https://web.dev/articles/reduce-javascript-payloads-with-code-splitting) +- [Удаление неиспользуемого кода](https://web.dev/articles/remove-unused-code) ### Сбор мусора -- [Контроль общего использования памяти вашей веб-страницей с помощью `measureMemory()`](https://web.dev/monitor-total-page-memory-usage/) +- [Контроль общего использования памяти вашей веб-страницей с помощью `measureMemory()`](https://web.dev/articles/monitor-total-page-memory-usage) ## Ресурсы diff --git a/site/ru/docs/lighthouse/performance/non-composited-animations/index.md b/site/ru/docs/lighthouse/performance/non-composited-animations/index.md index 02f04c286..f6517eeae 100644 --- a/site/ru/docs/lighthouse/performance/non-composited-animations/index.md +++ b/site/ru/docs/lighthouse/performance/non-composited-animations/index.md @@ -5,7 +5,7 @@ description: Как пройти проверку «Avoid non-composited animati date: 2020-08-12 --- -Анимация, выполняемая за пределами этапа компоновки, может выглядеть «рваной» (т. е. не быть плавной) на медленных телефонах или во время выполнения ресурсоемких задач в основном потоке. Дергающиеся анимации могут увеличивать показатель [Cumulative Layout Shift](https://web.dev/cls/) (совокупное смещение макета, CLS) вашей страницы. Снижение CLS помогает улучшить оценку производительности в Lighthouse. +Анимация, выполняемая за пределами этапа компоновки, может выглядеть «рваной» (т. е. не быть плавной) на медленных телефонах или во время выполнения ресурсоемких задач в основном потоке. Дергающиеся анимации могут увеличивать показатель [Cumulative Layout Shift](https://web.dev/articles/cls) (совокупное смещение макета, CLS) вашей страницы. Снижение CLS помогает улучшить оценку производительности в Lighthouse. ## Предыстория @@ -27,12 +27,12 @@ date: 2020-08-12 ## Как обеспечить анимацию в рамках этапа компоновки -См. статьи [Используйте свойства, вызывающие только компоновку, и контролируйте количество слоев](https://developers.google.com/web/fundamentals/performance/rendering/stick-to-compositor-only-properties-and-manage-layer-count) и [Высокопроизводительная анимация](https://web.dev/animations-guide/). +См. статьи [Используйте свойства, вызывающие только компоновку, и контролируйте количество слоев](https://developers.google.com/web/fundamentals/performance/rendering/stick-to-compositor-only-properties-and-manage-layer-count) и [Высокопроизводительная анимация](https://web.dev/articles/animations-guide). ## Ресурсы - [Исходный код проверки *Avoid non-composited animations*](https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/audits/non-composited-animations.js) - [Используйте свойства, вызывающие только компоновку, и контролируйте количество слоев](https://developers.google.com/web/fundamentals/performance/rendering/stick-to-compositor-only-properties-and-manage-layer-count) -- [Высокопроизводительная анимация](https://web.dev/animations-guide/) +- [Высокопроизводительная анимация](https://web.dev/articles/animations-guide) - [Упрощение и сокращение областей прорисовки](https://developers.google.com/web/fundamentals/performance/rendering/simplify-paint-complexity-and-reduce-paint-areas) - [Взгляд изнутри на современные веб-браузеры (часть 3)](https://developers.google.com/web/updates/2018/09/inside-browser-part3) diff --git a/site/ru/docs/lighthouse/performance/offscreen-images/index.md b/site/ru/docs/lighthouse/performance/offscreen-images/index.md index 4c3b85b7a..a24fd614b 100644 --- a/site/ru/docs/lighthouse/performance/offscreen-images/index.md +++ b/site/ru/docs/lighthouse/performance/offscreen-images/index.md @@ -8,7 +8,7 @@ date: 2019-05-02 updated: 2020-05-29 --- -В разделе «Возможности» вашего отчета Lighthouse перечислены все закадровые или скрытые изображения на вашей странице, а также потенциальная экономия в [кибибайтах (KiB)](https://en.wikipedia.org/wiki/Kibibyte). Рассмотрите возможность отложенной загрузки этих изображений после завершения загрузки всех критически важных ресурсов, чтобы сократить показатель [Time to Interactive (время до интерактивности)](https://web.dev/tti/): +В разделе «Возможности» вашего отчета Lighthouse перечислены все закадровые или скрытые изображения на вашей странице, а также потенциальная экономия в [кибибайтах (KiB)](https://en.wikipedia.org/wiki/Kibibyte). Рассмотрите возможность отложенной загрузки этих изображений после завершения загрузки всех критически важных ресурсов, чтобы сократить показатель [Time to Interactive (время до интерактивности)](https://web.dev/articles/tti): <figure>{% Img src="image/tcFciHGuF3MxnTr1y5ue01OGLBn2/agMyJtIarLruD8iuz0Mt.png", alt="Снимок экрана аудита откладывания закадровых изображений Lighthouse", width="800", height="416" %}</figure> @@ -30,7 +30,7 @@ updated: 2020-05-29 ### Magento -Рассмотрите возможность изменения шаблонов продуктов и каталогов, чтобы использовать функцию [отложенной загрузки](https://web.dev/browser-level-image-lazy-loading/) веб-платформы. +Рассмотрите возможность изменения шаблонов продуктов и каталогов, чтобы использовать функцию [отложенной загрузки](https://web.dev/articles/browser-level-image-lazy-loading) веб-платформы. ### WordPress diff --git a/site/ru/docs/lighthouse/performance/performance-scoring/index.md b/site/ru/docs/lighthouse/performance/performance-scoring/index.md index 2b4333b70..c03260ce8 100644 --- a/site/ru/docs/lighthouse/performance/performance-scoring/index.md +++ b/site/ru/docs/lighthouse/performance/performance-scoring/index.md @@ -23,7 +23,7 @@ updated: 2021-06-04 Эта проблема более подробно рассмотрена в [документации Lighthouse по изменчивости оценки](https://github.com/GoogleChrome/lighthouse/blob/master/docs/variability.md). -Более того, даже если Lighthouse может предоставить вам единую общую оценку производительности, более полезно рассматривать производительность сайта как распределение оценок, а не как единое число. Ознакомьтесь с вводной статьей [«Ориентированные на пользователя показатели производительности»](https://web.dev/user-centric-performance-metrics/), чтобы понять причины такого подхода. +Более того, даже если Lighthouse может предоставить вам единую общую оценку производительности, более полезно рассматривать производительность сайта как распределение оценок, а не как единое число. Ознакомьтесь с вводной статьей [«Ориентированные на пользователя показатели производительности»](https://web.dev/articles/user-centric-performance-metrics), чтобы понять причины такого подхода. ## Как рассчитывается средневзвешенная оценка производительности {: #weightings} diff --git a/site/ru/docs/lighthouse/performance/render-blocking-resources/index.md b/site/ru/docs/lighthouse/performance/render-blocking-resources/index.md index fbf08192f..3b4b66d5f 100644 --- a/site/ru/docs/lighthouse/performance/render-blocking-resources/index.md +++ b/site/ru/docs/lighthouse/performance/render-blocking-resources/index.md @@ -46,13 +46,13 @@ updated: 2020-08-11 ## Как избавиться от таблиц стилей, блокирующих рендеринг -Используйте прием, аналогичный переносу критического кода во встроенный тег `<script>`, встройте критические стили, необходимые для первой отрисовки, в блок `<style>` элемента `head` HTML-страницы. Затем асинхронно загрузите остальные стили, используя ссылку `preload` (см. статью [«Отложите загрузку неиспользуемого CSS»](https://web.dev/defer-non-critical-css/)). +Используйте прием, аналогичный переносу критического кода во встроенный тег `<script>`, встройте критические стили, необходимые для первой отрисовки, в блок `<style>` элемента `head` HTML-страницы. Затем асинхронно загрузите остальные стили, используя ссылку `preload` (см. статью [«Отложите загрузку неиспользуемого CSS»](https://web.dev/articles/defer-non-critical-css)). Подумайте об автоматизации процесса извлечения и встраивания CSS верхней половины полосы с помощью [инструмента Critical](https://github.com/addyosmani/critical/blob/master/README.md). Другой подход к устранению стилей, блокирующих рендеринг, — это разделить эти стили на разные файлы, организованные по медиа-запросам. Затем добавьте атрибут media к каждой ссылке таблицы стилей. При загрузке страницы браузер блокирует только первую отрисовку, чтобы получить таблицы стилей, соответствующие устройству пользователя (см. статью [«Блокирующий рендеринг CSS»](https://developers.google.com/web/fundamentals/performance/critical-rendering-path/render-blocking-css)). -Наконец, вы захотите выполнить минификацию CSS-кода, чтобы удалить лишние пробелы или символы (см. статью [«Выполните минификацию CSS-кода»](https://web.dev/minify-css/)). Это гарантирует, что вы отправите пользователям минимально возможный бандл. +Наконец, вы захотите выполнить минификацию CSS-кода, чтобы удалить лишние пробелы или символы (см. статью [«Выполните минификацию CSS-кода»](https://web.dev/articles/minify-css)). Это гарантирует, что вы отправите пользователям минимально возможный бандл. ## Рекомендации по стекам @@ -75,6 +75,6 @@ updated: 2020-08-11 ## Ресурсы - [Исходный код проверки **Eliminate render-blocking resources** (Устраните ресурсы, блокирующие рендеринг)](https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/audits/byte-efficiency/render-blocking-resources.js). -- [Сократите полезную нагрузку JavaScript за счет разделения кода](https://web.dev/reduce-javascript-payloads-with-code-splitting/). -- [Удалите неиспользуемый код (codelab)](https://web.dev/codelab-remove-unused-code//). +- [Сократите полезную нагрузку JavaScript за счет разделения кода](https://web.dev/articles/reduce-javascript-payloads-with-code-splitting). +- [Удалите неиспользуемый код (codelab)](https://web.dev/articles/codelab-remove-unused-code/). - [Оптимизация загрузки JavaScript](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/javascript-startup-optimization/). diff --git a/site/ru/docs/lighthouse/performance/server-response-time/index.md b/site/ru/docs/lighthouse/performance/server-response-time/index.md index 6015e59ea..96e61a733 100644 --- a/site/ru/docs/lighthouse/performance/server-response-time/index.md +++ b/site/ru/docs/lighthouse/performance/server-response-time/index.md @@ -51,4 +51,4 @@ updated: 2019-10-04 ## Ресурсы - [Исходный код проверки **Reduce server response times (TTFB)** (Сократите время ответа сервера (TTFB))](https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/audits/server-response-time.js). -- [Адаптивное обслуживание с Network Information API](https://web.dev/adaptive-serving-based-on-network-quality/). +- [Адаптивное обслуживание с Network Information API](https://web.dev/articles/adaptive-serving-based-on-network-quality). diff --git a/site/ru/docs/lighthouse/performance/speed-index/index.md b/site/ru/docs/lighthouse/performance/speed-index/index.md index 569964b8d..99a7c99b6 100644 --- a/site/ru/docs/lighthouse/performance/speed-index/index.md +++ b/site/ru/docs/lighthouse/performance/speed-index/index.md @@ -59,7 +59,7 @@ Lighthouse отображает индекс скорости в секунда - [Минимизация работы основного потока](/docs/lighthouse/performance/mainthread-work-breakdown/) - [Уменьшение времени выполнения JavaScript](/docs/lighthouse/performance/bootup-time/) -- [Убедитесь, что текст остается видимым во время загрузки веб-шрифта](https://web.dev/font-display/) +- [Убедитесь, что текст остается видимым во время загрузки веб-шрифта](https://web.dev/articles/font-display) {% Partial 'lighthouse-performance/improve.njk' %} diff --git a/site/ru/docs/lighthouse/performance/third-party-facades/index.md b/site/ru/docs/lighthouse/performance/third-party-facades/index.md index 0298f487b..050e22dbe 100644 --- a/site/ru/docs/lighthouse/performance/third-party-facades/index.md +++ b/site/ru/docs/lighthouse/performance/third-party-facades/index.md @@ -7,7 +7,7 @@ description: |2 date: 2020-12-01 --- -[Сторонние ресурсы](https://web.dev/third-party-javascript/) часто используются для показа рекламы или видео и интеграции с социальными сетями. По умолчанию сторонние ресурсы загружаются сразу после загрузки страницы, однако такой подход может излишне ее замедлить. Если сторонний контент не критичен, затраты на производительность можно снизить за счет [отложенной загрузки](https://web.dev/fast/#lazy-load-images-and-video). +[Сторонние ресурсы](https://web.dev/articles/third-party-javascript) часто используются для показа рекламы или видео и интеграции с социальными сетями. По умолчанию сторонние ресурсы загружаются сразу после загрузки страницы, однако такой подход может излишне ее замедлить. Если сторонний контент не критичен, затраты на производительность можно снизить за счет [отложенной загрузки](https://web.dev/articles/fast#lazy_load_images_and_video). Этот аудит выявляет сторонние встраиваемые файлы, для которых можно выполнить отложенную загрузку при взаимодействии. В этом случае вместо стороннего контента используется *фасад* до тех пор, пока пользователь не начнет с ним взаимодействовать. diff --git a/site/ru/docs/lighthouse/performance/total-byte-weight/index.md b/site/ru/docs/lighthouse/performance/total-byte-weight/index.md index 65dc6826c..02a035c0d 100644 --- a/site/ru/docs/lighthouse/performance/total-byte-weight/index.md +++ b/site/ru/docs/lighthouse/performance/total-byte-weight/index.md @@ -22,22 +22,22 @@ updated: 2020-05-29 ## Как уменьшить размер нагрузки на сеть -Старайтесь, чтобы общий размер в байтах не превышал 1600 КиБ. Этот целевой показатель основан на объеме данных, который теоретически может быть загружен через соединение 3G, при этом метрика [TTI (Время до интерактивности)](https://web.dev/tti/) должна составлять не более 10 секунд. +Старайтесь, чтобы общий размер в байтах не превышал 1600 КиБ. Этот целевой показатель основан на объеме данных, который теоретически может быть загружен через соединение 3G, при этом метрика [TTI (Время до интерактивности)](https://web.dev/articles/tti) должна составлять не более 10 секунд. Вот несколько способов уменьшить размер нагрузки на сеть: -- Откладывайте запросы до тех пор, пока они не понадобятся. Один из возможных подходов см. в статье о [шаблоне PRPL](https://web.dev/apply-instant-loading-with-prpl/). +- Откладывайте запросы до тех пор, пока они не понадобятся. Один из возможных подходов см. в статье о [шаблоне PRPL](https://web.dev/articles/apply-instant-loading-with-prpl). - Оптимизируйте запросы, чтобы максимально уменьшить их размер. Возможные методы: - - [Выполните минификацию и сжатие сетевых данных](https://web.dev/reduce-network-payloads-using-text-compression/). - - [Используйте формат изображений WebP вместо JPEG или PNG](https://web.dev/serve-images-webp/). - - [Установите уровень сжатия изображений в формате JPEG на 85](https://web.dev/use-imagemin-to-compress-images/). -- Кешируйте запросы, чтобы страница не загружала ресурсы заново при повторном посещении. (См. [целевую страницу «Надежность сети»](https://web.dev/reliable/), чтобы узнать, как работает кеширование и как его реализовать.) + - [Выполните минификацию и сжатие сетевых данных](https://web.dev/articles/reduce-network-payloads-using-text-compression). + - [Используйте формат изображений WebP вместо JPEG или PNG](https://web.dev/articles/serve-images-webp). + - [Установите уровень сжатия изображений в формате JPEG на 85](https://web.dev/articles/use-imagemin-to-compress-images). +- Кешируйте запросы, чтобы страница не загружала ресурсы заново при повторном посещении. (См. [целевую страницу «Надежность сети»](https://web.dev/explore/reliable), чтобы узнать, как работает кеширование и как его реализовать.) ## Рекомендации по стекам ### Angular -Применяйте [разделение кода на уровне маршрута](https://web.dev/route-level-code-splitting-in-angular/), чтобы минимизировать размер пакетов JavaScript. Подумайте также о предварительном кешировании активов с помощью [Angular service worker](https://web.dev/precaching-with-the-angular-service-worker/). +Применяйте [разделение кода на уровне маршрута](https://web.dev/articles/route-level-code-splitting-in-angular), чтобы минимизировать размер пакетов JavaScript. Подумайте также о предварительном кешировании активов с помощью [Angular service worker](https://web.dev/articles/precaching-with-the-angular-service-worker). ### Drupal diff --git a/site/ru/docs/lighthouse/performance/unused-css-rules/index.md b/site/ru/docs/lighthouse/performance/unused-css-rules/index.md index ba3daf13c..f40c90985 100644 --- a/site/ru/docs/lighthouse/performance/unused-css-rules/index.md +++ b/site/ru/docs/lighthouse/performance/unused-css-rules/index.md @@ -44,7 +44,7 @@ updated: 2020-05-29 Подумайте об автоматизации процесса извлечения и встраивания CSS-кода верхней половины полосы с помощью [инструмента Critical](https://github.com/addyosmani/critical/blob/master/README.md). -Дополнительные сведения см. в статье [«Отложите некритичный CSS-код»](https://web.dev/defer-non-critical-css/). +Дополнительные сведения см. в статье [«Отложите некритичный CSS-код»](https://web.dev/articles/defer-non-critical-css). ## Рекомендации по стекам diff --git a/site/ru/docs/lighthouse/performance/unused-javascript/index.md b/site/ru/docs/lighthouse/performance/unused-javascript/index.md index ebec4267a..e39f9dba2 100644 --- a/site/ru/docs/lighthouse/performance/unused-javascript/index.md +++ b/site/ru/docs/lighthouse/performance/unused-javascript/index.md @@ -54,7 +54,7 @@ date: 2020-07-07 ### React -Если вы не выполняете рендеринг на стороне сервера, [разделите бандлы JavaScript](https://web.dev/code-splitting-suspense/) с помощью `React.lazy()`. В противном случае разделите код с помощью сторонней библиотеки, такой как [loadable-components](https://www.smooth-code.com/open-source/loadable-components/docs/getting-started/). +Если вы не выполняете рендеринг на стороне сервера, [разделите бандлы JavaScript](https://web.dev/articles/code-splitting-suspense) с помощью `React.lazy()`. В противном случае разделите код с помощью сторонней библиотеки, такой как [loadable-components](https://www.smooth-code.com/open-source/loadable-components/docs/getting-started/). ### Vue @@ -67,7 +67,7 @@ date: 2020-07-07 ## Ресурсы - [Исходный код для проверки **Remove unused code** (Удалите неиспользуемый код)](https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/audits/byte-efficiency/unused-javascript.js). -- [Удалите неиспользуемый код](https://web.dev/remove-unused-code/). +- [Удалите неиспользуемый код](https://web.dev/articles/remove-unused-code). - [Добавление интерактивности с помощью JavaScript](https://developers.google.com/web/fundamentals/performance/critical-rendering-path/adding-interactivity-with-javascript). - [Разделение кода](https://bundlers.tooling.report/code-splitting/). - [Устранение мертвого кода](https://bundlers.tooling.report/transformations/dead-code/). diff --git a/site/ru/docs/lighthouse/performance/uses-long-cache-ttl/index.md b/site/ru/docs/lighthouse/performance/uses-long-cache-ttl/index.md index 14213fc47..e7f3ccd30 100644 --- a/site/ru/docs/lighthouse/performance/uses-long-cache-ttl/index.md +++ b/site/ru/docs/lighthouse/performance/uses-long-cache-ttl/index.md @@ -63,7 +63,7 @@ Cache-Control: max-age=31536000 Более длительный срок хранения кеша не всегда лучше. В конечном итоге вам решать, какова оптимальная продолжительность кеширования ресурсов. -Существует множество директив для настройки того, как браузер кеширует различные ресурсы. Дополнительные сведения о кешировании ресурсов см. в статьях [«HTTP-кеширование: руководство по первой линии обороны»](https://web.dev/http-cache/) и [«Codelab для настройки поведения HTTP-кеширования»](https://web.dev/codelab-http-cache/). +Существует множество директив для настройки того, как браузер кеширует различные ресурсы. Дополнительные сведения о кешировании ресурсов см. в статьях [«HTTP-кеширование: руководство по первой линии обороны»](https://web.dev/articles/http-cache) и [«Codelab для настройки поведения HTTP-кеширования»](https://web.dev/articles/codelab-http-cache). ## Как проверить кешированные ответы в Chrome DevTools diff --git a/site/ru/docs/lighthouse/performance/uses-optimized-images/index.md b/site/ru/docs/lighthouse/performance/uses-optimized-images/index.md index 7a6d71f90..ba0c1c781 100644 --- a/site/ru/docs/lighthouse/performance/uses-optimized-images/index.md +++ b/site/ru/docs/lighthouse/performance/uses-optimized-images/index.md @@ -20,13 +20,13 @@ Lighthouse находит все изображения в формате JPEG Оптимизировать изображения можно многими способами, в том числе указанными ниже. -- [Использование сетей доставки контента (CDN) для изображений](https://web.dev/image-cdns/) -- [Сжатие изображений](https://web.dev/use-imagemin-to-compress-images/) -- [Замена анимированных GIF-файлов видеофайлами](https://web.dev/replace-gifs-with-videos/) -- [Отложенная загрузка изображений](https://web.dev/use-lazysizes-to-lazyload-images/) -- [Передача адаптивных изображений](https://web.dev/serve-responsive-images/) -- [Передача изображений с правильными размерами](https://web.dev/serve-images-with-correct-dimensions/) -- [Использование изображений WebP](https://web.dev/serve-images-webp/) +- [Использование сетей доставки контента (CDN) для изображений](https://web.dev/articles/image-cdns) +- [Сжатие изображений](https://web.dev/articles/use-imagemin-to-compress-images) +- [Замена анимированных GIF-файлов видеофайлами](https://web.dev/articles/replace-gifs-with-videos) +- [Отложенная загрузка изображений](https://web.dev/articles/use-lazysizes-to-lazyload-images) +- [Передача адаптивных изображений](https://web.dev/articles/serve-responsive-images) +- [Передача изображений с правильными размерами](https://web.dev/articles/serve-images-with-correct-dimensions) +- [Использование изображений WebP](https://web.dev/articles/serve-images-webp) ## Оптимизация изображений с помощью средств с графическим пользовательским интерфейсом diff --git a/site/ru/docs/lighthouse/performance/uses-rel-preconnect/index.md b/site/ru/docs/lighthouse/performance/uses-rel-preconnect/index.md index be1ee74f3..93bf08461 100644 --- a/site/ru/docs/lighthouse/performance/uses-rel-preconnect/index.md +++ b/site/ru/docs/lighthouse/performance/uses-rel-preconnect/index.md @@ -57,5 +57,5 @@ updated: 2020-05-06 - [Исходный код проверки **Preconnect to required origins (Используйте предварительное подключение к необходимым доменам)**](https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/audits/uses-rel-preconnect.js). - [Приоритизация ресурсов — как заставить браузер помочь вам](https://developers.google.com/web/fundamentals/performance/resource-prioritization#preconnect). -- [Устанавливайте сетевые подключения заранее, чтобы улучшить воспринимаемую скорость загрузки страницы](https://web.dev/preconnect-and-dns-prefetch/). +- [Устанавливайте сетевые подключения заранее, чтобы улучшить воспринимаемую скорость загрузки страницы](https://web.dev/articles/preconnect-and-dns-prefetch). - [Типы ссылок: preconnect](https://developer.mozilla.org/docs/Web/HTML/Link_types/preconnect#Browser_compatibility). diff --git a/site/ru/docs/lighthouse/performance/uses-rel-preload/index.md b/site/ru/docs/lighthouse/performance/uses-rel-preload/index.md index bc35acf58..3c9a4273d 100644 --- a/site/ru/docs/lighthouse/performance/uses-rel-preload/index.md +++ b/site/ru/docs/lighthouse/performance/uses-rel-preload/index.md @@ -46,7 +46,7 @@ index.html <figure>{% Img src="image/tcFciHGuF3MxnTr1y5ue01OGLBn2/tJLJXH2qXcrDBUfsSAK5.png", alt="Если предварительная загрузка настроена, styles.css и ui.js запрашиваются одновременно с app.js.", width="800", height="478" %} <figcaption> Если предварительная загрузка настроена, <code>styles.css</code> и <code>ui.js</code> запрашиваются одновременно с <code>app.js</code>. </figcaption></figure> -Более подробная информация приведена в статье [«Настройте предварительную загрузку критически важных ресурсов для повышения скорости загрузки»](https://web.dev/preload-critical-assets/). +Более подробная информация приведена в статье [«Настройте предварительную загрузку критически важных ресурсов для повышения скорости загрузки»](https://web.dev/articles/preload-critical-assets). ### Совместимость с браузером @@ -60,7 +60,7 @@ index.html ### Angular -[Предварительно загружайте маршруты](https://web.dev/route-preloading-in-angular/), чтобы ускорить навигацию. +[Предварительно загружайте маршруты](https://web.dev/articles/route-preloading-in-angular), чтобы ускорить навигацию. ### Magento diff --git a/site/ru/docs/lighthouse/performance/uses-responsive-images/index.md b/site/ru/docs/lighthouse/performance/uses-responsive-images/index.md index 2d123a29f..20547302c 100644 --- a/site/ru/docs/lighthouse/performance/uses-responsive-images/index.md +++ b/site/ru/docs/lighthouse/performance/uses-responsive-images/index.md @@ -18,9 +18,9 @@ Lighthouse сравнивает размер каждого отрисованн В идеале ваша страница не должна содержать изображения, размер которых превышает размер изображений, отображаемых на экране пользователя. Это приводит к напрасной трате байтов и замедляет время загрузки страницы. -Современный подход к предоставлению изображений правильного размера получил название «отзывчивые изображения». При использовании отзывчивых изображений вы создаете несколько версий каждого изображения, а затем с помощью медиа-запросов указываете, какую версию применять в HTML или CSS, а также прописываете размеры области просмотра и так далее. Дополнительные сведения см. в статье [«Предоставляйте отзывчивые изображения»](https://web.dev/serve-responsive-images/). +Современный подход к предоставлению изображений правильного размера получил название «отзывчивые изображения». При использовании отзывчивых изображений вы создаете несколько версий каждого изображения, а затем с помощью медиа-запросов указываете, какую версию применять в HTML или CSS, а также прописываете размеры области просмотра и так далее. Дополнительные сведения см. в статье [«Предоставляйте отзывчивые изображения»](https://web.dev/articles/serve-responsive-images). -[CDN для изображений](https://web.dev/image-cdns/) — это ещё один современный подход к предоставлению изображений подходящего размера. CDN для изображений можно рассматривать в качестве веб-API для преобразования изображений. +[CDN для изображений](https://web.dev/articles/image-cdns) — это ещё один современный подход к предоставлению изображений подходящего размера. CDN для изображений можно рассматривать в качестве веб-API для преобразования изображений. Другой подход заключается в применении векторных форматов изображений, таких как SVG. Изображения в формате SVG можно масштабировать до любого размера с помощью небольшого объема кода. Дополнительные сведения см. в разделе [«Замените сложные значки на SVG-иконки»](https://developers.google.com/web/fundamentals/design-and-ux/responsive/images#replace_complex_icons_with_svg). @@ -30,7 +30,7 @@ Lighthouse сравнивает размер каждого отрисованн ### AMP -Применяйте атрибут [`srcset`](https://amp.dev/documentation/components/amp-img/?format=websites) для компонента [`amp-img`](https://web.dev/use-srcset-to-automatically-choose-the-right-image/), чтобы указать, какие файлы изображений использовать в зависимости от размера экрана. См. также статью [«Создание отзывчивых изображений с помощью атрибутов srcset, sizes и heights»](https://amp.dev/documentation/guides-and-tutorials/develop/style_and_layout/art_direction/). +Применяйте атрибут [`srcset`](https://amp.dev/documentation/components/amp-img/?format=websites) для компонента [`amp-img`](https://web.dev/articles/use-srcset-to-automatically-choose-the-right-image), чтобы указать, какие файлы изображений использовать в зависимости от размера экрана. См. также статью [«Создание отзывчивых изображений с помощью атрибутов srcset, sizes и heights»](https://amp.dev/documentation/guides-and-tutorials/develop/style_and_layout/art_direction/). ### Angular @@ -55,4 +55,4 @@ Lighthouse сравнивает размер каждого отрисованн ## Ресурсы - [Исходный код проверки **Properly size images** (Выбирайте размер изображений правильно)](https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/audits/byte-efficiency/uses-responsive-images.js). -- [Предоставляйте изображения с правильными размерами](https://web.dev/serve-images-with-correct-dimensions/). +- [Предоставляйте изображения с правильными размерами](https://web.dev/articles/serve-images-with-correct-dimensions). diff --git a/site/ru/docs/lighthouse/performance/uses-text-compression/index.md b/site/ru/docs/lighthouse/performance/uses-text-compression/index.md index df519af2f..9a192cf26 100644 --- a/site/ru/docs/lighthouse/performance/uses-text-compression/index.md +++ b/site/ru/docs/lighthouse/performance/uses-text-compression/index.md @@ -66,7 +66,7 @@ Lighthouse собирает все ответы, в которых: 3. Включите поддержку больших строк запросов. См. раздел [Использование больших строк запросов](https://developers.google.com/web/tools/chrome-devtools/network/reference#request-rows) . 4. Посмотрите столбец **Size** (Размер) для интересующего вас ответа. Верхнее значение — размер сжатых данных, нижнее значение — размер несжатых данных. -См. также раздел [Уменьшение и сжатие сетевых данных](https://web.dev/reduce-network-payloads-using-text-compression/) . +См. также раздел [Уменьшение и сжатие сетевых данных](https://web.dev/articles/reduce-network-payloads-using-text-compression) . ## Инструкции для разных стеков diff --git a/site/ru/docs/lighthouse/performance/uses-webp-images/index.md b/site/ru/docs/lighthouse/performance/uses-webp-images/index.md index 88c1746d3..166985dbd 100644 --- a/site/ru/docs/lighthouse/performance/uses-webp-images/index.md +++ b/site/ru/docs/lighthouse/performance/uses-webp-images/index.md @@ -62,6 +62,6 @@ Lighthouse собирает каждое изображение BMP, JPEG и PNG ## Ресурсы - [Исходный код для проверки **использования современных форматов изображений**](https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/audits/byte-efficiency/modern-image-formats.js). -- [Используйте изображения в формате WebP](https://web.dev/serve-images-webp/). +- [Используйте изображения в формате WebP](https://web.dev/articles/serve-images-webp). <!-- https://www.reddit.com/r/webdev/comments/gspjwe/serve_images_in_nextgen_formats/ --> diff --git a/site/ru/docs/lighthouse/pwa/installable-manifest/index.md b/site/ru/docs/lighthouse/pwa/installable-manifest/index.md index c8ca6f347..62e5b84c7 100644 --- a/site/ru/docs/lighthouse/pwa/installable-manifest/index.md +++ b/site/ru/docs/lighthouse/pwa/installable-manifest/index.md @@ -10,13 +10,13 @@ date: 2019-05-04 updated: 2019-09-19 --- -Возможность установки — основное требование для [прогрессивных веб-приложений (PWA)](https://web.dev/progressive-web-apps/). Предлагая пользователям установить прогрессивное веб-приложение, вы предоставляете им возможность добавить его на начальный экран. Если пользователь добавит приложение на начальный экран, он будет чаще использовать это приложение. +Возможность установки — основное требование для [прогрессивных веб-приложений (PWA)](https://web.dev/explore/progressive-web-apps). Предлагая пользователям установить прогрессивное веб-приложение, вы предоставляете им возможность добавить его на начальный экран. Если пользователь добавит приложение на начальный экран, он будет чаще использовать это приложение. -В [манифесте веб-приложения](https://web.dev/add-manifest/) содержатся ключевые сведения, необходимые для того чтобы можно было устанавливать приложение. +В [манифесте веб-приложения](https://web.dev/articles/add-manifest) содержатся ключевые сведения, необходимые для того чтобы можно было устанавливать приложение. ## Почему не удается пройти аудит манифеста веб-приложения в Lighthouse -[Lighthouse](https://developers.google.com/web/tools/lighthouse/) помечает страницы, у которых нет [манифеста веб-приложения](https://web.dev/add-manifest/), отвечающего минимальным требованиям для возможности установки приложения: +[Lighthouse](https://developers.google.com/web/tools/lighthouse/) помечает страницы, у которых нет [манифеста веб-приложения](https://web.dev/articles/add-manifest), отвечающего минимальным требованиям для возможности установки приложения: <figure>{% Img src="image/tcFciHGuF3MxnTr1y5ue01OGLBn2/039DlaixA4drrswBzSra.png", alt="Результаты аудита Lighthouse, в которых сказано, что пользователю не удастся установить веб-приложение на начальный экран", width="800", height="98" %}</figure> @@ -28,13 +28,13 @@ updated: 2019-09-19 - Свойство [`display`](https://developer.mozilla.org/docs/Web/Manifest/display) со значением `fullscreen`, `standalone` или `minimal-ui` - Свойство [`prefer_related_applications`](https://developers.google.com/web/fundamentals/app-install-banners/native) со значением, отличным от `true`. -{% Aside 'caution' %} Манифест веб-приложения _необходим_, чтобы можно было устанавливать приложение, но его _недостаточно_. Сведения о том, как выполнить все требования, чтобы приложение поддерживало установку, см. в публикации [о том, что нужно, чтобы приложение поддерживало установку](https://web.dev/progressive-web-apps/). {% endAside %} +{% Aside 'caution' %} Манифест веб-приложения _необходим_, чтобы можно было устанавливать приложение, но его _недостаточно_. Сведения о том, как выполнить все требования, чтобы приложение поддерживало установку, см. в публикации [о том, что нужно, чтобы приложение поддерживало установку](https://web.dev/explore/progressive-web-apps). {% endAside %} {% Partial 'lighthouse-pwa/scoring.njk' %} ## Как сделать, чтобы прогрессивное приложение (PWA) поддерживало установку -Убедитесь, что у вашего приложения есть манифест, соответствующий указанным выше критериям. Дополнительные сведения о создании прогрессивных приложений (PWA) см. в коллекции [Installable](https://web.dev/progressive-web-apps/). +Убедитесь, что у вашего приложения есть манифест, соответствующий указанным выше критериям. Дополнительные сведения о создании прогрессивных приложений (PWA) см. в коллекции [Installable](https://web.dev/explore/progressive-web-apps). ## Как проверить, поддерживает ли прогрессивное приложение (PWA) установку @@ -42,7 +42,7 @@ updated: 2019-09-19 Если прогрессивное веб-приложение соответствует минимальным требованиям для установки, Chrome запускает событие `beforeinstallprompt`, с помощью которого можно предлагать пользователям установить это приложение. -{% Aside 'codelab' %} Узнайте, как сделать приложение поддерживающим установку в Chrome, с помощью codelab «[Добавление возможности установки](https://web.dev/codelab-make-installable//)». {% endAside %} +{% Aside 'codelab' %} Узнайте, как сделать приложение поддерживающим установку в Chrome, с помощью codelab «[Добавление возможности установки](https://web.dev/articles/codelab-make-installable/)». {% endAside %} ### В других браузерах @@ -57,7 +57,7 @@ updated: 2019-09-19 ## Ресурсы - [Исходный код аудита **Web app manifest does not meet the installability requirements**](https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/audits/installable-manifest.js) -- [Добавление манифеста веб-приложения](https://web.dev/add-manifest/) -- [Узнайте, что нужно, чтобы приложение поддерживало установку](https://web.dev/progressive-web-apps/) +- [Добавление манифеста веб-приложения](https://web.dev/articles/add-manifest) +- [Узнайте, что нужно, чтобы приложение поддерживало установку](https://web.dev/explore/progressive-web-apps) - [Манифест веб-приложения](https://developer.mozilla.org/docs/Web/Manifest) - Аудит [Does not use HTTPS](/docs/lighthouse/pwa/is-on-https/) diff --git a/site/ru/docs/lighthouse/pwa/load-fast-enough-for-pwa/index.md b/site/ru/docs/lighthouse/pwa/load-fast-enough-for-pwa/index.md index 1050be48b..a8bcc69fc 100644 --- a/site/ru/docs/lighthouse/pwa/load-fast-enough-for-pwa/index.md +++ b/site/ru/docs/lighthouse/pwa/load-fast-enough-for-pwa/index.md @@ -21,7 +21,7 @@ updated: 2020-06-10 На восприятие времени загрузки влияют две основные метрики: - [Первая отрисовка контента](/docs/lighthouse/performance/first-meaningful-paint/) (First Meaningful Paint, FMP) — показывает, как быстро основное содержимое страницы начинает выглядеть визуально завершенным. -- [Время загрузки для взаимодействия](https://web.dev/tti/) (Time to Interactive, TTI) — показывает, как быстро страница становится полностью интерактивной. +- [Время загрузки для взаимодействия](https://web.dev/articles/tti) (Time to Interactive, TTI) — показывает, как быстро страница становится полностью интерактивной. Например, если страница кажется визуально законченной через 1 секунду, но пользователь не может взаимодействовать с ней в течение 10 секунд, то время загрузки, скорее всего, будет восприниматься как 10 секунд. diff --git a/site/ru/docs/lighthouse/pwa/maskable-icon-audit/index.md b/site/ru/docs/lighthouse/pwa/maskable-icon-audit/index.md index b0ef43d91..a8eff2142 100644 --- a/site/ru/docs/lighthouse/pwa/maskable-icon-audit/index.md +++ b/site/ru/docs/lighthouse/pwa/maskable-icon-audit/index.md @@ -7,7 +7,7 @@ description: |2- date: 2020-05-06 --- -[Маскируемые значки](https://web.dev/maskable-icon/) — это новый формат значков, благодаря которому значки прогрессивных веб-приложений (PWA) отлично выглядят на всех устройствах с ОС Android. На новых устройствах с ОС Android значки прогрессивных веб-приложений, которые не соответствуют формату маскируемых значков, имеют белый фон. При использовании маскируемого значка он занимает все пространство, отведенное для него ОС Android. +[Маскируемые значки](https://web.dev/articles/maskable-icon) — это новый формат значков, благодаря которому значки прогрессивных веб-приложений (PWA) отлично выглядят на всех устройствах с ОС Android. На новых устройствах с ОС Android значки прогрессивных веб-приложений, которые не соответствуют формату маскируемых значков, имеют белый фон. При использовании маскируемого значка он занимает все пространство, отведенное для него ОС Android. ## Почему не удается пройти аудит маскируемых значков в Lighthouse @@ -29,7 +29,7 @@ date: 2020-05-06 1. Преобразуйте существующий значок в маскируемый значок с помощью [редактора Maskable.app](https://maskable.app/editor). -2. Добавьте свойство `purpose` в один из объектов `icons` в [манифесте веб-приложения](https://web.dev/add-manifest/). Задайте для свойства `purpose` значение `maskable` или `any maskable`. См. раздел «[Значения](https://developer.mozilla.org/docs/Web/Manifest/icons#Values)». +2. Добавьте свойство `purpose` в один из объектов `icons` в [манифесте веб-приложения](https://web.dev/articles/add-manifest). Задайте для свойства `purpose` значение `maskable` или `any maskable`. См. раздел «[Значения](https://developer.mozilla.org/docs/Web/Manifest/icons#Values)». ```json/8 { @@ -47,12 +47,12 @@ date: 2020-05-06 } ``` -3. С помощью Chrome DevTools проверьте, правильно ли отображается маскируемый значок. См. раздел «[Готовы ли мои текущие значки?](https://web.dev/maskable-icon/#are-my-current-icons-ready)». +3. С помощью Chrome DevTools проверьте, правильно ли отображается маскируемый значок. См. раздел «[Готовы ли мои текущие значки?](https://web.dev/articles/maskable-icon#are_my_current_icons_ready)». ## Ресурсы - [Исходный код аудита **Manifest doesn't have a maskable icon**](https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/audits/maskable-icon.js) -- [Поддержка адаптивных значков в прогрессивных веб-приложениях (PWA) с маскируемыми значками](https://web.dev/maskable-icon/) +- [Поддержка адаптивных значков в прогрессивных веб-приложениях (PWA) с маскируемыми значками](https://web.dev/articles/maskable-icon) - [Редактор Maskable.app](https://maskable.app/editor) -- [Добавление манифеста веб-приложения](https://web.dev/add-manifest/) +- [Добавление манифеста веб-приложения](https://web.dev/articles/add-manifest) - [Свойство `icons` в MDN](https://developer.mozilla.org/docs/Web/Manifest/icons) diff --git a/site/ru/docs/lighthouse/pwa/service-worker/index.md b/site/ru/docs/lighthouse/pwa/service-worker/index.md index 32897d727..a82bdccd6 100644 --- a/site/ru/docs/lighthouse/pwa/service-worker/index.md +++ b/site/ru/docs/lighthouse/pwa/service-worker/index.md @@ -6,13 +6,13 @@ date: 2019-05-04 updated: 2020-06-10 --- -Регистрация [сервис-воркера](https://web.dev/service-workers-cache-storage/) — это первый шаг к реализации основных функций [прогрессивного веб-приложения (PWA)](https://web.dev/progressive-web-apps/), таких как: +Регистрация [сервис-воркера](https://web.dev/articles/service-workers-cache-storage) — это первый шаг к реализации основных функций [прогрессивного веб-приложения (PWA)](https://web.dev/explore/progressive-web-apps), таких как: - офлайн-работа; - поддержка push-уведомлений; - возможность установки на устройство. -Подробнее см. в статье [Сервис-воркеры и Cache Storage API](https://web.dev/service-workers-cache-storage/). +Подробнее см. в статье [Сервис-воркеры и Cache Storage API](https://web.dev/articles/service-workers-cache-storage). ## Совместимость с браузерами @@ -34,15 +34,15 @@ Lighthouse проверяет, возвращает ли [Chrome Remote Debuggin Для регистрации сервис-воркера требуется всего несколько строк кода, но смысл в ней есть только в том случае, если вы собираетесь реализовать одну из функций PWA, перечисленных выше. Это потребует более серьезных усилий: -- Чтобы узнать о кешировании файлов для использования в офлайн-режиме, см. статью [Что такое надежность сети и как ее измерить](https://web.dev/network-connections-unreliable/). -- Чтобы узнать, как обеспечить возможность установки приложения, см. интерактивный урок [Добавление возможности установки](https://web.dev/codelab-make-installable/). +- Чтобы узнать о кешировании файлов для использования в офлайн-режиме, см. статью [Что такое надежность сети и как ее измерить](https://web.dev/articles/network-connections-unreliable). +- Чтобы узнать, как обеспечить возможность установки приложения, см. интерактивный урок [Добавление возможности установки](https://web.dev/articles/codelab-make-installable). - Чтобы узнать, как добавить push-уведомления, см. интерактивный урок [Добавление push-уведомлений в веб-приложение](https://codelabs.developers.google.com/codelabs/push-notifications), созданный Google. ## Ресурсы - [Исходный код проверки **Does not register a service worker that controls page and `start_url`**](https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/audits/service-worker.js) - [Сервис-воркеры: введение](https://developers.google.com/web/fundamentals/primers/service-workers) -- [Сервис-воркеры и Cache Storage API](https://web.dev/service-workers-cache-storage/) -- [Что такое надежность сети и как ее измерить?](https://web.dev/network-connections-unreliable/) -- [Добавление возможности установки](https://web.dev/codelab-make-installable/) +- [Сервис-воркеры и Cache Storage API](https://web.dev/articles/service-workers-cache-storage) +- [Что такое надежность сети и как ее измерить?](https://web.dev/articles/network-connections-unreliable) +- [Добавление возможности установки](https://web.dev/articles/codelab-make-installable) - [Добавление push-уведомлений в веб-приложение](https://codelabs.developers.google.com/codelabs/push-notifications) diff --git a/site/ru/docs/lighthouse/pwa/themed-omnibox/index.md b/site/ru/docs/lighthouse/pwa/themed-omnibox/index.md index 2866828ee..2c4304c9e 100644 --- a/site/ru/docs/lighthouse/pwa/themed-omnibox/index.md +++ b/site/ru/docs/lighthouse/pwa/themed-omnibox/index.md @@ -8,7 +8,7 @@ date: 2019-05-04 updated: 2020-06-17 --- -Установив тему для адресной строки браузера согласно брендовым цветам своего [современного веб-приложения](https://web.dev/progressive-web-apps/) (Progressive Web App, PWA), вы сделаете интерфейс более единообразным. +Установив тему для адресной строки браузера согласно брендовым цветам своего [современного веб-приложения](https://web.dev/explore/progressive-web-apps) (Progressive Web App, PWA), вы сделаете интерфейс более единообразным. ## Совместимость с браузерами @@ -20,7 +20,7 @@ updated: 2020-06-17 <figure> {% Img src="image/tcFciHGuF3MxnTr1y5ue01OGLBn2/YadFSuw8denjl1hhnvFs.png", alt="Аудит Lighthouse показывает, что для адресной строки не установлена тема согласно цветам страницы", width="800", height="98" %}</figure> -Аудит считается непройденным, если Lighthouse не находит метатег `theme-color` в HTML-коде страницы или свойство `theme_color` в [манифесте веб-приложения](https://web.dev/add-manifest/). +Аудит считается непройденным, если Lighthouse не находит метатег `theme-color` в HTML-коде страницы или свойство `theme_color` в [манифесте веб-приложения](https://web.dev/articles/add-manifest). При этом Lighthouse не проверяет, являются ли найденные значения допустимыми цветами CSS. @@ -47,7 +47,7 @@ updated: 2020-06-17 ### Шаг 2. Добавьте свойство `theme_color` в манифест веб-приложения -Свойство `theme_color` в манифесте веб-приложения оформляет адресную строку в стиле бренда, когда пользователь запускает PWA с главного экрана. В отличие от метатега `theme-color`, это свойство нужно определить только один раз — в [манифесте](https://web.dev/add-manifest/). Установите для свойства любое допустимое значение цвета CSS: +Свойство `theme_color` в манифесте веб-приложения оформляет адресную строку в стиле бренда, когда пользователь запускает PWA с главного экрана. В отличие от метатега `theme-color`, это свойство нужно определить только один раз — в [манифесте](https://web.dev/articles/add-manifest). Установите для свойства любое допустимое значение цвета CSS: ```html/1 { @@ -61,5 +61,5 @@ updated: 2020-06-17 ## Материалы - [Исходный код для аудита **Не установлен цвет темы для адресной строки** (Does not set a theme color for the address bar)](https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/audits/themed-omnibox.js). -- [Как добавить манифест веб-приложения](https://web.dev/add-manifest/). +- [Как добавить манифест веб-приложения](https://web.dev/articles/add-manifest). - [Поддержка `theme-color` в Chrome 39 для Android](https://developers.google.com/web/updates/2014/11/Support-for-theme-color-in-Chrome-39-for-Android). diff --git a/site/ru/docs/privacy-sandbox/attribution-reporting/index.md b/site/ru/docs/privacy-sandbox/attribution-reporting/index.md index 21ccd3111..a33684a0c 100644 --- a/site/ru/docs/privacy-sandbox/attribution-reporting/index.md +++ b/site/ru/docs/privacy-sandbox/attribution-reporting/index.md @@ -48,7 +48,7 @@ authors: Attribution Reporting API позволяет измерять два связанных между собой события: событие на сайте издателя, такое как просмотр объявления или нажатие на него пользователем, и последующую конверсию на сайте рекламодателя. -Этот API поддерживает измерение атрибуции конверсий по кликам (доступно в первой реализации этого API в виде [пробной версии источника](https://web.dev/conversion-measurement/#browser-support)) и измерение атрибуции по просмотрам (см. [объяснение для всех](https://github.com/WICG/conversion-measurement-api/blob/main/event_attribution_reporting.md)). +Этот API поддерживает измерение атрибуции конверсий по кликам (доступно в первой реализации этого API в виде [пробной версии источника](/docs/privacy-sandbox/attribution-reporting/#browser-support)) и измерение атрибуции по просмотрам (см. [объяснение для всех](https://github.com/WICG/conversion-measurement-api/blob/main/event_attribution_reporting.md)). API предлагает два типа отчетов об атрибуции в зависимости от сценария использования: @@ -67,8 +67,8 @@ API предлагает два типа отчетов об атрибуции - [Введение в отчеты по атрибуции (измерение конверсий)](/docs/privacy-sandbox/attribution-reporting-introduction) - [Технические описания API](https://github.com/WICG/conversion-measurement-api/) -- (⚠️ устарело) [Более конфиденциальный способ измерения конверсии рекламы](https://web.dev/conversion-measurement/): обзор первой версии этого API для веб-разработчиков +- (⚠️ устарело) [Более конфиденциальный способ измерения конверсии рекламы](/docs/privacy-sandbox/attribution-reporting/): обзор первой версии этого API для веб-разработчиков - (⚠️ устарело) [Более конфиденциальный способ измерения конверсии рекламы-видео](https://www.youtube.com/watch?v=jcDfOoWwZcM): демонстрация первой версии этого API для веб-разработчиков (только клики) -- (⚠️ устарело) [Использование Event Conversion Measurement API](https://web.dev/using-conversion-measurement/): как экспериментировать с первой версией этого API для веб-разработчиков +- (⚠️ устарело) [Использование Event Conversion Measurement API](/docs/privacy-sandbox/attribution-reporting/): как экспериментировать с первой версией этого API для веб-разработчиков - [Погружение в Privacy Sandbox](https://web.dev/digging-into-the-privacy-sandbox) - [Отладка API с помощью Chrome DevTools](/blog/new-in-devtools-93/#attribution-reporting) diff --git a/site/ru/docs/privacy-sandbox/first-party-sets/index.md b/site/ru/docs/privacy-sandbox/first-party-sets/index.md index 3bb9d1bfb..f14a94a1b 100644 --- a/site/ru/docs/privacy-sandbox/first-party-sets/index.md +++ b/site/ru/docs/privacy-sandbox/first-party-sets/index.md @@ -13,7 +13,7 @@ authors: ## Статус реализации -- [Доступно в рамках испытания Origin Trial](https://web.dev/origin-trials/) в Chrome с 89 по 93. +- [Доступно в рамках испытания Origin Trial](/docs/web-platform/origin-trials/) в Chrome с 89 по 93. - [Регистрация для участия в испытании Origin Trial](/origintrials/#/view_trial/988540118207823873). - [Статус платформы Chrome](https://chromestatus.com/feature/5640066519007232). - [Проекты Chromium](https://www.chromium.org/updates/first-party-sets). diff --git a/site/ru/docs/privacy-sandbox/floc/index.md b/site/ru/docs/privacy-sandbox/floc/index.md index 336e45671..4293409ce 100644 --- a/site/ru/docs/privacy-sandbox/floc/index.md +++ b/site/ru/docs/privacy-sandbox/floc/index.md @@ -37,7 +37,7 @@ FLoC предоставляет механизм подбора по интер ## Как работает FLoC? -В статье [«Что такое FLoC?»](https://web.dev/floc/#how-does-floc-work) приведено простое пошаговое объяснение принципа работы FLoC. +В статье [«Что такое FLoC?»](https://web.dev/articles/floc#how_does_floc_work) приведено простое пошаговое объяснение принципа работы FLoC. На диаграмме ниже изображены участники процесса выбора и отображения релевантной рекламы с помощью FLoC. diff --git a/site/ru/docs/privacy-sandbox/glossary/index.md b/site/ru/docs/privacy-sandbox/glossary/index.md index 6fcf6cb2f..64be75fce 100644 --- a/site/ru/docs/privacy-sandbox/glossary/index.md +++ b/site/ru/docs/privacy-sandbox/glossary/index.md @@ -124,7 +124,7 @@ glitch.me ## Испытание Origin Trial {: #origin-trial } -Испытания Origin Trial предоставляют доступ к новым и экспериментальным функциям, при помощи которых можно создавать новую функциональность и давать пользователям возможность тестировать ее в течение ограниченного периода времени, прежде чем функция становится общедоступной. Когда в Chrome для той или иной функции доступно испытание Origin Trial, вы можете зарегистрировать [источник](#origin) для участия в этом испытании, чтобы активировать функцию для всех пользователей, просматривающих страницы с этого источника, без необходимости включения скрытых настроек или перехода на альтернативную сборку Chrome (хотя может потребоваться обновление). Испытания Origin Trial позволяют разработчикам использовать новые функции при создании демонстраций и прототипов. Они также помогают инженерам Chrome лучше понять сценарии использования новых функций и то, как они взаимодействуют с другими веб-технологиями. Подробнее см. в статье [«Начало работы с испытаниями Chrome Origin Trial»](https://web.dev/origin-trials/). +Испытания Origin Trial предоставляют доступ к новым и экспериментальным функциям, при помощи которых можно создавать новую функциональность и давать пользователям возможность тестировать ее в течение ограниченного периода времени, прежде чем функция становится общедоступной. Когда в Chrome для той или иной функции доступно испытание Origin Trial, вы можете зарегистрировать [источник](#origin) для участия в этом испытании, чтобы активировать функцию для всех пользователей, просматривающих страницы с этого источника, без необходимости включения скрытых настроек или перехода на альтернативную сборку Chrome (хотя может потребоваться обновление). Испытания Origin Trial позволяют разработчикам использовать новые функции при создании демонстраций и прототипов. Они также помогают инженерам Chrome лучше понять сценарии использования новых функций и то, как они взаимодействуют с другими веб-технологиями. Подробнее см. в статье [«Начало работы с испытаниями Chrome Origin Trial»](/docs/web-platform/origin-trials/). ## Пассивная поверхность {: #passive-surface } diff --git a/site/ru/docs/privacy-sandbox/overview/index.md b/site/ru/docs/privacy-sandbox/overview/index.md index 98caa42f9..2a0fab34c 100644 --- a/site/ru/docs/privacy-sandbox/overview/index.md +++ b/site/ru/docs/privacy-sandbox/overview/index.md @@ -35,7 +35,7 @@ authors: ### Защита собственных ресурсов -- [**Изменения в работе файлов cookie с атрибутом SameSite**](https://web.dev/samesite-cookies-explained/): защита сайтов путем явной пометки межсайтовых файлов cookie. +- [**Изменения в работе файлов cookie с атрибутом SameSite**](https://web.dev/articles/samesite-cookies-explained): защита сайтов путем явной пометки межсайтовых файлов cookie. - [**Наборы собственных доменов**](/docs/privacy-sandbox/first-party-sets): позволяют связанным доменным именам, имеющим общего владельца, объявлять принадлежность к одному и тому же источнику. ### Обнаружение мошенничества @@ -45,7 +45,7 @@ authors: ### Ограничение сбора данных - [**Бюджет конфиденциальности**](https://www.youtube.com/watch?v=0STgfjSA6T8): механизм, дающий сайтам возможность получать информацию об используемом браузере или устройстве, но при этом позволяющий браузеру ограничивать общий объем доступной сайту информации, чтобы не дать ему идентифицировать пользователя. -- [**User-Agent Client Hints**](https://web.dev/user-agent-client-hints/): строка [User-Agent](https://developer.mozilla.org/docs/Web/HTTP/Headers/User-Agent) (UA)—одна из важных пассивных поверхностей [фингерпринтинга](https://w3c.github.io/fingerprinting-guidance/#passive) и вдобавок ее сложно анализировать. С помощью Client Hints (клиентских подсказок) разработчики могут активно запрашивать только ту информацию об устройстве или настройках пользователя, которая им необходима, вместо того чтобы извлекать эти данные из строки User-Agent. +- [**User-Agent Client Hints**](https://web.dev/articles/user-agent-client-hints): строка [User-Agent](https://developer.mozilla.org/docs/Web/HTTP/Headers/User-Agent) (UA)—одна из важных пассивных поверхностей [фингерпринтинга](https://w3c.github.io/fingerprinting-guidance/#passive) и вдобавок ее сложно анализировать. С помощью Client Hints (клиентских подсказок) разработчики могут активно запрашивать только ту информацию об устройстве или настройках пользователя, которая им необходима, вместо того чтобы извлекать эти данные из строки User-Agent. - [**Gnatcatcher**](https://github.com/bslassey/ip-blindness): позволяет ограничить возможность идентификации конкретных пользователей по IP-адресу. Предложение состоит из двух частей: [<strong data-md="">добровольный отказ от обработки IP-адресов</strong>](https://github.com/bslassey/ip-blindness/blob/master/willful_ip_blindness.md) позволяет сайтам сообщать браузеру, что они не идентифицируют пользователей по IP-адресу, в то время как <a href="https://github.com/bslassey/ip-blindness/blob/master/near_path_nat.md"><strong>Near-path NAT</strong></a> позволяет группам пользователей направлять свой трафик через один и тот же анонимизирующий сервер, фактически скрывая свои IP-адреса от владельцев сайтов. Gnatcatcher также предоставляет сайтам возможность получать доступ к IP-адресам в легитимных целях, таких как предотвращение злоупотребления, при условии прохождения сертификации и аудита. ### Идентификация @@ -90,10 +90,10 @@ authors: ### Статьи и видео для веб-разработчиков - [Погружение в Privacy Sandbox](https://web.dev/digging-into-the-privacy-sandbox) -- [Объяснение SameSite—атрибута файлов cookie](https://web.dev/samesite-cookies-explained/) +- [Объяснение SameSite—атрибута файлов cookie](https://web.dev/articles/samesite-cookies-explained) - [Знакомство с токенами доверия](https://web.dev/trust-tokens) -- [Более конфиденциальный способ измерения конверсий рекламы](https://web.dev/conversion-measurement/) -- [Что такое FLoC?](https://web.dev/floc/) +- [Более конфиденциальный способ измерения конверсий рекламы](/docs/privacy-sandbox/attribution-reporting/) +- [Что такое FLoC?](https://web.dev/articles/floc) - [Знакомьтесь: бюджет конфиденциальности](https://www.youtube.com/watch?v=0STgfjSA6T8) ### Принципы и концепции, на которых основаны предложения diff --git a/site/ru/docs/privacy-sandbox/status/index.md b/site/ru/docs/privacy-sandbox/status/index.md index b227ff137..ad977d737 100644 --- a/site/ru/docs/privacy-sandbox/status/index.md +++ b/site/ru/docs/privacy-sandbox/status/index.md @@ -15,7 +15,7 @@ authors: *Старое название—«Измерение конверсии».* -- [Текущее испытание origin trial](https://web.dev/origin-trials/): с Chrome 86 [теперь расширено](https://groups.google.com/u/1/a/chromium.org/g/attribution-reporting-api-dev/c/ZKf9T8sRqAM) до Chrome 93. +- [Текущее испытание origin trial](/docs/web-platform/origin-trials/): с Chrome 86 [теперь расширено](https://groups.google.com/u/1/a/chromium.org/g/attribution-reporting-api-dev/c/ZKf9T8sRqAM) до Chrome 93. - [Регистрация для участия в испытании Origin Trial](/origintrials/#/view_trial/3411476717733150721). - [Демонстрация](https://goo.gle/demo-event-level-conversion-measurement-api). - [Статус платформы Chrome](https://www.chromestatus.com/features/6412002824028160). @@ -31,25 +31,25 @@ authors: - [Отчеты по атрибуции (измерение конверсии)](/docs/privacy-sandbox/attribution-reporting) - [Введение в отчеты по атрибуции (измерение конверсии)](/docs/privacy-sandbox/attribution-reporting-introduction) - [Технические описания API](https://github.com/WICG/conversion-measurement-api/) -- (⚠️ устарело) [Более конфиденциальный способ измерения конверсии рекламы](https://web.dev/conversion-measurement/): обзор первой версии этого API для веб-разработчиков +- (⚠️ устарело) [Более конфиденциальный способ измерения конверсии рекламы](/docs/privacy-sandbox/attribution-reporting/): обзор первой версии этого API для веб-разработчиков - (⚠️ устарело) [Более конфиденциальный способ измерения конверсии рекламы-видео](https://www.youtube.com/watch?v=jcDfOoWwZcM): демонстрация первой версии этого API для веб-разработчиков (только клики) -- (⚠️ устарело) [Использование Event Conversion Measurement API](https://web.dev/using-conversion-measurement/): как экспериментировать с первой версией этого API для веб-разработчиков +- (⚠️ устарело) [Использование Event Conversion Measurement API](/docs/privacy-sandbox/attribution-reporting/): как экспериментировать с первой версией этого API для веб-разработчиков - [Погружение в Privacy Sandbox](https://web.dev/digging-into-the-privacy-sandbox) ## Токены доверия -- [Текущее испытание origin trial](https://web.dev/origin-trials/): с Chrome 84 [теперь расширено](https://groups.google.com/a/chromium.org/g/blink-dev/c/-W90wVkS0Ks/m/Jfh5-ZWpAQAJ) до Chrome 94. +- [Текущее испытание origin trial](/docs/web-platform/origin-trials/): с Chrome 84 [теперь расширено](https://groups.google.com/a/chromium.org/g/blink-dev/c/-W90wVkS0Ks/m/Jfh5-ZWpAQAJ) до Chrome 94. - [Регистрация для участия в испытании Origin Trial](/origintrials/#/view_trial/2479231594867458049). - [Демонстрация](https://trust-token-demo.glitch.me/). - [Статус платформы Chrome](https://www.chromestatus.com/feature/5078049450098688). - [Статус Blink](https://groups.google.com/a/chromium.org/g/blink-dev/search?q=trust%tokens). - [GitHub](https://github.com/WICG/trust-token-api): задавайте вопросы и участвуйте в обсуждении API в разделе [Issues](https://github.com/WICG/trust-token-api/issues). - [Интеграция с Chrome DevTools](https://developers.google.com/web/updates/2021/01/devtools?utm_source=devtools#trust-token). -- Дополнительная информация: [Начало работы с токенами доверия](https://web.dev/trust-tokens/) +- Дополнительная информация: [Начало работы с токенами доверия](https://web.dev/articles/trust-tokens) ## Наборы собственных доменов -- [Текущее испытание Origin Trial](https://web.dev/origin-trials/): Chrome с 89 по 93. +- [Текущее испытание Origin Trial](/docs/web-platform/origin-trials/): Chrome с 89 по 93. - [Регистрация для участия в испытании Origin Trial](/origintrials/#/view_trial/988540118207823873). - [Статус платформы Chrome](https://chromestatus.com/feature/5640066519007232). - [Статус Blink](https://groups.google.com/a/chromium.org/g/blink-dev/search?q=first-party%20sets). @@ -64,7 +64,7 @@ authors: - [Предложение API](https://github.com/WICG/floc) в настоящий момент обсуждается с [WICG](https://www.w3.org/community/wicg/) и другими заинтересованными группами. - [GitHub](https://github.com/WICG/floc): задавайте вопросы и участвуйте в обсуждении API в разделе [Issues](https://github.com/WICG/floc/issues). - [Статус платформы Chrome](https://www.chromestatus.com/features/5710139774468096). -- Дополнительная информация: [Что такое FLoC?](https://web.dev/floc/) +- Дополнительная информация: [Что такое FLoC?](https://web.dev/articles/floc) ## FLEDGE @@ -91,7 +91,7 @@ authors: ### Испытания Origin Trial -- [Знакомство с испытаниями Chrome Origin Trial](https://web.dev/origin-trials/) +- [Знакомство с испытаниями Chrome Origin Trial](/docs/web-platform/origin-trials/) - [Что такое сторонние испытания Origin Trial?](https://web.dev/third-party-origin-trials) - [Знакомство с испытаниями Chrome Origin Trial](/blog/origin-trial-troubleshooting/) - [Руководство по испытаниям Origin Trial для веб-разработчиков](https://github.com/GoogleChrome/OriginTrials/blob/gh-pages/developer-guide.md) diff --git a/site/ru/docs/privacy-sandbox/trust-tokens/index.md b/site/ru/docs/privacy-sandbox/trust-tokens/index.md index 0cdbfe131..35be32094 100644 --- a/site/ru/docs/privacy-sandbox/trust-tokens/index.md +++ b/site/ru/docs/privacy-sandbox/trust-tokens/index.md @@ -11,7 +11,7 @@ authors: ## Статус реализации -- [Доступно в рамках испытания Origin Trial](https://web.dev/origin-trials/) в Chrome с 84 по 94. +- [Доступно в рамках испытания Origin Trial](/docs/web-platform/origin-trials/) в Chrome с 84 по 94. - [Регистрация для участия в испытании](/origintrials/#/view_trial/2479231594867458049). - [Демонстрация](https://trust-token-demo.glitch.me/). - [Интеграция с Chrome DevTools](https://developers.google.com/web/updates/2021/01/devtools?utm_source=devtools#trust-token). @@ -62,7 +62,7 @@ authors: 12. Объявление отображается на сайте издателя. 13. Сайт засчитывает показ объявления. -{% Aside %} Подробнее о вызовах JavaScript, используемых в этом примере, см. [«Пример использования API»](https://web.dev/trust-tokens/#sample-api-usage). {% endAside %} +{% Aside %} Подробнее о вызовах JavaScript, используемых в этом примере, см. [«Пример использования API»](https://web.dev/articles/trust-tokens#sample_api_usage). {% endAside %} --- @@ -78,6 +78,6 @@ authors: ## Дополнительная информация - [Техническое описание API токенов доверия](https://github.com/dvorak42/trust-token-api) -- [Начало работы с токенами доверия](https://web.dev/trust-tokens/): обзор для веб-разработчиков +- [Начало работы с токенами доверия](https://web.dev/articles/trust-tokens): обзор для веб-разработчиков - [Знакомство с испытаниями Chrome Origin Trial](https://web.dev/origin-trials) - [Погружение в Privacy Sandbox](https://web.dev/digging-into-the-privacy-sandbox) diff --git a/site/zh/articles/file-sharing/index.md b/site/zh/articles/file-sharing/index.md index f88847c45..84c211394 100644 --- a/site/zh/articles/file-sharing/index.md +++ b/site/zh/articles/file-sharing/index.md @@ -13,9 +13,9 @@ hero: image/admin/tf0sUZX6G7AM8PvU1t0B.jpg alt: 多种颜色的绑定器。 --- -{% Aside %} 文件处理 API 是[功能项目的](https://web.dev/blog/fugu-status/)一部分,目前正在开发中。本博文将根据实施进展随时更新。{% endAside %} +{% Aside %} 文件处理 API 是[功能项目的](https://web.dev/articles/blog/fugu-status)一部分,目前正在开发中。本博文将根据实施进展随时更新。{% endAside %} -现在,Web 应用程序[能够读写文件](https://web.dev/file-system-access/),下一个逻辑步骤是让开发人员将这些 Web 应用程序声明为他们的应用程序可以创建和处理的文件的文件处理程序。利用文件处理 API 即可实现。将文本编辑器应用程序注册为文件处理程序并安装后,您可以在 macOS 上右键单击 `.txt` 文件并选择“获取信息”,然后指示操作系统始终将该应用程序作为打开 `.txt` 文件的默认应用程序。 +现在,Web 应用程序[能够读写文件](https://web.dev/articles/file-system-access),下一个逻辑步骤是让开发人员将这些 Web 应用程序声明为他们的应用程序可以创建和处理的文件的文件处理程序。利用文件处理 API 即可实现。将文本编辑器应用程序注册为文件处理程序并安装后,您可以在 macOS 上右键单击 `.txt` 文件并选择“获取信息”,然后指示操作系统始终将该应用程序作为打开 `.txt` 文件的默认应用程序。 ## 文件处理 API 的建议用例 {: #use-cases } @@ -35,8 +35,8 @@ alt: 多种颜色的绑定器。 文件处理 API 本身不能实施填充代码 (Polyfill)。但是,使用 Web 应用程序打开文件的功能可通过另外两种方式实现: -- [Web 共享目标 API](https://web.dev/web-share-target/) 支持开发人员将应用程序指定为共享目标,以便从操作系统的共享表中打开文件。 -- [文件系统访问 API](https://web.dev/file-system-access/) 可以集成文件拖放操作,因此,开发人员可以在打开的应用程序中处理拖放文件。 +- [Web 共享目标 API](https://web.dev/articles/web-share-target) 支持开发人员将应用程序指定为共享目标,以便从操作系统的共享表中打开文件。 +- [文件系统访问 API](https://web.dev/articles/file-system-access) 可以集成文件拖放操作,因此,开发人员可以在打开的应用程序中处理拖放文件。 ### 功能检测 @@ -52,7 +52,7 @@ if ('launchQueue' in window && 'files' in LaunchParams.prototype) { ### 文件处理 API 的声明部分 -第一步,Web 应用程序需要在 [Web 应用程序清单](https://web.dev/add-manifest/)中以声明方式描述可处理的文件类型。该文件处理 API 使用一个称为 `"file_handlers"` 的新属性扩展了 Web 应用程序清单,该属性可接受一组文件处理程序。文件处理程序是具有两个属性的对象: +第一步,Web 应用程序需要在 [Web 应用程序清单](https://web.dev/articles/add-manifest)中以声明方式描述可处理的文件类型。该文件处理 API 使用一个称为 `"file_handlers"` 的新属性扩展了 Web 应用程序清单,该属性可接受一组文件处理程序。文件处理程序是具有两个属性的对象: - 其一是 `"action"` 属性,它指向应用程序范围内的 URL,将其作为值 - 其二是 `"accept"` 属性,它以 MIME 类型的对象作为键,并将文件扩展名列表作为值。 diff --git a/site/zh/blog/chrome-ux-report-looker-studio-dashboard/index.md b/site/zh/blog/chrome-ux-report-looker-studio-dashboard/index.md index 08ff7a120..3c17f7a6d 100644 --- a/site/zh/blog/chrome-ux-report-looker-studio-dashboard/index.md +++ b/site/zh/blog/chrome-ux-report-looker-studio-dashboard/index.md @@ -70,7 +70,7 @@ https://developer.chrome.com/chrome-ux-report-looker-studio-dashboard/ ### Core Web Vitals 概述 -第一页显示了源的 [Core Web Vitals](https://web.dev/vitals/) 月度表现概览。这些是 Google 建议关注的最重要的用户体验指标。 +第一页显示了源的 [Core Web Vitals](https://web.dev/articles/vitals) 月度表现概览。这些是 Google 建议关注的最重要的用户体验指标。 {% Img src="image/admin/h8iCTgvmG4DS2zScvatc.png", alt="CrUX Dashboard Core Web Vitals 概览", width="800", height="906" %} @@ -88,7 +88,7 @@ https://developer.chrome.com/chrome-ux-report-looker-studio-dashboard/ 每个页面顶部都设有**设备**过滤器,您可以用它来限制体验数据中的窗体因子。例如,您可以专门深入研究电话用户体验。此设置支持跨页面调用。 -这些页面上的主要可视化内容各种体验的月度分布图,其类别有“良好”、“需要改进”和“差”。图表下方的颜色编码图例表示该类别包含的体验范围。例如,在上面的截图中,您可以看到[Largest Contentful Paint(最大内容绘制,LCP)](https://web.dev/lcp/#what-is-a-good-lcp-score)“良好”体验的百分比在最近几个月波动并稍有恶化。 +这些页面上的主要可视化内容各种体验的月度分布图,其类别有“良好”、“需要改进”和“差”。图表下方的颜色编码图例表示该类别包含的体验范围。例如,在上面的截图中,您可以看到[Largest Contentful Paint(最大内容绘制,LCP)](https://web.dev/articles/lcp#what_is_a_good_lcp_score)“良好”体验的百分比在最近几个月波动并稍有恶化。 最近一个月的“良好”和“差”体验百分比显示在图表上方,以及与上个月的百分比差异指标。对于这个源,“良好”的 LCP 体验环比下跌了 3.2%,现在是 56.04%。 @@ -116,7 +116,7 @@ PageSpeed Insights 等工具中对应的 P75 值并非基于公共 BigQuery 数 {% Aside 'key-term' %}有效的连接类型之所以被认为是*有效的*,是因为它们基于用户设备上的带宽测量值,并不暗示使用了任何特定技术。例如,使用快速 WiFi 的桌面用户可能被标记为 4G,而较慢的移动连接可能被标记为 2G。 {% endAside %} -这些维度的分布是使用 [First Contentful Paint](https://web.dev/fcp/) (FCP) 直方图数据的分段计算的。 +这些维度的分布是使用 [First Contentful Paint](https://web.dev/articles/fcp) (FCP) 直方图数据的分段计算的。 ## 常问问题 diff --git a/site/zh/blog/new-in-devtools-101/index.md b/site/zh/blog/new-in-devtools-101/index.md index 85bb23862..93e899df7 100644 --- a/site/zh/blog/new-in-devtools-101/index.md +++ b/site/zh/blog/new-in-devtools-101/index.md @@ -104,8 +104,8 @@ Chromium 议题: [1296855](https://crbug.com/1296855), [https://crbug.com/130340 <!-- These are some noteworthy fixes in this release: --> 下面列出的是此次更新需要注意的 bug 修复: -<!-- - The [Back/forward cache](/blog/new-in-devtools-98/#bfcache) now displays the extension ID which blocked [bfcache](https://web.dev/bfcache/) when present.( [1284548](https://crbug.com/1284548)) --> -- [Back/forward cache](/blog/new-in-devtools-98/#bfcache) 选项卡现在会显示那些禁止 [bfcache](https://web.dev/bfcache/)功能的插件 ID,前提是插件有 ID。( [1284548](https://crbug.com/1284548)) +<!-- - The [Back/forward cache](/blog/new-in-devtools-98/#bfcache) now displays the extension ID which blocked [bfcache](https://web.dev/articles/bfcache) when present.( [1284548](https://crbug.com/1284548)) --> +- [Back/forward cache](/blog/new-in-devtools-98/#bfcache) 选项卡现在会显示那些禁止 [bfcache](https://web.dev/articles/bfcache)功能的插件 ID,前提是插件有 ID。( [1284548](https://crbug.com/1284548)) <!-- - Fixed autocompletion support for array-like objects, CSS class names, `map.get` and HTML tags. ([1297101](https://crbug.com/1297101), [1297491](https://crbug.com/1297491), [1293807](https://crbug.com/1293807), [1296983](https://crbug.com/1296983)) --> - 修复类数组对象、CSS 类名、`map.get` 以及 HTML 标签的自动填充问题。([1297101](https://crbug.com/1297101), [1297491](https://crbug.com/1297491), [1293807](https://crbug.com/1293807), [1296983](https://crbug.com/1296983)) <!-- - Fixed incorrect highlights when double-clicking on words and undoing autocomplete. ([1298437](https://crbug.com/1298437), [1298667](https://crbug.com/1298667)) --> @@ -127,8 +127,8 @@ Chromium 议题: [1296855](https://crbug.com/1296855), [https://crbug.com/130340 <!-- Apart from the existing **navigation** mode, the **Lighthouse** panel now support two more modes on measuring user flows - **timespan** and **snapshot**. --> 除了现有的**导航**模式,Lighthouse 面板现在支持两种新模式,用于评估用户流程 - **timespan** 和 **snapshot**。 -<!-- For example, you can use the **timespan** reports to analyze user interactions. Open this [demo](https://coffee-cart.netlify.app/) page. Select the **Timespan** mode and click on **Start timespan**. On the page, click on a coffee and end the timespan. Read the report to find out the [Total Blocking Time](https://web.dev/tbt/) and [Cumulative Layout Shift](https://web.dev/cls/) that were caused by the interaction. --> -例如,您可以使用 **timespan** 报告来分析用户交互。打开这个 [demo](https://coffee-cart.netlify.app/) 页面。选择 **Timespan** 模式,然后点击**开始 timespan** 按钮。在页面上,点击咖啡杯图案并结束 timespan。读取报告,以便于找出上述交互所产生的 [Total Blocking Time](https://web.dev/tbt/) 和 [Cumulative Layout Shift](https://web.dev/cls/)。 +<!-- For example, you can use the **timespan** reports to analyze user interactions. Open this [demo](https://coffee-cart.netlify.app/) page. Select the **Timespan** mode and click on **Start timespan**. On the page, click on a coffee and end the timespan. Read the report to find out the [Total Blocking Time](https://web.dev/articles/tbt) and [Cumulative Layout Shift](https://web.dev/articles/cls) that were caused by the interaction. --> +例如,您可以使用 **timespan** 报告来分析用户交互。打开这个 [demo](https://coffee-cart.netlify.app/) 页面。选择 **Timespan** 模式,然后点击**开始 timespan** 按钮。在页面上,点击咖啡杯图案并结束 timespan。读取报告,以便于找出上述交互所产生的 [Total Blocking Time](https://web.dev/articles/tbt) 和 [Cumulative Layout Shift](https://web.dev/articles/cls)。 <!-- Each mode has its own unique use cases, benefits, and limitations. Please refer to the [Lighthouse documentation](https://github.com/GoogleChrome/lighthouse/blob/master/docs/user-flows.md) for more information. --> 每个模式都有属于自己特有的使用场景,优点和限制。请参考 [Lighthouse 帮助文档](https://github.com/GoogleChrome/lighthouse/blob/master/docs/user-flows.md)以获取更多信息。 diff --git a/site/zh/blog/new-in-devtools-102/index.md b/site/zh/blog/new-in-devtools-102/index.md index cef43f115..55cbe9299 100644 --- a/site/zh/blog/new-in-devtools-102/index.md +++ b/site/zh/blog/new-in-devtools-102/index.md @@ -54,8 +54,8 @@ Chromium 议题: [1270700](https://crbug.com/1270700) <!-- ## New shortcuts to emulate light and dark themes {: #emulation } --> ## 新的模拟浅色和深色主题的快捷方式 {: #emulation } -<!-- You can now emulate the light and dark themes quicker (CSS media feature [prefers-color-scheme](https://web.dev/prefers-color-scheme/#the-prefers-color-scheme-media-query)) with the new shortcuts in the **Styles** pane. --> -您现在可以在**样式**边栏中利用新的快捷方式来更快速地模拟浅色和深色主题(CSS 媒体功能 [prefers-color-scheme](https://web.dev/prefers-color-scheme/#the-prefers-color-scheme-media-query))。 +<!-- You can now emulate the light and dark themes quicker (CSS media feature [prefers-color-scheme](https://web.dev/articles/prefers-color-scheme#the_prefers_color_scheme_media_query)) with the new shortcuts in the **Styles** pane. --> +您现在可以在**样式**边栏中利用新的快捷方式来更快速地模拟浅色和深色主题(CSS 媒体功能 [prefers-color-scheme](https://web.dev/articles/prefers-color-scheme#the_prefers_color_scheme_media_query))。 <!-- Previously, it took more steps to [emulate themes](/docs/devtools/rendering/emulate-css/) in the **Rendering** tab. --> 在此之前,在**渲染**标签页中[模拟主题](/docs/devtools/rendering/emulate-css/)需要更多步骤。 @@ -73,8 +73,8 @@ Chromium 议题: [1314299](https://crbug.com/1314299) <!-- DevTools now apply the Content Security Policy (CSP) in the **Preview** tab in the **Network** panel. --> **网络**面板中的**预览**标签页现在应用了内容安全政策(CSP)。 -<!-- For example, the first screenshot shows a page that contains [mixed content](https://web.dev/what-is-mixed-content/). The page loads over a secure HTTPS connection, but the stylesheet loads over an insecure HTTP connection. --> -例如,第一个屏幕截图显示了一个包含[混合内容](https://web.dev/what-is-mixed-content/)的页面。该页面通过安全的 HTTPS 连接加载,但样式表通过不安全的 HTTP 连接加载。 +<!-- For example, the first screenshot shows a page that contains [mixed content](https://web.dev/articles/what-is-mixed-content). The page loads over a secure HTTPS connection, but the stylesheet loads over an insecure HTTP connection. --> +例如,第一个屏幕截图显示了一个包含[混合内容](https://web.dev/articles/what-is-mixed-content)的页面。该页面通过安全的 HTTPS 连接加载,但样式表通过不安全的 HTTP 连接加载。 <!-- The browser blocked the stylesheet request by default. However, when you opened the page via the **Preview** tab in the **Network** panel, the stylesheet was not blocked previously (hence the background turned into red). It is now blocked as you would expect (second screenshot). --> 浏览器默认阻止样式表请求。但是,当您通过**网络**面板中的**预览**标签页打开页面时,样式表此前并没有被阻止(因此背景变成了红色)。现在像您期望的那样,该样式表被阻止了(第二个屏幕截图)。 @@ -128,7 +128,7 @@ Chromium 议题: [1295750](https://crbug.com/1295750) 一旦您完成了一个[实时表达式](/blog/new-in-devtools-70/#watch) 的输入,您即可通过回车键来提交它。在此之前,按回车键会导致添加新行。这行为与 DevTools 的其他部分不一致。 <!-- To add a new line in the **live expression** editor, use `Shift` + `Enter` instead. --> -使用 `Shift` + `回车键` 来添加新行。 +使用 `Shift` + `回车键` 来添加新行。 {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/yB7m2052mYzgsRgjIMvs.png", alt="通过回车键提交实时表达式", width="800", height="541" %} @@ -212,7 +212,7 @@ Chromium 议题: [1024156](https://crbug.com/1024156) {# https://chromium.googlesource.com/devtools/devtools-frontend/+/afe5698f1cd20304d2763574ef8e9faf6a4a6db1 #} {# ​​https://chromium.googlesource.com/devtools/devtools-frontend/+/5de1d6140cad945783f3ca54055134f4a7db42a1 #} -{# https://chromium.googlesource.com/devtools/devtools-frontend/+/573dfc1cca09e49177ece3898c9ba9619c386f06 #} +{# https://chromium.googlesource.com/devtools/devtools-frontend/+/573dfc1cca09e49177ece3898c9ba9619c386f06 #} Chromium 议题: [1268754](https://crbug.com/1268754) diff --git a/site/zh/blog/new-in-devtools-104/index.md b/site/zh/blog/new-in-devtools-104/index.md index a30a44ce0..231c6974a 100644 --- a/site/zh/blog/new-in-devtools-104/index.md +++ b/site/zh/blog/new-in-devtools-104/index.md @@ -1,4 +1,4 @@ ---- +--- layout: "layouts/blog-post.njk" title: "DevTools 新功能(Chrome 104)" authors: @@ -28,9 +28,9 @@ tags: ## 在调试时进行帧重启 {: #restart-frame } -**帧重启** 功能回归了! 您可以在调试时的函数中途从头开始重启当前代码行之前的代码。这个功能曾经因为稳定性问题在 Chrome 92 版本被弃用。 +**帧重启** 功能回归了! 您可以在调试时的函数中途从头开始重启当前代码行之前的代码。这个功能曾经因为稳定性问题在 Chrome 92 版本被弃用。 -在这个 [例子](https://jec.fish/), 调试器暂停在这个靠近`toggleColorScheme`函数尾端的断点(343 行) 。 在函数 `toggleColorScheme`开始处重启调试器, 扩展在**调试器**面板中的 **调用** 部分, 在`toggleColorScheme`上右点击并选取**帧重启**。 +在这个 [例子](https://jec.fish/), 调试器暂停在这个靠近`toggleColorScheme`函数尾端的断点(343 行) 。 在函数 `toggleColorScheme`开始处重启调试器, 扩展在**调试器**面板中的 **调用** 部分, 在`toggleColorScheme`上右点击并选取**帧重启**。 {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/uBcTkuIaoHHTgJCiGNED.png", alt="在调试时进行帧重启", width="800", height="499" %} @@ -39,66 +39,66 @@ tags: Chromium 议题: [1303521](https://crbug.com/1303521) -## 录制面板中的慢速重播选项 {: #recorder } +## 录制面板中的慢速重播选项 {: #recorder } -您现在可以对用户流程进行慢速重播 - 慢、很慢和极慢. 这些选项使您能在屏幕上更加详细地观察到每一个重播的步骤。 +您现在可以对用户流程进行慢速重播 - 慢、很慢和极慢. 这些选项使您能在屏幕上更加详细地观察到每一个重播的步骤。 -[打开](/docs/devtools/recorder/#open) **录制** 面板,然后[开始一个新的录制](/docs/devtools/recorder/#record)。 录制完成后,在**重播**的下拉按钮上点击, 选择一个速率来进行重播流程。 +[打开](/docs/devtools/recorder/#open) **录制** 面板,然后[开始一个新的录制](/docs/devtools/recorder/#record)。 录制完成后,在**重播**的下拉按钮上点击, 选择一个速率来进行重播流程。 {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/yLIIMlaew0EWfEYdDbXJ.png", alt="录制面板上的慢速重播选项", width="800", height="486" %} Chromium 议题: [1306756](https://crbug.com/1306756) -## 为录制面板创建 extension {: #recorder-extension } +## 为录制面板创建 extension {: #recorder-extension } 您可以创建或安装一个Chrome扩展来使用您喜爱的格式来导出重播脚本。 看 [录制扩展应用程序界面API](/docs/extensions/reference/devtools_recorder/) 文档来学习如何自己创建一个Extension。 -按照[这些步骤](https://github.com/puppeteer/replay#create-a-chrome-extension-for-recorder-available-from-chrome-104-onwards) 安装一个演示扩展。 +按照[这些步骤](https://github.com/puppeteer/replay#create-a-chrome-extension-for-recorder-available-from-chrome-104-onwards) 安装一个演示扩展。 {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/xRO1d79tBe0ILcBoD0oh.png", alt="为录制面板客制化扩展", width="800", height="486" %} Chromium 议题: [1325751](https://crbug.com/1325751) -## 使用面板中的已编写/已部署来进行分组 {: #authored-deployed } +## 使用面板中的已编写/已部署来进行分组 {: #authored-deployed } + +启用新的**已编写/已部署**来进行分组以组织您的源面板中的文件。当使用框架(例如, React, Angular)来开发网络应用程序, 在浏览源文件的时候会非常困难,那是因为由构建工具(例如, Webpack, Vite)所产生的缩图造成的。 -启用新的**已编写/已部署**来进行分组以组织您的源面板中的文件。当使用框架(例如, React, Angular)来开发网络应用程序, 在浏览源文件的时候会非常困难,那是因为由构建工具(例如, Webpack, Vite)所产生的缩图造成的。 - -使用这个复选框, 您可以将文件分组成两个类别以进行快速搜索: +使用这个复选框, 您可以将文件分组成两个类别以进行快速搜索: - **已编写 (Authored)**. 类似您在集成开发环境(IDE)中的源文件。 DevTools 根据您的源图产生这些文件 (由您的构建工具DevTools所提供). -- **已部署(Deployed)** - 浏览器读取的真正文件。 通常这些是已压缩的文件。 - -您可以自己做一个尝试,用这个链接 [React demo](https://reactjs.org/)! +- **已部署(Deployed)** - 浏览器读取的真正文件。 通常这些是已压缩的文件。 + +您可以自己做一个尝试,用这个链接 [React demo](https://reactjs.org/)! {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/5E1qbkl0Gx1REx7FdqEr.png", alt="使用源面板中的已编写/已部署进行分组", width="800", height="521" %} {# https://chromium.googlesource.com/devtools/devtools-frontend/+/6bc65d0595702fc826ca87e2cfe519a134b62d90 #} - + Chromium 议题: [960909](https://crbug.com/960909) ## Performance insights 面板新增了用户计时轨道 {: #performance } -您现在可以透过 **Performance insights** 面板新增的**用户计时**轨道来查看您 performance recording 的 `performance.measure()` 标记。 +您现在可以透过 **Performance insights** 面板新增的**用户计时**轨道来查看您 performance recording 的 `performance.measure()` 标记。 -例如, 这个 [网页](https://jec.fish/demo/perf-measure) 使用 [`performance.measure()`](https://web.dev/usertiming/#calculating-measurements-with-measure())方法进行文字载入耗时的计算。 +例如, 这个 [网页](https://jec.fish/demo/perf-measure) 使用 [`performance.measure()`](https://web.dev/articles/usertiming#calculating_measurements_with_measure())方法进行文字载入耗时的计算。 -当您开始 [测量页面载入](/docs/devtools/performance-insights/#record), **用户计时** 追踪显示在录制中。在旁侧面板中点击计时物件检视计时细节. +当您开始 [测量页面载入](/docs/devtools/performance-insights/#record), **用户计时** 追踪显示在录制中。在旁侧面板中点击计时物件检视计时细节. {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/nxPCp6UaiGWJCWWx4Laa.png", alt="Performance insights 面板新增了用户计时轨道", width="800", height="499" %} Chromium 议题: [1322808](https://crbug.com/1322808) - -## 显示元素的分配槽(slot) {: #slot } -**元素**面板中的槽原件有一个新的`槽`徽章。当调试布局的问题时,使用这个功能快速地确认影响节点布局的元素 . +## 显示元素的分配槽(slot) {: #slot } + +**元素**面板中的槽原件有一个新的`槽`徽章。当调试布局的问题时,使用这个功能快速地确认影响节点布局的元素 . -这个 [样本](https://mdn.github.io/web-components-examples/slotted-pseudo-element/) 包含了几个被命名槽的卡片。 检查`个人-职业` 槽的卡片, 点击`槽` 靠近它的徽章以显示他的分配槽。 +这个 [样本](https://mdn.github.io/web-components-examples/slotted-pseudo-element/) 包含了几个被命名槽的卡片。 检查`个人-职业` 槽的卡片, 点击`槽` 靠近它的徽章以显示他的分配槽。 -[学习](https://developer.mozilla.org/docs/Web/Web_Components/Using_templates_and_slots) how to use [<template>](https://developer.mozilla.org/docs/Web/HTML/Element/template) and [<slot>](https://developer.mozilla.org/docs/Web/HTML/Element/slot) 元素分配一个可以用来填充网页组件的影子文件对象模型 (Shadow DOM) 的自由面板。 +[学习](https://developer.mozilla.org/docs/Web/Web_Components/Using_templates_and_slots) how to use [<template>](https://developer.mozilla.org/docs/Web/HTML/Element/template) and [<slot>](https://developer.mozilla.org/docs/Web/HTML/Element/slot) 元素分配一个可以用来填充网页组件的影子文件对象模型 (Shadow DOM) 的自由面板。 {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/7uQGHp9WoMCG1RIAkgIF.png", alt="显示元素的分配槽", width="800", height="486" %} @@ -107,22 +107,22 @@ Chromium 议题: [1322808](https://crbug.com/1322808) Chromium 议题: [1018906](https://crbug.com/1018906) -## 模拟性能录制的硬件并发 {: #simulate } - -在**性能** 面板中的**硬件并发**新设置让开发者设置由`navigator.hardwareConcurrency`报告的值。 - +## 模拟性能录制的硬件并发 {: #simulate } + +在**性能** 面板中的**硬件并发**新设置让开发者设置由`navigator.hardwareConcurrency`报告的值。 + 一些应用程序使用 `navigator.hardwareConcurrency`来调控他们的应用程序的并行程度, 例如, 调控Emscripten的可移植操作系统接口线程池(PThread)的大小. 使用这个功能, 开发者可以测试他们的应用程序在不同的内核数下的性能。 - + {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/PyykGRv29FZbBKJAwWOW.png", alt="模拟性能录制的硬件并行", width="800", height="536" %} {# https://chromium.googlesource.com/devtools/devtools-frontend/+/b26de259d74a45e700d989ad9178c5e3a8b73145 #} - + Chromium 议题: [1297439](https://crbug.com/1297439) -## 在自动填充层叠样式表(CSS)时预览非颜色数值的值 {: #css-var } +## 在自动填充层叠样式表(CSS)时预览非颜色数值的值 {: #css-var } -当完成自当填充层叠样式表(CSS)变量时, DevTools 可以使用有意义的数值填充非颜色变量,并且让你预览改变后的节点数值。 +当完成自当填充层叠样式表(CSS)变量时, DevTools 可以使用有意义的数值填充非颜色变量,并且让你预览改变后的节点数值。 {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/V4slwNtX9HwLPdAyr8JF.png", alt="在自动填充层叠样式表(CSS)时预览非颜色数值的值", width="800", height="431" %} @@ -130,21 +130,21 @@ Chromium 议题: [1297439](https://crbug.com/1297439) Chromium 议题: [1285091](https://crbug.com/1285091) - -## 识别退后/前进缓存面板中的阻塞帧 {: #bfcache } -[退后/前进缓存](/docs/devtools/application/back-forward-cache/) 面板中的**应用程序** 有新的 **帧** 分部来帮助你识别阻止页面符合bfcache条件的阻塞帧 . +## 识别退后/前进缓存面板中的阻塞帧 {: #bfcache } + +[退后/前进缓存](/docs/devtools/application/back-forward-cache/) 面板中的**应用程序** 有新的 **帧** 分部来帮助你识别阻止页面符合bfcache条件的阻塞帧 . {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/UaRYEoYYoXhjSIn9seYK.png", alt="识别退后/前进缓存面板中的阻塞帧", width="800", height="486" %} - + {# https://chromium.googlesource.com/devtools/devtools-frontend/+/897799b24fff0639d483111dd2d957288ba2bd06 #} - -Chromium 议题: [1288158](https://crbug.com/1288158) - - -## 改良JavaScript对象的自动填充建议 {: #autocomplete } -JavaScript对象属性的自动填充现在可以根据这个规律显示: +Chromium 议题: [1288158](https://crbug.com/1288158) + + +## 改良JavaScript对象的自动填充建议 {: #autocomplete } + +JavaScript对象属性的自动填充现在可以根据这个规律显示: 1. 拥有可枚举的属性 2. 拥有不可枚举的属性 @@ -156,32 +156,32 @@ JavaScript对象属性的自动填充现在可以根据这个规律显示: {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/IvFTcOWrBOTTMRHqn8u4.png", alt="JavaScript对象属性的自动填充现在可以根据这个规律显示", width="800", height="563" %} {# https://chromium.googlesource.com/devtools/devtools-frontend/+/cee5205ae93c95b1dce49e220b9ebfa8c998d5a6 #} - + Chromium 议题: [1299241](https://crbug.com/1299241) - + ## 源图优化 {: #sourcemaps } - -以下是列出了几个源图的修复,这些优化改进了整体调试体验: - -- 您现在可以在带有 sourceURL 注释的内联的 `<script>`脚本中设置断点。 -- 调试器现在可以解析带有源图的**范围**视图中的块作用域变量。 + +以下是列出了几个源图的修复,这些优化改进了整体调试体验: + +- 您现在可以在带有 sourceURL 注释的内联的 `<script>`脚本中设置断点。 +- 调试器现在可以解析带有源图的**范围**视图中的块作用域变量。 {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/gv9cGnDMF7OVlXPWntII.png", alt="解析块作用域变量lock scoped variables", width="800", height="532" %} -- 调试器现在可以解析带有源图的的**范围**视图中的块箭头函数的变量. +- 调试器现在可以解析带有源图的的**范围**视图中的块箭头函数的变量. {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/CZk0xjwMQAqknkW5G4Xf.png", alt="解析箭头函数中的变量", width="800", height="479" %} Chromium 议题: [1329113](https://crbug.com/1329113), [1322115](https://crbug.com/1322115) - - -## 其他亮点 {: #misc } - -这里是一些本版本中需要注意的修复: - + + +## 其他亮点 {: #misc } + +这里是一些本版本中需要注意的修复: + - 修复源面板中的**自动填充**设置。之前, 这个功能的关闭设置是失效的。 ([1323286](https://crbug.com/1323286)) - 更新**应用程序**面板中的**清单文件(Manifest)**来解析最新的配色方案的格式。 ([1318305](https://crbug.com/1318305)) - 改进了 **Performance insights** 中的 `<script async>` 渲染阻塞问题的建议。 之前,既使已经在脚本标注为异步, DevTools 也会建议用户`将异步属性添加到脚本标签`。 ([1334096](https://crbug.com/1334096)) -- **性能洞察**面板现在将iframes检测为布局变化的潜在原因。 你可以检看**细节**面板 中的iframe 细节。 ([1328873](https://crbug.com/1328873)) -- 当**命令菜单**中 [打开文件](/docs/devtools/resources/#open) , 编写文件 (源图产生的文件) 的排名会更加高,因此他们会出现在被相似命名的部署脚本之上。 ([1312929](https://crbug.com/1312929)) +- **性能洞察**面板现在将iframes检测为布局变化的潜在原因。 你可以检看**细节**面板 中的iframe 细节。 ([1328873](https://crbug.com/1328873)) +- 当**命令菜单**中 [打开文件](/docs/devtools/resources/#open) , 编写文件 (源图产生的文件) 的排名会更加高,因此他们会出现在被相似命名的部署脚本之上。 ([1312929](https://crbug.com/1312929)) {% Partial 'devtools/reach-out.md' %} diff --git a/site/zh/blog/new-in-devtools-105/index.md b/site/zh/blog/new-in-devtools-105/index.md index 8878d37d1..0f93a6eb9 100644 --- a/site/zh/blog/new-in-devtools-105/index.md +++ b/site/zh/blog/new-in-devtools-105/index.md @@ -58,8 +58,8 @@ Chromium 议题: [1257499](https://crbug.com/1257499) <!-- ## Largest Contentful Paint (LCP) in the Performance insights panel {: #lcp } --> ## Performance insights 面板中的最大内容绘制 (LCP) {: #lcp } -<!-- LCP is an important, user-centric metric for measuring [perceived load speed](https://web.dev/user-centric-performance-metrics/#types-of-metrics). You can now find out the critical paths and root causes of a [Largest Contentful Paint (LCP)](https://web.dev/lcp/). --> -最大内容绘制 (LCP) 是测量[感知加载速度](https://web.dev/user-centric-performance-metrics/#types-of-metrics)的一个以用户为中心的重要指标。 您现在可以找出 [最大内容绘制 (LCP)](https://web.dev/lcp/) 的关键路径和根本原因。 +<!-- LCP is an important, user-centric metric for measuring [perceived load speed](https://web.dev/articles/user-centric-performance-metrics#types_of_metrics). You can now find out the critical paths and root causes of a [Largest Contentful Paint (LCP)](https://web.dev/articles/lcp). --> +最大内容绘制 (LCP) 是测量[感知加载速度](https://web.dev/articles/user-centric-performance-metrics#types_of_metrics)的一个以用户为中心的重要指标。 您现在可以找出 [最大内容绘制 (LCP)](https://web.dev/articles/lcp) 的关键路径和根本原因。 <!-- In a [performance recording](/docs/devtools/performance-insights/#record), click on the LCP badge in the **Timeline**. In the **Details** pane, you can view the LCP score, learn how to fix resources that slow down the LCP and see the critical path for the LCP resource. --> 在 [性能录制](/docs/devtools/performance-insights/#record) 中,单击 **时间线** 中的 LCP 徽章。 在 **细节** 边栏中,您可以查看 LCP 分数,了解如何修复降低 LCP 速度的资源并查看 LCP 资源的关键路径。 <!-- See [Performance Insights](/docs/devtools/performance-insights/) to learn how to get actionable insights and improve your website’s performance with the panel. --> @@ -71,12 +71,12 @@ Chromium 议题: [1326481](https://crbug.com/1326481) <!-- ## Identify flashes of text (FOIT, FOUT) as potential root causes for layout shifts {: #foit-fout } --> ## 识别闪烁的文本(FOIT、FOUT)为布局偏移的潜在根本原因 {: #foit-fout } -<!-- The **Performance insights** panel now detects [flash of invisible text (FOIT) and flash of unstyled text (FOUT)](https://web.dev/preload-optional-fonts/#font-rendering) as potential root causes for layout shifts. --> -**Performance insights**面板现在可以检测 [flash of invisible text (FOIT) 和 flash of unstyled text (FOUT)](https://web.dev/preload-optional-fonts/#font-rendering) 作为布局偏移的根本原因。 +<!-- The **Performance insights** panel now detects [flash of invisible text (FOIT) and flash of unstyled text (FOUT)](https://web.dev/articles/preload-optional-fonts#font_rendering) as potential root causes for layout shifts. --> +**Performance insights**面板现在可以检测 [flash of invisible text (FOIT) 和 flash of unstyled text (FOUT)](https://web.dev/articles/preload-optional-fonts#font_rendering) 作为布局偏移的根本原因。 <!-- To view the potential root causes of a layout shift, click on a screenshot in the **Layout shifts** track. --> 单击 **Layout shifts** 轨道中的屏幕截图,以便查看布局偏移的潜在根本原因。 -<!-- See [Optimize WebFont loading and rendering](https://web.dev/optimize-webfont-loading/) to learn the technique to prevent layout shifts. --> -请参阅 [优化 WebFont 加载和渲染](https://web.dev/optimize-webfont-loading/) 以了解防止布局偏移的技术。 +<!-- See [Optimize WebFont loading and rendering](https://web.dev/articles/optimize-webfont-loading) to learn the technique to prevent layout shifts. --> +请参阅 [优化 WebFont 加载和渲染](https://web.dev/articles/optimize-webfont-loading) 以了解防止布局偏移的技术。 {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/AMN5oD5hlKhPhnq98sIB.png", alt="FOUT in the Performance insights panel", width="800", height="497" %} Chromium 议题: [1334628](https://crbug.com/1334628), [1328873](https://crbug.com/1328873) @@ -84,8 +84,8 @@ Chromium 议题: [1334628](https://crbug.com/1334628), [1328873](https://crbug.c <!-- ## Protocol handlers in the Manifest pane {: #manifest } --> ## Manifest 窗格中的协议处理程序 {: #manifest } -<!-- You can now use DevTools to test the [URL protocol handler registration](https://web.dev/url-protocol-handler/) for [Progressive Web Apps (PWA)](https://web.dev/learn/pwa/). --> -您现在可以使用 DevTools 测试[渐进式网络应用 (PWA)](https://web.dev/learn/pwa/) 的 [URL 协议处理程序注册](https://web.dev/url-protocol-handler/)。 +<!-- You can now use DevTools to test the [URL protocol handler registration](https://web.dev/articles/url-protocol-handler) for [Progressive Web Apps (PWA)](https://web.dev/learn/pwa). --> +您现在可以使用 DevTools 测试[渐进式网络应用 (PWA)](https://web.dev/learn/pwa) 的 [URL 协议处理程序注册](https://web.dev/articles/url-protocol-handler)。 <!-- The URL protocol handler registration lets installed PWAs handle links that use a specific protocol (e.g. [`magnet`](https://wikipedia.org/wiki/Magnet_URI_scheme), `web+example`) for a more integrated experience. --> URL 协议处理程序注册允许已安装的 PWA 处理使用特定协议的链接(例如 [`magnet`](https://wikipedia.org/wiki/Magnet_URI_scheme)、`web+example`)以获得更集成的体验。 <!-- Navigate to the **Protocol Handlers** section via the **Application** > **Manifest** pane. You can view and test all the available protocols here. --> @@ -104,8 +104,8 @@ Chromium 议题: [1300613](https://crbug.com/1300613) ## 元素面板中的顶层徽章 {: #top-layer } <!-- Use the [top layer badge](/blog/top-layer-devtools/#top-layer-support-design-in-devtools) to understand the concept of the top layer and visualize how the top layer content changes. --> 使用【顶层徽章】(/blog/top-layer-devtools/#top-layer-support-design-in-devtools) 了解顶层的概念,可视化顶层内容的变化。 -<!-- The [`<dialog>` element](https://web.dev/building-a-dialog-component/) has recently become stable across browsers. When you open a dialog, it is put into a [top layer](/blog/top-layer-devtools/). Top level content renders on top of all the other content. --> -[`<dialog>` 元素](https://web.dev/building-a-dialog-component/) 最近在浏览器中变得稳定。 当您打开一个对话框时,它会被放入一个 [top layer](/blog/top-layer-devtools/)。 顶层内容呈现在所有其他内容之上。 +<!-- The [`<dialog>` element](https://web.dev/articles/building-a-dialog-component) has recently become stable across browsers. When you open a dialog, it is put into a [top layer](/blog/top-layer-devtools/). Top level content renders on top of all the other content. --> +[`<dialog>` 元素](https://web.dev/articles/building-a-dialog-component) 最近在浏览器中变得稳定。 当您打开一个对话框时,它会被放入一个 [top layer](/blog/top-layer-devtools/)。 顶层内容呈现在所有其他内容之上。 <!-- In this [demo](https://jec.fish/demo/dialog), click **Open dialog**. --> 在此 [演示](https://jec.fish/demo/dialog) 中,单击 **Open dialog**。 <!-- To help visualize the top layer elements, DevTools adds a top layer container (`#top-layer`) to the DOM tree. It resides after the closing `</html>` tag. --> diff --git a/site/zh/blog/new-in-devtools-106/index.md b/site/zh/blog/new-in-devtools-106/index.md index 4804c16ff..3f1aad323 100644 --- a/site/zh/blog/new-in-devtools-106/index.md +++ b/site/zh/blog/new-in-devtools-106/index.md @@ -200,7 +200,7 @@ Chromium 议题: [1347390](https://crbug.com/1347390) <!-- ## LCP timings breakdown in the Performance Insights panel {: #insights } --> ## 性能洞察面板中的LCP时序分解 {: #insights } -<!-- The **Performance Insights** panel now shows the [timings breakdown](https://web.dev/optimize-lcp/#lcp-breakdown) of the [Largest Containful Paint (LCP)](/docs/devtools/performance-insights/#largest-contentful-paint). Use these timings information to understand and identify an opportunity to improve LCP performance. --> +<!-- The **Performance Insights** panel now shows the [timings breakdown](https://web.dev/articles/optimize-lcp#lcp_breakdown) of the [Largest Containful Paint (LCP)](/docs/devtools/performance-insights/#largest-contentful-paint). Use these timings information to understand and identify an opportunity to improve LCP performance. --> **性能洞察**面板现在显示了[时间表分类](web.dev/optimize-lcp/#lcp-breakdown)中的[Largest Containful Paint (LCP)](/docs/devtools/performance-insights/#largest-contentful-paint)。 并使用这些时间信息来了解和提高 LCP 性能的机会。 <!-- {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/hU6RmoRjFskL8P2ZAB9l.png", alt="LCP timings breakdown in the Performance Insights panel", width="800", height="523" %} --> @@ -235,8 +235,8 @@ Chromium 议题: [1351383](https://crbug.com/1351383) - 之前,[Recorder 扩展] (/docs/devtools/recorder/reference/#extension-troubleshooting)不时会在 **Recorder** 面板上不被显示出来。 <!-- - The **Styles** pane now displays a color picker for the [SVG `<stop>`](https://developer.mozilla.org/docs/Web/SVG/Element/stop) element’s `stop-color` property. ([1351096](https://crbug.com/1351096)) --> - **样式**边栏现在显示 [SVG `<stop>`](https://developer.mozilla.org/docs/Web/SVG/Element/stop) 元素的 `stop-color` 属性显示一个颜色选择器。([1351096](https://crbug.com/1351096)) -<!-- - Identify script causing [layout](https://web.dev/avoid-large-complex-layouts-and-layout-thrashing/) as the potential root causes for layout shifts in the **Performance Insights** panel. ([1343019](https://crbug.com/1343019)) --> -- 在 **Performance Insights** 面板中,识别导致[布局](https://web.dev/avoid-large-complex-layouts-and-layout-thrashing/)的脚本是布局转变的潜在根源。([1343019](https://crbug.com/1343019)) +<!-- - Identify script causing [layout](https://web.dev/articles/avoid-large-complex-layouts-and-layout-thrashing) as the potential root causes for layout shifts in the **Performance Insights** panel. ([1343019](https://crbug.com/1343019)) --> +- 在 **Performance Insights** 面板中,识别导致[布局](https://web.dev/articles/avoid-large-complex-layouts-and-layout-thrashing)的脚本是布局转变的潜在根源。([1343019](https://crbug.com/1343019)) <!-- - Display critical path for LCP web fonts in the **Performance Insights** panel. ([1350390](https://crbug.com/1350390)) --> - 在 **Performance Insights** 面板中显示 LCP 网页字体的关键路径。 ([1350390](https://crbug.com/1350390)) diff --git a/site/zh/blog/new-in-devtools-112/index.md b/site/zh/blog/new-in-devtools-112/index.md index ca821b437..3fc186e56 100644 --- a/site/zh/blog/new-in-devtools-112/index.md +++ b/site/zh/blog/new-in-devtools-112/index.md @@ -48,8 +48,8 @@ Chromium 议题: [1400243](https://crbug.com/1400243). ### 使用 pierce 选择器记录 {: #pierce-selectors } <!-- In addition to [custom, CSS, ARIA, text, and XPath selectors](/docs/devtools/recorder/reference/#selector), you can now record using [pierce selectors](https://pptr.dev/guides/query-selectors#pierce-selectors-pierce). These selectors behave like CSS ones but can also pierce through shadow roots. --> 除了 [custom, CSS, ARIA, text 和 XPath 选择器](/docs/devtools/recorder/reference/#selector),您现在还可以使用 [pierce 选择器](https://pptr.dev/guides/query-selectors#pierce-selectors-pierce)。 这些选择器的行为类似于 CSS 选择器,但也可以穿透影子根。 -<!-- Start a new recording on a page with [shadow DOM](https://web.dev/shadowdom-v1/) and check {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/hmp8j3HiLMCcqPArD9yt.svg", alt="Checkbox.", width="22", height="22" %} **Pierce** in **Selector types to record**. Record your interaction with elements in the shadow DOM and inspect the corresponding step. --> -在含有 [shadow DOM](https://web.dev/shadowdom-v1/) 的页面上开始一个新的记录。在 {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/hmp8j3HiLMCcqPArD9yt.svg", alt="复选框.", width="22", height="22" %} **Selector types to record** 选择 **Pierce**,并开始记录您与子 DOM 中元素的交互并检查相应的步骤。 +<!-- Start a new recording on a page with [shadow DOM](https://web.dev/articles/shadowdom-v1) and check {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/hmp8j3HiLMCcqPArD9yt.svg", alt="Checkbox.", width="22", height="22" %} **Pierce** in **Selector types to record**. Record your interaction with elements in the shadow DOM and inspect the corresponding step. --> +在含有 [shadow DOM](https://web.dev/articles/shadowdom-v1) 的页面上开始一个新的记录。在 {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/hmp8j3HiLMCcqPArD9yt.svg", alt="复选框.", width="22", height="22" %} **Selector types to record** 选择 **Pierce**,并开始记录您与子 DOM 中元素的交互并检查相应的步骤。 {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/Spqbf2DG3Fr0D2sc1kgC.png", alt="将记录器设置为使用 pierce 选择器; Pierce 选择器使用中。", width="800", height="534" %} @@ -98,7 +98,7 @@ Chromium 议题: [1417104](https://crbug.com/1417104), [1413168](https://crbug.c 如果您很了解 CSS,您可能会觉得工具提示很麻烦。 要将它们全部关闭,请选择 {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/hmp8j3HiLMCcqPArD9yt.svg", alt="复选框。", width="22", height="22" %} **Don't show**. <!-- To turn them back on, check {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/9gzXiTYY0nZzBxGI6KrV.svg", alt="Settings.", width="24", height="24" %} [**Settings** > **Preferences** > **Elements**](/docs/devtools/settings/preferences/#elements) > {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/hmp8j3HiLMCcqPArD9yt.svg", alt="Checkbox.", width="22", height="22" %} **Show CSS documentation tooltip**. --> -要重新打开它们,请检查 {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/9gzXiTYY0nZzBxGI6KrV.svg", alt="设置。", width="24", height="24" %} [**Settings** > **Preferences** > **Elements**](/docs/devtools/settings/preferences/#elements) > {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/hmp8j3HiLMCcqPArD9yt.svg", alt="Checkbox.", width="22", height="22" %} **Show CSS documentation tooltip**. +要重新打开它们,请检查 {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/9gzXiTYY0nZzBxGI6KrV.svg", alt="设置。", width="24", height="24" %} [**Settings** > **Preferences** > **Elements**](/docs/devtools/settings/preferences/#elements) > {% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/hmp8j3HiLMCcqPArD9yt.svg", alt="Checkbox.", width="22", height="22" %} **Show CSS documentation tooltip**. {% Aside %} <!-- DevTools pulls the descriptions for tooltips from [VS Code Custom Data](https://github.com/microsoft/vscode-custom-data). --> diff --git a/site/zh/blog/new-in-devtools-92/index.md b/site/zh/blog/new-in-devtools-92/index.md index 6ee88bbcd..38fa457f3 100644 --- a/site/zh/blog/new-in-devtools-92/index.md +++ b/site/zh/blog/new-in-devtools-92/index.md @@ -159,7 +159,7 @@ Chromium 议题: [622660](https://crbug.com/622660) ## 在**性能**面板中添加"计算相交部分" {: #computed-intersections } -DevTools 现在会在火焰图中显示**计算相交部分**了。这项更新可以帮助您发现 [intersection observers](https://web.dev/intersectionobserver-v2/) 事件,并调试这些事件潜在的性能开销。 +DevTools 现在会在火焰图中显示**计算相交部分**了。这项更新可以帮助您发现 [intersection observers](https://web.dev/articles/intersectionobserver-v2) 事件,并调试这些事件潜在的性能开销。 {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/Nx3K0Lpst0lICGbtpzsW.png", alt="性能面板中的计算相交部分", width="800", height="496" %} @@ -208,7 +208,7 @@ Chrome DevTools 使用 [Chrome DevTools 协议 (CDP)](https://chromedevtools.git {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/mRVrHC9WEet7cwA7QAeV.png", alt="协议监视器", width="800", height="496" %} -{# https://chromium.googlesource.com/devtools/devtools-frontend/+/40fcb9a9aae81ac1df2c19dee467ab3a4cf4088b #} +{# https://chromium.googlesource.com/devtools/devtools-frontend/+/40fcb9a9aae81ac1df2c19dee467ab3a4cf4088b #} {# https://chromium.googlesource.com/devtools/devtools-frontend/+/006e20c4226a7b2e5fde4026191b1eaf05bf8b8e #} Chromium 议题: [1204004](https://crbug.com/1204004), [1204466](https://crbug.com/1204466) @@ -230,10 +230,10 @@ Chromium 议题: [1204004](https://crbug.com/1204004), [1204466](https://crbug.c {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/kh1Z4jcWxbO6rYCSoIPn.png", alt="Puppeteer Recorder", width="800", height="557" %} -{# https://chromium.googlesource.com/devtools/devtools-frontend/+/b36b600405ef18131b89edf85cca816c955c1590 #} +{# https://chromium.googlesource.com/devtools/devtools-frontend/+/b36b600405ef18131b89edf85cca816c955c1590 #} {# https://chromium.googlesource.com/devtools/devtools-frontend/+/a2ffe4a8d202e56d640c2f8744c905354e2bca8e #} Chromium 议题: [1199787](https://crbug.com/1199787) {% Partial 'devtools/reach-out.md' %} -{% Partial 'devtools/whats-new.md' %} \ No newline at end of file +{% Partial 'devtools/whats-new.md' %} diff --git a/site/zh/blog/new-in-devtools-93/index.md b/site/zh/blog/new-in-devtools-93/index.md index ce9fbfb56..be59d56ea 100644 --- a/site/zh/blog/new-in-devtools-93/index.md +++ b/site/zh/blog/new-in-devtools-93/index.md @@ -24,7 +24,7 @@ tags: {% YouTube id="1VaPAnUGRz8" %} ## 样式窗格(Styles pane)可编辑 CSS 容器查询(container queries) {: #container-queries } -现在,您可以在**样式**窗格(Styles pane)那里查看以及编辑 [CSS 容器查询(container queries)](https://web.dev/new-responsive/#responsive-to-the-container)。 +现在,您可以在**样式**窗格(Styles pane)那里查看以及编辑 [CSS 容器查询(container queries)](https://web.dev/articles/new-responsive#responsive_to_the_container)。 容器查询的出现,给响应式设计提供更多的动态解决方案。虽`@container` @规则的工作方式与媒体查询(`@media`)类似,然而 `@container` 查询的对象是满足一定条件的祖先容器节点,而不是查询视口以及 user agent 信息。 @@ -41,7 +41,7 @@ Chromium 议题: [1146422](https://crbug.com/1146422) ## 网络面板可预览 Web bundle {: #web-bundle } -[Web bundle](https://web.dev/web-bundles/) 是一种新兴的文件格式,用于封装一个或多个 HTTP 资源。现在,您可以在**网络**面板那里预览 web bundle 的网络请求。 +[Web bundle](https://web.dev/articles/web-bundles) 是一种新兴的文件格式,用于封装一个或多个 HTTP 资源。现在,您可以在**网络**面板那里预览 web bundle 的网络请求。 web bundle 特性现还处于实验阶段。测试该特性之前,请在 `chrome://flags` 那里打开 `#enable-experimental-web-platform-features` 开关。 diff --git a/site/zh/blog/new-in-devtools-96/index.md b/site/zh/blog/new-in-devtools-96/index.md index 426bc8db7..fbe07ba98 100644 --- a/site/zh/blog/new-in-devtools-96/index.md +++ b/site/zh/blog/new-in-devtools-96/index.md @@ -224,8 +224,8 @@ Chromium 议题: [1232937](https://crbug.com/1232937), [1255586](https://crbug.c <!-- ## Deprecated Application cache pane in the Application panel {: #app-cache } --> ## 弃用应用程序面板里面的应用程序缓存边栏 {: #app-cache } -<!-- The [Application cache](/docs/devtools/storage/applicationcache/) pane in the Application panel is now removed as the support for [AppCache](https://web.dev/appcache-removal/) is removed from Chrome and other Chromium-based browsers. --> -由于 Chrome 以及基于 Chromium 的浏览器都已移除对 [AppCache](https://web.dev/appcache-removal/) 的支持,因此**应用**面板里面的[应用缓存](/docs/devtools/storage/applicationcache/)边栏现已被移除。 +<!-- The [Application cache](/docs/devtools/storage/applicationcache/) pane in the Application panel is now removed as the support for [AppCache](https://web.dev/articles/appcache-removal) is removed from Chrome and other Chromium-based browsers. --> +由于 Chrome 以及基于 Chromium 的浏览器都已移除对 [AppCache](https://web.dev/articles/appcache-removal) 的支持,因此**应用**面板里面的[应用缓存](/docs/devtools/storage/applicationcache/)边栏现已被移除。 {# https://chromium.googlesource.com/devtools/devtools-frontend/+/de4d15e955d6145674e3885cde8a5a70f1269b79 #} @@ -240,8 +240,8 @@ Chromium 议题:[1084190](https://crbug.com/1084190) 要启用实验,请在**设置** > **实验**下勾选带有**在应用面板里面启用 Reporting API 边栏**字样的复选框选项。 {% endAside %} -<!-- The [Reporting API](https://web.dev/reporting-api/) is designed to help you monitor security violations of your page, deprecated API calls, and more. --> -[Reporting API](https://web.dev/reporting-api/) 旨在帮助您监控违规网页,过时的API调用以及更多。 +<!-- The [Reporting API](https://web.dev/articles/reporting-api) is designed to help you monitor security violations of your page, deprecated API calls, and more. --> +[Reporting API](https://web.dev/articles/reporting-api) 旨在帮助您监控违规网页,过时的API调用以及更多。 <!-- With this experiment enabled, you can now view the reports status in the new **Reporting API** pane in the **Application** panel. --> 启用此实验后,您现在可以在**应用程序**面板的新 **Reporting API** 边栏里面查看报告状态。 @@ -249,8 +249,8 @@ Chromium 议题:[1084190](https://crbug.com/1084190) <!-- Please note that the **Endpoints** section is currently still under active development (showing no reporting endpoints for now). --> 请注意,**Endpoints** 部分目前仍在积极开发中(目前没有 reporting endpoints)。 -<!-- Learn more about the **Reporting API** with [this article](https://web.dev/reporting-api/). --> -欲了解更多有关于 **Reporting API** 的信息,请阅读[这篇文章](https://web.dev/reporting-api/)。 +<!-- Learn more about the **Reporting API** with [this article](https://web.dev/articles/reporting-api). --> +欲了解更多有关于 **Reporting API** 的信息,请阅读[这篇文章](https://web.dev/articles/reporting-api)。 {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/hbwFqi9aNDOj70FhLXsn.png", alt="应用程序面板里面新增 Reporting API 窗格", width="800", height="476" %} diff --git a/site/zh/blog/new-in-devtools-98/index.md b/site/zh/blog/new-in-devtools-98/index.md index 9b735b9af..abceecb88 100644 --- a/site/zh/blog/new-in-devtools-98/index.md +++ b/site/zh/blog/new-in-devtools-98/index.md @@ -85,7 +85,7 @@ Chromium 议题:[1238818](https://crbug.com/1238818),[1268754](https://crbug <!-- Optionally, you can adjust the **Timeout** in the **Replay settings** for all the steps. Expand the **Replay settings** and edit the **Timeout** value. --> 另外,您可以在**重放设置**中为所有步骤调整**超时**。展开**重放设置**并编辑**超时**数值。 - + {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/y7RDpIp3pd2n6Vnxc5Du.png", alt="用户操作录制的超时设置", width="800", height="530" %} Chromium 议题:[1257499](https://crbug.com/1257499) @@ -94,8 +94,8 @@ Chromium 议题:[1257499](https://crbug.com/1257499) <!-- ## Ensure your pages are cacheable with the Back/forward cache tab {: #bfcache } --> ## 使用“往返缓存”选项卡确保您的页面可缓存 {: #bfcache } -<!-- [Back/forward cache (or bfcache)](https://web.dev/bfcache/) is a browser optimization that enables instant back and forward navigation. --> -[往返缓存(或 bfcache)](https://web.dev/bfcache/) 是一种浏览器优化,可提供即时的后退和前进导航。 +<!-- [Back/forward cache (or bfcache)](https://web.dev/articles/bfcache) is a browser optimization that enables instant back and forward navigation. --> +[往返缓存(或 bfcache)](https://web.dev/articles/bfcache) 是一种浏览器优化,可提供即时的后退和前进导航。 <!-- The new **Back/forward cache** tab can help you test your pages to ensure they're optimized for bfcache, and identify any issues that may be preventing them from being eligible. --> 新的**往返缓存**标签页可以帮助您测试您的页面,以确保它们针对 bfcache 进行了优化,并指出任何可能阻止它们符合 bfcache 条件的问题。 @@ -127,8 +127,8 @@ Chromium 议题:[1110752](https://crbug.com/1110752) {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/ewmNloO4ohRxlWRNuEW1.png", alt="属性边栏过滤", width="800", height="505" %} -{# https://chromium.googlesource.com/devtools/devtools-frontend/+/0980f52facf75b6c03e14472d13fe27968d4732b #} - +{# https://chromium.googlesource.com/devtools/devtools-frontend/+/0980f52facf75b6c03e14472d13fe27968d4732b #} + Chromium 议题:[1269674](https://crbug.com/1269674) @@ -191,7 +191,7 @@ Chromium 议题:[1263866](https://crbug.com/1263866) Chromium 议题: [1050021](https://crbug.com/1050021) - + <!-- ### Keyboard shortcut to expand all search results {: #toggle-search-result } --> ### 用于展开所有搜索结果的键盘快捷键 {: #toggle-search-result } @@ -219,8 +219,8 @@ Chromium 议题: [1255073](https://crbug.com/1255073) <!-- The **Lighthouse** panel is now running Lighthouse 9. Lighthouse will now list all the elements sharing the same id. --> **Lighthouse** 面板现在已运行 Lighthouse 9。Lighthouse 现在将列出所有共享相同 id 的元素。 -<!-- Non-unique element id is a common accessibility problem. For instance, the id referenced in an `aria-labelledby` attribute is used on [multiple elements](https://web.dev/duplicate-id-aria/). --> -重叠元素 id 是一个常见的无障碍(accessibility)问题。例如,`aria-labelledby` 属性中的 id 用于[多个元素](https://web.dev/duplicate-id-aria/)。 +<!-- Non-unique element id is a common accessibility problem. For instance, the id referenced in an `aria-labelledby` attribute is used on [multiple elements](https://web.dev/articles/duplicate-id-aria). --> +重叠元素 id 是一个常见的无障碍(accessibility)问题。例如,`aria-labelledby` 属性中的 id 用于[多个元素](https://web.dev/articles/duplicate-id-aria)。 <!-- Check out the [What’s new in Lighthouse 9.0](/blog/lighthouse-9-0/) for more details on the updates. --> 更多的 Lighthouse 更新细节,请参考 [What’s new in Lighthouse 9.0](/blog/lighthouse-9-0/)。 @@ -246,7 +246,7 @@ DevTools 升级使用 [CodeMirror 6](https://codemirror.net/6/)。此升级为** {# https://chromium.googlesource.com/devtools/devtools-frontend/+/c1ab112d9002d5c3b3bb70cf2839bac182f0cdb5 #} -Chromium 议题: [1241848](https://crbug.com/1241848) +Chromium 议题: [1241848](https://crbug.com/1241848) <!-- ## Miscellaneous highlights {: #misc } --> ## 其他的更新 {: #misc } @@ -256,7 +256,7 @@ Chromium 议题: [1241848](https://crbug.com/1241848) <!-- - Properly displaying the waterfall diagram of network requests. Previously, the style was broken. ([1275501](https://crbug.com/1275501)) - The code highlight was broken when searching in documents with very long lines in the **Sources** panel. It’s now fixed. ([1275496](https://crbug.com/1275496)) -- No more duplicate **Payload** tab in network requests. ([1273972](https://crbug.com/1273972)) +- No more duplicate **Payload** tab in network requests. ([1273972](https://crbug.com/1273972)) - Fixed the missing layout shifts details in the **Summary** section of the **Performance** panel. ([1259606](https://crbug.com/1259606)) - Support arbitrary characters (e.g. `,`, `.`), in **Network Search** queries. ([1267196](https://crbug.com/1267196)) --> - 修复网络请求的瀑布图。([1275501](https://crbug.com/1275501)) @@ -280,12 +280,12 @@ Chromium 议题: [1241848](https://crbug.com/1241848) <!-- The **Endpoints** section is now available. It gives you an overview of all the endpoints configured in the `Reporting-Endpoints` header. --> 这次我们加入了**端点**部分。它为您提供了在 `Reporting-Endpoints` 标头中配置的所有端点的概述。 -<!-- Learn to use the [Reporting API](https://web.dev/reporting-api/) to monitor security violations, deprecated API calls, and more. --> -浏览 [Reporting API](https://web.dev/reporting-api/) 文档,以学习如何使用 Reporting API 来监控违规网页,过时的API调用以及更多。 +<!-- Learn to use the [Reporting API](https://web.dev/articles/reporting-api) to monitor security violations, deprecated API calls, and more. --> +浏览 [Reporting API](https://web.dev/articles/reporting-api) 文档,以学习如何使用 Reporting API 来监控违规网页,过时的API调用以及更多。 {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/D1fUz4zuS1xwDbszgft1.png", alt=" Reporting API 窗格", width="800", height="560" %} -{# https://chromium.googlesource.com/devtools/devtools-frontend/+/a831b26b7ecde579144a42a4faaa7b639789bf3c #} +{# https://chromium.googlesource.com/devtools/devtools-frontend/+/a831b26b7ecde579144a42a4faaa7b639789bf3c #} Chromium 议题: [1200732](https://crbug.com/1200732) diff --git a/site/zh/blog/new-in-devtools-99/index.md b/site/zh/blog/new-in-devtools-99/index.md index 6e32f09f3..df335ffce 100644 --- a/site/zh/blog/new-in-devtools-99/index.md +++ b/site/zh/blog/new-in-devtools-99/index.md @@ -49,8 +49,8 @@ Chromium 议题: [423246](https://crbug.com/423246) <!-- Use the new **Reporting API** pane to monitor the reports generated on your page and their status. --> 使用 **报告 API** 新边栏来查看有关自己页面情况的报告以及报告对应的状态。 -<!-- The [Reporting API](https://web.dev/reporting-api/) is designed to help you monitor security violations of your page, deprecated API calls, and more. --> -该 [Reporting API](https://web.dev/reporting-api/) 是为了帮助您了解自己页面的安全违规情况,弃用 API 的调用情况以及更多。 +<!-- The [Reporting API](https://web.dev/articles/reporting-api) is designed to help you monitor security violations of your page, deprecated API calls, and more. --> +该 [Reporting API](https://web.dev/articles/reporting-api) 是为了帮助您了解自己页面的安全违规情况,弃用 API 的调用情况以及更多。 <!-- Open a page which uses the Reporting API (e.g. [demo page](https://reporting-api-demo.glitch.me/)). In the **Application** panel, scroll down to the **Background services** section and select the **Reporting API** pane. --> 打开一个使用 Reporting API 的页面(例如 [demo 页面](https://reporting-api-demo.glitch.me/))。在**应用**面板里面,把滚动条滚动到**后台服务**区域,然后选择 **Reporting API** 边栏。 @@ -169,8 +169,8 @@ Chromium 议题: [1284737](https://crbug.com/1284737) <!-- ### Display worker source files in the Sources panel {: #worker-sourcemap } --> ### Sources 面板里面显示 Worker 源文件 {: #worker-sourcemap } -<!-- [Worker](https://web.dev/workers-overview/) (e.g. web worker, service worker) source files with relative SourceURL are now displayed in the **Source** panel. Previously, worker source files were not handled correctly. --> -现在,[Worker](https://web.dev/workers-overview/)(例如:web worker、service worker)源文件在使用相对 SourceURL 的情况下,会被显示在 **Source** 面板里面。在此之前,Worker 源文件不会被正确处理。 +<!-- [Worker](https://web.dev/articles/workers-overview) (e.g. web worker, service worker) source files with relative SourceURL are now displayed in the **Source** panel. Previously, worker source files were not handled correctly. --> +现在,[Worker](https://web.dev/articles/workers-overview)(例如:web worker、service worker)源文件在使用相对 SourceURL 的情况下,会被显示在 **Source** 面板里面。在此之前,Worker 源文件不会被正确处理。 {% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/apH5n92bqYWINMQn5VXa.png", alt="Sources 面板里面显示 Worker 源文件", width="800", height="509" %} @@ -227,10 +227,10 @@ Chromium 议题: [1284245](https://crbug.com/1284245), [1284995](https://crbug.c - 修复 **Cookies** 面板里面关于 [edit cookies](/docs/devtools/storage/cookies/#edit) 问题。([1290196](https://crbug.com/1290196)) <!-- - Use `Shift` + `Tab` to select the previous command in the [Command menu](/docs/devtools/command-menu/). ([1278743](https://crbug.com/1278743)) --> - 使用 `Shift` + `Tab` 可以选择[命令菜单](/docs/devtools/command-menu/)里面的前一个命令。([1278743](https://crbug.com/1278743)) -<!-- - Report [CORS preflight request](https://web.dev/cross-origin-resource-sharing/#preflight-requests-for-complex-http-calls) issues in the [Issues](/docs/devtools/issues/) tab. ([1272445](https://crbug.com/1272445)). --> -- 在 [Issues](/docs/devtools/issues/) 选项卡里面,会报告 [CORS preflight request](https://web.dev/cross-origin-resource-sharing/#preflight-requests-for-complex-http-calls) 问题。([1272445](https://crbug.com/1272445)) -<!-- - Report [User-Agent Client Hints](https://web.dev/user-agent-client-hints/) issues in the [Issues](/docs/devtools/issues/) tab. ([1219359](https://crbug.com/1219359)). --> -- 在 [Issues](/docs/devtools/issues/) 选项卡里面,会报告 [User-Agent Client Hints](https://web.dev/user-agent-client-hints/) 问题。([1219359](https://crbug.com/1219359)) +<!-- - Report [CORS preflight request](https://web.dev/articles/cross-origin-resource-sharing#preflight_requests_for_complex_http_calls) issues in the [Issues](/docs/devtools/issues/) tab. ([1272445](https://crbug.com/1272445)). --> +- 在 [Issues](/docs/devtools/issues/) 选项卡里面,会报告 [CORS preflight request](https://web.dev/articles/cross-origin-resource-sharing#preflight_requests_for_complex_http_calls) 问题。([1272445](https://crbug.com/1272445)) +<!-- - Report [User-Agent Client Hints](https://web.dev/articles/user-agent-client-hints) issues in the [Issues](/docs/devtools/issues/) tab. ([1219359](https://crbug.com/1219359)). --> +- 在 [Issues](/docs/devtools/issues/) 选项卡里面,会报告 [User-Agent Client Hints](https://web.dev/articles/user-agent-client-hints) 问题。([1219359](https://crbug.com/1219359)) <!-- - Fixed `Shift` + `Delete` and `Page up` / `Page down` behaviors in the **Sources** and **Console** panel. ([1278461](https://crbug.com/1278461), [1285662](https://crbug.com/1285662)) --> - 在 **Sources** 和 **Console** 面板里面修复 `Shift` + `Delete` 和 `Page up` / `Page down` 的行为。([1278461](https://crbug.com/1278461), [1285662](https://crbug.com/1285662)) <!-- - Close the breakpoint edit dialog on breakpoint removal in the **Sources** panel. (922513) --> diff --git a/site/zh/docs/lighthouse/best-practices/external-anchors-use-rel-noopener/index.md b/site/zh/docs/lighthouse/best-practices/external-anchors-use-rel-noopener/index.md index de08115e7..4d4122a00 100644 --- a/site/zh/docs/lighthouse/best-practices/external-anchors-use-rel-noopener/index.md +++ b/site/zh/docs/lighthouse/best-practices/external-anchors-use-rel-noopener/index.md @@ -45,10 +45,10 @@ Lighthouse 使用以下过程将链接识别为不安全: - `rel="noopener"` 阻止新页面访问 `window.opener` 属性,并确保它在单独的进程中运行。 - `rel="noreferrer"` 具有相同的效果,但还会阻止将 `Referer` 标头发送到新页面。请参阅[链接类型“noreferrer”](https://html.spec.whatwg.org/multipage/links.html#link-type-noreferrer) 。 -有关更多信息,请参阅[安全地共享跨源资源](https://web.dev/cross-origin-resource-sharing/)帖文。 +有关更多信息,请参阅[安全地共享跨源资源](https://web.dev/articles/cross-origin-resource-sharing)帖文。 ## 资源 - [**指向跨源目的地的链接不安全**审计源代码](https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js) -- [安全地共享跨源资源](https://web.dev/cross-origin-resource-sharing/) +- [安全地共享跨源资源](https://web.dev/articles/cross-origin-resource-sharing) - [面向 Web 开发人员的站点隔离](https://developers.google.com/web/updates/2018/07/site-isolation) diff --git a/site/zh/docs/lighthouse/best-practices/image-aspect-ratio/index.md b/site/zh/docs/lighthouse/best-practices/image-aspect-ratio/index.md index 5b8d7c4a1..64a8b17dd 100644 --- a/site/zh/docs/lighthouse/best-practices/image-aspect-ratio/index.md +++ b/site/zh/docs/lighthouse/best-practices/image-aspect-ratio/index.md @@ -25,7 +25,7 @@ updated: 2020-04-29 ### 使用图像 CDN -图像 CDN 可以更轻松地将创建不同大小版本图像的过程自动化。查看[使用图像 CDN 优化图像](https://web.dev/image-cdns/)来了解基本情况,并查看[如何安装 Thumbor 图像 CDN](https://web.dev/install-thumbor/)来了解 codelab 实践。 +图像 CDN 可以更轻松地将创建不同大小版本图像的过程自动化。查看[使用图像 CDN 优化图像](https://web.dev/articles/image-cdns)来了解基本情况,并查看[如何安装 Thumbor 图像 CDN](https://web.dev/articles/install-thumbor)来了解 codelab 实践。 ### 检查影响图像纵横比的 CSS @@ -37,11 +37,11 @@ updated: 2020-04-29 但是,如果您使用的是响应式图像,那么在 HTML 中指定图像尺寸可能会很困难,因为您无法在知道视区尺寸之前知道宽度和高度的值。请考虑使用 [CSS Aspect Ratio](https://www.npmjs.com/package/css-aspect-ratio) 库或[纵横比框](https://css-tricks.com/aspect-ratio-boxes/)来保留响应式图像的纵横比。 -最后,查看[以正确尺寸提供图像](https://web.dev/serve-images-with-correct-dimensions/)一文,了解如何为每个用户的设备提供合适尺寸的图像。 +最后,查看[以正确尺寸提供图像](https://web.dev/articles/serve-images-with-correct-dimensions)一文,了解如何为每个用户的设备提供合适尺寸的图像。 ## 资源 - [**显示纵横比不正确的图像**审计的源代码](https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/audits/image-aspect-ratio.js) - [CSS Aspect Ratio](https://www.npmjs.com/package/css-aspect-ratio) - [纵横比框](https://css-tricks.com/aspect-ratio-boxes/) -- [以正确尺寸提供图像](https://web.dev/serve-images-with-correct-dimensions/) +- [以正确尺寸提供图像](https://web.dev/articles/serve-images-with-correct-dimensions) diff --git a/site/zh/docs/lighthouse/performance/bootup-time/index.md b/site/zh/docs/lighthouse/performance/bootup-time/index.md index dabb961a4..0e41ea1a2 100644 --- a/site/zh/docs/lighthouse/performance/bootup-time/index.md +++ b/site/zh/docs/lighthouse/performance/bootup-time/index.md @@ -20,7 +20,7 @@ tags: - **执行成本** - JavaScript 也在主线程上执行。如果您的页面在真正需要之前运行了大量代码,这也会延迟您的[交互时间](https://web.dev/tti/),这是与用户如何看待您的页面速度相关的关键指标之一。 + JavaScript 也在主线程上执行。如果您的页面在真正需要之前运行了大量代码,这也会延迟您的[交互时间](https://web.dev/articles/tti),这是与用户如何看待您的页面速度相关的关键指标之一。 - **内存成本** diff --git a/site/zh/docs/lighthouse/performance/critical-request-chains/index.md b/site/zh/docs/lighthouse/performance/critical-request-chains/index.md index d85a8eed9..fa7d0990e 100644 --- a/site/zh/docs/lighthouse/performance/critical-request-chains/index.md +++ b/site/zh/docs/lighthouse/performance/critical-request-chains/index.md @@ -32,7 +32,7 @@ Lighthouse 使用网络优先级作为识别阻塞呈现的关键资源的代理 - 优化关键字节数以减少下载时间(往返次数)。 - 优化剩余关键资源的加载顺序:尽早下载所有关键资产,缩短关键路径长度。 -了解有关优化[图像](https://web.dev/use-imagemin-to-compress-images/)、[JavaScript](https://web.dev/apply-instant-loading-with-prpl/)、[CSS](https://web.dev/defer-non-critical-css/) 和 [Web 字体的更多信息](https://web.dev/avoid-invisible-text/)。 +了解有关优化[图像](https://web.dev/articles/use-imagemin-to-compress-images)、[JavaScript](https://web.dev/articles/apply-instant-loading-with-prpl)、[CSS](https://web.dev/articles/defer-non-critical-css) 和 [Web 字体的更多信息](https://web.dev/articles/avoid-invisible-text)。 ## 特定于堆栈的指南 diff --git a/site/zh/docs/lighthouse/performance/dom-size/index.md b/site/zh/docs/lighthouse/performance/dom-size/index.md index ad8018257..bb83cd70e 100644 --- a/site/zh/docs/lighthouse/performance/dom-size/index.md +++ b/site/zh/docs/lighthouse/performance/dom-size/index.md @@ -49,11 +49,11 @@ Lighthouse 使用 DOM 树标记页面: ### Angular -如果要渲染大型列表,请使用组件开发工具包 (CDK) 中的[虚拟滚动](https://web.dev/virtualize-lists-with-angular-cdk/)。 +如果要渲染大型列表,请使用组件开发工具包 (CDK) 中的[虚拟滚动](https://web.dev/articles/virtualize-lists-with-angular-cdk)。 ### React -- 如果在页面上渲染许多重复元素,[`react-window`](https://web.dev/virtualize-long-lists-react-window/) 之列的“窗口化”库可以最大限度减少创建的 DOM 节点的数量。 +- 如果在页面上渲染许多重复元素,[`react-window`](https://web.dev/articles/virtualize-long-lists-react-window) 之列的“窗口化”库可以最大限度减少创建的 DOM 节点的数量。 - 使用 [`shouldComponentUpdate`](https://reactjs.org/docs/optimizing-performance.html#shouldcomponentupdate-in-action)、[`PureComponent`](https://reactjs.org/docs/react-api.html#reactpurecomponent) 或 [`React.memo`](https://reactjs.org/docs/react-api.html#reactmemo) 最大限度减少非必要的重新渲染。 - 如果使用 `Effect` 挂钩来提高运行时性能,则仅在某些依赖项发生更改后[跳过效果](https://reactjs.org/docs/hooks-effect.html#tip-optimizing-performance-by-skipping-effects)。 diff --git a/site/zh/docs/lighthouse/performance/lighthouse-total-blocking-time/index.md b/site/zh/docs/lighthouse/performance/lighthouse-total-blocking-time/index.md index edcd88b94..542201fc4 100644 --- a/site/zh/docs/lighthouse/performance/lighthouse-total-blocking-time/index.md +++ b/site/zh/docs/lighthouse/performance/lighthouse-total-blocking-time/index.md @@ -16,7 +16,7 @@ Lighthouse 报告以毫秒为单位显示 TBT: ## TBT 测量什么 -TBT 测量页面被阻止响应用户输入(例如鼠标点击、屏幕点击或按下键盘)的总时间。总和是[首次内容绘制](https://web.dev/fcp/)和[互动时间](https://web.dev/tti/)之间所有[长时间任务](https://web.dev/long-tasks-devtools/)*的阻塞部分*之和。任何执行时间超过 50 毫秒的任务都是长任务。50 毫秒后的时间量是阻塞部分。例如,如果 Lighthouse 检测到一个 70 毫秒长的任务,则阻塞部分将为 20 毫秒。 +TBT 测量页面被阻止响应用户输入(例如鼠标点击、屏幕点击或按下键盘)的总时间。总和是[首次内容绘制](https://web.dev/articles/fcp)和[互动时间](https://web.dev/articles/tti)之间所有[长时间任务](https://web.dev/articles/long-tasks-devtools)*的阻塞部分*之和。任何执行时间超过 50 毫秒的任务都是长任务。50 毫秒后的时间量是阻塞部分。例如,如果 Lighthouse 检测到一个 70 毫秒长的任务,则阻塞部分将为 20 毫秒。 ## Lighthouse 如何确定您的 TBT 分数 @@ -53,11 +53,11 @@ TBT 测量页面被阻止响应用户输入(例如鼠标点击、屏幕点击 ## 如何提高您的 TBT 分数 -请参阅[是什么导致了我的长时间任务?](https://web.dev/long-tasks-devtools/#what-is-causing-my-long-tasks)了解如何使用 Chrome DevTools 的性能面板诊断长时间任务的根本原因。 +请参阅[是什么导致了我的长时间任务?](https://web.dev/articles/long-tasks-devtools#what_is_causing_my_long_tasks)了解如何使用 Chrome DevTools 的性能面板诊断长时间任务的根本原因。 一般来说,导致长时间任务的最常见原因是: -- 不必要的 JavaScript 加载、解析或执行。在性能面板中分析您的代码时,您可能会发现主线程正在执行加载页面并不真正需要的工作。[通过代码拆分减少 JavaScript 负载](https://web.dev/reduce-javascript-payloads-with-code-splitting/)、[删除未使用的代码](https://web.dev/remove-unused-code/)或[有效加载第三方 JavaScript](https://web.dev/efficiently-load-third-party-javascript/) 应该可以提高您的 TBT 分数。 +- 不必要的 JavaScript 加载、解析或执行。在性能面板中分析您的代码时,您可能会发现主线程正在执行加载页面并不真正需要的工作。[通过代码拆分减少 JavaScript 负载](https://web.dev/articles/reduce-javascript-payloads-with-code-splitting)、[删除未使用的代码](https://web.dev/articles/remove-unused-code)或[有效加载第三方 JavaScript](https://web.dev/articles/efficiently-load-third-party-javascript) 应该可以提高您的 TBT 分数。 - 低效的 JavaScript 语句。例如,在性能面板中分析您的代码后,假设您看到对`document.querySelectorAll('a')`的调用返回 2000 个节点,则重构您的代码以使用仅返回 10 个节点的更具体的选择器,这样应该会提高您的 TBT 分数。 {% Aside %}在大多数网站上,通常有很大的空间改进不必要的 JavaScript 加载、解析或执行。 {% endAside %} @@ -67,10 +67,10 @@ TBT 测量页面被阻止响应用户输入(例如鼠标点击、屏幕点击 ## 资源 - [**总阻塞时间**审计的源代码](https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/audits/metrics/total-blocking-time.js) -- [长的 JavaScript 任务是否会延迟您的交互时间?](https://web.dev/long-tasks-devtools/) -- [优化首次输入延迟](https://web.dev/optimize-fid/) -- [首次内容绘制](https://web.dev/fcp/) -- [互动时间](https://web.dev/tti/) -- [通过代码拆分减少 JavaScript 负载](https://web.dev/reduce-javascript-payloads-with-code-splitting/) -- [删除未使用的代码](https://web.dev/remove-unused-code/) -- [高效加载第三方资源](https://web.dev/efficiently-load-third-party-javascript/) +- [长的 JavaScript 任务是否会延迟您的交互时间?](https://web.dev/articles/long-tasks-devtools) +- [优化首次输入延迟](https://web.dev/articles/optimize-fid) +- [首次内容绘制](https://web.dev/articles/fcp) +- [互动时间](https://web.dev/articles/tti) +- [通过代码拆分减少 JavaScript 负载](https://web.dev/articles/reduce-javascript-payloads-with-code-splitting) +- [删除未使用的代码](https://web.dev/articles/remove-unused-code) +- [高效加载第三方资源](https://web.dev/articles/efficiently-load-third-party-javascript) diff --git a/site/zh/docs/lighthouse/performance/non-composited-animations/index.md b/site/zh/docs/lighthouse/performance/non-composited-animations/index.md index f56568537..cdfb24634 100644 --- a/site/zh/docs/lighthouse/performance/non-composited-animations/index.md +++ b/site/zh/docs/lighthouse/performance/non-composited-animations/index.md @@ -5,7 +5,7 @@ description: 如何通过“避免非合成动画”Lighthouse 审计。 date: 2020-08-12 --- -在低端手机上,或当主线程上运行高性能任务时,非合成动画可能会出现卡顿(即不流畅)。卡顿的动画会提高页面的 [Cumulative Layout Shift](https://web.dev/cls/) (CLS)。降低 CLS 将提高 Lighthouse Performance 得分。 +在低端手机上,或当主线程上运行高性能任务时,非合成动画可能会出现卡顿(即不流畅)。卡顿的动画会提高页面的 [Cumulative Layout Shift](https://web.dev/articles/cls) (CLS)。降低 CLS 将提高 Lighthouse Performance 得分。 ## 背景 @@ -27,12 +27,12 @@ date: 2020-08-12 ## 如何确保合成动画 -请参阅[坚持仅合成器的属性和管理层计数](https://developers.google.com/web/fundamentals/performance/rendering/stick-to-compositor-only-properties-and-manage-layer-count)和[高性能动画](https://web.dev/animations-guide/)。 +请参阅[坚持仅合成器的属性和管理层计数](https://developers.google.com/web/fundamentals/performance/rendering/stick-to-compositor-only-properties-and-manage-layer-count)和[高性能动画](https://web.dev/articles/animations-guide)。 ## 资源 - [*避免非合成动画*审计的源代码](https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/audits/non-composited-animations.js) - [坚持仅合成器的属性和管理层计数](https://developers.google.com/web/fundamentals/performance/rendering/stick-to-compositor-only-properties-and-manage-layer-count) -- [高性能动画](https://web.dev/animations-guide/) +- [高性能动画](https://web.dev/articles/animations-guide) - [简化绘制的复杂度、减小绘制区域](https://developers.google.com/web/fundamentals/performance/rendering/simplify-paint-complexity-and-reduce-paint-areas) - [深入了解现代 Web 浏览器(第 3 部分)](https://developers.google.com/web/updates/2018/09/inside-browser-part3) diff --git a/site/zh/docs/lighthouse/performance/third-party-facades/index.md b/site/zh/docs/lighthouse/performance/third-party-facades/index.md index 3ec001e6d..25bd2700e 100644 --- a/site/zh/docs/lighthouse/performance/third-party-facades/index.md +++ b/site/zh/docs/lighthouse/performance/third-party-facades/index.md @@ -5,7 +5,7 @@ description: 了解使用 Facade 延迟加载第三方资源的机会。 date: 2020-12-01 --- -[第三方资源](https://web.dev/third-party-javascript/)通常用于展示广告或视频以及集成社交媒体。默认方法是在页面加载后立即加载第三方资源,但这可能会不必要地减慢页面的加载速度。如果第三方内容不是那么重要,则可以通过[延迟加载](https://web.dev/fast/#lazy-load-images-and-video)来降低这种性能消耗。 +[第三方资源](https://web.dev/articles/third-party-javascript)通常用于展示广告或视频以及集成社交媒体。默认方法是在页面加载后立即加载第三方资源,但这可能会不必要地减慢页面的加载速度。如果第三方内容不是那么重要,则可以通过[延迟加载](https://web.dev/articles/fast#lazy_load_images_and_video)来降低这种性能消耗。 此审计重点介绍了可以在交互时延迟加载的第三方嵌入内容。在这种情况下,在用户与其交互之前,将使用*{nbsp}facade*替换掉第三方内容。 diff --git a/site/zh/docs/lighthouse/performance/total-byte-weight/index.md b/site/zh/docs/lighthouse/performance/total-byte-weight/index.md index 8b3174bc4..0bb0668e3 100644 --- a/site/zh/docs/lighthouse/performance/total-byte-weight/index.md +++ b/site/zh/docs/lighthouse/performance/total-byte-weight/index.md @@ -22,22 +22,22 @@ updated: 2020-05-29 ## 如何减少有效负载大小 -争取将总字节大小保持在 1600 KiB 以下。该目标基于理论上可通过 3G 连接下载的数据量,同时仍可实现 10 秒或更短的[Time to Interactive](https://web.dev/tti/)。 +争取将总字节大小保持在 1600 KiB 以下。该目标基于理论上可通过 3G 连接下载的数据量,同时仍可实现 10 秒或更短的[Time to Interactive](https://web.dev/articles/tti)。 以下是一些降低有效负载大小的方法: -- 在真正需要请求之前尽量推迟它们。请参阅 [PRPL Pattern](https://web.dev/apply-instant-loading-with-prpl/) 提供的一种可能办法。 +- 在真正需要请求之前尽量推迟它们。请参阅 [PRPL Pattern](https://web.dev/articles/apply-instant-loading-with-prpl) 提供的一种可能办法。 - 将请求优化得尽可能小。可能实现的技术包括: - - [缩小和压缩网络有效负载](https://web.dev/reduce-network-payloads-using-text-compression/)。 - - [图像使用 WebP 格式,而不是 JPEG 或 PNG](https://web.dev/serve-images-webp/)。 - - [将 JPEG 图像的压缩级别设为 85](https://web.dev/use-imagemin-to-compress-images/) 。 -- 缓存请求,避免在重复访问页面时重新下载资源。 (请参阅[网络可靠性登录页面](https://web.dev/reliable/)来了解缓存的工作原理以及实现方法。) + - [缩小和压缩网络有效负载](https://web.dev/articles/reduce-network-payloads-using-text-compression)。 + - [图像使用 WebP 格式,而不是 JPEG 或 PNG](https://web.dev/articles/serve-images-webp)。 + - [将 JPEG 图像的压缩级别设为 85](https://web.dev/articles/use-imagemin-to-compress-images) 。 +- 缓存请求,避免在重复访问页面时重新下载资源。 (请参阅[网络可靠性登录页面](https://web.dev/explore/reliable)来了解缓存的工作原理以及实现方法。) ## 针对堆栈的具体指导 ### Angular -应用[路由级代码拆分](https://web.dev/route-level-code-splitting-in-angular/),将 JavaScript 包最小化。此外,请考虑使用 [Angular 服务工作进程](https://web.dev/precaching-with-the-angular-service-worker/)来预缓存资产。 +应用[路由级代码拆分](https://web.dev/articles/route-level-code-splitting-in-angular),将 JavaScript 包最小化。此外,请考虑使用 [Angular 服务工作进程](https://web.dev/articles/precaching-with-the-angular-service-worker)来预缓存资产。 ### Drupal diff --git a/site/zh/docs/lighthouse/performance/unused-css-rules/index.md b/site/zh/docs/lighthouse/performance/unused-css-rules/index.md index aa7dc8d08..e9db89ac2 100644 --- a/site/zh/docs/lighthouse/performance/unused-css-rules/index.md +++ b/site/zh/docs/lighthouse/performance/unused-css-rules/index.md @@ -44,7 +44,7 @@ Lighthouse 报告的“Opportunities(机会)”部分列出了所有未使 考虑使用[关键工具](https://github.com/addyosmani/critical/blob/master/README.md)自动化提取和内联“首屏”CSS 的过程。 -在[延迟非关键 CSS](https://web.dev/defer-non-critical-css/) 中了解更多信息。 +在[延迟非关键 CSS](https://web.dev/articles/defer-non-critical-css) 中了解更多信息。 ## 特定于堆栈的指南 diff --git a/site/zh/docs/lighthouse/performance/uses-optimized-images/index.md b/site/zh/docs/lighthouse/performance/uses-optimized-images/index.md index a73d9b87e..71c9709c5 100644 --- a/site/zh/docs/lighthouse/performance/uses-optimized-images/index.md +++ b/site/zh/docs/lighthouse/performance/uses-optimized-images/index.md @@ -18,13 +18,13 @@ Lighthouse 会收集页面上的所有 JPEG 或 BMP 图像,将每个图像的 可以采取许多步骤来优化图像,包括: -- [使用图像 CDN](https://web.dev/image-cdns/) -- [压缩图像](https://web.dev/use-imagemin-to-compress-images/) -- [用视频替换动画 GIF](https://web.dev/replace-gifs-with-videos/) -- [延迟加载图像](https://web.dev/use-lazysizes-to-lazyload-images/) -- [提供响应式图像](https://web.dev/serve-responsive-images/) -- [提供尺寸正确的图像](https://web.dev/serve-images-with-correct-dimensions/) -- [使用 WebP 图像](https://web.dev/serve-images-webp/) +- [使用图像 CDN](https://web.dev/articles/image-cdns) +- [压缩图像](https://web.dev/articles/use-imagemin-to-compress-images) +- [用视频替换动画 GIF](https://web.dev/articles/replace-gifs-with-videos) +- [延迟加载图像](https://web.dev/articles/use-lazysizes-to-lazyload-images) +- [提供响应式图像](https://web.dev/articles/serve-responsive-images) +- [提供尺寸正确的图像](https://web.dev/articles/serve-images-with-correct-dimensions) +- [使用 WebP 图像](https://web.dev/articles/serve-images-webp) ## 使用 GUI 工具优化图像 diff --git a/site/zh/docs/lighthouse/performance/uses-rel-preconnect/index.md b/site/zh/docs/lighthouse/performance/uses-rel-preconnect/index.md index f32fc9e90..768964e26 100644 --- a/site/zh/docs/lighthouse/performance/uses-rel-preconnect/index.md +++ b/site/zh/docs/lighthouse/performance/uses-rel-preconnect/index.md @@ -57,5 +57,5 @@ Lighthouse 报告的“机会”部分列出了所有尚未使用 `<link rel=pre - [**预连接到所需的源**审计的源代码](https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/audits/uses-rel-preconnect.js) - [资源优先级——让浏览器帮助您](https://developers.google.com/web/fundamentals/performance/resource-prioritization#preconnect) -- [尽早建立网络连接以提高感知页面速度](https://web.dev/preconnect-and-dns-prefetch/) +- [尽早建立网络连接以提高感知页面速度](https://web.dev/articles/preconnect-and-dns-prefetch) - [链接类型:预连接](https://developer.mozilla.org/docs/Web/HTML/Link_types/preconnect#Browser_compatibility) diff --git a/site/zh/docs/lighthouse/performance/uses-text-compression/index.md b/site/zh/docs/lighthouse/performance/uses-text-compression/index.md index a9d0f6d02..50727489b 100644 --- a/site/zh/docs/lighthouse/performance/uses-text-compression/index.md +++ b/site/zh/docs/lighthouse/performance/uses-text-compression/index.md @@ -64,7 +64,7 @@ Content-Encoding: br 3. 启用大请求行。请参阅[使用大请求行](https://developers.google.com/web/tools/chrome-devtools/network/reference#request-rows)。 4. 查看您感兴趣的响应的 **Size** 列。上面的值是压缩大小,下面的值是解压缩大小。 -另请参阅[缩小和压缩网络有效负载](https://web.dev/reduce-network-payloads-using-text-compression/)。 +另请参阅[缩小和压缩网络有效负载](https://web.dev/articles/reduce-network-payloads-using-text-compression)。 ## 程序栈特定的指南 diff --git a/site/zh/docs/lighthouse/pwa/installable-manifest/index.md b/site/zh/docs/lighthouse/pwa/installable-manifest/index.md index 45c0fadaa..34c572cf8 100644 --- a/site/zh/docs/lighthouse/pwa/installable-manifest/index.md +++ b/site/zh/docs/lighthouse/pwa/installable-manifest/index.md @@ -10,13 +10,13 @@ date: 2019-05-04 updated: 2019-09-19 --- -可安装性是 [Progressive Web Apps (渐进式 Web 应用,PWA)](https://web.dev/progressive-web-apps/) 的核心要求。通过提示用户安装您的 PWA,您允许用户将其添加到他们的主屏幕。将应用添加到主屏幕的用户会更频繁地使用这些应用。 +可安装性是 [Progressive Web Apps (渐进式 Web 应用,PWA)](https://web.dev/explore/progressive-web-apps) 的核心要求。通过提示用户安装您的 PWA,您允许用户将其添加到他们的主屏幕。将应用添加到主屏幕的用户会更频繁地使用这些应用。 -[Web 应用清单](https://web.dev/add-manifest/)包含使您的应用可安装所需的关键信息。 +[Web 应用清单](https://web.dev/articles/add-manifest)包含使您的应用可安装所需的关键信息。 ## Lighthouse Web 应用程序清单审计如何失败 -[Lighthouse](https://developers.google.com/web/tools/lighthouse/)会标记没有满足可安装性最低要求的[Web 应用程序清单](https://web.dev/add-manifest/)的页面: +[Lighthouse](https://developers.google.com/web/tools/lighthouse/)会标记没有满足可安装性最低要求的[Web 应用程序清单](https://web.dev/articles/add-manifest)的页面: <figure>{% Img src="image/tcFciHGuF3MxnTr1y5ue01OGLBn2/039DlaixA4drrswBzSra.png", alt="显示用户无法从其主屏幕安装 Web 应用的 Lighthouse 审计", width="800", height="98" %}</figure> @@ -28,13 +28,13 @@ updated: 2019-09-19 - 设置为 `fullscreen` 、`standalone` 或 `minimal-ui` 的 [`display`](https://developer.mozilla.org/docs/Web/Manifest/display) 属性 - 设置为非 `true` 值的 [`prefer_related_applications`](https://developers.google.com/web/fundamentals/app-install-banners/native) 属性。 -{% Aside 'caution' %}要使您的应用可安装,Web 应用清单是*必需\*\*的,但这还不够*。要了解如何满足可安装性的所有要求,请参阅[了解可安装性](https://web.dev/progressive-web-apps/)帖子。 {% endAside %} +{% Aside 'caution' %}要使您的应用可安装,Web 应用清单是*必需\*\*的,但这还不够*。要了解如何满足可安装性的所有要求,请参阅[了解可安装性](https://web.dev/explore/progressive-web-apps)帖子。 {% endAside %} {% Partial 'lighthouse-pwa/scoring.njk' %} ## 如何使您的 PWA 可安装 -确保您的应用具有符合上述条件的清单。有关创建 PWA 的更多信息,请参阅[可安装](https://web.dev/progressive-web-apps/)集。 +确保您的应用具有符合上述条件的清单。有关创建 PWA 的更多信息,请参阅[可安装](https://web.dev/explore/progressive-web-apps)集。 ## 如何检查您的 PWA 是否可安装 @@ -42,7 +42,7 @@ updated: 2019-09-19 当您的应用满足可安装性的最低要求时,Chrome 会触发 `beforeinstallprompt` 事件,您可以使用该事件提示用户安装您的 PWA。 -{% Aside 'codelab' %}通过[使其可安装](https://web.dev/codelab-make-installable/)代码实验室了解如何使您的应用可安装在 Chrome 中。 {% endAside %} +{% Aside 'codelab' %}通过[使其可安装](https://web.dev/articles/codelab-make-installable)代码实验室了解如何使您的应用可安装在 Chrome 中。 {% endAside %} ### 在其他浏览器中 @@ -57,7 +57,7 @@ updated: 2019-09-19 ## 资源 - [**Web 应用清单不符合可安装性要求**审计源代码](https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/audits/installable-manifest.js) -- [添加 Web 应用清单](https://web.dev/add-manifest/) -- [了解如何具备可安装性](https://web.dev/progressive-web-apps/) +- [添加 Web 应用清单](https://web.dev/articles/add-manifest) +- [了解如何具备可安装性](https://web.dev/explore/progressive-web-apps) - [Web 应用清单](https://developer.mozilla.org/docs/Web/Manifest) - [不使用 HTTPS](/docs/lighthouse/pwa/is-on-https/) diff --git a/site/zh/docs/lighthouse/pwa/load-fast-enough-for-pwa/index.md b/site/zh/docs/lighthouse/pwa/load-fast-enough-for-pwa/index.md index 4eed68f02..af26c673b 100644 --- a/site/zh/docs/lighthouse/pwa/load-fast-enough-for-pwa/index.md +++ b/site/zh/docs/lighthouse/pwa/load-fast-enough-for-pwa/index.md @@ -21,7 +21,7 @@ updated: 2020-06-10 有两个主要指标影响了用户对加载时间的体验: - [首次有效绘制 (FMP)](/docs/lighthouse/performance/first-meaningful-paint/) ,它衡量页面的主要内容何时看起来完整 -- [交互用时 (TTI)](https://web.dev/tti/) ,衡量页面何时完全交互 +- [交互用时 (TTI)](https://web.dev/articles/tti) ,衡量页面何时完全交互 例如,如果一个页面在 1 秒后看起来完整,但用户在 10 秒内无法与其交互,则用户可能会认为页面加载时间为 10 秒。 diff --git a/site/zh/docs/lighthouse/pwa/maskable-icon-audit/index.md b/site/zh/docs/lighthouse/pwa/maskable-icon-audit/index.md index 5ed54b0bf..c733751d5 100644 --- a/site/zh/docs/lighthouse/pwa/maskable-icon-audit/index.md +++ b/site/zh/docs/lighthouse/pwa/maskable-icon-audit/index.md @@ -5,7 +5,7 @@ description: 了解如何向 PWA 添加可屏蔽图标支持。 date: 2020-05-06 --- -[可屏蔽图标](https://web.dev/maskable-icon/)是一种新的图标格式,可确保您的 PWA 图标在所有 Android 设备上看起来都很棒。在较新的 Android 设备上,不遵循可屏蔽图标格式的 PWA 图标被赋予白色背景。当您使用可屏蔽图标时,它可以确保该图标占用 Android 为其提供的所有空间。 +[可屏蔽图标](https://web.dev/articles/maskable-icon)是一种新的图标格式,可确保您的 PWA 图标在所有 Android 设备上看起来都很棒。在较新的 Android 设备上,不遵循可屏蔽图标格式的 PWA 图标被赋予白色背景。当您使用可屏蔽图标时,它可以确保该图标占用 Android 为其提供的所有空间。 ## Lighthouse 可屏蔽图标审计如何失败 @@ -27,7 +27,7 @@ date: 2020-05-06 1. 使用 [Maskable.app Editor](https://maskable.app/editor) 将现有图标转换为可屏蔽图标。 -2. 将` purpose` 属性添加到您的[Web 应用清单](https://web.dev/add-manifest/)中的其中一个 `icons` 对象中。将` purpose` 的值设置为 `maskable` 或 `any maskable`。请参阅[值](https://developer.mozilla.org/docs/Web/Manifest/icons#Values)。 +2. 将` purpose` 属性添加到您的[Web 应用清单](https://web.dev/articles/add-manifest)中的其中一个 `icons` 对象中。将` purpose` 的值设置为 `maskable` 或 `any maskable`。请参阅[值](https://developer.mozilla.org/docs/Web/Manifest/icons#Values)。 ```json/8 { @@ -45,12 +45,12 @@ date: 2020-05-06 } ``` -3. 使用 Chrome DevTools 验证可屏蔽图标是否正确显示。请参阅[我当前的图标是否准备就绪?](https://web.dev/maskable-icon/#are-my-current-icons-ready) +3. 使用 Chrome DevTools 验证可屏蔽图标是否正确显示。请参阅[我当前的图标是否准备就绪?](https://web.dev/articles/maskable-icon#are_my_current_icons_ready) ## 资源 - [**清单没有可屏蔽的图标**审计源代码](https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/audits/maskable-icon.js) -- [PWA 中具有可屏蔽图标的自适应图标支持](https://web.dev/maskable-icon/) +- [PWA 中具有可屏蔽图标的自适应图标支持](https://web.dev/articles/maskable-icon) - [Maskable.app Editor](https://maskable.app/editor) -- [添加 Web 应用清单](https://web.dev/add-manifest/) +- [添加 Web 应用清单](https://web.dev/articles/add-manifest) - [MDN 上的 `icons` 属性](https://developer.mozilla.org/docs/Web/Manifest/icons) diff --git a/site/zh/docs/lighthouse/pwa/service-worker/index.md b/site/zh/docs/lighthouse/pwa/service-worker/index.md index ab5f6db5c..6c4a159c0 100644 --- a/site/zh/docs/lighthouse/pwa/service-worker/index.md +++ b/site/zh/docs/lighthouse/pwa/service-worker/index.md @@ -6,13 +6,13 @@ date: 2019-05-04 updated: 2020-06-10 --- -注册[服务工作进程](https://web.dev/service-workers-cache-storage/)是启用以下关键[渐进式 Web 应用程序 (PWA)](https://web.dev/progressive-web-apps/) 特性的第一步: +注册[服务工作进程](https://web.dev/articles/service-workers-cache-storage)是启用以下关键[渐进式 Web 应用程序 (PWA)](https://web.dev/explore/progressive-web-apps) 特性的第一步: - 离线工作 - 支持推送通知 - 可以安装到设备 -有关更多信息,请参阅文章[服务工作进程和缓存存储 API](https://web.dev/service-workers-cache-storage/)。 +有关更多信息,请参阅文章[服务工作进程和缓存存储 API](https://web.dev/articles/service-workers-cache-storage)。 ## 浏览器兼容性 @@ -34,15 +34,15 @@ Lighthouse 检查 [Chrome 远程调试协议](https://github.com/ChromeDevTools/ 注册服务工作进程只需几行代码,但使用服务工作进程的唯一原因是可以实现上述 PWA 特性之一。实际上,实现这些特性需要更多工作: -- 要了解如何缓存文件以供离线使用,请参阅文章[什么是网络可靠性以及如何进行测量?](https://web.dev/network-connections-unreliable/)。 -- 要了解如何使应用程序可安装,请参阅[使其可安装](https://web.dev/codelab-make-installable/) codelab。 +- 要了解如何缓存文件以供离线使用,请参阅文章[什么是网络可靠性以及如何进行测量?](https://web.dev/articles/network-connections-unreliable)。 +- 要了解如何使应用程序可安装,请参阅[使其可安装](https://web.dev/articles/codelab-make-installable) codelab。 - 要了解如何启用推送通知,请参阅 Google 的[向 Web 应用程序添加推送通知](https://codelabs.developers.google.com/codelabs/push-notifications)。 ## 资源 - [**不注册可控制页面和 `start_url` 的服务工作进程**审计的源代码](https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/audits/service-worker.js) - [服务工作进程:简介](https://developers.google.com/web/fundamentals/primers/service-workers) -- [服务工作进程和缓存存储 API](https://web.dev/service-workers-cache-storage/) -- [什么是网络可靠性以及如何进行测量?](https://web.dev/network-connections-unreliable/) -- [使其可安装](https://web.dev/codelab-make-installable/) +- [服务工作进程和缓存存储 API](https://web.dev/articles/service-workers-cache-storage) +- [什么是网络可靠性以及如何进行测量?](https://web.dev/articles/network-connections-unreliable) +- [使其可安装](https://web.dev/articles/codelab-make-installable) - [向 Web 应用程序添加推送通知](https://codelabs.developers.google.com/codelabs/push-notifications) diff --git a/site/zh/docs/lighthouse/pwa/splash-screen/index.md b/site/zh/docs/lighthouse/pwa/splash-screen/index.md index a5c40b411..43c9d63ab 100644 --- a/site/zh/docs/lighthouse/pwa/splash-screen/index.md +++ b/site/zh/docs/lighthouse/pwa/splash-screen/index.md @@ -6,7 +6,7 @@ date: 2019-05-04 updated: 2019-09-19 --- -自定义初始屏幕使您的[渐进式 Web 应用 (PWA)](https://web.dev/progressive-web-apps/) 感觉更像是为特定设备专门构建。默认情况下,当用户从主屏幕启动您的 PWA 时,Android 会显示一个白屏,直到 PWA 准备就绪。用户可能会看着这个空白的白色屏幕长达 200 毫秒。通过设置自定义初始屏幕,您可以向用户显示自定义背景颜色和 PWA 图标,提供品牌化、吸引人的体验。 +自定义初始屏幕使您的[渐进式 Web 应用 (PWA)](https://web.dev/explore/progressive-web-apps) 感觉更像是为特定设备专门构建。默认情况下,当用户从主屏幕启动您的 PWA 时,Android 会显示一个白屏,直到 PWA 准备就绪。用户可能会看着这个空白的白色屏幕长达 200 毫秒。通过设置自定义初始屏幕,您可以向用户显示自定义背景颜色和 PWA 图标,提供品牌化、吸引人的体验。 ## Lighthouse 初始屏幕审计如何失败 @@ -18,7 +18,7 @@ updated: 2019-09-19 ## 如何创建自定义初始屏幕 -只要您在 [Web 应用清单](https://web.dev/add-manifest/)中满足以下要求,Android 版 Chrome 就会自动显示您的自定义初始屏幕: +只要您在 [Web 应用清单](https://web.dev/articles/add-manifest)中满足以下要求,Android 版 Chrome 就会自动显示您的自定义初始屏幕: - `name` 属性设置为您的 PWA 的名称。 - `background_color` 属性设置为有效的 CSS 颜色值。 diff --git a/site/zh/docs/lighthouse/pwa/themed-omnibox/index.md b/site/zh/docs/lighthouse/pwa/themed-omnibox/index.md index 1cca7196d..33a7525a2 100644 --- a/site/zh/docs/lighthouse/pwa/themed-omnibox/index.md +++ b/site/zh/docs/lighthouse/pwa/themed-omnibox/index.md @@ -6,7 +6,7 @@ date: 2019-05-04 updated: 2020-06-17 --- -通过设置浏览器地址栏的主题,来匹配您的[渐进式 Web 应用 (PWA)](https://web.dev/progressive-web-apps/) 的品牌颜色,提供更加身临其境的用户体验。 +通过设置浏览器地址栏的主题,来匹配您的[渐进式 Web 应用 (PWA)](https://web.dev/explore/progressive-web-apps) 的品牌颜色,提供更加身临其境的用户体验。 ## 浏览器兼容性 @@ -18,7 +18,7 @@ updated: 2020-06-17 <figure>{% Img src="image/tcFciHGuF3MxnTr1y5ue01OGLBn2/YadFSuw8denjl1hhnvFs.png", alt="Lighthouse 审计显示地址栏的颜色与页面颜色不匹配", width="800", height="98" %}</figure> -如果 Lighthouse 没有找到页面的 HTML 中的`theme-color`元标记和 [web 应用清单中的](https://web.dev/add-manifest/)`theme_color`属性,则审计将失败。 +如果 Lighthouse 没有找到页面的 HTML 中的`theme-color`元标记和 [web 应用清单中的](https://web.dev/articles/add-manifest)`theme_color`属性,则审计将失败。 请注意,Lighthouse 不会测试这些值是否为有效的 CSS 颜色值。 @@ -45,7 +45,7 @@ updated: 2020-06-17 ### 第 2 步:将`theme_color`属性添加到您的 web 应用清单 -Web 应用清单中的`theme_color`属性,可确保在用户从主屏幕启动您的 PWA 时对地址栏进行品牌化。与`theme-color`元标记不同,您只需要在[清单](https://web.dev/add-manifest/)中定义一次。将该属性设置为任何有效的 CSS 颜色值: +Web 应用清单中的`theme_color`属性,可确保在用户从主屏幕启动您的 PWA 时对地址栏进行品牌化。与`theme-color`元标记不同,您只需要在[清单](https://web.dev/articles/add-manifest)中定义一次。将该属性设置为任何有效的 CSS 颜色值: ```html/1 { @@ -59,5 +59,5 @@ Web 应用清单中的`theme_color`属性,可确保在用户从主屏幕启动 ## 资源 - [**没有为地址栏设置主题颜色**审计的源代码](https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/audits/themed-omnibox.js) -- [添加 web 应用清单](https://web.dev/add-manifest/) +- [添加 web 应用清单](https://web.dev/articles/add-manifest) - [对 Android 版 Chrome 39 中的`theme-color`](https://developers.google.com/web/updates/2014/11/Support-for-theme-color-in-Chrome-39-for-Android) 的支持 diff --git a/site/zh/docs/privacy-sandbox/attribution-reporting/index.md b/site/zh/docs/privacy-sandbox/attribution-reporting/index.md index e624e2ee6..77e494b91 100644 --- a/site/zh/docs/privacy-sandbox/attribution-reporting/index.md +++ b/site/zh/docs/privacy-sandbox/attribution-reporting/index.md @@ -48,7 +48,7 @@ authors: 归因报告 API 可以测量两个联系在一起的事件:发布商网站上的事件(例如用户浏览或点击广告)与随后在广告商网站上发生的转化。 -该 API 支持点击型转化归因测量(在 API 的第一次实现中即可使用,该 API 目前处于[原始试验](https://web.dev/conversion-measurement/#browser-support)阶段)和浏览型归因测量([请参阅公开详细说明](https://github.com/WICG/conversion-measurement-api/blob/main/event_attribution_reporting.md))。 +该 API 支持点击型转化归因测量(在 API 的第一次实现中即可使用,该 API 目前处于[原始试验](/docs/privacy-sandbox/attribution-reporting/#browser-support)阶段)和浏览型归因测量([请参阅公开详细说明](https://github.com/WICG/conversion-measurement-api/blob/main/event_attribution_reporting.md))。 该 API 提供两种类型的归因报告,可用于不同的用例: @@ -67,8 +67,8 @@ authors: - [归因报告介绍(转化测量)](/docs/privacy-sandbox/attribution-reporting-introduction) - [API 技术详细说明](https://github.com/WICG/conversion-measurement-api/) -- (⚠️ 已过时)[一种测量广告转化更私密的方式](https://web.dev/conversion-measurement/):此 API 第一次迭代的概述(面向网络开发者) +- (⚠️ 已过时)[一种测量广告转化更私密的方式](/docs/privacy-sandbox/attribution-reporting/):此 API 第一次迭代的概述(面向网络开发者) - (⚠️ 过时)[一种衡量广告转化的更私密方式 - 视频](https://www.youtube.com/watch?v=jcDfOoWwZcM):此 API 第一次迭代的演示(仅限点击) -- (⚠️ 已过时)[使用事件转化测量 API](https://web.dev/using-conversion-measurement/):如何使用此 API 的第一次迭代进行实验(面向网络开发者) +- (⚠️ 已过时)[使用事件转化测量 API](/docs/privacy-sandbox/attribution-reporting/):如何使用此 API 的第一次迭代进行实验(面向网络开发者) - [深入挖掘隐私沙盒](https://web.dev/digging-into-the-privacy-sandbox) - [使用 Chrome DevTools 调试 API](/blog/new-in-devtools-93/#attribution-reporting) diff --git a/site/zh/docs/privacy-sandbox/first-party-sets/index.md b/site/zh/docs/privacy-sandbox/first-party-sets/index.md index 01f733de0..a6b4aca6f 100644 --- a/site/zh/docs/privacy-sandbox/first-party-sets/index.md +++ b/site/zh/docs/privacy-sandbox/first-party-sets/index.md @@ -13,7 +13,7 @@ authors: ## 实现状态 -- [源站试用](https://web.dev/origin-trials/):Chrome 89 到 93。 +- [源站试用](/docs/web-platform/origin-trials/):Chrome 89 到 93。 - [注册源站试用](/origintrials/#/view_trial/988540118207823873)。 - [Chrome 平台状态](https://chromestatus.com/feature/5640066519007232)。 - [Chromium 项目](https://www.chromium.org/updates/first-party-sets)。 diff --git a/site/zh/docs/privacy-sandbox/floc/index.md b/site/zh/docs/privacy-sandbox/floc/index.md index 2d50d344d..2d5d0fb72 100644 --- a/site/zh/docs/privacy-sandbox/floc/index.md +++ b/site/zh/docs/privacy-sandbox/floc/index.md @@ -37,7 +37,7 @@ FLoC 为基于兴趣选择广告和其他内容提供了一种隐私保护机制 ## FLoC 的运作方式 -[什么是 FLoC?](https://web.dev/floc/#how-does-floc-work)提供了有关 FloC 运作方式的简要分步说明。 +[什么是 FLoC?](https://web.dev/articles/floc#how_does_floc_work)提供了有关 FloC 运作方式的简要分步说明。 下图显示了使用 FLoC 选择和投放相关广告时不同角色的示例。 diff --git a/site/zh/docs/privacy-sandbox/glossary/index.md b/site/zh/docs/privacy-sandbox/glossary/index.md index 30613c28a..fa834c70f 100644 --- a/site/zh/docs/privacy-sandbox/glossary/index.md +++ b/site/zh/docs/privacy-sandbox/glossary/index.md @@ -124,7 +124,7 @@ glitch.me ## 源站试用 {: #origin-trial } -源站试用可提供对新功能或实验性功能的访问,从而可以构建可供用户试用的功能,以在该功能面向所有用户发布之前的有限时间内进行试用。当 Chrome 针对某项功能提供源站试用时,可为试用注册一个[源站](#origin),从而对该来源的所有用户启用该功能,而用户无需切换任何标志或切换到其他版本的 Chrome 浏览器(虽然他们可能需要升级)。源站试用使开发者能够构建使用新功能的演示和原型。试用还可以帮助 Chrome 工程师了解新功能的使用情况,以及它们与其他网站技术的交互情况。了解更多信息:[Chrome 源站试用入门](https://web.dev/origin-trials/)。 +源站试用可提供对新功能或实验性功能的访问,从而可以构建可供用户试用的功能,以在该功能面向所有用户发布之前的有限时间内进行试用。当 Chrome 针对某项功能提供源站试用时,可为试用注册一个[源站](#origin),从而对该来源的所有用户启用该功能,而用户无需切换任何标志或切换到其他版本的 Chrome 浏览器(虽然他们可能需要升级)。源站试用使开发者能够构建使用新功能的演示和原型。试用还可以帮助 Chrome 工程师了解新功能的使用情况,以及它们与其他网站技术的交互情况。了解更多信息:[Chrome 源站试用入门](/docs/web-platform/origin-trials/)。 ## 被动图面 {: #passive-surface } diff --git a/site/zh/docs/privacy-sandbox/overview/index.md b/site/zh/docs/privacy-sandbox/overview/index.md index 752c7101c..d27048d25 100644 --- a/site/zh/docs/privacy-sandbox/overview/index.md +++ b/site/zh/docs/privacy-sandbox/overview/index.md @@ -35,7 +35,7 @@ Chrome 团队开发的主要提案如下。 ### 第一方保护 -- [**SameSite Cookie 变更**](https://web.dev/samesite-cookies-explained/):通过显式标记您的跨网站 Cookie 来保护网站。 +- [**SameSite Cookie 变更**](https://web.dev/articles/samesite-cookies-explained):通过显式标记您的跨网站 Cookie 来保护网站。 - [**第一方集**](/docs/privacy-sandbox/first-party-sets):使同一实体拥有的相关域名能够声明自己属于同一个第一方。 ### 欺诈检测 @@ -45,7 +45,7 @@ Chrome 团队开发的主要提案如下。 ### 限制数据收集 - [**隐私预算**](https://www.youtube.com/watch?v=0STgfjSA6T8):允许网站获取有关用户浏览器或设备的信息,但浏览器可以对网站可访问的信息总量设置配额,从而无法识别用户身份。 -- [**用户代理客户端提示**](https://web.dev/user-agent-client-hints/):[用户代理](https://developer.mozilla.org/docs/Web/HTTP/Headers/User-Agent) (UA) 字符串是一个重要的被动["指纹"收集](https://w3c.github.io/fingerprinting-guidance/#passive)图面,并且难以处理。客户端提示使开发者能够主动请求其确切需要的用户设备或条件相关信息,而不需要从用户代理字符串中解析这些数据。 +- [**用户代理客户端提示**](https://web.dev/articles/user-agent-client-hints):[用户代理](https://developer.mozilla.org/docs/Web/HTTP/Headers/User-Agent) (UA) 字符串是一个重要的被动["指纹"收集](https://w3c.github.io/fingerprinting-guidance/#passive)图面,并且难以处理。客户端提示使开发者能够主动请求其确切需要的用户设备或条件相关信息,而不需要从用户代理字符串中解析这些数据。 - [**Gnatcatcher**](https://github.com/bslassey/ip-blindness):限制通过访问个人用户 IP 地址来识别个人用户身份的能力。提案包含两部分:[<strong data-md="">Willful IP Blindness</strong>](https://github.com/bslassey/ip-blindness/blob/master/willful_ip_blindness.md) 为网站提供了一种使浏览器知晓其并未将 IP 地址与用户相联系的方式;以及 [**Near-path NAT**](https://github.com/bslassey/ip-blindness/blob/master/near_path_nat.md) 允许用户组通过同一个私有化服务器发送其流量,从而有效地对网站主机隐藏其 IP 地址。Gnatcatcher 还可确保需要出于合法目的(例如防止滥用)而访问 IP 地址的网站可以在获得认证和审核的情况下予以访问。 ### 身份 @@ -90,10 +90,10 @@ API 提案说明需要反馈,特别是在缺少的用例和如何以更加保 ### 面向网站开发者的文章和视频 - [深入了解隐私沙盒](https://web.dev/digging-into-the-privacy-sandbox) -- [SameSite Cookie 说明](https://web.dev/samesite-cookies-explained/) +- [SameSite Cookie 说明](https://web.dev/articles/samesite-cookies-explained) - [信任令牌使用入门](https://web.dev/trust-tokens) -- [一种更私密的广告转化衡量方式](https://web.dev/conversion-measurement/) -- [什么是 FLoC?](https://web.dev/floc/) +- [一种更私密的广告转化衡量方式](/docs/privacy-sandbox/attribution-reporting/) +- [什么是 FLoC?](https://web.dev/articles/floc) - [隐私预算简介](https://www.youtube.com/watch?v=0STgfjSA6T8) ### 提案背后的原则和概念 diff --git a/site/zh/docs/privacy-sandbox/status/index.md b/site/zh/docs/privacy-sandbox/status/index.md index 8a519ab9e..5304c3a93 100644 --- a/site/zh/docs/privacy-sandbox/status/index.md +++ b/site/zh/docs/privacy-sandbox/status/index.md @@ -15,7 +15,7 @@ authors: *以前称为转化衡量。* -- [当前源站试用](https://web.dev/origin-trials/):现已从 Chrome 86 [扩展](https://groups.google.com/u/1/a/chromium.org/g/attribution-reporting-api-dev/c/ZKf9T8sRqAM)到 Chrome 93。 +- [当前源站试用](/docs/web-platform/origin-trials/):现已从 Chrome 86 [扩展](https://groups.google.com/u/1/a/chromium.org/g/attribution-reporting-api-dev/c/ZKf9T8sRqAM)到 Chrome 93。 - [注册源站试用](/origintrials/#/view_trial/3411476717733150721)。 - [演示](https://goo.gle/demo-event-level-conversion-measurement-api)。 - [Chrome 平台状态](https://www.chromestatus.com/features/6412002824028160)。 @@ -31,25 +31,25 @@ authors: - [归因报告(转化衡量)](/docs/privacy-sandbox/attribution-reporting) - [归因报告简介(转化衡量)](/docs/privacy-sandbox/attribution-reporting-introduction) - [API 技术说明](https://github.com/WICG/conversion-measurement-api/) -- (⚠️ 过时)[一种衡量广告转化的更私密方式](https://web.dev/conversion-measurement/):此 API 第一次迭代的概述(面向网站开发者) +- (⚠️ 过时)[一种衡量广告转化的更私密方式](/docs/privacy-sandbox/attribution-reporting/):此 API 第一次迭代的概述(面向网站开发者) - (⚠️ 过时)[一种衡量广告转化的更私密方式 - 视频](https://www.youtube.com/watch?v=jcDfOoWwZcM):此 API 第一次迭代的演示(仅限点击) -- (⚠️ 过时)[使用 Event Conversion Measurement API](https://web.dev/using-conversion-measurement/):如何使用此 API 的第一次迭代进行实验(面向网站开发者) +- (⚠️ 过时)[使用 Event Conversion Measurement API](/docs/privacy-sandbox/attribution-reporting/):如何使用此 API 的第一次迭代进行实验(面向网站开发者) - [深入了解隐私沙盒](https://web.dev/digging-into-the-privacy-sandbox) ## 信任令牌 -- [当前源站试用](https://web.dev/origin-trials/):现已从 Chrome 84 [扩展](https://groups.google.com/a/chromium.org/g/blink-dev/c/-W90wVkS0Ks/m/Jfh5-ZWpAQAJ)到 Chrome 94。 +- [当前源站试用](/docs/web-platform/origin-trials/):现已从 Chrome 84 [扩展](https://groups.google.com/a/chromium.org/g/blink-dev/c/-W90wVkS0Ks/m/Jfh5-ZWpAQAJ)到 Chrome 94。 - [注册源站试用](/origintrials/#/view_trial/2479231594867458049)。 - [演示](https://trust-token-demo.glitch.me/)。 - [Chrome 平台状态](https://www.chromestatus.com/feature/5078049450098688)。 - [Blink 状态](https://groups.google.com/a/chromium.org/g/blink-dev/search?q=trust%tokens)。 - [GitHub](https://github.com/WICG/trust-token-api):有关 API 问题和讨论,请参阅[议题](https://github.com/WICG/trust-token-api/issues)。 - [Chrome DevTools 集成](https://developers.google.com/web/updates/2021/01/devtools?utm_source=devtools#trust-token)。 -- 发现更多:[信任令牌使用入门](https://web.dev/trust-tokens/) +- 发现更多:[信任令牌使用入门](https://web.dev/articles/trust-tokens) ## 第一方集 -- [当前源站试用](https://web.dev/origin-trials/):Chrome 89 到 93。 +- [当前源站试用](/docs/web-platform/origin-trials/):Chrome 89 到 93。 - [注册源站试用](/origintrials/#/view_trial/988540118207823873)。 - [Chrome 平台状态](https://chromestatus.com/feature/5640066519007232)。 - [Blink 状态](https://groups.google.com/a/chromium.org/g/blink-dev/search?q=first-party%20sets)。 @@ -64,7 +64,7 @@ authors: - 正在与 [WICG](https://github.com/WICG/floc) 和兴趣小组探讨 [API 提案](https://www.w3.org/community/wicg/)。 - [GitHub](https://github.com/WICG/floc):有关 API 问题和讨论,请参阅[议题](https://github.com/WICG/floc/issues)。 - [Chrome 平台状态](https://www.chromestatus.com/features/5710139774468096)。 -- 发现更多:[什么是 FLoC?](https://web.dev/floc/) +- 发现更多:[什么是 FLoC?](https://web.dev/articles/floc) ## FLEDGE @@ -91,7 +91,7 @@ authors: ### 源站试用 -- [Chrome 的源站试用入门](https://web.dev/origin-trials/) +- [Chrome 的源站试用入门](/docs/web-platform/origin-trials/) - [什么是第三方源站试用?](https://web.dev/third-party-origin-trials) - [Chrome 源站试用问题排查](https://github.com/GoogleChrome/OriginTrials/blob/gh-pages/developer-guide.md) - [面向网站开发者的源站试用指南](https://github.com/GoogleChrome/OriginTrials/blob/gh-pages/developer-guide.md) diff --git a/site/zh/docs/privacy-sandbox/trust-tokens/index.md b/site/zh/docs/privacy-sandbox/trust-tokens/index.md index 6cecdd675..4185272ab 100644 --- a/site/zh/docs/privacy-sandbox/trust-tokens/index.md +++ b/site/zh/docs/privacy-sandbox/trust-tokens/index.md @@ -11,7 +11,7 @@ authors: ## 实现状态 -- [源站试用](https://web.dev/origin-trials/):Chrome 84 到 94。 +- [源站试用](/docs/web-platform/origin-trials/):Chrome 84 到 94。 - [注册试用](/origintrials/#/view_trial/2479231594867458049)。 - [演示](https://trust-token-demo.glitch.me/)。 - [Chrome DevTools 集成](https://developers.google.com/web/updates/2021/01/devtools?utm_source=devtools#trust-token)。 @@ -62,7 +62,7 @@ authors: 12. 发布商网站展示广告。 13. 计为一次广告观看展示。 -{% Aside %} 有关此示例中 JavaScript 调用的更多详细信息,请参阅[示例 API 用法](https://web.dev/trust-tokens/#sample-api-usage)。{% endAside %} +{% Aside %} 有关此示例中 JavaScript 调用的更多详细信息,请参阅[示例 API 用法](https://web.dev/articles/trust-tokens#sample_api_usage)。{% endAside %} --- @@ -78,6 +78,6 @@ authors: ## 发现更多 - [Trust Token API 技术说明](https://github.com/dvorak42/trust-token-api) -- [信任令牌入门](https://web.dev/trust-tokens/):面向网站开发者的概述 +- [信任令牌入门](https://web.dev/articles/trust-tokens):面向网站开发者的概述 - [Chrome 的源站试用入门](https://web.dev/origin-trials) - [深入了解隐私沙盒](https://web.dev/digging-into-the-privacy-sandbox) From bc9bc2c378b541248b060e48bc1b9b9336ebc1a6 Mon Sep 17 00:00:00 2001 From: Joe Medley <jmedley@google.com> Date: Wed, 11 Oct 2023 13:24:24 -0700 Subject: [PATCH 890/982] Rough in 'Support and feedback' section. (#7263) * Rough in 'Support and feedback' section. * Add content. * Update site/en/docs/extensions/support-feedback/file-a-bug/index.md Co-authored-by: amysteamdev <37001393+AmySteam@users.noreply.github.com> * Update site/en/docs/extensions/support-feedback/file-a-bug/index.md Co-authored-by: amysteamdev <37001393+AmySteam@users.noreply.github.com> * Update site/en/docs/extensions/support-feedback/file-a-bug/index.md Co-authored-by: amysteamdev <37001393+AmySteam@users.noreply.github.com> * Update site/en/docs/extensions/support-feedback/file-a-bug/index.md Co-authored-by: amysteamdev <37001393+AmySteam@users.noreply.github.com> * Update site/en/docs/extensions/support-feedback/file-a-bug/index.md Co-authored-by: amysteamdev <37001393+AmySteam@users.noreply.github.com> * Update site/en/docs/extensions/support-feedback/file-a-bug/index.md Co-authored-by: amysteamdev <37001393+AmySteam@users.noreply.github.com> * Update site/en/docs/extensions/support-feedback/find-a-bug/index.md Co-authored-by: amysteamdev <37001393+AmySteam@users.noreply.github.com> * Update site/en/docs/extensions/support-feedback/find-a-bug/index.md Co-authored-by: amysteamdev <37001393+AmySteam@users.noreply.github.com> * Update site/en/docs/extensions/support-feedback/find-a-bug/index.md Co-authored-by: amysteamdev <37001393+AmySteam@users.noreply.github.com> * Update site/en/docs/extensions/support-feedback/index.md Co-authored-by: amysteamdev <37001393+AmySteam@users.noreply.github.com> * Update site/en/docs/extensions/support-feedback/submit-a-feature-request/index.md Co-authored-by: amysteamdev <37001393+AmySteam@users.noreply.github.com> * Update site/en/docs/extensions/support-feedback/submit-a-feature-request/index.md * Update site/en/docs/extensions/support-feedback/submit-a-feature-request/index.md Co-authored-by: Oliver Dunk <oliverdunk@google.com> * Update site/en/docs/extensions/support-feedback/submit-a-feature-request/index.md * Update site/en/docs/extensions/support-feedback/find-a-bug/index.md Co-authored-by: Oliver Dunk <oliverdunk@google.com> * Update site/en/docs/extensions/support-feedback/file-a-bug/index.md Co-authored-by: Oliver Dunk <oliverdunk@google.com> * Update site/en/docs/extensions/support-feedback/file-a-bug/index.md --------- Co-authored-by: amysteamdev <37001393+AmySteam@users.noreply.github.com> Co-authored-by: Oliver Dunk <oliverdunk@google.com> --- redirects.yaml | 2 ++ site/_data/docs/extensions/toc.yml | 9 ++++++- site/_data/i18n/docs/extensions.yml | 4 ++- .../support-feedback/file-a-bug/index.md | 27 +++++++++++++++++++ .../support-feedback/find-a-bug/index.md | 18 +++++++++++++ .../getHelp}/index.md | 0 .../docs/extensions/support-feedback/index.md | 15 +++++++++++ .../submit-a-feature-request/index.md | 23 ++++++++++++++++ 8 files changed, 96 insertions(+), 2 deletions(-) create mode 100644 site/en/docs/extensions/support-feedback/file-a-bug/index.md create mode 100644 site/en/docs/extensions/support-feedback/find-a-bug/index.md rename site/en/docs/extensions/{gethelp => support-feedback/getHelp}/index.md (100%) create mode 100644 site/en/docs/extensions/support-feedback/index.md create mode 100644 site/en/docs/extensions/support-feedback/submit-a-feature-request/index.md diff --git a/redirects.yaml b/redirects.yaml index b83f09f7e..ad3d497ce 100644 --- a/redirects.yaml +++ b/redirects.yaml @@ -774,6 +774,8 @@ redirects: - from: /docs/privacy-sandbox/fledge/... to: /docs/privacy-sandbox/protected-audience/... +- from: /docs/extensions/gethelp + to: /docs/extensions/support-feedback - from: docs/extensions/mv3/single_purpose/ to: docs/extensions/mv3/quality_guidelines/ diff --git a/site/_data/docs/extensions/toc.yml b/site/_data/docs/extensions/toc.yml index 92bed1258..dafcfb22b 100644 --- a/site/_data/docs/extensions/toc.yml +++ b/site/_data/docs/extensions/toc.yml @@ -1,6 +1,13 @@ - url: /docs/extensions/mv3 - url: /docs/extensions/whatsnew -- url: /docs/extensions/gethelp +- url: +- title: i18n.docs.extensions.support + sections: + - url: /docs/extensions/support-feedback/ + - url: /docs/extensions/support-feedback/getHelp + - url: /docs/extensions/support-feedback/file-a-bug + - url: /docs/extensions/support-feedback/submit-a-feature-request + - url: /docs/extensions/support-feedback/find-a-bug - title: i18n.docs.extensions.get-started sections: - url: /docs/extensions/mv3/getstarted/ diff --git a/site/_data/i18n/docs/extensions.yml b/site/_data/i18n/docs/extensions.yml index a52f12183..547ad1e21 100644 --- a/site/_data/i18n/docs/extensions.yml +++ b/site/_data/i18n/docs/extensions.yml @@ -36,4 +36,6 @@ mv2: apps: en: 'Develop Chrome Apps' service_workers: - en: 'Service workers' \ No newline at end of file + en: 'Service workers' +support: + en: 'Support and feedback' \ No newline at end of file diff --git a/site/en/docs/extensions/support-feedback/file-a-bug/index.md b/site/en/docs/extensions/support-feedback/file-a-bug/index.md new file mode 100644 index 000000000..861f59d21 --- /dev/null +++ b/site/en/docs/extensions/support-feedback/file-a-bug/index.md @@ -0,0 +1,27 @@ +--- +layout: 'layouts/doc-post.njk' +title: File a bug +description: 'TBD' +date: 2023-10-11 +tags: + - extensions +--- + +## File a bug + +While developing an extension, you may find behavior that does not match the extension's documentation or is otherwise unexpected. This may be the result of a Chrome bug. Regardless, please let us know by filing an appropriate issue report. Please provide enough information to reproduce the issue by following these steps: + +1. Before filing a bug, [search the Chromium issue tracker](/docs/extensions/support-feedback/find-a-bug) to verify that your issue hasn't already been reported. +1. Build a *minimal* test extension to demonstrate the issue to us. It should have as little code as possible—generally 100 lines or fewer— to demonstrate the bug. If you can't reproduce the bug in this space, it may indicate that the bug is in your own code. Consider searching for a solution or posting a question in the [Extensions Google Group](https://groups.google.com/a/chromium.org/group/chromium-extensions/topics). +1. File an issue in [the issue tracker](https://crbug.com). Be as explicit as possible when filling out the bug. The easier it is to reproduce the issue, the greater the chance it will be fixed promptly. + - Choose a descriptive title. + - Specify the Chrome version and platform where you see the behavior. + - Explain the steps needed to reproduce the bug. + - Describe the expected and actual behavior. + - Add a link to your test extension. + - Add screenshots, if appropriate. + - If your bug relates to service worker lifetime behavior, include the section of the `chrome://extensions-internals` page relating to your extension. + - If your bug relates to a crash, upload it at `chrome://crashes` and share the crash ID. + +1. Wait for the bug to be updated. Most extension bugs are triaged within a week, although it can sometimes take longer. *Please do not reply to the bug requesting an update*. If your bug has not been modified after two weeks, please post a message to the [Google group](https://groups.google.com/a/chromium.org/group/chromium-extensions/topics) with a link to your bug. +1. If you originally reported your bug in the discussion group and were directed here, post a link to the issue you created or found in the discussion group thread. This makes it easier for others who encounter the same issue. \ No newline at end of file diff --git a/site/en/docs/extensions/support-feedback/find-a-bug/index.md b/site/en/docs/extensions/support-feedback/find-a-bug/index.md new file mode 100644 index 000000000..f025a96c5 --- /dev/null +++ b/site/en/docs/extensions/support-feedback/find-a-bug/index.md @@ -0,0 +1,18 @@ +--- +layout: 'layouts/doc-post.njk' +title: Find and follow a bug +description: 'TBD' +date: 2023-10-11 +tags: + - extensions +--- + +## Find and follow a bug + +Before filing a bug or submitting a feature request for extensions, you should check whether either has already been reported by checking open Chromium issues. These issues are kept in [the Chromium issue tracker](https://crbug.com). This database lets you search for and follow any issue that's been reported for Chromium. + +1. Open the [the issue tracker](https://crbug.com) and use the search box at the top to verify whether the issue has already been reported. Most extension issues are filed under `component=Platform>Extensions`. For example, a search for `component=Platform>Extensions Type=Bug chrome.scripting.executeScript` gives you [this list of results](https://bugs.chromium.org/p/chromium/issues/list?can=2&q=component%3DPlatform>Extensions+Type%3DBug+chrome.scripting.executeScript). +1. If you find a ticket that matches your bug or feature request, click the star icon to express your interest and to be notified when the bug is updated. +1. If you're not signed in, you will be prompted to do so. If you do not have an account in the issue tracker you may create one by clicking **Create account** on the sign-in prompt and following the on-screen instructions. + +Please do not respond to any bugs or feature requests by saying "me too", and prefer using the [Google group](https://groups.google.com/a/chromium.org/group/chromium-extensions/topics) for updates on when a bug will be fixed. However, if you have valuable information, such as a better test case or a suggested fix, please add a comment. diff --git a/site/en/docs/extensions/gethelp/index.md b/site/en/docs/extensions/support-feedback/getHelp/index.md similarity index 100% rename from site/en/docs/extensions/gethelp/index.md rename to site/en/docs/extensions/support-feedback/getHelp/index.md diff --git a/site/en/docs/extensions/support-feedback/index.md b/site/en/docs/extensions/support-feedback/index.md new file mode 100644 index 000000000..28e1cefda --- /dev/null +++ b/site/en/docs/extensions/support-feedback/index.md @@ -0,0 +1,15 @@ +--- +layout: 'layouts/doc-post.njk' +title: Support and feedback +description: 'TBD' +date: 2023-10-11 +tags: + - extensions +--- + +Communication helps both you and us to build better products. The Chrome extensions team is dedicated to helping your work, and the feedback you give us allows us to improve. Use the links below to find help, or let us know if something is broken. + +* [Get help with Chrome extensions](/docs/extensions/support-feedback/getHelp) +* [File a bug](/docs/extensions/support-feedback/file-a-bug) +* [Submit a feature request](/docs/extensions/support-feedback/submit-a-feature-request) +* [Find and follow a bug](/docs/extensions/support-feedback/find-a-bug) \ No newline at end of file diff --git a/site/en/docs/extensions/support-feedback/submit-a-feature-request/index.md b/site/en/docs/extensions/support-feedback/submit-a-feature-request/index.md new file mode 100644 index 000000000..c6489f4d4 --- /dev/null +++ b/site/en/docs/extensions/support-feedback/submit-a-feature-request/index.md @@ -0,0 +1,23 @@ +--- +layout: 'layouts/doc-post.njk' +title: Submit a feature request +description: 'TBD' +date: 2023-10-11 +tags: + - extensions +--- + +## Submit a feature request + +If you identify a feature that you believe could improve the extension's platform, file a request as described below. + +1. Before submitting a feature request, [search the Chromium issue tracker](/docs/extensions/support-feedback/find-a-bug) to verify that your feature has not already been proposed. +1. File an issue in [the issue tracker](https://crbug.com). Be as explicit as possible when filling out a feature request. The easier it is to understand the use case, the greater the chance it will be taken into consideration. + - Choose a descriptive title. + - Explain exactly what feature you would like. + - Explain how you plan to use it. + + The better we understand your use case and your needs, the easier it will be to meet them. + +1. Wait for the bug to be updated. Most requests are triaged within a week, although it can sometimes take longer. *Please do not reply to the ticket requesting an update*. If your ticket has not been modified after two weeks, please post a message to the [Google group](https://groups.google.com/a/chromium.org/group/chromium-extensions/topics) with a link to your request. +1. If you originally posted your request in the discussion group and were directed here, post a link to the issue you created or found in the discussion group thread. This makes it easier for others with the same request to find the correct ticket. \ No newline at end of file From f8e06f9b5120ad509f9d0a65b8744c097b75aa2e Mon Sep 17 00:00:00 2001 From: Joe Medley <jmedley@google.com> Date: Wed, 11 Oct 2023 18:39:13 -0700 Subject: [PATCH 891/982] Add missing descriptions to support and feedback. (#7517) --- .../support-feedback/file-a-bug/index.md | 18 +++++++++--------- .../support-feedback/find-a-bug/index.md | 2 +- .../docs/extensions/support-feedback/index.md | 2 +- .../submit-a-feature-request/index.md | 4 ++-- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/site/en/docs/extensions/support-feedback/file-a-bug/index.md b/site/en/docs/extensions/support-feedback/file-a-bug/index.md index 861f59d21..9e4a61bbc 100644 --- a/site/en/docs/extensions/support-feedback/file-a-bug/index.md +++ b/site/en/docs/extensions/support-feedback/file-a-bug/index.md @@ -1,7 +1,7 @@ --- layout: 'layouts/doc-post.njk' title: File a bug -description: 'TBD' +description: 'How to report extension bugs or problems with documentation.' date: 2023-10-11 tags: - extensions @@ -14,14 +14,14 @@ While developing an extension, you may find behavior that does not match the ext 1. Before filing a bug, [search the Chromium issue tracker](/docs/extensions/support-feedback/find-a-bug) to verify that your issue hasn't already been reported. 1. Build a *minimal* test extension to demonstrate the issue to us. It should have as little code as possible—generally 100 lines or fewer— to demonstrate the bug. If you can't reproduce the bug in this space, it may indicate that the bug is in your own code. Consider searching for a solution or posting a question in the [Extensions Google Group](https://groups.google.com/a/chromium.org/group/chromium-extensions/topics). 1. File an issue in [the issue tracker](https://crbug.com). Be as explicit as possible when filling out the bug. The easier it is to reproduce the issue, the greater the chance it will be fixed promptly. - - Choose a descriptive title. - - Specify the Chrome version and platform where you see the behavior. - - Explain the steps needed to reproduce the bug. - - Describe the expected and actual behavior. - - Add a link to your test extension. - - Add screenshots, if appropriate. - - If your bug relates to service worker lifetime behavior, include the section of the `chrome://extensions-internals` page relating to your extension. - - If your bug relates to a crash, upload it at `chrome://crashes` and share the crash ID. + - Choose a descriptive title. + - Specify the Chrome version and platform where you see the behavior. + - Explain the steps needed to reproduce the bug. + - Describe the expected and actual behavior. + - Add a link to your test extension. + - Add screenshots, if appropriate. + - If your bug relates to service worker lifetime behavior, include the section of the `chrome://extensions-internals` page relating to your extension. + - If your bug relates to a crash, upload it at `chrome://crashes` and share the crash ID. 1. Wait for the bug to be updated. Most extension bugs are triaged within a week, although it can sometimes take longer. *Please do not reply to the bug requesting an update*. If your bug has not been modified after two weeks, please post a message to the [Google group](https://groups.google.com/a/chromium.org/group/chromium-extensions/topics) with a link to your bug. 1. If you originally reported your bug in the discussion group and were directed here, post a link to the issue you created or found in the discussion group thread. This makes it easier for others who encounter the same issue. \ No newline at end of file diff --git a/site/en/docs/extensions/support-feedback/find-a-bug/index.md b/site/en/docs/extensions/support-feedback/find-a-bug/index.md index f025a96c5..08703a837 100644 --- a/site/en/docs/extensions/support-feedback/find-a-bug/index.md +++ b/site/en/docs/extensions/support-feedback/find-a-bug/index.md @@ -1,7 +1,7 @@ --- layout: 'layouts/doc-post.njk' title: Find and follow a bug -description: 'TBD' +description: 'Check whether a bug or feature request has already been reported.' date: 2023-10-11 tags: - extensions diff --git a/site/en/docs/extensions/support-feedback/index.md b/site/en/docs/extensions/support-feedback/index.md index 28e1cefda..067b55d39 100644 --- a/site/en/docs/extensions/support-feedback/index.md +++ b/site/en/docs/extensions/support-feedback/index.md @@ -1,7 +1,7 @@ --- layout: 'layouts/doc-post.njk' title: Support and feedback -description: 'TBD' +description: 'Give us feedback to help us improve the platform and fix its bugs.' date: 2023-10-11 tags: - extensions diff --git a/site/en/docs/extensions/support-feedback/submit-a-feature-request/index.md b/site/en/docs/extensions/support-feedback/submit-a-feature-request/index.md index c6489f4d4..3b9cdef67 100644 --- a/site/en/docs/extensions/support-feedback/submit-a-feature-request/index.md +++ b/site/en/docs/extensions/support-feedback/submit-a-feature-request/index.md @@ -1,7 +1,7 @@ --- layout: 'layouts/doc-post.njk' title: Submit a feature request -description: 'TBD' +description: 'Submit a request for a feature that you believe could improve the extension platform.' date: 2023-10-11 tags: - extensions @@ -9,7 +9,7 @@ tags: ## Submit a feature request -If you identify a feature that you believe could improve the extension's platform, file a request as described below. +If you identify a feature that you believe could improve the extension platform, file a request as described below. 1. Before submitting a feature request, [search the Chromium issue tracker](/docs/extensions/support-feedback/find-a-bug) to verify that your feature has not already been proposed. 1. File an issue in [the issue tracker](https://crbug.com). Be as explicit as possible when filling out a feature request. The easier it is to understand the use case, the greater the chance it will be taken into consideration. From 4c3875b0dba36dc167e314aae4529c41252fbbf3 Mon Sep 17 00:00:00 2001 From: Rachel Andrew <rachelandrew@google.com> Date: Thu, 12 Oct 2023 10:54:04 +0100 Subject: [PATCH 892/982] Homepage updates (#7522) * homepage updates * image * chore: sync directory structure to devsite * fix: add webp version of listening version --------- Co-authored-by: Matthias Rohmer <mrohmer@google.com> --- site/_includes/layouts/devsite-home.njk | 814 +++++++++++++----- .../dcc => images}/bringing-safety-thumb.jpg | Bin .../dcc => images}/case-study-thumb.jpg | Bin .../dcc => images}/chrome-117-beta.jpg | Bin site/_static/images/chrome-119-beta.png | Bin 0 -> 56020 bytes .../dcc => images}/chrome-at-io-thumb.jpg | Bin .../dcc => images}/chrome-devtools-thumb.svg | 0 .../chrome-extensions-thumb.svg | 0 .../dcc => images}/chrome-for-devs-thumb.png | Bin .../{static/dcc => images}/chrome-twitter.svg | 0 .../dcc => images}/chrome-web-store-thumb.svg | 0 .../{static/dcc => images}/chrome-youtube.svg | 0 .../dcc => images}/get-inspired-icon.svg | 0 site/_static/images/hero.webp | Bin 0 -> 98856 bytes .../dcc => images}/new-in-chrome-116.jpg | Bin site/_static/images/new-in-chrome-118.png | Bin 0 -> 114581 bytes .../new-in-devtools-118-thumb.webp | Bin .../{static/dcc => images}/open-icon.webp | Bin .../{static/dcc => images}/powerful-icon.webp | Bin .../dcc => images}/productivity-icon.webp | Bin .../dcc => images}/solutions-icon.webp | Bin .../dcc => images}/web-on-android-thumb.svg | 0 site/_static/static/dcc/hero.webp | Bin 106046 -> 0 bytes site/en/blog/new-in-chrome-118/index.md | 2 +- site/es/blog/new-in-chrome-118/index.md | 2 +- 25 files changed, 593 insertions(+), 225 deletions(-) rename site/_static/{static/dcc => images}/bringing-safety-thumb.jpg (100%) rename site/_static/{static/dcc => images}/case-study-thumb.jpg (100%) rename site/_static/{static/dcc => images}/chrome-117-beta.jpg (100%) create mode 100644 site/_static/images/chrome-119-beta.png rename site/_static/{static/dcc => images}/chrome-at-io-thumb.jpg (100%) rename site/_static/{static/dcc => images}/chrome-devtools-thumb.svg (100%) rename site/_static/{static/dcc => images}/chrome-extensions-thumb.svg (100%) rename site/_static/{static/dcc => images}/chrome-for-devs-thumb.png (100%) rename site/_static/{static/dcc => images}/chrome-twitter.svg (100%) rename site/_static/{static/dcc => images}/chrome-web-store-thumb.svg (100%) rename site/_static/{static/dcc => images}/chrome-youtube.svg (100%) rename site/_static/{static/dcc => images}/get-inspired-icon.svg (100%) create mode 100644 site/_static/images/hero.webp rename site/_static/{static/dcc => images}/new-in-chrome-116.jpg (100%) create mode 100644 site/_static/images/new-in-chrome-118.png rename site/_static/{static/dcc => images}/new-in-devtools-118-thumb.webp (100%) rename site/_static/{static/dcc => images}/open-icon.webp (100%) rename site/_static/{static/dcc => images}/powerful-icon.webp (100%) rename site/_static/{static/dcc => images}/productivity-icon.webp (100%) rename site/_static/{static/dcc => images}/solutions-icon.webp (100%) rename site/_static/{static/dcc => images}/web-on-android-thumb.svg (100%) delete mode 100644 site/_static/static/dcc/hero.webp diff --git a/site/_includes/layouts/devsite-home.njk b/site/_includes/layouts/devsite-home.njk index 797cd7caf..53c82e955 100644 --- a/site/_includes/layouts/devsite-home.njk +++ b/site/_includes/layouts/devsite-home.njk @@ -1,39 +1,51 @@ -{% extends "layouts/devsite.njk" %} +{% extends "layouts/devsite.njk" %} {% block devsite_main %} <main role="main" class="devsite-content"> - {% include 'partials/banner.njk' %} <devsite-content> <article class="devsite-article"> - <div class="devsite-article-body clearfix - "> - <section class="devsite-landing-row devsite-landing-row-1-up devsite-landing-row-100 dcc-hero" header-position="top"> + <div class="devsite-article-body clearfix"> + <div class="devsite-page-title-meta"></div> + + <section + class="devsite-landing-row devsite-landing-row-1-up devsite-landing-row-100 dcc-hero" + header-position="top" + > <div class="devsite-landing-row-inner"> <div class="devsite-landing-row-group"> - <div class="devsite-landing-row-item" description-position="bottom"> - <div class="devsite-landing-row-item-media - "> + <div + class="devsite-landing-row-item" + description-position="bottom" + > + <div class="devsite-landing-row-item-media"> <figure class="devsite-landing-row-item-image"> <img - alt="A cartoon-style rendering of a diverse set of people building a website on a whiteboard." - src="/static/dcc/hero.webp" + alt="A cartoon-style rendering of a diverse set of people building a website on a whiteboard" + src="/images/hero.webp" loading="lazy" - width="1160" - height="608" - fetchpriority="high"> + /> </figure> </div> + <div class="devsite-landing-row-item-description"> <div class="devsite-landing-row-item-body"> - <h3 id="a-powerful-web-spanmade-easierspan" data-text="A Powerful Web. Made Easier." class="hide-from-toc no-link"> - A Powerful Web. - <span>Made Easier.</span> + <h3 + id="a-powerful-web-spanmade-easierspan" + data-text="A Powerful Web. Made Easier." + class="hide-from-toc no-link" + > + A Powerful Web. <span>Made Easier.</span> </h3> + <div class="devsite-landing-row-item-description-content"> - Helping you build, grow and innovate on the web. + Simplifying the web to help you build, grow and innovate. </div> + <div class="devsite-landing-row-item-buttons"> - <a href="/#features-tools-and-programs-to-make-developers-successful-on-the-web" class="button - " aria-label="Get started with documentation for web features, tools and programs.">Get Started</a> + <a + href="/#features-tools-and-programs-to-make-developers-successful-on-the-web" + class="button dcc-filled-button" + >Get Started</a + > </div> </div> </div> @@ -41,74 +53,107 @@ </div> </div> </section> + <section - class="devsite-landing-row devsite-landing-row-2-up devsite-landing-row-cards devsite-landing-row-no-image-background - dcc-featured" - header-position="top"> + class="devsite-landing-row devsite-landing-row-2-up devsite-landing-row-cards devsite-landing-row-no-image-background dcc-featured" + header-position="top" + > <div class="devsite-landing-row-inner"> <div class="devsite-landing-row-group"> - - <div class="devsite-landing-row-item dcc-blog-card" description-position="bottom"> - <div class="devsite-landing-row-item-media - "> + <div + class="devsite-landing-row-item dcc-blog-card" + description-position="left" + > + <div class="devsite-landing-row-item-media"> <figure class="devsite-landing-row-item-image"> - <a href="/blog/we-are-chrome-for-developers/"> - <img alt="" src="/static/dcc/chrome-for-devs-thumb.png" loading="lazy" width="376" height="240"> + <a href="/blog/chrome-at-io23"> + <img + alt="" + src="/images/chrome-at-io-thumb.jpg" + loading="lazy" + /> </a> </figure> </div> + <div class="devsite-landing-row-item-description"> <div class="devsite-landing-row-item-body"> <div class="devsite-landing-row-item-labels"> - <span class=" - - ">FEATURED</span> + <span + class=" + + " + >FEATURED</span + > </div> - <h3 id="we-are-chrome-for-developers" data-text="We are Chrome for Developers" class="hide-from-toc no-link"> - <a href="/blog/we-are-chrome-for-developers/"> - We are Chrome for Developers + <h3 + id="10-updates-at-google-io" + data-text="10 updates at Google I/O" + class="hide-from-toc no-link" + > + <a href="/blog/chrome-at-io23"> + 10 updates at Google I/O </a> </h3> + <div class="devsite-landing-row-item-description-content"> - Celebrating Chrome's 15th anniversary and our role as a trusted, helpful partner to developers. + We're wrapping things up on this year's Google I/O, with + more than 100 new APIs, components, and tools discussed on + the keynote stage, and in Chrome's on-demand sessions. </div> + <div class="devsite-landing-row-item-buttons"> - <a href="/blog/we-are-chrome-for-developers/" class="button - " aria-label="Read the Chrome for Developers blog post.">Read more</a> + <a href="/blog/chrome-at-io23" class="button" + >Explore Now</a + > </div> </div> </div> </div> - <div class="devsite-landing-row-item dcc-blog-card" description-position="bottom"> - <div class="devsite-landing-row-item-media - "> + + <div + class="devsite-landing-row-item dcc-blog-card" + description-position="bottom" + > + <div class="devsite-landing-row-item-media"> <figure class="devsite-landing-row-item-image"> - <a href="/blog/new-in-devtools-118/"> - <img alt="" src="/static/dcc/new-in-devtools-118-thumb.webp" loading="lazy" width="565" height="178"> + <a href="/blog/extension-safety-hub"> + <img + alt="" + src="/images/bringing-safety-thumb.jpg" + loading="lazy" + /> </a> </figure> </div> + <div class="devsite-landing-row-item-description"> <div class="devsite-landing-row-item-body"> <div class="devsite-landing-row-item-labels"> - <span class="dcc-label-top - ">LATEST NEWS</span> + <span class="dcc-label-top">LATEST NEWS</span> </div> + <h3 id="bringing-safety-check-to-the-chromeextensions-page" - data-text="What's New in DevTools (Chrome 118)" - class="hide-from-toc no-link"> - <a href="/blog/new-in-devtools-118/"> - What's New in DevTools (Chrome 118) + data-text="Bringing Safety check to the chrome://extensions page" + class="hide-from-toc no-link" + > + <a href="/blog/extension-safety-hub"> + Bringing Safety check to the chrome://extensions page </a> </h3> + <div class="devsite-landing-row-item-description-content"> - Check out the latest set of features and updates landing in the next release. + Starting in Chrome 117, Chrome will proactively highlight + to users when an extension they have installed is no + longer in the Chrome Web Store. </div> + <div class="devsite-landing-row-item-buttons"> - <a href="/blog/new-in-devtools-118/" class="button - " aria-label="Read more about new features in Chrome 118 DevTools.">Explore Now</a> + <a href="/blog/extension-safety-hub" class="button" + >Explore Now</a + > </div> </div> </div> @@ -116,79 +161,123 @@ </div> </div> </section> + <section - class="devsite-landing-row devsite-landing-row-3-up devsite-landing-row-cards devsite-landing-row-no-image-background - dcc-case-studies" - header-position="top"> + class="devsite-landing-row devsite-landing-row-3-up devsite-landing-row-cards devsite-landing-row-no-image-background dcc-case-studies" + header-position="top" + > <div class="devsite-landing-row-inner"> <div class="devsite-landing-row-group"> - <div class="devsite-landing-row-item" description-position="bottom"> - <div class="devsite-landing-row-item-media - "> + <div + class="devsite-landing-row-item" + description-position="bottom" + > + <div class="devsite-landing-row-item-media"> <figure class="devsite-landing-row-item-image"> - <img alt="" src="/static/dcc/get-inspired-icon.svg" loading="lazy" width="40" height="40"> + <img + alt="" + src="/images/get-inspired-icon.svg" + loading="lazy" + width="40" + height="40" + /> </figure> </div> + <div class="devsite-landing-row-item-description"> <div class="devsite-landing-row-item-body"> - <h3 id="get-inspired" data-text="Get Inspired" class="hide-from-toc no-link"> + <h3 + id="get-inspired" + data-text="Get Inspired" + class="hide-from-toc no-link" + > Get Inspired </h3> + <div class="devsite-landing-row-item-description-content"> - Extend your product’s reach through the browser, increase engagement by improving quality and make the most of the web’s - capabilities. See how businesses are succeeding on the web. + Extend your product’s reach through the browser, increase + engagement by improving quality and make the most of the + web’s capabilities. See how businesses are succeeding on + the web. </div> + <div class="devsite-landing-row-item-buttons"> - <a href="/tags/case-study" class="button - ">All stories</a> + <a href="/tags/case-study" class="button">All stories</a> </div> </div> </div> </div> - <div class="devsite-landing-row-item dcc-blog-card" description-position="top"> - <div class="devsite-landing-row-item-media - "> + + <div + class="devsite-landing-row-item dcc-blog-card" + description-position="top" + > + <div class="devsite-landing-row-item-media"> <figure class="devsite-landing-row-item-image"> - <a href="/blog/how-photoshop-solved-working-with-files-larger-than-can-fit-into-memory"> - <img alt="" src="/static/dcc/case-study-thumb.jpg" loading="lazy" width="395" height="222"> + <a + href="/blog/how-photoshop-solved-working-with-files-larger-than-can-fit-into-memory" + > + <img + alt="" + src="/images/case-study-thumb.jpg" + loading="lazy" + width="395" + height="222" + /> </a> </figure> </div> + <div class="devsite-landing-row-item-description"> <div class="devsite-landing-row-item-body"> <div class="devsite-landing-row-item-labels"> - <span class=" - - ">CASE STUDY</span> - <span class="dcc-label-top - "></span> + <span + class=" + + " + >CASE STUDY</span + > + + <span class="dcc-label-top"></span> </div> + <div class="devsite-landing-row-item-description-content"> case study </div> </div> </div> </div> - <div class="devsite-landing-row-item devsite-landing-row-item-no-media" description-position="bottom"> + + <div + class="devsite-landing-row-item devsite-landing-row-item-no-media" + description-position="bottom" + > <div class="devsite-landing-row-item-description"> <div class="devsite-landing-row-item-body"> <h3 id="how-photoshop-solved-working-with-files-larger-than-can-fit-into-memory" data-text="How Photoshop solved working with files larger than can fit into memory" - class="hide-from-toc no-link"> - <a href="/blog/how-photoshop-solved-working-with-files-larger-than-can-fit-into-memory"> - How Photoshop solved working with files larger than can fit into memory + class="hide-from-toc no-link" + > + <a + href="/blog/how-photoshop-solved-working-with-files-larger-than-can-fit-into-memory" + > + How Photoshop solved working with files larger than can + fit into memory </a> </h3> + <div class="devsite-landing-row-item-description-content"> - Learn how Adobe managed to let users edit even the biggest files on the web version of its iconic Photoshop app. + Learn how Adobe managed to let users edit even the biggest + files on the web version of its iconic Photoshop app. </div> + <div class="devsite-landing-row-item-buttons"> <a href="/blog/how-photoshop-solved-working-with-files-larger-than-can-fit-into-memory" - class="button - button-white - ">Read more</a> + class="button button-white" + >Read more</a + > </div> </div> </div> @@ -196,113 +285,223 @@ </div> </div> </section> + <section - class="devsite-landing-row devsite-landing-row-4-up devsite-landing-row-cards devsite-landing-row-no-image-background - dcc-pillars" + class="devsite-landing-row devsite-landing-row-4-up devsite-landing-row-cards devsite-landing-row-no-image-background dcc-pillars" background="pale-blue" - header-position="top"> + header-position="top" + > <div class="devsite-landing-row-inner"> <header class="devsite-landing-row-header"> <div class="devsite-landing-row-header-text"> <h2 id="features-tools-and-programs-to-make-developers-successful-on-the-web" - data-text="Features, tools and programs to make developers successful on the web."> - Features, tools and programs to make developers successful on the web. + data-text="Features, tools and programs to make developers successful on the web." + > + Features, tools and programs to make developers successful on + the web. </h2> </div> </header> + <div class="devsite-landing-row-group"> - <div class="devsite-landing-row-item dcc-services-card" description-position="bottom"> - <div class="devsite-landing-row-item-media - "> + <div + class="devsite-landing-row-item dcc-services-card" + description-position="bottom" + > + <div class="devsite-landing-row-item-media"> <figure class="devsite-landing-row-item-image"> - <img alt="" src="/static/dcc/powerful-icon.webp" loading="lazy" width="176" height="176"> + <img + alt="" + src="/images/powerful-icon.webp" + loading="lazy" + width="176" + height="176" + /> </figure> </div> + <div class="devsite-landing-row-item-description"> <div class="devsite-landing-row-item-body"> - <h3 id="powerful-platform-capabilities" data-text="Powerful platform capabilities" class="hide-from-toc no-link"> + <h3 + id="powerful-platform-capabilities" + data-text="Powerful platform capabilities" + class="hide-from-toc no-link" + > Powerful platform capabilities </h3> + <div class="devsite-landing-row-item-buttons"> - <a href="/capabilities" class="button dcc-web-app-features-link dcc-icon-button - ">Web App Features</a> - <a href="/docs/android" class="button dcc-web-on-android-link dcc-icon-button - ">Web on Android</a> - <a href="/docs/extensions" class="button dcc-chrome-extensions-link dcc-icon-button - ">Chrome Extensions</a> + <a + href="/capabilities" + class="button dcc-icon-link dcc-web-app-features-link dcc-icon-button" + >Web App Features</a + > + + <a + href="/docs/android" + class="button dcc-web-on-android-link dcc-icon-button" + >Web on Android</a + > + + <a + href="/docs/extensions" + class="button dcc-chrome-extensions-link dcc-icon-button" + >Chrome Extensions</a + > </div> </div> </div> </div> - <div class="devsite-landing-row-item dcc-services-card" description-position="bottom"> - <div class="devsite-landing-row-item-media - "> + + <div + class="devsite-landing-row-item dcc-services-card" + description-position="bottom" + > + <div class="devsite-landing-row-item-media"> <figure class="devsite-landing-row-item-image"> - <img alt="" src="/static/dcc/solutions-icon.webp" loading="lazy" width="176" height="176"> + <img + alt="" + src="/images/solutions-icon.webp" + loading="lazy" + width="176" + height="176" + /> </figure> </div> + <div class="devsite-landing-row-item-description"> <div class="devsite-landing-row-item-body"> - <h3 id="solutions-for-quality-experiences" data-text="Solutions for quality experiences" class="hide-from-toc no-link"> + <h3 + id="solutions-for-quality-experiences" + data-text="Solutions for quality experiences" + class="hide-from-toc no-link" + > Solutions for quality experiences </h3> + <div class="devsite-landing-row-item-buttons"> - <a href="https://web.dev/vitals/" class="button dcc-cwv-link dcc-icon-button - ">Core Web Vitals</a> - <a href="/tags/css" class="button dcc-design-link dcc-icon-button - ">Design and UI</a> - <a href="/tags/identity" class="button dcc-identity-link dcc-icon-button - ">Identity</a> + <a + href="https://web.dev/vitals/" + class="button dcc-cwv-link dcc-icon-button" + >Core Web Vitals</a + > + + <a + href="/tags/css" + class="button dcc-design-link dcc-icon-button" + >Design and UI</a + > + + <a + href="/tags/identity" + class="button dcc-identity-link dcc-icon-button" + >Identity</a + > </div> </div> </div> </div> - <div class="devsite-landing-row-item dcc-services-card" description-position="bottom"> - <div class="devsite-landing-row-item-media - "> + + <div + class="devsite-landing-row-item dcc-services-card" + description-position="bottom" + > + <div class="devsite-landing-row-item-media"> <figure class="devsite-landing-row-item-image"> - <img alt="" src="/static/dcc/productivity-icon.webp" loading="lazy" width="176" height="176"> + <img + alt="" + src="/images/productivity-icon.webp" + loading="lazy" + width="176" + height="176" + /> </figure> </div> + <div class="devsite-landing-row-item-description"> <div class="devsite-landing-row-item-body"> - <h3 id="productivity-made-easier" data-text="Productivity made easier" class="hide-from-toc no-link"> + <h3 + id="productivity-made-easier" + data-text="Productivity made easier" + class="hide-from-toc no-link" + > Productivity made easier </h3> + <div class="devsite-landing-row-item-buttons"> - <a href="/docs/devtools" class="button dcc-dev-tools-link dcc-icon-button - ">Chrome DevTools</a> - <a href="https://developers.google.com/speed/" class="button dcc-performance-link dcc-icon-button - ">Performance - Tools</a> - <a href="/docs/puppeteer" class="button dcc-puppeteer-link dcc-icon-button - ">Puppeteer</a> - <a href="/blog/chrome-for-testing" class="button dcc-chrome-testing-link dcc-icon-button - ">Chrome for Testing</a> + <a + href="/docs/devtools" + class="button dcc-dev-tools-link dcc-icon-button" + >Chrome DevTools</a + > + + <a + href="https://developers.google.com/speed/" + class="button dcc-performance-link dcc-icon-button" + >Performance Tools</a + > + + <a + href="/docs/puppeteer" + class="button dcc-puppeteer-link dcc-icon-button" + >Puppeteer</a + > + + <a + href="/blog/chrome-for-testing" + class="button dcc-chrome-testing-link dcc-icon-button" + >Chrome for Testing</a + > </div> </div> </div> </div> - <div class="devsite-landing-row-item dcc-services-card" description-position="bottom"> - <div class="devsite-landing-row-item-media - "> + + <div + class="devsite-landing-row-item dcc-services-card" + description-position="bottom" + > + <div class="devsite-landing-row-item-media"> <figure class="devsite-landing-row-item-image"> - <img alt="" src="/static/dcc/open-icon.webp" loading="lazy" width="176" height="176"> + <img + alt="" + src="/images/open-icon.webp" + loading="lazy" + width="176" + height="176" + /> </figure> </div> + <div class="devsite-landing-row-item-description"> <div class="devsite-landing-row-item-body"> - <h3 id="open-by-design" data-text="Open by design" class="hide-from-toc no-link"> + <h3 + id="open-by-design" + data-text="Open by design" + class="hide-from-toc no-link" + > Open by design </h3> + <div class="devsite-landing-row-item-buttons"> - <a href="https://web.dev/baseline/" class="button dcc-baseline-link dcc-icon-button - ">Baseline</a> - <a href="/aurora" class="button dcc-aurora-link dcc-icon-button - ">Project Aurora</a> - <a href="https://web.dev/" class="button dcc-webdev-link dcc-icon-button - ">web.dev</a> + <a + href="https://web.dev/baseline/" + class="button dcc-baseline-link dcc-icon-button" + >Baseline</a + > + + <a + href="/aurora" + class="button dcc-aurora-link dcc-icon-button" + >Project Aurora</a + > + + <a + href="https://web.dev/" + class="button dcc-webdev-link dcc-icon-button" + >web.dev</a + > </div> </div> </div> @@ -310,74 +509,119 @@ </div> </div> </section> - <section class="devsite-landing-row devsite-landing-row-2-up dcc-chrome-releases" header-position="left"> + + <section + class="devsite-landing-row devsite-landing-row-2-up dcc-chrome-releases" + header-position="left" + > <div class="devsite-landing-row-inner"> <header class="devsite-landing-row-header" icon-position="top"> - <div class="devsite-landing-row-header-icon-container" size="medium"> - <div class="devsite-landing-row-header-icon material-icons" aria-hidden="true"> + <div + class="devsite-landing-row-header-icon-container" + size="medium" + > + <div + class="devsite-landing-row-header-icon material-icons" + aria-hidden="true" + > verified </div> </div> + <div class="devsite-landing-row-header-text"> <h2 id="always-updating" data-text="Always updating"> Always updating </h2> + <div class="devsite-landing-row-description"> - See what's included in Chrome's latest stable and beta releases + See what's included in Chrome's latest stable and beta + releases </div> </div> </header> + <div class="devsite-landing-row-group"> - <div class="devsite-landing-row-item dcc-blog-card" description-position="bottom"> - <div class="devsite-landing-row-item-media - "> + <div + class="devsite-landing-row-item dcc-blog-card" + description-position="bottom" + > + <div class="devsite-landing-row-item-media"> <figure class="devsite-landing-row-item-image"> - <a href="/blog/chrome-117-beta"> - <img alt="" src="/static/dcc/chrome-117-beta.jpg" loading="lazy" width="371" height="200"> + <a href="/blog/chrome-119-beta"> + <img + alt="" + src="/images/chrome-119-beta.png" + loading="lazy" + width="371" + height="200" + /> </a> </figure> </div> + <div class="devsite-landing-row-item-description"> <div class="devsite-landing-row-item-body"> - <h3 id="chrome-117-beta" data-text="Chrome 117 beta" class="hide-from-toc no-link"> - <a href="/blog/chrome-117-beta"> - Chrome 117 beta - </a> + <h3 + id="chrome-119-beta" + data-text="Chrome 119 beta" + class="hide-from-toc no-link" + > + <a href="/blog/chrome-119-beta"> Chrome 119 beta </a> </h3> + <div class="devsite-landing-row-item-description-content"> - Chrome 117 beta brings you subgrid for CSS grid layout, entry and exit animation support in CSS, array grouping, - iterator helpers, and more. You can also register for several new origin trials, including tabbed web apps. + Chrome 119 beta brings you CSS relative color syntax, new + pseudo-classes, keyboard focusable scroll containers, + Intersection Observer scroll margin, and much more. </div> + <div class="devsite-landing-row-item-buttons"> - <a href="/tags/beta" class="button - ">All beta blog posts</a> + <a href="/tags/beta" class="button" + >All beta blog posts</a + > </div> </div> </div> </div> - <div class="devsite-landing-row-item dcc-blog-card" description-position="bottom"> - <div class="devsite-landing-row-item-media - "> + + <div + class="devsite-landing-row-item dcc-blog-card" + description-position="bottom" + > + <div class="devsite-landing-row-item-media"> <figure class="devsite-landing-row-item-image"> - <a href="/blog/new-in-chrome-116"> - <img alt="" src="/static/dcc/new-in-chrome-116.jpg" loading="lazy" width="371" height="200"> + <a href="/blog/new-in-chrome-118"> + <img + alt="" + src="/images/new-in-chrome-118.png" + loading="lazy" + width="371" + height="200" + /> </a> </figure> </div> + <div class="devsite-landing-row-item-description"> <div class="devsite-landing-row-item-body"> - <h3 id="new-in-chrome-116" data-text="New in Chrome 116" class="hide-from-toc no-link"> - <a href="/blog/new-in-chrome-116"> - New in Chrome 116 - </a> + <h3 + id="new-in-chrome-118" + data-text="New in Chrome 118" + class="hide-from-toc no-link" + > + <a href="/blog/new-in-chrome-118"> New in Chrome 118 </a> </h3> + <div class="devsite-landing-row-item-description-content"> - The latest stable Chrome includes the Document Picture-in-Picture API—open an always-on-top window populated with any - HTML content. You’ll also discover new features that make debugging missing stylesheets much easier in Chrome DevTools. + The latest stable Chrome includes scoped CSS, new media + features script and prefers-reduced-transparency, plus + Sources panel improvements in DevTools. </div> + <div class="devsite-landing-row-item-buttons"> - <a href="/tags/new-in-chrome" class="button - ">All stable blog posts</a> + <a href="/tags/new-in-chrome" class="button" + >All stable blog posts</a + > </div> </div> </div> @@ -385,112 +629,194 @@ </div> </div> </section> - <section class="devsite-landing-row devsite-landing-row-4-up dcc-docs" header-position="left"> + + <section + class="devsite-landing-row devsite-landing-row-4-up dcc-docs" + header-position="left" + > <div class="devsite-landing-row-inner"> <header class="devsite-landing-row-header" icon-position="top"> - <div class="devsite-landing-row-header-icon-container" size="medium"> - <div class="devsite-landing-row-header-icon material-icons" aria-hidden="true"> + <div + class="devsite-landing-row-header-icon-container" + size="medium" + > + <div + class="devsite-landing-row-header-icon material-icons" + aria-hidden="true" + > description </div> </div> + <div class="devsite-landing-row-header-text"> - <h2 id="docs" data-text="Docs"> - Docs - </h2> + <h2 id="docs" data-text="Docs">Docs</h2> + <div class="devsite-landing-row-description"> All the resources you need to start building </div> </div> + <div class="devsite-landing-row-header-buttons"> - <a href="/docs" class="button - ">See all docs</a> + <a href="/docs" class="button">See all docs</a> </div> </header> + <div class="devsite-landing-row-group"> - <div class="devsite-landing-row-item dcc-docs-card" description-position="bottom"> - <div class="devsite-landing-row-item-media - "> + <div + class="devsite-landing-row-item dcc-docs-card" + description-position="bottom" + > + <div class="devsite-landing-row-item-media"> <figure class="devsite-landing-row-item-image"> - <img alt="" src="/static/dcc/chrome-devtools-thumb.svg" loading="lazy" width="128" height="128"> + <img + alt="" + src="/images/chrome-devtools-thumb.svg" + loading="lazy" + width="128" + height="128" + /> </figure> </div> + <div class="devsite-landing-row-item-description"> <div class="devsite-landing-row-item-body"> - <h3 id="chrome-devtools" data-text="Chrome DevTools" class="hide-from-toc no-link"> + <h3 + id="chrome-devtools" + data-text="Chrome DevTools" + class="hide-from-toc no-link" + > Chrome DevTools </h3> + <div class="devsite-landing-row-item-description-content"> - Diagnose problems and edit source files quickly to build better, faster websites, directly in the Chrome browser. + Diagnose problems and edit source files quickly to build + better, faster websites, directly in the Chrome browser. </div> + <div class="devsite-landing-row-item-buttons"> - <a href="/docs/devtools" class="button - ">See all documentation</a> + <a href="/docs/devtools" class="button" + >See all documentation</a + > </div> </div> </div> </div> - <div class="devsite-landing-row-item dcc-docs-card" description-position="bottom"> - <div class="devsite-landing-row-item-media - "> + + <div + class="devsite-landing-row-item dcc-docs-card" + description-position="bottom" + > + <div class="devsite-landing-row-item-media"> <figure class="devsite-landing-row-item-image"> - <img alt="" src="/static/dcc/chrome-extensions-thumb.svg" loading="lazy" width="128" height="128"> + <img + alt="" + src="/images/chrome-extensions-thumb.svg" + loading="lazy" + width="128" + height="128" + /> </figure> </div> + <div class="devsite-landing-row-item-description"> <div class="devsite-landing-row-item-body"> - <h3 id="extensions" data-text="Extensions" class="hide-from-toc no-link"> + <h3 + id="extensions" + data-text="Extensions" + class="hide-from-toc no-link" + > Extensions </h3> + <div class="devsite-landing-row-item-description-content"> - Customize the Chrome browsing experience using on web technologies, such as HTML, CSS, and JavaScript. + Customize the Chrome browsing experience using on web + technologies, such as HTML, CSS, and JavaScript. </div> + <div class="devsite-landing-row-item-buttons"> - <a href="/docs/extensions" class="button - ">See all documentation</a> + <a href="/docs/extensions" class="button" + >See all documentation</a + > </div> </div> </div> </div> - <div class="devsite-landing-row-item dcc-docs-card" description-position="bottom"> - <div class="devsite-landing-row-item-media - "> + + <div + class="devsite-landing-row-item dcc-docs-card" + description-position="bottom" + > + <div class="devsite-landing-row-item-media"> <figure class="devsite-landing-row-item-image"> - <img alt="" src="/static/dcc/chrome-web-store-thumb.svg" loading="lazy" width="128" height="128"> + <img + alt="" + src="/images/chrome-web-store-thumb.svg" + loading="lazy" + width="128" + height="128" + /> </figure> </div> + <div class="devsite-landing-row-item-description"> <div class="devsite-landing-row-item-body"> - <h3 id="chrome-web-store" data-text="Chrome Web Store" class="hide-from-toc no-link"> + <h3 + id="chrome-web-store" + data-text="Chrome Web Store" + class="hide-from-toc no-link" + > Chrome Web Store </h3> + <div class="devsite-landing-row-item-description-content"> - Publish your extensions and themes to Chrome’s online marketplace. + Publish your extensions and themes to Chrome’s online + marketplace. </div> + <div class="devsite-landing-row-item-buttons"> - <a href="/docs/webstore" class="button - ">See all documentation</a> + <a href="/docs/webstore" class="button" + >See all documentation</a + > </div> </div> </div> </div> - <div class="devsite-landing-row-item dcc-docs-card" description-position="bottom"> - <div class="devsite-landing-row-item-media - "> + + <div + class="devsite-landing-row-item dcc-docs-card" + description-position="bottom" + > + <div class="devsite-landing-row-item-media"> <figure class="devsite-landing-row-item-image"> - <img alt="" src="/static/dcc/web-on-android-thumb.svg" loading="lazy" width="128" height="128"> + <img + alt="" + src="/images/web-on-android-thumb.svg" + loading="lazy" + width="128" + height="128" + /> </figure> </div> + <div class="devsite-landing-row-item-description"> <div class="devsite-landing-row-item-body"> - <h3 id="web-platform" data-text="Web Platform" class="hide-from-toc no-link"> + <h3 + id="web-platform" + data-text="Web Platform" + class="hide-from-toc no-link" + > Web Platform </h3> + <div class="devsite-landing-row-item-description-content"> - Learn key Chrome concepts, discover Chrome web APIs, and experiment with origin trials + Learn key Chrome concepts, discover Chrome web APIs, and + experiment with origin trials </div> + <div class="devsite-landing-row-item-buttons"> - <a href="/docs/web-platform" class="button - ">See all documentation</a> + <a href="/docs/web-platform" class="button" + >See all documentation</a + > </div> </div> </div> @@ -498,60 +824,102 @@ </div> </div> </section> + <section - class="devsite-landing-row devsite-landing-row-2-up devsite-landing-row-cards devsite-landing-row-no-image-background - dcc-social" + class="devsite-landing-row devsite-landing-row-2-up devsite-landing-row-cards devsite-landing-row-no-image-background dcc-social" background="pale-blue" - header-position="top"> + header-position="top" + > <div class="devsite-landing-row-inner"> <header class="devsite-landing-row-header"> <div class="devsite-landing-row-header-text"> - <h2 id="connect-with-the-team" data-text="Connect with the team"> + <h2 + id="connect-with-the-team" + data-text="Connect with the team" + > Connect with the team </h2> </div> </header> + <div class="devsite-landing-row-group"> - <div class="devsite-landing-row-item dcc-social-card" description-position="bottom"> - <div class="devsite-landing-row-item-media - "> + <div + class="devsite-landing-row-item dcc-social-card" + description-position="bottom" + > + <div class="devsite-landing-row-item-media"> <figure class="devsite-landing-row-item-image"> - <img alt="" src="/static/dcc/chrome-twitter.svg" loading="lazy" width="57" height="57"> + <img + alt="" + src="/images/chrome-twitter.svg" + loading="lazy" + width="57" + height="57" + /> </figure> </div> + <div class="devsite-landing-row-item-description"> <div class="devsite-landing-row-item-body"> - <h3 id="chrome-for-developers-on-x" data-text="Chrome for Developers on X" class="hide-from-toc no-link"> + <h3 + id="chrome-for-developers-on-x" + data-text="Chrome for Developers on X" + class="hide-from-toc no-link" + > Chrome for Developers on X </h3> + <div class="devsite-landing-row-item-description-content"> - Follow us to get real time updates and announcements about Chrome and the web. + Follow us to get real time updates and announcements about + Chrome and the web. </div> + <div class="devsite-landing-row-item-buttons"> - <a href="https://twitter.com/ChromiumDev" class="button - ">Follow</a> + <a href="https://twitter.com/ChromiumDev" class="button" + >Follow</a + > </div> </div> </div> </div> - <div class="devsite-landing-row-item dcc-social-card" description-position="bottom"> - <div class="devsite-landing-row-item-media - "> + + <div + class="devsite-landing-row-item dcc-social-card" + description-position="bottom" + > + <div class="devsite-landing-row-item-media"> <figure class="devsite-landing-row-item-image"> - <img alt="" src="/static/dcc/chrome-youtube.svg" loading="lazy" width="57" height="57"> + <img + alt="" + src="/images/chrome-youtube.svg" + loading="lazy" + width="57" + height="57" + /> </figure> </div> + <div class="devsite-landing-row-item-description"> <div class="devsite-landing-row-item-body"> - <h3 id="chrome-for-developers-on-youtube" data-text="Chrome for Developers on YouTube" class="hide-from-toc no-link"> + <h3 + id="chrome-for-developers-on-youtube" + data-text="Chrome for Developers on YouTube" + class="hide-from-toc no-link" + > Chrome for Developers on YouTube </h3> + <div class="devsite-landing-row-item-description-content"> - Subscribe to stay up to speed with Chrome and web updates, tutorials, case studies and more. + Subscribe to stay up to speed with Chrome and web updates, + tutorials, case studies and more. </div> + <div class="devsite-landing-row-item-buttons"> - <a href="https://www.youtube.com/@ChromeDevs" class="button - ">Learn more</a> + <a + href="https://www.youtube.com/@ChromeDevs" + class="button" + >Learn more</a + > </div> </div> </div> diff --git a/site/_static/static/dcc/bringing-safety-thumb.jpg b/site/_static/images/bringing-safety-thumb.jpg similarity index 100% rename from site/_static/static/dcc/bringing-safety-thumb.jpg rename to site/_static/images/bringing-safety-thumb.jpg diff --git a/site/_static/static/dcc/case-study-thumb.jpg b/site/_static/images/case-study-thumb.jpg similarity index 100% rename from site/_static/static/dcc/case-study-thumb.jpg rename to site/_static/images/case-study-thumb.jpg diff --git a/site/_static/static/dcc/chrome-117-beta.jpg b/site/_static/images/chrome-117-beta.jpg similarity index 100% rename from site/_static/static/dcc/chrome-117-beta.jpg rename to site/_static/images/chrome-117-beta.jpg diff --git a/site/_static/images/chrome-119-beta.png b/site/_static/images/chrome-119-beta.png new file mode 100644 index 0000000000000000000000000000000000000000..f32c22912bfdb3ff993a9e24ff3450dd47e7be47 GIT binary patch literal 56020 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 literal 0 HcmV?d00001 diff --git a/site/_static/static/dcc/chrome-at-io-thumb.jpg b/site/_static/images/chrome-at-io-thumb.jpg similarity index 100% rename from site/_static/static/dcc/chrome-at-io-thumb.jpg rename to site/_static/images/chrome-at-io-thumb.jpg diff --git a/site/_static/static/dcc/chrome-devtools-thumb.svg b/site/_static/images/chrome-devtools-thumb.svg similarity index 100% rename from site/_static/static/dcc/chrome-devtools-thumb.svg rename to site/_static/images/chrome-devtools-thumb.svg diff --git a/site/_static/static/dcc/chrome-extensions-thumb.svg b/site/_static/images/chrome-extensions-thumb.svg similarity index 100% rename from site/_static/static/dcc/chrome-extensions-thumb.svg rename to site/_static/images/chrome-extensions-thumb.svg diff --git a/site/_static/static/dcc/chrome-for-devs-thumb.png b/site/_static/images/chrome-for-devs-thumb.png similarity index 100% rename from site/_static/static/dcc/chrome-for-devs-thumb.png rename to site/_static/images/chrome-for-devs-thumb.png diff --git a/site/_static/static/dcc/chrome-twitter.svg b/site/_static/images/chrome-twitter.svg similarity index 100% rename from site/_static/static/dcc/chrome-twitter.svg rename to site/_static/images/chrome-twitter.svg diff --git a/site/_static/static/dcc/chrome-web-store-thumb.svg b/site/_static/images/chrome-web-store-thumb.svg similarity index 100% rename from site/_static/static/dcc/chrome-web-store-thumb.svg rename to site/_static/images/chrome-web-store-thumb.svg diff --git a/site/_static/static/dcc/chrome-youtube.svg b/site/_static/images/chrome-youtube.svg similarity index 100% rename from site/_static/static/dcc/chrome-youtube.svg rename to site/_static/images/chrome-youtube.svg diff --git a/site/_static/static/dcc/get-inspired-icon.svg b/site/_static/images/get-inspired-icon.svg similarity index 100% rename from site/_static/static/dcc/get-inspired-icon.svg rename to site/_static/images/get-inspired-icon.svg diff --git a/site/_static/images/hero.webp b/site/_static/images/hero.webp new file mode 100644 index 0000000000000000000000000000000000000000..14e5b0e74386d7a2befd37fdd93ae345914d0e33 GIT binary patch literal 98856 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 {4Qt@doFKs2j<j&?llG}$o`iJ*YHHy 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 G|NRfrps`T^ literal 0 HcmV?d00001 diff --git a/site/_static/static/dcc/new-in-chrome-116.jpg b/site/_static/images/new-in-chrome-116.jpg similarity index 100% rename from site/_static/static/dcc/new-in-chrome-116.jpg rename to site/_static/images/new-in-chrome-116.jpg diff --git a/site/_static/images/new-in-chrome-118.png b/site/_static/images/new-in-chrome-118.png new file mode 100644 index 0000000000000000000000000000000000000000..4178cde393733b26d6ebfbe4105094809abf5bdc GIT binary patch literal 114581 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 `k?hU zcLixVfCWngt>Yt1@K1ozda;MTf!L;lvCqL!?4|64gLlE{%u~*smR}RugHwyXg7S`K zJix#96<HPZn+XPSX9Q$^X8FAMfFFGV4a>|4%at>46)lAAsvfjmn%g}*9h~0Bk6#jI z?A)oal$%(jI_~p%sJnfPf0ui28y`ll_dOEEHR2+0Rjc22u8tm7hhO#d?g#m8NIG$v zzTXk(qTu_aQcJ5Q;%2&Rak}u7v)Zxl-3UTVyC<ZnYQ)~qRK`_WGGD=Gp?#min7irn za9t_v>3PplDKP<|6-_%uM3UBfVL4&~qtdn-f%iquJR@Wo9gmEj8VV=xP~J_|aiZ{5 zVh#BozqlE7r$(b{eYP5gxb%GhHtbLLCQt;j)<mw(T3|*04p}RqT}x6}A86PsS<@J+ zjoQA!!{i+fgclGlO|`vcU;}n;H_weg;~$q+y}t$$^FT_8TLZe;doeK$j7pkz>-C-j zPdIgcM#OW71>_j*UzYEN?l*ODw}@Vr>`4D%*r||yGfeZTHjT{9vsL)EMLf3nCZB{r zbda!(iX_i-!U!K<;R_k=1Rgm?AdvDyu@@`-dF!{Xd|K|dnvC0*|C=1g7u&h>_=Y%Q zZc&~pb~zSrD@$vszWGhe553Ik{56rQrywk4gFGLdr&M;oxESD4s5M63{y1Rs;6&Tl z`3IEcNsJ=SHPeNOrIy;ngTOthx|FlM=1TtlwR=N{WKVPEElwfYm_`Q4SMpBXNh1c< z+oy7=xpN@o9c_JcY1UI5#ZsH*#r&{yfO|rrYQfsD%RRw=_Y5DMYCF{c__7JmqJ&;v z-fUmUw3Hmm0jIk6*2=A=gL>rnzK{x{s4E6O&H{20@-Gn0Z|6(%*7MK(b;(k>@{@yf z;hHc_C{s<o7jI;?d*^)MCr8HF0$Mx9e^Ze%O7T7s11cVIaG}7D6HU`k{{S0<4!|h# z9Na)9&aXbvGsraE*vIPoyCJP=JnijIuj8fg_*`=5qbFm>?a{)5h(VU~T^&Y*ECoiF zm`mCt7dXqW1BC&RVSDpFDpS%Cm3>M(0N8FCO>VE5l<YX0JU91GvF7bY-VVD%!4F{! zH#HEAt9aDC9KK~VtX7*hX=b?5^WBFMWNy?>rk!XWk0$obNk&Qqu4u#I%-6SBr}gn* zE#np!VEF~CmRJA}f%esUsnnVm#Q+9~6O<|Jn){Liy_XfmNwY=0y$4@>dToT<ni9L; zyT1?r$*q4!kvB2+d$w$)Jdb^BKYlrKd?$s{06iM5$C-5`<c|&DVfn9OO7ab_+%<t1 z*UGR#LiZeej9?jzm>9iWZj@XJ-6H998n@@2XVB(Vh|8QaQYH_XHRAtD<!WF%l}m~# zKa6qHODTNbMn13odH!rQ<a8RQ&@77ercP>Xy{u?fvu&tTjfx}IHoW8wTALdgf&W?C zV>MVS8gt%vMxYf2>xpV|C+ieK?`F5j)A<@|FkvmtB$9pMlH|-MZH(>m_R;D5WlT_P z;*~f{`dt72zc_uM<mliq{_qanYnB%J7_di2U=wHG^~Iu<9JeWOg3f(1*-HHfrQct> zh=}nud368D7BlM9>g2ww3A?7#y4_f28>{a{(6lldHLH%NxN0`t>R`ow0k4Y~$m6Cb zUO#@N(l4g{0CQse4e4X*c<cDM2C}B&ki@IVSZs!RyCL@>>sLqG*Pzb8@{)>o0QEEg zL}?A!GhH&=p(lkDT<0v2Q{nq&g3tb_<N?MZLPX}$syBLn%1}N}N;)6Qfm~kDa0nS2 zd<)4BKC#e|_Fwcy;m*4k_j`-_Un={=f8d=^*)(kD3hzu)5Eqo|d{L<qGc!dl86<+b z=h&^Nf?NdCWt}bTY|egg?R1JQ5zZr4bnMb>sm^iQrm7XXS~O>He0vOsV=&JeB)$S) zCh`-|N|cQTZZx(#tx5iS@g68OfQ<9*zJZbd&OO*aM@Q8!rTno=5PPX-O;jkRxvZA2 zbDCCdML~P1&UWi6)8T$UXNjBQ2$iTC1dc6wGH|)XOvMhroPHaAe<oQm)mNy^uO}m@ zqCUNt)?r3^qDSi|beV+<H;#!Yn($MRU&`}XpF2~C!H!UfSfdrW@{pyZRx{P0t}lt@ zUJwI^mrP*RwA_0R<lHb6rI3)*bn0C0<UoR@XSH&N?DpC?Ugn%MRYT9mhq#Fjq~|9B z%qcZ^hEHyo8AuYAJoIFosA6wV&dLa&<n1?B(CV~WPibG1S$j{!vsq#Bp550ao>EgD zWF;&ZQhuqLnz#!v!tv|b7O6ma8L}$ny9E1B>Bcsv)A|olKaF4PC@zzohh}S$Q(oRL zp3L!CDpxo0Zu`F_HI4#$l@L5t-Es>^NVEWNq86}2Q~FHCJ&`Typ#zX&(b2d-AO;%= zE*mw$Py^=Gb&k)@wf>Fbgd(?r1LO0wHC9J>Ly@K&gC=mc<suj;fj@qdcvzU_ZEXA` zDQDi~dk(^mNR?f)S4v$1E#GE3q7(hBOA?=7XtZd0B^FJiM&=In7%o9>I`MP)f2gl7 z?c-Ow%a-bs#VlhzM=0?<1uD0<1Ex+-<x#XtX)EI13J&NO!$w}IJL+QUem_WST*Tk0 z%u3n(bO&B>;#gS_xb6#}fv^OI@OUoKqg%O(u-`ppo|||Ov*rn{;Djdt*+6=ahtKG! zOvX+nvIt2VyEDO$=o}FIhd~Xfjbl}wd8)6ean;9h-w4LYe?LVwTVQnJu5)^;fvRX> zVt*tuXx2p`jj-(`c4l1ftA)s#!HBtaNt4ey0Le}@cBmFh1>5hK0d}BeZ{Dx*IUJ1? z<FM*oF4`H4k-Ce{=Ynz;vX)Y;i22{W$N|J!DA+POx2AoE?7ucL?!CWQG74V(Y?ijl zKGfj3FUmc6g|c%5bi77Q_VtdA6*k27=~A5zlOO$D<FN~ly3R>s<pl*qiUHV)e@1BU z#v|SpDk`zN^Z*KBpxLFx3Ce1Z*?r)WwvJWY_x|tXrTa|H#L~Omvn;@xb|s?WbkUiE zwRSqJak&`F4yF{udF^!(t}xw>!tvTg6mBIzd%3ZWadp~OWOccWDl<z;*-b>@(|hsH znu?z~Qg@CypI)=PM8iA^aR@7O2J>5872AD`b*NIY`5mV?0axzdit=Oab@PFQy;Co) zO5@;SXT!ha%im3^&#ILJYf{&BME<kU<2zEsE?*IyIq{SYIC`u8%}?Ri5zgD?2ne#r z7gRnD_}BMx%0a9-_0OC0wr?nlM1M?l<$l?huiR{<JCg)=Yi=eWv*e;X-zS#fsUP=0 z!TRhJE9Gk>BkddI-gmD>m+bN`6YI9lX6PBPD9IZ;8HKI<i~q?v0d^85b?%3c-$r)o zXERe})Oqx67Fog_R6bK>SY23HNCC2&Y#e<XkOR1S+$;eitxm^`84eK?;VHZAk^*Sw zYe?i_x6E;<ZNS|?N7uEOd{}2WIm2{{NT&X(y>~gk!@**^mV)|$u-M$6VL?MnuMZo# z!uCrlOV9h`Dy~=5yoC2Od?wXU&Aa+wg+^?#OdACj@R}a0I#$UvdsT%t@B`6Ko8`_U zIP4V;U+O2$OV(y<8m5oRO5PykeOw!xRv-9`!mY!8->1<O)VV0aC%|a?3#O`B!Mow_ z%yrs-@0WF5_@ApI{#(UlUYRa8)pBz2UyWyBR<I4{QkDO}nh@sp<bKfQ3N1pZn6Nr$ zH*QdXz|3Cv+$=SW#uFB>KPR3Z%cTZidhSq8ujXqV|M?i{eRU!)!<D7)cv@?BS-E-{ zO`4i3Zja=Opc*xtKdE)HEzg|~vUzR^0U>>6O^Ub!S5=~AiCdirRKrei>TkByh5sEK zVkjD4s<=W=IsH+U<|ST8H9giZi;Ir~&iAwx6e2miXz)MM^pDHjh4=^fPc5fW34geX zREY3hLb#N3^gM2RAwhgK!shcOZ)LA_zJ%d!Z;Ni;ZmzdnG=@~e0sSszhCBDr$kSe? z7mc9YKcG+&W-=@Y#0sMi$5kO6;865w;|<50_~8UXAFqbcBCP&KZB($LK?8HI+;t$J zpUU<fE*LUme~UWl4|2Wpb~2jI;L>U@yhZ$)|E;54i&$nf=g9%(nZSeFv1TGkc;=$q ziMjXOmAycI!cg0!Qmj18zYhV5J3GGYLy0z9iGsSux%1QzXQNfZHFN>}iTglM%r1+o z*!aYPXew@?$mS+=^wHKTnh13T^LUuROF7hduz;0O)OJ}Xbr;UPbp}89cjRLE{(ftW zKIrJP`B{4mMTTId9^Fm%^=am8hmo$XZVl-CM>X68KBL)}Ze{7lNUZ7V6W<OESii{E zcXM@h{Wc^Iasa0R7`3QZlDVMGte4)wrLCxq6ryaG5IXZL{`3iiX4@idJgnl^%{Qm# zwKAa{n518(eN6|y0Bgz5GYeOHR;e!FrLDbE>k(d>IN2|Go4tJ^7}jmSa-S25*0M^U zotSq{&bZ-rkq7PLs%-vRjVNH8CR5fo$<A3l&;(B2tT~;AspWh4Hbtt?o(C+nwLz*G zR%qV9BYF4WWo?U2(l_sJHV*`t4xU9L$h4FzkKKA$9P(`H;^bV{uV6et{YZb*=J_P) z`#T)A_kY<J-P&MIOB$1&%a6V_t-t$s_LYt##JDOev#JjQuc;P%XO~ZFd^#tm5A~BE zuFLy7XMK3sAAku+AD!)=qWh)P%Xc{=N}dJwa8*%k(du;0Or^z{U~615HM8^)_<kzT z&&E~A7X1Glm+4Ipzr2xbug?6P*h#aSJ1@ke`6i=CzqYQq1+n$1Gh_1Bi&`P^5sf3p z^GWNo>BsNQEMsW9lbYHP<EVHj*wT_QDDaI;=&!bjV_7A|tDf*zvztaEvdty(=6<>w z%s*SMy1ma~eul)UYBg_%?JQ!Ngs^%XUKWIS<_<}oDHt0b-17RTujVD%ZgMqGX=DTC zIMmZHvk)wu2nCX$PGemIwOzse(CLYZ9WT*C(GeEajSRco@o7Nc3g}E<QWGFg@~+hp zm*=pZSl14X@NlKzUNOLp>{DV5T?5wI6AfC^!c&#SO^lq^*`IuSf1E#79;InIP2;?W zwu%IxmV6>xW{cpDI5meRR3@or&Vqd<WX|0tGpVRoCP0wT4Ps=tx%CSxPRONsD&rMH znnIzbsM^M<GB(B&42E9PjeeNo&DniOCUg;2XP{wqdYkNVUE8OB$CfY0maZ+RU7cxl zTF;+!{p+rMI5j5>xyZj+vf*K1Zl^<;>n}Qc*798Npoq^r(|qq1a+ez>Lzk}Foy29B z48J?Wa49(FUW9ldg-rdo;ipA(cT@jzTRaqiuP^5ya2Cl&eAXx2W#)sp)bHGsJWw+{ z444Z2@Rkj6>#NtT<!2LaJ3GrJEj@DRNxO4!AbxhDp|ddV*yNs70_%D*mTFtnRq%6` zdn8S7gm!!Tx*;60p(}#hzDQlpAvtkB9b?XG^Cd(OHaPw^tLn?*=ge|T|9kgk<X6=g z_>4M$b1+4f7~IM$NcIe1>okHK;an8R`^c9$Ua$Ajj=q!S_p0B%yO?`}p7{KB-`uM< zBRO*v$ei6q$IJ>Cv27cIXG}P@m*8uAAdjX-{treP0~AOy!;19PCr%h~R=4J@KOi7e z9|X!D<z!Y0IJ^6h?^iss)fK-70rmmtK^yS#zv}4fmgkwHo(5eTFYB0^ni`$WPkHii zUQ=)bb1Vq)GDTl+pcQeUs->Ma{szj4Xcx_AIX8AhW_5IRgf!I+0)f;Z^yEZY>a-Xe z`uE~EZ8r^C>&|WGEV<IGWl--s-~r4OJwJ4Yr{*Yq62Mq*{i_>J#!)8*Vrjg%#r)A~ z#z+%dGYG4B`%QL;RG_g-kjGvzWzl(V%9S50K*FWokIQv!KmqH)0I_1UWL%*_4G{-k z414cHp>k39wEPe<CiNFz&BLG~te4xz`VUTLmK6jhiJWK`Eu9QIq5ZDg&P54K_)v)# zM{FmPa5qk_gc)IS1auS;(XGUm-gsSa3IwjWu49#ejhwg7N8b}{L_dZ`rVIW<CC%qo zSHCsCIN;tH1$RyVdwLQc0bWYPK@gxd{CawfzqvDHeoHr;DaZl3_M}!oqnF~mjJ1pk z0X<VQt;_gf-MND;_%5GzP7u|}V^!Qv{1=K%r-(I7_@WJsB^spR6x&!G`Oy|*Z-Hxl zWMm8r6v@BhE3#?iTf2}i)cj*8O8~^$U4UX@o{eN(4W3p4tDy}<>T9mN;mw*l&k=se zzPD)Ipbovt)uJ>OiK^u-^rWuHIJe#leFAA`cHkB~7w4my_)z3OHA0|LYwog*a;o|= z{I;WPW(&me61~xu5zY;s-`SG1Yctjkwr3RSw5tu+T%CAdBu413(CJ)I5^&yjT@syw zzYmLtLjLqE`&oZQ;o*dYTI-S}RxyYYN}kq9ogEE%uE_XDQptJ$4t!m>4?U2QyuC;U z%pc|P!Kb|d>k=%}W8v@0VmsJTSkRGRJ3Xvt>{NN>fBn^rK0G3lg>J3w#jd?sc#-Iz zxMRuoYpOc=4Kk@IkY}B-k;b35H1kzWGVS)&)lPX$Q~c{?BFmbuG;kvU%&+rA^={J@ z4sq^J{Lx~1uiN7<^3+CQq!thF#npf%Dq6DlUEVwVQ)<u6XhdiD1+&oCY^l$tzHa>9 zbxSMaIEdYeAhQd8PI#uGFJ+0WU;&vnEKW$nzH7<hx*T?)AFIrQ>IHc|WWTpdD>99w z8CHMCx^1AAhjhWXIsUO^@-c7yIIzz{CB_zdV-vE$rI2OxeuZ0tQOOh?mn*)qb@?IA zyIEXpiUmaw8+Z$ZNOpa<4{jTuFqCHzGH}Qc4hU`@2YkJfZ0T#X1EkGA%=9r}fL3WL z1+W2ho#Y(&nc_BJY(D+k>rQQYIa%4k#ZY6xQ$}~Y0`}^`BJ*tk!$-2Y6)A_xD!v*O zbZ~h=e0+^R7mrs*ge3^HERJ{J8kbP;HUHYx+SWK9_X}}YD}MdAO}%Vx1}a(jwCy)H zcxvJ?@B*K8YMk)+o9u7-B9xy7-$P3YFf0}>-p0h(Qk1_?cg(x_9D4;6>k(s@a>x{d z$Np99__aF3^T%4o<eXx7-@EOkNv%oLd7K?6$lXdOh{y**=2g55f}qm&AY9Vo`S=`* zG`G--xh<MXPW0~2jG&G9-6la;AHvG--3O+hogRk*X_2bxQ@}7lnj)VCUvxO_w63{+ zb+!g|NZ1J58;-l}V5@+7i&FASj&Er@YB=tAonE|BSa@N`Tya8X(C$`UB1&40CjL>5 z|Daoj?^s(TjizCC9|1*u8j>nepbJ|3uLGE>OP|E-!|wiisLBCBsPy%=y5~-LsjuD} zW;2Sk)D-q7kIJe`rW+|SQyCQG@k<!qNX({+3^qxnd6mTFF1f}%=vGWg@rolj7h70* zr=!ishg#5t@bf+NxI5e$wfMccYO6ur48o#eS=$)K4l#KHET{B!EvBRdF8>6(%3iJZ z{R_&s|AKP$QMlO3-j);_YP=B>2L;KEE8`5h8z~FUDJ)QhW0$Be5lurgse@LsLtb;) z*0>rtZQtcK*iD^WyBgDUUJ9H$CKiV`%QMlJ!^0gS9KTKcHe50d$!nRjKVjGxSf2fA zak~t59^K~-Sa09Iw@pSUi<+gGyvqhDTp<aJ!Egs8jnm7{qv8-uwkxh5pHT9%(s`Mn z`)w9A4=1U+VF2lucNf?QtorRF^UR5F`!7Fcv~OerAvmv9|NODJLb%q>M3VxkH%ttq zq+~xEVvI74CFbvrD}p(*Q)=^tmygs2b|(_=yiemlCRoyeHAmfx2NJ&)@5L;hC&`Pk z%kCv2N24Sg7VGoks{#ZPXkf7ei702|{{2^SAe!sK<E=e>cv5yEh!&nJ4_Z?kg9~r5 za$5@^5+@M^(f32kUOUio(PHpCgM}v^0kKG4Z#x(Nuet0a48Cxi2CK=?bqyohRQP`Y zb*(Y2E#Mch)FE?;+d9iBzsudP6`FV4cR#(HePD_g>IA$3uVrpa-MG~JZjv*Oz)P%V zM4P&<xN(yb(I9!b=6CyAB{lN=$Lw%pvBDybq5c%~T3!rbY&@Sog&7kFI|C|>5}3kN z_IjG1v%=N1HpIJ0>}n4CJoq36A|ls&bRVM+i0d2!v<QOeqxji?f3LS~1rTis$W}kh z+NeGuh(u+X-|_K(TYj8zUnJGdvY^7Ta(d_0BNJOMR{LS)>)@xWB3d5t<NMwo&Sg6v zOy%(^<fVpq?`@RjMHX$$U0HpbF<7<tbnf<Vy7TC$^YXL^@YFdPNUxh#rJTF!snT+A z%^E+RkGqP{o~%(7U?nh`K<bI(M%pi9h5#?C0KUkRr{-t>HJim;+u#3C&V7F==az9^ zZ8{UzwuR5b?!~oerb4*)SJ$lqxQ`g_(zEeR^QT{oi-tNJOG>0cIfh$zTWSimhRA)W zv`tNkF@)ug=_CI$-+<N5)){-ff~jol$S7T1d7JS4uC#t1aSG8U@}%?KVB<U}Lq({4 zmF@PgMd+-ig_SJb^2*XdPLXo2ye^g&G6V{jv$Ygxno7_5O}~&Rnd^J36m)tQWCA_k zMg6;YW?XXx!}yCfS|xWj^-arlEA{+L`=TDh+}K~f{9>wGel`PX+83rA?uf%Rz0Xi^ zkV{Y$%21U42dktf%5zgsh4i|!nj3B?U%{Q03*z(NQ#NM8nvk((tfHY#y<(W?t`m5| zOX=xQ0r7nSX}S!l_Bzqx|3i&o;Ry5}-x91(+|Ykuz5*(B64BYplO)wepAT%BRGkb~ z%BsKM6YWH_{g_Zub8G2dmZYA>=l&`!5A}l<k;coTY|}RQ%p_+gvJ1=3P-<XAEZn)% zwi?>+rTgX>e<>`)^Eb7tx}sIF{>z3_IAbKXv{ml4FvfmfPhIywpg4i}Rjqg-rD{)S zBGgCR2=a5rNe_B=?r7LNjyAj~VZb<C091@MSC@C&Nb|eYe-$$HhH-0KEwIZR;Pf4$ zYJ&`svw7QI6kS>-T2+Ak5asDr3d$R|w{5a~$S|=Km$=eW1b%1S`COpkR|wvuk)<QR zB<eFGP=zJuxfGIob_d@fC3`U+d++zkqkGG7qFb63S%hK&fzZK(;F~MCJ}L@!#-ps2 z<>2lazah@))OM;ToMpWJcRy2Wd?k+Xc5ms+eJSsGw|AZ}4o$bc%SCK%i4*$GVqErp zfT#f}5e0a?rAG4pe{fQR&(=?uM}vU0uv1ZXpZZA0Hzk@uiJlhNp{JUgBm9G-A(!52 zS$3yzyJUEuBN^t=_*F!4z!@>bCTm1WA@9zKkqH<?r2(M8Pe!Rr3Jp*jsRUd)wqciG z-i*$G^PS1O%PIiR056XCD>@FN5&|t0{}ZrDVb!s=m$ozP8k{_96SJBIMhtNb3Q7nR z_k{K|?bfykf1(1`)HLPgPK>9LbCQ>Vjac;Mjd>UsWkr*ZD3p2_q>caX>pzg!6?Z2l zOId8s37GYCAHneITUM!|{dN=%3ZKXOs#CcPXs^3cZHm7o=#W#QR{`=&!FfCUjb_fA z47UZwAs`=bQ2T%Nl!O2El!O)PB=noOXgt2ga$=r|h(G%!us1~8;M-@CLO#)CfC+9n zRx{`>DW3!XI||S48HRY==>?Ypm0s)lJe3l6j@>q4mK|+fUNaAWdr@ts6&rO-1vp~) z1wN&NVGi`*&$c8a0(7@%&^<-1Bz>bG@TZrR5I!+HI_H1x??ct3E0-PHt-3zh{^~Js zwrathZ_-QwS?OOb?n9~m%Ll?}^ns7R={Ir}b%R3npdG%9$5ij<8~BPi#YwGV*efeN zx4L^`sAu5#)j{$B3$bV3=~gG}YJGfKz*7H>DZ>y{RBI{SZAwf^%XfgXjn^iIM67|^ z%2R?mmaHyrNxnPdg>!5RzTHH(P|h<w(RTObk`0%lg`|w-DitBteJV=7;lV0%4vd7S zt#V;ip6JhUX0XYbcC39NVqmi~G>Ws;+rl)HQw1KFMnHFN{Nz)(&J3VOpUTX354&0x z?!S!_+Vg6<x@+`VcGsHPr0bUEZ$$ZTuB>dCMhid-qeue|m_7+QPT8N5SsiflGN&@i z$BxexMnw~0$wo)Lz*U5buf%zG?t^kN4i4f=XsCURZGF7Yr4DA}%}1b!3_Bm-Z`bI# zUl+O%?A#lmqS*3)h4iD-tF}0Yq8Q0r=CkBOwU5cYOgQOJK0tmZ))|IP4>WST5I18! zPhH_@P4YXEKZ!Txo0-6sbRliZOWkg@XuvED?YD`WYy}aa809i-6=Xhrt**vbmpCH1 zMQ?zA5rk`D#Ix`v)gUk2HeNRNZmoP`p_P-DkC?aIWf>=)Fs(OuIq-8x&MN55uk$}g zzVEsSpU?4DRv5mvNq(#!^<((b0kfnH6a796XPgegI)*hSt)DNVvYT9of9o2_SWTk( zb^ppwf5P{`n#1ehJCT@_DZ|>Ldp%5OpI!6i=>v0y_$XGnqvSNLnKciu2ZaWuzh&ZR zn5-O^$3}z@pRzH8>aJQ44?9jxfB$kpAK+SDbsCYbL_IM_1`XE|N5F22itGa<+S07; zRd(!Ygq|O-xhj{}$M@D^o(Qpw9I1?-RCX`JVl9_9gM4)?P<mGJ1<rQAJIp^NefltI z?7&^ASN&~%GdmAZKYacX_A{9!lSV%N$J(bDh-ELf^L)efE{`{Kf5H6S&Bc*z<T#sB zQbJCOjW;>H%BW&wFU2*gTSw4aGDVkWZjo^niA#}Jt$pa>b^dc%fQqLft@~52pejwF zl}1;HF3tuTmp|;2jOnA(QBu~Q&$g0DZ}iiNZuAql64oBy4!wU=JRb)4H2AQ_uNVGv z*-f;%`|w5Rpu9((i0<cQlqeC=Ue5!bk}AQsn0KZwH#iXwR?Zv-_w~3<k1n3JRE!Nc zj)_)!2{36iT%Qd0F_{y_@oeu*hJnIkzvR(d`np&jQHzVzOYIYKrMz%yk@)(3uK)N% zNV1UKRoUe8pqEbMT*WdgM+?=p-$4^ayJ#V8(ZC9-l})s~A{qcGG^IJgLW6^Y!vy_L ziWFkIS?It~9;2f0T@8O~T6Gc*mDE5h??+G|*Z22=Q!TG}3>Rv962AN7TT*fw)k)A6 zc5M$6##EEiMU8SFixbJq<rhUYok$Ok&yODukc#-%#U(4)lTWKCL<HTzNe_N4>$e=6 za4z+oJ~J?Pa(Vpvkv-eOvz#c_L?%7?kO7NPu5nGcV<54&MZrfTv*+EJ17W?OS_h4h zvx#8YlWrJTwJKRe_u<R|5A)Za@I+~KJO*d?#S{hx)kSs6Cuk&M_nAR!Px_{y_}g#v zoxSmF2+YUPzXi8{31<=e6k^M5z$$;=Wi%Cx%&kQs>Z88(qrf;A6_u6l!-BJ`K>V7J zI7zR`Nu~Kp=lN1k6cNKOf|CB#BiZ`X?cLE|1ePt!h)d)3jXo($idd<jt8|*z232|- ze0)}LHMq@~*m|{@#WVp$<1D*Dlajn{<AdtYD(pBiwW^_PC1SQQ6Fl{Kao<jBY9sya zu<k}4)QLur-4j<0-WN>K?Ut22>RXjlcGzP-OuMWX?P<Mn!wQ;cp9f>={@CAhyI%>O zbtao5|G*f~1QDQY%(=x%l-9qi93$enI20ENYmR+rr?QnrhIZ;|HCd?<rOaH2_3MnM zB)QceTMc3|AbI0Wh%x55@;Ul@X1C0Ec^T>46!G0?@%s<6GA$Io*-ud<oqVGCbCbh4 z;$$p&?<qHi%`LoHBL+rCdx5+us@sFR{ntiD!eq48BEYdwiH(gl=n4#<x5RivOJ$es z-ac>X>2#R?$~N)|<k#+Zknx^&=&?V}$)I&${i~h`F`OkAF=ac^2YshA?t_Z>3ItQ* z+zKBh+`aU%+!|S0U88Gn{V=oM!Crc$dD7=M;-*Kj)`+O*YAu0<A7$4o^?wiT8}U(W zx$pB<*X?BYzTE|JGp4U>z5D&*A{EA})@jGNGvc>q?H>j3R^nDLe~><^!Si<muf=r| z1z9U5VH3&MY+v;Bbu8g|Gb^X*<5EkrUxCzix$k}Mg^sRkSuOV?E3qh_o(3r=8rn|y zj|6jGWaKR=K^qn8Fo9pib8l}C$UV>P1!RI1^9AI#S4aJ;1(CF}?(W=;Z?@fiB{U_f z%wbErPrR>Dv9k;e43Lxxd2#`_{CWD1!|&>!OES>x)tsd}FC$SAUIC^LDrGpb7<F2d z=wmtNIAvhjEA5@4BLgg*&uktIXz@hs=;5GGh-(v`Pm>luOg^yn9@Z435y~Kg0;lAg zy2%a^ZC)kAlMfUT{c%aW%?F`RE%$KRu@4i>suFPeqgX5KVDt97ya|>MnIkW+Xx??N zN9qyQS#MI7np5fU8YgjBx_SG?+j!Dh#UosW-On5<3?b7Uqo%OT^t?-1NjVsG?((TD za;CbsZPPRXsGx?aN8M;}w+eS>w{;E<@M$}4PA8Qc-(WnEkhlFM0@TvieDAH_LpVnV ze#Oi~?uWW4d;2(gsu<M2?JEU}LiLyWqGsfJ?aO;i^O%u@kMyqNkVOh9H&|g$O-_6u zpO(fcr@ykkeuIlOxbsWWe8!8$UxXB2R+fa6Iiy^{V3P50`A=U<SSrS%)Z5VaAt$A> zRTv}n_bw@@pW`bik(g#laZDCa1-b+nkaKpN>~{0qXYT@+P5GEV=bC%5BD6Ip6|A^b zPbwN3eA!0>#q3UVzRT7!F|!CN@*_(|G^;Yac(JzC9tVb9GTUZ*Kbxs}o2}e#A4AUj zm~QmyiN1-uC`q`}z3)%sS)yA?RA7R@%V@gWHgm&)c+$q+M@nWcTvw@I(rM)9oV}^4 zAakB?krg>LaKfs}l*3DZtdk)dXXk{K16zZa(r;H*h-pgWCfw}7G@XrMx={J;P7mjj z_E;+|+XSX=DxSNxO{2fXp!Wd}iu`Xmr25e8`0$x>tIO+6*AmDBRg8Ecp3oWXbuk9; zh@(VzgrikFw4SK|?5R%2NHwACJ>DltmRdnjRmR8cF2)vfHm8s}$aB1f(BY_?wpqdc z=?TyLm7}znyuqt-!(Q+}C)3IM0SR|=vsdfUtng}Xz<y-K*S^<b`lfyqOW*^V7+T4} z|9XL|SuNS;XJ9LDz<^Crn)}ZCktGHH#`DHEQHuWZ{;Ck<d#{dsU9bEGrEjxTHh~be zp3!MO6GV(k$$SWr93~6FERR=I+^b7W2>CDt+X${1uWrlnyKgV$G78~VFJ=TxBP~dI zh%`;y@GSr{n(hksiJ*jU#8D*rPb9~MTXh`GejLp8glP%q?VU-keIy5*2!Vzn%B*Bv z*J|=3o~gL8h6sODN{++_<Yi~rA(tsM@qd0$Va1VCqQ3H08NAM=p|9=@a3kBBVX&Mr zswWYL8xtS!r$t4@0FI-G&s<%PQ7C-d$ahiM+0GKE^|f><v@dYG6MZETDS+sJ)F;XK z*=j7z>bcI|<d&k=gCv1xu+d=x2Ir9`0Rds5erq_U3@Gbk1v3uZh{>MbWW&fh-xVU` zP$Oe0e^XNs?W2bw+%|0f8B)5F#ZdPi`tgWq!%Vy~6T33}AqJ6VRXt|9|Cc+LCkC`1 z1f?hUx=ppu)eoDQEwJ2zGv|pI^Hc*oKlP6e#Yome3_}=RD@H7kS~$bDq&M_I)8{He z;5Ng^<q%#xL(H#)1e|^2OnuBDo2mSU>5iF;fp0(gH<+3HE>zfpx6nlgl=K;W?WYNN zYzw~PP4;5`eI#o;*Y1@yPmh72Ci+KKBu5Q6*F#^Fp3<{ea!`K$fmu0yAvBg*^yq)R z&13eb`Tw`G(ax@Od+&p1hx*wqJO+rze)Eds%1jzysmhWNs$yuzpL{o=2_=6i?7quN z(Z8Gg#p#F=mS^vdUcTUPB`T{DKKt&i>~K!EtZ<&Z(j*6~WuiKd@07&2=@?G`NuvGQ zVA59u^6{JMS{wrO7LzK|uRhU{5`kEbh|(gfRP@I#oeX8k3;eaqQ+O5`u-~_Qdq#Y9 zx()JXm81k<aPQaQtYLzC7;fuC3P9JM<KyS&4ZiVh?2U?I7{0KE?!F8W9z%f|sJqjb z#MCItR|i7HuKqlFllm$8qZ~Hw#E02caiif+p%__VF0&uv9&&zp@AcwEH15;xskNI$ zMjns0BRetT5O^t@#@V2zAPex!GLMqgv~!7`#-vf0_yub`nyyp8kG^Fvn+)X^@}>>2 z`?RVUv(4fI?HeO1=~FYg2<A_Ql@II*i(?i(a(B_2Dm1MLO&TiGEOMJY2zK%&C!!GZ zd?b~Nx)*%(xzf@S+5543?bGk-!j5mdz)Q3q(tOEAZqtgR$bst^g>VrL%)-nupIzYW zPQVOZi`Yq*QthpKeNQ1Q1`D+`kKNuL%hGN8Q~jZkpyGvlR!o}>-!s>wqh37<Cr4|b zSk)EjzAiEj6UO-7pr}9Hbf3CMR@R!tj9w%D^z<E#w!&b99tmc5_iLQlw+TnHe|kO| z76~7z*;Ms$%E7J3-M?Miv~~MobJYseX}qqXvEO-@)bsHPyA!n0B~oNXYC~tMHMjy( zbPyp@-OY<;3>=r!^6uzC-i=hQsA|6`)JfV~fBsJ0V_H}L_fXr(AsX<w(<l#cb*{g- z+4u2z&d)!&t6@(kk;|GpQ)TMp{iqJUN6wQEo41r*pR<bV%gejN!^EkJdoSYbeSg7Y zuNS@)VVVcLdF6D3cq@-%j6+*CD2JBghhdMP{XAy7Q?NciJK5+*sHOOW2aJZH(-}Al z-uL*Tl@k#@<hzEKL?Cf#Q;Tg|iVU^<`Njie-5v5>3x--{NG~xp%-!H#q+GWH{w?P) zyG4tvo<xBI<xAX$?4P3Eh2vQ4B$}`vehb7u&vCgiUTNqh4Xo4aClDUn!eb_U>hOt@ zY8hpDQZ{ZE0<L;m=0LQS0{YeST&0`0gwHnBD|aB<fRSQi{~FH4o`&q~j-bJ0xRQnC z^*$WDc;~U1a!DML7!>1VFup>3Q7?4FZ1+TSG)1NqM`@_%B#XA+rDZKKlI|Ojq>XK= zzWd2EgMz|$r@Y_&_a_z^<zl@13$guAe`p&Tw$0P8jJ;v*w|=|eJ1{cRr>Q{u$<I8< z#+%hrlLV{b#T(()J&>6Z&o*3G!4qyc<eV9Y__WO|yrQk`ibJTotS$RwEYy^#CKxoj ziK?;L{yqY~A5wEa6C<#h)ZXBhXknK7;}|q|J%9Z)yu=gt3w{5q5gH6ri*vCtqsTm_ zE%7yt=9T3N$`GO-1(M8pxEE7%jM0K`?fwF<2(4YGR94S}8Zwb0t^SMKKJVA+|AN4w z-4%+Qe!^mk<!zRCVkc&n+W0%<w`ki??S2YjMgDr7Z@(Hw?u5MDPOphDx>ygcetT{+ z(*WNexM4}R`MC8pP6jsQ%=+4{aLcVKgIF{1UUDw$<zqUj$KcjY7m33a2HVK@G72<a z4`>5+iB37$c*RL}umJ$@Fuwl-@Jgk|-tK`!U_PK{x677d*e34AuxOlLLHXjt%}jsr znfR>MM}S6I+iQA}CvPSNw%Q3==<JUa?T-f!9r*l9mF$n<nh5p+u-WG9W&jKS`K{sf zJyS&}cqzqM7nRedSI>VGy|O&j2`Si_7`X^j(s<r#8gu~KP3|C_6Sm~oBb!`;M@5ZU zBDzQ*`1}P^chtv-rj6>c%oa=z>5x=u%&yhV*PNmx1*+U$4`X08p9M4}iWT2zGA9Gz zqP`md7xwW%<!j6OgApxqQr=%;tn_va>U6u;$P^n{M)Hdzovb6O$3efmH`0(IUfJ$X z3EGVw`W}aDoogGiX#Cl^67m?ts*!lHV@l6$`t7?Jaq8?Yc-pfJxWvK3XQQ&RvTSP; zD%?Grd80iOt}uS_FX+XfS(?_XoysK0U=0h<aq4Fl7oEKyVT9bGlN-?|To2>v;$MBh zez(^5);5y(S<&o{H`E9pkxOJ`1Rq=237fOytQNp<An0C0eX|9<a#y;C2@<MusV`z$ zk@>tME0gBK;v9g<Hb#K_I%>&rP2K<%ssOR!BNHI&miB(Vt2F0$_E<&Gj?S0&)IQ6+ zl3KyRFe5#DzzCeTnrpn>Jk}cbdv-B$-yobUFO+TjQl*HQGNxlO`O~O$mfFa0y7wkY zSczBE>OMNDi)9EYdu8$3!9GLqnp$JUllOBN3e5X%Vcf$HuE=D;8y(Ib=MPnEvbs0K ztY{~BKZwQqIh(I_RTxQj3&RcXsmgwF^!GXrQk48K?f8QsUgB{Ur+d=7`wt1ae-SPN zsV-){)}~2+2T$NT0&o^aNTHb=Fj|o+CAp1b0bUvTIg$@gyFYy`Z^P&01YI+MeU2Vt zmbp4dJi*NT+QaNL(9k+QIv@3cuf@{Mp9a@?FCk%JcK1D8NJOvWV~jdi<XWkIq1x^K zTL+W)(@URk^*7uJQ}^|=hKR>@un4%u-7hd``tirzcNFpMV#nQfSn($#c0}Ig$KeEd z#q5*-dk>j|m!XRS_adj~b}U=y%A8j$n20oA7N2E2)O?g{R%NxLND-dVrzS{cz`EKG ze|mt~`6GFOWum^WD2shg1Lxk$S`rbLV)y<9-uu=ammd93|7?GVRZ1V>B-}GFgc$aR zeA^n@VmV6-brq9(R{8ibhtU4zRlV{uV&_v-lvbqVky;yT95x~C$LsyhhcMWtRO6eT zaI)-3=)o;bLu2DGLHLXBYoFegx3&HJ+aE74FM;o`c`aU?ptkcC8v<H(@n)sher$$p zsvf@a{{0$55JU_Sz#;ir!<9uSEZFk;QE1_f#2g5MzRk5cdNK4{&fE^qF^HlJWg|mc zt_5YZD8IykG-TB6UeHFlC&3{{{KbOR@@Go0NY2`W{T-vvFM&e7;ZMP}e0!dZA@Z`P zIp91NynJ_D9wPjFuZkAC<6d{AGLbGxZTT~DgC{>3m|hgt@Z3|C%vHfMORrt+nhfZJ z7Ze~`L7=i{tqx!PyJ1<=oh6lMZz^pT;j)AEVi7Go4o_;~iB`Py57$b*9(hdf2q?(W zXHG^B^rk;2*m{j{l8J!dPeElJx<1}!5VN0Gv`SUQKY)h14u?~TR(^?MB^CAWbD;KG z4Z|Dh&lWYe=$ZYjIuG{ur_2rft(pCPkS(Frz<**5IEcT`AN~RWR6<7LO*Q|^XLvQO zyIK-g-;;r>%4evSV$D3Zo2W6*XsP1C^E1uqBwzn3lt1WJ215!)rxtl1$RQg78Qb79 zjXXPj-((3D#%o@B9Q8;c-JA20StaDf0jiNCMmO=E&E{898}&-n&kc6I_On8aICZ;A z5p&2*Nw^-P#q5xC;=O{a@zayQDegP+-1fmJ+Bd~hUpehB4~1f&7v}?1B42x#J?rfN zZjn5P)#V5ip6U5z{p(1;$0$}Jx3Z6qx}iv{k+Lb?F7QsC{ZxBQmW@FYN5PE83QU1t zhiF(NavaBkVYr&4b&^ozJa3mWQ8P#kI~#Og{w(hH)yvw)Xc0ria}C4`jcgipa6Hw^ z)oHr(-2g4=HM1wK7#Hj@{c^IhKZ{sD;3VaaysKXURs`LrPt`(4?N)X>pHO>mkw{#w zuWilNnwy-f)b|4C^T*ouZ%nbciOI=ff}STVs?xNsooE6f{XXIPXKaSN-oMzE^3=^p z=O##0Zy>(nxdCij{teBebS8A1lEXyDw=a|8wCwn=N}(1iqoL0AZxZXx1v$q2zRjq1 z&0sqlicuNEuIVscPS~4uYpFPHy`=lh4#i30(lMW>U&PKHyR8DPmOivnmzap+b6$n4 zxa3(0?euPob$vlkE2sn>%6m!eh99Yp2cZ{Ic4`0k;mjXDj*hkWUH6X>{XeTeF3`4C z#Fdecw=S9mzJ715Ezhg)yfDO2mBon&H<j&U<K+DDhOn;%bdck-7%^)OPWjnR^7mT4 znk2Rw>q&ayG|nC!mIV$fnzu}6rp2*%`w$|aV$h+~w=0ONx1VsXa*G+Ffb^Fn(8Z^{ ze#UfTrM|@;2tsMxyd7}g8gR#57s2A&mC5A182$R-Da@7yYz%Sft~k%_`(_vX=`G$8 zzu+bGa}D<4Bs{*reN7od20qf;_x~{U6;M%k+uOrX0@5Wdjf8ZkgmkHNhje#$NC*f> zH%g~;mxR(CL!+Q{cYKHU-uwUFSp%|I%i;V^?EUQL*?XUOF)cWh04ba?SEU7dDvmc$ z-znTwYuEhFq2CdX>;&@fS-Qt0FUH~doX9GANj?ha3b#IF&8{8>j(3okldq=lf#+5W zWlx>PZlg6lD2o~ShBQ0D^D|ztHSRf;oRn0m5Mi$Hi0}oeg6Mr?%0Z#OrReR&ox4L1 z`fSh44}q{mVh~Y|<9vnkeOAcg!j>lU44F3ykxYs=e^%eF*Nv(3-lti;>l-7{wC$VZ z(wS>6L|4V~B5R9<yUN^RqL0HY7IwC<%rbRubgD!tBf&K*_x$DpjC(QT+BYjwe~7Kr zS-Zb=EJeI$eIS@->IfUdwf0f9AolaxQEjwh93LYWavyO@BYj7Y^FID5wrYt?7AIyN zpNCg<OmqE|5{@NwZoy*FBts~Gf_m-RC%<}nbK@FGd6|WSt%B=%)<o(n2Fs9y>0gXM zGxyW}&s6aJdqM><yYyW}7+P@Xm&Uk*{t+MEV9!2$Z37tuH~SrgfB#yt!}=fjl2lI7 z&hHVp#`TzTPld7uEEMd%_mwv+M%UKPwJCoz+4V>m{LSIwz2|4B_%ZsS{B2c^cwfQm zVpw%lkV{~MFSo*9HO$I>^w`;!8-o@YyhaO2x$VnKct%K0do_wqy@rXjBH1=c`uNQL zYcVy67*#d3si~>_wk5J*32w>G$*^IxhbXDhTU4eMPaGDVnN+ej$?vjBMBA^PY^Q-c zpxbJ2>~G&ro_(Nyf`vVPpVCCR5Cx3!CF2?Ez)$OF!Bl~w%8+%_#u2&a<$i|4JR9+! zsJ#YNXjY5baVGZ0?d{k44oz^OnszEAe|p^1*_C(A7d56vVJ?k0*70oE*x0=?EAco& z=YJ%^>}UVFtT%}Y2N!1fK%1KQ!|bzh0KJs=T|-kPz`(#i6Y#0>ynNN~CG(hb;L?d{ zeblfOZY#<^jqM*?ixBY`zGEe$|2XC_WJpHjMGf^6y*}TcUNew&#CEEwfj|hPUa6ZQ zaZF4aHq7T(5igQsrlsjr<riSUO0CDICQvIY(?Q<kBKpT+3p>k?*GJNMZFXogBVKT5 z+0Df7o%O>T>XsAvsMah?UZ1pr8`QkaY0U`9KI6Xs@Zo9C)v@G_hkaWok%?>cL3Z;A zwfX^8ieDT%?2YMaP_U^`L-h3LHO+6ThPuV<Fu5AIw_fsmRw}3cWxSA~%IIAxr}5Wh zldq*HdglB%nB&6$QK1*j{QkzAO2VN{TTZek%ENHt-fSo(aP<CyU*yInh7y)8<Vls~ zb?o@`8Cz%Eo~jdoMz3X+m3aXX7qF7;RbyhF;e|@Tq7_8D!ptq02+w)>ZR+4aL~FtF z8MMezw#X*Fs!d9qVX#6Q|B;e;5DL7l6?Q-L@OAKR1s4>>Ki_liT0KX4P}ht@-Vw1@ zzJZ6kyo2-b74c{lscl*q-?R#sQjN>X3L84*8aNK@f2OUYr=o^_<;j1uH|rpt0}|00 zlZV75t}v^YG@`W{SYG+{3H>Ti1Y=RMOv8wxGJZ(I!9If&r>{{(c5gU;v>i{k*tDHM zZ`)5{R}cG`O=omfrV#!q!5>_J7nIO1`9M{+P|}0zb@3HrQv;=uy5)ZN`4YxZM^|LL zu8GpQE1VDZD>Y8ArD$2Tk{lm=FR1A01-EUN++Zx17bKOOTC>4N9#r|7%n_>LpqISO z&Z^{dS)Bd$6O3P506+eO``cVS`&GY^wG77VO;ff=t~={~L`S5P-lB9bhoh1~>mXAc zLzK^@@Tb&W1{h&;^WzJ#+j~fv`k>zr14xxt`GAbF#4G)mVBdx21qppA<j?&p0FZi> zt+|?m#%MZhud9BK+rrA~ReC9ze&y(x`cB$PRQaGtPyCkscg%-o(Z2~DEl-#4?dKA| zXEIb;lJ-ziaX{blNM>p-F|eJ4PYpvfngU9^Hk3|LIcRn5#E!=;a3g7Me{&(?;#6@I z^}*W|DYYi-+4H<6e=COUS0dM%aQe+EP#|_*6$`LwU$ll}0&vtS_1g{ydN5!6Jhc1X ztS-4Pe;?+(BX(<n+p$r31AxtI2hdzK90IZ6^w^t|{FIOo98S^5YJ{_Q!yy1iidu=9 zI4yhW6#U4L{M@F!Y)(DR+`xM_E8SmA%}vTKCcQ!mcLnKT)T7mLrF<R|AO)H}$I+l* zw2)mj@wezm4}Od0(GaYko$B7>Ka^^#*s*Y~%P%fQtaC-5t8YWnsoxiKRU{)OP8*w8 zKx*iZ5)(sjvaN6UiUAH`Pj_Ku-$JZ`r1#QH+<r1Ms(d)$u9Dv=ayA=geJGNa8{(wO zLpU6IBxD8{h7?+V<zgq<O^tVmvD<hjlb5Upy9yBZqz4dl5)d^yrv*{A(U5Xz_PLX| zww{;A96Z&1;M11p{rhYg);RlIJB{4;>+bqTXgKYh>-P!8h~z{%z=|hse%WjyCfZ1R ztJF7dKH7s!;e$7GHzIVxwRjWm9haO;m_NWkbmWm|@!rfVg$xQTv54mkGy3eSeCdrO zgOv~F_oo^2xx4)XKi`4-e4l@+L^1S^dgMsCZQsa5aD^lONoE4l@^cvWbz{V|Rac-> zjrYh{H%a)X_e7~ge;;?54lwiOwhm3gGH52yP%NmQf6k=a7D3c|ceQWRR)O!gM!zxV zH(8OD06Si1-5$tBX+*(_*h7~_Cf>lM7%U~5!44+M^g9CEI9%hq)zC_=MR#qhc15#$ zW`{1kjr!zFq(xrEE|wbHe5dR49@D3P@mm+;APPh@CO@AOiK=gVyf2RVDmbK!F!}<w zaowRNf6n9%BQUI@h1b=3gpRDi0<{dqCFWi#^s15@9LZFPc$(XlC3mB)pim17i{0~c zw-&Nk;cF}~ZP71h$-ZPo^y5k~iFR~8MkaOKbs#c%Yo6sOP;UbZb6@dZ*;Nr3n|d;< zBLJZkpkvs91<S6Kv%HZROnZSdMz52@rIDi%CPpJ)QBe3bx32C)vX(|R?mbZn@jTxr z8rgxLGSX&V+L9NdSZZpyC5&#r%R?*jY&S41^o23A7KX$2nN-V_(!-{A@cGK1ZfJ%Y zkZ`rm0tg0EP)E%Z5T`)VI6)X9iPttYWP?rgtL+SG9zFetnDxpkEpZr137!Epc6w;M z=e@2z?P2Bg=19Ddb5V#hy{lh5UwcRN*3F=1lhmrgij`*7bn7oe&nPjqU@=QS<99E8 zt;N3Dctb8d(_@alMjU0$>$0j$_aU%h(-wTcJXQ8nN}tD8$zx(*=){c`jRf5@nqS)U zuB{#c-in^h<1mL$>h+HgVD6|{S!W;Tj)d2iLog(z<*3<O_3hgzL<4_7__iQIZ#42> z_Z(p6EMdOm`B7vQKems#=ZE;W>x=!04ffeD+tTTv(`YW6ip8*il6@Oz7Klt7ElNN@ zi6uZ*!Bm3|e7l(y$cy+d;)h(Ga8;rWTNCD8ZB^zp>llBFmHhS0hsNrzYc^-N;ldeq zby6l1u!PFT4CO&vt%dN&A9e&stQ#UW`EIRz^r{PaLKlcn7Z~w@3OuGNFVO8aJ~I6Z zDY4-CS@v1Lj+N&;aEVLtm1}xuhMaS}T|dYKX-QyS8qp<#DR)oaF<*L?cJ8cLrF8UW zcyug%$>$Pf$Ee`{-6w>+VuSb0z-pi%?|f-<%61+wF0X9h6mwH}_V{!ix|%$;GDk|g z?Are#Ejsj^Iq;D>#ze<s1ODornHe1iCx?PTu>0_+wZf9W&;WpG_lMrM_n3Y@H7>>T zYY+%Dvz9t0Y<8#jVJ4I(E6xu7dTX0u7+;3h<2Yk<Cwz7*l$oiD0hQ)OO6#O6nK%NB zy`g?jXj3N$MXzNTsbvYNf8^mKy}<?#S9w<W%(wSgY1Ngo9C6ZF1T%ZwaE*5Xu#N-% zi~FrroS+|Tdec4LINvkrV?WzjA;0?%@rSAa!F4rx#N-rQ8NB>wN_@-u`5W8RroReE zcpa=h1tKfgbPDM7?tVN{EXm^0>^@Mg4*6V0v82(R;L9?n!g6^1hGjour|CU(OEGfi zrC?o?e$GUW+&n+NK!xz@zzoR7kpXey6tHo5zvyIf{M@(5F0Xf_=Bo3(E)KlU7`wCY zFS#%TciC|B^G!jdmd9>)tI4cg`+e$JyFoitBpcJMWoe4fc-X3Xwd>}fSNLK%+&<aY z+=@A^WUnmdBSk6nbQq&zCq0`y-Fl<1fS{-(($Ck+{n}k`wmQEaBdq{5kd*j@e+lpR z2s3;|Y9U|`VuX`{Xj!Sy#Qb+vS4cpq6@HrfXs|a-V51>ha)BcpzR!(%MG>^=4N(3( zwy?&U*-=2iuPJN;<2ACuuVU)@xzVjahGA{&l1fb_$8&p1gWAOz<vR7%kVLBk!{;>r zi14`^(_yD2!6F;G2nBmQ!lIB?UmIt){QbVIW_5`4NbPDl8Z)1*%q>SU(>8*Y&ah~G zJ7*4H=jzCF$`)?>YxA`XZS$`jfrs7w$HT_U>g$t}`|o~QdJs10`*C@i5Svn#|KZRh zPv#?q=*TWsP6;EA-J*rtGsm?m*wGv{=0*{9EE_jQ#|mM>9^;#SYkgU0Bqt)qi)lwd zGvQuuv&-Kjy~BU0;ho%I365jI-+>=LB~|^%kDY7ATZ*uJy)VR#{9bZQPJ)hqi{z}t zX=$oDD~1-)UY+3u(<jw`Grg<#P6)kxj(OWg9ikc39aO4gC=o#>6G9{h!Z*^c$VHFQ z4Gq`M-^j#EIQ0#3b5jgPdgUP$4L>gH<@#pvIofsm9m%NjWPl#WfbbIEV~q*$_eoy% zsmUF)j(r{`r2&D4B*_Nk<%YTjD6u1xD)VN4Hr+`wSk|&O@T2$46>cS>XcxUp5R<1- zTB{X$=<%UceOqZO_5^(I%bI?Fb4IU7ymL#4S!)|EPkUJY!t)C#-J)NcP{!<n;(xOD zlYT6%XeOnWj(*gb;k7n1EFww4!TtVWt>;n0s`5G;ea7$fW!~s}=(KTH59T818F}S7 zbZe3Hg8kBm^5qywLFV8t6^wFBR5^!>K4l;ZIlE!!OFb5J&khq%H{Uoo1#T6SejD~y z_5|u8B>W(covm`~2(0(wy1T{Ko?!{vzaaiL{7yy42?y!d9x>Cr|Bxi)@Stq<tfZyH z6Rwi6tJ3)5ptS@c8`Z**!OH%>Jj=0Q(gz0J;^bkf$WIqDXc_G4fUz%j?Oq!XXlS2y z+;FUxolzvG*(h)45Yf(E`+eYA`^;rH!5+CHm3iaz2-SxDlID>vyhTA3DgK~pkkK~8 zI_vmT^CYHpK|S#ESs$JJRwA0NUt@0iQ<w(6?n5$zx?2nY!L(n!9~>~hXx1iwAqTEC z)Osu@@DbBpdaa3PxGy)Eg=6!6W8OGlSqzF7@jYCZXO)OOQ#kPTSjtMVX|N9?l!)9L zaQptS+uBmdhNVIo5->ULTk2Ta3*8ZsU6=82OU!kg)@@|;-xld4FPi;R!L&xZYt_RX zHw{jpXmZIiJ7ue&5oz4&<oWIH%9ZmMbq&r(4~jw;5Yc^jsY_<BODVl*#;4kLoDhR6 zJ@{;bi3grgiNs-z5><($a&_lSz^r2CNKf&Semx$6bX=!9dYmJMn63xA2V7Q%B*d=~ zHF(y&ZVP20e-0zM@paw28SWDuP%MY4p+mo3Z9Wa-u1E7phS(MXZj|AOO-uSU;MdoP z`5drpc$jYQ1BxAe?ym?f?Cqt!yqb$0zr#Yevcq#FkT%+pDPGIV%j=#OmoP#D=USKB zY|jSVP9uKQx0uwq3755651U9u*sd%6VbmV%keDp-Jmj{C_}d<zD$GgvH`Et>sXz*e zndkXZ{lTR?{dBLfd5~tpD*E%3=NK;WLd#bx*ZS#2?y^O;ld6e7Xn?rSmja<f?b&`E zm?~<)XYXY7KEM@DNLZr>jZhnF5Qs-^tG}u_l*pO#yJ)M-(mSt-1Ao#5mY0it)Y%p3 za@G#$=0f>8-x(l;A`wLs{fC8Gkj3q2Z!egFtIX<yGE^0}6EoeFRB$2#cOH?wBvG$k zR@$<i|KRg)b{Q*NY}Iul{qNt=z=k0Na`E5E!nH}|2XiY@KYz$zl5e<4Y^IeJsaXo2 z5%m75A^B*PI(EJAGm}ZXs4_^G9o}@9Gpf_XQn^TUL#4!0QTx*zP+-lTNt5rnFxF}Y zmo~#3uo*GlZ1SRDbF24BqfRa|RPZJoo}dMnKw5x#<mnuz(<4d8%`$oDE042U1;r>8 zt2a65a1rst9dn}%4c;qi^Fx8)0)b}D5SSi?QRW$T*O2J$p($bqU2T@beRtxQLNp>M zEw@imq|uWd-WfCdPrZ^V@1#iXYw$hnMs>#NEGIYoQ9nl`zx5d{L+}M%`u@x;$^3ol zfCX8f-5h+{2e3bk0paxJFNz`L(&c=YJQaczke4TZd!;<OUjEPu?!rCy8e(*T>s(qU zud!|DcYx(GFbqi8>IpCC+JR7b?c|_iU&C3RL|a?0YQC%rX5%nt3%+C1hx?-IjMZ9^ zgN+hAX3}A!QF2(vZS)(a9O9y*Ro$7Cifpb#Ny^{0I>ZvhS@<MoQNL^DJ-#@HMcXEP zHDi}Q(YdfS0UG6;XYdDxr@;M({`d-IWgT-Ijh-rjA_bVYkF!^IMCSreYx;8odH+Ts zn0V`UZBZ^z@V3is{-`!jE}S5rX5^<=V48ZMzSfa&7Rc~9Qa39A4-Fohoy_O3>(MHB zJltVAZjp6Jsj7aO&rK0eqS5s_lH%JQpgx@990e<0`gBFQlOkZH!T-$^Lz>zCFY`*f zS2c@h!-`BG!dtQno;D7YQhg4&^Z|a`?+NAV$<^A))%XH|P4<BcUtGdxxG36?HA~9X zl3NtT(#@_m6Nw=TjZvysBg`T329b**5;>*%m)i}UZ}q|ohDG5oJs-SfaDdP(1A4L4 z2H|}9eSvb%#PCYn&T%Ndr=*~Z_~((hq$C6!oyY;$j!TA!df(i{lw2Z`%j!t1TB}<G z;=E<?*_=2f<n~A&e<yt-Tj<oXQ(4D_RDiEttux9*_eG0OP3H@f4R7Z1qKRCN2YJaU z>cq{{))RaxDmg!iaEw<g?Y>p6J8nQl0cjMGrIqbJci9xCJ8JPpAO6N(8t)6WUQP@a z*;}yLz+NT~R@u6~o?JJ8+nEhu8OA9|qv2|%eJW!u?q~#OsulE2V|^5$@2_>}k$KNW zd6C`H@qrAWUx{f~NoW^~tX_&ZpGt(hn7n_H_x{fK5h9AEJ66go(`l7C5MYGVc(7&k zO04d3KY7^!`WdVLu~hoCwYl5+HK4(bGi{bd-1>^+iL3JGRxIdpl9z|h_IP9Q#&;B1 z_0@qFlG=V0UkJ~oyo^L2|9P$IubGMLS1yrjDZq?c8W8b8ycgi`5P-wi43c#WWvj(k z6>U3xvn@QfNzuw)oX<6%EOVe!B&8<v>*`WE{8_!+8!d!7o3yI$2ceP`Mt`(_<Bbgy z#l=2*W~p97{hW#lHJf>`@iGtX=-1oPG&0ot>u&kR!)~;=q$D#phJtt+6nauobZH7t zgyn}-iQAj<2gxOUtx2xhhF%`HUAGpK<~uzXIFJemI4YGT##bx+iH4uK@aFX51c;37 zmQrs=Mu)?C$Zgy=t6%^?eM-ng1YsRRCZ^(z&dyk?mx%TZYZ&=q@8+vBtVn8S^Kb5K z6OrMa`YNch`+Td(@6pt)8(M^AoCQ{0_#iS4c<7Rj<6?LU0%T`{W_j;>-ncXn#Eo%# z5SOl5mc5pk$0WNq8yo=hCTe=RO`-6V@C;3my$noVG0!u3Njz$BE~PBq2X~g?3yfsp zJ-F(a?3I>7mG6~%mI@i-ya&ECBks5e)k$JjSX;)k@@zM1y<Jc8FsPFXr|(M$O|~Jl zaExkHOZ0~C)cDN&KpXj${J0Lw*@qlBF0Xo%SYaMYoKAG~k15<cCb}MLh-TsOSfm)p zFWWAuGCZ#>FAu^wk5({6B;PtaOTwJ$nx0EK8D#S`fdCn7!`p>>f8`nk3=jRCvn#`D z&DAQH;GMU5dG-=)HsA8mfotTpNK)@9*9#cRj)v9Dj%+WlcU8T=K>ge9$<IHhsuR_> zseZcuKD<@qb2%*wN$=ZAvCW)_xua?8vDQzDHis=~V}Go~H~K!4`DKfGFk{?JZ(xaw z5q8!21wWjxgq2vTFr!u$e)u2`1a?(CAcL-@tl=DUzCEbjXgd>_*z07O#QWl9{`q&h z%OZDS0#hoV^*OwC{oiLA#M!clD>jjLy@^<zn4h8jG0~&1YOP8!Vy{?f0i}SAt(yEg z`dJJ%b(qnTz{xD9@AhAF$DhT8&zT-`VQ^l*evR~~$m#m5A*P)CPQJ95>DO$r^BuUD z<wCb*DQAynD{5Q1L^V`~fN&V-bongZ>pEZ~?Ld{JFZQ%U2*j-CIlxIoGswTP9Z&c~ zqZ7w(igS#ShUERK<3oKe1BcVMnz6a5prjd|UuNce?&+r!!DA0YEmf}P&W8;%QY7bg z==e;zUJJm-^(}K_x8QWOBy@Wnnk!BkMvM#eNJ<vdoXHVJtQT=ZS{t9c!iL-H-}Fyr zTaUfDpft7&jY$`s$)OuCxivHKF>Bn0Uba$+U<zchq;8zuf~Plrrk}W8GX?DUd)fF9 zdDf=6T{Z|pX@G(Mo@-5yjEs6IK48*0?$6iJJoY|!Y~-PhNUN$EHC$NR+C|8pRTdC& z!fQ{1eG*FYen`L6&=sWe8x-RI$+VU-Z?okR=EE3Mi&t`O$hp7KD)Kn7d*^?Ll+b~# zl94))%?BU+(i5+(P@l;0*gZMAmTS&Ny>S7STarnkGgAgV72I>v<V4F`m~AIMFGfWQ z%1-#k+>^&prOgZ+B=C+ZrUhJJPjo5E=P|UkDfRy>nNk#Jt9#uaoLzKyIUMud<79Tb z@$4=7J%a2#wDaNTnUc=pGh0A0A=&R<z(Y<-C3Ryc)X?h3L9_~9a!7?4P8>G%-!;eX zQ_Zs_JUyG{jc97Sf|1t3b}D*r>>rT*{r@7~u9q-5j{Q-MyO4c-<tx%?+<JcSvYGsf zy9%PR6@Pd~K$KmfdbmVDR98_!KdWV$<6qIK8tjrG^rq*J@pDd-hqL?^;@QI)HRJwP zf8!0Ehwv~8GwDU8M*5nq3yGsCCbrA<eib%HB<7L3QdjEF37-)u&&$>piR8U7<dj;; zzkNM9U;b27IVTF|^ZZRo10xL;#}gefT%y&ZCgOY7Cd4GXJrRyl-JD}veC3SX91XYQ zY*Q4tTkD9h4xeO?AKg~GD(cj1WqkFcCliWC-n)M2mzGg663G2-BjXEuP!>N2BgH(; z4ew~+-UqNeJv|$bBL|NfIy#Kq7$5=O`%Q%Qtw#c7Gv8(8=ow|>*^Dn8qMwP7YUukB zwd%8i%(1BK*|Od+bdtj^WX=r&d2es;xeLdufS+_kpA~V00>}2>rhphqBZo$(^V{fG zUnM01kfRFQo4*s(!qDgXBgok$KD)Ni3RNuK>Uyh(?KXq}!QnuPme^0(h@0`&96DdG zf&l?$Z2$Z@J(F_>V1?&S<WxNV%ok~$Qb?TZ7}R&i?E$5U99UH%!~a>;#Ac~8(P=c@ z)38Y70wz8yk7JP$0ss~aEG~sGc2-_*!xRO=@cZ3(x-yP0Meb=y5HZL|VZPrvixmM0 z1oHGkoJWNPjc_{UJMJ(l+pmeiB?B73kiG+kl#bMg?eXjWv2)}SzTX?3nOowjuUg`2 z2_diDEjR@@_dvdC%zYDd<mD!UOngYtt?nhq#M;?)4jP#_VU;GcgSHD-*)2|;s9%Jb zcMUscLHH+I3{y-|XcID-wFm4s{Es0SX<rjuT|3Ng921xxEg7o)Il#|&So2D?DQhgL zUoNB>jt+hF(g8s)pkzP2`u}FKfve;P=HhK}7#c6CuBh6pq{-b6-8DW5G05#>RXw(D zG<r8a!JY5Jd+lyMpFz`gHqs&YP6;vTT!=Hze%FOU+CNOD^+`%5K6~wOX8_I#Tu&H! z54a>JU{oaC<Z(|(Q+VT;^vCo9T^{TaS#xktkH={>{YJBL!%ZhVX)~k*79_huR*rLu z6$WR6I>ssu$kykqEUk|4fYSo+CxP43XsUN-{^RO3O*?*LE@Jg%;=f2;n7@TnV9alS z*lEwiKsMD1Ye`37gWxIg<LZc9<x}32S87JYAN4=`#zIA93{4qeD~DU{MHJXi{gmgM zb8&pGO=e&-anxdhr$9n0p>%jOi<I0Mg~m0+j4M0dRNE?*Q}QZ@OO$8)C5-ez(z297 zvqrJMaboUWZ1VJzck~{{+5bS?B2M0w)144m2z=+qj&>pnze93x70NIMt)<OMI~nhy zhx6h^Y00)<hxM_{qas$P6=eS)dLW$?us&oMwYAQSJ^n0qjGN0&JEDX(JI8S&c5E8U zTYl1S;`*udev0J)0~vfu?MyihoFxXbt{pGn*7Ha`$~enM9p+B1J7+<C?%hmsC5T-< z42V5$=|7pS0!kE2CN`EFUx@N2R}uF!@{M+#$au+LnEcH7ZjH8g45hfuS<7Z}X^h`p z*k~CRkUKHqOf}TcfQcS_b4loIeD;yTXAtC*Ia0%|lKMSbzl~^8ejIb~$s)H7N%Of7 z2xwX7xaZ2dTF$#7X7>_S?N(S<hd-<5PrbcEvfgg5h^CL`4HZ+X3HkY&$hLiKKRum5 z;re`-ph}uge7B_d`^<qz&pG}{&Q;qd+mPok)J@S-qZipH4M&;S1xX<RJx0NUdtsvo z(rGn21OZwS7_XMTVdgKJ?=>IfEhGJ>c<WQw{{hN7(1o$<EVlAarsq2qS+ZiH<E09} znXR9M+AJfR_vaX1zlrf(Ufv{`VHR9I^SmQixh?)>^+?9la0V*bENS_7Q|QhjYC--# zE6U)x<k546k^o|~I_ueuf^`32LW4^*ki9&NL2u+KM84>AVqfL-+v@H4L2`y>qw4E& zrdl-HLVUp0{sAQ-ljQRvYS|<p3!pFQeRh``+1)~=a4JAH{P{7jMvC%t_;7Z7%^Kz* z5E1_z7=nY>-)9myoy#*w093CH#Efe91GgQ6Vn`KSZiSUnC*D7wfKy4ulaw@z%KV@p z@ne>Fg#5+E95x3ML0=`#0tqC^e&(oGfGpb<Z!BJj;!>hqOs`bTD5-jM?Ra=on4Npy zuyoU?w@;*?1S#+%i|l<62+HTKe}D1o2Z6{of7nx^AP{;$A8xmH%)-CH@}%S)dOq^5 zg?5OH(m2oykz?Am?Ya5X8RlBD^Bp6*r{C5Mh-L2@*4Z1q{v~hXnP#n8_lw#_=N_@t zH~$yIZY)^GIDQK#4L^JM7QR#<jjW1VISjUN;w4cpkb|5j`m!YH4zs7gfcVS}OgM^R zWMJvaTcf4an`kplJB`nV9O@1tw{>BJ?Mqt-#p(3aiCZP?-+4sL7G^Mn9@=8II%e60 zq`QxTX%)6vjV!98PoJ14yS*mttfvc{h9M-`O|VzWb+$R%roSV?X#d56Uyrqk9r9My z+Kp*9UF6N$JFMxb+5<h`C4;C_P5FA1jECz$gVTL|P%O94e%W+C%1FjJ8#deCQknu& z6lp)W)C_gXf%FJ%x{g>r-&Ri>-hBdw9qqb-KD!Z&X_nX2)Vr(Vrqk%a?sqk4eFzdT ztH@6E7Zw&AcFG$zKq|H3$DV@|(nI@DBA|uH)(6l=5{J&%{+?_713y)9g(SX(=<%I~ zC>6e+`Xa~DfdG?7FfC3K4^dmDvI#-Q4ZHPBP4&PTri=zcQQ*vRJ53wI+Ts&m(*z`_ ziXmH_3nTMBhs&_x;X<>~d>QZ?l4GPB7{cC0b2^%!5)Y4ODmUN)NmW9@V0wOVM)L%_ zY}@q;L03O#o~0@uac+U8Dp!B?#wxI$MrW2+x13VRPp05P&inZ#Yg$UepS84?Iq)C# z6gu~K;7B*<VWo%<p*_1PEfc@J>!TVy6mTC=G6bmG8_VAQu`s(9fQtn#-R3VEFXIOf zC!$z${2$)b^swvM+OpU+|0VEg+4ZiG2rO_TefFaY{?6GIRBt+H=fm7~>Nyhqujq(> z`hT#K5YDiXmlzqK{>16USVrV&7LH3G8y|p0PtRnj6}DT`=GQ_Aqokq&L?1(pUkTx5 zu}Cdvzp0!R5c|1s1e6xw1pMp{uA6FNon#jtE++IvWp3{6R$#8xD<k`}uDY52^D>#Y zO@oaB^U@mZdpd!+17h|08|C8jN(~Pzu1EbN{?otjF<n;nvl5gJNY*ZHmtl%gPAUli z2xDjZEm(S7WL{LA!VW;8V(_Dh7^)fR8f0w?c=47loh-(3ra~`#r=kV!vzpEj1|sCS z3mFgMpLE=^^I`d@_RlKbdj#N7k*sEYNis5(v8#WditoSbr?j5SjblNo{~kq6iSWgj z^%kSENPR|pc1*tk{ck93m`&`5B6<^G<-x0Y%96vWa^=SjjT~+9$<4r<e%S7{=Yg$U z=B?d<?Lm6t(%pqpeE$t?_{EYRFUs=W`O*)bz&7$(xU9ncFa>6gxZi)gC^Bhv1*7a& zeBIBTH7@3F&X?#MB^KTJ{LyGD^fJ^(2&k#@rcA0e4?E#6Hl~Qo#njYldj94V7ZYt6 zII!P4j4m}E|76Nxh@7YF{fGsvG4qXv`QNmJc<Gh!R&>@8D#GlY%xG>a%o2w^(FOf7 zFuT6nf1kLC5q|_~%l2IHZ7T@{J5^fZ>8>waHkJv`@I^TQe`^W>%L<;cNLqg1C^f4z zaS#g!TQ!nc#OK+5)0W+$|AT~C_(X9yx!+UJa<xkWQ#c?#eoA?Qi<^7nh(4=R@SxS+ zjp62~fmbT?7QZ>H&cHvq9Bn!5OY=vRvhYvL>ZX{&cugh+T}f|k-1x%AxX?kmxD^VE zZ%#c)gIiOnU8xZaSj8WYhYiS7A<1&G+9Cwt$L*1?$-2?39T`zlQAwaOq7W2o1{^4* z1$rOc36BWuC}@f+;LzeyB5V$)hkM^Uh`Q|-@d#!pUHP;Z?HlN|6R)&CP-$D$Qw_e1 z8=>XtHkKWIwg0DhfZP)g&%1ek?b**Q%nDZ9hENBUCxK$t<wiH^z8N3H0J5AC6a=+$ zR8$fu<JD&sV*S56Puu+V$C8?G_3HSSZw`>J4=Olf^vZ=7uS6~omi4G=YU;<m9~h_H zen1T029R!Ltsrsb{Gi5Y-FMW0p;u2kHAXBHEpWMCG{`ixDGS;fth*S{P*HJY^cr_j zV~U0(C}qLL_M5ozWm-8mIrL|`Z!BFb_b<6GMWEo)rI5uNfgTPa=2>^tB3HjSL9x~w z?KIB3n_@rKB>!818P<E7iwIw_1PGIkXn4047Z#XpN|RLtnQvgi+1Hk@nl`H3JN&9E zEd@`-ToSO)&8nr`bb(Kj2Jq!E=$^x<Wlj<M@M8*ou>&Ug{#nG#-95QflU32qM3}e1 z^As^r6%Nh`NhYk{8y{7ne2KQ<UIu!xK7s&-|9G@Fw@34Z4ohbpJc5ZYLAN%i4Brt% zzKv+2#{C6rcBfxYY9u1(&i7zP*E<j0gZ|#YdW#=}He^)0H@kC(xJj*dgtfe`Wphst z7fa;hnW>$}B!7{+kdjKl1OH#Zr5N776Fg}YPAVSM(q>hcdo#+w$nD}SDJhKq$RY!P zjZ=R^3zjRgGC@fIn^)H#UEkx#9&Fn3SdnW43g1%{CDFTgx_<LtQ`n5eWq#yKs;H~S zxUcwPR^Fa)|B>Yw++7yEr3gbOgZe+Ot!EIQtuj7O*AzYoRx)=k@p3RWuC+!jB<{_M z$@nBqX@2@nbHaHDgZ`y9Y~gu`nAvL!+j5=3WTNJWpstOlOXS$9%7A@)wA0wMWQG56 zUh5l4I(B`^Od3W<>-Iw!v^3!KMrzfF^ro=qJN~65G+C(KP*G7abkn?XY+2H*wP0WN z+|nD$y!br77V^F?I>E6QKRMjzrasJy*=K`jO2h8Yu^Sv&71Q|ZWa11&Usbk!4^xa( zs3J|jBoZ~a$Dwi2Zf>tWZb7uAp)$PEG2Q4U86Rx|P5vqDaeR--2>*;PbAmLf5U8A^ zh7GWzp-JWSUFVVh^F2ZEc&4T5chM_LXWo#`$KV22nGY_3URhi=!t+Pw=B8Ph<`Ffx z`7<2T+%M$Zt--Qd((3yMBah2m<Xi?+m$n;j?}qXlIJ6ZHB)^7I7!0YFJPVRUgZDJ^ z!$gm=^nH#a*$joM8h&8sh`*q}x*E47W1j?Nh?s;4Cj`ZFex7ov&~9Eq!o(0H%u#JT zW@`NRmDm{>6?L>N`Vhl8Du78I+Yj!CIG;CnJ_KJ71l*L#SW$A5KJt*Yp0M06Ul0hQ zjwBMrpG-|p=a!X`mTFY?<@L%}IjkA?T;M8SU3q$3eI*3xP`I~JyeDhwzE>iCx4ViT zuo4pC^q^zDZ}_Jfc#yA2h0wo-kBDi%+QP*H$|87YjKp-za*@GtLqJyu2eHr+OUDn3 zn&^tdPl^~pYNBDC+e4O(ehb#}f?`-7+vT4c^ndon|K=Ucy=oANh!5ZW(FLL7kFOeO zWODCj%3%SnJLk1j^{~AZkO>Gv_Q;8eH>WROzP7W&aB@D0OWF*X{2S7<HfJvwC<Y;q zMFwvc78a0wBc`V(TyL`!2|8i>fCC7wweCB~?M(#cMfCoj<ND&DUHr`~7qjQh=-lO< zhS6S6wh#Yc5ua0}ir1f~i3%AQQPj0(b{Ah6IPiKgb|+tIJ*jTd)<iElY}PxhZ-7&$ zr{O>PSw@nsvwH6FDQoko<(`56B*v8QNqa84=C0CdrblZojOPEW_@nWpl7mW<IwEBG zZ9Cqc$FvM#^s<3;f+zx(E`WEz5y-v!eI>fS8r<)Gsb`MZ30FySa)0#1icvkh4O0)2 z21&#-u%s@0U^o@sb-{}f!iy(OKl7!P4H`BJ9X3ORn3|hI|DZz-YkBhO>;zlw2;Zq8 z<B=qu>JIRj6Y4~xQz8(jX@k+Oy3BpbPM_TKojNzOx!d*pQ!+ZH8J6u4nhT?*+Wz|= zuk)Yr;%sGkV*vDh?{ENb7B231yvwP){v|<a``oSlTz$xM4bx(woqydIkxNXr3)@6i zRYhpiB9YvU_}leUc5VW5b@B`?&zrmDEvr{L65Op7>fjtckqtB*4WSh#SvtRo2`I39 ztX=_8mRB0CC;w9A4T(j0|IGX-<tj&gvxsm9FA|w&!9NrE_s!u>#v}AFrs`#ad;B53 z_kFS+s^X->13YFr8EWsG1m<#h&8P@CTunN}hgSxEvGvzvs(Y+C@(y3d1Ul<aZB8?N zaIVRmP;H2SI6O(~{hDW&=!V{?E&$W^OmNlCGH7Khln$bqS@mU0{7o75-r&YrUT!gB za|JaMCp^Da>e6yyn-#a)kUxG}rEs1v`G+!1hs!f%l4iw!0{q8OeTY|hC16gCg^jJ} z*!$bTTgc=1hdF4=V*Cr#Sa*XFd##elbU9PG%jZ-6FnI1d12@7z9&jI?8M9v9FIF#^ zM5BloIUSR+3?Db?Ef&6lMme_pF6z8Mz+>s9MF~c(CS~Dov1<4Bn92f63oFY|*hVPx zAOqt-uu1k=)Wz54G?j}xX^W+*siN@ObQ)Q{Uxb)FpFZ1P)<=Bs68I0W`M^+&=OU5? zY8IyQ0oSur*+QU|n%cO9d67<rLA1LTe$Y=#Xt21q_pXD`*`QtY+pkKRu1{Hr(ys|7 zz8%LUWro+5kxsGRV2RTh;aAb*I$WA2lKUYYBgL=_0?1B-Lgd*N_i5I;qvL9^++kXy zXTvIV<sdxZ=~7yZfCi))OGeq5ie3;+j?ntKw>59B=bm`2x({+LQgp0=I@?v`jS8D- z>lzH8pZ|{cpJ|P!k!?JkkdI4G4<_-yBdO`348FZ;GIzZGTj=U7h|<{{N<rOHh4~Hb z1_H6M{2OOVr0z{@Dit`rA26H>=dFzdepw~RxjHbgka{^BHYE#na6A*>Qm<gYHtLP; z-IvTp>CZo{nglu}08Jr=%7Z~|T%|n+@6>|lbVFUDkme79Dm~F|OHlP@bFbP|+Flk_ z&|MNY016OedI_iI(#BGYZ#}H=lj=L-8ec5zGnfB>iU0VO>bJ_m_*z=?jhhQ3AhB%- zBb>?<Alr+MwhusmCO-D1%XErZb37$?cX>k-klEDBAiT?Un#zVw;GH(Vmh!Sn<7Phq zV^{kpe~$bU0vDaQS#K;ie0O<)oP*Z30<=q=oi+PKBvU+U&W>m8eJmE0FjRZ%d?R+b z_>gwoLX$<$2J!gDGBi-D#r`kX@he7PTgK<ItEKTiEWOHd(yXQ@m+fp{FFM)anyD{_ z%-W6N53dpN%-sREg<s`-t_!34>a&0BPjrg0CQh})ajgWE+CnCqnybsL=a%g|+sf>V z=8pyNX;1nJcLM59E}Ea*mk(yU+qoa`K_JHFP7Mi~`Lk$o-f*F~Y{py;9{#kAnD&CY zbvoy_rLdqR+uw(^QwN?^OI33j4CKxT7y^6Rnv)zKp8^RRBLFZG|9$1*u^E4V()s{$ zST|x;jFxYKWF$eE#$^f3dN|1*YXN=LCEy_7f3mMu5fy13wu4+$x)<tm;pFf)ugoEy z@Tw?=8%c)7_)q9G&f0K_w@0!OzX*#S+}*VK72HiXozu9L$GH4TiV?H>`vIe2oEzVE z`g4)~33?jiZ1<!t^7Jgm6R~PR!_fgLr4FOVIRYjx=0f5*)%MZ9Ehsi9K=b(fmGH1o zR5+Ya|2BPoO@;Sm<ErkW`vC>e3N=}x!^zz#>&sKjEpAq1o=CsE4OR~IKm37pp0UcB zu7F-FZE-9E_{Mqvh(AlFy+OP2T>~$ToRUEt=z4^$^gj?F`J>OQW^F|9pwqhYo(#Bg zFddmdhVVE~r9ZkfiKWv$CWMrYJdGB-Q1ATWs$I9(b*RupW?R^fv{DpxPUHV#)AU8k zrLB#51Q)g{hY8|;;LxL6MoklNWfZwHB>=$>=B3lV57;A_7{tP;{<j;G&jehGz_uv1 z_--1_cZ6DYvtoTTpG!ln;`HoRVl+UVO+e&^D}@Rfw+NCW6Tl4Wy=dH4Ue9}y$U>Q& zctzo>7+U-Ysu;b`XV=U<w?4YxwI)c--&t##R@1k)nJn#WEnU<wJO{aY{{xVZBZ_2v zxgVOW?*(_zb|JFwziI>&`5KAsad2s-_97t8WF9L7662l<?~7ZAVE)|fz^(CpVl4oL zR}SH^L5dqk;|M|-!ibnsiZ47~7M1s2z(2Ti?w7P8{4wc^Tb#N4dROU-Te6TMqBtSM z831b8sQ+#}ImWBMFZjA&1B5L>5QRvn=Rz4HaLpie{l_Fl_{JHG!4ar+Vf_@|2pj#e zU<_3s`K}oGoV|_Cq*=vg-}Th*46wX@=ouCJ5n`!g6O-97{S+o5B~1uw`9Wm=nEd$o zd@?Cc`I4$}q==kgc~J`OWl`?0lednpwz4;xckDR?GsriZt^Ff(?3xgj3iEGB=!@>d zvw{{U)-M0vZH=|MO1y(PZQ`5E$##gXeRvV4ply=UOdk?}6;ug6JRT6y|M)5JttcGi ztkY+@#LpX@GW1jU`@Es|cmJ`?`AmBGl(hcgl$(*DH5{Bt$`y@j{<x%Bk{+dIV$b0I zUN$+<VGNA{^g#dt58%)K?^u#|@40Q{Yf*qw)!5^;aL(}tdjmYe3l71=BB0*^E<DHd zmfd2h8hg4lImhvYxOVzoH*BHm#w~I>?6li&;IAM;Q*a-(|DW$|3qo(djfG+$I$iM6 zfG8L=M)}8*{<8tl5TKW*lk*;%^P)zBN#($o=eJ(Xz&sA_9@b|&+ToIQeb|prPKGdk zU}?1>Q<h%jV055)=&IOY4E)S8GS3zTT&-zBe8q_?$d^>lXqWikIZDiP(d*A(ZSQ<h zm=&|Kc&$U{uLw#Y4|i)ujkc#OFZ-D)JAXTY0wM*?Od_)Qj_VOu(--_Gl${!&?HT{S zO>59hxlZ_CWh3gWt~314pW+6UpN$KLe|Ps_ipC@;iQpUf9KHWZFYT%bidiD#$F7KR zuxY9P<?r6e$jhT;`D|NexEx!8_$LBb4*Gh#r5FP}XJH`i2)uh|!zGxJGM*}=;AI1^ zD4Ce?Z^Hv8{>0~e{(<c-B;lwVjTJcd(A6l`Eu(7``i-lt2WSJ#7H|(Z;$q52s9RY9 zm6X`3PXF2&3_qr)rdE?y79)4;8&N=)7+_C~#$3rpg>FbkM7D%(FE?V%!cCs3#}pu` zJK|!~(*JAd@rhVa=k`k|eU=NO+3@w$t^)(=&Wvqms(EI(sOSUX<8keYNbCD<^z)z2 zFUQp>WRU+YE_UeXZ>O~g`mAn}2fx8xl>xC)ksDG1=1XE_(K7@ja4D-BAGXPF3+elF z^~*)uCmwoFJQlDI_wPp0Syn^0FT~G0bFUZ2pniW!D4GeL+?N%DpCNNs&K3y>Wic+0 z0OPt>>dXKg5TxTqPGj_1Nmu4>u-_Je>M1C+>j8Gw0Rcw^8uvw0hy|SU$IOTS4UIMx zorLFcQo;b`_J}w;kAE|<ZPar96DR^)4A!ISEb&+6_DSdD8)Ri`>f62Y!{)R#_l8c` z%+n6<E&qmw&e>(uT<e1G&kpO|FIRjm;V@q-3e#s%f}=_L@2E~v<j#c$(B2J)H;>qx zeQJ5X&vo{Jcvk-eZP5)@4tighh2wpDXZf&eYaLYh6=Q$%+Ay!-EBXHB>Vuc|HfG8@ zMY{b>uNvT!@}514Gyi=tpddiugdT1U4!5=p*aYz+^OGOWQF&|_dH_TT1Z~f2dQc)N z=ttA4{oF}(&tPNAn&=umZjHolIc-LQ3nZoP4Z2G2^))zM6obncz|bTmk^a4Ny6Woc z*7hH6g#Sa$P~r|fY+Glz-%DNItmuD_qm&rJD3rgh;5NaHF8m5-Tc>7Gz7$lyz*swN zFX7$ehR|wPBf*)Bbyzz?E!>bi{|O8GQ{caMwjnn+cjJCDN!5D)XYkkQ7HTay!It#7 z-8f)1`kDB`EZkYltn#7sTF9b!nN;C?=3Q=GJ*sV;&YL_v=dwl};>Qn@WB>QM77eHK zZu~6u3mi@_1yCJF%-WjdW&1DG*3)$Zhufn`Fygn(1RV%f+b21m-iX?6Hj*djA1#)v zvG+bsi$T?&({s2xXU<cCp?3XysAAyq>n=5o2UPCIVh<c#;4@76Nkejb!VEhD;28F& z(SUkAFg*MUq;X74Osu*H7}aTCv;bs(=+S!UA>`1cYhh{m%EW|vdwW|&O)c~|^5dmr zud;=6lY)n7_16+czpK)n!+!JZZY}dnOE*5UCzLt;3|A%A#M&jixt4=ST((P{rj>z0 z!)IpUVql^EOW%r9L1fI3UjeH(B~hkTgG6ZH#GjT9xZ+;6a0)*L4B=BO&;SZG7zsmC zRu;vEN9Q|iaA;`v_@KEWzquLd^XK$xw><%$4j=x_(FbDkSo(Eex_BM?7I^(^OhP@6 zK!COicKT>d+H4gq%Cy6;ZPQiTY?<m0EW!*DR+F4m3%^ntFowMykrs0j3r8$54M#$I z_rgQLvPwMRoYVl0FGm8y^MS|XxzXsxrw}A2P^;JSq=Li-TVy~bS1gq3whD!}?68Z< zN97A-*GrHl1%@Mtx5rZUxUk&+Uf8&IviBIId=OA&LrkZb7E*1}?~-1{oyI))XR?qN zGz$9IgCY1-!@w8+)=%`&U>|fC#Egn&2ZNM;irJKCw~M6<h*&pGV7}HvLp686nU3&f z?$5~VdabH9e)!H`nGcY;i$%BldX^O3DKw&)0eY<OY14Gn)T7W3hVN^?SjV~Gf7=hw z^EMh6uG-$KvfTSKeGWfS=fx+9HgQJBC&gr1<QVlCAGp!t@PD~cgleOnurEsY=d63- zQ7@YzZwtwT!EatANmMpQBc~6Cfd?_(ovVKAs{zvY)S0zFTVc-&VP=E&?%hKwCot?z zqXv3O!9NZ-oh2{VO6!RIO7Jx6)N<Mtp>Z>NchF`Gy(e>@zmqQzv}nJT51^3^un7!6 zBqkk;LwwM0V8M)Dsq|W))Lz3YmzgD5!()-b9Uhq4iKE<(`#MYYwlX*<fU>$-=bxj* z9dXAZ`#%RdB>|djA|~tkslB1|X9Ykv!+V6E?{f91N;BSkpxS<=o$ulH!~u|bd1Yl! zYeeo5DqD}WC+Z^F&*}x^Qd1)~VzbS(pEkc7(}TB=N}?R(FxBdwq_{eoPCH}@^G!q5 ziZ@iO`hj?ZT1ez(US8AohM@HgLE5i&<kppnFAfFz!3wJ3Hf_Y7*95<;bb914TIQi? z9~geqjLtv%pB-0?EUB#QXZ81Fv9huPI=LyRRBk*9+i{rDGS72ASO#hj=(xdVGskv& zehzaOuJntTuMzDrFz^7y#x~r7wQ+jxca=vo=?~qBFA@~z{mrL4;%W92uH|mjf*)FG zzqyTzC<g1PQZ?IC;ixjF?<P5|synIVKixa@MuDb!q5D}J8_U&G^ycBTP1pUYd>Q^# zV$U&dWiN=}P(pS!X#w~h@_+eLg<ozhj+2TFhIe5cH4-SYX0MU#u7)cemz%bz1O;Kc z4o{Ome-1@sZG`}RoX%|Y{wZ+N(l$%YOS@Igz(`ayoqIi2qO*fis>TC<4X9?)dj>(= z_IMgsFCEGNFAdXFW&3!V0I3fk2Tb<Ne(EMH#0$^3)Lk&_7p4SAJ^Sb?0O@3G9l&z^ z^YybyTr-~U^k)df-I;|04O7<^Fp)nVdmcH4y_bKc3VHe>P9>h2l9g;gHX-gak|{rp z49@DV>9_QL%tl}6ONy~g#BFUvD;NS}dVs4dlxYXiNBfon^S_Hj%c?i)2ne0^^sj?J z+|mL0`?I|I;Y<~c(0`&DT<7!5o$V}-brg`#`><YIm?f1y_})!Z&&tlOi+ff#+<oN^ z6F|R>W_u}B!?)trgRQl?QH{sk(~JQ<nmqi>`vH+$QLY^;$TY}lU;HfMZ;Ud}G-a?H zKB%7-TXcO2t&Rx&@L@d`#Zb<Yh`><WA7w+1CVH2}#DNv%@A*Le?^-ye^pM*jy^g<p z!K$-?K+r~?hL(an{3g}@ne(D<`u||zJiLoh4TE0LmSlF9t(p7oa>HR(uY>dJw<#M- zOUuUF<3WcBS^Bl6t@~)+6))IsT=TnXM_j)fnBdXzAZxc-l!3ef?e|}-kfA%Rj~=33 z2oBp%t^4z!&mfCdkiRo`xScn96gWa}cs9!})&?X@a8N-3;&a#b7ZGm6@w97GYd9E0 z3`Q;yPpvazoV1XT@Z_GUFsy~JciO6`Xwg^MB*e^HBPPxEZ<@Z;ZXl=Hh@_5A=f1i$ zCtlVf%rB1m?{R)%y4Ee_ak<t%jFB(T&p+?+YYo})=L>p@s!V%j)pzecNRxX$Da_=7 zcVD{mpKERUxf_RJaj#*pp*(s=<i32Q1EiU$Q5|Xu!DCBCjxr_qe0GhZ^1PnuiV~Tc z5D~WK`6VWvK;SlCq(BN1<E-IFNN7#2Wr*^x<zzwzu~AxZx=}~6p*Gfdm&WBW4eHx- zYdnGiV21O4)wQcb@`q!BK-?q%tGDeLZdkN(d#0DhzF~U1mbH?v!Achf?r_ZwU)|6G z01ae#*Udfv%!_;q;PA%k(FVKkHRu355r`$`tMe-qr+5}B@EX4}5E3~#Dben$XKhSS z33LEcFt9H?bOzni3GWriD0`NDrE%YW{w3RZ`~(ry+8Tlk#@VF5m-S)v>i?ZH;g6$R zJ((RXB#Mf|;PYRAHpIvjjf8~y9&o1or}gc^vY-+Vv?JFi_4<?Bc-P>b*CxzvezW2R zBLgu_tctd_6)0x()xo~H?hxCi4KPuI+f|2`!OVy9<@C~F0FexNbd})+*{nu4$rhu> zjTM>_X~N}?l{PKB)d3@pd&go#`z-UWaoPx#%KwQ3N5`@LtwFs}9iWk~(%BvinPS+7 zg3!PRJE3FgKOrEM$kiovG&y(ou7kkzrqd&pApRVSO)zn3Q>yyD@+AVaISUVERYkBM z%HrFap3P+b;|lUxXseCBUjm(Z5J%S;iWUCiE8O1yrb45`NW{&XcIN6!lDpgqCAd9d zMl?B2xElu(`qN|s^>G1<z>$dc*#0XD8Z;Ni@LxaDP&dzn)2vxSOjbMLJa)?cH>Tby zgUC^d<?dXt^?KXdEW8@_vt%G4TAxL;z$zJ66pnPe^DB99MybZ6;aj``qYBvFm0S`W zF7{Vcx_}oiPUVsHQ*u|Q2ZJJ3-f?=yMbEO<tlk%+awHU`rT!NUi*Etj3iL$~uojMp zK9IJaPM|R`Gjj<heo4&C{3v>Nq;<Pa_$WsdlKbw;mgzK%?6T#c<xu`S^S6zJz8Ly$ zMunSp#A!=yo6wdQ4}5suyH8%JTyihIAuMvq_91sv8E?z*|C)L6V;~P=uAF$Z_L(4q z?|CQ%!+$KED(2aCX(iBN7I)dso$p*by7NI_sKQB0kf=6nRkwce;Lf{$xd&q0iQ=1m z@6J>8G5NvTB4V^FF76i#qVQ|A0X%*yaC+e^L5zRNhHY*@A{-;wv?1JJ(}pK&JKR;H zPVAXU<BCdY;baNHf}{&yIMDT9G5^=#y5^Ua2~p~Zu3V?5JM@!vg!US<3nnH$ALIaZ zir1p&76>!GWdl4Eiz%96Y4!BLmqZULF!58}IV1^g=4_5ekNU+I%Zo?h{6Bx!<qm=9 zp?N3>RBY7XsK*BoZM<)FjzH{j_S$p?5cKht$QXhJYI_TZF-$}omfX<n+OOyaIKrQN zq>;s`=-6KfQGklx4wwKLht2lkH}^P;$BwER-{)T`Wmry#4o_zwGt^}@Gl;9kIG|S? z?cr_=j$8%0#~mpmFGXeNNSy<Fj!O3qc=T(-#}eFsUh&gGhz2GjgwDW{1wZB*b+jLa zC2Graf7+FU8h8)0K4wyY{%*H-2M=uTSJE&%ZpUqV%8}yCWd9#kUl~>f6Lot?rIiqn z5~QR-x)tf}E<x$;ZjkOy>F$ya1p!IvI;3>Rp}E8RefPP~J^%Ot%*>hCd+oK>j{DI2 zVp*%E^r1nD4c^^2b+ceo=Nb6NcpzOvF|zCkbYX5X7&IVF@{q1Wz{;}jj>Nfc1Ni^b zhl)s5_2m37PzZ=UE6Q|6eK<O7)wm`yilbbO;`0uFKgvH0=qj!|n?5<UwRDHKy3I^C zKXd6{2)A%Z()o%s%QBSuz;%`WKDLOpx=Uw!3JR3qMo($U{}52FPDwLvr}t|XWyXG4 znJ+;l<>l0z<|YRl@TZtT0`2tFsVM+XHUMtqP<^w-@pO7XarNZ)TP%lRC^ztdcirxO z#^SvH0c@>q;PFcg^YX6eZ@KW%^@FI8$9$<H!d0}CB#&t8FNNnG{v0H({I(^SzAQ>n z4S=z0VJHS{OJDN7@Ow8RnGM(-el2}Z{oD1D5{d0><G(K%Kv(jrs&_j-w!qiibbii$ z2g+NZjso~O?g@YX$nZaI36Tp3fcZP$jxHPl|F=lHB@<Cu$AJ;*Z2UPjq6A|zZPJe! zHKh<WN)%^JKfV{<6Ybw4;~AgU0C12>_2m=nVDC_INkhr`yz3)`GXDUn*?%9!+;pKw z`UH@t0R7V_|2^dmjG2Qkg0#fv@xgU>;ORLF;99<NS-dPT_gx^<{aiD>F4pnaOyN@v zzEqah&tmY-+V4BFU$+@TM~nL25P(`bU*Xbkb}soOyLEP|{CM(R)7{?&RR0%~qM{~8 z)O%QfK1~&{)SuI2x%vZ8%@l}gu%F=Gy58A?3!nDTw6wJ5eT(s%?dik|v)5Xlg6H<s za(GTI9|_MUjb^QQK#y7@M4-{q(EP<Y2I49}!ejeY)i=;=O^1^*&h6eDAu0MN>wggm zs@z0+_0`)W9~M4zh_Ip}xpn8gnnXsB4PZUn_5;<Qw|CYPQxZU0<<UZ+Lmgl5Uo72p zF3juxZd_QE$!#bbu7ohz@{Vs`e2jcE)K*T>5-0$|2oU^)wW5hhTn#&_J&3){frE`G zop>?MYyjEI(?{ylQRkz6oyhFLY6z*YwRPp3;R{~?8~{xF=xG5uAMf$5JUf5|5`Wl* zj}v+I)KsuH;Xs446D<zY=LTdJ$gD9Ek29Y+|6%n}t2_OFC?b<vp^Tywcbi7f5{>p7 znyyI%)n|>9XqMJ5W+!N?3kZvyP$pY}%ZG2{jGI}o>PN%Z3UMgs!?9yR`aNCnC<tg& z8f!Yg_c0(?-nnb>kune1|FadSa+8u?-EAGX3}YfdY$p}PSFYBJQb~{xHi5SVur0jd zN@CVGbfzt?sOW7PN?P5{iwc_)RKc*lr6B8{Uo#I-O;Swxbdc?*pe@|*>{(?aMm?CG zt{9i~a{9h>m*-I8Q^G#DZkq{X;P~Ad;ajKL2<Y~Zl5Bt>y<&e)1$>qqb)A#5z1sTA zVpAjq42XxEZw9KZWl5kB@({OUH3%hVlQ@7bMwhHKr74KU5S*RKx{4}1f{{%Y5ZinJ z&;(g&X&MPKWTmMIip=x!>)Kyy03^8FAId$UDqln3At^j(c`4Msd1f@kV@{UV7Qc!Y z`6-uD^(7c{jEFw^^@iG)5H^r<h4o0}w6+m@P*O-a18ZI#jV~+mCR#DsFCUc~{yF<G zPe1o;*6No>9@RTD?b?@xuj4X{*@CCRh_M}UC5(SI5QE`e%*1@`LsoKSPA}i}zb`2E z+%vKf_9tuXCsu^rdLJ08)8~o&P;Tel@s!7@nXe)KzyPYR-KY5(4-XIP+(QUdT#)dy zhyxB=#dLnz1JXweIFdb70|-G}W&p;pEUhg!c}O#LHj{6QnqN<OzH}?j%W=7k2XQ;Q z(Q&q5Sm+T-ZxXT}&12E(Y_iJYW8zoWQy2Xfh~NU{@eme=&T&|nn}s8R6Xw<_eA9jM z0HB0FeR4lF8TDf_=rlh`NFX!%E){d+V{oAUX;FDy01WM)j>$xUv{B<d2OkB!L&ce^ z!j_$pv2{oH%U>b5J-<E5>45+o&o=Fszib7g;gXFc;S3xA9KM33{FBKp-18%Ty-C5^ zDZJ}#wmJ8vDqdC9#A<YJ=w!z<2ihW=b}#d?!ihtI<N{dgbf|JoecJyU8B7)($842* z?OQL)*FOYxy*W(8_P@!wP0wlTdLa-`!L9HVOZ6!~WS6S|2U68vX@$t>!vjHo<1%C! zTIn0{?1~?jzI?JKZES2ETZ098W@po-K4BqGLzCH@_4SZbL$?W8O!Y-=yN(PdtSWXL z>e^i}_0*@gU0tAiU{eq1CwsV0UqJG{&k8=Wz**@A&llVZ*V7SFoO#8-(pkU^(Q*5= zN#2k{bq0JRfKa{XX%(}*ZwMEyn^qU@ZABqFQm*~qOZToyzGDW-(MV0aM~{A|*W&TG zW5=LnNBb(`_dsuHu=`d07<MaO1GUN&2>T7e$w_H3DfI`ZK;P1`9IyEl1239kVpXnd zz>K+S%x)^3j&mkR&{A)P&h~)swHl{waVFSzrur8kqyf=Hy-?Faq`c65_MG7xdU_m? zjsShU!t+8|KFnInhZhx4vaa2!G7RXUQ1aEwk>5F`dm4)RXzAq!pX9PuPkt)9Fy^dl z!l6UjCnm=D7)gYtW<Fq$-|EZ^vPuH$n6D3WNCoA2w-VfLI{R2Pb3!}Zw?OUmxvkHp z-rE|t`Ir$eoHNkb-)X7!^)x5drP0$qW0P)A-vW3@f-C4iji#y!?i~P$31-NJJdMoW z-rjbE$K=2Be0!8k)G<sl{5`u4$(h;*&Oqk_`37aB0T$J{s~Y5pjhpY8CMS{F<cxDV z;$>O45BQq^<1b8!p;~eIYqW5q`Pa{6%k=7icsRky`|Wro{ESceYA2M8dj(i!tKW-@ zYN9>k_`mVbK&dLgHsK&F|D`>`hTJECI8Q%UyAE&#TQldtCA|n~S}YAavM4i*H73?k zK%@$d?}WSwVxfI~gu0?Dw(*aA=xe`A!_=|kd&4i+g@~375}!Vi8^Wi2UOOFULxzPd zg=z^S9cCA-kqJ>r{&OLNF^?V3=ibZbG;*TqoJEDvC8K;Gq>OnU&J3t_`^QFE;G5j` zP4d14C-IGd0ESUt1S=mpYA>*g`=61WaGBb0S!YJV)URT{?08@Om|u$e!oe3~;bP$V zft&$l44Y4jTosa@qD_(&A0Bs(?y0UFnZ`8j{owufzek1cx>NSu>g<=5(zl;oOp#Pp zu<BIqnizhF=VV{2_4_0p@`TQ-(AfU+QL&Ufz1V+^={W-C^z=!nWtZ*!kC%h+{%Zz& z>youI0dDZ(qK=HfzyA)Uii!$BW5pu_nj_EE{*=m{ihf9gY$QQ!ddSNkZZUCfKr(hX z{fP9Z46<Cn{vOTf3{7!)B4P^T;@JF_#$)D4Vq}eof&!l5>oeh!tzbzu_b(t9mwmoc zGs^y_RN`>sh$)(BI(8?9CATTi0;;YEdYj~KTiJx)b#M}L*H#7EwNs(fB`9PtJ|QiR z64kUG)>{~e+P+P$h_B~;TR1_d89%ZnG*9)nD_a{s5tJxb#+I@BV6iO4Z?1^9Ody1q zD1&<VG#!wYOEmUYzj^Qr$bJ`2@Y0Q_^*6)eo$u#34L;Wd`dwp7*;C@0NdC5m*Ocor zOkAmUZfh?^iY8BHzPfs?1FSZYO4IzZOOYDu3;MRg2~ml=@&(y~@uX-6kWk-K8uL)) zFO08VO*rOE(T}Ymn`<F)a-o)2zPhRrdt<QH@Wt*mOJQ=v_aJO{6F8()>{?>s;P!PB z1z|M7V9qLGFCqmflS0E8Yq`~nG4~a6V`blQBy8kO$?bH6^Z5%wFmY|TvWb(+4&h_3 z*?%~uXYdUb@ElfM|ET>qoZt`Olu41PQg0};*~J0GT2xw!dT{V>G%SnXEN+fm0TCFz zC_Kpu<_vQH84gH<IE=NmiI7ft&4R#7s?ykyJ2-_bS(7Jk{W9#YlEuVF+EB~)(~xEL zsHG?ocRV9yZTgOiIX|%T&WC;n>Z0iVw6fXt!*2#Q$o?R5OQ3)=k^iQ9abywB-qy|p zHxh+@e(UynB4OpGtHi*=!<8o3?A1zyAzKs?6ToWP^lK~Mw_3+rCy&uQgIs2)JYzTL z#q<l><Q3Gc%A3bg;|A@De9a25<%r4GS030VM4Ah0wc%P-KU(v$R4eq52l#i+I2s%{ z`&pQzxpWn3`{qeg$?Py2sbm{q^JSp)yh8e|;4gW!W@&J={tS|~1pkEtUPuMSvq7^T zlbWD~om;#ow3kwbA#t2b{v$1O5Cy^yGi>|6zHmt0>wEAJQlV=1^r#<1j-KtJZ%E_6 zi*HJEdlyHrdQqJZpd1L-0x>^k8Sv^iI5PT8^jt6)G+}t9wsTx?9GK9}gB?ZuW;I6; zTk5RfKCVp{#k&tOXV$%CZG0p!`u#<BDBNBtlA0x+Mu$lL`I$tl#q+a_01*F7)6vsE zxu1Y{5#%YtFA4ZYQt~Z;8cEycw=+9QjHBbW(A+M}sC6NT<lq2+*tQ$Ow4BCTN;cnk z3F&-YYJRf?f8ENlaYyECYFJC(C82fXRm@1jl)$X(1@!Xg1<OtJsk^n~Y^ZggmG4_! z1EPwO3e^Bv!V#`{(o0!kV1VekK&-$UoM!hpe<ShWq!{!>RX8zNB1=n^zeN-fQi_q- zFwWGtw*H`*>dazTukG#m9pz})2Zb-j`mVJ|hkzfQ1l(f?+eKt7oy24Px<yZfv?|zG zymA89Lxu?S=|U1sQPt(r0tXPNWJsUuI7IlLzV<@`i`?=-T-je$2%(D^Gs$io*C;Cn zO%E%FHPA@<<M9QzSA;)M)R17w5wW=CL<}H&xvQ03Sy$y1)G6z=ITr5}MV2F>ThCWy zlRAqO$RbfQn1B$*BSX|Z@H~I0_1=~_)fY;LT2vx%yA?<DJ{#I5$+ISlL&P<CM&lww zLV9O?T_e@+kLq{iLfHoieTk^F-uk3AyPR#CyF;vI7$RUX@CEM~A~M$N|IEBWWt5;c zQ?m?SBH2%@3LirdYnNZol>;yCbI9RuINXK91zx@qY&mD8=h5$8()q&v)oZY@abX42 z)+!!Yi@QnVcw0|a+Yh~oIOu1Gf2mlzO2b9C>n~YT@=#%cceV7W@eseQwYY@!2cO4J z8&lo(ZhMyc1R|W|D+0o3<LZbhZKQ`5g<cp(Nj(4d;Eo98-P&^`QP#AWm&{0*D?Pwm zgqZOy4dX+!C_GDja^UxNTpjNe|6iND%MXhEH>8X3JKNsamE4~`bhgcQkb;Y-l2@m@ z<k^6$Q%Uf3Vjurj5oV&@G9oayt`W*&Bk9t7M$f(T2I+`#=J???$$<Mt!dFRdpNxoi z2pgCO)$84cK%L33KGyvt3F6sv{8REm0mrgB5G-MF?&myUy$^Vvpa}-0s)mN|-5o#R zr>4E`uRTf<nQ{7U?`Y)db6-k=)}$_yWZd;Rz}gPp`PnBL#x^BZIO0K(2^`1!H?6rj zK3`wmn0)QdE1gv-`VW5zyc&=V<|+Kt(?y_yj0%Z<kQd1tJ(i8{)@m&wZnH0sD2rBz zG5iQi3Ap(Wm-D=dkD|dhKQ7$%^j~9Nf%U&jVP|o!m|Z6y#ncf{>>e;Op2glsAN&dz zMM7@0`<!ry6PV(qMqvohzSP-3^ma(_mqb|eu*CZ!d9{S{ideI9T|S(nnWDUhG~?}R z;oHax4a~&9s5;)o{%?_ouGZl(5-SEA7I6#UlI2xwx8LyO!$oM&4<y=78KQnAraXQ? zB>`RDMja&k9B2&Gk%8i2j*c@e8$t@CfRfU2lrkB%EdM-NXC}D;DHWvBvDw-9Q_j;I zyTa~pjwO49`PdK-3LQ&=^43>l6q3~Syo|40J?*kUFOpBe5;2BOQb;Dzk+MoFWevQ7 zT*as1pUbWx7AF_>@X;Ch1|KtU#BbxMR_af>8w4MZa4^0MmpJK=0B5ly`Pw%_X3mtc z%9JaEc5EZ*`2_Q?7bUR4-Wy0^7w)@r;(cgQ5m644SKw*M4oojf^ROgg{nWSe5hdE| zdr+opr)_-%8V!A+JT-w1?P|$i#;d=cc+!njms`;kaQM-QcDn>fmx%n@41W@A@5fQ) z2;Lp<vXLz4c5f-q-#=d3RJFN$_p66NVK*Wsy>d!43wxGJCzXBW`Cf;0M^+W63JK%~ zWC4yVoZ}>9y$`I;uS~dm&0EP}aEJBKj+WUzxT6JG;U%m0HP9!{Cr*WC-Sqy8u_}F` zI*}Y&N~zn!o12zmoGvH5>n@r=54+z=QcRH)PG_?hh?<XFxI`B5l-fXJOhUO5LrRs$ zj>K(Wd@>*qP3CH>7nWpRm@`7>OM@%rdWVjLWM|s+x)crxTd$+bzg0--#LDS3!`5Zf zUy;q4SIsZ(XHX~b@?3N;_lH9YbtrcfjrCg>A4uU>=n+cZPH7<LVE)F$E76A+@(xAu zUK2QLjsInET|>iz235bZOhaluGeuHHrWzsYHA6Veu<q8!H@*6-{F(Iq+cPR1pHKS> zo<xSW-ve*um5z5tdB0Z8@EN1?NzWc;{yAVkd3W$w7K7atH#rRDyIxv0Mrp-4SfWaU zMX~N9+Tt%P9Kon*d|SiA!J{+Yti#04)s#Yl><&A$a(<2*6c;D><RMcG>W0Uwy>B}n z+b-ztDC$p=R4gCS1C`)1_}3LT1&nz(0Qwfs{WdpYa)f}6Tmae1%j6-)uyx_;K*^H5 znK$bN>0kApvn_3Gy6aZyLLAo{Vzej*$+p=Zr#S+`CgS8a&|aqtBi@+bBZ|r_uG3@4 zS*qD74PdtPzZ+9YB5NwsDc6BN>|5~LEhJZ+IE*Qat$R7ABwflyT2Fs7oC1N1G;d{l z0@3}m3$ICj#54H@O3_mn{BU^S%hhKSr4p0+`KUW9LIj+N1WPS#?We~TaB4v}72Ke^ zJ5SKu%eQ!j+}p`)+rlZ|8os#|b%h)0vu_0kuV?9h4y(=BHYy2m6XPNgLJ2y0D^){r z+m_$P_UF#dR@<rgoePmh5J@9kH2gy3>Q-{@Hri*oy@~_(q7~yBDd?bZZLWn#_#|;{ zDEqpYL=@{}TiPttDDktIKkVBg>S!qc@d{zm+rm&@p^xm`{a}(p$l@LL_X`TW)uLsy z{mc3aeNZlffaKK*Oc_td{TsY=TnE1RWs>cT9qNs-<6{Qfj}%_+7hscz0!`%HlT~DD zDj^6P6n_tnumOl-oNQFODbPFapTsy~_2RHoVkOn6YABQMAaB$-;9n6n`W6-sV1KS{ z+{>8aeXZ=NJFKESLwX18*2E^|>xB=QT6Fywy9xp!-R>_oC6Y~1d&T@HO>%XVR;MnG z9f8l}6vyc4CCP+ofORduQz6pm=*+R1=&2sDEE(<U+Pl!yyQN=X>+*c)#vm&`-sfnH z`GP>oGv~jCC|U0O%Mi&M_>tOtEjdn0`AKIB-<h41fp>LF_dDiz!3d9^L%ugyY}`tE zBS!#%Syuqz_TCCQJ-$>v)5=u_zrhW=<II7R%^F#M{;m+AK?^f)(}5O-;l#J}!1(hG zug3`NURSlQYYdm$IrJOtbwd-4*lle@gv`?wkk11sE^v^s32a@yvx<Z7`dEC4ll;kh z)))q{#v;g@9K697auahsKw*T7(}mkmLWNz6At*HEw9>FC=}i5})D~^lcqQ~Nt})MW z6t!b}EfqhvZntbU<*57LFvPnDM5^!f<*jT#G<rndGe|V0lZ2k^tF2t_pn}FrKHhR2 zqcz^C*w$%j#5ibSbySOvDgHG0$k5g>#6_+p|F}iU=iWtvJlK_)<tsmI{#@U^8;CjX zl0-cfDNd7p1+2qH)^YhC3WA+5NKB^09duk$CnG2{Q4vih$%^AR{y&wL1Ju|&^C=S; zK9Gw*tj@@tN)QP8n@SMy4s`l^33X8nLbV~7swi22Z`tdlQAT2cSe9>way`W(^(0~Q z<oA(6irNjLIc*$2<N}`;+rc%FP#f7Qo@Ta@@qX$v6N#far0=KNIzxwuCrG%SpHIp> z98ySjafs75+w0hS4ePOp^$GlqxA@#Wxysge;K{5bB-;JkdKy{oQ-4$p>tG-#LZ{p< zQ4M1*I<@)xNh+W`F?>tN6|uWQ<An2n|6aPlh>AC*o7YD(y4Q!;Qum2)s?g%FItu*g z6Bx4ikB-6l?g~%(gp(IJ;6T58Q&N=8{Y(mtN#eM%M)&$c1!+z)=IUm_?UjzVtG(dp zGknSB$H@&-EbBme5LK;iZ(NrOc=-E&KxwnKHlajmwh!~~m8Q&K<8;f~YahTq9_n4Y z%^Gomz%o<P2B5kV`&}e|jW>AyL<N2>5j<VP1ptW1j-~X6cR!~N!>&5QIYT-+A}Qde zjZKB{3J*asLs&kG8nEyp8{h{LYpFqfg7{rQAY1+HY_G&$zv$_+p3pUBW|5vMYU+pn z&)GUCmz0((LX_G)Z;LeJN?RtMck)VghaxB+`E$ksBe+$re$9`13+yj3-o>%Jlbafn zLpu)Hd4>Cx`t1FyG=FrICejMZi<%F*WiAc`Vc))Ci#!!I|8ox~uu~XS-9$CIhmy`e z5JEo1sX|)4;HQQM@ZJMKSn^dWrj+ShhY0;g7m)_x_R(1@>>%?#ZX_N7h7W{TJ8CQ6 zmE$a|O!IzYAE%oEa7%g^ZQ)aFD!gjeR%En1-f@LE9f87_Lsb9jFKi~sG3R|^K_D2G zA`#U8jBZ>^htoCiXI(NvZ7uf3FdSK)z+!<{i4$(|VjY|JP2BP49Dl2v&~I^4pQC~m zCkRwc?>K$R*9H(%X_hc`;_|JGapt`K;-0@ZjQsm)wHh9lng1p)q`sr@H&~MI`VnRJ zqo9sH*p&q%blD{!6tVX>G*O^)2x<CB3;?}9#>U1^md#yz7ilE$qU4Iy*q?T@p@FRr zHs)D*E=>szwH1%8X#W8yR4D1+lqd+X15k5S7vj$-zbW;fE3!S@2*{g9+Am8GhG6Zu zp%i&t3?|v$Dx#96BpajMD=bPt<cR53$%KCX^RU&Z3`C>u?-<mW@~zeK3*+^ZjfCf$ z_vLNss$`8~XbrUF8)GKgPJU}B5gX`-g#G!)c`^mU3@OvPOC5*WQeg_Cr3g5%C?5}* z)^TW<)Hf`e;;!fC<8Cjsn_1gX&sAh0(n~sv+lDHVG;v{CQHh}Dh69SfbOo%YW-X=` z_F0IEyR;z0)UZK;?yuAkRCp71RYgU}YcCkv{;?(e%e4b~7eq7eE++V~J)8ub;7@@Y z>xLF7i6Bba+6?!~J`-fTNc_5g9851!Bp_-taII-?ws?Jwo(-l5DuvC>|GYn=%HY=M zd8E5~cnh}wdO-nUo1j`?S{i6Q=a)M+G4Wp~pY!_jZ--4aRBaZi39^7YvqTlg9zBQ( z>cty9h%BN7v_rEv4Pwc{B&~QCwBC46Udd!l&l9FlEUn>Qw|95Dg}|Q=#j#N8_iQg? zQ)9-&q?2Zc2gHm0zWOR|u4+DA|NO2^*TAab3HdO`A6r8coJr+G(R9wC70{RydLyKf zIKxNNvUNM1hnGJW`Av`=cw@8+yJZTCwhM~}2<JUBJw-Kz|Gj+8EnP>2{tglOl>~tv zL+{J}=|3~XB?jZK@JKnlZzB?cB`2OX;`H=$OG{kS<L9RC)$_IT!GRORC~w0kBlc(r zAG{24bs=~SfE2S+Z2Dq${`DO?HhlG<@W9AuPJp{K!Gd})W1orKuQ_ZfHcCqe!u0&M zl{bV1tmeJTE7-1Qd?fm+hoL-+=F8N~$K6`M2?6f!Gmu;5`tK8z6MFx1MLOdwJ1&~; z=L6_86+~1rBDCtl>51Q{IIE}&qBV%``S~#oyQTTqDr#LVhw2O@DRHtKQfc<m6o!(& zp!^@{8_)!mRcbM^R<z;?a7f-^rp+S>UVZ5IQQI-yHx5nL9SC4NfR}cDZs2t6QiPdc zJAjMS8)oED%TsA%p7F<=_xQq{<h}ZyhFbe0QeUOGX6O5zDBhLuVGnCAO7WgazbE>Q zkue#{s!lqII-TKQ&Q<+~GLXsIS47EA@61kkuPhv-=^QI(LIwjm>jqwf?kcN4W7+x= z2ftm=XJ?bIrb)78X{WWlH=#F2T7LM@>tBkXUq9`Es5Xt_sr2gZDDOtH*)-R`TQu}! zS&75oke7t4e7dH=YHNL)vR*5?E9|u&Y#O4ehJhcIXg5dzta74`WOwLSd!70)o`Vdm zC^}rWOW$VfWUYzU6PZfI2@d3_S6{=!^ktIl0=o~^9sc?%2M?zFU~+@{OpdqAZxHi8 z>G9WXx&H%ay>5YNU=FS2LgVmLoVD|^-0VJ@YPI4KE#DT&mJ5qsa|YO#fKk*Glw7yG zd|B}N=~T|i8Fe08XvM=2zkSR@Gnhst@zKfs&e&F9_y+NKK+I2`v$T2t4dDz)-p_LT zI!gJEo#+PA*vy@Exk~-n9n&@BVHYpywGipNaa}jXNkrvV>Q~vQ18sAeCA+3V`n{1o zb<?{RpgUIvnNdqProDF>r+Z!dsD5*Juf;ZYoBy#8;ynAwY3FrHfOJ$jQIi*L>_mZT z+C?PI(RNlxddXXg*7TfVK6h=6m5qt#li%kxY%|ax_~E=ExRj;SVIIB<n!J~y&14HZ zk($Iiea4oXj9C8O+CyE2{h?0jub+D7I7=%7Cv?HedqqCnDPam#$NpOl3T)>s)gLV^ z%99k}LHd&FP0@Q+?5_Vj%n`$STAcR&3&ArJ@h-hO7GLP4(}&~glv3jjEKxRIP##LC zDCPktozLZNAQaGDFX9lT`nz%&F>GzrBp&)}6Y20q;a31!kNm^oUgQ*SrH8htm-fEc zakR_?&b%*jTfJ~EMqPbzT<2}+1*Gb(c)d?^Nxvk6N2Sl#e^z$@1<vy>FKTF6>127n zJ+4zx3rcBwYl(s7S(;lT;M|`y46h^bj#cYtQ0XtmW1l*eHj)n@nSfgvR^`n~$)hls zKswqgbGo}!=GfmjTIOtgzIYNERvJ7@{Px~H(&OlSD8aV4JMjuMh*@u&rSgGYnx%GS zZ&?JBG9wXUN3BJGZkiNq8qRW2Pc2B37;ix<W!jHG6)SXK4~!@wkRLyI453ABtZj(4 zrHwwwppnMVy|EP>2Do4L3qc0M5cj_I0}6S6aP@q5FhvpyKAXC7YZt~*=~eAS^Ng!% zKv(3Eg=y&cPrq(f8H2tsF32J*G;Bsa&Euo@!_Qf-_IkH~=#!FPuNPUh#9h1#x|pGA zHRcxkg7Hy=OnI{_oHsQShX|y1I%tg}oLw{8h<bVikLbsL@LoT(sl3lWt($ws&mt~b zMss6zP^R8!JS%f0P5nDqO&blatzO|5*TNditKBiZ3uLM<kPlA@0<@*$e@xe5u!DWz z`{%jVzrK&MvW&ZXKQL|C=4-!%&ynvZrKjUh9}q1drNQewy5RpvCmoZ_gj9k$%Qsq0 z+w*XWf8Rcwq|x7PexyaIzx7=Z9INI<p0eL$gvT0DGnyE5Fo>h_MR;xdNJIC}rH09Z zU*>@3J8+R2)%8m6svs-AqQi`?8Gp8TQxk@?XXIdKr09FrNBJ;Q&E#vcRjTnt0aPyJ z2OSySMMHzubJ<9Iw5|6a%on>Xq$A~xwefQF)y|K;=dv5rb|3r^x>4*^N0!?_nOb9n z&#q)Uydav>{^-}OD?{<c_;WfyyZ*!{CL)0iFUJC!&Huslqp0@2M+Ve^ikvq><qMss zkwW`&ikG<H6=!SFNt4<h@WQD6As5m|%<@uEN#ZWnL`s8@Rl|cLRo=JQp#?&kR<Txe zGuz&*5A2f`yMA^tQGp&hY=v3bMTQ^H>D5G>re|k88`xWstTRgtMU?MI^XPnUx6Czk zUZt0%uZs;<Q(tkNl#_8VM2y>AtSMnU5UAQ6Sy|+D{beoX&Z<)s7ez0{3P&%-6f(-M znd;nge%^Kx@1}n9sP&y_+F3iv_w6msReCg-SzH*UBmsvx=-~u`s8wh^!32KU-dbkP z&s*_uaRZ%h<$W-HGMUA>RBH!H7cP8^6uV!D!(q%$bfJT}v90{Z7yV<%`tWIZ^Sx)h zaV=JoMM@pdB~8;P<M>LXz3!^lW<Jg6uitkKyvy1q4=ApF2;AJrl6ak{cdIxU>3JGW z97^zAUi#*<3RZU=b(z>vL@~|%a{zAaB+}t%ZQ{kM=I&GNO2g!bH6Z(-yS%?OS?AJA zdAVdqF5MN2+{lAz+Jz=v|82&H(;srY+Z0>%p}h*_9vjv!zN%?r8v+k1<`Njh-2XMJ zK*I-`SVYwL7x4O?Jb=&&fpDhdxw)-2`0CBPcnDljv4UID)zemwe_TxbFK|TwX(Fo) zx|{~vey~lPOnrsq%FeG7o_FPE@Zp>Ut<0jxH-$tk11YBF_^y^8?q-w^{+RVfR&XzF z+MsdVnXW-P!Ph3JzIyt)^I$!g>QMcpGs*1v&nw2epzfmuFGhyHCl2U*FCblQ!@T^+ z%!V=R-wq!_&SPWZzb^U?ZV6e;&VPLn{<X{N=foEgYGnHzH-3}h34Gmp&1?Ma>9Tpn zq!SSwECy=rESAeUp|a_m=}#OBKn%^H{hm#GtCF*f|KODQ){Z$SkAhxTKg8^|{BfZY zx%&GLluF-jRSZ_#a3&34yVr($Us~X5`)j3*Qna=6T*K#@u2I$HHVr4BLCb^c1K#l- zblX%qW-qY!8PQ|IsYpST%XErRtD`vIarCb~nt9Os!BD=7QUw?~-*J~;+=xU9YolZD z30Iq6G;G#n6Tcku!$2POZ4`5pA?Enq49i`>Y9k8Zyp6qqY8id5q3xR03w<P%UvePg zhkL4+DBa&Cr;+qn4<$1LX&GuSu=OwjdouDh2V42V<E^$({c|P~<wp4CbZJ&yycZC2 z0qZ*j_3+IGju?o><_2M*2@roO+Dl~FyprNxCWt68nT>!_ry4Ce`;D%T-MHDHHKO*G z9iL)oguG8`<Unalhg4+4z4?oZ{+>H^P2JA~pR#Wq!8eu2v9}b<rAFJgR~q}M2UbT= z&mkBSHb1*>F-J|(aF}B0F0={e<*bp%M~%sLoO0tHKpHQpAA94RZkK)WHWea=qMfGc z2a5cm-+dn8zJ^pU6xErelfVb9_F{nodXIH)Fc#L{<$HBe=Nbd~aYS2n3y258YtBh7 zqmwAB*~RIwwR(2q@m53;2YW-Tyxn=rnwDTd&o%-wy_dj%wP)p|v5m60F@LP>!s|{O zyNp+1&S3vT>bCgCGkV8fXh<w?p^E>nmAynBp}k@m-^Mx*j|=Vf=!16!p%+g3mk8Ov zT&<SdRXKkB<9PU!BQ>s|@;bvetT6Fr8y*D&I)d$i5W(dwH}>22;yA)V9~f6}x2SK5 z_@82ccsPWcbT9=nAO3W!ocK?ws(2lmEuf9HGZC+`twxi+Ce8y#t!@&wcN>+G5)I1A z4JTH|yQ;oNHPzfD{I1!%k23G*#In!PX(eYdYkuhFj3;UsaR5F<=g-%6h53JXS)Dz2 zQ1q-MzneLt{8=^~30>g~z>!S7{3-AfcIAhKoqvN5={sk=q^HV(d%PiMo#tF#XyQX0 zG>;G%iKxtonwD2}*I8(q`4IvA8X&#$EI_}ga^Lj5vxl?v227wi+OA(&GqNk{@@H!` zbo{f73>8WoM6S(*`$zrH;z%$>#pb7;>2m!4k!@Nk*Tb1R080(^sWB`oUmzwj#%tW^ z0}K9Deg64)mK{Pmx2>P9sxyjeOa628^flFOufqygj@JYU5|g7Dv`?Fa8BB;wfeIA= z*D=M*v9*`K<=!9WSE#G)W<f3~!-tUA4dpH@b+OX?nl0loqtm!8Ot9XuamH+>JMDi{ zzFoHU>JaN6)9Xv*gAK(S#J`-$w@~kZVnbnyb^TZO6^pN-{R&5N8KYU`L4ED`A$ZbP zD^kFPNt&I<%vTrAGn8v4uxAWAVD!b)rAXpD`(2~MGwA8!*Sp@b;67?|_)e*4F_+c1 zb+&r+cvUoKxX<Z6`Fvw@GsyE6=?k5w`_<Ox5nLuo^GoDvLus^9Z5`jwLDl&PoP73w z%Ox8|Y+N{}cT?C>vVr6<l)<UP={GJTGL4D*7ot`Hw*EEQe_v`Ak*nY`ekc8Mi`+as zALZhN<98A9Hx}VL(fongX});LfNHDo!Qc24&a;WJW3-(Md2i@JhXe`>NfHj(g9Jds zODfr4QfE_5_w#@aC~CMkTLX@iwx%Y}D`q{=*?uzU`fMw&u@TUlo%wFI^LkqDEu?=u zFu&l>th#8fX{$s=8*KVMU-6Oq><uxG?=MV<t#}NryfNN?sw>y0bjn;iQowCsC`MtM z#W5b&1O$C_BU1q$;i44pUV=bVHI<uY!D|Ap$d4rAj;=a~&W<^1UezF=`ydGC3*$tg zvmXf{^}K8+bNLCoACG$zFF#QsZ0-J;Sb88=J$UYA%*#@Ay$}#o&?@DLM}r1Hn0oHl zM=$)L@u3ocXu8SF{KT@2r<O(EyBuo##QA<cmIB2fyU<YC0`1k&Z1AvE1+Cl=WCHDt zWvYk!hog;Yr9CeV(tfIB@F&@xCQ$l1^08JZ7i4&dmnwh<pl#OoK{s7k1ir$Jn_+Yo zW+htT+uwz{prKK>G>d4|Ni4#JUqiz9Rs030hRl*~Q99?!{3A{1JsPw9Vz)*J)|s$a zK3foU?PvyDqS1Iji9xgW=RQj@&e^}w{@v`E6fj`Gdqvy3T$q1L1d+N#w2dDP0VI*D zLU%s?(y*HApcEyQh`4h{4a{me^-@)cjn(9;^syZgMQ#@0hK5Or2At3^8{JaEBn{-% z@dAweFOyA29gbuIKshJ$;)=I!WQ72Y4ST(=s)gz#`}T0Mk?PUtn~Eew{d+k!LT5pf zlAK>g&WHeI^vH1SajX;BUJ0ei7JD-$GXI4NC3`dkFj(jJS$LoPcTiDLKX!PvOXqOB zm}^jHYxJECjH+P5PnzEEnlD5)p10)AbwLr^+<ZIKSVT4NN2*;)<r@UyoT8R90h*0@ zG7u9aW?Mu;|6M7OCJmI+(CDp|6i)3w=N*&<7mIcp_9Hi)4ZE{Ps8Z1EhTPp&2jB3! zV*-lAb#^}gjd*K=TX!~jX?Uk!fQHJu_6;=Q{vH4butwA6(ZiSlm!}W6kD_kZ;6>kF znN*g;+`D|dXZ4k+YKybO{93UP;9m7iq}IV!!;b8H^pC&lvJd)SXJ1r<Y^Ipcx;Ztm zPt5(mJ{cm>FIIKJW!-rAy<t?ivyn^GzvM+w%SqDEcXdOZree~+?oTan2F&0`2bFTZ zJo#m9QkxNKhm?UTiJRA%{E*##i|J5aek=6ALp5-ont9L;3o7WH7@8>fMv*gnQA5G$ z`Kg*~G8^l1`6ZEor~)orV&Qqmm&W1CrMb+s)OrVRALF4v`w0p085<k-EtTz+nKJex zneoQ<_CBZg%bUhBq5RRlpTnu7AH5JD3OtxXcPt$2leYp9aDpeH@)rG3B;HsEaX=?t zI_mX+=8d)ff+nk(qHOQcO7&26bCs<elBJ_v_O>r_rn%HSlKtlRdEG%fTp7Ie+y@9c zq#y!9;HKR^44MNDB`|6JR<6@QBIl=jR^Xf=lGL=YKyu;i5rlnK9iBGR&!VnNb-6ew zs*hA9qJnqofw)<OzLmuiNV4P|4T1OuP{e-IvzsgM#xnA)JhWaq4`Lp43cwRiB<i<2 z|1k>9&&ry(8Edue_8iU@5-MBZ{~^$H;nN$;`q@|OkfK)wBHe9)(4GV#fJnW5M|665 z$9W{LH=_3k4CzF(mRpK(C2V%tx~l2tA=Eb4?kMZnFgn_>(*GDcDskYf=!Mi~IN~Oy zfddFtb3SD_9P)T$t-k2IT_U>(5xN^cGE}LDK0aWzoQ<^JllGBUw(O!3zC}z9C?GCr zpl^b3V;{fkj4e&igWH2^_bzJ69EU)bQLnU_!dAy4mpiA(IG4s2kw>}Ea)d3TMT$l= z+&lv%{$0AcNW41weGGxKy`;NFL-<fzSH{201%V{4r{qOXH`^IK{jUdDFIRCv!7ng| ze4r!Wy@~dmJTgSziFiNqd-vv1CtZc2e{Iy>@-ZVacA5)Q3(1!K(0pOpV2K9u9J??* zw&}L1dH1;4A<|6BhCfZyGDpXiFi=WKS=G(+4QPbOCAvlF`o`c4MKpG!0sncyG$8`S zSAjO4tL>rTX*<+t$Q-%DJSNA-S78ctQsUwv%U;6`VZT0mV{N{mALSK!Zvw`_32RHZ z9hi||j0-Tx_vJISfJjfYWP0Yn`znb-BHDN=&wq*?LH9>Bzn1c>U4Mnc^_{_UoT8e* zbYoW~KN4*2Lt$R=6U3S+sKg~{?@kXaQ6YiT=p}}{U;sKOKd1-+@F=aA4yk(lwsz7C z6)AZ>V64Qoc%|5WK4IP&!j=yRrWAV%{Ea*?tm;+YQL$)TTNq+FQaxouH6{xrq1?A~ zGgsrGVfq#)rG;)sxBmneY4AhOI_k;^2iO!Z&?Uhr8n-T3KYhuK<M*&4bz$}M;l1(a z`i=~twW%{1ot~o~J@+6GX#tWNup7PfqIyw`$$6sk(mRfS#p%G*<EZ7c^5f+NdG;16 z<}+`f&DwU+`-;4k`9iIuKH!^Kiw!{#-l5P9pz-dUSCoe<WnvN-oJe4M?(ZwL<%F~} z**Ebh%w5;L!0N2{0~yN^+xLr=dNlN{uR5>$Jt-Un65_tJCsl=U?k#k^GkS4R<s(u# z#A8g}Tv>MHxz&2pjpe-$QwY9jY-(4Hm2f_Q5v$L?8WuQ5L*j>E5(SI3gnZC`)*SR| z45Cmwm_I-*rOQrr?-7~jfOU4shcsol6a1dBeNRqm-B;-!7*52$r{Q$YEgXyoztS^> z9fu?CIsdr%0}Zh_;5@Zp&*sTgwBhZ+6Kg$CSl?x6|1ul%R!bNGA~ha{M`OC`f34Nv z9tjm8oEX->ZdnTr6g+-_4X~HsoP_PQ++4bJlreknJl>HGR+pBQIh}|y58XIFE~O~3 zMgL*mX3Qx#=k2O7^j|g|R1HwQaUe~dA73qP9aYs;wLQdvAR@uB@SnAsv|;&D?VSHA z9PyeS*XP2Hf)tpGCpT4%x~)q;2K4rzEJxKu(tUExspxN=S<4p_Ip7J-%R}mVd*3n( z$KwAs$uY6}J-~i*Ypt}8+(ui^D_uHgj=rPsr9<zcGE}6<uDWi&EXd&f8?qzzx?O;d zCqF=ky|KQ0I&$rQEdIfBYr`p2F9^HvDOgd5NGtt}3BIMpb0S8ncxN(%DL!PP1@2V{ zi$wLZ)k+ySfm)qIw=vT(=douD940fdg$z@tJZN9c4@hnFZ|nMrO3!S)mOg6m4=gl| zF&=mhAYCua9xgSS_e^B4nf7DuH`Og1y@Wtm>cInM{x4z&+>)Q54<oRPSR!i`8)gf- zjkmE9+jZHuo&zDBtF{vAdMBkB*0=kOcP-~Z^eb=0W{Dr<E|LE`5&P)NUhuwe-avwj zyw5ZYr@aWE2HS;a{`a!Al2a2l`ZjwN;>We0uIDBhe_=0Mjj|Oa)=9$}6v*OU$(&v) z@7=U}8hm`<bZM1xZ#M5?{Yz)y+(*OEu+=Vz1qGakV<k%L@n?d^dYvJxrO>;7nC<rm zN0XJht#_nSn!DTEV;)eL_x*8*(1{0aUdz9wqsc%N9Q&4o`K9aOdsQ){<6{_W8tU>h zza)}!1n|TZJDSWWCV5|G<mqMx@x=1D`ITU0z4%jP*+AuWzu8F5McDF>L3)Oi=+AAa z!NP_e-Z9~sG)!dmhl6Yo|DBxFU~CqYqz%iDR<J*@(b*NI!|O?RBu-1l*Lux|3Zd2A z%J%7a#guXcV-dUP5_+si*1wbz0Ge}etb+1#{mu_n-WO9hXW5TyFa@!xF@-812IJjY zu(2GyCn^fge;H<kV3h9^mG=R}wE)15`&mxPpJ-nI6;y2Iy64KU+zAuy=2b>dooHfi zsJA`szP<RT%&6;w%`Bgg+(6oN$Md<cB=w@;+Fi&cwEqCOVeOt(o8u%}1%&8RYj6)J zI3${+BLF6e#&-pY$J@@CYk`Oe%jGuJWStwS`!)Q|g!LEu5&xKduFLeC$En;Of|9{H ziwQa|J!AhWqdd}Nvo~~q7Oa{^b|QdJ`W>EoN9x440b#y+K`~4S529c%kphb30{=`y zLZ-y;Q-i?<wbEs$Aux#`SHAftniQ4gv@Ly7io@Xb?~g%KyI3`U=kUTzyP1Rycj5VR zVN|xI>BA?RN8}2_c4Al43#Owi`J{K5e4XcdAzikdHCeonoWM-Gz8&86bLD$dF|oLT zd_nu({_`vgXc-Bg^OZnG9I%!wkoP`ScE9CYuE@$NhV}yKqbQo=^=8$d>&tiIVbl&n z&|3PO`#Sd1*Ii1-^TIUB6NUWR0SJ(`{s>Zje2088Aq}wFF^pdSu(gvDZ9QgXRJ12t zm}}}kFCR1ahDWnsY@U^enMMbkx;%=B>$$M;T756MmMyq|cU?bO_F-MGk@ZyYcOhNc z|2>qvrWr0Xm%$1Tfou%3MAVkRFCPJQ>-3K;-D07~Yo;G?Wm<pw-$wJ7hBI}j2t5oi zdSg-1leM3`4f{mF1MT?Y;+@Sw2fDVi4c_l#d?wn?{9^$TE-~cALOQA2B5ByCT^x}4 zoh0a1Q_;l0JX&;|Z@!a6Z%M*ua(<HCJ~=tVT#rjP+8Tyh%SAn^4<na$hnf{AqxkH= zD~D5i+=g<b#yu>(Zo~399vv}lsc2SDv%t{R@K^0Z>mz7+aFj;tQ~Aw+%{I|8^WTk8 zD;oZ4C(Whv?~$Q#L3_Ihc+4AavLD@AwX~+M1&H+z7Jo<sX&bAq+tk#2wP8G1{lPN5 z3)D=<2}w6Aqv4UeX{OSI_b^3z-v9y#zAY&Mp#Myy4~x9vt~?LwEa0y~-Un9%EZb=3 zG1KUsj@anNI?d~r3v-XIw9Y)9FW*aS^eszT9PL>QB%;e<4@B7^vhUAZdhdN=<x69i z?c-p~JzI_3yOQo5nkvmS0+n=~`x4R@hVopg_(L(vEj^Qp@6o;fQAl%T7@D2To~Fy? ze(Uq_a;v9Agyd*EZ22tbf(~uqRFs2j=5cIpE2Api<{@l;{u1o1+%U1cmd&K>z4E$| z@ll)m0x&x*W#v3U0BLNrXF6G_xP7HylPcTGY4A-d2FF)v<1vC4elJ^Fcj?}76?(_4 zVZGZ_)!?+zJdu6n)vs9C;Z#t8f-x6;(fp&Z!zHz%PXP`Y*>xkD*$s-U6}N1gTVTYm z=fXwQNbYsYukEC|Y;*g-(S5t}?D5{KqG`1328eEH5=NS0^gIGfG;fz-7?R>LT<0Zd zj9#7v1qEMh1$}$w<_=)bArJyxFRym%n>&*`QZYH={&DrrOW91je^U1=Awnu34ugu& z6>BgQLhlb@ys$R3i}7eLCEcY>x7w4rQBNrx>WEPfzVu7%(=R>j6KBtRQNALvjAB4& zIS{*Oi$@o;m9*7Y<<0-eu$;%w%(tu>D{~aQ7xL=56B7~gC@65rGJI#b)seXg7XLA^ zv2UY82Tegi+arIg$@MV}OLKyTshYj0=Bhi2d<Tb~kuhWAz5^KXX1x-m?Diny)vbVT z9$1_N@)R=B`l*c-jj%X&*M9G>aSZz&t#7asZ=%iH)6X2)CFF(DDGq@Mf0g6ip=>|F zsJieV;Mv>XpD+=00IpZpj$V7(&}m?Od`}uz#M|0(UZ#JqwUyz}u?&0Io1AZ%J0joQ zuN`6<N5aoI8fbKOe#YF)kZ}B5wd;cpLi5|*(#Wl6zzFrx<m83vf!)q~7yL%Nb8m8O z_hD3NmyWsVvgDN4Uw%a97Gp_1dgPYqcXUt3zHfK?!I<`Wn?`;1wZ5;^r!KTkAL>pH zzu><bM%zQl8d{S&ZTL-JB(k}OCV*z4{m^GXQQr^~Kc};O<31T}xw&V;PWjFwK)^ok zdsFsjvxF#fE&jPN@sWn}R0jqURbOVC97oo7C=gnjBag>hc9#*$&XCw-ko0(+NIw?g zsAc3n-h+DaeocRZOw!hCuF5_0i`}W4(`1`z5MJ%|&OnPJ)3xqN)$|HwQp<@1?b{>9 z<#OIn&Lu;Cs6iY?4MoLLQe=K8=|ixPRl6VxTF-qIZGGleb}t`aF|Vdfnr;W9F)m$* zX;%sTIsf9dauai&Wh8rl&DdBeIIi?_y>S>sBsX(qR<czW&aJ-q4=u}6mzO=BF@)+i z+mCwId*_5fSdM+4@~hhZOqijeor(XnD}eI%hP=fc(VyYj-M+YNFioAf9j$j-t6vK# zrIF=wT#}Oh&cN%%kYc>uyQR^x<LMJ%fvaB5zm)+8!7KjWp~nTi0})}ciTC~9!o}cF z)dX-T$~*Fgd1y75ClVK(3!MR@7*U}9Ze{YBO61*IM7y}K@st)2Q0xrZ46Rzc`w~gQ zH(hr?b%xHkZhic5bTv@?`s(FRIs<qE2rVPn^kJiSf5%I$ehJj13QmuOjMO=T!mHPs zqx4XCHT8<25r)@48EGFcZ3!EJ;fa*_o&$$n0uiB>!D&x2tu^?!cDg%_G^j2U`s!3( zr(YT?`396^Ng1ca?fYazgqnM%4gaFSIIoYUqB!xsiwe@IPsAR&b>Gf>o=sYIDJ&RD zeznCu5##uaP5FrDZR>GUC(k;Dm+cqc=Ynp$N9iA$0_Y4N!h}3`$GsP!@=qC_tND7N zn%6@i^UmU#USXYDRvCyyEPw|@$kf!-CTxsS^2AjKc%7Ad->qkF57O&bfCHmD<F)NB za5;<PjWw)1<8#GJ;<8wiWnIUY1wDwj-c*4L5jT@1`0eED@|2Lgdp9=8!=lg=yL{W4 z@BP55ZL}B0cQUVHv3+WUq3c~<64|ON(9u2BIn8r3^Hsgw?G?3lu;VGN2+b&G{pZRO z&Gm2(C^hHnn?pP>NpY#sdZeSDFE{rZ@k!d(XqA=IP|wm>(06j*%4D+4j8#4CZ8tIV zNVy$jYjF3CJ(jaLotO6@YY!xx|Lwmr2<&M+a1%FS=A2SlKd=~QD=3TNXfTfZe#D<K z5e1JYAyX2+?44WiE54oZao;Yul4oh6z(eQ$flwT)vE}r3>F?3~Gez;LeCkedIEe5+ zJ=lEN1u%rzfptE{Lq$#&Z!U-&&(u4ZB-vz@X)<gx<hWN|8FgDeIeZ<Ro-9$u!wf-d z^y#;&_qxTjTC7)O?l{gR^|-SWIPU6%S6=1IKx5{YxA8tp=Z9KP1R(p^&8Q}dGnPot z0nsegyWL-uVxeYpFWYVrA)5dc5v}{KeFKFSoDY{-ih8>L8zwd}{l_hmOkza0BT><+ zYh~&%)zYtO;o-j2yrgKRUd8uDrW8YRy$nOPB)O22FpafuZ2x4(Y6|zzK}xJ|is)vd zAc^TpaUvdqe*AGT(fia^ij1eTn)&kN0xZSfiNyYtn}zVGhx6P#MosT1tn>-ZI*iPw z*~wGF!mtz8^CM<%E$9H+s~~)NNgvnw@jdko4PL&m&A%8+`~%Yh%-k&pJmLZ<HjUb3 zNqRs2Ob-4k>_NJE&(=OSh9oT`Fgr-G_+fHx>*-zk9c7kwvq2+RsamGC_X}VBS|G#U zj#wN^;QSk@`*tis@?2v@FP3)UHQGNjAZbivx64gSPv`h56AxU;RKV-IyK5fwF{H90 zQL12aVWDVwS<lJEr7SN`#N%>*93%?$W`C(GtTc;2r#3C!rKMkO=^g1pK3RfiJMu$~ z?Lx7KvKx;)oQEx?bb~ZDK9SS#yx;J;(qY_TR2$byt`OhF7m&PS(#3zfXD(D1HQ|<# zr=rdNb+Trch$3|~2{6f`bqVOTN!T$y)mG&z^(`Am$BjQdO`#+p4VvoLZrOE}PIqqA zYW=G!onF?^s(Ww{e|cHZIXO<iIr$>Ckn44tkf1I`vu#{SDTOz;Sv1IK^8)2)v!I<D z+x6FlU-3-e1(wD*o}4;r+-~!V`)IG5Pi5^x6VN3?WLX^h_(l4M+0b~+VjT0y_;(e6 zVl91MH&X>JJ`Cb(U}kAK>C$m8t82eQKe@cT3bPHPPL<gO5bFevyx=BG0sebQi6Zp& zu<2<%L58ii7^?z=^GOMc+QQFlDMp<NoLY$)vwBM7AquGA-goTu9#9pbEP!PimB90M z;4Zox%I~;X_`6JeGq@TQBJnyJ>_O(aC*;-G@lmsLPHi9)+9)2%qmz7tQ<;Axlrd4H zuQto9KNVQ;{#7ckQEYvaxK`a?#UX1mi=r};rHL#-^}~*)vTsz8C2Z^^dTH~frk5Hb zXVe6xRdkD2H@ACdQPT})%Y-W9{4<3JkS=Bb7fr%CZW%$mX|c)8Kp3z;+gNery_KFO z;Gx!i`SR3&n&(y5;LP_=VyWl*P7_1ph*su~OPEi$I38lx@h@1mvkFn{va>sq=Vq0! z_l<!R)NKM~ae%@<ub_7-np9?oq-~l?605@Lyof_)Bj*ZSeY+zjN-eH#c6#AP<^}6t z(|N6(6`hk4Bdsc}z0zh3V=CrV3IAJv-oxhg^NXsba+mg7t<DgCwzH=n)}w_wa&C)j z&$9h?9q89}82P1;ccpe6bX0GbD8`K}T#hx-AW}&B{eCtbr)1*L8*wQ-`{k`4`hsy2 z$z-efs0ByUTf_p5SzEh@OzQgXzSE<}qw?8~^&LF{H64NH7d|`;=?ZYUj#>~%LJctH z63%{@?7t^P9{jx}c>6BX=fMpLDlbC$Sk0zJ{ujZpm!QGm?Ki8OnS=6}X9SQz2po&& z#YI2ylB0{%yAh1q({-Ps^Xq3k|A(vZj;Hed|Gy6*yF%I0vJ%;3MfOPc9w9QacQ_@q zjEu4!*<1E@Bv~Od+mXFD*}v<Y<NbMjAHV+SLEZOtU)O6qU-P;yYgQ(vGXq6~ef;$R zm5iqfi+%nI*#YHg8&BG!>m5zh6YHW6^j&YCEKEh|*C?)^ewldNZeokqFb_emr<QU} zQptT6a6ul!67`c#B2TB`Fz4$^Zq?5ZP^EKMpR5sq5WMB-xN2~>Af$HVB7CYQS!{mc zW`hzt?Y7UYbgo%>lX{l)c&6LOGG2>sm6+-{(vyf@Ce{?}bRKDVy9+YCLN%<4_3ErW zW_$9gdBNZBXAdr&7lZcuaWPCr_?S8<#iRDb-h1+BVtQXq?YsC+3i(2(gSSS{o?trj zS@w)BUKtKaSi~2C`_NiQ?pI=vyNv?6f9v>L^8lTH(#!?33u5;de@fii?Xx2Ef0CrV z>bBb>aeF|=%wE`k$Mn6M{}c73p|z!&GetJI3u%+LMPh2QSo3mGM5zqN0wEc6@op10 z2vsLkZgU5@PKPiJKA1Qappo4i3{Mp73V<qKi@*J-4I86FUi}?W8tMjzA#Q>1TZs0} zEo~*=-c7!$dIf*9xMd*TL1n3X`L);6x9ywBs|Dgd9<y(d4W4}I$=m6qQHX{@kDcjY zjhr`JlM*Gv13G#FDSz$$Dg{Dt_>c+VOYq@6A68c8<g>BN-OqvzRasMow>V?%X6r)I z;*FCst~`?Udg+Zr8&r53gfJ13(8q{kmOFK)p;7ft4vOE12;a)OOnwM0IQCNK;{Nmw zUg;2-8#W$G;`+e)Pqg38dQ|<{1txE`>NUgFg_<)}HY!x+Vr0DGxT}B8(>pPampBnH z=;2f9poy(H!R0gG#XAkbILWaY*$)28%hgLc9KOS6W*W7ziUm;uzo(v%>HKn{`VnTn z?2f-_43j)yhGZ2E=cYrAJ(SdK%XNMdPN{i6?Y*|9x;Rp!zI2^L4k=nYFyPkk*ha@{ z!+82zn(KBQ+ql#$S3A<gfZlhv-c);5qW|y02lBM2nRMMx`lA8+r=S~|!{mVIWQRpU z)6K1HQu-Cx-$lEdYjSD`@;ONk=2?VvIkf5dPIuVTNq4NNkOi-Y@v8&Dp%LIXQzWZi zcX?Iy%DjT_QN1RD121^1RbQ^~&`GMI9!W^?dU<%f;B>w`Eot&f0{MfQ8bjZOeTBhe z8NCCY+}yBJ;cO$LMo-S_0@ovo(E2Te^sGZ*DiJkw=@B@wC&$mHrI6o#gc5+qjW|Jv zP`~}rQP(l2mP0X0{ztVJ;bPSCG}QK_rV8)zxk)C67jtsCJokyAc2XF(qCQZ|)0or_ zznI@ATq3Vbavcq7a>GvUXP+HNE9NWff5ll@i=5aEPV?JM-g1yWlK+reG4Z*dw+81l znCMk$`S`%mSxkTGa>r5N&@jizq=fomr^~Fb1S+JQ@str4di{L!Z}Z`}gTtTanMojD ztabqqEA+)tXCc4O9tc8iD8w0lIdgS3fuy@r-te}z``~)t9ejdE0@dGyWc939KTUX9 zDLT~N&Snv~uzuldiO%7aghus3i^7SY3isn<_*9zVV*HugPUGaAGAEA%v9kw0>4jtQ zy}SEq{l;eFM3?T46E0>Ds2}c0Xe=#l`|u6>JS)j1KVi$3!|m6C4)mI@IYSUk!0*`8 zcim^Q2dJAiASBM=?_hC6q5o<wEpJBKdI~*vZd(8(v_QppWT6S8|6ML)>v3V*4<;%6 z?Sv5u4>?<LblbIOOXMH#p$ips>$lT55KP*9Y*n~3%A$TaF&$csTX}jTJfy|F()+|A z!n?^?;|r5{w!q*0x3Zs|(~gXtcRJ<NN9Z*4&Ny)nYd|0(C-A_#<J)J|IIH%6+x0{? z4q>j#=4@g`J+p3aVPBmvF|3))jmzLPC_i~Q2Dhk*GZ3E+jIZv8qdpN*{9Mj8IVjf7 z(*-pYvTu&BZ|Ao;(B;8is$DXWL>EdLIZ!aTvo!Rv*wrC7*T+CZ<Y_{xAfxS4e_+N9 z<_5XwD&UEqY(AH3@a%fx!Q)F4IVf38`!D#h@ZtD}&<WSl^lfrps(ar&K-l3Aob@Sx z`uqvHU*tBDR)*CFjZvo?wW+ybJZ?We_S(|+QAD0@y-t;=UC0t#+_y$$PMuzHu$gz@ zgAhCkzI%$}Zhx5E0Os`Jo*h?AHa$$bSGytVdu-0s_l9u#gt0w5H0}j}9z{Yp=gkv` zv>THMe5CDj&|_K8@$I?W^#_kv-Q8Bl+4#?HrgvP67x8(Q-K-H3L84J}*lYXdbW>Pv z-+^qdjR6%6u=z|Zs`qh{{9=2PN@7jFrbb9Z;fklaw_|>)iP)?)RU;Ssk7{?FWMEK< z;~9*K`}^;gC=VZW@6V*?j}G|e8l8Aijq`FBYoBW4LhP+Oi+#IIOnxR6V_Po1hrG#O zrZ3e;#RGTK_fUiBkL8y-!wfxd6Xe+XkKqIV>kGMvOsgN<lng1eZoizOo%<d-h1-qI zvM$QIFN#OQu5Vm~U%u$`wAUlqd1pM6zSDuvwGl_UrCXrPH76xJtb42cp3Y-C*WJRa zavp^q17Efr?n(-ejI;PoON7=R#iW*4(dk!l8@;1uSBGZV>t1x?<}#dkm8I5|Qpg1A zm$eLBJB#ieYEjo0{?q@?MOnq+-UNxvU1qV8=7E4^da>GOtxNT{)~nU=8K%O6t#6zZ zW_+yv0YTy9qvg9l1?wMz+kK104|~Fvr{qqj_rt?eT)K_2!~Aw+RpLbk)>A&(98zmA zYbefK{(EO^N7y%;OK>`{==n$e+0o_79AaIZ1lKf`8ivkTNgNW$51=$EZ_#nL?5w)i zpMn2P8t*e|eer?cf7>$VRQZU?3$msaA3QM3AD&u@<t$(vo>|HsKT+LK+!0-?342hz z8#~oKB1gY>sbOV9`1(<^OXz7Sd&?2;4=NF{oO?%8k)eJkc^)QCt2sqE6>n~i5Byy! z_#Cyg5~Z4Gwon<H@mcvkUv|$1-=pVY873`{?VR1t@a0Cm4^N6On6y-gN4|(n{E)Jy zT0veoC0AZuy<`<DmM!OVkp!H)I6UVj!89dqaWM8Sdf{5oh<Cb)#Qega?y5L#uKXCY zr46>AXJLYx6nifuLOJZ$9m~9fb6F}Xy<g_~Y{W#NmM@*s-BWWIU$&XLki-YU+j$%& zM8};w9=jc_dVq>b-Mg|^N<%>McQ?bv5!>Ao4QaW41hypcBZ*ct4#~?o894QqY1&Zt zWO1oM9jHSUII0^IFm9ZDUgndO<^d*sLxn|(KD>~it6`CIp}c%$Ag7<tmoca&U8ZRg zO%{<upz^e)p#MwwS0|luUv-b<(wfnMJyo4ik+cC2et&DydQ4OBkXj|<jFe>*8gi)1 z{?wFghih86bBF&gZS-wVRweDn>eW7pxix>%nHGK)x$fMOE@{ay>5HW8Eu0Us$!536 zvQeAW;feMW^Jp<Flj~cxs3@%&>AxpdH?C!?;}v~%FJvo$Ng-Qw{Yq%5;OAjCUPAZ@ z&tG3^GsE;PAq!iVFRr88p)Y*IPqxSINE825(4gxpY?{;0zIS6lmPAGhw_zN}>0P$n zABMX>(z}eGTYbr0P3#S-D=;2eEiT{^{g#~w3iE2QcB6yQI>ssB7&~c@@6kHh(rMWA zk*A(nb@2Hxu^C#C`|VrLdWwa;l*%d0@t2d92JAL6g=Ec~Z&neuqTg5C)HB?1%!mhR z-or7~Oc-D&(DsnGp%IyBV-dZ0`kX_}TjX!Agg{kqhHv4b=xYJvCdoDZ5u>tFrHBVh zK8x}Vb8Z*8%632cF#reG?)w|U!{d30T#mw8DZ%j_yb-A{aI^}M`=L(aB>d|qrQ3#g zWTm-Q09N}x)ctcC_Y=t-S~=UxMg{ur7;{sFAONKq2rfC&-<3uIK@p`d52mVj2Mu-t z*8Sy(uSGd*=yrvQAIhI>eW_S@FnOx27u*oRXO$PdFYt6CKSHbbJI$|p0zs%CoPY*W zq=bR)0|<pH7_%)}PqXA$zBYRu7b;4A9;aWmb$8rro@uA7&`%GPqqltIsmz9ZZyz@9 zH>8gGZFA%cO<kaY>F&FKB3Q0g2Zn`@>X&)X@Uo3ZEN2NG^iT>kYXI-~nDl-HrApcv z4D?$_rG($B|Mzr!`%leIr^8DvaIw^ekNhjwogTR*7Kzh(zq6wUrOvZ@Je?@zrh9QQ z{&<cifiLNJ5*lfdgnzVn5W%UIEFisz`hrUE0)s=dcMud}>2E+D3kteQ6zDn?cx|Ce z;^d*k(IUCqNH)unSej(z#`o==c#|`!ipf3OM8CtuV*Al`X0Nr4?1RT_E$kUMLM6*R z__PqJ43+o_Jt$HfM8}*7YNz>EVGt|jXt^6W2XYDIbp}9(VA|yAp2y)ZX9fG!4+mnU z#ZOFhG6m}vcdNm@KYSREM#C|ZR(Uuh>etQD+$c!Mf|iHxa9=!?O^#IiG<qOC2uS6z zG=?^mpC0@=dqQoGjXk!$d2ZeqcWm1A-mjU=21n*eHk@|agXEjsF{5^y$nvi~H&CAX z&6b()bz}qtiW-`3<tclfYgQ$MI?je{0c35Ko#B)`B+YWqy;Q)qP^9h8yzaS8)%=}! zUFH{tt^21>DiT||wrTd?R_xj;dx>B2TdldZ|DfId#Cz>yxyj_3#w*6)m&Rv-wG!!` zc|=vKuj}i#JxP2=-5I;d8P8VAjfz^#X5v53x>(Jagl&zgi+vUs%Op4xu~VA1`H0)_ zF*9vkOgcGY-X(9Vx&iMcNgbn(n|$1$HT}?fl5uwa<ffreBS?Z?H0H-+*SPUX?Z(vl z_rcGWY**g>6T$Zkn5W<=^E>e#_dmlu?6j}I=6UERK~;#TZsj|%YkPL4^+<oVA9;(Q zi+Er5Zen(A`M0mkd2t99WCY{t``icoTa?FXMcL{6DK|p0JV~Sv`v`0`scLKRq1$1= z4~HPnE}<BQy&CS5lAd*EY1}h&lG;N!vYQ*<cq)9EY-Ar{#58uM*1&XISG>~R965V* z#ye6UV)m0$fmw-G=fOs=bZ9q%>F~^N<G$#|wEX__H=Fd8c3CZsZ$>|sPksu0B0kC} zYBhA}lZ_Ms*T<i76HIEVK<K5IpQ%leCOvNLUl}ez`@MBjq=h<4N*@^g{#^#X&$#!$ zPiOzcO1}!P_DAj(f4JA*#*&!U7764xA%Z)*>-S;Tae2>tCDmm}PT9O4s<eul{KD}k zdT`yj)Kl?vSr!*6#)uUBH4Tp_Ul5tlkxBjJ>B05XNmBgDXJ_vC1Rnz`%KVRR;vt*x zD@AtprHusoj|bHDJ61h>`oeDnbhQVQz>kc$E#8VR1W$!Fq3(z698G0R%Z}}FH?V3# zqPne$XUm1Dk8Sd3Ps$<4)HBG;dZN|~gd0i5M<cmqR^5zZM=LIe>*isL>;4ToTy>=* z>&)KIHva~S%&$a?%*B|y4w-fI_xI22hbwkP9UkM>De4gjB{VA7Il#kYI?&mc4O|Qy z5oP%Q7TyX>wQK3DciT{_p|SrXy_$JuZ}^8n4KJZh+@-o<crxv}teA1?as8#EU(H?j zbV9V!9UsA<i=p6}!$kLyY?0Mcjon7_S`%>aav!*HEfZu87r{~7gAGhCb-(HUS~m-2 zzw&NjCQ^Ih?aj}&AV|?Kx61|x@XzcQDNcNx1JkP~(qj~eXiQP8Rv&ZYCHl}ox(wmM zB`(5Y5TvF#dxdt+;_a)MD<bnnbSu35n`6VAolNW9o}h3}2`*h6oN0@61IMT-MS%J< zIK-gL-TnhO5-4+bS<rfSi62zWulW)N*^dtPrhh1NoWkjh<5$|A@9eAfa^d$qbR8DZ zNE_A{nxH*VOhw>$B0yux5ZQ#DI3Uo!fD$^4ERPF*;k}+UwjaQpeP-B=Dtj5s>q&}| z_LFFLm$es5m@4n{NSmCMF7*_jDL*N=#FHN6H<0x%s-K3=d&{<eHPo^0$$YGAO+#!R zMZ);AzJ_imRolwJ-pdBGlMbY_T`~Owf*YRV72`b$CELkq7r;pcCH6<i!^RWPgfw0= zTIw=SwmS4pnjtaKW^%NkT+F95(>@Gb>0D|)ubLjgR<=5PQ^Cg8Rzoz2x+t+NvQMj; zba(f?rVL+sl^(?%RkiJy`!+9LXuG(SfQ!=k{EmfGl0@}DuW6*ElQ=3`hC(b0a_6`O zbvY(Z8@Fg_m<9j+;PxOfp?-%5Y9+@?N;|_|urwE~ld5S{@gFI?uvGg8%l!5PiLYuR zp0?5NJ=l7&UDI%o*B3uuzFlX}b6bX>i`>@8U=8HVp$U+c2PMltz|ktR8|G;U4xr~u zmc?_-xIvS2CX4GWdU&OGu&y9OAQIFq?teQJ0Ypayn5wQvWsHl_+k@Y@__gS0^6ei) z)Wh+U0xb1m^eTA!o~0{kq<j!19cG4bq(K=+C4~)m+AoWIUa%~|H67gbK=6pi2v-RC zN(hLQ<mP1vZPPE-4%Rg$s(~LjnqqQ}4Gy)XsERD*V<}-2;QwnMVQj|r4Si6U1QIA& zq@2^?Z&TGx`eI?&<c=0Hlx|Ei0T`F}Vc;(?h5~n{hhkrbd#C_#7eIo4&ICqJY>g7u z%~*!^@pn8|mYfF$KnDvxl>Q#`h9s&CRA>N5+6+>2tlR%!Pvho`Fw<rv-T2zd`G8}l z5g&d9-GK=~|5z(EMAL&Wf$tz6e7NKN8%G2|Rfr+LiW@w@XA(kCV%L;)5#3M&p%R-Z z>aw7Mk80eJ{P1)H0a6o9)Bo=oOAS#p$ET0)Mopy<xe{9gNML0Le}O+#uRtRi;8`|E zva}bKZ91~2<GE@DQ6cL>>4t7U6<BkRx`m4m|H=&EgU8e^Yp;?lxzd7_OVHjpz(ca> zC~70w^jVt_V_J^Vn`x0`uV7F!b~T8nY9QSJ<~V0VJ|aoLx3R(%pCH-_a-C?m;62)4 z19CT8+wc1Tseu~rXWwfeGR@|}K{;N{FHVJtGuje@G@LaC7$D7$DqwAZiqB*zsF1PT zw*q+$34~f<8zP@AVE@hU{X1cDlW(9+5Q2L=3t@)3G=-X^sb;SJMw4ap5=I=dsPn+7 zk6>Cdk$JThJ@eW>4``^6>N<tFAQx2U52-0)J_x^I-ri)A>%IxfB#@`s@XT@M7jr6g z%D6=l<oy<{aB>A=bU~K#0usH7Z=WO%bKJPd!O!q(S5-=*^zwvj6`#Wx+BPJsBD`_O z@Z-=T6o6SXYcWc7{vS)c`N)WI))VlG=I8L+149QgVBq|>+tbP%@O0CPSH=~Q=yzUW z=_Hea$A@0lQWGG1L7FEVxBKJ<O#$q#LLHh?*&to`^*V-0FE5R;CH7X-v}o~7?X!a6 zUz@#DIo0?T{Tp8-q1kMS(2;l{-^Xy*=^hz`Cx;b0=1Lcl`nCd6KI{rI_-1N|iu!e6 zGAU;4@Z0I#!_RR^p}_NpuUBe_%$g0TqSXcBQg$fanvhMVJ9a6#XbUm@mZGzUScNds zh2&~X`m-sM5gY~bsSs3q-+`VJ!D~jRo<Rdb0xHx!3|}r|`65oZk)YaUJKoVl0JQA; zYmnTFZO<Te4bO%DQ3o75pDN<-BMPkS2U==uIlvf*9fyWZ1ndz3wPYKIiJ|O>WkKj4 zR`WIpT^LVo≧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 literal 0 HcmV?d00001 diff --git a/site/_static/static/dcc/new-in-devtools-118-thumb.webp b/site/_static/images/new-in-devtools-118-thumb.webp similarity index 100% rename from site/_static/static/dcc/new-in-devtools-118-thumb.webp rename to site/_static/images/new-in-devtools-118-thumb.webp diff --git a/site/_static/static/dcc/open-icon.webp b/site/_static/images/open-icon.webp similarity index 100% rename from site/_static/static/dcc/open-icon.webp rename to site/_static/images/open-icon.webp diff --git a/site/_static/static/dcc/powerful-icon.webp b/site/_static/images/powerful-icon.webp similarity index 100% rename from site/_static/static/dcc/powerful-icon.webp rename to site/_static/images/powerful-icon.webp diff --git a/site/_static/static/dcc/productivity-icon.webp b/site/_static/images/productivity-icon.webp similarity index 100% rename from site/_static/static/dcc/productivity-icon.webp rename to site/_static/images/productivity-icon.webp diff --git a/site/_static/static/dcc/solutions-icon.webp b/site/_static/images/solutions-icon.webp similarity index 100% rename from site/_static/static/dcc/solutions-icon.webp rename to site/_static/images/solutions-icon.webp diff --git a/site/_static/static/dcc/web-on-android-thumb.svg b/site/_static/images/web-on-android-thumb.svg similarity index 100% rename from site/_static/static/dcc/web-on-android-thumb.svg rename to site/_static/images/web-on-android-thumb.svg diff --git a/site/_static/static/dcc/hero.webp b/site/_static/static/dcc/hero.webp deleted file mode 100644 index 3243542b5b78a926652dee97390f7c5fbcd9b31c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 106046 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 P0000000000000001pB|u diff --git a/site/en/blog/new-in-chrome-118/index.md b/site/en/blog/new-in-chrome-118/index.md index c7f2e56f7..f23bad767 100644 --- a/site/en/blog/new-in-chrome-118/index.md +++ b/site/en/blog/new-in-chrome-118/index.md @@ -6,7 +6,7 @@ layout: 'layouts/blog-post.njk' date: 2023-10-10 authors: - ajara -hero: 'image/SeARmcA1EicLXagFnVOe0ou9cqK2/My3ZVJzsSh1BmVasr2sZ.png' +hero: 'image/kheDArv5csY6rvQUJDbWRscckLr1/Fykb6HbizvuTjzhXB8IW.png' alt: > New in Chrome hero logo tags: diff --git a/site/es/blog/new-in-chrome-118/index.md b/site/es/blog/new-in-chrome-118/index.md index cca2f9bab..67925f112 100644 --- a/site/es/blog/new-in-chrome-118/index.md +++ b/site/es/blog/new-in-chrome-118/index.md @@ -6,7 +6,7 @@ layout: 'layouts/blog-post.njk' date: 2023-10-10 authors: - ajara -hero: 'image/SeARmcA1EicLXagFnVOe0ou9cqK2/My3ZVJzsSh1BmVasr2sZ.png' +hero: 'image/kheDArv5csY6rvQUJDbWRscckLr1/Fykb6HbizvuTjzhXB8IW.png' alt: > New in Chrome hero logo tags: From d07af2b81303b8b842113ace2253d2d6e5b834e7 Mon Sep 17 00:00:00 2001 From: Neil Berg <nberg@google.com> Date: Thu, 12 Oct 2023 02:55:09 -0700 Subject: [PATCH 893/982] Report Issues Link Fix (#7519) Report Issues Link Fix --- site/en/blog/cookie-countdown-2023oct/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/en/blog/cookie-countdown-2023oct/index.md b/site/en/blog/cookie-countdown-2023oct/index.md index 523402676..d501c259f 100644 --- a/site/en/blog/cookie-countdown-2023oct/index.md +++ b/site/en/blog/cookie-countdown-2023oct/index.md @@ -167,7 +167,7 @@ Primarily these are authentication or payment flows where a top-level site eithe **Next step:** We will publish an Intent to the blink-dev mailing list with further details in this month and continue to update documentation here. -## Reporting issues with third-party cookies and getting help +## Reporting issues with third-party cookies and getting help {: #report-issues } We want to ensure we are capturing the various scenarios where sites break without third-party cookies to ensure that we have provided guidance, tooling, and functionality to allow sites to migrate away from their third-party cookie dependencies. If your site or a service you depend on is breaking with third-party cookies disabled, you can submit it to our breakage tracker at [goo.gle/report-3pc-broken](https://goo.gle/report-3pc-broken). From 3b104447b806e58f74f3ec1553ce153399b60abe Mon Sep 17 00:00:00 2001 From: Veniamin Krol <153412+vkrol@users.noreply.github.com> Date: Thu, 12 Oct 2023 11:55:59 +0200 Subject: [PATCH 894/982] Replace irrelevant :scope documentation link in New in Chrome 118 (#7515) --- site/en/blog/new-in-chrome-118/index.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/site/en/blog/new-in-chrome-118/index.md b/site/en/blog/new-in-chrome-118/index.md index f23bad767..44d3d38c0 100644 --- a/site/en/blog/new-in-chrome-118/index.md +++ b/site/en/blog/new-in-chrome-118/index.md @@ -159,7 +159,7 @@ Like in the following example, we could apply style to the text and exclude cont } ``` -Checkout the [`@scope` documentation](https://developer.mozilla.org/docs/Web/CSS/:scope) for more information. +Checkout the article [Limit the reach of your selectors with the CSS @scope at-rule](/articles/at-scope/) for more information. ## `scripting` and `prefers-reduced-transparency` media features {: #new-media-queries } @@ -235,4 +235,4 @@ To stay up to date, [subscribe](https://goo.gl/6FP1a5) to the and you'll get an email notification whenever we launch a new video. Yo soy Adriana Jara, and as soon as Chrome 119 is released, I'll be right here to -tell you what's new in Chrome! \ No newline at end of file +tell you what's new in Chrome! From 1b0e2cf38c12d6370d9c8d3bf3b16116bfd9692a Mon Sep 17 00:00:00 2001 From: amysteamdev <37001393+AmySteam@users.noreply.github.com> Date: Thu, 12 Oct 2023 10:33:08 -0500 Subject: [PATCH 895/982] Fix list items in file a bug (#7526) * Fix list items * Update site/en/docs/extensions/support-feedback/file-a-bug/index.md --- .../support-feedback/file-a-bug/index.md | 21 +++++++++---------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/site/en/docs/extensions/support-feedback/file-a-bug/index.md b/site/en/docs/extensions/support-feedback/file-a-bug/index.md index 9e4a61bbc..6069558c7 100644 --- a/site/en/docs/extensions/support-feedback/file-a-bug/index.md +++ b/site/en/docs/extensions/support-feedback/file-a-bug/index.md @@ -12,16 +12,15 @@ tags: While developing an extension, you may find behavior that does not match the extension's documentation or is otherwise unexpected. This may be the result of a Chrome bug. Regardless, please let us know by filing an appropriate issue report. Please provide enough information to reproduce the issue by following these steps: 1. Before filing a bug, [search the Chromium issue tracker](/docs/extensions/support-feedback/find-a-bug) to verify that your issue hasn't already been reported. -1. Build a *minimal* test extension to demonstrate the issue to us. It should have as little code as possible—generally 100 lines or fewer— to demonstrate the bug. If you can't reproduce the bug in this space, it may indicate that the bug is in your own code. Consider searching for a solution or posting a question in the [Extensions Google Group](https://groups.google.com/a/chromium.org/group/chromium-extensions/topics). +1. Build a *minimal* test extension to demonstrate the issue to us. It should have as little code as possible—generally 100 lines or fewer— to demonstrate the bug. If you can't reproduce the bug in this space, it may indicate it is in your own code. Consider searching for a solution or posting a question in the [Extensions Google Group](https://groups.google.com/a/chromium.org/group/chromium-extensions/topics). 1. File an issue in [the issue tracker](https://crbug.com). Be as explicit as possible when filling out the bug. The easier it is to reproduce the issue, the greater the chance it will be fixed promptly. - - Choose a descriptive title. - - Specify the Chrome version and platform where you see the behavior. - - Explain the steps needed to reproduce the bug. - - Describe the expected and actual behavior. - - Add a link to your test extension. - - Add screenshots, if appropriate. - - If your bug relates to service worker lifetime behavior, include the section of the `chrome://extensions-internals` page relating to your extension. - - If your bug relates to a crash, upload it at `chrome://crashes` and share the crash ID. - + - Choose a descriptive title. + - Specify the Chrome version and platform where you see the behavior. + - Explain the steps needed to reproduce the bug. + - Describe the expected and actual behavior. + - Add a link to your test extension. + - Add screenshots, if appropriate. + - If your bug relates to service worker lifetime behavior, include the section of the `chrome://extensions-internals` page relating to your extension. + - If your bug relates to a crash, upload it at `chrome://crashes` and share the crash ID. 1. Wait for the bug to be updated. Most extension bugs are triaged within a week, although it can sometimes take longer. *Please do not reply to the bug requesting an update*. If your bug has not been modified after two weeks, please post a message to the [Google group](https://groups.google.com/a/chromium.org/group/chromium-extensions/topics) with a link to your bug. -1. If you originally reported your bug in the discussion group and were directed here, post a link to the issue you created or found in the discussion group thread. This makes it easier for others who encounter the same issue. \ No newline at end of file +1. If you originally reported your bug in the discussion group and were directed here, post a link to the issue you created or found in the discussion group thread. This makes it easier for others who encounter the same issue. From 8b26c8230af2c993c333d45632a602266dee106f Mon Sep 17 00:00:00 2001 From: Joe Medley <jmedley@google.com> Date: Thu, 12 Oct 2023 09:21:22 -0700 Subject: [PATCH 896/982] Update index.md (#7518) --- site/en/docs/extensions/mv3/tut_debugging/index.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/site/en/docs/extensions/mv3/tut_debugging/index.md b/site/en/docs/extensions/mv3/tut_debugging/index.md index 8b5f96e29..9bd9dc86f 100644 --- a/site/en/docs/extensions/mv3/tut_debugging/index.md +++ b/site/en/docs/extensions/mv3/tut_debugging/index.md @@ -1,7 +1,7 @@ --- layout: "layouts/doc-post.njk" -title: "Debugging extensions" -seoTitle: "Chrome extensions tutorial: debugging extensions" +title: "Debug extensions" +seoTitle: "Chrome extensions tutorial: debug extensions" date: 2012-09-18 updated: 2023-08-09 description: Instructions for debugging Chrome Extensions. @@ -16,7 +16,7 @@ Extensions can access the same [Chrome DevTools][chrome-devtools] as web pages. This guide assumes that you have basic web development experience. We recommend reading [Development Basics][doc-dev-basics] for an introduction to the extension development workflow and [Architecture overview][doc-arch] to learn about the different extension components. -## Breaking the extension {: #locate_logs } +## Break the extension {: #locate_logs } This tutorial will break one extension component at a time and then demonstrate how to fix it. Remember to undo the bugs introduced in one section before continuing to the next section. Start by downloading the [Broken Color sample][gh-broken-color] on GitHub. From 00a9203ac4ea70844b0be6a9f6c0525aa9770193 Mon Sep 17 00:00:00 2001 From: Oliver Dunk <oliverdunk@google.com> Date: Thu, 12 Oct 2023 17:40:59 +0100 Subject: [PATCH 897/982] Add documentation on testing Chrome Extensions (#7479) * Add documentation on testing Chrome Extensions * Address feedback * Seperate unit testing and end-to-end testing documentation * Add note on general capabilities of end-to-end testing libraries * Use Jest as test runner in Puppeteer tutorial * Address feedback * Link and table tweaks * Final tweaks * Update release date --------- Co-authored-by: amysteamdev <37001393+AmySteam@users.noreply.github.com> --- site/_data/docs/extensions/toc.yml | 3 + .../mv3/end-to-end-testing/index.md | 104 ++++++++++ .../mv3/tut_puppeteer-testing/index.md | 187 ++++++++++++++++++ .../docs/extensions/mv3/unit-testing/index.md | 66 +++++++ 4 files changed, 360 insertions(+) create mode 100644 site/en/docs/extensions/mv3/end-to-end-testing/index.md create mode 100644 site/en/docs/extensions/mv3/tut_puppeteer-testing/index.md create mode 100644 site/en/docs/extensions/mv3/unit-testing/index.md diff --git a/site/_data/docs/extensions/toc.yml b/site/_data/docs/extensions/toc.yml index dafcfb22b..69aa98c8e 100644 --- a/site/_data/docs/extensions/toc.yml +++ b/site/_data/docs/extensions/toc.yml @@ -82,6 +82,9 @@ - url: /docs/extensions/mv3/nativeMessaging - url: /docs/extensions/mv3/screen_capture - url: /docs/extensions/mv3/geolocation + - url: /docs/extensions/mv3/unit-testing + - url: /docs/extensions/mv3/end-to-end-testing + - url: /docs/extensions/mv3/tut_puppeteer-testing - title: i18n.docs.extensions.quality sections: - url: /docs/extensions/mv3/user_privacy diff --git a/site/en/docs/extensions/mv3/end-to-end-testing/index.md b/site/en/docs/extensions/mv3/end-to-end-testing/index.md new file mode 100644 index 000000000..04df61d87 --- /dev/null +++ b/site/en/docs/extensions/mv3/end-to-end-testing/index.md @@ -0,0 +1,104 @@ +--- +layout: "layouts/doc-post.njk" +title: "End-to-end testing for Chrome Extensions" +seoTitle: "End-to-end testing Chrome Extensions" +date: 2023-10-12 +description: How to write end-to-end tests for extensions. +--- + +End-to-end testing involves an extension package being built and loaded into a browser. A testing +tool communicates with the browser to automate interactions and test the same flows that a user +would go through. A library that supports end-to-end testing will generally provide ways of +controlling the browser, simulating user input and observing the current state of any open pages. + +See [Testing Chrome Extensions with Puppeteer][tutorial] for a tutorial and [Unit testing][unit-testing] for details on writing unit tests for Chrome extensions. + +## Using browser testing libraries {: #libraries } + +Extensions are supported by a range of testing libraries. + +| Library | Guidance | +|:------------------------|:-------------------------------------------------------------------------------------------------------------------------------------| +| Puppeteer / Playwright | See Chrome Extensions ([Puppeteer][puppeteer-testing] / [Playwright][playwright-testing]). | +| Selenium | Use the [ChromeOptions][selenium-chromeoptions] object to load extensions. More information is available [here][selenium-extensions]. | +| WebDriverIO | See [Web Extension Testing][webdriverio-testing]. | + +## Running tests in headless Chrome {: #headless } + +When running tests as part of an automated workflow, it is often necessary to load your extension on +a machine that does not have a screen. Chrome's [new headless][new-headless] mode allows Chrome to +be run in an unattended environment like this. Start Chrome using the `--headless=new` flag +(headless currently defaults to "old", which does not support loading extensions). Depending on the +automation tool you choose, there may be a setting that adds the flag for you automatically. + +## Setting an extension ID {: #set-extension-id } + +It is often desirable to have a fixed extension ID in tests. This makes many common tasks easier such as allow-listing the extension's origin on a server it needs to communicate with, or opening extension pages within tests. To do this, follow the steps under [Keeping a consistent extension ID][consistent-id]. + +## Testing extension pages {: #extension-pages } + +Extension pages can be accessed using their corresponding URL, e.g `chrome-extension://<id>/index.html`. Use the normal navigation methods available in your automation tool of choice to navigate to these URLs. + +## Testing an extension popup {: #extension-popup } + +Opening an extension popup in the context of another page is not currently possible. Instead, open the popup's URL in a new tab. If your popup uses the active tab, consider implementing an override where a tab ID can be passed explicitly to your popup. For example: + +```js +const URL_PARAMS = new URLSearchParams(window.location.search); + +async function getActiveTab() { + // Open popup.html?tab=5 to use tab ID 5, etc. + if (URL_PARAMS.has("tab")) { + return parseInt(URL_PARAMS.get("tab")); + } + + const tabs = await chrome.tabs.query({ + active: true, + currentWindow: true + }); + + return tabs[0]; +} +``` + +## Inspecting extension state {: #inspect-state } + +To avoid test failures when you change the internal behavior of your extension, it is generally best +practice to avoid accessing internal state in an integration test. Instead, you should base your +tests on what is visible to the user. However, it can sometimes be desirable to directly access data +from the extension. In these cases, consider executing code in the context of an extension page. + +In Puppeteer: + +```js +const workerTarget = await browser.waitForTarget( + target => target.type() === 'service_worker' +); +const worker = await workerTarget.worker(); + +const value = await worker.evaluate(() => { + chrome.storage.local.get('foo'); +}); +``` + +In Selenium: + +```js +// Selenium doesn't allow us to access the service worker, so we need to open an extension page where we can execute the code +await driver.get('chrome-extension://<id>/popup.html'); +await driver.executeAsyncScript( + 'const callback = arguments[arguments.length - 1];' + + 'chrome.storage.local.get(\'foo\').then(callback);' +); +``` + +[puppeteer-testing]: https://pptr.dev/guides/chrome-extensions +[playwright-testing]: https://playwright.dev/docs/chrome-extensions +[selenium-chromeoptions]: https://www.selenium.dev/documentation/webdriver/browsers/chrome/ +[selenium-extensions]: https://chromedriver.chromium.org/extensions +[webdriverio-testing]: https://webdriver.io/docs/extension-testing/web-extensions/ +[new-headless]: /articles/new-headless/ +[consistent-id]: /docs/extensions/mv3/manifest/key/#keep-consistent-id +[tutorial]: /docs/extensions/mv3/tut_puppeteer-testing/ +[unit-testing]: /docs/extensions/mv3/unit-testing + diff --git a/site/en/docs/extensions/mv3/tut_puppeteer-testing/index.md b/site/en/docs/extensions/mv3/tut_puppeteer-testing/index.md new file mode 100644 index 000000000..14eced76c --- /dev/null +++ b/site/en/docs/extensions/mv3/tut_puppeteer-testing/index.md @@ -0,0 +1,187 @@ +--- +layout: "layouts/doc-post.njk" +title: "Tutorial: Testing Chrome Extensions with Puppeteer" +seoTitle: "Tutorial: Testing Chrome Extensions with Puppeteer" +date: 2023-10-12 +description: How to write an automated test for Chrome Extensions using Puppeteer. +--- + +_For general advice on testing extensions, see +[End-to-end testing of Chrome Extensions][automated-testing] and [Unit testing in Chrome Extensions][unit-testing]._ + +[Puppeteer][puppeteer] provides a framework for building automated tests of websites, which also +includes the ability to test Chrome Extensions. These are high-level end-to-end tests that test the +functionality of a website or extension once it has been built into the final product. In this +tutorial, we demonstrate how to write a basic test for an extension from our samples repository. + +## Before you start {: #prereq } + +Clone or download the [chrome-extensions-samples][samples-repo] repository. We'll use the history +API demo in `api-samples/history/showHistory` as our test extension. + +You'll also need to install [Node.JS][node] which is the runtime Puppeteer is built on. + +## Writing your test {: #write-test } + +### Step 1: Start your Node.JS project {: #step-1 } + +We need to set up a basic Node.JS project. In a new folder, create a `package.json` file with the +following: + +{% Label %}pacakge.json:{% endLabel %} + +```js +{ + "name": "puppeteer-demo", + "version": "1.0" +} +``` + +Similar to an extension's `manifest.json` file, this file is required by all Node projects. + +### Step 2: Install Puppeteer and Jest {: #step-2 } + +Run `npm install puppeteer jest` to add Puppeteer and Jest as dependencies. They will be +automatically added to your `package.json` file. + +It is possible to write standalone Puppeteer tests, but we'll use Jest as a test runner to provide +some additional structure to our code. + +### Step 3: Create an entry point {: #step-3 } + +Create a new file called `index.test.js` and add the following code: + +{% Aside %} +Jest adds `beforeEach` and `afterEach` to our environment when running the tests, so we do not need +to import them. However, you may need to configure [ESLint][eslint] or [TypeScript][typescript] +accordingly. +{% endAside %} + +{% Label %}index.test.js:{% endLabel %} + +```js +const puppeteer = require('puppeteer'); + +const EXTENSION_PATH = '../../api-samples/history/showHistory'; +const EXTENSION_ID = 'jkomgjfbbjocikdmilgaehbfpllalmia'; + +let browser; + +beforeEach(async () => { + // TODO: Launch the browser. +}); + +afterEach(async () => { + // TODO: Close the browser. +}); +``` + +### Step 4: Launch the browser {: #step-4 } + +{% Aside %} +In this example, `headless` is set to `false`. This causes the browser window to be visible while +the tests are running which can be helpful during development. Outside of development, consider +setting it to `'new'` which uses Chrome's [new headless mode][new-headless]. +{% endAside %} + +Update `beforeEach` and `afterEach` to launch and close the browser. When running many tests, you +may wish to consider using the same browser. However, this is generally discouraged as it reduces +the isolation between your tests and may cause one test to impact the outcome of another. + +{% Label %}index.test.js:{% endLabel %} + +```js +beforeEach(async () => { + browser = await puppeteer.launch({ + headless: false, + args: [ + `--disable-extensions-except=${EXTENSION_PATH}`, + `--load-extension=${EXTENSION_PATH}` + ] + }); +}); + +afterEach(async () => { + await browser.close(); + browser = undefined; +}); +``` + +### Step 5: Add an alias {: #step-5 } + +To make running the tests easier, add an alias to your `package.json` file: + +{% Label %}package.json:{% endLabel %} + +```js +{ + "name": "puppeteer-demo", + "version": "1.0", + "dependencies": { + "puppeteer": "^21.3.6" + }, + "scripts": { + "start": "jest ." + } +} +``` + +This will run all files ending in `.test.js` in the current directory. + +### Step 6: Open the popup {: #step-6 } + +Let's add a basic test that opens the popup in a new page. We need to do this because Puppeteer +does not support accessing an extension popup from the popup window. Add the following code: + +{% Label %}index.test.js:{% endLabel %} + +```js +test('popup renders correctly', async () => { + const page = await browser.newPage(); + await page.goto(`chrome-extension://${EXTENSION_ID}/popup.html`); +}); +``` + +### Step 7: Assert the current state {: #step-7 } + +Let's assert something, so that our test can fail if the extension isn't behaving as expected. We +know that our popup should show recently visited pages, so let's check that we see one: + +{% Label %}index.test.js:{% endLabel %} + +```js +test('popup renders correctly', async () => { + const page = await browser.newPage(); + await page.goto(`chrome-extension://${EXTENSION_ID}/popup.html`); + + const list = await page.$('ul'); + const children = await list.$$('li'); + + expect(children.length).toBe(1); +}); +``` + +### Step 8: Run your test {: #step-8 } + +To run the test, use `npm start`. You should see output indicating that your test passed. + +You can see the [full project][full-project] in our chrome-extensions-samples repository. + +## Next Steps {: #next-steps } + +After mastering the basics, try building a test suite for your own extension. The Puppeteer +[API reference][api-reference] contains more information about what's possible - there are many +capabilities not described here. + +[automated-testing]: /docs/extensions/mv3/end-to-end-testing/ +[puppeteer]: https://github.com/puppeteer/puppeteer +[samples-repo]: https://github.com/GoogleChrome/chrome-extensions-samples +[node]: https://nodejs.org/ +[new-headless]: https://developer.chrome.com/articles/new-headless/ +[full-project]: https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/functional-samples/tutorial.puppeteer +[api-reference]: https://pptr.dev/api +[consistent-id]: /docs/extensions/mv3/automated-testing/#setting-an-extension-id +[eslint]: https://www.npmjs.com/package/eslint-plugin-jest +[typescript]: https://jestjs.io/docs/getting-started#type-definitions +[unit-testing]: /docs/extensions/mv3/unit-testing + diff --git a/site/en/docs/extensions/mv3/unit-testing/index.md b/site/en/docs/extensions/mv3/unit-testing/index.md new file mode 100644 index 000000000..9e3e586c7 --- /dev/null +++ b/site/en/docs/extensions/mv3/unit-testing/index.md @@ -0,0 +1,66 @@ +--- +layout: "layouts/doc-post.njk" +title: "Unit testing Chrome Extensions" +seoTitle: "Unit testing Chrome Extensions" +date: 2023-10-12 +description: How to write unit tests for extensions. +--- + +[Unit testing][unit-testing] allows small sections of code to be tested in isolation from the rest +of your extension, and outside of the browser. For example, you could write a unit test to ensure +that a helper method correctly writes a value to storage. + +Code written without using extension APIs can be tested as normal, using a framework such as +[Jest][jest]. To make code easier to test this way, consider using techniques such as +[dependency injection][dependency-injection] which can help to remove dependencies on the chrome +namespace in your lower level implementation. + +If you need to test code which includes extension APIs, consider using mocks. + +## Example: Using mocks with Jest {: #using-mocks } + +Create a `jest.config.js` file, which declares a setup file that will run before all tests: + +{% Label %}jest.config.js:{% endLabel %} + +```js +module.exports = { + setupFiles: ['<rootDir>/mock-extension-apis.js'] +}; +``` + +In `mock-extension-apis.js`, add implementations for the specific functions you expect to call: + +{% Label %}mock-extension-apis.js:{% endLabel %} + +```js +global.chrome = { + tabs: { + query: async () => { throw new Error("Unimplemented.") }; + } +}; +``` + +Then, use `jest.spy` to mock a return value in a test: + +```js +test("getActiveTabId returns active tab ID", async () => { + jest.spyOn(chrome.tabs, "query").mockResolvedValue([{ + id: 3, + active: true, + currentWindow: true + }]); + expect(await getActiveTabId()).toBe(3); +}); +``` + +## Next steps {: #continue } + +To ensure your extension functions as expected, we recommend adding [end-to-end tests][end-to-end]. See [Testing Chrome Extensions with Puppeteer][pupeteer-tutorial] for a complete tutorial. + +[unit-testing]: https://wikipedia.org/wiki/Unit_testing +[jest]: https://jestjs.io/ +[dependency-injection]: https://wikipedia.org/wiki/Dependency_injection +[pupeteer-tutorial]: /docs/extensions/mv3/tut_puppeteer-testing/ +[end-to-end]: /docs/extensions/mv3/end-to-end-testing/ + From b007fcafe549b4a922e9b8c3afb2012d352318fb Mon Sep 17 00:00:00 2001 From: Nancymic2 <nmichell@google.com> Date: Thu, 12 Oct 2023 14:43:25 -0400 Subject: [PATCH 898/982] Update API features statuses (#7480) * update API features statuses * bidding and auction update API features statuses * protected audience - update API features statuses * protected audience - update API features statuses * protected audience - update API features statuses * fix tabless * update API features statuses * update API features statuses * update date * date * update API features statusfor topics * Add Agg service to status page * Update fps-related website sets * Update first-party-sets.md * move related website sets in status doc * Link to PA status page from main status page * delete B&A partial * move B&A entry * edits * Update index.md --- .../timeline/aggregation-service.md | 17 ++++++ .../attribution-reporting-features.md | 18 +++--- .../timeline/fenced-frames-features.md | 41 ++++++++++--- .../timeline/first-party-sets.md | 6 +- .../timeline/fledge-features.md | 38 +++++++++--- .../timeline/private-aggregation-features.md | 23 +++++-- .../timeline/shared-storage-features.md | 10 ++++ .../timeline/topics-features.md | 2 +- .../aggregation-service/index.md | 6 +- .../attribution-reporting/index.md | 2 +- .../privacy-sandbox/fenced-frame/index.md | 2 +- .../feature-status/index.md | 60 +++++++++++++------ site/en/docs/privacy-sandbox/status/index.md | 16 +++-- 13 files changed, 181 insertions(+), 60 deletions(-) create mode 100644 site/en/_partials/privacy-sandbox/timeline/aggregation-service.md diff --git a/site/en/_partials/privacy-sandbox/timeline/aggregation-service.md b/site/en/_partials/privacy-sandbox/timeline/aggregation-service.md new file mode 100644 index 000000000..0dcdf9158 --- /dev/null +++ b/site/en/_partials/privacy-sandbox/timeline/aggregation-service.md @@ -0,0 +1,17 @@ +<table class="with-borders width-full simple fixed-table with-heading-tint"> + <thead> + <tr> + <th>Proposal</th> + <th>Status</th> + </tr> + </thead> + <tr> + <td>Aggregation Service support for Google Cloud Platform across Attribution Reporting API, Private Aggregation API <br><a href="https://github.com/WICG/attribution-reporting-api/blob/main/AGGREGATE.md#data-processing-through-a-secure-aggregation-service">Explainer</a></td> + <td>Expected in Q4 2023</td> + </tr> + <tr> + <td>Aggregation Service site enrollment and mapping of a site to cloud accounts (AWS, or GCP)<br><a href="https://github.com/privacysandbox/aggregation-service/issues/25">FAQs on GitHub</a></td> + <td>Expected in Q4 2023</td> + </tr> +</table> + diff --git a/site/en/_partials/privacy-sandbox/timeline/attribution-reporting-features.md b/site/en/_partials/privacy-sandbox/timeline/attribution-reporting-features.md index 34a5c648e..beed5d8b0 100644 --- a/site/en/_partials/privacy-sandbox/timeline/attribution-reporting-features.md +++ b/site/en/_partials/privacy-sandbox/timeline/attribution-reporting-features.md @@ -7,11 +7,11 @@ </thead> <tr> <td>Event-level reports for clicks and views<br><a href="https://github.com/WICG/conversion-measurement-api/blob/main/EVENT.md">Explainer</a></td> - <td>Now in general availability</td> + <td>Available in Chrome</td> </tr> <tr> <td>Aggregatable reports for clicks and views<br><a href="https://github.com/WICG/conversion-measurement-api/blob/main/AGGREGATE.md">Explainer</a></td> - <td>Now in general availability</td> + <td>Available in Chrome</td> </tr> <tr> <td>Conversion journey: app-to-web<br><a href="https://github.com/WICG/conversion-measurement-api/blob/main/app_to_web.md">Web explainer</a> and <a href="https://developer.android.com/design-for-safety/privacy-sandbox/attribution-app-to-web">Android explainer</a><br><a href="https://groups.google.com/u/0/a/chromium.org/g/attribution-reporting-api-dev/c/7cXZ4x62CmE">Mailing list announcement</a></td> @@ -23,27 +23,27 @@ </tr> <tr> <td>Preventing invalid aggregatable reports via report verification<br><a href="https://github.com/WICG/attribution-reporting-api/blob/main/report_verification.md">Explainer</a> </td> - <td>Expected in Chrome for origin trial in H1 2024</td> + <td>Expected in Chrome in H1 2024</td> </tr> <tr> <td>Support for multiple destinations in source registration<br><a href="https://bugs.chromium.org/p/chromium/issues/detail?id=1382389">Chromium Bug</a></td> - <td>Available in Chrome for origin trial in Q1 2023</td> + <td>Available in Chrome in Q1 2023</td> </tr> <tr> <td>Default allowlist for the Attribution Reporting API Permissions-Policy will remain *<br><a href="https://groups.google.com/a/chromium.org/g/attribution-reporting-api-dev/c/MV8gQ4sTc8w/">Mailing list announcement</a></td> - <td>Available in Chrome for origin trial in Q1 2023</td> + <td>Available in Chrome in Q1 2023</td> </tr> <tr> <td>Support for filter-based deduplication keys for aggregatable reports<br><a href="https://groups.google.com/a/chromium.org/g/attribution-reporting-api-dev/c/U-XsiJrxbRQ/">Mailing list announcement</a></td> - <td>Now in general availability</td> + <td>Available in Chrome in Q1 2023</td> </tr> <tr> <td>Support for source registration success reports in verbose debugging<br><a href="/docs/privacy-sandbox/attribution-reporting-debugging/part-3/#verbose-debug-report-of-type-source-success">Debugging cookbook</a></td> - <td>Now in general availability</td> + <td>Available in Chrome in Q1 2023</td> </tr> <tr> <td>Reducing delays for aggregatable reports<br><a href="https://github.com/WICG/attribution-reporting-api/issues/738">Github issue</a> | <a href="https://github.com/WICG/attribution-reporting-api/blob/main/AGGREGATE.md#aggregatable-reports">Updated Explainer</a></td> - <td>Now in general availability</td> + <td>Available in Chrome in Q2 2023</td> </tr> <tr> <td>Phase 1 Lite Flexible Event-Level<br><a href="https://github.com/WICG/attribution-reporting-api/blob/main/flexible_event_config.md#phase-1-lite-flexible-event-level">Flexible event-level configurations explainer</a></td> @@ -55,7 +55,7 @@ </tr> <tr> <td>Support for Attribution Reporting debugging after third-party cookie deprecation<br><a href="https://github.com/WICG/attribution-reporting-api/issues/705">Seeking feedback on GitHub</a></td> - <td>Expected in Chrome in H2 2023</td> + <td>Expected in Chrome in H1 2024</td> </tr> <tr> <td>Support for Attribution Reporting API and Aggregation Service for Google Cloud<br><a href="https://github.com/WICG/attribution-reporting-api/blob/main/AGGREGATE.md#data-processing-through-a-secure-aggregation-service">Attribution Reporting API Explainer</a><br><a href="https://github.com/WICG/attribution-reporting-api/blob/main/AGGREGATE.md#data-processing-through-a-secure-aggregation-service">Aggregation Service Explainer</a></td> diff --git a/site/en/_partials/privacy-sandbox/timeline/fenced-frames-features.md b/site/en/_partials/privacy-sandbox/timeline/fenced-frames-features.md index c3a807402..a195f462e 100644 --- a/site/en/_partials/privacy-sandbox/timeline/fenced-frames-features.md +++ b/site/en/_partials/privacy-sandbox/timeline/fenced-frames-features.md @@ -7,26 +7,53 @@ </thead> <tr> <td>Web API changes for urn to config<br><a href="https://github.com/WICG/fenced-frame/blob/master/explainer/fenced_frame_config.md">Explainer</a></td> - <td>Now in general availability. </td> + <td>Available in Chrome in Q1 2023.</td> </tr> <tr> <td>Add size to API for K-Anon check for URLs and Frame Size<br><a href="https://github.com/WICG/turtledove/issues/312">Github Issue</a></td> - <td>Now in general availability. </td> + <td>Available in Chrome in Q2 2023.</td> </tr> <tr> <td>Protected Audience Fenced Frames support for event-level reports with Attribution Reporting<br><a href="https://github.com/WICG/turtledove/issues/289">Github Issue</a></td> - <td>Now in general availability. </td> + <td>Available in Chrome in Q1 2023.</td> </tr> <tr> <td>Protected Audience, Fenced Frames, and Private Aggregation API support<br>urn-iframes reportEvent<br><a href="https://github.com/WICG/turtledove/issues/309">Github Issue</a></td> - <td>Now in general availability. </td> + <td>Available in Chrome in Q1 2023. +</td> </tr> <tr> <td>Protected Audience component ads reporting <br><a href="https://github.com/WICG/turtledove/issues/332">Github Issue</a></td> - <td>Now in general availability. </td> + <td>Available in Chrome in Q2 2023. +</td> </tr> <tr> - <td>Deprecate `src` attribute for the config attribute<br><a href="https://github.com/WICG/fenced-frame/blob/master/explainer/fenced_frame_config.md">Github Issue</a></td> - <td>Now in general availability. </td> + <td>Deprecate <code>src</code> attribute for the config attribute<br><a href="https://github.com/WICG/fenced-frame/blob/master/explainer/fenced_frame_config.md">Github Issue</a></td> + <td>Available in Chrome in Q2 2023.</td> </tr> + <tr> + <td>Creative Macros in Fenced Frames for Ads Reporting (FFAR)<br> +<a href="https://github.com/WICG/turtledove/pull/763">GitHub Issue</a></td> + <td>Available in Chrome in Q3 2023.</td> + </tr> + <tr> + <td>Send Automatic Beacons Once<br> +<a href="https://github.com/WICG/turtledove/pull/718">GitHub Issue</a></td> + <td>Available in Chrome in Q3 2023.</td> + </tr> + <tr> + <td>Serializable Fenced Frames Configs<br> +<a href="https://github.com/WICG/fenced-frame/pull/111">GitHub Issue</a> </td> + <td>Available in Chrome in Q3 2023.</td> + </tr> + <tr> + <td>Additional Fortmat Option for Protected Audience Ad Size Macros<br> +<a href="https://github.com/WICG/turtledove/pull/417">GitHub Issue</a></td> + <td>Available in Chrome in Q4 2023.</td> + </tr> + <tr> + <td>Automatic beacons sending to all registered URLs<br> +<a href="https://github.com/WICG/fenced-frame/pull/122">GitHub Issue</a>, <a href="https://github.com/WICG/turtledove/pull/808">GitHub Issue</a></td> + <td>Available in Chrome in Q4 2023.</td> + </tr> </table> diff --git a/site/en/_partials/privacy-sandbox/timeline/first-party-sets.md b/site/en/_partials/privacy-sandbox/timeline/first-party-sets.md index d81826b52..b9f33840f 100644 --- a/site/en/_partials/privacy-sandbox/timeline/first-party-sets.md +++ b/site/en/_partials/privacy-sandbox/timeline/first-party-sets.md @@ -1,6 +1,6 @@ -* First-Party Sets is in incubation in [WICG](https://github.com/WICG/first-party-sets/issues) -* The first [origin trial](/docs/web-platform/origin-trials/) ran from Chrome 89 to 93. +* Related Website Sets (formerly First-Party Sets) is in incubation in [WICG](https://github.com/WICG/first-party-sets/issues) +* The first [origin trial](https://web.dev/origin-trials/) ran from Chrome 89 to 93. * [Chrome Platform Status](https://chromestatus.com/feature/5640066519007232). * [Blink status](https://groups.google.com/a/chromium.org/g/blink-dev/search?q=first-party%20sets). * [Chromium Projects](https://www.chromium.org/updates/first-party-sets) -* [First-Party Sets submission guidelines](https://github.com/GoogleChrome/first-party-sets/blob/main/FPS-Submission_Guidelines.md) +* [Related Website Sets submission guidelines](https://github.com/GoogleChrome/first-party-sets/blob/main/FPS-Submission_Guidelines.md) diff --git a/site/en/_partials/privacy-sandbox/timeline/fledge-features.md b/site/en/_partials/privacy-sandbox/timeline/fledge-features.md index ec9ca7654..d82e31f44 100644 --- a/site/en/_partials/privacy-sandbox/timeline/fledge-features.md +++ b/site/en/_partials/privacy-sandbox/timeline/fledge-features.md @@ -7,38 +7,58 @@ </thead> <tr> <td>Per-Buyer Latency Reporting<br><a href="https://github.com/WICG/turtledove/issues/299">Github Issue</a></td> - <td>Available in Chrome for origin trial in Q1 2023</td> + <td>Available in Chrome in Q1 2023</td> </tr> <tr> <td>Direct Seller Destination Support<br><a href="https://github.com/WICG/turtledove/issues/441">Github Issue</a></td> - <td>Available in Chrome for origin trial in Q1 2023</td> + <td>Available in Chrome in Q1 2023</td> </tr> <tr> <td>Per-Buyer Wall-Time Timeout <br><a href="https://github.com/WICG/turtledove/issues/293">Github Issue</a></td> - <td>Available in Chrome for origin trial in Q1 2023</td> + <td>Available in Chrome in Q1 2023</td> </tr> <tr> <td>Accuracy-limited ad cost for cost-per-click billing <br><a href="https://github.com/WICG/turtledove/issues/356">Github Issue</a></td> - <td>Available in Chrome for origin trial in Q2 2023</td> + <td>Available in Chrome in Q2 2023</td> </tr> <tr> <td>Event-level User Bidding Signals for Modeling <br><a href="https://github.com/WICG/turtledove/issues/435">Github Issue</a></td> - <td>Available in Chrome for origin trial in Q2 2023</td> + <td>Available in Chrome in Q2 2023</td> </tr> <tr> <td>Buyer Reporting ID for Custom Breakdowns<br><a href="https://github.com/WICG/turtledove/issues/165">Github Issue</a></td> - <td>Expected in Chrome for origin trial in Q3 2023</td> + <td>Available in Chrome in Q3 2023</td> </tr> <tr> <td>Currency for Highest and bid Highest Other Scoring Bid<br><a href="https://github.com/WICG/turtledove/issues/166">Github Issue</a></td> - <td>Expected in Chrome for origin trial in Q3 2023</td> + <td>Available in Chrome in Q3 2023</td> </tr> <tr> <td>Macro Support for Third-party Ad Trackers (3PAT)<br><a href="https://github.com/WICG/turtledove/issues/477">Github Issue</a></td> - <td>Expected in Chrome in Q3 2023</td> + <td>Available in Chrome in Q3 2023</td> </tr> <tr> <td>Support for Negative Interest Group Targeting<br><a href="https://github.com/WICG/turtledove/issues/319">Github Issue</a></td> - <td>Expected in Chrome in Q3 2023</td> + <td>Expected in Chrome in Q4 2023</td> </tr> + <tr> + <td>Secure Propagation of Auction Signals without WebBundles<br> +<a href="https://github.com/WICG/turtledove/issues/119">Github Issue</a></td> + <td>Expected in Chrome in Q4 2023</td> + </tr> + <tr> + <td>Bulk Interest Group Deletion<br> +<a href="https://github.com/WICG/turtledove/issues/475">Github Issue</a></td> + <td>Expected in Chrome in Q4 2023</td> + </tr> + <tr> + <td>Increase Interest Group Cap from 1K to 2K<br> +<a href="https://github.com/WICG/turtledove/issues/798">Github Issue</a></td> + <td>Expected in Chrome in Q4 2023</td> + </tr> + <tr> + <td>Support for Bidding and Auction Beta 1 <br> +<a href="https://github.com/privacysandbox/fledge-docs/blob/main/bidding_auction_services_api.md#beta-1-november-2023">Explainer</a></td> + <td>Expected in Chrome (via Origin Trial) in Q4 2023</td> + </tr> </table> diff --git a/site/en/_partials/privacy-sandbox/timeline/private-aggregation-features.md b/site/en/_partials/privacy-sandbox/timeline/private-aggregation-features.md index 8ff3d882c..431a8e9c2 100644 --- a/site/en/_partials/privacy-sandbox/timeline/private-aggregation-features.md +++ b/site/en/_partials/privacy-sandbox/timeline/private-aggregation-features.md @@ -7,18 +7,33 @@ </thead> <tr> <td>Support for debugging mode and testing of reporting aggregation with the debug mode and local testing tool<br><a href="/docs/privacy-sandbox/private-aggregation/#enabledebugmode">Private Aggregation API documentation</a></td> - <td>Available in Chrome for origin trial in Q2 2023</td> + <td>Available in Chrome in Q2 2023</td> </tr> <tr> <td>Private Aggregation API available for origin trial testing in Chrome stable channel<br><a href="https://github.com/patcg-individual-drafts/private-aggregation-api">Explainer</a></td> - <td>Now in general availability</td> + <td>Available in Chrome in Q2 2023</td> </tr> <tr> <td>Prevent invalid Private Aggregation API reports with report verification for Shared Storage<br><a href="https://github.com/patcg-individual-drafts/private-aggregation-api/blob/main/report_verification.md">Explainer</a></td> - <td>Now in general availability</td> + <td>Available in Chrome in Q2 2023</td> </tr> <tr> <td>Private Aggregation debug mode availability dependent on 3PC eligibility<br><a href="https://github.com/patcg-individual-drafts/private-aggregation-api/issues/57">GitHub issue</a></td> - <td>Expected in Chrome in H2 2023</td> + <td>Expected in Chrome in Q4 2023</td> </tr> + <tr> + <td>Reducing report delay<br> +<a href="https://github.com/patcg-individual-drafts/private-aggregation-api/blob/main/report_verification.md#reduced-delay">Explainer</a></td> + <td>Expected in Chrome Q4 2023</td> + </tr> + <tr> + <td>Support for Private Aggregation API and Aggregation Service for Google Cloud<br> +<a href="https://github.com/patcg-individual-drafts/private-aggregation-api#aggregation-coordinator-choice">Explainer</a></td> + <td>Expected in Chrome Q4 2023</td> + </tr> + <tr> + <td>Padding for aggregatable report payloads<br> +<a href="https://github.com/patcg-individual-drafts/private-aggregation-api#padding">Explainer</a></td> + <td>Expected in Chrome Q4 2023</td> + </tr> </table> diff --git a/site/en/_partials/privacy-sandbox/timeline/shared-storage-features.md b/site/en/_partials/privacy-sandbox/timeline/shared-storage-features.md index e92180a07..87bc9363d 100644 --- a/site/en/_partials/privacy-sandbox/timeline/shared-storage-features.md +++ b/site/en/_partials/privacy-sandbox/timeline/shared-storage-features.md @@ -9,4 +9,14 @@ <td><a href="https://github.com/WICG/shared-storage#event-level-reporting">Event-level reporting</a> for Content Selection (<code>selectURL()</code>)</td> <td>Available until at least 2026</td> </tr> + <tr> + <td>Per-site budgeting<br> +<a href="https://github.com/WICG/shared-storage#outside-the-worklet">Explainer</a></td> + <td>Expected in Chrome Q4 2023</td> + </tr> + <tr> + <td>Allow writing from response headers<br> +<a href="https://github.com/WICG/shared-storage/blob/main/README.md#from-response-headers">Explainer</a></td> + <td>Expected in Chrome Q4 2023</td> + </tr> </table> diff --git a/site/en/_partials/privacy-sandbox/timeline/topics-features.md b/site/en/_partials/privacy-sandbox/timeline/topics-features.md index d65489f5f..85854a123 100644 --- a/site/en/_partials/privacy-sandbox/timeline/topics-features.md +++ b/site/en/_partials/privacy-sandbox/timeline/topics-features.md @@ -8,7 +8,7 @@ <tbody> <tr> <td><a href="https://github.com/patcg-individual-drafts/topics/blob/main/taxonomy_v2.md">Improved taxonomy for Topics</a> (latest <a href="https://groups.google.com/a/chromium.org/g/topics-api-announce/c/iNYk69wKnJs/m/yrVCBHvXAQAJ">note</a>)</td> - <td>Expected in Chrome in Q3 2023.</td> + <td>Expected in Chrome in Q4 2023.</td> </tr> </tbody> </table> diff --git a/site/en/docs/privacy-sandbox/aggregation-service/index.md b/site/en/docs/privacy-sandbox/aggregation-service/index.md index 74d8df783..de684aaf5 100644 --- a/site/en/docs/privacy-sandbox/aggregation-service/index.md +++ b/site/en/docs/privacy-sandbox/aggregation-service/index.md @@ -8,7 +8,7 @@ description: > Deploy and manage this service to produce summary reports for the Attribution Reporting API or the Private Aggregation API. date: 2022-11-29 -updated: 2023-09-18 +updated: 2023-10-09 authors: - alexandrawhite --- @@ -30,6 +30,10 @@ The explainer outlines [key terms](https://github.com/WICG/attribution-reporting-api/blob/main/AGGREGATION_SERVICE_TEE.md#key-terms), useful for understanding the Aggregation Service. +### Availability + +{% Partial 'privacy-sandbox/timeline/aggregation-service.njk' %} + ## Secure data processing The Aggregation Service decrypts and combines the collected data from the aggregatable reports, [adds noise](#noise-scale), and returns the final summary report. This service runs in a trusted execution environment (TEE), which is deployed on a cloud service that supports necessary security measures to protect this data. diff --git a/site/en/docs/privacy-sandbox/attribution-reporting/index.md b/site/en/docs/privacy-sandbox/attribution-reporting/index.md index 8d85de186..fc40f57b4 100644 --- a/site/en/docs/privacy-sandbox/attribution-reporting/index.md +++ b/site/en/docs/privacy-sandbox/attribution-reporting/index.md @@ -8,7 +8,7 @@ description: > Measure when an ad click or view leads to a conversion, such as a purchase on an advertiser site. date: 2021-05-18 -updated: 2023-09-18 +updated: 2023-10-09 authors: - maudn - alexandrawhite diff --git a/site/en/docs/privacy-sandbox/fenced-frame/index.md b/site/en/docs/privacy-sandbox/fenced-frame/index.md index 0b329804b..c9d5f4aa0 100644 --- a/site/en/docs/privacy-sandbox/fenced-frame/index.md +++ b/site/en/docs/privacy-sandbox/fenced-frame/index.md @@ -10,7 +10,7 @@ authors: - alexandrawhite - kevinkiklee date: 2022-03-07 -updated: 2023-09-18 +updated: 2023-10-09 --- ## Implementation status diff --git a/site/en/docs/privacy-sandbox/protected-audience-api/feature-status/index.md b/site/en/docs/privacy-sandbox/protected-audience-api/feature-status/index.md index 21c0e9b50..040cec630 100644 --- a/site/en/docs/privacy-sandbox/protected-audience-api/feature-status/index.md +++ b/site/en/docs/privacy-sandbox/protected-audience-api/feature-status/index.md @@ -8,7 +8,7 @@ description: > Learn more about Protected Audience API auction features as we approach third-party cookie deprecation. date: 2023-02-09 -updated: 2023-06-01 +updated: 2023-10-09 authors: - tristramsouthey - kevinkiklee @@ -91,52 +91,76 @@ find a list of the scoped Protected Audience API features and when they'll be su </thead> <tr> <td>Event-level user bidding signals for modeling (<a href="https://github.com/WICG/turtledove/issues/435">Github Issue</a>)</td> - <td>Later in 2023</td> - <td>Available in Chrome for origin trial in Q2 2023.</td> + <td>2023</td> + <td>Available in Chrome in Q2 2023.</td> </tr> <tr> <td><a href="https://github.com/WICG/turtledove/issues/299">Per-Buyer Latency Reporting</a></td> - <td>Later in 2023</td> - <td>Available in Chrome for origin trial in Q1 2023.</td> + <td>2023</td> + <td>Available in Chrome in Q1 2023.</td> </tr> <tr> <td><a href="https://github.com/WICG/turtledove/issues/293">Per-buyer wall-time timeout</a></td> - <td>Later in 2023</td> - <td>Available in Chrome for origin trial in Q1 2023.</td> + <td>2023</td> + <td>Available in Chrome in Q1 2023.</td> </tr> <tr> <td><a href="https://github.com/WICG/turtledove/issues/165">Buyer reporting ID for custom breakdowns</a></td> - <td>Later in 2023</td> - <td>Expected in Chrome for origin trial in Q3 2023.</td> + <td>2023</td> + <td>Available in Chrome in Q3 2023.</td> </tr> <tr> <td><a href="https://github.com/WICG/turtledove/issues/441">Direct seller destination support</a></td> - <td>Later in 2023</td> - <td>Available in Chrome for origin trial in Q1 2023.</td> + <td>2023</td> + <td>Available in Chrome in Q1 2023.</td> </tr> <tr> <td><a href="https://github.com/WICG/turtledove/issues/356">Accuracy-limited ad cost for cost-per-click billing</a></td> - <td>Later in 2023</td> - <td>Available in Chrome for origin trial in Q2 2023.</td> + <td>2023</td> + <td>Available in Chrome in Q2 2023.</td> </tr> <tr> <td><a href="https://github.com/WICG/turtledove/issues/166">Currency for highest bid and highest other scoring bid</a> </td> - <td>Later in 2023</td> - <td>Expected in Chrome for origin trial in Q3 2023.</td> + <td>2023</td> + <td>Available in Chrome in Q3 2023.</td> </tr> <tr> <td><a href="https://github.com/WICG/turtledove/issues/477">Macro Support for Third-party Ad Trackers (3PAT)</a> </td> - <td>Later in 2023</td> - <td>Expected in Chrome in Q3 2023.</td> + <td>2023</td> + <td>Available in Chrome in Q3 2023.</td> </tr> <tr> <td><a href="https://github.com/WICG/turtledove/issues/319">Support for Negative Interest Group Targeting</a> </td> <td>Later in 2023</td> - <td>Expected in Chrome in Q3 2023.</td> + <td>Expected in Chrome in Q4 2023.</td> </tr> + <tr> + <td>Secure Propagation of Auction Signals without WebBundles<br> +<a href="https://github.com/WICG/turtledove/issues/119">Github Issue</a></td> + <td>Later in 2023</td> + <td>Expected in Chrome in Q4 2023</td> + </tr> + <tr> + <td>Bulk Interest Group Deletion<br> +<a href="https://github.com/WICG/turtledove/issues/475">Github Issue</a></td> + <td>Later in 2023</td> + <td>Expected in Chrome in Q4 2023</td> + </tr> + <tr> + <td>Increase Interest Group Cap from 1K to 2K<br> +<a href="https://github.com/WICG/turtledove/issues/798">Github Issue</a></td> + <td>Later in 2023</td> + <td>Expected in Chrome in Q4 2023</td> + </tr> + <tr> + <td>Support for Bidding and Auction Beta 1 <br> +<a href="https://github.com/privacysandbox/fledge-docs/blob/main/bidding_auction_services_api.md#beta-1-november-2023">Explainer</a></td> + <td>Origin Trial, later in 2023</td> + <td>Expected in Chrome (via Origin Trial) in Q4 2023</td> + </tr> </table> ## Event-level auction win reporting diff --git a/site/en/docs/privacy-sandbox/status/index.md b/site/en/docs/privacy-sandbox/status/index.md index 60c18ffa7..d0c0e9ab7 100644 --- a/site/en/docs/privacy-sandbox/status/index.md +++ b/site/en/docs/privacy-sandbox/status/index.md @@ -8,7 +8,7 @@ description: > Review Chrome platform status, resources, and feature release timelines. date: 2021-05-18 -updated: 2023-07-03 +updated: 2023-10-09 authors: - alexandrawhite --- @@ -19,6 +19,10 @@ different expected availability. To review the latest information on any proposal or API, visit the respective overview documentation and the [Privacy Sandbox timeline](https://privacysandbox.com/open-web/). +## Aggregation Service + +{% Partial 'privacy-sandbox/timeline/aggregation-service.njk' %} + ## Attribution Reporting {% Partial 'privacy-sandbox/timeline/attribution-reporting.njk' %} @@ -43,10 +47,6 @@ To review the latest information on any proposal or API, visit the respective ov {% Partial 'privacy-sandbox/timeline/fenced-frames-features.njk' %} -## First-Party Sets - -{% Partial 'privacy-sandbox/timeline/first-party-sets.njk' %} - ## IP Protection {% Partial 'privacy-sandbox/timeline/ip-protection.njk' %} @@ -64,12 +64,16 @@ To review the latest information on any proposal or API, visit the respective ov ## Protected Audience Descendant of [TURTLEDOVE](https://github.com/WICG/turtledove). Formerly -named FLEDGE. +named FLEDGE. Also refer to [Status of pending Protected Audience API capabilities](/docs/privacy-sandbox/protected-audience-api/feature-status/) for more information. {% Partial 'privacy-sandbox/timeline/fledge.njk' %} {% Partial 'privacy-sandbox/timeline/fledge-features.njk' %} +## Related Website Sets (formerly First-Party Sets) + +{% Partial 'privacy-sandbox/timeline/first-party-sets.njk' %} + ## Shared Storage {% Partial 'privacy-sandbox/timeline/shared-storage.njk' %} From 7d06991b3bf02a9d6ff6b4b9fec7c09b3ac318f8 Mon Sep 17 00:00:00 2001 From: Mike Taylor <miketaylr@chromium.org> Date: Thu, 12 Oct 2023 14:47:26 -0400 Subject: [PATCH 899/982] Update Storage Partitioning articles to reflect feature status (#7512) Fixes #7511 Co-authored-by: Kevin K. Lee <kevinkiklee@google.com> --- .../index.md | 5 +++-- .../index.md | 15 +++++++-------- .../storage-partitioning/index.md | 17 +++++------------ 3 files changed, 15 insertions(+), 22 deletions(-) diff --git a/site/en/blog/storage-partitioning-deprecation-trial-extended/index.md b/site/en/blog/storage-partitioning-deprecation-trial-extended/index.md index 2b108f23b..88b881124 100644 --- a/site/en/blog/storage-partitioning-deprecation-trial-extended/index.md +++ b/site/en/blog/storage-partitioning-deprecation-trial-extended/index.md @@ -2,7 +2,7 @@ layout: 'layouts/blog-post.njk' title: Storage partitioning deprecation trial extended description: > - Sites that haven't had time to adapt their sites for third-party storage partitioning can take part in a deprecation trial to temporarily unpartition and restore prior behavior of storage, service workers, and communication APIs in content embedded on their site. + Sites that haven't had time to adapt their sites for third-party storage partitioning can take part in a deprecation trial to temporarily unpartition and restore prior behavior of storage, service workers, and communication APIs in content embedded on their site. subhead: > The deprecation trial will now be available until the release of Chrome 127, scheduled for September 3, 2024. date: 2023-06-09 @@ -14,7 +14,8 @@ tags: --- To prevent certain types of side-channel cross-site tracking, -[Chrome is partitioning storage and communications APIs in third-party contexts](/docs/privacy-sandbox/storage-partitioning/). +[Chrome has partitioned storage and communications APIs in third-party contexts](/docs/privacy-sandbox/storage-partitioning/) +in Chrome 115 and above. Sites that haven't had time to adapt their sites for third-party storage partitioning can take part in a deprecation trial to temporarily unpartition and diff --git a/site/en/blog/storage-partitioning-deprecation-trial/index.md b/site/en/blog/storage-partitioning-deprecation-trial/index.md index e5af1882e..302edbd8a 100644 --- a/site/en/blog/storage-partitioning-deprecation-trial/index.md +++ b/site/en/blog/storage-partitioning-deprecation-trial/index.md @@ -12,11 +12,11 @@ tags: - privacy --- -Beginning gradually in [Chrome 115](https://chromiumdash.appspot.com/schedule), -storage, service workers, and communication APIs will be +As of [Chrome 115](https://chromiumdash.appspot.com/schedule), storage, +service workers, and communication APIs are be [partitioned in third-party contexts](/docs/privacy-sandbox/storage-partitioning/). In addition to being isolated by the same-origin policy, the affected APIs used -in third-party contexts would also be separated by the site of the top-level +in third-party contexts are also be separated by the site of the top-level context. Sites that haven't had time to implement support for third-party storage partitioning can take part in a deprecation trial to temporarily **unpartition** (continue isolation by same-origin policy but remove isolation @@ -104,8 +104,7 @@ on its pages, top-level sites need to register for one or both of the deprecation trials and add the corresponding trial token(s) to their HTTP response headers (see detailed example below). -Each deprecation trial is available on Windows, Mac, Linux, Chrome OS, Android, -and Android WebView. +Each deprecation trial is available on Windows, Mac, Linux, Chrome OS, and Android. ## Participate in the deprecation trials @@ -128,12 +127,12 @@ deprecation trials. For more detailed instructions, visit navigations: [`DisableThirdPartySessionStoragePartitioningAfterGeneralPartitioning`](/origintrials/#/view_trial/3444127815031586817) 1. Add an origin trial token to your page: - 1. For the `DisableThirdPartySessionStoragePartitioningAfterGeneralPartitioning` trial you may add an `Origin-Trial: <DEPRECATION TRIAL TOKEN>` to your top-level site’s HTTP response header, where `<DEPRECATION TRIAL TOKEN>` contains the token you got when registering for the deprecation trial. You can also do this via HTML `<meta> tag. - 1. For the `DisableThirdPartyStoragePartitioning` trial, the token must be given via an HTML `<meta>` tag. The HTTP header method is not supported. + 1. For the `DisableThirdPartySessionStoragePartitioningAfterGeneralPartitioning` trial you may add an `Origin-Trial: <DEPRECATION TRIAL TOKEN>` to your top-level site’s HTTP response header, where `<DEPRECATION TRIAL TOKEN>` contains the token you got when registering for the deprecation trial. You can also do this via HTML `<meta> tag. + 1. For the `DisableThirdPartyStoragePartitioning` trial, the token must be given via an HTML `<meta>` tag injected via JavaScript. The HTTP header method is not supported. 1. Load your website in Chrome 115 (or later) with `ThirdPartyStoragePartitioning` still enabled and verify that any partitioning related issues have been properly mitigated. -1. To stop participating in the deprecation trial simply remove the header +1. To stop participating in the deprecation trial simply remove the token you added in step 2. The `DisableThirdPartyStoragePartitioning` deprecation trial does support the diff --git a/site/en/docs/privacy-sandbox/storage-partitioning/index.md b/site/en/docs/privacy-sandbox/storage-partitioning/index.md index f1507171b..881674208 100644 --- a/site/en/docs/privacy-sandbox/storage-partitioning/index.md +++ b/site/en/docs/privacy-sandbox/storage-partitioning/index.md @@ -16,17 +16,11 @@ tags: ## Implementation status -- Full implementation is available for testing in Chrome Beta 113 and later. -- The initial implementation has been [available behind a flag since Chrome 105](/blog/storage-partitioning-dev-trial/). +- The feature has shipped in Chrome 115 and later. - [Storage Partitioning proposal](https://github.com/privacycg/storage-partitioning) is open for discussion. - [Chrome Platform Status](https://chromestatus.com/feature/5723617717387264) - -The feature is rolling out to a small percentage of users starting in Chrome 113. -Depending on the stability and compatibility, it will be made fully available in -Chrome Stable mid-year 2023. Testing third-party storage partitioning now -and filing bugs will help uncover any potential issues and resolve them before -the full rollout. +The feature has been enabled for all users on Chrome 115 and later. ## What is storage partitioning? @@ -87,7 +81,7 @@ To try it out: 1. Use Chrome Canary version 113 or higher. 1. Visit `chrome://flags/#third-party-storage-partitioning`. -1. Enable the "Experimental Third-party Storage Partitioning" flag. +1. Enable the "Third-party Storage Partitioning" flag. Participate in testing and [report bugs](https://bugs.chromium.org/p/chromium/issues/entry?labels=StoragePartitioning-trial-bugs&components=Blink%3EStorage) @@ -207,11 +201,10 @@ For more information, see the [extension docs](/docs/extensions/mv3/storage-and- ## Engage and share feedback -The shared storage proposal is under active discussion and subject to change in -the future. If you try these APIs and have feedback, we'd love to hear it. - - **GitHub**: Read the [proposal](https://github.com/wanderview/quota-storage-partitioning/blob/main/explainer.md), [raise questions and participate in discussion](https://github.com/wanderview/quota-storage-partitioning/issues). - **Developer support**: Ask questions and join discussions on the [Privacy Sandbox Developer Support repo](https://github.com/GoogleChromeLabs/privacy-sandbox-dev-support). +- **File bugs**: File a bug in the [Chromium tracker](https://bugs.chromium.org/p/chromium/issues/entry?labels=StoragePartitioning-trial-bugs&components=Blink%3EStorage) + if you believe something is not working as expected. From f3a5515a3d90aef91e9050c450400e207da5b3eb Mon Sep 17 00:00:00 2001 From: Joe Medley <jmedley@google.com> Date: Thu, 12 Oct 2023 14:22:37 -0700 Subject: [PATCH 900/982] Update index.md (#7516) --- site/en/docs/extensions/mv3/tut_websockets/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/en/docs/extensions/mv3/tut_websockets/index.md b/site/en/docs/extensions/mv3/tut_websockets/index.md index a2e3cf341..ab129f27a 100644 --- a/site/en/docs/extensions/mv3/tut_websockets/index.md +++ b/site/en/docs/extensions/mv3/tut_websockets/index.md @@ -1,6 +1,6 @@ --- layout: 'layouts/doc-post.njk' -title: 'Using WebSockets in Service Workers' +title: 'Use WebSockets in service workers' seoTitle: 'How to use WebSockets in Chrome extension Service Workers' date: 2023-07-04 description: 'Step-by-step instructions on how to connect to a WebSocket in your Chrome extension.' From 3eddaaa259d505d231008e3335a5ca305a4eb696 Mon Sep 17 00:00:00 2001 From: Anusmita <anusmitaray@google.com> Date: Fri, 13 Oct 2023 09:57:36 +0100 Subject: [PATCH 901/982] Move permissions policy to articles (#7523) * Move permissions policy * Add redirect --- redirects.yaml | 3 +++ site/_data/docs/privacy-sandbox/toc.yml | 3 --- .../privacy-sandbox => articles}/permissions-policy/index.md | 3 +++ 3 files changed, 6 insertions(+), 3 deletions(-) rename site/en/{docs/privacy-sandbox => articles}/permissions-policy/index.md (99%) diff --git a/redirects.yaml b/redirects.yaml index ad3d497ce..266eadb8d 100644 --- a/redirects.yaml +++ b/redirects.yaml @@ -779,6 +779,9 @@ redirects: - from: docs/extensions/mv3/single_purpose/ to: docs/extensions/mv3/quality_guidelines/ +- from: /docs/privacy-sandbox/permissions-policy/ + to: /articles/permissions-policy/ + # DO NOT REMOVE. This seems pointless but we rewrite "." to "_" inside our server's code, so if the # URL is fine for all but incorrect syntax, we'll fix it up. - from: /... diff --git a/site/_data/docs/privacy-sandbox/toc.yml b/site/_data/docs/privacy-sandbox/toc.yml index 97859a3b7..45968685b 100644 --- a/site/_data/docs/privacy-sandbox/toc.yml +++ b/site/_data/docs/privacy-sandbox/toc.yml @@ -41,9 +41,6 @@ - url: /docs/privacy-sandbox/fedcm-developer-guide - url: /docs/privacy-sandbox/fedcm-updates - title: i18n.docs.privacy-sandbox.control-browser-features - sections: - - url: /docs/privacy-sandbox/permissions-policy - title: i18n.docs.privacy-sandbox.permissions-policy - url: /docs/privacy-sandbox/shared-storage - url: https://goo.gle/shared-storage-walkthrough title: i18n.docs.privacy-sandbox.shared-storage-walkthrough diff --git a/site/en/docs/privacy-sandbox/permissions-policy/index.md b/site/en/articles/permissions-policy/index.md similarity index 99% rename from site/en/docs/privacy-sandbox/permissions-policy/index.md rename to site/en/articles/permissions-policy/index.md index b95f0417f..850701918 100644 --- a/site/en/docs/privacy-sandbox/permissions-policy/index.md +++ b/site/en/articles/permissions-policy/index.md @@ -8,6 +8,9 @@ description: > date: 2022-04-20 authors: - kevinkiklee +tags: + - monitoring + - security --- Permissions Policy, formerly known as Feature Policy, allows the developer to From 9ebf9cb8bfb370edc8d3aa19e53fc1fd56598c55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Beaufort?= <beaufort.francois@gmail.com> Date: Fri, 13 Oct 2023 13:01:24 +0200 Subject: [PATCH 902/982] Add Serial over Bluetooth blog post (#7531) * Add Serial over Bluetooth blog post * Update index.md --- site/en/blog/serial-over-bluetooth/index.md | 109 ++++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 site/en/blog/serial-over-bluetooth/index.md diff --git a/site/en/blog/serial-over-bluetooth/index.md b/site/en/blog/serial-over-bluetooth/index.md new file mode 100644 index 000000000..856f800cd --- /dev/null +++ b/site/en/blog/serial-over-bluetooth/index.md @@ -0,0 +1,109 @@ +--- +layout: "layouts/blog-post.njk" +title: "Serial over Bluetooth on the web" +description: "The Web Serial API added support for Bluetooth RFCOMM services." +hero: "image/vvhSqZboQoZZN9wBvoXq72wzGAf1/uabT6SZieVHZgpYLsnF2.jpg" +alt: "A human hand holding Google Pixel Buds Pro charging case." +date: 2023-10-13 +#updated: YYYY-MM-DD +authors: + - beaufortfrancois +tags: + - capabilities + - devices + - chrome-117 +--- + +The [Web Bluetooth API](/articles/bluetooth/) and the [Web Serial API](/articles/serial/) allow web apps to communicate with Bluetooth Low Energy (BLE) devices and serial devices, respectively. While many web developers are already using these APIs to great success, there is a growing demand for support for Bluetooth Classic devices as well. + +Now, the Web Serial API supports communicating with RFCOMM services on paired Bluetooth Classic devices including the [Serial Port Profile](https://www.bluetooth.com/specifications/specs/serial-port-profile-1-1/) (SPP) in Chrome 117 on desktop. This opens up new possibilities for web developers and users alike. Here are some real-world devices that can benefit from this: + +- Pixel Buds Pro and other wireless earbuds use RFCOMM to manage audio settings and firmware updates. +- Mobile point-of-sale systems use Bluetooth SPP to communicate with receipt printers. +- Livestock RFID tag readers use Bluetooth SPP to log animal movements. + +## The Bluetooth RFCOMM protocol + +Take yourself back to the late 90s. You just put your Palm Pilot into its cradle to sync your calendar for the next day. Wouldn't it be nice if you could do that wirelessly instead? With this new "Bluetooth" technology you can get rid of all those messy cords. Wireless is the future! There's only one problem, everything that exists is designed to connect with an RS-232 cable. So, Bluetooth uses the [Radio Frequency Communication](https://www.bluetooth.com/specifications/specs/rfcomm-1-1/) (RFCOMM) protocol to provide that interface to all of the existing software and hardware. + +Even today, RFCOMM services are widely used in new and existing hardware. It allows for meeting specific latency and bandwidth requirements that are not met by Bluetooth Low Energy so far. That is why we’ve developed an integration between Web Serial, an API for connecting to serial devices, and Bluetooth, to enable access to these legacy RFCOMM services before manufacturers eventually migrate to Bluetooth Low Energy and developers can use the Web Bluetooth API instead. + +## Web Serial API changes + +Starting in Chrome 117 on desktop, web developers can now reliably communicate with paired Bluetooth Classic devices through RFCOMM services using the Web Serial API. This was made possible by the following updates to the Web Serial API: + +- Chrome now enumerates paired Bluetooth devices that expose a serial interface using the standardized Bluetooth Classic Serial Port Profile. +- Chrome can now communicate with the serial interface even if the operating system has not created a [device node](https://en.wikipedia.org/wiki/Device_file) through an emulated serial port specifically. +- Chrome can now communicate with a non-Serial Port service that exposes an RFCOMM serial interface (see [non-standard Service Class IDs](https://github.com/WICG/serial/blob/main/EXPLAINER_BLUETOOTH.md#non-standard-service-class-ids)). + +You can learn about how to use the Web Serial API in the [Read from and write to a serial port](/articles/serial/) article. This article assumes you have basic knowledge about Bluetooth and focuses on the serial over Bluetooth changes. + +Without specifying any filters, calling `navigator.serial.requestPort()` allows users to select non-Bluetooth serial ports, Bluetooth serial ports that have been mapped already, and any unmapped serial ports provided by the standardized Bluetooth Classic Serial Port Profile. + +```js +// Prompt user to select any serial port. +const port = await navigator.serial.requestPort(); +``` + +Although most devices expose SPP-based communication through the standardized Bluetooth Classic Serial Port Profile, some use custom RFCOMM-based services. These devices have a Service Class ID that is not in the standard Bluetooth UUID range. + +You need to pass the `allowedBluetoothServiceClassIds` list to `navigator.serial.requestPort()` to access these custom RFCOMM-based services as shown in the example below. + +```js +const myBluetoothServiceUuid = "01234567-89ab-cdef-0123-456789abcdef"; + +// Prompt user to select any serial port. +// Access to the custom Bluetooth RFCOMM service above will be allowed. +const port = await navigator.serial.requestPort({ + allowedBluetoothServiceClassIds: [myBluetoothServiceUuid], +}); +``` + +Note that all Service Class IDs that use the Bluetooth SIG Base UUID (that is, all UUIDs that end in "-0000-1000-8000-00805f9b34fb") are blocked except the Serial Port Profile ID as Chrome does not support Bluetooth Classic services such as audio and video. + +You can also use the `bluetoothServiceClassId `filter key when calling `navigator.serial.requestPort() `to prompt the user with a list of filtered Bluetooth serial ports identified by Service Class IDs. See the example below. + +```js +const myBluetoothServiceUuid = "01234567-89ab-cdef-0123-456789abcdef"; + +// Prompt the user to select Bluetooth serial ports with +// the custom Bluetooth RFCOMM service above. +const port = await navigator.serial.requestPort({ + allowedBluetoothServiceClassIds: [myBluetoothServiceUuid], + filters: [{ bluetoothServiceClassId: myBluetoothServiceUuid }], +}); +``` + +If the serial port is part of a Bluetooth device, a new `bluetoothServiceClassId` key containing the Service Class ID associated with the RFCOMM channel that the port is connected to is available in the serial port info returned by calling `port.getInfo()`. If the serial port is mapped, it returns "00001101-0000-1000-8000-00805f9b34fb" or 0x1101 in its short form. + +```js +const { bluetoothServiceClassId } = port.getInfo(); +``` + +## Use case example: Control Pixel Buds Pro + +The Pixel Buds Pro Web Companion App is a new web app that allows users to control their Pixel Buds Pro from any device with a web browser. It is built using [Progressive Web Apps](https://web.dev/progressive-web-apps/) technologies for an instant load experience and can optionally be installed alongside other operating system apps. + +The app uses the Web Serial API to communicate with the Pixel Buds Pro. This allows users to control various settings on their Pixel Buds Pro, such as active noise control, equalizer, in-ear detection, and firmware updates. + +To try the Pixel Buds Pro Web Companion App, visit [mypixelbuds.google.com](https://mypixelbuds.google.com) on a ChromeOS device (other platforms coming soon). + +<figure> + {% Img src="image/vvhSqZboQoZZN9wBvoXq72wzGAf1/MGZqWBWp7He7IxlZu88l.jpg", alt="Screenshot of the Pixel Buds Pro Web Companion App.", width="800", height="450" %} + <figcaption> + Pixel Buds Pro Web Companion App. + </figcaption> +</figure> + +## Resources + +- [Explainer](https://github.com/WICG/serial/blob/main/EXPLAINER_BLUETOOTH.md) +- [Spec changes](https://github.com/WICG/serial/pull/189) +- [ChromeStatus entry](https://chromestatus.com/feature/5686596809523200) +- [TAG review](https://github.com/w3ctag/design-reviews/issues/854) +- [Intent to Ship](https://groups.google.com/a/chromium.org/g/blink-dev/c/P4YwDCcvdvs/m/CHbyTu_gAAAJ) + +## Acknowledgments + +Thanks to Reilly Grant, Thomas Steiner, Ben Morss, and Vincent Scheib for their reviews. +Hero image by [Mika Baumeister](https://unsplash.com/@mbaumi) on [Unsplash](https://unsplash.com/photos/QC87Pjb4hG4). From 679595985cdf5ee0fa7b9d5c9252ff78cf6421cb Mon Sep 17 00:00:00 2001 From: Thomas Steiner <steiner.thomas@gmail.com> Date: Fri, 13 Oct 2023 13:07:46 +0200 Subject: [PATCH 903/982] [Manifest ID article] Fix future-looking language and add constraints (#7524) * No more future-looking * Update site/en/blog/pwa-manifest-id/index.md Co-authored-by: Rachel Andrew <rachelandrew@google.com> * Move the article and add redirect * Update site/en/articles/pwa-manifest-id/index.md Co-authored-by: Rachel Andrew <rachelandrew@google.com> * Update site/en/articles/pwa-manifest-id/index.md Co-authored-by: Rachel Andrew <rachelandrew@google.com> --------- Co-authored-by: Rachel Andrew <rachelandrew@google.com> --- redirects.yaml | 3 ++ .../pwa-manifest-id/index.md | 33 +++++++++---------- 2 files changed, 19 insertions(+), 17 deletions(-) rename site/en/{blog => articles}/pwa-manifest-id/index.md (79%) diff --git a/redirects.yaml b/redirects.yaml index 266eadb8d..06c2e4a21 100644 --- a/redirects.yaml +++ b/redirects.yaml @@ -21,6 +21,9 @@ redirects: # Simple redirects +- from: /blog/pwa-manifest-id/ + to: /articles/pwa-manifest-id/ + - from: /docs/privacy-sandbox/first-party-sets/ to: /docs/privacy-sandbox/related-website-sets/ diff --git a/site/en/blog/pwa-manifest-id/index.md b/site/en/articles/pwa-manifest-id/index.md similarity index 79% rename from site/en/blog/pwa-manifest-id/index.md rename to site/en/articles/pwa-manifest-id/index.md index 0242e4326..8f99eb786 100644 --- a/site/en/blog/pwa-manifest-id/index.md +++ b/site/en/articles/pwa-manifest-id/index.md @@ -4,9 +4,10 @@ title: Uniquely identifying PWAs with the web app manifest id property authors: - petelepage date: 2021-09-16 +updated: 2023-10-12 description: | - There's a new optional `id` property as part of the web app manifest spec, - that allows you to explicitly define the identifier used for your PWA. + The optional `id` property is part of the web app manifest spec, + and allows you to explicitly define the identifier used for your PWA. Adding the `id` property to the manifest removes the dependency on the `start_url` or the location of the manifest, and makes it possible for them to be updated in the future. @@ -38,13 +39,11 @@ that matches the already installed PWA, it will treat that as the installed PWA. ## Browser support -Support for the `id` property is expected to land in desktop Chromium-based -browsers starting with version 96. Support for mobile (which currently uses -the manifest url as the unique id) should land in the first half of 2022. +Support for the `id` property landed in Chrome 96. -## What should I do today? +## What should I do if I have an app without an `id`? -Today, there is **nothing you need to do**, and nothing will break if you +There is **nothing you need to do**, and nothing will break if you don't add an `id` to your web app manifest (as long as the `start_url` and the manifest path remains the same). To future-proof your PWA, you can add an `id` property to your web app manifest. @@ -54,7 +53,7 @@ an `id` property to your web app manifest. The safest, and the most accurate, way to determine the `id` for a PWA is to check the value calculated by Chrome. -1. Using Chrome 96 or higher (currently available as Chrome Canary), open the +1. Using Chrome 96 or higher, open the **Manifest** pane of the **Application** panel in DevTools. 1. Hover your mouse over the `(!)` icon next to the **App Id** property. The `(!)` tooltip icon will only appear when the `id` is **not** specified in @@ -82,22 +81,22 @@ DevTools. ## What if I don't set an `id`? -**Don't worry, nothing will break**. Starting in Chrome 96 on desktop, the -browser will generate an `id` if there is not one in the manifest. On desktop, -it will be calculated based on the `start_url` in the web app manifest. +**Don't worry, nothing will break**. Starting in Chrome 96, the +browser will generate an `id` if there is not one in the manifest +based on the `start_url` in the web app manifest. -In the future, adding an `id` to the web app manifest will make it possible -to change the `start_url` and the manifest path, because the browser will +Adding an `id` to the web app manifest makes it possible +to change the `start_url` and the manifest path (if and only if their particular +[origin](https://developer.mozilla.org/docs/Glossary/Origin) stays the same!), +because the browser will identify the PWA based on the specified `id`, rather than the `start_url` or manifest path. -## How do I test this today? +## How do I test this? -To test the behaviour before Chrome 96 is available as stable, follow +To test the behavior, follow these steps: -1. Using Chrome 96 or later (currently Chrome Canary), enable the - `#enable-desktop-pwas-manifest-id` flag, then restart the browser. 1. Install the PWA. 1. Open `about://web-app-internals/` and check the `unhashed_app_id` and `start_url` property for the installed PWA. From 0a3b0e8e15e7d45e0f0b45b258508824f4ad879f Mon Sep 17 00:00:00 2001 From: Milica <mihajlija@google.com> Date: Fri, 13 Oct 2023 15:36:03 +0200 Subject: [PATCH 904/982] Passkeys landing page (#7491) * Add passkeys landing page * Change the page path and add video * Replace images with SVGs --- site/en/docs/identity/passkeys/index.njk | 115 +++++++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 site/en/docs/identity/passkeys/index.njk diff --git a/site/en/docs/identity/passkeys/index.njk b/site/en/docs/identity/passkeys/index.njk new file mode 100644 index 000000000..2833f2e9f --- /dev/null +++ b/site/en/docs/identity/passkeys/index.njk @@ -0,0 +1,115 @@ +--- +title: 'Passkeys on the web' +description: > + Passkeys are an easier and more secure replacement for passwords, enabling users to sign in to their account by unlocking their device screen! +layout: 'layouts/landing.njk' +collection_tag: 'passkeys' +sections: + implementation: + - url: https://web.dev/passkey-registration/ + title: Create a passkey + description: Learn how to add the functionality for users to create passkeys in your web app. + - url: https://web.dev/passkey-form-autofill/ + title: Sign-in with a passkey + description: Learn how to add a passwordless sign-in with passkeys while accommodating existing password users. + - url: https://developers.google.com/codelabs/passkey-form-autofill + title: Codelab + description: A step by step codelab on how to implement passkeys with form autofill in a web app to create a simpler and safer sign-in. + blog: + - url: /blog/passkeys-on-icloud-keychain/ + title: Chrome passkeys and iCloud keychain + description: Chrome supports passkeys on iCloud Keychain starting in Chrome 118, on macOS 13.5 or later. + - url: /blog/webauthn-conditional-ui/ + title: What is Conditional UI + description: Conditional UI leverages browser's form autofill functionality to let users sign in with a passkey seamlessly in the traditional password based flow. + - url: https://web.dev/articles/passkey-google-ux + title: Designing the user experience of passkeys on Google Accounts + description: Get insights and UX recommendations from the design team behind passkeys on Google Accounts. + resources: + - url: https://passkeys.dev/docs/tools-libraries/libraries + title: Passkeys libraries + description: A list of open source libraries that support passkeys integration in different languages on client and server side. + - url: https://fidoalliance.org/passkeys + title: FIDO Alliance + description: Passkeys resources from FIDO allience, an open industry association with a mission to develop and standardize technical specifications that reduce the reliance on passwords to authenticate users. +--- + +{% from 'macros/cards/hero-card-wide.njk' import heroCardWide with context %} +{% from 'macros/landing-section-expanded.njk' import landingSectionExpanded with context %} +{% from 'macros/cards/hero-card.njk' import heroCard with context %} +{% from 'macros/cards/blog-card.njk' import blogCard with context %} +{% from 'macros/icon.njk' import icon with context %} +{% from 'macros/landing-section.njk' import landingSection with context %} +{% from 'macros/landing-deco.njk' import landingDeco with context %} +{% from 'macros/cards/featured-card.njk' import featuredCard with context %} + +{{ heroCard( + title, + description, + "Documentation", + "https://developers.google.com/identity/passkeys", + "image/vgdbNJBYHma2o62ZqYmcnkq3j0o1/WXvtL5Wuc28z1ViwhajX.svg", + "", + "blue", + "" + ) +}} + +<div class="landing-section rounded-lg width-full display-grid"> +{% YouTube id='2xdV-xut7EQ' %} +</div> + +{{ landingSectionExpanded( + "Add passkeys to your web app", + "", + sections.implementation, + "blue", + "right", + true, + "image/vgdbNJBYHma2o62ZqYmcnkq3j0o1/GFZzsg1duOfck1JDwmV0.svg", + "Passkeys illustration", + 200, + 200, + "", + "" + ) +}} + +{{ landingSection( + 'More news about passkeys', + 'Learn about the latest developements related to passkeys.', + sections.blog, + 'blue', + 'left', + true, + 'image/vgdbNJBYHma2o62ZqYmcnkq3j0o1/AUk4AMv17EoyC28kkmpa.png', + 'Passkeys illustration', + 800, + 451, + '' + ) +}} + +<div class="landing-section landing-section--boxes rounded-lg width-full display-grid gap-top-500"> + {{ landingDeco( + 'More resources', + 'Learn more about passkeys', + 'yellow', + 'image/jxu1OdD7LKOGIDU7jURMpSH2lyK2/RzvgX7vWeDEwkA1IojgU.svg', + 'link icon', + 291, + 251, + 'image/jxu1OdD7LKOGIDU7jURMpSH2lyK2/d7PJT7aAzObC0ij7EDIJ.svg' + ) + }} + {% for item in sections.resources %} + <div class="rounded-lg pad-300 md:pad-400 width-full hairline display-flex direction-column"> + <h2 class="type--h4"> + <a class="surface display-inline-flex color-text" href="{{item.url}}"> + {{ item.title }} + </a> + </h2> + <p class="flex-1">{{ item.description }}</p> + </div> + {% endfor %} +</div> \ No newline at end of file From ca1ea221b25c8310ed5bee6101cfaf30d2467ba8 Mon Sep 17 00:00:00 2001 From: Nancymic2 <nmichell@google.com> Date: Fri, 13 Oct 2023 09:36:56 -0400 Subject: [PATCH 905/982] Update where available section of PS overview (#7525) * update where APIs are availalble * small edits * Add Rowan's note about WebView * small edits * Update site/en/docs/privacy-sandbox/overview/index.md Co-authored-by: Anusmita <anusmitaray@google.com> * revert change * Update site/en/docs/privacy-sandbox/overview/index.md Co-authored-by: Anusmita <anusmitaray@google.com> * Update site/en/docs/privacy-sandbox/overview/index.md Co-authored-by: Anusmita <anusmitaray@google.com> * Update index.md --------- Co-authored-by: Anusmita <anusmitaray@google.com> --- .../en/docs/privacy-sandbox/overview/index.md | 46 ++++++++++++++----- 1 file changed, 35 insertions(+), 11 deletions(-) diff --git a/site/en/docs/privacy-sandbox/overview/index.md b/site/en/docs/privacy-sandbox/overview/index.md index f382f4f5f..942b4ca56 100644 --- a/site/en/docs/privacy-sandbox/overview/index.md +++ b/site/en/docs/privacy-sandbox/overview/index.md @@ -6,7 +6,7 @@ subhead: > third-party cookies or other tracking mechanisms. description: "What's in it, what's it for, and how to get involved." date: 2021-05-18 -updated: 2023-09-18 +updated: 2023-10-11 authors: - samdutton - alexandrawhite @@ -133,18 +133,42 @@ the [Privacy Community Group](https://www.w3.org/community/privacycg/participant ## Where are the Privacy Sandbox APIs available? -Five API implementations are currently available for testing in Chrome. +Privacy Sandbox APIs are implemented in [Chromium](https://wikipedia.org/wiki/Chromium_(web_browser)), +which is the open-source browser used to make Chrome. Code for the Privacy Sandbox APIs +can be accessed with [Chromium Code Search](https://source.chromium.org/search). You can +[download Chromium](http://chromium.org/getting-involved/download-chromium), then +[run it with flags](https://www.chromium.org/developers/how-tos/run-chromium-with-flags) to allow access to APIs that are in the process of implementation. -The APIs are implemented in -[Chromium](https://en.wikipedia.org/wiki/Chromium_(web_browser)), which -is the open-source browser used to make Chrome. Code for the Privacy Sandbox -APIs can be accessed via -[Chromium Code Search](https://source.chromium.org/search?q=floc). +Privacy Sandbox technologies, including [relevance and measurement APIs](/blog/shipping-privacy-sandbox/#whats-shipping) +as well as [CHIPS](/docs/privacy-sandbox/chips/) and +[Related Website Sets](/docs/privacy-sandbox/related-website-sets/), +are now available for all users for all Chrome channels on Android and desktop. As with all technologies, use feature detection to check for support and availability before accessing a Privacy Sandbox feature. -You can -[download Chromium](http://chromium.org/getting-involved/download-chromium), -then [run it with flags](https://www.chromium.org/developers/how-tos/run-chromium-with-flags) -to allow access to APIs that are in the process of implementation. +[Chrome Platform Status](chromestatus.com) details browser and implementation status on desktop, Android, iOS, and Android WebView, for individual APIs: +* The [All features](https://chromestatus.com/features) section of the Chrome status page provides shipping milestones, standardization signals, relevant [Blink](https://www.youtube.com/watch?v=CVRLeOX-TGI) + components, and other information for an individual feature. You can star a feature to be notified of updates, and view your starred features from [My features](https://chromestatus.com/myfeatures). +* [HTML & JavaScript usage metrics](https://chromestatus.com/metrics/feature/popularity) +shows the percentage of page loads in Chrome that use a feature across all channels and +platforms. Note that this reflects how often the API is being called from pages, not how many users +have a feature enabled on their browser. + +Chrome Status metrics charts for Privacy Sandbox ads APIs are collated on [pscs.glitch.me](https://pscs.glitch.me). + +### MacOS, iOS and iPadOS +Chrome on MacOS supports the Privacy Sandbox APIs, but Safari on MacOS (which uses WebKit) does not. + +[Apple's App Store rules](https://developer.apple.com/app-store/review/guidelines/#:~:text=2.5.6) mean that Chrome and other browsers on iOS and iPadOS must use the WebKit browser engine, which does not support the Privacy Sandbox APIs. + +### Android WebView + +[WebView](https://developer.android.com/reference/android/webkit/WebView) allows you to display web content in an app, but lacks some of the features of +fully developed browsers. We don't currently include WebView at this stage of third-party +cookie deprecation or Privacy Sandbox API rollout and testing, beyond enabling [Cross App and Web Attribution Measurement](https://github.com/WICG/attribution-reporting-api/blob/main/app_to_web.md) (more on [measurement with WebView](https://developer.android.com/design-for-safety/privacy-sandbox/attribution-app-to-web#register-attribution)). Third-party cookies have been off by default in WebView since Android 5 - Lollipop, but in practice many apps enable them for web content. If we do make announcements in the future, these will be communicated through both Android and Chrome channels. For individual APIs and features, support in WebView will be shown on the feature's Chrome Status entry. + +### Custom Tabs + +[Custom Tabs](/docs/android/custom-tabs/) allow a customized +browser experience directly within an Android app. Custom Tabs support all the Privacy Sandbox APIs. ## When will the APIs be implemented? From 9ff33aa5353f9d7e55647de3809a6419e9c8d5bc Mon Sep 17 00:00:00 2001 From: Joe Medley <jmedley@google.com> Date: Fri, 13 Oct 2023 06:44:01 -0700 Subject: [PATCH 906/982] Add some clarifying text to 'File a bug'. (#7530) * Add some clarifying text to 'File a bug'. * Update site/en/docs/extensions/support-feedback/file-a-bug/index.md Co-authored-by: amysteamdev <37001393+AmySteam@users.noreply.github.com> --------- Co-authored-by: amysteamdev <37001393+AmySteam@users.noreply.github.com> --- site/en/docs/extensions/support-feedback/file-a-bug/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/en/docs/extensions/support-feedback/file-a-bug/index.md b/site/en/docs/extensions/support-feedback/file-a-bug/index.md index 6069558c7..4cf41493f 100644 --- a/site/en/docs/extensions/support-feedback/file-a-bug/index.md +++ b/site/en/docs/extensions/support-feedback/file-a-bug/index.md @@ -9,7 +9,7 @@ tags: ## File a bug -While developing an extension, you may find behavior that does not match the extension's documentation or is otherwise unexpected. This may be the result of a Chrome bug. Regardless, please let us know by filing an appropriate issue report. Please provide enough information to reproduce the issue by following these steps: +While developing an extension, you may find behavior that does not match the extension's documentation or is otherwise unexpected. This may be the result of a Chrome bug or something we should add to the documentation. Regardless, please let us know by filing an appropriate issue report. Please provide enough information to reproduce the issue by following these steps: 1. Before filing a bug, [search the Chromium issue tracker](/docs/extensions/support-feedback/find-a-bug) to verify that your issue hasn't already been reported. 1. Build a *minimal* test extension to demonstrate the issue to us. It should have as little code as possible—generally 100 lines or fewer— to demonstrate the bug. If you can't reproduce the bug in this space, it may indicate it is in your own code. Consider searching for a solution or posting a question in the [Extensions Google Group](https://groups.google.com/a/chromium.org/group/chromium-extensions/topics). From 0862d8f44477370a6c3eb1f0b281123e0511e378 Mon Sep 17 00:00:00 2001 From: Rachel Andrew <rachelandrew@google.com> Date: Fri, 13 Oct 2023 15:31:00 +0100 Subject: [PATCH 907/982] putting feature back on homepage (#7534) * putting feature back on homepage * images --- site/_includes/layouts/devsite-home.njk | 96 ++++++++-------------- site/_static/images/new-in-chrome-118.png | Bin 114581 -> 130611 bytes site/en/blog/new-in-chrome-117/index.md | 2 +- site/en/blog/new-in-chrome-118/index.md | 2 +- 4 files changed, 34 insertions(+), 66 deletions(-) diff --git a/site/_includes/layouts/devsite-home.njk b/site/_includes/layouts/devsite-home.njk index 53c82e955..aa0551851 100644 --- a/site/_includes/layouts/devsite-home.njk +++ b/site/_includes/layouts/devsite-home.njk @@ -55,105 +55,73 @@ </section> <section - class="devsite-landing-row devsite-landing-row-2-up devsite-landing-row-cards devsite-landing-row-no-image-background dcc-featured" - header-position="top" - > + class="devsite-landing-row devsite-landing-row-2-up devsite-landing-row-cards devsite-landing-row-no-image-background + dcc-featured" + header-position="top"> <div class="devsite-landing-row-inner"> <div class="devsite-landing-row-group"> - <div - class="devsite-landing-row-item dcc-blog-card" - description-position="left" - > - <div class="devsite-landing-row-item-media"> + + <div class="devsite-landing-row-item dcc-blog-card" description-position="bottom"> + <div class="devsite-landing-row-item-media + "> <figure class="devsite-landing-row-item-image"> - <a href="/blog/chrome-at-io23"> - <img - alt="" - src="/images/chrome-at-io-thumb.jpg" - loading="lazy" - /> + <a href="/blog/we-are-chrome-for-developers/"> + <img alt="" src="/images/chrome-for-devs-thumb.png" loading="lazy" width="376" height="240"> </a> </figure> </div> - <div class="devsite-landing-row-item-description"> <div class="devsite-landing-row-item-body"> <div class="devsite-landing-row-item-labels"> - <span - class=" - - " - >FEATURED</span - > + <span class=" + + ">FEATURED</span> </div> - <h3 - id="10-updates-at-google-io" - data-text="10 updates at Google I/O" - class="hide-from-toc no-link" - > - <a href="/blog/chrome-at-io23"> - 10 updates at Google I/O + <h3 id="we-are-chrome-for-developers" data-text="We are Chrome for Developers" class="hide-from-toc no-link"> + <a href="/blog/we-are-chrome-for-developers/"> + We are Chrome for Developers </a> </h3> - <div class="devsite-landing-row-item-description-content"> - We're wrapping things up on this year's Google I/O, with - more than 100 new APIs, components, and tools discussed on - the keynote stage, and in Chrome's on-demand sessions. + Celebrating Chrome's 15th anniversary and our role as a trusted, helpful partner to developers. </div> - <div class="devsite-landing-row-item-buttons"> - <a href="/blog/chrome-at-io23" class="button" - >Explore Now</a - > + <a href="/blog/we-are-chrome-for-developers/" class="button + " aria-label="Read the Chrome for Developers blog post.">Read more</a> </div> </div> </div> </div> - - <div - class="devsite-landing-row-item dcc-blog-card" - description-position="bottom" - > - <div class="devsite-landing-row-item-media"> + <div class="devsite-landing-row-item dcc-blog-card" description-position="bottom"> + <div class="devsite-landing-row-item-media + "> <figure class="devsite-landing-row-item-image"> - <a href="/blog/extension-safety-hub"> - <img - alt="" - src="/images/bringing-safety-thumb.jpg" - loading="lazy" - /> + <a href="/blog/new-in-devtools-118/"> + <img alt="" src="/images/new-in-devtools-118-thumb.webp" loading="lazy" width="565" height="178"> </a> </figure> </div> - <div class="devsite-landing-row-item-description"> <div class="devsite-landing-row-item-body"> <div class="devsite-landing-row-item-labels"> - <span class="dcc-label-top">LATEST NEWS</span> + <span class="dcc-label-top + ">LATEST NEWS</span> </div> - <h3 id="bringing-safety-check-to-the-chromeextensions-page" - data-text="Bringing Safety check to the chrome://extensions page" - class="hide-from-toc no-link" - > - <a href="/blog/extension-safety-hub"> - Bringing Safety check to the chrome://extensions page + data-text="What's New in DevTools (Chrome 118)" + class="hide-from-toc no-link"> + <a href="/blog/new-in-devtools-118/"> + What's New in DevTools (Chrome 118) </a> </h3> - <div class="devsite-landing-row-item-description-content"> - Starting in Chrome 117, Chrome will proactively highlight - to users when an extension they have installed is no - longer in the Chrome Web Store. + Check out the latest set of features and updates landing in the next release. </div> - <div class="devsite-landing-row-item-buttons"> - <a href="/blog/extension-safety-hub" class="button" - >Explore Now</a - > + <a href="/blog/new-in-devtools-118/" class="button + " aria-label="Read more about new features in Chrome 118 DevTools.">Explore Now</a> </div> </div> </div> diff --git a/site/_static/images/new-in-chrome-118.png b/site/_static/images/new-in-chrome-118.png index 4178cde393733b26d6ebfbe4105094809abf5bdc..9713bc14921feec46fc356267bad1b8028f11ed2 100644 GIT binary patch literal 130611 zcmdSBcU)A<wm;aSsDPqJKoA6xq-2^*6GcF>O3uOVCPO2s$w5UAk|c>p5G4yV83cp| zlq5OloO8};b_dTr_szY(``*mFKZXy=X7AcntJeC~cZI4Z;EC#^tHjjAAQ0%Pg1n3x z2z1F81iB!6`66&<zN`8n@Po)+Ue^%>A|b>4I|uq0M+E|1*|gNqaneyyhCmUvT&6I@ zGdP#4tv%2h1QL^UwKs)Y!=31#!Obo0#2MDg(G2vKFmVQL0Tmt<`-gA~OL=z(xVpQl z2GrdeDgtAWl%N-Lg#aDc!ktX%U2Sdb93iga4A_1lz%}MJHv>JkiIcTB!voBK^g1d} z=pP~+;PfI~U`{9x513v^gv(SI#xEqm$1lP`&&$Kh$IZjX&CACL=7aDEK==jd@m~zU zfDSM-h?<NXemLMaaRv(~CwmAtHxh~DLh^AT9L%}FA|fK(JiOezyqrJ_PDeL8CsS8W zJ4eRfJ;=Zvp$?YzPL>EedQ6X|&k)W|;tYVWxLMfR|JALXBVJR0&bVDo?YY5RJeXNw z8^WM}wX=72u)z)vgL1=d;I?o(Cr6+y_^-D176>PVqXpvMbp6-ke;NSLu8PWEWBf~5 zY;FG<!qG|A1(*h2A^)<qqlTM3oLdd<h;Vj*!ew0mF&Tf)#?eU){ttcrH(m#t|Mjwy zrP;rE7xUzwCIxr3{5MT8PyT9Z4|(VSH+4cdXdn<azv1)bw-)Jn`MHGX?`vDy!4ODC zR?HmmFTiC?o#5gO7$9+id4O*XFh7J}2*M}K$-@uf;lVXkLBK4{-2O{bum%{6Y04wa z&IA5OQvk>?Qzz5^*cb+dm?0c&O#vHN+M1ffx$W)D8R-AAEaV}=2H^k<3`oa^l|n@Y zqG0FfWNHV6E69j508`+yw1h!SO?jS)2#E-C0_#GUlOG1-=M***66ECPh4KpsnZn@w zLh#@3%OIf67_ed9$1Ob=0t)o;k5S=*e9yqoL|~kzzy&9-DZd%#GhRV3Cm1Rs1m*{W z&CEp1e)sm+!4g>grZ#`?6(bc4=<%7LF!UL)@HtKS1x-1Hh4`OwK7)aIIiCreiU{-Y zm_m64p$zmGYeRr;0Fg{F>r0#gjK8UaL7j~=?xqkg5Aeke#{7?euKORJ|KqWyoh6`R zUIuy$UT|7f2iOZxtDt}Yp8)>;6H8aPjgE{ZpdCk?AR@fLSlD;4&vgI(j7OLU!w&yY zn+Dv~N!ip5?%;^09cfc@{FRO6-;9cFqiSjkj1C3^{r{r}>=R5km?y#v-2dTiRXCE~ z(vJS2g#*GCFz>(Y=bzjBryl=*BoAPj|1_I_p8Nl@et5zEOY(4I{0$CD-2X7~KY<NP z`Ve_bM}Yg>@SstLKmP}Ousjbjh2oYH6vL8m7y~`-w&lMdl>gq+#l4TTfCG#6|G=KO zW{wCmC#0zZ{DC>J(*Gkn|IN1lEWD$s%l}z)K0ZES9<T^6Ck)05<}?%L=j9aU<rCr* zhVh!gp=Lb7@Mq6{PyJtsE+7E#_;2F>e<C_wtxyY7J99V?4{`q;82`h`m<j`2%P-8s z2^TN}=v?F(Fc|@1IH!OqADrKe2M#<G`ZtsLzq_XY!DLiSp_X=-=mYSRxYzzW(}5!F zT;L9WgO<Ii1Hf}m040hum;o$BZ)$IEV+qCbJhzJ-3?C`|1#5aI1pPl8;lITI4DMk0 zHx&GRl)prv|Nn5j|A@K&p8v%u^1op2f7eV{^1x96_kU#x-0w0tUCLpsgN^4P|B4U( zyEp^_JO~g@{1ssQ&q4v*_=x|vAq56E*oprwYX5x;NChyLf2AS7FMlO6a64eNIsj=( zwJJd?=-m38g3JRA*SO^oq$dpNwRX0*7nkuhQ*%IbV0NX)$YaEIn1@ubI(6nFwIV_E zb?N(luhvPJiTs8yNIP`N-y@p7C@nAT+kV?hnXkt;c%`UsX=M?9cyM}36&1$MM{W5l z=2k_5*iWn3!ce)v9gESe15cH@j+~|sLW;!c*P+CAde4uD>j!y5qJ9Y%$1NQ?*>u!@ zZFY=ywu$$?ll8dIa4V19E~g9q=Bk^`MoVo-iRQ5c|72d}$uj@=-e<eBt2te3KMs$O zmMdqcLNjez;u4bUOJnhD3FUWvTs)5@*4H|}1j}B_ZmYKnuFrNIWjm$K>KZH1^0HxJ zl&yIywg8buNu)-73ObL;_kNi$kC46VX3h99_YCtpsHixVr=5JHUV}lZ*+VyNKTkDm zMXAkvC44D6-z;KFp~JpZM@5s=mt-}3#B2^hapuj%ozXCrx81KSCm63azkb($ccs;b z1JhSx=OID38B>a8)_EZ91cBPcHeY`f*_$CzcP!E8BzZhnd~?Od(0w%J2qL@qaZIR9 zqI9l>hK@4bQsTY<p-Ur?8l_i@TX9<fi75Hi?BGb`7V%iDXG!#^v2@}}mQzSnF~!j> z-f%U`0U5Q4d$j8NgY58{iJCb=%wQUCqxe<lNidg7jf!`d6(@4z;MFPMRM&kA+ugES z6kIEv+4w^l|2qSh1u@#%rbRwCRonMIA3aV>cXjWjMY%ks4OE+AE}A~pz3*hSyTFEi zBr9#enBC54C=D{;e<GA0kQ_9{<~gECZ0Hi8%%ig(hZ)TGEh7k%fcx&$4f<bin`QcN z@WQ}4dKnu1CPAq!FA^L+$BE{SX5>_`ieCQI=xCfkIw@P!;>9U~oF$S}(kpRIA)SDW z>fWl4BJev<5sYX=1+X`AExEYNhUyC&CLB3f>p2ZXoi}0RJJN{+e}ouE?;Z<2G7{tR zmwr2JpDq1nSBZ;T6eEgM_C_pL@mcp0qOTq-cakHu>`G8`EtlSJHE&Kitg*5x8#e9c zhj8Y93WG({#ol|>vgJ&9)mQv6@f$dS-@r+bG7BU3&4{ch&R+lWtofAK-cub{%|kjW z=rr>U-p`3&gpAVKCtlWy2A{(WsQD0d1@lwqT@IhH_U9v-+I&^mqwr{C-|{YlF(NOw zdy5INtHXD6H}-0Gw2S7P<iQ|HA6Cve)&FHE=&6}I3(cv-0gHdAk@7y)auN(!U4pXi zum?XjvOMdtaf~E8<q|PVp)XdXt)h_Zr5XrOD6OclDm~F6+*`YQjJ5rzKR{S?zh@U@ zq0WRAi4oZm)HQ@WZlImlZZa%k&xMwcQD7yO!3+HB!wrbW)3RAoAN@}UT@EF-8|4g` znN)Gi@?sn2k5pbjQ<%x%<VqJHFu^|Nl?%UnrB3Y?8uQzeJ*sn8F&8>Ps^h<6J(OuY zZQ%$jH9yXmR;62{HO81{>FO7%Fh6~>2EgqyXo_AY(=s7JRD0OVw-PIYr6VKW(OB8< z`+~5xdk4P){luQFK=&BoY4G{wrEZ75u4yNieM3@AFNv3XaT)><w!A^NxkDznF}L|a zIQc;DDDgMw@HcX=;BT<tZb*5n<a=kIWx*o7#InbVB44jlVmhGKu396&T!5VGsA|R( z!De@lZC`EoDUM#izt0QtJ%@RoelaO-y###y6w_R43I~1=XtVC#Wgkp~L?RvnYD~ji zD#pY<T7;+c=O354H?u@%oC=Tdlepr9v)9e*rzlaJF53+*<N6QOT|yGJm`mv7<kY{% z3HR~ZIUY=p^pezm>{YWTg>?AQ9r1AC0PLjyN2=W;D>9r|TfZOBA7|$tdhih8L@UMP zB){3_(Av?i&vcKix0QxQeZJirXDo|ncw^ND-K;U;54M?Gdr%}6ix)%pFCG1)YFsy( zNPQNx{Bzo7|Hw&%meyPQ0!GGk2Jg&Em<tXbxqO$IlXj}0Fd;z}<kC&qPp9g*x#p5y z$Ky3N7Nl}>_*+mI?VV^*;l%gmVk&lzL-AO(!XqNL>TQZoY_-k)(v|JZnE@ngu5-iM zTg(_B0ckv*dHN0l--5$~z(pQ5(XY_eEBe;<Pcbc|DlYFEVlF_5tvU*%e2Gow1#USp zDqhw%PgNUk-G0(ku*!s8MZV5|lA2%|N|Bad*ZCq=*S(v^FX!T}x0)(ZH0*W>hl8x& zaK0@-%K7wGT|?a@??f&`$!PjGD)1O}8PmZynVb|B)A>4QCEyl+^yhb9kYci*8Q+}X z8!+O)San0|N|4ocpcAsK3B>-}CZ;!Qw3r^U%#XFOUFp0K9DmE_xY85lWn;_BTpGgg zxYQqK4*CGxg5k-5+-08C*nhqwHXtJ%W{uL=UxeZm4N}0HGbO9RkG;C})bi`PlzV~= zN9ue8N^^Ra21byzjx}4uq>v0|;Hqc9s#i-P_d;#$9a>YAu9(HhCvWy)9)b8d@JoPX z{y5uXwEvs*Bho*xcmr+X@s{|&b!v*(&{Muc6mbv7P1CY?6EzPmmlf5)%KcW}K1v)6 z3X6}^m~XgSbll80U08Bt_y=Z)L{&UOZ}K(!qJ-<Syb6oKn{{>5c0*t1yAaV`9Zx$t zF%3a2{<zuanxM8QXY#^>;tkaYvMK@x0fHndefZMKt?qHt%1VYw7^bza8J_qWKDK$S zEC-ifGn2~E711pN=XZ5E2-&JF89r7w8G8RV3d^S!MtHq3&x3a3!TEXLl!dbzvW3`k zJ<{;tq?Y-;7<OQ&B}(u7fLF>)S@SC;Y)*})=q4;x@L&JU8TS(I#me9JJn11eey;4` zwkC)XD$xl)if%zXT8sbOQLWy9t8@oVj`p-dpCT!`7>gmTH)BlL-U7jdgF>V8AEcx2 zXigXF!)pE-h8~Zm7p3cchlULhXwdfn1%ED)FYnXDHCb-psa@*jZ&EOY2Zi0ejJnMi zn>FVl791wT`*l1a-pXy)kT*NK2!$oub{RY$DSa5Ix&e<R@gxyXsB2JF{WVf7+wrOL zVe9MGk5L%M53*1_hsJs@P&W~K%)xqe@7ShJ%cTW>y2ntMx!JVMa5_d1z$+AS-N3xi z{%Rga;>~kWUp7ke-#VYxk@1H8$soA{Bivg>*<u&0Zz>)+?__rM)iWYt;<9$7PbZQn z`5b64y*vTq)CcMgFUk*ytm!k(UKh|-KrJC<F^_#&@Z2EPqT_}ErGtEjJ|c{W@PrGy zvf5$z3A#0NUbZ>mO0I5^@UDaPodCF8Z}_8Vc!xhm{^uADZ7TS+mV4W}Q|r%|t3I>? z0nbZCi&@?0Xn9vwyeV;tQ2R>}fpK=4k!=>Aw~+37tx{-)$CV1JsYYmatV#L7cwGE? zjefme(is${!UC7R>z`Au<rfHeI^0rd#4iOiPTjq}n2G>_f`!6qH)2EYm=_*MyeBcC zrN?QK13W}zbAn2$cGFT!qbS?HLC7t_P<l*^wPm`5_YroLH|LWq^?tE&F_Qzvx$iUs zjxniPbHHc|v~&UQV*-aucmc`=vm%$?F$fuPlMx@_1Tvw$iyJFZ4OqM%)l7~AWmorE zV?tce>;#xDviR@@(RdMN!*G`@nC*C)hP<D58gCHiKXFUempC^gC~||`ZL@`#PGTA< zf_d53`7NH#nwq`)2Vz5XsJ_YcMyRp+BfhDAUP8Smx`1cbTs%iukk-K@pPX|HP1z}b zS7!paqR1DQ_E<L~W8u;dev1Ufi9~&;8Zkq);fi_<-ju7KUL8rA=S$!s3&88zBp&C+ z+xIVXOk9G(($Z!~x7pq6Z5_%4@l8PZj^e=KMS+MUURRDl%#v3MWGET=QWav0k79h8 zaBH#UncY>Brm`Z62mAVQ<|!JA6PeuF^OHZkwXq1O62mnM4$aMXn0?_yZWi=C@3}u0 zT6rQC5lL_kFTM#K)+oMpk4ysez;dGv=`Y?~yMMSX3j6Z(cauMGJ%JQWgO<A^35H6r zn6%Bt`{OF!<_wH=+V``fZkv1MoLNVY^7sqR8nc(SL(NwXy$$B57-Qud3JU>i#ZHrw z{+_QJ4t^E}j!B>9db2s1)0>63%K9%`@}2o)ikh<y#ZkQGow;4U%;7jRTREMQ_EEBT zcHqO@U<jj#h<4t<^?`4z;m&^18qeMj-`}3mQ>bIjA2BPT%wIlwcdwgEM>}Dtl;*8h z=-ldVmQ9`de(w^6m_x38JO&J){U9tDq@X%C*JElw>BpXQIa97hlQ~hRJt3Z-Zj@JP zy<@g95{Rmpt{S#&4Tna*4l2F7y!lFKE>c!{3EroZFOC2K*$u50$+>ldcXY(RE<k2~ zjKlr84m+DSk8au;-CZ_fy<)su!M?kdyF6))-d+AYI-OjjZHQXG+V|_iz9u$^dxGB2 zrT_$zI$^(=Kl>VeP<)HAk=&9?py@}gtl#GX;iEXoIUDorMj{nT=U=TWpZ4lD+rh>l zn`WC+1Nw18>d9HQn^rf6-XG~GcIM|6R84({ZB43?I9;2gGtMGGrmPE<y#5{vJ?-K$ zD0hu62FS;x%??9!EVsEFc(KYjeuVX)iFxE#=ty3D>zyUK?zk6w@*(#AcZ)cugw`?H zzD7zx?vcnG$6oRb>$@f`LkH#a?y|+%J&N@=mwvXEdj!nsm)Sh8-pZNuDD9kI{XS>> zy`}Z%^!E0B&z2tEj`?46I9QtFP`((e8`(N*JSS9=B+%vpt$-`l&EDp4bLnUqrqL3y z?&A7I9L&U>R>vGWE7{g%D@q9}KY%=^BrW!@QBWWMP6FrVbZOibs~=oGVIeozckjG4 zpbQyn+=_}7Zwdbhxa+2}=h~MeqTwr<L_Y(O%-qA;FvCfhBJmrFvds^})u%OmSVBz< z!3B!x2*G>DEzy&ZR_VR$Ifa<!<yDafU$wKy_zRv<T36G%G&*ZlcxBh4$U!+XWeNAl zh?G8$*GMb?E20oq5eL=U(}62yTXG6Sd)nk3Z6eiZ+I|JrQ@Cxa5U-9H9uH#G+>KvJ zEv&|A_7#o#&syVUAGT0bRtj9GYP!P*WN_MlfV8=PX4``dmW83y!H@5|Za>4&lf%g5 zKg(-DH<RVH^yd4_P2E1%4m%1`brKhvHm<C4BLWjBtp48gYMFdk+89??r`mBDZtxfi zv)AV^KzsQ?Uz;)tT#~w~7+=@&Q(llRdSNiJAp#LT)Q5L%pe$-UF9=ZX3+l~rFNUjl z@P;!8jU|rzdEuF;>LX5f76x@3q&~C{sSLQ1b`Geh8AZXL+h?L#omMonj<9aqLI=-n zpW<V6Y?7V%^S*7G^&J@^Fp)cI+^^#8@F{uBlixA74j-Po5EU-jT3wz<=LktuT|;Yg z!^#p6nA~e}a{A37aGb|z?+*%l{!uJhrl(&+k%e4sx;K`hzo-lEdG6ETJda6rr*l+n zTzmj4;Ftg^)Nt6RxP?(p`~LpQO^j+D>OazDW^1H!OM(*94(2pG9$_PViRU>fS$s~> zONry}t85NK*}R;bzn|Cseohe^XSlaFOEbONKa2A{APsW72!?qZ-=wt-Key*8op518 z!QbVLcCjEPU34bkbS!qy+0rTXom|aZ#pa%g2Y5x>7x?8^=I3@IT6XQZ4EIW+oUvIK zs09~1NWJ8Hg{BZVauw8NEK*5<OPltdV29ur$0<}wi%iw4l{Y^kf|yqHR~a_N_D#hv z{_2=G$peZ@N>q%Z5`ay-hzoF|o6wH;VB>|WtyZR2oFZB{<=lc`P_T%X*W2Unh#5@g zjC~H${7oabx{{%RPq|`uVL?y#>z2s-i<<DJNGHNcausDsiINowf~BRBi@E1XYa8Dc zIS#_u0@Qm6Z~ex>fxI@6h8K6?K*;n#&16qi)()-7a(fq7NB~*A#!<K<{eCS6#=(@Z zdQR;)xVs;7Ve>=ZkN9wu|5}^kt;Z8fD4>}30G)XbGfLttE;!>CtdoF-U@`y-v0Uv5 zeY<xre*4D1np{d65b#rY$zJne`Jp8c$2kGv&1&&o*#w6`W&TCHh4)|Jq?zK|I(wrC z4&HIqYm0b(+dl^_xB3s~jlhS51<f{dh?hmDiuvm5#6}ne&~25IV*~?v;)2q|=ehy1 zzL`m;bWZ`erIPnosE4JEvXPPE6B$q?Zg%b8Zo<(Qs+WKW56E)ZJ%9X71E4W{gf}ao z7i2f3K$!DQ1E>}J240yIj`oT8)nEZ{dE{Jdq^rF=$h|jP)Of~mAr+{b5O1*NLqn;p zTs;Z3A*#miIj9W)fD^B`Vl!qUv@3W*kQ%|oitSYnH=0TxFY)Er+;$B8lre>}YEw)| zYZuUF%QcT4>%mU*i8kH<L^sCsbz59cdY|uGV`3D-Ys=dEht|w*jIFVjYN$p0!n{HK z30#04xqd1rz&H?dt90l!dFjf{7>l3yL_J*;&oMN?=%v>x9^q5>Jx2r_kTzT8x3L2* z-oP!vM6mK>cBkcZ0CPrT(687r*8jlK9SgXRILHhG?uX}zjeW9}g_rT>?dHVkLB)5y zBu2L_;<omLb<X>8piY2`Zqu#t!w(y*H!)OEXy1z|i;q*A?+m<kg00|55#deWbnD<# z1`VUANJ>?L;ajmCEjdZ7YkWe08=<9o+H;@QKrkQjG1XR`HO4{%7%9AKXbLY0{{>vT z;G7WYraE}hvETNdUr_`AqvsjY(MHSq*n$~|pBmRp$}5KE<U1l1NDy?1{qYg5@9PJ6 zkKZDY&bwPGJxeElN7QFdPSO||6_*fP*>et~Gbu(q#%>2SdgorYzqJ|cxBK~RX-C^5 z{H&_1@Ce(?bSAZ75*5g<^2X06R|~I^G0#2jU$aoMTon&B`owmMdMcbos;Kb+puL&P zA|Ftat7*IKWv2JJiCc4iQ^|{i03(8Log6N^Z`iaxFb1-{XAZ9~l6!X+0X30p*fb2( zejAS@RB2V`?5NaC_v}XDLLs?5Mdhwlss0-)2Ng_DppO)IBTMb;yKObP@2FsKaKj%} z`JyNeJKy_cxE6JAf!LE?o-7;pqN`oD94yGDchY^v_4DS~e%SC;qw#Cj%<P0Y!l_lo zfDgdhP)hx;6>#&MnS(tP2&wzO5xgM<GIN0-Z(PVBjTg800Nn0P`JyLx<J)kxw?D!= zT$z9Jw~?>nt=9rn;sK4Q+wZBOm9Ro4X5hVnN#U8`Z7A#>3x(J><IndD?};4iVUDhW zq?k8iG5No5ojG%3Gxwz+;*6TI?}9Or1)tS1sO{>|+StO%n>+g31dah~2KRV~?A>ex z_XSefuBF6()Ee&$q!4yU+`NaSQxMLaAFB*Z0*KQ`r!3M^Df-dcVE|<kUCeaBR+T`# zzg>6mddZ8gdpdgDjD#<V4WGxvB_w<`z>W#RyGbikNNRgt5+>aoi^3|ly&JC?t}-8* z7b-tz>_(FT(rA#W`AsnD_+qF=lu9!B_enKE7n?miZGOaMGN42VkUM_RSReQHPjHH# zF8l4ByYR2VVg^Eq^BR-muEql^yeMwB_*Xo(EDR#YRd5nFbYok%bjiL|HaFjQ9e7Ge zdS|=*23Ek{-&Uy|i1`qgtxxfN(ILj99Zvx|LU{27tqTm%PN!O<)OXZkH<C@HCYExv zOqxvK)>ue`WbsP3r~?mlw55M95(A<eRb@7NlTSEDI7oyUPKt9QRv2?(;un=%8e&y` z_=Ak7G}eQnbXPIP{#z$*jrvmH;Xubv5Zz|6lJtq$(oC*8F!X*d0znvv8!-jHj`x3E z=FICJydy8l$7tRsOKgZNBEPJW%YqpN^n?wMxdYw=WuEkPP3;ES{$->9_F<Mj&iuZc zKzsnss5<o`HuUnxb9pWb9Dxb+q{w1ujBPYK??bJlZwsM6J1`3n>yKL(7q1tW8r~oh ziFK!_TxA1fC$7ap*;fsxiI%G7Gvih-k&>0=vzWN^Z)cKN+UkanHf^KxAAF9X;V)$3 zj}ryJ!fqSO+26bZ&7Ky{uWQhW74Ma=bIw14h#bXu{s^^ERXNBJ*wg$_)NSw!8ef9C z(OR)jKq$z0;-=#OJ>6a2YjkF+H|&S+KIijGgz*&=O`}tV_>#uql<c`ah%k4oOj4XU zeFistsGUfRplO~V(o<=*g~EslLmiKV-HPWfesg=NP(J-l%rCEiNyfm5+I+&La%-s6 z(1BofST8Gz;9Sh^ZmobY;fqdB<Eh~yM-+l-;Kj}~iEQ>;{}~b?67di>m(~*F&xc!v z$c2f(*61#Qm1gg2X64>0!W><F>fbIZ2qrwSpOYmv@`@rK*H*?_;J6MkhtV-38}o5X zL1<XMVS#_yBND<8|C%w`XqWdkLIsA&1$(-&E4-Xkpx8;jv}T(h%i*@YToPPDui{9` zwg?mb%i^>by^Y+BKi9Lht<=WG%{X&va!hB-gW}SZgptDqU^O0{!l|KGDecUZO|<je zM%S=orw33NfiYK4qGx%_)Dk+luj=+upSF4>hzh!$LKW6yx&L(0y6h9ZiiQ<54%ue< z+q=bdLOi2w*<~}1D8!OqP4$Vfc`Q`=uQrpNqGsJORc(jjtE~1GJ_^RT#g#6Bty%fL zh85h+70@g0weuUH42i9H%5lMv`mmLjug|%RgQ@i(Sx2~3t<S1DuQ}WhQta+>)r9Oy zYY3O18Vh5rs#3zu7YlHK*$f{$sNeIBCOIi?+Rp|Y!<^q*?JJ?tcI>-4?}a5GYsH?7 zmCS?&F;844hBFFncv)joB%yMODJk+Ye&>(idS7aB!3RhHw*klhr8KX8w9~|{aevfP zKRD*BAkm@hv9)uSQ28t(ma){%#RI}9D$WVF*#LceBCjtsD&VUm=3?hD`k~T@PDx=? zET;HoOz_0AZGD(Z+DveWq6^p4zT;0W4r%~%r&X;Q)-GW+4HCeGe_29~6VFHU8l9W< z9fk&vjUU!28kxCKI)Zn|e;zsmJJ0a%{wt1>j4?seZh>;1L#_s`sS<>th74rWeTvwg z7KzXq7{ax<QY**IT@ix_a_(^KdwPATFORU#STL|ex6wV}#UpMllR4R1Yy99PH3SBj z%Xa#px37MtlZ%QcjfdD08#=qWY-3BxpmcV;AMky;+edR_e3SffhizR1(Hn~In+_te zLOm!BY+p}!acmNt-O<Zyr%@*l1iH%uDdRKI2Zp!^<vz}jN<kf!ch76WBNSqS4T+7M zOO>qy$7Zm7_!8h46~rD`OD^W{#4qsLfgzR~LHF_D_IdV7GtOV{w%P}E3|hy1UuYX~ zkzF~|!(?+H(ESix#V=RKE_GFxH9~7WJdom>#Tx`Oj($4vt|&k2y@1A$j`FIkD0$i9 zhv~A)NNnB&Qp9C6pawn2)1fUUC^^JEAg(3$<SW+Cg0cwk@dDsy<zMgkvNx)#u)5lR zdZBGRfn>#skSK#!*N@Is&B*$#WB_1{Z{U!@6BITY07c?zmQqu(BtF?={`}Vfc5SZ( zv^mL(cle-8e4Oq#Fn}q2zg0|wLqw-n$JjB+08W=W_%OYSK`=(cq>t-wjxkpeCjm8O zFq*=gOhKeVocMPCJwgJ!Qw3@LE<Mx7M3#G%1F;C29jhOZHEv+gJ0@V?N7V;SaI~jD zismA~%&h&-{a`xG1-*54WaIr@Wc08~#qTbA@r79W+9`)i7s>lew0SvDxG*>g=ZcP> zU3s9-4Ae{G=M?Ousspe68t9+F`<lcnSc!d&FSBP>0cpp>eDyA3y8g`Z9_>v>tofy0 z;=H-9bF-Nk5Fz^ohBg!y9pE-ULHICk{1TK&bSPW#2i%S7<hx6qd{-Co@<_@!JbE9m zwR8{`qgC8yyFYFi)!Y$`3b#b4k9Q^kyA;2tf{*sniw^91N?SF1vkgUSwgmX(fR*d_ z;}V6KOZS=;Mhze-e;k^;O>MxQum}YaadBcJ2N@RfO?(3K<SuSncV_D)j|?yOGGp^P z;ap>&pWkTExQ<2C6USt96ns9_D8*(Ek@JG`PB_uU6I@mc`rX9Z@qincBJ5roc|SUO z6}uG<`iOsD=@mMPuTQFFs+3JI;a$0Npmd*+!XCDo08+sjXZ@-rkLUGJcGvwxf^y{V zb(N0GLK0^k^tE*_Q58YSh(sQ~BsOr6aoBghj+v*g*-ykV<|5bVCmAsvB(X|%=mdqW z{)04#@Ztw~qllsTcN(lKkM`zk!<P>6rb)knXN9)bkWLm5R}fzAUL1ZCQ{OwC-O$l` zJ(Zhk`-jsR7HPTO>%<tVk5kqdcN33bs}`Uv8muxwAAbx}S#U_>r?y0b9e?~%nGd@O z*ZNEz$J^fnP~c4cxbFJJB&+#T?D{r2!Ih7E&18Rfpo-gc^K}kvHP#4IVVbtNr7=Fw z{9BZe_H$Smw^&pjA!G4zt1mSk(^Z4$^e+diV@h0~kFcBmzRtKBMLM%}fzOT8FCQm~ z2(PWC{eFluL^?B+=}p>1Ivr5M7$}zYOQP&L!IsUcAmr=i7)_gq^VKyR8eaJL2At2w z=TL&s9{&PthXd^HOQB;u<EE9cbJJ&4*RA(gtG9f?8nZyi?fR$m<7`xy8+ddtgWg@j zY6Zkk6s!DeVMTL&{ahKQaO63w%f95cY4+04x?;c=IkDA~tMyCg@vSy>ws<XNBEs|M z{2x9j727)xn#QFyRxNss&-2%M_r%bdmUMOUdiAux)-s0kfG|1q_GURy(e_Q9ZMj(P zQVc~-II_2G&6c}laz?4L1K(7a?^6?X{c#2K4!>2ZVhW&Rl2MIk9-H-CwX~bw>{J~Y zwj0&+FV759Op8irO=rIGlwL}R2b6`x8eA&-Rzbp%M&^$X1Ek~5R!{fVa21_&rQX3> z!}3v^{@5)y@z>=k`Mp+<o9aqTUrgRbpPn-jpF(57)IJV4`?Q=;3@mc(IGtA910~yT zHGMZ~{yAj@{)6!R_v34zC5kgFKCFVAOWABrCv1l8g7a&i0koL|6f3>8fu5c`FP(}m zh%YN0DPLkA27)NM=&nwNzURk4QE&V_4&)Xlf)QbsmYU<^-mKI+7#8r=+;Hgai9hpf z{8--7`aCG;`7~9*dMR|8ig60I7M&le$uh-?)fT0AT9F#ZO>KQ^CC<tVAgOpfQso52 zld700*<BA(uyXLUDQ=y!%M(Dx#`DpPQ`a|ul_ZeOUsKPEgfP}WC%<wrazm_kk_gTl z^Ww-{>~R20apJntD^Qg?{$SD7U#VTZ*_^-vmrpI~!DKR35U`N@z)fApl7SzF(EN#P zKAKrB&&u{9{gxDCgZiiXN*Z~t(v2El$Grn!YM-Ax;gCKL!Y@1!|5q8c)r5HBW#|f^ z;3sYi%5pKvEHtaFp;o)y(*t&b%`IISu}5wKKSp}~l&i__y?L9+Hd~V|O6$HnQ2tsX zI$OlXEH=Q-+s9-726$FfR$7&xmxH^<F~(u?2Pm^7!PrtXAYGA$-w(=N;s<hthAQ;$ zbl5F?3Cr#5@<$tIIAJ#WdT*WfVDi>uSkT8x|1VlWPk&VCX<wuXWe2v{UqsWkc&`9Y z;p<|L^JJtKoF)X|ONOiaGd5|c0-pD7yIW>J?NXRrO)RXTT)eAlOdV7;i0AhYYkJJb zoW_oo?@GP^v#qRf5VYOIWQgtK;Te(7HjXDuE9`M*794iIon|M;d&EqBh5U+dcCvC^ z#1f>4lNdBkgTu&GJ3$%aN8E>igKh2Q1Q3QsRoY=Rht=_~k|pyo%F^%F$fxa1Tk#aP zpwne2-k9T&$^=YgvV@~s5dTLRwd#kL$iG>XV<^e@qSnfKA5{dPX|m;6RH@Q8eK2Z@ zoYXg4dkXMX-gvfxnMr=Q5PV}mLoqc?e|6Om&(ao80$}-B>wVKM%Qtl#qiv9R1!<2L zjvL9`C-bHtCqEV9C6TIgt=FtwZ4Aixz$#3giXK`aQ|aYNDjqIt-4UPM-=Io&^$5?i zqa%$ul=sBECxD}SuW*qVwLchJ@pQ=`xU`22UM!x(D9dfg<R^O>_Gwl*&p=wg2q5$N zH$I6a-tjs+a^L^_X1jkX)Y=uM0gdST7;-PN0T!vN0$PG^|7`e{us`TkHfOzO`OrGh z=&+M=301zzcGxefIsxj}12nAj7#BgJKa}noC-MU|kgmS8@s1zBNjpr8>3fkP@SfK2 zz3Z3n-ym%?oHNZS(n`A{ii)Ve)0;sSy0E;^1@YL;;tC2`Jl;=M4X%&OaQFrRmf+rT z$EW#-Py5NEJFCddau4X}$!+z0kJ`%?ARS}ekdjnC=FPK=I8as9C&a5`b4X^O>imFN zofZCl($s|ihSvT5V}zj6y$Hxo|MPgy>AUe_8y{NZMUu8CTbF7YKFHlm<EK-y;9bZt z`qFhr+|z*DYoTd-ZtaZEcC^rPz(qaz{D(i<LAjMUSW2DGT_{wx&IF20iXG{=$wevO zG~O%Gtr=_F0DGMc?JeB9CYC70lHq9HHh=6-LQO~8*WVpf2USo>t9b1pIlKNd+2|xN zr+4gRWbA873cN!wt%15K$oHb}4(>3_`ol0vbKmbb6iPi@*m8YxaA=Eabd@dld01`o z@D*Bp3JTe1e+gjak@Mm7)ZwPrSkL-?aw_yWvzld!_>g_|s#RPi&zG|;6mlVZ&9(l^ zQ81WSjxBP>J)!=v1(d6bn@&-&&4RJn11MpyVz2sm)j1$)#X3A{4Yqi$Z!J_w^1>QF ztTt&RJoFyl_K~@FM;z64?@nLo)||7cs|@258Fg%cB}0PNi|2KR&C!)#%kQ{8@z`6{ zbwYzfZ2We-#jRzJNkB{Iaq$YfmRpUnhDL-$F|Zj{4vi(Cyp!w!@O74MT@(56%_|pR zUysG6wxRVqKa=X67k?%}ycQ!{KZ#~;F+!>1KXmsyDU&q@b;8P-kCr4)pcO~gMoZ=; z>OZ`&zNz1)Xt%RO0NM}5u7LEI;S2qW4&8+T%xvs2S|)3Br7wXUCcvXme~4xkI~Aca zI8v(3aMHVWJnm6;COX!!F;(w;*sN<vMccLCT{xLhm^H@=&$bxO&O&$sI}Isa#20T? zB153b1R`kdL_R7|yC)8S#@COvH0)5LFpS6ZDImDCtCTeWaOkgb3ccG};rcaOL5_2+ zOR;++X>aJfW#(EFdZt3@`us^K`TtPjpX$mji{8$vJPOWP=<n%k9Wz&+ScB%RNrDnf z@ra`>0FE|c>Yt;)5lie04DTMZ3!b{!*ckZi*ZX{F^FF0>qccq2nLb5uk^0i6t?zYo zzPJinx`+=GIW8FJnz<Mb&w4y)O6_tGbYTTRMLymq1UP3GYs0a<iANzzMF`g<Ik`vd z27j<k1dxStmKiP|DPOWb$?rw&vs~rB_$EUoo$UJyOrVsgz;BvM7szfueghkiU`Y8w zP#7^>Ibn{Ige%qDY&%s5?Y~|Uay2vv=!nBJ-wDx|T`>1rKmxpgymdcfN_eosF?I|N z3dbtZ_wZ*qTH7p}sXTW#r?C`$iw-@I(>9X#Fg2wX6ZcDz@zjMC9Xyn3)8h;#J)1>H zCi0oLX`y+t2G;j~ei<UAt-8vZAir-&z(#+A^uUmS2M2?OsG}E+Unn1&Nq)LU?Reu+ zJ?k(Mf+XcT@~Pt}G@^<SFYdP(OW_{>5cjzGi|BhBB(czs);<lBH=c7XMV<1Qvc_AT zwuB*uyUv_LxyQxkDT%S!^?HpF<o58vL8hg~>B?6zdwIXy&Sf=_z_kV_l}H>mdtyA| zpBXkPp-1DE>L!VoM^ma&C@DpNBree@1kBcbzRc;^hBv0WUUH*xk<vduNVSEdtfDg= z(Kh(yF4(F~FH?pA&{4XtJkv6g2!FstN{{Y%mc&P8)tlt#gS20IBhg;-vg_n9y~C<O zwaMwYTgT3O&s8c*%TPJHKlQR$fI}MBvsy<Cd8Q2~hFwsCoYw^B=w6DY8R(7Ww{0cZ z7q<@UzOGJGHm~2LtlX?<(A?Jh<t86w^O>@d_%)h6&SRlCrCdjWkB|5^gdVAGJTV0X zvRc*8gCZNzE&9B4`}eMiXJsrbP;2-*D5t)EbQm(lapc{amvFDtuBfSo?I)2>tQ?av zDCiKk1Hz%1%je>@um8PVJv@$C#5SP{VL2|g=Vtfq8%Ls%d-!my()s0-9q#NQj<dpX z=s3A#Ns>Rvb>WprpP_eJ&!m*wsu*xy;-k`%1`jGW%@MM<YqRGPaL&HEUj3^c$VQzN zsCv#A6jr?Y1QgJGJIQ0M@}0!i8}B8gyNIOwCYuX@d9y--N4EATmbQ1ZC^isY3O{e1 z4Rh4|At#mOoyAj*N$_<pDH8P)2QhOAKg;f?nm#zvzRWQ9Vzg9seE3?-%pT`p!rX__ zYv%q(b7fZ1Uc$1)oEf&3UXIX@@S8s5i!4T#%}%R*+Vgqbt_FVBJvt-^5ge7GYrIyO zmu=?g-pcOXVoi7loQ|#P<xKemq#h=Ot@*4xBv~c<0V+!TdMgf3?%tz2ZTvD+TPNi~ zw*=~=f%wM0oDwDmHpipSH78*|jPOA}RA_H^lD3dzrNFU#aB|6pQ#=|xpsE99vd$ms zTJT@ldXSM^`1CYnm|&#dEM<kH#5Rv~Qo7oTHNGviq1bcj<{XLSmR*CR?^BnnGxj<T zBg^+!o%CGH%sOtgki40RD<5}`F7WSFH*z|?QRcaYFc>|FRcIo*Fmr{JHvuSAYG`zr z*f(zV0$*0qFNsCmj{l%7JN|kwq#7oquBV?aMCBcDZyscKF^p#foz8us3ec=?p>Vq4 zO%S*3j=}MlfR;UireP6>l9mvGRur11A)&XaAyv%{C4yWix)@knLTS)d+`Ys#BB6a| zb$-0Z0J-oy;hz5sUPD7Qdiq;H{jrILrp->@@~2~CpW(y?+g_f5dv+shX|z!mK$5j> zfNpaYRm1*hcWL~X=T%YB!*z+mVRn1+`3Qz6e&}UhpsiB5d&Bg^xSJ9iA0`_3*9@f$ z%}RbEiHu*K>%A%YNSsY0Cyn6%6-|pau$Se{mH-v|Ei;NxDtaVDHfo50P+HeN3CZte z4X+HrsLFwph-_K?m*-PxtGv7}R0U5iFYpE0#cFzfn&7UJ6bhC90HVS>cd40a{VqWy zlv&g_FdO~7P^t6*feB4$(@36*-@{9RpMbx3U~=^>m*E#1Vc|Y;YGQx#s~5?YQUdAD zpBYl!(se4=xs=NcLa_%3PkoA&6|T8#(H&jGCkZGSr17*PnLP7dOJwYHo^r~}>JTHc zDG?hyuxL7Y^)o{gMH#CxHlw18)p08C-|OGfIsYx8{oL?vAd|h{fR0Y*#+_)FqRq{S zRDN7SQ0~HIBnsr4i7#$LiMbjkblHXGT(mthTb1kBTvlR5`P{`Ux9x|YmMV2X!u1R@ z1+}dlv-RQ!B+U^eB5M74hyC_ab80G^X4M3BspdCFj54~0^vWkC(t};UIM7yIt5aP# zkUThf8;{7Kfsiij6{C}_<`6I}bR==m;hyb1CnwUpe3l;ye~JE6fG?@4gAq7zIF1eV z0w_pMzcXjpJl2kOT9mFujZEr|lvQ_K6-;_G6_OxN9sl@Na9XgMNHpn(n$LEb);)`Q zMUng7rD-nk?Fo`|Es+EJ)S<QHu?bp`sPHHt?tf98NKkO6+T=-Hn$U&{)BDf`mmt<} zqd9ZBrFJhRk#+>VddzJ7=i<WB8kJ{8bMrKsp$5)(!!9qKeL2N>Y~L}l$1JzsdvuTn zbeICFd;2!Tw>VI}b9B^5K{BJih)?jSuHs$Tu8jCf0GG`cQ;HbtyoSq2jaJ`cNU)`s zjd1RL7+2Js8+C>KgN^=46HaE%@;2v@10G=^Di;Io9`ZJw+SD|1TiaN4n{Y^E<MhZ_ zL4twSn{8SE5s$E}i%UEAYd<VM@<Yx-Pjd6V4Ud$Qi#fHgsR8aZLSN<5`s`^7MMbeS zvE-UFlYeHU!tTXvyRi?wJ|Pz(jb_x>!nWq3{;XFT6pCoPAJND$H1<3Wkl=Q}{mxFc zjX#<tPe+kX+lxy#QI<iQ_2_|C^?mL?(vpgGUoi&x%AHKuN?;I4t<R^N(*&C~DtrhO z&ankgmDcBPFH|YLsBY0O*4iHYEFgg>2xn1GU<r>A$e|UZ`sG59llpq0u`&F|*fX&< zb>6V{?e0i9E`#;~fXy4+9KDwG_kf^c`^aFGpgH|Ao+H7vMEG<6RooQbeUj7>Dl9Ws zY_!I!jJ$!3H>n;G*#rc~%9RoK4%Azta=zTM@r`K>wJ~9#q&vZN0`b2>(n!nYE(yvx zZ#^j&e61~{=f(ru*<LM_0ILmttm=x0$b|T0@Wupj#ffLGR!Ycz>4>^^zq&CZl)KDU zd192i?R_adFB?Nb;`wj4WNMtwzDVHrA8oEC#0&yQDYT7H<CWsr5U%%}I_#=RoBr)9 zq#C*Bg(u}ZZp=Qd>q@Bfx|@nfi0z1p>CRsX2<j<mYnwj}`;bs#p5%f=*{!rxCiWC~ zbRKr6XF6s~n!2(T9Un&VL&UOL&Yzb>-%Eiw?hXU)1LDg`TUA-m%l6=sz51UrI%kwS zxZ-oVK<_DVh^Mt-!9v@lPnESQ2iR**Jbdd6QW`L^vhx~z|Nf@`?Iai>!H?=E8>p^F z_aYAK1}sM;Z)ksgwZzP)b;r|QCI>Q{nb5G9@TjO%t8HF&DKi39DH$*6S!A?R4y#a> z13vL=WoylTWN^uQ{oz7C*wWL0`i?eFjE0APEIDaYaY+-+?MP&Ys+%bC7afF2e8HVn zX6}pe*FR2I-`e!fk)E2>wu#=GT;B?RjK%U#c1$hMcPuDOEOZ0C^py85a*vB}cX=06 z49E=;uH(>OLxup$bG2rxGsHrkGPUWBW;yfsV|PBw$9wUgI)qwV=A}6*79Cmmv_5%x zsv*}_^>*@5VW_nR3y=OTpV0D;%^cobtKU#T;HJ7~+IqZnIlxw3KyAvAPwu>gxu@r; z<6ilgp{EoRgP~iBQ<q9-+i_5#kI#TWqEnB~nUDnm^%ZCB<L~#mZr`PP<b_N8LFi;P zhrQ+ZU42s+qB5ZchcLo<-AdegBQpI_{lP2Q@Jm%8VJ>p{v_)E-j8jBjC&NMB{5P~y zn|*g4B@Kj3n1qGZ*V+*2i<byxBUDNcTMLtvRYfK&G&W*l@)z|LQl;bT(q2~g&|VK! zGTxWoow7wlaFxoqk8UMLf0tRDD77rgJ4HC!-+uJD=XB(}Rq}Byw%(T2GJM}6O9{x* z`FQA&ZCu{K;c_Vz3Yzm3g;Pc41qI7XD<Q7LRGB%S;(I+Ry|jEzl1xubgtc7u*%d6? ztoXwuo4GWr<h6^<w~t2)LkiuAn<d0nDE0@nC$&sYj1?dhY>rn}kd=%T8^N8u*`3@c z;ZBn>vWwE*8^Y)8`Tl&ha4LI(Q&PK3^YWvU0zNR1>9XfWZ?pk$ERJIs$sY~hL3(&J ztz8tSQd!FJ;m`5`j?0Dd{us0Z{0nNSVP4jY)o^sy63U<6is}iCHVU?9QVZLP;}!xX zkOeCEY(MIhrBujq^>^B}fwu;_0i+$lif)o3lwrs^3p~W_{_Xpt+J5oL4OG8y=9+4h zVRR@VZM>ip1Jtv+-?MItbr%Fax`7z{UYcc1Yq7CyT>of$US_6GEQ+a*%GrP9Z35q< zd~}KVc1>lWQErlK^p&0aR9VN4f_=^uwzk;~rK#u7!M}98jZ;!{k=Z{Q<6ar%JQ+J< z*R;?ONS0yH-6=|WN)yI&j%Se)S2*te5L`b4FlF`2Bkb9+tcR*$c|TkfF0GHhx3#WR zZIGwo?Q*xza-Xu>L(2AkKV4G{O7?r#<M>+oFj(nmd)TX@tPrh!LZjD1O+@K+TU)FI zytuf)N?n)J+x?m?C@Uc@(&)r$AvHGn(Vgt$gTBwMUm%FrQY-#g%AU-g1=g8Vc1!k2 zQ+Xx3xwrVtMK@(W%TiHf!$3E-uwp{XR(vtHWLjjgs(1yEs8ewaecgC#gPll3uEfqZ zXYjyLL=IATH~k^ai@?=8s;&@`h+cmky*a35@K1H>;52~<HnBy>^~>p*X^%b=Bd;0# zDWg%O8HnDOU6_BmfH>1C+iJBkgd6^O5BS8@E#Z))Cp_OaLwxb&rNq}jj@>nsS%nIu zIuC%>^QqH??eM4Qm!e#3OTZvKx=Z}a)Z)lCxgD8fuYhvV<#f^8;bk|G1m0FZ=j+LC zrKq!}bXmH^C=2qul_3w2VH-RUo%7^LkEf8d4#@*ApvsfS4mlTE5VNJr)U{I=s#@r8 zq#jZ31Y?T|>m)hR8c)uPf7tj&@F<kcbsiU6Ia{T4)b<V@_~sWRC1qK=QP8zdQYQs^ zd?|BFub8wxd*4*hsl%HT6Pd;tlJ<uD-HQkQHKwJ0Qkv3Z25BSI6~kxmOJMa6&IUdy z*m-$fTZ}K#YJ@qDlKTz5#ZotJaH*++@Y_8;q&C2*3;?GJK_oy0SAw^$;igXb&jKww zRh?T-L2A~@4*E3@g6o>DeRoefN4sR*ky62FMU>^WGNK6753dE^+irK24pn7wmUypK z)-Xl>;p)pDzz23ZEOf0e&pGDT%&{+WpQ(L}36oeqCq1qy&lFC0Hu^bFhE1%7Hk}_E zELU;w&}n^{v=O_DoFgS9UBRBH%xx73dCC$Y`DcDYOJ%8@yPo^LsjX7l_Pc`O=y0K8 z*`1&J%^yRqLge0*B|&=ozO1b5@Y(H1b7bcv#PsgHhQ3WHU@V}m?`Us-=dwDSvARlE zR8;iK`TW~@C<M70ry3{x`OO_~89sIOk1-#^!E#|18n(2w6#69l8o70$9hW5U6A}zK z``x-^814$B&qV3(?32AuRR}imCztoBr*~LHfzWYx#o^6s%=Q5&%Q576WXI%=cl;YV zwebXx>ER>E&Jr}I_;D^Qdv&nj5n3o0uF_{|Y1>o0s~|3@>%QJIcB32a#R(ZC(@a(^ z^J2E-2<z~P|Ioho2AUtPr?0=0C5q@$5gJKnM}3oCSy_<{4XvL#9NnwT@mMW=^yzpy z&1rX8x7N%Iz+U%2Pl`$Ucc}&Csy9-L=kL6`crkhGAb!xe{9G+r*4fY%ASC}YKsDVF z8wG=&oCmf|yM}=CM5-C@rw)LXx(TF$y>8>@{7=UuS@%0af4NPEeLo^i?y|0Ib&_*m zO$a_5x^s1@S$X1V``x~Id89`4UXew5b|qvfD>)}Fp>s}El{IFg&~3}CVv>Tp&k#A1 zA<v|?>BbQDC+gdzgW>bq8TTJFMmcTXyN-vM=tFj(P%PPA%4gm^*qhplLJ8zhc(&$* z6|T8QJMHIgf1f*WJh^xylnf;FQvO@zY4C65AGg!fW(HUD*G<L9{~9UR_wxdF8GxP4 zEM!7j71~R=TJrcIVdY^D1#(R(+w1CBM$l7__6~N^oq46S)a~E`zK_aqCitfsTgz(; zoufBt7ed&U%|3Ofh-d25v4sJrpQovliW8H3)sOCZ<rSv+cw1;(3t=V?klAL>Ig+hd z_ve0++q^2-=j=RW`?y0r!68%Ppz-nI$l9qS23z3)uLO6u@8`bW3cd6)|MNTL&Ntv6 zl4o0;%+d0fNV`u5uh!^g!t#%IawpL8uXcQ%p5Y3Ai8ng|ZY*vZXkWlO_=<e3!#SV# zqla3AcU%*ve+a^RN6*FOt92^gt)GAY*=0nm8x;VP3kcGD)c#a>e16+W(O6V8yPhQi zLZf8Ok)T!C6Cf&$0@kf9;+mzoxsLwOLrt$c;}#4_=!1^j*Hf0X5}xvFZf$GU=`~7j zR8Xg*m6D~8)~Jr5u~Sm7MfI~367x1IC}Qnn@5O}C+y}OEt(t{(;mytR$T3c@tyr~~ zq^wv?hOo$@gT4_tXuy7t?KS+_iYL}Aa}jd$2C@Ud2fobhrGR}3T%ekX@O*e!YaCg5 zx}$lAx|D|_3j7lWfszx$UUD;L@J(B>tStDnsxA%9L8(KyFEoeQ>v-&~Xdsa#gM)+9 zW#?+2@c}yiPUmy{TwF}z^P76I!{J5+=T`=Xon$?lvHCr?9Quq*=zeSzo-RIOq<);d z(`+vB5aG3ixUW%b;`rnBRrfWIv80!m&J@vSM{6Daj&t23Lz(Mra>`1b@=6-EnqQyG zj-6F*w;~l09<jz0-9@f7Z(40MfXq1d_7l9R_`hA0@0h}T(2xBavILtE@37pA@IL8F z*{gWG`CTBshACoEky(J+Kz|+_6INzs91xNs?sYnyT=`rgRih3lSeBh0E;;?UDm1^C znbW(wGBho$TJ0Dwyzy<dd`-gZbn8<eW#zi8*G6|_rGuGX^tQ}SBqyyE$xVr3jV{*5 zK6_Q^b!3(m`?ZppLX{iZz2CXktWJj8DwHcK#ND@IeGD1r+A=-5QZ)(N=3YLq&3@*^ z?mj1)GAC&~*s?X6GD*~XW_vMY>b}P8W!J=;I0T}*=Vh7po3~(J{s5e`{5fwzz$XZ7 zzq|vh-y8+P(=_T|$$hs$kIjRaGS>|LTp$Zov4BK91>$h;Q(5lr5#$;7&hGAePgJ&k ziN#VcXW0@;R6s%k73#fhywm4%B6QeWN^)2&Z%{&7wDh$l+uA!Y(LBWm$N_%jMJDWI znJ=m!+^4A93SE$+ZfRy_&)n-pz15R|iIkwx7WWgD3YWIFS~L{hSFBS)eTK&%i%-N< zLBm%VOv`*asDAl~Vvph{(qney%Vhm3f_#9wxxjW<sJyn3ZrHkZc(I$c@g-LV+ntFw za+rS<O*$3R%-p?m5@)&<hdt<TU)PZtt*xrqo8}T*#_lcF-U<!`hx<uWhevlpEm$gw z?dCiZK6FDP6lg_Vlo38hL%jz2r3pvF<vU*}E1oPk=_OHeMS2b^l;kJn_DxHksUQB* zK1O{(=~zc8ryg^ir??)Fd&*6X+rq#cdFZ=J1N=dT+mWKe^O(~|CKaxG<tcMwk3Pm^ z^s|;Uq85a?BRa%G<NA<XKMTE%T)d_k&$2K!?*<A0d4mAEp6;D_`=6djo~pbdrR_cs zeSR`<jmv_mvaJ2kfFt|N`<Wt*piTSQ$>`dz9T8=(lO^LcucKX7x<E@a_p)TDD&ZoG ze?@e30!ir1947y3u;_$V+AH7{k#7eTo|+VGAe?Eyc4MWuS^)G2a2CHdGtnPU(sRAJ z3l^b37TfwsJhRbNtz_6CP+~L8r}y;ah}~!iIBZ+8`0~#2Bk`@6wsw25Y{_yTojGXA zo2olLP6i1@Sa+ZjE2x>>s^%|!_oQ|0xcGK`$IpHpg>#bw0wD{iZ;yTS0EY)C(C#Oh z0$NGR{}rS2Ci05Txg04#43GtbbFXf^@-N^IS^x*)usbrnFO5%nfCD%b+bP<VAdiH! z3CFoe)s$@v5ddr7qi1kXFKW<%@a2P(Uc^bN(dp)=J}0&$^yx-!-3|7>(|MTMwa|M` z^X(7Br*0uND_Yf7hDsi{dCu}hDWnOAi<C~Drag4-j^DrMGYM#nF~Q_y%xqjZM7kQX zkbg-FclfH?Kvll+{`~Cw)`o#fP1VOZk}%sVN9z{>KrGW9s1|lO{jS!S?7f&~*M$H? z>2-?B2g~Jnt#B{Na=U+KxpC`c>LsJ1M{T(|djDr6(?V2^XG$C-c6jrbcBOR4R3tel z^tE)ppVZZ_Y}Ichm};MSYd@u&d`>WKcAco}B(UzO@fkB_Ti#ay{Iz7&7;}nbNz-JH z>xDP4Q*C(XBpujQ(cHPQqMnldfL$Sij7;(86vScrPwzc|->149KLdIcTBxHzv}Y_t zo^Is@yf{)};&Znb!>sSc)L6SLO*dv5Dynwdl95y=NcKLl-`A+f!Ebqj{@Ji+(uY6q z9iwWHf6J7dyG^fU;f@cklYBODRAQRBvdeDYL5eNpv@Ac83^&^T^3|AySInT(dqG1n z0t&UVwe49uJ3V{aUjIC!j;dnG5S?^->g{#1Tu2w+JXU*rGVviRYPIbDV(Ke^qI$pg zR}>T!6eOgT4uOw!gMxH-EueHuE*+wP3X61icZ1|&(A~|VfW*?>{9nND{Qk}`10&qM z_q->cbIx;73dkR;QPa+2L$uOmD^dPOdA)GU7}dH^ukKAO&lo8hSseuNJ{uk#L}LDC zEXG%+Lc@U^-DNX6FNbIjR4R_rG?^*K#Cac-O7(iXgC_@92o6ap$)l<?>|B4MxHvi0 z_UkkTCnoZcM<JJr;d`5HZBc9iryZ^?f}5(zJCP(B)%;_6jv-h271X9V4XdQp@&7Ed z*P&>dLRw<9tqxa|JjarJax0|uri(Egk2`~q@1=_XqX^+111{H-gFS03c46LI{_#*- z235~s8}=|ILBb)w+jsXkM0OKN)T_!#?HXS4%)0vb_Ga##|8Aj<6k-<Qj#B|K(q*He zJqJsZ@ZKG#36r+S4&z7}f=l7V`@^=4iv-vYWe<^?FoLGf|0{;RhCasj9r;%|ldUqU zhPEx*BAGx5e{&$KO{bZMO*Ppu)4vHeA<1NvF*N5t*cw#ess?OAh@GgCNE#5IhSN_2 z=PhVClHn9WtCHFU4h!vXq*eH}8#4Cfl7tSf-Cwij|CQ=Sc@>ucX#oQFuh77{vw(x$ zaR=?XOB^3oHCSN4V#3bVxb}4)%eKpy{d3#f$tJIQ+q#ujohY?(YDpZ_c$pEuP|{%D z%14~Z``gyJjYe$;<t6rKNA`_}jXtTA=gX2NDa<KJ0x+4u&*aUDvHTtrm-Wc~dNkyf z4<@|yPJ3}(wYRF6T>>Npte8xfvyQl1>b|BOch%c~lVg!hZeF?KRBf-lj6qF=&TbbD zKBlix1?myfZD|Nqd<yI3NVbomSrH&2Y!wZquXuJ6&7#}M4+DKTS%VYy#>;b`v?ZZU zboZm*fnEFt!sq7+w9>O!-!Cz9;1Z&;DEB)~Aa8;$Sv}?Xa)srGWC>r&UXQ3@chcd3 zdaQE>tjAy9!uf&Ssl$Z)%8&0xg3;LOc8K%5DkifL+s6G42Qo<!;xB#3n4R+9dNg>9 zsA+?f!5HVi-P+PBf)rzvXWuEKotr#$bf;**hx`4>P)L$bb6dbgFmK5VDtqejkVszP z{hWk1br_G+C3jLVJ^dt=nYmQ{P%oH;>z@-ow^*4%9xM(Dq5pVpRRoe-3=E7)XVfT( zrh47MfeSgmlhV>#3;FEwneIF}Zn+SNuKT`}o?G8v*KF1<QONhXyw>cTzBd`gFVlzd zbAMlNZ%zC9^S_@UdYZwe-TRk_E{H}J{DS%FC?Hm9^xAb`Db5yb&nMp`jqxL!7sYll z8;PBi=Gm%@+E&ghS&~+I1FKMn4%+Zc4h}|Ic8!&ZywUmj$0kWIYisL)bvZiK?J8e- zdU{%m7ThUfqsYl|^#Q9G+NkiiWl@J#ul`RR=l_jpVU>OQkeGH0P=s7(s__Fxq0%X* ziFPre&oTLyGF2I+2SJv`?A@crl%?6YO5{8r!h_mPLFBCMI>Qd7!Y_XN;Wo~b=Inn| zolx3mHaM2iURqz(q4<_804pwZWaT1KA+6Y{r!?aiV0K?GmyaYW<)H!s?TAF0q@w+; z+w_yTA*L8kRGz6U<o0)WV_0exu_G=l3G)ED=;paB)}%k16st788$FZKVLXO0TW%uT zQgR#?diF*5^4R057HquOx9gANFze(u&>X{%4!6oIT7L!|4#ReNm9~SH42*)czAv^@ zm|oES&j%XDM_O(n$bo3{*Co(uXV8R@qR}K93u%3X`52P1y_J7G9;)UGV5GI_w7K8^ zBr_s%=8q&Ww{kz`Z=SVgn4X+e*+zN&zHg9tDM%5DqP*PpH%YSVOP&eO{Nkar_t{_Q z#Gt++sXkQ1JH2pM-))fqi&dN2>D{~3E3wq{zDxa3CDk`J<(@_B#KM!{>c>?v;CkIi z-M(pna8)gQ40S$wB~?)lmafuXf*sa>XOs~tbM4b6!?lG6U5dNPK$ZVzOu%htA$`i= z>`x33gKKpJ+q#LB?S1~qM>xxOMZOtqyL$F4tuHV4J0|b09Zv}f3Gus@mfJlz`^$r1 zl*Wqc4{@C>s))Hj+0Zy+|N39;oI5+KbSpBo_n)4Iv}LP+@iwrr9i&7FT4ilSO>;2x z@Jtq$<9p_2F2`T;^71|#^s&~?{(LB+H+uZG%(|V_i7>fheeD5boZKqP;8H?+$@?l7 zOR%j|o|z%thr=46#VBC0dP}`YL$@Ca<{C0^Ub+(Pep9Wr(iE@kl~5TI{lA1a_FvNe z2%kIDSY{*oCA!PT*7ZPJVUwEvl2z7&MeU*CZj5jvBO?NYzMb7>`V<)2iin7?5=Jg8 zfYV=K6(kbrCkUhQI-937*ma}L%gTD~vqSGw$mVk_Tep%;+QmPnl5+Hm-lRyqGOO~% zR47Z5;6hF{w?$G>nq`qXdu@X*MF>5fwt+~!ImJzTjWRe|-d|!KoK)h4H<+frIjIp% z#OjrJF62xnyd0B?=@o^Qw^5(~b)Bfvk$LcP*KKPGIh>}XLh49Yw=w%jL$-e;N8~)N z{Kul@wxA;A#a1A#^Z;I)waCWsK>H-L{;W9lFW#qxGjk`->UMsQU9|X{aako<jSmQQ z_0zkf*@F%zPcDH|&1Z-Rqi}EEWTKIt=~yT~eP4kx65dmCn~&SAorg~m&CFI=nQ3Q4 zQJxP6R?$bQl|Y~Lp-3{APts**@J{Lxr_J$wP?p1K$50Blg>O^?xoCc((rt+kMhC_x zou5G39(P?Pr@r_|?YsxW{5R2`nl0s<puo-u3%Z7&KT~+A$&9q|PGEDCnH-|Of5`{W zINhi(`2!6-Jy;(~g3a>zoK65-B))I|=wTC!$L~m*yc|b+`gN{^Dg1ZA7aN<xslR`R zaT#O`f@FL4boNj>d{RI_R+x2>SH_mX>oR|`eryxVlJ);fMpv`%YWV#F8XtdWYDXx| z(A~(RP@&F;HqXRbaPvIvomNIhhWnh~T_*1y<XKM*3fs;#2^6x(LJ+@dt@tH9Embb} zq7A}ns;b3@XX{*poviu?A}}U7xwx`mh|?L9F+E1gqh=)PcOa!kW!CF7b$EKxb9+6f z5vX$%l3-Zx|1|d7jm8>=TvZb{;CyFq%3=L`w~h9o_sKPD7gC%|(kDl4BFfuV82&FC z*G$-k?(1)P^7XD74EAQKob;D8sTe6Hew}|}Lpq%ZL(pSaS{Tu!ULJ*pq7WCTp~Yxu z^<4^AC7-Rko1n&CU0c=J-(I2)V^XV<fm1_$8j<S5kym)Am(yB?;B}ML{-&)~^=ohG z?~fzUzf!tiwrCV{&iPfpsmY?UO1<^T`6=SEUd5TcSf?|<p3-d!wbwt^L?b;Z{7riR z4eIr>ZJAGir~QS5o%e1D>S%ku>bY~+_O^ZFK~;$=dz_k?X3R9+*hP=?DD?aV0c<a~ z^7Ft*&(km|4NrXjGhA(xF(IXYh%_fR<!$E#xsH`}lQRxLnpV7Gfne4$wlZ~VM)AVa zSy=deE*gX{wlDY6^3Q}%a}YV3UMEOeX|eOh)m3Y@y35gnuilnc^`@q#d*Lw+YG%EO zMX%$&{F=AFO59}HLMb(6tqOD|Cr6!<BdqR)FmD`yEr8U&e?BeReHAsjNltH?84#<m z?S)G5MQdW?n_J;WL1y2^g!)Ej9!x0oiJT9Ks8jvEB*{gdmiP?$T=rZ>(d;|JEL33@ zMv*1!c0&M-aXwh%Yg~TKHfR(oq|w7p6qlGd+;=|R<&5+~YVhI>1Z-?@rJ#c6HA>65 z+%I;o@5FhlB6J7XhZ2}CCvJ|vIh|&baq(9hVA6JNcKtdnny4b$)G4YeLT{bIc>l7h zvU+v9O>vd&;t!jZ-pJdG9K}_m%`+}(6*G^50Pe%$)uSAn&0&Isa)U0%lv6=a0wZ%J z;=TwTj2nT^HOK`3kuH`b)#}E26ytnIK+YLX32VI^uqh-7Shl!AAm8~ZZ;NL9s~osW zJ3y}RvR3T&jdz1e1|kWbmor8%ek;l-kcH1LpKo5?pYgdo=PI-;yF6>GVSK?+r1W1Z zxmbdxP-%;l`w3j(3cni|cyWa_jDS?_G=Ffyx@ZJ()+Kp`S?P)ZOcCG4LK$X|60ADg zb!hfpxWwS(57DWI7v)tRJK9Gwt|c&f`8wm@Qq4%Gt3$dnpKd@VyFo0d`?Lnu%op7U zl4OXc|JD`r^Vq5}MGaaRobt=d$qkp57q%fTZO)g!q=eDf5HCldif!=A!<@R5>h()u z8R^9XDVN8m`$Hn<PF{aGQlgd?Dg7IDkmnn){U1aZg|j=+mx^Uta!F9=q?YN@W@3dm zhSto?V3+=1<i1z96phJ!r}m7pt9}DET$AZ4u|t$vTmJ;qNYggD1mhK5S91f+?xhwH zSAw(u$n{BAM|Wg!G`o#bBrgVW=EF=8I+j~r=pk|j3(p)i7bl&Z>J&y^6bI=$W@-l3 zXSknjN1S9CxQ8TP><R3rJv@(SZEMr?YBFZeQ}o_ZbzhP7QGg-O1;N20RT#)L?0gWD zOyle1Flg3P=jF-R0#`{`y0TC4dd3aD4=C9NmeIVg_dg1)J~U%nygA!VMP`BWdEanJ z0a#(CGiW?BHT4CAkOClJe`eEL6NJgjQIPLY<~3qi5$pCPY+kId&nlJeR%4LQG}g<G z9n`Gu($nwH{R~|u-#n6U+)YAc7`4GyJ~Ok9g;7gZ+DvI+KX}j{mxLG5Va&<So<843 zIRYYoDu4m3>JDd1EZp67!toz`93Gg+laiHfvFzcRm@O{O%gax!PwiD$Q7_3~=R%1$ zU{U{2_5g4m{*D{AO{&}t#vdQ3yf5Z#W%B-IZNllb>$l9P;So@QxsGqj&`5v(jmtOM z$;_TT{v-oTAYi8m<k)%6le&Muub(M$F)uRM-;dQ{A4hSv;UyzycDoNg+8LOyJNfEl z!fS?~QWn*;%W-lcrFS^%QL@o^IQ#k(Kq|Gx2{oq^&d{pLs=TTq`7|aNF<kt|YW^z0 zj_YnhRtTw;*GSzzi;CUuGxz*=r{Xq~c{c2fX1k_*Q`I92?m%I}GczQ!`n*RsnaTwf zXF4)_OCIU>eryKt+Vc0il*3S%km?ou=F~=BqnTCcv2kp7KAYh4I;MLT2czI{2WH2a zI#unmTwO$7_ed5s04~s-$%)rz&K{-QSy9eiv@x1WbxTqx%$HjN?Zh_!HJw)dyA`lO z9e)tIITb^G*?^<{Kgh26$c*!5I|NJ^8H@D0{;@}|wlg}vT9(k&G=PfSD$Tqwe%k`k z>I`Tm_3+^06E5xm0pK?_BK;ct1T<1~>yzqnORDq=iTwc2@Yq{X^pPN)3C8ac9yt(X zZp*uH+(<ST6&i>#u=M%wZ+md9dI|m5V_R%$h*9Pt!ayhIxAqm(KDx=SbSvy0d9%4^ z_cd#ruZmkT{)5gLZW?q~5f%_L(nxK$>fgWSrjIC?L^M{Y3MKF`KfzilFgVW#wo<>h zs)>*=xIE!maGT99u`3#>X>v}P-ODx@QUyBz!sjb}xojlE9EW?owlStV!3GCIpTyUZ z5ckQVH*;qvW3pog2KA_sIM=t%KJ-e6WrzgF9KrS8Q%DJ+)ul}NN@e1PE#LY12m<Wq zix#7bBPJ&^^B57#VKmsrg9XBL_*i)*2!pH6TVia#naHWO*Fi<fNVdFJ-D0#Zz%61{ z+ry|=H#cMIX})zEv-3NzR(gZ{6gBIyIYNXuqD>NXQwbj?##wIlbAgVIQH?!mVH4+k z`~`K^{%ukx-NY-2m|5OUVu;v+iQ_cKj58_>FIjm|<|TC%uLks%g=71WVS8uK?)08@ z{=u!SJke5aqPiWKl^UOV?y-E;?K`MT?%QAo2Ww<`6I<!^O;XzzOoQ=}D+r|7hKT9) z!b|YLme0welTXxEeo}(L5$QqSniGhtf~;-=2(I`kaRXq+s5eQV<RO?@IhngFLL=<} z)og5R{47r80F{i0P$eNJS7)j!ZOS(aKCr%ry6QuXKM6~yXplj+V!Q8s;vgYU>CfK4 zw)`ZqGa6Ptp#)>1mS6hNph}!!!FKA_u<&=G7A1g1Y@s+jL~E1GKfT7`)hF}Vf|B3Y zpKIB8x<UJ-T{5%(gd&0TCVshkU6N(E-4s;jXjN`6dRpflFzy=j3s^b`0WbG@qp98& zZSK2V_L`%(jt;(sMOc-_Cs(}=@mG1qDgf7B>P?B+7wmY#*UB*WWPSa!xhiMsb#aNS z!E2CElo>)g>1^w&mLaW(6y!?7_QGvh><z3_CAQ#?Sf4El$c*y-Z+<zD0}ci}>e7WW zKA3sB4K3ALhL+n{gaL1pnU=PypVND7a~iX_&Y{3N5ME1PRGuYS-P*YFgrINkZh}n5 z#4x?tlt#yJlLv@$qKY2z!&A&jBAYPURqaKR=9VW$_@5*QJ`qxmHPrMBMXi7IH)CGe z{xIPGLX&>dg~`?|rQ(>AYbs(d$wD%eHaK~BrLW>5PgInfB<fQOlh2N!(n*a^1f0C! ztd>;n%H+D8EitYw4hN3B9(WNIlgb8+cnseFee%`f&OQ@<xc-F$qTnlyb5Hm1Sv)e% zg;VvZq!0ycPjTt?$&r-k!`4JFzm5}}9U{!NTHIh1^~<A<*=NvP4WOi%^dhx8OSYoh z;)}D7Zutz{3O2pL2akTV51U)t?-mRkErIlB&R5P(QN9?AlYAX3(2s&X95)*nD2q4X zFv{9gV8Ky&oV=H(teHaQ%(eQHq&`dLi1)xOy{M?1er+`zz&JmUWdEn!fbH^j?!9Z= z2cqS-FUV(8<Z!~naRG?6jtUS4C&wTy$BJ{(A!X*ps8bVx^X<y!2Ac&7vy=5x+w1>j zHRaU%9#-vfD04W=423}#dnfMPAkW1MNP=dwvzTjcDUEQsPU7X5dar^jIYFfCyeoz$ zS78K`3t|wm-OM5BjJ)81wg70zSSbpy(2JX;xPqmwI@7Vj4;8i_TNROBHGBIdvK|L& ze?8@|x~A-lV3HluDv}X*qsYxz)>MqJRD+EJK(vSk1hbCj-KBe0{OX+1r;b9AhRn<J z*N9WL%kRzZ;mB+{`Y45*D2r0aky`Dot=5o1<YnVt+Cyn_@+ijqPc(Sa+Ezd;ph44r zEBNm}h&EQaNTcXAtyW(ICdPs-c{tOE&@JHgi^m!j_+9(Q@J_t2UisiTa;p67MXq#6 zhu}Pv4F@ISk1(m8Vkjnk7vGVYkH*RGhgn1osVa+{Nv`P!Nn5!%Als1pU$#N{dX}J9 zpjESP@+?$0?R1PODtc&!B?p0USONeHgC+yb`8rZY(}3j|{}+zwS?z{eHusn`Z3GD= zxjGd^3=J6nuvuF#>S<wK{!kIX^J3N|;i`QZqpx%PK3<OMe?S``zwClA-E6k*cf_{% z5Z3vyE_0Y3H`Ug6bky)&I(MI4F3yHIYL<D$Y`i5Du90vc*B*-k9J*0tnsj)|++_Oh zv$W1EjlI)VyCYT0R=WE7v-1wJ?Wcx4>xP`C=nF{aWAZMmUR8zPC_>&=8LT_TP|4Pc zaOyZiQ3c5y<Hp5MXc=AD`?08o72?`@Sm#VxWBb*Pu;;tA*gZJRc<j!>chPJKY3mS> z;mXhf6rCU?PMO^-WPbF(#o5KV1K({{tAxT)mduJ2OS;cJdJhDo7^ucfdOV1TJ<rHY z&p6_5mWfyUroS-3E6y&mUfQL3Wla=100uCVn8k37-GcOmfUGb2!}f$5DW^2B`iKg} zrukh@+hFRBUW{0{oK;si$!AK$yLG`(#j^F|1D1WA+Cyz=ct>r$=vKqKws6H=^a)x$ z*m1zel)EUC+XqTgrbaP@Fx@2|M^Wjq|H3gpF4!XJhC1A@rXg|8S4(6rcSQz$&Ln%- zW)dt5=d2t&^@dbc9RT}X;_*^h@=`~aab(A1^S~c(oUO<E-x;MihTIV=2m2IERh}6y z2BS1(`n-yr4rf#h4A$>k8-kX~J>LYh`IG_c>x#NxO9P9MXq_La5sx?>;^muKdcQC+ zrL$w!1mQIpvrL10(<=J-YCQ_h##IV!N)uhDO)k+osvmS?I&kjx#y+MK5^zl0IwPOh zv`WkC|5z7J+p!C%)!Szp@|wSc;}PbNI0^LmT3oMia&c(ozEbRJ6w)OBYrZpcNGH#Z z?+F$oUI^3VV7g&0UmaQmSfEc4W<f_Ayf`0J*OXRt58sQ-d2|x}EKIJWJW&x0kjBq% z^8Xij4NdG*^W0;BRZf0}W@VAZ+U?3reX(P;LcT3wj?EIlN4c|bK=kDe>s25PlT-Ie z2`@^yFAt{{CTiyLcI+ziBBy(9J791V@q$z%701a*D&<JrMQAR9-pXa-U|=8~T7buW zaKJ<y+O;dFZMEbtU=&O?rvCJi($go_?JxS6YY(&72C@4*!YZvaU4}WBs0Iw}-iy9* zf@Dlw`<GPjh2o`zP3Ulem)ZUqireM*XsH(U{9MrPiFtJ3r`nYGEb7!<a#S}))WnMx zu=(&en7-Z#Uw3wkzmI6{`K0~F^)GCOOAi?z!CCLW%{spO;_#cNYW8kOzrLDja$9M? z^OvmZQJG@u*BR{J4G&O&?$_)Of$r_`gxE;X58|7dd5r^F*txgG#0G^9rFdo;gto=y zSuOA|owHR)9%5KIG&+D%SxWW`(&Xq*V3G37yE$K^3Gg!SA>XdY-Ev=Ckl&WMuIPPF zIEeOGu{}e=b_%;_rFR+@b6)VJ#0p|p(uPK`W-#-@5~{#H#C)AfbC2yVJ0QTGIML*4 zb<2wXVpn5AmQZigVkorfj<7n9kG9?wj8l?Q_%9ZFBm_{{ErtX?_YoZ10o#E1p<OG> z3{A=GAT&3QSIL6*Po}PI7=`yYx|r#3i$sX4kbuud1Co|Aix*^CAK%3myK+)q2O`eE z+KtKAhl}3f^m7IKI`X5el$wb%N~bzZv<4H|?KoW$>TE(T1h?MNMGSEzJ0bw#C+)4$ z2*8ZqQeqW>$p<A}*t?EkoL_CGGCejySCE+$Lvz9<Vf10XH$fz7`khe-%J$CxnNRQy zAjO%T4(;p|=%`=5kj)x&z`$7C7;jn~ymCw<L)2gv1C-6o=N&0(`zpF5`ys)o?(yMB zwy~u6<blUIeJ2j<mY`D=ADehk|3FRD%&Z<s3nBPNs%XD>-<_EjaCqfOW>-|mT$Pu( z=}J;3^CHo<b<*xF%$Z?f`Fhz%=2G$dtDQ%3(=n*tUw`=RcPiP&Fk}ec+~JIWbYB}p z9EkS|y3?0K;^)$4#&z87Gu2h@w*W#U$|86=F?fC`3qwMqhU{cK)cM$$tf-`w9xfOK zE1TT~b%O9siB<YRK4)QXzmxpQ))n`b?~cvvbFbxVy#kS9Kov%hM<7I*Pi>S{L9ciO z#ZZE!|1Om)Tm0yY@o&1-&)`3lE<0ll!l3s6&<KNYtHcLX5=;UO(hENmT9GE;Gik%O zO6C4cPa(7c!xWvdumSInxRc6sBj%?uRpC+H*}@&p*Ss02<-uWB3G{t~uN#e;?#EqO zU<53Mm7QPb`yVCw914%&O+4Sap@D(F;8N;0@m{ppNk`#OqV{&eHFrg7U2%iT$*xFD zZ(^A6!HX3Wwg{IEy%EO5JjN<xErV*@ME5`T2wBK#Z!0#rcML@B^*?g<REO@hw#f;Q z&le{-xLB7+y#^9?X2TEPXaFzekj_z*1=Z5tJf-YIA)50A`oUU9mFINw3NoKQ3{NsS zyU37}uZHD3e(NC9C;&T11n2GC@+6}dFkW{-@^2_^a;r>Gm*o`iOw^X`<!Bf84%%1N z^SZC*>`3H&5POAYQ4JnD7B#X%9ZZBDWS&rv?*c&;i~oERXM#w%-Qx##gu%c6+IEd! zJp=qai<qlG3BD?7>J}hrQ}6toe+(XHIBIm15IkP~O;CrJPB`g+rEoy`a)nz!ID<oy z3ezU;wdNRI|1uoT{eQo_^(9WXWb_1z`Ikl&X#7I?1)v!b?Kp9-KWDu~8!P8_{U;%$ zuDe+A|K^FirRf&;_S^egu1>yOJ|Ql7@LqWG$oNM`uue9NZWPQfFnN_$-cT4eKP+U^ z^$}FeE>c&x{A+D=#X}@h?)I*K6Hh6<jnZxW>U1Ar2bvr;lF2`xgI(!3L@Bved2+D~ zICgn2Kta>V2C@S~a^ms2nXA77``rV-nTv}j_UrhkoY%trx$5;<Xu=t_b>mDtDUOCE zIlV5rKc5nhjr=xi((;q4q#FB(AMyb_Q0_mHw6B?JKthte5b6iu^E8Z3lh3_leDRXJ z{}{`c5Iw*csY<KJ9<#>hpeAx!MO@@9oJUBq4Mme~=DvLmiN~Z)y}C<L9j(h4=Tz{W zMpjlM6gNgWKV)vYwgOy9JHkwZs8un!*v9o?YS|5T$z`TxR6W~WbXo7lf#LuqOW{k8 z*f$X&hOWjy!~bLE;;79(=g2dTV!GA;&mk3hTo2QyUh{_oY4?BSt}NxYpngJ;uvHIe zC9wZl0~4*8Y6$=$uiN$JQbN$e-N}1&e=xx@Lxv$Y+qzZ~;rsRX7Roy!6O(Nj0S)Vw z@dpeymURJ<zOQU!qk@!D++0r!$xh5SL%R6j!O<08ljzS?)YJkDli}qD9znF`x|_)s zLuf@_WMY$ktv?Xm)xDLT+zmVfIx{{Dc!)6}z9cswX=zi|5PMP*JLmvixr+YM02jTh zi+vw3(gcgOkW`F+`7fkNCTnrerK_^$n$1S^=cK~`U`-Uow5?qS3M*P$IAU}-n<3e> zg&87z@YR|wqgvj7(q+GA@_a#HG2qEA_RUC1vwL(0V3X}wK|Uv*zvd*uwh~iJc?DM< z1V{584QF#Ak3}qa)z)~$RnFkzXU*y`tf_kW;@9wp0LqInij!%d<p7>0+4TerA{$EY zBT4?l`AtSHjx2M{(36J-#ntk+tDcjKhTNR0R*f|i3v8FJ_IAS&Pzt5ugVc=Q;;jIk zX)f?NjsZGna*`r)zHai{uK3ds{T_1DJ0tm|7oqkPZ)71Z0{q`8In;IQ?iU!R#8gS6 zdJJN(3QIyKUylnSQi|~(P%htn=A`fyRM_?Il~Q%@XfCjP-=*pOA^uWe;U=jMIDRhe z9q}|({_&15Q&??FIWv<_=F3w=>=Q)?BEpS}D9(3s_G^(RCRvZSnbht#+udmf*M*Fh z7|SRqhRWSVT`~1U7Svb#+{F9ZMj#owJW}Fab#>)Y9qbg>%!PBx^VOw25uXzUTDrC` z8$3Jhw@)q*XEt#ow{j%`!2r0}+1ub><rNoiuCOrQ&#SZJwB#b7NNcyB=h9p)vh%4Y z3)C-_IOsQ0G~Wq)XmQzF^jYEu^M;7qs=YQU%4s9T^RI#Pwxd2B{S!4N?jlN`KR?~q ze1vm4Diqs!;oR1>QUZ40paOQ@@nkVlnCAFrHdiHhDeHusj)G=P;w;7W(2P0OxxfEl z&BkH<11U@FK!9;IswkeWqyTMK6BP^#2S|poWedcWj&Lk)H)C?TMwx~7L(7V|UPkD- z_;>Sy4Y$J*^OGMF$2Qy%1MSog%@@M%I-SX0W|4X?La}OK(dYY+T;bV+t8uEM_i$At zNE6)M7xn-d#+9L{j>EQ1ykkm>iKPX&ZHAc*&d|Kp3@$%z!IJnz*oy}~Nn?j9M0$1) zA9K_#!I0k=&Y-J5#6*T;kcS!_lQNN*shu}(zBn@!$5^XTlj+UY=WCp~F&uo>#uJj- zRt7OqHG<+W{#V8P>2I8?Y6?o~WrZ3WCj~)Q;S|Rl*%HG<5^@5i^E4gXI^0~SX)0XV zHPe{hTziNpia?%}2f(3-=t0Qv4b{{fDc;;?9r;|_B4e_+V%E_s=A7KG=A8Nd0yV21 z4~7217_k`_o?zRUtHaC!>*~34?Nn1RFlusrP#W0l<9YI8y63F8@(fA6%fk;hnB6Yh zE|$Qnl~Qm0^CUil7JNdaiwAbsTUEZ<JMUu}<m}G&kz4h_b$BkB+?tc)6KToC3j5Y; zDt1UZ8;U1trA5%YaJ}^JMN?<2kDVFf<W_!+e;8b;q*?h?LBz>NuBxcn_Sx!I3;+Ts z&lbKJhoZKczAW%Fmyqzg9T-oHp(}w^S#UtUY|H%n5%O6Jdo~dqymQw>l}S<x^2@(3 zFFy2MYzfOJy6bhsF`9&bI$rlv(n>o}aJHUJpKT1}bXs$-vLlJKhf)^kH(C|fO5BBQ z^q)VZJgkq5H@DB!7|S22vUJP@K;cNzx#NLLvlPpWR~;%;cnwx-{xqi#8?|>F_L@3r z{!`|kPno^gq4^$Sfz=Q8qVOjP|F~(y1=CA+W^y=)F{gByvRgG#_)gwTpPU)elyT~q z6#abxXa=p9BZsC`dp=*0`YdIsp3F*KNVFl27+YEczHB5&(?!O{_b;pfQi~cy{^r@x zsY!4~bh5C`beU$7|J2BfQuQRUsgWi(DZh7_5(X`+jq5x<s%-AtviP!K{?w!=*wlY! z;!#acl#auzS+HO0T$qT593!SA&9iJYXAKpy*C3K;qm}-xqy$Y`#|nHelfwbXG6v<I z7ymB9q*Y;DpXH{>8KxBfKR$>8?Lxv4Lsf9%LMq?R$}GSc$eO4~d!4iSD296PSC}|= zX`?Jo&WPnxL^9g;KYqk+&8;$v;J;gwXJj~)E+S?_PH=?PIfO)LBTkEv11RrBd6|(n zHK|6K+-7O2FxKuQ#Jcg%Ss7uYLw1W6dI^G+<@`DAfnbSNx}~4UrVUnXn~ks+_eDYy zJa|?C46KmIUy!#FtB_Qmn%2|k9d-YI?+?;47z7ax>VR>2oj-D>1#TXHYuc{ydCI2V zvY`n|#NVpO<H>aS-*D_zvhi&AcN?%cH_`ihG+F*j-*%j$Ea)P`ywqp$VSCH8CqEAx zB@rh8IzQTzYw0tPYL>FOl{Yf}dOmiEAEv8U5M8C%%_3{<1SY&*n+Ph>_a#Qq*sNKP zMPHnKx7}=2Flh)*=5>6z6wp>#3(G*m=4Pc3b-sx&=ANyQf)^9nstz99FRoxYwa9%z zuZ<dSFf?)oH9$$p1+Ps18ZYNZ`z=*1>uR3Be^O&P)h3)3ZRagkuHiry2WPb~{{j{% zy7v{sfhJ=GbmlK^efK|U^EvWpJQPBd^m(lmm?X)D|9~rdjH_!}ec^U-F=tw|5HrgO zsD5B^m^=g4@C!y7^9&9zr$m<PFE`mboAk3<BmzgOY+^u|fG6>Zq^t2$kJ)n$BQ>3n z@-t9=4{tTV9yK2^v^qQIb135bkFdeeOFGBo#C>sZ=!%JriTVX!@ula`7nFO_m=jfT z*gWvKN4LW>BObq)Vd`lL>+OVxO3hObo+G2qb9`d41E6u((81`U!8B@iP;x-+v+x<t zO%}09`S%ZC4PqibJDBHPB9|gw$IJ!;D`DFvr>~(Ia499I4a?;CKw8tR?Y_-q;YAt? z$#fl57q+RayA%*!OuW9zTHB=aIVAb8{?2fjF?&`8kp!(to8aBsEduT#FD$J>EUn+l zl)0u8(xRC^{TDrBoOF5v6s})y0|LMN)2l~uo!JEh+<Wzr>cksCo!M;d_*jl1VTJSp z{Le#hWRa)UYj-adb_y5j*hzV0bgQLf$fDdv9W&RbD%$Y><K)a8YuIph??LJ3h*PEQ z60w@Qztt-m$UQl^i=RLDWOX@!AKMpogpIa^?5H3zE>dT}S2Iww$oN4{FVHs~&5MoM z{68_DZwbb|)9TG`N@r8L3hqC^&eS$fL+S4yNIs5oOX&K`UhDq^JztVEJ@s1BWk*~P zGCqpLA^VC$(d|vf`;?rY#%8K|4gdE$Ein*K=L}yr!L!n#$7AyQy4HK|K>`BLe0(2T zugdWv1a5XoPCPkGo%0K+Zu-_<T7^M;__pDT3w2=rkpAZGwLst^(E+=WSzsc?b%0qs z-P1M5`n9lQ-x~6k6Hm#i?re8lO3U=E%*kJ#3d-84NgWfM?tmYGI4mE2=~hSj{6<SB z<<?lAUW_FMl`vtj&_(;%QfNx=g>_|>#K?&DWM+ED3USM0X=xS7seEMTt<--nN7CW} zT&re3G58v<4lPyiN`bpea;9>7Vd9*eDt=XB)Nd@_GHudvaIt`4fQeAD>P9HPtJ2^8 zv=-=3f@Lh68dxVL#$uL=NlHQZpZQ?lRtIXM$Gb@ly4*3djouF2oEzp=%A92J2&8?v zU2u;vJ3%3yXvU2<FZIqGx|$7puy>svm>Yij^ulZNrw_=BOavOs)Fqj5A%X7;gn!8? z0Q@}Ry!{Q2Qzw~lIJW;%tJLN!OD&v}gSw|1ygCDrUk(l%A2ewlc+1O652+4z2Xo)m zac1JuxERxT$??+(VpJ>6G!=jx8p(?`&&)Imkfi5)+;=fUu7^j`S9G5&VI7CH)$+~u zT;&p@nlX~kwluO4a&)r-*j)D}f|0MWQ3cTDGXg33c`aTxiH+`_v1V95W_i=Gn>o>J zUS!Rn)%li;_Jz^>U`$iwdF*4Hj;UI8CVQxwbX{emx>-#PbH!()d=}vsOjbg~s<ZPU zf6HrgWY>$7tD>J=xF_e(_nMAHY;3G5$r^8Oau0D#*#3#r(i<vs9oU5j%Xj+-a|u<f z=^Z=SAfYNrkh2z_tM~yad>9v;2zQA~w!JQHu&qrO-uF)Xq##Yy<X*S_Do(rYs*Wce zcR!<mKhwrRCnhnzQ01kSk&xo2?H6D#H|a%dZV@e$>YoGxg%nC<rljb3UXtlbSBnJ4 zpGNWVpL&qqdke%_gU3WC$;qGk?skMb9sI~;kBdT%I}Aj4=V$WYI{JcR2$JOlU`}cN z><K)w<m4(;&jk3HPMiJ9a}-aZ<fS+xijuD?!27onL!b^<AcrV%)4rcbWFge84I?aU zA=(3Ptj7gcvy6E%kuq%EI^tDUXv&O`V38{Mn<U$klod7(>Lr4S(t%C({!}mt+S}7a zoL-P2Up(KgV?jqTR{Oi`7(Uxuts&q03ty3DKO;~f7g3^1%0G$!;F}DM>J=5(#Qlt& zLUmqzz_6vk9yKaPpWNTeavST;&SgRAX$LIdW6Uq!s}VAKMXKw&-)z4yyRBARGs^@+ z3NwDaWb_qslvpY8RF8Y;BYyDXW5X#Z`#Oz{xvj6OI1|48BoEEmJU^Nc8J$DN*WZ2B ze#B>3nHF{DIhIcaYB-Nag@&#~c(_O18*clrd;F*rxCp-_L64WSYotm6ZFHQ896#K8 z1K`}y$}9umHH19>RI030UIpmKIlZh?JS3P_W23j^+veRDep$%Nx9$0-kZB$U;8clI z11?BQI<Q!fp{u{ePJTKurgm<1M~V2#qB;4NI+^j$S~NR|$@J_ED%>jG_qk`kSF9Jy z3%w{91gl2!`@Jp@lpa5|nHc?5A*@y5C~}d^-thq_kXmP6zc@+Fn(!ZjxRqE=?q~IB z84E^K7K)mQWMeVaF!i$X!4?VE3a;{S)%k)+A8;1~+iP08(dJrZt}5J1TnXU2gu41l z`-4qM534UY8?)I%OA?&y!nNkp9>6)<Y37{N)i3Z$0G`GAYCiWXRpTH|BBjuEIq!)< zGN}3^mLN?2S0_S8cvKt1=z4hB3IC%L@=ojf(k#nT`x{!Hd7HtbRd2>yN@#$Dlt)%? z33KtP@SfFY)DxkG097+`TXwtzFdIQku@b}@nnU*`A(n&4cuH53fcK%ouPQ57iHFWL zYT#LZwSqRi20yOB$OXM(N(@a^m3Y-*I?IlrVuzYe@)9FH7Sq?IP4WL8^^f`q+pKJ= zvqz}_MoU1ihp$J0?Oa{6+CNKvrE5nE!GJ3<IP)EE=K0u6;TP6=OL+r&h|eQP#-C|6 zZ)MZVi`B$w9TV@3C1cR?C~&;Mx}VIeJg}Q(aH2BNhg2PKL^Id_&eNdaC$PbQBHQ@x zkA+w|jC5T`Wq#_wQpbP@x1U|E%{a$C)||rF@}TReyMO;VPRmS@5>|^$R5TXX>P0pF z<SUDTI;GRqVe;I8^eicRwhi0*=cst&zn(sK%xEX%9H<UA>kgP`IQnW~aj(M7dih9( zW6c>7&t=8M#cg?O%@Wq`1w6)rP!oDH85KPHX%U}+nHc|P(8313NX5c*$1Tl41dpxr z&jUjTC3(V}P@%Y_FYl=&e||HqGHyH0|6HoHMEFh<A3aTBEyYGfT}?VzGV0f^S@)RD zBpH^SKHUy;Q`z>dunK(i)#ZU%kC)Qo3pw4e=?$0NL(VD}n-6k{&Dx*EB~%r>?4z7Z z9=Qk%FVMv1YetcO3<?T5(|XFiS)J1=#_{Joxx<5!i+Q3JzL*L%97L}p>keQ#-iN&* zG=oHlnad@rwyo4PhjF$cg>nx6(o*H$BW+%QMV{=Z37=Q4JrNfdmbI9D5G`QKQ<<Ho z%@Mm<_p?7<{1;BC=ES<vpZPQz+Af7xKqTIB6*?x8|4k2kkm_!v!K{5_tMKieGwK-+ zW7{D4RQ|W8Y3%`o77m&<<wOKB<SCwke-<t|+|WOkPOK@ZqvtV7Qz*O^_j^CY(7~1m zLt>u?Qu>~snn*sQ+Tn{1q;RreqcMxS`!L|(^g&R!+)t~=xNeD1e>|f5T#PSW@TjQL zQ#Dmo-tX->kqNkv(JN$9Gc%KFPiXVT+2aut6H6(I`29$yGER1CIOKKPp(*5^a^uQZ zcP?DTB_;LW3c8o6CN1$+1ur}z{1GK(=(lfLnVFfXmLvJODp^=Re*VPnVEte#MQ#xB z*t9hfL)zSflW3pgJoBaY+mGR4=wWM<sQT8GV_p*S&yT};S(2<cb(Q@h?K^y4O9o_E zs-RI(|1@MY+0>^>AKbFLzoV$EtVA#8>wVWO0~a?*)@Fz#J6m2zMHlnF|4IPr&E*0| z=rBFi4o%ubT5Ib&J`XA?Dz@^ebzZ0CM=qNa{$P>J=&*QZyv~^v{D^W{H);z_IYfRQ z&V%0XN#GIl$H4CYW^cr4u0&a7Ir6^c&lyFcpMokuVKMHP`GK_Mcf5C>#eeCsW$S}r zKo-U6#I5n?e$8f^_1@}VG~_nrk$XS#rAs4)@D0|j(IWK8>fMv^1zk0IyID<jf;@G; z-IyS~pBVogvs5Wk2Kn87X4)GGbgtbj_C){p#0j*n^p>3QhoJ(I2$(s^@Ul6>r%&Y( zk8p9(D;pXFt*0w7QDa4IC)lK=PAd+Pk&*3ibjY~R+|vU}Ue{Tpw6wJ4(W3j4m9`<( zHdE=Zzx)k?!=oenVPv1N#Z14ULvc*0^ZMIj8VJ!k2b_ZVx%Bv1eq^W3gy}smAy|sj zTMVAMNQvtANqER<gR=;)Pu(MhY)O1b#mDPF*afvajzj1!vlx^lLj$;BtcEpR3S#05 zkJTRbTnMQmB(NFm?H^4{P>=^QY}sEL*x|WgTfRjbHs<#I6ciL}Tr*W>(xp)dttb3K z$kO`9C#D^~5FQ?mcedO2>go#u*LD%|(Epq)<emzxuQngd#FQiI?N`N*IZWD@M1Mxt zU6K++XyIn=Kt=iap--30OWdzX_i>5l2i>YFzP#h4!@v6{Sev4ON?AjI6&dmAUBX{i zLzHQdnWSjLK1rmmt-r&3kEmXvX8BjUAUT;Za=#$7C%{(6u51-fhIzgib8Rk|t9f3f zf)dK9dV`R+`y_pEG5iOSju%}M&B<94X}{WD$^R+000z4ORBF7^;_=0?*{y7a1bAho z(?r;V3=}`%bFB~P_X%%7EHgFQLU?9<yI4`5Onc(L8?%2mt`@C0J}T7mzlT1q#YNJV z@oHdE>0qKY>!AwVOjKMFO@TGfL+6y5uRZAA%a=h`OSMeJ<8XZsMXF)_&hp8Xl}DQm z=-UH#m5Q4%I@e*h_E$YPA0A`8{!zXnjxPv~2az-D#j{804LR710cs^xJgyaUAe8_7 zBQ`$O4o^G=7afizo*CpZF0T40P>~moqtE4%_*qipn-=*z7Z~Ue=d4#>SGWE(!B%{~ z-Q0YF-b8XYe=qk@w{7ePg}`!Up_)Y6#*be-Fi53`$mHkL#!S_8IQ@D9%eNI9#qT|w ziHy@S|7min@FQLQzmU4jCvR63AF2AhA8fq)?leiM&IQ)ZPftbVfD43wnVz1i5DPhn z3mDTsqY9UK;c)<8<ZumS3M)HugZs%C=;)5G!534+#IiD}!ru&K_qbaAl3JUrn(D8E z&A17)!o9xt$1j|^3Za+$`0?tw-nV;5uS20|7K3L3aJ9ftvKC#tMt=bk`c!4T*fm~# z&9^FL-xSbDOz~6q%LH??So~Ss;>>9Uh=RWO1v%MBFD;-k$0xS8jWQ_*n8|e1q_<tj z#X607^S<qPYuNENXf;o1qwa3!9I0>rT>VB+Q0~q+B-=OjVCD9UcTazH$CYP1!j-1p z*=giZP!7{<eTJo_w=+?{c5TQY^u7FHTQfgphxmDf8DT7$25Ckyx{?dI;}2!aw-Fh5 zeq2i=o3Qun3<yq7wT7frb1>qqC_h_vc}hA!d$5}_Ow$Vye$5w+ql^IbBc{5Ui@#l+ z7}$TZ1ei#JH_O%Bp2*_qN^;)2_e=J%?~=sJ0rgaSqf|#T!)8dE53s?`W{m&PF<$%e zyK`37I^L>p{4@V42rX;`D=Z0{mbEwIXOLK+piT<IR@o^^y$*wxpG3wwc#TG!0tVLl z1bP0tU76{GG6Q7G9ZSLEVD0;ufscO);#k22Kc$K>;~vjwXduZiww3aq&tn~>@g^yH zUN?6C01&bs+DRoIb7b)IpoKdz3aWRm{N!J~@H_Rle7*tO?LSuH#=mX)nwif{37&cD z73A(iG{+^h$8@~$(=T3#u1|^<Xf&I|-15h`rJnyygaH@#Scuz~(U4&uB}UGNchbey z1%D+@6VhZyDQ7e3TG+(E^nSdt&1nBqP%s@Qwx!$yxlhGj_oNo=E{>NdgP$BfC@(KJ zxe@;n8SlGCDe`ge!AhS#cn*39S!YeUi&M}VgUW<DdV%GyKdx%`_{lo#*X*pujN8y4 z4D{^J-e&kd8oLNimt8Y=<RmJv`c=o}?H}>c+~-$p+-_%wHA9<X<VEHqQ3ae*`;2*1 zf*o0??sGWZyPpA~ZE#V9w`eGZZ-?xZ1TJov;vAhfzS400CdTS;7`cCt6p2j_N$BVp zkBv)12MvhcCf&oO6KQnxFXf9iW_ZQ*Rg{!`fv#X4PM<;&oENzD6~EI{Q{T30*rsDe zjU@CK5Owo^Wfpkf$NPi`&KE;7Z~OuMb10|pvpbO)D^dJa-loq~9KSFNIYsPw&c`Dx zh)sBWx{NArNx~ub2_Yp-SbE;I8H{A)*ql}v)1Dk#zXKtfhg4Kp=GG8Z!%v^z^S^n& zhA%EYXztVdf#G@KQL{{WU-Ej{q_{Xmnw6*;%_9;f0nD)9)pkhuGoG2?zHHBD0$At} zaGNcbRew%5eMC#TN}4adw!+qUy_b}l2<Sh5L!YoXenxi&6~WX+<%k}&4~_%x9=X=Z zwJJc-`|?}Q{$imnd7oIpyjv8>?yJr)P6lG_fMK+`Z(#x=l;d>-M=SJmzXSbrs>niq z=d1h4vY{t?;>B{^FVzVljR^|Md~-V%4L+IkFw*a~N!wGZaB3c+1B9u2W@VEV(O%1? zdnPw-nB+aspd5BRjNYc+;i@a1uir$pscRYpf;H<dxR^J5Om$1U-i5rl-uu5~(p|Kj z-CdKmZC#PgUbHa@ep!a*fWK9xbLE5#Scf5tWl{6QzJE^&7nJJZ@W2Wvf6jRr8K*SQ z+$B9!l+U$tu*WK9VqH{+q|_L5>tL$6*$++%4$;qLos1*MtoIHM<$(eP6&3q~Lr8XW z#&y6Ih854het@g|wakYbJ-at4b+phzPq~0#^l+A^m;yJ9XMA1h?b|du+75+R#<6>Q zkDu_^l9~1-GyfAlEj|6+&8AZd;mbeF6Ut~m2GB^kQ=Y&2^6TA%vS;UZ{&p;1DtR3% z($BJueKBBwlc9~{sfwzeaFvceCUBRAW-7+DZH#Eko(!bGWSJ6np34WiZ!svDi?YB7 z2+>fZd`$|na(DQh-gOghASum<FqAxvJ9%(%p&vMW8J{xluf8OI@yg`^6%}8hh8Dft zhjtFr6-K~WeN6Ti#r<;?7nfL~x$NAIF+~Vd-k*fB4fv{HTG{A7`31#qD&P;kqZq#x zYL($>LcLfL5E!QxnuJ(PWoqwInK7#jznk=w70U}P=TBp#g(uz5N_D^<8ExBnq^ozZ zfTw=XN#v`E-0qlZVBO|dJ5HZ2haH;#Jh-=}9pMw-_gDG68+{OK#^T~?SXW*pZlj4b z7pi-8r;NWggi3`)M!(XPt|!=~$zQhks)>v1n~tUaY7qrGb*87R{6gR79DCZk4JsvK z|H_4I$FU*#y{x_ci&@us`Dq7~4X;y>>^Bm5$dTbLruq9XFJnwS=1F3wYOr_G7kk4s z;8_CI81`XIcdqIRoz7Z1XzEgvT;^ZGddkvYtL7KcM-#L4r-!%M8W+s(82AX4dN;0t z<iiOE-0Hj6ufKEtv&QAi^T6=miZ4Z6OC8WZe|ZCf;5g!Ba@<f{d^R1WL`9X>Dgg=& zHH&)KW^0jH;2-~oBGKd@(I6!`a}IzbeA;D-{0Q+-IGmg|)g;C|wtSz)>A+VuikR}F z_W9IX1M;z$H{5cc2xKHQvJ^s?tJ6lxcI^tQ&Cy~ug+4`k-X^Jj-J*0ziDB*C5R&w$ zxdee`GleD==zuV!qN4l`&XN<Py9~GQcEVo*Pd#2iM0+R%nR+Pl3Ll@>E!?--9s4t- zH~u6ghal<KpmzTcJs4bkxc4x_$iaII>WYmf_g22`bQYAo`6)4B-`=<FjwO7bh~>w~ zm|kENikG^N6lX#Eg^4bP8CuMDTkbb*F%nv%Sud;!BO)Jkev)g}sSU8n2u90Xh=D*} zt@FEYc8I=B>p7P@{s{kD0(Gp9?mN2hNVQO%8&YKELdAo06=dk>+^_vC_RO2Dqmw=a zNl_$VA1I25ZGTO8bB=hJTBL&>mW*R=hBW@%Ah;~x(#(BMgpa&@TG$7FpS#xmhKkCL z$x4?`K9B?#hnB9jz&<GWYh2u?-#=4+w1@Tmuynk<ZHi?JbmdDi>S!TC@rCtxV|$OY zkH8a$*$X{pIy))Jv?LF-7!#i)rq~e#3;W~r29a-%l;GK#Cwskt4v#dge-hLyQWYn9 z`6Xp7EWG4%#lOYpEXelo+og9~dB1j4f}1=@QjIi&(UMh4D28#VQxQ9#*BHdb9S8_s zCR}tKpC0EkZFbV8`_edJ%ZSrNK4HC-yD(YojCyi0EJY^dF6V-e1-a5@Wo2AC1$SJL zv#p3VhL_9*;y=5rLXFIS-r<Blj395LUzGf4v_W9gzl!iOFQ2KGMQ28TE$YH5o`~YP z7w@n;;Oxf#BO~3nU+K^xu{*#)@ZN#p<vNey5M7&30#8g*KoG<7J0NcKp&8iiDyuG_ zAqyVkXSC^}CKY1xG9U8XxhAB85>-Hb3btG*d5{jI|BHLTr-cfhJV`(ZixM^S2(WLj z!{xNNnvhH(#Y|erYzjiXQM8sfgeCAIvOZoru0kwOEaQ;99-sXgB#?~Rwc!ts`{ll9 z>dtII{C(g|$fl3tDqWi71fLi59*49UpDaDyF#f-nE?A(3q}m~b2I7IqH%#-L+jnuu zn#p0aA8Y6k)c-u}(yvdCzbz%7mKuJinowRQn=1djy;{d<-NzJ7-eN{xKo}Z#d-AvI zi0dYHz6G4F^l@ajb#DDb(GE7=%k4t4ws|*nlSFNaMrsQs_V@3k7v7`IwUYV`WH8V0 zf^>Pz9@89)#4<&=|1QplSUy!3d{DGEXEK;w7DSf6K-Kmc9F3#5CAl3<O9NCTcWLuD zUvKNneN@t}M;Ze>LxxmUsAT+OOCMiOWkc4;^F=*$_-322gJ)8*pB=l{ryvJGH|1k? z?`Wb$CV!pL-5j4*6G4O3zWHgnMWN7L#1ea7$=vk)KF0O2R}fQ<4-<D@!_Lm|zYtsM zJ^x_&UMCAHQj6QS1BUtRKcm(Mf&!KgK7amf-1bbQ4aLZtm6J0MUM|sEy)FQ<UKM;R z{-%krPY3E$|K%z?e{RymeP6%j&9kE%&HJ1)F85e?HUd{a3fV`k={;q|pki;>yDd|w z6q<ee<Kh|AvO?fsD<mW!H+s$0%YYC>Q_t?j0Q+XQV-v%9iMc5|zi+$~7C}L16yWp( z@zJvfGTx*Jj8$dn16Ze>D~rolQN-o9V-{IX;<4dcqUmPbWj;}&&v!P~La*LU0(GI1 z6whi?iyou>_u)i$_+Zmtgxi_tJ=EA-*W_-G-=XC%4{qJ7y?>y0<P|ewE@Jk;jC8wL zu!O%XNXe}&GUoUXQtzDtAGT}S?N_&6y-KB_0m2%N=StOTs4sjPR#9G2vAxq(GPjgB z^e+MBEjvbujAj!35ltrGF~AGW$Mv*Pi7%43q$-jjt7Dmh=X&-bf2EVj2Id-|&c?D| ziFUNVcc2<tSr3m)6l6I5_((nC*`IVaVbP&93PBxj4!+p4eIoF3P$Pr6Y<ZKMXCQOa zLyLd^`NjztgY<_AOV5OhJV_W4Y!GvLhTgMSPSR8Cna4`8Y1vrrZOdNXago1#syy=9 zDw0m{fs9(FYz$>sO`!pTVhqX?+r!U(2Lz4CxVVnLB`JK$#%+NK9HoC;zxJWAv~~P4 z?_Na`-nG=+J~N~p-HkC~W%8>#d=$ACp}^zQ*U!ly2^ZsghhI9;Cv00GHUkUlLEc}V zM0Z-fbG97_Y7OyQAs}5?js-#ZBvb_LE>1ffPmqc#)oBwW%R-gG8TCq9{v#gI-Cr#) zG4J1g^{Q8->D!a^(nsw*AKN?pc-`@NJ)fMw$sfta+|qve%>WD6O~IH(Zhi8VjVoqk zJl9no{V6mM5BFB0fMdVq$9~SBGtZz1`e*D4uSCFKR@?OR*kY_5l((f0MolrW7M$vi z&PS2AX`77vmtGzCWXCH;MfG0aFn4&d80LN0nUCCpm^C+Pw&w+(zSlnXzv4*$`1siM zC`@wVY+uX;YS?-~w${t|eeT5m9*?7K??-FG$I<_fsJD))!h60zFAdV&4T5xcgCY$| zcL>r*UAm+}KqRHRyBm}i5R~o?>F#)k&-eG<bGg=K>HULq&YYP&d-lwM+I=z8SReB} zph!N*(CbwZj77mF|CikB#WjD?cNBbaikh`A28sQKj7<!4(G`0}`qM?zSM1XWZ`Vw9 zG`o?XA8?YPAopCs#YY&wJ{db~QGkB)FQ{|Cy!aKMI^P)juJiFmDLx`7SdgR}1tmIW zQm-Bsk_?eR4x^RLa#%pF{(y4ceC7|kB&r}&p;l7R<?@;`d9E?E*l_Xm%0`HluIG<0 z8Ya@WxKY2~_Mr`4m~{!IStFU4u?Yv^GaV{nwMLum0qhP_1vwJ>0?v(fXG5N4pB)tp zU|Y%_0!O`cSvNTuev7h`l8KYX%{n@(hxMMMflSj#^>TFN`&_<7t8wQBYM9erhE~z} z_OFBGq(=C2gnIUp-1xJ3)QoWi<7$bh7z8P4m?Es#!DBJxp|9$N;%D9^uF`(nI9}~0 z;@uTw(P{aAV^q?lb?>-}cwhpv7RUwdXA(8OT=8XeMWL^$@xRPl!~HzA<f-9EBS^5A zWH0Tl+3^t(8+Lao&_8w_V^1jFjDd`OT(mR2`iWGWLc8&IHTx&UFZ(>e7=zJ`U&#OG zbkY2ic@?1XUGHe|3+9jfJ$vz0t*4HMi6UV0-=HU3Pe2ec;4}OvZX@u=EQY~%=ef-i zX+A9JGftKe8&30Wd4MJlBEv?JEfiei7N;ze3mFq?`HCIX8QYLamp41Z;^bapByTsi zb2omK-aA<odg`bI0dk|t^OBg`*lSy~d-wZM2Wn!f16Q8rAJ#@mfo3lMxq4I<EhB{Y zXBNK?%ywC7i3|FojI9@tn+`N*v?@b<=Ge#F_Id2l{MLrk&o;@|t-Hs&w}rlu@Kgv) zR-s`E-!+X<%SXT{@fX1CZ=7xN`HKov=xrNLK&Hs~qk3gBMMo<nH@0AT-(}0ZNf0N9 zB}As?_;{%Qh3tmq^i1>|h7SQ9q;*Qj0sPCJsI?ZOfILV0YBqU%1H?9E6j4jOxjr5S z#8#&{-JFFEq;)!-gi%n6lVPe1>%TQOdu_zrWC~JGkHTYB+5c^J;NF+7Dz#U8NDq6J zQS4=m98nbL$sU+N*zp9c#*aJFLBr{&<BQ!Q)Ay`O?gA5r?ZzH^tlAc%pFNk`3E5vA zz})^ypeQbd9&W_8Y(~#^q-S5mhanfWdlKu`{^U&M<7~S@h1`aq`_A6yM;03h)9ybl zNzWwz;i$JYu|2zzdWk!n4*u~%3tQ+AfwA7&)1HNfDZN1WQ8Z!|&G;KLJ3HoRCkFwh z=sDy600@ukE|2%=Al@wJfJ6&~fNZe4P><`Y*~P*;KpSb{m)U7iqI&Vk$`zrO4#oP- zc98GPU|*l9JfjO(M8JNH$M?wW;J%a~6SnX^@Vv;1CNgnfG|ri*L^_kD{J~|%G_llf zptm)P>tQ_|;&J^+mezfzoPu28?#>}*LPM|a`0Zj1W4WHBoE&FcMR9+A$TUmLTzjkR zuJse!$y<X{ihOzeAVsp6s_lM>a;@p1KxU45o5<rqho9bOSVz%Hc>DW&jB??I&9A-` zv83|Z{ahgpS!q4;{rX>Gz%W;30+-<d1yzg<YNXRLcZYQp+d-E9z)X3DKL9h-tn`5U zIgL*vTiGoQ2*+JqiuoQE23SZVLPDgCZE3$VrI>hrbW+5Lii6lWm=V(et6?H--zReG zqajh@xC)&35)BjIL&4-irQo&fkP_|t%5jC?EmFlAL$nGCNw3@2UW`uIecUfwd(m&R z`0F}{o_=im$;{i}lw{mo6#Mc~n1fVgXwjUS8oBv`AV`@ANk(R1L`qCvGFU+|?kos0 zY{9r{QWK~86>zoJAnty;;GH&`u2`&D|C+geAp`ju8yg@?;iC^lJFTK=jXrX-SiABO ztlG2nO(<X#fqy!;4u8^}Ds~sfRpI>ZZ*LF~N(ujXMfB-{ii+!<a-sws{P9oJt|)$3 z{e#b81FRjB_0%n@if9lC?>p8YhQx)ah|gB{?(2Jq9Qk_u+K;!m1+9nhKfUh)HR`S2 zYj->#7OZwhIlS8wI-j)pQjQ{UDbR86w7!=pd9d@HzA&LjhLL>EEAR5P;>)5aQc^?B z`6d)bCayL%kI<Xn^VqlN$c%qFYVS*nU73U0FS&p<&8mgLrdou8067V#2ZyDx0R~|- zJp~|f`u?Q*UvQ#<jJcAp_eJ&p$?dEB@}|Q|Ll;JD#vAtE>xJkd9x0dxp3-0sAKh%K zzeAY{uVo-+nMf2~@H>vL#`3v8?Xh-k@IxFb1@LzYRFH(+5TR#V3^X~v))0#}=9PK< zVI;g(5t2U+b9lcJ2l?I(9HPW<in-;YM4s3U{4l1-ijfzC9t+2!7iN5eoiQaRtU!i^ zww2E+Z1OFMc%bIN7{#sIGO^*6lzh1^g#pg=L@D8ZhUGUSiGvC32qX)Q-Jv8>!??EY z)9c(Sv>kTgH^mdW^;oxm>EcBmSY(u=_XT7E1}h|^B7=45<)An(xX!jm`v(d$Uu$YM z>@(tlwwFIv;t!xdB}EV<_%ZT|ZzblTc4Jw-J`+W1a2h4*lHT4TYip(^)!JAT6d02q zq^<?|v-Qd~XAYov`1n8U8)^CZ2^mx@)&SNQ@ZLbaJem*HD4n8u=s^iz*4fO*pF8<c zfJ>w;j7a`optX*NSdJ6$Dy%}~bHTbu?dRLxR|XQ@3T(b2FA<42$=ugoby;61CmL6o zqmE_69k0g#Zm?z?3;Tv#e0NQi<DIGLCyPI+Pmh6*>oKZFP2DS!c*$>KLVT7)x_-AZ zE8vr(pLrcg9xN$AzsbL!ZwTJJJ2LUR_rucTBYpQiQxu7ayYHCZpuHZmYOYg!<p+J- z1O~Z?=3SekkQ-k|QGsMC_w;qkhGXL0(Z%f6k(G6Q2{N%TBE3q?TBooK1yztg3C@e4 z+e>+RJb@Q4UI3=*Xr=a*(Ll5mjQ=!ly3KOO17Mjx?-PZ*)4)$Mn1VBCg-VXUR8sBq zg`;C&kaRq0w+f0o>Q>1R314h=Gn;QX&~C9MCScP?Yt3v!Z2Sk?c{KFnFbzlFh#kYk zf^EZ{I<@x;{bEX%<fK5IK`WAl($#`7Cueki=FqpVkUASw7NgZ>v>%MZq(lN(?f~*{ zyp8dVel3G%37pO{0lw>!!vzX%*7*TyzO{yQsM_vippYs2xt1YkoxMbn0cv85*k>oX zS8f8g#NZ3s1>T7BaVk<ooUP;5!43B0ii@qSMtfxP?{MM^l&Bl*dFu{?C)g+~(=zlr zp?1&UbANt&)={^Cr>&sFE_GcA@dkgq>#<7TFMXd#nUmKNG9-=Jb-DC37%lY<MM4dR z5z^?v9X*1W|Hd`Bg!s-gwuooG(V_o%mA1<64pGRJxL0NQr^Q(N1PZ&qy~@!LCu zX#+2Gw)XRPb=H$Ov4#umyquia;o;#s6UDgCGZyji@QlF?)^58tx<4Iq@a2?tSFqrW z#!Kt^ig;2)Znt0J9$@PBVEtAl`t?=*JXVsy%6G{U&GM!j?e><BeHhRd43RUmDk$sm z&2~Wbw$q#ol?{q1Dn_nBs3`LLvM{v><4~0Ep6bDc{fxoL?`;|Js0RpF@hLKkwtm2q z3(~;S|9p2?ZDILVmHdu9bIgotrRi`zrvPsL60${<)yF}VHk5&TBLvdHMuTfiPhYX~ z!8jAo3ytnjE)WZzE7O5U=#>YR@h_E(AH841GiiK~<y3azVR7h0pT|`p`U^ir$j;XW zG>X<S6k{T@km&G$xw_)*-OQZJJ=BBT7*T!+b-W403v~8U$D5Cxxf2z^U+<3M$h+wi znQtYQYw+j9Q9sC1zhIG)KtV_NDF~M=B0KGRf832p#P9oUd6<rNxpyyI{%o(Z(`4|k zd5xKRN=Zr6#Z;=}W><jabOkF*;wdS{5~zHKvl+BxDI~EGiQUVU>C_^2K5@dmFH{b# z@cMLFlv<;}<K4gumoy#LXI}hgg=`>lvront+R10xYR^t`C}e#Px$(fKe7};t#VvS$ z&t2sse0+B#kuFp-uD*1L(sfu3@wbFTr9cJ{z9LfLy{*{nfvQ<WJFl%n=!7}9#2`?r z4qY)-HNR%~u3|8BoP7}KH;dROc!8>clcB&PID=`p)%tXzw6G7WbJQF2Ic$%Fa^4sC zJ-d?>#6vv3Z6~e|>Jof@Dv=SNHxC-K>+BDpuO3FlVK5hB%NuNL+(*uKua1!1SJ9h_ z&17Syv|8P`eO0Wfvqm50XHquQwy623&Swj=gKms!88#|}Vb>4MX^e8LR87I_%UO`b z3}4t7v0I`(5%K5|At%yG1|}t4U6PlI-fGY<@^W&;pB>jT`b!dqI2?bvyBsbIeoW~k ztkGuK`J0bw=y5~OVsy#gCvwGtgNyT_pDB*bzY}xQ<kuA1hAuBCf_<wf(H`%BAuyUl zo5BhdXBO~86VO#Q)0qx%-HRfRV{34v9jhSc@ax#8OK@8upG8^tI0PH*ODl|kt>KSu zd}<|6Oc`Ng)(@*$y1HKMb1U)hXx>ZK^L2R&hu@`@@&9(k<Maa+?_|4Bvj<4~cwUYR zf_o1WH+bAqSWJ;zufHpxlma<9$tYd^bL|syvFJth%j><YSijR^z3SfW_FrjveKM9S zv^es>JT+yXSQBMlzl1!xSvf`tR-GC=EsT~I{{zK<Wo2L*dU{w69T*)=0%kf{qS>43 z&=%siHQJr-wh+(*B6qC*I{?=foJU2qn?8vdrt$nJB>i#cRQ@0A8u}lHR1q8Y9d4ew zUB0Y3SUepz-nI7kxlzEmi&=l}UvmpspF3EGj#t8Rn=@SI3>+c6(ok5M5(ogA^S@H? z>+Q+Ui{D34s;C*0h|XOT2S3vB5hSXJ^Ll5R8|A4N!=9x&z?OLV;qNLW62<SZ&@;V| z|A=|;$A(YZZoH4Xo*k60Cn_uZf0d5t5gESMYyNqhBC}b2-h%exDuRY91WV#Aa(tC4 zSbY}=mFxA>hW!U_3&CH$#Qh)I+MI22r0ux56rSZwBcPy&Cd}}|@Ou(P0#!tEz^;9e zby84Q#{(lZ35GMp329}~LU*^e5i;IcPM<7BD-O>j!L_n|=s%GQUd>MS^I*2MRU^&G zY4=L6w-e@oid4C#uDgQjoiL*JH8#fsp;;f*_KpyTDg38-I|;Se=LAD+kl&~mD_!$9 zDU#1m_^>*j?of3QA#Nw$hfH4(ZZ$GUTa8IT(JIyS>iqxBeq1cce!56n4=(&MVQ+w5 zi2~W(Z2y&Ja1?ve;<<IFT2dfUuG4+oa=YLWGEK*nGzdSW#Q#fKvgQ+PRkbZ&Q8<cf zDZ*ov?S^P8^x!|ry*ow>@Y(+vLkt$IgOV@6AcY2gi@eECS7d0U(4=L4Uv@lF(n#<q z0`l2YMxdAvTM~JpI&4=&9jteqARMTa1$kQq!P?pzlKNfQhyO$lw8vVgB~0c(X?kE= z`EAk_N9+IkiR68%{?($J#MNO}0Nk^9<c93o7bi^T{Tc}t^Qe&x;eE#B7#&LclZ7GD z2Y;l&qPZ7caN{u&jO4Y+L=k=NFyL?nixBtK^sN^&Ktn;}@QH2%yi`<Xc>d)M43R70 z(W~2RX)Lcx65Y4~;;jmUEcZ{%E~l<(^(J_r&^V^bxVl=CtNM&J#|u>Yvm~|5x)IkK z@3U5Z?uDmSe;9nnavJ#Nov9S8*xfm8+ezPEk!E?yz5s<rp)$Gm{hv_xv#4n-;(w`1 zhi1Wi-c|qL0YwJHd9})P{ia*~PyzMvE<34xXjael!M`G$sdBivMkE5Zc)-*T6aocJ zNBL*WqaH0I$udK``zAFtjwsTP-UgHffM+^;xbpI)N=3i*dy>3cMVjf44m_x6H9lBG zn#xG}F?Yr_gSZTtf57Z|yd@p;eZV*EkFFisb&r@uJ4@!YXGJJy*RwXJLaI0EcKY~3 ztHu8A@;U7SjM7ET5L#tvgUv^GC7%SOM=@%rH*b*@eJa1Ee;()r*d7uc8L-=ZcNyz9 zFg)B7r-IS{UnQV+@W1LJuAua^YunlHRuGMf+>Q*d_bSE5THPEN5tqO2m8xs>UQ8Q> zihsP1zC4)w75$#6l<jzL$@ad988yZ98zA9zq=&B?z22AEFGEtoDZ`P{zM!o{F#BIE z#XaxI$73VmQ>zHv5q7%;fiCNNayLL~sNP=jw^gXrXd7n;{K@sAjBNKZ$rK@;vR^dm zbVRPJUI!!nXnRiayH>lqPS(L+ETE2J(S`T<g=d-jrW-m^Uj>8@ccGM0Wa5X_-tvKn zsz)uQf4BGi9?bQV$5{xvNeks$8&to=p_l(ddmp2KURlg%W9_bVaC8H%j8kH>9^ou@ z*nK9Je=ls1Hc)_wH<<Ry>$_gmUz>#>87`}htzO9d)~)$~GF71m(0+4<_nM>k`6|*| zIk{N!*AZYU(F%y+Kgk<06Ug%wQ<Vu!PFr%r6w4WeBSz<3<y?pVO(P0cBQAc*OhZ#I z-I~gS<qBKG5P1~%G;JW^SpDo2{(4l*OMig>n0Tbuh;chntQtyk53B#|BS|hhpP+62 z$i@ZODw4%V-}#YfM9Jr#9w>plrpy}*4$JO5V>`ck!rUcq>~?v2pwMBObeT37^SjP| z$BqLYt;4#zlq}Yp9#gd5Rv!EKo2SAsQ!HfC$x1));~rBKiIg1Ir++U6Dl|@({X*E8 zl{(}$wxs53@NcK=#xVCo-zp%TqLSTJhXhL&8<Jb6b~elC9P%*e?}F`743fu66a z6c!jNB1WLr_1C5H&{-uQKQ9kH)BE(*Qp$bw|I(dU<{&IkUK;(-&lopr+vjzp{N~BH zS+0X@b=3qwcNP*p>o88UK44HKWjN?VlT1yUDHSuP{cagX8Y7tI{clX6oeh?a_LwC5 zVw%k~<a2P1m<T26j`w2hl-CDt##=0p!{&Fp%*I0mD~-$k6Y9_0d){if+{V26q$7g? z!Z`{q)!)Bpl!nDxn7i*)02Nj^QHm7zXXNaC-E6JN-tuz$){zGS?+#Ej%xh>#XY!9G zr);a@;ASs5tK^SPYnE|vL<P>3BvfArL3!#jYU6|88OfPDM^A$%4j0i&T~it?qE>ka zuXb9mvNp;a)m-)ts+7I4FaLE)7}a8|jhTd%v4oY`hMDzeR~jJQog10>{KLmXZ-=8l zYR7yy#*W$Mc0E4CIiQPk+Koh`b)n+vDaQX0#^&-|6!pDJx1EZmb{CB;<+EQ1%O6S{ zidHLWn$h-tTI9EV%#c>YLu<d#^u8UG<?#AM&+B&2b3sVwauBnWyDa6dpR+F@CdXZ@ zJ-Ld*@^1-m3XAZGtQ88A;dyF%MhMBtB|~4;v*+St)cBpkE71z=`bPikt>vE8fgR39 ziV5`mgtr@m6vRtBwnRX}ENguSJ6<~~z&}2RpMrR|S1Ijv?-xz%`etar|Ka56hnNSK z@iB#N!CobjV!}MTY^G@c7z-q8q5@r=*TRD}Uzxnfb(iQ}DVJh98-H2iTtU4_z4ACA z8&})Q8;sbb&~I)_uTR!h1QKtjT(?!GTrF$2bFNoqP11$P$9Q5kd3YVRs=?48Wff%O zr)ljL40@3-=*CXrSg@T>k4T7UZ7)iv%M!>#@5w3|O3Em|v{=m<J62a;gAuEL0{CAg zmZ)SdU7tpddN-il53zUB<m>36d2c$aJ1puz$ueE5EO0E)Ekkh!l`C#PaKX4O8D5?R zR=|ID`R<Y#mx!qED|q|^>A(E}<>VU?dg>p=>;LEBz5R<All!8$J1Q_$Q}{#YN|UNz z+wslFMuj{M7WPfC27`|(@u#+IC1ZMegx!@N2|`+B1~&I%y%DA}nXz-7nG>5)8o6RT z9N)9}tV|Wl-^)Px&hv-R%H=wwmur!FV;(T)_M7bq{+c}P+Qhe=B(CyjrWNp6uEe&; zNJ@?adQ>tzDj_}SUIq%~%kY8XWw@Wd0x0PJT)T$mn>UCB%6G4!Um}A-L)TLsI%I(4 z%Ut%vYO%$&d;7h}(~YdT_r(Q2BNNjbOGPp^(wi4^OOK4|wXdNpnd(^B5uIL*Kex8( zshDmT^6bg8+NM)WUesCITZ%aajv$JhB7b^%@SkK7M#qlTss`b2G`QWc-f>;zG^Y7k z_5#sAeCu->E<XxoO~9&BNr8WuHi|0MfqA$RH>TuY8hg-~kPKwX{5Z+f?UYu~z;E&I zL%jl_^sc(+y>5NhgtK3zRlSdJ_m$hkbj3P_D2)7k8*wjfhU5N;jrxdRQr1TLm59>_ z@Jy;W%`$o`>v+baSgKMis#4M)kf_D0d>=gZoewUqJ$7CGkA!l&f4K7AsVGxkr_c1c z<xJuKh&x1_WH?8D)Up0u<KIGTLPFH$kjmmt8Kb4h%A51lW9ppJsjsBNvM8^A^bxoo zk8ZN65>e=024tJy6LNdzi#jbAX2Obk!S*vXZ*ybEQkudgduKA&3QUy;in*4Y5dT*S zgwaa6I9cHWPlf_-l%GVR`|fT_Z)f?**iz}^PUk)Bf$VzX@H@RmC`-FO%G~l9`jBJF zTut!Z>$P>XOkO==YtZI6y<_W5t9N&0)NS+4`*x|Fk@yT&Ro~X#&Tf@v<}t;}-2ehS z_4!+a90>*<a`_MN@yV96Y6GFOwtU{_fBKtzkFm%^+~59BDl%Xoh3tK|cvWMjzmbq+ zBr{#%<Un=FuVuiC+?{!!xlcs+UC4FLqcf(`83nQJoOt&FxlIn^ja(^Cs1DrR+9zvb z{w)e2^^=jVJ4_<VFAI&P2xASbRSW!A`V2H&Bmnx~=`ZvvWpcpKu#OxP$+vr|W_tdr zkMnl_$9}QorSD*wB)!~(Jr~JNqB*KDmq$o_xzAaUTq0Gx!D3u(i7f+d;1pC=D^U+v zvygs!Fg-dZe)NmW^>71<Uhm2b2cCU?ftt;(ZE30WO=V*vYa{qXB78g1y+-K<c5Oqh zdr$Kc5ici;0p6HX8U=9ZOpDplp`Wf6uhu4~m;R4s=K5Knlv)L(!Lyvdo#*WuO$WY` zn)e@rp&#c|w^yxF&@X4h8Qhq%(PV;0oX*+;LgE513@AM)5;>;DoKXqrvk6!Z|Df5- z@%mR79-nyFvsE>vr4C$CLiijmZ6!+D*82m7*x(8jW1n%*Iw+ZS#igS9)O<`_;(SKI zC7b6bIaOn{f(sUWq+GaXXr=gbsO%7~r1HP6Ge&;hRrETOhl|YV(pO!E6V{^{hw01Z zsgiOFxqQ~}0?n0f#Wb{N%d{HHRX@z`n!nLWWo@)SoxOFw6yYPa<$mO8EBm(7_e3l6 zLvfl+5B|CfU1dWr2rF6iBL<?O2X7*a!AoI`8$m;r4|$#2q@ADRg-Q6@;73J7apYfn zWxXpNw&3oIp^V9+Tb}!CzMAtoU(B#jj}pz@;|0zx@2L~bQ+2J$e<-J!laS|^_!G|c zQD>wIsDZjWb2TQPx@t0iI%@Cg#)Rp(on^(2g?U!1(sew}(JBeZ0P&E0+FAeIP9(DV zSc2+;)lUP7R59|ONQb&WqAj`H^yjOt^?IL#x_bWaiyqr|^>*{WGHv;~CtB)FbQVmx zer)uOAXzsa`uCa|Q%UI6^o)7ZW%~5W?-<@nOg&C3A_r=DsjjV|mCNGs1aaIiBcJ+t zczC!!23Nc9WXr~8X0rd^(&-GQPv#x`2BIA^w2VAZ)DpZY6)`kQ=+-xrHp-(lQ)X+o z;&1fT<z3IopI}nZT6!bH?-exl=`5}sB1JDsGkmJ@;N5R{SMs&|m!BYy_o(hyJ}a}^ z{<sVq!SqRCMg@{bb1*X<O3#vs7-Jv>Ocb+ETaRW7{2wi_Vfad{1-?$`Q<h`z=~;IB zS%u@pLf+GTEoU%GqWoyf<n{=6+f5~qL+Ur}e~p_EYY!NBD}B}^eK1vjx(&5-Fvfvs zGP_{z&nx2Slvnwj7GL!-Glf_jpBe)FZ1%-KKQats#5w>M$|H{&X4g-c>Gf9QFVQ+o zkUQ=Uk!ID<O!!j&Wcz@;_%lHz1J@iFS?RblW&-Ym`^ux&pE)givP<W7FQe$v%9eM~ zFWkUtLU1>E=r!Vq?d*N9+B1CMOsY=|6}QCqU*a<h^Y#3-S2C_mtDPI}Q|iJLhgtT; zWYNQzIXIR2rXZt;C-Y9kxKWbQoA>xkrG^&h?xI1FQ`_{x)AD^GiIFydzP!JRHxYbX zQ7rS*9Uac=XPqG`;DsSrpT5ixUND2nnTai=!MB~7`1gnK=#anF()qt#-EJ&%zdxsl z(#)<Eb2a(dI&~v@{`aubHsACw=@qD=NjovUJ<g+2(aH;hLP>RF7#Wczs<k19PYRHI zsBp*qDYL%M$i+;(P2;{mh~-=zr^WpVGa_b(Av8X#doNtXe70t@hBgfw7dHxtqR9yQ z#Xp<zMTV!fz=Zr#&jAXvRz=BivNfx)@d~q1mhR9mpGzz>j0yR^vPZkv*q&632i-6P z8s5$QBYcG0YfdcM5U-Ekyu-rl?kVA3VSue%_Mn&AfVu4n$Fl0<hm8l-I1IP7*8!Mp zs0HWyF!W1V!a~9RkG+I_6I>A^AVG#o%fGVU=PhM7w0#@mtO2Don)DCp9QYk#F>!@Q zfpKv<WFV$g{0(g~ShOiUn|-~*E})O^fUq*A_-Mw;RucD$o!;qt0ZeSHssNn84!O85 z*_HS)Ri8>Sop6K+czujQ@!^Jn$9_Tk|JH8>9uxuVKRF+##d4U~hKGj~X_OLB_+Co_ zJ4rs;@Er#>uyZlIXX(5bsCv_pr+%Yml003A-@sFj^5eD7eN2f&rOv^c#w8wt>18I? zL**xylLNU|)1D0-0CuQuTF<@;D}sF%`3{W)^8uDXJ~ad#j>-BB{`JzZ)aG9W^wNBX zS=j3FmA+7zo*#iB6KcB?#plhpU&LWjN4}C37AI&&EBqUSk$?AX-fZuQEx_mcJ(iA+ z{WL6OJb%$ZO!nYU_YD1eUi7)Nnky-qr`)4ixN5h|tNz9I{xMH^<SP!aBUq{|1dQ2f zFl579qnR-QT86=(m0~d3G^{5GUh!rh_Y1`Z3k{7x_s@9%${EbT^JE7?W?E4tW#Iqy zoq5H3u7c(rNO!qw{kI=PDfvE%=c?lI5WAq>Mn6H+UQLRU4yynJ;a9$E`oo-674P?S z=A(>yDQr+eJ5#!VH^g)Mvg^<w1NF~7Zq`(;grd#N@I`C_e)xS3houF+W-|C$XH~0u z5q6|3XMkXB;)HJ!ex!`1lB4XWne*At?C%=jYqPW1A1T;tw2*T2U`~=?%L`#0(?zei zX=tR6HQ8RcukBT4V^W~i2mVl)`OgWH)wLe6-4PktLip{hwOQ*uoP+jH+YzhOK(5oj z)SPhRJUkTGVTC)<V23{R9Cw03Tk9I@<_a6B&Gt|U1Rh&G(E-o!snyWjm+j5)2eG6M zGo(*k<6|jwNj{U-f^d4}SO^HJU*>G)KX4UbsB!#pWsJpEHO(<+pho%s>pEf$Tv4RA z=gnle42lwyC9m))6+_l8WR|MT`Y~p)f4gtQhGOC4(+j_mC;?qvhwW}eVmBXvq7eM) zS!%x<D^im#9F;4YMus!Y_&oW3spm1@&x<4dNyw0wf*Yw$ItgD`^?^~`=-8D;jDY5M zIDVil{a7V2vg=QUt`*WKOw(w@lnx}wTfH-O0za|7Yfh0YwI|Xs`!TZ`Gptxt?{z*N z8qD$jD7Z4s?!A&{Mt8Y$csrP#4d$S)rtimFtEsZT+q()$B+2j+Z^O(8%1{-_g<C|+ zfG+6qs1pM5`6Jc12NS*3vTMo*_E@@4Oi8cf=X22NFwJlKA$sh9hTSZI++`Z@Q`A53 zH+W~p5xg#gpjfM{q49<EN<{4T7>;j`ZUt<~>2hCG4K3u8K5ZbP!7H#Mt&c*>vo>CP z4drZ^W+;&o)3O<|Nuh7LKWs$k!{pITd=3^(H8YsM9n*OH;;re<C{zDoJ4Op{XEY|n z-9CPs3me-5^djNm_1s>J6)5v|RONK>SmPP9nQ^sO^7`ZApy^-;Bs22bXx{1rFYI4I znvAF_?B;Z<oo{H+m{={QWYqZk<cAQ%=TTfjGJBpEM&e*{=$}~vB6=2G>#<Zjjg$mX z!8Li(r4Nh(lF?ABkDV=%j}Q9?C!7FJ-Tw3kyiYC${cg)Xp`{fa81oHxzZHetc<d*z z{O%u_58Ku;lAB0^v`#!}9Q3Hq`g)xgIIe~0NN>a<+5UoKcRAdDjGBF;-3m3xA1(K? z5=XOLz(vs!yA({qoLyqXcfM<oG<0d&XLO;C+nu?Zo=hcDM_9Z1hZTqj;afUal6edT zA&BHZ=W7)*t?^v80|-@RYm-<kLpXk_{DbVV_{m9vm<E~fmbS%=g#1vVGG!?Sk?}zC z?ON|gKeI+@J);}`sO@*cb#9L{^83X46h23Wpq~Z3T+ZpAZ1e#7r`?w*G~c9mV3C1l zHL#6N^Z}m2=bZD4hcDSav=zjhroG?uoUXenmQ%w`2f71-Z5ade5s{JApwDiW69UmP z6jX%<WpP~J?tPGjKv=Y^#>&rfh23PAn@PvqLpQDr#aOt-UihKgh8{${2jV{GFcJ-z z$o$joqh+}E_rk`@VsP)lG5@DabaKvC%Gi(nTVT@duUpUNslT!1`JwICyWOb-@*hWx z)z$XtmF)bNQSG{oY%3e&bJp9x4>7g%(R`L}ydKgFG3E@cM^aRGr`--``0UV#&v<+` znWXn(z1Ma)0ipKxS*J?yf<CR5_4AJkgVs-*S*08{P~)-<Y(mmV6|oyEv;K}QQ2}~j z%3NfEPCX3ve8`xXvY{B{ANrABi0Uu=8hj7l5eq3R+y6yqxkyq{k$cc0+GP93A}DbN zZHVBli$-q?-vy_cDpGuqX2-v`eOQAiSZc9{gf)p0oi*&o+h|udV67;?q}6+-jiim* z=dOSL$HKautP2YE#cX1*J?*#bST-t817eJE;8n@)!rws@6jf4wM=t>%pyd3VZ+9W+ zj6Q#)-o6$Qf%y)vNGU44J<DKh;^h-VP0a^cDjK<<XAxc?2{vdj@sNxn;f?)<L*(`S za(5EfZzL^%`Sv`PoZb=`Eive)h?<Q9ueV7HIAokgFlm%z`Ls6Fm_Z=XWR7O^Wg8!; zCOK>CZ~rKwrPUK?jMqe=5cmVx(n<d$xf&5Rld$|4PAoQ-22K=n5fhdl$gpJ|1A)m3 z-Cm#gk6gFnO^W$so$t9l2F}ig#H?c+KJEFK_A7@y+@Y5jH&nX+``{|!*R}s>Xf*dX zpHMtG6VvC+qR|G<zxaKx7YXyhyfo)0#6STj_@68J&2nO~-(LyCf<7`bucwfp0SqZa zAVvt8HuTYfqBTYlbHB*+zQ-=nDt##|uL@KwT>Jdj4<_cWdq4&dl;zZm-{I)o_aiWL zf%((#UH#S9n&-Mz*yWG&NWpq*@xLtiRx1Mz1aP$xBWJ76YXjsV@ol#y*}UOlBH_;~ zGF=q194{dLKOA@hvtiZ2N6VVVZKhw)@-&^-U>Xb~`TLz7PvtSudw#g3VH=Y3S!a14 zdG>NneH8255DC*8H?tHWtpz%0aKkUSQpi`AoGfs2R&p3?aIw<!|Ebc@X7}_BC`%ds zt+RSBayE=S%gMC)O@U-3X4&tDDCk{2Yd#`<OJb<9Vb^-KA4?7c8Eez&Jz^ddVAX5* zN)F=>!%wAOB^pQLZ=r{|8qxVAt?uhc%z(fTv;&}5;ivst|FK~%<Cu*)_XpD+tCq#+ z*{E-vABW)vgsSGNT4ZE0di*>X8UNujNTmswxEtgfiWaGed2C%}5OuRsx2=zvw;cM0 z3+D5yF)I{nmfyEKOG{-nSZ`hm0C{NFU|haf;YgbKz$oHNTt%NDBgDC|qfPy}`<sv{ zTF~o|#n{G4J%HA_$Cjz1Jgy@hy7c+qxbK@tf{s7%S+xMP@Y~I|C_&+aLPBzs)8}f; z;1d)`_~OATtGpUhqe`dB6?_C<(GtR0R7wNt;!-d<hVct>@6Vy@tNO;UcseSY;jYiH zLpFWcj1ylzf8iM>y+Xz)*ZrXHLqmfJdQv{WSH`GoT)up3HC|;RQLY=koF)Ks{g+EX zpX85g@8R+frm3=E0pA6Gj*rFdY|MAfOYJalmy#1n?Cf`gxC~jObzf@c@@-~S0PoCu z991(g;IG}dROKlnvjMjcEvn{JjYC^lj`TLPv}Am#l!83zKdCFi%Ea^n4C@nnsZ12J zvtv2yScC`MXDYOL-k)2dFq+)B`WVsC;aP4IHL+V`*3^k~fxzuQYF<72$LAlPi*7xx z#fU#?ADp6Rg0`)th895g45m3$IO}NT&Ekr^*&DS_TXPB#Cr9(_#_M&XK6}naG&!i( zkFBIMnAk?XDBvlKbyV5sgmz(enGl~?{Eay=ry2JQQJqm;$J~s0XhMVesH!Ua-oHnP zRDAROnbjs=n1QkNEG#lQ>xE#w7r(TF{+MPZXBh!#F2wo`!H@^;q$hd%&0w@zg+i-a z_r8u_j$fy*s(aKe53o%1*RNj>jEuyQ!zrckB$87z)}I9=AYL9WZW{))xCSJjHZB%* zZVTLw8iro)!(R2hkkCt=>WNifs@vhrrp79M6_UsTj4?;;pBIY5<0kX{-Q`&o;oaEB zP8pePkfMH00V%2pdWUmyyO;F8X-o*!3m;3PUs4@ZjtK+9JbBTNjnzXKr6VZ`5BhhP z_S4f>N1;W=4pcr<wvGKTkf2cM10RoKm11%s67IfNw=`^jq-8*ehY1R<fg#JYZ?$6t zwG%3!pUUvDpes<k!2=Ja)#QGS1NK>H{_*2bG#Er@kUAtjqzdYBv)G@wxN$YX5GtC@ zVOTNNmyK8tTV=A{>9UKY%n;VSzsNUgtH6*cG=dFlNsL#lDOyINJw}EyoBb>=I+KMj zP4Ln<pqt_}G_;^JC#h6sfND3#vyRIALNWIZj0N|K0=n@Cn{dD~c7HVSJ6WS9EE?hd zuey+|o<6C6pB!_w{w)y8OMRZdxJY1T7J0KjkK~h?>V}zVy1Udq(Lb5kcMwYpA}YI% zwYDhe(!iDq#nHT#$HBX1AwUInbQEf_y7*_J^>~l{{Ye+xm2<d;_;X6hI^T5_bof@T zm_}GiwM4i4TqkHLF(F~o5Qc%I3zD@fG*`J8MG@IZRo8PpNci~6g44`ux(}<(<Bw{N zCqC6gSNV}kKz{wYDw%1;@z}n!7w28`-PaDgK*x1lY+@inc;WdBX&97=47EV{BeC5p zJ8cPb1__iSX0h)_)dCMSCtY`Jz8E0t9zY$(>&m{@Rs7w4I9PBj)g<Q1(4G4>6&|jN z-o|ZU)JQSL^IwmgwBSW=d+tIv=GbSQhue$epEI1#VGKOY`R4w1h^NkeQ5T9=LI+G# zZg$q5Zwc*N@&LW1`CDcAZ@|TTO-<bct0V0yoD^`vfwL%=miKJ%T1WgE7yf5vrY3ry z2u7N&N2=$ImUk8^R5s-k-QZ0M{Y~@rc79>i-qAAp2#}peM>v>Jzi<&099!}w-6AxK zPwzQX&fqDFpQ(mx@H%4lYwmp^9?5#N@Io1Cv+yEKZ@w!P?)-J6@$Ptkm8W&;R8v*D z)$YpUH&+@~bklCc!syAZ-+?y;sS6bEfi{1xc-(_KW|Be_&7ehAuWhDE7q}kUeJCSv zJ=c=Zu~w@Atl@NS%*ZDL8uR;s0pzyZUkXG5pQx@Z&_TP>!22@I<zxin=S)RP^)w-~ zbzVV2YpozYEC)ybarC9Fl_qX#%JkO07DO*~LS{EM?(MHnwbYdRKf9?)UXto^snnW` z&{wGJ{NWYW^m`<z!90{~6{ZZeHr)#j+gMwcl7aLj8A(x!G@a{&!N}whH&O<FOL;*i ztSL!5mHx7VVU+dBO67pMX!JYk7Yg(s(%R|Bxh7659N09^vjQGVNUuL}?XC6pN2bUq zQtD{R(07v$`DGJ^N$JxNzIumk=m>X2MAlPnR}*l#Z`QVr4%P4^HZeJ8zK>WarU_8^ z+@Z_J$%Sk6A1*Z08hTyePn7A5m#%-?KK7(hdBw!`e9TzH#IL~OBO<t<A*SZ|_=K%m zSytm`Vv(N`Y2Z^F#KPk1Y+3f^;1RHYv<HW(`X`W+ns)8Gs=69L$(}xN30^+%9y^PS zSai2(7TZtGTwEOu2s%NM#5iHH|5PK=)6zJRC;7h=dQHiXQFYU|*hEol*XmfGlamGS z-o5atw|8u+lE1>xl5rwKbo5^HV0rXw%`NOSNq&mtkc5$dmyX@i!q*l^*25L$$|mL! z=*u|^Vgv1AjEIZ+uOGon54y=5zGYhdWP+vw9k-{be0#81l?<owBeD&7oT-A8GKiC1 z_!SG;tzP6QBNCAW31Xr*GHi&$x{)cNTnj_k5GPaGs%GM+-<2$CxlG2K$4A@-{hhA3 zCcLQ&YzZB9a2Dcjl;B)Bsfe)EHn01bF=;5NrYeH@>{9lLDCisPxa$VX_3ej!Yk$Z* zT^UL5y-F8Ozp0<gkDR}dQO0l~Ollb?WO4D*hp1Xl`2WocSf9Swl>#E{JT}OVLK3lN zB;$@_Gv6saa6|-%yj)UHoKtN61r8#gTlYs^>vCOQPP<(dckn7L77otZ$;n#`!2j0e z&@3mzC^`iN2M+@8%gE&9jL4x{Y@RiWZ(6_pmtOCW;{{uC-AcwoOTCrShU`sW{i=#g zf=n2r*)rUISi_3@XGdl_ybpOMhcls$?orj52sqe+k?6)b&N~3<5H)R=j#kf8V~}%| zrFkl!#ir#x@s5wZYy(`~I^m!kC|NkQW^~w-udFS0-Tuu7gFNhG&>_3{S^|&r5AUSG z;A>kxOXn>Tt(dSdZ`36J0_UQV2uCv`i995S7fmL|uGa_CMnI9J)s5l;ZlPt$BEJPB zj!f$MP44(tGP}7ZBRGk`#r`qB-$Ff`ctr0;DgTv3T-fanMz3ngsKd)Rea_}}<{_P$ zt~9k&f>b5pnVsmFRox_2La5OyRb<pDz!;I=32|@->24nij~T0Nl1%C+2w43|4i6%+ zU21Bx9hOYB1?zo%sKh9&J0JZAALy;mdlQ<N)sS~=rkX_gAjv|mfHbp<^58~+fR}<L z3^PnFfbE6O?5oD%WRp}8iXuc$OsKb=ugP@pg@7{M!Jxw$kTJdX_D);97~}_u1Wj&y zd{e{6ibBQ+7)qp8LAY!EYQf+g{*R(;vp&OBDUVyKQFM9vJz!CkEEfHLM-gl0ZIh?} z)@C}`r(Fsrwh3cg0=K(@i!BJib`EM7d#B6rXEasQ^*8Gg-xWC)p{b4+pMyFk>gf}Q z@=G`{{cs8-wOWiyn}}|g{j_$~?M_Uu`jN5#2L#ZaYAP>x9tFg5D3Me%5}eA{9Eey= zA;nF!WFVr6#8XGe<la~Zxy9oJQbqHYHKYCu@g3kKa%J9-G}aXfmmyZjzy3YW)4Gog z@&AeydG}hkp3B9CD6Sy4d)J`JWl%Fn+h=`y!;VyU5@e-UuU?#|Orm{<IEGY!x9#a> zqRMna0+|U-mzrc%zs7EzRELE@z!}Ns$51-#aJ6^HWO7fB(aTQQRKQ3{qn8q*ofG?! z+<r7}*<~_I^jm7e2Ezjun$MmBiZ+_J)ikszydm-~b$9g;iD~j_5is!PWi}i^<a*=| zSxJfM{tO`&A?Y5pd{yNUbJ_b0A5f3$z8t3tz|<HmB6Xl(9=D`#$3C*;t7Tc=Lju}M zl9&isw&tD(A;KaLMmV^S<*!e}$+~UsT0p21&>WdDkAjOTN<j-EZ8bV=NXE+R_pmPw zMKvd%iJCP#l)Z(*G3;PrCj@{~dKXr2ldY8cQaI$}{vxX5ioeNbd>&oV)uN5IXf7kU z@K2FVZt(Fd+6minpXi)i_(OkFSc8kzrb>fuw!@6EHbL%=u$xp~;d5uJI-l~rQ)HEm zs+k#R#iLC4_U*GAyK>R_4ez_s^+L+dZnGHC2-T%yqH_Snuzz;{G?#^}2uBSV$8FP! zyLDGc2VTN-sLGh2+zu~?ZKYyLpj5HGcWu9Sur!ODGn8NRld<KI`FzK3n$G-w=ESJ| zgS3rME*(GVQ`<FN!~F$r2k8?U2HENtW13Sma9Y2zKrz^HEeQC%Y|=KmihmWY{u^}C zHZ8rT0XNNmR9jsFHX}z(9@m^14O)LGyHeynp)C|xjeQ(-EDd_B3{cP`mC@^vg2Dsb z#lw~<zeyxu45{cmBuN@=y-X<uYS+%3T+AiKx2M4J++NGdKKr(Tfq}08GN-@2iW*I( zp+!$Quv`)AB77GlF{Fevc9;2trKY}C?bv2D`Xl$+Vcs4OKk4BiP4P=#_=lwh_t-J4 zuw4x_R;$L@W0f<KkSUkoirMOoIR3A`#*{TqXL*}cIbD5-9BMjFPFd||(ffE5)CEes zbs0FMsAmf7#Jc0;peZyf%`oDvS{8H{e&}Q7&-(*@RZo2;{)Jb!WzQ_T>~aVBr!#4Y z-KA}&o>2ObI4(8<2X$7Eb`w5Af`S^}7m^DgTTRn@$H~Kk=g@INvgCb+PAA}jfq)5+ zS4EG^a+9MFYg8%S;3tuTrsoR=6rN@;JgQ*4bra6X(9)U-crh~1ueCD(3osVk6+XQ0 z6f-}W)#3(wgR0@We^*K}(>LbA(nLoL#dV;g|KEZHpMi%_qcRk&I~@H<a(}_fQVEF8 zvX=ZZvw4{l%m%QML(pD5G&k6p-0aXMcRo?bXNnmrL&d7iLbDYdTNR8<x)f*cy?0Xi zTaEguZaW^tF1TOP&;)`>WTvKBBp1{#5z6xN=-N)@d-<6gtj0<F9&V5-Iv<6K-uMo@ zg$bU<ZKkEBHUyWgtHbB+gDkSV7xV}u=xS<eV9pd@L2_uKe}`(=WHiN-z2qHlYxZu7 zR^NG0kU;;aC^G}4RD3($`48PeMwEJY=EPCl;#U$yFn5}nX3kQK%6->;-|nAtb2n-k z{IUL+t7e_3H)DP`lgBAr44FY(mS0z0)ANC{|15c%N&m$=yU7=cZc70-g_%I^znAYq zIR3@5g+wNkcmAu;T#b3i1n1`t>x6w|03NL(e$r<RzIv{prG_l1Zk@%5UUGCi9g<E| z8jVI44;Y<z=KP9?j((#ae{Y`EXuHS+z>{w0qxdZLSd*IcdPII61a$FfRl=gXk-vTt z+{2F3+o|V_!gI4mac?ciu1Yg6ch&f@<oRkTVsl)^luYJJwckeziSDhrj%pG(?ASs; z7^%ZlLs{#r#y|9Pq&-e*fx<{10dJ~_$EJDFw9!Xf0|xMcIYe3sN3ebLO+A%A)co{= zw(ku>Nl;&XC5sBn<v}RN4#p>t;C0C!4oq%=+%q67Oyu7%&RE}X<Sft${vyNIldeRg z+;eID)hmtT2R9?L>o^q}78b>KLZ|$|QIePI)dQlzX1YRFPR@A0beElri|f;V(>;9_ zss7)tna_qP2;RE-P?+bm711l&!*wBIr^Vl3{Fi8-DJSjz#NJff=hM^~Bx};v<#MA4 z<iNL_4Qe*E&-YMW+6D*vh6}iqwExeg^fA2(cpPHyn?^?uzR6F@660OCp37I$NPZLT z@397-l+wBVj)eE~&7_ve&4pG`AQCBAm96OrNtnxx7rRxdCW)p(UcMy1yT^(ACg|)n zMLn`+;3E5|`wbI21(BYQpn#4IM(MZQ+qYdnPUOCI6<9&$|E!P%n*FzmuOB0(aWype zp2=hXMf?7xb}#dOWF}#^!)Js%R%Z3y4As+was~A}FFCo^ffQ(zFs`0$7xT4hI1&w0 zn!oyK&FY8nW9MyuP4`Xk>rILzFbd<o2%??SRC7c*@^Xi_g!uOHy(P&Oe+jI?rk5_w z3kq8Zt{^P~(wy+ofU=3e!$Bi87k3o9E!U6xl|T-^J9IE<EUMBk;%^c5@UkD$^SA@V z{nC6MTjaAKlq%5woQu65+}`4C^4-*DX*p!-EI7Zsp4SFYoiDs?5#!ibaK<)rGDN+M zXAIm{CbbNI3Lmva<$+Cjo6x@(&XlW``vw#xfbL=GIia1cvx<B6Jc#J`UWmud*5o1q z0ku=quV}S&L&j~P!Y<UR>ZYt$O<|w<cd=ggZc-vaLf_+}4Zcjks$j>hfaJW<=rZNw z`PG+){6W^y6@%sl+w=P5yl?2wUH5<)Yf4g|S9YFgd(@lBY8R*kTJ57sNVPcz$HkeD z@M9!q`UcJYx^68@0HxF=@7h&Yh1@66W#;wx*Wgggj2tYLd>T0KP+AjKGZAWNvA`|) z_p|y|78zs~(;`pzL}<iLwCd~&`?3Ks!0(h8wzoVl?(yNuXcqhPult*)foGCJuQ9qB zfu7GFhN>ouNbCNAGR01CC-zoH&|~2DNae9W?I1j)N`r&;<{W2CGZozvVIE9kuvpo) zd~QW);t-UfV~~=0LqtMt@TaQW0>U#99;V;p#wf!ETo97&Cj0i9!}-;6=*;Gi{4g3C zV-g`eYQND?t5ZEN$E;kRTqD@YgFSi4gOvJg>!-^&78TFLOj+UV!I+`vAhXx(F3?eI zY`A-;arGP7-7D%;e`G(0Lqe<EJHP(^eN5|DrVg0VK~Z1@&_I?GiltNRPo4D-R3L<u zw1Cl%dEe#<iLHL80kV?uD>*G=USVd}F0YMwzr;uiuWEk853ixAQY0B!QoZrl5m=V> zj^dtAwb-k#@kh&C6BjE?j<U^WoR1mnA}+6Zg)K_wm;~5F&iA7td+~<}e!q<fMh@~b zYp_R1WJ5^duRK=8CP#_2wauNft~D`vj;mn!6k%UQz66+VI9ESbpb|Q$P%GUoHErVe zk6yb#@nrv7zgjGZfd{>!mLW=PEKIdI>bc!~z{4FC2E}IqFv$8sN+%o{=^YRgy(g7l zY*7Vw9Srr0pV1!O6b=Q+)@rTk5QSo32b5JY$>=csge{Bxcvw-#XH&kY-o`5r`kDum zr#^fKHsDwi9sv>DbucCKrHBZcmi`}7zmfP>r*D%M-6a~Oe@ds#-#Nnv0(s^yU=usb zotY>6<%|(#l*W|FY8l@Wqk!R?dThTD&|Q3ZnPV+<N30V*84~vC{rCP9W%5#+O%*y0 zfWC{Fcnm@(Eo5Z`=kMoOUT*Zfp<<gKb(qj@Kzl0(^LT?q!~xOP>l?wMCJ37-3Bh39 z2bW(t;CCac3|<~+Ky!)}v%&!_yV-OML(!&0)z?Or;`fm8v1~(P6*>9Oe`^^)Lfp=k z!Q6AWIA-WGS!%Y6N+@pyiCoa%i6r#OYv4O_NDf6id3zAC6G<RPoD?=-eoyr|ER2!S zwX?4E96U%eoF*8DZp?lSgnQ3bD3`;DKit7Sd7xD)o1Ra<!IB%wBj0;Fb&*w?;P<1P z>BX=G?miTq&+CTUOR4asx~1n$KMc_8glL)ukATNA|3JRt6K+1CubjIWU)g6#!hwFQ zEC(awNrch{fcHrzA#v5X@2B!*Xc+!Vmm&cV4+D;2qa=-N=ctoiIC!-#JdO%_7*8%; zkwY^h8*_QfwS2oT2>LCw`r%h*##=sbhBGPH&Ol-lw_@iuqf<fQqZ&*qqXS%Z?R<7m zkH94i03fHdcDh50{1+fR`n~q_YymWs-P7ZPcHIE~Qf`Co>|gF+`Xe~~lsCfBS<4F- zVZWV^Y6;?YlP_#4S88!D)N^&FU-$B=@Cw$yut0^AP%f+XT9vQ$ZeH)Ku8#iR)$W;o zRacY<u>O3JXu<AG0twX}BQCZE4r!N6LYCj7U{45ojTzC9Mc{+qQ{cew#B>=9YGc0# z*DzMSHgTvUrwa<0oxLjTQqQ|&6rlsixKC?ry5QILlR{?P-p_plFa|qYa~=$snwUfm z2RYu(^c#%E8hZpP_Gb@VVIV~N>eV23uTK>?s1uzVA`UO|-2+j>e<UACTQ~V_@Oy7! zW>iKAre61stlbxJ6z<*DnGgMb6ym}G?c!N}eh~lX`Gow?p+=lk{K%9-&~*_uK>3U+ z<mQ4<V5Ti`gx!9K-3nHY`d=W-sfbHH{bTT0_p*Go#gz~*0TQuX>76Hc3%}J<_lNDb zV15+%jcGJA9EVu>hoWI1*DHZBs@mF&ppgA*aPS91rteE(M950ZUd4(2iN%OF^ff`P zf%JBQ@E^NbsJ3l_5zNSJdmOX<KcUAbH%${6e-@**^Upq2v^4%8t|6X>7HRg5Wd|)r zdnoy=Ba+h4%!1odLRam{dv4^HK;Hey^f%dzkta&g%3+^G4!btQZcV0{*y8u8^|}F2 zBOV{8dixCGgr$+i07=-I>CV~H$&$N_3|-8#s8qtz-<uI^xn$uqf<o3WCqPa64IfA8 zlmu*nP9kZ^00*9Fuk)RM&1(dxV{OgbyQEo{0WN6C?HJ(<XH2dgunbo?P*crH<}zvv z={>nxbJVY?UXNzf)L>|pq#VyDixw<x16Goo)eaA7SnSwFu*(~WcA#JA3)(CvS|OPB zweO(BcOP8J{&%`8;9-!#ydP3iljY@jV`cZRCIZtb32SV+;^JPQ(2|s2ZdL(w#M24X zKUJnAGYX?%W2@zZA_a03DR2C<rS$DNP_tJ$MR772XlfFG$(w+Jh4?={R7fN+4Q7z% zx!R0Qfo4Zv?22ozKm{e^gNdci!lch^L;vV=(!akdYvx#$;zk&dy=uWI({?;r&(2nT z)PbiL?EPvIt?l1FxrSB@x?_=HH;k}p<N!(1d6fb3p=`fv>V5W3G|L1dn*Qm3LrLAf z%RXYY8}+`c-vlT~--e1g7ifk2{eP&s3aF~KZhdG3rMpFx1_^0tL{RBYr9lL#14tZ7 zK)OR3q&uWjr5jX0;?UiB=(mpd{_p*74~JuT#~u6Zz4lsj%{Av2WFF9r1t<5NHF;Ut zRw-2)V=!&Jp99D{?T2FUm^9TsZC9J@Q#`1BYsQ|RW(?p~MaHhPF6s0?@c-7&Q9Bpz zE799aoFpf8s@=RaaIiuB*lSi)vASVV+50g!6YX0S?;}PX>C6FR^xV%L9;akeC5Xfq z;INg(+;fwApEn)oH4;z@^h7KWUc?Q*f!(-Aa+7lSi^IgX@t>mWlvd@WX5F4AYFij? zP1m6reQqcl&e%)SZGei_2s?>M;1O1CfQce&7UheE#qdM^RLN_r)V0Fn%nm&BH-PUr zxVfb70rMZU0Q^8+<>s9!@J>u35CxEovfF#TTuKF~oo5dy!#fSU(R4)l(CQZ(Kd%b? zj&Jcn`*yfuE|FiPvdRexfT}AtTd1(Q64eGLAgHMmb^StSnG!5apII)^K>2kE<&Qh* z9t;umiL{**(vp`~PLuSo8B2?s^hXhNA6uRBySqpGJx1Tv#1L5-)k{gk8%cXk7rnoO z86Q9L7pjw;gOsLaEUF0zK%a4+psg}Z<yk!^e|=PW)_c<hWEDS>clAa%ba|c4`j4or zQKj1*#8S3*7j=nx*}hS|1Ch@W;Qw+({lr$F+tQD8kOUKwa(!H~7-EU5zl~DE20vVh z$j$7}x)MNB949OLMT)u^TAqDW?@CBSy7WvE=u81hLNp5Cm5#u!H34y+uy~>!y7P5} zoHK^Dlao=D`qWZh%H!zOlxp8{_-cu`M{Revki8f;$6yI3w>dW@QgR6J1sG9nUdACs zeq`+$-t3=%gLb9kijC(%XJVBp;wyLC)jtdZG@l#?_rYJ<9+nmBR$x=w3tI{N_Ixd6 z!5t&w*M2tRH#V`~ABs?D)TGdK$QK7%zmX2IVfqlfg}f5z?MD-^FWY~-vbLe3SLf7N zGFFWLe)a@lgUGI#y}~A`TxJy%WJy#&JmL)&c!L^{nD8r}afxaBYzFr-lv{ck0e|_z z>x633jt0OT?}GQq9Zp>ty)e1;4u0zKRHW-8a%PE6>tUA*e*NS}l<4)y`1?xFr(hNc zzwIOe+QnHs?NV5xvHLxCt&%v}@7$$&UvaqG4nbkra>jLU_PL_s;hc~6W8BH@<uJYb z=v9t~D3Hq075ICW03SoqSqK*_@4Z6r)Vm(G&zg53(HNbibW7TOf3Og!eRUF&8}9C% z-JK65-EY71wM7=G(Rwj^`cUmOYKkxtsxpA?Zx74V)Ck-|8Hy7*-i9EmMM0x|)q;~? zcYp!l*puDiLDxf~z7OQhx(lN~w`Or(D)QHaR@tG>4)4mcG`#AU>B@;=6GH?>57CM& zN$TVeuu<dKfa7w(Hujo3K(9ND`0u?y8y(G&Kj_Jc?2m8=1jOm3i0Ky50{U&VR8Pi< z!X@4+$JbzUXTu>f>4!UhnY8hLZ%b<MM!oLGX1(wnV3FDux!qY`Z=Sb>p!poa=%pI6 zVN+PxlIJIj3Umn-*vAw%jGqmi^v#Kg2r)>&iSq6j*a1cW`Kf3;7a(9gi2MfKDjm^A ztdBLhyN|S95!JF|N!^}XPFWjdmmbf|{=R@8iD@;7{c&6~UT!j)mM@nAdo_(AgbbH} zh!Gisqo+UfTl;O5os6lqC<y^sJ}i1q3SC{@svN|}nHdAI<B<nFJwmLaeUy=6hYUs9 z<-4;|*O@2=OYbomm3DUY6BdcsBWPSp_7md>aH|`xp1pe$oulxUCxzX1lPu#i3Jsaw z!L~8vdC!2;rcm30G#UjYu6IwmVY4wbV+7;p1ROOcwqHn9syJm=rmow_hxG@p$7^E3 za~9;w=DkXSOrlvuMmPpPdHbgA8gFv99__*pBi(RyV(R6_#)$YW&2JR6td>)esI8gV zG*D>WN`6%OTscUmY3RXM_Uz%$;e2&Js0=;Q0Y!z7P~pqp<He(geMp^ovtU3jeGUyc zvYl>4i<G!QKRiS&K{2n$&Sn(5X=AQ%0DzQ~4=;i{{iXx)PHx)0E6{5c#z)=H@d`dn zWhm2#ea3q=L1@C0^C3PYab$>_1$BPLr~@Pab0^`Op(hWCd5_XWhU~Ye(7xn1Ifon` z7OU9NL+30N``U|reEr$P>Y#~p^(Nbw!Ou$;9X0mm6;))Hb-}rk@@0uG8epXW<Ud=b zC&u=f1mx{4%82+miAlNZS(2Os&oS)w<8=d1h2b3aA8LEl<m9=**9?_5qyeGa!D(6L zM(^BSS$<mT&f1$XcQd?hM+u(wxLXd)2E2VdfZVkz#CjwXWtR?`zfG~GTjfki=f2D% z;M=dFp%H)-Wz3cX-VcuH(GN1D<JpL)jD8iNu(Hn4Psjl<(CFKRN3tXd;>7h4h73}w zqnS$gl3uRBoVn1W($=iTp2^E;37sZmzIOxJTm3d_0I5E^*w9|R5H9%amd~VG)=(tL zRfuA<0B>k~?a|M7!8ftuQfl8<xgxi$3EyM|huoD{GbjPlj3k)@RcI>nqk(sYn`kmb z>HE^e&%W$&WG!*L`^jQuAAe}_qZFT&l;Oem@S~Rbc`2*%HoTpai7fuNIJq!b0j;Ri zyGergiyte-ooN^M3D;8uq&W0(yoL-iGv~LDQ1;(coOIn^<9@3<dZsaVl%LTT>#<gF zk`<I05R~DSIb&Z4T)?`IvcFvAruZedI#Y(&*AtT7aP+r8hs2pfLc;DqL#{9Bv#w7) zl7~Yb%g;kIh%p??_hJZ@(N+(Qv>Nu;=CLk|fwnkd^Z`I7-$$xb^bGYz)2@WU5;;0s z&SoPc#jgOP{-A0J5eD?^#e}a|2Qu0up>an)i?zuCScZ*Ta_e_{s_<c#tD2&oKv{Yv zj=UPN11}GiKqw^$htHon5`mVBkPbWL3u*Q_8z#Xv2($?k5*+!7?M$b55HDr0(&V+7 ztXo4js^r%tlt%Q+D)aWQ6OG<;`-Cd$YCi1j>E|9<6_akqlt%(uFmXx`vYVBQNjekW zLMx5BJmA<s(hhcqC4k62ov?dSdR70)@++!*guzw4s06-*KAEiT6i%fJwNf2V-04nc zjorOmB|{b<k;TM}2KZ0eIldK-C7-U9Dc<*4Gy&pr4BYsP?6`}QJi-20_o3T9I<2VK z$D&cy)x)=53|DP&8G8u6r-P*f;)hSqc~kB!n&s^oiFS4pbatAH8`_~wYL{&|1<#0` zc_)Y?p2qiPR1tyUJ&y+UWS|-11f)90K^A2BtLO=Z$T8Ftv4B-z*p#p>G=|h%tn9u; zs?+pDI7T~|X2`pN2`U$9J>JFrPkQzQ-#l|QE0kIP3!U&M&>klVOl;F|x=@gh72pyn z`qtuigoA?uv5391pv0f}c2CgTTqvUg^fiWQKX~LSYYvh*H{M$R_*E3-0>7dUm=B+j zB|(6pV=O0l`&+t1*W<>&V~hjn4>C!o8h$vNX$$4P@@NQKagQI5G<3caZWD4EkW)@S zGGM*ME6C*-h3>vQ<!gIdXT-Xc;Bb@d&n;5ommAF8+}mr0I*?a=sgpba%G8kcH4^SM zOApoEP&$t5nNaU#u2hfFNyWna)Teo=D~Em5)y)pWtPBGd1qup2ooXGGAl<lG0V=}Z zlqHlq`{EC4_gM#l5+z6r{0~Nh=raMlxoYWo^}A`P7-HnRklTLLHVb*f>Za8CTuajo z!Mi^_v~Y$;ujKRNn<^?Soq`>WJ_lN%viTHg60wyer|ell<mKfw+-zUk-6yI-wY`Op z|1NWRnR=(N{?6{5@C&#P$T}*Q(<&>-&=Jc-j5r@axI-?HEiT&|qsb)BQj`)FpAWkZ zx%?l7`4g2T@{C4^In7h~@{8Nuy}FP1Sa28=-Aj%gxWsR5TaVgGk6IIPS?lX5KQwl2 zU{*{4P0GzhQ^m`ZkCB?ILfYN$Yv&reHR_*8x!*fFq-xLiPOu=3TmIr00nllO$`;j> zOWon$GmFc7XYCSc*Ti&nr|LIW^?57?SY}+-(jF)GWgJjE2dv?xNJ<KxL&}UxClsHg zBr5>a8@IHtje95wCXdRF&Z7@pb77=uRM|q?ix%d{r8?`3E_dGo00KioR%6N1|J(|8 zeZqWyG>FAcJS7nq2if|Kk|z2hROPF?=yA$14_ONjPJ=w&^L_v+v0m9TQwHBjmLyKm z`X>D-;|TxhuMy4nwdcBX+J)bR9p*N;HC=WPk~cso0!Q-yuvvKuu|^>4mGF6x`_7Bh z2k5%<*!;8-J6Kj1pSr^ENi_N#09;6VBT#;p<IBdkk(Wsndh-)&59@?0vAbs9q%Re? zu%Lz4(LdXR31pv1P!p<}$(bnK|5G}x{-#u^Q{>OGzA7hw$;=Yy@7{I6Ltj4}&gayB zB#M%)t~P4_E$I2Xam~N9B9MClfze=3natB8rQze2{fRYNCm<~?d@Bdusyz^|g><&* z+|Jab!%uEq;x$2@Qrc?uD^;XkD(uG7z<os%v9V@dwG_8;u~pX5j)G>^{a!^g)BMF0 z>s|BOw*_ryLO?|7)9#Df?4662=L-Gedr2>#v~qRk(*#<!E$deV#mF-Dw_hpvOSN9f z^^S9xKZQIGvzMe_*jlwg@kL7JRtoJqT@jKX8R1xnUgueq<8Rs20)k<|Vty|q|ISG8 z<c&Z3b(c$0r;-<Es8$98T~5!;pSrFt9A%J`avB;8HJC#Sl!vc4&yv(5aZ!>6f!=#u z6hU{8nHIaOQrVKFo?f8Zi*%1vVz@f%(50?{bJALu%hrrKhO7mdtdbH&H!^r}S5Jj0 z#6B`<Z<hjm*BGF1fz->qNLB?Mda87<Q|p>{(^^ob@7vRL`1UPNC}B59<weKbFB%=| zqdCjm*Pdkp?>zH5)?R(ZPn8V+&g@X4Ck8Md_emHY)nWgNwD@K_F+@YIs^f?3L%oq@ zQF`?3y9LjE-Zu1J$_ABwk4Vzz30(1M^LOP`M=uhv2(*jEwY(46_@_Hxc``D>Ix!!E z$0XELO0L$G!?@RuBc6G<*pThFHtar@<lsV!eaDxI(7}k$kc2z~4k>&2jy!|Aj&ird zVOE43hXFlcu<v0eI1$YMDl^2jZ#fa6`>?JGP7+@~4C>u&U3g^RbiyFE-;M?xPAa#b z$3u_TRRQ%E*gD0sR^<q-%(~7!Gcm~qX$o$pmye<Om^1j0RX-_P$wOE;q-5WGB3C=l z1f)i<OP@v;b7tWjr8@E8LM`G@I92$!fxA-<!NGSskPiT^9@yj)BrDfz=erVEIr!`F za(cQC``$o-<?xaoW-=eIy#TxQKz;kW#CKP|n$mUWPdK^p2g=0L^%cQE_*!?^v+f80 z3a{585cKKA=uhlddLJF|A$$ZjmjB#lL<2eXWdNoRxpbLAvke~KOHNfA;#~s&^j!rv zrkQPoM$>+`h7BNa1@Rg%CX76udS7f<nwcS1Z5x4M2M}DuKb!HOzc{7#85X~svH$!V z*~I~k4H;<I*ps)blZOEXV&XM-j~l)%5{;~#yQ-E4MQ#_rl3m8UdHeTwk-xp1BP}Cy z&_!MTX8)ed`(uEDcSx<ZJ|Ytn-4uqj``mbq*4Z07uaD3HnBy2P063anU))Q&9hN}s z)WKC%R9HA)m_Gq*2V!O=pI);V+Fa+XEXnb_cEIw8jp9D)plr`CB*PVvKyWPD{Q7>e zCmuj><6w$SIQkK}-~D?XzR@h!>ReM7?{t}f2ZMxq%E3V3?Ww`Q=cnX8IlfbCA>vk3 z*}_x;w!r{qlJxYksRp($_{G-~yR(zc)_e(EhJmm|#A=C*<-<oz^Er{?vIYjJ+bk<@ z#{=)ZW`o0SQO?gLHNXMd+(zs@w#nO{9b>ND-}RCJkCHID|G%Ha0Yu1e`5B(U({^ny zpd@v+@Jixo*KM(*%aIWkXDc|~J!&IAy{|S|AUFm`M#^}4qB1gmBLt#66%`eso0GNz zfV`enP=GBgER6JfQZh4}-_QC!S#620Rc;g-3zF}v-(r2X0!u)2_1Vs!uV(UvIv{V; zHttoDYJEB38_(`L*J94hs{J*AcGP}RUgx;WYMD-y1^J{e{(aK5_rscpq%+9C>8DX= zH@knaRsMRp$I@J$=cR(e9VE-~;fuuHh{f?a4_DqlHP)P>flhyFqSJh?Iu2LF;Sfxp zb(<%D?|yNEPBU8p<o6jF^9!rcfL#)}gkMa)1IV5?MMi%^G$X4Wg%|~KS7bb(f2<D* z8p(hXvw8P>qpjan#8DDDn-VXo^cfjPoqqIN@vf6017j+H5&XT?Ir$Ly&e;sEmpgTD zwsDcr4Q_x@<3RStr+5sAsd0anvWsGzH<Gf`ypX!QBd0mK`WtKXWMM5+kE3ddfKW5| z9uUI+_mXg0OLLvyh*s{6kfP&XZLo9zw*^3BVFS$1Y%yu~Y~fs@ANx0*_d?l?-0&A1 zJ|SIY;sKQFKQ~~M$YH^u^V~;ynfe$h!0Dqv+`Rxeg9)@bz>nsUC5JAfs8lY~Z+pKR zZm*CZ7q5UA8Y3GqD0lzoLYDD><iASu?c6lL{rb+iuW{a`6(I?cuy+UY3c{x6j#GEo zIK{XKy^P$*UAT9EjRc`;;eXFDQ*9&nhpji8xIobWsk!?&Wf0-nmtTKTR1Ers#{Z6L z?Mo<XT@uIr^}`XTzsy9ETD{<&x_$eH|MxPk8@aOw{l^)qb#}B<ss%)#haCbi^U~!; zi3&<4Q9m^pSQVf+hc2S7sFajd>h-0)nffD6%l#FyvVFk##TiJc{^z}9Q8FEtx{@xA zfQx!@{x-|9ACSv2xj4=ktpZ!AYFMXvW-q08GYBU|b-Q8S#NyJ<Uq2&<7X^T>kr6Za z>eF8}ngBph0C6Rjh?p3eB+h4HA^nt6-;YO8@Bh*U4AZYRRXG%qK>s2zgB#7OENS!W z2$<&uzpHY#SpxZj0(&DQWx0R|!9O<*GW4gSMtj1liu77z%pfHq^2^Vl`@}7NOY-T? zovI}jR%s5h=JT$%Zs#kBVEO|0B1;fghjbb>pr|q*Wn~wt@{Q$U+3i8SO@;6i5X@s> zBuCOvkk^geKebtnvVN|nyD-qG`f#@UP!uOEN4Gi;aWo8fxIUSXy0bjNU#j1)Bzg0C zkgDAxHtm~ANKy9SNYLnchpNgT*_6XwLc_11VF6kLpbqi(xxrtk8h{FjSpSZ{KNd<% zNCnJYltw%dSy=nyk?^IM7hKV_okvsx=%_AGKFa(8Y@IeEP<twv$dR~c-sk$Zcm;bH zi1>5w|2;2wWRiBkY`1Gzu^71Zz{A8_XBJgbv6(5j?|p5~_AG+Nx2Na%ltZ(Orf&kL zc|HTI!n0u;oi6rgChLXr1<9Qgs@@1S>&hpajQk>6z^DUhCG~eCkbg-rJb6O82f#1l zSMyJ&RQ>wU&fuZO-pLWaJL;Ku&rrbf012G0yc`qLLJ0YsOq!h+h+c6&1q{JMW-I<@ z9)MS8dCn5zcXNH&A3>;bVK9mXG;^v<d;Ttu4YjE|VnZZEA!U(bk-r7u_;Ls3wJ&$d zTFjC6*e`DbGC2QU1!Fk4xCcv-620Iy-q$CBG!p3mOGeWnw3Te&x{UpPKXaSJX!Lk9 z3z?JYe7iD*ZGXXh)o{xlo$;UfgM65FARuuC6gbx<<`u)Jo<4)7W*&kzV7BG3k=tI& znFBAMI+SM5W)$^tvKbgMg7!;@G0WFi+Q%sfLXfSR%NMGQ7u&}J)Ce2E9{y+bWkYhe zL{<k=g4nSP!<mC3+krrXxjc>{=#>M3GAtnKNv)puQpy`(>z>aMl40^&GlDqh&!B^O zVZc-Pb<}>WyWmfA+BS>1qTM9wlRqwrz{BYO|3D2OOV7BkJ)XI3|NalZ8=XNyf<D&B z69Wy?;FCM-_TK$~?dR#;UOt61sFJE~Oo|*?RXJ{k&&~KhJiWxE!mn3_#)YyxBL0K# zfvQ3RB6C5^e?=l32Cz%Hfq{MedR|kf$~k#kNF(ICe8eKC?ti<+7XyXc)4qr$-5IPT zE){fA%EwC(X@^V~=GUW)0j=ka+d672MIp6y5+O=w5@^575@^@L68wW4_KX=NfC<gt z_z(V4g%C);{#`P)KJ5w-N9>yd8<IP)+iQGe=5jU%qyPBvW7U!y2t`um6l_Z0!u+v2 zpaG`z($R#m!RxNfIYXawvG?Yi`WZZ4T=!#U4<GF@a0md$DGmE^jKQ*oSIBAn{~|OO zC+9t7u>&SL?`57Z8AA6(@fsw7LfFY~Q3^4{Guz1uDJad7!=3d^)9@z`h%IQOv7roi zJqSbib)xWzogqAe@L<eoL579OAV{nN)F31JXN53WJ?M8_s1^I8blUDTN{B~*W(x)q zwfUdPdKE{2dbBzSwnpv6NJ`Mfl(Cy^HDxYqx_Q=oHh0Ow${J1EEp%`IOu4GmqnI_( z9uu@zL%bn}Mj_n}I#F1}{HgDl0{IIf|2SD@cHtX$7?c*3)QEF3R^otoKxgB+v2#*M zOwHf9k~0?|%s;SYN*sOQX{qY|pZUn>sORl1ZsfJ&;(57q_IGRge1%8GsTT&Cd!#N~ zfFRjT@$L@<7y~FtJu5`beCVSE(L;MKa=U>@iWMTHL~Uswz0#DHiRQOKk4dLRdC32> zN%uNRnE&o9ofqA~*R7?t3<>`cm&i!nrWf|e3Wfme6Dlz6{NDiLZLv0#=C=50VY1dM z2y7t$Fjb0lf(jL!bGvtac>*j?yucH*T|W}V(9{z1A%pyBA4QZJ-7FLpJ=k<4cC=g% zZq61g^4b@Wruup2IV73QV)fxfg-OunlliS6AqJ&29c32{RiJ<jeb+;;vV-Sdj4^-! z`@cgVaX2xMOmVY}{Z|pT#~)C%4@P7n!F=B9*k{g=Esz*awFNv6R7W|Ip`rbE7@0)u zZryil7*=bC3HZz^DyRHjI_8koAD)y~uAJFddaVwRlyq_88-o|FX*dA}JX$;@j|k6! zhtU6hcpm`w_t<NT1YcPaq!ii8;>mt#qOJ=k000fFS2~#y*#hs(m@^LpzVm#qdq`95 zxrMrBJFCyi<KpPk-_%4KPE+lyf3Jc3-lb7cnv-`&`bSun5OeX^SMbrp1Fy^EJ$EoM znIAG5fBU~h6&=~%-~WAmba-L7%>sz#5&;803K_db48U-_PsP9gJ@3`vXGv+)C_sq3 zgCdFTlPA;^wD%D5@)<s(kEsOOS9-q2_aiuwFJzIW^w191`|q|s&=@t5FhgynhqAl~ zvbVkb9>f+i<|@3^csoV-YuY*Rq1aex;iu<h|Ml{oIzYFS&U5_@SXHV}k{Bzbu(9WN z0;I0j`ebF!wouvIam*wMV`#{{8RiIfgoXVJ$Sa7Bm_&*9`ilZv2({7^eU(ykd5yOl z2oK3>UDfxCLLpVWui4pv=kd1(ghZ6#>qSpq<KZR(PzTe$wF2at>yh7qx6ywOob|uP z!UM^SID?=dzKnenF}?S`_{H%Cr)b36NysT3hNO(p=ay0wel&(RxYkc#v?}%F!3AsA z9sa?+M1COoAW&~f02SnAng0rmhf?}=cAc|lGeJmiN>#CMwgNf864c5~0qtj@Iu@&@ zdK5v14*~(CVB|n|5p`i<p+bi%y{Nz%lyE{+L1p~v%5!;nnSqZF98*%;JN&UK!ERFm z-=_!eXAeCs)6MIq9pKmai=}l&-7XVG?4l7zdUXkD4DVUrZ%=zPE=<$-l$RWOY-45K zI8~_=5Mt2&_oxs2F4gC8UZ?$ABJO-_*yQ{Sth|vDUG<-(`sCoKhJEKwp>xan`nqGr zgbQu=_}Kf`x8AnXwX^`j*y;B%6g;BF29H-S&{I}bGw=hlS_)8-wHoUOqEfF5QRJ)Z zNNK|16ouA(&}|Ro4>SGO=H3&8u6P7a9U}Fso5droG9ERyquJjAOGh;{<xXsVskG=l zao!liaD_j;t5r;jRBitJ<Sh?yKPb`r+Ett!CSY?+0ojjy^gidAq?-@{!#%h1;*jdW zIRVJxN|%G)jTXb61VdvyvfC*ITqOQ?ann~ittqwH-TW@nB(9rrB<9+hBECm05KvT9 z^&pLzi3uH$TxI(cI33PrzrRQ9zv0lYrIEN5BLzVyk+xjzSvZ~lNQDaA81Ii6D$rZe zDg*Q@38uyEn4wb0m*=mR(oH3h2l8d}f2xfC9AA87g76k1M1#)FkIwS$3%=f;?*Js< zCj%C@=RK9r!l@{Dm!HkJE!_j#Gr7e8f>>Src5E-<6P>sxQ+7`FXuh&Ns9#JpKA~<m z|I~4Q4^E{vPO-IqCiy*aVX_3IxXm3fqwxRil!O=sVPSV?Jm6^0frvkCr*(8Rp&Q5; z9cEo7vXOc7QoWoi39?<P{PYP85Gv)i82bDXUmSrA2<Qp4gVy*@uUJ|yPv1IkPf9`K zs=nHBiu&#aw@*Dx(?=@^Z{LX|qerbuKs}fR`W1{gRR8s&3K}{(!QFJX^w8azhoT|s z+1c6qKW^zd?+MQMOit>66qlTs*gwU-@eYvK=0yH%-CSxI$QAk`H19XfMqtsoVUOos zhh3a(^+u>SA_HC&^Ib_kq0g<QC_l00_1V89z8D`IIVPB_A+XZJ-u{5Sy>_E5dU=T( zY0bO-=0`U)?wS+Kb5dZ>w$8$-2O0b<W&INyut_CN7~|@N7zD@^U*63ul5|6KGLw-? zk&r;Zncj{|_JfEla07%%{P<l8s^<{zTCsl)v4n)ZAVKSj%<v&)*8*AZeND}So(K4g zL!x`KCenUDF_oNZb5gs`7~YyB@J_@Cw#2!-w$>k^Sq8jBLB{2eIM1h#N&?uEp-#P8 zXV25Tt*ThJbPP#T$h-NZm1*oT@o-muOPMzloaDE95^e4P3X_%ZZSPAEzo%tMBm4<* zaUatg06;Vd!7EjCc1cqT5hyl60r$jzEE9!*Qnx{GVL|2Fci%5ekld1<>@9-JGnws4 z6d-CjVmXL<y5qzy{_o7dsO4@&ph_sGafv?rh!h$b7C#Ex8{#<03=YPgap>Lw$UTWU z_cKG!+v~`x2k~$B=Da`&+8U_`i+$&yGEd)4Xr!K}!lihdsY`vq3Q-$inqaREvAaRI zyz%>G0saK4FlKIK<qp-iR74kVBpiLNt1{n(;~fJH)?k);urPe{b@>V=jBuTIaDWC# zyFRzGCMi-CZSxlz=3SqSWJ`wAy`WYTj30Y#G93D=X*67F-C{_nF16OMxC0{qyz-RL z{qsJmnHOj9he^ka>{X_5>|6q5u|}yrzQFQ871hOGZB3&vCXAf<)elWT#`#$=3QU?a zx1XEq)xYNfhi$_!8ewUW)B;gvihHjyB+*i5zt>UvIFXUoY>`dAi_oq4Q#e)I`H<}p z$9eLEAV8ieZm#F)-UJRFjkAGe;jiLLBN@1YyEWDub}pZXB{9TKU@rknUj6lRr9j8a z9hJ+ops{A*d0hMFBp3jD`S@2U?u;YukA?3eYXiPFD~at=a4&z!e{-I6*X16<tG!PE z%EU5}$&U4UAZaZsCWcWoM0sPTf%pcoB-nhus*l**vN!K$9mk^g4*UI1Zz)6^oScM> zQv}-2;QdOfthH2GEH*^`e$Nhinwai9d_$O@poaJHTBXPR1xMl|kn%J0@&d-2-_Olo zX%sw<6Z*)c8Mfw?G^{Cpcz^=5J0*~-n~1}s%@jj002rn3$e6LtIS$fZXSV?>PjoM! z)t2&DS>mHkvknx90R6oVtAK?x=uNPgnVa`VsIh_4^1+f(`=B5kU9<G6HN%%fM1%^+ zUHA+cikSWg&PNveMAZrd@##Oc-CWTEgYOvHm6G43=FIQ)R88(G2^9F2T>OfjVj%t9 z<CKRW%eY|7H=~;bhd#n+<bm5;fs!A46AfR|8a^jzaoPCIHt<gl)=#>p3<9=3r?6Wr z9@nyMjeo~=8HgJSV7y4=Or*`xKoWdFO;57gV$e+fz&#{86Y$BcepV3Dd2RF9&NdoC zzl4INyR>1M-YIAd!w8kTF{*&j@cDRYI2e%dZsjvpd$UzheaRL|ctJ+JvV8LniJC@6 zn%;7jrykO@JgAC6c%UdDZ9Pl13WllG@!|1=k-tt8sHG#v3eFs`1ZZMC`0pkwQ0$w9 zb)jKuC-pU=z^U>HaBJv~Sk&GGYKePomt@0F1u=ny2B+wdoK~4ZI9RqsXK+}?HVfXT zPXK%j4vAH<?Np?@RtSOTa$47$EHA_2X<1*BTIA*kapS%jJwTRJFfhQQNr1+S%Qy4_ z0PuzJd8Z)>Hz$CyaeKjDLvD;-Rc$Vhe6+(?WPHc5$w-?gz3HF?Uhuq*(r@0}PxrQn z+os5+a$I^HMlDDN5)>dxME)r}ymPtN9$CChIy_ITS~6H((KeEaq)W^O#UD^Zud(CI zMX|-jci~twfRFAEDl6=N2z;I3{#vw1aF0<GlTcL!WCETkMbciUx&>!5XtJ1y7<ORP zMr|JeP`cpB0ua}(Q^@3ah*?&0E?CYxm=EL+J<47HtMvB_OF{0w?|ZrbQ~moJfukI0 zR~-(rFuJEWptUV7-0!hne}FhmDfcpET^D%gL&+y59`^L7-*)4#Xm=ZY_?68k0#D@! zuU5U0NlEj^^35JgR$5VMuWJ{Ua8TM<)KrXTd)#&{a15}-;ZztTBs~%T&L~;CKR_W( zSpXvg0XKEqu9VLzD%xg2k<!!@yV{pg(IhQzxyjoWTGRb%a}QZ-03iCDZ5Fy|ES<Wf zXhTtq<a;&@)!r`4zn=%rf8F6zqT6rrssflbQn2)5f97WdUaaRxS`}=wII`gUEG`cm z%f_hbrVpB|QGg=96Y?rzx{nUFnR`<_T)bDkw+o~4^uFIHqXX4QFu)!TfglWs5uJ%f z&-UgLAMo&~+7b9uwSW7<*rbJ1wTYa=F3Ug5aAto5mX}wNEi+0iv1G>-A^n?4_Ce|j zk4e2dZkZvqF{2A5%E<g#ihHCi(IIX}^J7@uyc;B`$SYe>r^by36fL+#yW9b!gBf5s z-Uz^+E;|zoi851Xc=F0YQ~4a7j`lb5GZv;SGoq=#K;JQN;q?qbH~6zydP<YSN<I|! z*hYnHi)d!)A_(gwdc`WzkXah{d|SjaUt9!jmiImiFpL8lt(=5}kJ}D$YW{r9YTNa2 z#RaXhXzBn6BAFdj1thDdcifi3>&&`^hC!q^`B`Auuw5O*8sZoI;2FbHPTIEX-Sca^ zw37qojD-Y!J1I~sU&gc^$JD9FyfP(WD7VQr4Yc>yF#A=C>7f(sdKfKlwhNEY+X2e& z{-B2hLXNmp!^Wc|BX7#!usGUI!9uo|kz%O1dQYsrXT$*W%zv&_evq2lPE~0FeLy{a z`#^HzRP^d(dfX5GK=wJ{&Qhi8p1AEyjV>4%@e71$^VL|WqfCvRp$(c2e=~Xzu}rjP zn+Wfgb`U4yz~xkrX%*g%AHW_qqkIhR$wAa{DCCP>J$@O>Tz$TUesZz(=3?2@hdT=V zHp}Fl`=TgdBtC9KMZwPY6v)v9hlRC!?6rg<r9f2u6rG*<=e*9|$v%4qkO*A>bQIR& zan^Uw;RF3V(8}=GMQObz6N27#4_$q8`E@q>cQ##08%mEI=d+>8Yasnah#>}ze$M9d zlO@T>4Fy!U<PWHU5bI;F3)U3mshuQMgETu6^1%pLL4bdf>Q%hI58e60DcVH|pyr>i z%whf-VAK!(6qh3<Chc3#wd{PP{Cz+Jt;NH4SR5@752HxyV`*^t5vt*;?>}Kx3>x*E z%4L9}Kv@ihWd<>%2`sDLTp%7y@gT>$SxNO30mesy26tqjBaDB6?W-()qXEVqG<q?v zFHYlW9~9i97@-%u*B}M{YwOLb=$G8wUR(lt{GWwRqu+mjL*28yU*0EHAp^LR**>7q zq>v?cLh`el4%nEK7q)zm+W3vE3H@`ib#{fPR9NhQW&;GG854W(bDueD|B+`QiCjl8 zq4Is6`%+L605so9;#pD#3)6&i02KPfI4*mPtONj77dY9415XT*l{t?$RKhWQu-P}& z9XH!7!MQJxIrQHvTkU0vxFIxv?~xKsBm&_!#e*%WrbcAswjc~XDdKpX^>6iONlc3i zg?2xn?EcmW7jiUEKkGsvI9z~g_&A()i~4fn&kg|=K5)vxa+rs_-)H!7uq636yUnz= z#M3k}@rfhJe0C4ms{w6v@_$pW0izo@=r*0M8T%v&3^pwxF)rYWR(EuC1g=ODNRWDc zjfddz#yIdy5a|ZK1_vh-aFd<Jld2q~`4Tvk;UpS;DBNbToWz-e;9(|X)jlXR;`{r6 zWFWXb4X5fj-faT0tp*zj=F}|C<Tk+Ofr&>M_u=-bSv<mpOg8>H*mBB<3=0@*lla-s z9W?fp9T0to(Ira3qXBQ_fzK<*?rLx!Bf9nh0~oZTb_ravc01q?jskJpEL>3WT6pFu z@*T9rk}cD_qEhUlX)z%C)Antb8fcSxNz9_C?ozA1JAe0Wey}-;O3Q$SMBF}pZ%hp- zQ!eb3d3#L!qc1)JEBs=<F%x2P;cPXYk5+`U(zum5=S=)lDJ?8xB{c*8QvCtL>HtqI z7jl%^2)`Wwl)-Y2_w|b46d?oxV5oA%TAb$HnQArma6F_l6D~Pd0xd?{wK&?agaoF8 zgF{sg1Umw=BF`G&A9WWT7=4V7R&(inzdokFPpJBL`(^@9$o^B?_~Y0YAU8n*zUl2M z^}2c<q_Z=fUS;AwASeFeZj-d1BHAQYmTb9lG^Oe|Kd+ED#Qwo}ZjXapCts?PvN8q& zytkA7F3nsK=r+ZTVU-5-E~MQbUz|Y{HC_rdqG0eA@lnWc7g_+Cl|**s<WV4#ey{Og zzZwUMCG4VsW~j+nbvZUmr&azS959vLO4H@fyhr<)Vt@L_4PdLRmbyCTzOo<RUP|oo z!?*`393B8o#XzrhmEggY+2Z(kj7v29igSPlly#=E1n`?^eEmw3k4SQconcd^Tqs$U zsfsX=#0jt%{M-k=W|F9D`Zl(u4lb%IW<{?p5=EZdit506HgFA^biqC9Lcmjqo%K%M z9pW%!yas+Pc3=wN1L!|0D)Z+DsSF8RAHC)!fvnV>aesVJSSd@(h{xDzy=3@Zg3^9X z_HWtEbC!|5!S`~gY1hZ(Cz;MNAz-=#ZlB4I9!oR%4rAEhw=W7vV8;C?L1j~K>OR1D zgX#i;KHeAOcnQ6m5$*mu2+40nVc)l-X3WTLy{ghay(aZIm25h<SRWS0UA~;-<pBcn z6>yOGw|XgMJQy3#nsr|*T;&Eg#o!n+15G#_3Q)O5yj``O;voRqs=Kp|fTpgrK6~ky zku+ufb*f@&P;)zs;BLRfxUQTqB}?B>6mnx?=!LmRp}g3D({E~OyL-|Au(TDBWaKd3 zJ*b?y57Nl%BCx{B5K6CsP4>IV$HC#$Em2`0`@CbT7E`|PL;={bSZ&q5tC-%YGM!&d z31SdSt-gCLWne&qX$&hxvLK$k{oMyxH2o6l8@%}MDXkb8l|j}fCZm}ZLAy1Tn*oGG zi_4|kZoOGAue216=xV0zgKmz7&FL8N=%E8-b5)(89mq*|6=WhHHQWo@zQMukj41+k zNCN14xeW2D2T`~er=Yco3VA)ndmhVP0(3{6m8y{C6GB@^tUL>Hqm@D%zW4g8H1$)e z#htpRf`M4p59FmUx2r?x$b;}Yyf1g!)1MNlQU1W%bp}v?Y)F2A&)_NoM2ExsK$I5n zZ9)0NYBc*Ja8dLF+Y*wY229X|K~eXMMFlC4W3uJN-}af`6ql6^G(}4aBM0KKzF1<~ zaGQ^(1AGL=u$=~;X2}d8!asuW)bp0fCi2t!G7$39JEwAs=w~|&z~5K;{e~g<!E80F z&;PW{eWkSVWUW9R2YwTT^5bpyLga`(jbVPMgWG`aTv187^5FId;otBWfsEf`o8!td z3JM1=9qwlW0P?|ie4lJLi@V%o-C@2&#Av{Kw|fA-)NL;B2#@|AFCoZJqF8REGF=m> z)+Qcj^UDXgGVt*DoTs*xg@mHK^6%+&;7?WlBC`$0_nQ6CZ8Y-m;Vz8cx6jOPtdtt) zm}Xu{c%0GFYrEvbu7q7fKAY=1qD)W5gtI>hz`N6u?>Z(hrBNlJrZ9y*hOO{C_lp#f zw1}>>Pe1@aLjawkkBV)>>)w_EJ*|{vkKsLh-CCyNt)Wy=zKpZh0lm-3PW0g~O59gH zhqLF_CI?dQ^O=W`gzhvMyVluS=G(q4t}zYryZA7r>4LM{W^D7;i4699Jik};R3}+3 zbeWc4d9@uaw@}?Y?^P`5cl7mP&Pk*t>}*8;aqX|I?Gt#?XE#@p`Nn@cR=Lk^a(#7+ z1!A%K(!HCG(|$uO*?+Zn;PbCbR|C1ucDQjXchg(#y^Mu-)1>_TEN-j17|P<TxwEeb zA7jxm>;*qq=G5h|AEHT4<}=UJI=wkxzjaj+;oQ2c+S#cJ53dS;g(G0AvcK(wqg58; z37?vnf62?b7e#tV_Ny;NP<ajo>sZ`XJ^%DZ_$3qO%<Sp$@y*lmR{h!*!;T2rs%cji zE32s6E5*X<{!wyN2;{K?HMpI;eEt@N$m*o2fqXl9s@u0a7i$uGuCy`$1oVqgo@QbD zf~38(u)#Z*&60ju1QS9+g7Z3nJvz#LiMqPhb3cc^7mr6oIOClDJec1+q~@)*RNNov zk`V5E2#&kGn}2ilaE$BZ8#U{V^~fnFdUe(Ne6G85%H2$?X<91U`STgK8t<of#u7M} z`qhKOqFr}|4~ImJ=SI1AIhUTP>#-sK7;<vzG3^Bqe~{R_#7T!4ZQOcmL-``j`bgaK z)AA<oboYxcN6iW1gslxLG2V}T{#-q;XF&LUTgtn)#eTnvNyQHAG0v`J65uiqcti2E zwws+uMK3xJ@kFd_+sG=DUTVgJKN|YQ;7%{>KjheIC;C~YYp(7#t-#NGNYHhM_h_r6 zE31bzwu8T~oLpX-$$EI>Cy%KCiCGlEsa?DCVR81`j-VCzt)x`j{Z9QFmC9IUjqMQ` zQvJuUwis8Yyf0tQUP+ASDa4qtC+szi>S0W~_LLXL-Y%;j-d=zC8H*z-j^q1P_}l{( z;!|m3W%Zs`D#jV{Ca598=Z?_fbJyIru;R_lRHF<&pHOvmnKYXS(P@{v5Ed4acI^0u zb;jhW>guZ6mOXKdj7tNp-%vK}5B+fIky*~KkvnOhEe=fF_h4-%mT9cvxluI5veI*J zf=&{8=@CADu%~Rd<PwQ3XBi8Irl=-~2H6NvIANdO)3sFgok^Yx+E|6oo2{LYmea2- z53MOoc-*JN;2uJs0)RP@`u27;iRfm51L><J^E_qk?fNAW(Osd9>@#*yX1HlN>$|<C zReSsPcbTZ_!C8y;r@Ch0xUY@y{YO))tD}2XVJ2&-r3iLoR{N<jl`>9+ypordOA(se z^`_?V>4IbWn}UINbuS8|`rF(L4ib$s5$<cf`i~`k=DxBnT<oUFLGX0<v~H#K&A8O@ z)?F#pwmdfa@mNzcB*V3KkvWaYK3GsCz=`m|UOU<{t(y-~e)^bxk;F+2@7XN(?I-4H zr&r4vvIbJ7v3~ESSAKE4Ps4;j6x6(0E>S0s#D4w$-5B9}N2g}}^#mc4Lh+WCXp6Wg z82$dPUpQA`%@i&ekbsYEs)THNrS^k;jnHnqbNZ{-TECyUZR<Qk8x~fnRQ8mvbQ&JC z`NXVnDCW+b&an4`m_+O-?5enYgO<<`y?LTl3k-{($I_(JkAd{uN&UI(N$`p<Gj<t# zqU+2)H9ve2=hiK{EU}--D>%#4<fyq@EgRsv$*S1AM4LsP?+*e+yyt`{DeN3W5spwl zKbxWMYpet#wM=cq&1bb{Cy>;q_|WLcrgK<Sdqdwle}J=Yb!V!<qQmncd|#w9QWQEb zv~6I}RHJb~9HD&`utaJ*mwjyL%6fF>@g=OuVIeq5?3xb)!t!#<$gRT#o%SUAf$*)M zGGLsm^A#2U;!hA<u^2Utl*nShUUpB9-O3kX@d;IpQYe1c|3P!mcu@ogLUI=bjILBz z>p+LDTV3{79PwLs>&w&qiD&iCSbbVT=gJWtaCS|tRTh=DxAfli&GgqQH}tzvu+GFU zW#7b%#|F}J5ag{4dy}Sy^2w=`d?c_v50bWdRMuqYv^;Iz!b!?}cIbum;q6HQuf$E| zHd|dzrDN|vdg+gD@$5;ShNsE{DNpquW?X#X<#zw1rftZ#%8KTn>`%^m-VsWQ>(G6e zRBou1w>%BcL-aBiu1!z$*iA+q-6b}+7*;!Mo6AESbSp#{K{kg|1hpUTA-ErM2^kma z+b6>Iye{F^UwD>t!dd7KP8GyzZ{Ky@^@6t!<GW7FmZj`P(jMA*h;Q6GGC+aMkKk_2 zkhcfX4<Xh(&BI1RBgGYAx0ka@PR=eag}Glf!FZ+_NDN}HXaAb12tlQQNXw#xjU?f6 z5A-#5%)0i^LG{7xs<(ZyH6l2WR*VpAyU*R-IqEH@T&dlrI2SF?a`Z{Lr_5kOK)I)x zPf7dADP!6r&%!9Alf+}Vi4-=T(goG3#O-2%eme-E^$5H2*j2swv!}?(S*C6tkDOKB z2pL}We35<viE}1*EN-<;c5ODD77NeFmi=(W)^q7K`$zj^oN60_Wg5f3CfM8%g!#J9 zNJCi<Rs~rPs*XH{x56pxe{;mQ-nJYLi@zw$xG{kC|DL19BrmX-S1yTu31_~Xwck^I z)fO{-_eP=3rA3PV>?yQ89}_NKfUd;!A=3BpGsQ<MgP(<e*lF<{f4zX)Va|#ReV-3H z?SFH|u7WiS`$6OyCx{-Vv4}S$mfn4Otp`2pNqNG)COU=!q3AstZn~v&y1Cj`+LVII znR~h}4W*H^_cY{PXo?^nmcIuiTO7>tBnF!J_(LV(hgU95jU)z8UBninD0HU{ZITAo zya>P1QtB#=h}W%GImo#BQitw6k22vPz0k7rPSJDuyBf!;NMAs*X@u$`F?}L=w7r`= z7y{_&)M13EQZlt&6l`m!jM!Z6s?=U<k#;Y*Yj+q8U!zyMtt6ejt!%!sTOKCq-Vl>< z<+iu`EBLXwIotJe_phUC`X1M-p_>J_{=~v%w7u9wEN;3kGER-DH7?D~p*EJIwYF1l z$2L?qV^-U+nmUu&@@?8IF**Y%o@O5&f{zzb+j2|UvwI%7cJCVVV~gDSWAhCa7#9}Y zH6U_OXtxQVcbh|93up%~ug#LW@!U=KU_g@_u3gb&T3|^A@kyO-@u<`5cH~e?7)<8t zc0qsnt=ZklP(F(3iGYC3RF%1KTiHF&+$K>cZ$sJdWu+&5Um8i36B;8>AsD_BF9>j) z7Cw%}v1XN1&p3u^7}H-g_TWuV3eB534NWOt?O!~PZ}S@XS*U2>6h5$#-xR@XUFq8P z;!~s-Kdj%_l;m~<OVe@Z$+`N?scGIT^+i*9^~Ei1MXn*%p=<;em)c_6ttiooJ;)!j zVqQpa?oCEB<0Mh?X<Q7J%N1SCvXiOz-g-(_sv9ke^m;FrdwlKVy7e@QYxC$_Qfxh3 zVLRXN<c*iP)@PEp{NYHlgZ^?=fv;svGJiZP7X|W~7i8iqB7RJTMMZtcHxJvSEPL=g zrrIf3J#G7j)8aR#%~Zu7<c3Qz>Mlp_KA7t83=z6JS2~{pzY8-o3*QmMoJfU!CW2q( zX=tr-jaVtZh_63XOeSyXaf!KeWOSz2$=xbsKP<&xZNYZFM9+HjyKdFqw?%&YORR?D z(mh^znq3h^mc`p^rH9~up5O^IQ+%O$n0y<rD|Xy)WN~U6@458$kc?}<p~@k+Gp-q7 zk}OBqtD{#0Mk6<-uJxh4{AO1Iw|XzL1eeo1N=r^$_w@scOD}(iGTOTbNga>kgqP_% zgwp*}mnk>oA0Hoqv+je^(o*DWvITj{&>VKwSno#6Zj`&!KWMEAI~caI(^(Ngg^+|@ zd49wnU3AwKo_>Nj%E$%k)W+nxHKzGYy&U>^$S4%Q+R>B1s!nqIyDrXqi8?p$(S&tZ zCyjSK5&f;(O+uSIP1!Q3b`Q;apDmUw9zM$=5NXvmKffiNIgp=lc*Fq(Go<;1v&=NC zCoaBlxoWuJ5{>+Yq2Z;tgi8_ldJo;5@SKzEY+qV`QWQUTaDgoo73OyvMu5-nxRFoN z|D6`$@6Kmga2yj^bg8e+s#6W^QT=|I;W6EW|J4=ec%HDwAIAF)UN=Xuwy}GbwZX}` z<Y3)Lk{n~U_e7m_s@Cvw2%XMhwj+^pNw-;sVzYrl=t4wvg7%2A{Q+lG@AHEITaQbY zGYklWpomB|Pc5`BPH}?p@g4J(73BE+2^3mnC;uRlT^UQas{%ojbYt=1v0gRj#)WNL z6R_0pHol*b{XNz7tniEML2-FZvcRBADi0qPT>&Cqo9$@stTBQYTA8$HjPR^+)ro8u zU2uEYdPthg5f<TE_C>Z=+0$U7P<`cgbE0fKEJgRR@h5z*$J}!|^R#Z6G4xk3MK7=6 znqZxmz1-ePbItB{{^9<Du4P1fu*k6q@8RB)!R7|G>u;7TgTY+|4UdyT9OJ#OayD-+ z1WA9EQaUeTo3FFfMa~3998TWUVfe<q?5p;$u{8a{5Vf;G*$AN<{<GBV)q^U8HIeqy z^zvE+eY%!?vfg_6E0AuB9vZSDX`i#Qr<3^-AOCF0<0@j7R;jEX@AbCbOp!)6*F*N~ zN@_aDA?1TiFeJ;dGREWL*EPp8PFdxl9Mg@OmBXHTAU&N>=o%E=U~(__NZX<?CG&uL ztk8-bBc=<Ej4sq3w%we3<A7aK<ouA^)83xlb4)WcFd=VM=p8nC6f1Af5uD-ux%ok4 z6w||-HO5Y@lK0eBs6_c0T=t!Zsm2onDaBRXo@JSRaPhomgWQa(`sP1W6RHr1WOT41 zia~<>Z9?~r7&jI7FR0MP^#Emi)R(*uP!u#titK}OoaHA@ZiqEQOxTUn`dh|JqP8Zv z$~svO+wJEj^fwh6nkyn*1u=qi1t4qQ5a|j?GL6tW4B=kscH1XlnmfnqoV&1?;OXKx zXq@QNujz3KJK%Zt$+cBxPJx-tq2s)4{AJi0>p}WVt8V*1f!4+vcWkn1+W6LL3@f*G zZ?^<nEEcTXlt>7R0zyFOd(S`~B0XL?{faQf1f8GhiC~E{s9oToVmy8{$e~ZR>(|Qd zaWuG4b|=g?nMbDb_MCo#=b8EHV7#KDK{th9wezPK<7=C_h|=_eAD45?dsjyW-7Hp> zr2U$Qqxfr`lbZ`a$hZ?+2Sytjbaayyxi7<-b*mkno(468rFOUwdUSDy8E9#e?iajW ziwa>#Q*4T0P*BXxi3Yf4=em^9@!*8jK#>VTNG5{{#MCiDL=oq_L|b2*`Q0ql=I3^u zPNNgH!p8TmKZN<r759?c+?@rSt;CdjBfT|Nqpql5r7FKP&)vd~O>pzF>l#V)JocA+ zLM2>lTS#Q@9lJ%*gUS8K1**_Iat{*hlb%k8%*!cnTzSe}Tu9GSrYTVFDQw!=t6CmG zCwL$Xd#VsqwE;r;z}7sk#ZMy>=v^h*(v@Pg<uvA>xDC1NJ5VQhW?0!Zd&$MQNe>&k zlWHap&3UnC<9@yUVSKCC8TnM8cp^A^83UX-QZ1JTQ6Q2=$!e70uq{_t*QN*`h2TEw zI|gsi`7hq%J%+qAnsI?F*Nt=o+JN#?(u>dSZf<Mo?6=c!C~eN`A6(7IBO#RbyRg%| zucGJSk|Jyuw=9RDC`|QgraHcLp{s;rk5jiKMzG~R`&;~|-X3FcfcisD@^hl!ZuZgi zB+I$SP-luBE8n}K=5wsx6ba+G4lMTC3V|lm&!#-_&1<up7Xy~Ue6=Gw>=>yH*pT<b ze4~@5mD8hBrP%Tw9uBt`xlJLLTixP=_lo&%JM$YsS<^inl_FN1_y$|SWB6%S`JJ$! zWI^TCICZnVreT-3W=k6zlD75hGE>=SS2g1#sU8tmZ8w81B(fUYh@~oZNVf@F0|HG= z%;WYLSHMo=Vi(5ZG%WF<`w&liz4mLb9WPG0e#4o1o=u}kep=BFUCTb8P|AMZ{23!8 z!z*tL*2K=frA*;<{Nv#w4pj<??W~rDDH!Ha4I`sn<YxT!>o2ewOY7^WY+=WIISj#J zo_Ga5YGguqvH3d&;%LDMh@^Nnr0Yu(8XmT5$Et;Oe*%cKH7Ca`Zo9%$FbP)uI>pnE zCoQ6#VbQFd@iuSG5;&rTuim?N(>#dHIdX5o<%%+XjZrb%YS_Uy3{vN*OELRdw&_2N zy*)3}*nr5VQ#(q_@Yy##_fYbFKu#)r+a=-s=_QvjcBNJaPziebn+@4d-_e^|wJ6M$ z>qCsyJT(R|7x&P_9{rl<bBE??*49IekLGT@&(9<nTvl(Vl#mBSW%0uKb4?s0Hz^z2 z7*FGnPP5ga=)%J2I?rSiZV@%G-A_0Kk)a<>v}DdFTauI*=D$8#oxA0%(o$qH16qG| zh}Z5xw0Q`^pclPnT1#$NGz@&MWwt%H`blo%Th#)APpxd!HYeJmZ-+0Ln*-ljYp&M9 z*^e$oNhFS(AHors$=2#JFQ?egi?rFi_9SviESFFqKJPnCc#vyK)K#Dn%<swCcYg;y zBxI&7s{_+_%#c>NjVqgVcDC^J9rY6zJo{sGpHE=?mtSVkZ8}1?eydE#ID?VEsGDKD zwUkJt3PNE1N}7A6dU8^AcB3A%?2+EA-KJORdZn$^6?wMSvMzU6{oy0cf!F!%RsI$H zTIqBFEZ0b$Dp6O(Kh=ag!>~Em@v+>)At9N$Ps}}{%LKjDm!jM))x&CF1~L<RZ*ND? z9^QH<UP)X@)xP<@57=YP4ejFRai@59ITiXu*JwJ2C6vL@$inq*DHESl;39d8a<aW~ z+OI7$^$KX(SlfBHpGOcZHej|v{bHE!a1W6)7SpV5RP-Z-JFX5fKZ8N5@F?ea_Kd}8 z>s=MK;Lhb$rZKF^G~bUoBgXquG&fI+&0!%Wu72K=HM&QyX40XX&FOMaMt^wVbM6mz zBf38yu5<UAj0?A593Ne@bO~6F&YD&v4hx9(J_HdlXOIjvdL$KXD5koWjlmG61zX?l zKa)g*FlN_qxZ1PP_L9wMWJ~}BziqG{tQF;UhifdZ_%Pqv=qLc`s8~sqFa@4B<n4s+ z`46gCu$SS`rYrU~wjCS#GgE(kd(HP-rH6Azbe-HcFx}|}Ydn$Xd9_-#t>WxkYts9B zF!rNC`@XWGlzl4bAl3QX-#u+NACl4Vqs}%bdO&?FM`DDc6Mi{&$Jlk?9J;HqIw9EG zc3#&as?40toI4*O!RFFUZ?09Mas}g3+g{K4eoy52q95+^?dq*r-SSk5(U|rBF!kQ? zRKNfK_*3$#BpO!9D9I*-Y^li3&NxO^h0J5dkwQlH2q7U^hwObw_R2i=-p9yZ$2q_2 z(EIcK-ERF;o#*p;J+JF=U604(e!o8+&vY-`#RJp<N@C$hNHrJ5TBVW1p48WU{fV64 zBjX$*qqnBe{p{fT&egWmw4u9W3i!qU%-3q<Sdwv3RU(cB5ncK}l`15vb|ThY_17Q! zg74tEdmTEO<FIHu^jJNJzx#?O2<xaY?qKr6*JC<IAR0H580AM&`+J7eS*UfQKzaO| zFLDNg0u6M@Ge|#~fhPG#X5*{c{mR&*y?e?XzwRe>Q!ei>XmX@$atO{JB|JA6=n6i- zwV0{5aH(cFq?f0tTvUC~1!DhZeahO;Us_x3&@(ylzXryU+Y6GcM;T%sQc1s6+9v(z zqHudCD%9?cxVRw^-kvY+uf3>imx}nM4#TmG$7OpnVa`Rv0BHhEkv==iHW}`Tx)m3v z7`QCn(~grGO=&MiE6`7UQZE5X_i;*SvlK>&MG~8`^694PT`ELZWpoWTa3v?1q$F24 zlNXjUnVG@*^P|>$EJ{27RV0Xu19H~B(W@NtBD4-GCz3S}ERCM$C8@quU@<Dc&1o84 z{hplEhFbv7)S!Cajnzvucg+gLiJwCFR<2#<cfma=$<$3}#3ujoLb(c9vUzO=w2tD9 z*)T*9^t5L?Y=TKjEmU&140HbTSKxUij<*GnrcWcXZeqPu;47^Mf`uJ=+1&c2t$GQ? zR<x!?pmChr%;&)vUOnMltuXnvpaonpF~oM(cMnC@oETTwC`j(C<adK4*vB{_A=<0U zV=o$Il5;Q{*;=*dSzu$6k~@^FTlIhwW1;0z+7k;a$-~0$?9N{-EGe<E)mbj+;@Ilv ze8i17y0})MFR_lbCBe6h3r}ols7A&)8V?LmM6NDATMmj<MPgT3%l0JGkw+$MR-fb! zOGct=b}Lg>utm8x%Lmg`1v80e_x=OO`G=B6q6Y)Q{*@!cdT^t?`Y%x^Pb@+rYi-@A z)DrFXU^=7beo^rxE%R3*=n9{?!kXMXx%ts9{p;D{=&B<78Cmp|U64KYB&5ha`zYoO zT6ppD>WDKiZiV)22HKCIs;a7(+Kl7@bf_ns=Lm3!O=>Z3KKr@3sl4*azqp_0<SWIZ z%J*Lku_lvwzN&m3&7XYy<*JSm)gj&0_Fv+3tZ^!wo<ruOYc)-;$ky8h3JN&YBdkqR z)fw@>(;D?cbu|jr8L?qkjj&a~+fw5W1Ik|5x<~Ts7+u2+n~<JKui07s(`JVck!qDX zWNT0%-3vxfnK8IZFEQdC^a&)b?yf2vZ)b2E{5khXUn3$4bgPkiT2f=8-u8K@kWy;* zbC}GI!ZD6wbG@1uV`)w?FSY$q9f0YZ<}@D)4Bs9&04&msE<r|@BIM516L;QGXnzQK z``m{wYeq*$XJ%)&!6|cf3uOfg@3UVV(kOK=#+>))_#(o*fL3yGp2fzO-}4yAu^+?# z)v3|%!cO^drME~aU&_{m6^;_NpQ7)<F4L^+;7oG*GnYN4+dk4uT?m!k4b}qZ3rBmX zHvCrdBO~;O2Y!MyJvv6KRoH0vCMnDJHa1$zj~F9h#T=X%3ie2~!-B3B#N@jiE=H*> zGFH>DCg$TKDYmk8+)B>zF(%Fai|>84x<+LM&l!DP-4Xl<jC7#-@?nL=7v8I6EV$NK z|B54YUbe<ztgvs%xNACM!-|AXW|(TqEil>X#RDtfcL*E=h3y6NiJCpRuMlXN<Te1J znA%=dd=vabwL#T8rhZ*l=C7<TmRAlqa&sK$nfc=}j{7$*LzJ|n#!8>rc`te@k1*ia zl*{HO9D-Kp5$!m5%>j32rC6V!^5ags8yE3w9+cQ&7+-G_@G^rzMmKT4GNaU!%QZo; zGnFTC!z#LFyO4DG7ecrsPDmLL7i6Ae`DYV^Ik)N=&22n^`{JjtIJl`jp#!q;bWKsK z*ryY5zQSMIlgx-#+!U&2XYGDHRTs@oS~ptX{iHXLwU8l2k<0Z7wf|&_>+GH@@hyny zHZ@NU9IzDIwZytOVIdjI+<utL*s7@C9rn1VKPran&M&HbKck>t@FFYADyBT-%JtO| zVYV^Y=gN8_rV)@Jo0JG(f6Csas|=h99xIZ^#Uh(K8cJ*;5fh$M$m^kPeSIG)EvN_Q zEzEgPVEyGI_Lg=0J;oOqmN3ZJ<2}?P;FkEWr}G}=SW`FlHFb(JZwuB(;D)-=opu8? z<TvrVdpXGDay$`9mqc>E)jlAAgl5$c7Q;pI5|YlNd?_^nEIVja%bVew!|vCp#P_PO z6?Wr93?OdfV839V+w#-HYt}i(Ipv;5qqODGI;h=fe6cazK*;#l5R(rD1%)d^-r4`i zv;A|pvqLxy4W0VJ1I?$74!hGX{w15-;5Ss-h~U>k=h)G+@aGi29=e>ku?U5!f|s`+ z8q7_Y5g-YN#bxKkxVt+zS5I~!E+D#zDaa5VVdh>AsYRSOQX^iNtUVa5M@&y_B91YC z(Db~O=8D?R^^GCo>KvbBE(ku$f0O9rfeSyzh;NwfewRw?1w26EN{+;$=)>j(c$|F5 zf1#*tmRl_0fa>H&9m8H?l(i4@ZdJcxV$cC>)-T<QZ*<#uj3MbeeSKVZ^d@<%1+HY* ze(epKhL(rqqi=DJMuldEysSb_sTaHryz@%d=6+*~+!Mz~iJ0?HSS;aH5)-HLM9dZT zt$qbe9xRyS?c`MQUai-NZBN8D)|Cs-m<ZdbUw-GH8F9Z@eY_`q3K^%s4kC{amGgJ@ zOUJ)6tq6QnRG3Y?>18je3os8s29^9bFzta3@x#v`ywlb7$T#j7wxi+VPVB2U_4n7Y zwpjC!c6M=+eRB{h$uJy(8FVmw-r|wOI?|nKOw;rcf=075GvVM}K;M8~_}Soko6?Cj z(O-sbG3D2#zPvb>f7QG?FX%4k_t&lMA|btx<ur}~oC7iOg5+ZQhKnC+<o2{VT_ewa z1Fr+3+ez<Xy`LRAcpvG6kC~8vI0;O=MeNv#oq+=0(Qbt2pbO`F?#VBVy|XQ7+Qdk6 z7$0dOCN{TF0FCGKabo6+eve<?oREm5EuW{akg-_qvvYW!z0HWH?9?;a@FcmFcy5jR zGh?f$9ozg)%`K*j%!dHT&Kn+Hym`y1iE-VG%qeLw-{d_IHL9WccJ-?EjakuiWX9~e zHR~^{mT!#b3}+OY`&W$U8#F=QRgZ{*TP}F4Sbtog`b9s|msZ<fsUz%baK~5co7p3s zSZso=bK(o$^=9UJ*uBIU#Efb^OyF!?edq_tHR0{V-bhOEouVj(xfOTkrp~`;>(}ak z*IB_%8^qX*Q7^k&T(#_N3~^U`DS{QWlEDxEx@<jmqgC{$+m?*(xe&fHHvmduZf-7m z*dSLPa!a1nM;df}cq(Vfl#M$?qsl|>)qZ;t<lv=jmD>aBjuV|#m^lA3;EZejyk8h- ziY|TSyh}E9V2F)Pbes@((T)<sm(sv)5(;r9^S7*(maCnAgVKHgmM3o|_(d|4?MB2i z^cEumPz*88&}2dQSd^dMu=^Ix(-t!oMRfRns8rI(#S%ZfiXmPKf5EdOe6X?ci=pkE z@w%yMQ>hZCOb)L-L`p7=pvB?+%scEmk7v3V?$!piI6JYu9BB~KCxXK5rUO_P18&w_ zvA-jA(4xBIhejFxlvj#<=)AMNz1Sp0j%e+BOz+U_prxa;fUQ_UjzzdWGWupcK|Yy9 zqG%q>YL&{j(@{Kss1@%q7=Sbd5W*Dvs*;M8)sMC~kuSDt=Y0_43v1K#-RzGGxm{<k zps)P*SBAl5egdxZ1LNC*?@gSFDGn&By4+=*m^0bk<lrtbGDd$Gk1Oo*ubKbIA2(`f zd-mt~PYmtn#@{wdF9?|4G3PH>Dgq(|=xIdAgU$0GEYT~p$OY{I9-{f~`5>?}jKfz_ zgbR{4dtyb)-^6brSmar#jz}k63p6zr`YJA7<5OM%y%g+IL1I0)I#LhIuh5GZ6CM=| z*Iz1Hfvq(v4Iz0f(Vgr7zx52oP<q6@Cy!`t{iS~|THUTo>X$yRH9dVw=sO`0+#-e5 zO46SQrEOI3kf=&T_hN=h!a^T^{t-wTm&Ji*-wceCXammCkFOw;tg;MDxc%ZS|1w}E zJ81mVnAEGc*&|yPD<_WLVQ7hOI<|MKAQP5fx;TvekdIQn{&yo-uTgqW9=_7E*7#B- zfY|#7AsM}Y|3gih$no|c^y9U`Pju<Xzb;!QOqHholqoJ363p9VV7$*uRRUe(7{!ka zeqiE0uE>yKthHhR>%S6n6G8v*exrk15OqaJn2S<WmwVIV3%<<4N6tEr$3GB3Z0?Q= zo&AAxQ(lPs*Fj;@N6^gW7MRx$gn4yeE5E7AbE6?#j$vuGB2$Ib_|@d~+N%o?MWaY9 zbWakb50rG9<PYTe<>&!I)J&h?D@<aHaIXIkEc<znw;uV<Ha{@tkMcQ2ZN=N$uM?)v zc|-_(<!;B?;FPG3z_>w(IxVk;i21hIt;4~gv(U#d$4-$E_y?jI+>R|rhy8`{p5ETn zJj8JV(v-|@g-_0EzCBI_nfT&t(H(YOzP}xrz4JU#G^!62u1R$4P=Y}*5C(O$t&x)V zD#Tgf&3{wpJ-HtEQ5HvZYU=n`81|8_r3{8Cz80|2`+-r8vUz1sZ_;DkywJOFO~A7P zbKb2fN~bKuyJho50evD;1A_9=Ev(5aqQ4-#+q~}a6opG!$UCn$2V?6+&SMt|gQ_E0 z5UUgt^Y&m-IOk<M-7uXMkLpv4Uwk!GCM$Hiw-jPxBw&Y0Z`DcNW|MSFlt|r#Z#gsx z36+ODqqP3eD5V%7Bk9-&y!NvDkTHf%X3U;Cj<3kZ26;_M&#ZF>UaP6>LQm8z!OR{R z(9Y%zzUld3+D<u951_M<(f)L7QKGQ5+^-mJ{q6oduMT+d@fW9_fKH?`(Wuqm^DpJ& z)vhImZz9dr$6k-<tpmNw>?IJD#b0tG%X+~VCtSk^HiDQ<F7g_s?~g?I%ZRCvJ3yL~ zf{Ya$lbFhl{@D1OwUQH$+9;8D@|N7~RVL=_L6ZRTnsI@+YDuMHNhGWm@_q@Vv)xuk zTd&c4{|y4#t!B44ug$^QN8{n;#cZQ$b^0p_h6PSbSGjcyeh=;RCI)*8HEMjb#-Ayx zaQ1zFzZ>wwJ>cU-&2(V#?jN-aq~t9nuD@9!yBjbjT;5If(<eLa&gf1>#V;7IqP33e zL{Wkne^K$>^vi~qm*vY<CW8Z-=`L(4JcCdRL5T}3fI)ShZ^DDA3al?*NSYD-<@Kf# zl(HYM<0nOB)hds7CorLi!$J)0k=vH9Z3N%iIBncKnK6ss;4!DXhD8Tm0WFVq$0azD z8Im6V3eJt8bBtu3%8s+)J-7Tn)bMz71vJ&eY;}@?Z>d=R(&wbUXv<B>OFFrMxnR#K zHTp9~IE4thJ-3(|I?x^`V9+$!h4(sC&($yOga>~s0`QvWd{0+J2wxg#FEh5Z;~~0< zxY}>V(#GM3t>TmI4}LeE4d1%B+1qgR-4>#yAgtGMZ}KlGfu5~d&q-nch%<Tc-=a>5 zxGym(;9GdNy&GM_IIhQLNNGG{aU6!n$*eWJD6pwCONfWD0y;47@$D2BEP4diG^nbo z8p>0%|LFC_BlykWAGx{8jMz#4{%du@j7e_uOIew^llO_mywlAZicD-1)C$G@<-c|O zR|EQ=*%NX+0yNKio>Cm=y4dEvkjzVOC%uR{)9jOv3gG6v=u*wamp(OD#6DgZ*itxl zg^nWmoHZw}7xh`Ii>4nWps!!6R?KO@d6=dJ&)!*5MaZ((oNEbCx|`a@bCjdqpX*F- z{?xYSuX4z>=cLB+Ems=Fbu=J~Kco48#e|wK0&$RU^+M8LnneC5<4sZwxC%(dQe){E zTA<L<x57}HmN`1wuhdX<bm8)oz{J^^m@Qap<1=l)_TOMT(~~-{Isn14HxV_D!H>dD z(Rz6Bt>Xh;M6XWGrWT1(SW6bu`R(F7Pl<>HoI=kRVv0UR!_BK1*VPm03$P>412$9S zq!rbNw&OSwgarIweFI=K)aZAHHYFcuSysvMWA5V^Bi{Z2KVTqX#l?OVU*d#$`*sTI zxN<JRB}O{q<UWggF@8$6u?8$hq<OIQ-TFHuAW%I<kE9C!SJBnwg;Vrg5SvJU+ji9| z7g@RHe!TBT2a~%#a5RB8jE;(W&{4ZKVc4>n$voaEQhQXiKA5A)in4`_@7tq^o-qxN zP>s4IS6!50u+`MQyB^3%S+#02g}lh5X|n!RKu{3u=}Q(ZAjl~EQs;YlaA4riz$O7x z;YGkdczh10xyL*z*<+K+EwOAWSF<)5E4<31uq9*sf^TSy9=LiaKlz%f_(R25p6=!T zZt=p+WviN0C(+zc&z00o@!fzA>3P`WMq$*dXls6JYwLEPP8CRV(nSyU%I<H1gD49L zLw4ZZ?#aFS)|us2&p}^?rA0r4n0nZ}uiQ97;8}fPkm6>ixW=wvUU>Ct$shE8m&q$_ z^nYO7ZpCH~O>$EljFl=YPa*xkQO+muRS{Fr9=siur~Zj#Xv4*vF%OQC-wWwgy<?C; zuy|K-B!%Z+{L(aq*Kc@~iRbzex@FH3=Frka8M>uDWk&MwD=>Uf&n<nO@(})S6b9Rp zAm*tIc}P?x_w8-e8P__8of?gp^_O=t%ag!D%hu~3UB2P5kXXQ5bs6`ovH574CLO@^ zh}9pNIZlbt=gXDua4^)1G_ts^_odTe&(MHFAcad%W_&ey^wKJB)4}alsOY(ZMuCDc ziGsvLWF%omff*`Zq;7YiH+_tT;hACXOXkbV%MSD`dFj2cJm)x#KD|9iP`b1IUAVd% z<cz`IYmr=x2ZCW{2b5Z!Avk;8@}ALW3xL*s%s_Hah6=l^qpOPsN}<7Gw1xR<^MggE z2K=Fp8({V@cWTRq{Qd)3cNK{#Uqhz|Yt_y#A&|ioq^Iz_!eAc3C>lWS$YstCLP)Xs zhLl`i+@Ul3*4ptOTGi#X@YTsDR*>{|R8-VrM5yO)c(B?Sc4T7dTM$kTe00W%o`tu# zxOgd*@%Zzb{T5YVwfzl@SjLVd383qfSI-JE6;JEFXbh}CH|hPIgOu!CHCXN^LIjzn z1~F^yo|6h2`^n5{m7t*-?Q$>&kc#p^(gp<9G_Kr{>S$4J&hxMrd5vg>+Ip0B*?s(a z25{z|Uo0fjtbJ6Q(D}PkIF;)^O?8&E#QKs=`QR0~4<*!LS|EiQ>mUcopjjel8>Clp z|4?ph)CEuMzG`KZw~*w~2}q#=FVE`n&4JP-RTo?XJW36C*38oC9UG+SO7t@A)L`80 z2wISyoJRFp1dl)%umK1iJA^H5+}0)5!`=2O3rlLQwWPg}!k4!PQh7*GdEk%cVD`TC z&uaHctOh<*7_R(CHM=e9CFDF_o`R&Y9=-$jEqj0CNe6|!u$%RedR$i4pMiStg&p!_ z%R8iC#2;9$UhrIwOtzypRT8op|E7bQ-#OgLvsJ%*7CG~H+z5B5Q#~D>*R$2NAa{Ky zAk^qvR@M?>%xh-n^7&+2HUrhxbp#Os!8C0TzhVD82JkxbH%NBTCl3L0KH6R3T5}8Z z#BK4@7=BLNapaEET*;7%c4_B38l&_W8KJD?7`AMLj)(GH^4*iB*WGo>to&-lHqN>! z*3;u}I=h8TQ|FLx>}ha)-!HfHFJ(CV`HhG?bVHm3#9-bZ#g4aoorYg!l!fr!jZ>11 zHQW{P+^=Ws-nFi7j9eHV8QE#zHAGUpoqPdznr%WojN#SK60Vv8paWUhG})v?C8FcU zUJy$}yriw#F7aFdAYpae_B5e;H-YjlFI%y02W@G4Y^MGbyv+QnZP&P<Lki$Rjd1GY zEvytCH0y$SYAc5rmQbmzkCON#kF>A}dIqu8`*DP5*|A`Hog5WK&fp=wEvQz7m1B&Q z!QOpfKYv|a9MBum+A9*o52Qf%9*C0FRB3$W%-U9y)UobD;vWC;Ql}WZ-l5xUIASR} z?`^TyVWCl32tQ9OZ1*}ipTX-w%wL;?aOJ9S<sw67d-kzn{YsZN&cJit4${7$Yl7O7 z7%H|Zba_V@yO-8HGh@rRV8PPY_mrp|ZMP;ysbyHTW0%%SBVD=~|G7GE`IoP?FYhKF zJ(dA0e0428^0LRO)hsv(+Y_B+ah`krm3IT<$9`(m&2y*ZT4rTaB8J?+_NBIMspB~4 zYntO083gpE?}GeTaPK+j@yO;}8+@YyKO@>$R#Z~FG#w<BvsaD3ovXj+gL$B`I`~r~ z)^pd<eM^7*`=Q?@<V<iI9gtNfivPNMR!1Ec?5z?LngJQ|9VP}obv(rw3fR2E=^uWb z3^F3~6rO~BetwaB7*)lHd&a@tF%FlpP!V~up>G>~T`piY(LD=nkT^}gLpLUGMO;0F zf6aH7{i(oe3<3M90^fcK1oM-UhmqRL>8lg2I<GU|!ukltdl0YFrWtblBp@fKA?od3 zC8gBz6OKx35XZqb>l`<Q%YCuUFc9>)D1tQc4g>`+daiqh&UZ-xae{p%2I=9{S-yY) z4RW<L91AfIMEZw@GL5j)v7%c!j@#KrW3!^2Wy;Ay%CQDl6NPp5V%N;hIu%qowC^Pf zWoU1h;i|~vZIn-AK{K%PtyYY1-zG!E3cTposq&t!AS=yO#Q8Ajc&_ybMM~7ve{sa* zw0Kk12M;%la54Zvm*Ho+S+|PnYNeC9ia(wJsyd!+coP?c&UBkmMCQ#SVRO^DiLFpT z=<~ZwTw8YkUZCDWQN`OQ$jZDiaFHrIcj>tH=>~J?vmqMEjGitp+3{Pq)_b}Fy1R~k z(Ynf(h&6y@%)2=|C#O#b<=~5<y>|8NJLGZao>Sv>%OyX$H_!C-O+wdKmzKH#ZiL+G zM8rw%9q_*1Tf=g3=Iw9J#Y=d^fKXW81>QW&^@gG4T7dluB$Skqb)Z=A`7Wx++90>K zs|?WV;XuEcLn?XvD)T3JVZL*WIfJ%d%<HY3>FigAQ;PgWwx2b;LBW1fc)nCm{nDW( z$Bx4o$qQKeeI`F23Lw$C!Y)6Q-R+d$b4F2s48a!5nFe3gc`I*7-FdqtF>w=rSo#M| zVtxGI0l^&!cwsjJjV8S)omSFWIo)u7L|*tad@JZO%<Abf;sA(`!xw9x2MWCR8@EHe zOXy+9R8Rqs6{#wzyZ*Kbgu0*eVU@%1hS)q1#<|DW;Ex$!j+EFSnSHaWt6_k{!}p3T zB;|qV<=SwWeI(}TwcTNKl>!aW^<rorDZu9}Qy5A%R-l-)<>9w)d##+$#uW{h<hT&_ za=;ndq5eTOykm0P8rz~|OInpn)uW$BYmsgfNA6wk9BmGr++vN8p!;T<$41a2-JYE1 zDf=CG){eMqt?tr;{H0?t(eRG#B?Uvz==NLwX6DDY8eS+E*q6WH^_16+*~8oC^*vF0 zx6+I~M*cx_xh){romco$^2D^q)#S3aJ=eqAo5d_l+hVg<5K<{UKqmDwHKbil^g*fR z+52MNM9=}y8y@`tZKW1P8`D<CtMw=L=S$(!^1S_c+<L~&{!A!mWJ}kW>wsRaVYS}G z;jWhGMq2D*Z*q+iD4}qow^E<)Oib;1JKxKniai>NzE6^$c7d{1kh1m|h;$r)Nar^D znM>D66RYQ_Nl*vMok+|1cD0p@M$fP*{<Fs@{KEX($)#R`(+-^Q$a}H=HbYbW>hh*V z_w5G6k^U<aFGT9cUzFG-m7!dHAoPzD(P**C3wN2nuB(gi&f;J}dE^4tCnj;{y>#47 z+}OwI$b%7Bfl26WP=n^?PYO=wo(oe*u^7c<C!bcHgC9{(gOB+XV}EQ%GU_bp@aU`z zrWSsF^DSra%+1?fK*0uWDwvz6BM*0lVNK^d@MCX-#{V`7W7-Qly8$xu3=W5rI{dt4 z908c=oC(}6b@j$4n&r_g!|&@}dq>NQY{3XsgPm2|SB=5ffsf+s|Jerr@bqcSC)@a` zs5r;yoX_#;_YX2M34x-Y3{mix^O8I4Lt5p>jHZRg?_R_jX6;{7W!qh~ZM%thyPN0M z&KC&tEWS!1`D5^$B$Ea#vDylh<!mH)aXY>wcX@Qi)FhW5R6`Zdbwsf%7;dmMNFAfp zpSWowrxM}c6}+5NtC$OfWrQ5@#08h=3Q8ouD#<RPjwQCumH9J!Lf<|OK%?$%7yH+I zRh#~lr?GSnKT*~?fqQY0CTrW2QEe%f*G1isSq=pDA>>0shELBzv!To(4`ht?v6f(d z`u#4^!ROF5Dd4Cm?-V^UfH`&)yDz5r_m7XSiN@byk5&MUM3TBc3F9<r0FmR~qNv)- zDz)=U0{0sQle^fD_gcOtx>jZiYob-lilndY*>`~yd&r!L){CvIs`)eD5adh_(@5g4 zPq(+5f%u&YwOaBe*~ls@%M1vM#(im82heSjhd+Eg)}yPB-n`nogHHhr$``lq?XN%~ z)6yMK$RyJut_=#AsE&rZW{tLqhFFuDmx|wo?+YKxZU|RBv{)NmF{q_&FxpXQP!Uy& zGn%-ApPx{ukvcHf0SrGe(A|CJ3N2H%j4Iz~TrngLi^8quDtz%QY2SV|#d9-=-EAsi zHurf-9|eM|(o?Psvu*+`yya*jbuiG*aP%X0j@D2Eo*A!|r@6d`2*dwH-Dx8q^)U&K z+A!B(N6SMHZEPv(*v5T1GsEd<eH~CHP8c*A1Cl0YP(7i_dK2+Q<-wFIJ;2*Q)07lY z?w?`CA6JYy_wcLDNU7DMNAHsmUg=4$(-)4nYK|^i_^;a;I@h_m?^R9^Bzm+&W1PBt zI0AxFULuKqN!>HcXhmFX{XADUsBrJD7t|~VbmEB>q6Z-Me<5`szsMZk)Y>;d_~QXI ztxB>0rW@M9nA6=zyF_PJY7^<a5;j)jX&eWNp4#7?Q`iE9Udg-~8qAJ=>-dX{)!m$( znL?t$M*X>NkloInq2T7;NlqHJ&UqY}%;q*^u3H@(C#V=efq1$hY{Z7QMZ_YG*3E@& zZcN-}k$1C9&fO<jXcOCPR_mg^^k^P<O{3?@I~YhIJ?ik7QFAk-)YAN5A87t}bMrWl zODm&rW4Y>2dDG%r6&j3=UbA$GK5G4S(dXyEId(Uk+p_z<QA(bKq=hPxP5MiQwiv{V zpX1#Nalw=e`t*>r*I#i}qy1kCS~{hAoI3sGA(4UriAwQj?0!TcRj}u{;c5Ur6Y@ER zM>l79SdZRrk|+zArLEQPq#VcpWNvPbgOgL^#Yg#jHS5{g+4?XTY#4xA!^6XUqoX;X zY2532ze{?hYa|i}eZ9jHL&ErlI2J`}jH1zD#I)OA+mxh`mn)<$+-iD!YfX0Kf2Dy! zjm?|LIBXHG2$3}4j@LH<@z{VYli9qf$`smUPR-qVfE@cn@(#QH)_;>G{2F$O{D7uP z=_d_i^o|uMg`z@?=u;su`jq$YHzQ%$#-LChd^b~HFD-_eeMYhOyF%~x7Ov+^wk=ly z(A%P4qRGM8=H4h-QmnPK?!{|~Cgw+>9&KnCWj(jC(H;;^PbWyo6~4gz_(LVXx5HdG zpBKBIxp*B&u(I}FWw3dT{^TEeTloBLYEm*bY7FJuOv@e}vAPx$$6r&}2SIkPK)2$< zI*OVM9n>NGwT+b{J*y>uTyWCcO?HWcSq)?=<%gx-@1WJY*H=PTk{T>u5p?Ex#MQYO zyo=Q<^XS%Wi|j%cvEI*{%8tYf5OJ+BuvL+x8OAmchy7Ib;%60GB~8R9uD9Y2?<Ofe zR-f0O&|LAOOY7+wHTXjdWG3o1xuE(hI>9PL<Ipep=@pS9(kH+4(!I8?MSCt?)b-qo z271%!B8}(=tC~YG)Ibcx;c8Ot!>w;ty1wWsAe*0I$ITv|8BfrbZvsJSsa?v8bG#rN z!!H&FJUw1rCmld9%<46BUkhb_Ig<W0Q<smBl_i0$ZNOt7jBLHyMySrd!#rpf0LFxd z?MZMOJjaN(ezyNFKZ-5kw&~qn&*9)<D#}`q{}T>>C)5^%KO`b!T`8?e|N2d4yn&`N zBm#|1#y+mo0x$#-SsPL}d;5|w+Xfz&jA09(l-du&PT=d{WRxkB2hj@08>(RCs6@(> zGPBgNWv1yfAssC{jrF#JU;C5^?5#DQtPo+P>=VyI-WNpH%4VEai**Qb{)#B+CQ#%U zq=R+?;~+4e0*sr;yD^j}AhTc1MB>T#l)bF7jM7E?85RIY{Mc{idKH^R-CQhZ+5C-0 zUX?I>n-NDDRuN?Eshfyh$AeIbc~L*dlAmgsd7d3$fIqjp5G<%>m+IlQH#=|F&qb_* znuz8kM{hp2jWTPigq6+{$m5;~Z{_3}7_OlU3|D+}j*|y{u#mg}5|VV$xR7YB1Xm)1 zV&hD*Yeajm-#lL;ARDA4_r8#V*FG>hR6lF<@ski<PD<Nu2)HV!k;`+*ya0UfIb=#j zHB{ZG%HTD3QeoBQhc$Ugc?b<>G!I&SG+({zlaxk&=0`ja$A3Sc+Y*hAPK#cEpvcXV z(rT?_>~9vNDHDZ(^AdiU+tv-B!q<MCf2sW1%>G-EO!PUf^Msjs^TUx4^!T2k?HpS7 zRK>BxKBcEeran$yZ^I9xDc>Hn0X%1>cQ~uhQj)o{@;s`%P<v_ptxjDp9;`*!SP5)Q z2O+1B0h4Pf?@L6)fDbW(hmHh?^Ir$-6Tw}4rZf%asaQNdT$GcX6(zmB5}91~c-<Xc zY0&gJOi4A?y4El3_Z??QQ60Xz85S{%THB?D3)!B;qwmkqh8x>f$m4uzsQ1Y0x>v?? z+gYX3C(ohFRn91Vgq15SDe^{FRD!2xZim`Vjv75y_&ckyT!WKSzg!j)ArJ?ILEF5D zRnh+(SQvEv^l|N^84!SD^<cik$#c9GtoQt!hSKrbK|Jn=@eoJ_PPt_E?crU=|MKs2 z{78Y;@-n@m0e^n^I%VxgvZKY+%`PdU-EcVrxqzFMuOj(vJrh>ey%t1C@38}FmJNO| z_eA4N2I7G8Knf2MmRc`tB|asI4smzrmz0apR=dFRLFXQ<Nt(wkDN3Qmxe$D5C=7q- ze8vc@QALQ)`GeM2RGJIwXv|F?rvR`edGClQuH=0J+abAb?Do_3>8nj6M`DtD&~^$W zTLc=813#^9*RQ3n8j86eetFchlt0haccoXgGUUvM+hv$H={(g%`ArY?M=H1W4jC&{ z&X93#HHq~DeTkyiR0yn1{2<D`2Dj>iyTSKCVgWk$se^#uT_!aR9zR}l!O%^V^}s0~ z%)2FlQnB^L4%?bP@F;mjcu8f*<qH7?f$|dLL9F+Wzc$=TZ$WU=>9h?`$2pTg%wTkP zNOTO@@t17FVAaELN*7VlStEO2tP4v2^(*_t|ITaK;fWPs4go+pfK2_6mm#-g>#2|H z@>&zUa4!q6^+<y3P2an6Q-DJ1Taqn|+ngWBu$zDge{nI&X5q;bNZQ2h7-N``Jns4) zz_JE%?}&RdlzWv?xb#lYcoD58^AIpa1<YSrGAk@}&&!iOs;Jah9RZ42knjOPW^+NP zBnLiNfYQJtw@=N$)WpZ1LH%%!SLg2xBbYt2PoB%K(#MY(NV+5!L=|2F1(&-d?m{Q_ ziQ&dN;@Md8u@C683X{9wU#u|Zp5Tr=W)MRJX|)4ATbRv^fe0i$C9>0}v0bT;Q$5#_ zfDt8ic)3v*<b=sZ_1ibmW56wYU?k#H);A-lBI$^@<po}Ae+WynyDxZBD{%YW8QSic z7PkFXohXroo1mX1?5`!&Ft>ix!FI+RYL2@H=p$z!T}zjhXUm@J8bI?o=czU$h0S*# z-(eWaphbsZujP0=9E*Lc9w)~Lr#Dw$K{~^YJac<c)%|eFGD_8EA;A{#={WdR2r78d z5J*+AGobI(sz@jWb(q9%b#`|M<C6iUuqdkVqX!h{0aHxCl25i0FL0{qG04RK`tuK= z1>DJIeFdC!{80OV#*po3&=lGGAum@Mw}a+%JX|Ue22jMMF#Vdmc0n}TPIxHC4_muL zi_sM%OaXDkkuJ5t-dN0>2f+B{^38<hgSs6z5mDi-_QK`EKFe9D!!iup$1}WlM~0R} zNgzm9z-oZ&_^&@26fdLDa7wdoRw?@cWcBV1EiJ$&vN%a3Dp`f6Jw8v8&zF=n&wJ^X zvdPP_BJGEF!65)WkRuANdVxPsJpkJTyH`_MdcJdyzRt#G)3)s4l7@=f-{`!j5)uHA z?K~SQnbijheYaJ;ZYNNfPIwyOCh*9l(i#{px3pY^_`_YG5bocp3uW`f6BAAw0gjO# zph7&BmN2SOj}bQc8oD4)pNJhHg`WLUP*B*;RP|Js!cI}#H*cL)yz{teMYnJpV{~l5 zxL^AuuxSQ4V@3k_smHp$!8Dz1Tm6D<k90FGpY@W>O+W(|3UvaEhIdG8EezkP(~4NN zqQcJcy6sIT<>tjA`n42Lvn-@MD1+BFaQX`$|C@+K98>gfH43vk9<8c#%!zj6a-#9g zsJ<;+P!w)Dc5o-i$IPXe6W(7;nB}N|#pjMA-6?&!rP*7ijIo4Me1_@uG#`mgE@^x` z;mBmdbV_2l#tt&1?p>{ru3GWga%!SSp#xZxfPHAEKOlY(wbA8i(WegWq5Do~Ej#4B z2^qg{CX8;6!I4SXp2WSiTiPbJE*|%YB0AWf-UhL{O3L8=v@W-_6*tF=?1j1q`qJ8? zjUw?N^4^UpWpf^P<L}L=>;Pva&~cf+sgQSOnRxp3!CBrMovzrLZ`(aA3RTNgfsBqt zv##f4{(!5i_t+g5j5ba6paR>E@9s4Qfh8!gS?w7el>>z^==rYXJi0gg;a(d-M$3Uf zg8Ps`$)QdfNMS0ln_ZaVJhx9(Va~p?x>@h9{4ohetZ5i}dMj{d_l<QX^s#{E3eir1 z7)of8n&cj7J!sW1aTtTO^;8sHx#yPWRoouH+IrLZbCi;3kU1TlIgq^6fztYM=Y+no zRj!L+p(`PYtp=W-_$Q8P{$Ei(8_=VxK_K?kJJ=iN#P7M}>oY##d|oXpF|l8wE?~jt zHNONDi#}BcTaM12BfZS{ILm0azqbzX?p(aG8udS2l^$9p_%zBk6t%-|K#;?2hENO& zf0XFHq-gXF9H?9Fv*B_uxnH!29-X>}E0(;yRc>1baxHOAG`90f+Dez;)ywhb!<#G2 zDag3I;ZoaY6_t+ydPqU#Rqb_BW6C7UWUarWj@1bdK^ogBraHfvI!EvRqkXzT{YebY zU+TPBsckH*T5mTq!)zU8wA=k~!upAwrGwp$;HGVr{RfZW2)DoJzUAFSzq&53?|rM0 z;-STObl-qbdGYSwyh;^Zo|nk5Z&QpsDYwq}(+sLndw(CXwP)`C|E>|2<3t=~jtkB8 z^{H|Ub0-53oMj7)1^Oi`m3%%3KLOOfFIL}{eu`n{NWj`<!HZ1i?_cKSn!nt{j=}o| zp;$p(xu!Et$7nIRGWZu1`4x%bS|LGp&n<3+iMK)R*!PrDQx6)*r3}V@>BVhs{^g+r zgo|ygQK>AhSG5hO`qaCU!v9{uI(|G4N<c=2K?M`UrVvEKJHYFO6Byg9oLFiDo4%4B zOUGy`;4#4Ex#k$VjNR(u4TPaQ0Wd(~)d(kBh%le3k=2D2`kZm4u*%gF${AQm2l}fs zQ0Fr!HNUv1dE6;-MOir0HZKemzbxg~n}N?Ai7Ya`Y9xzWe*J1$6C{l-TWJLa?=a6f z;Vx~?&I+rmJ!@kHV$RKPM()~-a{)Q>3JS-v+FHLMSm~n3{OQllRo~qo)t4uR*x~R` zZ<D)kTh3T5FD`Znbz@{#-JD<Ty&*whBYmWBnR_!!y|eTlIqlz`Y?8;bg8HXwL{bK! zm&y>n%TaVpA6dK}10-KIucOAQbRU8&n>9IVET3=BsMpL1-sT+ojC#I4dCEz)#BDM` zPL|7?`A~2uW?;%T_~m>{eu5CEXPb?}M9<N8y7fulO;F$?Y>R9sI@heJ)25Uemic4x zxNs0p!foXNco^qaXQ$?pRrP$w44>Q)kRG!A(C3Ep2@*#d2U|DBj&*cig{1Alsaf$? z*|z6;Mlv!RStE-&=;%N)n}qG5)+G*W&++tt50e8!7ipB*BXvAm^joC%y`XTP8br+Y znzEKnbT`g2%`%yOxvb1E(k)z)!l?G#rXko$s0kMN%_GTJ|G8UX>ppM{RgOMt{Tf!} zF_LyCiP&0jQrYk>L!`~CNO$+Nh^ul_AaS(XT^TxD)~U(4II(>fc2JzhM=g4$Q(}RO zK+G1IwOmE3eKEm0=H<&tv!2QshsVkU``}wzr;^6n%;`98(CG#G>iT<{bXe~?@g>MR zjX6|Y1_eTr?Nmm?jC94IQdg&?MH<HR1h3<Z$CKwKc$YVIA^?5C5}Rh`Rwm{RA{{?i zt*5BI^N-50RW&#?c@>0;5aj)9#!X!=)>^-kz#}~NS#T4@<Ou9EiFxH&A#pJ$0^v-y zn*gyn?54=;1%6+a^^2VkS??QKqH4K85JHho*2U9lmxCTiz*LFBE!o63KKsOIlYIJg z5-+j`JeJ9OJI4uhx}%u@TfD(-RMH1e^Kse^3hntMbrAjrwdz86=$u;>*$C@c3%Rj8 z#|1Z_cGBX0&SAP=J&-|Qqop^d$&A6>Arj-sTeWwoW5@a%&%cBqzwoDbwhJ!u{3&1f zlIjn9hVZCe>RKh92>o+&yp899Dt^ZZpKcl|;Wt)OZ+zA%&w2$4VO11_tK<%sR9!wC zKKKzpUke4&{%<<2v(L1xt=SQ>$)`b0Goo`*8cwb3887ErwJLT>Mz({DunH0&4oIE* z#IEsu5r#h|uRiS0>-pt-5!MtSE-Ss)+IYP-;(n^L2+3cD%n%q@&L<icop7MTa0mft zDJZ#R$B5SM2j4(Xp-uhEONy(drtOEmQ)gD{0|v=P2!b~M1X8uZmjYEW)A&893h*(C z<@p3ewm$<P_H&v=XM%gTfs9dw*K<ixOHFM`RAt=wTs|c)d*sFoUERtGi*iHP#m=0Z z#89v@1e;a>6eR?G45>5Sls$4SYVzNC{;6nfvMD5NXzjX&cv<OomBh7R|1y=5n(uGl zu1qcr2vm2Cd1p*K{rP;|CY_~v0kR#tYiqLFj3(KvwK6)oQ9Vt?>k@y9x~(&)zgfad z%H&S(cjew}!ySd{Wv#qE&}|#OUXAawMR){hBeNXoJIW(fMb&schDgAK#=Zt6&d8bB zbbzr(%th<!dkl~IZcbkyiE|o2hO5S7bY9hUTN3CO5jjBOf~vOb0{Oq`3>MwS|CUlz z<ZT>Eu9eQ`hmLJA+OD5F!lC#I8du8O*w75=9|YgGjdzn8cadQYj2^xsZn?pp6sDt9 zj2Ao_7?{kn|2WbS=0dySTsdL$C|6?Nif-ER5p@Z3PNh-1eGK*(T~e}F9^8~(tI!zB zF5jBqXbecCqV}T9g1B}zt1}0;!k@B*KLvWYGj;2%!Tn&(i|wXls<#r?|5U&++kfjr z7eR)h3%)V@1M^bE5roX&bgHJ!ML|`Jpk?PxwEd=GR_Yl1>_UM(&X$pvTBjeI{#p-j zKzMDSHwwRW=6aVS!B7ajLm+5Kpp1-R+3|f48dti*>wSc%ui5K;FD3kz$U1mw%vDUC zsLCi#tPc))u=sOS`Eyw0y5mj7+4+74T}h=He-u;nK2KuN@e$QfJr&ZF>vvPJl^fR{ zeH-~?%37~5x#)b$@7-Vzl{+jGv8yXLOq2ncMBPZsZCLf3;J-#Da6*E@!We*i_X7k4 zh;u6RvzN6iLuliv+G3Yh3cGsvKm(t83Mr-D3{@BU%&+&(=qYHM*`6b0$hxvXRdTmK zw<LE5P}<=@%o?U~Vuj7QHQ(O!B_>5gM-Pp}tX)sO*|_6hxoa1DeyL~1(DtvVY^&rb z{C=xx&Z<rkh2v^nXsPqFTPUMH@6r$Q_rQA1aC`fUo-145byX^{iS=pxer4b+1YJ{u z!E!ZJC7xs?xd-x;&zcTbz_Wq8OSeB4*$e(X7km)<Ibq+LhGeCsJ!VaQ`^|9s8*}lC z15$eD!4y&O^*&e=$8)a=|L)(dYp2?s@cx}GWyg920E0d8KUt8eWuw0#sVnpaqhxok zi`k7GGYBj?zB}|puD6dp^qqStvTJK7SBBbMDWYH7z}1Saj1i5kzk7IZdpM~SUwpK_ zOYfkxb(uL;ZbaFdHNUMCpVt)Duy(#-<!LgVD$(ek$9Fu^!79C$@mayh?(RnH0t6Ww z0R3mGh~xa?7st*RAPv55Gg_twz8%ne5o7r0@X#I5S+ZSHs2+K~o1snc#T3pW>m_y2 z`snpWM1$Vjzjg6ah?;48!`mHHz}YES*n^W*IZjYDpn&~LX_XwP0-#RZ<|oh-8T;r< zz~~B65f2}{)_w4H=)qUno4LQ~(<cj=$0TDMZ3Nrr$Bv!<kZZi&P1M!bWsg+al|-_# z5c;9T)gHmnbZ!}cKN_i`Za(@_Zq?x>9BjIJOID8p_dB10ak->B>BwY_?yNdLdtQYC z2Y0kMP-(Xa3GR(s1h1@(ky>;`*-UT?2v&-5Lr|^chU?q)gE~>GiG}w}&rD4LR6mGZ z1tb9)348tOm6oGpVSIc-e_vl3y_hpw<VOE!AD8^=*RRz%B<#?OUnDA>I5V`fiqanU z3uM7-SBA2(vee=5;;ig!LHMvHXilTyIN#n4l!{bA4Gz0IrY|#jNR8Q#2t{8&uJe60 zJE?gYzWD?*PcxgL5y%n&m{#di|Hf45H(V~(<0(t0BOb946*E)e`9a-X99^tkpglfL zkCG)lGvwrMYa)U)h}@5t<*F}q9lM91r#xGoeBsd9Ct+LwQR(6CLPW=$pu#y=qv34H zOmIC{Cf$-Ox{}g|3N1l&NA5^}P9$b+#f~0)fEH-PdV=HU0IoV%tJBsf7+=2l3`F2e zmW>b2QGf-5HbVoNs8+0_Q074d(Kz%ZFT*hwb3QzbExY+p5TKow$2Shr%1sD()xTZn zeNDTbEK2q>a6GU|%9ZQ405}M_^dx?f=adiFTuCD0k~i<Q%(5PC&oN>(0*;+c=w$bL zU))BOo9qVrj(3zj1ec)IVIck2ROb_9MQ0*)V<IuL?|11FqNgvNhXT+4^QqLKEhR<3 zX%gZAh_cwpvhrkbZ8+fSvykRw+mhNHbb};hUtLcl2p(Ey-H{{WA*xW$m)4s3agKoA zg$xwbAkHMNXqq4ZQukks2?~F7bRVq&Mh5iH;Jy%Pd_WUO0_KE)%oxN=&-!SIxLG(k z99?oZ*|WY#08SvN;<U8^lO^CL2tz4(PB=mUenSX;peNk@b>x!<pFnB{tEXL*gxP#r zemw`;xitX91^mBV;FUkR3vLBtW2EtVgv1wOdmZc@6ERmlLd2y8Q4EaM(!TuPkEN%A zz-UI&K#K!_bV7j<$tvv4X|N_c9yEzvKbD2xkShZnTyU3gw)mXfo^S=#eIbs)Q{ct> z+i#$J1VGvsL*AIDuMex9h*VodfgrU-@B2L>wzvOYIw_!mkom04w)29=(69kfw&PoX zQEH*N+71L$IsTs<r{FaBAUwuw#F_o&YX=bHKwsI?D@6_DK7Ih|*Dpqe6&6oA^RAnB z>~O;5An%-12=r5f!kSi+7%gTi-IA<bN`1b^7<>TpTg$Y>Lx5%r#7jXG_-gozUPENM z2<nZdpkN;%8q_^;-O$$uzdf3yvoo3qV3PN@-rk46v@V=u{`zSl^EEEwi;-{^aD3X6 zmW0xmoNp)3dv<f$o<xj}%6e#-09s3T%e$;PgPjmTrIBb*3fR9$jO@SuWQ22zz%+qT zQj%N?YAGq<7#vyz9m@z;!3&6=M?{dH0LYg}>=1yI0^K+M_mnVv4*d?Tal;Hy4O8A% zC&aF^dSHnISrld)uBjj;%;ya(D??L%5IAmWlhdhqb`xm8Gvw-a>8pJ~<7UXg@5&$b zf~uaS9n1WSu6ZzhOtd__5=1V#j|h<qH2Y<2i&%svi1Xzb%Sh+NFz`?1QOmOvMlBA) zGs#DQDwF)b#zf6GfH8oHCCToVqc(lpxcQ}VrXV-BAov|vgl6_mDCTNNCw{eFq?Xv8 z{GPXr?8y@z)R7z0DBVsm20aN9O3O}6|Gtlso>xT^A+Mx*BPSiJt({r*x}=v(O@@f< zYZ!<K!DHAMK$!lWnnb?@0Onx3+*kjC=WIDX4PAY~2K`xSpRG<0uy`<IUr*NMiwTY0 zk4D#`f`BG7eSMa;EpYmTU5v7>HVE|wnvr;OB=chh4T(x`B1(c?gIDq8i-~UbaWx>o z5Q)mC``;JHH9);e2tirg?~~5oSOy9UJ1(6X+`k8XJ%-=CqH~hs=@aDK5F2S`Cpr4c z?OST|HIPb__K!_(5<*jpe?@G7bOMj_<{aoD7BhZfKQtf&><1=ydSM7Czqozt`nxNC zA~a!@qwo*Si~q01h|}pl3RL8}J5r-xCuFz?E^79r1U3y0LeLmT;5D1~(acR_$oJ#v zHr<f_4R&1mzl}|5SP=wn9L41#bw)4ZdzaXAL#{PZS+o1XghNyO-`!QkQ;aQBeLD0{ zj}2Fl79g1)EHqprxE9l=%N_gxC?~uR=uB83L}+m)^W<c8zb<}$ECV`!Zn6_>yddPt zpYEaKk&Ft9IIu$DYipWEB`1o~AOH41GJt$Ef_%6~{ypdwsWE8ZqXl*S(47*MN&5#O z|L^8(ar=O+B5te(_cqfwjZ7oVH4Nlvzi!qZC`83no-EBtQNaJ6knz|6*C`9k1~3M| zZ1T@Yr7C3s!Rx{|p)<p@s#;sI72u-WgaHo1aR+(-`Ii+c+zkhE*GEKv`vecWG?VP{ zB$uExiU<9d9?MQz_EornzCqCC(@g+1ume(NkPE?i`g=vyCLY2nUik?o`+jQ7nKIOO zzY}Td%ab?vHYkh;##|2Li?{?x;yYHb48qz!T~Z-z{%_*$BzA5)ME_T+3nr72{KP_` z2F`HJe9#M`@$ShvO{xw~fQYn+%}gXS8DIwp)7)L-`M&2w4=&C2Z<_NS8`Oo!b`lXb z=2d5CPk~TEa}T@>6?hrHVr_0Z5GNBsDW~S_(77A(&d>2KL#&OpdcJw~iIXN_?;lzd zmAP}LjRPh}OQ<mFI|a=@{Bs8zo8m*73Uwu`Ux>j;5=H`q(9t;`Er`D4e9mGQSRm{g z<<n#O*}o}%)AGS5@zcMb0~uG9tIW^G0T|l)EF{>u$(=Fuptla8rr|C@#}AIkq{8?< zrPckUGoMdftW50kS4bsB859VC&v_F6lRf?WvE4iS`f!tJKF|Z}^u2xVGk;|k1Hw<j zCictvs_G~~a?cyvG_eeB4F%HuTWIF5>5qTAKuwY9@uC?6@Zjc`FV5ZbJ|lf%-eoV2 zWNGNo@?lRMKm#5~x|v{2s<9Z_&L^HAPVM+%PUe&hT2QUNnRTUw4o-&+T?O93<@AD& zprZ+xav4yfj5(h=eRJ|1=(8kU^Y5_URubnK83f=C7|^Y0?1bS#KC$a*u8HQmom!sK z32H1pgJ!tk|C!LcVwN$Emi2rA3*o2Jf$lvOJw?f(pxqbtpcm#c*x5za&$;Q&0#dm4 z!@rZ1$#a226*_s}4}tWx)te?KW7nM*l`%8>zak{1Q-}e2deliYUNm}HRx)1a75 zQv%w7MuKQhoiKdK)8RuqV&_~jLWDL~5UI?GT|Q2ttOdn7Z3#K$U;>$vPY1wb*J-^? z=wJj%pNeGEmPCJjrZv^<pk1ui6GkyfB{~pR{lm$sLx<am#8rjeCj+QzI{&gIsNtjw zAfJW6Yp~-lUl;n@U-9Y_*o^mX{qJ1e#oa@`{~9WPml8A=HTJANF=01ef(iRL1{9E@ zuQaB|pK<m6?%pU(+^l+f>}|%5Z839gl=*zOIM65bzk-YlPJ%KZ3%JK~8eb}bg?JC9 zdzSOmV+e*Md?Gi!qdP<|md13_&Xp-Ioy{At<kO<R%Itx^Ton@%XuT<Icp57>eEKE) z)<iO+B@LVSiB!n;f<2fn@97usrI(Q8XudCsQ41zS25q#9o;i9#edXjt(9EgdgpNNy zR<E1y*u>Bo5FACbKEU*~)RT+|w4i&PgM1^wR<n!<e0(t7NhAwx(*SA2o7FKQ>meja zmF`^umqdq(c}LD^Xo`3wVQ9m<M{CKAp@Y+G(e9lgUyqV}0G4|MFe-pK1lu^4;8H=j z^_YPWWA_UNzgz3=ANYYRkp-cQvBBy2Vx0fj0LTpLVscMh=4`qqEAW}@x`tp~KRg2` zg#n6C9YjlWdWO;d2JIT0SE5jW$tT4BZUF+`9&=Vi1}9>8M?!ak8{o#Xr$4Wy;*@>p zpSgZ;|5nbN8z{>F4XLMre*@}?r*MZTzdN8P%RugP*z?<&OIy^0s(%3gY<UuSV}XtX z+#Px(e+Oh6n)#7iHQ;ZJ!2MN&$P6a;IsY^Skgc#P9d@}#e_k5*@B9n?ggU6Za}6wy zc7Dw`oDw{%sva1gD_?_RD<J#9g@l7s;Z$I4-2QJC*nsKGQy=_uHDN9%Q)kDc3qHsG zK|bz8s+>uf^S+aEkl^d5i$vBy+u}+pWD`?SL8yy?nmO5>A<mPzOQY@50I@g0(PF*} zf<7Ju8^3#M<JYuf9{%Z$RcZzeXX17)olZOzA?Pwcs0MLlmQ^faZ+MBOmvCbUj*Tzn zBq$17D9}kuaFrpfmjy6>pvI0aCbEP$@q_>e{{M?R|6Slc^;?{TK5<jnCW1?>1Prk8 zcE_5Ly!tmT6u6@2R9s0oXuzr7Omi|gX%*d_iJz~{%}0Ifo`ZRGUeV0|-v$m_UM6IT z3LKj#;7+fvoEguyQT(SkG}b)bh@{fgP13B9o2Ay#MqMYTp=tP<wF|h66o_I19KDYU zg`Tzf^%D-Ye}2A+mg}bd&(GG5g&=C71(-8*?>}}>pymtIKL5~iLX@9+x(mbb|EUa+ zNAt<@Ct(jS6;!(NT?3o_ekKo?Kh1lV3o)k==*b2-se7cQI$f+_3ostsKRbWS0BTC9 zT0uQI-=E{v)8>POT>+dCFf{Lr1N<rvLO+|S<4SBu2l8C#0q4uKNyvCE{(zF|Xcvj% zmw}`Rf|vs<$-xDXaq!AGe#JzykM;bz&bJX0Nyam#X_^YS#t!w%PZ`$J!S%E%6_Ho| zG`cE8X#s~Ce^T)sKBt@$kv8wA74NucPneSY6MK9{8@z;nXe%tbvYIO4g`#W14^}5{ z?jDcowUDXZ+>H)+gcSHy%(^A`$#o<NPv%AwS&a#CKl(c2BOTbZi!TmsV7W$y#ik)E z7j_FANR+uj;ZC^ApNGs7j35pB_>=g#LKICWumpvZ@b+N1*ycSDMEyBAQMykKEpIIU zXs2QqU4@gNh3dxZ-7)LK=+BK9mwO8MU-=Vyo{SVcH;(c$9+pzXrLVhNOpy0KSNiVI zIxhCPE_B_9mZI}sAAHZS1iw{;h_gCcxM7`k#<eIh?>KoRg?dfjquJ{9hbHoHv_jx@ zcIrrLCS7I?z1yJkwqKV}QrCL*7-mfW=GlU{U~rzD%!sTs5!e66)py5J{r3MKJ7kl+ zXGUhoi0qlY%Lo;+R|rR02}#Jx-Xk(YMwGphy=7)+Z@=q(j_&*ZeS17UkIx^@`<&~2 zU9a_gzQ)Ch`}EK;brn(e<yKvtSMF8USr~FWjRvDZcrj_e6|Nh_v<-nm=ZX4)E6%S} z8!i_A%nrLt|Fk_Q7STnSyxe`&HU2Gi7qhz5#{<0$E4H#l(k}yJJ4*bGA_p8x%CBi& zVGKoL<$zK3@UN-s7FCP&K!eN_MS|R;P_wObzk#jV%!O61)QERem8$pbCZ<KmptJXf z>_1Vms=k^lEu$OoY=sx^8llh>jH3aom%D*w0CbN*YER0}cF;8!bIS93hC}!h!wt`i zO}@i16So7d6s&d8X-BTjhDV-FzUq$rcaC;t&-*psj(}O47Cq^7B0uRZKHYvW{Q5E7 zKL5GjRJ8I~E8Ey`)jNL(i<9ycx{*JDv3KFvL6lpnXX#f8pUxAZ5kX8UX}7=Cx4~y{ zUR9o-7!{&yxziN$;a5DdTuBigRuMR-pWiU?*uFJ;v6xn5)sq&2S6d~L_q-w?=8u2s zx3?l_QZtvXvKyG2mwz?I<FF<_%|*C-{?$~V`Xw3t(}Q*E@M1`E(eKg~UK}fsaQ^0! z$dl)-i%+BLTXpl;v9I!<dy-=F67Omo0;S4`SzV8!-N#D`;?*(*Gi~ah%lsk`GlV*U zGv#Cua3qS-L7NCB3iVUL;AcM%Wd@vhIWW#uCH!Z>sO(1nYDZGnEiBndi|_g_F)p8H z?1xqU#)B!4F-m)%l9anP$5}DH^;5Rh9*8<tzkj~I($^+8Lc8q#N;;=PcN(QUt88a_ z*>S`HW1@P)_ijtgX45hk=mC21?VbvacROgc1zSn!ae2V`9Rc9VlTn|)b@R*x+33MR zG&|tC;pfQs7tNyuUvDKy7e?SY^RtywW1%+aXf)lA_Q1!l(lOUL6vOFqLft3<R76@& zcyy@oc9S1~BVgnF7l-3qG1uvpC-sn}(rt_ez@LRb3496^*mms)ezTIf$l>WMD(U+h z1cWE!E$SD83|JqqyHM$isrC}E+NIP~(z?jFti~$#w3#?v;B_FFPER%{f&k})cmCX0 z0G<Jm2JV4He62eBFRhUdsS-!P1~PY2NTbb1*Q&&?0ot6j4XW3Kz!Kg?uY$oRx?eC# z2YvAQyfOY$|8a`+L=PwzM~%W2Bdhh<-*@t1f`q@h6aWo+c~C@C`(Mb^<cH8+c(TAF ze76h1jx4Y`Fr*R@pAg>s1L5ps!B!3<(>XDPVO?GNw1G}eM7Rv`AbZHYu93S;vcBW} zC<0XT9a9S{C#X4m!Uo|DmiEJBl*zi&>e9Az-4Q2zr__TD>X=Q?EQtogL`DM-($IVT zv$H#eo@qYbH%6c?Cg!1^OCXR8l7RZidO$SE)M8v12V@XfUl`K*bH!nbrY2Zve;cO7 zSw)6yq2apZ%xS8e06?{ic|ZUP3W|*pZwE7H0+og~*1`hNMx<##X8!d~GcQ~<N9`Bz zu@Blp!*ehJk|E?le82R4yz%|6TeD~S#s%gr3f99#t`I%eRO2?{U_|{Ta_&J!QL}qs za^5E+fZD9wgdGh$ecpihp_Cly$<(5hzXSU2CPd$X00*|Ly?znP!ukee=HyT$3<Uuz z0xFL{j1G%()j!=pZ~b2Lf>ToCo?`A99(6W+>K0h#m+U$Yc=qp`@WLD1vHZH%eG}IJ zRF%W>7l#;|CYJc<te5I03y$NUv=!*0PJXWk1d5G>K|quoip**P$^8agd<HVum%ecQ zf;$=$(>_zGl`v#C6$HK~6b6!%oN=^Jk`l=ytd3?+ML@%6V9LnNmJJWMbuA?~tx)G% zjyi&Wl8-=yc|UYu2LA;rx=3MYV%gtBo#ytRXG36><UfDRfyHADvx4kiQk|x$1dt@a zh#+{uXr%B>jywM1t%KtRfT5m^e)R%<pWGmS-ULcdFiNe$3a$Xx?<>I7rON;#LSjZ3 z=p&EmXrHN27Jd)P1;I1eh$xK=Vv^qJTw$05-RkkGVF-jHkGI!IIqqX)y6bsNTwJH) zC_|$|#5@Do42LYSF_dI(-V{(5EQ<A<0g?!)qZ9liM18NuIa;d@>KTyll?IE8mKVCH z>5DPi4YOU}ho}cR6y)&-TJ%w@bSppsApCdCCWy(t)mZ(|9U*e*rN~^xP<;sGZMcWG zT_YE4v*rR)Mhz&?9zI6|S7Ew2xvIk3fFJ&3=-J$BetpjrLSe7BuwY-Vm>`&8jTCx3 ze?O3u=iu6{8c=5W<2jP)1(BR~;wq>NXyQR)+2s?m*mcxf+^tHWv@SS8TWmuNL~zo* zSrnJt$|`Z>U}ldpXVP6A>tBx{9sy7WO}CL)0)quL$lE4g0922kue&0nV6}qsDX94e zA~|NS*TD~MW<DF`_f7%r<amS>7~J(U9z(W-n5hPxixa$eE1AGNx&Sf&J-$5msT z*?#~mEfi@TrAL1|ALD^wQ4|;Oh@>HI<aM+F<7g!#02m73YmxMZ=6B>~F+A%CJc~$* zHLB}HK-Xj?_fj-N&Q02;4v66QjY3415d4A$c!Tr%#D`gHj<6W^of3`FW={ZJMG7^M zXnn_kV%T%{%G(8n#h}R?CXdXwN~gSe{LNNHmF(G6PTD(iU$A9!0Gr2f6h{3GJ7x96 znGFERX%J$jDUlssQh|4b-5T|idi~h*H6IHJi0JhmZ+IgtTG=gmlm~-=;nnRi<DUP4 zv^HRe9gs_tz5!^xdphsWV%?$oK(N{<JtQY+us)y4dNYpW=bqOa=&5N}xYr0Td=g0s zJea)=CzSVOue{0g4rF`IdXf+%XM2I0LCD&*URExEtO>C}fgpgG;lOfLZq53jz-o|G zJk02kiVEqo$vm|wV}wALvAthKFz*0U_2NS~0L$(Z1bE?02xkvtxRiIpDg}&pq2fjD zzIHIVJeZ(t@d#9_$k{*?F`s>}3}F2s_XRGr0okQ6LWDNVs_3e!1{PMxU7UDluMK~J zn8GMBFj@(KJXGd1AIkrQVe3&?QLadh+ey`OOsD&%JrxtfG5S^hf(oHd%`p&30uGMe zGVSp1ubY+jMqsE5oC(RWe<A)>Cg3lB))C&eSW;rpKfZ*>8LVi3+<=IojBwO18ty#* zVgEI)uB2%~C3<H~grnTH5|R8#S1ku1Pq+EnN_|dua+lIN<RllUkOtds81Nsh?$OOZ z50g0)`|_1pNTGC_$464onGS>?kn;!N%|}rrMz6O@Zw*ytn*#F#e8W`+47LEj$@SjM zjMsnnF=FFoVpm5O0r%&Gxh<WH_VsOLfUz(i-Zklef;$?TYLfIe<16l$EIBa8uye2& zsvdzc=mJuYID1jRwA(#gX%3KGiPWngqoFB>d?!-Ex@AT59};7q9FEt9yB-UG!bz|= zHg%Nlqh-dJ|BJ!okuJi?daI_AgUZ@^XJmv+r@9rPT>X3NkI{uNw);mhzV>al7Kf{1 zMF}DgDT<jbLATWF%~|d3m`h-c%z+lF=<5Q(Qx*gk6b|m`03!o9h>?cDZdipaae0^t zml*rlZUiJ}7NFy4$~w-c!?@dK!qNpw7qp@7hncnYA%y=HLA(t7!5Z~>H!kCkn+Z{k zUWEc{rcg-^%zWVLT%(ElWv_q|5I;=7JU+O><1;(YqRYSu3EjR~UUq-Scf=WN0vqd) zJPP+`wC5~Cm0XZ={HK*bn&>JlnY%ukVcpra2<^hmEaYIDva-a*!H3atX6FF&B(1)V ziW!A=C8{QL2P@D<*p#2?6(Y1SJ|?9X(E32;l8O3T5)ftiUm&COKm&v&r^quh5XJrS zeB=0bUy*5HT4j$jAjROXRXsPM{1y-(3Eq_cy;t}ifU^N<vA9YwH4BDAgLE-pG_{!; zEnW!}t|G|&_)=ZqDp^<oHp;LCViyZ#0}h~U0EZKD?@9ED#r@g4Hjf)$ytt(<@hL4| zIU%-?b;gqx3+$wfHZ90rX30@vY%4t;1OpBsA7W4oj9U}ZK*O2AtbH&lLg0!ai;n_X z5x^9>v~F;45+s*AS582hTv7(u7}80JS{$A=SsCRYaxY3)MJr<@RkfSdw;~81Y-LX! z7(18frKeEq^8(XSAj0kcslJAzUXgO2D455j6KaQWj3*G}4MnxCBFGl^@?Us81HzTs z)R*VJD+Z!uQa+@o%RTY9NSwY*%@sGu{H|2y(dTNjv&C&58`EAglh@7J+60DTpS=eL z<bGT^+H>v#yPNP+FnbwXi}CL_7l_}d@`pkKBl152)7q_(OJT`{GyAz9@2+%qtR7_K z5DfSFRkUrs?6`7}f{`4O1XuT}IXl6$HU)Qn0W~%69zCDn((1jo^10v>(9*kzshLxM zfXzZhZqou)9lV@fBh>^7Fe>CPR&PU{+%UjkIhC+HfxR{QpBR`14UIwkN+krfw~iZq zq@+I!DwOFb)QVy7fZ`VDL1jR>0ec+9ow_O}1B$_*20S1GWuQw2{Mjkp@dM{M?@3Ht zr`h34fj)_4gbv1+q5=Q>6-2dPwFImaf!Ujf!nE6fNrtaqDaB~{{QGivOUz7P_Uks% ziY@)eQ@Gk}^J0KsY0A_72=$7igZU5Hpymw9l#G3SIJLn8iJ<hAni$L^G-8y!ACLLa zWmd2M=So#5$bc7M<)T251j&1}+o0P;`UcW7-WeG&W_oaZ`85%Q`f-rs4x5^Tcpk`c zci_)D=Np&mwrZ;H*?h`{VG`cGhyyzgi&{QWupw_3o_(%%fxAZbY-SGehN0TDq)i|N z^7VPMd-zvkjX2xYWN<MHf^fEidS$>rxlnL{z_v{NK%WHY!~m}qN`caIwEQ|ztGpYe z3Y8F}=@75PccoR~hj@C7A2HUw%JO4?5&Q?wT2$P%VS*Q4j|%KSoJ4pN1XT>r5RXXr z?p40`RkyxKHG0Dhel5rE)j(f~8^WF$=0i3^^aDpBP(WS~Ek}U_A2L)<YeH^G%|PR& zya#E!s~ylNa0B3Z>XUyuEOn2K2O{@dYOLh5!6-LC<?8{`7gEbIi^^vpv_MINUwuo} zOzRA)4G$5W9c1N795o*U8Xv-yr^?8toemeAS?IN)3~75-?NC+aGzg6_uDrxI?UP4V zIV}0$nnZ!VyM0^aAV9uD+Eh=Rj3Qx?j3z+{@*meouJ%+<fU(h`@+GY}!ctK%OjUvj zcS;-<=zD>n_UJ8YJw4D~3nX{=pfs+dk0KV}fJ+&G10=Q(rvUqx?^QsN&}ya7<26L& zUL5=aTq{um!3Zj_aHk)}3a5{(QrMGJxXKIeSC#*Qs@&mV_!^jbASV+|Tl8Mw6@S0a zSd#&udm*VLL`o&0^`dnrn8?59pW==<g%U)*S6M+?L&d$v1z@V|{1gyrHxqf%LNdZ( zt3O7GVIOjy=5)RKRc(`pev%=SX9cK5_xBIpXl1sCpoajaiAV*Dws=H$=Je@~RZy<l z+JU)7(A6K(hDa4Ijc>RdZ6IK=#GHE4-`3*mP%#lsdF)K`(388`=anOM%LqlQJC+%H zskX%3ZT{9hzgyQ1F3&={68)s;c}8YSJhQMOJvKf|(whzm9j}>cKDPcytVnlv#}cg4 zB`t)gACyu4ApUyCu?&>`*zNk$xzREck9$7TFL14nUi|tQ*0g{Whk1)&4iELloqj<d z;Yq5F-Gk`{vz{mRTk{ecIV?4oiLzwv=l+{sr&I2YZC<j)BZuiC+w&-2eLqmyZhXVo zE@eF=eB;ydLefWSd0(EQdG>UxMu&UY<j9zd_5IG{UW(u8%nwHPOzh(C4oBv~rc3DQ zH4^U5wxZaL_2PrvJS+9OPYPHwjk0GMny3-DPmND^L>sncIaHQ@AB$UR+?^2Sg)CT! z&%5|h63jt?wa!hOv9iV$VC}sntlJ@)wt|-qi#u@p*s?6p@=(X841bd@gbN;Wl4$vP z`f^4jV{8{Q(oPuMn@ey(6<n(^(?|09yhL10L2z4&dFu<Eb@AMm)NFA2mdG=L$rAJ` z{fnHQ9Zw-nkEZoGI<T}Tl4O+b<3@{o(<XowZV#1Y!7%x3zS`4(zr|m(!&38}K0Lm6 zIClEWqPKu{)!7Hn_-hHD@Z<izo`zKFLKJbQLqF4Vzq>ncr}4TUo4=dzk7!_e-hLXs zb6jsWj!q{&>C48LdLKs^LBNoG)kFwBd;p4DML#T@&1kZ8<>t8@+(URCM0kw@gC<?T z;D1ZcarNsQCtb~ApH^<!$LU9l$o&{?tXMZgJ@wFBUfZzaIHeODj2vmO!@FR(7Cc5< zblx@k?Krr8>iWZ4{4ZS;9$omJsYHDnv>AklUw!MsB!Btba?-H9eB>ASu-0RHLw0fm z|Iqz<wa4Yx(<zC`5%F%SoS8nIo7VcDw4Zf+lYLtYrM?52`Z(UNLRX?FNQZ!;gc=}e zU>G)W?KssCNNSbY2!g;Ustqane^<FoPcJTKQTbL5cm1lzB!jY*Sq@^0?lC0YC*a?F ze%bbRtxC&brlg<d&%w9F9hOhx`EB?PO0UumyJskez%3l0jdd(PE#F4tSTZi!<5~6F zqZdK@FRt&Km~SNv_@D;>bVzE#XVy`EpZ>TOoRU%W<Fj%WoLN3l3}w(_=?UesdiD#2 zw%R`c!^rUVilq~X+qG_~<>_w2pO&YIMKz>)e#2#E{`4;SBNUp~W?0H$UfKp91h@=t zI{$VSAR}Xz0@A^N>y3oq*x=1`Y%d;B^0HAML6oTu@GI~RkX8W;fVH!e0YhV4yw{kD zsJ0@_cY`u{9<Y%AAL4~15M#hBulNnG@1W4%!;_=jqdw+-9Rv=;G@<M-2fRi9A<`*% zZs?yz_5h34Zi)0Tkz;ecr$4^0`-&-2=01>ClMfQ;lPrPk8x)a{rX%ZFTq5VM>0B8& za2qTDY&%y;=>^L7;asCNI)9#|ynoTF41Tlb2mY*ShX7bAsO<_0V@EI;If$!)7NEv( zum>YWi$b}jpj0o@(69q?@Mb05wfj&+0%v*;Q6Nys7HN}(0AjEXgl31;?MRO(LHM=+ za!KGTVC}Lw0OACzcS;;r#8{96kKF!I7pf2J_4*t5=r!>OKMwvs)Hm0Y0%Jp3{`T9J zpoG$7;?y;;#W;WTK>q_vte;=D05Wd}XNvw;$dJyU2h7Uh2y&dF7ZT>fc4BVc)GGBV zJR2%}V}}k3?wvS$D4SID)!b>*8PpT*d|0l692Ch_v^J1dZp)KR%hp2CL1BHdTl8{c z0#RQg{}L2`y`*h25`?@=rG35u+Yo3agi9dN^8!^iuZ&e^7hsEC4roYpZ1Di2;vSHy zm6O|rX!!v-Pf~7B4A3?%jVu^pAh;6ALC+;#dD`Yj;R{}!5_Q_300^<Gs2`BKN}-c1 z30$rwvifP~3UoK8Y4tZ*#g}PY4~uZ@cJD$lB^<TwXxS7vwkPVyAq2>Z9;nzVDg=p0 z7-pcBV<_~kdiC%QI94AhrPg^9UjF)F)9F<!KXhcE;|rWv6PX7Jvl`hV0HyjTfBowq zY>#7zj6a*Mt*j>k_7P2Js02*RkxoH|%5YR@qGInY>lDAphfUxY?6g7CC^2(dd9m#` zZAwc>GL|sGx6fZe`tP^Q1M@Q;Bn%bC`h_E&5T}rz;JSyBtOvT!^yv6z0C)fqDxWDb zB*TqqU|g9XYH}TWvUO|rNh&C3cY`nvDFeiGTA;fPBdaR}z=-X^v9D7gtns=EYl4VH zAB2al>6zwq*Sf1n?IuHPKpKo6)p+NT^N(ndD<+lbMWM?BdjV@j)`7xs5NM&AbN5VT z%x&BqI0Q{|Z7|{WK9oe%B>kTvFsMG2LL9Mg47o*^;oOhOokU-z9b&QAS?8!}Egg$l zgSuB3OePM>;(n`PnNM|XMzl@8f(S$CmL#5;T^I#5;wxasC5~r;LA5L$P!3p_6Wrhd z5Gf3nt|EwP+);KDh*QM>j|AIEt^!cJag1;$LsgVXXoK{SPkp|Z<|ZNzCjphkH3FHB zAwp+Bw-K63>xC>qg5hX_Pk%&yTG{jSsX??#Cnd^9u2`&IgRfZ#1c#UsAf1AQ3oZ_Q zUmlJ5Nny#f-U6~hSVjr}st0U28uZ(eb3=s)h`U7QdOpGwket-Q0Q^s1_)7(k1gmJo zK?@;hFgesGu;m-euq~1!%1Q@QFrEP}fwYbcQu{MX5$T_CK>!%YF$8rBsp#{eihcNB zWOw!11uAO)ce04(Tg+XbHN^%?(Ut%I>%hXVT5@U{FynXqTP#>rGw*VPo8w^cs6Ein z01Ep+V4lA6e{vbp-;s)X%Wyv~&aJ5(1@QzQ08}6$;aXCQ*i4IJy)Ixc`C)QM06&Y9 zr2mc!u^h(P>*oKeA2`I;VRU&lK(?CNuW;Uk_@^(9Zu}E)_Q)H)MF<ID<C;R$+H|<| zUb?4SbqWD9)doRm+gTcO81of9_(vQko|vSj-=BON3T=UGEI_6|mb=7_HvK7ZgMcX( z5KF2qtgHV4lz<3{y1$qgTa6x5<Jg^U6tpUV`^YCov-T`6<G@f2NQ)LI6{K}wbs&qO z31u<D;m9(gu%OC;K^5y1AJadI^sb2CBC<ov9z!XT12+XeMB+3XBu?X#xTpf`4eWu% zi0zHiLT{ngU8}m<*yFx(Fr*fu(BKm99v_yl^uj!Drf?4p-l>F09e^k(un~x27ANyf z%a7eV9%N*|?&zJoW=B+odNB?Cpl)MPkggN{znKg|Eo7*#X{81l?^ho|u7#o;l#+qq z9#n!l{I}ey$q8u((<t^gP%jR3AkG^u5w&Uy)kjdEYz$Y_;4c0k`EL})bmc|DqFzJA z;3`tbG3&QX`+=WjRt1U}9a9t!P`K7EqGIe{0s~Po7RrFsV-D@dDnSF6Uib4)=@-td zKy5{aF1sVedkPd<jQ^XzV0ejK-U6>!R|mfW+YN)Iv1L*S;o^Z*4j;~}X*k^DEue0p z8Xnmz4y;Yh5xaYH2wM=sIllM)u&2aO(1W84ez!Tf0TOMkyD=QaPPCaT5E}b93MEh} zz|0YFLNHQ6%Pct=@I-W@MJ9v~88Sv8{xFZPHP8E-Hk1fN3~Ig!3HEiwGw`z~hi9NZ zY=Irz^xoKT?~meT52XKmV65j&qt?xtym(NZQU7eV(ES(H|2)>*Z-8p~NF^FTF)shz z8xV0Wjh<acf%35^en|}V0GVsc5*h*-^QM1<Lh3t~E~BRR<^T(eQ^gwTv4iOkkN{o# zJPb0qb6`LV@OFv{$eG1p-f=smAFq(=3iFPQ<0yBD5a1m|_$?-usUb#%Vx`wE;1TS9 ziH-Xnf6zve6<ja|Wr5dUURDW%X*vj#v;G6P({OlX-2Y}Y7-Wz~1gkFs?mjkuCars% z96?_Zy<0_;*+g4|uEXe6kXV9%1ek>^4a&GckOks5{cz^%A71~k^4!oq8C$lht9#f6 zLVS?xn&kRM+4L@&J2j(o3=0vu;(?+5r36=7u7E`&ren$ml5W=ef0>9uXfcq?!>P=f z4}=dD6VOh+$S8aT*v?R-d5)SX+Bgr`ex4H3$+4Td3>eb7`(P0?s_vlp<Pnw=DQIH2 zDlH>I)_O5CQqGIryC-nv?%%b6nmouPh{k{bD~<!6nTH5{p}e=yZSY1b|H)M;2gGAY z8l5lMP&2be0~M(_3y!$21Kz9}8mcLbOfO?%zGhVs@||Xar0S5yyn+3yE;LQk>4wva znoa&0NFdPryo6i>>1V)4gEXC5%Il2(Ei`)uW{patUu~yrMT3!^e$Jj?-_7#JA0c1f z^bVo)$(CoXZV-u!Y;7P!L7E46z<R^RASgt*XpK;j+zWjswjm6d4JW3dAuz4qm6a^^ z6SFzRuO)6>2_uMr5JEIJFrZ!?_-T1GsnT$#u0AK=9};p?-9G{bNi+(Yr<swADq0W@ zH93GF7U;|`DnzF@ED|Y-?XKbQUg7s@ox+tI=k1MF;-e_&Flm0!>3|@8ds!(_Xl=k$ z^fry$!76J|k8o8_1IWH^V{q}UwSI}t$!B&%9C|0_5wM*%0XwEt_$eEVra`v)APaC{ z;M5P2jov&H;D<UF{`gDgm``{>q_}isRviZ@E7a=6pXEpraQy^T@wJ75tKN}0Qy2~! ztJ82om`gUG#P{1Xq47pQTwKy}Euror5bUiaL3%x2HOK{_Ks31Q)uw)i?3B()$0bL3 zr0WmBpJ1-THh+N6&jYb6!W#tK6!bz!{zp@K6eHOl904eIRFT?=f2Pq1g;Y`2hyosv z-M)uH<Nn`h_v$HFxQ18FfX3bbKr1UF4Tvdz7X_Mp7h?Z!t^@zd0JQ#KAua>Aba}1M zlx?izpu*Ckpqx9aEJ`x_RjNb9Iaoxq;>zesapg#bJie}xRVfgw6Ju(WyVr8r=?BDW zR;}Q@ASnDqWSs-}<Nq7=!kLk~fP=-ly%15UCIYzHeD)OGQfs>^NC6Zf+Vt_E<3*lv zX-ru|Diryq8D6dLfIr%b)$a5z#l<I}bAX~6JSPCf6}Q06=x}hJanYnrUd&p?>78gx zP$W;<B>nfQ0&nD*xiyc8e>oGyx!3K*MHQ*@Z~?A07s6{$TMI-?b%cSMc5@meJ4p#> z+SO-Zwjm}A>*`gjB{M_ivDX73Xk?$OO(4NEF@+#{uW5m)55m_Tv^jzHgX19JYHWc! z)r`5)0g@-h;8q}zScvgE(i*V=auurm@v^c06yGtka~yUtouK9H=`ACse2ryLT84l% zfYkV@s-vn&TvaKap|_Etp}9o>fk*istP4{n&)IvcJ|s%UTZZP4$>#CqVOu+ARib?d z^TgJc*LA9%N%1yjBM&#XUh92cn5bX^%;Ek{-9bQxtw+c^x`O&qDWBRYEy8zr@h~<f z@GoOY<C;>FEk=*ZEE~Hn#=zRECqExi_#BMW;u8@OvA!-TXx=0ocq#avCoPFY-j$)z zgubq&^ka=XfdsE_Sbd`p6|Q20+>baOj}SRI^-yec=u4TH%9Jh*&_avUR+6fl#T^-& z^xw(J$??3bF6)NAjajg3lQ1u3ylO|dzqNUPJM#QS*;gFcc2^c^x7eoWI)(V~QhR7# zJ|Bu2cnthgW)u)eE181%3KrsqhK3rWvcY+J!)fYd)4Xj*b~)-~OC#>OQ@$X1jHYlD zA`lUVQ&fBI!QHq-wX*nZ>;B*X|9`$H{ma9C&kcqB?y)Gkw^MV3L_}K5#|7~$sIVtD zOr%9b?tHA1b+sO)RrnPRzu0)Oq7(OB;@RPoREy0H_RL4SOKdpdq3ccPd|-2kh{hCy z{W?zk6CO|9_NNvgXnbkrPM3KiNyj9Dbuu2Yeao<WKmK)SXyP453@$iIQ^L0!{XG$c zIO7K^j-C|iorfC|E3W$NZqLR}_TvSuuK6X1-Tt9P^zNZh9U23)iy1<UatjlmBi~d? zt@9Bzl-zS2nPx|kFBUibRrK95V@AXBP;r7CrbIMnS*;w#HD*cnqt?UX5W8s(mi5|v zlBhM<R~5&~3*$wXzKr<JwY-nwKO*0Q{Tl$UYC=Of<`E)|*I%{#PPEi3d&)ux`#eOR zZ|PJ12!)w5|BVQm*8wFBVbh1xNg3^-?YGomB+xro-bh!LVwDkOU@YSOqfr!0!<50w z!#ouk1G}LTn8jU$ZaFKRJsdA4vdVTVNJ{C~brwE(k13IrK;nZQL$bEp)j_3Iva$i! zl2uU&-Fr>A`a?etPm|9b#VZ@LHjf%RE0Wn2g-TQ%%v&ZB-Xf2|-(XIb7=MVWeJwPS z);uomTeUasApQo5Ua@#E^d@vB(rA(4Mca+6`D0Hf)|BdGpAw(MWcNS$^t9j5hQiQi z#+SpSk*@9QUrh8%2X<TjE4jC|f5axp{A{Fwcld85N%3uwz|d$neDP9;m!fVjzVDto zs!|qdN4TYoI}fQb5*0DwtD<%_c?HEpS-5tZ|E{?&5$Y#t`z9_l;)aNAwrQ;B(7?~7 z$V1G>Pr05lGT0hmD0XpUMUM}kF|kvh#BKDS?gbC$dak<?19>xkguyp!weMISJ5)t7 zdB<M!p}v(T$4yJ_v1`7o0}6e+yAzI?Zu_=YDSl!nQ-0zuC;O^0ZgN)aer`aRLPPT^ z^ORTRjRi&as<uD02T$_K62ElrBg$hrxHN0uK9y~>QW|nn*Rx~b=X`l68_cdIztYgu zVYh+n*U?`?v_r-}_rNZ*_mF0piiLB!GMwReSS?ehL51&6x;OpLZCL|IP73m$eX9B6 zCUb*a)~p_XV7c({Pz7k=fhB7EMru-Bm88k0SkqD~?Y1vJ*G*StSkh8o+t~-xW-LXT zfWwK3Zx#HOrTz!&S=}0P>Tk)K5Gt%If_?p{(9*8+5o;Eyy9wjSHTCY`9=$c1&%<39 z&0Kb}TUeUa#h<0-@;HV?u?ukwJ8P94P?R``-h^1PzhwTd%f3WG_Um)O3zB>o{yG62 zyWQ3sG5HO2uTUkuCSpR{cCjWISTM?;{o#)ytv9Wob{C+|0E(P;qQ!kR>S(A9EFwn# zg&vtlh`IO^{ZCVjn#>g&UZe*_51)EcC_h=}3Ur)YsJ+~@fnm>*!}J&rW68-aTfV;@ z<#T45bP%b%P8W{Sc#P-$(D$}U2FY!bf9k+?+mSH-@t);%=J>o{0sY*c&{yA86fHM= zIh8LCEW>_^53FEQzM*AdeH0nl@F97+z1v{5;_vUQI)5cQPQoJyy~^mZTHx&+!2{`N zw#FV^VL0(vxONZwP9Aa@8DaEQBxu&T2Mw3|tV5=R!+vGjHa^(FlcLJ?aT)5DJ9an8 znzU7Pb@kJ~R9w#v`mu5{B=hBK#N}~#%vo`9Z7tQrQunv2JFaO{&zZ&WXhP?~Rb_i$ zm#8@K6*DavG6v02;~|*}Z63-GCi{8VMs1er>wGv;@HAFsYF>7PDzehSSzz8)+0xEG z(d?SEo}C`o$ktaN)l0n(w|mXdD^=OA<q94=2i8gjcREbFPF4x`8OqexnzCImI2N~) zV6##@#=EfKAni*9DQmVh$4#CP2MQRxh5Q2Dz^Ew3{t>bA#c&QaCVsJLM5V}7p!(s= z+eq>U@ZJv(UPfjr-0NEE!_gA6xLRhSNTKZQ?D8V+qZ_<I^V_CQ$uFX(enM6p^@ZM| zM@ZC-2jJJ&D>uBX%9UU~zIRDK#HD9dT>p`6z3uJm9@#PDd(Ga1O!(vhp7I5%zD$1o zWmU-+in_LlmQCmRG|`VwrJhlUy`_BBOKx`EV7WIU@?9uZ$dy;KZOyt=<-<;H4QxR% zGREoqZLRrsoq(0MZ8Hk&AP2r9D@hY<w!OVf9NjjnO7iXZNNd4${7n27K22?XI;9hR zeZ4l?U-mt{3aQoU9cCzL%y1<xSdu9({@FGf^q>CalE_onoeq70qiEGA--UM(cnP6Y z@PAHKh36)ti_5G@HOe$)`E0{;w<(Wb2(cbT9d8D%#Vm<VQTiH&c4Aelh05!)oiOR< z>Y}e1rt=^5Ouux_v%j9dDR=(95w3Tf)F0NUo$+)|hLq<)C?0`i;QGb+&*Ny-ey?td z1p-Rc^a4ClaiSq|5~S`9z8I?Tk0T~j<6u)%*K^;&&PAJ!Elj5yqK~{d*LJ~&4j-Qv zSYmVBl{jhF+IJJ#<SGZx>~~y080cqYRnYuk&F0`Kf!hd6U~lv|WpMJ6P_oA2rOY$H zPqIJqc)<jypZD&lCvE?F!}~jz+)PgSF`Iz*UQ?6!)^{S$DU2VBwzEZYqy#gJj0m@Q zgTY<7Yq)F1Sp0S11fJyx-SfxY0ejD*#YBLEV*OB3z-W^Z7edy=BU_hpp0pq_L`QIN z?m|fIKOQX4rEfV@t3KM`DiWsJMHPEi{CD?tJ!5R}dBk-8f+HsU4D%y@GD=!j8L^Lu z!}m@sx~43TjnchNuFpP`qDNt2(N365I6tlefZJw_sxU$9WE|y&6m6M>C7GEo*we>v ziaYJ0EfM!=JVNy`^TS<QdRTnX$MuAbq>1O=gsEb-m1(L*8*fP1_OB{h!&+O~xMI_{ zJQJQ7rFj&!4lL&{$n48MpJ(0Ozes*8`@Rw1usHR7I>m6;Ys|vL(Y(B->A&-z&ra5~ z`ad(@xK1DWklq(Pe@$78S!=EJMnA&Z%2~aGsb%eDHp}QRa7k`=ClOS75<IQ<&e^mA zf7f+{1b%0&gy7kmNc%KAN&MB<iZGS60(O@#f{dh}491BUXoso8mf-oPRJY$+By#ZZ zC_39vf*sQ|8j2cnqh8j0>k);zQg4MDNO?&@g{OYO2@_+ub19UEuK7#%E`j^*i1vuH z)3^{#vM`>BsW&#e?=frH$$@%v!fRt*HaOCeCA`=FT^3N>pZ8i>+RCbF@-y}Ho!xZz zKd4`lJrw1^LSZ;hdYZ$M9P#Tk=r~?Fo~f+}#>t91@(s?PqGq_CO)a)}e-=kqA(kKN z&+(BWbuck2an@Fei8TP$<~n3;3iAThUfmLwpPKmQWV<5nsMF2j1a=gtz}nN<QO(#3 zQCQ(ex37sO1Gnw?z<tB~ZpSWP>fDrN(B+Cr{z?Cta)(EA2UEY$R7H8&tjTB0=?33f z33sJ14F#~qzq(uFLDr2YdV>drWu>GIeL3Ia>v6_^<jVe;+946_4d(`7Dhmix+XIQ4 z$YS+4{u&&`#l^NLHILVK{LVXIbkrc)IV5E~lveJHZuBaRu8go~wmp5YG~>ba*JB{X z_q6ol8y5e{FAZu+46U_)qDLej*UVDt^fU@swr-Pa#WQo7<Lq|s{6O#uctPOfu~E5A zBT9H^=-PMh`Ao{S`8>L)WrE;x-@8KUK?A50vf@T4lNoX*SflfQF^$DO#Ke93@Yt@u zwyPkjG56YW-J2-)Jc$dK(5>S&_|QSk_2DP7b`5ZI@ux%<sqomneU!YHddDX3#roht zhx!V?r}Rm+H5r%%6}m15`!dTF)BM{#0rUbm>*^;?`PViDJ7zGTCRVaDN6ZDe-O{br zAEZmkgoudV@%X(sv7t#6%r&(f#1l7nn2tz&yBUn;D<-Q)CQ3skr2b0w*Q}H1tkaRB zo$<$s9!87q8~r@09wDEctgJH2iYQpK7XvtFY~QwR_BSgttZCN7?oGK~+bmo4#^Y6J zdEdxcgzlh));5v@Ysc!3N@cN06cuu$t9{_-6`jFo`|v+#sF=;5BiS)}@IiZyO+F7~ zZNJh)PS?+hT06Z@hGOTJVdT86OUo&C{f6=){l1HRPwO%XC$Q)vSCg+d&8t5v%8*mL zZg+7hej7_Dgi496P?#nBBjsOxuIwebYXMVOs-<4%RCTiXvhi##1Tjqh;P4MfziDmQ zZ9lO7OYm9=r5{uJPO}uTvCa=JJKrCPZ5RwB(l@9M`zlr?eW>^o^V~rc26^nzP^PDe zD&}+j45}(~MqjV5!kN<-$_7AGoR?1#8*Av-f)^G1Gta9GKXyJZ-|qA7QHtnjou!PW z+ONR2wV<{n^Jc?qPx0~YhqRbk7a8ldR&s{lR)6&?{hr=X>kC!bC~7V1>fqY7XQqwg zn}GK$=#!o{wUeCr>dUIR*LqHas$W)>&UK?YWT>F#E|*zS<wXfoO=_3>!ZN$FaK>=Z zKc{(-m}lqQbz}VEj@#`LQZqx~!(3-4N{LeP1*4ohFr<m6OIZQbITAiQ?#ny++m_Xx zO~K}UYa%!qE&J#=tHq+Aqj>aocHqd`tC1u_>nuX1M?s%k=HNLPTyN|SY>cNGrQ%@@ zUYIF&h+P}$9Vd=I#+q{d0n?W6G{(rZFI*HCH>sQqdXmk*FzlEKPUhXa?1&S2su}i} z&GtARmJ^q0XAr7$KVW5qAj3>*cDsdfyaJ`H4F1f&E^gH}?JG@L(e=?<GM6>|_MRlh z4?M3XD>@n<(?C$@wrcu$`zU_x+%uIN++30dYp!(KpIDKZSi-(AU>J(Kzk#7#8xbPW zcO54_207_HFFo#Nwh&!E)%*}cY??}7YIaWCdYkNfVotiJmu%7>?b_9W!>3;aC-XiP z%+%IKywlSDW7b!FEkPdd;YSf?d)S%w+j&8hg=~(v)^>UciaTh>Tc{bqk5J<idF2B{ z_jN<x@CH+ek!Bc_99d2}G;IVwouONqqJA`5I@@687jVas&gvdY_e)fUZwG>4fdG+f zldum2bz$t9GfD_9NpJjoRh$M)vv%II7R(}Wv6POm|8TmCn^_I*1lFPQ*qvw|A&Un_ z)>G_4A@%pPRNVeJi&ohir<NTD#k6yBS4TJ05q#5|Qy!~f>Ok+umS+5IfGTcY>33fw ztR*1R%%^9QFEsHs8$AE`&meXuPqlQ-Z=5uf>V=+(bhH?LOE|w}T3lT7*@<2JRs(KA zmar(a#u(1qiv`@L>a{sV=yAkMyyOl0)N=`9B$OY*A9FnglEWfcZ>rX~E^u}<<=Gyr zxBsDFxOfaJ$$$TuU)v`Dac}k?e$k0ef$3i-sX0|G+JA9)<KFIIHMXlu4GIlr8ilk? zj3p_I_MP8lnD&EP$=h=wPhD5@Jwjv#ivVxXqd4+ObF+cE(|rWxmVs?wY!dF`$y)jY zPulK|_ZAH&oD1WX`I77ic|avcakv@Sg)vh`)*mUFjM&TQr^^Or7CY`E=>=uP@K{pL zkjjH6!qKVd1)W`LJK^fQ)h!m#BKe$Fo~j+6O)2zcdbuwgn}{!O@&-JLR}Q`9g<j;* zpHNy5;9Gg%F73@4N?J|*@K)XR^VH|4Mv62Ro}zL+refzWNaUAX?$sQcavV-!iGEb~ zabQdfr$Dj(el32!t>yWFQCexKjU~h@WT5k7PZA>xua?W7*w}apZ=tH5M7?ER5Wq4T zcFZQqX_e8ezKe{oCdn<}q`6f+Wub|);JF%{Joz9dR-rH=qE~MYo5j}^KTi0Kzuy;_ z8;T}M6Pk3;e)?NCC4B4sKd&M)6*K4aw4Qn%jA;rAtmD7V`=Jz)>YS1Ho$`sa*B{o< z>G}<Pj7~BG={s8z6n&CdyXAebvFm<y5Xn#p$k3@W<N^ntov$#f)t!4hm-sxwFobf3 zT4?`_8WzFxEw9%(^NU@QLhmEqCk5h!(Z#g~cTuSgc+^)$yMN<cdN;_obL6WzTjevF zv-+0XN6PlJOP{*-$%pLrDYpI0d^c2G(gS|$ff`K5dq9Z8{}?xB=3;nLsd;hnp6_4z z(B0lwe`jAwJAa;n4ws0ipZl(t#(s-F6k*{l^Kdq25iyrqc0_we6k?W=>qm3Y>t~zG zu1hqKXFZ)x?RBj)I-iK9b^cAMMbgw9(|*_RF{|$(&CBwEiSIuvxxvW=+|N`n(rb9~ z5hF;-L{9xBwz-Ow{e;YUpFhKW@t#ek4DDWVg5RfG7LzWx3pwf@A+nG@Xrt!9y5J`G zRWAX7XB(d?bxw*QGKF5!M}9fW(P>fnrUxS`<m5caeS15SV<To{)-@ORL)~$Sh1ySA z_g0P<yVG`27q{MqIWRbyVMBq3qZz+$iGyok&xgc>*9R@Z>EPT}L|s?}ex=p1YuSBA z=gTJhSx6qEAr&Ng<^-nOs=96AZxoiKU7n0Y;ocZUFoi@I!>}9X%1&t5h8=ruhMQSA zWP4(WC8`9P>IXv@W5cmNNCFmAI(%f$ft`k~FCa?)x;nDwBAXN~rzl{vV%j?{44%&k zgSA+k-xAToC_C^C(_R+MAFl7yB~$uQtMS(Pfu;4*0-H6RiU#E!uct}xu|BUVE^OVD z*}TxcR?aWQUu@Fb6cA9=yU{B_f@6|LG8PH;lsd!HF^_}|_ON!8R^@kDdAjcr<6hn7 z%Ve>k&8LtbHBL{=;*Gylk4q#@byGq`BXl5t(PbdL<|#_kh7>}UMp9Dqp^fTH+vWQ( zX*L)+{8j0=m`E@RSHc5KJKx#oJtkAu5t5cJO7a2u#{Q!e_-pn~I%MA#oRiVr@AHdy zRk%(0?1!8<1OS>%)!4(Mw9|8t!)kBE!c$337nh_d=7!wiW)JVNNy|p?!NEkoV=cDJ z#f!R32=CZhAGJOh7-Z?Si(c6_Kvne-Tn*6g7hIOv=s?I~`U`n^!^0-D(c^De?g#lW zF%%9A&G6Ps;X~9>0tPgFrqQ46$J*-gY`XsUa#sacrS5%ZuR+lozq42?{@Hf&aNFUe zV^cFRXwowBUYk~Czr})5h2*&#$Nk(XMk1~2YOwd`JG<#G4vcoyE{2_I(jsVa&j(a% z*dPw{9S^FJs;x~{V0%xHV+-5!oF2K>AI~t<<>b&|r)+9Xt6-m>TwcVtEjAa7OI}Nx zD@4W8J8pC_uMF0Y=6fQht=r%}J>Y)#1x&@y9nbH@5@nsNvTEd4i3;(<2X0i7RJ4kb zfpsP#b+Swu-m{MUWgmAwG)nJn*m+V!eE5jBe}0($mI{NEe1aAaQc<l}gSuGRCSni2 zByaPWU>7^mi$+qK0|O~12X5_}d3*bC@>TtO8@og+b{a06$*?&2efo82R(S8z1V;hf z?ChMXo4Q~N;$isjd?uZNAlYk(<H^{)mYR|)M)UXX@NoGpH`_|RfzNzXZsb$HsSn;s zk4SD$q79^&JjU(BO_joVLD&^9Q~0TEOExuKMsX5>e5F35_Ybc;oFSM=m))o1f>i_! zHP;Xhk2geE!$i^3EQyy?MDU+{9g56nZKoGNkF2t%-V+=m7TwwXId``E(|JM3je;L_ zvjx9goP|k+*f0F`Gxp`)pk$$rO}=P_WLNwcYKKzs>yT+5PJdi%%;xw0*2bs27(%a_ zZTmB#l$SQ}5j#(4jp{i-g1KvFQH#FJ1uL)@2$<`kJz-%LNE1`u&7#(aRpZO({rr2j zyMdqi=UTv5lKaw)jb|9SeF?9Kun2yCzq}xya;ypJFw3|R-1wuNE)kP8Yjxzsj&jq7 za6P4gS10|l(rs}^V~WsHgjmro(-q$7vr{KD*m2@k;{s$n_pqUJQxoW%_WeY*s;?Jf zkMU_j(PsQpE4=g!_3DnFo;ki~_@>tL5S+p~K4UhG{Y1vvkimQ)!QH0g(*ui@okh`| zu_r$d!UY+0hc>rEIpjxC6Q8963mMZ!A9BZ6tkg$jp~{}`^4yW5@w|8{omJ68cu<i( z$a%)sLs16WgF!x<+N{@3VvMR?vkBFN#xpJH6^>7UBFf3#{OrG^28KsxZ<CQ{l0+Z= z<fbpG^x;Ao-23HpwB;DOZiOyym5I-+h$@q{G1IuuhQ5PEpwRY?89F0CoHWbvYH@uh zc&hcwZsJC#ECI?b^1(KGf=PQ2CukZzwKVU@4yQ!pw+fxI_#XET<!3%ge-7TP(<nlE zwdR$MW-4qL9VbWCRo1j~Oc+aJ2y4dr{m-z6-sj4COL!=PCC2Cu@RjZl8Sp<@P>LZZ zZ$Y!`nQlD`nn%$@Hy43R!orBuE(%IH16-;3N~onxnSV2>V10_Dedl@h*CXU7N3X|5 z|9<V7Q?nwy#rFU-QP-bLd;Y68EAH&;viZL@zNrt>d9Sni1+BdU1s2M0$<P`Z^q>r# zgD2>?8CTQPJO3~HPxp2*uA&nA3Ak)Xvx(XpimgXK#>q7{J_rBYuF;m>`-8^sO&as- z{woSm!gl=Q@EjYN&2fwxE9~wL9rNCJA`!pEue%JGG#Id`I**pKoi5#A4I8-%d)&ol z-1KB8)cyuZO;h|DN8a$Q#*iAfgsHjPVPY>R<oZ%R6BHB$78M0f)>H4~@<g$+s*^mx zWe{_JDg0Yv(28Uan}nf@YaK5vG_f%;*|C<D^QJos1AuT3D@a!@KF*1)g}0v5YJe?d z>l`j_DKK%A|Cu50^i8Gv23j7>9QHKi`*eS7>F`o9y5=H1btekLugk@~nGe`@4`*Ky zMZW!xl7@D~PEmQCR`IPuM;Ks|-|?k$KnhE%7$E~i6e3RvM~c}p_&`MQtFt%QWy0RV z^Jd>&T+0O|X_ff-)_Z3sBZP{yLur2&4>rJs+#=mz$#33d(vQZYI~7E?-DHUr$6rNj zd_^H9baF2Y^=BrQ+*>-$Ta7d>Tc#8x7idd?*jf{*9LsniE@Rf902K@oX(|r%{)W+i zamLOdSiX5by#kKD?ZojUMXQ8=X{m=Vw-5fer&<lOjZw_=rANztfW7YyDS}b7g{9w& zGW}(XF;$2)XzF~o2@ozZt!k+RQuW)Y!cwQ)Y9%6|!PMQJzbJ5%&XDIrIg#2V<`O)1 zy;%8V*iWP_$UIuam|j!_-eRstW6&B}{TR<8Cn+x*iXDWd4wHe5FRTt?(<+2ZLmC1s z+1#_XY|T&(F@OM+Z;DL97J@}$h=6`LA1_ADx1j~2?EX|t_xme<&h{w}etfpeCv^nt z->*>rE_|n&dNuXp+Tv2uny<Rthg<!oXVl&NADW)e-fO=xn36<wpYjgzxQ@m+t-`q0 z$^NT>68efHhro-D+<vK(QEwh#j&gqV_7%TDms7y(mh{n*bY~MNsl#DvvG>#kTD8A) zzDUm9us}@8V@T-iPgi8+$XL`lDRB7#b*<;&Tw~)wqYOq-paW*ncgGBMb27u&`b8Li z`ev#js{YOgM{XU}fu%v6x%R#gUVSYs5|Xf&!nrB7#f#$JLOb_G1Gaofw3?565))&- ztQLeG7QVfUb6&Rvt~6|~ab;vze@SsiARV}4cRt5@vYqABmcF4}g75w5gy*MdAH|G3 z<6@*Q_DB}aj-$8?hV!54efom>Xm3SyMo!YdV^u61iw;&$uqyKD^LRzT!Ir;lvM9&d z#ejA^21eAI8}}S8I%?VQvE*{^6SmQySr00OTE4}j`IPKI_5FjHbmQL~v5|P=g!N~l zbSJK(4_o*C@R4)FNXa_+6|29f-1k}`T<8;j={b0IR7fQ^Ax!wN7M8x@KI!nZu>oVX zUvTbxw<QV-U&!Vw0KAce?&7gd*t7bIR#wf`E_f1>wJnloG}3cPkAT^I5kE9!=rrxc z@vxF}$(a&X+pN+VhqC>x;AnqX>^?*Mc8~Ntr(3xNYZR`99zEJ{Qpbi?^+|kQ4M{=R zee#EafabKaquIRm5Q<Qs*kB_B?^UKcwaGkV#?l*Xb6bH&O|VcDG^VZf0gO(`!=}BG zOS`+rEQ1y;FvW^sp&J1IhEqGDbG}ly`QH9cbF-2D_tCuN+o{iJOQWCpq|W$C@0K1f ze$d3id+G8^{k6X(c2xP3ma~QTS-q4xkJ&2TO5rq4lacAGE^9~?zYmX-k#?BE;WmWL zn_a$i8Mo0)^|_IuNC1PcjFYYEXxwW&UdlP8<Jib+2@WczE^fT2)%&yhq@wA@>{5pO zw&dx^EN!I}?6-&Podb%z<y0*9BPZ!{zv8e4-?<mdm$UV!rtOkGiF}WMQxAIstF|pb z&Ex#KOD?-MMr(ZOhja#|JSAU=MUG8mVeNnY|CB~I-nQH41feOrIDa9^%7WBexixP= zqpl9XlG;A1->fa{AZe2M)qha&t0-$LPpe&WQ&j($SWDX}0n=8Xxl#X_5ZE|a2rVWo zYNG1fi^Hk-wyxWD=95mce8&@?nFj#|IGOfwe%}aV@ZN);?EUJ`Q463D?XUeMWFc|F z(S3Q&yLoh?d8?KqfA>e`#r#m|LdgSg5p?Lg;oItI#AC@)^bNST0`ENebla~DpMpR# zrtEpX7a`h9JJ&A2Q2hNXN}Z`pGBm_T&Ks~b*4XTNj>l(EjK5C2G0}4Tdj?*_O^wFF zWXsC3s*kEu$Rseyceo|Hzwn2zt8)WC1SDZBq#DmXUbWhk7QC<{ZZ=Y~*ZUMU9D9ZV zGiZwhFk8K-CqFksHTkgg{kN$~F7HWiuKOpyal^T}zuS~QPM>KZU_LyWPdH=E$O0*+ z#BkBIqEW0bQ=0TX+@&@RJ2*}&nhTbyD&~`JIt&RnBSle-@1cAjdom*R$?rVP_x$$v z?YUuE?dInzjP3htYmx?ouGi_Ve|eys#CyZKn}P$}Og<V{sDH0<wcx~nQD0xCaUMTD z^##s(q8;PmhN?@};AH68S(AOuF?*BH1}+<3$HTh0`Yk^SjQ41VuTvyvk9s}|E6B?Y zb}H$kR2u^>b@5yEU&ZHa8fafDsULyta&{`92{kKSa{**0J${8XL5n&zJ6b)Xpm4aU z{87hQwErU6m2WotgVXTpkf`IxEgBII?%D?)logYcSt)Nq^Ds%828CQ)86)qoZCd;; z>teVs@pGKxX29|9H$-m*>HTR&>qf>Q3HQImb=#cWJ_4rT@|fUzey;HZ9YOf%Cfar8 zgD-M-KI#*T4n4S)_f~>t@)mcX-<rJzPubd!wV;cm`KZ%F5eYWEh>6a+4lAoH2Z!pq zi`0JCy7$zwoQ+Zp{nHe%S=HvGg8ax4{2c5Vvs4fV7|q_=kAB05FZK1p_0Gq+HQd}x zE2$8YMK|LTp8V(nf_0&vSOJf;hqhC#Gj7NRpQX}k+V;o=Q%_@nptEWK5p@3EAp=MO z^+!KQb*<wEJeytbN6EdPI=#Z;q|leL;?+h=Az^{4Kzif%;GbVVmkIo(9Z<L4kr1(> z&7fqlG2Xv>XHG77XT6+H;VmXCp5Fhu^KK8JA|2%@??_R=@$vF-aDj~P^2b(If4iqt z71cArj-z~OrGzf?3h}AFn2WV*R8k@^a9e_TchZNLnv9hBovr|UTGWYF9SyXgAoXc6 zxxEeC{Tyn>UK*UAL$+%XJ1+5dBlqqnpn|k5T0voEq`|G)YZ(tsU~pi|7Boy?@&N+g zLNQz=aF_MZ@GcA^!)vbVh7|M)rb)7UTLg<cU1`@TQGe!YFj%l0ZoGO>PxTlOfH!r1 zvz^4^@&-Qrg$Xm~eu!CP@yh)&iczzq?nY+^yNTVr3U-Y(S9iWnn*R}zrv8n)TKDk> z3;i(mLEsiC+8oxl{A#j+cByEL@9r^rSt;M<KHdxesXE#E-!2@vDVRT(x1+Wkr546- z^RbaNCG%%~<KdUDcF^plqN<|xHUYOy1?n4hpkbM-CEakpYuyCP%T$!T^G7Z;MY4qs z%(EAZf6v|$FUam-{aNgh-1c9?3JRAAVQH<j6i>RrH@q(eW;xc5omU9=K3@j#|6L1y zaf<gOaa-~d^+9T6IdQCvblnN(^HhJvCBAn_xce`EYW9husm$CBSSaA;c~xV>+<nJ2 zom>r5B1OzHw!t@@#{Yr&M7$VY8J#0bo@}tRTQ!}TkrDQMh%(Vz9q;|JM>KAz0G$Vn zxYsz+ckff1t9`_@>=?+ZwjiSwmlnT#k@rgD<v^XtY#CKjN0~spltVDTKg!-8!QWM1 z3?lDPsmwGCkJ5^pbDLT8q$c5RWZ<T!c;m#RNER*U*fdYp;I@`o_xp1^?KkdSO(RLe z6DRM~Qj{6|Dtx+p8_3mNYtC-_3Cp$@&mB1w>Fs~KC?#w?!x%oV_qkWM@F=g17VT#h zkCio9_x_sJ`TDNKe9#1*{pcM{4La0p1C48!>~E~WA9+m7xlK`h$FH|jlym_5G02@e zsfHbbR#rrl0&;E#t0<MK#1|i>K@7<B>HbHc9T`w2`l*f%hfMK({h0<)*FV}t4fFWx zNuvDe{9(UdS3OC2eILp4wclOMJ9-5`9jO1ZB@VdlL2}2VpCPpC)~mA}Rp}9nyMF`q z=GLAxT-3%sAVlrN6G7(+exL5^lSd$ReV)L-v=>~SrunH}_zw196pKdzhk+^47akGE z;Ny+zn^I3^Uu0+N%UlG^+^au7sKvfqf5wrUd_CDkAcooz?l-X!CGH`YtXjV@EInX$ z_w3q2I+LjBsp3aY+n?!Za)DAgauZdWKvz4Dmlc!E+%~WOtPzaa?F*T#!aD(8`j!## zzK@P$4Mv8)KUYd){WZ%8VbK&noUqGRINx4l$j#i<JUs|-IbPhJ@|Rjjtc1Z9D}JR( zUK)f}*|)Tb(h#1X+}ju-fSAn2Wx9B~VYvtl_`XGu&sLCk%RZ5mAryG8Ok#I#&qXDP zv>dKjg8#Lp2%`S1=B>b@5C2-Ckt%lDz1YRf2A4lQ=)c%g%+oTic+>ka-DC5*`w<_w zpZwb)h=mOl8!^ZCNAB&dVZoyMB(Tc!u0<}VzH({CcJD3R+l*it`aAMQ!U@(YG9yzz zX)K~3x%_N)(IBHLQ<s+luMN7ewf9rG#=?>`tpvsD?6-c02JD6pX2rV}#724;;O}_T z={EgRr@X`&Hcn^9Z~tFgUmaBC_kB%wcbAlaa1m(<0hKNR=@1YB2|+q84JzH8f=GjO zT|!c%1TF#+(hbu69^@n6_mAH*<BW6X@I0r_-g~XRjxX8FDST!`386vX{(MRK6}ch7 z?g3<nBHaV8&uM+uYj-=cVLby<+`bwxzeGJ(yYM?ivyh1meeIopX1WkYI55ArCAM|t z{;*d9XHa121%i*b6IJLUXC^K^T9<)~)JTc!a}stj56RV^$l<&Rk{QSRjr86)$DVK6 z$!JAdPFgNhBZTX>`Xk+{uz9Zk*7NF8Wdx<jVP8_nt_c;vxWoY6^b$#^q@F0;x&+IE zOXg+J!CWu_SVXh++goLan^|3jT{O4{i8*t%Yx1r$l-OR==e0A`YNye@F#Nle=kRBi zLGWktAsbv2lP)cMZX)+f>T%ji!byQg@J48|O1j?%kzL{UeX|i)DK*Fr{S^qZR3sIe zKE=6Q<0R=%56hVGrbhQZ&Qc!r*2)lHfjBUWgj4t)E~jJjbAC%Veiy<dyEh#@qK*OW z(99m`qQkBXj{EZRk@6ud%SazbxF;jgUMO?Q!|r}N3Idq*m_s?iPFoq!AVu|2TYue_ zv8QK;1YM|{2;T=JRNP4o70nk1(>=)6(p)-=56Q$lq&%*?7^3*OACQK-Oe@z0Rtx>c zcts3*pL|~I=(#;@-*`kfvR<mP;`)k;=ITi6*Mi-qo9J7gy)>61nZ3a*`^J+e*T3<e zxD8GpTYNQB@|nc#(zBClTI~!dSbGffw)Z|pBuN=7Rtw+2U#^YFVTD=~H+i(598Rk8 z(8i2of)778EQvW+LVxn;kv)iAy0`5TMmSEnp{GJGpM71hv&pv66Uy*Fn<y>8X)xNF z#&zs?-%>4LW!Cnl;8Qx$VJcrU=GAOScdy_2B22nrr7eJnv$w_9zUcrhHizmci##d; z{fHA93{FZSD;+L?9D2@r3(?m~%!Lz&f8z<<Yn>TY0{kKNL2g=P_%jtrvzMLXmCsdb zjl6^%{s<!397AdiJrS9B%K4!*31PnT6NU5QWNUJ4Z5QKr%8gXcWt;`{VOO-3bIYtG z$ZGC?t`r|E&WIO3;%iQ262+d*{Wg~*#^d&_9#D*OB}>75FPD!-K8Cx`p;ihnk~Fku zJ{YoHQN=l3AP#-_7Nfn|wqtPd+ncf8I0_x@5J%`K<~8w9#NaJq3`{20SsPJNDMuya zly)W;JGNmv=;R27jL`Qf-Os&WIPymxYC-8&9Sg)@+V~AwM9siIg+{IU!bh=p!TFUl z^y9r@Q<31tv;EGGLWkpJ0Y0fzO{8}6{Ssyn5Q-e@%#wyodtxu`TLMA=0j<b2tdd{z z3+*_DCVSmvknWgv|5JLnaH;!G^VWl$!UAJ55=q+$6f<*anx7Iy+3IgMvAWK-5ibv0 z5EyD~19ykIBC*M(=tNNFoTX_zaALt;?$9rM>5H`1jxVjH(UJ;bbbbgoL>|h;MrcVD zpzTDbZ#mz6ijjc*JAgRz;*h(ri4S36LDJ**8}=@GdRb#iVz##9Z75^S6;9M#kkBsk zE0<}@Dtj~r5L=#hL*IuzHoThH-T0y!goEh~ZE$Hno|R7gK&CU3@eP&N7-2-A3k4>T zfDPtb(9y&?gUeRv$wgrF*<mZjXQt<9_(3~0pQ6u>+Ci|&<X$Fpnohv*?KWChik;NL z0!qZsX4+GWj8^>$l8V}K_lIaWKF+(3Rr??QfHI+mOI%Ur7h$PnKgl$7H7Q#wFTm>D zr_}nkv%wYO?Zrr(Kc-0PIM14yjkI%xED5YCE?pYuQ0Gz2!IB06*QbwJ_IKw^`jW66 z2W&Ak{a1b>ua%i-A&p%<bT~ic?*8S`#^HNV3Jd&^fk7_jE=dVNc!`w3^!zDWOvlpc z0i?zjcT0mrD8mz}H|he}r6;Xn_Uzm-k@GoXt~pqZxmSdP+;tSa@BEAQEX-R^_G5O= zmu$PGgNYi9v-G)ZFHeg`u^N^dA3q*s^TstDBC<AcP^uDFyuYFUsy!IBBuwD9XUnqx z(f6wlZdl-DszIp4>79)ygKSDcCqGntN~A$AZ5Cx|-T!4-m8umXhSonLfiUm|8g{J9 z4Z;cQNuS!H>pFYm24NR;OG_C=hrjCTR6((cM1{<^Ukv%;fKzh*gMQX+qi6iy;NISB z?b6!pR3W@YzX@&lLDt(X6ky+32mio?d%2)P*<>+ij$$%Z((oLYl`(>mvmGs7Ne}qU zXJaG5`<<3IA#gjNIt#l#>!-1Y%*GeqR-He;y=6>!Bk}4n;sf0DpL>~fW2gXNAE&(z z_RENEHxf5=hDi_kp#r!TAsoO5`zQ1Cn|S`iQ3Tx^zb3cXLqdo;Q6T)7Lq7aUu^wB# z!nQPJE<6kI_aHM~<l_}ALKc3c>9~yjV&pq)KBiS@CFDw9n$=??i7p~AY&Eo=*p#Mn z@b?&<%ts8`HKYDXFhc4<*U>_oPjfN8+(E7!5Dx?xJ3^+ubJ8eTP2<DU#>;?s{c4<3 ze^?EXge0U~?b#|DN@ao}j>09?b|dn9m|%N>xS0;+0*JGGQVDkGq#QK#{;3Ni_c=VC z2bcvJpPX*Y`KXZxZYQh@ZTTKgaH<IDwA<e7`Eicqw^zAK?a1m<(EXvZHF+IFJYh?s zM#rU=lU25{U=)OWz*)T5=7E3KQhO2+bl+3kcrsO#yjeoRjD^y=#K}!~AypW%+~<28 zFHHCDt$(7UGf3x-(cG{de%dt3DhT3b3(tIQy1qg2S$!_f%qlr#9{bKGS+qsNPGMKL z7ZTfO#QIX&yZ!07+Z#W@@*(d3l!0_k8Xx|YE~w6(e_?v1hrPqd+_FR$b;gL!|Dh`c z;xc}<$-vULDIrbys%ft1SQLAN07Qj$Q$+oOw|^oJY+oTzMtjB}0Lw~ieMSz|zWEqQ z#*hx7Wp{QPSj=?VM`MYiaQT8WPVrH-JM+LsYH(In!Sl|PygF<syO`)8m&W|8FYvP8 z@2Dd|O5Byv=RFq19(hY53}GVIbhh@4+gc?>z<$b2v~l3--l5a`mN)CA?a{E#Mz@{j zbNuf2SXY)814sPUa|U0?P7{n;4@TyFGgLO)u))_6O<UXYmsRUsYHVGbb{<{{Qt<bj zB-aUEU~K2nX91T?Uqu{o&PZBa%nhS*u02yFN!LPo*=`G?u=e0`S!~5f2`7a-E^ZLG zUgD;#sYkz%zr*^g-S>wE`>E-^faK8PmuX8Ju14pgp`@I}o4Nxo2LbcQ))z=V%k)<P z;vUMzdQ@l&hnqXLGkB(}_iHmeaqNYRZLfrP++}4(h%joXE6Om^Ex%+QuAs3*ZC!IZ zloVf41$kcZ$LqV_#rvLS?IKjHb#1*beHR>J4BQq3Ap(AuYM;Ekp-4f!DO=#46OBJG zazk}6+4+7x=-k!AiiU@yA=9Ij5-nI>z-m{bEAwh}{qmx`uv<O%Bg$!UjZV)D#zHtP z#1QB6Yo~@R94ZnQ-8yq@&zfI!ikCrupc%d0QNCupvnrR(hwgpx(50!monKDRcPKs) zuWdu=1?e1nW6Kuo64$I&?3#6!ZRcZD)+)zv^YeW!$Mjk^H#S<RY7pNeZBBb2r8s;e zJHFg`%6UQ^xckdxa0a6@JJlWQt54o%Z?&i4I9hj*24}p{Phnl1o`%U_A)K8_phUc> z%LLz>a_q60oW1zv-@0HouIy15Z)Rd*pQH8S`|i4)Un%D3s8ckoDk(*v^-KoB$TLyp zFW|1RgJ2NMdsmycIL!lZ)}bR*h4zg%WKKs7(R8V3RyhHCBCK_6WvTvPr+KF)f1Lu^ zM|_TRB_jgAAKL%Z_v7nqnVJ%?TeFwha2etZd>KHGfe|K(I%l5ZL;biou%?z9=c@w@ z9mNL3=oK%YBzwSZH6+f-t<xMOx(?t-y2n%Uux3>iQU0>c6bNtPdDvI5agV}{ZBKcH zwn-B@t_J-q+xGe#eHZK~uJ#O8$9Y{dx{$q;_XVRuajECr=C4#Q7Wnc{=cOUgqAT|~ z85v6j`H=I6$76N@%MD1ffE#y>b~8Ct+eQ3%+5dHSyZM8&bg)#|mwg<TryxEgw9(7? z=J#^Od@3$=;yDXbHd!Dk2nJDUt1*`}68-+=!uY%hL0%s4&HT>J<5cfv6%eF}JldMJ zsoLP;M3&;9q~^2hH48YO&#V`5T7K8+x_+<Q>+A)cDVZW#I#k^Lo(!xRTr^g`?6ve$ zGS2kDT9_b;?KdR}-8dL#<hO)&*DJ65nrU$3a}cio$}r2z(a)Es5~lr@-1=rLyw(LV zUg8wn=bVR$x^eG8oV7cQ8hNtU@>3wo@IJYb;>sI=&M<%HZ{K~FOGVsC_E9E~1moSE z%9M)h-rU(gno)U`TIVUe4-m`=ez^7?4n5k%0sIb|%Y`QtD!jGVF2E@FZLrGpvA6ih zmwv3*XX13^d;pHuuOnLeL#m3VL+`8_j30d2k>GoAS~K$qgcz*v@DZ=+NSnyyYgG9W zm{_AyqsA1&MJ1e8l1wx|Hp8zlSKOy44pb!komW|W+D)pS(>vqsM@YOAEeUeo?P&e@ zR+F@`^!!d1er0!?^iK1EfIifX0)auqB}l}~zK_G$>lBAVA-*%?EWv2@Y`|mev~B0P zGCp30=)P`mG|@4rp^IT6t7paqc?lccm!-{d!d{;o<B|`Td<7~=SdJG#<GVquLaE9j zc$<v)GMC19K8cthn*35lK4ePYm7FJV_yAHHly3VM879Qke0-#5`w09i7bUr-9Uxwt ztJ0Ro&y?JjlDbLNbl*$B2%?W8d38zP3LL~OSv`_h?r}=J5aZA*rpq^)nvoudC^dV3 zOzF65?1Jkc?nvkeGQoHR!2H8m{N-Y*bvgF3@ydJ0l`%8b!*;}Uap^k<GIykx6>t<0 z4e3`fzZT7oj@~gdu{}n|i_Mbu=iL}b<a^Tbf})hXGu3$g`QpbIB5F8BwgNf(Q(DS# z0rB&EL(<jGu6e&MPOMnIoYK~NE*m~|uigAjmFoIJTa<KY71cRErP6qcMc#LJaz%O4 zjm{c-dEpxx>A3NqD?(P$Y-iJ3-h~3+eDdpXVC^m&x@`)zKnsp#EByy9PXBTTP5bou zaHUuJv&VdXc74<_tkPtpY!AVy#ItemSnQ%Qu`8H$V1CG=59dr+D;NiFlD@uJC5h~d zx=3vK3l_6(bc&Ijh;Z62{Bn2)+WEQ)oB(M{;sQ~=+f-?U=;zdq?{MlMiR`mBJ`3?s z8;QvqHVv?Dddooo`pGMPGqHCu%6=4lXbx=wJG7V@+5Gad4JuKgYet!day_TfEFHd+ zOqCZF#8DEL6wcpYVA(7t&xMQGrOFE;5Of8xC4wvbh(F{22O+ZXIl8Xw2h#}D&c`Lw zF?uzu0v58U>F2`b2Z`ox!ZKR%RdaYS?%p9}X}s9M%j2${R^Iwf4l#E${Jm1XRC#{u zX(R+iVsLaGQ1Rf?1=PJU%?zw`*dKzhdXnyr4<6R7%2rxZPvz(1OlgE;Sne8VqHYGQ z6YM?0N&5jKE9Q^#8Ez8o``%jJ1R@J<t59xEHX8h)T)u^AAaszmne)BMnh}ZzmDU%& zpZGQS2Wpqye9b)G*YRe99p~bzi1{#VTIxc6M;Y}t?aHqOl4zN9KP67H0s|p6HY%RB z?LOsiDJ%DakP%|r@$ox<Wl4`uz~oEQ?Weu1kB_yB(++00(Q-XPx5$DJ`F!ETjsSqb zCP$4vmd|L9+8uaq@_HP@bdHIlaI9sjE{2ki>AkZ2I;WxD>5>!@6DM(Jzd=5CqF*0% zNnrO2YbCHkt`|uippfRN8BUiu`CI@8-~X~5-$b*-0nQD=L#CltDD4;}g6nSuY6G1< zx;=Zjr_wqpEKKmL{?XP%T>ajtmR5YUrMb!e7>r*A-tN~$FEp5`4X9qNDE6U;zbkfB zo0gxvNnM+vDlag@$M%lMwou6z^LQd55TCs4SWz%>2cwuHuHooGzSx(k3esx}wuI3m zA2H%7F_D;mk4oL0#9HDssp#6Iq`{Kf>^Zg`Y^V+YQhy*9Hy$%{Rn(n1kL`;c-lQZ| z>4IMC=U2MC&RA1gr!;uE19MK{asl1n6wb%{=OU^oODDvU`1VCywrDPDQ6v%xZ9-Q_ z&NIVS#u+z+4n7hirfP4WAbveJxcfnYs3h;G@sd>^_zCDVi}>o2wDuatdSnSL+ErMm zZ5@z!ZiUTlw(L9xmXCKCN64bfJ}$%%$)|X_!fk!-TVmbkrot7Xy`leK(;bLjBPuD~ z8R{K;g(r&B`^zQx7t8bF_YU^+Jx=RLq@BO>bD{;`aB%v-i!dk27}q}tSijTA4`fyR zU8NiDoIDtiFZx8Y!crw#rdGcvg=_R(`k;0pb*+G%xon)Pb2P_JN}|yDPT9hz6Vozz zK}!Qvgpi52_If;1^)jV0k>BScr1}$Oj>r))T=xQb3&%vJC@FgiPYa&Lea5g%!bP}W zsVABJ30sGgu7Jv`&Id*BK`^FU8UbS|G1Hwp!$Y{l>+YlT7SFY`vOy;LoY!{yj`eT0 zKYN*J{3KfvSBObhM`)FNwXCdF2t-A%RjL7>yE1j1W6IW*oIA*6)j{0o`oso|?hcSM z$d6eEh4vNn%CH|zA@9Yg_%wMG3$v-9+14^r&W$pDQo)}h^G9Q`P&ZJqoV2R5z+dPL zBe<+C?u~oi5<1*j+kt6W{2_>S?7s8_f&epbtQF$`t?3jS#G(&lhMrUBxyN&44u|y) z@;?t<9+Xvd5>|venP0^CtV$l#V4)!#dqU#T;T(7dd!zc*G|l)DGJt{4OK0TxBTwXL z6<A@LYlTHww4zd!Z>7d{d#q&7EKL6_)DN8K4iH|<zkz5Kh0+-n)voW>vq|fILe_er zdFpu}YOX}>)Z%U`F>yj&!RoP++@Bt4t;K0Oum>%ie8*rb^=pDhVV%{Qx(_m&a?I~3 zq3GwnFPZPJ?Bm`yr0O12vq-i%*?KU0q3V9*ca)>`$HQMYKAAaJJ!T+gEP}+*10>QD zHCKUrrHX8%QNCr#%?VVifv*W1f75Hh^5wo>zUAiF_AihpO~$&reNMaYK(?C5!PTMP zkq$R7t$|(|pe5`LAgA;`CTB6%t@HBeEyU@=G<pPBga|%DTS6gx0|BXgY`M#d=nh8q zUeAU;$7uf4=42#}z_9#G^Xe+?$$~F(Yk`^p0I@8O5dmXEX%g=l9fqOAP;rW;ug(Cz zM2I0{L>CW?`CfG%lY?VccpY<@O<x9mx`vnrMdPM@i+*{<n+TKQ3x^}yL{2S9a4`n_ zNmu|p13?RK8#fnfZ=-)PxqV0Z?uYjb6P4w*&!4x4jyq*}zv;MxPlG`}UBzi8CMp{e zIfMBpVddUJT>FbkvIr5@k4<hvS&@@-Y3OEiS@rKu+{J_B7WZ1U%kM{iCAXQ7r1fN~ z%(9Te)%h~{W|aj3oj~$xZ5!#38X-|k`U9)eZA`XWi?2YlXTQsMpU-6L=Z7^*z9_eY zI42QR5G}iY_+73SuhixKvvYqUhLXnnWy+kM;)z%17V1m5=9k-0-zt&ErG^Cl=xpYO zbxzjmOYb^p1i6dW6ff2t=i-WS<3feiWlQwPr&Kiou%r&doU&zSq*ujA;Zf?2<WG+y zj?suqXIeVNZN*h8gf@bW48WFUcLm3a?Uh_6{9*nWI-*m@8+&CJFIVQ>%%Fvf4$-Sd zQ0m&^bhnobbWS7P#x#Xm(pyuMZ#-A5;~l2T<sx`~3m<I;bKz@w7UH^==&f(-0`Mf8 zj;-D~aAlBj?J~p>Uqswq4|rj&=}l*C;%~F*JaC4SxH$a8-8c&9y^ux+U>E@!I-=ao zgPq+WRQarOJs){S{k!`E>_&9~LsHf<f$rw?U=jrx?n+EanEZ=L7D#scNg$D{?zPVF zQfI3_1X#?jB@NrkhKuc;VLeG~@xZYyy}VO)x8BMBaETh%+G*{Rz5_4Kvrm!%8aR2> zb*AWm_~vT^*y-#1h8LryZDSYUMr}o{S8}HPDb%(1!o@`f*F*`kJzPTQl;G2<wv%Xe z9xldu4X4TOVQ_BP!y>0jUKiWYoF5T~DWX|;)MVoVc>_Lm&Nkz`oxfRHaX%4HoGi0= z`-S4LchQm`K}@%%W+zJV&_^8mL3C!#t<`aL#*^5~Q#N!h^AUjo@pg6Q{u=5~xoKM$ zx-6#SP<Bh6b8G$%e=dlgw5X|`9^k&F#x{LkVMWf8zM-K)L!xEyI-qhS$Rwbud#s<@ zuoP}!KI=1X9U&O-0}}+P-avyX72?~-)lp0KH)E!RLXveAigl|##9ms>lDR4cBE8~x zxJTaFz@(mlebd1=ybvOXA*PlGG4~UMR+-shr*Ty#6p*b(Vhl^fDdT#)3qcqnR`FO- zwhBE6!T&sVyXX^o7xFP}*&m-ldII^wmw}+ejB-g?{ukLJ)OG=f!wLknqHVjoPc73> z1iHM4YKsAtCN}c0p*+O)SLWqmjjs)GG!~Y=%SDuyhkpLy6RA}@aVLVgy1C>BW*7EA zyYQTXkfAGGw#zoj6G}5+JKO6CUp&aa(+^yfm7l~D#W1|rDGKpYm*<Y5gsajEOKrOg z#Mi+_`wT9wfXfMMr|`H2=T?16&o4R+7Xl%Nn?xcJ^XW5f2NQ+%O@|z@kJw}+RN*Fy z=|tliPa^`{Pb~@R>a=h=SRgN-+7a3*rcvorYirKc9??n4%?<?h;ehZX&KCZR|K1V4 z<lE0ih2|G2#)}oNCdv9Iy=muH2y6vYk7lUHV{^?1Ejny{w`&)e*qhutGDO>Pm(yy{ zmrDx#cwG!#rx@Y7Z&z`;NE6sds)q~7r&J`~g<hRw19Zmk)$1<QPsHJc(7?WOyY_<? zufd=+VwVugQ_)I7dI~0a>LQdp6wCzdiVC7p)MqBIt?8h4|Lr0yfEaH@m75!BJ;rP! z0#=Hj^%X!8<_ij`5>QG?g1py@0Sz5xOFhH2O}F6zWusv?i^6aE1e`p~3qcoPX_3|{ z;Lu{(I3UJibIY>(-l=y9KI|7&&2W9_>X{;-+Aq$jsV11r>+PB8B#7`zMFQ9SYe=Fg zARG>MhND`IjiF}3&K-JRypAp4SlMo(AJ+&MLj%xTgaPfUL+kGE4}j8#ih;OzzL&!F zt~7!kzs|+Zcyf0oM|B`9Erh7az3n98x&LOQ67lI(Q(P}3MrwZzbMtU=_WYbLzr7!K z3xqzlRq!9tal9AmKiX<&6?Sl(J3mt>*CWD41om^5fjziWKzK_i-y)TeuX@m|U>GJr z18Zg}vmqh*`q~ZHT$xaQ-m>EKw?wJ<=iG<uFJ7|ht4NS)pXtyFBW0&sZzit`wj|Pf z-W%g?#t5gj3(*;3tN1eOzJ|%pXzg~^8TJ82R@;sU=TnhdofbQt(n+!xyQGkT&z{0g z6Nnk4;ctU9<*4hoO6TjXe``5&{;F>~_?qL>ju@4OyZQSA!Y4lGzTIQb!G1a_*?m!f z&GiyKm60&Sc*TZ~`8t_Vq6Uzo(_;yAbRf>#k2G5~x_jjt?)<j}%D-neuL=1b17I=c z!RiN$z-*K_C+JM%l?3t12ni{AUZgea(nqOY&KJKY8Yw%01z7c&4CG9_*{b7xG8&;@ z@l{^tfu=%Rn-m4y5dFaa2$?hk#Fg`}JZXCY5tvOmK);dVPuF)X&ClO3hZZ3rrr|*j zmnW)0a2q45#$DD>m&?%yyMh5-$QLTmp!pp9;$Cef|HCy-2sW0n=T6oEB1$`u5o^cu z2b@b)yJq3no0_H@+TC%SKdPNR?hZXw?H5LW5A{+rKZXdM(IZ~7!FWwsRp*REM>m5U z##CQ{3}(V;0=`d5{=$~(KTz}xaA$~B+D^t&wAuz2{pJJ7GZoXYKp4!V#E3qBkjS7x zs_B^N6<nV<esFBYL&8(cgqj^-hg~@l0aNo(+gg1Bn?H>1hkman^ZJF{W)T{p-a<>K z%S*kQgRo<wiNyq+<+WebB}X%Xfd2@=!eYSJ{e_WPpc*bp7EW!8QFt6D>e427D8W0Q z0RE$2B~lhtiXr!QZN{72kqhA%VCcPo4C1acaK~vxwl-V@>$Ho$UAv56=a@5qk1sRb zjg>}l8e!<}_^Hm-mPcY%aWwIQ#|19?QyRkj_s;q*xFe6c+K*<gTD9xBB5TR&gjEMb zz7?d}ObS4zwX12|W%cG|&CFS3Ub4zGINQSxu{@1DF}>6uK}<5{f}A@k?e#sJv_-8Q zCk2k16A4VDFt^w3+AjWl&=R#^oNYX^%?I%ROaig7?Ks6s0ONJ&&Xa;B!H8<?^ykqb z3=nG9y_(j(?oJ2WOPsT<>r+y8yB^B9O3>q91S567pQZXHe`IT~@5nzAxg00%=se%A zVn%-V=VcPr6M6QNlbzy8pEbX`-L=LKW)(BPVcnQAYE&TYGC36R8D^W$q6IPlxp@sh zUbTy4obSL8gj$#QQV0|EUK~l&Ks`5Hoi}`how@q(B~Uz@XYrK26hLFTL(BVL7IdeH zW*K>-j=-7_Sj@hw3^fRj%v^BqzU%GHl-Nb-D^0od$mglEBHf?4z?MJrf|CA?E4 zKf7iHKp%t}Q7$!&_VeG^6ok45d87uxmo3Qlje7zzM%HQ1hMGhxEz*5oCP%`~Uuagm z-O&CtJP9DL=B}8t#_%o>$!Z1;Dv0MJY38i$%z<zgI!7Ucf<jT(9SK;!_WTE)%m~`a zkGoHpfT=^JenOcL3u(SWJf*giicjbgn>t$3y9O3%-SeE90bO*fmNs0}wkEw)oL(kH zz^OoLvDJU);XX#BWN!53W{v$RaSMN+`M35l%kYAFs_8De;B~tJ^f8#G`$53o5DXy? z(`|==frL{{k8||}mo~->HE!W-d@x??-ioRH#lg>(fkKB7HG8oWA!CZjz(Ah@smj7h zfl2)uyy@jDGMAr-fGE^GtPWr<L|Z``xB+&T6I>Vm3sO{PeL>UHbT;d@RN6W=UbQ?` zj-0-Hg$6gG!+ZF0Z8jzoPrPRhMNJ<`h?X#84|p;`;+(=g&rOG39E;QAca@fuZGlYV z#w{wL(mJfAEip+aelSm+#2bxmC-G*!?n8^&-phs<6D3kT%|0-A%E)l-u5tNJ)M2N7 z!h0uiElUF)_Arn<sPv@72*1u-?5hu=T*@<GCyZbc8&7+SE{qkAxv?r$=%yS3y8PSx z(LdGC*sLYxFc(xL9`$F~X}UjgbyTQ3)D6+zyubc!y@~}92Z5c#?@d=)B;ZQ9&ARx0 zG?BtVUP>@(b3LF31l*6@oy>fI?7dyTo^`QlM-Uub<g)IJPNZ#8P+;76em`_T+?veJ zxwlQq73#%F6Y&tq+)Va^^<&?Bw{-Xm&t24g7>ou+Yl}tkBTss32EQvtMQVSAa4ISZ zF)B&TMN*U0v$P3szOXcztJ5s9qXS~`J?Qe}s!cblD|dZI{1Syma0Ue&R_z?ycf3>) z5&B3u=e)M+j05dyIyZzPkK)mEk&t~1BjC(+E<6v9BoMmj=>pvU^t95xC(@#%reVms z+QvSf_To`>nju)K-pp@4@)m+#8EXe}Xz>4W183(~yIC&~t-wE!VXUZ_bvxAoxw*RC z$#X*`4do7`jXW?c9g@0Sm)Y7yPSuO$;JNb)WYu~n>@AS!Au?vOd#|uy_6+6{9e-Xt z2g2mt759bg8pUf3YqKR+r|<pV?M$xPX*`d}@3F~#=_@z8U}a7^+P3OblrMR(ucO-V z)^DQF;`|YaNL)Xb?}168{s(py=(_g#WB*+MD2te5^^qI;oLrvy3SKV8-;30%mZ2nB z{9ZJrpAS8jR-fm?#`3AC_}H(rO#xUHfQR=r$wHD+jOusnvo_sUG}k6z-?XF(6EBe) zNp49H?1f1<uHGN1{8}v6!bUPsxk^ASfIt93c<^5mULs#R!^Rp5*I~|;U_CS|aQiyU z1*&$2`Z^51bJErQwmE5{oQyI*AK@#6N$c1dD*5oGpS4cPvpj?oEvK})H_uXY*2AOp zUg!@Ds~-ahu-78vQPYwYyG1IZnRy`nGj$}>Eq#i4ao_!}Y3-%x+{nx23dJ1{q#}8R z0nO*qv|?Cmf#g!chvOI#T?3FjW#3)ct`_zb#ek@3KTQa|pq^u?k<pbMGoI<s``v$D zNqo6nka~=222S+prbr1JUjRL8by!MIvkNMLF~>h$xC`P_IBPl<qs6Ze+)V)THlJc= z(wAWbTL>CJznC%2qValwAi3r~PSx-(^6}%H%SB#xwloX?(`Dk(>04Y_>VPUwdr}xF z`_x@ntoLKUrRg~Qc-`dfjhr;oOp&_ixB`~vV3K01GOu!;O3^-GFS2RipJAlHCX>oI z#_da9@L-CNeu8G4ymM*IwXgF9FovG1s)+D<hM9u6qC4*Xc5{ucA=~kBvV_f}1F<7% zYG>|BlVvI43g|DZ-@iOE2hz|lQtTKN6mt6Sxor7~d*wMbR6fYsgYS6l(e8IB%uzTJ zRz6ettmn1?eC!&!X1^W?8ISpJXfjVVR5?p)zh3nV-A>7`{8JOG3fo#VCQ;5yq5r&? z2h2FADpDaZ29Ps3opQJQu#1wDnpdEV%v8ElV5w0cEX=K#O4uc*b8PudcYjc|0}Fxr zyLb(c!xqmon?xfo^D5Rb(u8lQi$!0GKBinL*&Xz-Wlec|s7nv?)VAnCtCt$fzfNT= zbV1m<3bMcT`0k(hRNM#b^EIuF-1WT@aZ_46&bhQ0(<;B|8n_kpv`?LR1%0qts3u8B ziGlCAXUm{(_6vaZs6!1O?C?*m1^|LElPGmXJ=Hi&B2rs<zftbW?Ui5ofg3LQ=ES2) zYwUauv!u9J;Xj9KKf{b3`>qUk6mT4_f}z#YTVn1c-F3%A1Ux+%!;(>~Q`M-^3gOne zG?!^an?9hG=(sMRG4sq?2T93)xVSKm2Dl%9G~mkrM!Gcj2WGAUIYT?HYhxrj{+JEn zbO`)PCPR-&V#eyMNZ9ASL*m(CmrYz+xP(F&Ej3@-Xe=x^rV94XFd^D)I`&+QIpE+C z_T%z&cvSjim?sU@!FK%8{jmp(Q??;fH0!!ph#Jq^xj0J?9(`JJEheI2L+NW{svQug z-TKDun_q>4{GYXu9D|To0SpE$H{rf=)2xTb##T!}!;Kv{7mGb?07vuDuNy8v;^wZN z&|O-V-d{m{vr$gKmVvW(b%~$&kP?9bPl5(y$TRcP2wQ7GPEu@pd;LaJ?=`*XT*fX{ zwY8in`I}a?F=6h){BGBsvBt*wWT4>*I4I{ZN8dJR<zd!=M7S+6B@e^9#Rcnw_(IGv zCGF>RboUyG7Z1=1V{Di|d?>~`Q(ZlrVzR=ihUS??UMJU2vwX{XyM_WE{IUL)`>)y# z5VCOr2~9D4R|h<Wy#j1(PHbu<A;c;HLc3q{gTbI1Hy&u&ch5%z*IX(h&1YOGu6bVX zktC15Q?<y1F+V_6M=$s^;5Xb%OVfo@2{IV}KH2VSzv-o7&A@^0IfvSi<8w0QC>d9E z_z?&g^tvsxxLlSt`{_3deZJOA18~TDImy~zk&ip_(?yUweT_E4Z;siJd_$n!p_jPb zgkI;}WV4*WsRg)6trLR}@>L#2O%cZeSn=@ZLciQ~m4?bs6QbqhLmFu)^s2K?C*>k9 z@x%YV9>l89L87bJTiT^<C_Y8dy-$L4(1$y$Sq__3fZ?4qbz<a-C}huYQ=99gST=n4 zvuasMGmF-mm$VOmSRmJnT{-{PVFf_prbocx=l#Ue#^Hr!el|rP{pP6&kRyBACBf?C zEo_R`7a=acmU>;OSfAvtxdhHnhwno$aoDjkKkxJzVQlwmIzRoJ?hOhMfVXKa6_!f% zCy%~mD=G=198T8pnnldCnf$24<FXy(eRbjaB@}c>{@qdK(?53Q3v*Qg_H_)LoN5LT z($g`U|5C@npd`F>K^W<!L<<$&@;UwGLg00lcm8$>(4@A0VPha(r+FJ)iMYiiB(&F_ zyv(c>as%D3Htag%LEro)Lz_C!(hedM>sfT3s}V)S#EIRR?v;P)OjKdph$ipd{7da- z`V&6xz%s4?B7%Luf<4?)TD4qg_JT~ibCwl9ycEi0S>+?3!{48@1zH++h4;YV{&D-O zj`mzL4v2ZFRg|mqyD__pS^vcaC{hG+*4DRAJOXY;e3<GwU3#HE4Z_{@AXm<K?_?SA zikkoT{*SCsim23gg@su_Mk{h}iN!+vdZt+=CiDB;#k4A6DJ(z+iOSys?K(I>7!Kua z`(Hf#`mIbrLt{7yFoJ>K83}MPaA!TINjSZoO+LrSrwrx(uZxR+Q?l1a7W%G}FlEd* zSFirCdFQUqup(%syixMEXno=Oyre>u>c80?0s_mGOaKRc(~26ox6I~bIKSJ4Jj&2p z1(%|6Gs{_y6?KuK=VM(hznR{rMBL=SCn~_slbWgjzGZ*Y){r%z&o(>&xP1VCf7$Kc z6lS8Fic$CWbJaDoT?J}&p870Ll3py?`tt8<ssz-f%*<QIzu;@mkhO4emy6z1hv{!l zqWiE@BG`cD-*Yn5@c({xK!@LFk%9ZV03;??TEllv<mHXeS5+XkO{DDHw#N^z+X=F^ z<S=uU#6#%?bJkL}84C+G|1CUr$uFV^+1d+Jb&!5>>fWX!sk&|PmenG->t1mUgUdD= zLWp5g=9IIZzbS85L@=QCNt&4WFaH&wAX9$wOBSk*^fDkZ7l-Rp^u*qsvVD6Q!lS^i zEH7}vh3$&c%8x#5a2>~&$~YO)P2CBSu3bCYCjGB-HLiOFa3A)zp}{AspZ+J$F=gU# z<xOGNOgXNV?uukDwB}-a*F-rTXK(a5BfO+)>%$S+-x-<<n}Gi4P^9Y=uFk@gVWf)l z#M$`35B=DXvl&A)NTa1(#X48WPJs8cc;WTRIL6+{vhEmO(X{E~)Qc#5C80dmGg3sM zv>k3eJfMFkgpU9I&A)!mYXxjGdO%<FTp&y=Z9-d&*UQv@gF0BOH`4wcc1fCFgn|(A zLnZkB3z^@`93ZXs0DjFx`_n~FO)Y#~x1aa4h6U7_wAB3MR5fwwsVqIehld<}7>t@* zmi%aN>Du<Eh^dX&_Z^cbwCV*WC0A^IlIl8?pA@E!l#CXYKz>r2Tq|{#SBsLUO+FDR z>O)Q-1||KR55_xfHOFEGL_&+eoR%%2fxvpUch!VKhVBn{N_3H{yhQVxJUYSwhyVIv z?+D16mBZL2|0<8hHveo@t@}x6*h$YCN#|?$cp|(Y%2Cj&$RNVMKq}Rp<13(Gf$-W; z;dA2z;A5Vml55-P-o>iyiD5*;2@#v&fwiOx;#XuM0F!t2fK_7Y$)?JWjP{qp0*71L z^X6Fe!AnA8)yv9!o;1UU{127rgU62QM|R*>WG7SdbK{9huWe4n`rx^z8!ByXIV@*Z zY~0qg&(GZ7z1j;A+8a|&AETqLR})pE=6Ode;;Zh_wzC(a4d)oE%BOxcWlie1b-EF8 zzcgfjd`y_V^WmEsQ$-2~TOC8hD#xd_Pc!gyz0Ow3|BE!{hND2@0OiFqiFKjT4QwGg zlOPzA>VPE!^9Bj3=o|td)dq(ZT3G1&#{qZ{#y}LPSdS58Dger#!w*(##i;=F>p|q# z%Ytr?Hsi|7JYTnyxtkm3T69s9vw!szgY)StU3ys@Rzhp{yIu0xL0_r(C^?xHTyvQ7 z2%A-~v`4>0$(*Lt9=ch7h$o0(jlxG75oR9ty0nkO&>XA^3c|;5+gJ<5-gLPq#Sv^x z|BP=;L~FsU{dkewb%`g)W5FJS4UYU**_VmQqYSB*GE8ZbBkX|}4VC_!sorCS#tTc3 z=E>F7IZgXTw}4VBJ#W(*+%@PzB`V0dNksn*o|{Mc4QuvexH+o5>KD%~=Djx|ab=-p zJoZgiwA5A6S^;#0GO|oh6vUa%Cqp#|sVVNXT|T$C^P+HB*HmhN$D}G)YjhU)Yr_vN zgokvO!|pp(T5B#hyPmBx_n4+q56dGxCEiv48p8M1xG38kF@TnVMO6p23$v@0f8#Yq z4QHqEe~bL1DJtZ;FA1yE)q`g66aqT6q19vJl=VExW^7-rr9x`cZM&a%4Oq*!Z2EQg z|Di_)L|3j-l#i4Wi2B5jDw<~|@co&XN@;0??26ooA6j@FJ#7qUz20Gk9taJHVN1<R zH2l?}3(2?KHOl_G-O0RruUC~ko7fpzY|unqj8r?l95#HaqefJSV7ud%^5QjeS4Wy) zo46+GN11~nVFH`UHn(BS@@2N0O3PPhe=oXOLm~O;KnX}k4RfIH=b+10wJ6O^5i9fm zw8ns4#rhXH10?H#jXKB&g<G3Om+(J@ybuh@J{ITC&EVMT52~}^Y2>qz*3$ZU&3?Up zs)+tmAtj8eQZ7OH($d2Wymi#=yze`G>FBGwe`&IR3nJYXe2hRuq%LpmPt}^CmcSaj z@fy&>d|ZaqTOb>F*CqsbbcOzXKA#LzHXeyB5P<<DV95sn(yj?52sl5s^8c0#$w$4_ zBC{flRQC&Pkz05xc@1`-Asvqu*ZeyTty=%JIXg4i$tUSpiTiKM<KwfehDlaLUH;c1 z)qfRLt4(Hxup|Hl1YwBthRo>KZDX>y|20VRU%99ZiFM8vkUlR9&ME3+0lP<w$E6IM z9RKS~ihr#MNsf+H1t|nNRa9{^mk2tVHh-B<*QcD{t<*H*_*I=81|m4~8b2iDxKAj` z8r1wdMXeZb+o20I$FQU@T2^Ha&L8h^=_64D0kxFBj~ezreP}`*B)6I5$3E800S1Kp zMp+4vF%xBU<CXkN6Rbwg=Yo&TZYJGG+pR$LBXwP)Sd_L5l=vaX6?G|K@}^s9s3akJ z?TzK(T+57tN0;GWi`aq6UXMlZ%4o~Yxeuc!HS)ssS}tM54g0Sw*=^ZWf>wEBXCGUt zYo*Gz@p5cUBPjZp+VOu@P<|4yf^Pnbofh<_&2?`+UOavWl51~!Gnw)BeX>mMg)ijA z?q)44wKQ1WD`-B&tEiv&-`oCawuXS#r846V<Z+(V?UWdPSd;s~P?(5vvq@!ty>0p& ziZ*5{4!<?qH#B|OEXi8^{A4lw(H}3R*4)*lZ{ULLc#!9PvyT467%vINt+^SHa$@R> zK?xsXlOg6MC70baApi00*R4#DgjUVkqu1M35pak{QGWojJQ8D;o4tjw1Dw}4!#1k^ z13CFM8%w|>>gqw(+B*HL!I%DjtzrLuTTL=&sIm&^?pj7MIt`T!+?nc(TbpQ@;y=|x z84{_}Nz!M!z(^LQzGe>5T#?4K+>AB}>Hi8rz{TqKdwSm9W&HEUcx(DYFAtm4OaqUb z<6o_9LbVUK)e9uvVdKt)`cpm8HmI_WZn=*MR|lSqexk==j{C4iVy<~u#<e~ncyvi_ z$0%eS;Zs1-XEf#ED$<`i;HdZSy;AbgQBO{l`)})e{7(Tm#193`Y1Y`rhpzA<=|ys4 zM$W>G>zwNAXBg$S&de+fGG#=Gw3$DWqf@ZACk{Zw;=Y+v)n74n(3NUbw{Og^BSMnb zB72A(p9vJUSbc9k36cbFh7gO9g#ot=|1DoOI{~Gw#z0!cnxAE)rXtc!<Evi&TjOd% zn4E+_xpOZI6r=>xf`0VbOG$Si=yKDeG6J`w&BZTgL|Abz3B^``1hsAR$!H_$wLg`Z z_n(Lt;jQvLQ#J$HC9BR4L&Z5&Mh((YzNMBgu6O?pQZd18gTv)!nWL199^XTpb9m(5 zn15=E^?#J2jA@Z$V47CE3wE}tNOAiAqloeY&AbXyObsN#p{n8-6hkzMCqGhCZaVn& zt*$33ztguD@@Zwv_J|KTwZ0VG6v!vN?bSA*-sUjE?Av6hL9Xa;_v7V1EG?Vlb~|R* z9A=E*zJ^%(vY9lzjSyxI({6j~E|B#4Z>!?yPA+}Wjii7X6@%;uH`MUvCF~ry9RQ90 z4M4SzG83hPSm5_8*${y`$kE2*j^k3}*E1$|H+}*jYTXt#Q$%8WhoOZunTi|)Cbomg z#?KG$d06jb-l+MHAl<H|kz`rSsDv)&o9d`x-*$qUb^E^`Km30`e!cziwh1~P0~YFG zJ#ky`7`dByl}+|fu$id>!-U0mGdw5P(pGLZBk8|A$EyE!8@E@_gAP~JeXh$}bvHnk zo4v?C{!RUFq9*hHTSxhLm}RtYbL6g`^D(l>r07FgcHsYdiT~Mc!!s`&C$#bftiP`$ zCtn9sfOq_VloDd~dzMM5iL7w@9lqP|aI^a83EuvG@89ns>W{K@NH51)|F!?iZTnG2 zH7>DC>}c-EDaau~PjEd`YHm--|7~u8F+>ohYG38}WPNwXrc{2=QgqeJpX58-M&@D? zH&c-P-tD-=5`Aw%e~WRKvEqxb6+Q>-k}f^>+rRFUzilvKuFR{|Qk<W*dB8ximp*-~ zaRG_@Hwq7K$1TuweVN&MODt3Rde(~nYu+%)za?fCbwBakoTzpei8fPjyec#nMF6KE z=Vp^&lKB5R0l^1{bu7gVeFc&wH|w{WpU#h8F=6^w!3FFDDE~_4SI29WTh$E8*emoR zoyD~5tmdDaU=`%`0np}eTiJ16A>6;X`p;^sfM6=VizKptr8>gpx^xc(WtPreBzB6X z;m*yeV-<$t^AJ}O(?=Z?yxDQok+M-WKdb*xCBXo?R{ZOk2P=5X<;edIf_(mH1iW*J Zv22@-HH7$I;1(kUxyQ;fB~r$I{|{GaUcUeU literal 114581 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 `k?hU zcLixVfCWngt>Yt1@K1ozda;MTf!L;lvCqL!?4|64gLlE{%u~*smR}RugHwyXg7S`K zJix#96<HPZn+XPSX9Q$^X8FAMfFFGV4a>|4%at>46)lAAsvfjmn%g}*9h~0Bk6#jI z?A)oal$%(jI_~p%sJnfPf0ui28y`ll_dOEEHR2+0Rjc22u8tm7hhO#d?g#m8NIG$v zzTXk(qTu_aQcJ5Q;%2&Rak}u7v)Zxl-3UTVyC<ZnYQ)~qRK`_WGGD=Gp?#min7irn za9t_v>3PplDKP<|6-_%uM3UBfVL4&~qtdn-f%iquJR@Wo9gmEj8VV=xP~J_|aiZ{5 zVh#BozqlE7r$(b{eYP5gxb%GhHtbLLCQt;j)<mw(T3|*04p}RqT}x6}A86PsS<@J+ zjoQA!!{i+fgclGlO|`vcU;}n;H_weg;~$q+y}t$$^FT_8TLZe;doeK$j7pkz>-C-j zPdIgcM#OW71>_j*UzYEN?l*ODw}@Vr>`4D%*r||yGfeZTHjT{9vsL)EMLf3nCZB{r zbda!(iX_i-!U!K<;R_k=1Rgm?AdvDyu@@`-dF!{Xd|K|dnvC0*|C=1g7u&h>_=Y%Q zZc&~pb~zSrD@$vszWGhe553Ik{56rQrywk4gFGLdr&M;oxESD4s5M63{y1Rs;6&Tl z`3IEcNsJ=SHPeNOrIy;ngTOthx|FlM=1TtlwR=N{WKVPEElwfYm_`Q4SMpBXNh1c< z+oy7=xpN@o9c_JcY1UI5#ZsH*#r&{yfO|rrYQfsD%RRw=_Y5DMYCF{c__7JmqJ&;v z-fUmUw3Hmm0jIk6*2=A=gL>rnzK{x{s4E6O&H{20@-Gn0Z|6(%*7MK(b;(k>@{@yf z;hHc_C{s<o7jI;?d*^)MCr8HF0$Mx9e^Ze%O7T7s11cVIaG}7D6HU`k{{S0<4!|h# z9Na)9&aXbvGsraE*vIPoyCJP=JnijIuj8fg_*`=5qbFm>?a{)5h(VU~T^&Y*ECoiF zm`mCt7dXqW1BC&RVSDpFDpS%Cm3>M(0N8FCO>VE5l<YX0JU91GvF7bY-VVD%!4F{! zH#HEAt9aDC9KK~VtX7*hX=b?5^WBFMWNy?>rk!XWk0$obNk&Qqu4u#I%-6SBr}gn* zE#np!VEF~CmRJA}f%esUsnnVm#Q+9~6O<|Jn){Liy_XfmNwY=0y$4@>dToT<ni9L; zyT1?r$*q4!kvB2+d$w$)Jdb^BKYlrKd?$s{06iM5$C-5`<c|&DVfn9OO7ab_+%<t1 z*UGR#LiZeej9?jzm>9iWZj@XJ-6H998n@@2XVB(Vh|8QaQYH_XHRAtD<!WF%l}m~# zKa6qHODTNbMn13odH!rQ<a8RQ&@77ercP>Xy{u?fvu&tTjfx}IHoW8wTALdgf&W?C zV>MVS8gt%vMxYf2>xpV|C+ieK?`F5j)A<@|FkvmtB$9pMlH|-MZH(>m_R;D5WlT_P z;*~f{`dt72zc_uM<mliq{_qanYnB%J7_di2U=wHG^~Iu<9JeWOg3f(1*-HHfrQct> zh=}nud368D7BlM9>g2ww3A?7#y4_f28>{a{(6lldHLH%NxN0`t>R`ow0k4Y~$m6Cb zUO#@N(l4g{0CQse4e4X*c<cDM2C}B&ki@IVSZs!RyCL@>>sLqG*Pzb8@{)>o0QEEg zL}?A!GhH&=p(lkDT<0v2Q{nq&g3tb_<N?MZLPX}$syBLn%1}N}N;)6Qfm~kDa0nS2 zd<)4BKC#e|_Fwcy;m*4k_j`-_Un={=f8d=^*)(kD3hzu)5Eqo|d{L<qGc!dl86<+b z=h&^Nf?NdCWt}bTY|egg?R1JQ5zZr4bnMb>sm^iQrm7XXS~O>He0vOsV=&JeB)$S) zCh`-|N|cQTZZx(#tx5iS@g68OfQ<9*zJZbd&OO*aM@Q8!rTno=5PPX-O;jkRxvZA2 zbDCCdML~P1&UWi6)8T$UXNjBQ2$iTC1dc6wGH|)XOvMhroPHaAe<oQm)mNy^uO}m@ zqCUNt)?r3^qDSi|beV+<H;#!Yn($MRU&`}XpF2~C!H!UfSfdrW@{pyZRx{P0t}lt@ zUJwI^mrP*RwA_0R<lHb6rI3)*bn0C0<UoR@XSH&N?DpC?Ugn%MRYT9mhq#Fjq~|9B z%qcZ^hEHyo8AuYAJoIFosA6wV&dLa&<n1?B(CV~WPibG1S$j{!vsq#Bp550ao>EgD zWF;&ZQhuqLnz#!v!tv|b7O6ma8L}$ny9E1B>Bcsv)A|olKaF4PC@zzohh}S$Q(oRL zp3L!CDpxo0Zu`F_HI4#$l@L5t-Es>^NVEWNq86}2Q~FHCJ&`Typ#zX&(b2d-AO;%= zE*mw$Py^=Gb&k)@wf>Fbgd(?r1LO0wHC9J>Ly@K&gC=mc<suj;fj@qdcvzU_ZEXA` zDQDi~dk(^mNR?f)S4v$1E#GE3q7(hBOA?=7XtZd0B^FJiM&=In7%o9>I`MP)f2gl7 z?c-Ow%a-bs#VlhzM=0?<1uD0<1Ex+-<x#XtX)EI13J&NO!$w}IJL+QUem_WST*Tk0 z%u3n(bO&B>;#gS_xb6#}fv^OI@OUoKqg%O(u-`ppo|||Ov*rn{;Djdt*+6=ahtKG! zOvX+nvIt2VyEDO$=o}FIhd~Xfjbl}wd8)6ean;9h-w4LYe?LVwTVQnJu5)^;fvRX> zVt*tuXx2p`jj-(`c4l1ftA)s#!HBtaNt4ey0Le}@cBmFh1>5hK0d}BeZ{Dx*IUJ1? z<FM*oF4`H4k-Ce{=Ynz;vX)Y;i22{W$N|J!DA+POx2AoE?7ucL?!CWQG74V(Y?ijl zKGfj3FUmc6g|c%5bi77Q_VtdA6*k27=~A5zlOO$D<FN~ly3R>s<pl*qiUHV)e@1BU z#v|SpDk`zN^Z*KBpxLFx3Ce1Z*?r)WwvJWY_x|tXrTa|H#L~Omvn;@xb|s?WbkUiE zwRSqJak&`F4yF{udF^!(t}xw>!tvTg6mBIzd%3ZWadp~OWOccWDl<z;*-b>@(|hsH znu?z~Qg@CypI)=PM8iA^aR@7O2J>5872AD`b*NIY`5mV?0axzdit=Oab@PFQy;Co) zO5@;SXT!ha%im3^&#ILJYf{&BME<kU<2zEsE?*IyIq{SYIC`u8%}?Ri5zgD?2ne#r z7gRnD_}BMx%0a9-_0OC0wr?nlM1M?l<$l?huiR{<JCg)=Yi=eWv*e;X-zS#fsUP=0 z!TRhJE9Gk>BkddI-gmD>m+bN`6YI9lX6PBPD9IZ;8HKI<i~q?v0d^85b?%3c-$r)o zXERe})Oqx67Fog_R6bK>SY23HNCC2&Y#e<XkOR1S+$;eitxm^`84eK?;VHZAk^*Sw zYe?i_x6E;<ZNS|?N7uEOd{}2WIm2{{NT&X(y>~gk!@**^mV)|$u-M$6VL?MnuMZo# z!uCrlOV9h`Dy~=5yoC2Od?wXU&Aa+wg+^?#OdACj@R}a0I#$UvdsT%t@B`6Ko8`_U zIP4V;U+O2$OV(y<8m5oRO5PykeOw!xRv-9`!mY!8->1<O)VV0aC%|a?3#O`B!Mow_ z%yrs-@0WF5_@ApI{#(UlUYRa8)pBz2UyWyBR<I4{QkDO}nh@sp<bKfQ3N1pZn6Nr$ zH*QdXz|3Cv+$=SW#uFB>KPR3Z%cTZidhSq8ujXqV|M?i{eRU!)!<D7)cv@?BS-E-{ zO`4i3Zja=Opc*xtKdE)HEzg|~vUzR^0U>>6O^Ub!S5=~AiCdirRKrei>TkByh5sEK zVkjD4s<=W=IsH+U<|ST8H9giZi;Ir~&iAwx6e2miXz)MM^pDHjh4=^fPc5fW34geX zREY3hLb#N3^gM2RAwhgK!shcOZ)LA_zJ%d!Z;Ni;ZmzdnG=@~e0sSszhCBDr$kSe? z7mc9YKcG+&W-=@Y#0sMi$5kO6;865w;|<50_~8UXAFqbcBCP&KZB($LK?8HI+;t$J zpUU<fE*LUme~UWl4|2Wpb~2jI;L>U@yhZ$)|E;54i&$nf=g9%(nZSeFv1TGkc;=$q ziMjXOmAycI!cg0!Qmj18zYhV5J3GGYLy0z9iGsSux%1QzXQNfZHFN>}iTglM%r1+o z*!aYPXew@?$mS+=^wHKTnh13T^LUuROF7hduz;0O)OJ}Xbr;UPbp}89cjRLE{(ftW zKIrJP`B{4mMTTId9^Fm%^=am8hmo$XZVl-CM>X68KBL)}Ze{7lNUZ7V6W<OESii{E zcXM@h{Wc^Iasa0R7`3QZlDVMGte4)wrLCxq6ryaG5IXZL{`3iiX4@idJgnl^%{Qm# zwKAa{n518(eN6|y0Bgz5GYeOHR;e!FrLDbE>k(d>IN2|Go4tJ^7}jmSa-S25*0M^U zotSq{&bZ-rkq7PLs%-vRjVNH8CR5fo$<A3l&;(B2tT~;AspWh4Hbtt?o(C+nwLz*G zR%qV9BYF4WWo?U2(l_sJHV*`t4xU9L$h4FzkKKA$9P(`H;^bV{uV6et{YZb*=J_P) z`#T)A_kY<J-P&MIOB$1&%a6V_t-t$s_LYt##JDOev#JjQuc;P%XO~ZFd^#tm5A~BE zuFLy7XMK3sAAku+AD!)=qWh)P%Xc{=N}dJwa8*%k(du;0Or^z{U~615HM8^)_<kzT z&&E~A7X1Glm+4Ipzr2xbug?6P*h#aSJ1@ke`6i=CzqYQq1+n$1Gh_1Bi&`P^5sf3p z^GWNo>BsNQEMsW9lbYHP<EVHj*wT_QDDaI;=&!bjV_7A|tDf*zvztaEvdty(=6<>w z%s*SMy1ma~eul)UYBg_%?JQ!Ngs^%XUKWIS<_<}oDHt0b-17RTujVD%ZgMqGX=DTC zIMmZHvk)wu2nCX$PGemIwOzse(CLYZ9WT*C(GeEajSRco@o7Nc3g}E<QWGFg@~+hp zm*=pZSl14X@NlKzUNOLp>{DV5T?5wI6AfC^!c&#SO^lq^*`IuSf1E#79;InIP2;?W zwu%IxmV6>xW{cpDI5meRR3@or&Vqd<WX|0tGpVRoCP0wT4Ps=tx%CSxPRONsD&rMH znnIzbsM^M<GB(B&42E9PjeeNo&DniOCUg;2XP{wqdYkNVUE8OB$CfY0maZ+RU7cxl zTF;+!{p+rMI5j5>xyZj+vf*K1Zl^<;>n}Qc*798Npoq^r(|qq1a+ez>Lzk}Foy29B z48J?Wa49(FUW9ldg-rdo;ipA(cT@jzTRaqiuP^5ya2Cl&eAXx2W#)sp)bHGsJWw+{ z444Z2@Rkj6>#NtT<!2LaJ3GrJEj@DRNxO4!AbxhDp|ddV*yNs70_%D*mTFtnRq%6` zdn8S7gm!!Tx*;60p(}#hzDQlpAvtkB9b?XG^Cd(OHaPw^tLn?*=ge|T|9kgk<X6=g z_>4M$b1+4f7~IM$NcIe1>okHK;an8R`^c9$Ua$Ajj=q!S_p0B%yO?`}p7{KB-`uM< zBRO*v$ei6q$IJ>Cv27cIXG}P@m*8uAAdjX-{treP0~AOy!;19PCr%h~R=4J@KOi7e z9|X!D<z!Y0IJ^6h?^iss)fK-70rmmtK^yS#zv}4fmgkwHo(5eTFYB0^ni`$WPkHii zUQ=)bb1Vq)GDTl+pcQeUs->Ma{szj4Xcx_AIX8AhW_5IRgf!I+0)f;Z^yEZY>a-Xe z`uE~EZ8r^C>&|WGEV<IGWl--s-~r4OJwJ4Yr{*Yq62Mq*{i_>J#!)8*Vrjg%#r)A~ z#z+%dGYG4B`%QL;RG_g-kjGvzWzl(V%9S50K*FWokIQv!KmqH)0I_1UWL%*_4G{-k z414cHp>k39wEPe<CiNFz&BLG~te4xz`VUTLmK6jhiJWK`Eu9QIq5ZDg&P54K_)v)# zM{FmPa5qk_gc)IS1auS;(XGUm-gsSa3IwjWu49#ejhwg7N8b}{L_dZ`rVIW<CC%qo zSHCsCIN;tH1$RyVdwLQc0bWYPK@gxd{CawfzqvDHeoHr;DaZl3_M}!oqnF~mjJ1pk z0X<VQt;_gf-MND;_%5GzP7u|}V^!Qv{1=K%r-(I7_@WJsB^spR6x&!G`Oy|*Z-Hxl zWMm8r6v@BhE3#?iTf2}i)cj*8O8~^$U4UX@o{eN(4W3p4tDy}<>T9mN;mw*l&k=se zzPD)Ipbovt)uJ>OiK^u-^rWuHIJe#leFAA`cHkB~7w4my_)z3OHA0|LYwog*a;o|= z{I;WPW(&me61~xu5zY;s-`SG1Yctjkwr3RSw5tu+T%CAdBu413(CJ)I5^&yjT@syw zzYmLtLjLqE`&oZQ;o*dYTI-S}RxyYYN}kq9ogEE%uE_XDQptJ$4t!m>4?U2QyuC;U z%pc|P!Kb|d>k=%}W8v@0VmsJTSkRGRJ3Xvt>{NN>fBn^rK0G3lg>J3w#jd?sc#-Iz zxMRuoYpOc=4Kk@IkY}B-k;b35H1kzWGVS)&)lPX$Q~c{?BFmbuG;kvU%&+rA^={J@ z4sq^J{Lx~1uiN7<^3+CQq!thF#npf%Dq6DlUEVwVQ)<u6XhdiD1+&oCY^l$tzHa>9 zbxSMaIEdYeAhQd8PI#uGFJ+0WU;&vnEKW$nzH7<hx*T?)AFIrQ>IHc|WWTpdD>99w z8CHMCx^1AAhjhWXIsUO^@-c7yIIzz{CB_zdV-vE$rI2OxeuZ0tQOOh?mn*)qb@?IA zyIEXpiUmaw8+Z$ZNOpa<4{jTuFqCHzGH}Qc4hU`@2YkJfZ0T#X1EkGA%=9r}fL3WL z1+W2ho#Y(&nc_BJY(D+k>rQQYIa%4k#ZY6xQ$}~Y0`}^`BJ*tk!$-2Y6)A_xD!v*O zbZ~h=e0+^R7mrs*ge3^HERJ{J8kbP;HUHYx+SWK9_X}}YD}MdAO}%Vx1}a(jwCy)H zcxvJ?@B*K8YMk)+o9u7-B9xy7-$P3YFf0}>-p0h(Qk1_?cg(x_9D4;6>k(s@a>x{d z$Np99__aF3^T%4o<eXx7-@EOkNv%oLd7K?6$lXdOh{y**=2g55f}qm&AY9Vo`S=`* zG`G--xh<MXPW0~2jG&G9-6la;AHvG--3O+hogRk*X_2bxQ@}7lnj)VCUvxO_w63{+ zb+!g|NZ1J58;-l}V5@+7i&FASj&Er@YB=tAonE|BSa@N`Tya8X(C$`UB1&40CjL>5 z|Daoj?^s(TjizCC9|1*u8j>nepbJ|3uLGE>OP|E-!|wiisLBCBsPy%=y5~-LsjuD} zW;2Sk)D-q7kIJe`rW+|SQyCQG@k<!qNX({+3^qxnd6mTFF1f}%=vGWg@rolj7h70* zr=!ishg#5t@bf+NxI5e$wfMccYO6ur48o#eS=$)K4l#KHET{B!EvBRdF8>6(%3iJZ z{R_&s|AKP$QMlO3-j);_YP=B>2L;KEE8`5h8z~FUDJ)QhW0$Be5lurgse@LsLtb;) z*0>rtZQtcK*iD^WyBgDUUJ9H$CKiV`%QMlJ!^0gS9KTKcHe50d$!nRjKVjGxSf2fA zak~t59^K~-Sa09Iw@pSUi<+gGyvqhDTp<aJ!Egs8jnm7{qv8-uwkxh5pHT9%(s`Mn z`)w9A4=1U+VF2lucNf?QtorRF^UR5F`!7Fcv~OerAvmv9|NODJLb%q>M3VxkH%ttq zq+~xEVvI74CFbvrD}p(*Q)=^tmygs2b|(_=yiemlCRoyeHAmfx2NJ&)@5L;hC&`Pk z%kCv2N24Sg7VGoks{#ZPXkf7ei702|{{2^SAe!sK<E=e>cv5yEh!&nJ4_Z?kg9~r5 za$5@^5+@M^(f32kUOUio(PHpCgM}v^0kKG4Z#x(Nuet0a48Cxi2CK=?bqyohRQP`Y zb*(Y2E#Mch)FE?;+d9iBzsudP6`FV4cR#(HePD_g>IA$3uVrpa-MG~JZjv*Oz)P%V zM4P&<xN(yb(I9!b=6CyAB{lN=$Lw%pvBDybq5c%~T3!rbY&@Sog&7kFI|C|>5}3kN z_IjG1v%=N1HpIJ0>}n4CJoq36A|ls&bRVM+i0d2!v<QOeqxji?f3LS~1rTis$W}kh z+NeGuh(u+X-|_K(TYj8zUnJGdvY^7Ta(d_0BNJOMR{LS)>)@xWB3d5t<NMwo&Sg6v zOy%(^<fVpq?`@RjMHX$$U0HpbF<7<tbnf<Vy7TC$^YXL^@YFdPNUxh#rJTF!snT+A z%^E+RkGqP{o~%(7U?nh`K<bI(M%pi9h5#?C0KUkRr{-t>HJim;+u#3C&V7F==az9^ zZ8{UzwuR5b?!~oerb4*)SJ$lqxQ`g_(zEeR^QT{oi-tNJOG>0cIfh$zTWSimhRA)W zv`tNkF@)ug=_CI$-+<N5)){-ff~jol$S7T1d7JS4uC#t1aSG8U@}%?KVB<U}Lq({4 zmF@PgMd+-ig_SJb^2*XdPLXo2ye^g&G6V{jv$Ygxno7_5O}~&Rnd^J36m)tQWCA_k zMg6;YW?XXx!}yCfS|xWj^-arlEA{+L`=TDh+}K~f{9>wGel`PX+83rA?uf%Rz0Xi^ zkV{Y$%21U42dktf%5zgsh4i|!nj3B?U%{Q03*z(NQ#NM8nvk((tfHY#y<(W?t`m5| zOX=xQ0r7nSX}S!l_Bzqx|3i&o;Ry5}-x91(+|Ykuz5*(B64BYplO)wepAT%BRGkb~ z%BsKM6YWH_{g_Zub8G2dmZYA>=l&`!5A}l<k;coTY|}RQ%p_+gvJ1=3P-<XAEZn)% zwi?>+rTgX>e<>`)^Eb7tx}sIF{>z3_IAbKXv{ml4FvfmfPhIywpg4i}Rjqg-rD{)S zBGgCR2=a5rNe_B=?r7LNjyAj~VZb<C091@MSC@C&Nb|eYe-$$HhH-0KEwIZR;Pf4$ zYJ&`svw7QI6kS>-T2+Ak5asDr3d$R|w{5a~$S|=Km$=eW1b%1S`COpkR|wvuk)<QR zB<eFGP=zJuxfGIob_d@fC3`U+d++zkqkGG7qFb63S%hK&fzZK(;F~MCJ}L@!#-ps2 z<>2lazah@))OM;ToMpWJcRy2Wd?k+Xc5ms+eJSsGw|AZ}4o$bc%SCK%i4*$GVqErp zfT#f}5e0a?rAG4pe{fQR&(=?uM}vU0uv1ZXpZZA0Hzk@uiJlhNp{JUgBm9G-A(!52 zS$3yzyJUEuBN^t=_*F!4z!@>bCTm1WA@9zKkqH<?r2(M8Pe!Rr3Jp*jsRUd)wqciG z-i*$G^PS1O%PIiR056XCD>@FN5&|t0{}ZrDVb!s=m$ozP8k{_96SJBIMhtNb3Q7nR z_k{K|?bfykf1(1`)HLPgPK>9LbCQ>Vjac;Mjd>UsWkr*ZD3p2_q>caX>pzg!6?Z2l zOId8s37GYCAHneITUM!|{dN=%3ZKXOs#CcPXs^3cZHm7o=#W#QR{`=&!FfCUjb_fA z47UZwAs`=bQ2T%Nl!O2El!O)PB=noOXgt2ga$=r|h(G%!us1~8;M-@CLO#)CfC+9n zRx{`>DW3!XI||S48HRY==>?Ypm0s)lJe3l6j@>q4mK|+fUNaAWdr@ts6&rO-1vp~) z1wN&NVGi`*&$c8a0(7@%&^<-1Bz>bG@TZrR5I!+HI_H1x??ct3E0-PHt-3zh{^~Js zwrathZ_-QwS?OOb?n9~m%Ll?}^ns7R={Ir}b%R3npdG%9$5ij<8~BPi#YwGV*efeN zx4L^`sAu5#)j{$B3$bV3=~gG}YJGfKz*7H>DZ>y{RBI{SZAwf^%XfgXjn^iIM67|^ z%2R?mmaHyrNxnPdg>!5RzTHH(P|h<w(RTObk`0%lg`|w-DitBteJV=7;lV0%4vd7S zt#V;ip6JhUX0XYbcC39NVqmi~G>Ws;+rl)HQw1KFMnHFN{Nz)(&J3VOpUTX354&0x z?!S!_+Vg6<x@+`VcGsHPr0bUEZ$$ZTuB>dCMhid-qeue|m_7+QPT8N5SsiflGN&@i z$BxexMnw~0$wo)Lz*U5buf%zG?t^kN4i4f=XsCURZGF7Yr4DA}%}1b!3_Bm-Z`bI# zUl+O%?A#lmqS*3)h4iD-tF}0Yq8Q0r=CkBOwU5cYOgQOJK0tmZ))|IP4>WST5I18! zPhH_@P4YXEKZ!Txo0-6sbRliZOWkg@XuvED?YD`WYy}aa809i-6=Xhrt**vbmpCH1 zMQ?zA5rk`D#Ix`v)gUk2HeNRNZmoP`p_P-DkC?aIWf>=)Fs(OuIq-8x&MN55uk$}g zzVEsSpU?4DRv5mvNq(#!^<((b0kfnH6a796XPgegI)*hSt)DNVvYT9of9o2_SWTk( zb^ppwf5P{`n#1ehJCT@_DZ|>Ldp%5OpI!6i=>v0y_$XGnqvSNLnKciu2ZaWuzh&ZR zn5-O^$3}z@pRzH8>aJQ44?9jxfB$kpAK+SDbsCYbL_IM_1`XE|N5F22itGa<+S07; zRd(!Ygq|O-xhj{}$M@D^o(Qpw9I1?-RCX`JVl9_9gM4)?P<mGJ1<rQAJIp^NefltI z?7&^ASN&~%GdmAZKYacX_A{9!lSV%N$J(bDh-ELf^L)efE{`{Kf5H6S&Bc*z<T#sB zQbJCOjW;>H%BW&wFU2*gTSw4aGDVkWZjo^niA#}Jt$pa>b^dc%fQqLft@~52pejwF zl}1;HF3tuTmp|;2jOnA(QBu~Q&$g0DZ}iiNZuAql64oBy4!wU=JRb)4H2AQ_uNVGv z*-f;%`|w5Rpu9((i0<cQlqeC=Ue5!bk}AQsn0KZwH#iXwR?Zv-_w~3<k1n3JRE!Nc zj)_)!2{36iT%Qd0F_{y_@oeu*hJnIkzvR(d`np&jQHzVzOYIYKrMz%yk@)(3uK)N% zNV1UKRoUe8pqEbMT*WdgM+?=p-$4^ayJ#V8(ZC9-l})s~A{qcGG^IJgLW6^Y!vy_L ziWFkIS?It~9;2f0T@8O~T6Gc*mDE5h??+G|*Z22=Q!TG}3>Rv962AN7TT*fw)k)A6 zc5M$6##EEiMU8SFixbJq<rhUYok$Ok&yODukc#-%#U(4)lTWKCL<HTzNe_N4>$e=6 za4z+oJ~J?Pa(Vpvkv-eOvz#c_L?%7?kO7NPu5nGcV<54&MZrfTv*+EJ17W?OS_h4h zvx#8YlWrJTwJKRe_u<R|5A)Za@I+~KJO*d?#S{hx)kSs6Cuk&M_nAR!Px_{y_}g#v zoxSmF2+YUPzXi8{31<=e6k^M5z$$;=Wi%Cx%&kQs>Z88(qrf;A6_u6l!-BJ`K>V7J zI7zR`Nu~Kp=lN1k6cNKOf|CB#BiZ`X?cLE|1ePt!h)d)3jXo($idd<jt8|*z232|- ze0)}LHMq@~*m|{@#WVp$<1D*Dlajn{<AdtYD(pBiwW^_PC1SQQ6Fl{Kao<jBY9sya zu<k}4)QLur-4j<0-WN>K?Ut22>RXjlcGzP-OuMWX?P<Mn!wQ;cp9f>={@CAhyI%>O zbtao5|G*f~1QDQY%(=x%l-9qi93$enI20ENYmR+rr?QnrhIZ;|HCd?<rOaH2_3MnM zB)QceTMc3|AbI0Wh%x55@;Ul@X1C0Ec^T>46!G0?@%s<6GA$Io*-ud<oqVGCbCbh4 z;$$p&?<qHi%`LoHBL+rCdx5+us@sFR{ntiD!eq48BEYdwiH(gl=n4#<x5RivOJ$es z-ac>X>2#R?$~N)|<k#+Zknx^&=&?V}$)I&${i~h`F`OkAF=ac^2YshA?t_Z>3ItQ* z+zKBh+`aU%+!|S0U88Gn{V=oM!Crc$dD7=M;-*Kj)`+O*YAu0<A7$4o^?wiT8}U(W zx$pB<*X?BYzTE|JGp4U>z5D&*A{EA})@jGNGvc>q?H>j3R^nDLe~><^!Si<muf=r| z1z9U5VH3&MY+v;Bbu8g|Gb^X*<5EkrUxCzix$k}Mg^sRkSuOV?E3qh_o(3r=8rn|y zj|6jGWaKR=K^qn8Fo9pib8l}C$UV>P1!RI1^9AI#S4aJ;1(CF}?(W=;Z?@fiB{U_f z%wbErPrR>Dv9k;e43Lxxd2#`_{CWD1!|&>!OES>x)tsd}FC$SAUIC^LDrGpb7<F2d z=wmtNIAvhjEA5@4BLgg*&uktIXz@hs=;5GGh-(v`Pm>luOg^yn9@Z435y~Kg0;lAg zy2%a^ZC)kAlMfUT{c%aW%?F`RE%$KRu@4i>suFPeqgX5KVDt97ya|>MnIkW+Xx??N zN9qyQS#MI7np5fU8YgjBx_SG?+j!Dh#UosW-On5<3?b7Uqo%OT^t?-1NjVsG?((TD za;CbsZPPRXsGx?aN8M;}w+eS>w{;E<@M$}4PA8Qc-(WnEkhlFM0@TvieDAH_LpVnV ze#Oi~?uWW4d;2(gsu<M2?JEU}LiLyWqGsfJ?aO;i^O%u@kMyqNkVOh9H&|g$O-_6u zpO(fcr@ykkeuIlOxbsWWe8!8$UxXB2R+fa6Iiy^{V3P50`A=U<SSrS%)Z5VaAt$A> zRTv}n_bw@@pW`bik(g#laZDCa1-b+nkaKpN>~{0qXYT@+P5GEV=bC%5BD6Ip6|A^b zPbwN3eA!0>#q3UVzRT7!F|!CN@*_(|G^;Yac(JzC9tVb9GTUZ*Kbxs}o2}e#A4AUj zm~QmyiN1-uC`q`}z3)%sS)yA?RA7R@%V@gWHgm&)c+$q+M@nWcTvw@I(rM)9oV}^4 zAakB?krg>LaKfs}l*3DZtdk)dXXk{K16zZa(r;H*h-pgWCfw}7G@XrMx={J;P7mjj z_E;+|+XSX=DxSNxO{2fXp!Wd}iu`Xmr25e8`0$x>tIO+6*AmDBRg8Ecp3oWXbuk9; zh@(VzgrikFw4SK|?5R%2NHwACJ>DltmRdnjRmR8cF2)vfHm8s}$aB1f(BY_?wpqdc z=?TyLm7}znyuqt-!(Q+}C)3IM0SR|=vsdfUtng}Xz<y-K*S^<b`lfyqOW*^V7+T4} z|9XL|SuNS;XJ9LDz<^Crn)}ZCktGHH#`DHEQHuWZ{;Ck<d#{dsU9bEGrEjxTHh~be zp3!MO6GV(k$$SWr93~6FERR=I+^b7W2>CDt+X${1uWrlnyKgV$G78~VFJ=TxBP~dI zh%`;y@GSr{n(hksiJ*jU#8D*rPb9~MTXh`GejLp8glP%q?VU-keIy5*2!Vzn%B*Bv z*J|=3o~gL8h6sODN{++_<Yi~rA(tsM@qd0$Va1VCqQ3H08NAM=p|9=@a3kBBVX&Mr zswWYL8xtS!r$t4@0FI-G&s<%PQ7C-d$ahiM+0GKE^|f><v@dYG6MZETDS+sJ)F;XK z*=j7z>bcI|<d&k=gCv1xu+d=x2Ir9`0Rds5erq_U3@Gbk1v3uZh{>MbWW&fh-xVU` zP$Oe0e^XNs?W2bw+%|0f8B)5F#ZdPi`tgWq!%Vy~6T33}AqJ6VRXt|9|Cc+LCkC`1 z1f?hUx=ppu)eoDQEwJ2zGv|pI^Hc*oKlP6e#Yome3_}=RD@H7kS~$bDq&M_I)8{He z;5Ng^<q%#xL(H#)1e|^2OnuBDo2mSU>5iF;fp0(gH<+3HE>zfpx6nlgl=K;W?WYNN zYzw~PP4;5`eI#o;*Y1@yPmh72Ci+KKBu5Q6*F#^Fp3<{ea!`K$fmu0yAvBg*^yq)R z&13eb`Tw`G(ax@Od+&p1hx*wqJO+rze)Eds%1jzysmhWNs$yuzpL{o=2_=6i?7quN z(Z8Gg#p#F=mS^vdUcTUPB`T{DKKt&i>~K!EtZ<&Z(j*6~WuiKd@07&2=@?G`NuvGQ zVA59u^6{JMS{wrO7LzK|uRhU{5`kEbh|(gfRP@I#oeX8k3;eaqQ+O5`u-~_Qdq#Y9 zx()JXm81k<aPQaQtYLzC7;fuC3P9JM<KyS&4ZiVh?2U?I7{0KE?!F8W9z%f|sJqjb z#MCItR|i7HuKqlFllm$8qZ~Hw#E02caiif+p%__VF0&uv9&&zp@AcwEH15;xskNI$ zMjns0BRetT5O^t@#@V2zAPex!GLMqgv~!7`#-vf0_yub`nyyp8kG^Fvn+)X^@}>>2 z`?RVUv(4fI?HeO1=~FYg2<A_Ql@II*i(?i(a(B_2Dm1MLO&TiGEOMJY2zK%&C!!GZ zd?b~Nx)*%(xzf@S+5543?bGk-!j5mdz)Q3q(tOEAZqtgR$bst^g>VrL%)-nupIzYW zPQVOZi`Yq*QthpKeNQ1Q1`D+`kKNuL%hGN8Q~jZkpyGvlR!o}>-!s>wqh37<Cr4|b zSk)EjzAiEj6UO-7pr}9Hbf3CMR@R!tj9w%D^z<E#w!&b99tmc5_iLQlw+TnHe|kO| z76~7z*;Ms$%E7J3-M?Miv~~MobJYseX}qqXvEO-@)bsHPyA!n0B~oNXYC~tMHMjy( zbPyp@-OY<;3>=r!^6uzC-i=hQsA|6`)JfV~fBsJ0V_H}L_fXr(AsX<w(<l#cb*{g- z+4u2z&d)!&t6@(kk;|GpQ)TMp{iqJUN6wQEo41r*pR<bV%gejN!^EkJdoSYbeSg7Y zuNS@)VVVcLdF6D3cq@-%j6+*CD2JBghhdMP{XAy7Q?NciJK5+*sHOOW2aJZH(-}Al z-uL*Tl@k#@<hzEKL?Cf#Q;Tg|iVU^<`Njie-5v5>3x--{NG~xp%-!H#q+GWH{w?P) zyG4tvo<xBI<xAX$?4P3Eh2vQ4B$}`vehb7u&vCgiUTNqh4Xo4aClDUn!eb_U>hOt@ zY8hpDQZ{ZE0<L;m=0LQS0{YeST&0`0gwHnBD|aB<fRSQi{~FH4o`&q~j-bJ0xRQnC z^*$WDc;~U1a!DML7!>1VFup>3Q7?4FZ1+TSG)1NqM`@_%B#XA+rDZKKlI|Ojq>XK= zzWd2EgMz|$r@Y_&_a_z^<zl@13$guAe`p&Tw$0P8jJ;v*w|=|eJ1{cRr>Q{u$<I8< z#+%hrlLV{b#T(()J&>6Z&o*3G!4qyc<eV9Y__WO|yrQk`ibJTotS$RwEYy^#CKxoj ziK?;L{yqY~A5wEa6C<#h)ZXBhXknK7;}|q|J%9Z)yu=gt3w{5q5gH6ri*vCtqsTm_ zE%7yt=9T3N$`GO-1(M8pxEE7%jM0K`?fwF<2(4YGR94S}8Zwb0t^SMKKJVA+|AN4w z-4%+Qe!^mk<!zRCVkc&n+W0%<w`ki??S2YjMgDr7Z@(Hw?u5MDPOphDx>ygcetT{+ z(*WNexM4}R`MC8pP6jsQ%=+4{aLcVKgIF{1UUDw$<zqUj$KcjY7m33a2HVK@G72<a z4`>5+iB37$c*RL}umJ$@Fuwl-@Jgk|-tK`!U_PK{x677d*e34AuxOlLLHXjt%}jsr znfR>MM}S6I+iQA}CvPSNw%Q3==<JUa?T-f!9r*l9mF$n<nh5p+u-WG9W&jKS`K{sf zJyS&}cqzqM7nRedSI>VGy|O&j2`Si_7`X^j(s<r#8gu~KP3|C_6Sm~oBb!`;M@5ZU zBDzQ*`1}P^chtv-rj6>c%oa=z>5x=u%&yhV*PNmx1*+U$4`X08p9M4}iWT2zGA9Gz zqP`md7xwW%<!j6OgApxqQr=%;tn_va>U6u;$P^n{M)Hdzovb6O$3efmH`0(IUfJ$X z3EGVw`W}aDoogGiX#Cl^67m?ts*!lHV@l6$`t7?Jaq8?Yc-pfJxWvK3XQQ&RvTSP; zD%?Grd80iOt}uS_FX+XfS(?_XoysK0U=0h<aq4Fl7oEKyVT9bGlN-?|To2>v;$MBh zez(^5);5y(S<&o{H`E9pkxOJ`1Rq=237fOytQNp<An0C0eX|9<a#y;C2@<MusV`z$ zk@>tME0gBK;v9g<Hb#K_I%>&rP2K<%ssOR!BNHI&miB(Vt2F0$_E<&Gj?S0&)IQ6+ zl3KyRFe5#DzzCeTnrpn>Jk}cbdv-B$-yobUFO+TjQl*HQGNxlO`O~O$mfFa0y7wkY zSczBE>OMNDi)9EYdu8$3!9GLqnp$JUllOBN3e5X%Vcf$HuE=D;8y(Ib=MPnEvbs0K ztY{~BKZwQqIh(I_RTxQj3&RcXsmgwF^!GXrQk48K?f8QsUgB{Ur+d=7`wt1ae-SPN zsV-){)}~2+2T$NT0&o^aNTHb=Fj|o+CAp1b0bUvTIg$@gyFYy`Z^P&01YI+MeU2Vt zmbp4dJi*NT+QaNL(9k+QIv@3cuf@{Mp9a@?FCk%JcK1D8NJOvWV~jdi<XWkIq1x^K zTL+W)(@URk^*7uJQ}^|=hKR>@un4%u-7hd``tirzcNFpMV#nQfSn($#c0}Ig$KeEd z#q5*-dk>j|m!XRS_adj~b}U=y%A8j$n20oA7N2E2)O?g{R%NxLND-dVrzS{cz`EKG ze|mt~`6GFOWum^WD2shg1Lxk$S`rbLV)y<9-uu=ammd93|7?GVRZ1V>B-}GFgc$aR zeA^n@VmV6-brq9(R{8ibhtU4zRlV{uV&_v-lvbqVky;yT95x~C$LsyhhcMWtRO6eT zaI)-3=)o;bLu2DGLHLXBYoFegx3&HJ+aE74FM;o`c`aU?ptkcC8v<H(@n)sher$$p zsvf@a{{0$55JU_Sz#;ir!<9uSEZFk;QE1_f#2g5MzRk5cdNK4{&fE^qF^HlJWg|mc zt_5YZD8IykG-TB6UeHFlC&3{{{KbOR@@Go0NY2`W{T-vvFM&e7;ZMP}e0!dZA@Z`P zIp91NynJ_D9wPjFuZkAC<6d{AGLbGxZTT~DgC{>3m|hgt@Z3|C%vHfMORrt+nhfZJ z7Ze~`L7=i{tqx!PyJ1<=oh6lMZz^pT;j)AEVi7Go4o_;~iB`Py57$b*9(hdf2q?(W zXHG^B^rk;2*m{j{l8J!dPeElJx<1}!5VN0Gv`SUQKY)h14u?~TR(^?MB^CAWbD;KG z4Z|Dh&lWYe=$ZYjIuG{ur_2rft(pCPkS(Frz<**5IEcT`AN~RWR6<7LO*Q|^XLvQO zyIK-g-;;r>%4evSV$D3Zo2W6*XsP1C^E1uqBwzn3lt1WJ215!)rxtl1$RQg78Qb79 zjXXPj-((3D#%o@B9Q8;c-JA20StaDf0jiNCMmO=E&E{898}&-n&kc6I_On8aICZ;A z5p&2*Nw^-P#q5xC;=O{a@zayQDegP+-1fmJ+Bd~hUpehB4~1f&7v}?1B42x#J?rfN zZjn5P)#V5ip6U5z{p(1;$0$}Jx3Z6qx}iv{k+Lb?F7QsC{ZxBQmW@FYN5PE83QU1t zhiF(NavaBkVYr&4b&^ozJa3mWQ8P#kI~#Og{w(hH)yvw)Xc0ria}C4`jcgipa6Hw^ z)oHr(-2g4=HM1wK7#Hj@{c^IhKZ{sD;3VaaysKXURs`LrPt`(4?N)X>pHO>mkw{#w zuWilNnwy-f)b|4C^T*ouZ%nbciOI=ff}STVs?xNsooE6f{XXIPXKaSN-oMzE^3=^p z=O##0Zy>(nxdCij{teBebS8A1lEXyDw=a|8wCwn=N}(1iqoL0AZxZXx1v$q2zRjq1 z&0sqlicuNEuIVscPS~4uYpFPHy`=lh4#i30(lMW>U&PKHyR8DPmOivnmzap+b6$n4 zxa3(0?euPob$vlkE2sn>%6m!eh99Yp2cZ{Ic4`0k;mjXDj*hkWUH6X>{XeTeF3`4C z#Fdecw=S9mzJ715Ezhg)yfDO2mBon&H<j&U<K+DDhOn;%bdck-7%^)OPWjnR^7mT4 znk2Rw>q&ayG|nC!mIV$fnzu}6rp2*%`w$|aV$h+~w=0ONx1VsXa*G+Ffb^Fn(8Z^{ ze#UfTrM|@;2tsMxyd7}g8gR#57s2A&mC5A182$R-Da@7yYz%Sft~k%_`(_vX=`G$8 zzu+bGa}D<4Bs{*reN7od20qf;_x~{U6;M%k+uOrX0@5Wdjf8ZkgmkHNhje#$NC*f> zH%g~;mxR(CL!+Q{cYKHU-uwUFSp%|I%i;V^?EUQL*?XUOF)cWh04ba?SEU7dDvmc$ z-znTwYuEhFq2CdX>;&@fS-Qt0FUH~doX9GANj?ha3b#IF&8{8>j(3okldq=lf#+5W zWlx>PZlg6lD2o~ShBQ0D^D|ztHSRf;oRn0m5Mi$Hi0}oeg6Mr?%0Z#OrReR&ox4L1 z`fSh44}q{mVh~Y|<9vnkeOAcg!j>lU44F3ykxYs=e^%eF*Nv(3-lti;>l-7{wC$VZ z(wS>6L|4V~B5R9<yUN^RqL0HY7IwC<%rbRubgD!tBf&K*_x$DpjC(QT+BYjwe~7Kr zS-Zb=EJeI$eIS@->IfUdwf0f9AolaxQEjwh93LYWavyO@BYj7Y^FID5wrYt?7AIyN zpNCg<OmqE|5{@NwZoy*FBts~Gf_m-RC%<}nbK@FGd6|WSt%B=%)<o(n2Fs9y>0gXM zGxyW}&s6aJdqM><yYyW}7+P@Xm&Uk*{t+MEV9!2$Z37tuH~SrgfB#yt!}=fjl2lI7 z&hHVp#`TzTPld7uEEMd%_mwv+M%UKPwJCoz+4V>m{LSIwz2|4B_%ZsS{B2c^cwfQm zVpw%lkV{~MFSo*9HO$I>^w`;!8-o@YyhaO2x$VnKct%K0do_wqy@rXjBH1=c`uNQL zYcVy67*#d3si~>_wk5J*32w>G$*^IxhbXDhTU4eMPaGDVnN+ej$?vjBMBA^PY^Q-c zpxbJ2>~G&ro_(Nyf`vVPpVCCR5Cx3!CF2?Ez)$OF!Bl~w%8+%_#u2&a<$i|4JR9+! zsJ#YNXjY5baVGZ0?d{k44oz^OnszEAe|p^1*_C(A7d56vVJ?k0*70oE*x0=?EAco& z=YJ%^>}UVFtT%}Y2N!1fK%1KQ!|bzh0KJs=T|-kPz`(#i6Y#0>ynNN~CG(hb;L?d{ zeblfOZY#<^jqM*?ixBY`zGEe$|2XC_WJpHjMGf^6y*}TcUNew&#CEEwfj|hPUa6ZQ zaZF4aHq7T(5igQsrlsjr<riSUO0CDICQvIY(?Q<kBKpT+3p>k?*GJNMZFXogBVKT5 z+0Df7o%O>T>XsAvsMah?UZ1pr8`QkaY0U`9KI6Xs@Zo9C)v@G_hkaWok%?>cL3Z;A zwfX^8ieDT%?2YMaP_U^`L-h3LHO+6ThPuV<Fu5AIw_fsmRw}3cWxSA~%IIAxr}5Wh zldq*HdglB%nB&6$QK1*j{QkzAO2VN{TTZek%ENHt-fSo(aP<CyU*yInh7y)8<Vls~ zb?o@`8Cz%Eo~jdoMz3X+m3aXX7qF7;RbyhF;e|@Tq7_8D!ptq02+w)>ZR+4aL~FtF z8MMezw#X*Fs!d9qVX#6Q|B;e;5DL7l6?Q-L@OAKR1s4>>Ki_liT0KX4P}ht@-Vw1@ zzJZ6kyo2-b74c{lscl*q-?R#sQjN>X3L84*8aNK@f2OUYr=o^_<;j1uH|rpt0}|00 zlZV75t}v^YG@`W{SYG+{3H>Ti1Y=RMOv8wxGJZ(I!9If&r>{{(c5gU;v>i{k*tDHM zZ`)5{R}cG`O=omfrV#!q!5>_J7nIO1`9M{+P|}0zb@3HrQv;=uy5)ZN`4YxZM^|LL zu8GpQE1VDZD>Y8ArD$2Tk{lm=FR1A01-EUN++Zx17bKOOTC>4N9#r|7%n_>LpqISO z&Z^{dS)Bd$6O3P506+eO``cVS`&GY^wG77VO;ff=t~={~L`S5P-lB9bhoh1~>mXAc zLzK^@@Tb&W1{h&;^WzJ#+j~fv`k>zr14xxt`GAbF#4G)mVBdx21qppA<j?&p0FZi> zt+|?m#%MZhud9BK+rrA~ReC9ze&y(x`cB$PRQaGtPyCkscg%-o(Z2~DEl-#4?dKA| zXEIb;lJ-ziaX{blNM>p-F|eJ4PYpvfngU9^Hk3|LIcRn5#E!=;a3g7Me{&(?;#6@I z^}*W|DYYi-+4H<6e=COUS0dM%aQe+EP#|_*6$`LwU$ll}0&vtS_1g{ydN5!6Jhc1X ztS-4Pe;?+(BX(<n+p$r31AxtI2hdzK90IZ6^w^t|{FIOo98S^5YJ{_Q!yy1iidu=9 zI4yhW6#U4L{M@F!Y)(DR+`xM_E8SmA%}vTKCcQ!mcLnKT)T7mLrF<R|AO)H}$I+l* zw2)mj@wezm4}Od0(GaYko$B7>Ka^^#*s*Y~%P%fQtaC-5t8YWnsoxiKRU{)OP8*w8 zKx*iZ5)(sjvaN6UiUAH`Pj_Ku-$JZ`r1#QH+<r1Ms(d)$u9Dv=ayA=geJGNa8{(wO zLpU6IBxD8{h7?+V<zgq<O^tVmvD<hjlb5Upy9yBZqz4dl5)d^yrv*{A(U5Xz_PLX| zww{;A96Z&1;M11p{rhYg);RlIJB{4;>+bqTXgKYh>-P!8h~z{%z=|hse%WjyCfZ1R ztJF7dKH7s!;e$7GHzIVxwRjWm9haO;m_NWkbmWm|@!rfVg$xQTv54mkGy3eSeCdrO zgOv~F_oo^2xx4)XKi`4-e4l@+L^1S^dgMsCZQsa5aD^lONoE4l@^cvWbz{V|Rac-> zjrYh{H%a)X_e7~ge;;?54lwiOwhm3gGH52yP%NmQf6k=a7D3c|ceQWRR)O!gM!zxV zH(8OD06Si1-5$tBX+*(_*h7~_Cf>lM7%U~5!44+M^g9CEI9%hq)zC_=MR#qhc15#$ zW`{1kjr!zFq(xrEE|wbHe5dR49@D3P@mm+;APPh@CO@AOiK=gVyf2RVDmbK!F!}<w zaowRNf6n9%BQUI@h1b=3gpRDi0<{dqCFWi#^s15@9LZFPc$(XlC3mB)pim17i{0~c zw-&Nk;cF}~ZP71h$-ZPo^y5k~iFR~8MkaOKbs#c%Yo6sOP;UbZb6@dZ*;Nr3n|d;< zBLJZkpkvs91<S6Kv%HZROnZSdMz52@rIDi%CPpJ)QBe3bx32C)vX(|R?mbZn@jTxr z8rgxLGSX&V+L9NdSZZpyC5&#r%R?*jY&S41^o23A7KX$2nN-V_(!-{A@cGK1ZfJ%Y zkZ`rm0tg0EP)E%Z5T`)VI6)X9iPttYWP?rgtL+SG9zFetnDxpkEpZr137!Epc6w;M z=e@2z?P2Bg=19Ddb5V#hy{lh5UwcRN*3F=1lhmrgij`*7bn7oe&nPjqU@=QS<99E8 zt;N3Dctb8d(_@alMjU0$>$0j$_aU%h(-wTcJXQ8nN}tD8$zx(*=){c`jRf5@nqS)U zuB{#c-in^h<1mL$>h+HgVD6|{S!W;Tj)d2iLog(z<*3<O_3hgzL<4_7__iQIZ#42> z_Z(p6EMdOm`B7vQKems#=ZE;W>x=!04ffeD+tTTv(`YW6ip8*il6@Oz7Klt7ElNN@ zi6uZ*!Bm3|e7l(y$cy+d;)h(Ga8;rWTNCD8ZB^zp>llBFmHhS0hsNrzYc^-N;ldeq zby6l1u!PFT4CO&vt%dN&A9e&stQ#UW`EIRz^r{PaLKlcn7Z~w@3OuGNFVO8aJ~I6Z zDY4-CS@v1Lj+N&;aEVLtm1}xuhMaS}T|dYKX-QyS8qp<#DR)oaF<*L?cJ8cLrF8UW zcyug%$>$Pf$Ee`{-6w>+VuSb0z-pi%?|f-<%61+wF0X9h6mwH}_V{!ix|%$;GDk|g z?Are#Ejsj^Iq;D>#ze<s1ODornHe1iCx?PTu>0_+wZf9W&;WpG_lMrM_n3Y@H7>>T zYY+%Dvz9t0Y<8#jVJ4I(E6xu7dTX0u7+;3h<2Yk<Cwz7*l$oiD0hQ)OO6#O6nK%NB zy`g?jXj3N$MXzNTsbvYNf8^mKy}<?#S9w<W%(wSgY1Ngo9C6ZF1T%ZwaE*5Xu#N-% zi~FrroS+|Tdec4LINvkrV?WzjA;0?%@rSAa!F4rx#N-rQ8NB>wN_@-u`5W8RroReE zcpa=h1tKfgbPDM7?tVN{EXm^0>^@Mg4*6V0v82(R;L9?n!g6^1hGjour|CU(OEGfi zrC?o?e$GUW+&n+NK!xz@zzoR7kpXey6tHo5zvyIf{M@(5F0Xf_=Bo3(E)KlU7`wCY zFS#%TciC|B^G!jdmd9>)tI4cg`+e$JyFoitBpcJMWoe4fc-X3Xwd>}fSNLK%+&<aY z+=@A^WUnmdBSk6nbQq&zCq0`y-Fl<1fS{-(($Ck+{n}k`wmQEaBdq{5kd*j@e+lpR z2s3;|Y9U|`VuX`{Xj!Sy#Qb+vS4cpq6@HrfXs|a-V51>ha)BcpzR!(%MG>^=4N(3( zwy?&U*-=2iuPJN;<2ACuuVU)@xzVjahGA{&l1fb_$8&p1gWAOz<vR7%kVLBk!{;>r zi14`^(_yD2!6F;G2nBmQ!lIB?UmIt){QbVIW_5`4NbPDl8Z)1*%q>SU(>8*Y&ah~G zJ7*4H=jzCF$`)?>YxA`XZS$`jfrs7w$HT_U>g$t}`|o~QdJs10`*C@i5Svn#|KZRh zPv#?q=*TWsP6;EA-J*rtGsm?m*wGv{=0*{9EE_jQ#|mM>9^;#SYkgU0Bqt)qi)lwd zGvQuuv&-Kjy~BU0;ho%I365jI-+>=LB~|^%kDY7ATZ*uJy)VR#{9bZQPJ)hqi{z}t zX=$oDD~1-)UY+3u(<jw`Grg<#P6)kxj(OWg9ikc39aO4gC=o#>6G9{h!Z*^c$VHFQ z4Gq`M-^j#EIQ0#3b5jgPdgUP$4L>gH<@#pvIofsm9m%NjWPl#WfbbIEV~q*$_eoy% zsmUF)j(r{`r2&D4B*_Nk<%YTjD6u1xD)VN4Hr+`wSk|&O@T2$46>cS>XcxUp5R<1- zTB{X$=<%UceOqZO_5^(I%bI?Fb4IU7ymL#4S!)|EPkUJY!t)C#-J)NcP{!<n;(xOD zlYT6%XeOnWj(*gb;k7n1EFww4!TtVWt>;n0s`5G;ea7$fW!~s}=(KTH59T818F}S7 zbZe3Hg8kBm^5qywLFV8t6^wFBR5^!>K4l;ZIlE!!OFb5J&khq%H{Uoo1#T6SejD~y z_5|u8B>W(covm`~2(0(wy1T{Ko?!{vzaaiL{7yy42?y!d9x>Cr|Bxi)@Stq<tfZyH z6Rwi6tJ3)5ptS@c8`Z**!OH%>Jj=0Q(gz0J;^bkf$WIqDXc_G4fUz%j?Oq!XXlS2y z+;FUxolzvG*(h)45Yf(E`+eYA`^;rH!5+CHm3iaz2-SxDlID>vyhTA3DgK~pkkK~8 zI_vmT^CYHpK|S#ESs$JJRwA0NUt@0iQ<w(6?n5$zx?2nY!L(n!9~>~hXx1iwAqTEC z)Osu@@DbBpdaa3PxGy)Eg=6!6W8OGlSqzF7@jYCZXO)OOQ#kPTSjtMVX|N9?l!)9L zaQptS+uBmdhNVIo5->ULTk2Ta3*8ZsU6=82OU!kg)@@|;-xld4FPi;R!L&xZYt_RX zHw{jpXmZIiJ7ue&5oz4&<oWIH%9ZmMbq&r(4~jw;5Yc^jsY_<BODVl*#;4kLoDhR6 zJ@{;bi3grgiNs-z5><($a&_lSz^r2CNKf&Semx$6bX=!9dYmJMn63xA2V7Q%B*d=~ zHF(y&ZVP20e-0zM@paw28SWDuP%MY4p+mo3Z9Wa-u1E7phS(MXZj|AOO-uSU;MdoP z`5drpc$jYQ1BxAe?ym?f?Cqt!yqb$0zr#Yevcq#FkT%+pDPGIV%j=#OmoP#D=USKB zY|jSVP9uKQx0uwq3755651U9u*sd%6VbmV%keDp-Jmj{C_}d<zD$GgvH`Et>sXz*e zndkXZ{lTR?{dBLfd5~tpD*E%3=NK;WLd#bx*ZS#2?y^O;ld6e7Xn?rSmja<f?b&`E zm?~<)XYXY7KEM@DNLZr>jZhnF5Qs-^tG}u_l*pO#yJ)M-(mSt-1Ao#5mY0it)Y%p3 za@G#$=0f>8-x(l;A`wLs{fC8Gkj3q2Z!egFtIX<yGE^0}6EoeFRB$2#cOH?wBvG$k zR@$<i|KRg)b{Q*NY}Iul{qNt=z=k0Na`E5E!nH}|2XiY@KYz$zl5e<4Y^IeJsaXo2 z5%m75A^B*PI(EJAGm}ZXs4_^G9o}@9Gpf_XQn^TUL#4!0QTx*zP+-lTNt5rnFxF}Y zmo~#3uo*GlZ1SRDbF24BqfRa|RPZJoo}dMnKw5x#<mnuz(<4d8%`$oDE042U1;r>8 zt2a65a1rst9dn}%4c;qi^Fx8)0)b}D5SSi?QRW$T*O2J$p($bqU2T@beRtxQLNp>M zEw@imq|uWd-WfCdPrZ^V@1#iXYw$hnMs>#NEGIYoQ9nl`zx5d{L+}M%`u@x;$^3ol zfCX8f-5h+{2e3bk0paxJFNz`L(&c=YJQaczke4TZd!;<OUjEPu?!rCy8e(*T>s(qU zud!|DcYx(GFbqi8>IpCC+JR7b?c|_iU&C3RL|a?0YQC%rX5%nt3%+C1hx?-IjMZ9^ zgN+hAX3}A!QF2(vZS)(a9O9y*Ro$7Cifpb#Ny^{0I>ZvhS@<MoQNL^DJ-#@HMcXEP zHDi}Q(YdfS0UG6;XYdDxr@;M({`d-IWgT-Ijh-rjA_bVYkF!^IMCSreYx;8odH+Ts zn0V`UZBZ^z@V3is{-`!jE}S5rX5^<=V48ZMzSfa&7Rc~9Qa39A4-Fohoy_O3>(MHB zJltVAZjp6Jsj7aO&rK0eqS5s_lH%JQpgx@990e<0`gBFQlOkZH!T-$^Lz>zCFY`*f zS2c@h!-`BG!dtQno;D7YQhg4&^Z|a`?+NAV$<^A))%XH|P4<BcUtGdxxG36?HA~9X zl3NtT(#@_m6Nw=TjZvysBg`T329b**5;>*%m)i}UZ}q|ohDG5oJs-SfaDdP(1A4L4 z2H|}9eSvb%#PCYn&T%Ndr=*~Z_~((hq$C6!oyY;$j!TA!df(i{lw2Z`%j!t1TB}<G z;=E<?*_=2f<n~A&e<yt-Tj<oXQ(4D_RDiEttux9*_eG0OP3H@f4R7Z1qKRCN2YJaU z>cq{{))RaxDmg!iaEw<g?Y>p6J8nQl0cjMGrIqbJci9xCJ8JPpAO6N(8t)6WUQP@a z*;}yLz+NT~R@u6~o?JJ8+nEhu8OA9|qv2|%eJW!u?q~#OsulE2V|^5$@2_>}k$KNW zd6C`H@qrAWUx{f~NoW^~tX_&ZpGt(hn7n_H_x{fK5h9AEJ66go(`l7C5MYGVc(7&k zO04d3KY7^!`WdVLu~hoCwYl5+HK4(bGi{bd-1>^+iL3JGRxIdpl9z|h_IP9Q#&;B1 z_0@qFlG=V0UkJ~oyo^L2|9P$IubGMLS1yrjDZq?c8W8b8ycgi`5P-wi43c#WWvj(k z6>U3xvn@QfNzuw)oX<6%EOVe!B&8<v>*`WE{8_!+8!d!7o3yI$2ceP`Mt`(_<Bbgy z#l=2*W~p97{hW#lHJf>`@iGtX=-1oPG&0ot>u&kR!)~;=q$D#phJtt+6nauobZH7t zgyn}-iQAj<2gxOUtx2xhhF%`HUAGpK<~uzXIFJemI4YGT##bx+iH4uK@aFX51c;37 zmQrs=Mu)?C$Zgy=t6%^?eM-ng1YsRRCZ^(z&dyk?mx%TZYZ&=q@8+vBtVn8S^Kb5K z6OrMa`YNch`+Td(@6pt)8(M^AoCQ{0_#iS4c<7Rj<6?LU0%T`{W_j;>-ncXn#Eo%# z5SOl5mc5pk$0WNq8yo=hCTe=RO`-6V@C;3my$noVG0!u3Njz$BE~PBq2X~g?3yfsp zJ-F(a?3I>7mG6~%mI@i-ya&ECBks5e)k$JjSX;)k@@zM1y<Jc8FsPFXr|(M$O|~Jl zaExkHOZ0~C)cDN&KpXj${J0Lw*@qlBF0Xo%SYaMYoKAG~k15<cCb}MLh-TsOSfm)p zFWWAuGCZ#>FAu^wk5({6B;PtaOTwJ$nx0EK8D#S`fdCn7!`p>>f8`nk3=jRCvn#`D z&DAQH;GMU5dG-=)HsA8mfotTpNK)@9*9#cRj)v9Dj%+WlcU8T=K>ge9$<IHhsuR_> zseZcuKD<@qb2%*wN$=ZAvCW)_xua?8vDQzDHis=~V}Go~H~K!4`DKfGFk{?JZ(xaw z5q8!21wWjxgq2vTFr!u$e)u2`1a?(CAcL-@tl=DUzCEbjXgd>_*z07O#QWl9{`q&h z%OZDS0#hoV^*OwC{oiLA#M!clD>jjLy@^<zn4h8jG0~&1YOP8!Vy{?f0i}SAt(yEg z`dJJ%b(qnTz{xD9@AhAF$DhT8&zT-`VQ^l*evR~~$m#m5A*P)CPQJ95>DO$r^BuUD z<wCb*DQAynD{5Q1L^V`~fN&V-bongZ>pEZ~?Ld{JFZQ%U2*j-CIlxIoGswTP9Z&c~ zqZ7w(igS#ShUERK<3oKe1BcVMnz6a5prjd|UuNce?&+r!!DA0YEmf}P&W8;%QY7bg z==e;zUJJm-^(}K_x8QWOBy@Wnnk!BkMvM#eNJ<vdoXHVJtQT=ZS{t9c!iL-H-}Fyr zTaUfDpft7&jY$`s$)OuCxivHKF>Bn0Uba$+U<zchq;8zuf~Plrrk}W8GX?DUd)fF9 zdDf=6T{Z|pX@G(Mo@-5yjEs6IK48*0?$6iJJoY|!Y~-PhNUN$EHC$NR+C|8pRTdC& z!fQ{1eG*FYen`L6&=sWe8x-RI$+VU-Z?okR=EE3Mi&t`O$hp7KD)Kn7d*^?Ll+b~# zl94))%?BU+(i5+(P@l;0*gZMAmTS&Ny>S7STarnkGgAgV72I>v<V4F`m~AIMFGfWQ z%1-#k+>^&prOgZ+B=C+ZrUhJJPjo5E=P|UkDfRy>nNk#Jt9#uaoLzKyIUMud<79Tb z@$4=7J%a2#wDaNTnUc=pGh0A0A=&R<z(Y<-C3Ryc)X?h3L9_~9a!7?4P8>G%-!;eX zQ_Zs_JUyG{jc97Sf|1t3b}D*r>>rT*{r@7~u9q-5j{Q-MyO4c-<tx%?+<JcSvYGsf zy9%PR6@Pd~K$KmfdbmVDR98_!KdWV$<6qIK8tjrG^rq*J@pDd-hqL?^;@QI)HRJwP zf8!0Ehwv~8GwDU8M*5nq3yGsCCbrA<eib%HB<7L3QdjEF37-)u&&$>piR8U7<dj;; zzkNM9U;b27IVTF|^ZZRo10xL;#}gefT%y&ZCgOY7Cd4GXJrRyl-JD}veC3SX91XYQ zY*Q4tTkD9h4xeO?AKg~GD(cj1WqkFcCliWC-n)M2mzGg663G2-BjXEuP!>N2BgH(; z4ew~+-UqNeJv|$bBL|NfIy#Kq7$5=O`%Q%Qtw#c7Gv8(8=ow|>*^Dn8qMwP7YUukB zwd%8i%(1BK*|Od+bdtj^WX=r&d2es;xeLdufS+_kpA~V00>}2>rhphqBZo$(^V{fG zUnM01kfRFQo4*s(!qDgXBgok$KD)Ni3RNuK>Uyh(?KXq}!QnuPme^0(h@0`&96DdG zf&l?$Z2$Z@J(F_>V1?&S<WxNV%ok~$Qb?TZ7}R&i?E$5U99UH%!~a>;#Ac~8(P=c@ z)38Y70wz8yk7JP$0ss~aEG~sGc2-_*!xRO=@cZ3(x-yP0Meb=y5HZL|VZPrvixmM0 z1oHGkoJWNPjc_{UJMJ(l+pmeiB?B73kiG+kl#bMg?eXjWv2)}SzTX?3nOowjuUg`2 z2_diDEjR@@_dvdC%zYDd<mD!UOngYtt?nhq#M;?)4jP#_VU;GcgSHD-*)2|;s9%Jb zcMUscLHH+I3{y-|XcID-wFm4s{Es0SX<rjuT|3Ng921xxEg7o)Il#|&So2D?DQhgL zUoNB>jt+hF(g8s)pkzP2`u}FKfve;P=HhK}7#c6CuBh6pq{-b6-8DW5G05#>RXw(D zG<r8a!JY5Jd+lyMpFz`gHqs&YP6;vTT!=Hze%FOU+CNOD^+`%5K6~wOX8_I#Tu&H! z54a>JU{oaC<Z(|(Q+VT;^vCo9T^{TaS#xktkH={>{YJBL!%ZhVX)~k*79_huR*rLu z6$WR6I>ssu$kykqEUk|4fYSo+CxP43XsUN-{^RO3O*?*LE@Jg%;=f2;n7@TnV9alS z*lEwiKsMD1Ye`37gWxIg<LZc9<x}32S87JYAN4=`#zIA93{4qeD~DU{MHJXi{gmgM zb8&pGO=e&-anxdhr$9n0p>%jOi<I0Mg~m0+j4M0dRNE?*Q}QZ@OO$8)C5-ez(z297 zvqrJMaboUWZ1VJzck~{{+5bS?B2M0w)144m2z=+qj&>pnze93x70NIMt)<OMI~nhy zhx6h^Y00)<hxM_{qas$P6=eS)dLW$?us&oMwYAQSJ^n0qjGN0&JEDX(JI8S&c5E8U zTYl1S;`*udev0J)0~vfu?MyihoFxXbt{pGn*7Ha`$~enM9p+B1J7+<C?%hmsC5T-< z42V5$=|7pS0!kE2CN`EFUx@N2R}uF!@{M+#$au+LnEcH7ZjH8g45hfuS<7Z}X^h`p z*k~CRkUKHqOf}TcfQcS_b4loIeD;yTXAtC*Ia0%|lKMSbzl~^8ejIb~$s)H7N%Of7 z2xwX7xaZ2dTF$#7X7>_S?N(S<hd-<5PrbcEvfgg5h^CL`4HZ+X3HkY&$hLiKKRum5 z;re`-ph}uge7B_d`^<qz&pG}{&Q;qd+mPok)J@S-qZipH4M&;S1xX<RJx0NUdtsvo z(rGn21OZwS7_XMTVdgKJ?=>IfEhGJ>c<WQw{{hN7(1o$<EVlAarsq2qS+ZiH<E09} znXR9M+AJfR_vaX1zlrf(Ufv{`VHR9I^SmQixh?)>^+?9la0V*bENS_7Q|QhjYC--# zE6U)x<k546k^o|~I_ueuf^`32LW4^*ki9&NL2u+KM84>AVqfL-+v@H4L2`y>qw4E& zrdl-HLVUp0{sAQ-ljQRvYS|<p3!pFQeRh``+1)~=a4JAH{P{7jMvC%t_;7Z7%^Kz* z5E1_z7=nY>-)9myoy#*w093CH#Efe91GgQ6Vn`KSZiSUnC*D7wfKy4ulaw@z%KV@p z@ne>Fg#5+E95x3ML0=`#0tqC^e&(oGfGpb<Z!BJj;!>hqOs`bTD5-jM?Ra=on4Npy zuyoU?w@;*?1S#+%i|l<62+HTKe}D1o2Z6{of7nx^AP{;$A8xmH%)-CH@}%S)dOq^5 zg?5OH(m2oykz?Am?Ya5X8RlBD^Bp6*r{C5Mh-L2@*4Z1q{v~hXnP#n8_lw#_=N_@t zH~$yIZY)^GIDQK#4L^JM7QR#<jjW1VISjUN;w4cpkb|5j`m!YH4zs7gfcVS}OgM^R zWMJvaTcf4an`kplJB`nV9O@1tw{>BJ?Mqt-#p(3aiCZP?-+4sL7G^Mn9@=8II%e60 zq`QxTX%)6vjV!98PoJ14yS*mttfvc{h9M-`O|VzWb+$R%roSV?X#d56Uyrqk9r9My z+Kp*9UF6N$JFMxb+5<h`C4;C_P5FA1jECz$gVTL|P%O94e%W+C%1FjJ8#deCQknu& z6lp)W)C_gXf%FJ%x{g>r-&Ri>-hBdw9qqb-KD!Z&X_nX2)Vr(Vrqk%a?sqk4eFzdT ztH@6E7Zw&AcFG$zKq|H3$DV@|(nI@DBA|uH)(6l=5{J&%{+?_713y)9g(SX(=<%I~ zC>6e+`Xa~DfdG?7FfC3K4^dmDvI#-Q4ZHPBP4&PTri=zcQQ*vRJ53wI+Ts&m(*z`_ ziXmH_3nTMBhs&_x;X<>~d>QZ?l4GPB7{cC0b2^%!5)Y4ODmUN)NmW9@V0wOVM)L%_ zY}@q;L03O#o~0@uac+U8Dp!B?#wxI$MrW2+x13VRPp05P&inZ#Yg$UepS84?Iq)C# z6gu~K;7B*<VWo%<p*_1PEfc@J>!TVy6mTC=G6bmG8_VAQu`s(9fQtn#-R3VEFXIOf zC!$z${2$)b^swvM+OpU+|0VEg+4ZiG2rO_TefFaY{?6GIRBt+H=fm7~>Nyhqujq(> z`hT#K5YDiXmlzqK{>16USVrV&7LH3G8y|p0PtRnj6}DT`=GQ_Aqokq&L?1(pUkTx5 zu}Cdvzp0!R5c|1s1e6xw1pMp{uA6FNon#jtE++IvWp3{6R$#8xD<k`}uDY52^D>#Y zO@oaB^U@mZdpd!+17h|08|C8jN(~Pzu1EbN{?otjF<n;nvl5gJNY*ZHmtl%gPAUli z2xDjZEm(S7WL{LA!VW;8V(_Dh7^)fR8f0w?c=47loh-(3ra~`#r=kV!vzpEj1|sCS z3mFgMpLE=^^I`d@_RlKbdj#N7k*sEYNis5(v8#WditoSbr?j5SjblNo{~kq6iSWgj z^%kSENPR|pc1*tk{ck93m`&`5B6<^G<-x0Y%96vWa^=SjjT~+9$<4r<e%S7{=Yg$U z=B?d<?Lm6t(%pqpeE$t?_{EYRFUs=W`O*)bz&7$(xU9ncFa>6gxZi)gC^Bhv1*7a& zeBIBTH7@3F&X?#MB^KTJ{LyGD^fJ^(2&k#@rcA0e4?E#6Hl~Qo#njYldj94V7ZYt6 zII!P4j4m}E|76Nxh@7YF{fGsvG4qXv`QNmJc<Gh!R&>@8D#GlY%xG>a%o2w^(FOf7 zFuT6nf1kLC5q|_~%l2IHZ7T@{J5^fZ>8>waHkJv`@I^TQe`^W>%L<;cNLqg1C^f4z zaS#g!TQ!nc#OK+5)0W+$|AT~C_(X9yx!+UJa<xkWQ#c?#eoA?Qi<^7nh(4=R@SxS+ zjp62~fmbT?7QZ>H&cHvq9Bn!5OY=vRvhYvL>ZX{&cugh+T}f|k-1x%AxX?kmxD^VE zZ%#c)gIiOnU8xZaSj8WYhYiS7A<1&G+9Cwt$L*1?$-2?39T`zlQAwaOq7W2o1{^4* z1$rOc36BWuC}@f+;LzeyB5V$)hkM^Uh`Q|-@d#!pUHP;Z?HlN|6R)&CP-$D$Qw_e1 z8=>XtHkKWIwg0DhfZP)g&%1ek?b**Q%nDZ9hENBUCxK$t<wiH^z8N3H0J5AC6a=+$ zR8$fu<JD&sV*S56Puu+V$C8?G_3HSSZw`>J4=Olf^vZ=7uS6~omi4G=YU;<m9~h_H zen1T029R!Ltsrsb{Gi5Y-FMW0p;u2kHAXBHEpWMCG{`ixDGS;fth*S{P*HJY^cr_j zV~U0(C}qLL_M5ozWm-8mIrL|`Z!BFb_b<6GMWEo)rI5uNfgTPa=2>^tB3HjSL9x~w z?KIB3n_@rKB>!818P<E7iwIw_1PGIkXn4047Z#XpN|RLtnQvgi+1Hk@nl`H3JN&9E zEd@`-ToSO)&8nr`bb(Kj2Jq!E=$^x<Wlj<M@M8*ou>&Ug{#nG#-95QflU32qM3}e1 z^As^r6%Nh`NhYk{8y{7ne2KQ<UIu!xK7s&-|9G@Fw@34Z4ohbpJc5ZYLAN%i4Brt% zzKv+2#{C6rcBfxYY9u1(&i7zP*E<j0gZ|#YdW#=}He^)0H@kC(xJj*dgtfe`Wphst z7fa;hnW>$}B!7{+kdjKl1OH#Zr5N776Fg}YPAVSM(q>hcdo#+w$nD}SDJhKq$RY!P zjZ=R^3zjRgGC@fIn^)H#UEkx#9&Fn3SdnW43g1%{CDFTgx_<LtQ`n5eWq#yKs;H~S zxUcwPR^Fa)|B>Yw++7yEr3gbOgZe+Ot!EIQtuj7O*AzYoRx)=k@p3RWuC+!jB<{_M z$@nBqX@2@nbHaHDgZ`y9Y~gu`nAvL!+j5=3WTNJWpstOlOXS$9%7A@)wA0wMWQG56 zUh5l4I(B`^Od3W<>-Iw!v^3!KMrzfF^ro=qJN~65G+C(KP*G7abkn?XY+2H*wP0WN z+|nD$y!br77V^F?I>E6QKRMjzrasJy*=K`jO2h8Yu^Sv&71Q|ZWa11&Usbk!4^xa( zs3J|jBoZ~a$Dwi2Zf>tWZb7uAp)$PEG2Q4U86Rx|P5vqDaeR--2>*;PbAmLf5U8A^ zh7GWzp-JWSUFVVh^F2ZEc&4T5chM_LXWo#`$KV22nGY_3URhi=!t+Pw=B8Ph<`Ffx z`7<2T+%M$Zt--Qd((3yMBah2m<Xi?+m$n;j?}qXlIJ6ZHB)^7I7!0YFJPVRUgZDJ^ z!$gm=^nH#a*$joM8h&8sh`*q}x*E47W1j?Nh?s;4Cj`ZFex7ov&~9Eq!o(0H%u#JT zW@`NRmDm{>6?L>N`Vhl8Du78I+Yj!CIG;CnJ_KJ71l*L#SW$A5KJt*Yp0M06Ul0hQ zjwBMrpG-|p=a!X`mTFY?<@L%}IjkA?T;M8SU3q$3eI*3xP`I~JyeDhwzE>iCx4ViT zuo4pC^q^zDZ}_Jfc#yA2h0wo-kBDi%+QP*H$|87YjKp-za*@GtLqJyu2eHr+OUDn3 zn&^tdPl^~pYNBDC+e4O(ehb#}f?`-7+vT4c^ndon|K=Ucy=oANh!5ZW(FLL7kFOeO zWODCj%3%SnJLk1j^{~AZkO>Gv_Q;8eH>WROzP7W&aB@D0OWF*X{2S7<HfJvwC<Y;q zMFwvc78a0wBc`V(TyL`!2|8i>fCC7wweCB~?M(#cMfCoj<ND&DUHr`~7qjQh=-lO< zhS6S6wh#Yc5ua0}ir1f~i3%AQQPj0(b{Ah6IPiKgb|+tIJ*jTd)<iElY}PxhZ-7&$ zr{O>PSw@nsvwH6FDQoko<(`56B*v8QNqa84=C0CdrblZojOPEW_@nWpl7mW<IwEBG zZ9Cqc$FvM#^s<3;f+zx(E`WEz5y-v!eI>fS8r<)Gsb`MZ30FySa)0#1icvkh4O0)2 z21&#-u%s@0U^o@sb-{}f!iy(OKl7!P4H`BJ9X3ORn3|hI|DZz-YkBhO>;zlw2;Zq8 z<B=qu>JIRj6Y4~xQz8(jX@k+Oy3BpbPM_TKojNzOx!d*pQ!+ZH8J6u4nhT?*+Wz|= zuk)Yr;%sGkV*vDh?{ENb7B231yvwP){v|<a``oSlTz$xM4bx(woqydIkxNXr3)@6i zRYhpiB9YvU_}leUc5VW5b@B`?&zrmDEvr{L65Op7>fjtckqtB*4WSh#SvtRo2`I39 ztX=_8mRB0CC;w9A4T(j0|IGX-<tj&gvxsm9FA|w&!9NrE_s!u>#v}AFrs`#ad;B53 z_kFS+s^X->13YFr8EWsG1m<#h&8P@CTunN}hgSxEvGvzvs(Y+C@(y3d1Ul<aZB8?N zaIVRmP;H2SI6O(~{hDW&=!V{?E&$W^OmNlCGH7Khln$bqS@mU0{7o75-r&YrUT!gB za|JaMCp^Da>e6yyn-#a)kUxG}rEs1v`G+!1hs!f%l4iw!0{q8OeTY|hC16gCg^jJ} z*!$bTTgc=1hdF4=V*Cr#Sa*XFd##elbU9PG%jZ-6FnI1d12@7z9&jI?8M9v9FIF#^ zM5BloIUSR+3?Db?Ef&6lMme_pF6z8Mz+>s9MF~c(CS~Dov1<4Bn92f63oFY|*hVPx zAOqt-uu1k=)Wz54G?j}xX^W+*siN@ObQ)Q{Uxb)FpFZ1P)<=Bs68I0W`M^+&=OU5? zY8IyQ0oSur*+QU|n%cO9d67<rLA1LTe$Y=#Xt21q_pXD`*`QtY+pkKRu1{Hr(ys|7 zz8%LUWro+5kxsGRV2RTh;aAb*I$WA2lKUYYBgL=_0?1B-Lgd*N_i5I;qvL9^++kXy zXTvIV<sdxZ=~7yZfCi))OGeq5ie3;+j?ntKw>59B=bm`2x({+LQgp0=I@?v`jS8D- z>lzH8pZ|{cpJ|P!k!?JkkdI4G4<_-yBdO`348FZ;GIzZGTj=U7h|<{{N<rOHh4~Hb z1_H6M{2OOVr0z{@Dit`rA26H>=dFzdepw~RxjHbgka{^BHYE#na6A*>Qm<gYHtLP; z-IvTp>CZo{nglu}08Jr=%7Z~|T%|n+@6>|lbVFUDkme79Dm~F|OHlP@bFbP|+Flk_ z&|MNY016OedI_iI(#BGYZ#}H=lj=L-8ec5zGnfB>iU0VO>bJ_m_*z=?jhhQ3AhB%- zBb>?<Alr+MwhusmCO-D1%XErZb37$?cX>k-klEDBAiT?Un#zVw;GH(Vmh!Sn<7Phq zV^{kpe~$bU0vDaQS#K;ie0O<)oP*Z30<=q=oi+PKBvU+U&W>m8eJmE0FjRZ%d?R+b z_>gwoLX$<$2J!gDGBi-D#r`kX@he7PTgK<ItEKTiEWOHd(yXQ@m+fp{FFM)anyD{_ z%-W6N53dpN%-sREg<s`-t_!34>a&0BPjrg0CQh})ajgWE+CnCqnybsL=a%g|+sf>V z=8pyNX;1nJcLM59E}Ea*mk(yU+qoa`K_JHFP7Mi~`Lk$o-f*F~Y{py;9{#kAnD&CY zbvoy_rLdqR+uw(^QwN?^OI33j4CKxT7y^6Rnv)zKp8^RRBLFZG|9$1*u^E4V()s{$ zST|x;jFxYKWF$eE#$^f3dN|1*YXN=LCEy_7f3mMu5fy13wu4+$x)<tm;pFf)ugoEy z@Tw?=8%c)7_)q9G&f0K_w@0!OzX*#S+}*VK72HiXozu9L$GH4TiV?H>`vIe2oEzVE z`g4)~33?jiZ1<!t^7Jgm6R~PR!_fgLr4FOVIRYjx=0f5*)%MZ9Ehsi9K=b(fmGH1o zR5+Ya|2BPoO@;Sm<ErkW`vC>e3N=}x!^zz#>&sKjEpAq1o=CsE4OR~IKm37pp0UcB zu7F-FZE-9E_{Mqvh(AlFy+OP2T>~$ToRUEt=z4^$^gj?F`J>OQW^F|9pwqhYo(#Bg zFddmdhVVE~r9ZkfiKWv$CWMrYJdGB-Q1ATWs$I9(b*RupW?R^fv{DpxPUHV#)AU8k zrLB#51Q)g{hY8|;;LxL6MoklNWfZwHB>=$>=B3lV57;A_7{tP;{<j;G&jehGz_uv1 z_--1_cZ6DYvtoTTpG!ln;`HoRVl+UVO+e&^D}@Rfw+NCW6Tl4Wy=dH4Ue9}y$U>Q& zctzo>7+U-Ysu;b`XV=U<w?4YxwI)c--&t##R@1k)nJn#WEnU<wJO{aY{{xVZBZ_2v zxgVOW?*(_zb|JFwziI>&`5KAsad2s-_97t8WF9L7662l<?~7ZAVE)|fz^(CpVl4oL zR}SH^L5dqk;|M|-!ibnsiZ47~7M1s2z(2Ti?w7P8{4wc^Tb#N4dROU-Te6TMqBtSM z831b8sQ+#}ImWBMFZjA&1B5L>5QRvn=Rz4HaLpie{l_Fl_{JHG!4ar+Vf_@|2pj#e zU<_3s`K}oGoV|_Cq*=vg-}Th*46wX@=ouCJ5n`!g6O-97{S+o5B~1uw`9Wm=nEd$o zd@?Cc`I4$}q==kgc~J`OWl`?0lednpwz4;xckDR?GsriZt^Ff(?3xgj3iEGB=!@>d zvw{{U)-M0vZH=|MO1y(PZQ`5E$##gXeRvV4ply=UOdk?}6;ug6JRT6y|M)5JttcGi ztkY+@#LpX@GW1jU`@Es|cmJ`?`AmBGl(hcgl$(*DH5{Bt$`y@j{<x%Bk{+dIV$b0I zUN$+<VGNA{^g#dt58%)K?^u#|@40Q{Yf*qw)!5^;aL(}tdjmYe3l71=BB0*^E<DHd zmfd2h8hg4lImhvYxOVzoH*BHm#w~I>?6li&;IAM;Q*a-(|DW$|3qo(djfG+$I$iM6 zfG8L=M)}8*{<8tl5TKW*lk*;%^P)zBN#($o=eJ(Xz&sA_9@b|&+ToIQeb|prPKGdk zU}?1>Q<h%jV055)=&IOY4E)S8GS3zTT&-zBe8q_?$d^>lXqWikIZDiP(d*A(ZSQ<h zm=&|Kc&$U{uLw#Y4|i)ujkc#OFZ-D)JAXTY0wM*?Od_)Qj_VOu(--_Gl${!&?HT{S zO>59hxlZ_CWh3gWt~314pW+6UpN$KLe|Ps_ipC@;iQpUf9KHWZFYT%bidiD#$F7KR zuxY9P<?r6e$jhT;`D|NexEx!8_$LBb4*Gh#r5FP}XJH`i2)uh|!zGxJGM*}=;AI1^ zD4Ce?Z^Hv8{>0~e{(<c-B;lwVjTJcd(A6l`Eu(7``i-lt2WSJ#7H|(Z;$q52s9RY9 zm6X`3PXF2&3_qr)rdE?y79)4;8&N=)7+_C~#$3rpg>FbkM7D%(FE?V%!cCs3#}pu` zJK|!~(*JAd@rhVa=k`k|eU=NO+3@w$t^)(=&Wvqms(EI(sOSUX<8keYNbCD<^z)z2 zFUQp>WRU+YE_UeXZ>O~g`mAn}2fx8xl>xC)ksDG1=1XE_(K7@ja4D-BAGXPF3+elF z^~*)uCmwoFJQlDI_wPp0Syn^0FT~G0bFUZ2pniW!D4GeL+?N%DpCNNs&K3y>Wic+0 z0OPt>>dXKg5TxTqPGj_1Nmu4>u-_Je>M1C+>j8Gw0Rcw^8uvw0hy|SU$IOTS4UIMx zorLFcQo;b`_J}w;kAE|<ZPar96DR^)4A!ISEb&+6_DSdD8)Ri`>f62Y!{)R#_l8c` z%+n6<E&qmw&e>(uT<e1G&kpO|FIRjm;V@q-3e#s%f}=_L@2E~v<j#c$(B2J)H;>qx zeQJ5X&vo{Jcvk-eZP5)@4tighh2wpDXZf&eYaLYh6=Q$%+Ay!-EBXHB>Vuc|HfG8@ zMY{b>uNvT!@}514Gyi=tpddiugdT1U4!5=p*aYz+^OGOWQF&|_dH_TT1Z~f2dQc)N z=ttA4{oF}(&tPNAn&=umZjHolIc-LQ3nZoP4Z2G2^))zM6obncz|bTmk^a4Ny6Woc z*7hH6g#Sa$P~r|fY+Glz-%DNItmuD_qm&rJD3rgh;5NaHF8m5-Tc>7Gz7$lyz*swN zFX7$ehR|wPBf*)Bbyzz?E!>bi{|O8GQ{caMwjnn+cjJCDN!5D)XYkkQ7HTay!It#7 z-8f)1`kDB`EZkYltn#7sTF9b!nN;C?=3Q=GJ*sV;&YL_v=dwl};>Qn@WB>QM77eHK zZu~6u3mi@_1yCJF%-WjdW&1DG*3)$Zhufn`Fygn(1RV%f+b21m-iX?6Hj*djA1#)v zvG+bsi$T?&({s2xXU<cCp?3XysAAyq>n=5o2UPCIVh<c#;4@76Nkejb!VEhD;28F& z(SUkAFg*MUq;X74Osu*H7}aTCv;bs(=+S!UA>`1cYhh{m%EW|vdwW|&O)c~|^5dmr zud;=6lY)n7_16+czpK)n!+!JZZY}dnOE*5UCzLt;3|A%A#M&jixt4=ST((P{rj>z0 z!)IpUVql^EOW%r9L1fI3UjeH(B~hkTgG6ZH#GjT9xZ+;6a0)*L4B=BO&;SZG7zsmC zRu;vEN9Q|iaA;`v_@KEWzquLd^XK$xw><%$4j=x_(FbDkSo(Eex_BM?7I^(^OhP@6 zK!COicKT>d+H4gq%Cy6;ZPQiTY?<m0EW!*DR+F4m3%^ntFowMykrs0j3r8$54M#$I z_rgQLvPwMRoYVl0FGm8y^MS|XxzXsxrw}A2P^;JSq=Li-TVy~bS1gq3whD!}?68Z< zN97A-*GrHl1%@Mtx5rZUxUk&+Uf8&IviBIId=OA&LrkZb7E*1}?~-1{oyI))XR?qN zGz$9IgCY1-!@w8+)=%`&U>|fC#Egn&2ZNM;irJKCw~M6<h*&pGV7}HvLp686nU3&f z?$5~VdabH9e)!H`nGcY;i$%BldX^O3DKw&)0eY<OY14Gn)T7W3hVN^?SjV~Gf7=hw z^EMh6uG-$KvfTSKeGWfS=fx+9HgQJBC&gr1<QVlCAGp!t@PD~cgleOnurEsY=d63- zQ7@YzZwtwT!EatANmMpQBc~6Cfd?_(ovVKAs{zvY)S0zFTVc-&VP=E&?%hKwCot?z zqXv3O!9NZ-oh2{VO6!RIO7Jx6)N<Mtp>Z>NchF`Gy(e>@zmqQzv}nJT51^3^un7!6 zBqkk;LwwM0V8M)Dsq|W))Lz3YmzgD5!()-b9Uhq4iKE<(`#MYYwlX*<fU>$-=bxj* z9dXAZ`#%RdB>|djA|~tkslB1|X9Ykv!+V6E?{f91N;BSkpxS<=o$ulH!~u|bd1Yl! zYeeo5DqD}WC+Z^F&*}x^Qd1)~VzbS(pEkc7(}TB=N}?R(FxBdwq_{eoPCH}@^G!q5 ziZ@iO`hj?ZT1ez(US8AohM@HgLE5i&<kppnFAfFz!3wJ3Hf_Y7*95<;bb914TIQi? z9~geqjLtv%pB-0?EUB#QXZ81Fv9huPI=LyRRBk*9+i{rDGS72ASO#hj=(xdVGskv& zehzaOuJntTuMzDrFz^7y#x~r7wQ+jxca=vo=?~qBFA@~z{mrL4;%W92uH|mjf*)FG zzqyTzC<g1PQZ?IC;ixjF?<P5|synIVKixa@MuDb!q5D}J8_U&G^ycBTP1pUYd>Q^# zV$U&dWiN=}P(pS!X#w~h@_+eLg<ozhj+2TFhIe5cH4-SYX0MU#u7)cemz%bz1O;Kc z4o{Ome-1@sZG`}RoX%|Y{wZ+N(l$%YOS@Igz(`ayoqIi2qO*fis>TC<4X9?)dj>(= z_IMgsFCEGNFAdXFW&3!V0I3fk2Tb<Ne(EMH#0$^3)Lk&_7p4SAJ^Sb?0O@3G9l&z^ z^YybyTr-~U^k)df-I;|04O7<^Fp)nVdmcH4y_bKc3VHe>P9>h2l9g;gHX-gak|{rp z49@DV>9_QL%tl}6ONy~g#BFUvD;NS}dVs4dlxYXiNBfon^S_Hj%c?i)2ne0^^sj?J z+|mL0`?I|I;Y<~c(0`&DT<7!5o$V}-brg`#`><YIm?f1y_})!Z&&tlOi+ff#+<oN^ z6F|R>W_u}B!?)trgRQl?QH{sk(~JQ<nmqi>`vH+$QLY^;$TY}lU;HfMZ;Ud}G-a?H zKB%7-TXcO2t&Rx&@L@d`#Zb<Yh`><WA7w+1CVH2}#DNv%@A*Le?^-ye^pM*jy^g<p z!K$-?K+r~?hL(an{3g}@ne(D<`u||zJiLoh4TE0LmSlF9t(p7oa>HR(uY>dJw<#M- zOUuUF<3WcBS^Bl6t@~)+6))IsT=TnXM_j)fnBdXzAZxc-l!3ef?e|}-kfA%Rj~=33 z2oBp%t^4z!&mfCdkiRo`xScn96gWa}cs9!})&?X@a8N-3;&a#b7ZGm6@w97GYd9E0 z3`Q;yPpvazoV1XT@Z_GUFsy~JciO6`Xwg^MB*e^HBPPxEZ<@Z;ZXl=Hh@_5A=f1i$ zCtlVf%rB1m?{R)%y4Ee_ak<t%jFB(T&p+?+YYo})=L>p@s!V%j)pzecNRxX$Da_=7 zcVD{mpKERUxf_RJaj#*pp*(s=<i32Q1EiU$Q5|Xu!DCBCjxr_qe0GhZ^1PnuiV~Tc z5D~WK`6VWvK;SlCq(BN1<E-IFNN7#2Wr*^x<zzwzu~AxZx=}~6p*Gfdm&WBW4eHx- zYdnGiV21O4)wQcb@`q!BK-?q%tGDeLZdkN(d#0DhzF~U1mbH?v!Achf?r_ZwU)|6G z01ae#*Udfv%!_;q;PA%k(FVKkHRu355r`$`tMe-qr+5}B@EX4}5E3~#Dben$XKhSS z33LEcFt9H?bOzni3GWriD0`NDrE%YW{w3RZ`~(ry+8Tlk#@VF5m-S)v>i?ZH;g6$R zJ((RXB#Mf|;PYRAHpIvjjf8~y9&o1or}gc^vY-+Vv?JFi_4<?Bc-P>b*CxzvezW2R zBLgu_tctd_6)0x()xo~H?hxCi4KPuI+f|2`!OVy9<@C~F0FexNbd})+*{nu4$rhu> zjTM>_X~N}?l{PKB)d3@pd&go#`z-UWaoPx#%KwQ3N5`@LtwFs}9iWk~(%BvinPS+7 zg3!PRJE3FgKOrEM$kiovG&y(ou7kkzrqd&pApRVSO)zn3Q>yyD@+AVaISUVERYkBM z%HrFap3P+b;|lUxXseCBUjm(Z5J%S;iWUCiE8O1yrb45`NW{&XcIN6!lDpgqCAd9d zMl?B2xElu(`qN|s^>G1<z>$dc*#0XD8Z;Ni@LxaDP&dzn)2vxSOjbMLJa)?cH>Tby zgUC^d<?dXt^?KXdEW8@_vt%G4TAxL;z$zJ66pnPe^DB99MybZ6;aj``qYBvFm0S`W zF7{Vcx_}oiPUVsHQ*u|Q2ZJJ3-f?=yMbEO<tlk%+awHU`rT!NUi*Etj3iL$~uojMp zK9IJaPM|R`Gjj<heo4&C{3v>Nq;<Pa_$WsdlKbw;mgzK%?6T#c<xu`S^S6zJz8Ly$ zMunSp#A!=yo6wdQ4}5suyH8%JTyihIAuMvq_91sv8E?z*|C)L6V;~P=uAF$Z_L(4q z?|CQ%!+$KED(2aCX(iBN7I)dso$p*by7NI_sKQB0kf=6nRkwce;Lf{$xd&q0iQ=1m z@6J>8G5NvTB4V^FF76i#qVQ|A0X%*yaC+e^L5zRNhHY*@A{-;wv?1JJ(}pK&JKR;H zPVAXU<BCdY;baNHf}{&yIMDT9G5^=#y5^Ua2~p~Zu3V?5JM@!vg!US<3nnH$ALIaZ zir1p&76>!GWdl4Eiz%96Y4!BLmqZULF!58}IV1^g=4_5ekNU+I%Zo?h{6Bx!<qm=9 zp?N3>RBY7XsK*BoZM<)FjzH{j_S$p?5cKht$QXhJYI_TZF-$}omfX<n+OOyaIKrQN zq>;s`=-6KfQGklx4wwKLht2lkH}^P;$BwER-{)T`Wmry#4o_zwGt^}@Gl;9kIG|S? z?cr_=j$8%0#~mpmFGXeNNSy<Fj!O3qc=T(-#}eFsUh&gGhz2GjgwDW{1wZB*b+jLa zC2Graf7+FU8h8)0K4wyY{%*H-2M=uTSJE&%ZpUqV%8}yCWd9#kUl~>f6Lot?rIiqn z5~QR-x)tf}E<x$;ZjkOy>F$ya1p!IvI;3>Rp}E8RefPP~J^%Ot%*>hCd+oK>j{DI2 zVp*%E^r1nD4c^^2b+ceo=Nb6NcpzOvF|zCkbYX5X7&IVF@{q1Wz{;}jj>Nfc1Ni^b zhl)s5_2m37PzZ=UE6Q|6eK<O7)wm`yilbbO;`0uFKgvH0=qj!|n?5<UwRDHKy3I^C zKXd6{2)A%Z()o%s%QBSuz;%`WKDLOpx=Uw!3JR3qMo($U{}52FPDwLvr}t|XWyXG4 znJ+;l<>l0z<|YRl@TZtT0`2tFsVM+XHUMtqP<^w-@pO7XarNZ)TP%lRC^ztdcirxO z#^SvH0c@>q;PFcg^YX6eZ@KW%^@FI8$9$<H!d0}CB#&t8FNNnG{v0H({I(^SzAQ>n z4S=z0VJHS{OJDN7@Ow8RnGM(-el2}Z{oD1D5{d0><G(K%Kv(jrs&_j-w!qiibbii$ z2g+NZjso~O?g@YX$nZaI36Tp3fcZP$jxHPl|F=lHB@<Cu$AJ;*Z2UPjq6A|zZPJe! zHKh<WN)%^JKfV{<6Ybw4;~AgU0C12>_2m=nVDC_INkhr`yz3)`GXDUn*?%9!+;pKw z`UH@t0R7V_|2^dmjG2Qkg0#fv@xgU>;ORLF;99<NS-dPT_gx^<{aiD>F4pnaOyN@v zzEqah&tmY-+V4BFU$+@TM~nL25P(`bU*Xbkb}soOyLEP|{CM(R)7{?&RR0%~qM{~8 z)O%QfK1~&{)SuI2x%vZ8%@l}gu%F=Gy58A?3!nDTw6wJ5eT(s%?dik|v)5Xlg6H<s za(GTI9|_MUjb^QQK#y7@M4-{q(EP<Y2I49}!ejeY)i=;=O^1^*&h6eDAu0MN>wggm zs@z0+_0`)W9~M4zh_Ip}xpn8gnnXsB4PZUn_5;<Qw|CYPQxZU0<<UZ+Lmgl5Uo72p zF3juxZd_QE$!#bbu7ohz@{Vs`e2jcE)K*T>5-0$|2oU^)wW5hhTn#&_J&3){frE`G zop>?MYyjEI(?{ylQRkz6oyhFLY6z*YwRPp3;R{~?8~{xF=xG5uAMf$5JUf5|5`Wl* zj}v+I)KsuH;Xs446D<zY=LTdJ$gD9Ek29Y+|6%n}t2_OFC?b<vp^Tywcbi7f5{>p7 znyyI%)n|>9XqMJ5W+!N?3kZvyP$pY}%ZG2{jGI}o>PN%Z3UMgs!?9yR`aNCnC<tg& z8f!Yg_c0(?-nnb>kune1|FadSa+8u?-EAGX3}YfdY$p}PSFYBJQb~{xHi5SVur0jd zN@CVGbfzt?sOW7PN?P5{iwc_)RKc*lr6B8{Uo#I-O;Swxbdc?*pe@|*>{(?aMm?CG zt{9i~a{9h>m*-I8Q^G#DZkq{X;P~Ad;ajKL2<Y~Zl5Bt>y<&e)1$>qqb)A#5z1sTA zVpAjq42XxEZw9KZWl5kB@({OUH3%hVlQ@7bMwhHKr74KU5S*RKx{4}1f{{%Y5ZinJ z&;(g&X&MPKWTmMIip=x!>)Kyy03^8FAId$UDqln3At^j(c`4Msd1f@kV@{UV7Qc!Y z`6-uD^(7c{jEFw^^@iG)5H^r<h4o0}w6+m@P*O-a18ZI#jV~+mCR#DsFCUc~{yF<G zPe1o;*6No>9@RTD?b?@xuj4X{*@CCRh_M}UC5(SI5QE`e%*1@`LsoKSPA}i}zb`2E z+%vKf_9tuXCsu^rdLJ08)8~o&P;Tel@s!7@nXe)KzyPYR-KY5(4-XIP+(QUdT#)dy zhyxB=#dLnz1JXweIFdb70|-G}W&p;pEUhg!c}O#LHj{6QnqN<OzH}?j%W=7k2XQ;Q z(Q&q5Sm+T-ZxXT}&12E(Y_iJYW8zoWQy2Xfh~NU{@eme=&T&|nn}s8R6Xw<_eA9jM z0HB0FeR4lF8TDf_=rlh`NFX!%E){d+V{oAUX;FDy01WM)j>$xUv{B<d2OkB!L&ce^ z!j_$pv2{oH%U>b5J-<E5>45+o&o=Fszib7g;gXFc;S3xA9KM33{FBKp-18%Ty-C5^ zDZJ}#wmJ8vDqdC9#A<YJ=w!z<2ihW=b}#d?!ihtI<N{dgbf|JoecJyU8B7)($842* z?OQL)*FOYxy*W(8_P@!wP0wlTdLa-`!L9HVOZ6!~WS6S|2U68vX@$t>!vjHo<1%C! zTIn0{?1~?jzI?JKZES2ETZ098W@po-K4BqGLzCH@_4SZbL$?W8O!Y-=yN(PdtSWXL z>e^i}_0*@gU0tAiU{eq1CwsV0UqJG{&k8=Wz**@A&llVZ*V7SFoO#8-(pkU^(Q*5= zN#2k{bq0JRfKa{XX%(}*ZwMEyn^qU@ZABqFQm*~qOZToyzGDW-(MV0aM~{A|*W&TG zW5=LnNBb(`_dsuHu=`d07<MaO1GUN&2>T7e$w_H3DfI`ZK;P1`9IyEl1239kVpXnd zz>K+S%x)^3j&mkR&{A)P&h~)swHl{waVFSzrur8kqyf=Hy-?Faq`c65_MG7xdU_m? zjsShU!t+8|KFnInhZhx4vaa2!G7RXUQ1aEwk>5F`dm4)RXzAq!pX9PuPkt)9Fy^dl z!l6UjCnm=D7)gYtW<Fq$-|EZ^vPuH$n6D3WNCoA2w-VfLI{R2Pb3!}Zw?OUmxvkHp z-rE|t`Ir$eoHNkb-)X7!^)x5drP0$qW0P)A-vW3@f-C4iji#y!?i~P$31-NJJdMoW z-rjbE$K=2Be0!8k)G<sl{5`u4$(h;*&Oqk_`37aB0T$J{s~Y5pjhpY8CMS{F<cxDV z;$>O45BQq^<1b8!p;~eIYqW5q`Pa{6%k=7icsRky`|Wro{ESceYA2M8dj(i!tKW-@ zYN9>k_`mVbK&dLgHsK&F|D`>`hTJECI8Q%UyAE&#TQldtCA|n~S}YAavM4i*H73?k zK%@$d?}WSwVxfI~gu0?Dw(*aA=xe`A!_=|kd&4i+g@~375}!Vi8^Wi2UOOFULxzPd zg=z^S9cCA-kqJ>r{&OLNF^?V3=ibZbG;*TqoJEDvC8K;Gq>OnU&J3t_`^QFE;G5j` zP4d14C-IGd0ESUt1S=mpYA>*g`=61WaGBb0S!YJV)URT{?08@Om|u$e!oe3~;bP$V zft&$l44Y4jTosa@qD_(&A0Bs(?y0UFnZ`8j{owufzek1cx>NSu>g<=5(zl;oOp#Pp zu<BIqnizhF=VV{2_4_0p@`TQ-(AfU+QL&Ufz1V+^={W-C^z=!nWtZ*!kC%h+{%Zz& z>youI0dDZ(qK=HfzyA)Uii!$BW5pu_nj_EE{*=m{ihf9gY$QQ!ddSNkZZUCfKr(hX z{fP9Z46<Cn{vOTf3{7!)B4P^T;@JF_#$)D4Vq}eof&!l5>oeh!tzbzu_b(t9mwmoc zGs^y_RN`>sh$)(BI(8?9CATTi0;;YEdYj~KTiJx)b#M}L*H#7EwNs(fB`9PtJ|QiR z64kUG)>{~e+P+P$h_B~;TR1_d89%ZnG*9)nD_a{s5tJxb#+I@BV6iO4Z?1^9Ody1q zD1&<VG#!wYOEmUYzj^Qr$bJ`2@Y0Q_^*6)eo$u#34L;Wd`dwp7*;C@0NdC5m*Ocor zOkAmUZfh?^iY8BHzPfs?1FSZYO4IzZOOYDu3;MRg2~ml=@&(y~@uX-6kWk-K8uL)) zFO08VO*rOE(T}Ymn`<F)a-o)2zPhRrdt<QH@Wt*mOJQ=v_aJO{6F8()>{?>s;P!PB z1z|M7V9qLGFCqmflS0E8Yq`~nG4~a6V`blQBy8kO$?bH6^Z5%wFmY|TvWb(+4&h_3 z*?%~uXYdUb@ElfM|ET>qoZt`Olu41PQg0};*~J0GT2xw!dT{V>G%SnXEN+fm0TCFz zC_Kpu<_vQH84gH<IE=NmiI7ft&4R#7s?ykyJ2-_bS(7Jk{W9#YlEuVF+EB~)(~xEL zsHG?ocRV9yZTgOiIX|%T&WC;n>Z0iVw6fXt!*2#Q$o?R5OQ3)=k^iQ9abywB-qy|p zHxh+@e(UynB4OpGtHi*=!<8o3?A1zyAzKs?6ToWP^lK~Mw_3+rCy&uQgIs2)JYzTL z#q<l><Q3Gc%A3bg;|A@De9a25<%r4GS030VM4Ah0wc%P-KU(v$R4eq52l#i+I2s%{ z`&pQzxpWn3`{qeg$?Py2sbm{q^JSp)yh8e|;4gW!W@&J={tS|~1pkEtUPuMSvq7^T zlbWD~om;#ow3kwbA#t2b{v$1O5Cy^yGi>|6zHmt0>wEAJQlV=1^r#<1j-KtJZ%E_6 zi*HJEdlyHrdQqJZpd1L-0x>^k8Sv^iI5PT8^jt6)G+}t9wsTx?9GK9}gB?ZuW;I6; zTk5RfKCVp{#k&tOXV$%CZG0p!`u#<BDBNBtlA0x+Mu$lL`I$tl#q+a_01*F7)6vsE zxu1Y{5#%YtFA4ZYQt~Z;8cEycw=+9QjHBbW(A+M}sC6NT<lq2+*tQ$Ow4BCTN;cnk z3F&-YYJRf?f8ENlaYyECYFJC(C82fXRm@1jl)$X(1@!Xg1<OtJsk^n~Y^ZggmG4_! z1EPwO3e^Bv!V#`{(o0!kV1VekK&-$UoM!hpe<ShWq!{!>RX8zNB1=n^zeN-fQi_q- zFwWGtw*H`*>dazTukG#m9pz})2Zb-j`mVJ|hkzfQ1l(f?+eKt7oy24Px<yZfv?|zG zymA89Lxu?S=|U1sQPt(r0tXPNWJsUuI7IlLzV<@`i`?=-T-je$2%(D^Gs$io*C;Cn zO%E%FHPA@<<M9QzSA;)M)R17w5wW=CL<}H&xvQ03Sy$y1)G6z=ITr5}MV2F>ThCWy zlRAqO$RbfQn1B$*BSX|Z@H~I0_1=~_)fY;LT2vx%yA?<DJ{#I5$+ISlL&P<CM&lww zLV9O?T_e@+kLq{iLfHoieTk^F-uk3AyPR#CyF;vI7$RUX@CEM~A~M$N|IEBWWt5;c zQ?m?SBH2%@3LirdYnNZol>;yCbI9RuINXK91zx@qY&mD8=h5$8()q&v)oZY@abX42 z)+!!Yi@QnVcw0|a+Yh~oIOu1Gf2mlzO2b9C>n~YT@=#%cceV7W@eseQwYY@!2cO4J z8&lo(ZhMyc1R|W|D+0o3<LZbhZKQ`5g<cp(Nj(4d;Eo98-P&^`QP#AWm&{0*D?Pwm zgqZOy4dX+!C_GDja^UxNTpjNe|6iND%MXhEH>8X3JKNsamE4~`bhgcQkb;Y-l2@m@ z<k^6$Q%Uf3Vjurj5oV&@G9oayt`W*&Bk9t7M$f(T2I+`#=J???$$<Mt!dFRdpNxoi z2pgCO)$84cK%L33KGyvt3F6sv{8REm0mrgB5G-MF?&myUy$^Vvpa}-0s)mN|-5o#R zr>4E`uRTf<nQ{7U?`Y)db6-k=)}$_yWZd;Rz}gPp`PnBL#x^BZIO0K(2^`1!H?6rj zK3`wmn0)QdE1gv-`VW5zyc&=V<|+Kt(?y_yj0%Z<kQd1tJ(i8{)@m&wZnH0sD2rBz zG5iQi3Ap(Wm-D=dkD|dhKQ7$%^j~9Nf%U&jVP|o!m|Z6y#ncf{>>e;Op2glsAN&dz zMM7@0`<!ry6PV(qMqvohzSP-3^ma(_mqb|eu*CZ!d9{S{ideI9T|S(nnWDUhG~?}R z;oHax4a~&9s5;)o{%?_ouGZl(5-SEA7I6#UlI2xwx8LyO!$oM&4<y=78KQnAraXQ? zB>`RDMja&k9B2&Gk%8i2j*c@e8$t@CfRfU2lrkB%EdM-NXC}D;DHWvBvDw-9Q_j;I zyTa~pjwO49`PdK-3LQ&=^43>l6q3~Syo|40J?*kUFOpBe5;2BOQb;Dzk+MoFWevQ7 zT*as1pUbWx7AF_>@X;Ch1|KtU#BbxMR_af>8w4MZa4^0MmpJK=0B5ly`Pw%_X3mtc z%9JaEc5EZ*`2_Q?7bUR4-Wy0^7w)@r;(cgQ5m644SKw*M4oojf^ROgg{nWSe5hdE| zdr+opr)_-%8V!A+JT-w1?P|$i#;d=cc+!njms`;kaQM-QcDn>fmx%n@41W@A@5fQ) z2;Lp<vXLz4c5f-q-#=d3RJFN$_p66NVK*Wsy>d!43wxGJCzXBW`Cf;0M^+W63JK%~ zWC4yVoZ}>9y$`I;uS~dm&0EP}aEJBKj+WUzxT6JG;U%m0HP9!{Cr*WC-Sqy8u_}F` zI*}Y&N~zn!o12zmoGvH5>n@r=54+z=QcRH)PG_?hh?<XFxI`B5l-fXJOhUO5LrRs$ zj>K(Wd@>*qP3CH>7nWpRm@`7>OM@%rdWVjLWM|s+x)crxTd$+bzg0--#LDS3!`5Zf zUy;q4SIsZ(XHX~b@?3N;_lH9YbtrcfjrCg>A4uU>=n+cZPH7<LVE)F$E76A+@(xAu zUK2QLjsInET|>iz235bZOhaluGeuHHrWzsYHA6Veu<q8!H@*6-{F(Iq+cPR1pHKS> zo<xSW-ve*um5z5tdB0Z8@EN1?NzWc;{yAVkd3W$w7K7atH#rRDyIxv0Mrp-4SfWaU zMX~N9+Tt%P9Kon*d|SiA!J{+Yti#04)s#Yl><&A$a(<2*6c;D><RMcG>W0Uwy>B}n z+b-ztDC$p=R4gCS1C`)1_}3LT1&nz(0Qwfs{WdpYa)f}6Tmae1%j6-)uyx_;K*^H5 znK$bN>0kApvn_3Gy6aZyLLAo{Vzej*$+p=Zr#S+`CgS8a&|aqtBi@+bBZ|r_uG3@4 zS*qD74PdtPzZ+9YB5NwsDc6BN>|5~LEhJZ+IE*Qat$R7ABwflyT2Fs7oC1N1G;d{l z0@3}m3$ICj#54H@O3_mn{BU^S%hhKSr4p0+`KUW9LIj+N1WPS#?We~TaB4v}72Ke^ zJ5SKu%eQ!j+}p`)+rlZ|8os#|b%h)0vu_0kuV?9h4y(=BHYy2m6XPNgLJ2y0D^){r z+m_$P_UF#dR@<rgoePmh5J@9kH2gy3>Q-{@Hri*oy@~_(q7~yBDd?bZZLWn#_#|;{ zDEqpYL=@{}TiPttDDktIKkVBg>S!qc@d{zm+rm&@p^xm`{a}(p$l@LL_X`TW)uLsy z{mc3aeNZlffaKK*Oc_td{TsY=TnE1RWs>cT9qNs-<6{Qfj}%_+7hscz0!`%HlT~DD zDj^6P6n_tnumOl-oNQFODbPFapTsy~_2RHoVkOn6YABQMAaB$-;9n6n`W6-sV1KS{ z+{>8aeXZ=NJFKESLwX18*2E^|>xB=QT6Fywy9xp!-R>_oC6Y~1d&T@HO>%XVR;MnG z9f8l}6vyc4CCP+ofORduQz6pm=*+R1=&2sDEE(<U+Pl!yyQN=X>+*c)#vm&`-sfnH z`GP>oGv~jCC|U0O%Mi&M_>tOtEjdn0`AKIB-<h41fp>LF_dDiz!3d9^L%ugyY}`tE zBS!#%Syuqz_TCCQJ-$>v)5=u_zrhW=<II7R%^F#M{;m+AK?^f)(}5O-;l#J}!1(hG zug3`NURSlQYYdm$IrJOtbwd-4*lle@gv`?wkk11sE^v^s32a@yvx<Z7`dEC4ll;kh z)))q{#v;g@9K697auahsKw*T7(}mkmLWNz6At*HEw9>FC=}i5})D~^lcqQ~Nt})MW z6t!b}EfqhvZntbU<*57LFvPnDM5^!f<*jT#G<rndGe|V0lZ2k^tF2t_pn}FrKHhR2 zqcz^C*w$%j#5ibSbySOvDgHG0$k5g>#6_+p|F}iU=iWtvJlK_)<tsmI{#@U^8;CjX zl0-cfDNd7p1+2qH)^YhC3WA+5NKB^09duk$CnG2{Q4vih$%^AR{y&wL1Ju|&^C=S; zK9Gw*tj@@tN)QP8n@SMy4s`l^33X8nLbV~7swi22Z`tdlQAT2cSe9>way`W(^(0~Q z<oA(6irNjLIc*$2<N}`;+rc%FP#f7Qo@Ta@@qX$v6N#far0=KNIzxwuCrG%SpHIp> z98ySjafs75+w0hS4ePOp^$GlqxA@#Wxysge;K{5bB-;JkdKy{oQ-4$p>tG-#LZ{p< zQ4M1*I<@)xNh+W`F?>tN6|uWQ<An2n|6aPlh>AC*o7YD(y4Q!;Qum2)s?g%FItu*g z6Bx4ikB-6l?g~%(gp(IJ;6T58Q&N=8{Y(mtN#eM%M)&$c1!+z)=IUm_?UjzVtG(dp zGknSB$H@&-EbBme5LK;iZ(NrOc=-E&KxwnKHlajmwh!~~m8Q&K<8;f~YahTq9_n4Y z%^Gomz%o<P2B5kV`&}e|jW>AyL<N2>5j<VP1ptW1j-~X6cR!~N!>&5QIYT-+A}Qde zjZKB{3J*asLs&kG8nEyp8{h{LYpFqfg7{rQAY1+HY_G&$zv$_+p3pUBW|5vMYU+pn z&)GUCmz0((LX_G)Z;LeJN?RtMck)VghaxB+`E$ksBe+$re$9`13+yj3-o>%Jlbafn zLpu)Hd4>Cx`t1FyG=FrICejMZi<%F*WiAc`Vc))Ci#!!I|8ox~uu~XS-9$CIhmy`e z5JEo1sX|)4;HQQM@ZJMKSn^dWrj+ShhY0;g7m)_x_R(1@>>%?#ZX_N7h7W{TJ8CQ6 zmE$a|O!IzYAE%oEa7%g^ZQ)aFD!gjeR%En1-f@LE9f87_Lsb9jFKi~sG3R|^K_D2G zA`#U8jBZ>^htoCiXI(NvZ7uf3FdSK)z+!<{i4$(|VjY|JP2BP49Dl2v&~I^4pQC~m zCkRwc?>K$R*9H(%X_hc`;_|JGapt`K;-0@ZjQsm)wHh9lng1p)q`sr@H&~MI`VnRJ zqo9sH*p&q%blD{!6tVX>G*O^)2x<CB3;?}9#>U1^md#yz7ilE$qU4Iy*q?T@p@FRr zHs)D*E=>szwH1%8X#W8yR4D1+lqd+X15k5S7vj$-zbW;fE3!S@2*{g9+Am8GhG6Zu zp%i&t3?|v$Dx#96BpajMD=bPt<cR53$%KCX^RU&Z3`C>u?-<mW@~zeK3*+^ZjfCf$ z_vLNss$`8~XbrUF8)GKgPJU}B5gX`-g#G!)c`^mU3@OvPOC5*WQeg_Cr3g5%C?5}* z)^TW<)Hf`e;;!fC<8Cjsn_1gX&sAh0(n~sv+lDHVG;v{CQHh}Dh69SfbOo%YW-X=` z_F0IEyR;z0)UZK;?yuAkRCp71RYgU}YcCkv{;?(e%e4b~7eq7eE++V~J)8ub;7@@Y z>xLF7i6Bba+6?!~J`-fTNc_5g9851!Bp_-taII-?ws?Jwo(-l5DuvC>|GYn=%HY=M zd8E5~cnh}wdO-nUo1j`?S{i6Q=a)M+G4Wp~pY!_jZ--4aRBaZi39^7YvqTlg9zBQ( z>cty9h%BN7v_rEv4Pwc{B&~QCwBC46Udd!l&l9FlEUn>Qw|95Dg}|Q=#j#N8_iQg? zQ)9-&q?2Zc2gHm0zWOR|u4+DA|NO2^*TAab3HdO`A6r8coJr+G(R9wC70{RydLyKf zIKxNNvUNM1hnGJW`Av`=cw@8+yJZTCwhM~}2<JUBJw-Kz|Gj+8EnP>2{tglOl>~tv zL+{J}=|3~XB?jZK@JKnlZzB?cB`2OX;`H=$OG{kS<L9RC)$_IT!GRORC~w0kBlc(r zAG{24bs=~SfE2S+Z2Dq${`DO?HhlG<@W9AuPJp{K!Gd})W1orKuQ_ZfHcCqe!u0&M zl{bV1tmeJTE7-1Qd?fm+hoL-+=F8N~$K6`M2?6f!Gmu;5`tK8z6MFx1MLOdwJ1&~; z=L6_86+~1rBDCtl>51Q{IIE}&qBV%``S~#oyQTTqDr#LVhw2O@DRHtKQfc<m6o!(& zp!^@{8_)!mRcbM^R<z;?a7f-^rp+S>UVZ5IQQI-yHx5nL9SC4NfR}cDZs2t6QiPdc zJAjMS8)oED%TsA%p7F<=_xQq{<h}ZyhFbe0QeUOGX6O5zDBhLuVGnCAO7WgazbE>Q zkue#{s!lqII-TKQ&Q<+~GLXsIS47EA@61kkuPhv-=^QI(LIwjm>jqwf?kcN4W7+x= z2ftm=XJ?bIrb)78X{WWlH=#F2T7LM@>tBkXUq9`Es5Xt_sr2gZDDOtH*)-R`TQu}! zS&75oke7t4e7dH=YHNL)vR*5?E9|u&Y#O4ehJhcIXg5dzta74`WOwLSd!70)o`Vdm zC^}rWOW$VfWUYzU6PZfI2@d3_S6{=!^ktIl0=o~^9sc?%2M?zFU~+@{OpdqAZxHi8 z>G9WXx&H%ay>5YNU=FS2LgVmLoVD|^-0VJ@YPI4KE#DT&mJ5qsa|YO#fKk*Glw7yG zd|B}N=~T|i8Fe08XvM=2zkSR@Gnhst@zKfs&e&F9_y+NKK+I2`v$T2t4dDz)-p_LT zI!gJEo#+PA*vy@Exk~-n9n&@BVHYpywGipNaa}jXNkrvV>Q~vQ18sAeCA+3V`n{1o zb<?{RpgUIvnNdqProDF>r+Z!dsD5*Juf;ZYoBy#8;ynAwY3FrHfOJ$jQIi*L>_mZT z+C?PI(RNlxddXXg*7TfVK6h=6m5qt#li%kxY%|ax_~E=ExRj;SVIIB<n!J~y&14HZ zk($Iiea4oXj9C8O+CyE2{h?0jub+D7I7=%7Cv?HedqqCnDPam#$NpOl3T)>s)gLV^ z%99k}LHd&FP0@Q+?5_Vj%n`$STAcR&3&ArJ@h-hO7GLP4(}&~glv3jjEKxRIP##LC zDCPktozLZNAQaGDFX9lT`nz%&F>GzrBp&)}6Y20q;a31!kNm^oUgQ*SrH8htm-fEc zakR_?&b%*jTfJ~EMqPbzT<2}+1*Gb(c)d?^Nxvk6N2Sl#e^z$@1<vy>FKTF6>127n zJ+4zx3rcBwYl(s7S(;lT;M|`y46h^bj#cYtQ0XtmW1l*eHj)n@nSfgvR^`n~$)hls zKswqgbGo}!=GfmjTIOtgzIYNERvJ7@{Px~H(&OlSD8aV4JMjuMh*@u&rSgGYnx%GS zZ&?JBG9wXUN3BJGZkiNq8qRW2Pc2B37;ix<W!jHG6)SXK4~!@wkRLyI453ABtZj(4 zrHwwwppnMVy|EP>2Do4L3qc0M5cj_I0}6S6aP@q5FhvpyKAXC7YZt~*=~eAS^Ng!% zKv(3Eg=y&cPrq(f8H2tsF32J*G;Bsa&Euo@!_Qf-_IkH~=#!FPuNPUh#9h1#x|pGA zHRcxkg7Hy=OnI{_oHsQShX|y1I%tg}oLw{8h<bVikLbsL@LoT(sl3lWt($ws&mt~b zMss6zP^R8!JS%f0P5nDqO&blatzO|5*TNditKBiZ3uLM<kPlA@0<@*$e@xe5u!DWz z`{%jVzrK&MvW&ZXKQL|C=4-!%&ynvZrKjUh9}q1drNQewy5RpvCmoZ_gj9k$%Qsq0 z+w*XWf8Rcwq|x7PexyaIzx7=Z9INI<p0eL$gvT0DGnyE5Fo>h_MR;xdNJIC}rH09Z zU*>@3J8+R2)%8m6svs-AqQi`?8Gp8TQxk@?XXIdKr09FrNBJ;Q&E#vcRjTnt0aPyJ z2OSySMMHzubJ<9Iw5|6a%on>Xq$A~xwefQF)y|K;=dv5rb|3r^x>4*^N0!?_nOb9n z&#q)Uydav>{^-}OD?{<c_;WfyyZ*!{CL)0iFUJC!&Huslqp0@2M+Ve^ikvq><qMss zkwW`&ikG<H6=!SFNt4<h@WQD6As5m|%<@uEN#ZWnL`s8@Rl|cLRo=JQp#?&kR<Txe zGuz&*5A2f`yMA^tQGp&hY=v3bMTQ^H>D5G>re|k88`xWstTRgtMU?MI^XPnUx6Czk zUZt0%uZs;<Q(tkNl#_8VM2y>AtSMnU5UAQ6Sy|+D{beoX&Z<)s7ez0{3P&%-6f(-M znd;nge%^Kx@1}n9sP&y_+F3iv_w6msReCg-SzH*UBmsvx=-~u`s8wh^!32KU-dbkP z&s*_uaRZ%h<$W-HGMUA>RBH!H7cP8^6uV!D!(q%$bfJT}v90{Z7yV<%`tWIZ^Sx)h zaV=JoMM@pdB~8;P<M>LXz3!^lW<Jg6uitkKyvy1q4=ApF2;AJrl6ak{cdIxU>3JGW z97^zAUi#*<3RZU=b(z>vL@~|%a{zAaB+}t%ZQ{kM=I&GNO2g!bH6Z(-yS%?OS?AJA zdAVdqF5MN2+{lAz+Jz=v|82&H(;srY+Z0>%p}h*_9vjv!zN%?r8v+k1<`Njh-2XMJ zK*I-`SVYwL7x4O?Jb=&&fpDhdxw)-2`0CBPcnDljv4UID)zemwe_TxbFK|TwX(Fo) zx|{~vey~lPOnrsq%FeG7o_FPE@Zp>Ut<0jxH-$tk11YBF_^y^8?q-w^{+RVfR&XzF z+MsdVnXW-P!Ph3JzIyt)^I$!g>QMcpGs*1v&nw2epzfmuFGhyHCl2U*FCblQ!@T^+ z%!V=R-wq!_&SPWZzb^U?ZV6e;&VPLn{<X{N=foEgYGnHzH-3}h34Gmp&1?Ma>9Tpn zq!SSwECy=rESAeUp|a_m=}#OBKn%^H{hm#GtCF*f|KODQ){Z$SkAhxTKg8^|{BfZY zx%&GLluF-jRSZ_#a3&34yVr($Us~X5`)j3*Qna=6T*K#@u2I$HHVr4BLCb^c1K#l- zblX%qW-qY!8PQ|IsYpST%XErRtD`vIarCb~nt9Os!BD=7QUw?~-*J~;+=xU9YolZD z30Iq6G;G#n6Tcku!$2POZ4`5pA?Enq49i`>Y9k8Zyp6qqY8id5q3xR03w<P%UvePg zhkL4+DBa&Cr;+qn4<$1LX&GuSu=OwjdouDh2V42V<E^$({c|P~<wp4CbZJ&yycZC2 z0qZ*j_3+IGju?o><_2M*2@roO+Dl~FyprNxCWt68nT>!_ry4Ce`;D%T-MHDHHKO*G z9iL)oguG8`<Unalhg4+4z4?oZ{+>H^P2JA~pR#Wq!8eu2v9}b<rAFJgR~q}M2UbT= z&mkBSHb1*>F-J|(aF}B0F0={e<*bp%M~%sLoO0tHKpHQpAA94RZkK)WHWea=qMfGc z2a5cm-+dn8zJ^pU6xErelfVb9_F{nodXIH)Fc#L{<$HBe=Nbd~aYS2n3y258YtBh7 zqmwAB*~RIwwR(2q@m53;2YW-Tyxn=rnwDTd&o%-wy_dj%wP)p|v5m60F@LP>!s|{O zyNp+1&S3vT>bCgCGkV8fXh<w?p^E>nmAynBp}k@m-^Mx*j|=Vf=!16!p%+g3mk8Ov zT&<SdRXKkB<9PU!BQ>s|@;bvetT6Fr8y*D&I)d$i5W(dwH}>22;yA)V9~f6}x2SK5 z_@82ccsPWcbT9=nAO3W!ocK?ws(2lmEuf9HGZC+`twxi+Ce8y#t!@&wcN>+G5)I1A z4JTH|yQ;oNHPzfD{I1!%k23G*#In!PX(eYdYkuhFj3;UsaR5F<=g-%6h53JXS)Dz2 zQ1q-MzneLt{8=^~30>g~z>!S7{3-AfcIAhKoqvN5={sk=q^HV(d%PiMo#tF#XyQX0 zG>;G%iKxtonwD2}*I8(q`4IvA8X&#$EI_}ga^Lj5vxl?v227wi+OA(&GqNk{@@H!` zbo{f73>8WoM6S(*`$zrH;z%$>#pb7;>2m!4k!@Nk*Tb1R080(^sWB`oUmzwj#%tW^ z0}K9Deg64)mK{Pmx2>P9sxyjeOa628^flFOufqygj@JYU5|g7Dv`?Fa8BB;wfeIA= z*D=M*v9*`K<=!9WSE#G)W<f3~!-tUA4dpH@b+OX?nl0loqtm!8Ot9XuamH+>JMDi{ zzFoHU>JaN6)9Xv*gAK(S#J`-$w@~kZVnbnyb^TZO6^pN-{R&5N8KYU`L4ED`A$ZbP zD^kFPNt&I<%vTrAGn8v4uxAWAVD!b)rAXpD`(2~MGwA8!*Sp@b;67?|_)e*4F_+c1 zb+&r+cvUoKxX<Z6`Fvw@GsyE6=?k5w`_<Ox5nLuo^GoDvLus^9Z5`jwLDl&PoP73w z%Ox8|Y+N{}cT?C>vVr6<l)<UP={GJTGL4D*7ot`Hw*EEQe_v`Ak*nY`ekc8Mi`+as zALZhN<98A9Hx}VL(fongX});LfNHDo!Qc24&a;WJW3-(Md2i@JhXe`>NfHj(g9Jds zODfr4QfE_5_w#@aC~CMkTLX@iwx%Y}D`q{=*?uzU`fMw&u@TUlo%wFI^LkqDEu?=u zFu&l>th#8fX{$s=8*KVMU-6Oq><uxG?=MV<t#}NryfNN?sw>y0bjn;iQowCsC`MtM z#W5b&1O$C_BU1q$;i44pUV=bVHI<uY!D|Ap$d4rAj;=a~&W<^1UezF=`ydGC3*$tg zvmXf{^}K8+bNLCoACG$zFF#QsZ0-J;Sb88=J$UYA%*#@Ay$}#o&?@DLM}r1Hn0oHl zM=$)L@u3ocXu8SF{KT@2r<O(EyBuo##QA<cmIB2fyU<YC0`1k&Z1AvE1+Cl=WCHDt zWvYk!hog;Yr9CeV(tfIB@F&@xCQ$l1^08JZ7i4&dmnwh<pl#OoK{s7k1ir$Jn_+Yo zW+htT+uwz{prKK>G>d4|Ni4#JUqiz9Rs030hRl*~Q99?!{3A{1JsPw9Vz)*J)|s$a zK3foU?PvyDqS1Iji9xgW=RQj@&e^}w{@v`E6fj`Gdqvy3T$q1L1d+N#w2dDP0VI*D zLU%s?(y*HApcEyQh`4h{4a{me^-@)cjn(9;^syZgMQ#@0hK5Or2At3^8{JaEBn{-% z@dAweFOyA29gbuIKshJ$;)=I!WQ72Y4ST(=s)gz#`}T0Mk?PUtn~Eew{d+k!LT5pf zlAK>g&WHeI^vH1SajX;BUJ0ei7JD-$GXI4NC3`dkFj(jJS$LoPcTiDLKX!PvOXqOB zm}^jHYxJECjH+P5PnzEEnlD5)p10)AbwLr^+<ZIKSVT4NN2*;)<r@UyoT8R90h*0@ zG7u9aW?Mu;|6M7OCJmI+(CDp|6i)3w=N*&<7mIcp_9Hi)4ZE{Ps8Z1EhTPp&2jB3! zV*-lAb#^}gjd*K=TX!~jX?Uk!fQHJu_6;=Q{vH4butwA6(ZiSlm!}W6kD_kZ;6>kF znN*g;+`D|dXZ4k+YKybO{93UP;9m7iq}IV!!;b8H^pC&lvJd)SXJ1r<Y^Ipcx;Ztm zPt5(mJ{cm>FIIKJW!-rAy<t?ivyn^GzvM+w%SqDEcXdOZree~+?oTan2F&0`2bFTZ zJo#m9QkxNKhm?UTiJRA%{E*##i|J5aek=6ALp5-ont9L;3o7WH7@8>fMv*gnQA5G$ z`Kg*~G8^l1`6ZEor~)orV&Qqmm&W1CrMb+s)OrVRALF4v`w0p085<k-EtTz+nKJex zneoQ<_CBZg%bUhBq5RRlpTnu7AH5JD3OtxXcPt$2leYp9aDpeH@)rG3B;HsEaX=?t zI_mX+=8d)ff+nk(qHOQcO7&26bCs<elBJ_v_O>r_rn%HSlKtlRdEG%fTp7Ie+y@9c zq#y!9;HKR^44MNDB`|6JR<6@QBIl=jR^Xf=lGL=YKyu;i5rlnK9iBGR&!VnNb-6ew zs*hA9qJnqofw)<OzLmuiNV4P|4T1OuP{e-IvzsgM#xnA)JhWaq4`Lp43cwRiB<i<2 z|1k>9&&ry(8Edue_8iU@5-MBZ{~^$H;nN$;`q@|OkfK)wBHe9)(4GV#fJnW5M|665 z$9W{LH=_3k4CzF(mRpK(C2V%tx~l2tA=Eb4?kMZnFgn_>(*GDcDskYf=!Mi~IN~Oy zfddFtb3SD_9P)T$t-k2IT_U>(5xN^cGE}LDK0aWzoQ<^JllGBUw(O!3zC}z9C?GCr zpl^b3V;{fkj4e&igWH2^_bzJ69EU)bQLnU_!dAy4mpiA(IG4s2kw>}Ea)d3TMT$l= z+&lv%{$0AcNW41weGGxKy`;NFL-<fzSH{201%V{4r{qOXH`^IK{jUdDFIRCv!7ng| ze4r!Wy@~dmJTgSziFiNqd-vv1CtZc2e{Iy>@-ZVacA5)Q3(1!K(0pOpV2K9u9J??* zw&}L1dH1;4A<|6BhCfZyGDpXiFi=WKS=G(+4QPbOCAvlF`o`c4MKpG!0sncyG$8`S zSAjO4tL>rTX*<+t$Q-%DJSNA-S78ctQsUwv%U;6`VZT0mV{N{mALSK!Zvw`_32RHZ z9hi||j0-Tx_vJISfJjfYWP0Yn`znb-BHDN=&wq*?LH9>Bzn1c>U4Mnc^_{_UoT8e* zbYoW~KN4*2Lt$R=6U3S+sKg~{?@kXaQ6YiT=p}}{U;sKOKd1-+@F=aA4yk(lwsz7C z6)AZ>V64Qoc%|5WK4IP&!j=yRrWAV%{Ea*?tm;+YQL$)TTNq+FQaxouH6{xrq1?A~ zGgsrGVfq#)rG;)sxBmneY4AhOI_k;^2iO!Z&?Uhr8n-T3KYhuK<M*&4bz$}M;l1(a z`i=~twW%{1ot~o~J@+6GX#tWNup7PfqIyw`$$6sk(mRfS#p%G*<EZ7c^5f+NdG;16 z<}+`f&DwU+`-;4k`9iIuKH!^Kiw!{#-l5P9pz-dUSCoe<WnvN-oJe4M?(ZwL<%F~} z**Ebh%w5;L!0N2{0~yN^+xLr=dNlN{uR5>$Jt-Un65_tJCsl=U?k#k^GkS4R<s(u# z#A8g}Tv>MHxz&2pjpe-$QwY9jY-(4Hm2f_Q5v$L?8WuQ5L*j>E5(SI3gnZC`)*SR| z45Cmwm_I-*rOQrr?-7~jfOU4shcsol6a1dBeNRqm-B;-!7*52$r{Q$YEgXyoztS^> z9fu?CIsdr%0}Zh_;5@Zp&*sTgwBhZ+6Kg$CSl?x6|1ul%R!bNGA~ha{M`OC`f34Nv z9tjm8oEX->ZdnTr6g+-_4X~HsoP_PQ++4bJlreknJl>HGR+pBQIh}|y58XIFE~O~3 zMgL*mX3Qx#=k2O7^j|g|R1HwQaUe~dA73qP9aYs;wLQdvAR@uB@SnAsv|;&D?VSHA z9PyeS*XP2Hf)tpGCpT4%x~)q;2K4rzEJxKu(tUExspxN=S<4p_Ip7J-%R}mVd*3n( z$KwAs$uY6}J-~i*Ypt}8+(ui^D_uHgj=rPsr9<zcGE}6<uDWi&EXd&f8?qzzx?O;d zCqF=ky|KQ0I&$rQEdIfBYr`p2F9^HvDOgd5NGtt}3BIMpb0S8ncxN(%DL!PP1@2V{ zi$wLZ)k+ySfm)qIw=vT(=douD940fdg$z@tJZN9c4@hnFZ|nMrO3!S)mOg6m4=gl| zF&=mhAYCua9xgSS_e^B4nf7DuH`Og1y@Wtm>cInM{x4z&+>)Q54<oRPSR!i`8)gf- zjkmE9+jZHuo&zDBtF{vAdMBkB*0=kOcP-~Z^eb=0W{Dr<E|LE`5&P)NUhuwe-avwj zyw5ZYr@aWE2HS;a{`a!Al2a2l`ZjwN;>We0uIDBhe_=0Mjj|Oa)=9$}6v*OU$(&v) z@7=U}8hm`<bZM1xZ#M5?{Yz)y+(*OEu+=Vz1qGakV<k%L@n?d^dYvJxrO>;7nC<rm zN0XJht#_nSn!DTEV;)eL_x*8*(1{0aUdz9wqsc%N9Q&4o`K9aOdsQ){<6{_W8tU>h zza)}!1n|TZJDSWWCV5|G<mqMx@x=1D`ITU0z4%jP*+AuWzu8F5McDF>L3)Oi=+AAa z!NP_e-Z9~sG)!dmhl6Yo|DBxFU~CqYqz%iDR<J*@(b*NI!|O?RBu-1l*Lux|3Zd2A z%J%7a#guXcV-dUP5_+si*1wbz0Ge}etb+1#{mu_n-WO9hXW5TyFa@!xF@-812IJjY zu(2GyCn^fge;H<kV3h9^mG=R}wE)15`&mxPpJ-nI6;y2Iy64KU+zAuy=2b>dooHfi zsJA`szP<RT%&6;w%`Bgg+(6oN$Md<cB=w@;+Fi&cwEqCOVeOt(o8u%}1%&8RYj6)J zI3${+BLF6e#&-pY$J@@CYk`Oe%jGuJWStwS`!)Q|g!LEu5&xKduFLeC$En;Of|9{H ziwQa|J!AhWqdd}Nvo~~q7Oa{^b|QdJ`W>EoN9x440b#y+K`~4S529c%kphb30{=`y zLZ-y;Q-i?<wbEs$Aux#`SHAftniQ4gv@Ly7io@Xb?~g%KyI3`U=kUTzyP1Rycj5VR zVN|xI>BA?RN8}2_c4Al43#Owi`J{K5e4XcdAzikdHCeonoWM-Gz8&86bLD$dF|oLT zd_nu({_`vgXc-Bg^OZnG9I%!wkoP`ScE9CYuE@$NhV}yKqbQo=^=8$d>&tiIVbl&n z&|3PO`#Sd1*Ii1-^TIUB6NUWR0SJ(`{s>Zje2088Aq}wFF^pdSu(gvDZ9QgXRJ12t zm}}}kFCR1ahDWnsY@U^enMMbkx;%=B>$$M;T756MmMyq|cU?bO_F-MGk@ZyYcOhNc z|2>qvrWr0Xm%$1Tfou%3MAVkRFCPJQ>-3K;-D07~Yo;G?Wm<pw-$wJ7hBI}j2t5oi zdSg-1leM3`4f{mF1MT?Y;+@Sw2fDVi4c_l#d?wn?{9^$TE-~cALOQA2B5ByCT^x}4 zoh0a1Q_;l0JX&;|Z@!a6Z%M*ua(<HCJ~=tVT#rjP+8Tyh%SAn^4<na$hnf{AqxkH= zD~D5i+=g<b#yu>(Zo~399vv}lsc2SDv%t{R@K^0Z>mz7+aFj;tQ~Aw+%{I|8^WTk8 zD;oZ4C(Whv?~$Q#L3_Ihc+4AavLD@AwX~+M1&H+z7Jo<sX&bAq+tk#2wP8G1{lPN5 z3)D=<2}w6Aqv4UeX{OSI_b^3z-v9y#zAY&Mp#Myy4~x9vt~?LwEa0y~-Un9%EZb=3 zG1KUsj@anNI?d~r3v-XIw9Y)9FW*aS^eszT9PL>QB%;e<4@B7^vhUAZdhdN=<x69i z?c-p~JzI_3yOQo5nkvmS0+n=~`x4R@hVopg_(L(vEj^Qp@6o;fQAl%T7@D2To~Fy? ze(Uq_a;v9Agyd*EZ22tbf(~uqRFs2j=5cIpE2Api<{@l;{u1o1+%U1cmd&K>z4E$| z@ll)m0x&x*W#v3U0BLNrXF6G_xP7HylPcTGY4A-d2FF)v<1vC4elJ^Fcj?}76?(_4 zVZGZ_)!?+zJdu6n)vs9C;Z#t8f-x6;(fp&Z!zHz%PXP`Y*>xkD*$s-U6}N1gTVTYm z=fXwQNbYsYukEC|Y;*g-(S5t}?D5{KqG`1328eEH5=NS0^gIGfG;fz-7?R>LT<0Zd zj9#7v1qEMh1$}$w<_=)bArJyxFRym%n>&*`QZYH={&DrrOW91je^U1=Awnu34ugu& z6>BgQLhlb@ys$R3i}7eLCEcY>x7w4rQBNrx>WEPfzVu7%(=R>j6KBtRQNALvjAB4& zIS{*Oi$@o;m9*7Y<<0-eu$;%w%(tu>D{~aQ7xL=56B7~gC@65rGJI#b)seXg7XLA^ zv2UY82Tegi+arIg$@MV}OLKyTshYj0=Bhi2d<Tb~kuhWAz5^KXX1x-m?Diny)vbVT z9$1_N@)R=B`l*c-jj%X&*M9G>aSZz&t#7asZ=%iH)6X2)CFF(DDGq@Mf0g6ip=>|F zsJieV;Mv>XpD+=00IpZpj$V7(&}m?Od`}uz#M|0(UZ#JqwUyz}u?&0Io1AZ%J0joQ zuN`6<N5aoI8fbKOe#YF)kZ}B5wd;cpLi5|*(#Wl6zzFrx<m83vf!)q~7yL%Nb8m8O z_hD3NmyWsVvgDN4Uw%a97Gp_1dgPYqcXUt3zHfK?!I<`Wn?`;1wZ5;^r!KTkAL>pH zzu><bM%zQl8d{S&ZTL-JB(k}OCV*z4{m^GXQQr^~Kc};O<31T}xw&V;PWjFwK)^ok zdsFsjvxF#fE&jPN@sWn}R0jqURbOVC97oo7C=gnjBag>hc9#*$&XCw-ko0(+NIw?g zsAc3n-h+DaeocRZOw!hCuF5_0i`}W4(`1`z5MJ%|&OnPJ)3xqN)$|HwQp<@1?b{>9 z<#OIn&Lu;Cs6iY?4MoLLQe=K8=|ixPRl6VxTF-qIZGGleb}t`aF|Vdfnr;W9F)m$* zX;%sTIsf9dauai&Wh8rl&DdBeIIi?_y>S>sBsX(qR<czW&aJ-q4=u}6mzO=BF@)+i z+mCwId*_5fSdM+4@~hhZOqijeor(XnD}eI%hP=fc(VyYj-M+YNFioAf9j$j-t6vK# zrIF=wT#}Oh&cN%%kYc>uyQR^x<LMJ%fvaB5zm)+8!7KjWp~nTi0})}ciTC~9!o}cF z)dX-T$~*Fgd1y75ClVK(3!MR@7*U}9Ze{YBO61*IM7y}K@st)2Q0xrZ46Rzc`w~gQ zH(hr?b%xHkZhic5bTv@?`s(FRIs<qE2rVPn^kJiSf5%I$ehJj13QmuOjMO=T!mHPs zqx4XCHT8<25r)@48EGFcZ3!EJ;fa*_o&$$n0uiB>!D&x2tu^?!cDg%_G^j2U`s!3( zr(YT?`396^Ng1ca?fYazgqnM%4gaFSIIoYUqB!xsiwe@IPsAR&b>Gf>o=sYIDJ&RD zeznCu5##uaP5FrDZR>GUC(k;Dm+cqc=Ynp$N9iA$0_Y4N!h}3`$GsP!@=qC_tND7N zn%6@i^UmU#USXYDRvCyyEPw|@$kf!-CTxsS^2AjKc%7Ad->qkF57O&bfCHmD<F)NB za5;<PjWw)1<8#GJ;<8wiWnIUY1wDwj-c*4L5jT@1`0eED@|2Lgdp9=8!=lg=yL{W4 z@BP55ZL}B0cQUVHv3+WUq3c~<64|ON(9u2BIn8r3^Hsgw?G?3lu;VGN2+b&G{pZRO z&Gm2(C^hHnn?pP>NpY#sdZeSDFE{rZ@k!d(XqA=IP|wm>(06j*%4D+4j8#4CZ8tIV zNVy$jYjF3CJ(jaLotO6@YY!xx|Lwmr2<&M+a1%FS=A2SlKd=~QD=3TNXfTfZe#D<K z5e1JYAyX2+?44WiE54oZao;Yul4oh6z(eQ$flwT)vE}r3>F?3~Gez;LeCkedIEe5+ zJ=lEN1u%rzfptE{Lq$#&Z!U-&&(u4ZB-vz@X)<gx<hWN|8FgDeIeZ<Ro-9$u!wf-d z^y#;&_qxTjTC7)O?l{gR^|-SWIPU6%S6=1IKx5{YxA8tp=Z9KP1R(p^&8Q}dGnPot z0nsegyWL-uVxeYpFWYVrA)5dc5v}{KeFKFSoDY{-ih8>L8zwd}{l_hmOkza0BT><+ zYh~&%)zYtO;o-j2yrgKRUd8uDrW8YRy$nOPB)O22FpafuZ2x4(Y6|zzK}xJ|is)vd zAc^TpaUvdqe*AGT(fia^ij1eTn)&kN0xZSfiNyYtn}zVGhx6P#MosT1tn>-ZI*iPw z*~wGF!mtz8^CM<%E$9H+s~~)NNgvnw@jdko4PL&m&A%8+`~%Yh%-k&pJmLZ<HjUb3 zNqRs2Ob-4k>_NJE&(=OSh9oT`Fgr-G_+fHx>*-zk9c7kwvq2+RsamGC_X}VBS|G#U zj#wN^;QSk@`*tis@?2v@FP3)UHQGNjAZbivx64gSPv`h56AxU;RKV-IyK5fwF{H90 zQL12aVWDVwS<lJEr7SN`#N%>*93%?$W`C(GtTc;2r#3C!rKMkO=^g1pK3RfiJMu$~ z?Lx7KvKx;)oQEx?bb~ZDK9SS#yx;J;(qY_TR2$byt`OhF7m&PS(#3zfXD(D1HQ|<# zr=rdNb+Trch$3|~2{6f`bqVOTN!T$y)mG&z^(`Am$BjQdO`#+p4VvoLZrOE}PIqqA zYW=G!onF?^s(Ww{e|cHZIXO<iIr$>Ckn44tkf1I`vu#{SDTOz;Sv1IK^8)2)v!I<D z+x6FlU-3-e1(wD*o}4;r+-~!V`)IG5Pi5^x6VN3?WLX^h_(l4M+0b~+VjT0y_;(e6 zVl91MH&X>JJ`Cb(U}kAK>C$m8t82eQKe@cT3bPHPPL<gO5bFevyx=BG0sebQi6Zp& zu<2<%L58ii7^?z=^GOMc+QQFlDMp<NoLY$)vwBM7AquGA-goTu9#9pbEP!PimB90M z;4Zox%I~;X_`6JeGq@TQBJnyJ>_O(aC*;-G@lmsLPHi9)+9)2%qmz7tQ<;Axlrd4H zuQto9KNVQ;{#7ckQEYvaxK`a?#UX1mi=r};rHL#-^}~*)vTsz8C2Z^^dTH~frk5Hb zXVe6xRdkD2H@ACdQPT})%Y-W9{4<3JkS=Bb7fr%CZW%$mX|c)8Kp3z;+gNery_KFO z;Gx!i`SR3&n&(y5;LP_=VyWl*P7_1ph*su~OPEi$I38lx@h@1mvkFn{va>sq=Vq0! z_l<!R)NKM~ae%@<ub_7-np9?oq-~l?605@Lyof_)Bj*ZSeY+zjN-eH#c6#AP<^}6t z(|N6(6`hk4Bdsc}z0zh3V=CrV3IAJv-oxhg^NXsba+mg7t<DgCwzH=n)}w_wa&C)j z&$9h?9q89}82P1;ccpe6bX0GbD8`K}T#hx-AW}&B{eCtbr)1*L8*wQ-`{k`4`hsy2 z$z-efs0ByUTf_p5SzEh@OzQgXzSE<}qw?8~^&LF{H64NH7d|`;=?ZYUj#>~%LJctH z63%{@?7t^P9{jx}c>6BX=fMpLDlbC$Sk0zJ{ujZpm!QGm?Ki8OnS=6}X9SQz2po&& z#YI2ylB0{%yAh1q({-Ps^Xq3k|A(vZj;Hed|Gy6*yF%I0vJ%;3MfOPc9w9QacQ_@q zjEu4!*<1E@Bv~Od+mXFD*}v<Y<NbMjAHV+SLEZOtU)O6qU-P;yYgQ(vGXq6~ef;$R zm5iqfi+%nI*#YHg8&BG!>m5zh6YHW6^j&YCEKEh|*C?)^ewldNZeokqFb_emr<QU} zQptT6a6ul!67`c#B2TB`Fz4$^Zq?5ZP^EKMpR5sq5WMB-xN2~>Af$HVB7CYQS!{mc zW`hzt?Y7UYbgo%>lX{l)c&6LOGG2>sm6+-{(vyf@Ce{?}bRKDVy9+YCLN%<4_3ErW zW_$9gdBNZBXAdr&7lZcuaWPCr_?S8<#iRDb-h1+BVtQXq?YsC+3i(2(gSSS{o?trj zS@w)BUKtKaSi~2C`_NiQ?pI=vyNv?6f9v>L^8lTH(#!?33u5;de@fii?Xx2Ef0CrV z>bBb>aeF|=%wE`k$Mn6M{}c73p|z!&GetJI3u%+LMPh2QSo3mGM5zqN0wEc6@op10 z2vsLkZgU5@PKPiJKA1Qappo4i3{Mp73V<qKi@*J-4I86FUi}?W8tMjzA#Q>1TZs0} zEo~*=-c7!$dIf*9xMd*TL1n3X`L);6x9ywBs|Dgd9<y(d4W4}I$=m6qQHX{@kDcjY zjhr`JlM*Gv13G#FDSz$$Dg{Dt_>c+VOYq@6A68c8<g>BN-OqvzRasMow>V?%X6r)I z;*FCst~`?Udg+Zr8&r53gfJ13(8q{kmOFK)p;7ft4vOE12;a)OOnwM0IQCNK;{Nmw zUg;2-8#W$G;`+e)Pqg38dQ|<{1txE`>NUgFg_<)}HY!x+Vr0DGxT}B8(>pPampBnH z=;2f9poy(H!R0gG#XAkbILWaY*$)28%hgLc9KOS6W*W7ziUm;uzo(v%>HKn{`VnTn z?2f-_43j)yhGZ2E=cYrAJ(SdK%XNMdPN{i6?Y*|9x;Rp!zI2^L4k=nYFyPkk*ha@{ z!+82zn(KBQ+ql#$S3A<gfZlhv-c);5qW|y02lBM2nRMMx`lA8+r=S~|!{mVIWQRpU z)6K1HQu-Cx-$lEdYjSD`@;ONk=2?VvIkf5dPIuVTNq4NNkOi-Y@v8&Dp%LIXQzWZi zcX?Iy%DjT_QN1RD121^1RbQ^~&`GMI9!W^?dU<%f;B>w`Eot&f0{MfQ8bjZOeTBhe z8NCCY+}yBJ;cO$LMo-S_0@ovo(E2Te^sGZ*DiJkw=@B@wC&$mHrI6o#gc5+qjW|Jv zP`~}rQP(l2mP0X0{ztVJ;bPSCG}QK_rV8)zxk)C67jtsCJokyAc2XF(qCQZ|)0or_ zznI@ATq3Vbavcq7a>GvUXP+HNE9NWff5ll@i=5aEPV?JM-g1yWlK+reG4Z*dw+81l znCMk$`S`%mSxkTGa>r5N&@jizq=fomr^~Fb1S+JQ@str4di{L!Z}Z`}gTtTanMojD ztabqqEA+)tXCc4O9tc8iD8w0lIdgS3fuy@r-te}z``~)t9ejdE0@dGyWc939KTUX9 zDLT~N&Snv~uzuldiO%7aghus3i^7SY3isn<_*9zVV*HugPUGaAGAEA%v9kw0>4jtQ zy}SEq{l;eFM3?T46E0>Ds2}c0Xe=#l`|u6>JS)j1KVi$3!|m6C4)mI@IYSUk!0*`8 zcim^Q2dJAiASBM=?_hC6q5o<wEpJBKdI~*vZd(8(v_QppWT6S8|6ML)>v3V*4<;%6 z?Sv5u4>?<LblbIOOXMH#p$ips>$lT55KP*9Y*n~3%A$TaF&$csTX}jTJfy|F()+|A z!n?^?;|r5{w!q*0x3Zs|(~gXtcRJ<NN9Z*4&Ny)nYd|0(C-A_#<J)J|IIH%6+x0{? z4q>j#=4@g`J+p3aVPBmvF|3))jmzLPC_i~Q2Dhk*GZ3E+jIZv8qdpN*{9Mj8IVjf7 z(*-pYvTu&BZ|Ao;(B;8is$DXWL>EdLIZ!aTvo!Rv*wrC7*T+CZ<Y_{xAfxS4e_+N9 z<_5XwD&UEqY(AH3@a%fx!Q)F4IVf38`!D#h@ZtD}&<WSl^lfrps(ar&K-l3Aob@Sx z`uqvHU*tBDR)*CFjZvo?wW+ybJZ?We_S(|+QAD0@y-t;=UC0t#+_y$$PMuzHu$gz@ zgAhCkzI%$}Zhx5E0Os`Jo*h?AHa$$bSGytVdu-0s_l9u#gt0w5H0}j}9z{Yp=gkv` zv>THMe5CDj&|_K8@$I?W^#_kv-Q8Bl+4#?HrgvP67x8(Q-K-H3L84J}*lYXdbW>Pv z-+^qdjR6%6u=z|Zs`qh{{9=2PN@7jFrbb9Z;fklaw_|>)iP)?)RU;Ssk7{?FWMEK< z;~9*K`}^;gC=VZW@6V*?j}G|e8l8Aijq`FBYoBW4LhP+Oi+#IIOnxR6V_Po1hrG#O zrZ3e;#RGTK_fUiBkL8y-!wfxd6Xe+XkKqIV>kGMvOsgN<lng1eZoizOo%<d-h1-qI zvM$QIFN#OQu5Vm~U%u$`wAUlqd1pM6zSDuvwGl_UrCXrPH76xJtb42cp3Y-C*WJRa zavp^q17Efr?n(-ejI;PoON7=R#iW*4(dk!l8@;1uSBGZV>t1x?<}#dkm8I5|Qpg1A zm$eLBJB#ieYEjo0{?q@?MOnq+-UNxvU1qV8=7E4^da>GOtxNT{)~nU=8K%O6t#6zZ zW_+yv0YTy9qvg9l1?wMz+kK104|~Fvr{qqj_rt?eT)K_2!~Aw+RpLbk)>A&(98zmA zYbefK{(EO^N7y%;OK>`{==n$e+0o_79AaIZ1lKf`8ivkTNgNW$51=$EZ_#nL?5w)i zpMn2P8t*e|eer?cf7>$VRQZU?3$msaA3QM3AD&u@<t$(vo>|HsKT+LK+!0-?342hz z8#~oKB1gY>sbOV9`1(<^OXz7Sd&?2;4=NF{oO?%8k)eJkc^)QCt2sqE6>n~i5Byy! z_#Cyg5~Z4Gwon<H@mcvkUv|$1-=pVY873`{?VR1t@a0Cm4^N6On6y-gN4|(n{E)Jy zT0veoC0AZuy<`<DmM!OVkp!H)I6UVj!89dqaWM8Sdf{5oh<Cb)#Qega?y5L#uKXCY zr46>AXJLYx6nifuLOJZ$9m~9fb6F}Xy<g_~Y{W#NmM@*s-BWWIU$&XLki-YU+j$%& zM8};w9=jc_dVq>b-Mg|^N<%>McQ?bv5!>Ao4QaW41hypcBZ*ct4#~?o894QqY1&Zt zWO1oM9jHSUII0^IFm9ZDUgndO<^d*sLxn|(KD>~it6`CIp}c%$Ag7<tmoca&U8ZRg zO%{<upz^e)p#MwwS0|luUv-b<(wfnMJyo4ik+cC2et&DydQ4OBkXj|<jFe>*8gi)1 z{?wFghih86bBF&gZS-wVRweDn>eW7pxix>%nHGK)x$fMOE@{ay>5HW8Eu0Us$!536 zvQeAW;feMW^Jp<Flj~cxs3@%&>AxpdH?C!?;}v~%FJvo$Ng-Qw{Yq%5;OAjCUPAZ@ z&tG3^GsE;PAq!iVFRr88p)Y*IPqxSINE825(4gxpY?{;0zIS6lmPAGhw_zN}>0P$n zABMX>(z}eGTYbr0P3#S-D=;2eEiT{^{g#~w3iE2QcB6yQI>ssB7&~c@@6kHh(rMWA zk*A(nb@2Hxu^C#C`|VrLdWwa;l*%d0@t2d92JAL6g=Ec~Z&neuqTg5C)HB?1%!mhR z-or7~Oc-D&(DsnGp%IyBV-dZ0`kX_}TjX!Agg{kqhHv4b=xYJvCdoDZ5u>tFrHBVh zK8x}Vb8Z*8%632cF#reG?)w|U!{d30T#mw8DZ%j_yb-A{aI^}M`=L(aB>d|qrQ3#g zWTm-Q09N}x)ctcC_Y=t-S~=UxMg{ur7;{sFAONKq2rfC&-<3uIK@p`d52mVj2Mu-t z*8Sy(uSGd*=yrvQAIhI>eW_S@FnOx27u*oRXO$PdFYt6CKSHbbJI$|p0zs%CoPY*W zq=bR)0|<pH7_%)}PqXA$zBYRu7b;4A9;aWmb$8rro@uA7&`%GPqqltIsmz9ZZyz@9 zH>8gGZFA%cO<kaY>F&FKB3Q0g2Zn`@>X&)X@Uo3ZEN2NG^iT>kYXI-~nDl-HrApcv z4D?$_rG($B|Mzr!`%leIr^8DvaIw^ekNhjwogTR*7Kzh(zq6wUrOvZ@Je?@zrh9QQ z{&<cifiLNJ5*lfdgnzVn5W%UIEFisz`hrUE0)s=dcMud}>2E+D3kteQ6zDn?cx|Ce z;^d*k(IUCqNH)unSej(z#`o==c#|`!ipf3OM8CtuV*Al`X0Nr4?1RT_E$kUMLM6*R z__PqJ43+o_Jt$HfM8}*7YNz>EVGt|jXt^6W2XYDIbp}9(VA|yAp2y)ZX9fG!4+mnU z#ZOFhG6m}vcdNm@KYSREM#C|ZR(Uuh>etQD+$c!Mf|iHxa9=!?O^#IiG<qOC2uS6z zG=?^mpC0@=dqQoGjXk!$d2ZeqcWm1A-mjU=21n*eHk@|agXEjsF{5^y$nvi~H&CAX z&6b()bz}qtiW-`3<tclfYgQ$MI?je{0c35Ko#B)`B+YWqy;Q)qP^9h8yzaS8)%=}! zUFH{tt^21>DiT||wrTd?R_xj;dx>B2TdldZ|DfId#Cz>yxyj_3#w*6)m&Rv-wG!!` zc|=vKuj}i#JxP2=-5I;d8P8VAjfz^#X5v53x>(Jagl&zgi+vUs%Op4xu~VA1`H0)_ zF*9vkOgcGY-X(9Vx&iMcNgbn(n|$1$HT}?fl5uwa<ffreBS?Z?H0H-+*SPUX?Z(vl z_rcGWY**g>6T$Zkn5W<=^E>e#_dmlu?6j}I=6UERK~;#TZsj|%YkPL4^+<oVA9;(Q zi+Er5Zen(A`M0mkd2t99WCY{t``icoTa?FXMcL{6DK|p0JV~Sv`v`0`scLKRq1$1= z4~HPnE}<BQy&CS5lAd*EY1}h&lG;N!vYQ*<cq)9EY-Ar{#58uM*1&XISG>~R965V* z#ye6UV)m0$fmw-G=fOs=bZ9q%>F~^N<G$#|wEX__H=Fd8c3CZsZ$>|sPksu0B0kC} zYBhA}lZ_Ms*T<i76HIEVK<K5IpQ%leCOvNLUl}ez`@MBjq=h<4N*@^g{#^#X&$#!$ zPiOzcO1}!P_DAj(f4JA*#*&!U7764xA%Z)*>-S;Tae2>tCDmm}PT9O4s<eul{KD}k zdT`yj)Kl?vSr!*6#)uUBH4Tp_Ul5tlkxBjJ>B05XNmBgDXJ_vC1Rnz`%KVRR;vt*x zD@AtprHusoj|bHDJ61h>`oeDnbhQVQz>kc$E#8VR1W$!Fq3(z698G0R%Z}}FH?V3# zqPne$XUm1Dk8Sd3Ps$<4)HBG;dZN|~gd0i5M<cmqR^5zZM=LIe>*isL>;4ToTy>=* z>&)KIHva~S%&$a?%*B|y4w-fI_xI22hbwkP9UkM>De4gjB{VA7Il#kYI?&mc4O|Qy z5oP%Q7TyX>wQK3DciT{_p|SrXy_$JuZ}^8n4KJZh+@-o<crxv}teA1?as8#EU(H?j zbV9V!9UsA<i=p6}!$kLyY?0Mcjon7_S`%>aav!*HEfZu87r{~7gAGhCb-(HUS~m-2 zzw&NjCQ^Ih?aj}&AV|?Kx61|x@XzcQDNcNx1JkP~(qj~eXiQP8Rv&ZYCHl}ox(wmM zB`(5Y5TvF#dxdt+;_a)MD<bnnbSu35n`6VAolNW9o}h3}2`*h6oN0@61IMT-MS%J< zIK-gL-TnhO5-4+bS<rfSi62zWulW)N*^dtPrhh1NoWkjh<5$|A@9eAfa^d$qbR8DZ zNE_A{nxH*VOhw>$B0yux5ZQ#DI3Uo!fD$^4ERPF*;k}+UwjaQpeP-B=Dtj5s>q&}| z_LFFLm$es5m@4n{NSmCMF7*_jDL*N=#FHN6H<0x%s-K3=d&{<eHPo^0$$YGAO+#!R zMZ);AzJ_imRolwJ-pdBGlMbY_T`~Owf*YRV72`b$CELkq7r;pcCH6<i!^RWPgfw0= zTIw=SwmS4pnjtaKW^%NkT+F95(>@Gb>0D|)ubLjgR<=5PQ^Cg8Rzoz2x+t+NvQMj; zba(f?rVL+sl^(?%RkiJy`!+9LXuG(SfQ!=k{EmfGl0@}DuW6*ElQ=3`hC(b0a_6`O zbvY(Z8@Fg_m<9j+;PxOfp?-%5Y9+@?N;|_|urwE~ld5S{@gFI?uvGg8%l!5PiLYuR zp0?5NJ=l7&UDI%o*B3uuzFlX}b6bX>i`>@8U=8HVp$U+c2PMltz|ktR8|G;U4xr~u zmc?_-xIvS2CX4GWdU&OGu&y9OAQIFq?teQJ0Ypayn5wQvWsHl_+k@Y@__gS0^6ei) z)Wh+U0xb1m^eTA!o~0{kq<j!19cG4bq(K=+C4~)m+AoWIUa%~|H67gbK=6pi2v-RC zN(hLQ<mP1vZPPE-4%Rg$s(~LjnqqQ}4Gy)XsERD*V<}-2;QwnMVQj|r4Si6U1QIA& zq@2^?Z&TGx`eI?&<c=0Hlx|Ei0T`F}Vc;(?h5~n{hhkrbd#C_#7eIo4&ICqJY>g7u z%~*!^@pn8|mYfF$KnDvxl>Q#`h9s&CRA>N5+6+>2tlR%!Pvho`Fw<rv-T2zd`G8}l z5g&d9-GK=~|5z(EMAL&Wf$tz6e7NKN8%G2|Rfr+LiW@w@XA(kCV%L;)5#3M&p%R-Z z>aw7Mk80eJ{P1)H0a6o9)Bo=oOAS#p$ET0)Mopy<xe{9gNML0Le}O+#uRtRi;8`|E zva}bKZ91~2<GE@DQ6cL>>4t7U6<BkRx`m4m|H=&EgU8e^Yp;?lxzd7_OVHjpz(ca> zC~70w^jVt_V_J^Vn`x0`uV7F!b~T8nY9QSJ<~V0VJ|aoLx3R(%pCH-_a-C?m;62)4 z19CT8+wc1Tseu~rXWwfeGR@|}K{;N{FHVJtGuje@G@LaC7$D7$DqwAZiqB*zsF1PT zw*q+$34~f<8zP@AVE@hU{X1cDlW(9+5Q2L=3t@)3G=-X^sb;SJMw4ap5=I=dsPn+7 zk6>Cdk$JThJ@eW>4``^6>N<tFAQx2U52-0)J_x^I-ri)A>%IxfB#@`s@XT@M7jr6g z%D6=l<oy<{aB>A=bU~K#0usH7Z=WO%bKJPd!O!q(S5-=*^zwvj6`#Wx+BPJsBD`_O z@Z-=T6o6SXYcWc7{vS)c`N)WI))VlG=I8L+149QgVBq|>+tbP%@O0CPSH=~Q=yzUW z=_Hea$A@0lQWGG1L7FEVxBKJ<O#$q#LLHh?*&to`^*V-0FE5R;CH7X-v}o~7?X!a6 zUz@#DIo0?T{Tp8-q1kMS(2;l{-^Xy*=^hz`Cx;b0=1Lcl`nCd6KI{rI_-1N|iu!e6 zGAU;4@Z0I#!_RR^p}_NpuUBe_%$g0TqSXcBQg$fanvhMVJ9a6#XbUm@mZGzUScNds zh2&~X`m-sM5gY~bsSs3q-+`VJ!D~jRo<Rdb0xHx!3|}r|`65oZk)YaUJKoVl0JQA; zYmnTFZO<Te4bO%DQ3o75pDN<-BMPkS2U==uIlvf*9fyWZ1ndz3wPYKIiJ|O>WkKj4 zR`WIpT^LVo≧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 diff --git a/site/en/blog/new-in-chrome-117/index.md b/site/en/blog/new-in-chrome-117/index.md index 3c740b0af..cdc75980c 100644 --- a/site/en/blog/new-in-chrome-117/index.md +++ b/site/en/blog/new-in-chrome-117/index.md @@ -6,7 +6,7 @@ layout: 'layouts/blog-post.njk' date: 2023-09-12 authors: - ajara -hero: 'image/SeARmcA1EicLXagFnVOe0ou9cqK2/msCTpRahj6qrF4R4m5y3.png' +hero: 'image/kheDArv5csY6rvQUJDbWRscckLr1/EydB5vnOb9zGdw06UzZK.png' alt: > New in Chrome hero logo tags: diff --git a/site/en/blog/new-in-chrome-118/index.md b/site/en/blog/new-in-chrome-118/index.md index 44d3d38c0..1580fa6dd 100644 --- a/site/en/blog/new-in-chrome-118/index.md +++ b/site/en/blog/new-in-chrome-118/index.md @@ -6,7 +6,7 @@ layout: 'layouts/blog-post.njk' date: 2023-10-10 authors: - ajara -hero: 'image/kheDArv5csY6rvQUJDbWRscckLr1/Fykb6HbizvuTjzhXB8IW.png' +hero: 'image/kheDArv5csY6rvQUJDbWRscckLr1/rcB2kRXs70qfYA0i4iTx.png' alt: > New in Chrome hero logo tags: From eda2249e106397b31f9f9240a7c8a1c105da0410 Mon Sep 17 00:00:00 2001 From: Adam Argyle <argyle@google.com> Date: Fri, 13 Oct 2023 08:13:53 -0700 Subject: [PATCH 908/982] fixes spec typo from color 4 to color 5 (#7536) --- site/en/blog/css-relative-color-syntax/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/en/blog/css-relative-color-syntax/index.md b/site/en/blog/css-relative-color-syntax/index.md index 2fe21b8c1..6776a48a2 100644 --- a/site/en/blog/css-relative-color-syntax/index.md +++ b/site/en/blog/css-relative-color-syntax/index.md @@ -17,7 +17,7 @@ alt: > --- In Chrome 119 is a very powerful color feature from [CSS Color Level -4](https://www.w3.org/TR/css-color-5/#relative-colors). Relative color syntax +5](https://www.w3.org/TR/css-color-5/#relative-colors). Relative color syntax creates a smooth path for color manipulation within CSS, offering ways for authors and designers to: From be1db12052896b292d04186597e06775cc6fbd15 Mon Sep 17 00:00:00 2001 From: amysteamdev <37001393+AmySteam@users.noreply.github.com> Date: Fri, 13 Oct 2023 10:26:31 -0500 Subject: [PATCH 909/982] Remove aside from Commands API (#7496) * Remove aside * Update site/en/docs/extensions/reference/commands/index.md --- site/en/docs/extensions/reference/commands/index.md | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/site/en/docs/extensions/reference/commands/index.md b/site/en/docs/extensions/reference/commands/index.md index 73e37c3b6..09d163f42 100644 --- a/site/en/docs/extensions/reference/commands/index.md +++ b/site/en/docs/extensions/reference/commands/index.md @@ -276,17 +276,10 @@ If an extension attempts to register a shortcut that is already used by another second extension's shortcut will not register as expected. You can provide a more robust end user experience by anticipating this possibility and checking for collisions at install time. -{% Aside %} - -`_execute_action` will not appear in the list -of commands returned by `commands.getAll()`. - -{% endAside %} - {% Label %}service-worker.js:{% endLabel %} ```js -chrome.runtime.onInstalled.addListener((reason) => { +chrome.runtime.onInstalled.addListener(({reason}) => { if (reason === chrome.runtime.OnInstalledReason.INSTALL) { checkCommandShortcuts(); } From 4df35b3c333898e67ed083d5c9947928554b1213 Mon Sep 17 00:00:00 2001 From: aiktb <hey@aiktb.com> Date: Sat, 14 Oct 2023 03:46:59 +0800 Subject: [PATCH 910/982] Fix typo `function` is `func` (#7532) --- site/en/docs/extensions/mv3/manifest/activeTab/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/en/docs/extensions/mv3/manifest/activeTab/index.md b/site/en/docs/extensions/mv3/manifest/activeTab/index.md index 7e64570be..ab8247848 100644 --- a/site/en/docs/extensions/mv3/manifest/activeTab/index.md +++ b/site/en/docs/extensions/mv3/manifest/activeTab/index.md @@ -66,7 +66,7 @@ chrome.action.onClicked.addListener((tab) => { if (!tab.url.includes('chrome://')) { chrome.scripting.executeScript({ target: { tabId: tab.id }, - function: reddenPage + func: reddenPage }); } }); From 80bf478e5124aea8b39c9c193fe6a5a8d99173af Mon Sep 17 00:00:00 2001 From: Oliver Dunk <oliverdunk@google.com> Date: Mon, 16 Oct 2023 12:09:56 +0100 Subject: [PATCH 911/982] Fix alignment of search icons on extension samples and fugu pages (#7533) --- site/_scss/blocks/_fugu-showcase.scss | 4 ++++ site/_scss/layouts/extension-samples.scss | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/site/_scss/blocks/_fugu-showcase.scss b/site/_scss/blocks/_fugu-showcase.scss index b09429c04..a5e72117e 100644 --- a/site/_scss/blocks/_fugu-showcase.scss +++ b/site/_scss/blocks/_fugu-showcase.scss @@ -17,6 +17,10 @@ } } + .search-box__btn { + display: flex; + } + .search-box__btn--close { justify-self: end; } diff --git a/site/_scss/layouts/extension-samples.scss b/site/_scss/layouts/extension-samples.scss index 0b08da935..7004e81e2 100644 --- a/site/_scss/layouts/extension-samples.scss +++ b/site/_scss/layouts/extension-samples.scss @@ -67,6 +67,10 @@ } } + .search-box__btn { + display: flex; + } + .search-box__btn--close { justify-self: end; From b9920593ba69cee9a96bb6c4328fc4d479a9f309 Mon Sep 17 00:00:00 2001 From: Sofia Emelianova <42939855+sofiayem@users.noreply.github.com> Date: Mon, 16 Oct 2023 14:46:41 +0100 Subject: [PATCH 912/982] DevTools: Refresh overview (#7549) * refresh overview prior to migration * typo * upd recorder img * Update site/en/docs/devtools/overview/index.md Co-authored-by: Rachel Andrew <rachelandrew@google.com> * Update site/en/docs/devtools/overview/index.md Co-authored-by: Rachel Andrew <rachelandrew@google.com> --------- Co-authored-by: Rachel Andrew <rachelandrew@google.com> --- site/en/docs/devtools/overview/index.md | 115 ++++++++++++------------ 1 file changed, 55 insertions(+), 60 deletions(-) diff --git a/site/en/docs/devtools/overview/index.md b/site/en/docs/devtools/overview/index.md index 391b81344..f2ce4dc53 100644 --- a/site/en/docs/devtools/overview/index.md +++ b/site/en/docs/devtools/overview/index.md @@ -20,11 +20,11 @@ prototyping CSS, debugging JavaScript, and analyzing load performance. There are many ways to open DevTools, because different users want quick access to different parts of the DevTools UI. -- When you want to work with the DOM or CSS, right-click an element on the page and select - **Inspect** to jump into the **Elements** panel. Or press Command+Option+C (Mac) or - Control+Shift+C (Windows, Linux, ChromeOS). -- When you want to see logged messages or run JavaScript, press Command+Option+J (Mac) or - Control+Shift+J (Windows, Linux, ChromeOS) to jump straight into the **Console** panel. +- To work with the DOM or CSS, right-click an element on the page and select + **Inspect** to jump into the **Elements** panel. Or press <kbd>Command</kbd>+<kbd>Option</kbd>+<kbd>C</kbd> (Mac) or + <kbd>Control</kbd>+<kbd>Shift</kbd>+<kbd>C</kbd> (Windows, Linux, ChromeOS). +- To see logged messages or run JavaScript, press <kbd>Command</kbd>+<kbd>Option</kbd>+<kbd>J</kbd> (Mac) or + <kbd>Control</kbd>+<kbd>Shift</kbd>+<kbd>J</kbd> (Windows, Linux, ChromeOS) to jump straight into the **Console** panel. See [Open Chrome DevTools][2] for more details and workflows. @@ -33,12 +33,12 @@ See [Open Chrome DevTools][2] for more details and workflows. If you're a more experienced web developer, here are the recommended starting points for learning how DevTools can improve your productivity: -- [View and Change the DOM][3] -- [View and Change a Page's Styles (CSS)][4] +- [View and change the DOM][3] +- [View and change CSS][4] - [Debug JavaScript][5] -- [View Messages and Run JavaScript in the Console][6] -- [Optimize Website Speed][7] -- [Inspect Network Activity][8] +- [View messages and run JavaScript in the Console][6] +- [Optimize website speed][7] +- [Inspect network activity][8] ## Discover DevTools {: #discover } @@ -54,95 +54,90 @@ seriously boost your productivity. ### Device Mode {: #device-mode } -{% Img src="image/BrQidfK9jaQyIHwdw91aVpkPiib2/KCl7BybVtFjmOigO56Si.png", alt="Device Mode", width="800", height="613" %} +{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/roZeihCLy8b7qwT6HY4G.png", alt="Device mode turned on in viewport.", width="800", height="625" %} Simulate mobile devices. -- [Device Mode][9] -- [Emulate Sensors: Geolocation & Accelerometer][11] +- [Device mode][9] +- [Emulate device sensors][11] -### Elements panel & CSS {: #elements } +### Elements panel {: #elements } -{% Img src="image/BrQidfK9jaQyIHwdw91aVpkPiib2/UjVAPTnFGxLEc5RLDwBy.png", alt="Elements Panel", width="800", height="609" %} +{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/wSHhyk4ReCEtXESW4SIl.png", alt="Elements panel.", width="800", height="490" %} View and change the DOM and CSS. -- [Get Started With Viewing And Changing The DOM][12] -- [Get Started With Viewing And Changing CSS][13] -- [Inspect and Tweak Your Pages][14] -- [Edit Styles][15] +- [Get started with viewing and changing the DOM][12] +- [Get started with viewing and changing CSS][13] +- [Edit CSS][15] - [Edit the DOM][16] - [Find invalid, overridden, inactive, and other CSS][51] - [Identify potential CSS improvements][53] - [Emulate light/dark themes, contrast, and other CSS media features][52] -- [Find Unused CSS][18] -- [Inspect Animations][17] +- [Find unused CSS][18] +- [Inspect animations][17] ### Console panel {: #console } -{% Img src="image/BrQidfK9jaQyIHwdw91aVpkPiib2/hlgSxlGaLKLeQ45nGwUC.png", alt="Console Panel", width="800", height="469" %} +{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/SvFMhX9k5z5f9oIfgq3V.png", alt="Console panel.", width="800", height="560" %} View messages and run JavaScript from the Console. -- [Get Started With The Console][19] -- [Using the Console][20] -- [Interact from Command Line][21] -- [Console API Reference][22] +- [Get started with the Console][19] +- [Console Utilities API reference][21] +- [Console API reference][22] ### Sources panel {: #sources } -{% Img src="image/BrQidfK9jaQyIHwdw91aVpkPiib2/tYPZahEdu0RMGFFcCvyp.png", alt="Sources Panel", width="800", height="655" %} +{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/asZUgjzzWVOOt4APCCBb.png", alt="Sources panel.", width="800", height="559" %} Debug JavaScript, persist changes made in DevTools across page reloads, save and run snippets of -JavaScript, and save changes that you make in DevTools to disk. +JavaScript, and save changes that you make in DevTools to local sources. -- [Get Started With Debugging JavaScript][23] -- [Pause Your Code With Breakpoints][24] -- [Save Changes to Disk with Workspaces][25] -- [Run Snippets Of Code From Any Page][26] -- [JavaScript Debugging Reference][27] -- [Persist Changes Across Page Reloads with Local Overrides][28] -- [Find Unused JavaScript][29] +- [Get started with debugging JavaScript][23] +- [Pause your code with breakpoints][24] +- [Edit and save files in a workspace][25] +- [Run snippets of JavaScript][26] +- [JavaScript debugging reference][27] +- [Override web content and HTTP response headers locally][28] ### Network panel {: #network } -{% Img src="image/BrQidfK9jaQyIHwdw91aVpkPiib2/XE91VMkc9x1jdMQR1Iep.png", alt="Network Panel", width="800", height="649" %} +{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/QxdsutNioCfOjBzf9IfD.png", alt="Network panel.", width="800", height="657" %} View and debug network activity. -- [Get Started][30] -- [Network Issues Guide][31] -- [Network Panel Reference][32] -- [Inspect Resources][43] +- [Inspect network activity][30] +- [Network features reference][32] +- [View page resources][43] ### Recorder panel {: #recorder } -Record, replay, and measure user flows. +{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/fpZHfKigjAf3PB8cNQsL.png", alt="Recorder panel.", width="800", height="646" %} -{% Img src="image/dPDCek3EhZgLQPGtEG3y0fTn4v82/XKjlKjhuoccuFPCQqQ05.png", alt="Recorder panel.", width="800", height="606" %} +Record, replay, and measure user flows. -- [Get Started][54] -- [Explore extensions][55] -- [Replay beyond Recorder][56] +- [Record, replay, and measure user flows][54] +- [Customize the Recorder with extensions][55] +- [Recorder features reference][56] ### Performance panel {: #performance } -{% Img src="image/BrQidfK9jaQyIHwdw91aVpkPiib2/nCVPdzEUA2XIY5txAG1G.png", alt="Timeline Panel", width="800", height="649" %} +{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/8WrcYMjztXXwvgPF8UUB.png", alt="Performance panel.", width="800", height="693" %} Find ways to improve load and runtime performance. -- [Optimize Website Speed][33] -- [Get Started With Analyzing Runtime Performance][34] -- [Performance Analysis Reference][35] -- [Analyze runtime performance][36] -- [Diagnose Forced Synchronous Layouts][37] +- [Optimize website speed][33] +- [Analyze runtime performance][34] +- [Performance features reference][35] ### Memory panel {: #memory } -{% Img src="image/BrQidfK9jaQyIHwdw91aVpkPiib2/oR8gZtwxxhRLj77xYsWd.png", alt="Profiles Panel", width="800", height="655" %} +{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/e1Ij43yPpTlhmRrlab9h.png", alt="Memory panel.", width="800", height="562" %} + +Find and fix memory issues that affect page performance, for example, memory leaks. -- [Fix Memory Problems][38] -- [JavaScript CPU Profiler][39] +- [Fix memory problems][38] ### Application panel {: #application } @@ -152,17 +147,17 @@ Inspect all resources that are loaded, including IndexedDB or Web SQL databases, storage, cookies, Application Cache, images, fonts, and stylesheets. - [Debug Progressive Web Apps][40] -- [Inspect and Manage Storage, Databases, and Caches][41] -- [Inspect and Delete Cookies][42] +- [View and edit local storage][41] +- [View, add, edit, and delete cookies][42] - [View origin trial information][50] ### Security panel {: #security } -{% Img src="image/BrQidfK9jaQyIHwdw91aVpkPiib2/wB3jgziVHoF13hYf8Yi1.png", alt="Security Panel", width="800", height="573" %} +{% Img src="image/NJdAV9UgKuN8AhoaPBquL7giZQo1/pmyoJrTpfD8s1vA3uEiR.png", alt="Security panel.", width="800", height="562" %} Debug mixed content issues, certificate problems, and more. -- [Understand Security Issues][44] +- [Understand security issues][44] ## Community {: #community } @@ -237,8 +232,8 @@ DevTools also has a Slack channel, but the team doesn't monitor it consistently. [49]: https://chromiumdev.slack.com/messages/devtools/ [50]: /docs/web-platform/origin-trials/#devtools [51]: /docs/devtools/css/issues/ -[52]: /docs/devtools/rendering/emulate-css/ +[52]: /docs/devtools/rendering/ [53]: /docs/devtools/css-overview/ [54]: /docs/devtools/recorder/ [55]: /docs/devtools/recorder/extensions/ -[56]: /blog/extend-recorder/ +[56]: /docs/devtools/recorder/reference/ From 3d1bc26faba87dd18ac11207aa882db2762822de Mon Sep 17 00:00:00 2001 From: Oliver Dunk <oliverdunk@google.com> Date: Mon, 16 Oct 2023 16:08:57 +0100 Subject: [PATCH 913/982] Add requires policy tag (#7548) --- external/build/lib/dts-parse.js | 4 ++++ site/_includes/macros/render-type.njk | 6 ++++++ types/site/_data/types.d.ts | 1 + 3 files changed, 11 insertions(+) diff --git a/external/build/lib/dts-parse.js b/external/build/lib/dts-parse.js index 191de4d2e..cd17047e3 100644 --- a/external/build/lib/dts-parse.js +++ b/external/build/lib/dts-parse.js @@ -767,6 +767,10 @@ class Transform { chromeOsOnly = false; } break; + case 'chrome-install-location': + if (text === 'policy') { + out.requiresPolicyInstall = true; + } } }); diff --git a/site/_includes/macros/render-type.njk b/site/_includes/macros/render-type.njk index ce6ddb361..a9a36d096 100644 --- a/site/_includes/macros/render-type.njk +++ b/site/_includes/macros/render-type.njk @@ -508,6 +508,12 @@ </span> {% endif %} + {% if feature.requiresPolicyInstall %} + <span class="aside--important tag-pill type--label rounded-lg" title="Only available to policy installed extensions"> + Requires policy + </span> + {% endif %} + {% if feature.deprecated %} <span class="aside--warning tag-pill type--label rounded-lg"> Deprecated diff --git a/types/site/_data/types.d.ts b/types/site/_data/types.d.ts index e6c93bb5f..a55564f4a 100644 --- a/types/site/_data/types.d.ts +++ b/types/site/_data/types.d.ts @@ -48,6 +48,7 @@ declare global { permissions?: string[]; manifestKeys?: string[]; chromeOsOnly?: true; + requiresPolicyInstall?: true; } /** From 040c36bedf45d9414d9d609cbb292bd653a52cc2 Mon Sep 17 00:00:00 2001 From: Rachel Andrew <rachelandrew@google.com> Date: Mon, 16 Oct 2023 16:34:58 +0100 Subject: [PATCH 914/982] issue tracker blog post (#7535) * issue tracker blog post * Update description --- .../chromium-issue-tracker-migration/index.md | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 site/en/blog/chromium-issue-tracker-migration/index.md diff --git a/site/en/blog/chromium-issue-tracker-migration/index.md b/site/en/blog/chromium-issue-tracker-migration/index.md new file mode 100644 index 000000000..0dc7a3751 --- /dev/null +++ b/site/en/blog/chromium-issue-tracker-migration/index.md @@ -0,0 +1,31 @@ +--- +layout: 'layouts/blog-post.njk' +title: "Chromium issue tracker migration" +description: > + Chromium issue tracking is migrating to a tool powered by the Google Issue tracker in January 2024. +subhead: > + Chromium issue tracking is migrating to a tool powered by the Google Issue tracker in January 2024. +date: 2023-10-16 +--- + +Chromium is moving to a different issue tracker to provide a well-supported user experience for the long term. The Google team is targeting **January 2024** for migration—this post explains the details. + +## What's happening + +We will migrate all Chromium issues, including issue history and stars, from Monorail to a different tool: **Chromium Issue Tracker**, powered by the [Google Issue Tracker](https://developers.google.com/issue-tracker). This tooling change will provide a feature-rich and well-supported issue tracker for Chromium's ecosystem. Chromium will join other open source projects (Git, Gerrit) on this tooling. Existing transparency levels to bugs will be maintained. + +## Timing + +We are targeting **January 2024** for Chromium's migration, and will share milestones and timing updates throughout the coming months. + +## Migration readiness + +In due course, we will share additional resources, including a walkthrough of the new issue tracker, highlighting key features. + +## Post-migration + +While there will be differences, we are working to make the migration straightforward. Once the migration completes, existing Monorail issue links will redirect to the migrated issues in the new issue tracker. + +## Help and feedback + +You can reach out at any time to [issue-tracker-support@chromium.org](mailto:issue-tracker-support@chromium.org) with questions or concerns. \ No newline at end of file From 7e0f5c41ac2291d69e4237d7bb3dda08d5513490 Mon Sep 17 00:00:00 2001 From: Alexandra White <alexandrawhite@google.com> Date: Mon, 16 Oct 2023 14:27:02 -0400 Subject: [PATCH 915/982] move origin trial concepts in nav --- site/_data/docs/web-platform/toc.yml | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/site/_data/docs/web-platform/toc.yml b/site/_data/docs/web-platform/toc.yml index 89e903274..6240b76b9 100644 --- a/site/_data/docs/web-platform/toc.yml +++ b/site/_data/docs/web-platform/toc.yml @@ -3,9 +3,6 @@ - url: /docs/web-platform/chrome-release-channels - url: /docs/web-platform/chrome-flags - url: /docs/web-platform/chrome-variations - - url: /docs/web-platform/origin-trials - - url: /docs/web-platform/third-party-origin-trials - - url: /docs/web-platform/origin-trial-troubleshooting - title: i18n.docs.web-platform.shipped sections: @@ -24,15 +21,15 @@ - title: i18n.docs.web-platform.origin-trials sections: + - url: /docs/web-platform/origin-trials + - url: /docs/web-platform/third-party-origin-trials + - url: /docs/web-platform/origin-trial-troubleshooting - url: /docs/web-platform/launch-handler - url: /docs/web-platform/popup-api - url: /docs/web-platform/bfcache-notrestoredreasons - url: /blog/soft-navigations-experiment/ - url: /docs/web-platform/compute-pressure -- title: i18n.docs.web-platform.developer-trials - sections: - - title: i18n.docs.web-platform.not-pursuing sections: - url: /docs/web-platform/declarative-link-capturing From d2dbc162e947fd35b85a39b697d7b8c41b4e5351 Mon Sep 17 00:00:00 2001 From: Alexandra White <alexandrawhite@google.com> Date: Mon, 16 Oct 2023 14:27:21 -0400 Subject: [PATCH 916/982] Revert "move origin trial concepts in nav" This reverts commit 7e0f5c41ac2291d69e4237d7bb3dda08d5513490. --- site/_data/docs/web-platform/toc.yml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/site/_data/docs/web-platform/toc.yml b/site/_data/docs/web-platform/toc.yml index 6240b76b9..89e903274 100644 --- a/site/_data/docs/web-platform/toc.yml +++ b/site/_data/docs/web-platform/toc.yml @@ -3,6 +3,9 @@ - url: /docs/web-platform/chrome-release-channels - url: /docs/web-platform/chrome-flags - url: /docs/web-platform/chrome-variations + - url: /docs/web-platform/origin-trials + - url: /docs/web-platform/third-party-origin-trials + - url: /docs/web-platform/origin-trial-troubleshooting - title: i18n.docs.web-platform.shipped sections: @@ -21,15 +24,15 @@ - title: i18n.docs.web-platform.origin-trials sections: - - url: /docs/web-platform/origin-trials - - url: /docs/web-platform/third-party-origin-trials - - url: /docs/web-platform/origin-trial-troubleshooting - url: /docs/web-platform/launch-handler - url: /docs/web-platform/popup-api - url: /docs/web-platform/bfcache-notrestoredreasons - url: /blog/soft-navigations-experiment/ - url: /docs/web-platform/compute-pressure +- title: i18n.docs.web-platform.developer-trials + sections: + - title: i18n.docs.web-platform.not-pursuing sections: - url: /docs/web-platform/declarative-link-capturing From 49390822712d95046bd44835de307b624d765291 Mon Sep 17 00:00:00 2001 From: Jack J <jxck@google.com> Date: Tue, 17 Oct 2023 15:04:54 +0900 Subject: [PATCH 917/982] Blog post "Sanitizer API deprecation" (#7521) * Blog post "Sanitizer API deprecation" add blog post for sanitizer api deprecation. * update tags * fix authors * Update site/en/blog/sanitizer-api-deprecation/index.md Co-authored-by: Rachel Andrew <rachelandrew@google.com> --------- Co-authored-by: Rachel Andrew <rachelandrew@google.com> --- .../blog/sanitizer-api-deprecation/index.md | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 site/en/blog/sanitizer-api-deprecation/index.md diff --git a/site/en/blog/sanitizer-api-deprecation/index.md b/site/en/blog/sanitizer-api-deprecation/index.md new file mode 100644 index 000000000..a94629c6c --- /dev/null +++ b/site/en/blog/sanitizer-api-deprecation/index.md @@ -0,0 +1,22 @@ +--- +title: Sanitizer API deprecation +description: > + The current Sanitizer API implementation is deprecated from Chrome 119 to catch up with future specification updates. +layout: 'layouts/blog-post.njk' +date: 2023-10-14 +authors: + - jackjey +tags: + - security + - chrome-119 +--- + +Work on [the Sanitizer API](https://github.com/WICG/sanitizer-api) began in 2020, with the aim of building a secure API to sanitize HTML on browsers. + +Chrome shipped an initial version of the Sanitizer API in Chrome 105, based on the specification draft at that time. We introduced this version of the API to developers, and gathered useful implementation experience. + +However, changes to the specification mean that the proposed API shape has changed substantially. To prevent the current API from becoming entrenched, we decided to deprecate the current implementation in Chrome 119. + +See more details in [Intent to Deprecate: Remove "Sanitizer API MVP"](https://groups.google.com/a/chromium.org/g/blink-dev/c/PNTt4oFXt8c/m/C1bS0ityBAAJ). + +The new API is still being discussed in the [WICG](https://github.com/WICG/sanitizer-api/), and we intend to implement the result in Chrome when the specification matures. We'll post an article to introduce it once it’s ready. From 16970f7df6dce63132e65f8d5d17a69b17975b42 Mon Sep 17 00:00:00 2001 From: Jecelyn Yeen <5917927+jecfish@users.noreply.github.com> Date: Tue, 17 Oct 2023 09:42:58 +0200 Subject: [PATCH 918/982] Update broken link (#7557) --- site/en/docs/web-platform/chrome-release-channels/index.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/site/en/docs/web-platform/chrome-release-channels/index.md b/site/en/docs/web-platform/chrome-release-channels/index.md index bba7896e3..84a606408 100644 --- a/site/en/docs/web-platform/chrome-release-channels/index.md +++ b/site/en/docs/web-platform/chrome-release-channels/index.md @@ -236,7 +236,7 @@ Chrome Canary, Beta or Dev, and maintain control over software roll-out to their The operating system used by Chromebooks, Chrome OS, works the same way. If you're feeling adventurous or you want to try out new features early on, you can [switch your Chromebook to a -different Chrome OS channel](support.google.com/chromebook/answer/1086915). +different Chrome OS channel](https://support.google.com/chromebook/answer/1086915). ## Find out more @@ -246,4 +246,4 @@ different Chrome OS channel](support.google.com/chromebook/answer/1086915). - Find the latest versions for each Chrome release channel and platform, and access tools for viewing the difference between versions: [omahaproxy.appspot.com](https://omahaproxy.appspot.com/) - [Report bugs](https://www.chromium.org/getting-involved/dev-channel/#reporting-dev-channel-and-canary-build-problems) -- [Manage Chrome release channels for enterprise and education](support.google.com/chrome/a/answer/9027636) \ No newline at end of file +- [Manage Chrome release channels for enterprise and education](support.google.com/chrome/a/answer/9027636) From 56d9499b59adceef1bf089b321835deeeb1c7272 Mon Sep 17 00:00:00 2001 From: wizardofdocs <83661258+wizardofdocs@users.noreply.github.com> Date: Tue, 17 Oct 2023 06:59:30 -0700 Subject: [PATCH 919/982] Copyedits to Cookies reference (#7502) * Copyedits to Cookies reference * Removed answered comment from cookies reference * Clarified partitioned cookie explanation --- site/en/docs/extensions/reference/cookies/index.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/site/en/docs/extensions/reference/cookies/index.md b/site/en/docs/extensions/reference/cookies/index.md index f76094cd5..64949043e 100644 --- a/site/en/docs/extensions/reference/cookies/index.md +++ b/site/en/docs/extensions/reference/cookies/index.md @@ -4,8 +4,8 @@ api: cookies ## Manifest -To use the cookies API, you must declare the "cookies" permission in your -manifest, along with [host permissions][1] for any hosts whose cookies you want +To use the cookies API, declare the `"cookies"` permission in your +manifest along with [host permissions][1] for any hosts whose cookies you want to access. For example: ```json @@ -25,10 +25,10 @@ to access. For example: ## Partitioning {: #partitioning } [Partitioned cookies][chips] allow a site to mark that certain cookies should be keyed against the -origin of the top level frame. This means that if site A is embedded using an iframe in site B -and site C, a partitioned cookie can have a different value in each. +origin of the top-level frame. This means that, for example, if site A is embedded using an iframe in site B +and site C, the embedded versions of a partitioned cookie from A can have different values on B and C. -`chrome.cookies` does not support partitioning, which means that all methods +Because `chrome.cookies` doesn't support partitioning, all of its methods read and write cookies from all partitions. The [`cookies.set()`](#method-set) method stores cookies in the default partition. From 6aa6ee16c6a66c0f927cb25373661b8fb1b88b3e Mon Sep 17 00:00:00 2001 From: amysteamdev <37001393+AmySteam@users.noreply.github.com> Date: Tue, 17 Oct 2023 12:34:10 -0500 Subject: [PATCH 920/982] Update Known issues (#7558) * Init commit * Add DNR rules * Update content * Update date * Apply suggestions from code review Co-authored-by: Joe Medley <jmedley@google.com> * Update site/en/docs/extensions/migrating/known-issues/index.md --------- Co-authored-by: Joe Medley <jmedley@google.com> --- .../migrating/known-issues/index.md | 20 +++++++++---------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/site/en/docs/extensions/migrating/known-issues/index.md b/site/en/docs/extensions/migrating/known-issues/index.md index 3ecdd0662..fb9301844 100644 --- a/site/en/docs/extensions/migrating/known-issues/index.md +++ b/site/en/docs/extensions/migrating/known-issues/index.md @@ -4,7 +4,7 @@ title: Known issues when migrating to Manifest V3 seoTitle: Known issues when migrating Chrome Extensions to Manifest V3 description: '' date: 2022-09-23 -updated: 2023-05-10 +updated: 2023-10-17 tags: - extensions-news --- @@ -24,25 +24,22 @@ Recently, we announced changes to the Manifest V2 deprecation timeline, and whil We are committed to closing the following gaps before announcing a new Manifest V2 deprecation timeline: -1. **User Script support:** Allow registering content scripts with arbitrary code by adding new functionality to the scripting API. (See [our proposal](https://github.com/w3c/webextensions/blob/main/proposals/user-scripts-api.md) for details.) -1. Additional strong service worker keepalives for certain operations taking longer than five minutes. - - **Work in progress:** Added in Chrome 116 for `permissions.request()`, `desktopCapture.chooseDesktopMedia()`, `identity.launchWebAuthFlow()` and `management.uninstall()`. -1. **Increase the number of static and enabled rulesets** for Declarative Net Request (DNR). -1. Extend **[Offscreen document](/docs/extensions/reference/offscreen/) functionality** to support more reasons for using an offscreen document. - - **Work in progress:** `GEOLOCATION` added in Chrome 116 1. **Support File Handling API on ChromeOS** as a replacement for [`chrome.fileBrowserHandler`](/docs/extensions/reference/fileBrowserHandler/). +1. **User Script support:** Allow registering content scripts with arbitrary code with the new [userScripts API](/docs/extensions/reference/userscripts/). (See [our proposal](https://github.com/w3c/webextensions/blob/main/proposals/user-scripts-api.md) for details.) These issues have been collected based on feedback from partners, bug reports, and developers. In addition to these, we will continue our ongoing work to address stability issues and improve overall performance. The following issues have recently been addressed: +1. Additional **strong service worker keepalives** for certain operations taking longer than five minutes. + * Added in Chrome 116 for `permissions.request()`, `desktopCapture.chooseDesktopMedia()`, `identity.launchWebAuthFlow()` and `management.uninstall()`. + * Added in Chrome 118 for `chrome.debugger` +1. **Increase the number of static and enabled rulesets** for Declarative Net Request (DNR). Enabled static rulesets increased from 10 to 50 and total static rulesets from 50 to 100 [Chrome 120]. +1. Extend **[Offscreen document](/docs/extensions/reference/offscreen/) functionality** to support more reasons for using an offscreen document. Added [`GEOLOCATION`](/docs/extensions/mv3/geolocation/) in Chrome 116. 1. Improving **support for the [`chrome.tabCapture`](/docs/extensions/reference/tabCapture/) API** [Chrome 116]: * Support calling `getMediaStreamId()` from a service worker. * Support obtaining a `MediaStream` from a stream ID in an offscreen document. -1. **Extending service worker lifetimes** while there are active `WebSocket` connections [Chrome 116]. - +1. **Extending service worker lifetimes** while there are active [`WebSocket` connections](/docs/extensions/mv3/tut_websockets/) [Chrome 116]. ## Manifest V3 frequently asked questions @@ -67,3 +64,4 @@ The following issues have recently been addressed: **A:** We are confident that most request blocking use cases can be solved with the new [`declarativeNetRequest` API](/docs/extensions/reference/declarativeNetRequest/), which has the added benefit of avoiding the performance overhead of interprocess communication, executing code on every request, or requiring an active extension process at the time of the request. However, for complex [enterprise (or education) use cases](https://support.google.com/chrome/a/answer/9296680?hl=en), dynamic request blocking is still supported. **Did we miss something?** [Please let us know](https://groups.google.com/a/chromium.org/g/chromium-extensions). + From 2a360931e31e8f714ecc948c720551d672c25916 Mon Sep 17 00:00:00 2001 From: Joe Medley <jmedley@google.com> Date: Tue, 17 Oct 2023 10:35:16 -0700 Subject: [PATCH 921/982] Add remotely-hosted code advice to 'What's New' (#7560) * Fix date. * Change linking. * Update site/en/docs/extensions/whatsnew/index.md Co-authored-by: amysteamdev <37001393+AmySteam@users.noreply.github.com> --------- Co-authored-by: amysteamdev <37001393+AmySteam@users.noreply.github.com> --- site/en/docs/extensions/whatsnew/index.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/site/en/docs/extensions/whatsnew/index.md b/site/en/docs/extensions/whatsnew/index.md index 52f2c7504..fd4c2299c 100644 --- a/site/en/docs/extensions/whatsnew/index.md +++ b/site/en/docs/extensions/whatsnew/index.md @@ -3,7 +3,7 @@ layout: 'layouts/doc-post.njk' title: What's new in Chrome extensions description: 'Recent changes to the Chrome extensions platform, documentation, and policy' date: 2021-02-25 -updated: 2023-10-09 +updated: 2023-10-17 tags: - extensions-news @@ -15,6 +15,14 @@ tags: Check this page often to learn about changes to Chrome extensions, extensions documentation, or related policy or other changes. You'll find other notices posted on the [Extensions Google Group](https://groups.google.com/a/chromium.org/g/chromium-extensions). The [Extensions News](/tags/extensions-news/) tag lists articles about some of the topics listed here. (It even has [an RSS feed](/feeds/extensions-news.xml).) The [Chrome schedule](https://chromiumdash.appspot.com/schedule) lists stable and beta release dates. +### Improved guidance around remotely-hosted code {: #remotely-hosted-code } + +<p class="color-secondary-text type--caption">Posted on <time>October 17, 2023</time></p> + +A requirement for Manifest V3 is that extensions may no longer use remotely-hosted code. Although this has been [part of our migration guide](/docs/extensions/migrating/improve-security/#remove-remote-code) from the beginning, we thought it was worth improving the guidance around this issue. That page now provides more information, describing what's still possible in Manifest V3 and providing more information on strategies for upgrading. + +There is a related addition to the [Troubleshooting Chrome Web Store violations](/docs/webstore/troubleshooting/). A new section describes common reasons that extensions with remotely-hosted code are rejected. + ### Chrome 118: isUrlFilterCaseSensitive now defaults to false {: #118-url-filter-case-sensitive } <p class="color-secondary-text type--caption">Posted on <time>October 11, 2023</time></p> From 859a711790c77321f16671c44a59faf2920b9908 Mon Sep 17 00:00:00 2001 From: Joe Medley <jmedley@google.com> Date: Tue, 17 Oct 2023 10:51:07 -0700 Subject: [PATCH 922/982] Revert "Update Known issues (#7558)" (#7561) This reverts commit 6aa6ee16c6a66c0f927cb25373661b8fb1b88b3e. --- .../migrating/known-issues/index.md | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/site/en/docs/extensions/migrating/known-issues/index.md b/site/en/docs/extensions/migrating/known-issues/index.md index fb9301844..3ecdd0662 100644 --- a/site/en/docs/extensions/migrating/known-issues/index.md +++ b/site/en/docs/extensions/migrating/known-issues/index.md @@ -4,7 +4,7 @@ title: Known issues when migrating to Manifest V3 seoTitle: Known issues when migrating Chrome Extensions to Manifest V3 description: '' date: 2022-09-23 -updated: 2023-10-17 +updated: 2023-05-10 tags: - extensions-news --- @@ -24,22 +24,25 @@ Recently, we announced changes to the Manifest V2 deprecation timeline, and whil We are committed to closing the following gaps before announcing a new Manifest V2 deprecation timeline: +1. **User Script support:** Allow registering content scripts with arbitrary code by adding new functionality to the scripting API. (See [our proposal](https://github.com/w3c/webextensions/blob/main/proposals/user-scripts-api.md) for details.) +1. Additional strong service worker keepalives for certain operations taking longer than five minutes. + + **Work in progress:** Added in Chrome 116 for `permissions.request()`, `desktopCapture.chooseDesktopMedia()`, `identity.launchWebAuthFlow()` and `management.uninstall()`. +1. **Increase the number of static and enabled rulesets** for Declarative Net Request (DNR). +1. Extend **[Offscreen document](/docs/extensions/reference/offscreen/) functionality** to support more reasons for using an offscreen document. + + **Work in progress:** `GEOLOCATION` added in Chrome 116 1. **Support File Handling API on ChromeOS** as a replacement for [`chrome.fileBrowserHandler`](/docs/extensions/reference/fileBrowserHandler/). -1. **User Script support:** Allow registering content scripts with arbitrary code with the new [userScripts API](/docs/extensions/reference/userscripts/). (See [our proposal](https://github.com/w3c/webextensions/blob/main/proposals/user-scripts-api.md) for details.) These issues have been collected based on feedback from partners, bug reports, and developers. In addition to these, we will continue our ongoing work to address stability issues and improve overall performance. The following issues have recently been addressed: -1. Additional **strong service worker keepalives** for certain operations taking longer than five minutes. - * Added in Chrome 116 for `permissions.request()`, `desktopCapture.chooseDesktopMedia()`, `identity.launchWebAuthFlow()` and `management.uninstall()`. - * Added in Chrome 118 for `chrome.debugger` -1. **Increase the number of static and enabled rulesets** for Declarative Net Request (DNR). Enabled static rulesets increased from 10 to 50 and total static rulesets from 50 to 100 [Chrome 120]. -1. Extend **[Offscreen document](/docs/extensions/reference/offscreen/) functionality** to support more reasons for using an offscreen document. Added [`GEOLOCATION`](/docs/extensions/mv3/geolocation/) in Chrome 116. 1. Improving **support for the [`chrome.tabCapture`](/docs/extensions/reference/tabCapture/) API** [Chrome 116]: * Support calling `getMediaStreamId()` from a service worker. * Support obtaining a `MediaStream` from a stream ID in an offscreen document. -1. **Extending service worker lifetimes** while there are active [`WebSocket` connections](/docs/extensions/mv3/tut_websockets/) [Chrome 116]. +1. **Extending service worker lifetimes** while there are active `WebSocket` connections [Chrome 116]. + ## Manifest V3 frequently asked questions @@ -64,4 +67,3 @@ The following issues have recently been addressed: **A:** We are confident that most request blocking use cases can be solved with the new [`declarativeNetRequest` API](/docs/extensions/reference/declarativeNetRequest/), which has the added benefit of avoiding the performance overhead of interprocess communication, executing code on every request, or requiring an active extension process at the time of the request. However, for complex [enterprise (or education) use cases](https://support.google.com/chrome/a/answer/9296680?hl=en), dynamic request blocking is still supported. **Did we miss something?** [Please let us know](https://groups.google.com/a/chromium.org/g/chromium-extensions). - From a1fb713fa481c8885a7ee65f93e2079b4648db31 Mon Sep 17 00:00:00 2001 From: Joe Medley <jmedley@google.com> Date: Tue, 17 Oct 2023 13:50:02 -0700 Subject: [PATCH 923/982] Known issues update (#7562) * Init commit * Add DNR rules * Update content * Update date * Apply suggestions from code review Co-authored-by: Joe Medley <jmedley@google.com> * Update site/en/docs/extensions/migrating/known-issues/index.md --------- Co-authored-by: amysteam <jackandamydev@gmail.com> Co-authored-by: amysteamdev <37001393+AmySteam@users.noreply.github.com> --- .../migrating/known-issues/index.md | 20 +++++++++---------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/site/en/docs/extensions/migrating/known-issues/index.md b/site/en/docs/extensions/migrating/known-issues/index.md index 3ecdd0662..fb9301844 100644 --- a/site/en/docs/extensions/migrating/known-issues/index.md +++ b/site/en/docs/extensions/migrating/known-issues/index.md @@ -4,7 +4,7 @@ title: Known issues when migrating to Manifest V3 seoTitle: Known issues when migrating Chrome Extensions to Manifest V3 description: '' date: 2022-09-23 -updated: 2023-05-10 +updated: 2023-10-17 tags: - extensions-news --- @@ -24,25 +24,22 @@ Recently, we announced changes to the Manifest V2 deprecation timeline, and whil We are committed to closing the following gaps before announcing a new Manifest V2 deprecation timeline: -1. **User Script support:** Allow registering content scripts with arbitrary code by adding new functionality to the scripting API. (See [our proposal](https://github.com/w3c/webextensions/blob/main/proposals/user-scripts-api.md) for details.) -1. Additional strong service worker keepalives for certain operations taking longer than five minutes. - - **Work in progress:** Added in Chrome 116 for `permissions.request()`, `desktopCapture.chooseDesktopMedia()`, `identity.launchWebAuthFlow()` and `management.uninstall()`. -1. **Increase the number of static and enabled rulesets** for Declarative Net Request (DNR). -1. Extend **[Offscreen document](/docs/extensions/reference/offscreen/) functionality** to support more reasons for using an offscreen document. - - **Work in progress:** `GEOLOCATION` added in Chrome 116 1. **Support File Handling API on ChromeOS** as a replacement for [`chrome.fileBrowserHandler`](/docs/extensions/reference/fileBrowserHandler/). +1. **User Script support:** Allow registering content scripts with arbitrary code with the new [userScripts API](/docs/extensions/reference/userscripts/). (See [our proposal](https://github.com/w3c/webextensions/blob/main/proposals/user-scripts-api.md) for details.) These issues have been collected based on feedback from partners, bug reports, and developers. In addition to these, we will continue our ongoing work to address stability issues and improve overall performance. The following issues have recently been addressed: +1. Additional **strong service worker keepalives** for certain operations taking longer than five minutes. + * Added in Chrome 116 for `permissions.request()`, `desktopCapture.chooseDesktopMedia()`, `identity.launchWebAuthFlow()` and `management.uninstall()`. + * Added in Chrome 118 for `chrome.debugger` +1. **Increase the number of static and enabled rulesets** for Declarative Net Request (DNR). Enabled static rulesets increased from 10 to 50 and total static rulesets from 50 to 100 [Chrome 120]. +1. Extend **[Offscreen document](/docs/extensions/reference/offscreen/) functionality** to support more reasons for using an offscreen document. Added [`GEOLOCATION`](/docs/extensions/mv3/geolocation/) in Chrome 116. 1. Improving **support for the [`chrome.tabCapture`](/docs/extensions/reference/tabCapture/) API** [Chrome 116]: * Support calling `getMediaStreamId()` from a service worker. * Support obtaining a `MediaStream` from a stream ID in an offscreen document. -1. **Extending service worker lifetimes** while there are active `WebSocket` connections [Chrome 116]. - +1. **Extending service worker lifetimes** while there are active [`WebSocket` connections](/docs/extensions/mv3/tut_websockets/) [Chrome 116]. ## Manifest V3 frequently asked questions @@ -67,3 +64,4 @@ The following issues have recently been addressed: **A:** We are confident that most request blocking use cases can be solved with the new [`declarativeNetRequest` API](/docs/extensions/reference/declarativeNetRequest/), which has the added benefit of avoiding the performance overhead of interprocess communication, executing code on every request, or requiring an active extension process at the time of the request. However, for complex [enterprise (or education) use cases](https://support.google.com/chrome/a/answer/9296680?hl=en), dynamic request blocking is still supported. **Did we miss something?** [Please let us know](https://groups.google.com/a/chromium.org/g/chromium-extensions). + From 4b21104588822bb95610180912e76046f6034b62 Mon Sep 17 00:00:00 2001 From: amysteamdev <37001393+AmySteam@users.noreply.github.com> Date: Tue, 17 Oct 2023 15:50:39 -0500 Subject: [PATCH 924/982] What's Happening October edition (#7500) * First draft * Fix linting issues * Fix links * Add screenshots and update banner * Content tweak * Fix typo * resize screenshot * Change picture * typo fix * change title * Update links * Add space * bulb * Add link * DNR rules * Apply suggestions from copy-editing Co-authored-by: Joe Medley <jmedley@google.com> * Update site/en/blog/extension-news-october-2023/index.md * Tweaks * Apply suggestions from code review * Update UsrScr * Update site/en/blog/extension-news-october-2023/index.md Co-authored-by: Oliver Dunk <oliverdunk@google.com> * Apply suggestions from code review * Apply Sebastian's suggestions Thanks Sebastian! Co-authored-by: Sebastian Benz <sebastian.benz@gmail.com> --------- Co-authored-by: Joe Medley <jmedley@google.com> Co-authored-by: Oliver Dunk <oliverdunk@google.com> Co-authored-by: Sebastian Benz <sebastian.benz@gmail.com> --- .../blog/extension-news-october-2023/index.md | 151 ++++++++++++++++++ 1 file changed, 151 insertions(+) create mode 100644 site/en/blog/extension-news-october-2023/index.md diff --git a/site/en/blog/extension-news-october-2023/index.md b/site/en/blog/extension-news-october-2023/index.md new file mode 100644 index 000000000..fae39c2f0 --- /dev/null +++ b/site/en/blog/extension-news-october-2023/index.md @@ -0,0 +1,151 @@ +--- +layout: 'layouts/blog-post.njk' +title: What's happening in Chrome Extensions? +description: > + An overview of the recent changes in Chrome Extensions, plus exciting upcoming extension features developers can look forward to. +date: 2023-10-13 +authors: + - amysteam +tags: + - extensions-news +hero: 'image/BhuKGJaIeLNPW9ehns59NfwqKxF2/zHJnWcckEKIRCdXOGYNo.png' +alt: > + What's happening in Chrome extensions? +--- + +Back in July, we launched [a new blog series](/blog/extension-news-july-2023/) to keep you up-to-date on extension developments. Thanks to your valuable feedback and our ongoing collaboration with fellow browser vendors in the WebExtensions Community Group, we continue to enhance extension APIs and work towards greater consistency across browsers. + +Welcome to the October edition! In this post, we'll look at some of the changes the Chrome extension team has made in the past few months, as well as some new features that'll come out later this year. Let's get started! + +{% Aside %} + +If you’d like a TL;DR, feel free to jump to the [Coming soon...](#coming-soon-apis) section for new extension features you can start looking forward to 🙂. + +{% endAside %} + +## New extension APIs and features {: #new-apis } + +In this section, we share some significant API launches, briefly review other API improvements, and share upcoming releases. All launches are currently available in the latest Beta release. See the [chromium release schedule](https://chromiumdash.appspot.com/schedule) for details. + + +### Highlights {: #apis-highlights } + +#### Resolved known issues {: #closing-gap } + +The extension team has been actively working to resolve Manifest V3 stability issues. [Chrome 116 launched many improvements](/blog/chrome-116-beta-whats-new-for-extensions/) that helped us make significant progress toward closing the feature gap between Manifest V2 and V3. In Chrome 120, we will have finished addressing all our prioritized platform gaps and closed all critical bugs that are documented on the [known issues page](/docs/extensions/migrating/known-issues/). All features are currently available in Chrome 120 Canary, except fileHandler support for ChromeOS Lacros, and the userScripts API which will land later this month. Check out the updated [known issues page](/docs/extensions/migrating/known-issues/) for more details. + +#### Improved Service Worker stability {: #stable-sw } + +Service worker-related stability issues have been resolved. In Chrome 116, we added strong keep-alives to extension APIs that [display a user prompt](/blog/chrome-116-beta-whats-new-for-extensions/#sw-keepalive) and improved support for WebSockets (see the [Using WebSockets in extensions](/docs/extensions/mv3/tut_websockets/) tutorial). From Chrome 118 onward, a service worker will stay alive during an [active Debugger API session](/docs/extensions/reference/debugger/). + +Check out our updated [Service Worker guidance](/docs/extensions/mv3/service_workers/service-worker-lifecycle/#timeouts) for more details. If your users still encounter service worker-related stability issues in Chrome versions after 119, [please let us know](/docs/extensions/support-feedback/). + +#### Increased security {: #security-increase } + +Previously, navigating to some `chrome://` URLs using [`tabs.update()`](/docs/extensions/reference/tabs/#method-update), [`tabs.create`](/docs/extensions/reference/tabs/#method-create), and [`windows.create()`](/docs/extensions/reference/windows/#method-create) emitted an error or would crash Chrome. Also, [`tabs.update()`](/docs/extensions/reference/tabs/#method-update) couldn't open a Javascript URL. In Chrome 117, we expanded the number of supported `chrome://` URLs, and the Javascript URL blocking now also applies to all extension API methods. + +In Chrome 117, users will receive proactive notifications on the Chrome Extensions page if an extension they've installed is no longer available on the Chrome Web Store. This can happen if the developer unpublishes the extension, it's taken down for policy violations, or it's identified as malware. For a deep dive, see [Bringing Safety Check to the chrome://extensions page](/en/blog/extension-safety-hub/). + +In Chrome 118, extensions will not be allowed to navigate to `file://` URLs using the `chrome.tabs` and `chrome.windows` APIs unless the “Allow access to file URLs” option is enabled on the extension’s details page. See the [WECG discussion](https://github.com/w3c/webextensions/issues/426). + +### More API launches {: #apis-others } + +- **Runtime API:** Starting in Chrome 116, you can use [`runtime.getContexts()`](/docs/extensions/reference/runtime/#method-getContexts) to retrieve information about active contexts. For example, you can check if there's an [active offscreen document](/docs/extensions/reference/offscreen/#example-maintaining-the-lifecycle-of-an-offscreen-document). +- **Side Panel API** In [Chrome 116](https://chromiumdash.appspot.com/commit/8e7430446eaa0b80964b0ab1fd816ac6f33fd4cd) you can use [`sidepanel.open()`](/docs/extensions/reference/sidepanel/#user-interaction) to open the extension side panel programmatically in response to a user gesture, such as a context menu click. +- **TabCapture API** Added the ability to call `getMediaStreamId()` from the extension service worker and obtain a [`MediaStream`](https://developer.mozilla.org/docs/Web/API/MediaStream) object from a stream ID in an offscreen document in Chrome 116. See [Audio recording and screen capture](/docs/extensions/mv3/screen_capture/) for examples. +- **DeclarativeNetRequest API:** The default value for the [`isUrlFilterCaseSensitive`](/docs/extensions/reference/declarativeNetRequest/#property-RuleCondition-isUrlFilterCaseSensitive) property was changed to `false` in [Chrome 118](https://chromiumdash.appspot.com/commit/d90e6a56d0e77ce5d278a5b070098c5d8f7081fd). + +### Coming soon... {: #coming-soon-apis } + +We plan to address all remaining items on the [known issues page](/docs/extensions/migrating/known-issues/#closing-the-platform-gap) with the release of Chrome 120. Additionally, we plan to add the following features: + +- The **UserScripts API** will allow user script managers to coordinate how and when to inject a collection of user scripts into web pages. See the [WECG proposal](https://github.com/w3c/webextensions/blob/main/proposals/user-scripts-api.md) for details. +- The **ReadingList API** will allow developers to create, read, update, and delete metadata located in the Reading List panel of the side panel. Watch [What's new in Chrome extensions](/docs/extensions/whatsnew/) for the announcement. +- Following [feedback](https://github.com/w3c/webextensions/issues/318) in the Web Extensions Community Group, we are **significantly increasing the limit on enabled static rulesets from 10 to 50**. Additionally, we are **increasing the total number of allowed static rulesets from 50 to 100**. This is currently available in Canary. +- The **File Handling API:** will be available for ChromeOS extensions starting in ChromeOS 120, which lets extensions open files with specified MIME types and file extensions in a similar manner to web platform file handling. +- Extensions will be able to use the web [Push API](https://developer.mozilla.org/docs/Web/API/Push_API) via [`self.registration.pushManager.subscribe()`](https://developer.mozilla.org/docs/Web/API/PushManager/subscribe) without showing a user-visible notification by setting `userVisibleOnly` to `false`. This will make push notifications a more seamless alternative to WebSockets in service workers (MV3) for asynchronous client-server communication. See [Chromium bug](https://bugs.chromium.org/p/chromium/issues/detail?id=1319986) and [WECG discussion](https://github.com/w3c/webextensions/issues/208) for details. + +Stay tuned to the [What's new in extensions](/docs/extensions/whatsnew) page for announcements as soon as these features are available in [Chrome Beta](https://chromestatus.com/roadmap). + +## Documentation upgrades {: #new-docs } + +We've also been improving and adding to our documentation. Please continue to ask questions on the [chromium-group](https://groups.google.com/a/chromium.org/g/chromium-extensions) and [report documentation issues](/docs/extensions/support-feedback/file-a-bug/). + +### Highlights {: #doc-highlights } + +- We've revamped the [Samples landing page](/docs/extensions/samples/). You can now filter by API, permission, and type, making it easier to locate specific samples. This enhancement was a collaborative effort with our Summer of Code intern, Xuezhou Dai. Read about his experience in [this blog post](/blog/google-summer-of-code-and-chrome-extensions/). +- [Using your Google Analytics account with the Chrome Web Store](/docs/webstore/google-analytics/) describes how to view Google Analytics 4 for your Chrome Web Store listing, complementing the data provided by the Developer Dashboard. This guide provides steps to opt into Google Analytics, monitor ad performance, track conversions, and grant other accounts access to Google Analytics data. +- We published a new guide on [how cookies and web storage APIs](/docs/extensions/mv3/storage-and-cookies/) work in Chrome extensions. It includes all you need to know about [Privacy Sandbox](/docs/privacy-sandbox/) as an extension developer. +- We launched new articles on how to integrate testing in your extension projects: [Unit testing Chrome extensions](/docs/extensions/mv3/unit-testing/) and [End-to-end testing for extensions](/docs/extensions/mv3/end-to-end-testing/) covers general guidance and best practices across a number of popular frameworks. For a practical tutorial, see [Testing Chrome Extensions with Puppeteer](/docs/extensions/mv3/tut_puppeteer-testing/). + +### More updates {: #doc-others } + +- We've rewritten the [Declarative Net Request API](/docs/extensions/reference/declarativeNetRequest/) guidance in a way that paints a clearer picture of how to implement declarative rulesets. +- We added more guidance for [migrating remotely hosted code to Manifest V3](/docs/extensions/migrating/improve-security/). Plus, to minimize the risk of encountering issues during the release, we offer strategies for [Publishing your Manifest V3 extension](/docs/extensions/migrating/publish-mv3/) in stages. +- Learn how to connect to a [WebSocket in your extension's service worker](/docs/extensions/mv3/tut_websockets/). +- We expanded our [Get Help guide](/docs/extensions/support-feedback/) to include more detailed instructions on how to file a bug, keep track of existing issues, request new features, and more. + +### Coming soon... {: #coming-soon-docs } + +- User Scripts API reference and tutorial. +- Firebase tutorial and samples. +- ReadingList API reference. + +## Redesigning the Chrome Web store 🌈 {: #cws-redesign } + +<figure> + {% Img src="image/sQ51XsLqKMgSQMCZjIN0B7hlBO02/Hl9EIC00L5beXdmY1t07.png", alt="Screenshot of the Chrome Web Store home page.", width="800", height="536", class='screenshot' %}. + <figcaption> + The new Chrome Web Store home page + </figcaption> +</figure> + +Earlier this month, we announced an early preview of the revamped Chrome Web Store, as we hinted at Google I/O. Check it out for yourself! [https://chromewebstore.google.com/](https://chromewebstore.google.com/). A few noteworthy changes are: + +- Increased the list of categories from a list of eleven to a new list of [seventeen in three](/docs/webstore/best_practices/#category-revisions) category groups. +- Improved autocomplete in the search. +- Screenshots are now being displayed at significantly higher quality. If you haven't already, you can upload 1280x800 screenshots. +- Replies to questions on the Support tab now show newlines. +- When replying to user reviews and support questions, your response will now include a “Developer” badge beside your name. +- You can provide users with a direct link to the reviews page by adding "/reviews" at the end of your store item URL For example: `https://chromewebstore.google.com/detail/_EXTENSION_ID_/reviews`. + +Thanks for everyone's input so far on the [chromium-google group](https://groups.google.com/a/chromium.org/g/chromium-extensions/c/9lc7Prf9vLk/m/3trCFBWYAQAJ). Feel free to join in the discussion or send your feedback directly to the CWS team using the **Give feedback** menu item: + +<figure> + {% Img src="image/BhuKGJaIeLNPW9ehns59NfwqKxF2/ERwUa61uGIFQ65VUgsVn.png", alt="Give feedback in the Chrome Web Store page", width="400", height="323", class='screenshot' %} + <figcaption> + Giving feedback on the Chrome Web Store page + </figcaption> +</figure> + +Additionally, you can [submit a self-nomination form](https://docs.google.com/forms/d/e/1FAIpQLSf4goBOeJDSVwp7xGCZw5vORovPOBhCv_kWM-VXWDhSA0NUQg/viewform) to be featured in the Editors’ Picks collection. Stay tuned for improvements coming soon to the developer dashboard as well! + +## 💡 Did you know? {: #tips } + +- There's a new video on Debugging Chrome extensions. It covers many topics you may already be familiar with, but it also shares a few neat tricks for using DevTools in extensions. + {% YouTube id='Ta-YTDhiBIQ' %} +- You are now required to provide a privacy policy for each extension. Previously, you could only add one privacy policy per developer account, but it was awkward if you had a few extensions under one developer account. This new interface is available in the **Privacy Tab** of your item in the developer dashboard. This means that account-level privacy policies are no longer supported. +<figure> + {% Img src="image/sQ51XsLqKMgSQMCZjIN0B7hlBO02/BB2ziYwins4YpyJ7aETj.png", alt="Screenshot of the privacy policy box", width="474", height="178" %} + <figcaption> + Screenshot of the privacy policy box + </figcaption> +</figure> + +## Reaching out 🙌 {: #connecting } + +We've continued reaching out to the extension developer community through 1:1's, launching new programs, and attending summits. Here are a few highlights: + +- The extensions [Google Developer Experts program](https://developers.google.com/community/experts) was launched in August. We have over a dozen new Chrome extension-focused GDEs from around the world providing us with great feedback. It's a very exciting time for the program! +- We attended [TPAC](https://www.w3.org/2023/09/TPAC/) (W3C's annual conference) as part of the [Web Extensions Community Group](https://github.com/w3c/webextensions) and met with representatives from Firefox and Safari along with several members of the community. We made significant progress on several topics, including moving towards more consistent extension APIs, working on a specification, and building on top of Web Platform Tests to create a new testing suite. Read the full minutes in the [WECG repository](https://github.com/w3c/webextensions). +- Last week, the extension team participated in the [Ad-Filtering Dev Summit](https://adfilteringdevsummit.com/) in Amsterdam. They met several of you at a coffee chat they hosted before the summit week and the open office hours on Friday. + <figure> + {% Img src="image/BhuKGJaIeLNPW9ehns59NfwqKxF2/Dc2jNjuo21hkCq4cZBiI.jpg", alt="Extension team in Ad-filtering Dev Summit", width="600", height="533" %} + <figcaption> + Extension team in Ad-filtering Dev Summit + </figcaption> + </figure> + +Even if you were unable to attend any of these events, you can continue getting involved by asking questions on the [chromium-extensions](https://groups.google.com/a/chromium.org/g/chromium-extensions) Google group, following browser partner discussions on the [WECG](https://github.com/w3c/webextensions/issues), and reporting any documentation issues. + +Thanks again for being a part of the extension developer community! \ No newline at end of file From 4d76407721ab62b760ece747bd3340b25514c562 Mon Sep 17 00:00:00 2001 From: Oliver Dunk <oliverdunk@google.com> Date: Wed, 18 Oct 2023 00:03:05 +0100 Subject: [PATCH 925/982] Update date of What's happening in extensions (#7566) --- site/en/blog/extension-news-october-2023/index.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/site/en/blog/extension-news-october-2023/index.md b/site/en/blog/extension-news-october-2023/index.md index fae39c2f0..9f06e5798 100644 --- a/site/en/blog/extension-news-october-2023/index.md +++ b/site/en/blog/extension-news-october-2023/index.md @@ -3,7 +3,7 @@ layout: 'layouts/blog-post.njk' title: What's happening in Chrome Extensions? description: > An overview of the recent changes in Chrome Extensions, plus exciting upcoming extension features developers can look forward to. -date: 2023-10-13 +date: 2023-10-17 authors: - amysteam tags: @@ -148,4 +148,4 @@ We've continued reaching out to the extension developer community through 1:1's, Even if you were unable to attend any of these events, you can continue getting involved by asking questions on the [chromium-extensions](https://groups.google.com/a/chromium.org/g/chromium-extensions) Google group, following browser partner discussions on the [WECG](https://github.com/w3c/webextensions/issues), and reporting any documentation issues. -Thanks again for being a part of the extension developer community! \ No newline at end of file +Thanks again for being a part of the extension developer community! From fa7c040a604cb2d1a809f5bb38111c48fe5c5965 Mon Sep 17 00:00:00 2001 From: Oliver Dunk <oliverdunk@google.com> Date: Wed, 18 Oct 2023 00:15:07 +0100 Subject: [PATCH 926/982] Add What's New (#7567) --- site/en/docs/extensions/whatsnew/index.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/site/en/docs/extensions/whatsnew/index.md b/site/en/docs/extensions/whatsnew/index.md index fd4c2299c..decc990fc 100644 --- a/site/en/docs/extensions/whatsnew/index.md +++ b/site/en/docs/extensions/whatsnew/index.md @@ -15,6 +15,21 @@ tags: Check this page often to learn about changes to Chrome extensions, extensions documentation, or related policy or other changes. You'll find other notices posted on the [Extensions Google Group](https://groups.google.com/a/chromium.org/g/chromium-extensions). The [Extensions News](/tags/extensions-news/) tag lists articles about some of the topics listed here. (It even has [an RSS feed](/feeds/extensions-news.xml).) The [Chrome schedule](https://chromiumdash.appspot.com/schedule) lists stable and beta release dates. +### Blog post: What's happening in Chrome Extensions - October 2023 {: #whats-happening-10-23 } + +<p class="color-secondary-text type--caption">Posted on <time>October 17, 2023</time></p> + +We've just published the second edition of [What’s Happening in Chrome Extensions](/blog/extension-news-october-2023/). The post discusses what the extension team has been working on for the past few months, including, addressing service worker stability issues, and making good progress on closing all MV3 platform gaps. We also share exciting upcoming API releases like the Reading List API and the User Scripts API. + +### Increased static ruleset limits in Declarative Net Request API {: #canary-dnr-rules-increase } + +<p class="color-secondary-text type--caption">Posted on <time>October 17, 2023</time></p> + +Following [feedback](https://github.com/w3c/webextensions/issues/318) in the Web Extensions +Community Group, we are significantly increasing the limit on enabled static rulesets from 10 to 50. +Additionally, we are increasing the total number of allowed static rulesets from 50 to 100. This is +currently available in Canary. + ### Improved guidance around remotely-hosted code {: #remotely-hosted-code } <p class="color-secondary-text type--caption">Posted on <time>October 17, 2023</time></p> From 377bed1b580512b776b476aa08c9abe869b03a0c Mon Sep 17 00:00:00 2001 From: wizardofdocs <83661258+wizardofdocs@users.noreply.github.com> Date: Wed, 18 Oct 2023 07:31:57 -0700 Subject: [PATCH 927/982] Updated History reference and cleaned up navigation type table (#7537) * Updated History reference and cleaned up navigation type table * Update site/en/docs/extensions/reference/history/index.md Updated phrasing Co-authored-by: Joe Medley <jmedley@google.com> * Updated phrasing in History reference --------- Co-authored-by: Joe Medley <jmedley@google.com> --- .../extensions/reference/history/index.md | 54 ++++++++++++++----- 1 file changed, 40 insertions(+), 14 deletions(-) diff --git a/site/en/docs/extensions/reference/history/index.md b/site/en/docs/extensions/reference/history/index.md index 3c81c1c13..a6e2b7a4d 100644 --- a/site/en/docs/extensions/reference/history/index.md +++ b/site/en/docs/extensions/reference/history/index.md @@ -3,9 +3,11 @@ api: history has_warning: This permission <a href="/docs/extensions/mv3/permission_warnings/#permissions_with_warnings">triggers a warning</a>. --- +To interact with the user's browser history, use the history API. + ## Manifest -You must declare the "history" permission in the [extension manifest][1] to use the history API. For +To use the history API, declare the `"history"` permission in the [extension manifest][1]. For example: ```json @@ -19,15 +21,48 @@ example: } ``` -## Transition types +## Concepts and Usage + +### Transition types -The history API uses a _transition type_ to describe how the browser navigated to a particular URL +The history API uses transition types to describe how the browser navigated to a particular URL on a particular visit. For example, if a user visits a page by clicking a link on another page, the transition type is "link". -The following table describes each transition type. +The following are all available transition types: + +`"link"` +: The user arrived at this page by clicking a link on another page. + +`"typed"` +: The user arrived at this page by typing the URL in the address bar. This is also used for other explicit navigation actions. + +`"auto_bookmark"` +: The user arrived at this page through a suggestion in the UI, for example, through a menu item. + +`"auto_subframe"` +: The user arrived at this page through subframe navigation that they didn't request, such as through an ad loading in a frame on the previous page. These don't always generate new navigation entries in the back and forward menus. <!--This is my understanding of auto vs manual subframes. What am I missing?--> + +`"manual_subframe"` +: The user arrived at this page by selecting something in a subframe. + +`"generated"` +: The user arrived at this page by typing in the address bar and selecting an entry that didn't look like a URL, such as a Google search suggestion. For example, a match might have the URL of a Google search result page, but it might appear to the user as "Search Google for ...". These are different from typed navigations because the user didn't type or see the destination URL. They're also related to keyword navigations. + +`"auto_toplevel"` +: The page was specified in the command line or is the start page. + +`"form_submit"` +: The user arrived at this page by filling out values in a form and submitting the form. Not all form submissions use this transition type. <!--For example, forms that use scripts to submit their contents use what type?--> + +`"reload"` +: The user reloaded the page, either by clicking the reload button or by pressing Enter in the address bar. Session restore and Reopen closed tab also use this transition type. + +`"keyword"` +: The URL for this page was generated from a replaceable keyword other than the default search provider. -<table><tbody><tr><th>Transition type</th><th>Description</th></tr><tr id="tt_link"><td>"link"</td><td>The user got to this page by clicking a link on another page.</td></tr><tr id="tt_typed"><td>"typed"</td><td>The user got this page by typing the URL in the address bar. Also used for other explicit navigation actions. See also <a href="#tt_generated">generated</a>, which is used for cases where the user selected a choice that didn't look at all like a URL.</td></tr><tr id="tt_auto_bookmark"><td>"auto_bookmark"</td><td>The user got to this page through a suggestion in the UI—for example, through a menu item.</td></tr><tr id="tt_auto_subframe"><td>"auto_subframe"</td><td>Subframe navigation. This is any content that is automatically loaded in a non-top-level frame. For example, if a page consists of several frames containing ads, those ad URLs have this transition type. The user may not even realize the content in these pages is a separate frame, and so may not care about the URL (see also <a href="#tt_manual_subframe">manual_subframe</a>).</td></tr><tr id="tt_manual_subframe"><td>"manual_subframe"</td><td>For subframe navigations that are explicitly requested by the user and generate new navigation entries in the back/forward list. An explicitly requested frame is probably more important than an automatically loaded frame because the user probably cares about the fact that the requested frame was loaded.</td></tr><tr id="tt_generated"><td>"generated"</td><td>The user got to this page by typing in the address bar and selecting an entry that did not look like a URL. For example, a match might have the URL of a Google search result page, but it might appear to the user as "Search Google for ...". These are not quite the same as <a href="#tt_typed">typed</a> navigations because the user didn't type or see the destination URL. See also <a href="#tt_keyword">keyword</a>.</td></tr><tr id="tt_auto_toplevel"><td>"auto_toplevel"</td><td>The page was specified in the command line or is the start page.</td></tr><tr id="tt_form_submit"><td>"form_submit"</td><td>The user filled out values in a form and submitted it. Note that in some situations—such as when a form uses script to submit contents—submitting a form does not result in this transition type.</td></tr><tr id="tt_reload"><td>"reload"</td><td>The user reloaded the page, either by clicking the reload button or by pressing Enter in the address bar. Session restore and Reopen closed tab use this transition type, too.</td></tr><tr id="tt_keyword"><td>"keyword"</td><td>The URL was generated from a replaceable keyword other than the default search provider. See also <a href="#tt_keyword_generated">keyword_generated</a>.</td></tr><tr id="tt_keyword_generated"><td>"keyword_generated"</td><td>Corresponds to a visit generated for a keyword. See also <a href="#tt_keyword">keyword</a>.</td></tr></tbody></table> +`"keyword_generated"` +: Corresponds to a visit generated for a keyword. <!--How are keyword, keyword_generated, and generated different?--> ## Examples @@ -35,12 +70,3 @@ To try this API, install the [history API example](https://github.com/GoogleChro repository. [1]: /docs/extensions/mv3/manifest -[2]: #tt_generated -[3]: #tt_manual_subframe -[4]: #tt_typed -[5]: #tt_keyword -[6]: #tt_keyword_generated -[7]: #tt_keyword -[8]: https://github.com/GoogleChrome/chrome-extensions-samples/tree/master/_archive/mv2/api/history/ -[9]: https://chromium.googlesource.com/chromium/src/+/master/chrome/test/data/extensions/api_test/history/ -[10]: /docs/extensions/mv2/samples From 98b1e4e7a45b0fd9d5139778136f45aeb480adf7 Mon Sep 17 00:00:00 2001 From: Joe Medley <jmedley@google.com> Date: Wed, 18 Oct 2023 09:39:39 -0700 Subject: [PATCH 928/982] Add theme categories to web store docs. (#7177) * Add descriptions of theme categories. * Add theme categories to web store docs. * Add theme descriptions. * Update site/en/docs/webstore/best_practices/index.md Co-authored-by: Oliver Dunk <oliverdunk@google.com> * Update site/en/docs/extensions/mv3/themes/index.md * Update site/en/docs/webstore/best_practices/index.md * Update site/en/docs/webstore/best_practices/index.md Co-authored-by: Oliver Dunk <oliverdunk@google.com> * Update site/en/docs/webstore/best_practices/index.md Co-authored-by: Oliver Dunk <oliverdunk@google.com> * Update site/en/docs/webstore/best_practices/index.md Co-authored-by: Oliver Dunk <oliverdunk@google.com> * Update site/en/docs/webstore/best_practices/index.md Co-authored-by: Oliver Dunk <oliverdunk@google.com> * Update site/en/docs/webstore/best_practices/index.md Co-authored-by: Oliver Dunk <oliverdunk@google.com> * Update site/en/docs/webstore/best_practices/index.md Co-authored-by: Oliver Dunk <oliverdunk@google.com> * Update site/en/docs/webstore/best_practices/index.md Co-authored-by: Oliver Dunk <oliverdunk@google.com> * Update site/en/docs/webstore/best_practices/index.md Co-authored-by: Oliver Dunk <oliverdunk@google.com> * Update site/en/docs/webstore/best_practices/index.md Co-authored-by: Oliver Dunk <oliverdunk@google.com> * Remove 'Artist Series' (at least for now). --------- Co-authored-by: Oliver Dunk <oliverdunk@google.com> --- site/en/docs/extensions/mv3/themes/index.md | 4 +- site/en/docs/webstore/best_practices/index.md | 42 ++++++++++++++++++- 2 files changed, 43 insertions(+), 3 deletions(-) diff --git a/site/en/docs/extensions/mv3/themes/index.md b/site/en/docs/extensions/mv3/themes/index.md index 16aa99eaa..8fe4abcbd 100644 --- a/site/en/docs/extensions/mv3/themes/index.md +++ b/site/en/docs/extensions/mv3/themes/index.md @@ -3,13 +3,15 @@ layout: "layouts/doc-post.njk" title: "What are themes?" seoTitle: "Chrome Extensions: What are themes?" date: 2012-09-18 -updated: 2022-07-14 +updated: 2023-09-29 description: Guidelines on how to create a theme. --- A _theme_ is a special kind of extension that changes the way the browser looks. Themes are [packaged][1] like regular extensions, but they don't contain JavaScript or HTML code. +Themes are uploaded to the Chrome Web Store using the [same procedure as an extension](/docs/webstore/). During upload, you'll be asked to select a category. You'll find a list of theme categories in Chrome Web Store documentation [under Best practices](/docs/webstore/best_practices/#choose-theme-category-well). + You can find and try a bunch of themes at the [Chrome Web Store][2]. {% Img src="image/BrQidfK9jaQyIHwdw91aVpkPiib2/FKXt2rwf5OUMDbS5jOt1.png", diff --git a/site/en/docs/webstore/best_practices/index.md b/site/en/docs/webstore/best_practices/index.md index 2314dd7b7..4f0ea0da8 100644 --- a/site/en/docs/webstore/best_practices/index.md +++ b/site/en/docs/webstore/best_practices/index.md @@ -3,7 +3,7 @@ layout: "layouts/doc-post.njk" title: Best Practices seoTitle: Best Practices for Chrome extensions date: 2017-08-30 -updated: 2023-08-24 +updated: 2023-09-29 description: > How to create a high-quality extension and Chrome Web store listing. --- @@ -66,7 +66,7 @@ Include all the [required images][cws-images] (icon, tile, marquee, and screensh ### Choose your extension's category well {: #choose-category-well} -The developer console lets you specify a category for each extension. Choose the most appropriate category: +The developer console requires you to specify a category for your extension. Choose the most appropriate category: Accessibility : Extensions designed to enhance the browsing experience for individuals with visual impairments, hearing loss, limited dexterity, and other disabilities. This may include tools like screen readers, dark mode extensions, or utilities that help with navigation, using keyboard shortcuts, voice commands, among others. @@ -150,6 +150,44 @@ Social & Communications * Travel * Well-being +### Choose your theme's category well {: #choose-theme-category-well} + +The developer console also asks you specify a category for your theme. Choose the most appropriate category: + +Animals +: Themes inspired by animals. + +Art & Design +: Themes built merely to make your browser look pretty. + +Cars +: Themes relating to cars, such as current and classic cars. + +Colors +: Themes that skin your browser in custom colors. + +Dark & Black +: Themes that feature dark colors and imagery. + +Entertainment +: Themes inspired by popular entertainment, such as television and film franchises. + +Games & Anime +: Themes inspired by video games and anime. + +Minimalist +: Themes that simplify the look of your browser. + +Nature & Landscapes +: Themes inspired by the great outdoors. + +Space +: Themes inspired by space. + +Other +: A category for themes that don't have a home anywhere else. + + [api-sidepanel]: /docs/extensions/reference/sidePanel/ [completing-listing]: /docs/webstore/cws-dashboard-listing/ [cws-branding]: /docs/webstore/branding From fbb1eb5222b8c3a3b164ed7261643ae3913557d3 Mon Sep 17 00:00:00 2001 From: amysteamdev <37001393+AmySteam@users.noreply.github.com> Date: Wed, 18 Oct 2023 13:33:03 -0500 Subject: [PATCH 929/982] Split CWS publish article (#7559) * Split Publishing first draft * Change zip your extension * Final touches * Fix links in register * fix links * Sort links * Fix list format * FInal tweaks --- site/_data/docs/webstore/toc.yml | 2 + site/en/docs/webstore/prepare/index.md | 66 ++++++ site/en/docs/webstore/publish/index.md | 212 +++++------------- site/en/docs/webstore/register/index.md | 40 ++-- site/en/docs/webstore/set-up-account/index.md | 71 ++++++ 5 files changed, 214 insertions(+), 177 deletions(-) create mode 100644 site/en/docs/webstore/prepare/index.md create mode 100644 site/en/docs/webstore/set-up-account/index.md diff --git a/site/_data/docs/webstore/toc.yml b/site/_data/docs/webstore/toc.yml index 7f6ee0b24..d8dcef94c 100644 --- a/site/_data/docs/webstore/toc.yml +++ b/site/_data/docs/webstore/toc.yml @@ -12,6 +12,8 @@ - title: i18n.docs.webstore.publish sections: - url: /docs/webstore/register/ + - url: /docs/webstore/set-up-account/ + - url: /docs/webstore/prepare/ - url: /docs/webstore/publish/ - url: /docs/webstore/manage/ - url: /docs/webstore/update/ diff --git a/site/en/docs/webstore/prepare/index.md b/site/en/docs/webstore/prepare/index.md new file mode 100644 index 000000000..23fc326c9 --- /dev/null +++ b/site/en/docs/webstore/prepare/index.md @@ -0,0 +1,66 @@ +--- +layout: "layouts/doc-post.njk" +title: "Prepare your extension" +seoTitle: "Preparing and zipping your Chrome extension for the Chrome Web Store" +date: 2023-10-16 +description: Prepare your extension files. +--- + +After [registering][register] and [setting up][setup-account] your developer account, you can submit your extension to the Chrome Web Store. But before you do so, there are a few ways to prepare your extension and other content before submitting your item. + +## Test your extension in production {: #test } + +[Load your extension locally][locally] and make sure all your features work as intended before uploading your extension to the Chrome Web Store. + +## Review your manifest {: #manifest } + +After uploading your item, you won't have the ability to edit the metadata of your manifest in the developer dashboard. This means, that if you notice a typo, you will have to edit the manifest, increase the version number, and zip the files all over again. + +Make sure you check and include the following fields: + +`"name"` +: This [name][name] appears in the Chrome Web Store and the Chrome browser. + +`"version"` +: The [version][version] number of this extension release. + +`"icons"` +: An array specifying the [icons][icons] of your extension. + +`"description"` +: A string of no more than 132 characters that [describes][description] your extension. + +Set the initial [version number][version] in the manifest to a low value, such as 0.0.0.1. That way, you have room to increase the version number when you [upload new versions][upload] of your item. Each new +version that you upload to the Chrome Web Store must have a larger version number than the +previous version. + +## Zip your extension files {: #zip } + +To upload your extension, you need to submit a ZIP file that contains all extension files. Make sure you place the manifest file in the **root directory**, not in a folder. + +## Additional store listing content {: #listing } + +Besides the metadata in your manifest, you will also need to provide content, images, and URLs that +will help your users understand what value your extension offers. See [Creating a great listing +page][best-listing] for details on creating a high-quality listing page that clearly +communicates what your item will offer, using the item description, images, and other listing +metadata. + +## Next steps + +- [Publish your extension][publish]. + +[description]: /docs/extensions/mv3/manifest/description/ +[dev-dashboard]: https://chrome.google.com/webstore/devconsole +[icons]: /docs/extensions/mv3/manifest/icons +[locally]: /docs/extensions/mv3/getstarted/development-basics/#load-unpacked +[name]: /docs/extensions/mv3/manifest/name +[publish]: /docs/webstore/publish +[publish]: /docs/webstore/upload +[register]: /docs/webstore/register +[setup-account]: /docs/webstore/set-up-account +[version]: /docs/extensions/mv3/manifest/version +[best-listing]: /docs/webstore/best_listing/ + + + diff --git a/site/en/docs/webstore/publish/index.md b/site/en/docs/webstore/publish/index.md index df808609c..06d5fa5df 100644 --- a/site/en/docs/webstore/publish/index.md +++ b/site/en/docs/webstore/publish/index.md @@ -3,157 +3,57 @@ layout: "layouts/doc-post.njk" title: "Publish in the Chrome Web Store" date: 2014-02-28 updated: 2023-10-05 -description: > - How to publish a new extension or theme to the Chrome Web Store. +description: How to publish a new extension or theme to the Chrome Web Store. --- -This page describes how you publish a new extension or theme ("item") to the Chrome Web Store. - -{% Aside 'note' %} - -To publish updates to an existing item, or to update the percent rollout, see [Update your Chrome -Web Store item][update]. To learn about group publishers, see [Set up group -publishing][group-publishers]. - -{% endAside %} - -Before you publish an extension, you need to load it locally and test that it works, as described in -[Development Basics][dev-basics]. Make sure that it runs correctly and that all its functionality works as you -intend. - -To publish your item to the Chrome Web Store, follow these steps: - -1. Create your item's zip file. -2. Create and setup a developer account. -3. Upload your item. -4. Add assets for your listing. -5. Submit your item for publishing. - -We'll go into detail about each step below. - -## Create your item's zip file {: #create-your-items-zip-file } - -To upload your item, you need to create a ZIP file that contains the -manifest file located in the **root directory** and the files for your extension. The manifest file must specify at least the following fields: - -- `"name":`—This [name][name] appears in the Chrome Web Store and in the Chrome browser -- `"version":`—The [version][version] of the metadata, incremented -- `"icons":`—An array specifying the [icons][icons] your item uses -- `"description":`—A string of no more than 132 characters [describing][description] your extension - -Your zip file may also include other images and any files that the item requires. The contents of -the ZIP file and manifest depend on the specifics of your item. - -**Tips:** - -- Set the initial [version number][version] in the manifest to a low value, such as 0.0.0.1. That way, you - have room to increase the version number when you upload new versions of your item. Each new - version that you upload to the Chrome Web Store must have a larger version number than the - previous version. - -## Create and setup a developer account {: #create-setup-a-developer-account } - -Before you can publish your item on the Chrome Web Store, you need to pick a developer account to own your items, then set up your account in the Chrome Web Store. - -### Create your account {: #create-a-developer-account } - -First you will need to [register as a Chrome Web Store developer][register]. We suggest using a new account just for your item instead of your personal account. - -If you already host your item in Google Play and you want your Chrome Web Store listing to show an "Available for Android" link, your item must have the same name as your Google Play listing, and both items must be owned by the same developer account. To transfer your Chrome Web Store item to a different developer, submit this [form][cws-support]. - -### Set up your account {: #setup-a-developer-account } - -After registering, finish setting up your developer account on the Account page. (To access the Account page click the link in the left menu. - -{% Img src="image/sQ51XsLqKMgSQMCZjIN0B7hlBO02/3TbrDEevyQgXd6sgvf9Y.png", alt="Chrome Web Store Account page", width="800", height="274" %} - -Here you can provide your developer profile information, configure management settings and enable email notifications, among other things. The page itself provides instruction; however, there a few fields worth calling out. - -Publisher name (Required) -: Appears under the title of each of your extensions. If you are a [verified publisher][verified-publisher], you can display an official publisher URL instead. - -Add email (Required) -: Only displayed under your extensions' contact information. Any notifications will be sent to your Chrome Web Store developer account email. - -Physical address (Required in some circumstances) -: Only items that offer functionality to purchase items, additional features, or subscriptions must include a physical address. - -Trusted tester accounts (Optional) -: A comma-separated list of individuals' email addresses to make your extension available to them for testing. - -{% Aside 'important' %} -The Trusted tester accounts field does *not* support using group email addresses such as those used for posting to Google groups or other forums. If you need to test with a group, do so using the item level visibility setting. Click **Items** in the menu at left. Scroll to **Visibility**. Then select **Private** and **Only trusted testers from the current publisher settings**. -{% endAside %} - - -### Verify your email address {: #verify-contact-email } - -Verifying your contact email address is now mandatory when you set up a new developer account. When -you click **Add email** on your account page, you can enter an email address and then request -verification. The Chrome Web Store then sends a verification link to that address; use that link to -verify your address. - -**If you have an existing account** and you haven't verified your contact email address yet, your -address appears as "unverified" in the developer dashboard, as shown in this screenshot: - -{% Img src="image/SHhb2PDKzXTggPGAYpv8JgR81pX2/KZbN4VNG8mEFEDsiWglX.png", alt="Contact email field -showing as unverified", width="250", height="98", class="screenshot screenshot--filled" %} - -Click the **Verify email** link to send the verification link to your email. +After [registering][register] your developer account, [setting it up][setup-account], and [preparing your extension][prepare] follow the steps in this article to publish your extension for the first time. ## Upload your item {: #upload-your-item } -To upload your item, use the [Chrome Developer Dashboard][dev-dashboard]. +Use the following steps to upload your item: -If you need the item ID to complete your item's code, then you need to upload the item while you're -still writing its code. Otherwise, you can wait until the item is finished. You can upload your item -many times before submitting it for review. +1. Go to the [Chrome Developer Dashboard][dev-dashboard]. +1. Sign in to the developer account. +1. Click the **Add new item** button. +1. Click **Choose file** > your zip file > **Upload**. If your item's manifest and ZIP file are valid, you can edit your item on the next page. -When your item, its Chrome Web Store listing, and all the sites it relies on are ready, you can -publish your item. +Once you've uploaded your extension, you will see it as an item in the dashboard. + +<figure> + {% Img src="image/BhuKGJaIeLNPW9ehns59NfwqKxF2/xky1FZXklZRMH4UUB1az.png", alt="Screenshot of the Developer dashboard item listing page", width="800", height="499" %} + <figcaption> + Developer dashboard item listing page + </figcaption> +</figure> {% Aside %} You cannot have more than 20 _extensions_ published on the Chrome Web Store. There is no such limit on the number of themes. - {% endAside %} -Here's how to upload your item: +## Fill out information about your item {: #info } -1. Go to the [Chrome Developer Dashboard][dev-dashboard]. -2. Sign into the developer account you chose in Step 1. -3. Click the **Add new item** button. -4. Click **Choose file** > your zip file > **Upload**. If your item's manifest and ZIP file are - valid, you can edit your item on the next page. - -## Submit your item for publishing {: #submit-your-item-for-publishing } - -Once you've uploaded your extension, you will see it as an item in the dashboard. - -{% Img src="image/BrQidfK9jaQyIHwdw91aVpkPiib2/g06GNVoineSSnxt4N6Fy.png", - alt="Screenshot of the Chrome Web Store item listing page", height="472", width="800" %} - -You need to fill out additional listing information before you can publish, as contained in the -left-hand tabs. Here is a quick summary of the information on these tabs; click through for more -detail about how to fill in each tab. +Now you can fill out additional listing details in the left-hand menu. Here is a quick summary of the information you will need to fill out on each of these tabs. The links provided include detailed instructions on how to fill out each section. - The Package tab displays details of your uploaded item. This page isn't editable when you first create an item. -- The [Listing][listing] tab contains details of your listing and how it should display in the Chrome Web - Store. -- The [Privacy][privacy] tab is where you include declarations about how your item uses privacy and - security related features. -- The [Distribution][distribution] tab lets you control which countries will list your item and - which set of users will see it. +- The [Store Listing][listing] tab contains details of your listing and how it will be displayed in the Chrome Web Store. +- The [Privacy][privacy] tab is where you declare your extension's single purpose and how your extension is handling user data. +- The [Distribution][distribution] tab lets declare if your extension is a paid item, which countries will list your item and the set of users that will see it. + +## Submit your item {: #publish-item } -### To publish your item: {: #publish-item} +After [filling out the information](#info) about your item, you are ready to submit your item. When you click the **Submit for Review** button the following dialog appears, letting you confirm that you want to submit the item for review. -1. Make sure you've completed the details on all the tabs described above. -2. Click the **Submit for Review** button. -3. The following dialog appears, letting you confirm that you want to submit the item for review. -{% Img src="image/BrQidfK9jaQyIHwdw91aVpkPiib2/BiZituXHHZ74SIkwc3q7.png", +<figure> + {% Img src="image/BrQidfK9jaQyIHwdw91aVpkPiib2/BiZituXHHZ74SIkwc3q7.png", alt="Screenshot of the Chrome Web Store confirm submission dialog", height="388", width="800" %} + <figcaption> + Screenshot of the Chrome Web Store confirm submission dialog + </figcaption> +</figure> + ### Deferred publishing option {: #deferred-publishing } @@ -162,34 +62,39 @@ you uncheck the checkbox, your item will **not** be published immediately after complete. Instead, you'll be able to manually publish it at a time of your choosing once the review is complete. -{% Aside %} - -If you submit your item for review with "Publish automatically" set, you can still turn off -automatic publishing using the **Defer publish** option described below. - -{% endAside %} +If you submit your item to publish automatically after review, you can still choose deferred publishing by selecting the **Defer publish** option located in the item's menu. -{% Img src="image/SHhb2PDKzXTggPGAYpv8JgR81pX2/yoMNFt1ht6qSLXzFyrWj.png", - alt="Screenshot showing the 'more' menu's defer publish option", width="286", height="184" %} +<figure> + {% Img src="image/BhuKGJaIeLNPW9ehns59NfwqKxF2/s58dN9mMogWe5W900eD4.png", + alt="Screenshot of defer publish option in the 'more' menu", width="286", height="184", class='screenshot' %} + <figcaption> + Deferred publishing option in the items menu + </figcaption> +</figure> -This lets you pause the rollout of a submitted item if you discover an error after submitting it or -if you simply want to change your rollout time. +This lets you pause the release of a submitted item if you discover an error after submitting it or +if you simply want to change your release time. +{% Aside 'important' %} Once the review is complete, you will have up to **30 days** to publish. After that period expires, the staged submission will revert to a draft which will have to be submitted again for -review. You can check when your staged submission will expire under the status of your item. +review. +{% endAside %} -{% Img src="image/BhuKGJaIeLNPW9ehns59NfwqKxF2/sYCH3lvreW0bUWznlOsE.png", alt="Chrome Web Store -staged item -status", width="700", height="84" %} +You can check when your staged submission will expire under the status of your item. +<figure> + {% Img src="image/BhuKGJaIeLNPW9ehns59NfwqKxF2/sYCH3lvreW0bUWznlOsE.png", alt="Chrome Web Store staged item status", width="700", height="84", class='screenshot' %} + <figcaption> + Chrome Web Store staged item status + </figcaption> +</figure> -### Review of submitted items {: #review-of-submitted-items } +## The review process {: #review-of-submitted-items } -After you submit the item for review, it will undergo a review process. The time for this review -depends on the nature of your item. See [review times][review-times] for more details. +After you submit the item for review, it will undergo a review process. The time for this review depends on the nature of your item. See [Understanding the review process][cws-review] for more details. -There are important emails like take down or rejection notifications that are enabled by default. To receive an email notification when your item is published or staged, you can enable notifications in the Account page. +There are important emails like take down or rejection notifications that are enabled by default. To receive an email notification when your item is published or staged, you can enable notifications on the **Account page**. {% Img src="image/BhuKGJaIeLNPW9ehns59NfwqKxF2/l27aRFGCN4MJURmpoCQN.png", alt="Screenshot of enable staged and reviewed items", width="709", height="238" %} @@ -197,28 +102,21 @@ staged and reviewed items", width="709", height="238" %} ## Additional resources - [Update your Chrome Web Store Item][update]. -- Learn how to [Manage your Chrome Web Store Item][cws-manage]. - Understand the [Chrome Web Store Review Process][cws-review]. -[cws-manage]: /docs/webstore/manage/ [cws-review]: /docs/webstore/review-process/ [cws-support]: https://support.google.com/chrome_webstore/contact/one_stop_support -[description]: /docs/apps/manifest/description/ -[dev-basics]: /docs/extensions/mv3/getstarted/development-basics/#load-unpacked [dev-dashboard]: https://chrome.google.com/webstore/devconsole [distribution]: /docs/webstore/cws-dashboard-distribution [group-publishers]: /docs/webstore/group-publishers -[hello-extension]: /docs/extensions/mv3/overview/#hello-extensions -[icons]: /docs/extensions/mv3/manifest/icons [listing]: /docs/webstore/cws-dashboard-listing -[name]: /docs/extensions/mv3/manifest/name +[prepare]: /docs/webstore/prepare [privacy]: /docs/webstore/cws-dashboard-privacy [register]: /docs/webstore/register [review-times]: /docs/webstore/review-process/#review-time +[setup-account]: /docs/webstore/set-up-account [update]: /docs/webstore/update -[user-data]: /docs/webstore/user_data/ [verified-publisher]: /docs/webstore/cws-dashboard-listing/#displaying-your-verified-publisher-status -[version]: /docs/extensions/mv3/manifest/version diff --git a/site/en/docs/webstore/register/index.md b/site/en/docs/webstore/register/index.md index 4667d4c25..f7687df45 100644 --- a/site/en/docs/webstore/register/index.md +++ b/site/en/docs/webstore/register/index.md @@ -1,26 +1,26 @@ --- layout: "layouts/doc-post.njk" -title: "Register as a Chrome Web Store developer" +title: "Register your developer account" +seoTitle: "Register as a Chrome Web Store developer" date: 2020-08-19 -updated: 2021-08-02 +updated: 2023-08-02 description: How to register as a Chrome Web Store developer. --- -Before you can publish items on the Chrome Web Store, you must register as a CWS developer and pay a -one-time registration fee. You must provide a developer email when you create your developer -account; here are some tips about which email to use: +Before you can publish items on the Chrome Web Store, you must register as a CWS developer and pay a one-time registration fee. You must provide a developer email when you create your developer +account; here are some tips about which email to choose: -* Because you will receive important emails about your extension or you may want to delete one of your accounts, we suggest using a new email account just for publishing your Chrome Web Store items. -* Make sure to check this address frequently so that you're aware of any important alerts or - announcements. -* If you recently [deleted your Chrome Web Store developer account][1], you can't reuse its associated +- Because you will receive important emails about your extension or you may want to delete one of your accounts, we suggest using a new email account just for publishing your Chrome Web Store items. +- Make sure this is an email that you check frequently since it's where you will receive important alerts or announcements. +- If you already host your item in Google Play and you want your Chrome Web Store listing to show an "Available for Android" link, your item must have the same name as your Google Play listing, and both items must be owned by the same developer account. To transfer your Chrome Web Store item to a different developer, submit this [form][cws-support]. +- If you recently [deleted your Chrome Web Store developer account][delete-account], you can't reuse its associated email identity to create a new one. {% Aside 'warning' %} - If you requested the deletion of your account by mistake, please [contact developer support][2] + If you requested the deletion of your account by mistake, please [contact developer support][one-stop] immediately. {% endAside %} -To register, just access the [developer console][3]. The first time you do this, the following registration screen will appear. First agree to the developer agreement and policies then pay the registration fee. +To register, just access the [developer console][console]. The first time you do this, the following registration screen will appear. First agree to the developer agreement and policies then pay the registration fee. {% Img src="image/sQ51XsLqKMgSQMCZjIN0B7hlBO02/TicgeLawYpcvWXvTThia.png", alt="Screenshot of the Chrome Web Store developer registration page", height="678", width="800" %} @@ -29,13 +29,13 @@ Once you pay the registration fee and agree to the terms, you will not see this ## Next steps {: #next-steps } -1. [Continue setting up your developer account][4] -1. [Upload your item to the Chrome Web Store][5] -1. If you want to share the ownership of your extension [set up a group publisher][6] +1. [Continue setting up your developer account][setup] +1. [Prepare your extension][prepare] +1. [Publish to the Chrome Web Store][publish] -[1]: /docs/webstore/account-deletion/ -[2]: https://support.google.com/chrome_webstore/contact/one_stop_support -[3]: https://chrome.google.com/webstore/devconsole -[4]: /docs/webstore/publish#setup-a-developer-account -[5]: /docs/webstore/publish/#upload-your-item -[6]: /docs/webstore/group-publishers/ +[console]: https://chrome.google.com/webstore/devconsole +[delete-account]: /docs/webstore/account-deletion/ +[one-stop]: https://support.google.com/chrome_webstore/contact/one_stop_support +[prepare]: /docs/webstore/publish/ +[publish]: /docs/webstore/publish/ +[setup]: /docs/webstore/set-up-account/ diff --git a/site/en/docs/webstore/set-up-account/index.md b/site/en/docs/webstore/set-up-account/index.md new file mode 100644 index 000000000..a0e28bbf0 --- /dev/null +++ b/site/en/docs/webstore/set-up-account/index.md @@ -0,0 +1,71 @@ +--- +layout: "layouts/doc-post.njk" +title: "Set up your developer account" +seoTitle: "Set up your Chrome Web Store developer account" +date: 2023-10-16 +description: How to set up your Chrome Web Store developer account. +--- + +After [registering your developer account][register], you can proceed to fill out additional information about your account. + +## Fill out your account information + +To set up your account go to the **Account page** in the developer dashboard, located on the left menu. + +<figure> +{% Img src="image/BhuKGJaIeLNPW9ehns59NfwqKxF2/pSgZrafhiuoLlHJqkBde.png", alt="Chrome Web Store account page", width="800", height="675" %} + <figcaption> + Chrome Web Store Account page + </figcaption> +</figure> + +Here you can provide your developer profile information, configure management settings and enable email notifications, among other things. The page itself provides instructions; however, there are a few fields worth calling out. + +Publisher name (Required) +: Appears under the title of each of your extensions. If you are a [verified publisher][verified-publisher], you can display an official publisher URL instead. + +Verify your email (Required) +: Only displayed under your extensions' contact information. Any notifications will be sent to your Chrome Web Store developer account email. See [Verify your email address](#verify-contact-email) for details + +Physical address (Required in some circumstances) +: Only items that offer functionality to purchase items, additional features, or subscriptions must include a physical address. + +Trusted tester accounts (Optional) +: A comma-separated list of individuals' email addresses to make your extension available to them for testing. + +{% Aside 'important' %} +The Trusted tester accounts field does *not* support using group email addresses such as those used for posting to Google groups or other forums. If you need to test with a group, do so using the item level visibility setting. Click **Items** in the menu at left. Scroll to **Visibility**. Then select **Private** and **Only trusted testers from the current publisher settings**. +{% endAside %} + +## Verify your email address {: #verify-contact-email } + +Verifying your contact email address is required when you set up a new developer account. When +you click **Add email** on your account page, you can enter an email address and then request +verification. The Chrome Web Store then sends a verification link to that address; use that link to +verify your address. + +{% Img src="image/SHhb2PDKzXTggPGAYpv8JgR81pX2/KZbN4VNG8mEFEDsiWglX.png", alt="Contact email field +showing as unverified", width="250", height="98", class="screenshot screenshot--filled" %} + +Click the **Verify email** link to send the verification link to your email. + +## Next steps + +- [Prepare your extension][prepare]. +- [Publish your extension][publish]. + +[group-publishers]: /docs/webstore/group-publishers +[listing]: /docs/webstore/cws-dashboard-listing +[name]: /docs/extensions/mv3/manifest/name +[prepare]: /docs/webstore/prepare +[privacy]: /docs/webstore/cws-dashboard-privacy +[publish]: /docs/webstore/publish +[register]: /docs/webstore/register +[review-times]: /docs/webstore/review-process/#review-time +[update]: /docs/webstore/update +[user-data]: /docs/webstore/user_data/ +[verified-publisher]: /docs/webstore/cws-dashboard-listing/#displaying-your-verified-publisher-status +[version]: /docs/extensions/mv3/manifest/version + + + From 5b2244536ac8dbbf5d44cce5cf074c35ce5d8a86 Mon Sep 17 00:00:00 2001 From: Willie Ho <wkite2001@gmail.com> Date: Thu, 19 Oct 2023 02:34:35 +0800 Subject: [PATCH 930/982] fix: grammar error in tut-quick-reference/index.md (#7552) --- .../docs/extensions/mv3/getstarted/tut-quick-reference/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/en/docs/extensions/mv3/getstarted/tut-quick-reference/index.md b/site/en/docs/extensions/mv3/getstarted/tut-quick-reference/index.md index c87703d5b..db89b0966 100644 --- a/site/en/docs/extensions/mv3/getstarted/tut-quick-reference/index.md +++ b/site/en/docs/extensions/mv3/getstarted/tut-quick-reference/index.md @@ -308,7 +308,7 @@ async function createAlarm() { createAlarm(); -// Update tip once a the day +// Update tip once a day chrome.alarms.onAlarm.addListener(updateTip); ``` From 5088763279993e0bd38c77b6c62c6b822fdc59b9 Mon Sep 17 00:00:00 2001 From: Joe Medley <jmedley@google.com> Date: Wed, 18 Oct 2023 13:19:11 -0700 Subject: [PATCH 931/982] Incorporate text that was in the FAQ (#7584) --- site/en/docs/extensions/mv3/index.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/site/en/docs/extensions/mv3/index.md b/site/en/docs/extensions/mv3/index.md index e5bbbb327..cf54340ce 100644 --- a/site/en/docs/extensions/mv3/index.md +++ b/site/en/docs/extensions/mv3/index.md @@ -5,10 +5,12 @@ seoTitle: Welcome to Chrome Extensions subhead: 'Learn about developing extensions for Chrome.' description: 'Documentation for Chrome extensions developers.' date: 2020-11-09 -updated: 2023-02-21 +updated: 2023-10-18 --- -These pages contain guides and reference information for developers who want to +Google Chrome Extensions are applications that run inside the Chrome browser and provide additional +functionality, integration with third party websites or services, and customized browsing +experiences. These pages contain guides and reference information for developers who want to create extensions for the Chrome browser. If you're not sure where to begin, have a look at the following starting pages: From a8261b89151f92be71f171a3cc8fe820c4328764 Mon Sep 17 00:00:00 2001 From: amysteamdev <37001393+AmySteam@users.noreply.github.com> Date: Wed, 18 Oct 2023 15:44:27 -0500 Subject: [PATCH 932/982] Fix links (#7585) --- site/en/docs/webstore/prepare/index.md | 4 ++-- site/en/docs/webstore/register/index.md | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/site/en/docs/webstore/prepare/index.md b/site/en/docs/webstore/prepare/index.md index 23fc326c9..e3ae48e0d 100644 --- a/site/en/docs/webstore/prepare/index.md +++ b/site/en/docs/webstore/prepare/index.md @@ -14,7 +14,7 @@ After [registering][register] and [setting up][setup-account] your developer acc ## Review your manifest {: #manifest } -After uploading your item, you won't have the ability to edit the metadata of your manifest in the developer dashboard. This means, that if you notice a typo, you will have to edit the manifest, increase the version number, and zip the files all over again. +After uploading your item, you won't be able to edit the metadata of your manifest in the developer dashboard. This means, that if you notice a typo, you will have to edit the manifest, increase the version number, and zip the files all over again. Make sure you check and include the following fields: @@ -56,7 +56,7 @@ metadata. [locally]: /docs/extensions/mv3/getstarted/development-basics/#load-unpacked [name]: /docs/extensions/mv3/manifest/name [publish]: /docs/webstore/publish -[publish]: /docs/webstore/upload +[upload]: /docs/webstore/upload [register]: /docs/webstore/register [setup-account]: /docs/webstore/set-up-account [version]: /docs/extensions/mv3/manifest/version diff --git a/site/en/docs/webstore/register/index.md b/site/en/docs/webstore/register/index.md index f7687df45..d6c4be0ed 100644 --- a/site/en/docs/webstore/register/index.md +++ b/site/en/docs/webstore/register/index.md @@ -12,7 +12,7 @@ account; here are some tips about which email to choose: - Because you will receive important emails about your extension or you may want to delete one of your accounts, we suggest using a new email account just for publishing your Chrome Web Store items. - Make sure this is an email that you check frequently since it's where you will receive important alerts or announcements. -- If you already host your item in Google Play and you want your Chrome Web Store listing to show an "Available for Android" link, your item must have the same name as your Google Play listing, and both items must be owned by the same developer account. To transfer your Chrome Web Store item to a different developer, submit this [form][cws-support]. +- If you already host your item in Google Play and you want your Chrome Web Store listing to show an "Available for Android" link, your item must have the same name as your Google Play listing, and both items must be owned by the same developer account. To transfer your Chrome Web Store item to a different developer, submit this [form][one-stop]. - If you recently [deleted your Chrome Web Store developer account][delete-account], you can't reuse its associated email identity to create a new one. {% Aside 'warning' %} @@ -36,6 +36,6 @@ Once you pay the registration fee and agree to the terms, you will not see this [console]: https://chrome.google.com/webstore/devconsole [delete-account]: /docs/webstore/account-deletion/ [one-stop]: https://support.google.com/chrome_webstore/contact/one_stop_support -[prepare]: /docs/webstore/publish/ +[prepare]: /docs/webstore/prepare/ [publish]: /docs/webstore/publish/ [setup]: /docs/webstore/set-up-account/ From 055ca78e51260a273cfb466456e8cda637d7b99e Mon Sep 17 00:00:00 2001 From: Matthias Rohmer <mrohmer@google.com> Date: Thu, 19 Oct 2023 14:49:26 +0200 Subject: [PATCH 933/982] fix: increase memory limit for external data 11ty build --- .cloudbuild/external.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.cloudbuild/external.yaml b/.cloudbuild/external.yaml index 85bdb99d2..69e25ba0d 100644 --- a/.cloudbuild/external.yaml +++ b/.cloudbuild/external.yaml @@ -29,6 +29,8 @@ steps: - name: node:16.14.2 id: 'Build eleventy in dev mode to confirm' entrypoint: npm + env: + - 'NODE_OPTIONS="--max_old_space_size=8192"' args: ['run', 'eleventy'] # This does NOT set `NODE_ENV=production`, as we don't need the full build. From e31cdcfe44cca70a36ed2b6793034118c2facd80 Mon Sep 17 00:00:00 2001 From: Oliver Dunk <oliverdunk@google.com> Date: Thu, 19 Oct 2023 14:39:16 +0100 Subject: [PATCH 934/982] Add note on reloading unpacked extensions (#7595) * Add note on reloading unpacked extensions * Apply suggestions from code review Co-authored-by: amysteamdev <37001393+AmySteam@users.noreply.github.com> --------- Co-authored-by: amysteamdev <37001393+AmySteam@users.noreply.github.com> --- site/en/docs/extensions/reference/runtime/index.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/site/en/docs/extensions/reference/runtime/index.md b/site/en/docs/extensions/reference/runtime/index.md index 440311dc5..cd00eb654 100644 --- a/site/en/docs/extensions/reference/runtime/index.md +++ b/site/en/docs/extensions/reference/runtime/index.md @@ -80,6 +80,14 @@ The following example shows how to declare the `nativeMessaging` permission in t } ``` +## Concepts and usage {: #concepts } + +### Unpacked extension behavior {: #unpacked } + +When an [unpacked][unpacked] extension is [reloaded][reload], this is treated as an update. This means that the +[`chrome.runtime.onInstalled`][method-oninstalled] event will fire with the `"update"` reason. This +includes when the extension is reloaded with [`chrome.runtime.reload()`][method-reload]. + ## Use cases {: #examples} ### Add an image to a web page {: #example-get-url } @@ -204,3 +212,5 @@ See the [Manifest V3 - Web Accessible Resources demo][github-war-sample] for mor [method-sendmessage]: #method-sendMessage [method-sendnativemessage]: #method-sendNativeMessage [method-setuninstallurl]: #method-setUninstallURL +[unpacked]: /docs/extensions/mv3/getstarted/development-basics/#load-unpacked +[reload]: /docs/extensions/mv3/getstarted/development-basics/#reload From beaeb09d07379ee29cc378761fa9c4d25c4afffb Mon Sep 17 00:00:00 2001 From: Joe Medley <jmedley@google.com> Date: Thu, 19 Oct 2023 08:56:38 -0700 Subject: [PATCH 935/982] Add a new storage procedure to migration guide (#7598) * Add a new storage procedure to migration guide. * Update site/en/docs/extensions/migrating/to-service-workers/index.md --- .../migrating/to-service-workers/index.md | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/site/en/docs/extensions/migrating/to-service-workers/index.md b/site/en/docs/extensions/migrating/to-service-workers/index.md index 027f4be64..4710c3041 100644 --- a/site/en/docs/extensions/migrating/to-service-workers/index.md +++ b/site/en/docs/extensions/migrating/to-service-workers/index.md @@ -4,7 +4,7 @@ title: Migrate to a service worker subhead: 'Replacing background or event pages with a service worker' description: 'A service worker enables extensions to run only when needed, saving resources.' date: 2023-03-09 -updated: 2023-05-19 +updated: 2023-08-28 --- {% Partial 'extensions/mv3-support.md' %} @@ -109,10 +109,17 @@ Communicate between offscreen documents and extension service workers using [mes ## Convert localStorage to another type {: #convert-localstorage } -The web platform's [`Storage`](https://developer.mozilla.org/docs/Web/API/Storage) interface (accessible from `window.localStorage`) cannot be used in a service worker. To address this do one of the following: +The web platform's [`Storage`](https://developer.mozilla.org/docs/Web/API/Storage) interface (accessible from `window.localStorage`) cannot be used in a service worker. To address this do one of two things. First, you can replace it with calls to another storage mechanism. The [`chrome.storage.local`](/docs/extensions/reference/storage/#property-local) namespace will serve most use cases, but [other options](/docs/extensions/mv3/service_workers/service-worker-lifecycle/#persist-data) are available. -* Move its calls to an [offscreen document](/docs/extensions/reference/offscreen/). -* Replace it with calls to another storage mechanism. The [`chrome.storage.local`](/docs/extensions/reference/storage/#property-local) namespace will serve most use cases. [Other options](/docs/extensions/mv3/service_workers/service-worker-lifecycle/#persist-data) are available. +You can also move its calls to an [offscreen document](/docs/extensions/reference/offscreen/). For example, to migrate data previously stored in `localStorage` to another mechanism: + +1. Create an offscreen document with a conversion routine and a [`runtime.onMessage`](/docs/extensions/reference/runtime/#event-onMessage) handler. +1. Add a conversion routine to the offscreen document. +1. In the extension service worker check [`chrome.storage`](/docs/extensions/reference/storage/) for your data. +1. If your data isn't found, [create](/docs/extensions/reference/offscreen/#method-createDocument) an offscreen document and call [`runtime.sendMessage()`](/docs/extensions/reference/runtime/#method-sendMessage) to start the conversion routine. +1. In the `runtime.onMessage` handler that you added to the offscreen document, call the conversion routine. + +There are also some nuances with how web storage APIs work in extensions. Learn more in [Storage and Cookies][storage-and-cookies]. ## Register listeners synchronously {: #register-listeners } From 72e5b946bd9911863321c41bc56e35dbdf0287bc Mon Sep 17 00:00:00 2001 From: Joe Medley <jmedley@google.com> Date: Thu, 19 Oct 2023 19:45:40 -0700 Subject: [PATCH 936/982] Use corp standard title. (#7592) --- site/en/docs/extensions/mv3/geolocation/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/en/docs/extensions/mv3/geolocation/index.md b/site/en/docs/extensions/mv3/geolocation/index.md index 2fd8d3321..4797528a6 100644 --- a/site/en/docs/extensions/mv3/geolocation/index.md +++ b/site/en/docs/extensions/mv3/geolocation/index.md @@ -1,6 +1,6 @@ --- layout: "layouts/doc-post.njk" -title: "Using geolocation" +title: "Use geolocation" seoTitle: "Using geolocation in Chrome Extensions" date: 2023-06-20 description: How to use geolocation in Chrome extension service workers, popups, side panels, or content scripts. From fd63fe7dae7395c99d35813ba9f3514bad640f3e Mon Sep 17 00:00:00 2001 From: Joe Medley <jmedley@google.com> Date: Thu, 19 Oct 2023 19:45:56 -0700 Subject: [PATCH 937/982] Change to corp standard title (#7591) --- site/en/docs/extensions/mv3/tut_analytics/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/en/docs/extensions/mv3/tut_analytics/index.md b/site/en/docs/extensions/mv3/tut_analytics/index.md index b39372454..76e5bf77a 100644 --- a/site/en/docs/extensions/mv3/tut_analytics/index.md +++ b/site/en/docs/extensions/mv3/tut_analytics/index.md @@ -1,7 +1,7 @@ --- layout: "layouts/doc-post.njk" -title: "Using Google Analytics 4" +title: "Use Google Analytics 4" seoTitle: "How to use Google Analytics 4 in your Chrome Extension" date: 2012-09-18 updated: 2023-05-23 From cd2b4f6475a642746ef5cc44c2dd34231ab7887d Mon Sep 17 00:00:00 2001 From: Joe Medley <jmedley@google.com> Date: Thu, 19 Oct 2023 19:46:21 -0700 Subject: [PATCH 938/982] Remove superfluous heading (#7589) --- site/en/docs/extensions/mv3/permission_warnings/index.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/site/en/docs/extensions/mv3/permission_warnings/index.md b/site/en/docs/extensions/mv3/permission_warnings/index.md index 63964a77c..10e1ef44f 100644 --- a/site/en/docs/extensions/mv3/permission_warnings/index.md +++ b/site/en/docs/extensions/mv3/permission_warnings/index.md @@ -11,8 +11,6 @@ anchorRedirects: understanding_permissions: /docs/extensions/mv3/declare_permissions --- -## Overview {: overview } - Chrome extensions enhance the user's browser experience. To do this extensions use [Chrome APIs][doc-apis] that require certain permissions. Some permissions are less intrusive and do not display a warning. Other permissions trigger a warning that users have to allow. @@ -439,4 +437,4 @@ the steps in [Viewing Warnings](#view_warnings). [section-update]: #update_permissions [section-view-warnings]: #view_warnings [section-warnings]: #permissions_with_warnings -[tabs-tab]: /docs/extensions/reference/tabs/#type-Tab \ No newline at end of file +[tabs-tab]: /docs/extensions/reference/tabs/#type-Tab From 1de8673d25f9f843de34fd61b5677ece789cbb03 Mon Sep 17 00:00:00 2001 From: Sam Dutton <samdutton@users.noreply.github.com> Date: Fri, 20 Oct 2023 14:56:18 +0100 Subject: [PATCH 939/982] RWS: minor fixes (#7604) --- .../docs/privacy-sandbox/related-website-sets/index.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/site/en/docs/privacy-sandbox/related-website-sets/index.md b/site/en/docs/privacy-sandbox/related-website-sets/index.md index ec7780112..58010e082 100644 --- a/site/en/docs/privacy-sandbox/related-website-sets/index.md +++ b/site/en/docs/privacy-sandbox/related-website-sets/index.md @@ -7,7 +7,7 @@ description: > Related Website Sets (RWS) is a way for a company to declare relationships among sites, so that browsers allow limited third-party cookie access for specific purposes. hero: image/vgdbNJBYHma2o62ZqYmcnkq3j0o1/OLx3AXkweLjAiDzoDslb.png date: 2023-03-07 -updated: 2023-09-26 +updated: 2023-10-20 authors: - mihajlija --- @@ -26,7 +26,7 @@ Related sites like these often rely on cookies to keep you signed in or show you As [Chrome moves towards blocking third-party cookies](https://blog.chromium.org/2020/01/building-more-private-web-path-towards.html) to improve privacy on the web, new mechanisms are needed to enable these experiences to work. {% Aside %} -Cookies set by the site you visit—the one shown in the URL bar—are first-party cookies. A site you visit can embed content from other sites, for example, images, ads, and text. Cookies coming from sites other than the current site are [third-party cookies](https://web.dev/articles/samesite-cookie-recipes#use_cases_for_cross_site_or_third_party_cookies). +Cookies set by the site you visit—the one shown in the URL bar—are first-party cookies. A site you visit can embed content from other sites: for example, images, ads, and text. Cookies coming from sites other than the current site are [third-party cookies](https://web.dev/articles/samesite-cookie-recipes#use_cases_for_cross_site_or_third_party_cookies). {% endAside %} ## Defining related sites with Related Website Sets @@ -35,7 +35,7 @@ Related Website Sets is a way for a company to declare relationships among sites At a high level, a Related Website Set is a collection of domains, for which there is a single "set primary" and potentially multiple "set members." -Site authors need to [submit their domains to a set](https://github.com/GoogleChrome/first-party-sets/blob/main/FPS-Submission_Guidelines.md). Set members can include a range of different domain types with [subsets based on use cases](https://github.com/WICG/first-party-sets#defining-a-set-through-use-case-based-subsets). +Site authors need to [submit their domains to a set](https://github.com/GoogleChrome/related-website-sets/blob/main/RWS-Submission_Guidelines.md). Set members can include a range of different domain types with [subsets based on use cases](https://github.com/WICG/first-party-sets#defining-a-set-through-use-case-based-subsets). ## Related Website Sets use cases @@ -51,8 +51,8 @@ An organization may have different top-level domains for: ## Find out more -- [First-Party developer guide](/docs/related-website-sets-integration/) -- [Related Website Sets technical explainer](https://github.com/WICG/first-party-sets#introduction) +- [Related Website Sets: developer guide](/docs/related-website-sets-integration/) +- [Related Website Sets: technical explainer](https://github.com/WICG/first-party-sets#introduction) - [Chrome Platform Status](https://chromestatus.com/feature/5640066519007232) - [Chromium Projects](https://www.chromium.org/updates/first-party-sets) - [Privacy Sandbox Developer Support repo](https://github.com/GoogleChromeLabs/privacy-sandbox-dev-support) From ece66e3d0d5e35bb1b47f90ffa01e9830254554a Mon Sep 17 00:00:00 2001 From: Joe Medley <jmedley@google.com> Date: Fri, 20 Oct 2023 07:12:05 -0700 Subject: [PATCH 940/982] Fix titles. (#7590) * Fix titles. * Update site/en/docs/extensions/mv3/sandboxingEval/index.md Co-authored-by: amysteamdev <37001393+AmySteam@users.noreply.github.com> --------- Co-authored-by: amysteamdev <37001393+AmySteam@users.noreply.github.com> --- site/en/docs/extensions/mv3/sandboxingEval/index.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/site/en/docs/extensions/mv3/sandboxingEval/index.md b/site/en/docs/extensions/mv3/sandboxingEval/index.md index ab17a24d5..83aab8bcf 100644 --- a/site/en/docs/extensions/mv3/sandboxingEval/index.md +++ b/site/en/docs/extensions/mv3/sandboxingEval/index.md @@ -1,6 +1,7 @@ --- layout: "layouts/doc-post.njk" -title: "Using eval in Chrome extensions" +title: "Use eval() in sandboxed iframes" +seoTitle: "Use eval() - Chrome Extensions" date: 2012-09-18 updated: 2023-02-06 description: How to use eval() in a Chrome Extension. From 805fc8bfbca3655a25ccd55ecf9b37cf997f822d Mon Sep 17 00:00:00 2001 From: amysteamdev <37001393+AmySteam@users.noreply.github.com> Date: Fri, 20 Oct 2023 12:04:07 -0500 Subject: [PATCH 941/982] fix screenshot (#7602) --- site/en/docs/webstore/publish/index.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/site/en/docs/webstore/publish/index.md b/site/en/docs/webstore/publish/index.md index 06d5fa5df..e4091a675 100644 --- a/site/en/docs/webstore/publish/index.md +++ b/site/en/docs/webstore/publish/index.md @@ -65,9 +65,9 @@ is complete. If you submit your item to publish automatically after review, you can still choose deferred publishing by selecting the **Defer publish** option located in the item's menu. <figure> - {% Img src="image/BhuKGJaIeLNPW9ehns59NfwqKxF2/s58dN9mMogWe5W900eD4.png", - alt="Screenshot of defer publish option in the 'more' menu", width="286", height="184", class='screenshot' %} - <figcaption> +{% Img src="image/SHhb2PDKzXTggPGAYpv8JgR81pX2/yoMNFt1ht6qSLXzFyrWj.png", + alt="Screenshot showing the 'more' menu's defer publish option", width="286", height="184", class='screenshot' %} + <figcaption> Deferred publishing option in the items menu </figcaption> </figure> From 47a45b7cb022ea967e775fb42452180905923607 Mon Sep 17 00:00:00 2001 From: wizardofdocs <83661258+wizardofdocs@users.noreply.github.com> Date: Fri, 20 Oct 2023 11:21:33 -0700 Subject: [PATCH 942/982] Updated header in UI customization guide (#7564) --- .../en/docs/android/custom-tabs/guide-ui-customization/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/en/docs/android/custom-tabs/guide-ui-customization/index.md b/site/en/docs/android/custom-tabs/guide-ui-customization/index.md index daa27ba35..b6e425587 100644 --- a/site/en/docs/android/custom-tabs/guide-ui-customization/index.md +++ b/site/en/docs/android/custom-tabs/guide-ui-customization/index.md @@ -72,7 +72,7 @@ CustomTabsIntent intent = new CustomTabsIntent.Builder() .build(); ``` -## Further customizations: Title, Autohide AppBar, custom close icon, and Referrer +## Further customizations: title, autohide AppBar, and custom close icon <figure> {% Video src="video/6hHqS5auVgWhN0cQNQztaJx5w4M2/6VwbdckaWUVq9sNZAosC.mp4", preload=true, loop=true, playsinline=true, autoplay=true, width="320", height="692", class="screenshot" %} From f5e3e4060a735f4e6aff97360d3b070654d13e52 Mon Sep 17 00:00:00 2001 From: Joe Medley <jmedley@google.com> Date: Fri, 20 Oct 2023 12:41:41 -0700 Subject: [PATCH 943/982] Remove an old stray document. (#7608) --- .../reference/experimental_inputUI/index.md | 12 ------------ 1 file changed, 12 deletions(-) delete mode 100644 site/en/docs/extensions/reference/experimental_inputUI/index.md diff --git a/site/en/docs/extensions/reference/experimental_inputUI/index.md b/site/en/docs/extensions/reference/experimental_inputUI/index.md deleted file mode 100644 index bf9d43610..000000000 --- a/site/en/docs/extensions/reference/experimental_inputUI/index.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -layout: "layouts/doc-post.njk" -title: "InputUI API" -date: 2012-09-17 -updated: 2014-05-21 -description: Reference documentation for the chrome.experimental.input.ui API. ---- - -Use the `chrome.experimental.input.ui` module to implement input method user interface. This module -is for ChromeOS only. [chrome.experimental.\* APIs][1] page. - -[1]: /docs/extensions/experimental From 0ad5ffaae5fc907ebb4285686c19fd044675844c Mon Sep 17 00:00:00 2001 From: wizardofdocs <83661258+wizardofdocs@users.noreply.github.com> Date: Fri, 20 Oct 2023 14:12:12 -0700 Subject: [PATCH 944/982] Added new intent extras to interactivity guide (#7556) Added EXTRA_DISABLE_DOWNLOAD_BUTTON and EXTRA_DISABLE_BOOKMARKS_BUTTON with code samples Co-authored-by: Sebastian Benz <sebastian.benz@gmail.com> * Updated code formatting in interactivity guide --------- Co-authored-by: Sebastian Benz <sebastian.benz@gmail.com> --- .../android/custom-tabs/guide-interactivity/index.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/site/en/docs/android/custom-tabs/guide-interactivity/index.md b/site/en/docs/android/custom-tabs/guide-interactivity/index.md index 3d0aee7f7..6c840a48d 100644 --- a/site/en/docs/android/custom-tabs/guide-interactivity/index.md +++ b/site/en/docs/android/custom-tabs/guide-interactivity/index.md @@ -193,5 +193,16 @@ CustomTabsIntent intent = new CustomTabsIntent.Builder() .build(); ``` +## Enable bookmarks and download buttons + +Enable the bookmarks and download buttons from the three dot menu in `CustomTabsIntent.Builder` using the following code: + +```java +CustomTabsIntent customTabsIntent = new CustomTabsIntent.Builder() + .setBookmarksButtonEnabled(true) + .setDownloadButtonEnabled(true) + .build(); +``` + Next up: [Learn how to speed up loading web content in a Custom Tab](/docs/android/custom-tabs/guide-warmup-prefetch/). From beb722520a2e2353b4401c26037d726bcc36a65f Mon Sep 17 00:00:00 2001 From: Devin Samarin <me@dsamar.in> Date: Sat, 21 Oct 2023 00:00:04 -0700 Subject: [PATCH 945/982] blog: css-relative-color-syntax typo "complement" (#7528) --- site/en/blog/css-relative-color-syntax/index.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/site/en/blog/css-relative-color-syntax/index.md b/site/en/blog/css-relative-color-syntax/index.md index 6776a48a2..43216e16b 100644 --- a/site/en/blog/css-relative-color-syntax/index.md +++ b/site/en/blog/css-relative-color-syntax/index.md @@ -29,7 +29,7 @@ authors and designers to: - [Chroma boost](#chroma-boost-a-color) - [Adjust opacity](#adjust-opacity-a-color) - [Invert](#invert-a-color) -- [Compliment](#compliment-a-color) +- [Complement](#complement-a-color) - [Convert](#color-conversion) - [Contrast](#contrast-a-color) - [Color palettes](#color-palettes) @@ -473,7 +473,7 @@ channel's value from 1. tab: 'result' } %} -### Compliment a color +### Complement a color If your goal wasn't to invert a color but rather complement it, then hue rotation is likely what you're looking for. Pick a color space which offers the @@ -482,7 +482,7 @@ Finding a color's complement is done by rotating by half a turn, in this case you can add or subtract from the `h` channel by `180` to achieve the result. ```css -.complimentary-color { +.complementary-color { background: hsl(from blue calc(h + 180) s l); } ``` @@ -627,7 +627,7 @@ and watch new palettes get built by the browser. #### Triadic palettes -Similar to complimentary colors, [triadic color +Similar to complementary colors, [triadic color palettes](https://www.studiobinder.com/blog/what-is-a-triadic-color-scheme-definition/) are opposing but harmonious hue rotations given a base color. Where a complementary color is on the opposite side of a color, like a straight line From 343f2d9865fae8fb404debe10add68ddb26bcc59 Mon Sep 17 00:00:00 2001 From: Jun <jkokatsu@google.com> Date: Sat, 21 Oct 2023 00:01:06 -0700 Subject: [PATCH 946/982] Update index.md (#7538) --- site/en/blog/migrate-way-from-data-urls-in-svg-use/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/en/blog/migrate-way-from-data-urls-in-svg-use/index.md b/site/en/blog/migrate-way-from-data-urls-in-svg-use/index.md index a421da240..ef849886c 100644 --- a/site/en/blog/migrate-way-from-data-urls-in-svg-use/index.md +++ b/site/en/blog/migrate-way-from-data-urls-in-svg-use/index.md @@ -12,7 +12,7 @@ tags: {% Aside %} We expect to [remove support for `data:` URLs in SVG `<use>` element](https://chromestatus.com/feature/5128825141198848) -in Chrome 119, scheduled to ship in November 2023. +in Chrome 120, scheduled to ship in December 2023. {% endAside %} The SVG spec was [recently updated](https://github.com/w3c/svgwg/pull/901) to remove support for `data:` URLs in SVG `<use>` element. From bcec09f88d513117d4c9f495ebb6f168a0ae5ef3 Mon Sep 17 00:00:00 2001 From: David Barton <43063460+theDavidBarton@users.noreply.github.com> Date: Sat, 21 Oct 2023 09:01:45 +0200 Subject: [PATCH 947/982] chore(footer): fix broken case studies and podcasts links (#7577) --- site/_includes/partials/footer.njk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/site/_includes/partials/footer.njk b/site/_includes/partials/footer.njk index 06790ca58..8f8febd6e 100644 --- a/site/_includes/partials/footer.njk +++ b/site/_includes/partials/footer.njk @@ -45,12 +45,12 @@ </a> </li> <li> - <a class="footer__link" href="https://web.dev/tags/case-study/"> + <a class="footer__link" href="https://web.dev/case-studies"> {{ 'i18n.footer.case_studies' | i18n(locale) }} </a> </li> <li> - <a class="footer__link" href="https://web.dev/podcasts/"> + <a class="footer__link" href="https://web.dev/shows"> {{ 'i18n.footer.podcasts' | i18n(locale) }} </a> </li> From 0c767b1e4054a756cb2c2549dbdc40e1ba54b132 Mon Sep 17 00:00:00 2001 From: Barry Pollard <barrypollard@google.com> Date: Mon, 23 Oct 2023 15:38:52 +0100 Subject: [PATCH 948/982] Correct critical rendering path links (#7630) --- .../lighthouse/performance/render-blocking-resources/index.md | 4 ++-- site/en/docs/lighthouse/performance/unused-css-rules/index.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/site/en/docs/lighthouse/performance/render-blocking-resources/index.md b/site/en/docs/lighthouse/performance/render-blocking-resources/index.md index 506ee0390..db54d885b 100644 --- a/site/en/docs/lighthouse/performance/render-blocking-resources/index.md +++ b/site/en/docs/lighthouse/performance/render-blocking-resources/index.md @@ -66,7 +66,7 @@ When the page loads, it will have what it needs to handle the page's core functi If there's code in a render-blocking URL that's not critical, you can keep it in the URL, and then mark the URL with `async` or `defer` attributes -(see also [Adding Interactivity with JavaScript](https://web.dev/articles/critical-rendering-path-adding-interactivity-with-javascript)). +(see also [Adding Interactivity with JavaScript](https://web.dev/articles/critical-rendering-path/adding-interactivity-with-javascript)). Code that isn't being used at all should be removed (see [Remove unused code](https://web.dev/articles/remove-unused-code)). @@ -86,7 +86,7 @@ to split up those styles into different files, organized by media query. Then add a media attribute to each stylesheet link. When loading a page, the browser only blocks the first paint to retrieve the stylesheets that match the user's device -(see [Render-Blocking CSS](https://web.dev/articles/critical-rendering-path-render-blocking-css)). +(see [Render-Blocking CSS](https://web.dev/articles/critical/rendering-path-render-blocking-css)). Finally, you'll want to minify your CSS to remove any extra whitespace or characters (see [Minify CSS](https://web.dev/articles/minify-css)). diff --git a/site/en/docs/lighthouse/performance/unused-css-rules/index.md b/site/en/docs/lighthouse/performance/unused-css-rules/index.md index f073b4dd6..90d3ed54f 100644 --- a/site/en/docs/lighthouse/performance/unused-css-rules/index.md +++ b/site/en/docs/lighthouse/performance/unused-css-rules/index.md @@ -44,7 +44,7 @@ These extra network trips can significantly increase the time that users must wait before they see any content on their screens. Unused CSS also slows down a browser's construction of the -[render tree](https://web.dev/articles/critical-rendering-path-render-tree-construction). +[render tree](https://web.dev/articles/critical-rendering-path/render-tree-construction). The render tree is like the DOM tree, except that it also includes the styles for each node. To construct the render tree, a browser must walk the entire DOM tree, and check which CSS rules apply to each node. The more unused CSS there is, From d6953bb810ebac9466c8a24108fcb099bbe2baa5 Mon Sep 17 00:00:00 2001 From: Una Kravets <una.kravets@gmail.com> Date: Mon, 23 Oct 2023 10:54:15 -0400 Subject: [PATCH 949/982] Adds post: hr in select for Chrome 119 (#7609) * appease the linter * update merge date * update tag * Update site/en/blog/hr-in-select/index.md * Update site/en/blog/hr-in-select/index.md --------- Co-authored-by: Rachel Andrew <rachelandrew@google.com> --- site/en/blog/hr-in-select/index.md | 45 ++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 site/en/blog/hr-in-select/index.md diff --git a/site/en/blog/hr-in-select/index.md b/site/en/blog/hr-in-select/index.md new file mode 100644 index 000000000..3d2290018 --- /dev/null +++ b/site/en/blog/hr-in-select/index.md @@ -0,0 +1,45 @@ +--- +layout: "layouts/blog-post.njk" +title: "Select element: now with horizontal rules" +description: "Learn how expanded select element capabilities enable visual horizontal breaks for better grouping." +authors: + - unakravets +tags: + - html + - chrome-119 +date: 2023-10-23 +--- +The select element gets a small but mighty upgrade in Chrome 119, with a feature that also landed in [Safari 17](https://webkit.org/blog/14445/webkit-features-in-safari-17-0/). Now, you can add `<hr>` (horizontal rule) elements into the list of select options and they will appear as separators to help visually break up the options for a better user experience. + +{% Img src="image/HodOHWjMnbNw56hvNASHWSgZyAf2/55LrQnjhGNU5h22nq2PK.jpg", alt="Screenshot of before and after with hr in select. The after image has dividers between groups.", width="800", height="811" %} + +To achieve this, add `<hr>` elements into the options list as shown in the following HTML: + +```html +<label for="major-select">Please select a major:</label> <br/> + +<select name="majors" id="major-select"> + <option value="">Select a major</option> + <hr> + <option value="arth">Art History</option> + <option value="finearts">Fine Arts</option> + <option value="gdes">Graphic Design</option> + <option value="lit">Literature</option> + <option value="music">Music</option> + <hr> + <option value="aeroeng">Aerospace Engineering</option> + <option value="biochemeng">Biochemical Engineering</option> + <option value="civileng">Civil Engineering</option> + <option value="compeng">Computer Engineering</option> + <option value="eleng">Electrical Engineering</option> + <option value="mecheng">Mechanical Engineering</option> +</select> +``` +{% Codepen { + user: 'web-dot-dev', + id: 'GRzKzVK', + height: 350, + tab: 'result' +} %} + +Small changes can make a difference to your users. For more information on the future of form controls, including how to make them fully stylable, learn about the [popover API](/blog/introducing-popover-api/) and keep an eye out for the future [selectlist](https://open-ui.org/components/selectlist/) element. From 0a00171b82d1302fc3154161d7b246aec6f7d175 Mon Sep 17 00:00:00 2001 From: Adam Argyle <argyle@google.com> Date: Mon, 23 Oct 2023 08:24:13 -0700 Subject: [PATCH 950/982] `new post` CSS text-wrap: pretty (#7581) * init * Apply suggestions from code review Co-authored-by: Rachel Andrew <rachelandrew@google.com> * Update site/en/blog/css-text-wrap-pretty/index.md --------- Co-authored-by: Rachel Andrew <rachelandrew@google.com> --- site/en/blog/css-text-wrap-pretty/index.md | 108 +++++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 site/en/blog/css-text-wrap-pretty/index.md diff --git a/site/en/blog/css-text-wrap-pretty/index.md b/site/en/blog/css-text-wrap-pretty/index.md new file mode 100644 index 000000000..af029c422 --- /dev/null +++ b/site/en/blog/css-text-wrap-pretty/index.md @@ -0,0 +1,108 @@ +--- +layout: layouts/blog-post.njk +title: "CSS text-wrap: pretty" +description: > + Opt-in optimized text wrapping, for beauty over speed. +subhead: > + Opt-in optimized text wrapping, for beauty over speed. +date: 2023-10-23 +authors: + - argyle +tags: + - css +hero: image/vS06HQ1YTsbMKSFTIPl2iogUQP73/spOTYANOG4RylwyIQyRH.png +thumb: image/vS06HQ1YTsbMKSFTIPl2iogUQP73/mY6BvPXwqyfz7Jn70jwG.png +alt: > + A tall building's windows are shown wrapping in a harmonious curve. +--- + +From Chrome 117 you can use a new text wrapping feature—`text-wrap: pretty` +from [CSS Text Level 4](https://www.w3.org/TR/css-text-4/#text-wrap). + +```css +p { + text-wrap: pretty; +} +``` + +<figure> + {% Video + src="video/vS06HQ1YTsbMKSFTIPl2iogUQP73/vQqvAvkTkAmVjqhvLLvw.mp4", + width="800", + height="450", + autoplay="true", + loop="true", + muted="true", + controls="true" + %} + + <figcaption> + <a href="https://codepen.io/web-dot-dev/pen/yLGmzLJ"> + https://codepen.io/web-dot-dev/pen/yLGmzLJ + </a> + </figcaption> +</figure> + +Typographic [widows and +orphans](https://fonts.google.com/knowledge/glossary/widows_orphans) are single +words that stand alone at the end of a paragraph or text block. Widows are words +alone at the top of a text block and orphans are alone at the end of a text +block. They can interrupt the way our eyes skim the text, making content harder +to read. Some designers avoid them at all costs and go through great lengths to +prevent them. + +<figure> + {% Img + src="image/vS06HQ1YTsbMKSFTIPl2iogUQP73/wfqjbgG80KgZryht7iiK.svg", + alt="A paragraph is shown with a widow at the beginning and an orphan at the end, compared to the same paragraph without the orphans or widows.", + width="800", + height="450" + %} + + <figcaption> + Image sourced from <a href="https://fonts.google.com/knowledge/glossary/widows_orphans">Google Fonts—Widows & Orphans</a> + </figcaption> +</figure> + +From Chrome 117, orphans can be avoided with one line of CSS: `text-wrap: pretty`. + +{% Aside %} `text-wrap: pretty` is different from CSS's +[`orphans`](https://developer.mozilla.org/docs/Web/CSS/orphans) property +which is relevant when using CSS [multi-column +layout](https://developer.mozilla.org/docs/Web/CSS/CSS_multicol_layout). +Also, `pretty` only handles orphans, not widows. {% endAside %} + +The feature does a little more than just ensure paragraphs don't end with a +single word, it also adjusts hyphenation if consecutive hyphenated lines appear +at the end of a paragraph or adjusts previous lines to make room. It will also +appropriately adjust for text justification. `text-wrap: pretty` is for +generally better line wrapping and text breaking, currently focused on orphans. +In the future, `text-wrap: pretty` may offer more improvements. + +<figure> + {% Img + src="image/vS06HQ1YTsbMKSFTIPl2iogUQP73/Snt1oo5WBdJeXVE8Wcrc.png", + alt="A comparison of a paragraph with orphans and one with no orphans, each with a badge of bad or good.", + width="540", + height="250" + %} + + <figcaption> + Image sourced from <a href="https://uxmovement.com/content/why-you-should-remove-orphans-from-your-body-text/">Why you should remove orphans from your body text.</a> + </figcaption> +</figure> + +There's also [`text-wrap: balance`](/blog/css-text-wrap-balance/), which doesn't +prevent orphans, but does ensure the text wraps in a way that creates a +harmonious text block. I personally use `balance` for headlines and `pretty` for +paragraphs. + +If you're interested in the details of the algorithm used to determine the +optimal number of lines, or performance considerations, [here's a link to the +design document created by the +engineer](https://docs.google.com/document/d/1jJFD8nAUuiUX6ArFZQqQo8yTsvg8IuAq7oFrNQxPeqI/edit#heading=h.cqq9czoal00g) +behind the feature, [Koji Ishii](/authors/kojiishi/). + +If you have other line breaking improvements or suggestions, we'd love to hear +them! File an issue in the [Chromium bug tracker](https://bugs.chromium.org/p/chromium/issues/entry) with the details, examples of +good and bad line breaks, and we'll get back to you. From 7f9bd2dd1c77377fb6608e1458ab2f73f9e942aa Mon Sep 17 00:00:00 2001 From: "Kevin K. Lee" <kevinkiklee@google.com> Date: Mon, 23 Oct 2023 11:59:15 -0400 Subject: [PATCH 951/982] Update the k-anonymity section (#7444) * Add ad size information to k-anonymity section * Update link --- .../protected-audience-api/feature-status/index.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/site/en/docs/privacy-sandbox/protected-audience-api/feature-status/index.md b/site/en/docs/privacy-sandbox/protected-audience-api/feature-status/index.md index 040cec630..ad3be31d0 100644 --- a/site/en/docs/privacy-sandbox/protected-audience-api/feature-status/index.md +++ b/site/en/docs/privacy-sandbox/protected-audience-api/feature-status/index.md @@ -215,12 +215,11 @@ aggregatable reports, and we will publish a proposal once it is ready. ## K-anonymity -We will soon publish an explainer with more details on how [k-anonymity](https://github.com/WICG/turtledove/blob/main/FLEDGE_k_anonymity_server.md) will be enforced using the Protected Audience API framework. +For a creative to be considered k-anonymous, the tuple of interest group owner, bidding script URL, creative URL, and creative size must meet the threshold of a crowd of 50 users per creative (`k=50`) within the past 30 days before the ad can be served. The creative is available to be served as soon as it hits the 50 users threshold and does not need to wait for 30 days. -For rendering a creative, we will require _a crowd of 50 users per creative within the past 7 days_ to pass the k-anonymity threshold before the ad can be served. The creative is available to be served as soon as it hits the 50 ads threshold and does not need to wait for 7 days. +The k-anonymity enforcement will be ramped up gradually. Later in 2023, we will begin to check the render URL for k-anonymity. Later in Q1 2025, we will begin to check the ad size in addition to the URL for k-anonymity. -K-anonymity requirements will be available for testing and will be enforced -later in 2023. We encourage feedback from ad tech on this parameter. +You can learn more about the parameters from the [k-anonymity explainer](https://github.com/WICG/turtledove/blob/main/FLEDGE_k_anonymity_differential_privacy.md). ## Bidding and Auction Services From 35817d63d94bd2e6ff9ad96b4c71fef96c577c17 Mon Sep 17 00:00:00 2001 From: Oliver Dunk <oliverdunk@google.com> Date: Mon, 23 Oct 2023 17:56:20 +0100 Subject: [PATCH 952/982] Add What's New on testing documentation (#7596) * Add What's New on testing documentation * Update site/en/docs/extensions/whatsnew/index.md --------- Co-authored-by: Joe Medley <jmedley@google.com> --- site/en/docs/extensions/whatsnew/index.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/site/en/docs/extensions/whatsnew/index.md b/site/en/docs/extensions/whatsnew/index.md index decc990fc..9538bc67d 100644 --- a/site/en/docs/extensions/whatsnew/index.md +++ b/site/en/docs/extensions/whatsnew/index.md @@ -15,6 +15,15 @@ tags: Check this page often to learn about changes to Chrome extensions, extensions documentation, or related policy or other changes. You'll find other notices posted on the [Extensions Google Group](https://groups.google.com/a/chromium.org/g/chromium-extensions). The [Extensions News](/tags/extensions-news/) tag lists articles about some of the topics listed here. (It even has [an RSS feed](/feeds/extensions-news.xml).) The [Chrome schedule](https://chromiumdash.appspot.com/schedule) lists stable and beta release dates. +### New guidance on testing extensions {: #testing-guidance-oct-23 } + +<p class="color-secondary-text type--caption">Posted on <time>October 23, 2023</time></p> + +We've just published new guidance on how to write automated tests for extensions, including [how +to write unit tests](/docs/extensions/mv3/unit-testing/) and both +[general guidance](/docs/extensions/mv3/end-to-end-testing/) and a +[tutorial](/docs/extensions/mv3/tut_puppeteer-testing/) on end-to-end testing. + ### Blog post: What's happening in Chrome Extensions - October 2023 {: #whats-happening-10-23 } <p class="color-secondary-text type--caption">Posted on <time>October 17, 2023</time></p> From 412205f5ff99bd0afa9310721a9172fa58dfed0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Beaufort?= <beaufort.francois@gmail.com> Date: Tue, 24 Oct 2023 09:30:58 +0200 Subject: [PATCH 953/982] What's New in WebGPU (Chrome 119) (#7527) --- site/en/_partials/webgpu/whats-new.md | 7 ++ site/en/blog/new-in-webgpu-119/index.md | 118 ++++++++++++++++++++++++ 2 files changed, 125 insertions(+) create mode 100644 site/en/blog/new-in-webgpu-119/index.md diff --git a/site/en/_partials/webgpu/whats-new.md b/site/en/_partials/webgpu/whats-new.md index 4f2f38a8a..6ad3f076c 100644 --- a/site/en/_partials/webgpu/whats-new.md +++ b/site/en/_partials/webgpu/whats-new.md @@ -2,6 +2,13 @@ A list of everything that has been covered in the [What's New in WebGPU](/tags/new-in-webgpu/) series. +### Chrome 119 {: #chrome119 } + +* [Filterable 32-bit float textures](/blog/new-in-webgpu-119/#filterable-32-bit-float-textures) +* [unorm10-10-10-2 vertex format](/blog/new-in-webgpu-119/#unorm10-10-10-2-vertex-format) +* [rgb10a2uint texture format](/blog/new-in-webgpu-119/#rgb10a2uint-texture-format) +* [Dawn updates](/blog/new-in-webgpu-119/#dawn-updates) + ### Chrome 118 {: #chrome118 } * [HTMLImageElement and ImageData support in copyExternalImageToTexture()](/blog/new-in-webgpu-118/#htmlimageelement-and-imagedata-support-in-copyexternalimagetotexture) diff --git a/site/en/blog/new-in-webgpu-119/index.md b/site/en/blog/new-in-webgpu-119/index.md new file mode 100644 index 000000000..d6694e90c --- /dev/null +++ b/site/en/blog/new-in-webgpu-119/index.md @@ -0,0 +1,118 @@ +--- +layout: "layouts/blog-post.njk" +title: "What's New in WebGPU (Chrome 119)" +description: "Filterable 32-bit float textures, unorm10-10-10-2 vertex format, rgb10a2uint texture format, and more." +hero: "image/vvhSqZboQoZZN9wBvoXq72wzGAf1/wl2nb6hZ75H1Ym5be9B6.png" +alt: "What's new in WebGPU logo" +date: 2023-10-24 +#updated: YYYY-MM-DD +authors: + - beaufortfrancois +tags: + - new-in-webgpu + - webgpu + - chrome-119 +--- + +## Filterable 32-bit float textures + +32-bit floating-point textures are used to store high-precision data, such as HDR images and depth maps. They are especially important for GPUs used in high-end gaming and professional applications. + +Filterable 32-bit float textures support describes the ability of a GPU to filter 32-bit floating-point textures. This means that the GPU can smooth out the edges of floating-point textures, making them appear less jagged. It is similar to the "OES_texture_float_linear" extension in WebGL. + +Not all GPUs support filterable 32-bit float textures. When the `"float32-filterable"` feature is available in a `GPUAdapter`, you can now request a `GPUDevice` with this feature and filter textures with "r32float", "rg32float", and "rgba32float" formats. See the following example and [issue dawn:1664](https://bugs.chromium.org/p/dawn/issues/detail?id=1664). + +```js +const adapter = await navigator.gpu.requestAdapter(); +if (!adapter.features.has("float32-filterable")) { + throw new Error("Filterable 32-bit float textures support is not available"); +} +// Explicitly request filterable 32-bit float textures support. +const device = await adapter.requestDevice({ + requiredFeatures: ["float32-filterable"], +}); + +// Create a sampler with linear filtering. +const sampler = device.createSampler({ + magFilter: "linear", +}); + +// Create a texture with rgba32float format. +const texture = device.createTexture({ + size: [100, 100], + format: "rgba32float", + usage: GPUTextureUsage.COPY_DST | GPUTextureUsage.TEXTURE_BINDING, +}); + +// Write data to texture, create a bindgroup with sampler and texture and +// send the appropriate commands to the GPU.... +``` + +## unorm10-10-10-2 vertex format + +A new vertex format called "unorm10-10-10-2" aka "rgb10a2" has been added to the [WebGPU specification](https://gpuweb.github.io/gpuweb/#dom-gpuvertexformat-unorm10-10-10-2). It consists of one packed 32-bit value with four normalized unsigned integer values, arranged as 10 bits, 10 bits, 10 bits, and 2 bits. See the following example and [issue dawn:2044](https://bugs.chromium.org/p/dawn/issues/detail?id=2044). + +```js +// Define the layout of vertex attribute data with unorm10-10-10-2 format. +const buffers = [ + { + arrayStride: 0, + attributes: [ + { format: "unorm10-10-10-2", offset: 0, shaderLocation: 0 }, + ], + }, +]; + +// Describe the vertex shader entry point and its input buffer layouts. +const vertex = { + module: myVertexShaderModule, + entryPoint: "main", + buffers, +}; + +// Pass vertex to device.createRenderPipeline() and +// use vec4<f32> type in WGSL shader code to manipulate data. +``` + +## rgb10a2uint texture format + +A new texture format called "rgb10a2uint" has been added to the [WebGPU specification](https://gpuweb.github.io/gpuweb/#dom-gputextureformat-rgb10a2uint). It consists of a 32-bit packed pixel format with four unsigned integer components: 10-bit red, 10-bit green, 10-bit blue, and 2-bit alpha. See the following example and [issue dawn:1936](https://bugs.chromium.org/p/dawn/issues/detail?id=1936). + +```js +// Create a texture with rgb10a2uint format. +const texture = device.createTexture({ + size: [100, 100], + format: "rgb10a2uint", + usage: GPUTextureUsage.COPY_DST | GPUTextureUsage.TEXTURE_BINDING, +}); + +// Write data to texture, create a bindgroup with texture and +// send the appropriate commands to the GPU.... +``` + +## Dawn updates + +Timestamp queries allow WebGPU applications to measure precisely (down to the nanosecond) how much time their GPU commands take to execute. The API shape to capture timestamps queries at the beginning and end of passes have been updated to match the WebGPU specification. See the following example and [issue dawn:1800](https://bugs.chromium.org/p/dawn/issues/detail?id=1800). + +```cpp +// Create a timestamp query set that will store the timestamp values. +wgpu::QuerySetDescriptor querySetDescriptor = { + .count = 2, + .type = wgpu::QueryType::Timestamp}; +wgpu::QuerySet querySet = device.CreateQuerySet(&querySetDescriptor); + +wgpu::RenderPassTimestampWrites timestampWrites = { + .querySet = querySet, + .beginningOfPassWriteIndex = 0, + .endOfPassWriteIndex = 1}; +wgpu::ComputePassDescriptor pass{.timestampWrites = ×tampWrites}; + +// Write the queue timestamp into beginningOfPassWriteIndex and +// endOfPassWriteIndex of myQuerySet respectively before and after the pass +// commands execute. +myEncoder.BeginComputePass(&pass); +``` + +This covers only some of the key highlights. Check out the exhaustive [list of commits](https://dawn.googlesource.com/dawn/+log/chromium/5993..chromium/6045). + +{% Partial 'webgpu/whats-new.md' %} From 1951eb489f0bd148954529835e7c4e9dfb291681 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Beaufort?= <beaufort.francois@gmail.com> Date: Tue, 24 Oct 2023 09:57:28 +0200 Subject: [PATCH 954/982] s/no-focus-change/focus-capturing-application/g (#7326) * s/no-focus-change/focus-capturing-application/g * Update index.md --- site/en/docs/web-platform/conditional-focus/index.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/site/en/docs/web-platform/conditional-focus/index.md b/site/en/docs/web-platform/conditional-focus/index.md index eb726fa34..dd19db57c 100644 --- a/site/en/docs/web-platform/conditional-focus/index.md +++ b/site/en/docs/web-platform/conditional-focus/index.md @@ -7,6 +7,7 @@ authors: - beaufortfrancois - eladalon date: 2022-11-28 +updated: 2023-10-24 hero: image/vvhSqZboQoZZN9wBvoXq72wzGAf1/O12v673aOekK889d5Upi.jpg alt: Person holding eyeglasses with distant items in focus through the glasses. tags: @@ -49,7 +50,7 @@ if (displaySurface == "browser") { } else if (displaySurface == "window") { // Do not move focus to the captured window. // Keep the capturing page focused. - controller.setFocusBehavior("no-focus-change"); + controller.setFocusBehavior("focus-capturing-application"); } ``` @@ -60,7 +61,7 @@ When deciding whether to focus, it is possible to take the [Capture Handle] into // Focus anything else. const origin = track.getCaptureHandle().origin; if (displaySurface == "browser" && origin == "https://example.com") { - controller.setFocusBehavior("no-focus-change"); + controller.setFocusBehavior("focus-capturing-application"); } else if (displaySurface != "monitor") { controller.setFocusBehavior("focus-captured-surface"); } From 5fc9d010f0699ffdee86a79536d28d750d459c2b Mon Sep 17 00:00:00 2001 From: Oliver Dunk <oliverdunk@google.com> Date: Tue, 24 Oct 2023 14:35:44 +0100 Subject: [PATCH 955/982] Disable smooth scrolling (#7637) --- site/_scss/_global.scss | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/site/_scss/_global.scss b/site/_scss/_global.scss index a09191291..c6a45d000 100644 --- a/site/_scss/_global.scss +++ b/site/_scss/_global.scss @@ -33,7 +33,8 @@ } html { - scroll-behavior: smooth; + // Disabled due to https://github.com/GoogleChrome/developer.chrome.com/issues/7412 + // scroll-behavior: smooth; } body { From 16f912e045f4ef0ee491a6298579b1664762b44b Mon Sep 17 00:00:00 2001 From: "Kevin K. Lee" <kevinkiklee@google.com> Date: Tue, 24 Oct 2023 09:54:16 -0400 Subject: [PATCH 956/982] Update k-anon lookback window (#7639) --- .../protected-audience-api/feature-status/index.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/site/en/docs/privacy-sandbox/protected-audience-api/feature-status/index.md b/site/en/docs/privacy-sandbox/protected-audience-api/feature-status/index.md index ad3be31d0..4440fefa7 100644 --- a/site/en/docs/privacy-sandbox/protected-audience-api/feature-status/index.md +++ b/site/en/docs/privacy-sandbox/protected-audience-api/feature-status/index.md @@ -66,9 +66,9 @@ find a list of the scoped Protected Audience API features and when they'll be su <tr> <td><a href="#k-anonymity">K-anonymity</a> </td> - <td>Later in 2023 Q3 + <td>Later in 2023 Q4 </td> - <td>For rendering creatives, the k-anonymity threshold of “a crowd of 50 users per creative over 7 days” must be met. + <td>For rendering creatives, the k-anonymity threshold of “a crowd of 50 users per creative over 30 days” must be met. </td> </tr> <tr> From 66c3a224dcf70446f3468f81779ead264863bc75 Mon Sep 17 00:00:00 2001 From: wizardofdocs <83661258+wizardofdocs@users.noreply.github.com> Date: Tue, 24 Oct 2023 07:26:29 -0700 Subject: [PATCH 957/982] Updated code examples in interactivity guide (#7631) --- .../android/custom-tabs/guide-interactivity/index.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/site/en/docs/android/custom-tabs/guide-interactivity/index.md b/site/en/docs/android/custom-tabs/guide-interactivity/index.md index 6c840a48d..be8318b17 100644 --- a/site/en/docs/android/custom-tabs/guide-interactivity/index.md +++ b/site/en/docs/android/custom-tabs/guide-interactivity/index.md @@ -193,14 +193,15 @@ CustomTabsIntent intent = new CustomTabsIntent.Builder() .build(); ``` -## Enable bookmarks and download buttons +## Bookmarks and download buttons -Enable the bookmarks and download buttons from the three dot menu in `CustomTabsIntent.Builder` using the following code: +The bookmarks and download buttons in the three dot menu are enabled by default. To disable them, use the following +code in `CustomTabsIntent.Builder`: ```java CustomTabsIntent customTabsIntent = new CustomTabsIntent.Builder() - .setBookmarksButtonEnabled(true) - .setDownloadButtonEnabled(true) + .setBookmarksButtonEnabled(false) + .setDownloadButtonEnabled(false) .build(); ``` From 9150a1f6628d2f6840c81d0ee76695b57841b7f5 Mon Sep 17 00:00:00 2001 From: Joe Medley <jmedley@google.com> Date: Tue, 24 Oct 2023 09:32:29 -0700 Subject: [PATCH 958/982] Set up redirect from examples/ to samples/ (#7632) `/examples` is one of our top ten URLs according analytics, despite the fact that we don't have such a page. This PR redirects to one we do have. --- redirects.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/redirects.yaml b/redirects.yaml index 06c2e4a21..34d46b79c 100644 --- a/redirects.yaml +++ b/redirects.yaml @@ -81,6 +81,9 @@ redirects: - from: /docs/extensions/mv3/xhr to: /docs/extensions/mv3/network-requests +- from: /docs/extensions/examples + to: /docs/extensions/samples/ + - from: /blog/fedcm-origin-trial to: /docs/privacy-sandbox/fedcm From 2b361148948358dfa2c185bedd4cb8c3a95d6c05 Mon Sep 17 00:00:00 2001 From: wizardofdocs <83661258+wizardofdocs@users.noreply.github.com> Date: Tue, 24 Oct 2023 09:39:25 -0700 Subject: [PATCH 959/982] Added SEND_TO_EXTERNAL_HANDLER to prefetch guide (#7600) * Added SEND_TO_EXTERNAL_HANDLER to prefetch guide TODO: redirect old native apps guide to this new section * Tweaked new code sample in prefetch guide * Redirected Custom Tabs native apps guide to warmup/prefetch guide * Delete site/en/docs/android/custom-tabs/howto-custom-tab-native-apps directory Page has been redirected * Update site/en/docs/android/custom-tabs/guide-warmup-prefetch/index.md Elaborated on external handler use case Co-authored-by: Sebastian Benz <sebastian.benz@gmail.com> * Updated grammar in prefetch guide to follow dev docs style guide * Fixed code formatting in prefetch guide * Update site/en/docs/android/custom-tabs/guide-warmup-prefetch/index.md Fixed formatting Co-authored-by: Joe Medley <jmedley@google.com> * Attempt at redirect YAML from howto-custom-tab-native-apps to new External Handler documentation * Attempt fix on redirect. --------- Co-authored-by: Sebastian Benz <sebastian.benz@gmail.com> Co-authored-by: Joe Medley <jmedley@google.com> --- redirects.yaml | 5 + .../guide-warmup-prefetch/index.md | 20 +++- .../howto-custom-tab-native-apps/index.md | 106 +----------------- 3 files changed, 22 insertions(+), 109 deletions(-) diff --git a/redirects.yaml b/redirects.yaml index 34d46b79c..52f28377a 100644 --- a/redirects.yaml +++ b/redirects.yaml @@ -788,6 +788,11 @@ redirects: - from: /docs/privacy-sandbox/permissions-policy/ to: /articles/permissions-policy/ +# PR 7600 replacing Custom Tabs native apps how-to with external handler section in warmup/prefetch guide + +- from: /docs/android/custom-tabs/howto-custom-tab-native-apps/ + to: /docs/android/custom-tabs/guide-warmup-prefetch/ + # DO NOT REMOVE. This seems pointless but we rewrite "." to "_" inside our server's code, so if the # URL is fine for all but incorrect syntax, we'll fix it up. - from: /... diff --git a/site/en/docs/android/custom-tabs/guide-warmup-prefetch/index.md b/site/en/docs/android/custom-tabs/guide-warmup-prefetch/index.md index fbf2b108b..3319c2bc0 100644 --- a/site/en/docs/android/custom-tabs/guide-warmup-prefetch/index.md +++ b/site/en/docs/android/custom-tabs/guide-warmup-prefetch/index.md @@ -8,7 +8,7 @@ authors: - sebastianbenz --- -The third part of this guide focuses on speeding up the browser startup via [`warmup()`](https://developer.android.com/reference/androidx/browser/customtabs/CustomTabsClient#warmup(long)) and prefetching web pages via [`mayLaunchUrl`](https://developer.android.com/reference/androidx/browser/customtabs/CustomTabsSession#mayLaunchUrl(android.net.Uri,android.os.Bundle,java.util.List%3Candroid.os.Bundle%3E))(). Warming up the browser process can save up to 700ms when opening a link. Pre-rendering content via `mayLaunchUrl` will make external content open instantly. Together both APIs can greatly improve the user experience of a Custom Tabs integration and are highly recommended. +The third part of this guide focuses on speeding up the browser startup via [`warmup()`](https://developer.android.com/reference/androidx/browser/customtabs/CustomTabsClient#warmup(long)) and prefetching web pages via [`mayLaunchUrl`](https://developer.android.com/reference/androidx/browser/customtabs/CustomTabsSession#mayLaunchUrl(android.net.Uri,android.os.Bundle,java.util.List%3Candroid.os.Bundle%3E))(). Warming up the browser process can save up to 700ms when opening a link. Pre-rendering content via `mayLaunchUrl` makes external content open instantly. Together both APIs can greatly improve the user experience of a Custom Tabs integration and are highly recommended. The required steps are: @@ -18,11 +18,7 @@ The required steps are: a. Warmup the browser process via [`CustomTabsClient.warmup()`](https://developer.android.com/reference/androidx/browser/customtabs/CustomTabsClient#warmup(long)). b. Create a new [`CustomTabsSession`](https://developer.android.com/reference/androidx/browser/customtabs/CustomTabsSession) via [`CustomTabsClient.newSession()`](https://developer.android.com/reference/androidx/browser/customtabs/CustomTabsClient#newSession(androidx.browser.customtabs.CustomTabsCallback,int)). 3. Optionally, prefetch web pages the user is likely to visit via [`CustomTabsSession.mayLaunchUrl()`](https://developer.android.com/reference/androidx/browser/customtabs/CustomTabsSession#mayLaunchUrl(android.net.Uri,android.os.Bundle,java.util.List%3Candroid.os.Bundle%3E)). -4. When launching a new Custom Tab, pass the [`CustomTabsSession`](https://developer.android.com/reference/androidx/browser/customtabs/CustomTabsSession) to the [CustomTabsIntent.Builder](https://developer.android.com/reference/androidx/browser/customtabs/CustomTabsIntent.Builder) via the constructor `new CustomTabsIntent.Builder(session)`. - -{% Aside 'important' %} -Passing a session to a `CustomTabIntent` will force open the link in a Custom Tab, even if the corresponding native app is installed. If you want to keep the default behavior of opening web links in native apps, you need to additionally follow our [guide on how to check if a link can be handled by an installed native app](/docs/android/custom-tabs/howto-custom-tab-native-apps/). -{% endAside %} +4. When launching a new Custom Tab, pass the [`CustomTabsSession`](https://developer.android.com/reference/androidx/browser/customtabs/CustomTabsSession) to the [CustomTabsIntent.Builder](https://developer.android.com/reference/androidx/browser/customtabs/CustomTabsIntent.Builder) via the constructor `new CustomTabsIntent.Builder(session)`. If your app targets **Android API level 30**, [`CustomTabsClient.getPackageName(...)`](https://developer.android.com/reference/androidx/browser/customtabs/CustomTabsClient#getPackageName(android.content.Context,java.util.List%3Cjava.lang.String%3E)) requires you to add a queries section to your Android Manifest, declaring an intent-filter that matches browsers with Custom Tabs support. @@ -109,4 +105,16 @@ A Custom Tabs service connection might fail while your activity is running. If y {% endAside %} +## Open webpages in native apps + +On Android, URLs can be handled by native applications. For example, if the user has the Facebook app installed and clicks on a link to a Facebook post, they usually prefer the link opening in the Facebook app instead of in the browser. + +By default, Custom Tabs opens links in the respective native application if installed. However, once a `CustomTabsServiceConnection` has been established, this behavior stops working and all URLs open in Custom Tabs instead. For an improved user experience, we recommend re-enabling this behavior using the following code: + +```java +CustomTabsIntent customTabsIntent = new CustomTabsIntent.Builder() + .setSendToExternalDefaultHandlerEnabled(true) + .build(); +``` + Next up: [Learn how to resize the Custom Tabs experience](/docs/android/custom-tabs/guide-partial-custom-tabs/). diff --git a/site/en/docs/android/custom-tabs/howto-custom-tab-native-apps/index.md b/site/en/docs/android/custom-tabs/howto-custom-tab-native-apps/index.md index c8ede76a2..f2407ac12 100644 --- a/site/en/docs/android/custom-tabs/howto-custom-tab-native-apps/index.md +++ b/site/en/docs/android/custom-tabs/howto-custom-tab-native-apps/index.md @@ -1,110 +1,10 @@ --- layout: "layouts/doc-post.njk" title: Let native applications handle the content -seoTitle: How to let native applications handle content +seoTitle: How to let native applications handle content date: 2020-02-04 updated: 2023-05-03 description: Learn how to open links in either a native app or a Custom Tab. +anchorRedirects: +native-apps : /docs/android/custom-tabs/guide-warmup-prefetch/#open-webpages-in-native-apps --- - -On Android, URLs can be handled by native applications. If the user has the Twitter app installed and -clicks on a link to a tweet, they usually prefer that the Twitter application will be opened instead of the browser. -When using Custom Tabs, you can support this use case by checking if a native app can handle a link, before opening a Custom Tab. - -## On Android 11 and above - -Android 11 introduces a new intent flag, [`Intent.FLAG_ACTIVITY_REQUIRE_NON_BROWSER`][1], which is the -recommended way to try opening a native app, as it doesn't require the app to declare any package -manager queries. - -The approach is to try to launch an intent and use `Intent.FLAG_ACTIVITY_REQUIRE_NON_BROWSER` to ask -Android to avoid browsers when launching. If a native app that is capable of handling this Intent is not found, an -`ActivityNotFoundException` will be thrown. - -```java -static boolean launchNativeApi30(Context context, Uri uri) { - Intent nativeAppIntent = new Intent(Intent.ACTION_VIEW, uri) - .addCategory(Intent.CATEGORY_BROWSABLE) - .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | - Intent.FLAG_ACTIVITY_REQUIRE_NON_BROWSER); - try { - context.startActivity(nativeAppIntent); - return true; - } catch (ActivityNotFoundException ex) { - return false; - } -} -``` - -## Before Android 11 - -Even though the application may target Android 11, or API level 30, previous Android versions will -not understand the `FLAG_ACTIVITY_REQUIRE_NON_BROWSER` flag. To support those devices: - -1. Use the [PackageManager](https://developer.android.com/reference/android/content/pm/PackageManager?cmdf=android+packagemanager) to query for applications supporting a generic "http" intent. Those applications are likely browsers. -2. Then, query for applications that handle intents for the specific URL you want to launch. This will -return both browsers and native applications set up to handle that URL. -3. Now, remove all browsers found on the first list from the second list. The resulting list only includes native apps. -4. If the list is empty, there are no native handlers and return false. Otherwise, launch -the intent for the native handler. - -```java -private static boolean launchNativeBeforeApi30(Context context, Uri uri) { - PackageManager pm = context.getPackageManager(); - - // Get all Apps that resolve a generic url - Intent browserActivityIntent = new Intent() - .setAction(Intent.ACTION_VIEW) - .addCategory(Intent.CATEGORY_BROWSABLE) - .setData(Uri.fromParts("http", "", null)); - Set<String> genericResolvedList = extractPackageNames( - pm.queryIntentActivities(browserActivityIntent, 0)); - - // Get all apps that resolve the specific Url - Intent specializedActivityIntent = new Intent(Intent.ACTION_VIEW, uri) - .addCategory(Intent.CATEGORY_BROWSABLE); - Set<String> resolvedSpecializedList = extractPackageNames( - pm.queryIntentActivities(specializedActivityIntent, 0)); - - // Keep only the Urls that resolve the specific, but not the generic - // urls. - resolvedSpecializedList.removeAll(genericResolvedList); - - // If the list is empty, no native app handlers were found. - if (resolvedSpecializedList.isEmpty()) { - return false; - } - - // We found native handlers. Launch the Intent. - specializedActivityIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - context.startActivity(specializedActivityIntent); - return true; -} -``` - - -### Putting it all together - -We need to ensure we are using the right method for each occasion: - -```java -static void launchUri(Context context, Uri uri) { - boolean launched = Build.VERSION.SDK_INT >= 30 ? - launchNativeApi30(context, uri) : - launchNativeBeforeApi30(context, uri); - - if (!launched) { - new CustomTabsIntent.Builder() - .build() - .launchUrl(context, uri); - } -} -``` - -`Build.VERSION.SDK_INT` provides the information we need. If it's equal or larger than 30, Android -knows the `FLAG_ACTIVITY_REQUIRE_NON_BROWSER` and we can try launching a native app with the new -approach. Otherwise, we try launching with the old approach. - -If launching a native app fails, we then launch a Custom Tab. - -[1]: https://developer.android.com/reference/android/content/Intent#FLAG_ACTIVITY_REQUIRE_NON_BROWSER From dedc27e6da999d465b9fb39cd958b5d775bcb4bc Mon Sep 17 00:00:00 2001 From: wizardofdocs <83661258+wizardofdocs@users.noreply.github.com> Date: Tue, 24 Oct 2023 10:31:56 -0700 Subject: [PATCH 960/982] Updated declare_permissions (#7249) * Updated declare_permissions Copyedits and definition reformatting. Left a few questions in comments. * Update site/en/docs/extensions/mv3/declare_permissions/index.md Updated phrasing Co-authored-by: Joe Medley <jmedley@google.com> * Updated phrasing in Declare Permissions intro * Update site/en/docs/extensions/mv3/declare_permissions/index.md Updated phrasing Co-authored-by: Joe Medley <jmedley@google.com> * Update site/en/docs/extensions/mv3/declare_permissions/index.md Updated phrasing Co-authored-by: Joe Medley <jmedley@google.com> * Update site/en/docs/extensions/mv3/declare_permissions/index.md Updated phrasing Co-authored-by: Joe Medley <jmedley@google.com> * Update site/en/docs/extensions/mv3/declare_permissions/index.md Fixed code formatting Co-authored-by: Joe Medley <jmedley@google.com> * Removed reference to deprecated API from declare_permissions * Updated phrasing Co-authored-by: Joe Medley <jmedley@google.com> * Added permissions to available permissions list Co-authored-by: Joe Medley <jmedley@google.com> * Updated geolocation API link Co-authored-by: Joe Medley <jmedley@google.com> * Updated phrasing in declare_permissions Co-authored-by: Joe Medley <jmedley@google.com> * Removed deprecated permissions Co-authored-by: Joe Medley <jmedley@google.com> * Updated API links Co-authored-by: Joe Medley <jmedley@google.com> * Updated code formatting Co-authored-by: Joe Medley <jmedley@google.com> * Fixed code formatting in permissions list * Update site/en/docs/extensions/mv3/declare_permissions/index.md Updated phrasing Co-authored-by: Joe Medley <jmedley@google.com> * Update site/en/docs/extensions/mv3/declare_permissions/index.md Updated phrasing Co-authored-by: Joe Medley <jmedley@google.com> * Update site/en/docs/extensions/mv3/declare_permissions/index.md Improved description of declarativeNetRequest API Co-authored-by: Joe Medley <jmedley@google.com> * Update site/en/docs/extensions/mv3/declare_permissions/index.md Removed commented-out entries on the permissions list Co-authored-by: Joe Medley <jmedley@google.com> * Update site/en/docs/extensions/mv3/declare_permissions/index.md Removed entry for experimental permissions Co-authored-by: Joe Medley <jmedley@google.com> * Updated update date for declare_permissions * Update site/en/docs/extensions/mv3/declare_permissions/index.md Added entry for audio permissions Co-authored-by: Joe Medley <jmedley@google.com> * Updated Declare Permissions Re-added `unlimitedStorage` to permissions list as specified in https://source.chromium.org/chromium/chromium/src/+/main:extensions/common/api/_permission_features.json;l=654 * Update site/en/docs/extensions/mv3/declare_permissions/index.md Co-authored-by: Joe Medley <jmedley@google.com> * Fixed definition formatting in Declare Permissions * Update site/en/docs/extensions/mv3/declare_permissions/index.md * Update site/en/docs/extensions/mv3/declare_permissions/index.md Added runtime to the permissions list Co-authored-by: Joe Medley <jmedley@google.com> * Update site/en/docs/extensions/mv3/declare_permissions/index.md * Final fixes. --------- Co-authored-by: Joe Medley <jmedley@google.com> --- .../mv3/declare_permissions/index.md | 613 +++++++----------- 1 file changed, 250 insertions(+), 363 deletions(-) diff --git a/site/en/docs/extensions/mv3/declare_permissions/index.md b/site/en/docs/extensions/mv3/declare_permissions/index.md index bbd37deff..67503df9b 100644 --- a/site/en/docs/extensions/mv3/declare_permissions/index.md +++ b/site/en/docs/extensions/mv3/declare_permissions/index.md @@ -3,43 +3,40 @@ layout: "layouts/doc-post.njk" title: "Declare permissions" seoTitle: "Chrome Extensions Declare permissions" date: 2012-10-08 -updated: 2023-08-24 +updated: 2023-09-27 description: An overview of the valid values for the permissions property in manifest.json. --- -To use most [Chrome APIs][api-ref], your extension must declare its intent in the permissions fields -of the [manifest](#manifest). Extensions can request the following categories of permissions, specified using the respective manifest keys: +To use most [extension APIs][api-ref] and features, you must declare your extension's intent in the [manifest's](#manifest) permissions fields. Extensions can request the following categories of permissions, specified using the respective manifest keys: [`"permissions"`](#permissions) -: contains items from a list of known strings (such as `"geolocation"`). Changes may trigger a [warning](#warnings). +: Contains items from a list of [known strings](#permissions). Changes may trigger a [warning](#warnings). [`"optional_permissions"`][api-perms] -: are like regular `permissions`, but are granted by the user at runtime, rather than in advance. +: Granted by the user at runtime, instead of at install time. [`"content_scripts.matches"`][doc-cs-static] -: contains one or more [match patterns][doc-match] that allows content scripts to inject into one or more hosts. Changes may trigger a [warning](#warnings). +: Contains one or more [match patterns][doc-match] that allows content scripts to inject into one or more hosts. Changes may trigger a [warning](#warnings). [`"host_permissions"`](#host-permissions) -: contains one or more [match patterns][doc-match] that give access to one or more hosts. Changes may trigger a [warning](#warnings). +: Contains one or more [match patterns][doc-match] that give access to one or more hosts. Changes may trigger a [warning](#warnings). `"optional_host_permissions"` -: are like regular `host_permissions`, but are granted by the user at runtime, rather than at install time. +: Granted by the user at runtime, instead of at install time. Permissions help to limit damage if your extension is compromised by malware. Some permission warning are displayed to users for their consent before installation or at runtime, as detailed in [Permission with warnings](#warnings). -{% Aside %} Consider using [optional permissions][api-perms] wherever the functionality of your extension permits, to provide users with informed control over access to resources and data. -See the [platform vision][vision-optperms] to better understand this recommendation. -{% endAside %} +For more information, see the [platform vision][vision-optperms] statement. -If an API requires a permission, then its documentation tells you how -to do so. For example, the [Storage API][api-storage] page shows how to declare the `"storage"` permission. +If an API requires a permission, its documentation explains how to declare it. For an +example, see [Storage API][api-storage]. ## Manifest {: #manifest } -The following is an example of the permissions part of a [manifest][doc-manifest] file: +The following is an example of the permissions section of a [manifest][doc-manifest] file: {% Label %}manifest.json:{% endLabel %} @@ -59,8 +56,8 @@ The following is an example of the permissions part of a [manifest][doc-manifest "https://www.developer.chrome.com/*" ], "optional_host_permissions":[ - "https://*/*", - "http://*/*" + "https://*/*", + "http://*/*" ], ... "manifest_version": 3 @@ -69,21 +66,15 @@ The following is an example of the permissions part of a [manifest][doc-manifest ## Host permissions {: #host-permissions } -Host permissions allow extensions to interact with the URL's [matching patterns][doc-match]. Some [Chrome APIs][api-ref] require host permissions in addition to their own API permission, which are documented on each reference page. The following are a few examples of what host permissions allow extensions to do: +Host permissions allow extensions to interact with the URL's [matching patterns][doc-match]. Some [Chrome APIs][api-ref] require host permissions in addition to their own API permissions, which are documented on each reference page. Here are some examples: - Make [`fetch()`][mdn-fetch] requests from the extension service worker and extension pages. -- Read and query the sensitive [tab properties][api-tabs-tab] (url, title, and favIconUrl) using the [`chrome.tabs`][api-tabs] API. +- Read and query the sensitive [tab properties][api-tabs-tab] (url, title, and favIconUrl) using the [`chrome.tabs`][api-tabs] API. - Inject a [content script programmatically][cs-prog]. - Monitor and control the network requests with the [`chrome.webRequest`][api-webrequest] API. - Access cookies with the [`chrome.cookies`][api-cookies] API. - Redirect and modify requests and response headers using [`chrome.declarativeNetRequest`][api-dnr] API. -{% Aside 'warning' %} - -Adding or changing match patterns in the `"host_permissions"` and `"content_scripts.matches"` fields will trigger a [warning](#warnings). To learn more, see [Updating permissions][perm-update]. - -{% endAside %} - ## Permissions with warnings {:#warnings } When an extension requests multiple permissions, and many of them display @@ -96,18 +87,20 @@ Users are more likely to trust an extension with limited warnings or when permis to them. Consider implementing [optional permissions][api-perms] or a less powerful API to avoid alarming warnings. For a complete list of best practices, see [Permission warnings guidelines][doc-warning]. +Adding or changing match patterns in the `"host_permissions"` and `"content_scripts.matches"` fields will also trigger a [warning](#warnings). To learn more, see [Updating permissions][perm-update]. + ## Allow access {: #allow_access } - -If your extension needs to run on `file://` URLs or needs to operate in incognito mode, users will have to give the extension access on the extension's details page. + +If your extension needs to run on `file://` URLs or operate in incognito mode, users must give the extension access on its details page. You can find instructions for opening the details page under [Manage your extensions](https://support.google.com/chrome_webstore/answer/2664769?hl=en#:~:text=Manage%20your%20extensions). {% Details %} {% DetailsSummary %} -### How to allow access to file URLs and incognito pages +### Allow access to file URLs and incognito pages {% endDetailsSummary %} -1. Right-click on the extension icon in Chrome. +1. Right-click the extension icon in Chrome. 2. Choose **Manage Extension**. <figure> @@ -129,345 +122,239 @@ If your extension needs to run on `file://` URLs or needs to operate in incognit {% endDetails %} -To detect if the user has allowed access, you can use [`extension.isAllowedIncognitoAccess()`][incognito-allow] or +To detect whether the user has allowed access, you can call [`extension.isAllowedIncognitoAccess()`][incognito-allow] or [`extension.isAllowedFileSchemeAccess()`][file-scheme-allow]. ## Permissions list {: #permissions } -The following table lists the currently available permissions. See the [Permission warnings][doc-warning-table] table for a list of permission warnings. - -<table> - <tbody> - <tr> - <th>Permission</th> - <th>Description</th> - </tr> - <tr id="activeTab"> - <td><code>"activeTab"</code></td> - <td>Gives temporary access to the active tab through a user gesture. See <a href="/docs/extensions/mv3/manifest/activeTab"><code>activeTab</code></a> - for details.</td> - </tr> - <tr id="alarms"> - <td><code>"alarms"</code></td> - <td>Gives access to the <a href="/docs/extensions/reference/alarms">chrome.alarms</a> API.</td> - </tr> - <tr id="background"> - <td><code>"background"</code></td> - <td> - <p id="bg">Makes Chrome start up early (as soon as the user logs into their computer—before the user launches Chrome), and shut down late (even after its last window is closed until the user explicitly quits Chrome).</p> - <div class="aside aside--note"><b>Note:</b> Disabled extensions are treated as if they aren't - installed.</div> - </td> - </tr> - <tr id="bookmarks"> - <td><code>"bookmarks"</code></td> - <td>Gives access to the <a href="/docs/extensions/reference/bookmarks/">chrome.bookmarks</a> API.</td> - </tr> - <tr id="browsingData"> - <td><code>"browsingData"</code></td> - <td>Gives access to the <a href="/docs/extensions/reference/browsingData/">chrome.browsingData</a> API.</td> - </tr> - <tr id="certificateProvider"> - <td><code>"certificateProvider"</code></td> - <td>Gives access to the <a href="/docs/extensions/reference/certificateProvider/">chrome.certificateProvider</a> API.</td> - </tr> - <tr id="clipboardRead"> - <td><code>"clipboardRead"</code></td> - <td>Required if the extension uses <code>document.execCommand('paste')</code>.</td> - </tr> - <tr id="clipboardWrite"> - <td><code>"clipboardWrite"</code></td> - <td>Required if the extension uses <code>document.execCommand('copy')</code> or - <code>document.execCommand('cut')</code>. - </tr> - <tr id="contentSettings"> - <td><code>"contentSettings"</code></td> - <td>Gives access to the <a href="/docs/extensions/reference/contentSettings/">chrome.contentSettings</a> API.</td> - </tr> - <tr id="contextMenus"> - <td><code>"contextMenus"</code></td> - <td>Gives access to the <a href="/docs/extensions/reference/contextMenus/">chrome.contextMenus</a> API.</td> - </tr> - <tr id="cookies"> - <td><code>"cookies"</code></td> - <td>Gives access to the <a href="/docs/extensions/reference/cookies/">chrome.cookies</a> API.</td> - </tr> - <tr id="debugger"> - <td><code>"debugger"</code></td> - <td>Gives access to the <a href="/docs/extensions/reference/debugger/">chrome.debugger</a> API.</td> - </tr> - <tr id="declarativeContent"> - <td><code>"declarativeContent"</code></td> - <td>Gives access to the <a href="/docs/extensions/reference/declarativeContent/">chrome.declarativeContent</a> API.</td> - </tr> - <tr id="declarativeNetRequest"> - <td><code>"declarativeNetRequest"</code></td> - <td>Gives your extension access to the <a href="/docs/extensions/reference/declarativeNetRequest/">chrome.declarativeNetRequest</a> API. Some operations may require host permissions to perform.</td> - </tr> - <tr id="declarativeNetRequestWithHostAccess"> - <td><code>"declarativeNetRequestWithHostAccess"</code></td> - <td>Gives your extension access to the <a href="/docs/extensions/reference/declarativeNetRequest/">chrome.declarativeNetRequest</a> API, but requires host permissions to the request URL and initiator to act on a request.</td> - </tr> - <tr id="declarativeNetRequestFeedback"> - <td><code>"declarativeNetRequestFeedback"</code></td> - <td>Gives access to events and methods within the <a - href="/docs/extensions/reference/declarativeNetRequest/">chrome.declarativeNetRequest</a> API which returns information on declarative - rules matched.</td> - </tr> - <!-- No corresponding reference entry - <tr id="displaySource"> - <td><code>"displaySource"</code></td> - <td>Gives access to the <a href="/docs/extensions/reference/displaySource/">chrome.displaySource</a> API.</td> - </tr> - <tr id="dns"> - <td><code>"dns"</code></td> - <td>Gives access to the <a href="/docs/extensions/reference/dns/">chrome.dns</a> API.</td> - </tr> - --> - <tr id="desktopCapture"> - <td><code>"desktopCapture"</code></td> - <td>Gives access to the <a href="/docs/extensions/reference/desktopCapture/">chrome.desktopCapture</a> API.</td> - </tr> - <tr id="documentScan"> - <td><code>"documentScan"</code></td> - <td>Gives access to the <a href="/docs/extensions/reference/documentScan/">chrome.documentScan</a> API.</td> - </tr> - <tr id="downloads"> - <td><code>"downloads"</code></td> - <td>Gives access to the <a href="/docs/extensions/reference/downloads/">chrome.downloads</a> API.</td> - </tr> - <tr id="downloads-open"> - <td><code>"downloads.open"</code></td> - <td>Permission required to use <a href="/docs/extensions/reference/downloads/#method-open">chrome.downloads.open()</a></td> - </tr> - <tr id="downloads-ui"> - <td><code>"downloads.ui"</code></td> - <td>Permission required to use <a href="/docs/extensions/reference/downloads/#method-setUiOptions">chrome.downloads.setUiOptions()</a></td> - </tr> - <tr id="enterprise.deviceAttributes"> - <td><code>"enterprise.deviceAttributes"</code></td> - <td>Gives access to the <a - href="/docs/extensions/reference/enterprise_deviceAttributes/">chrome.enterprise.deviceAttributes</a> API.</td> - </tr> - <tr id="enterprise.hardwarePlatform"> - <td><code>"enterprise.hardwarePlatform"</code></td> - <td>Gives access to the <a - href="/docs/extensions/reference/enterprise_hardwarePlatform/">chrome.enterprise.hardwarePlatform</a> API.</td> - </tr> - <tr id="enterprise.networkingAttributes"> - <td><code>"enterprise.networkingAttributes"</code></td> - <td>Gives access to the <a - href="/docs/extensions/reference/enterprise_networkingAttributes/">chrome.enterprise.networkingAttributes</a> API.</td> - </tr> - <tr id="enterprise.platformKeys"> - <td><code>"enterprise.platformKeys"</code></td> - <td>Gives access to the <a href="/docs/extensions/reference/enterprise_platformKeys/">chrome.enterprise.platformKeys</a> API. - </td> - </tr> - <tr id="experimental"> - <td><code>"experimental"</code></td> - <td>Required if the extension uses any <a href="/docs/extensions/reference/#experimental_apis/">chrome.experimental.* APIs</a>.</td> - </tr> - <tr id="fileBrowserHandler"> - <td><code>"fileBrowserHandler"</code></td> - <td>Gives access to the <a href="/docs/extensions/reference/fileBrowserHandler/">chrome.fileBrowserHandler</a> API.</td> - </tr> - <tr id="fileSystemProvider"> - <td><code>"fileSystemProvider"</code></td> - <td>Gives access to the <a href="/docs/extensions/reference/fileSystemProvider/">chrome.fileSystemProvider</a> API.</td> - </tr> - <tr id="fontSettings"> - <td><code>"fontSettings"</code></td> - <td>Gives access to the <a href="/docs/extensions/reference/fontSettings/">chrome.fontSettings</a> API.</td> - </tr> - <tr id="gcm"> - <td><code>"gcm"</code></td> - <td>Gives access to the <a href="/docs/extensions/reference/gcm/">chrome.gcm</a> API.</td> - </tr> - <tr id="geolocation"> - <td><code>"geolocation"</code></td> - <td>Allows the extension to use the <a - href="https://dev.w3.org/geo/api/spec-source.html">geolocation API</a> without prompting the user for - permission.</td> - </tr> - <tr id="history"> - <td><code>"history"</code></td> - <td>Gives access to the <a href="/docs/extensions/reference/history/">chrome.history</a> API.</td> - </tr> - <tr id="identity"> - <td><code>"identity"</code></td> - <td>Gives access to the <a href="/docs/extensions/reference/identity/">chrome.identity</a> API.</td> - </tr> - <tr id="idle"> - <td><code>"idle"</code></td> - <td>Gives access to the <a href="/docs/extensions/reference/idle/">chrome.idle</a> API.</td> - </tr> - <!-- No corresponding reference entry - <tr id="idltest"> - <td><code>"idltest"</code></td> - <td>Gives access to the <a href="/docs/extensions/reference/idltest/">chrome.idltest</a> API.</td> - </tr> - <tr id="login"> - <td><code>"login"</code></td> - <td>Gives access to the <a href="/docs/extensions/reference/login/">chrome.login</a> API.</td> - </tr> - <tr id="loginScreenStorage"> - <td><code>"loginScreenStorage"</code></td> - <td>Gives access to the <a href="/docs/extensions/reference/loginScreenStorage/">chrome.loginScreenStorage</a> API.</td> - </tr> - --> - <tr id="loginState"> - <td><code>"loginState"</code></td> - <td>Gives access to the <a href="/docs/extensions/reference/loginState/">chrome.loginState</a> API.</td> - </tr> - <tr id="management"> - <td><code>"management"</code></td> - <td>Gives access to the <a href="/docs/extensions/reference/management/">chrome.management</a> API.</td> - </tr> - <tr id="nativeMessaging"> - <td><code>"nativeMessaging"</code></td> - <td>Gives access to the <a href="/docs/extensions/mv3/nativeMessaging/">native messaging API</a>.</td> - </tr> - <tr id="notifications"> - <td><code>"notifications"</code></td> - <td>Gives access to the <a href="/docs/extensions/reference/notifications/">chrome.notifications</a> API.</td> - </tr> - <tr id="offscreen"> - <td><code>"offscreen"</code></td> - <td>Gives access to the <a href="/docs/extensions/reference/offscreen/"><code>chrome.offscreen</code></a> API. - </tr> - <tr id="pageCapture"> - <td><code>"pageCapture"</code></td> - <td>Gives access to the <a href="/docs/extensions/reference/pageCapture/">chrome.pageCapture</a> API.</td> - </tr> - <tr id="platformKeys"> - <td><code>"platformKeys"</code></td> - <td>Gives access to the <a href="/docs/extensions/reference/platformKeys/">chrome.platformKeys</a> API.</td> - </tr> - <tr id="power"> - <td><code>"power"</code></td> - <td>Gives access to the <a href="/docs/extensions/reference/power/">chrome.power</a> API.</td> - </tr> - <tr id="printerProvider"> - <td><code>"printerProvider"</code></td> - <td>Gives access to the <a href="/docs/extensions/reference/printerProvider/">chrome.printerProvider</a> API.</td> - </tr> - <tr id="printing"> - <td><code>"printing"</code></td> - <td>Gives access to the <a href="/docs/extensions/reference/printing/">chrome.printing</a> API.</td> - </tr> - <tr id="printingMetrics"> - <td><code>"printingMetrics"</code></td> - <td>Gives access to the <a href="/docs/extensions/reference/printingMetrics/">chrome.printingMetrics</a> API.</td> - </tr> - <tr id="privacy"> - <td><code>"privacy"</code></td> - <td>Gives access to the <a href="/docs/extensions/reference/privacy/">chrome.privacy</a> API.</td> - </tr> - <tr id="processes"> - <td><code>"processes"</code></td> - <td>Gives access to the <a href="/docs/extensions/reference/processes/">chrome.processes</a> API.</td> - </tr> - <tr id="proxy"> - <td><code>"proxy"</code></td> - <td>Gives access to the <a href="/docs/extensions/reference/proxy/">chrome.proxy</a> API.</td> - </tr> - <tr id="scripting"> - <td><code>"scripting"</code></td> - <td>Gives access to the <a href="/docs/extensions/reference/scripting/">chrome.scripting</a> API.</td> - </tr> - <tr id="search"> - <td><code>"search"</code></td> - <td>Gives access to the <a href="/docs/extensions/reference/search/">chrome.search</a> API.</td> - </tr> - <tr id="sessions"> - <td><code>"sessions"</code></td> - <td>Gives access to the <a href="/docs/extensions/reference/sessions/">chrome.sessions</a> API.</td> - </tr> - <tr id="sidePanel"> - <td><code>"sidePanel"</code></td> - <td>Gives access to the <a href="/docs/extensions/reference/sidePanel/">chrome.sidePanel</a> API.</td> - </tr> - <tr id="storage"> - <td><code>"storage"</code></td> - <td>Gives access to the <a href="/docs/extensions/reference/storage/">chrome.storage</a> API.</td> - </tr> - <tr id="system.cpu"> - <td><code>"system.cpu"</code></td> - <td>Gives access to the <a href="/docs/extensions/reference/system_cpu/">chrome.system.cpu</a> API.</td> - </tr> - <tr id="system.display"> - <td><code>"system.display"</code></td> - <td>Gives access to the <a href="/docs/extensions/reference/system_display/">chrome.system.display</a> API.</td> - </tr> - <tr id="system.memory"> - <td><code>"system.memory"</code></td> - <td>Gives access to the <a href="/docs/extensions/reference/system_memory/">chrome.system.memory</a> API.</td> - </tr> - <tr id="system.storage"> - <td><code>"system.storage"</code></td> - <td>Gives access to the <a href="/docs/extensions/reference/system_storage/">chrome.system.storage</a> API.</td> - </tr> - <tr id="tabCapture"> - <td><code>"tabCapture"</code></td> - <td>Gives access to the <a href="/docs/extensions/reference/tabCapture/">chrome.tabCapture</a> API.</td> - </tr> - <tr id="tabGroups"> - <td><code>"tabGroups"</code></td> - <td>Gives access to the <a href="/docs/extensions/reference/tabGroups/">chrome.tabGroups</a> API.</td> - </tr> - <tr id="tabs"> - <td><code>"tabs"</code></td> - <td>Gives access to privileged fields of the <a - href="/docs/extensions/reference/tabs#type-Tab"><code>Tab</code></a> objects used by several APIs - including <a href="/docs/extensions/reference/tabs">chrome.tabs</a> and <a href="/docs/extensions/reference/windows">chrome.windows</a>. In - many circumstances your extension will not need to declare the <code>"tabs"</code> permission to make use of - these APIs.</td> - </tr> - <tr id="topSites"> - <td><code>"topSites"</code></td> - <td>Gives access to the <a href="/docs/extensions/reference/topSites/">chrome.topSites</a> API.</td> - </tr> - <tr id="tts"> - <td><code>"tts"</code></td> - <td>Gives access to the <a href="/docs/extensions/reference/tts/">chrome.tts</a> API.</td> - </tr> - <tr id="ttsEngine"> - <td><code>"ttsEngine"</code></td> - <td>Gives access to the <a href="/docs/extensions/reference/ttsEngine/">chrome.ttsEngine</a> API.</td> - </tr> - <tr id="unlimitedStorage"> - <td><code>"unlimitedStorage"</code></td> - <td>Provides an unlimited quota for <a href="/docs/extensions/reference/storage">chrome.storage</a>, <a href="https://developer.mozilla.org/docs/Web/API/IndexedDB_API">IndexedDB</a>, - <a href="https://developer.mozilla.org/en-US/docs/Web/API/Cache">Cache Storage</a> and <a href="https://web.dev/origin-private-file-system/">Origin Private File System</a>. For more information, - see <a href="/docs/extensions/mv3/storage-and-cookies">Storage and cookies</a>.</td> - </tr> - <tr id="vpnProvider"> - <td><code>"vpnProvider"</code></td> - <td>Gives access to the <a href="/docs/extensions/reference/vpnProvider/">chrome.vpnProvider</a> API.</td> - </tr> - <tr id="wallpaper"> - <td><code>"wallpaper"</code></td> - <td>Gives access to the <a href="/docs/extensions/reference/wallpaper/">chrome.wallpaper</a> API.</td> - </tr> - <tr id="webAuthenticationProxy"> - <td><code>"webAuthenticationProxy"</code></td> - <td>Gives access to the <a href="/docs/extensions/reference/webAuthenticationProxy/">chrome.webAuthenticationProxy</a> API.</td> - </tr> - <tr id="webNavigation"> - <td><code>"webNavigation"</code></td> - <td>Gives access to the <a href="/docs/extensions/reference/webNavigation/">chrome.webNavigation</a> API.</td> - </tr> - <tr id="webRequest"> - <td><code>"webRequest"</code></td> - <td>Gives access to the <a href="/docs/extensions/reference/webRequest/">chrome.webRequest</a> API.</td> - </tr> - <tr id="webRequestBlocking"> - <td><code>"webRequestBlocking"</code></td> - <td>Required if the extension uses the <a href="/docs/extensions/reference/webRequest/">chrome.webRequest</a> API in a blocking fashion.</td> - </tr> - </tbody> -</table> +Here's the list of permissions. See [Permission warnings][doc-warning-table] for a list of permission warnings. + +`"accessibilityFeatures.modify"` +: Lets extensions modify accessibility states when using the <a href="/docs/extensions/reference/accessibilityFeatures/"><code>chrome.accessibilityFeatures</code></a> API. + +`"accessibilityFeatures.read"` +: Lets extensions read accessibility states when using the <a href="/docs/extensions/reference/accessibilityFeatures/"><code>chrome.accessibilityFeatures</code></a> API. + +`"activeTab"` +: Gives temporary access to the active tab through a user gesture. See <a href="/docs/extensions/mv3/manifest/activeTab"><code>activeTab</code></a> +for details. + +`"alarms"` +: Gives access to the <a href="/docs/extensions/reference/alarms"><code>chrome.alarms</code></a> API. + +`"audio"` +: Gives access to the <a href="/docs/extensions/reference/audio"><code>chrome.audio</code></a> API. + +`"background"` +: Makes Chrome start up early (as soon as the user logs into their computer, before they launch Chrome), and shut down late (even after its last window is closed, until the user explicitly quits Chrome). + +`"bookmarks"` +: Gives access to the <a href="/docs/extensions/reference/bookmarks/">chrome.bookmarks</a> API. + +`"browsingData"` +: Gives access to the <a href="/docs/extensions/reference/browsingData/">chrome.browsingData</a> API. + +`"certificateProvider"` +: Gives access to the <a href="/docs/extensions/reference/certificateProvider/">chrome.certificateProvider</a> API. + +`"contentSettings"` +: Gives access to the <a href="/docs/extensions/reference/contentSettings/">chrome.contentSettings</a> API. + +`"contextMenus"` +: Gives access to the <a href="/docs/extensions/reference/contextMenus/">chrome.contextMenus</a> API. + +`"cookies"` +: Gives access to the <a href="/docs/extensions/reference/cookies/">chrome.cookies</a> API. + +`"debugger"` +: Gives access to the <a href="/docs/extensions/reference/debugger/">chrome.debugger</a> API. + +`"declarativeContent"` +: Gives access to the <a href="/docs/extensions/reference/declarativeContent/">chrome.declarativeContent</a> API. + +`"declarativeNetRequest"` +: Gives access to the <a href="/docs/extensions/reference/declarativeNetRequest/">chrome.declarativeNetRequest</a> API. + +`"declarativeNetRequestWithHostAccess"` +: Gives access to the <a href="/docs/extensions/reference/declarativeNetRequest/">chrome.declarativeNetRequest</a> API when host permissions are required. + +`"declarativeNetRequestFeedback"` +: Gives permission to write errors and warnings to the DevTools console when using the <a + href="/docs/extensions/reference/declarativeNetRequest/">chrome.declarativeNetRequest</a> API. This permission is for use with [unpacked extensions](/docs/extensions/mv3/getstarted/development-basics/#load-unpacked) and is ignored for extensions installed from the Chrome Web Store. + +`"dns"` +: Gives access to the <a href="/docs/extensions/reference/dns/">chrome.dns</a> API. + +`"desktopCapture"` +: Gives access to the <a href="/docs/extensions/reference/desktopCapture/">chrome.desktopCapture</a> API. + +`"documentScan"` +: Gives access to the <a href="/docs/extensions/reference/documentScan/">chrome.documentScan</a> API. + +`"downloads"` +: Gives access to the <a href="/docs/extensions/reference/downloads/">chrome.downloads</a> API. + +`"downloads.open"` +: Allows the use of <a href="/docs/extensions/reference/downloads/#method-open">chrome.downloads.open()</a>. + +`"downloads.ui"` +: Allows the use of <a href="/docs/extensions/reference/downloads/#method-setUiOptions">chrome.downloads.setUiOptions()</a>. + +`"enterprise.deviceAttributes"` +: Gives access to the <a href="/docs/extensions/reference/enterprise_deviceAttributes/">chrome.enterprise.deviceAttributes</a> API. + +`"enterprise.hardwarePlatform"` +: Gives access to the <a + href="/docs/extensions/reference/enterprise_hardwarePlatform/">chrome.enterprise.hardwarePlatform</a> API. + +`"enterprise.networkingAttributes"` +: Gives access to the <a href="/docs/extensions/reference/enterprise_networkingAttributes/">chrome.enterprise.networkingAttributes</a> API. + +`"enterprise.platformKeys"` +: Gives access to the <a href="/docs/extensions/reference/enterprise_platformKeys/">chrome.enterprise.platformKeys</a> API. + +`"favicon"` +: Grants access to the [Favicon](/docs/extensions/mv3/favicon/) API. + +`"fileBrowserHandler"` +: Gives access to the <a href="/docs/extensions/reference/fileBrowserHandler/">chrome.fileBrowserHandler</a> API. + +`"fileSystemProvider"` +: Gives access to the <a href="/docs/extensions/reference/fileSystemProvider/">chrome.fileSystemProvider</a> API. + +`"fontSettings"` +: Gives access to the <a href="/docs/extensions/reference/fontSettings/">chrome.fontSettings</a> API. + +`"gcm"` +: Gives access to the <a href="/docs/extensions/reference/gcm/"><code>chrome.gcm</code></a> and <a href="https://developer.chrome.com/docs/extensions/reference/instanceID/"><code>chrome.instanceID</code></a> APIs. + +`"geolocation"` +: Allows the extension to use the <a + href="https://developer.mozilla.org/docs/Web/API/Geolocation_API">geolocation API</a> without prompting the user for permission. + +`"history"` +: Gives access to the <a href="/docs/extensions/reference/history/">chrome.history</a> API. + +`"identity"` +: Gives access to the <a href="/docs/extensions/reference/identity/">chrome.identity</a> API. + +`"idle"` +: Gives access to the <a href="/docs/extensions/reference/idle/">chrome.idle</a> API. + +`"loginState"` +: Gives access to the <a href="/docs/extensions/reference/loginState/">chrome.loginState</a> API. + +`"management"` +: Gives access to the <a href="/docs/extensions/reference/management/">chrome.management</a> API. + +`"nativeMessaging"` +: Gives access to the <a href="/docs/extensions/mv3/nativeMessaging/">native messaging API</a>. + +`"notifications"` +: Gives access to the <a href="/docs/extensions/reference/notifications/">chrome.notifications</a> API. + +`"offscreen"` +: Gives access to the <a href="/docs/extensions/reference/offscreen/"><code>chrome.offscreen</code></a> API. + +`"pageCapture"` +: Gives access to the <a href="/docs/extensions/reference/pageCapture/">chrome.pageCapture</a> API. + +`"platformKeys"` +: Gives access to the <a href="/docs/extensions/reference/platformKeys/">chrome.platformKeys</a> API. + +`"power"` +: Gives access to the <a href="/docs/extensions/reference/power/">chrome.power</a> API. + +`"printerProvider"` +: Gives access to the <a href="/docs/extensions/reference/printerProvider/">chrome.printerProvider</a> API. + +`"printing"` +: Gives access to the <a href="/docs/extensions/reference/printing/">chrome.printing</a> API. + +`"printingMetrics"` +: Gives access to the <a href="/docs/extensions/reference/printingMetrics/">chrome.printingMetrics</a> API. + +`"privacy"` +: Gives access to the <a href="/docs/extensions/reference/privacy/">chrome.privacy</a> API. + +`"processes"` +: Gives access to the <a href="/docs/extensions/reference/processes/">chrome.processes</a> API. + +`"proxy"` +: Gives access to the <a href="/docs/extensions/reference/proxy/">chrome.proxy</a> API. + +`"runtime"` +: Gives access to <a href="/docs/extensions/reference/runtime/#method-connectNative"><code>runtime.conntectNative()</code></a> and <a href="/docs/extensions/reference/runtime/#method-sendNativeMessage"><code>runtime.sendNatriceMessage()</code></a>. For all other features of the <code>runtime</code> namespace, no permission is required. + +`"scripting"` +: Gives access to the <a href="/docs/extensions/reference/scripting/">chrome.scripting</a> API. + +`"search"` +: Gives access to the <a href="/docs/extensions/reference/search/">chrome.search</a> API. + +`"sessions"` +: Gives access to the <a href="/docs/extensions/reference/sessions/">chrome.sessions</a> API. + +`"sidePanel"` +: Gives access to the <a href="/docs/extensions/reference/sidePanel/">chrome.sidePanel</a> API. + +`"storage"` +: Gives access to the <a href="/docs/extensions/reference/storage/">chrome.storage</a> API. + +`"system.cpu"` +: Gives access to the <a href="/docs/extensions/reference/system_cpu/">chrome.system.cpu</a> API. + +`"system.display"` +: Gives access to the <a href="/docs/extensions/reference/system_display/">chrome.system.display</a> API. + +`"system.memory"` +: Gives access to the <a href="/docs/extensions/reference/system_memory/">chrome.system.memory</a> API. + +`"system.storage"` +: Gives access to the <a href="/docs/extensions/reference/system_storage/">chrome.system.storage</a> API. + +`"tabCapture"` +: Gives access to the <a href="/docs/extensions/reference/tabCapture/">chrome.tabCapture</a> API. + +`"tabGroups"` +: Gives access to the <a href="/docs/extensions/reference/tabGroups/">chrome.tabGroups</a> API. + +`"tabs"` +: Gives access to privileged fields of the <a + href="/docs/extensions/reference/tabs#type-Tab"><code>Tab</code></a> objects used by several APIs, +including <a href="/docs/extensions/reference/tabs">chrome.tabs</a> and <a href="/docs/extensions/reference/windows">chrome.windows</a>. You usually won't need to declare this permission to use those APIs. + +`"topSites"` +: Gives access to the <a href="/docs/extensions/reference/topSites/">chrome.topSites</a> API. + +`"tts"` +: Gives access to the <a href="/docs/extensions/reference/tts/">chrome.tts</a> API. + +`"ttsEngine"` +: Gives access to the <a href="/docs/extensions/reference/ttsEngine/">chrome.ttsEngine</a> API. + +`"unlimitedStorage"` +: Provides an unlimited quota for <a href="/docs/extensions/reference/storage#property-local">chrome.storage.local</a>, <a href="https://developer.mozilla.org/docs/Web/API/IndexedDB_API">IndexedDB</a>, + <a href="https://developer.mozilla.org/docs/Web/API/Cache">Cache Storage</a> and <a href="https://web.dev/origin-private-file-system/">Origin Private File System</a>. For more information, + see <a href="/docs/extensions/mv3/storage-and-cookies">Storage and cookies</a>. + +`"vpnProvider"` +: Gives access to the <a href="/docs/extensions/reference/vpnProvider/">chrome.vpnProvider</a> API. + +`"wallpaper"` +: Gives access to the <a href="/docs/extensions/reference/wallpaper/">chrome.wallpaper</a> API. + +`"webAuthenticationProxy"` +: Gives access to the <a href="/docs/extensions/reference/webAuthenticationProxy/">chrome.webAuthenticationProxy</a> API. + +`"webNavigation"` +: Gives access to the <a href="/docs/extensions/reference/webNavigation/">chrome.webNavigation</a> API. + +`"webRequest"` +: Gives access to the <a href="/docs/extensions/reference/webRequest/">chrome.webRequest</a> API. + +`"webRequestBlocking"` +: Allows the use of the <a href="/docs/extensions/reference/webRequest/">chrome.webRequest</a> API for blocking. [api-cookies]: /docs/extensions/reference/cookies [api-dnr]: /docs/extensions/reference/declarativeNetRequest From 355bc76b53b464460e60f166af4a4fbc8296709c Mon Sep 17 00:00:00 2001 From: amysteamdev <37001393+AmySteam@users.noreply.github.com> Date: Tue, 24 Oct 2023 13:42:24 -0500 Subject: [PATCH 961/982] Remove link on known issues page (#7644) --- site/en/docs/extensions/migrating/known-issues/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/en/docs/extensions/migrating/known-issues/index.md b/site/en/docs/extensions/migrating/known-issues/index.md index fb9301844..3ba4ebca9 100644 --- a/site/en/docs/extensions/migrating/known-issues/index.md +++ b/site/en/docs/extensions/migrating/known-issues/index.md @@ -25,7 +25,7 @@ Recently, we announced changes to the Manifest V2 deprecation timeline, and whil We are committed to closing the following gaps before announcing a new Manifest V2 deprecation timeline: 1. **Support File Handling API on ChromeOS** as a replacement for [`chrome.fileBrowserHandler`](/docs/extensions/reference/fileBrowserHandler/). -1. **User Script support:** Allow registering content scripts with arbitrary code with the new [userScripts API](/docs/extensions/reference/userscripts/). (See [our proposal](https://github.com/w3c/webextensions/blob/main/proposals/user-scripts-api.md) for details.) +1. **User Script support:** Allow registering content scripts with arbitrary code with the new userScripts API. (See [our proposal](https://github.com/w3c/webextensions/blob/main/proposals/user-scripts-api.md) for details.) These issues have been collected based on feedback from partners, bug reports, and developers. In addition to these, we will continue our ongoing work to address stability issues and improve overall performance. From 0078cdd1aeb974eba6a8a878aa3993a28af4982e Mon Sep 17 00:00:00 2001 From: Joe Medley <jmedley@google.com> Date: Tue, 24 Oct 2023 12:54:22 -0700 Subject: [PATCH 962/982] Fix feature detection. (#7643) --- site/en/docs/extensions/reference/offscreen/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/en/docs/extensions/reference/offscreen/index.md b/site/en/docs/extensions/reference/offscreen/index.md index d4ea8f652..b801f2b36 100644 --- a/site/en/docs/extensions/reference/offscreen/index.md +++ b/site/en/docs/extensions/reference/offscreen/index.md @@ -124,7 +124,7 @@ to check for an existing offscreen document: ```js async function hasOffscreenDocument() { - if (chrome.runtime.getContexts) { + if ('getContexts' in chrome.runtime) { const contexts = await chrome.runtime.getContexts({ contextTypes: ['OFFSCREEN_DOCUMENT'], documentUrls: [OFFSCREEN_DOCUMENT_PATH] From 6b03a96203b9c5d785d3cd2240db12042c88e731 Mon Sep 17 00:00:00 2001 From: wizardofdocs <83661258+wizardofdocs@users.noreply.github.com> Date: Wed, 25 Oct 2023 08:22:00 -0700 Subject: [PATCH 963/982] Updated Match Patterns (#7215) * Updated index.md Condensed descriptions and examples. Converted example table to definition list. Integrated the invalid list with the descriptions and examples, to not confuse the reader with a list of things to not do. Please make sure the special cases and examples are up to date. * Updated Match Patterns Update date * Update site/en/docs/extensions/mv3/match_patterns/index.md Fixed formatting Co-authored-by: Joe Medley <jmedley@google.com> * Update site/en/docs/extensions/mv3/match_patterns/index.md Fixed formatting Co-authored-by: Joe Medley <jmedley@google.com> * Update site/en/docs/extensions/mv3/match_patterns/index.md Fixed formatting Co-authored-by: Joe Medley <jmedley@google.com> * Update site/en/docs/extensions/mv3/match_patterns/index.md fixed syntax Co-authored-by: Joe Medley <jmedley@google.com> * Update site/en/docs/extensions/mv3/match_patterns/index.md Updated phrasing Co-authored-by: Joe Medley <jmedley@google.com> * Update index.md Fixed formatting of path explanation * Update site/en/docs/extensions/mv3/match_patterns/index.md Fixed punctuation Co-authored-by: Joe Medley <jmedley@google.com> * Update site/en/docs/extensions/mv3/match_patterns/index.md Highlighted special syntax Co-authored-by: Joe Medley <jmedley@google.com> * Fixing links in match_patterns.md I've updated the syntax on the "grant access" link in line 36, but none of the internal links are working for me. Wondering if that's a permissions issue for me as a TVC. I can make the links work using the full path (/site/en/docs...), but specifying a language in a file path is bad for localization. * Updated match_patterns Converted long list sentence into bullet list * Updated match patterns I'd like to make the WAR and Externally Connectable lines more informative to match the permissions line. What do those things *do* with the match patterns? * Clarified match pattern use cases * Update site/en/docs/extensions/mv3/match_patterns/index.md Disambiguated host permissions from other permissions. Co-authored-by: amysteamdev <37001393+AmySteam@users.noreply.github.com> * Update site/en/docs/extensions/mv3/match_patterns/index.md Fixed link Co-authored-by: amysteamdev <37001393+AmySteam@users.noreply.github.com> * Updated match_patterns with another try at explaining `/*` * Update site/en/docs/extensions/mv3/match_patterns/index.md Fixed punctuation Co-authored-by: Oliver Dunk <oliverdunk@google.com> * Update site/en/docs/extensions/mv3/match_patterns/index.md Updated syntax Co-authored-by: Oliver Dunk <oliverdunk@google.com> * Updated scheme list in Match Patterns * Fixed code formatting in Match Patterns doc * Update site/en/docs/extensions/mv3/match_patterns/index.md Simplified scheme list Co-authored-by: amysteamdev <37001393+AmySteam@users.noreply.github.com> --------- Co-authored-by: Joe Medley <jmedley@google.com> Co-authored-by: amysteamdev <37001393+AmySteam@users.noreply.github.com> Co-authored-by: Oliver Dunk <oliverdunk@google.com> --- .../extensions/mv3/match_patterns/index.md | 181 +++++------------- 1 file changed, 50 insertions(+), 131 deletions(-) diff --git a/site/en/docs/extensions/mv3/match_patterns/index.md b/site/en/docs/extensions/mv3/match_patterns/index.md index 90f5e2476..f8f20d27b 100644 --- a/site/en/docs/extensions/mv3/match_patterns/index.md +++ b/site/en/docs/extensions/mv3/match_patterns/index.md @@ -3,159 +3,78 @@ layout: 'layouts/doc-post.njk' title: 'Match patterns' seoTitle: 'Chrome Extensions match patterns' date: 2012-09-18 -updated: 2023-07-28 +updated: 2023-08-31 description: Understanding URL match patterns in Chrome extensions. --- -## Overview {: #overview } - -Extensions use match patterns to specify a group of URLs. They are mainly used to declare [host permissions][host-permissions] along with other permissions to use certain Chrome APIs or when injecting [content scripts][content-scripts]. Extensions also use match patterns in: - -- [`"web_accessible_resources.matches"`][war] -- [`"externally_connectable.matches"`][ext-connect] - -## What is a match pattern? {: #what } - -A match pattern is a URL that begins with a permitted scheme, separated by a `://`, followed by a host and path. It can contain wildcard (`*`) characters. Most match patterns are composed of three parts: +A match pattern is a URL with the following structure, used to specify a group of URLs: ```text <scheme>://<host>/<path> ``` -Each part can use wildcards `*`. Below is a detailed description: +**scheme**: Must be one of the following, separated from the rest of the pattern using a double slash (`//`): + +- `http` +- `https` +- A wildcard `*`, which matches only `http` or `https` +- `file` -- **scheme**: Must include a valid scheme: `'http'`, `'https'`, `'file'`, `'ftp'`, or `'urn'`. The wildcard `*` only matches `http` or `https`. +For information on injecting content scripts into unsupported schemes, such as `about:` and `data:`, see [Injecting in related frames][cs-frames]. -- **host**: A hostname (`www.example.com`), a `*` before the hostname to match subdomains (`*.example.com`), or just a wildcard `*`. +**host**: A hostname (`www.example.com`). A `*` before the hostname to match subdomains (`*.example.com`), or just a wildcard `*`. + - If you use a wildcard in the host pattern, it must be the first or only character, and it must be followed by a period (`.`) or forward slash (`/`). -- **path**: Must start with `/` and be present. If alone, it is treated as `/*`. For example: `/*`, `/foo*`, or `/foo/bar`. Each '`*`' matches 0 or more characters. +**path**: Must contain at least a forward slash. The slash by itself matches any path, as if it were followed by a wildcard (`/*`). + +Extensions use match patterns in a variety of use cases, including the following: + +* Injecting [content script][content-scripts]. +* [Declaring host permissions][host-permissions] that some Chrome APIs require in addition to their own permissions. +* Granting access to [web-accessible resources][war]. +* Allowing message sending and receiving using ["externally_connectable.matches"][ext-connect]. ## Special cases {: #special } -`<all_urls>` -: It matches any URL that starts with a permitted scheme, including any pattern listed under [valid patterns](#valid-examples). This is a broad host permission, meaning the Chrome web store [review may take longer](/docs/webstore/review-process/#review-time-factors). +`"<all_urls>"` +: Matches any URL that starts with a permitted scheme, including any pattern listed under [valid patterns](#valid-examples). Because it affects all hosts, Chrome web store reviews for extensions that use it [may take longer](/docs/webstore/review-process/#review-time-factors). -`file:///` -: Allows your extension to run on local files. It has no host and requires the user to manually [grant access][permissions-allow-access]. +`"file:///"` +: Allows your extension to run on local files. This pattern requires the user to manually [grant access][permissions]. Note that this case requires three slashes, not two. Localhost URLs and IP addresses -: To match any localhost port during development, use `http://localhost:*/*`. For example, it will match any paths under `http://localhost:8080` or `http://localhost:3000`. For IP addresses, specify the address plus a wildcard in the path. For example: `http://127.0.0.1/*`. Another approach is to use `http://*:*/*` which will match localhost, IP addresses and any port. +: To match any localhost port during development, use `http://localhost:*/*`. Specify a port using the port number, as in `http://localhost:8080/*`. For IP addresses, specify the address plus a wildcard in the path, as in `http://127.0.0.1/*`. You can also use `http://*:*/*` to match localhost, IP addresses, and any port. Top Level domain match patterns -: [Top Level domain][mdn-tld] match patterns like `http://google.*/*` are not supported. They should be listed individually. For example: `http://google.es/*` and `http://google.fr/*`. - -## Examples {: #examples } - -### ✅ Valid patterns {: #valid-examples } - -<table class="fixed-table width-full"> - <tbody> - <tr> - <th style="margin-left:0; padding-left:0">Pattern</th> - <th style="margin-left:0; padding-left:0">What it does</th> - <th style="margin-left:0; padding-left:0">Examples</th> - </tr> - <tr> - <td><code>https://*/*</code></td> - <td>Matches any URL that uses the <code>https</code> scheme</td> - <td>https://www.google.com/ <br>https://example.org/foo/bar.html</li></ul></td> - </tr> - <tr> - <td><code>http://*/*</code></td> - <td>Matches any URL that uses the <code>http</code> scheme</td> - <td>http://74.125.127.100/search <br>http://example.com/</li></ul></td> - </tr> - <tr> - <td><code>https://*/foo*</code></td> - <td>Matches any URL that uses the <code>https</code> scheme, on any host, and a path that starts with <code>/foo</code></td> - <td>https://example.com/foo/bar.html https://www.google.com/foo</li></ul></td> - </tr> - <tr> - <td><code>https://*.google.com/foo*bar</code></td> - <td>Matches any URL that uses the <code>https</code> scheme, is on a google.com host, and the path starts with <code>/foo</code> and ends with <code>bar</code></td> - <td>https://www.google.com/foo/baz/bar<br>https://docs.google.com/foobar</td> - </tr> - <tr> - <td><code>file:///foo*</code></td> - <td>Matches any local file whose path starts with <code>/foo</code></td> - <td>file:///foo/bar.html<br>file:///foo</td> - </tr> - <tr> - <td><code>http://127.0.0.1/*</code></td> - <td>Matches any URL that uses the <code>http</code> scheme and is on the host 127.0.0.1</td> - <td>http://127.0.0.1/<br>http://127.0.0.1/foo/bar.html</td> - </tr> - <tr> - <td><code>http://localhost/*</code></td> - <td>Matches any localhost port</td> - <td>http://localhost:3000<br>http://localhost:8080</td> - </tr> - <tr> - <td><code>*://mail.google.com/*</code></td> - <td>Matches any URL that starts with <code>http://mail.google.com</code> or <code>https://mail.google.com</code>.</td> - <td>http://mail.google.com/foo/baz/bar<br>https://mail.google.com/foobar</td> - </tr> - <tr> - <td><code>urn:*</code></td> - <td>Matches any URL that starts with <code>urn:</code>.</td> - <td>urn:uuid:54723bea-c94e-480e-80c8-a69846c3f582<br>urn:uuid:cfa40aff-07df-45b2-9f95-e023bcf4a6da</td> - </tr> - </tbody> -</table> - -### ❌ Invalid patterns {: #invalid-patterns } - -Here are some examples of _invalid_ match patterns: - -<table class="fixed-table width-full"> - <tbody> - <tr> - <th style="margin-left:0; padding-left:0">Invalid pattern</th> - <th style="margin-left:0; padding-left:0">Why it's invalid</th> - </tr> - <tr> - <td><code>https://www.google.com</code></td> - <td>No <em>path</em></td> - </tr> - <tr> - <td><code>https://*foo/bar</code></td> - <td>'*' in the <em>host</em> can be followed only by a '.' or '/'</td> - </tr> - <tr> - <td><code>https://foo.*.bar/baz </code></td> - <td>If '*' is in the <em>host</em>, it must be the first character</td> - </tr> - <tr> - <td><code>http:/bar</code></td> - <td>Missing <em>scheme</em> separator ("/" should be "//")</td> - </tr> - <tr> - <td><code>foo://*</code></td> - <td>Invalid <em>scheme</em></td> - </tr> - <tr> - <td><code>chrome://*</code></td> - <td>Unsupported <em>scheme</em></td> - </tr> - <tr> - <td><code>chrome-extension://*</code></td> - <td>Unsupported <em>scheme</em></td> - </tr> - <tr> - <td><code>about:*</code></td> - <td>Unsupported <em>scheme</em>.</td> - </tr> - </tbody> -</table> - -{% Aside 'success' %} -Content scripts can be injected into related frames like `about:`, `data:`, etc by setting `"match_origin_as_fallback"` to `"true"` in the manifest. See [Injecting in related frames][cs-frames] for details. -{% endAside %} +: Chrome doesn't support match patterns for [top Level domains (TLD)][mdn-tld]. Specify your match patterns within individual TLDs, as in `http://google.es/*` and `http://google.fr/*`. + +## Example patterns {: #examples } + +`https://*/*` or `https://*/` +: Matches any URL using the `https` scheme. + +`https://*/foo*` +: Matches any URL using the `https` scheme, on any host, with a path that starts with `foo`. Examples of matches include `https://example.com/foo/bar.html` and `https://www.google.com/foo`. + +`https://*.google.com/foo*bar` +: Matches any URL using the `https` scheme, on a google.com host, with a path that starts with `foo` and ends with `bar`. Examples of matches include `https://www.google.com/foo/baz/bar` and `https://docs.google.com/foobar`. + +`file:///foo*` +: Matches any local file whose path starts with `foo`. Examples of matches include `file:///foo/bar.html` and `file:///foo`. + +`http://127.0.0.1/*` or `http://127.0.0.1/` +: Matches any URL that uses the `http` scheme and is on the host 127.0.0.1. Examples of matches include `http://127.0.0.1/` and `http://127.0.0.1/foo/bar.html`. + +`http://localhost/*` +: Matches any localhost port. + +`*://mail.google.com/` or `*://mail.google.com/*` +: Matches any URL that starts with `http://mail.google.com` or `https://mail.google.com`. [content-scripts]: /docs/extensions/mv3/content_scripts [cs-frames]: /docs/extensions/mv3/content_scripts/#injecting-in-related-frames [ext-connect]: /docs/extensions/mv3/manifest/externally_connectable/#manifest -[host-permissions]: /docs/extensions/mv3/declare_permissions/#host-permissions [mdn-tld]: https://developer.mozilla.org/docs/Glossary/TLD -[permissions]: /docs/extensions/mv3/declare_permissions/ +[permissions]: /docs/extensions/mv3/declare_permissions/#allow_access +[host-permissions]: /docs/extensions/mv3/declare_permissions/#host-permissions [war]: /docs/extensions/mv3/manifest/web_accessible_resources/#manifest-declaration From bcf2b00cba8b5c0e99062e097bc4915af3ded9e7 Mon Sep 17 00:00:00 2001 From: wizardofdocs <83661258+wizardofdocs@users.noreply.github.com> Date: Wed, 25 Oct 2023 08:22:43 -0700 Subject: [PATCH 964/982] Updated Action reference (#7501) * Updated Action reference Regrouped headers and updated phrasing * Update site/en/docs/extensions/reference/action/index.md Updated phrasing Co-authored-by: Joe Medley <jmedley@google.com> * Update site/en/docs/extensions/reference/action/index.md Updated phrasing Co-authored-by: Joe Medley <jmedley@google.com> * Update site/en/docs/extensions/reference/action/index.md updated phrasing and code syntax Co-authored-by: Joe Medley <jmedley@google.com> * Updated syntax in Action reference * Update site/en/docs/extensions/reference/action/index.md Updated syntax Co-authored-by: Joe Medley <jmedley@google.com> * Update site/en/docs/extensions/reference/action/index.md Updated phrasing Co-authored-by: Joe Medley <jmedley@google.com> * Update site/en/docs/extensions/reference/action/index.md Updated terminology Co-authored-by: Joe Medley <jmedley@google.com> * Fixed spelling in Action reference * Fixed terminology in Action reference * Update site/en/docs/extensions/reference/action/index.md Updated phrasing Co-authored-by: Joe Medley <jmedley@google.com> * Update site/en/docs/extensions/reference/action/index.md Updated phrasing Co-authored-by: Joe Medley <jmedley@google.com> * Update site/en/docs/extensions/reference/action/index.md Reverted default_popup phrasing Co-authored-by: Joe Medley <jmedley@google.com> * Update site/en/docs/extensions/reference/action/index.md Removed answered question Co-authored-by: Joe Medley <jmedley@google.com> * Update site/en/docs/extensions/reference/action/index.md Reverted "enabled" phrasing Co-authored-by: Joe Medley <jmedley@google.com> * Update site/en/docs/extensions/reference/action/index.md Updated phrasing Co-authored-by: Joe Medley <jmedley@google.com> * Update site/en/docs/extensions/reference/action/index.md Updated optional values explanation Co-authored-by: Joe Medley <jmedley@google.com> * Update site/en/docs/extensions/reference/action/index.md removed answered question Co-authored-by: Joe Medley <jmedley@google.com> * Update site/en/docs/extensions/reference/action/index.md Removed reference to MV2 Co-authored-by: Joe Medley <jmedley@google.com> --------- Co-authored-by: Joe Medley <jmedley@google.com> --- .../docs/extensions/reference/action/index.md | 114 ++++++++---------- 1 file changed, 53 insertions(+), 61 deletions(-) diff --git a/site/en/docs/extensions/reference/action/index.md b/site/en/docs/extensions/reference/action/index.md index ec34516ea..6ebb02a63 100644 --- a/site/en/docs/extensions/reference/action/index.md +++ b/site/en/docs/extensions/reference/action/index.md @@ -2,18 +2,16 @@ api: action --- -You can use the `chrome.action` API to control the toolbar button for your extension in Chrome's UI. -The action icons are displayed in the browser toolbar, to the right of the omnibox (on left-to-right -devices). After installation, by default, these appear in the extensions menu (the puzzle piece). -Users can choose to pin your extension icon to the toolbar. +To control your extension's toolbar button in Chrome's UI, use the `chrome.action` API. +The action icons are displayed in the browser toolbar next to the [omnibox](https://en.wiktionary.org/wiki/omnibox). After installation, these appear in the extensions menu (the puzzle piece icon). +Users can pin your extension icon to the toolbar. -Note that every extension will have an icon in the toolbar in Chrome, even if the `action` key is -not specified. +Every extension has an icon in the Chrome toolbar, even if the `action` key isn't added to the manifest. ## Manifest -To use the `chrome.action` API, you need to specify a `"manifest_version"` of `3` or higher -and include the `action` key in your [manifest file][doc-manifest]. +To use the `chrome.action` API, specify a `"manifest_version"` of `3` +and include the `"action"` key in your [manifest file][doc-manifest]: ```json { @@ -32,27 +30,27 @@ and include the `action` key in your [manifest file][doc-manifest]. } ``` -Each of these values is optional; an empty dictionary is technically allowed. +The `"action"` key (along with its children) is optional. When it isn't included, your extension is still shown in the toolbar to provide access to the extension's menu. For this reason, we recommend that you always include at least the `"action"` and `"default_icon"` keys. -These properties are described more below. +## Concepts and Usage -## Parts of the UI +### Parts of the UI -### Icon +#### Icon -The icon is the main image used in the toolbar button. Icons are 16 DIPs (device-independent pixels) -wide and tall. The icon is initially set by the `default_icon` key in the `action` entry in the -`manifest.json` file. This key is a dictionary of sizes to image paths. Chrome will use these icons -to choose which image scale to use. If an exact match is not found, Chrome will select the closest -available and scale it to fit the image. However, this scaling can cause the icon to lose detail or -look fuzzy. +The icon is the main image on the toolbar for your extension, and is set by the `"default_icon"` key in +your manifest's `action` entry. Icons must be 16 device-independent pixels (DIPs) wide and tall. -Since devices with less-common scale factors like 1.5x or 1.2x are becoming more common, you are -encouraged to provide multiple sizes for your icons. This also ensures that if the icon display size -is ever changed, you don't need to do any more work to provide different icons. +The `"default_icon"` key is a dictionary of sizes to image paths. Chrome uses these icons +to choose which image scale to use. If an exact match is not found, Chrome selects the closest +available and scales it to fit the image, which might affect image quality. -The icon can also be set programmatically using the `action.setIcon()` method. This can be used to -specify a different image path or to provide a dynamically-generated icon using the [HTML canvas +Because devices with less-common scale factors like 1.5x or 1.2x are becoming more +common, we encourage you to provide multiple sizes for your icons. This also +futureproofs your extension against potential icon display size changes. + +You can also call `action.setIcon()` to set your extension's icon programmatically +by specifying a different image path or providing a dynamically-generated icon using the [HTML canvas element][html-canvas], or, if setting from an extension service worker, the [offscreen canvas][html-offscreencanvas] API. @@ -68,36 +66,32 @@ chrome.action.setIcon({imageData: imageData}, () => { /* ... */ }); {% Aside %} -The `action.setIcon()` API is intended to set a static image. It should not be used to simulate -animation. +The `action.setIcon()` API is intended to set a static image. Don't use animated images for your icons. {% endAside %} -#### Formats - For packed extensions (installed from a .crx file), images can be in most formats that the Blink -rendering engine can display, including PNG, JPEG, BMP, ICO, and others (SVG is not supported). -Unpacked extensions must use images in the PNG format. +rendering engine can display, including PNG, JPEG, BMP, ICO, and others. SVG isn't supported. +Unpacked extensions must use PNG images. -### Tooltip (title) +#### Tooltip (title) -The tooltip, or title, appears when the user hovers the mouse on the extension's icon in the -toolbar. It is also included in the accessible text spoken by screenreaders when the button gets +The tooltip, or title, appears when the user holds their mouse pointer over the extension's icon in the +toolbar. It's also included in the accessible text spoken by screen readers when the button gets focus. -The default tooltip is set from the `default_title` field of the `action` object in `manifest.json`. -You can also set it programmatically with the `action.setTitle()` method. +The default tooltip is set using the `"default_title"` field of the `action` key in `manifest.json`. +You can also set it programmatically by calling `action.setTitle()`. -### Badge +#### Badge Actions can optionally display a "badge" — a bit of text layered over the icon. This makes it easy to update the action to display a small amount of information about the state of the extension, -such as a counter. The badge has a text component and a background color. +such as a counter. The badge has a text component and a background color. Because space is limited, +we recommend that badge text use four or fewer characters. -Note that the badge has limited space, and should typically use four characters or fewer. - -The badge does not have a default taken from the manifest; you can set it programmatically with -`action.setBadgeBackgroundColor()` and `action.setBadgeText()`. When setting the color, the values +To create a badge, set it programmatically by calling `action.setBadgeBackgroundColor()` and +`action.setBadgeText()`. There isn't a default badge setting in the manifest. Badge color values can be either an array of four integers between 0 and 255 that make up the RGBA color of the badge or a string with a [CSS color][css-color] value. @@ -118,30 +112,31 @@ chrome.action.setBadgeBackgroundColor( ); ``` -### Popup +#### Popup -An action's popup will be shown when the user clicks on the extension's action button in the +An action's popup is shown when the user clicks on the extension's action button in the toolbar. The popup can contain any HTML contents you like, and will be automatically sized to fit -its contents. The popup cannot be smaller than 25x25 and cannot be larger than 800x600. +its contents. The popup's size must be between 25x25 and 800x600 pixels. -The popup is initially set from the `default_popup` property in the `action` key in the -`manifest.json` file. If present, this should point to a relative path within the extension +The popup is initially set by the `"default_popup"` property in the `action` key in the +`manifest.json` file. If present, this property should point to a relative path within the extension directory. It can also be updated dynamically to point to a different relative path using the `action.setPopup()` method. {% Aside %} -The `action.onClicked` event will not be dispatched if the extension action has specified a popup to +The `action.onClicked` event won't be sent if the extension action has specified a popup to show on click on the current tab. {% endAside %} -## Per-tab state +## Use cases + +### Per-tab state -Extension actions can have different states for each tab. For instance, you could set the badge text -to be different on each tab (to show tab-specific state). You can set the value for an individual -tab using the `tabId` property in the various setting methods on the `action` API. For instance, to -set the badge text on a specific tab, you would do something like the following: +Extension actions can have different states for each tab. To set a value for an individual +tab, use the `tabId` property in the `action` API's setting methods. For example, to +set the badge text for a specific tab, do something like the following: ```js function getTabId() { /* ... */} @@ -156,14 +151,14 @@ chrome.action.setBadgeText( ); ``` -If the `tabId` property is omitted, the setting is treated as a global setting. Tab-specific -settings take priority over any global settings. +If the `tabId` property is left out, the setting is treated as a global setting. Tab-specific +settings take priority over global settings. -## Enabled state +### Enabled state By default, toolbar actions are enabled (clickable) on every tab. You can control this using the `action.enable()` and `action.disable()` methods. This only affects whether the popup (if any) or -`action.onClicked` event is dispatched to your extension; it does not affect the action's presence +`action.onClicked` event is sent to your extension; it doesn't affect the action's presence in the toolbar. ## Examples @@ -248,19 +243,16 @@ chrome.action.onClicked.addListener((tab) => { alert('Hello, world!'); ``` -### Emulating pageActions with declarativeContent +### Emulate pageActions with declarativeContent -The chrome.action API replaced the [browserAction][api-browser-action] and -[pageAction][api-page-action] APIs in Manifest V3. By default, actions are similar to browser -actions, but it is possible to emulate the behavior of a page action using the action API. -This example shows how an extension's background logic can (a) disable the action by default and (b) +This example shows how an extension's background logic can (a) disable an action by default and (b) use [declarativeContent][api-declarative-content] to enable the action on specific sites. ```js // background.js -// Wrap in an onInstalled callback in order to avoid unnecessary work +// Wrap in an onInstalled callback to avoid unnecessary work // every time the background script is run chrome.runtime.onInstalled.addListener(() => { // Page actions are disabled by default and enabled on select tabs From e65d737c30f2b57593130688379025e270853186 Mon Sep 17 00:00:00 2001 From: Oliver Dunk <oliverdunk@google.com> Date: Wed, 25 Oct 2023 16:51:09 +0100 Subject: [PATCH 965/982] Update documentation on static ruleset limits (#7636) * Update documentation on static ruleset limits * Update site/en/docs/extensions/reference/declarativeNetRequest/index.md Co-authored-by: Joe Medley <jmedley@google.com> * Add comment on minimum_chrome_version --------- Co-authored-by: Joe Medley <jmedley@google.com> --- .../reference/declarativeNetRequest/index.md | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/site/en/docs/extensions/reference/declarativeNetRequest/index.md b/site/en/docs/extensions/reference/declarativeNetRequest/index.md index f30c4c48d..e7af049d8 100644 --- a/site/en/docs/extensions/reference/declarativeNetRequest/index.md +++ b/site/en/docs/extensions/reference/declarativeNetRequest/index.md @@ -211,7 +211,13 @@ rule you're using. #### Static rules {: #static-rules } -Static rules are those specified in rule files declared in the manifest file. An extension can specify up to 50 static [rulesets](#type-Ruleset) as part of the `"rule_resources"` manifest key, but only 10 of these rulesets can be enabled at a time. The latter is called the [`MAX_NUMBER_OF_ENABLED_STATIC_RULESETS`](#property-MAX_NUMBER_OF_ENABLED_STATIC_RULESETS). Collectively, those rulesets are guaranteed at least 30,000 rules. This is called the [`GUARANTEED_MINIMUM_STATIC_RULES`](#property-GUARANTEED_MINIMUM_STATIC_RULES). +Static rules are those specified in rule files declared in the manifest file. An extension can specify up to 100 static [rulesets](#type-Ruleset) as part of the `"rule_resources"` manifest key, but only 50 of these rulesets can be enabled at a time. The latter is called the [`MAX_NUMBER_OF_ENABLED_STATIC_RULESETS`](#property-MAX_NUMBER_OF_ENABLED_STATIC_RULESETS). Collectively, those rulesets are guaranteed at least 30,000 rules. This is called the [`GUARANTEED_MINIMUM_STATIC_RULES`](#property-GUARANTEED_MINIMUM_STATIC_RULES). + +{% Aside 'note' %} +Prior to Chrome 120, extensions were limited to a total of 50 static rulesets, and only 10 of these +could be enabled at the same time. Use the [`minimum_chrome_version`][minimum-chrome-version] +manifest field to limit which Chrome versions can install your extension. +{% endAside %} The number of rules available after that depends on how many rules are enabled by all the extensions installed on a user's browser. You can find this number at runtime by calling [`getAvailableStaticRuleCount()`](#method-getAvailableStaticRuleCount). You can see [an example of this](#update-static-rulesets) under [code examples](#code-examples). @@ -400,12 +406,4 @@ The following example removes all cookies from both a main frame and any sub fra "condition": { "resourceTypes": ["main_frame", "sub_frame"] } } ``` - - - - - - - - - +[minimum-chrome-version]: /docs/extensions/mv3/manifest/minimum_chrome_version/ From ddf2bbe34a0bd6b1806e8ba60ef6d9b5c6a2d048 Mon Sep 17 00:00:00 2001 From: Oliver Dunk <oliverdunk@google.com> Date: Wed, 25 Oct 2023 16:53:50 +0100 Subject: [PATCH 966/982] Mention Ephemeral mode in minimum_chrome_version docs (#7655) --- .../mv3/manifest/minimum_chrome_version/index.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/site/en/docs/extensions/mv3/manifest/minimum_chrome_version/index.md b/site/en/docs/extensions/mv3/manifest/minimum_chrome_version/index.md index c53bb6851..20b8d91eb 100644 --- a/site/en/docs/extensions/mv3/manifest/minimum_chrome_version/index.md +++ b/site/en/docs/extensions/mv3/manifest/minimum_chrome_version/index.md @@ -3,7 +3,7 @@ layout: "layouts/doc-post.njk" title: "Manifest - Minimum Chrome Version" seoTitle: "Chrome Extensions Manifest: minimum_chrome_version" date: 2013-05-12 -updated: 2023-02-14 +updated: 2023-10-25 description: Reference documentation for the minimum_chrome_version property of manifest.json. --- @@ -35,3 +35,11 @@ Existing users of your extension will not receive updates when the `minimum_chrome_version` is higher than their current browser version. This happens silently so you should exercise caution and consider ways of letting existing users know that they are no longer receiving updates. + +{% Aside 'note' %} +Chrome OS users using [ephemeral mode][ephemeral] are treated as new users each time they sign in. +This means that if they are using a Chrome version lower than the `minimum_chrome_version`, your +extension will not be installed. +{% endAside %} + +[ephemeral]: https://support.google.com/chrome/a/answer/3538894 From fd74c7295ebe73731290dd2fbfec381fe70517cd Mon Sep 17 00:00:00 2001 From: Chris Mills <chrisdavidmills@gmail.com> Date: Wed, 25 Oct 2023 19:03:08 +0100 Subject: [PATCH 967/982] Add notRestoredReasons empty case information (#7494) --- site/en/docs/web-platform/bfcache-notrestoredreasons/index.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/site/en/docs/web-platform/bfcache-notrestoredreasons/index.md b/site/en/docs/web-platform/bfcache-notrestoredreasons/index.md index 7bfbbb0ce..4c99862dd 100644 --- a/site/en/docs/web-platform/bfcache-notrestoredreasons/index.md +++ b/site/en/docs/web-platform/bfcache-notrestoredreasons/index.md @@ -99,8 +99,10 @@ The properties are as follows: `url` : A string representing the URL of the navigated page. +For `PerformanceNavigationTiming` objects that do not represent history navigations, the `notRestoredReasons` property will return `null`. This is useful for determining whether bfcache is not relevant to a particular navigation, as opposed to `notRestoredReasons` not being supported in which case it would return `undefined`. + {% Aside %} -For `PerformanceNavigationTiming` objects that do not represent history navigations, `PerformanceNavigationTiming.notRestoredReasons` will return `null`. This is useful for determining whether bfcache is not relevant to a particular navigation, as opposed to `notRestoredReasons` support not being enabled (in which case it would return `undefined`). +`notRestoredReasons` may return `null` despite the navigation type being reported as a back/forward navigation. These circumstances include duplicating a back/forward navigation in a new tab and restoring a back/forward navigation tab after a browser restart. In such cases, some browsers copy the navigation type from the original tab, but as these are not actually back/forward navigations, `notRestoredReasons` returns `null`. {% endAside %} ### Reporting bfcache blocking in same-origin frames From 7057a24e2d631bbf9b7b959fe80be8ffdebb6891 Mon Sep 17 00:00:00 2001 From: Travis Vander Hoop <vanderhoop@me.com> Date: Wed, 25 Oct 2023 12:03:30 -0600 Subject: [PATCH 968/982] Update index.md (#7436) tiny little baby typo --- site/en/articles/long-animation-frames/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/en/articles/long-animation-frames/index.md b/site/en/articles/long-animation-frames/index.md index 1d538554c..0fbb760c8 100644 --- a/site/en/articles/long-animation-frames/index.md +++ b/site/en/articles/long-animation-frames/index.md @@ -141,7 +141,7 @@ These timestamps allow the long animation frame to be divided into timings: </tr> <tr> <td>Render duration</td> - <td><code>syleAndLayoutStart - renderStart</code></td> + <td><code>styleAndLayoutStart - renderStart</code></td> </tr> <tr> <td>Work duration</td> From 460f622d01f73689668d7ae709f3b9355e65b77e Mon Sep 17 00:00:00 2001 From: nick-w-nick <43578531+nick-w-nick@users.noreply.github.com> Date: Wed, 25 Oct 2023 14:03:51 -0400 Subject: [PATCH 969/982] fixed complext typo (#7400) --- .../en/docs/extensions/reference/declarativeNetRequest/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/en/docs/extensions/reference/declarativeNetRequest/index.md b/site/en/docs/extensions/reference/declarativeNetRequest/index.md index e7af049d8..16032be3d 100644 --- a/site/en/docs/extensions/reference/declarativeNetRequest/index.md +++ b/site/en/docs/extensions/reference/declarativeNetRequest/index.md @@ -232,7 +232,7 @@ All types of rules can use regular expressions; however, the total number of reg Additionally, each rule must be less than 2KB once compiled. This roughly correlates with the complexity of the rule. If you try to load a rule that exceeds this limit, you will see a warning like the one below and the rule will be ignored. ```bash -rules_1.json: Rule with id 1 specified a more complext regex than allowed +rules_1.json: Rule with id 1 specified a more complex regex than allowed as part of the "regexFilter" key. ``` From 6eca68599941c84a3e2808d615fe589cd0cf8dfa Mon Sep 17 00:00:00 2001 From: Adam Argyle <argyle@google.com> Date: Wed, 25 Oct 2023 11:04:38 -0700 Subject: [PATCH 970/982] add section with links to other color level 5 posts (#7647) --- site/en/articles/high-definition-css-color-guide/index.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/site/en/articles/high-definition-css-color-guide/index.md b/site/en/articles/high-definition-css-color-guide/index.md index c6d7b426b..824ac5b9c 100644 --- a/site/en/articles/high-definition-css-color-guide/index.md +++ b/site/en/articles/high-definition-css-color-guide/index.md @@ -1688,3 +1688,7 @@ and interpolations and overall deliver a more colorful experience to your users. - [https://en.wikipedia.org/wiki/CIE_1931_color_space](https://en.wikipedia.org/wiki/CIE_1931_color_space) - [https://www.joshwcomeau.com/css/color-formats/](https://www.joshwcomeau.com/css/color-formats/) - [https://ciechanow.ski/color-spaces/](https://ciechanow.ski/color-spaces/) + +### Additional Color Level 5 articles +- [CSS relative color syntax](/blog/css-relative-color-syntax/) +- [CSS color-mix](/blog/css-color-mix/) From 47390aa155396f60c3258ec7870bf0fe5ef7f7a0 Mon Sep 17 00:00:00 2001 From: Adam Argyle <argyle@google.com> Date: Wed, 25 Oct 2023 11:18:35 -0700 Subject: [PATCH 971/982] migration from docs (#7660) --- .../css-prefers-reduced-transparency/index.md | 234 ++++++++++++++++++ 1 file changed, 234 insertions(+) create mode 100644 site/en/blog/css-prefers-reduced-transparency/index.md diff --git a/site/en/blog/css-prefers-reduced-transparency/index.md b/site/en/blog/css-prefers-reduced-transparency/index.md new file mode 100644 index 000000000..9a0f6c498 --- /dev/null +++ b/site/en/blog/css-prefers-reduced-transparency/index.md @@ -0,0 +1,234 @@ +--- +layout: layouts/blog-post.njk +title: CSS prefers-reduced-transparency +description: > + Optimize and adjust for users who prefer an opaque UI. +subhead: > + Optimize and adjust for users who prefer an opaque UI. +date: 2023-10-25 +authors: + - argyle +tags: + - css +hero: image/vS06HQ1YTsbMKSFTIPl2iogUQP73/3QaCdrr6JiX2JSVu2ZzY.png +thumb: image/vS06HQ1YTsbMKSFTIPl2iogUQP73/k83UEFvMkHOeSfB59cxU.png +alt: > + A window covered in rain drops has bright pink and blue blurry shapes beyond the glass that are likely neon lights but they can't be fully made out. +--- + +From Chrome 118 the new media query feature +[`prefers-reduced-transparency`](https://developer.mozilla.org/docs/Web/CSS/@media/prefers-reduced-transparency) +from [CSS Media Queries +5](https://www.w3.org/TR/mediaqueries-5/#prefers-reduced-transparency) is +available. Non-opaque interfaces can cause headaches or be a visual struggle for +various types of vision deficiencies. This is why [Windows, macOS and iOS have +system +preferences](https://psdtohtml.dev/ideas/accessibility-transparencies-css/#:~:text=How%20to%20activate%20transparency%20reduction) +that can reduce or remove transparency from the UI. + +{% BrowserCompat 'css.at-rules.media.prefers-reduced-transparency' %} + +With this new media query in the browser, CSS can adapt the interface for users +specifying a desire for reduced transparency: + +```css +.example { + --opacity: .5; + + background: hsl(200 100% 50% / var(--opacity)); + + @media (prefers-reduced-transparency: reduce) { + --opacity: .95; + } +} +``` + +In the preceding code example, a CSS variable holds an opacity value at `50%` +which is then used with HSL to create a semi-transparent blue background. The +[nested](/articles/css-nesting/) media query checks for a user preference for +reduced transparency, and when true, adjusts the opacity variable to `95%`, a +nearly opaque opacity value. + +This media query fits in well with the other preference media queries, which +enable designers and developers to be creative while also adjusting for users. +You can think of these media queries like a chair in a car that automatically +adjusts the position to the user; when a user visits your website, it +automatically adjusts to them without them asking. So cool. + +## Use cases for reducing transparency + +The next few sections will be devoted to showing moments and opportunities for +reducing transparency in meaningful ways. + +### Semi-transparent captions on images + +It's fairly common to overlay an image or video thumbnail with a +semi-transparent caption or summary. The following example illustrates one way +to handle a preference for reduced transparency. The overlay is entirely +removed, and the same caption contents displayed below the image instead of +overlaid. + +{% Codepen { + user: 'web-dot-dev', + id: 'mdvJjgN', + tab: 'result' +} %} + +### Transparent modals, notifications and popovers + +Another way that UI elements overlay content, which often means elements of +opacity are present, is with modals, notifications and popovers. In these cases, +boosting the opacity can respect the user preference while also still allowing a +subtle amount of color from behind the overlay to peek through. + +```css +.card { + background: hsl(none none 100% / 20%); + + @media (prefers-reduced-transparency: reduce) { + background: hsl(none none 0% / 80%); + } +} +``` + +{% Codepen { + user: 'web-dot-dev', + id: 'poGJZmP', + tab: 'result' +} %} + +### Adaptive frosted glass + +Another popular image overlay style is frosted glass. In the following example, +the image behind the caption is a mirror reflection of the product image. This +has a couple advantages: the image is not cropped and the light or dark +preference can come through a bit more in the end result. + +```css +.adaptive-glass { + --glass-lightness: 100%; + --glass-alpha: 50%; + + background: hsl(0 0% var(--glass-lightness) / var(--glass-alpha)); + backdrop-filter: blur(40px); + + @media (prefers-color-scheme: dark) { + --glass-lightness: 0%; + } + + @media (prefers-reduced-transparency: reduce) { + --glass-alpha: 85%; + } +} +``` + +{% Codepen { + user: 'web-dot-dev', + id: 'dyaojEa', + tab: 'result' +} %} + +### Hero header + +A common homepage element has a bold message overlaying a looping video or +animated image. The following example has a colorful semi-transparent gradient +overlay and an infinitely animating background image. While this may attract +many eyes, it will also create issues for many, due to low contrast with +transparency and motion that can't be controlled. + +{% Codepen { + user: 'web-dot-dev', + id: 'QWYbBXG', + tab: 'result' +} %} + +This can be fixed with two CSS media queries: +[prefers-reduced-motion](https://developer.mozilla.org/docs/Web/CSS/@media/prefers-reduced-motion) +and prefers-reduced-transparency. Within the reduced-motion media query you can +apply the infinite animation only if the user has "no-preference" for reduced +motion, signaling to the code that it's ok for this user to have motion. + +Furthermore, with the reduced-transparency media query, you can decrease the +opacity so the overlay color is nearly 100%. Now the message can be read easily +without a motion distraction or problematic contrast. + +{% Codepen { + user: 'web-dot-dev', + id: 'qBgdyzJ', + tab: 'result' +} %} + +Put it all together and you can deploy a creative UI look while also ensuring +the target audience can read it and get the message. + +```css +.Hero img { + @media (prefers-reduced-motion: no-preference) { + animation: zoom 30s ease infinite; + } +} + +.Hero .overlay { + background: hsl(none none 0% / 95%); + + @media (prefers-reduced-transparency: no-preference) { + background: linear-gradient( + to top right in oklab, + oklch(40% 0.3 340 / 70%), + oklch(40% 0.4 200 / 70%) + ); + } +} +``` + +{% Codepen { + user: 'web-dot-dev', + id: 'KKJpBOW', + tab: 'result' +} %} + +## Additive versus subtractive perspectives on user preferences + +The previous example didn't check these user preferences for their reduced +preference, instead it checks for no preference. + +```css +@media (prefers-reduced-transparency: no-preference) { + … +} +``` + +Developers and designers often "fallback" the user experience based on these +preferences, in a subtractive mentality. This manifests in the media queries as +a check for "reduce," at which point something from the UI is removed. The +example shows an additive mentality, where motion and transparency are added if +the user is ok with it. + +This approach helps you to think about a healthy baseline experience that's +sturdy on its own. Then, if it's ok with the user, add to the experience. + +## Devtools + +The Chrome DevTools can emulate this preference for reduced transparency (and +more) in the [Rendering tab](/docs/devtools/rendering/). In the following video +see how to toggle the prefers-color-scheme and prefers-reduced-transparency +media queries to showcase the light, dark, transparent and reduced transparency +variants of the frosted glass card. + +<figure> + + {% Video + src="video/vS06HQ1YTsbMKSFTIPl2iogUQP73/R2fJI7kj1edxSEjE2EG8.mp4", + width="800", + height="450", + autoplay="false", + loop="true", + muted="true", + controls="true" + %} + + <figcaption> + <a href="https://codepen.io/web-dot-dev/pen/dyaojxr">https://codepen.io/web-dot-dev/pen/dyaojxr</a> + </figcaption> + +</figure> From 615be88dddd6a9cb8b9855454089c3247acc570f Mon Sep 17 00:00:00 2001 From: Sid Sahoo <5680745+siddharth-sahoo@users.noreply.github.com> Date: Wed, 25 Oct 2023 11:38:25 -0700 Subject: [PATCH 972/982] Update index.md (#7487) * Update index.md Fixing errors in signal-to-noise ratio explanation for batching frequency and campaign variables section. * Update site/en/docs/privacy-sandbox/summary-reports/design-decisions/index.md Co-authored-by: Nancymic2 <nanmichell@gmail.com> * Update site/en/docs/privacy-sandbox/summary-reports/design-decisions/index.md Co-authored-by: Nancymic2 <nanmichell@gmail.com> --------- Co-authored-by: Nancymic2 <nanmichell@gmail.com> --- .../summary-reports/design-decisions/index.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/site/en/docs/privacy-sandbox/summary-reports/design-decisions/index.md b/site/en/docs/privacy-sandbox/summary-reports/design-decisions/index.md index ccac250a5..69f14d1a9 100644 --- a/site/en/docs/privacy-sandbox/summary-reports/design-decisions/index.md +++ b/site/en/docs/privacy-sandbox/summary-reports/design-decisions/index.md @@ -233,8 +233,10 @@ batching frequency is how often you process aggregatable reports. A report that is scheduled for aggregation more frequently (e.g. each hour) will have fewer conversion events included than the same report with a less frequent +aggregation schedule (e.g. each week). As a result, the hourly report will include more noise.``` +have fewer conversion events included than the same report with a less frequent aggregation schedule (e.g. each week). As a result, the hourly report will have -a higher signal-to-noise ratio than the weekly report, all else being equal. **Experiment with reporting requirements at various frequencies, and assess signal-to-noise ratios for each.** +a lower signal-to-noise ratio than the weekly report, all else being equal. **Experiment with reporting requirements at various frequencies, and assess signal-to-noise ratios for each.** Learn more in [Batching](/docs/privacy-sandbox/summary-reports/#batching) @@ -275,8 +277,8 @@ single-touch attributable conversions to the closest power of 10: 10, 100, conversion count PER BUCKET**. 1. Click **Simulate**. 1. Observe that the noise ratios are now higher: this is because when you - have fewer conversions per bucket, signal-to-noise ratios are likely to be - higher. + have fewer conversions per bucket, more noise is applied to maintain + privacy. {% endDetails %} {% endAside %} From b00b06f947d1d193da0bedc2f8b1898c9b85e56b Mon Sep 17 00:00:00 2001 From: Jecelyn Yeen <5917927+jecfish@users.noreply.github.com> Date: Thu, 26 Oct 2023 09:30:01 +0200 Subject: [PATCH 973/982] Add link to WebSQL deprecation trial (#7373) * Add link to WebSQL deprecation trial * Update site/en/blog/deprecating-web-sql/index.md * Update timeline --------- Co-authored-by: Thomas Steiner <steiner.thomas@gmail.com> Co-authored-by: Thomas Steiner <tomac@google.com> --- site/en/blog/deprecating-web-sql/index.md | 5 +++-- site/en/blog/web-sql-deprecation-timeline-updated/index.md | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/site/en/blog/deprecating-web-sql/index.md b/site/en/blog/deprecating-web-sql/index.md index 2206ec77c..c3b54d00b 100644 --- a/site/en/blog/deprecating-web-sql/index.md +++ b/site/en/blog/deprecating-web-sql/index.md @@ -79,11 +79,12 @@ and outperforms Web SQL in many cases. **Chromium 115** ({% ChromeDate '115' %}) and a warning message is shown in the Chrome DevTools Issue panel. - [📍 We are here.] A - [deprecation trial](/docs/web-platform/origin-trials/#deprecation-trials) to + [deprecation trial](/origintrials/#/view_trial/494270059103911937) to keep using Web SQL is available from **Chromium 117** ({% ChromeDate '117' %}) to **Chromium 123** ({% ChromeDate '123' %}). + To learn more about deprecation trials, see the linked section of the article [Get started with origin trials](/docs/web-platform/origin-trials/#deprecation-trials). - [🔮 In the future.] Web SQL access in **all contexts** is no longer available - in **Chromium 119** ({% ChromeDate '119' %}) + in **Chromium 119** ({% ChromeDate '119' %}). ## Where to go from here diff --git a/site/en/blog/web-sql-deprecation-timeline-updated/index.md b/site/en/blog/web-sql-deprecation-timeline-updated/index.md index db1039f14..4c424e371 100644 --- a/site/en/blog/web-sql-deprecation-timeline-updated/index.md +++ b/site/en/blog/web-sql-deprecation-timeline-updated/index.md @@ -40,10 +40,11 @@ removal in insecure contexts and eventually all contexts is planned for Chromium **Chromium 115** ({% ChromeDate '115' %}) and a warning message is shown in the Chrome DevTools Issue panel. - [📍 We are here.] A - [deprecation trial](/docs/web-platform/origin-trials/#deprecation-trials) to + [deprecation trial](/origintrials/#/view_trial/494270059103911937) to keep using Web SQL is available from **Chromium 117** ({% ChromeDate '117' %}) to **Chromium 123** ({% ChromeDate '123' %}). + To learn more about deprecation trials, see the linked section of the article [Get started with origin trials](/docs/web-platform/origin-trials/#deprecation-trials). - [🔮 In the future.] Web SQL access in **all contexts** is no longer available - in **Chromium 119** ({% ChromeDate '119' %}) + in **Chromium 119** ({% ChromeDate '119' %}). See the post [Deprecating and removing Web SQL](/blog/deprecating-web-sql/) for all details on this deprecation. From af5de4d88c521140a71728999aba35490b2f2220 Mon Sep 17 00:00:00 2001 From: Oliver Dunk <oliverdunk@google.com> Date: Thu, 26 Oct 2023 14:22:38 +0100 Subject: [PATCH 974/982] Replace Chrome OS with enterprise in description of ephemeral (#7664) --- .../extensions/mv3/manifest/minimum_chrome_version/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/en/docs/extensions/mv3/manifest/minimum_chrome_version/index.md b/site/en/docs/extensions/mv3/manifest/minimum_chrome_version/index.md index 20b8d91eb..b199eaf43 100644 --- a/site/en/docs/extensions/mv3/manifest/minimum_chrome_version/index.md +++ b/site/en/docs/extensions/mv3/manifest/minimum_chrome_version/index.md @@ -37,7 +37,7 @@ happens silently so you should exercise caution and consider ways of letting existing users know that they are no longer receiving updates. {% Aside 'note' %} -Chrome OS users using [ephemeral mode][ephemeral] are treated as new users each time they sign in. +Enterprise users using [ephemeral mode][ephemeral] are treated as new users each time they sign in. This means that if they are using a Chrome version lower than the `minimum_chrome_version`, your extension will not be installed. {% endAside %} From ae3bddecad9a9dafdd987353ccf288f1a527e98a Mon Sep 17 00:00:00 2001 From: Adam Argyle <argyle@google.com> Date: Thu, 26 Oct 2023 07:30:07 -0700 Subject: [PATCH 975/982] `patch` - adds note about the additive strategy and support timing (#7661) * adds note about the additive strategy and support timing * verbiage adjustment since the preceding paragraph includes the word baseline --- site/en/blog/css-prefers-reduced-transparency/index.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/site/en/blog/css-prefers-reduced-transparency/index.md b/site/en/blog/css-prefers-reduced-transparency/index.md index 9a0f6c498..424643c5d 100644 --- a/site/en/blog/css-prefers-reduced-transparency/index.md +++ b/site/en/blog/css-prefers-reduced-transparency/index.md @@ -207,6 +207,10 @@ the user is ok with it. This approach helps you to think about a healthy baseline experience that's sturdy on its own. Then, if it's ok with the user, add to the experience. +{% Aside 'important' %} +The additive strategy is best when there is good browser support. +{% endAside %} + ## Devtools The Chrome DevTools can emulate this preference for reduced transparency (and From c2c30b87b8a3f6fc7c43dee90d6a96502671b319 Mon Sep 17 00:00:00 2001 From: Oliver Dunk <oliverdunk@google.com> Date: Thu, 26 Oct 2023 16:03:45 +0100 Subject: [PATCH 976/982] Add What's New for Matt Frisbie interview video (#7666) * Add What's New for Matt Frisbie interview video * Update site/en/docs/extensions/whatsnew/index.md Co-authored-by: amysteamdev <37001393+AmySteam@users.noreply.github.com> --------- Co-authored-by: amysteamdev <37001393+AmySteam@users.noreply.github.com> --- site/en/docs/extensions/whatsnew/index.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/site/en/docs/extensions/whatsnew/index.md b/site/en/docs/extensions/whatsnew/index.md index 9538bc67d..89d0ec1a5 100644 --- a/site/en/docs/extensions/whatsnew/index.md +++ b/site/en/docs/extensions/whatsnew/index.md @@ -3,7 +3,7 @@ layout: 'layouts/doc-post.njk' title: What's new in Chrome extensions description: 'Recent changes to the Chrome extensions platform, documentation, and policy' date: 2021-02-25 -updated: 2023-10-17 +updated: 2023-10-26 tags: - extensions-news @@ -15,6 +15,13 @@ tags: Check this page often to learn about changes to Chrome extensions, extensions documentation, or related policy or other changes. You'll find other notices posted on the [Extensions Google Group](https://groups.google.com/a/chromium.org/g/chromium-extensions). The [Extensions News](/tags/extensions-news/) tag lists articles about some of the topics listed here. (It even has [an RSS feed](/feeds/extensions-news.xml).) The [Chrome schedule](https://chromiumdash.appspot.com/schedule) lists stable and beta release dates. +### Video: A chat with Matt Frisbie {: #video-interview-oct-23 } + +<p class="color-secondary-text type--caption">Posted on <time>October 26, 2023</time></p> + +We've just published a new video on the Chrome for Developers YouTube channel chatting with Google Developer Expert and author Matt Frisbie. Watch it +[here](https://www.youtube.com/watch?v=8P-Sc8ZaViY). + ### New guidance on testing extensions {: #testing-guidance-oct-23 } <p class="color-secondary-text type--caption">Posted on <time>October 23, 2023</time></p> From 392c0a78f1368ee051892e50ed5bcf66f3af01b5 Mon Sep 17 00:00:00 2001 From: wizardofdocs <83661258+wizardofdocs@users.noreply.github.com> Date: Thu, 26 Oct 2023 09:19:37 -0700 Subject: [PATCH 977/982] Updated Messaging page (#7343) * Updated Messaging page Cleaned up phrasing, removed some confusing don'ts * Update site/en/docs/extensions/mv3/messaging/index.md Updated phrasing for MV3 Co-authored-by: amysteamdev <37001393+AmySteam@users.noreply.github.com> * Update site/en/docs/extensions/mv3/messaging/index.md Fixed grammar Co-authored-by: Joe Medley <jmedley@google.com> * Update site/en/docs/extensions/mv3/messaging/index.md Removed comment with answered question Co-authored-by: Joe Medley <jmedley@google.com> * Update site/en/docs/extensions/mv3/messaging/index.md Updated link Co-authored-by: Joe Medley <jmedley@google.com> * Update site/en/docs/extensions/mv3/messaging/index.md Fixed grammar Co-authored-by: Joe Medley <jmedley@google.com> * Update site/en/docs/extensions/mv3/messaging/index.md Updated phrasing Co-authored-by: Joe Medley <jmedley@google.com> * Update site/en/docs/extensions/mv3/messaging/index.md Fixed code formatting Co-authored-by: Joe Medley <jmedley@google.com> * Update site/en/docs/extensions/mv3/messaging/index.md Fixed syntax Co-authored-by: Joe Medley <jmedley@google.com> * Update site/en/docs/extensions/mv3/messaging/index.md Fixed code formatting Co-authored-by: Joe Medley <jmedley@google.com> * Update site/en/docs/extensions/mv3/messaging/index.md Fixed code formatting Co-authored-by: Joe Medley <jmedley@google.com> * Update site/en/docs/extensions/mv3/messaging/index.md Fixed code formatting Co-authored-by: Joe Medley <jmedley@google.com> * Update site/en/docs/extensions/mv3/messaging/index.md Fixed code formatting Co-authored-by: Joe Medley <jmedley@google.com> * Update site/en/docs/extensions/mv3/messaging/index.md fixed code formatting Co-authored-by: Joe Medley <jmedley@google.com> * Update site/en/docs/extensions/mv3/messaging/index.md fixed code formatting Co-authored-by: Joe Medley <jmedley@google.com> * Update site/en/docs/extensions/mv3/messaging/index.md Fixed code formatting Co-authored-by: Joe Medley <jmedley@google.com> * Small grammar fix to Messaging page * Update site/en/docs/extensions/mv3/messaging/index.md Fixed code formatting Co-authored-by: Joe Medley <jmedley@google.com> * Update site/en/docs/extensions/mv3/messaging/index.md Fixed code formatting Co-authored-by: Joe Medley <jmedley@google.com> * Update site/en/docs/extensions/mv3/messaging/index.md Fixed code formatting Co-authored-by: Joe Medley <jmedley@google.com> * Update site/en/docs/extensions/mv3/messaging/index.md Fixed code formatting Co-authored-by: Joe Medley <jmedley@google.com> * Update site/en/docs/extensions/mv3/messaging/index.md Fixed code formatting Co-authored-by: Joe Medley <jmedley@google.com> * Updated code samples on Messaging page * Added comparison labels to XSS section in Messaging doc * Updated list formatting on Messaging page * Update site/en/docs/extensions/mv3/messaging/index.md Updated wording Co-authored-by: amysteamdev <37001393+AmySteam@users.noreply.github.com> * Update site/en/docs/extensions/mv3/messaging/index.md Updated wording Co-authored-by: Joe Medley <jmedley@google.com> * Updated XSS warning on Messaging page * Update site/en/docs/extensions/mv3/messaging/index.md --------- Co-authored-by: amysteamdev <37001393+AmySteam@users.noreply.github.com> Co-authored-by: Joe Medley <jmedley@google.com> --- .../en/docs/extensions/mv3/messaging/index.md | 226 +++++++++--------- 1 file changed, 112 insertions(+), 114 deletions(-) diff --git a/site/en/docs/extensions/mv3/messaging/index.md b/site/en/docs/extensions/mv3/messaging/index.md index dee650522..e096320c0 100644 --- a/site/en/docs/extensions/mv3/messaging/index.md +++ b/site/en/docs/extensions/mv3/messaging/index.md @@ -3,31 +3,40 @@ layout: "layouts/doc-post.njk" title: "Message passing" seoTitle: "Chrome Extensions Message passing" date: 2012-09-18 -updated: 2023-02-22 +updated: 2023-09-22 description: How to pass messages between extensions and content scripts. --- -Since content scripts run in the context of a web page and not the extension, they often need some -way of communicating with the rest of the extension. For example, an RSS reader extension might use -content scripts to detect the presence of an RSS feed on a page, then notify the background page in -order to display a page action icon for that page. - -Communication between extensions and their content scripts works by using message passing. Either -side can listen for messages sent from the other end, and respond on the same channel. A message can -contain any valid JSON object (null, boolean, number, string, array, or object). There is a simple -API for [one-time requests][section-one-time] and a more complex API for [long-lived -connections][section-long] to exchange multiple messages within shared context. It is also possible to send -a message to another extension if you know its ID. That is covered in the [cross-extension -messages][section-external] section. - -## Simple one-time requests {: #simple } +Because content scripts run in the context of a web page, not the extension that runs them, +they often need ways to communicate with the rest of the extension. For example, an RSS +reader extension might use content scripts to detect the presence of an RSS feed on a page, +then notify the service worker to display an action icon for that page. + +This communication uses message passing, which allows both extensions and content scripts to +listen for each other's messages and respond on the same channel. A message can +contain any valid JSON object (null, boolean, number, string, array, or object). There are +two message passing APIs: one for [one-time requests][section-one-time], and a more complex one +for [long-lived connections][section-long] that allow multiple messages to be sent. For information +about sending messages between extensions, see the [cross-extension messages][section-external] section. + +## One-time requests {: #simple } + +To send a single message to another part of your extension, and optionally get a +response, call [`runtime.sendMessage()`][runtime-send-msg] or [`tabs.sendMessage()`][tabs-send-msg]. +These methods let you send a one-time JSON-serializable message from a content script to the +extension, or from the extension to a content script. To handle the response, use the returned +promise. For backward compatibility with older extensions, you can instead pass a callback as +the last argument. You can't use a promise and a callback in the same call. + +{% Aside 'caution' %} +If you use callbacks, the `sendResponse()` callback is only valid if used synchronously, +or if the event handler returns `true` to indicate that it will respond asynchronously. +The `sendMessage()` function's callback is automatically invoked if no handlers return +`true` or if the `sendResponse()` callback is garbage-collected. +{% endAside %} -If you only need to send a single message to another part of your extension (and optionally get a -response back), use the simplified [`runtime.sendMessage()`][runtime-send-msg] method or [`tabs.sendMessage()`][tabs-send-msg] -method. This lets you send a one-time JSON-serializable message from a content script to the -extension, or vice versa. To handle the response, use the returned Promise. For backward -compatibility, you can alternatively pass a callback as the last argument. You cannot use both a -promise and a callback. +For information on using promises, see [Promises on MDN][mdn-promise]. For information on converting +callbacks to promises and for using them in extensions, see [our promises documentation][doc-promises]. Sending a request from a content script looks like this: @@ -41,9 +50,8 @@ Sending a request from a content script looks like this: })(); ``` -Sending a request from the extension to a content script is similar, except that you need to -specify which tab to send it to. This example demonstrates sending a message to the content script -in the selected tab. +To send a request from an extension to a content script, specify which tab the request +applies to, as in the following example: {% Label %}service-worker.js{% endLabel %} @@ -56,8 +64,8 @@ in the selected tab. })(); ``` -On the receiving end, you need to set up an [runtime.onMessage][runtime-on-msg] event listener to handle the -message. This looks the same from a content script or extension page. +To receive the message, set up a [`runtime.onMessage`][runtime-on-msg] event listener. These +use the same code in both extensions and content scripts: {% Label %}content-script.js or service-worker.js:{% endLabel %} @@ -73,40 +81,30 @@ chrome.runtime.onMessage.addListener( ); ``` -In the above example, `sendResponse()` was called synchronously. If you want to asynchronously use -`sendResponse()`, add `return true;` to the `onMessage` event handler. +In the above example, `sendResponse()` was called synchronously. To use `sendResponse()` +asynchronously, add `return true;` to the `onMessage` event handler. -{% Aside %} If multiple pages are listening for `onMessage` events, only the first to call `sendResponse()` for a particular event will succeed in sending the response. All other responses to that event will be ignored. -{% endAside %} - -For new extensions you should prefer promises over callbacks. If you're using callbacks, the -`sendResponse()` callback is only valid if used synchronously, or if the event handler returns -`true` to indicate that it will respond asynchronously. The `sendMessage()` function's callback -will be invoked automatically if no handlers return true or if the `sendResponse()` callback is -garbage-collected. - -For information on using promises, see [Promises on MDN][mdn-promise]. For information on converting -callbacks to promises and for using them in extensions, see [our own article][doc-promises]. ## Long-lived connections {: #connect } -Sometimes it's useful to have a conversation that lasts longer than a single request and response. -In this case, you can open a long-lived channel from your content script to an extension page or -vice versa using [runtime.connect][runtime-connect] or [tabs.connect][tabs-connect], respectively. The channel can -optionally have a name, allowing you to distinguish between different types of connections. +To create a reusable long-lived message passing channel, call [`runtime.connect()`][runtime-connect] +to pass messages from a content script to an extension page, or [`tabs.connect()`][tabs-connect] +to pass messages from an extension page to a content script. You can name your channel to +distinguish between different types of connections. -One use case might be an automatic form filling extension. The content script could open a channel to -the extension page for a particular login, and send a message to the extension for each input -element on the page to request the form data to fill in. The shared connection allows the extension -to keep shared state linking the messages coming from the content script. +One potential use case for a long-lived connection is an automatic form-filling extension. +The content script might open a channel to the extension page for a specific login, and +send a message to the extension for each input element on the page to request the form +data to fill in. The shared connection allows the extension to keep shared state +linking the messages coming from the content script. <!--What is shared state linking? Can we make that make more sense?--> -When establishing a connection, each end is given a [runtime.Port][runtime-port] object which is used for +When establishing a connection, each end is assigned a [runtime.Port][runtime-port] object for sending and receiving messages through that connection. -Here is how you open a channel from a content script, and send and listen for messages: +Use the following code to open a channel from a content script, and send and listen for messages: {% Label %}content-script.js:{% endLabel %} @@ -121,15 +119,13 @@ port.onMessage.addListener(function(msg) { }); ``` -Sending a request from the extension to a content script is similar, except that you need to -specify which tab to connect to. Simply replace the call to connect in the above example with -[tabs.connect()][tabs-connect]. +To send a request from the extension to a content script, replace the call to `runtime.connect()` +in the previous example with [`tabs.connect()`][tabs-connect]. -To handle incoming connections, you need to set up a [runtime.onConnect()][runtime-on-connect] event -listener. This looks the same from a content script or an extension page. When another part of your -extension calls `connect()`, this event is fired, along with the [runtime.Port][runtime-port] object you can -use to send and receive messages through the connection. Here's what it looks like to respond to -incoming connections: +To handle incoming connections for either a content script or an extension page, set +up a [`runtime.onConnect`][runtime-on-connect] event listener. When another part of your +extension calls `connect()`, it activates this event and the [`runtime.Port`][runtime-port] +object. The code for responding to incoming connections looks like this: {% Label %}service-worker.js:{% endLabel %} @@ -149,44 +145,43 @@ chrome.runtime.onConnect.addListener(function(port) { ### Port lifetime {: #port-lifetime } -Ports are designed as a two-way communication method between different parts of the extension, where -a (top-level) frame is viewed as the smallest part. -Upon calling [tabs.connect()][tabs-connect], [runtime.connect()][runtime-connect] or [runtime.connectNative()][runtime-connect-native], a [Port][runtime-port] -is created. This port can immediately be used for sending messages to the other end via -[postMessage()][runtime-post-msg]. +Ports are designed as a two-way communication method between different parts of the extension. A top-level frame is the smallest part of an extension that can use a port. +When part of an extension calls [`tabs.connect()][tabs-connect`], [`runtime.connect()`][runtime-connect] or [`runtime.connectNative()`][runtime-connect-native], it creates a [Port][runtime-port] that can immediately +send messages using [`postMessage()`][runtime-post-msg]. -If there are multiple frames in a tab, calling [tabs.connect()][tabs-connect] results in multiple invocations of -the [runtime.onConnect][runtime-on-connect] event, once for each frame in the tab. Similarly, if -[runtime.connect()][runtime-connect] is called, then the onConnect event may be fired multiple times, once for every +If there are multiple frames in a tab, calling [`tabs.connect()`][tabs-connect] invokes +the [`runtime.onConnect`][runtime-on-connect] event once for each frame in the tab. Similarly, if +[`runtime.connect()`][runtime-connect] is called, then the `onConnect` event can fire once for every frame in the extension process. -You may want to find out when a connection is closed, for example if you are maintaining separate -state for each open port. For this listen to the [runtime.Port.onDisconnect][runtime-on-disconnect] event. This -event is fired when there are no valid ports at the other side of the channel. This happens in the -following situations: +You might want to find out when a connection is closed, for example if you're maintaining separate +states for each open port. To do this, listen to the [`runtime.Port.onDisconnect`][runtime-on-disconnect] event. This +event fires when there are no valid ports at the other end of the channel, which can have any of the following causes: - There are no listeners for [runtime.onConnect][runtime-on-connect] at the other end. - The tab containing the port is unloaded (for example, if the tab is navigated). - The frame where `connect()` was called has unloaded. - All frames that received the port (via [runtime.onConnect][runtime-on-connect]) have unloaded. -- [runtime.Port.disconnect()][runtime-port-disconnect] is called by _the other end_. Note that if a `connect()` call results - in multiple ports at the receiver's end, and `disconnect()` is called on any of these ports, then - the `onDisconnect` event is only fired at the port of the sender, and not at the other ports. +- [`runtime.Port.disconnect()`][runtime-port-disconnect] is called by _the other end_. If a + `connect()` call results in multiple ports at the receiver's end, and `disconnect()` is called + on any of these ports, then the `onDisconnect` event only fires at the sending port, not at the + other ports. ## Cross-extension messaging {: #external } In addition to sending messages between different components in your extension, you can use the -messaging API to communicate with other extensions. This lets you expose a public API that other -extensions can take advantage of. +messaging API to communicate with other extensions. This lets you expose a public API for other +extensions to use. -Listening for incoming requests and connections is similar to the internal case, except you use the -[runtime.onMessageExternal][runtime-on-msg-ext] or [runtime.onConnectExternal][runtime-on-connect-ext] methods. Here's an example of +To listen for incoming requests and connections from other extensions, use the +[`runtime.onMessageExternal`][runtime-on-msg-ext] +or [`runtime.onConnectExternal`][runtime-on-connect-ext] methods. Here's an example of each: {% Label %}service-worker.js{% endLabel %} ```js -// For simple requests: +// For a single request: chrome.runtime.onMessageExternal.addListener( function(request, sender, sendResponse) { if (sender.id === blocklistedExtension) @@ -207,9 +202,7 @@ chrome.runtime.onConnectExternal.addListener(function(port) { }); ``` -Likewise, sending a message to another extension is similar to sending one within your extension. -The only difference is that you must pass the ID of the extension you want to communicate with. For -example: +To send a message to another extension, pass the ID of the extension you want to communicate with as follows: {% Label %}service-worker.js{% endLabel %} @@ -217,7 +210,7 @@ example: // The ID of the extension we want to talk to. var laserExtensionId = "abcdefghijklmnoabcdefhijklmnoabc"; -// Make a simple request: +// For a simple request: chrome.runtime.sendMessage(laserExtensionId, {getTargetData: true}, function(response) { if (targetInRange(response.targetData)) @@ -225,16 +218,17 @@ chrome.runtime.sendMessage(laserExtensionId, {getTargetData: true}, } ); -// Start a long-running conversation: +// For a long-lived connection: var port = chrome.runtime.connect(laserExtensionId); port.postMessage(...); ``` -## Sending messages from web pages {: #external-webpage } +## Send messages from web pages {: #external-webpage } -As with [cross-extension messaging][section-external], your extension can receive and respond to -messages from regular web pages. To use this feature, you must first specify in your `manifest.json` -which websites you want to communicate with using [`"externally_connectable"`][43]. For example: +Extensions can also receive and respond to messages from other webpages, but can't send messages +to webpages. To send messages from a webpage to an extension, +specify in your `manifest.json` which websites you want to communicate with using [`"externally +connectable"`][43]. For example: {% Label %}manifest.json{% endLabel %} @@ -246,9 +240,9 @@ which websites you want to communicate with using [`"externally_connectable"`][4 This exposes the messaging API to any page that matches the URL patterns you specify. The URL pattern must contain at least a [second-level domain][wiki-second-level]; that is, hostname patterns such as "\*", -"\*.com", "\*.co.uk", and "\*.appspot.com" are prohibited. From the web page, use the -[runtime.sendMessage()][runtime-send-msg] or [runtime.connect()][runtime-connect] APIs to send a message to a specific app or -extension. For example: +"\*.com", "\*.co.uk", and "\*.appspot.com" are not supported. +[`runtime.sendMessage()`][runtime-send-msg] or [`runtime.connect()`][runtime-connect] APIs to send +a message to a specific app or extension. For example: {% Label %}webpage.js{% endLabel %} @@ -264,9 +258,9 @@ chrome.runtime.sendMessage(editorExtensionId, {openUrlInEditor: url}, }); ``` -From your extension, you may listen to messages from web pages via the -[runtime.onMessageExternal][runtime-on-msg-ext] or [runtime.onConnectExternal][runtime-on-connect-ext] APIs, similar to [cross-extension -messaging][section-external]. Only the web page can initiate a connection. Here is an example: +From your extension, listen to messages from web pages using the +[`runtime.onMessageExternal`][runtime-on-msg-ext] or [`runtime.onConnectExternal`][runtime-on-connect-ext] +APIs as in [cross-extension messaging][section-external]. Here's an example: {% Label %}service-worker.js{% endLabel %} @@ -289,59 +283,63 @@ Extensions [can exchange messages][native-client] with native applications that ### Content scripts are less trustworthy {: #content-scripts-are-less-trustworthy } -[Content scripts are less trustworthy][security-cs] than the extension service worker (for example, a malicious web -page might be able to compromise the renderer process where the content scripts run). Assume that -messages from a content script might have been crafted by an attacker and make sure to [validate and -sanitize all input][security-santize]. Assume any data sent to the content script might leak to the web page. +[Content scripts are less trustworthy][security-cs] than the extension service worker. +For example, a malicious webpage might be able to compromise the rendering process that +runs the content scripts. Assume that messages from a content script might have been +crafted by an attacker and make sure to [validate and sanitize all input][security-santize]. +Assume any data sent to the content script might leak to the web page. Limit the scope of privileged actions that can be triggered by messages received from content scripts. ### Cross-site scripting {: #cross-site-scripting } -When receiving a message from a content script or another extension, your scripts should be careful -not to fall victim to [cross-site scripting][wiki-cross-site]. This advice applies to scripts running inside the -extension background page as well as to content scripts running inside other web origins. -Specifically, avoid using dangerous APIs such as the ones below: +Make sure to protect your scripts against [cross-site scripting][wiki-cross-site]. When receiving data from an untrusted source such as user input, other websites through a content script, or an API, take care to avoid interpreting this as HTML or using it in a way which could allow unexpected code to run. -{% Label %}content-script.js or service-worker.js{% endLabel %} +{% Compare 'better', 'Safer methods' %} +Use APIs that don't run scripts whenever possible: + +{% Label %}service-worker.js{% endLabel %} ```js chrome.tabs.sendMessage(tab.id, {greeting: "hello"}, function(response) { - // WARNING! Might be evaluating an evil script! - var resp = eval("(" + response.farewell + ")"); + // JSON.parse doesn't evaluate the attacker's scripts. + var resp = JSON.parse(response.farewell); }); ``` -{% Label %}content-script.js or service-worker.js{% endLabel %} +{% Label %}service-worker.js{% endLabel %} ```js chrome.tabs.sendMessage(tab.id, {greeting: "hello"}, function(response) { - // WARNING! Might be injecting a malicious script! - document.getElementById("resp").innerHTML = response.farewell; + // innerText does not let the attacker inject HTML elements. + document.getElementById("resp").innerText = response.farewell; }); ``` +{% endCompare %} -Instead, prefer safer APIs that do not run scripts: +{% Compare 'worse', 'Unsafe methods' %} +Avoid using the following methods that make your extension vulnerable: -{% Label %}content-script.js or service-worker.js{% endLabel %} +{% Label %}service-worker.js{% endLabel %} ```js chrome.tabs.sendMessage(tab.id, {greeting: "hello"}, function(response) { - // JSON.parse does not evaluate the attacker's scripts. - var resp = JSON.parse(response.farewell); + // WARNING! Might be evaluating a malicious script! + var resp = eval(`(${response.farewell})`); }); ``` -{% Label %}content-script.js or service-worker.js{% endLabel %} +{% Label %}service-worker.js{% endLabel %} ```js chrome.tabs.sendMessage(tab.id, {greeting: "hello"}, function(response) { - // innerText does not let the attacker inject HTML elements. - document.getElementById("resp").innerText = response.farewell; + // WARNING! Might be injecting a malicious script! + document.getElementById("resp").innerHTML = response.farewell; }); ``` +{% endCompare %} -[doc-promises]: /docs/extensions/mv3/promises/ +[doc-promises]: /docs/extensions/mv3/promises/#compare-to-callback [mdn-promise]: https://developer.mozilla.org/docs/Learn/JavaScript/Asynchronous/Promises [native-client]: /docs/extensions/mv3/nativeMessaging/#native-messaging-client [native-host]: /docs/extensions/mv3/nativeMessaging/#native-messaging-host From b6b29da69b8132f47f26df1e757dbc507e661b3f Mon Sep 17 00:00:00 2001 From: amysteamdev <37001393+AmySteam@users.noreply.github.com> Date: Thu, 26 Oct 2023 11:47:30 -0500 Subject: [PATCH 978/982] Split CWS Manage Store listing (#7648) * Split check-review * support users first draft * Final draft and toc * Remove manage page * Update links to new sections. Update screenshots * Update metrics sections * FIx image * Apply suggestions from editorial review Co-authored-by: Joe Medley <jmedley@google.com> --------- Co-authored-by: Joe Medley <jmedley@google.com> --- site/_data/docs/webstore/toc.yml | 4 +- .../extensions/migrating/publish-mv3/index.md | 2 +- site/en/docs/webstore/check-review/index.md | 74 ++++++ .../webstore/cws-dashboard-listing/index.md | 37 +-- site/en/docs/webstore/manage/index.md | 224 ------------------ site/en/docs/webstore/metrics/index.md | 60 +++++ site/en/docs/webstore/support-users/index.md | 136 +++++++++++ 7 files changed, 296 insertions(+), 241 deletions(-) create mode 100644 site/en/docs/webstore/check-review/index.md delete mode 100644 site/en/docs/webstore/manage/index.md create mode 100644 site/en/docs/webstore/metrics/index.md create mode 100644 site/en/docs/webstore/support-users/index.md diff --git a/site/_data/docs/webstore/toc.yml b/site/_data/docs/webstore/toc.yml index d8dcef94c..c4aaaebae 100644 --- a/site/_data/docs/webstore/toc.yml +++ b/site/_data/docs/webstore/toc.yml @@ -15,9 +15,11 @@ - url: /docs/webstore/set-up-account/ - url: /docs/webstore/prepare/ - url: /docs/webstore/publish/ - - url: /docs/webstore/manage/ - url: /docs/webstore/update/ - url: /docs/webstore/review-process/ + - url: /docs/webstore/check-review/ + - url: /docs/webstore/support-users/ + - url: /docs/webstore/metrics - url: /docs/webstore/google-analytics/ - url: /docs/webstore/troubleshooting/ - url: /docs/webstore/branding/ diff --git a/site/en/docs/extensions/migrating/publish-mv3/index.md b/site/en/docs/extensions/migrating/publish-mv3/index.md index 9486ba080..28da204fa 100644 --- a/site/en/docs/extensions/migrating/publish-mv3/index.md +++ b/site/en/docs/extensions/migrating/publish-mv3/index.md @@ -172,4 +172,4 @@ To stay on top of user feedback you can add a link to a [dedicated support site] [migration-checklist]: /docs/extensions/migrating/checklist/ [review-factors]: /docs/webstore/review-process/#review-time-factors [spam-policy]: /docs/webstore/troubleshooting/#spam -[support-site]: /docs/webstore/manage/#dedicated-support-site +[support-site]: /docs/webstore/support-users/#provide-user-support diff --git a/site/en/docs/webstore/check-review/index.md b/site/en/docs/webstore/check-review/index.md new file mode 100644 index 000000000..d112ac9d9 --- /dev/null +++ b/site/en/docs/webstore/check-review/index.md @@ -0,0 +1,74 @@ +--- +layout: "layouts/doc-post.njk" +title: "Check on your review status" +date: 2021-08-17 +updated: 2023-03-27 +description: > + How to check the review status of your Chrome Web Store item. +--- + +After [publishing][publish] your extension for the first time or [uploading][update] a new version, your item will go +through a [review process][cws-review]. This page describes the how to check the status of your item . + +## The lifecycle of a Chrome Web Store item + +All Chrome Web Store items go through an automated [review process][cws-review]. In some instances, a manual review +is required, especially when sensitive permissions are requested. For this reason, review times +and/or approval times can take longer. Since a Chrome Web Store item goes through several stages, +it's important to keep track of your item's status. See the lifecycle diagram below: + +{% Img src="image/BhuKGJaIeLNPW9ehns59NfwqKxF2/yakIoAzWEchO8urosQLs.png", alt="Diagram of the lifecycle of a Chrome Web Store item", width="800", height="177" %} + +## Check your item's status + +The review status of your item appears in the [developer dashboard][dev-dashboard] next to each item. The +status can be Published, Pending, Rejected, or Taken Down. + +{% Img src="image/BhuKGJaIeLNPW9ehns59NfwqKxF2/bUbtISU01bab8WyWqonX.png", alt="Developer dashboard +status types", width="800", height="221" %} + +To stay informed of your item's status, you can: + +- **Enable email notifications**. There are mandatory emails like take down or rejection + notifications that are enabled by default. To receive notification when your item is published or + staged, you can enable email notifications on the Account page. + + {% Img src="image/BhuKGJaIeLNPW9ehns59NfwqKxF2/FgPIwRl3QEbNowNV1zRn.png", alt="How to enable + email notifications", width="658", height="219" %} + +- **Check your publisher email**. After enabling email notifications check your inbox often. To + ensure that CWS emails don't get flagged as Spam, add **chromewebstore-noreply@google.com** to + your contacts so that you receive all communications in a timely manner. + + +## Follow-up on rejections and takedowns + +If your extension has been determined to violate one or more terms or policies, you will receive an +email notification that contains the violation description and instructions on how to rectify it. + +If you did not receive an email within a week, check the status of your item (described above). If your item has +been rejected, you can see the details on the **Status tab** of your item. + +{% Img src="image/BhuKGJaIeLNPW9ehns59NfwqKxF2/C4wpnEeMriI9YeDAMDIr.png", alt="The Chrome Web Store +Status Tab", width="700", height="276" %} + +If you have been informed about a violation and you do not rectify it, your item will be taken down. See +[Violation enforcement][enforcement] for more details. + +{% Aside %} + +To request further clarification on the reasons for the takedown or to appeal the decision, +contact [Chrome Web Store Developer Support][cws-support]. For more examples and instructions on how +you can remedy the problem check the [Troubleshooting guide][troubleshooting]. + +{% endAside %} + +[cws-review]: /docs/webstore/review-process/ +[cws-support]: https://support.google.com/chrome_webstore/contact/dev_account_transfer +[dev-dashboard]: https://chrome.google.com/webstore/devconsole +[dev-policies]: /docs/webstore/program-policies +[publish]: /docs/webstore/publish +[update]: /docs/webstore/update +[enforcement]: /docs/webstore/review-process/#enforcement +[troubleshooting]: /docs/webstore/troubleshooting/ +[whats-new]: /docs/extensions/whatsnew/ diff --git a/site/en/docs/webstore/cws-dashboard-listing/index.md b/site/en/docs/webstore/cws-dashboard-listing/index.md index 9b330f8b0..67262cba5 100644 --- a/site/en/docs/webstore/cws-dashboard-listing/index.md +++ b/site/en/docs/webstore/cws-dashboard-listing/index.md @@ -46,7 +46,7 @@ At a minimum, you should provide the following promotional images: ### Learning more about images and branding -See [Supplying Images][cws-images] for help on designing the images for your item, and [Branding +See [Supplying Images][cws-images] for help designing the images for your item, and [Branding Guidelines][cws-branding] for information on how you can use Google brands. {% Aside %} @@ -60,16 +60,18 @@ You can include any of these optional links related to your item. ### Displaying your verified publisher status -The Chrome Web Store highlights verified publishers by placing a linked, official URL in the -"Offered by:" line of the store listing. This official URL appears under the listing title and is +The Chrome Web Store highlights verified publishers by placing a linked, official URL under the listing title and is linked to the website, as shown in the following example: -{% Img src="image/SHhb2PDKzXTggPGAYpv8JgR81pX2/Vkm8Uhstw2NFVSSt87Vl.png", alt="Offered by: -cecerduino.com example", width="351", height="143" %} +<figure> +{% Img src="image/BhuKGJaIeLNPW9ehns59NfwqKxF2/YEoohoq7YjMrpmkLtGMD.png", alt="Official URL in Chrome Web Store item page", width="348", height="230" %} + <figcaption> + Official URL in Chrome Web Store item page + </figcaption> +</figure> {% Aside %} -If you are not a verified publisher, you can't display this official URL: instead, the "Offered by:" -displays your publisher name instead. +If you are not a verified publisher, your publisher name will be displayed under the "Offered by:" in the **Details** section of your store listing. {% endAside %} To display your verified status, choose an official URL for your item from the **Official URL** @@ -85,16 +87,22 @@ more details. ### Adding a homepage URL {: #home-url } -To explain how your extension works in more detail, you can provide a direct link to your extension's website in the **Homepage URL**. This link appears under the Additional information of your item. - -{% Img src="image/BhuKGJaIeLNPW9ehns59NfwqKxF2/j71L391YIhEAIZTVUuBw.png", alt="Homepage URL in Chrome Web Store item page", width="306", height="106" %} +To explain how your extension works in more detail, you can provide a direct link to your extension's website in the **Homepage URL**. This link appears under the **Details** section of your item. ### Providing a support URL {: #support-url } -The Chrome Web Store provides a [built in user support][support-tab] experience under your items' **Support tab**, but you can use -a [dedicated support site][support-site] by including a link in the **Support URL**. +You can direct users to a dedicated support site by including a link in the **Support URL**. + +<figure> + {% Img src="image/BhuKGJaIeLNPW9ehns59NfwqKxF2/KsZdITw3oTNYnaoa4M8b.png", alt="Store listing support section linking to external support site", width="500", height="140" %} + <figcaption> + Store listing support section linking to an external support site. + </figcaption> +</figure> + +The Chrome Web Store also provides a built-in user support experience under your items' **Support hub**. See [Manage user feedback][user-support] to learn more. -### Enabling Mature Content {: #mature-content} +### Enabling Mature Content {: #mature-content } Content ratings help users know whether your extension and its content are mature in nature. See [Mature Content Guidelines][mature-guidelines] to determine whether your extension should be rated @@ -123,6 +131,5 @@ If you haven't done so yet, complete your listing by [keyword-spam]: /docs/webstore/spam-faq/#keyword-spam [mature-guidelines]: /docs/webstore/rating/ [privacy]: /docs/webstore/cws-dashboard-privacy -[support-tab]: /docs/webstore/manage/#user-support-tab -[support-site]: /docs/webstore/manage/#dedicated-support-site +[user-support]: /docs/webstore/support-users/#provide-user-support [verify-owner]: https://support.google.com/webmasters/answer/9008080 diff --git a/site/en/docs/webstore/manage/index.md b/site/en/docs/webstore/manage/index.md deleted file mode 100644 index fa0382bb0..000000000 --- a/site/en/docs/webstore/manage/index.md +++ /dev/null @@ -1,224 +0,0 @@ ---- -layout: "layouts/doc-post.njk" -title: "Manage your Chrome Web Store Item" -date: 2021-08-17 -updated: 2023-03-27 -description: > - How to manage an extension or theme ("item") in the Chrome Web Store. ---- - -This page describes how to manage an extension or theme ("item") that was previously submitted to -the Chrome Web Store. - -## About the lifecycle of an item in the Chrome Web Store - -All Chrome Web Store items go through an automated [review process][cws-review]. In some instances a manual review -is required, especially when sensitive permissions are requested. For this reason review times -and/or approval times can take longer. Since a Chrome Web Store item goes through several stages, -it's important to keep track of your item's status. See the lifecycle diagram below: - -{% Img src="image/BhuKGJaIeLNPW9ehns59NfwqKxF2/yakIoAzWEchO8urosQLs.png", alt="Diagram of lifecycle of a Chrome Web Store item", width="800", height="177" %} - -## Check your item's status - -The status of your item appears in the [developer dashboard][dev-dashboard] next to each item. The -status can be Published, Pending, Rejected, or Taken Down. - -{% Img src="image/BhuKGJaIeLNPW9ehns59NfwqKxF2/bUbtISU01bab8WyWqonX.png", alt="Developer dashboard -status types", width="800", height="221" %} - -To stay informed of your item's status, you can: - -- **Enable email notifications**. There are mandatory emails like take down or rejection - notifications that are enabled by default. To receive notification when your item is published or - staged, you can enable email notifications in the Account page. - - {% Img src="image/BhuKGJaIeLNPW9ehns59NfwqKxF2/FgPIwRl3QEbNowNV1zRn.png", alt="How to enable - email notifications", width="658", height="219" %} - -- **Check your publisher email**. After enabling email notifications check your inbox often. To - ensure that CWS emails don't get flagged as Spam, add **chromewebstore-noreply@google.com** to - your contacts so that you receive all communications in a timely manner. - -## Comply with Chrome Web Store policies - -To ensure a positive experience for your users follow the [developer program -policies][dev-policies]. These policies may change, so check the [new announcements][whats-new] page -frequently. - -If your extension has been determined to violate one or more terms or policies, you will receive an -email notification that contains the violation description and instructions on how to rectify. You -can also find this information in the Status tab of your item. - -{% Img src="image/BhuKGJaIeLNPW9ehns59NfwqKxF2/C4wpnEeMriI9YeDAMDIr.png", alt="The Chrome Web Store -Status Tab", width="700", height="276" %} - -If you have been informed about a violation and you do not rectify your item will be taken down. See -[Violation enforcement][enforcement] for more details. - -{% Aside %} - -To request further clarification on the reasons for the take down or appeal the decision -contact [Chrome Web Store Developer Support][cws-support]. For more examples and instructions on how -you can remedy the problem check the [Troubleshooting guide][troubleshooting]. - -{% endAside %} - -## Improve ratings and reply to user reviews - -Ratings and reviews help people decide whether or not to try out an extension. Not only do they -leave a positive impression, but can also increase your ranking on the Chrome Web Store. - -Users can leave comments in the **Reviews tab** of your store item; you can also post replies here -to those reviews. Each user can only rate an extension once, but they can update their rating or -review at any time. You can edit your reply at any time to provide the user with updates. - - {% Img src="image/BhuKGJaIeLNPW9ehns59NfwqKxF2/M09XcAQmPi1dS84EiVQo.png", alt="Store item -reviews tab", -width="600", height="201" %} - -{% Aside %} - -Users will not be notified when you reply to a review, but other users will see that -you are committed to solving issues as they arise. - -{% endAside %} - -Users are more likely to improve their review if you respond and address their concerns promptly. To -receive email notifications when users post reviews or update existing reviews, you can enable Item -Reviews in the **Account settings** of the Developer Dashboard. - - - {% Img src="image/BhuKGJaIeLNPW9ehns59NfwqKxF2/8KGlMCKpiVVBRVqPAkXF.png", alt="Enable reviews notifications", width="600", height="212" %} - -The **Rating tab** in the developer dashboard provides an overview of your extension’s ratings, -including the total number of reviews and ratings over time. - -{% Img src="image/BhuKGJaIeLNPW9ehns59NfwqKxF2/HXJU5d5hEtHNNgj7aehv.png", alt="Dashboard Ratings tab", width="600", height="408" %} - -{% Aside %} - -You can give users a direct link to the review page of your -store item by adding `/reviews` at the end of your item’s URL: -`https://chrome.google.com/webstore/detail/{your-item-id}/reviews` - -{% endAside %} - -## Provide user support - -To ensure the best user experience and build a great extension it's important to -collect, evaluate, and follow up on user feedback. You can manage your extension's user feedback in -two ways: - -- By using the built in CWS User Support tab, or -- By using a dedicated support site. - -Users will be able to communicate with you using the **Support** tab of your store item. - -{% Img src="image/BhuKGJaIeLNPW9ehns59NfwqKxF2/OBDYk7n5dBcaqs3z1HtL.png", alt="Store item Support tab", width="800", height="121" %} - -### Using the User Support tab {: #user-support-tab } - -Having a Support section on your extension's Chrome Web Store page allows users to easily report issues and suggest new features separately from leaving a review. To enable user feedback on your extension, the Visibility option (located in the Support tab area) must be switched on. -The Support Visibility option switch is located in the Chrome Web Store Developer Dashboard, in the Support Tab section of Account Options. - -{% Img src="image/6AZNJBRnkpQUWTKPzig99lQY8jT2/7K825tSAz4wbXJpjGYj2.png", alt="Visibility option", width="800", height="239" %} - -In the **User Support** tab of the developer console you can view, respond and manage user feedback. Use the **Type** -dropdown to filter user input by -feature request, bug report or question. You can assign a status to each request, and can respond to each inquiry. Each ticket includes the extension -version, browser type and operating system to help you reproduce bugs -more efficiently. - -{% Img src="image/BhuKGJaIeLNPW9ehns59NfwqKxF2/VvJFAHdrcMnUivTLm0kK.png", alt="Dashboard User -Support Tab", width="800", height="269" %} - -{% Aside %} -Currently, this feature does not provide notifications: - -- You will not be notified when a user posts a new request. -- The user will not be notified when you post a response. - -{% endAside %} - -### Using a dedicated support site {: #dedicated-support-site } - -You can set up a dedicated support site for your users, so that the support link goes there instead of the default forum experience. This site can be anything you like, such as: - -- A discussion group using Google Groups or some similar service. -- A form-handling site that lets users submit feedback or support tickets. -- A public information site with your product road map or other details. - -Once you set up the site, go to the **Store Listing** tab of the developer console and add the link to the **Support URL** -field. Your support link will then take users to your dedicated site. - -{% Img src="image/BhuKGJaIeLNPW9ehns59NfwqKxF2/7R8GYtBJjjRy1ih20dGd.png", alt="Store Listing Support -URL field", width="514", height="283" %} - -{% Aside %} - -Make sure you **turn off** the [User Feedback][support-tab] in the dashboard Account settings to disable the default support experience. - -{% endAside %} - -## Track your store listing performance - -Understanding your Chrome Web Store listing metrics can help you evaluate how changes to your store -listing have affected conversion rates. For example, you can identify countries with a high number -of visitors so you can prioritize internationalization of your extension for those countries. You -can also export all the reports described below as CSV files. - -### Impressions - -The impressions metrics track the number of users that discover your extension while searching or -browsing the Chrome Web Store. An impression occurs when your extension is featured in any -collection or direct visits to your store item. - -{% Img src="image/BhuKGJaIeLNPW9ehns59NfwqKxF2/Hu4dskyv3lIOuYB0qpv0.png", alt="daily impressions -statistics chart", width="800", height="299" %} - -### Daily installs and uninstalls - -You can track customer acquisition and churn using these reports: -- Track acquisition using the daily install report. -- Monitor user churn using the daily uninstalls analytics. - -These numbers include new and returning - users. You can configure this data by country, language, operating system, or time period using - the “filter by” dropdown menus. - -{% Img src="image/BhuKGJaIeLNPW9ehns59NfwqKxF2/bj6IRC7am3XgQwcfxpnr.png", alt="daily installs -statistics chart", width="800", height="586" %} - -### Weekly users - -You can monitor weekly user retention for different groups of users, categorized by country, -language, operating system, and item version. - -{% Img src="image/BhuKGJaIeLNPW9ehns59NfwqKxF2/jOUcBDD8sBcTFCXrGq1s.png", alt="weekly users -statistics chart", width="800", height="342" %} - -{% Aside %} - -The **Weekly Users** stats only captures installations; it doesn't monitor whether users are active or not. - -{% endAside %} - -### Google Analytics - -To track store item metrics, you can opt in to Google Analytics 4 by clicking **Opt in to Google Analytics** under **Additional metrics** on the **Store listing** tab. After opting in you will receive an email notification. - -The Chrome Web Store manages the account for you and makes the data available in Google Analytics. Chrome Web Store grants you access only to non user-level data. For group publishers, all developers within the group, regardless of their role within the group, are granted access to data for items owned by the group. -{% Img src="image/sQ51XsLqKMgSQMCZjIN0B7hlBO02/etCDPbAFMIeOcKvAW4rN.png", alt="Where to opt in to Google Analytics", width="713", height="123" %} - -Learn more [here][analytics]. - -[cws-review]: /docs/webstore/review-process/ -[cws-support]: https://support.google.com/chrome_webstore/contact/dev_account_transfer -[dev-dashboard]: https://chrome.google.com/webstore/devconsole -[dev-policies]: /docs/webstore/program-policies -[enforcement]: /docs/webstore/review-process/#enforcement -[support-tab]: #user-support-tab -[troubleshooting]: /docs/webstore/troubleshooting/ -[whats-new]: /docs/extensions/whatsnew/ -[analytics]: /docs/webstore/google-analytics/ diff --git a/site/en/docs/webstore/metrics/index.md b/site/en/docs/webstore/metrics/index.md new file mode 100644 index 000000000..1d425e063 --- /dev/null +++ b/site/en/docs/webstore/metrics/index.md @@ -0,0 +1,60 @@ +--- +layout: "layouts/doc-post.njk" +title: "Analyze your store listing metrics" +date: 2021-08-17 +updated: 2023-10-25 +description: > + Understanding metrics and performance of your Chrome Web Store store listing. +--- + +Interpreting your Chrome Web Store listing metrics can help you evaluate how changes to your extension and store +listing can affect conversion rates. For example, you can identify countries with a high number +of visitors so you can prioritize supporting languages for those countries. You can also export all +the reports described below as CSV files. + +## Installs and uninstalls + +You can track customer acquisition and churn using these reports: +- Track acquisition using the daily install report. +- Monitor user churn using the daily uninstalls analytics. + +These numbers include new and returning + users. You can configure this data by country, language, operating system, or time period using + the “filter by” dropdown menus. + +{% Img src="image/BhuKGJaIeLNPW9ehns59NfwqKxF2/bj6IRC7am3XgQwcfxpnr.png", alt="daily installs +statistics chart", width="800", height="586" %} + +## Impressions + +The impressions metrics track the number of users that discover your extension while searching or +browsing the Chrome Web Store. An impression occurs when your extension is featured in any +collection or direct visits to your store item. + +{% Img src="image/BhuKGJaIeLNPW9ehns59NfwqKxF2/Hu4dskyv3lIOuYB0qpv0.png", alt="daily impressions +statistics chart", width="800", height="299" %} + +## Users + +You can monitor weekly user retention for different groups of users, categorized by country, +language, operating system, and item version. + +{% Img src="image/BhuKGJaIeLNPW9ehns59NfwqKxF2/jOUcBDD8sBcTFCXrGq1s.png", alt="weekly users +statistics chart", width="800", height="342" %} + +{% Aside %} + +The **Users** stats only captures installations; it doesn't monitor whether users are active or not. + +{% endAside %} + +## Google Analytics + +To track store item metrics, you can opt in to Google Analytics 4 by clicking **Opt in to Google Analytics** under **Additional metrics** on the **Store listing** tab. After opting in you will receive an email notification. + +The Chrome Web Store manages the account for you and makes the data available in Google Analytics. Chrome Web Store grants you access only to non user-level data. For group publishers, all developers within the group, regardless of their role within the group, are granted access to data for items owned by the group. +{% Img src="image/sQ51XsLqKMgSQMCZjIN0B7hlBO02/etCDPbAFMIeOcKvAW4rN.png", alt="Where to opt in to Google Analytics", width="713", height="123" %} + +See [Using your Google Analytics account with the Chrome Web Store][analytics] to learn more. + +[analytics]: /docs/webstore/google-analytics/ diff --git a/site/en/docs/webstore/support-users/index.md b/site/en/docs/webstore/support-users/index.md new file mode 100644 index 000000000..753c9524f --- /dev/null +++ b/site/en/docs/webstore/support-users/index.md @@ -0,0 +1,136 @@ +--- +layout: "layouts/doc-post.njk" +title: "Manage user feedback" +date: 2021-08-17 +updated: 2023-03-27 +description: > + Follow-up on reviews and provide user support in the Chrome Web Store. +--- + +This guide covers how to manage user feedback on the Chrome Web Store. Learn how to reply to +reviews, check ratings, and provide user support. Whether you choose to use the built-in tools or +set up a dedicated support site, we'll show you the steps to improve your user engagement and handle +feedback efficiently. + +## Reply to user reviews + +Ratings and reviews help people decide whether or not to try out an extension. Not only do they +leave a positive impression, but can also increase your ranking on the Chrome Web Store. + +Users can leave comments in the **Reviews** section of your store item, under the item's overview. You can also post replies here +to those reviews. Each user can only rate an extension once, but they can update their rating or +review at any time. You can also edit your reply at any time to provide the user with updates. + +<figure> + {% Img src="image/BhuKGJaIeLNPW9ehns59NfwqKxF2/UAwuiEvk4BJHFzyPkhcl.png", alt="User review section in the store listing", width="600", height="382", class='screenshot' %} + <figcaption> + User review section in the store listing + </figcaption> +</figure> + +{% Aside %} + +Users will not be notified when you reply to a review, but other users will see that +you are committed to solving issues as they arise. + +{% endAside %} + +Users are more likely to improve their reviews if you respond and address their concerns promptly. To +receive email notifications when users post reviews or update existing reviews, you can enable Item +Reviews in the **Account settings** of the Developer Dashboard. + + {% Img src="image/BhuKGJaIeLNPW9ehns59NfwqKxF2/8KGlMCKpiVVBRVqPAkXF.png", alt="Enable reviews notifications", width="600", height="212" %} + +### The Rating tab + +The **Rating tab** in the developer dashboard provides an overview of your extension’s ratings, +including the total number of reviews and ratings over time. + +{% Img src="image/BhuKGJaIeLNPW9ehns59NfwqKxF2/HXJU5d5hEtHNNgj7aehv.png", alt="Dashboard Ratings tab", width="600", height="408" %} + +{% Aside %} + +You can give users a direct link to the review page of your +store item by adding `/reviews` at the end of your item’s URL: +`https://chrome.google.com/webstore/detail/{your-item-id}/reviews` + +{% endAside %} + +## Provide user support + +To ensure the best user experience and build a great extension it's important to collect, evaluate, +and follow up on bug reports and feature requests. Users will be able to seek support by scrolling +down to the **Support** section of your store item, under the **Privacy** section. You can respond +to user feedback in two ways: + +- By using the built-in [Support hub](#the-support-hub), or +- By directing users to a dedicated support site. + +<figure> + {% Img src="image/BhuKGJaIeLNPW9ehns59NfwqKxF2/rIOTquMOHdz8XgaOMruK.png", alt="Support section in the store listing", width="800", height="271", class='screenshot' %} + <figcaption> + Support section in the store listing + </figcaption> +</figure> + +### The support hub {: #user-support-tab } + +The Chrome Web Store provides a support hub, where users can leave questions, suggestions, and issues they are facing. To use the support hub, you need to enable it first by going to the **Account** management page and turning on the **Visibility** under the **Item support** section. + +<figure> + {% Img src="image/BhuKGJaIeLNPW9ehns59NfwqKxF2/i9AT9btb0qcJBr1ngXM5.png", alt="Visibility toggle under Item support section", width="214", height="123" %} + <figcaption> + Visibility toggle under Item support section + </figcaption> +</figure> + +In the **User Support** tab of the developer dashboard you can view, respond and manage user feedback. Use the **Type** +dropdown to filter user input by +feature request, bug report or question. You can assign a status to each request, and can respond to each inquiry. Each ticket includes the extension +version, browser type and operating system to help you reproduce bugs +more efficiently. + +<figure> + {% Img src="image/BhuKGJaIeLNPW9ehns59NfwqKxF2/JDKcMpp4YsssaiTK8god.png", alt="User Support tab in the developer dashboard item", width="800", height="309", class='screenshot' %} + <figcaption> + User Support tab in the developer dashboard item + </figcaption> +</figure> + +{% Aside %} +Currently, this feature does not provide notifications: + +- You will not be notified when a user posts a new request. +- The user will not be notified when you post a response. + +{% endAside %} + +### Using a dedicated support site {: #dedicated-support-site } + +You can set up a dedicated support site for your users, so that the support link goes there instead of the default forum experience. This site can be anything you like, such as: + +- A discussion group using Google Groups or some similar service. +- A form-handling site that lets users submit feedback or support tickets. +- A public information site with your product road map or other details. + +Once you set up the site, go to the **Store Listing** tab of the developer console and add the link to the **Support URL** +field. Your support link will then take users to your dedicated site. + +{% Img src="image/BhuKGJaIeLNPW9ehns59NfwqKxF2/7R8GYtBJjjRy1ih20dGd.png", alt="Store Listing Support +URL field", width="514", height="283" %} + +{% Aside %} + +Make sure you **turn off** the [Item support][support-tab] Visibility in the dashboard Account settings to disable the support hub. + +{% endAside %} + +[cws-review]: /docs/webstore/review-process/ +[cws-support]: https://support.google.com/chrome_webstore/contact/dev_account_transfer +[dev-dashboard]: https://chrome.google.com/webstore/devconsole +[dev-policies]: /docs/webstore/program-policies +[enforcement]: /docs/webstore/review-process/#enforcement +[support-tab]: #user-support-tab +[troubleshooting]: /docs/webstore/troubleshooting/ +[whats-new]: /docs/extensions/whatsnew/ +[analytics]: /docs/webstore/google-analytics/ From ed445dc3ba2fed56837619cab0dcae6142e97bdc Mon Sep 17 00:00:00 2001 From: Joe Medley <jmedley@google.com> Date: Thu, 26 Oct 2023 13:56:41 -0700 Subject: [PATCH 979/982] Add missing information (#7670) This adds two pieces of information that are in the content scripts document and will allow depublication of content later. --- .../en/docs/extensions/mv3/manifest/content_scripts/index.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/site/en/docs/extensions/mv3/manifest/content_scripts/index.md b/site/en/docs/extensions/mv3/manifest/content_scripts/index.md index e6539a816..5e9c18673 100644 --- a/site/en/docs/extensions/mv3/manifest/content_scripts/index.md +++ b/site/en/docs/extensions/mv3/manifest/content_scripts/index.md @@ -3,6 +3,7 @@ layout: 'layouts/doc-post.njk' title: 'Manifest - content scripts' seoTitle: 'Chrome Extensions Manifest: "content_scripts"' date: 2023-08-10 +updated: 2023-10-26 description: Reference documentation for the "content_scripts" property of manifest.json. --- @@ -47,7 +48,7 @@ Each file must contain a relative path to a resource in the extension's root dir : _Optional_. An array of CSS file paths, injected in the order of this array, and before any DOM construction or page rendering occurs. `"js"` - Array, -: _Optional_. An array of JavaScript file paths, injected in the order they appear in this array, after css files are injected. +: _Optional_. An array of JavaScript file paths, injected in the order they appear in this array, after css files are injected. Each string in the array must be a relative path to a resource in the extension's root directory. Leading slashes ('/') are automatically trimmed. ## Matching URLs {: #match-urls } @@ -239,7 +240,7 @@ By default, content scripts are injected when the document and all resources are : _Optional_. Specifies when the script should be injected into the page. It corresponds with the loading states of [Document.readyState][mdn-ready-state]: - `"document_start"`: the DOM is still loading. - `"document_end"`: the page's resources are still loading - - `"document_idle"`: the DOM and resources have finished loading. + - `"document_idle"`: the DOM and resources have finished loading. This is the default. [`"world"`][scripting-world] - `ISOLATED` | `MAIN` : _Optional_. The JavaScript world for a script to execute within. Defaults to `"ISOLATED"`, which is the execution environment unique to the content script. Choosing the `"MAIN"` world means the script will share the execution environment with the host page's JavaScript. See [Work in isolated worlds][cs-worlds] to learn more. From a3a45b44bf27f0129d1d92dd9f65abe589cb233d Mon Sep 17 00:00:00 2001 From: ilyaspiridonov <spiridonov.ilya@gmail.com> Date: Fri, 27 Oct 2023 13:09:29 +0300 Subject: [PATCH 980/982] [JA] October translations (#7673) * Translate index.md via GitLocalize * Translate index.md via GitLocalize * Translate index.md via GitLocalize * Translate index.md via GitLocalize * Translate index.md via GitLocalize * Translate index.md via GitLocalize * Translate index.md via GitLocalize * Translate index.md via GitLocalize * Translate index.md via GitLocalize * Translate ara.md via GitLocalize * Translate ara.md via GitLocalize * Translate ara.md via GitLocalize * Translate chips.md via GitLocalize * Translate chips.md via GitLocalize * Translate chips.md via GitLocalize * Translate fedcm.md via GitLocalize * Translate fedcm.md via GitLocalize * Translate fedcm.md via GitLocalize * Translate fps.md via GitLocalize * Translate fps.md via GitLocalize * Translate fps.md via GitLocalize * Translate paapi.md via GitLocalize * Translate paapi.md via GitLocalize * Translate paapi.md via GitLocalize * Translate permissions-policy.md via GitLocalize * Translate permissions-policy.md via GitLocalize * Translate permissions-policy.md via GitLocalize * Translate private-state.md via GitLocalize * Translate private-state.md via GitLocalize * Translate shared-storage.md via GitLocalize * Translate shared-storage.md via GitLocalize * Translate shared-storage.md via GitLocalize * Translate topics.md via GitLocalize * Translate topics.md via GitLocalize * Translate topics.md via GitLocalize * Translate ua-reduction.md via GitLocalize * Translate ua-reduction.md via GitLocalize * Translate ua-reduction.md via GitLocalize * Update index.md * Update index.md * Update index.md * Update index.md * Update ara.md --------- Co-authored-by: Nozomi Kugita <nozomi@nozygatos.com> Co-authored-by: mt-gitlocalize <mt@gitlocalize.com> Co-authored-by: dianayaromskaya <dy@alconost.com> --- .../ja/_partials/privacy-sandbox/demos/ara.md | 31 ++++ .../_partials/privacy-sandbox/demos/chips.md | 7 + .../_partials/privacy-sandbox/demos/fedcm.md | 7 + .../ja/_partials/privacy-sandbox/demos/fps.md | 9 + .../_partials/privacy-sandbox/demos/paapi.md | 15 ++ .../demos/permissions-policy.md | 7 + .../privacy-sandbox/demos/private-state.md | 7 + .../privacy-sandbox/demos/shared-storage.md | 13 ++ .../_partials/privacy-sandbox/demos/topics.md | 33 ++++ .../privacy-sandbox/demos/ua-reduction.md | 15 ++ .../ja/blog/cookie-countdown-2023oct/index.md | 161 ++++++++++++++++++ site/ja/docs/privacy-sandbox/demos/index.md | 36 ++++ site/ja/docs/privacy-sandbox/status/index.md | 50 +++--- 13 files changed, 370 insertions(+), 21 deletions(-) create mode 100644 site/ja/_partials/privacy-sandbox/demos/ara.md create mode 100644 site/ja/_partials/privacy-sandbox/demos/chips.md create mode 100644 site/ja/_partials/privacy-sandbox/demos/fedcm.md create mode 100644 site/ja/_partials/privacy-sandbox/demos/fps.md create mode 100644 site/ja/_partials/privacy-sandbox/demos/paapi.md create mode 100644 site/ja/_partials/privacy-sandbox/demos/permissions-policy.md create mode 100644 site/ja/_partials/privacy-sandbox/demos/private-state.md create mode 100644 site/ja/_partials/privacy-sandbox/demos/shared-storage.md create mode 100644 site/ja/_partials/privacy-sandbox/demos/topics.md create mode 100644 site/ja/_partials/privacy-sandbox/demos/ua-reduction.md create mode 100644 site/ja/blog/cookie-countdown-2023oct/index.md create mode 100644 site/ja/docs/privacy-sandbox/demos/index.md diff --git a/site/ja/_partials/privacy-sandbox/demos/ara.md b/site/ja/_partials/privacy-sandbox/demos/ara.md new file mode 100644 index 000000000..3f04bf415 --- /dev/null +++ b/site/ja/_partials/privacy-sandbox/demos/ara.md @@ -0,0 +1,31 @@ +{% Details %} {% DetailsSummary %} **アトリビューション レポート**{% endDetailsSummary %} + +**<a>デモ</a>** + +{% Columns %} {% Column %} Attribution Reporting API を使用すると、広告主とアドテックプロバイダーは、広告のクリックとビュー、サードパーティ iframe の広告、およびファーストパーティコンテキストの広告のコンバージョンを測定できます。このデモでは、広告主がアドテックプロバイダーを使用して、サイト運営者サイトに広告を掲載します。 + +[デモ](https://arapi-home.web.app/) + +[ドキュメント](/docs/privacy-sandbox/attribution-reporting/) + +[要約レポートのウォークスルー動画](https://drive.google.com/file/d/18RGEx_mrhDJuMsLUK1BZ0cK5FSZRAAqh/view) + +{% endColumn %} {% Column %} + +<a href="https://arapi-home.web.app/">{% Img src="image/RtQlPaM9wdhEJGVKR8boMPkWf443/cQABHch0L68I92idOgcN.png", alt="Attribution Repoting API のデモ。", width="707", height="512" %}</a> + +{% endColumn %} {% endColumns %} + +**Noiselab** + +{% Columns %} {% Column %} 集計可能なレポートがコレクタによってバッチ処理され、集計サービスによって処理される場合、ユーザーのプライバシーを保護するために、結果の要約レポートにランダムデータが追加されます。Noiselab を使用してさまざまな値を実験し、ノイズの影響を確認します。 + +[Noise Lab](https://noise-lab.uc.r.appspot.com/?mode=simple) + +[ドキュメント](/docs/privacy-sandbox/attribution-reporting/understanding-noise/) + +{% endColumn %} {% Column %} + +<a href="https://noise-lab.uc.r.appspot.com/?mode=simple">{% Img src="image/RtQlPaM9wdhEJGVKR8boMPkWf443/9pln3PilOb2Hh5zrLdhz.png", alt="Noise Lab.", width="686", height="448" %}</a> + +{% endColumn %} {% endColumns %} {% endDetails %} diff --git a/site/ja/_partials/privacy-sandbox/demos/chips.md b/site/ja/_partials/privacy-sandbox/demos/chips.md new file mode 100644 index 000000000..2f577fb77 --- /dev/null +++ b/site/ja/_partials/privacy-sandbox/demos/chips.md @@ -0,0 +1,7 @@ +{% Details %} {% DetailsSummary %} **CHIPS** {% endDetailsSummary %} {% Columns %} {% Column %} Cookies Having Independent Partitioned State(CHIPS)により、開発者は、トップレベルサイトごとに個別の Cookie ジャーを使用して、パーティション化されたストレージに Cookie をオプトインし、ユーザーのプライバシーとセキュリティを向上させることができます。このデモでは、その仕組みを説明します。 + +[デモ](https://chips-site-a.glitch.me/) + +[ドキュメント](/docs/privacy-sandbox/chips/) + +{% endColumn %} {% Column %} <a href="https://chips-site-a.glitch.me/">{% Img src="image/RtQlPaM9wdhEJGVKR8boMPkWf443/Un7OFSJTQHhly3twuEHw.png", alt="CHIPS のデモ。", width="597", height="417" %}</a> {% endColumn %} {% endColumns %} {% endDetails %} diff --git a/site/ja/_partials/privacy-sandbox/demos/fedcm.md b/site/ja/_partials/privacy-sandbox/demos/fedcm.md new file mode 100644 index 000000000..d90099eff --- /dev/null +++ b/site/ja/_partials/privacy-sandbox/demos/fedcm.md @@ -0,0 +1,7 @@ +{% Details %} {% DetailsSummary %} FedCM {% endDetailsSummary %} {% Columns %} {% Column %} FedCM は、連携された ID サービスに対するプライバシー保護のアプローチであり、ユーザーは ID サービスまたはサイトに個人情報を共有することなくサイトにログインできます。このデモでは、その仕組みを説明します。 + +[デモ](https://fedcm-rp-demo.glitch.me) + +[ドキュメント](/docs/privacy-sandbox/fedcm/) + +{% endColumn %} {% Column %} <a href="https://fedcm-rp-demo.glitch.me">{% Img src="image/RtQlPaM9wdhEJGVKR8boMPkWf443/r9RNu995n1Toyp9ysI5d.png", alt="FedCM のデモ。", width="514", height="380" %}</a> {% endColumn %} {% endColumns %} {% endDetails %} diff --git a/site/ja/_partials/privacy-sandbox/demos/fps.md b/site/ja/_partials/privacy-sandbox/demos/fps.md new file mode 100644 index 000000000..c92a6a5da --- /dev/null +++ b/site/ja/_partials/privacy-sandbox/demos/fps.md @@ -0,0 +1,9 @@ +{% Details %} {% DetailsSummary %} Related Website Sets {% endDetailsSummary %} {% Columns %} {% Column %} Related Website Sets は、企業がサイト間の関係を宣言し、ブラウザが特定の目的で限定的なサードパーティ Cookie を許可できるようにする方法です。Chrome は、これらの宣言された関係を使用して、サードパーティのコンテキストで、Cookie へのサイトアクセスをいつ許可または拒否するかを決定します。 + +[デモ](https://first-party-sets.glitch.me/) + +[ドキュメント](/docs/privacy-sandbox/related-website-sets/) + +[提出用 JSON ジェネレーター](https://rws-json-generator.ue.r.appspot.com/) + +{% endColumn %} {% Column %} <a href="https://first-party-sets.glitch.me/">{% Img src="image/RtQlPaM9wdhEJGVKR8boMPkWf443/xQbEZnwQ7Fjw8MOYuddS.png", alt="Related Website Sets のデモ。", width="600", height="400" %}</a> {% endColumn %} {% endColumns %} {% endDetails %} diff --git a/site/ja/_partials/privacy-sandbox/demos/paapi.md b/site/ja/_partials/privacy-sandbox/demos/paapi.md new file mode 100644 index 000000000..6f5de098e --- /dev/null +++ b/site/ja/_partials/privacy-sandbox/demos/paapi.md @@ -0,0 +1,15 @@ +{% Details %} {% DetailsSummary %} Protected Audience API {% endDetailsSummary %} {% Columns %} {% Column %} + +このデモでは、Protected Audience API を使用して 2 つの広告主サイトの広告インタレストグループに参加し、デバイス上のオークションを開始してサイト運営者サイトに表示する広告を選択します。 + +[デモ](https://protected-audience-demo.web.app/) + +[デモコード](https://github.com/GoogleChromeLabs/protected-audience-demo) + +[ドキュメント](/docs/privacy-sandbox/protected-audience-api/) + +{% endColumn %} {% Column %} + +<a href="https://protected-audience-demo.web.app/">{% Img src="image/RtQlPaM9wdhEJGVKR8boMPkWf443/pi7cN0x6j7OAJXoog0zo.png", alt="Protected Audience API のデモ。", width="800", height="708" %}</a> + +{% endColumn %} {% endColumns %} {% endDetails %} diff --git a/site/ja/_partials/privacy-sandbox/demos/permissions-policy.md b/site/ja/_partials/privacy-sandbox/demos/permissions-policy.md new file mode 100644 index 000000000..9af137db1 --- /dev/null +++ b/site/ja/_partials/privacy-sandbox/demos/permissions-policy.md @@ -0,0 +1,7 @@ +{% Details %} {% DetailsSummary %} **権限ポリシー** {% endDetailsSummary %} {% Columns %} {% Column %} 権限ポリシーを使用すると、開発者はブラウザが強制する一連のポリシーを宣言することで、ページ、その iframe、およびサブリソースで使用できるブラウザ機能を制御できます。このデモでは、利用可能なポリシーを試すことができます。 + +[デモ](https://permissions-policy-demo.glitch.me/demo/) + +[ドキュメント](/docs/privacy-sandbox/permissions-policy/) + +{% endColumn %} {% Column %} <a href="https://permissions-policy-demo.glitch.me/demo/">{% Img src="image/RtQlPaM9wdhEJGVKR8boMPkWf443/qaZFVmYVbQmEGhl004VT.png", alt="権限ポリシーのデモ。", width="676", height="458" %}</a> {% endColumn %} {% endColumns %} {% endDetails %} diff --git a/site/ja/_partials/privacy-sandbox/demos/private-state.md b/site/ja/_partials/privacy-sandbox/demos/private-state.md new file mode 100644 index 000000000..c8645e0c1 --- /dev/null +++ b/site/ja/_partials/privacy-sandbox/demos/private-state.md @@ -0,0 +1,7 @@ +{% Details %} {% DetailsSummary %} **Private State Token API** {% endDetailsSummary %} {% Columns %} {% Column %} Private State Token API を使用すると、ウェブサイトは信頼するユーザーに暗号トークンを発行し、後で別の場所で使用することができます。トークンはユーザーのブラウザによって安全に保存され、ユーザーの信頼性を確認するために他のコンテキストで引き換えることができます。このデモで API をご覧ください。 + +[デモ](https://private-state-token-demo.glitch.me/) + +[ドキュメント](/docs/privacy-sandbox/private-state-tokens/) {% endColumn %} + +{% Column %} <a href="https://private-state-token-demo.glitch.me/">{% Img src="image/RtQlPaM9wdhEJGVKR8boMPkWf443/OVudOoLOz1BKNEmfY1pc.png", alt="Private State Token API のデモ。", width="620", height="519" %}</a> {% endColumn %} {% endColumns %} {% endDetails %} diff --git a/site/ja/_partials/privacy-sandbox/demos/shared-storage.md b/site/ja/_partials/privacy-sandbox/demos/shared-storage.md new file mode 100644 index 000000000..d8703b8df --- /dev/null +++ b/site/ja/_partials/privacy-sandbox/demos/shared-storage.md @@ -0,0 +1,13 @@ +{% Details %} {% DetailsSummary %} 共有ストレージ {% endDetailsSummary %} + +{% Columns %} {% Column %} Shared Storage API は、クロスサイトで使用できるストレージを提供します。つまり、あるドメインに値を保存し、別のドメインから値を読み取ります。データは自由に設定できますが、ストレージからデータを取得する方法は制限されています。このデモでは、その仕組みを説明します。 + +[デモ](https://shared-storage-demo.web.app/) + +[ドキュメント](/docs/privacy-sandbox/shared-storage/) + +{% endColumn %} {% Column %} + +<a href="https://shared-storage-demo.web.app/">{% Img src="image/RtQlPaM9wdhEJGVKR8boMPkWf443/dOFtwOaI8ldFfwgmG5El.png", alt="Shared Storage API のデモ。", width="751", height="521" %}</a> + +{% endColumn %} {% endColumns %} {% endDetails %} diff --git a/site/ja/_partials/privacy-sandbox/demos/topics.md b/site/ja/_partials/privacy-sandbox/demos/topics.md new file mode 100644 index 000000000..9e4e4d72d --- /dev/null +++ b/site/ja/_partials/privacy-sandbox/demos/topics.md @@ -0,0 +1,33 @@ +{% Details %} {% DetailsSummary %} **Topics API** {% endDetailsSummary %} + +**<a>デモ</a>** + +{% Columns %} {% Column %} Topics API を使用すると、ブラウザはサードパーティ Cookie を使用せずに、ユーザーの興味に関する情報をサードパーティと共有できます。ユーザーが訪問するサイトを追跡せずに、インタレストベース広告(IBA)を可能にします。このデモでは、API の実際の動作の例を示します。 + +[デモ](https://topics-demo.glitch.me/) + +[ウォークスルー動画](https://www.youtube.com/watch?v=hEBzWuXjeTQ) + +[ドキュメント](/docs/privacy-sandbox/topics/overview/) + +{% endColumn %} {% Column %} + +<a href="https://topics-demo.glitch.me/">{% Img src="image/RtQlPaM9wdhEJGVKR8boMPkWf443/3YDJBguZVeVorWT4BdkA.png", alt="Topics API のデモ。", width="469", height="386" %}</a> + +{% endColumn %} {% endColumns %} + +**Colab** + +{% Columns %} {% Column %} この Colab を使うと、ホスト名からトピックを推測するために Chrome で使用される TensorFlow Lite モデルを簡単に読み込むことができます。 + +[Colab](https://colab.research.google.com/drive/1hIVoz8bRCTpllYvads51MV7YS3zi3prn) + +[Colab ドキュメント](/docs/privacy-sandbox/topics/colab/) + +[ウォークスルー動画](https://www.youtube.com/watch?v=hEBzWuXjeTQ) + +{% endColumn %} {% Column %} + +<a href="https://colab.research.google.com/drive/1hIVoz8bRCTpllYvads51MV7YS3zi3prn">{% Img src="image/RtQlPaM9wdhEJGVKR8boMPkWf443/Au0wqVDHINuCmWxN0lOR.png", alt="Topics API の Colab。", width="503", height="269" %}</a> + +{% endColumn %} {% endColumns %} {% endDetails %} diff --git a/site/ja/_partials/privacy-sandbox/demos/ua-reduction.md b/site/ja/_partials/privacy-sandbox/demos/ua-reduction.md new file mode 100644 index 000000000..3fb7c614e --- /dev/null +++ b/site/ja/_partials/privacy-sandbox/demos/ua-reduction.md @@ -0,0 +1,15 @@ +{% Details %} {% DetailsSummary %} **ユーザーエージェントの削減** {% endDetailsSummary %} {% Columns %} {% Column %} ユーザーエージェントの削減により、パッシブフィンガープリントに使用される可能性のあるユーザーエージェント文字列で共有される個人を特定できる情報が最小限に抑えられます。リソースリクエストの User-Agent ヘッダーは縮小されたため、特定の Navigator インターフェースからの戻り値が少なくなっています。このデモでは、この新しい UA 文字列値を実験することができます。 + +[デモ](https://uar-ot.glitch.me/) + +[ドキュメント](/docs/privacy-sandbox/user-agent/) + +{% endColumn %} {% Column %} <a href="https://uar-ot.glitch.me/">{% Img src="image/RtQlPaM9wdhEJGVKR8boMPkWf443/S5ALrfmMdD2xDkIpsnS0.png", alt="ユーザーエージェントの削減のデモ。", width="800", height="627" %}</a> {% endColumn %} {% endColumns %} {% Columns %} {% Column %} JavaScript によって縮小されたユーザーエージェント + +[デモ](https://reduced-ua.glitch.me/javascript.html) + +[ドキュメント](/docs/privacy-sandbox/user-agent/) {% endColumn %} {% Column %} <a href="https://reduced-ua.glitch.me/javascript.html">{% Img src="image/RtQlPaM9wdhEJGVKR8boMPkWf443/rQpRviM9Xv2tYAxDg0Bc.png", alt="JavaScript によって縮小されたユーザーエージェントのデモ。", width="694", height="396" %}</a> {% endColumn %} {% endColumns %} {% Columns %} {% Column %} サーバーサイドで縮小されたユーザーエージェント + +[デモ](https://reduced-ua.glitch.me/server-side) + +[ドキュメント](/docs/privacy-sandbox/user-agent/) {% endColumn %} {% Column %} <a href="https://reduced-ua.glitch.me/server-side">{% Img src="image/RtQlPaM9wdhEJGVKR8boMPkWf443/pon9P8soEiUNb4gTfluf.png", alt="サーバーサイドで縮小されたユーザーエージェントのデモ。", width="592", height="544" %}</a> {% endColumn %} {% endColumns %} {% endDetails %} diff --git a/site/ja/blog/cookie-countdown-2023oct/index.md b/site/ja/blog/cookie-countdown-2023oct/index.md new file mode 100644 index 000000000..ce10193fb --- /dev/null +++ b/site/ja/blog/cookie-countdown-2023oct/index.md @@ -0,0 +1,161 @@ +--- +layout: layouts/blog-post.njk +title: サードパーティ Cookie の廃止に向けた準備 +authors: + - rowan_m +description: サードパーティ Cookie の廃止時期が近付いています。あなたのサイトでその種の Cookie を使用している場合は、廃止対策を講じる時期が来ています。Chrome は、テストを容易に行えるように、2024 年第 1 四半期からユーザーの 1% に対してサードパーティ Cookie を無効にし、2024 年第 3 四半期からはユーザーの 100% に対して無効にすることを予定しています。この Cookie カウントダウンの連載記事では、そのタイムラインとサイトの対応状態を保証する上でユーザーがすぐに実行できる対応について説明します。 +date: 2023-10-11 +thumbnail: image/VWw0b3pM7jdugTkwI6Y81n6f5Yc2/XeTqWn3za0aUZVGb2kUM.jpg +alt: サードパーティ Cookie の廃止に向けた準備 +tags: + - privacy + - cookie-countdown +--- + +サードパーティ Cookie の廃止時期が近付いています。あなたのサイトでその種の Cookie を使用している場合は、廃止対策を講じる時期が来ています。Chrome は、テストを容易に行えるように、2024 年第 1 四半期からユーザーの 1% に対してサードパーティ Cookie を無効にし、2024 年第 3 四半期からはユーザーの 100% に対して無効にすることを予定しています。対象ユーザー 100% への増加は、[英国の競争市場庁(CMA)](https://www.gov.uk/cma-cases/investigation-into-googles-privacy-sandbox-browser-changes)による現在未対応の競争上の懸念に対する対処が条件となっています。 + +プライバシーサンドボックスの目標は、オンラインコンテンツやサービスに誰でも自由にアクセスできる機能を有効にしながら、サイト間のトラッキングを削減することです。サードパーティ Cookie にはサインイン、不正行為防止、広告などの重要な機能を有効にし、全体としてリッチなサードパーティコンテンツをサイトに埋め込む機能を有効にする機能が備わっている一方で、クロスサイトトラッキングの鍵となる要素でもあるため、その廃止と削除は簡単にはいきません。 + +前回のメジャーマイルストーンでは、アイデンティティ、広告、不正行為検出などのユースケースに対して、現在の一般的な手法に代わるプライバシーを重視した代替手段を提供するさまざまな API をリリースしました。代替手段が整ったので、サードパーティ Cookie の段階的な廃止に進むことができます。 + +この [Cookie カウントダウンに関する連載記事](/tags/cookie-countdown/)では、タイムラインと、サイトの準備が整っていることを確認するためにすぐに実行できる対応について説明します。 + +## 1% のサードパーティ Cookie の廃止と Chrome によるテスト {: #chrome-testing } + +[privacysandbox.com のタイムライン](https://privacysandbox.com/open-web/#the-privacy-sandbox-timeline)によると、 [Chrome によるテスト](/docs/privacy-sandbox/chrome-testing/)モードの一環として、2023 年第 4 四半期と 2024 年第 1 四半期に 2 つのマイルストーンが近づいていることがわかります。このテストは主にプライバシーサンドボックス広告関連 API をテストする組織を対象としていますが、その一環として、Chrome 安定版ユーザーの 1% に対してサードパーティ Cookie を無効にする予定です。 + +{% Img src="image/VWw0b3pM7jdugTkwI6Y81n6f5Yc2/Fl3J3HIW22U710lVSgtu.png", alt="サードパーティ Cookie 廃止のタイムライン。Chrome によるテストの一環として、ラベルモードを使用したオプトインテストが 2023 年第 4 四半期に開始され、1% 3PC デプリケーションモードは 2024 年第 1 四半期に開始されます。どちらも、サードパーティ Cookie の段階的廃止が開始される 2024 年の第 3 四半期半ばまで続きます。", width="800", height="276" %} + +これは、2024 年の初めから、Chrome が実施するテストに積極的に参加していない場合でもサードパーティ Cookie が無効になっているサイトの Chrome ユーザーの割合が増加することが予想されることを意味します。このテスト期間は 2024 年第 3 四半期まで継続され、[CMA との協議](https://www.gov.uk/cma-cases/investigation-into-googles-privacy-sandbox-browser-changes)の後、競争上の懸念が解決されることを条件として、すべての Chrome ユーザーに対してサードパーティ Cookie の無効化を開始する予定です。 + +## サードパーティ Cookie の段階的廃止に備える + +サードパーティ Cookie を使わずにサイトを実行する準備が整っていることを確認するために、プロセスを次の主要な手順に分割し、詳細を以下に示します。 + +1. [サードパーティ Cookie の使用状況を監査](#audit)します。 +2. [破損状況についてテスト](#test)します。 +3. 埋め込みなど、サイトごとにデータを保存するクロスサイト Cookie の場合は、[CHIPS による `Partitioned`](#partitioned) の使用を検討してください。 +4. 有意義にリンクされたサイトの小さなグループをまたぐクロスサイト Cookie については、[Related Website Sets](#rws) の使用を検討してください。 +5. 他のサードパーティ Cookie のユースケースについては、[関連する Web API に移行](#migrate)してください。 + +## 1. サードパーティ Cookie の使用状況を監査する {: #audit} + +サードパーティ Cookie は、`SameSite=None` 値によって識別できます。コードを検索して、 `SameSite` 属性をこの値に設定しているインスタンスを探す必要があります。以前 2020 年頃に Cookie に `SameSite=None` を追加する変更を加えた場合は、それらの変更から探すのが良いかもしれません。 + +Chrome DevTools の [ネットワーク] パネルには、リクエストに応じて設定して送信された Cookie が表示されます。[アプリケーション] パネルで、[ストレージ] の下に表示される [Cookie] という見出しでは、ページ読み込みの一部としてアクセスされたサイトごとに保存された Cookie を参照できます。`SameSite` 列で並べ替えて、すべての `None` Cookie をグループ化できます。 + +{% Img src="image/VWw0b3pM7jdugTkwI6Y81n6f5Yc2/xYNwixxMkPfMmlMmKY4L.png", alt="DevTools の [イシュー] タブに SameSite=None Cookie の警告が表示されている。", width="800", height="403" %} + +Chrome 118 以降、 [DevTools の [イシュー] タブ](/docs/devtools/issues/)には、「クロスサイト コンテキストで送信された Cookie は将来の Chrome バージョンでブロックされます」という重大な変更に関するイシューが表示されます。このイシューには、現在のページで影響を受ける可能性のある Cookie がリストされています。 + +{% Aside %} + +現在、ブラウジング セッション中の Cookie の使用状況の分析を容易にする DevTools 拡張機能を構築中です。これにより、Cookie のデバッグ経路と、プライバシーサンドボックスイニシアチブのさまざまな側面を学習して理解するためのアクセスポイントを備えたプライバシーサンドボックス機能が提供されます。<br> **2023 年 11 月のプレビュー公開にご注目ください!** + +{% endAside %} + +サードパーティによって設定された Cookie を特定したら、それらのプロバイダーにサードパーティ Cookie を段階的に廃止する計画があるかどうかを確認する必要があります。たとえば、使用しているライブラリのバージョンをアップグレードしたり、サービスの構成オプションを変更したりする必要がある可能性もあり、必要な変更をサードパーティが独自に処理しているのであれば何もアクションをとる必要がない可能性もあります。 + +## 2. 破損状況をテストする {: #test } + +`--test-third-party-cookie-phaseout` [コマンドラインフラグ](/docs/web-platform/chrome-flags)を使用して Chrome を起動するか、Chrome 118 を起動し、`chrome://flags/#test-third-party-cookie-phaseout` を有効にします。これにより、段階的廃止後の状態を最適にシミュレーションするために、Chrome でのサードパーティ Cookie のブロックと新しい機能と緩和策の有効が保証されます。 + +`chrome://settings/cookies` 経由でサードパーティ Cookie をブロックしてブラウジングを試すこともできますが、このフラグを使用すると​​、新しい機能や更新された機能も有効になることに注意してください。サードパーティ Cookie をブロックすることはイシューを検出するための良い方法ではありますが、必ずしもイシューが修正されたかどうかを検証できるわけではありません。 + +サイト用のアクティブなテストスイートを維持する場合は、2 つの並行実行を行う必要があります。1 つは通常の設定の Chrome で実行し、もう 1 つは `--test-third-party-cookie-phaseout` フラグで起動した同じバージョンの Chrome で実行します。最初の実行ではなく 2 回目の実行でテストが失敗した場合は、サードパーティ Cookie の依存関係を調査するのに適した候補となります。必ず見つかった[イシューを報告](#report-issues)してください。 + +イシューのある Cookie を特定し、そのユースケースを理解すれば、以降のオプションを試して必要な解決策を選択することができます。 + +## 3. CHIPS による `Partitioned` Cookie を使用する {: #partitioned } + +サードパーティ Cookie がトップレベル サイトとの 1 対 1 の埋め込みコンテキストで使用されている場合は、`Partitioned` 属性を Cookies Have Independent Partitioned State(CHIPS)の一部として使用して、サイトごとに使用される個別の Cookie でクロスサイト アクセスを許可することを検討してください。 + +{% Img src="image/VWw0b3pM7jdugTkwI6Y81n6f5Yc2/5JLh0cCChr0bKOzp6XxP.png", alt="Partitioned 属性により、トップレベル サイトごとに個別の fav_store Cookie を設定できます。", width="800", height="359" %} + +CHIPS を実装するには、`Set-Cookie` ヘッダーに `Partitioned` 属性を追加します。 + +`Partitioned` を設定すると、サイトはトップレベル サイトによってパーティション化された別の Cookie ジャーに Cookie を保存することを選択します。上の例では、Cookie は、ユーザーがお気に入りの店舗を保存できる店舗マップをホストする `store-finder.site` から取得されます。CHIPS を使用することにより、 `brand-a.site` が `store-finder.site` を埋め込むと、`fav_store` Cookie の値が `123` になります。その後で `brand-b.site` も `store-finder.site` を埋め込むと、`fav_store` Cookie の独自のパーティション化されたインスタンス(値 `456` など)を設定して送信します。 + +これは、組み込みサービスは引き続き状態を保存できても、クロスサイトトラッキングを可能にする共有クロスサイトストレージは備わっていないことを意味します。 + +**可能性のあるユースケース:** サードパーティチャットの埋め込み、サードパーティマップの埋め込み、サードパーティペイメントの埋め込み、サブリソース CDN によるロードバランシング、ヘッドレス CMS プロバイダー、信頼できないユーザー コンテンツを提供するためのサンドボックスドメイン、アクセス制御に Cookie を使用するサードパーティ CDN、リクエスト時に Cookie を必要とするサードパーティ API 呼び出し、サイト運営者ごとに範囲指定された状態付き埋め込み広告。 + +**[CHIPS について詳しく見る](/docs/privacy-sandbox/chips/)** + +## 4. Related Website Sets を使用する {: #rws } + +サードパーティ Cookie が少数の関連サイトでのみ使用されている場合は、[Related Website Sets](/en/blog/related-website-sets/)(RWS)を使用して、定義されたサイトのコンテキスト内でその Cookie のクロスサイト アクセスを許可することを検討できます。 + +RWS を実装するには、セットのサイトのグループを[定義して送信](https://github.com/GoogleChrome/first-party-sets/blob/main/RWS-Submission_Guidelines.md)する必要があります。サイトが意味のある関連性を持っていることを確認するために、有効なセットのポリシーでは、それらのサイトを、目に見える相互関係を持つ関連サイト(企業が提供する製品のバリエーションなど)、サービスドメイン(API、CDN など)、または国コードドメイン(*.uk、*.jp など)の項目ごとにグループ化する必要があります。 + +{% Img src="image/VWw0b3pM7jdugTkwI6Y81n6f5Yc2/es7ld9MfMP8sowe7PZzC.png", alt="Related Website Sets では、宣言されたサイトのコンテキスト内での Cookie アクセスは許可されますが、他のサードパーティサイト全体では許可されません。", width="800", height ="359" %} + +サイトはストレージ アクセス API を使って、`requestStorageAccess()` でクロスサイト Cookie アクセスを要求するか、`requestStorageAccessFor()`でアクセスを委譲できます。サイトが同じセット内にある場合、ブラウザは自動的にアクセスを許可し、クロスサイト Cookie が利用可能になります。 + +つまり、関連サイトのグループは限られたコンテキストでクロスサイト Cookie を使用し続けられますが、クロスサイトトラッキングを可能にする方法によって無関係なサイト間でサードパーティ Cookie を共有するというリスクがありません。 + +**可能性のあるユースケース:** アプリ固有のドメイン、ブランド固有のドメイン、国固有のドメイン、信頼できないユーザーコンテンツを提供するためのサンドボックスドメイン、API のサービスドメイン、CDN。 + +**[RWS について詳しく見る](/blog/related-website-sets/)** + +## 5. 関連する Web API に移行する {: #migrate } + +CHIPS と RWS は、ユーザーのプライバシーを維持しながら、特定のタイプのクロスサイト Cookie アクセスを可能にしますが、サードパーティ Cookie の他のユースケースにおいては、プライバシーを重視した代替手段に移行する必要があります。 + +プライバシー サンドボックスは、特定のユースケース向けに、サードパーティ Cookie を必要としない専用の API を多数提供しています。 + +- **[Federated Credential Management(FedCM)](/docs/privacy-sandbox/fedcm/)**: 連携された ID サービスを有効にし、ユーザーがサイトやサービスにサインインできるようにします。 +- **[プライベートステートトークン](/docs/privacy-sandbox/private-state-tokens/)**: 限定された非個人情報をサイト間で交換することにより、不正防止とスパム防止を可能にします。 +- **[Topics](/docs/privacy-sandbox/topics/overview/)**: インタレスト広告とコンテンツのパーソナライズを可能にします。 +- **[Protected Audience](/docs/privacy-sandbox/protected-audience/)**: リマーケティングとカスタムオーディエンスを有効にします。 +- **[アトリビューション レポート](/docs/privacy-sandbox/attribution-reporting/)**: 広告のインプレッションとコンバージョンを測定できます。 + +さらに、Chrome は、ユーザー操作を伴う iframe で使用するための **[Storage Access API](https://developer.mozilla.org/docs/Web/API/Storage_Access_API/Using)**(SAA)をサポートしています。SAA は、[Edge、Firefox、Safari ですでにサポートされています](https://developer.mozilla.org/docs/Web/API/Storage_Access_API#browser_compatibility)。ユーザーのプライバシーを維持しながら、ブラウザ間の互換性のメリットにより重要なクロスサイト機能を有効にすることが適切なバランスであると私たちは考えています。 + +Storage Access API では、ブラウザの許可を求めるプロンプトがユーザーに表示されることに注意してください。最適なユーザー エクスペリエンスを提供できるよう、このプロンプトは `requestStorageAccess()` を呼び出すサイトが埋め込みページと対話し、さらに以前にトップレベル コンテキストでサードパーティサイトにアクセスしたことがある場合にのみ表示されるようになっています。正しく許可されると、そのサイトに対するクロスサイト Cookie アクセスが 30 日間有効になります。可能性のあるユースケースは、ソーシャルネットワークのコメントウィジェット、ペイメントプロバイダー、登録済みの動画サービスなど、認証されたクロスサイトの埋め込みです。 + +これらのオプションで対応されないサードパーティ Cookie のユースケースがまだある場合は、[イシューを当社に報告](#report-issues)し、クロスサイトトラッキングを可能にする機能に依存しない代替実装があるかどうかを検討することをお勧めします。 + +## エンタープライズサポート + +企業が管理する Chrome には、一般的なウェブの使用と比較して常に固有の要件があるため、エンタープライズ管理者がブラウザでのサードパーティ Cookie の廃止を適切に制御できるようにする予定です。 + +大半の Chrome 実験と同様に、ほとんどのエンタープライズエンドユーザーは 1% のサードパーティ Cookie の廃止から自動的に除外されます。影響を受ける可能性のある少数の企業については、エンタープライズ管理者が [BlockThirdPartyCookies ポリシー](https://chromeenterprise.google/policies/#BlockThirdPartyCookies)を `false` に設定して、実験に先立って管理対象ブラウザをオプトアウトし、このポリシーやサードパーティ Cookie に依存しないように必要な変更を加える時間を確保することができます。詳細については、[Chrome Enterprise リリースノート](https://support.google.com/chrome/a/answer/7679408?sjid=16745203858910744446-EU#upChromeBrsrBB117)をご覧ください。 + +また、企業サイトでのサードパーティ Cookie の使用状況を特定するのに役立つレポートとツールをさらに提供する予定です。Chrome の使用状況に関するメトリクスにおいては、エンタープライズブラウザに関する認識があまりなされていません。つまり、企業が[破損状況をテスト](#test)し、[イシューを報告する](#report-issues)ことが特に重要となっています。 + +エンタープライズ SaaS 統合では、以下で説明するサードパーティデプリケーショントライアルを使用できるようになります。 + +## 広告以外のユースケースおけるサードパーティデプリケーショントライアルの期間延長リクエスト + +ウェブ上のこれまでの多くの廃止と同様に、サイトが必要な変更を加えるにはさらに時間がかかる場合があることを理解しています。このようなプライバシー関連の変更に関しては、ウェブを使用する人々の最善の利益とのバランスも考慮する必要があります。 + +そこで、クロスサイトコンテキストで使用されるサイトまたはサービスが限定期間でサードパーティ Cookie に継続的にアクセスできるようにするための登録を行える[デプリケーショントライアル](/docs/web-platform/origin-trials/#deprecation-trials)を提供する予定です。 + +{% Aside 'key-term' %} + +デプリケーショントライアルは、機能を一時的に再度有効にすることを可能にする[オリジントライアル](/docs/web-platform/origin-trials/#deprecation-trials)の一種です。 + +{% endAside %} + +計画が進むにつれて詳細を共有していきますが、まずは要点をいくつか説明します。 + +- これは、[サードパーティ](/docs/web-platform/third-party-origin-trials/)デプリケーショントライアルであり、サードパーティの埋め込みが一時的にサードパーティ Cookie の使用を継続することにオプトインできます。 +- 登録には、重要なユーザージャーニーに大きな影響を与える機能にのみデプリケーショントライアルが使用されることを保証するためのレビュープロセスが要求され、登録はケースバイケースで検討されます。 +- [CMA が説明しているように、2024 年の初めに計画されている広告テスト](https://www.gov.uk/cma-cases/investigation-into-googles-privacy-sandbox-browser-changes#industry-testing)に干渉することはありません。したがって、広告のユースケースはデプリケーショントライアルの対象にはなりません。 + +**次のステップ:** 今月、さらなる詳細を記載した [Intent](https://goo.gle/blink-intents) を [blink-devメーリングリスト](https://groups.google.com/a/chromium.org/g/blink-dev)に公開し、ここでドキュメントの更新を続けます。 + +## 重要なユーザーエクスペリエンスの維持 + +クロスサイト Cookie は、四半世紀以上にわたってウェブの重要な部分を占めてきました。そのため、あらゆる変更、特に破壊的な変更は、調整された段階的なアプローチを必要とする複雑なプロセスとなっています。追加の Cookie 属性とプライバシーに重点を置いた新しい API がユースケースの大部分を占めていますが、これらのサイトを使用するユーザーのエクスペリエンスを損なわないようにする必要がある特定のシナリオもあります。 + +これらは主に、トップレベルサイトがポップアップウィンドウを開くか、操作のためにサードパーティサイトにリダイレクトし、その後トップレベル サイトに戻り、その戻る過程において、または埋め込みのコンテキストで Cookie を使用する認証またはペイメントフローです。私たちはこれらのシナリオを識別するための一時的なヒューリスティック セットを提供し、サイトが限られた時間内でサードパーティ Cookie を許可して必要な変更を実装するための期間を延長する予定です。 + +**次のステップ:** 今月、さらなる詳細を記載した Intent を blink-dev メーリングリストに公開し、ここでドキュメントの更新を続けます。 + +## サードパーティ Cookie に関するイシューの報告とサポート {: #report-issues } + +サードパーティ Cookie を使用しない場合にサイトが機能しなくなるさまざまなシナリオを確実に把握し、サイトがサードパーティ Cookie の依存関係から移行できるようにするためのガイダンス、ツール、機能を確実に提供したいと考えています。サードパーティ Cookie が無効になっているためにサイトまたはサービスが機能しなくなっている場合は、破損トラッカー([goo.gle/report-3pc-broken](https://goo.gle/report-3pc-broken))に報告してください。 + +廃止プロセスと Chrome の計画についてのご質問がございましたら、開発者サポートリポジトリで [「third-party cookies deprecation」タグを使用して新しいイシューを作成](https://github.com/GoogleChromeLabs/privacy-sandbox-dev-support/issues/new/choose)してください。 diff --git a/site/ja/docs/privacy-sandbox/demos/index.md b/site/ja/docs/privacy-sandbox/demos/index.md new file mode 100644 index 000000000..e254b643b --- /dev/null +++ b/site/ja/docs/privacy-sandbox/demos/index.md @@ -0,0 +1,36 @@ +--- +layout: layouts/doc-post.njk +title: プライバシーサンドボックスのデモ +subhead: + デモと Colab で、プライバシーサンドボックス API について説明します。 +description: + デモと Colab で、プライバシーサンドボックス API について説明します。 +date: 2023-08-18 +updated: 2023-08-29 +authors: + - nmichell +--- + +プライバシー サンドボックス API に関する多数のデモが用意されています。ほとんどのデモでは API に精通している必要があるため、ドキュメントをまだお読みでない場合はデモとともにリストされているリンクを確認してください。 + +<p></p> + +## デモと Colab + +{% Partial 'privacy-sandbox/demos/paapi.njk' %} + +{% Partial 'privacy-sandbox/demos/topics.njk' %} + +{% Partial 'privacy-sandbox/demos/ara.njk' %} + +{% Partial 'privacy-sandbox/demos/shared-storage.njk' %} + +{% Partial 'privacy-sandbox/demos/chips.njk' %} + +{% Partial 'privacy-sandbox/demos/fps.njk' %} + +{% Partial 'privacy-sandbox/demos/permissions-policy.njk' %} + +{% Partial 'privacy-sandbox/demos/ua-reduction.njk' %} + +{% Partial 'privacy-sandbox/demos/private-state.njk' %} diff --git a/site/ja/docs/privacy-sandbox/status/index.md b/site/ja/docs/privacy-sandbox/status/index.md index 396464b69..fb9d7fe2a 100644 --- a/site/ja/docs/privacy-sandbox/status/index.md +++ b/site/ja/docs/privacy-sandbox/status/index.md @@ -4,14 +4,18 @@ title: API のステータスと機能のリリース subhead: Chrome プラットフォームのステータス、リソース、機能リリースのタイムラインをご覧ください。 description: Chrome プラットフォームのステータス、リソース、機能リリースのタイムラインをご覧ください。 date: 2021-05-18 -updated: 2023-03-16 +updated: 2023-10-09 authors: - alexandrawhite --- -プライバシー サンドボックスの各提案は、開発プロセスのさまざまな段階にあります。それぞれの提案には、予想される可用性が異なる機能が個別に存在します。 +プライバシーサンドボックスの提案は、それぞれに開発プロセスのさまざまな段階にあります。各提案には、期待される可用性が異なる個々の機能が存在します。 -提案または API に関する最新情報を確認するには、それぞれの概要ドキュメントと[プライバシー サンドボックス タイムライン](https://privacysandbox.com/open-web/)にアクセスしてください。 +提案または API に関する最新情報を確認するには、それぞれの概要ドキュメントと[プライバシーサンドボックスのタイムライン](https://privacysandbox.com/open-web/)をご覧ください。 + +## 集計サービス + +{% Partial 'privacy-sandbox/timeline/aggregation-service.njk' %} ## アトリビューション レポート @@ -37,18 +41,6 @@ authors: {% Partial 'privacy-sandbox/timeline/fenced-frames-features.njk' %} -## First-Party Sets - -{% Partial 'privacy-sandbox/timeline/first-party-sets.njk' %} - -## FLEDGE - -[TURTLEDOVE](https://github.com/WICG/turtledove) の子孫。 - -{% Partial 'privacy-sandbox/timeline/fledge.njk' %} - -{% Partial 'privacy-sandbox/timeline/fledge-features.njk' %} - ## IP 保護 {% Partial 'privacy-sandbox/timeline/ip-protection.njk' %} @@ -57,19 +49,23 @@ authors: {% Partial 'privacy-sandbox/timeline/private-aggregation.njk' %} +{% Partial 'privacy-sandbox/timeline/private-aggregation-features.njk' %} + ## プライベートステートトークン {% Partial 'privacy-sandbox/timeline/private-state-tokens.njk' %} -## Topics API +## Protected Audience -{% Partial 'privacy-sandbox/timeline/topics.njk' %} +[TURTLDOVE](https://github.com/WICG/turtledove) の後継。以前は FLEDGE と呼ばれていました。詳細については、[保留中の Protected Audience API 機能のステータス](/docs/privacy-sandbox/protected-audience-api/feature-status/)も参照してください。 + +{% Partial 'privacy-sandbox/timeline/fledge.njk' %} -## ユーザーエージェントの削減と User-Agent Client Hints (UA-CH) +{% Partial 'privacy-sandbox/timeline/fledge-features.njk' %} -ブラウザが提供するデータを制限して機密情報が含まれないようにし、フィンガープリンティングを削減します。 +## Related Website Sets(以前の First-Party Sets) -{% Partial 'privacy-sandbox/timeline/ua-ch.njk' %} +{% Partial 'privacy-sandbox/timeline/first-party-sets.njk' %} ## 共有ストレージ @@ -77,6 +73,18 @@ authors: {% Partial 'privacy-sandbox/timeline/shared-storage-features.njk' %} +## Topics API + +{% Partial 'privacy-sandbox/timeline/topics.njk' %} + +{% Partial 'privacy-sandbox/timeline/topics-features.njk' %} + +## ユーザーエージェントの削減と User-Agent Client Hints(UA-CH) + +ブラウザが提供するデータを制限して機密情報が含まれないようにし、フィンガープリンティングを削減します。 + +{% Partial 'privacy-sandbox/timeline/ua-ch.njk' %} + {% Details %} {% DetailsSummary %} ## 終了した提案 @@ -88,7 +96,7 @@ authors: [Topics API](#topics) に置き換えられました。 - [Chrome プラットフォームのステータス](https://www.chromestatus.com/features/5710139774468096)。 -- 最初の[オリジントライアル](https://groups.google.com/a/chromium.org/g/blink-dev/c/MmijXrmwrJs)は終了しました。最新情報については、<a>Intent to Experiment</a> をご覧ください。 +- 最初のオリジントライアルは終了しました。最新情報については、[Intent to Experiment](https://groups.google.com/a/chromium.org/g/blink-dev/c/MmijXrmwrJs) をご覧ください。 - [Blink のステータス](https://groups.google.com/a/chromium.org/g/blink-dev/search?q=floc)。 - [API の提案](https://github.com/WICG/floc)は、[WICG](https://www.w3.org/community/wicg/)、インタレストグループと検討されました。 - [GitHub](https://github.com/WICG/floc): API に関する質問とディスカッションについては、[イシュー](https://github.com/WICG/floc/issues)をご覧ください。 From 7db0c28e1a5cb7694ad68ef6d210edf6cc877907 Mon Sep 17 00:00:00 2001 From: Nancymic2 <nmichell@google.com> Date: Fri, 27 Oct 2023 09:18:45 -0400 Subject: [PATCH 981/982] Create PS Q3 feedback report (#7667) * first commit, q3 feedback * copy edits, formatting * subhead levels * subhead levels * summarizing * typo * typo * typo * typo * typo * typo * typo --- .../en/docs/privacy-sandbox/feedback/index.md | 1 + .../feedback/report-2022-q1.md | 4 +- .../feedback/report-2022-q2.md | 4 +- .../feedback/report-2022-q3.md | 4 +- .../feedback/report-2022-q4.md | 4 +- .../feedback/report-2023-q1.md | 4 +- .../feedback/report-2023-q2.md | 4 +- .../feedback/report-2023-q3.md | 1758 +++++++++++++++++ 8 files changed, 1771 insertions(+), 12 deletions(-) create mode 100644 site/en/docs/privacy-sandbox/feedback/report-2023-q3.md diff --git a/site/en/docs/privacy-sandbox/feedback/index.md b/site/en/docs/privacy-sandbox/feedback/index.md index 0c7120571..8595a5c6e 100644 --- a/site/en/docs/privacy-sandbox/feedback/index.md +++ b/site/en/docs/privacy-sandbox/feedback/index.md @@ -32,6 +32,7 @@ Regular updates for each Privacy Sandbox API are published on this site. In particular, these updates will cover a summary of common feedback themes per API. + * [Feedback report for 2023 Q3](/docs/privacy-sandbox/feedback/report-2023-q3/) * [Feedback report for 2023 Q2](/docs/privacy-sandbox/feedback/report-2023-q2/) * [Feedback report for 2023 Q1](/docs/privacy-sandbox/feedback/report-2023-q1/) * [Feedback report for 2022 Q4](/docs/privacy-sandbox/feedback/report-2022-q4/) diff --git a/site/en/docs/privacy-sandbox/feedback/report-2022-q1.md b/site/en/docs/privacy-sandbox/feedback/report-2022-q1.md index 9f23964dd..cb8a54ccf 100644 --- a/site/en/docs/privacy-sandbox/feedback/report-2022-q1.md +++ b/site/en/docs/privacy-sandbox/feedback/report-2022-q1.md @@ -2,10 +2,10 @@ layout: layouts/doc-post.njk title: Feedback Report - 2022 Q1 subhead: > - Quarterly report for 2022 Q1 summarising the ecosystem feedback received on + Quarterly report for 2022 Q1 summarizing the ecosystem feedback received on Privacy Sandbox proposals and Chrome's response. description: > - Quarterly report for 2022 Q1 summarising the ecosystem feedback received on + Quarterly report for 2022 Q1 summarizing the ecosystem feedback received on Privacy Sandbox proposals and Chrome's response. date: 2022-05-17 authors: diff --git a/site/en/docs/privacy-sandbox/feedback/report-2022-q2.md b/site/en/docs/privacy-sandbox/feedback/report-2022-q2.md index 9407bfc63..8b102b63b 100644 --- a/site/en/docs/privacy-sandbox/feedback/report-2022-q2.md +++ b/site/en/docs/privacy-sandbox/feedback/report-2022-q2.md @@ -2,10 +2,10 @@ layout: layouts/doc-post.njk title: Feedback Report - 2022 Q2 subhead: > - Quarterly report for 2022 Q2 summarising the ecosystem feedback received on + Quarterly report for 2022 Q2 summarizing the ecosystem feedback received on Privacy Sandbox proposals and Chrome's response. description: > - Quarterly report for 2022 Q2 summarising the ecosystem feedback received on + Quarterly report for 2022 Q2 summarizing the ecosystem feedback received on Privacy Sandbox proposals and Chrome's response. date: 2022-07-27 authors: diff --git a/site/en/docs/privacy-sandbox/feedback/report-2022-q3.md b/site/en/docs/privacy-sandbox/feedback/report-2022-q3.md index 1350b0942..8552ebeeb 100644 --- a/site/en/docs/privacy-sandbox/feedback/report-2022-q3.md +++ b/site/en/docs/privacy-sandbox/feedback/report-2022-q3.md @@ -2,10 +2,10 @@ layout: layouts/doc-post.njk title: Feedback Report - 2022 Q3 subhead: > - Quarterly report for 2022 Q3 summarising the ecosystem feedback received on + Quarterly report for 2022 Q3 summarizing the ecosystem feedback received on Privacy Sandbox proposals and Chrome's response. description: > - Quarterly report for 2022 Q3 summarising the ecosystem feedback received on + Quarterly report for 2022 Q3 summarizing the ecosystem feedback received on Privacy Sandbox proposals and Chrome's response. date: 2022-10-27 authors: diff --git a/site/en/docs/privacy-sandbox/feedback/report-2022-q4.md b/site/en/docs/privacy-sandbox/feedback/report-2022-q4.md index d1ee2c347..d5889f34f 100644 --- a/site/en/docs/privacy-sandbox/feedback/report-2022-q4.md +++ b/site/en/docs/privacy-sandbox/feedback/report-2022-q4.md @@ -2,10 +2,10 @@ layout: layouts/doc-post.njk title: Feedback Report - 2022 Q4 subhead: > - Quarterly report for 2022 Q4 summarising the ecosystem feedback received on + Quarterly report for 2022 Q4 summarizing the ecosystem feedback received on Privacy Sandbox proposals and Chrome's response. description: > - Quarterly report for 2022 Q4 summarising the ecosystem feedback received on + Quarterly report for 2022 Q4 summarizing the ecosystem feedback received on Privacy Sandbox proposals and Chrome's response. date: 2023-01-31 authors: diff --git a/site/en/docs/privacy-sandbox/feedback/report-2023-q1.md b/site/en/docs/privacy-sandbox/feedback/report-2023-q1.md index 886035151..82362b326 100644 --- a/site/en/docs/privacy-sandbox/feedback/report-2023-q1.md +++ b/site/en/docs/privacy-sandbox/feedback/report-2023-q1.md @@ -2,10 +2,10 @@ layout: layouts/doc-post.njk title: Feedback Report - 2023 Q1 subhead: > - Quarterly report for 2023 Q1 summarising the ecosystem feedback received on + Quarterly report for 2023 Q1 summarizing the ecosystem feedback received on Privacy Sandbox proposals and Chrome's response. description: > - Quarterly report for 2023 Q1 summarising the ecosystem feedback received on + Quarterly report for 2023 Q1 summarizing the ecosystem feedback received on Privacy Sandbox proposals and Chrome's response. date: 2023-04-27 authors: diff --git a/site/en/docs/privacy-sandbox/feedback/report-2023-q2.md b/site/en/docs/privacy-sandbox/feedback/report-2023-q2.md index 487e8df2d..67529a9cc 100644 --- a/site/en/docs/privacy-sandbox/feedback/report-2023-q2.md +++ b/site/en/docs/privacy-sandbox/feedback/report-2023-q2.md @@ -2,10 +2,10 @@ layout: layouts/doc-post.njk title: Feedback Report - 2023 Q2 subhead: > - Quarterly report for 2023 Q2 summarising the ecosystem feedback received on + Quarterly report for 2023 Q2 summarizing the ecosystem feedback received on Privacy Sandbox proposals and Chrome's response. description: > - Quarterly report for 2023 Q1 summarising the ecosystem feedback received on + Quarterly report for 2023 Q2 summarizing the ecosystem feedback received on Privacy Sandbox proposals and Chrome's response. date: 2023-07-27 authors: diff --git a/site/en/docs/privacy-sandbox/feedback/report-2023-q3.md b/site/en/docs/privacy-sandbox/feedback/report-2023-q3.md new file mode 100644 index 000000000..db3db04a7 --- /dev/null +++ b/site/en/docs/privacy-sandbox/feedback/report-2023-q3.md @@ -0,0 +1,1758 @@ +--- +layout: layouts/doc-post.njk +title: Feedback Report - 2023 Q3 +subhead: > + Quarterly report for 2023 Q3 summarising the ecosystem feedback received on + Privacy Sandbox proposals and Chrome's response. +description: > + Quarterly report for 2023 Q3 summarising the ecosystem feedback received on + Privacy Sandbox proposals and Chrome's response. +date: 2023-10-26 +authors: + - robertyang +--- + +<!-- noop --> +As part of its commitments to the CMA, Google has agreed to publicly provide +quarterly reports on the stakeholder engagement process for its Privacy Sandbox +proposals (refer to paragraphs 12 and 17(c)(ii) of [the +Commitments](https://assets.publishing.service.gov.uk/media/62052c6a8fa8f510a204374a/100222_Appendix_1A_Google_s_final_commitments.pdf)). +These Privacy Sandbox feedback summary reports are generated by aggregating +feedback received by Chrome from the various sources as listed in the [feedback +overview](/docs/privacy-sandbox/feedback/), including but not limited to: GitHub +Issues, the feedback form made available on +[privacysandbox.com](https://privacysandbox.com/), meetings with industry +stakeholders, and web standards forums. Chrome welcomes the feedback received +from the ecosystem and is actively exploring ways to integrate learnings into +design decisions. + +Feedback themes are ranked by prevalence per API. This is done by taking an +aggregation of the amount of feedback that the Chrome team has received around a +given theme and organizing in descending order of quantity. The common feedback +themes were identified by reviewing topics of discussion from public meetings +(W3C, PatCG, IETF), direct feedback, GitHub, and commonly asked questions +surfacing through Google's internal teams and public forms. + +More specifically, meeting minutes for web standard bodies meetings were +reviewed and, for direct feedback, Google's records of 1:1 stakeholder meetings, +emails received by individual engineers, the API mailing list, and the public +feedback form were considered. Google then coordinated between the teams +involved in these various outreach activities to determine the relative +prevalence of the themes emerging in relation to each API. + +The explanations of Chrome's responses to feedback were developed from published +FAQs, actual responses made to issues raised by stakeholders, and determining a +position specifically for the purposes of this public reporting exercise. +Reflecting the current focus of development and testing, questions and feedback +were received in particular with respect to Topics, Protected Audience, and Attribution +Reporting APIs. + +Feedback received after the end of the current reporting period may not yet have +a considered Chrome response. + +{% Details %} {% DetailsSummary %} + +**Glossary of acronyms** + +{% endDetailsSummary %} + +<dl> +<dt>CHIPS</dt> <dd><a href="/docs/privacy-sandbox/chips/">Cookies Having Independent Partitioned State</a></dd> +<dt>DSP</dt> <dd>Demand-side Platform</dd> +<dt>FedCM</dt> <dd><a href="/docs/privacy-sandbox/fedcm/">Federated Credential Management</a></dd> +<dt>FPS</dt> <dd><a href="/docs/privacy-sandbox/first-party-sets/">First Party Sets</a></dd> +<dt>IAB</dt> <dd><a href="https://www.iab.com/">Interactive Advertising Bureau</a></dd> +<dt>IDP</dt> <dd>Identity Provider</dd> +<dt>IETF</dt> <dd><a href="https://www.ietf.org/">Internet Engineering Task Force</a></dd> +<dt>IP</dt> <dd>Internet Protocol address</dd> +<dt>openRTB</dt><dd><a href="https://iabtechlab.com/standards/openrtb/#:~:text=OpenRTB%20is%20the%20communication%20protocol,in%20the%20digital%20advertising%20industry.">Real-time bidding</a></dd> +<dt>OT</dt> <dd><a href="/docs/web-platform/origin-trials/">Origin Trial</a></dd> +<dt>PatCG</dt> <dd><a href="https://www.w3.org/community/patcg/">Private Advertising Technology Community Group</a></dd> +<dt>RP</dt> <dd>Relying Party</dd> +<dt>SSP</dt> <dd>Supply-side Platform</dd> +<dt>TEE</dt> <dd><a href="/docs/privacy-sandbox/glossary/#tee">Trusted Execution Environment</a> +<dt>UA</dt> <dd><a href="/docs/privacy-sandbox/user-agent/">User Agent string</a></dd> +<dt>UA-CH</dt> <dd><a href="/docs/privacy-sandbox/user-agent/">User-Agent Client Hints</a></dd> +<dt>W3C</dt> <dd><a href="https://www.w3.org/">World Wide Web Consortium</a></dd> +<dt>WIPB</dt> <dd><a href="/docs/privacy-sandbox/gnatcatcher/">Willful IP Blindness</a></dd> +</dl> + +{% endDetails %} + +## General feedback, no specific API or Technology + +<table> + <thead> + <tr> + <th><strong>Feedback Theme </strong></th> + <th><strong>Summary</strong></th> + <th><strong>Chrome Response</strong></th> + </tr> + </thead> + <tbody> + <tr> + <td style="vertical-align: top;">Ecosystem readiness</td> + <td style="vertical-align: top;">SSPs highlighted a concern with publishers not being ready and not +doing the required deployment work.</td> + <td style="vertical-align: top;">Privacy Sandbox has outreach focused specifically on educating +publishers, which includes dedicated webinars and meetings with both +publishers and SSPs present to drive deployment work.</td> + </tr> + <tr> + <td style="vertical-align: top;">Third-party cookie deprecation</td> + <td style="vertical-align: top;">Concerns over third-party cookie deprecation (3PCD) ramp up in Q4 2023 due to industry tech blackout.</td> + <td style="vertical-align: top;">The timeline for the Privacy Sandbox has been discussed with the CMA, +with sequencing leading to a second half of 2024 readiness. Privacy +Sandbox will publish more detailed information on the sequencing of +ramping up 3PCD. Under the Commitments, 3PCD is subject to the CMA's +competition concerns being addressed.</td> + </tr> + <tr> + <td style="vertical-align: top;">Google Ad Manager</td> + <td style="vertical-align: top;">Google Ad Manager refuses to expose the API surface making testing +difficult.</td> + <td style="vertical-align: top;"><strong>Response provided by Google Ad Manager:</strong> For the reasons explained in <a href="#ad-manager">this response by Google Ad Manager</a>, Google Ad Manager's plans for its +Protected Audience API integration do not include supporting Google's +publisher ad server without control of the top-level auction. </td> + </tr> + <tr> + <td style="vertical-align: top;">Google Ad Manager</td> + <td style="vertical-align: top;">Google Ad Manager has a secret floor price that is only exposed to +AdX or Open Bidding SSPs.</td> + <td style="vertical-align: top;"><a +href="https://github.com/google/ads-privacy/blob/master/proposals/fledge-multiple-seller-testing/README.md#technical-details">Google +Ad Manager's public documentation</a> says that the winner of the +contextual auction is passed to the top-level scoring logic and not +to any component auction, including AdX or Open Bidding. <br> +Furthermore, that documentation says of the top-level scoring logic: +"Ad Manager will compare the winning bid of each component auction, +including Ad Manager's own component auction for interest group bids +of its buyers, as well as the best contextual ad (which is selected +via dynamic allocation), and will serve the ad with the highest bid."</td> + </tr> + <tr> + <td style="vertical-align: top;">Google Ad Manager</td> + <td style="vertical-align: top;">Google Ads products should be subject to the same rules as +third-parties' ads products.</td> + <td style="vertical-align: top;">Google Ads products are already subjected to the same rules as third +parties.</td> + </tr> + <tr> + <td style="vertical-align: top;">Chrome-facilitated testing</td> + <td style="vertical-align: top;">Add labels for browsers not in A or B.</td> + <td style="vertical-align: top;">We are not considering doing so at this time, as our investigation +has found that adding non-experiment labels may complicate privacy +concerns around traffic in incognito mode.</td> + </tr> + <tr> + <td style="vertical-align: top;">Advertising agency</td> + <td style="vertical-align: top;">Can agencies or companies without JavaScript on websites use Privacy +Sandbox APIs?</td> + <td style="vertical-align: top;">Anyone can call the Privacy Sandbox APIs. If an agency or anyone else +wants to build technologies directly on the APIs they can. +Client-side APIs require integrating with the client, just as cookies +do. Many of the APIs, like cookies, also have an HTTP header +interface. We've already seen one ad industry framework, Prebid, +build client-side integrations with the APIs. Other organizations +could do the same.</td> + </tr> + <tr> + <td style="vertical-align: top;">Client-side Solutions</td> + <td style="vertical-align: top;">Why is Google adopting client-side solutions for Privacy Sandbox when +an engineer has previously expressed concern on the scalability of +such solutions in 2012?</td> + <td style="vertical-align: top;">Privacy-enhancing technology (PET) as a field of study has evolved +significantly since 2012 and, with it, commercially viable +applications. At the core of Privacy Sandbox are combinations of PETs +which wouldn't have been feasible over a decade ago. In addition, +personal computing power has increased, as have consumer expectations +of browsers and regulatory expectations of privacy.</td> + </tr> + <tr> + <td style="vertical-align: top;">Machine Learning</td> + <td style="vertical-align: top;">What is Google's planned usage of Privacy Sandbox for machine +learning purposes?</td> + <td style="vertical-align: top;">Much of the ad tech ecosystem uses machine learning today and we do +not expect that to change. Privacy Sandbox does not prevent ad tech +companies or anyone else from continuing to use machine learning. Nor +does Privacy Sandbox require that companies integrating with its APIs +use machine learning. It is reasonable to expect that companies will +continue building products and services in ways that meet the needs +of their customers, whether that includes machine learning or not. +Any machine learning that Privacy Sandbox integrators do build will +obviously be known to them and thus not be obscured to them.</td> + </tr> + <tr> + <td style="vertical-align: top;">Data verification</td> + <td style="vertical-align: top;">How can companies verify that the data they receive from using the +Privacy Sandbox is accurate and is Google willing to be reviewed via +an entity such as the Media Ratings Council (MRC)?</td> + <td style="vertical-align: top;">Privacy Sandbox APIs are built within the open-source platform that +powers Chrome. The portions of the APIs meant to run in Trusted +Execution Environments are also open source and auditable. Anyone who +wants to inspect the code can, including MRC.</td> + </tr> + <tr> + <td style="vertical-align: top;">(Also reported in previous quarters) Production Support</td> + <td style="vertical-align: top;">What is the process in place for Chrome to support Privacy Sandbox +technical issues and escalations affecting the ecosystem?</td> + <td style="vertical-align: top;">Google provides a range of channels to allow ad techs to report +technical issues and enable any necessary escalations to resolve such +issues. In addition, Chrome expects to further build and scale a +process to resolve technical issues and escalations affecting the +health of the ecosystem. Chrome is committed to ensuring resources +for this effort. <br> +Please see our <a +href="https://developer.chrome.com/docs/privacy-sandbox/feedback/">developer +post</a> for more information on the public and private forums for +feedback and escalation.</td> + </tr> + <tr> + <td style="vertical-align: top;">Chrome-facilitated testing modes</td> + <td style="vertical-align: top;">More information about the timelines and exact implementations for +the Chrome-facilitated testing modes.</td> + <td style="vertical-align: top;">We have shared a <a +href="https://developer.chrome.com/docs/privacy-sandbox/chrome-testing/">blog post</a> +about testing modes and are working to share more information soon.<br> +We are <a +href="https://developer.chrome.com/docs/privacy-sandbox/chrome-testing/">welcoming suggestions</a> for what size the testing mode labels +should be.</td> + </tr> + <tr> + <td style="vertical-align: top;">Integration with other industry standards</td> + <td style="vertical-align: top;">Will the Privacy Sandbox APIs connect to either or both TCF v2.* and +Consent Mode?</td> + <td style="vertical-align: top;">We do not have plans to integrate Privacy Sandbox APIs directly with +TCF v2 or Consent Mode. However, companies and industry trade groups +are welcome to adapt their products and frameworks to work in +conjunction with Privacy Sandbox APIs. For example, with frameworks +like TCF, each participant must determine its own compliance approach +based on the TCF signal it receives and the associated TCF policies. +We expect companies to determine when and how to use various +functionality our Privacy Sandbox building blocks offer.</td> + </tr> + </tbody> +</table> + +## Enrollment & Attestation + +<table> + <thead> + <tr> + <th><strong>Feedback Theme </strong></th> + <th><strong>Summary</strong></th> + <th><strong>Chrome Response</strong></th> + </tr> + </thead> + <tbody> + <tr> + <td style="vertical-align: top;">Restriction</td> + <td style="vertical-align: top;">Enrollment process means Google can decide which company in the +ecosystem is allowed to use Privacy Sandbox APIs.</td> + <td style="vertical-align: top;">The Enrollment and Attestation process essentially entails +verification of the entity (for example, the entity has a DUNs number, can +provide a link to a privacy policy, and so forth) and makes the public +attestation a requirement for calling the APIs. Entities that can +successfully fulfill the enrollment requirements will be validated. +For companies that do not have a DUNs, we are providing an expedited, +complimentary process with Dun & Bradstreet to acquire one. The +objective is to enhance privacy protections of the APIs (by the +measures just mentioned) and also to add a layer of transparency to +the Privacy Sandbox APIs, so interested parties can better understand who is using +which API and what attestations they are making. We are open to +further industry feedback on this issue, which has already been used +to shape the process.</td> + </tr> + <tr> + <td style="vertical-align: top;">Re-enrollment overhead</td> + <td style="vertical-align: top;">Attestation file expires every 12 months and requires websites to +re-enroll.</td> + <td style="vertical-align: top;">We've heard feedback from the ecosystem and amended our approach +accordingly. This means that files will no longer expire after 12 +months or any set period of time. We are updating our enrollment +developer guide with additional context.</td> + </tr> + <tr> + <td style="vertical-align: top;">Attestation file</td> + <td style="vertical-align: top;">How is the attestation file used?</td> + <td style="vertical-align: top;">All companies calling relevance and measurement APIs will be required +by the enforcement deadline to upload the attestation file on their +site and keep it for public view as long as you are intending to +continue calling the APIs.<br> +<br> +Websites could expect approximately one request per hour from Privacy +Sandbox, and other potential entities may query as well. This will +be conducted via the enrollment system's own mechanism to query +enrolled entities' servers and ensure the attestation file is valid. +<br> +<br> +Attestations will be included in Transparency Reports and viewable by +the general public. We expect companies to act in accordance with +their stated attestations, as will the rest of the ecosystem and +relevant regulatory bodies.</td> + </tr> + <tr> + <td style="vertical-align: top;">Enrollment</td> + <td style="vertical-align: top;">Is enrollment per site or per origin?</td> + <td style="vertical-align: top;">Enrollment is at the site level.</td> + </tr> + </tbody> +</table> + +## Show Relevant Content & Ads + +### Topics + +<table> + <thead> + <tr> + <th><strong>Feedback Theme </strong></th> + <th><strong>Summary</strong></th> + <th><strong>Chrome Response</strong></th> + </tr> + </thead> + <tbody> + <tr> + <td style="vertical-align: top;">Performance</td> + <td style="vertical-align: top;">Performance concerns on the impact of Topics opt-in rate in the +European Economic Area.</td> + <td style="vertical-align: top;">We would suggest to concerned stakeholders to contact your relevant +Data Protection Authority about this issue. They are best placed to +address such concerns and influence whether applications of +privacy-enhancing technologies are incentivized by laws or instead +treated like tracking, requiring the same approaches to consent. The +latter could result in APIs like those in Privacy Sandbox not being +available as often.</td> + </tr> + <tr> + <td style="vertical-align: top;">Enrollment</td> + <td style="vertical-align: top;">Do downstream bidders need to enroll in Topics API to use Topics +signals from upstream SSPs?</td> + <td style="vertical-align: top;">The downstream receivers of topics beyond the initial Topics API +caller do not need to be enrolled, though many are likely to be +enrolled for other API usage. A list of Privacy Sandbox enrollees +will be provided programmatically as part of the program's +transparency efforts, which would allow an interested caller of the +Topics API to check if the recipient they are sending a topic to is +enrolled, if the caller should want to.</td> + </tr> + <tr> + <td style="vertical-align: top;">Topics filtering</td> + <td style="vertical-align: top;">Request to apply another caller's filtering to the topics that they +retrieve on the page, in order to share only what buyers are eligible +to retrieve.</td> + <td style="vertical-align: top;">We are considering this request and welcome <a +href="https://github.com/patcg-individual-drafts/topics/issues">additional +feedback</a> from the ecosystem.</td> + </tr> + <tr> + <td style="vertical-align: top;">Site exclusion</td> + <td style="vertical-align: top;">Exclude websites from contributing to a user's Topics.</td> + <td style="vertical-align: top;">Topics are not called by default. It's important to note that no page +content is taken into account when topics are selected, and all +topics are curated to make sure they are not sensitive. A website can +also restrict their site from being included in topic calculation via +the following permission policy header: <code>Permissions-Policy: +browsing-topics=()</code></td> + </tr> + <tr> + <td style="vertical-align: top;">Topics observation</td> + <td style="vertical-align: top;">Allow publishers to give permissions for Chrome to classify topics +based on page content (for example, head or body).</td> + <td style="vertical-align: top;">We previously considered offering functionality to classify sites +into topics based on page content, and made the decision not to move +forward based on privacy and security concerns. This proposal may +mitigate some of those concerns, but it's unclear as to what extent. Due +to the upcoming CMA experiment period, we don't expect this change to +occur before 3PCD. We <a +href="https://github.com/patcg-individual-drafts/topics/issues/224">welcome additional feedback here</a>.</td> + </tr> + <tr> + <td style="vertical-align: top;">Topics observation</td> + <td style="vertical-align: top;">Provide more fine-grained permission policies for publishers.</td> + <td style="vertical-align: top;">Providing more +fine-grained permission policies for publishers would enable +publisher sites to negatively impact the utility of the Topics API +for the ecosystem as a whole, without it negatively impacting the +utility of the Topics API for the site itself. Refer to the <a +href="https://github.com/patcg-individual-drafts/topics/issues/92">Update permissions policy to support separate permissions for retrieve and observe</a> GitHub issue for a more detailed discussion of the topic.</td> + </tr> + <tr> + <td style="vertical-align: top;">Medical and Health Topics</td> + <td style="vertical-align: top;">Why does the Topics taxonomy not cover topics in Medical or Health +categories?</td> + <td style="vertical-align: top;">Medical and health categories are considered sensitive topics and +thus excluded from the Topics taxonomy.</td> + </tr> + <tr> + <td style="vertical-align: top;">Topics retrieval</td> + <td style="vertical-align: top;">Faster way for DSPs to get Topics without fetching using +headers.</td> + <td style="vertical-align: top;">The header methods are more performant and less costly than creating +a cross-origin iframe and making a <code>document.browsingTopics()</code> call +from it. (A cross-origin iframe must be used for the call, because +the top-level context to observe a topic must match the context from +which topics are accessed.) This was <a +href="https://github.com/patcg-individual-drafts/topics/issues/7">discussed in detail here</a>.</td> + </tr> + <tr> + <td style="vertical-align: top;">Topics retrieval</td> + <td style="vertical-align: top;">Requests to support passing Topics via headers on cross-origin script +tag requests.</td> + <td style="vertical-align: top;">From a security perspective, this isn't possible. Each document and +its execution environment are associated with a single origin–that +of the document. Third-party subresources loaded and executed within +that same environment are considered to be owned by the origin of the +document. This is to prevent unconsented data leakage from one origin +to another.<br> +<br> +An alternative is to provide a <code>browsingTopics</code> attribute on <code><script></code> +tags. This should be clean from a security perspective, and not add +additional latency. We are open to <a +href="https://github.com/patcg-individual-drafts/topics/issues/239"> +feedback</a> from interested parties.</td> + </tr> + <tr> + <td style="vertical-align: top;">Awareness</td> + <td style="vertical-align: top;">Improve public awareness of Topics API and how the API will be +used.</td> + <td style="vertical-align: top;">We've engaged with the stakeholder who provided this feedback and +this issue was <a +href="https://github.com/patcg-individual-drafts/topics/issues/223#issuecomment-1648193589">resolved on GitHub</a>. +<br> +<br> +Going forward, we'll continue supporting ecosystem understanding of +the API and we look forward to hearing views from stakeholders. In +the meantime, we suggest stakeholders wanting to know more about the +Topics API familiarize themselves with the documentation in the +<a +href="https://developer.chrome.com/en/docs/privacy-sandbox/topics/">Chrome developer guide</a>.</td> + </tr> + <tr> + <td style="vertical-align: top;">Notification</td> + <td style="vertical-align: top;">Notification to alert user when their Topics are being observed by a +website.</td> + <td style="vertical-align: top;">We <a +href="https://github.com/patcg-individual-drafts/topics/issues/222">addressed this feedback on GitHub</a>. Users can learn more about Topics controls in the <a +href="https://support.google.com/chrome/answer/13355898#zippy=%2Cmanage-ad-topics">Chrome help center</a>.</td> + </tr> + <tr> + <td style="vertical-align: top;">Machine Learning</td> + <td style="vertical-align: top;">How ML can be used to infer user Topics?</td> + <td style="vertical-align: top;">We are discussing this issue and <a +href="https://github.com/patcg-individual-drafts/topics/issues/221">welcome additional feedback</a>.</td> + </tr> + <tr> + <td style="vertical-align: top;">Usefulness for different types of stakeholders</td> + <td style="vertical-align: top;">Smaller ad tech companies may not be able to observe Topics due to +the way browsers calculate them.</td> + <td style="vertical-align: top;">Only ad techs that observed the user visit a page about the topic in +question within the past three weeks will receive a topic. If the ad +tech did not call the API in the previous three weeks for that user +on a site about that topic, then the returned value will be +empty.<br> +<br> +This feature means that ad techs whose services are used by a larger +number of site owners, and therefore have more opportunities to +observe a site visit by a given user, may receive more topics than +other ad techs. This feature is essential for the privacy protections +of the API as it limits the availability of information about a user +to only those parties who are already able to observe the same +underlying information (currently via third-party cookies).</td> + </tr> + <tr> + <td style="vertical-align: top;">XHR Request</td> + <td style="vertical-align: top;">When will Topics inclusion in <code>XMLHttpRequest</code> (XHR) requests be +deprecated?</td> + <td style="vertical-align: top;">As Chrome <a +href="https://groups.google.com/a/chromium.org/g/topics-api-announce/c/5QPSa2moCAY">announced +in August 2023</a>, Chrome began deprecating support for XHR when +transitioning from Origin Trial to General Availability.<br> +<br> +As the ramp-up of Topics progressed, XHR support was only included +for users for whom the OT features were enabled and was fully +deprecated when the individual OT experiment groups were merged.<br> +<br> +If you were using Topics with XHR, your sites will not break. The +topics just won't be added to your XHR request headers. We recommend +that you either transition to <code>fetch</code> for your request, use the iframe +attribute, or use the JavaScript API to retrieve topics. Fetch is +supported by all modern browsers, but not Internet Explorer or Opera +Mini.</td> + </tr> + <tr> + <td style="vertical-align: top;">Taxonomy and classifier update process</td> + <td style="vertical-align: top;">More information on the Topics taxonomy and classifier release +cadence and how companies can prepare for such updates.</td> + <td style="vertical-align: top;">Our response remains unchanged from Q2:<br> +<br> +As shared in the <a href="/blog/topics-enhancements/">recent blog post</a>, we expect the taxonomy to evolve +over time, and for governance of the taxonomy to eventually +transition to an external party representing stakeholders from across +the industry. We also shared the ramp-up plan in the <a href="https://groups.google.com/a/chromium.org/g/topics-api-announce/c/iNYk69wKnJs">topics-announce +group</a>.</td> + </tr> + <tr> + <td style="vertical-align: top;">Abuse</td> + <td style="vertical-align: top;">Potential attack via redirect chain.</td> + <td style="vertical-align: top;">We are <a +href="https://github.com/patcg-individual-drafts/topics/issues/217">considering this issue</a> +and welcome additional feedback.</td> + </tr> + <tr> + <td style="vertical-align: top;">Publisher Inventory Types</td> + <td style="vertical-align: top;">What types of publisher inventory will Protected Audience and Topics +testing support?</td> + <td style="vertical-align: top;">Neither Protected Audience nor Topics are inherently restrictive in +terms of the types of inventory they can be used on.</td> + </tr> + <tr> + <td style="vertical-align: top;">Ramp-up time</td> + <td style="vertical-align: top;">Recommend no ramp-up time for new taxonomies to get to 100%.</td> + <td style="vertical-align: top;">Following <a +href="https://github.com/patcg-individual-drafts/topics/issues/236">this feedback request</a> + from the ecosystem and discussion during PATCG +meetings, we have announced our plan for the <a +href="https://github.com/patcg-individual-drafts/topics/issues/236#issuecomment-1726405252">rollout of the new +taxonomy</a>.</td> + </tr> + </tbody> +</table> + +### Protected Audience API (formerly FLEDGE) + +<table> + <thead> + <tr> + <th><strong>Feedback Theme </strong></th> + <th><strong>Summary</strong></th> + <th><strong>Chrome Response</strong></th> + </tr> + </thead> + <tbody> + <tr> + <td style="vertical-align: top;">Top-Level Auctions</td> + <td style="vertical-align: top;">Ability to use Google's publisher ad server without also giving +Google Ad Manager control of the top-level Protected Audience API +auction.</td> + <td id="ad-manager" style="vertical-align: top;"><strong>Response provided by Google Ad Manager:</strong><br> +Google Ad Manager's plans for the Protected Audience API do not include supporting Google's +publisher ad server without the control of the top-level Protected Audience auction, +for the following reasons. <br> +<br> +In order to properly serve our customers in the publisher ad serving +market, Google's publisher ad server needs to retain control of the +top-level Protected Audience auction. As a publisher ad server, our role is to +provide publishers forecasting so they can negotiate direct sold +campaigns without overbooking, and to pace and deliver their direct +reservations optimally. Doing this requires running the final auction +to compare all eligible direct and indirect demand.<br> +<br> +Forecasting and pacing are core functionalities that publishers expect +from an ad server. Without accurate forecasting, publishers may end +up overselling their inventory, which puts their business reputation +at risk. Pacing is also critical, as being unable to fulfill +reservation contracts with advertisers also risks damage to the +publisher-advertiser direct relationship, which could result in +significant impact to a publishers business.<br> +<br> +In short, therefore, we do not view a publisher ad server's activity +of running the top-level Protected Audience auction as distinct from the other +activities of the publisher ad server.</td> + </tr> + <tr> + <td style="vertical-align: top;"><code>directFrom<br>SellerSignals</code></td> + <td style="vertical-align: top;"><code>directFrom<br>SellerSignals</code><br>allows Google Ad Manager to prevent the +publisher from seeing the price of its contextual auction.</td> + <td style="vertical-align: top;"><strong>Chrome response:</strong><br> +Information passed into <code>runAdAuction()</code> is not known to come from the +seller unless the seller calls <code>runAdAuction()</code> from its own iframe. In +a multi-seller auction it becomes impossible to have all sellers +create the frame calling <code>runAdAuction()</code>. <code>directFromSellerSignals</code> +addressed this issue by loading content from a subresource bundle +loaded from a seller's origin. This ensures that the authenticity and +integrity of information passed into an auction from the +seller-auctions configurations cannot be manipulated. If publishers +want to use Protected Audience API to understand any of the +information their technology providers are passing into Protected +Audience auctions, they can ask those technology providers for this +functionality.<br> +<br> +<strong>Response provided by Google Ad Manager:</strong><br> +We have maintained a strong focus on auction fairness for years, +including our promise that no price from any of a publisher's +non-guaranteed advertising sources, including non-guaranteed line +item prices, will be shared with another buyer before they bid in the +auction, which we then later reaffirmed in our <a +href="https://blog.google/around-the-globe/google-europe/some-changes-our-ad-technology/">commitments +to the French Competition Authority</a>.<br> +<br> +For Protected Audience auctions, we intend to keep our promise by leveraging +<code>directFromSellerSignals</code>, and not share the bid of any auction +participant with any other auction participant prior to completion of +the auction in multi-seller auctions. To be clear, we won't share the +price of the contextual auction with our own component auction +either, as explained in the <a +href="https://github.com/google/ads-privacy/commit/cd5d7c5336a5ce9f6c22776b4532ccd529c55210">Further clarify top-level auction dynamics</a> update.</td> + </tr> + <tr> + <td style="vertical-align: top;">Information Exposure</td> + <td style="vertical-align: top;">Sensitive business logics and contractual details may be exposed by +the browser.</td> + <td style="vertical-align: top;">The person using a web browser can see everything that is happening +in the browser. When an ad auction happens inside the browser, it is +true that the person whose browser it is could watch that auction +take place, including seeing how much different parties choose to +bid. Since a browser is the user's agent, we do not think it is +possible or desirable to try to change this. Only the person using +the browser has visibility into these operations, however. An +on-device auction run using the Protected Audience API is not +observable to any servers, including Google's.</td> + </tr> + <tr> + <td style="vertical-align: top;"><code>PerBuyerExperiment<br>GroupId</code></td> + <td style="vertical-align: top;">Current value range of<br><code>PerBuyerExperiment<br>GroupId</code><br>could allow buyers +to correlate the contextual data with the trusted server +request.</td> + <td style="vertical-align: top;">Using the Protected Audience API in this way is inconsistent with +Privacy Sandbox's mandatory attestation that API users will not try +to circumvent the Privacy Sandbox protections. In the future, the +requirement that key-value servers run in trusted execution +environments (TEEs) will provide technical protection against this +attack.</td> + </tr> + <tr> + <td style="vertical-align: top;">Same-origin policy</td> + <td style="vertical-align: top;">Relax the same-origin policy to allow for subdomains.</td> + <td style="vertical-align: top;">We are considering this request and welcome <a +href="http://github.com/WICG/turtledove/issues/813">additional feedback</a> from +the ecosystem.</td> + </tr> + <tr> + <td style="vertical-align: top;">API versioning</td> + <td style="vertical-align: top;">Request for versioning and release notes for changes to the Protected +Audience API.</td> + <td style="vertical-align: top;">We are considering this request and welcome <a +href="http://github.com/WICG/turtledove/issues/813">additional feedback</a> from +the ecosystem.</td> + </tr> + <tr> + <td style="vertical-align: top;">Multi-SSP Auctions</td> + <td style="vertical-align: top;">Allow top-level auction signals to perform JSON merges with component +signal <code>auctionSignals</code>.</td> + <td style="vertical-align: top;">We are considering this request and welcome <a +href="https://github.com/WICG/turtledove/issues/787">additional feedback</a> from +the ecosystem.</td> + </tr> + <tr> + <td style="vertical-align: top;">Bid limit</td> + <td style="vertical-align: top;">Increase the limit on the number of ad components entering the bid +from 20 to 40.</td> + <td style="vertical-align: top;">We are considering this request and welcome <a +href="http://github.com/WICG/turtledove/issues/810">additional feedback</a> from +the ecosystem on why this would be useful.</td> + </tr> + <tr> + <td style="vertical-align: top;">(Also reported in previous quarters)<br> +Performance of Protected Audience Auctions</td> + <td style="vertical-align: top;">Report from testers that Protected Audience auctions have high +latency.</td> + <td style="vertical-align: top;">On questions of latency, the Protected Audience API has generally +followed the existing standard paradigm of building controls that let +sellers decide how much time and resources the bidders can consume, +and building tools that let buyers decide how to best use the +resources available to them. These controls and tools are generally +available today, but their full benefit will only be realized after +adoption by buyers and sellers. In addition, Chrome continues to work +on a variety of infrastructure improvements to auction speed (<a +href="http://crrev.com/1190815">crrev.com/1190815</a>, <a +href="http://crrev.com/1199839">crrev.com/1199839</a>, <a +href="http://crrev.com/1201837">crrev.com/1201837</a>, <a +href="http://crrev.com/1198339">crrev.com/1198339</a>, <a +href="http://crrev.com/1197323">crrev.com/1197323</a>). <br> +<br> +We invite feedback on both halves of this latency effort: new tools +that buyers and sellers would find useful, and reports of observed +bottlenecks that Chrome engineers should investigate.</td> + </tr> + <tr> + <td style="vertical-align: top;">Buy-side filtering</td> + <td style="vertical-align: top;">Add support for buy-side filtering based on interest groups.</td> + <td style="vertical-align: top;">We have suggested several ways in which SSPs and DSPs could change +their designs to handle this:<br> +<ul> +<li>Moving some work into the DSP's Key/Value server.</li> +</ul> +<ul> +<li>SSPs creating some contextual signals and giving those to DSPs.</li> +</ul> +<ul> +<li>SSPs caching contextual signals for DSPs.</li> +</ul> +</td> + </tr> + <tr> + <td style="vertical-align: top;">Publisher Interest Group Control</td> + <td style="vertical-align: top;">Support for publishers seeking to delegate + the use of publisher-created interest groups.</td> + <td style="vertical-align: top;">We have engaged in discussions with many parties about the request. +We believe that all such use cases involved in "delegating" the +publisher-created interest groups can be accommodated now, and +furthermore that we should build additional support to make some use +cases flow more smoothly in the future.</td> + </tr> + <tr> + <td style="vertical-align: top;">(Also reported in Q2) Trusted Execution Environments</td> + <td style="vertical-align: top;">Support for Trusted Execution Environments (TEE) in non-public cloud +environments.</td> + <td style="vertical-align: top;">Our response is similar to previous quarters: <br> +<br> +While we are continuing to explore support for options beyond public +cloud-based solutions, we have no current plans to support on-premise +TEEs. At this stage, given Privacy Sandbox security requirements and +the significant challenges presented by on-premise deployments, we +believe that continuing to expand and improve cloud-based deployments +(for example, supporting Google Cloud in addition to AWS) is the most +beneficial for the ecosystem. However, we welcome additional feedback +on why such a requirement is necessary and feasible given the privacy +and security constraints.</td> + </tr> + <tr> + <td style="vertical-align: top;">Trusted Execution Environment</td> + <td style="vertical-align: top;">Components in the TEE serving path, such as the load balancer, can +observe all the traffic and have information of the IP address of +each request.</td> + <td style="vertical-align: top;">Currently IP address is passed as a metadata in request headers to +untrusted seller's ad service in the case of both Bidding and Auction +and on-device Protected Audience auctions. Refer to <a +href="https://github.com/privacysandbox/fledge-docs/blob/main/bidding_auction_services_api.md#metadata-forwarding">Metadata forwarding</a> for more information. In the long term, we plan to proxy ad tech +and tracker traffic through an IP Proxy, which will prevent +components from observing all the traffic in the serving path.</td> + </tr> + <tr> + <td style="vertical-align: top;">Time-to-Live (TTL)</td> + <td style="vertical-align: top;">Will the time-to-live (TTL) before services have to request new keys +be set or is it intended to be flexible (or dynamic)?</td> + <td style="vertical-align: top;">The TTL is generally static. Currently, the TTL for the public is 8 +days, and the rotation happens every 7 days; the TTL is also the same +for private keys in the case of the Aggregation Service. In case of +Bidding and Auction services, private and public keys are fetched +every N hours in the non-request path and cached in-memory, so that +there is no more than an N-hour delay between keys rotating and +servers picking up these keys. The 1-day buffer between key rotation +and expiry is to ensure that even if the key generation fails, the +services can continue operating. We are considering extending the TTL +to be more resilient for outages. In case of a key leak, we plan to +manually force key generation and invalidate keys sooner. Note that +public keys are cached on the clients, currently for 24 hours, again +to ensure that in case of coordinator outage, the services can still +operate.</td> + </tr> + <tr> + <td style="vertical-align: top;">Traffic Shaping</td> + <td style="vertical-align: top;">Traffic Shaping support for Bidding and Auction Services.</td> + <td style="vertical-align: top;">Buyers can indicate, based on Publisher first party data or +contextual data, demand for Protected Audience auctions. Sellers can +do similar determinations as well in the seller's ad server or Ad +Exchange server. The models can be trained on 1P data and any +aggregate reports from Protected Audience auctions. Sellers can use +this information to avoid sending requests to Bidding and Auction +servers when there is no demand for Protected Audience auctions. We +believe this can be an effective way to shape traffic.</td> + </tr> + <tr> + <td style="vertical-align: top;">Component Auction</td> + <td style="vertical-align: top;">What top level auctionSignals are shared with Component sellers?</td> + <td style="vertical-align: top;">Buyers in a component auction only receive signals from the component +seller. We are looking to share documentation around the overall +sequence of a combined auction with header bidding and Protected +Audience auction soon.</td> + </tr> + <tr> + <td style="vertical-align: top;">Video Rendering</td> + <td style="vertical-align: top;">Support for video rendering using Protected Audience and Fenced +Frames.</td> + <td style="vertical-align: top;">Protected Audience API supports video rendering using a mechanism +that relies on iframes. However, we haven't yet designed a solution +that is compatible with Fenced Frames, and this is one of the reasons +we had decided to push back Fenced Frames enforcement to 2026. That +means if a partner does decide to enforce Fenced Frames now, the +support for video would be lacking for that partner.</td> + </tr> + <tr> + <td style="vertical-align: top;">Frequency capping</td> + <td style="vertical-align: top;">(Also reported in previous quarters)<br> +Per-user frequency controls within a campaign and ad group. </td> + <td style="vertical-align: top;">Our response is unchanged from the previous reports:<br> +<br> +Protected Audience will support frequency capping for on-device +auctions and contextual and branding campaigns as well. Shared storage +and site-specific caps can also be used for additional frequency +capping controls.</td> + </tr> + <tr> + <td style="vertical-align: top;">Ad Preferences</td> + <td style="vertical-align: top;">Does Protected Audience provide a way to opt-out or blocklist by +advertiser sites or a way to leave all interest groups from the same +owner?</td> + <td style="vertical-align: top;">There are several ways for users to <a +href="https://developer.chrome.com/docs/privacy-sandbox/protected-audience-api/opt-out/#opt-out-user">block access</a> to the Protected +Audience API and other Privacy Sandbox features.</td> + </tr> + <tr> + <td style="vertical-align: top;">Same-origin policy for source URL of bidding and auction scripts</td> + <td style="vertical-align: top;">Relax the requirement that all fields that specify URLs for loading +scripts or JSON must be same-origin with the owner.</td> + <td style="vertical-align: top;">We are currently considering this request and + <a +href="https://github.com/WICG/turtledove/issues/">welcome additional feedback</a> from the ecosystem.</td> + </tr> + <tr> + <td style="vertical-align: top;"><code>forDebuggingOnly</code></td> + <td style="vertical-align: top;">Potential for <code>forDebuggingOnly<br>.reportAdAuctionWin</code> to be misused if it +remains post 3PCD.</td> + <td style="vertical-align: top;">Over the past years we have been receiving feedback from the +ecosystem regarding functionality gaps in Protected Audience once +third-party cookies are deprecated, and we are working to formulate a +plan to support them post 3PCD without compromising on the goals of +Privacy Sandbox. We welcome any additional suggestions and feedback +on missing functionality that the ecosystem would like to see.</td> + </tr> + <tr> + <td style="vertical-align: top;">Multiple Interest Groups</td> + <td style="vertical-align: top;">Use multiple interest groups in the same bid.</td> + <td style="vertical-align: top;">This is not supported in Protected Audience API today, as it would +result in a change to the underlying privacy model. We welcome + <a +href="https://github.com/WICG/turtledove/issues/818">additional discussion here</a>.</td> + </tr> + <tr> + <td style="vertical-align: top;">On-device auctions</td> + <td style="vertical-align: top;">Will Chrome on Android support on-device Protected Audience +auctions?</td> + <td style="vertical-align: top;">Yes, on-device auctions <a +href="https://chromestatus.com/feature/5733583115255808">will be supported</a> in Chrome on Android.</td> + </tr> + <tr> + <td style="vertical-align: top;">(Reported in Q2 2023) Click-related data</td> + <td style="vertical-align: top;">Add click-related data to browserSignals.</td> + <td style="vertical-align: top;">We continue to evaluate this feature request and welcome <a +href="https://github.com/WICG/turtledove/issues/579">additional +feedback</a> on why this should be prioritized. </td> + </tr> + <tr> + <td style="vertical-align: top;">Trusted Execution Environment providers</td> + <td style="vertical-align: top;">Are there material differences in the Trusted Execution Environment +offerings of different cloud providers?</td> + <td style="vertical-align: top;">We are not aware of any major differences, but we recommend the +ecosystem review the public deployment guides to see which solution +best suits their needs.<br> +<br> +<a +href="https://github.com/privacysandbox/fledge-docs/blob/main/bidding_auction_services_gcp_guide.md">Google Cloud</a>.<br> +<a +href="https://github.com/privacysandbox/fledge-docs/blob/main/bidding_auction_services_aws_guide.md">AWS</a>.</td> + </tr> + <tr> + <td style="vertical-align: top;">(Reported in previous quarters )<br> +<br> +Support for negative Interest Group targeting</td> + <td style="vertical-align: top;">An API to support negative interest group targeting: showing ads only +if a user does not belong to an interest group.</td> + <td style="vertical-align: top;">We are looking into implementing this feature and are <a +href="https://github.com/WICG/turtledove/issues/319">discussing the +request</a>.</td> + </tr> + <tr> + <td style="vertical-align: top;">Content Violation</td> + <td style="vertical-align: top;">Support features that allow users to report bad ads served by +Protected Audience API in Fenced Frames.</td> + <td style="vertical-align: top;">We believe that the existing <a +href="https://github.com/WICG/turtledove/blob/main/Fenced_Frames_Ads_Reporting.md"> +Fenced Frame Ads Reporting mechanism</a> offers good options for ad +techs who want a user-generated "Bad Ads" reporting flow. This would +allow bad ads reporting in a way essentially unchanged from the +industry standard today. We welcome additional feature requests if +any gaps remain, including during the time after third-party cookie +removal but before Fenced Frame rendering becomes widespread.</td> + </tr> + <tr> + <td style="vertical-align: top;">Private Aggregation API Reporting</td> + <td style="vertical-align: top;">How can we calculate time the user has spent in that interest group?</td> + <td style="vertical-align: top;">In Chrome M116+ you should be able to use recency as defined <a +href="https://github.com/WICG/turtledove/pull/639">pull/639</a>.</td> + </tr> + <tr> + <td style="vertical-align: top;">K-Anonymity server</td> + <td style="vertical-align: top;">More information on K-Anonymity server.</td> + <td style="vertical-align: top;">We shared more information on <a +href="https://github.com/WICG/turtledove/issues/728">K-Anonymity servers here</a> and +welcome additional feedback.</td> + </tr> + <tr> + <td style="vertical-align: top;">Dynamic Creative URLs</td> + <td style="vertical-align: top;">Support for creative URLs without pre-declaration while still +respecting k-anonymity.</td> + <td style="vertical-align: top;">We are discussing this feature request and welcome <a +href="https://github.com/WICG/turtledove/issues/729">additional +feedback</a> on why this should be prioritized.</td> + </tr> + <tr> + <td style="vertical-align: top;">K-anonymity requirement</td> + <td style="vertical-align: top;">Will k-anonymity requirement on Interest Group updates be +re-introduced?</td> + <td style="vertical-align: top;">We don't anticipate changes to the position stated in <a +href="https://github.com/WICG/turtledove/issues/361#issuecomment-1430069343">this GitHub post</a>. As announced in that post, we decided to remove the +k-anonymity requirement on Protected Audience interest group updates, +which does not have a significant impact on the API's overall privacy +protections, and we plan to consider other potential more direct +protections (such as IP address privacy or a trusted update server) at a +later date when the related technologies are more developed, deployed +and adopted.</td> + </tr> + <tr> + <td style="vertical-align: top;">Bidding & Auction Services Beta Testing</td> + <td style="vertical-align: top;">When will Bidding & Auction Services Beta testing begin?</td> + <td style="vertical-align: top;">As stated in <a +href="https://github.com/privacysandbox/fledge-docs/blob/main/bidding_auction_services_api.md#timeline-and-roadmap">Timeline and roadmap</a>, +the first phase of Bidding and Auction Services testing begins in +November 2023.</td> + </tr> + <tr> + <td style="vertical-align: top;">Roadblocking</td> + <td style="vertical-align: top;">Request to support Creative coordination for Ad Networks (SSP and DSP +are in the same company or properties).</td> + <td style="vertical-align: top;">We appreciate the feedback for this use case and we're looking to +understand whether more ad techs are interested in seeing this +supported. We <a +href="https://github.com/WICG/turtledove/issues/776">welcome additional feedback</a>.</td> + </tr> + <tr> + <td style="vertical-align: top;">Native Advertising</td> + <td style="vertical-align: top;">Fenced Frame support for Native Advertising.</td> + <td style="vertical-align: top;">We are considering supporting the use case and are discussing +<a +href="https://github.com/WICG/turtledove/issues/741">possible workarounds and solutions</a>.</td> + </tr> + <tr> + <td style="vertical-align: top;">K-anonymity</td> + <td style="vertical-align: top;">How can I maximize interest group ads that meet k-anon +thresholds?</td> + <td style="vertical-align: top;">We have shared some <a +href="https://developer.chrome.com/docs/privacy-sandbox/protected-audience-api/interest-groups/#how-can-i-maximize-interest-group-ads-that-meet-k-anon-thresholds">tactical guidance on this topic</a>.</td> + </tr> + <tr> + <td style="vertical-align: top;">POST support</td> + <td style="vertical-align: top;">Support for sending auction data via POST requests.</td> + <td style="vertical-align: top;">We are evaluating this feature request and welcome <a +href="https://github.com/WICG/turtledove/issues">additional GitHub +issue submissions</a> on why this +should be prioritized.</td> + </tr> + <tr> + <td style="vertical-align: top;">Reporting granularity</td> + <td style="vertical-align: top;">What is the reporting granularity of Fenced Frame ad reporting with +Ads Composed of Multiple Pieces?</td> + <td style="vertical-align: top;">The current design does not allow capturing product ID or position as +this may compromise user privacy. Only the <code>reserved.top_navigation</code> +can be invoked, which would be sent when there is a user activation +(such as a click) on the ad component fenced frame, which results in a +top-level navigation.</td> + </tr> + <tr> + <td style="vertical-align: top;">Ad auction</td> + <td style="vertical-align: top;">Can an SSP participating in a component auction trigger another +component auction itself?</td> + <td style="vertical-align: top;">A <code>componentSeller</code> cannot also include <code>componentAuctions</code>.<br> +The multi-seller auction only has two levels:<br> +1. The component auctions in parallel.<br> +2. The top-level auction (where the winning ad from each +<code>componentAuction</code> competes).</td> + </tr> + <tr> + <td style="vertical-align: top;">Bidding & Auction Services availability</td> + <td style="vertical-align: top;">Will Bidding & Auction be available during the Chrome facilitated +testing phase?</td> + <td style="vertical-align: top;">Bidding and Auction Server will not be available during the Chrome +facilitated testing phase.</td> + </tr> + <tr> + <td style="vertical-align: top;">Bidding signals</td> + <td style="vertical-align: top;">Allow browsers to request and delete bidding signals.</td> + <td style="vertical-align: top;">We are discussing this request and <a +href="https://github.com/privacysandbox/fledge-docs/issues/56">welcome additional feedback</a> on why +this should be prioritized.</td> + </tr> + <tr> + <td style="vertical-align: top;"><code>generateBid()</code></td> + <td style="vertical-align: top;">Ability to update interestGroup's <code>userBiddingSignals</code> through +<code>updateURL</code>.</td> + <td style="vertical-align: top;">We are considering this proposal and <a +href="https://github.com/WICG/turtledove/issues/760">welcome additional feedback</a> and discussion.</td> + </tr> + <tr> + <td style="vertical-align: top;">Publisher Inventory Types</td> + <td style="vertical-align: top;">What types of publisher inventory will be supported by Protected +Audience and TOPICS testing?</td> + <td style="vertical-align: top;">Neither Protected Audience nor Topics are inherently restrictive in +terms of the types of inventory they can be used on.</td> + </tr> + <tr> + <td style="vertical-align: top;">Server-to-Server integration</td> + <td style="vertical-align: top;">Is direct integration between the SSP and DSP required for Protected +Audience?</td> + <td style="vertical-align: top;">Direct integration between the SSP and DSP is not required if DSP does +not need to process contextual signals in its own server in order to +pass that processed information into its on-device bidding +function.</td> + </tr> + <tr> + <td style="vertical-align: top;">A <code>bid_currency</code> field in B&A</td> + <td style="vertical-align: top;">Support for <code>bid_currency</code> field in Bidding and Auction Service.</td> + <td style="vertical-align: top;">B&A doesn't support a <code>bid_currency</code> yet, although we plan to support +that by the end of January 2024. Refer to the <a +href="https://github.com/privacysandbox/fledge-docs/blob/main/bidding_auction_services_api.md#timeline-and-roadmap">timeline here</a>.</td> + </tr> + <tr> + <td style="vertical-align: top;"><code>perBuyerSignals</code></td> + <td style="vertical-align: top;">Is there a size limit for <code>perBuyerSignals</code>?</td> + <td style="vertical-align: top;">There is no limit on the number of per-buyer signals, but sending too +much data may have detrimental effects on the browser's +performance.</td> + </tr> + <tr> + <td style="vertical-align: top;">Cross-site use cases</td> + <td style="vertical-align: top;">Can we use Protected Audience API interest groups across multiple +websites?</td> + <td style="vertical-align: top;">Protected Audience is not designed for such use cases, as explained in +<a +href="https://github.com/WICG/turtledove/issues/282">turtledove/issues/282</a>.</td> + </tr> + <tr> + <td style="vertical-align: top;">Interest Group HTTP Requests</td> + <td style="vertical-align: top;">Include Interest Group Blob in the HTTP headers.</td> + <td style="vertical-align: top;">We are considering this request and <a +href="https://github.com/WICG/turtledove/issues/777">welcome more feedback</a> on this +request.</td> + </tr> + <tr> + <td style="vertical-align: top;">Ad quality control</td> + <td style="vertical-align: top;">Loss of ad quality control related on cross-site information.</td> + <td style="vertical-align: top;">We are considering this feedback and <a +href="http://github.com/WICG/turtledove/issues/773">welcome additional feedback</a>.</td> + </tr> + <tr> + <td style="vertical-align: top;">Chrome DevTools</td> + <td style="vertical-align: top;">Outgoing Protected Audience network requests should be visible in the +Chrome Developer Tools Network Tab.</td> + <td style="vertical-align: top;">We are working on enabling this functionality in the network tab and +<a +href="https://github.com/WICG/turtledove/issues/778">welcome additional feedback</a> on why this should be prioritized.</td> + </tr> + <tr> + <td style="vertical-align: top;">Trusted Execution Environment</td> + <td style="vertical-align: top;">When will the details on which metrics are privacy-impacting (and +their degree) be added to the explainer on Trusted Execution +Environment monitoring?</td> + <td style="vertical-align: top;">We are in the process of updating the explainer with this +information. The updated explainer will be available by November +2023.</td> + </tr> + <tr> + <td style="vertical-align: top;"><code>directFrom<br>SellerSignals</code></td> + <td style="vertical-align: top;">Why is <code>directFrom<br>SellerSignals</code> not packaged as a web bundle?</td> + <td style="vertical-align: top;">We shared the <a +href="https://chromestatus.com/feature/5165311598264320">rationale for this decision here</a>.</td> + </tr> + <tr> + <td style="vertical-align: top;">Impression delegation</td> + <td style="vertical-align: top;">Is there any viable way to do impression delegation where the outcome +of an interest group being selected is yet another targeting +action?</td> + <td style="vertical-align: top;">Multiple nested auctions are not compatible with our privacy goals +for two reasons. First, when the winner of an auction renders inside +a Fenced Frame, our privacy goals for Protected Audience include the +resulting creative rendering without knowledge of the context: the +surrounding page's URL or first-party cookie are a privacy violation. +In that environment, a nested auction is not viable. Second, the +Protected Audience model says that each auction's winner should be +based on data from just one additional site. Nested auctions would +be a way to compound that, resulting in the possibility of choosing +ads based on a many-site profile. </td> + </tr> + <tr> + <td style="vertical-align: top;">Data at Rest criterion</td> + <td style="vertical-align: top;">Explain further the Data at Rest criterion in the Key/Value service +trust model.</td> + <td style="vertical-align: top;">Data in the Key Value Service is loaded into memory and served from +there rather than doing any read-through caching.</td> + </tr> + <tr> + <td style="vertical-align: top;">Buyer Data Signal</td> + <td style="vertical-align: top;">Is there a defined size limit for the <code>buyer_data</code> signals received +from the DSPs?</td> + <td style="vertical-align: top;">There are currently no browser imposed limits for <code>buyer_data</code> signals +received from DSPs.</td> + </tr> + </tbody> +</table> + +## Measure Digital Ads + +### Attribution Reporting (and other APIs) + +<table> + <thead> + <tr> + <th><strong>Feedback Theme </strong></th> + <th><strong>Summary</strong></th> + <th><strong>Chrome Response</strong></th> + </tr> + </thead> + <tbody> + <tr> + <td style="vertical-align: top;">Cross-device</td> + <td style="vertical-align: top;">Plan for cross-device support for Attribution Reporting API.</td> + <td style="vertical-align: top;">Cross-device presents new privacy challenges on top of 3PC and also +adds technology distribution challenges given the range of devices +and platforms a user might use. We are exploring potential solutions, +but we are focused on the critical use cases currently supported by +Attribution Reporting and do not have plans to introduce cross-device support before +the removal of third-party cookies.</td> + </tr> + <tr> + <td style="vertical-align: top;">(Also reported in previous quarters)<br> +Trigger Data Size</td> + <td style="vertical-align: top;">Why is the trigger data size limited to 3 bits?</td> + <td style="vertical-align: top;">The size is limited to 3 bits and 8 distinct values to ensure that +the amount of cross-site and cross-context information about a user is limited. +We welcome ecosystem players to <a +href="https://github.com/WICG/attribution-reporting-api/issues/694">submit feedback</a> on whether the +current parametrization for event-level reporting is sufficient.</td> + </tr> + <tr> + <td style="vertical-align: top;">Conversion funnel</td> + <td style="vertical-align: top;">Report multiple domains that were used in conversion.</td> + <td style="vertical-align: top;">This use case is possible since the +<a +href="https://github.com/WICG/attribution-reporting-api/pull/601">addition of multiple destinations</a>. +We welcome <a +href="https://github.com/WICG/attribution-reporting-api/issues/1048">additional feedback</a>.</td> + </tr> + <tr> + <td style="vertical-align: top;">Same domain in different country support</td> + <td style="vertical-align: top;">Does Attribution Reporting work with websites that have the same +Domain but multiple country TLDs?</td> + <td style="vertical-align: top;">This issue has been discussed and resolved with the stakeholder that +raised the question. If an ad tech needs to use multiple country TLDs +they will need to have multiple enrollments, with one for each +country TLD.</td> + </tr> + <tr> + <td style="vertical-align: top;">Protected Audience and Attribution Reporting</td> + <td style="vertical-align: top;">Can ad techs access both view-through conversions for Protected +Audience auctions as well as click-through conversions for +Attribution Reporting?</td> + <td style="vertical-align: top;">Yes, Privacy Sandbox should support both VTCs and CTCs within +Protected Audience.</td> + </tr> + <tr> + <td style="vertical-align: top;">Agaggregatable report delays</td> + <td style="vertical-align: top;">Reduce aggregatable report delays further.</td> + <td style="vertical-align: top;">We have heard recent feedback regarding this and have <a +href="https://github.com/WICG/attribution-reporting-api/issues/974">shared ideas here</a>. +We welcome additional feedback from the ecosystem.</td> + </tr> + <tr> + <td style="vertical-align: top;">Agaggregatable report delays</td> + <td style="vertical-align: top;">Reducing delays via introducing server mediation.</td> + <td style="vertical-align: top;">We are considering this proposal and <a +href="https://github.com/WICG/attribution-reporting-api/issues/920">welcome additional feedback </a>.</td> + </tr> + <tr> + <td style="vertical-align: top;">Event-level report delays</td> + <td style="vertical-align: top;">Reduce event-level report delays.</td> + <td style="vertical-align: top;">The full flexible event-level proposal, described in <a +href="https://github.com/WICG/attribution-reporting-api/blob/main/flexible_event_config.md">Flexible event-level configurations</a>, +can reduce event-level reporting delays down to 1 hour with a noise +tradeoff.</td> + </tr> + <tr> + <td style="vertical-align: top;">Source reporting origin per source</td> + <td style="vertical-align: top;">Limitation of max source reporting origins per source reporting site +prevents ad techs from registering sources from different reporting +origins for a single publisher origin.</td> + <td style="vertical-align: top;">This has been discussed with the stakeholder that raised the issue +and a potential solution of using 1 reporting origin per +source-reporting site is being tested before trying other potential +solutions involving redirects.<br> +<br> +We are open to any additional ecosystem feedback regarding this limit +as well.</td> + </tr> + <tr> + <td style="vertical-align: top;">Issue reporting</td> + <td style="vertical-align: top;">How can we report errors or issues with the Attribution Reporting API to +Chrome?</td> + <td style="vertical-align: top;">Currently we recommend ad techs report any Attribution Reporting API +errors they may be facing as an Issue on GitHub. If they are facing a +Chrome-related issue we recommend creating a Chromium bug. Links +for how and where to flag any issues can be found in <a +href="https://developer.chrome.com/docs/privacy-sandbox/attribution-reporting/#engage-and-share-feedback">Engage and share feedback</a>.</td> + </tr> + <tr> + <td style="vertical-align: top;">Deduplication</td> + <td style="vertical-align: top;">How can we deduplicate conversions across different pipelines and +devices?</td> + <td style="vertical-align: top;">Deduplicating across devices and measurement pipelines is a known and +current challenge that ad techs also face today with 3PCs. With the +Attribution Reporting API, ad techs can decide when to register +specific conversions and add specific metadata to indicate which +measurement pipelines they have used to track the conversions (in other words, +part of the aggregation key), which can be compared against other +measurement pipelines.<br> +<br> +We are open to any additional ecosystem feedback regarding this.</td> + </tr> + <tr> + <td style="vertical-align: top;">Deduplication and Priority</td> + <td style="vertical-align: top;">Request to have priority first before deduplication.</td> + <td style="vertical-align: top;">We are considering this request and <a +href="https://github.com/WICG/attribution-reporting-api/issues/700">welcome additional feedback</a>.</td> + </tr> + <tr> + <td style="vertical-align: top;">Anti-fraud</td> + <td style="vertical-align: top;">Risk of malicious user tampering the event-level data.</td> + <td style="vertical-align: top;">Report verification does not work for event-level reporting for the +reasons described in <a +href="https://github.com/WICG/attribution-reporting-api/blob/main/report_verification.md#why-doesnt-this-support-event-level-reports">Why doesn’t this support event-level reports?</a>.</td> + </tr> + <tr> + <td style="vertical-align: top;">Conversion type</td> + <td style="vertical-align: top;">How can we differentiate between view through and navigation in +Attribution Reporting?</td> + <td style="vertical-align: top;">We have the following built-in filtering option: <code>source_type</code>. +<a +href="https://developer.android.com/design-for-safety/privacy-sandbox/attribution#trigger-filters:~:text=Ad%20tech%20platforms%20can%20also,for%20%22source_type%22%3A%20%5B%22event%22%5D">Additional details are available here</a>.</td> + </tr> + </tbody> +</table> + +### Aggregation Service + +<table> + <thead> + <tr> + <th><strong>Feedback Theme </strong></th> + <th><strong>Summary</strong></th> + <th><strong>Chrome Response</strong></th> + </tr> + </thead> + <tbody> + <tr> + <td style="vertical-align: top;">Budget recovery</td> + <td style="vertical-align: top;">Some ad techs have requested the ability to reprocess reports in cases +where there are failures, errors, or deletions of their reports.</td> + <td style="vertical-align: top;">The team is exploring ways to address this in a privacy-preserving +way.</td> + </tr> + <tr> + <td style="vertical-align: top;">Site enrollment</td> + <td style="vertical-align: top;">Multiple ad techs have requested support for processing multiple +origins in the same account for use cases such as splitting data by +Geo, advertiser. This behavior is also expected by ad techs given +that the client API enrollment is now site-based (and not origin +based). Migration from origin to site enrollment streamlines the ad +tech onboarding process via consistency with the client enrollment +process.</td> + <td style="vertical-align: top;">We will be launching migration from origin enrollment to site +enrollment for the Aggregation Service soon and welcome <a +href="https://github.com/privacysandbox/aggregation-service/issues/25">feedback from +the ecosystem</a>. +</td> + </tr> + <tr> + <td style="vertical-align: top;">Release & Deprecation Plan</td> + <td style="vertical-align: top;">Release and depreciation schedule for Aggregation Service features +and patches published. The goal of the plan is to give ad techs +visibility into our release policies to enable them to prepare for +upcoming releases and deprecations, and ensure they run stable and +secure versions of services.</td> + <td style="vertical-align: top;">We have recently published a proposal for the Aggregation Service +<a +href="https://github.com/privacysandbox/aggregation-service/wiki/Aggregation-Service-release-and-deprecation-plan">release and deprecation plan</a> +and welcome <a +href="https://github.com/privacysandbox/aggregation-service/issues/23">additional feedback</a>. +</td> + </tr> + <tr> + <td style="vertical-align: top;">Coordinators</td> + <td style="vertical-align: top;">What happens if the coordinators go down on aggregation service?</td> + <td style="vertical-align: top;">Both coordinators need to be fully available for the system to +function correctly. Short unavailability is accommodated with retries +in our client libraries; longer unavailability of either of the two +coordinators will have aggregation jobs fail.<br> +<br> +Jobs can be rerun if the budget for privacy isn't consumed yet. In +the case where any service failure led to budget consumption without +a summary report written to ad tech storage, we currently recommend +they use debug reports to retrieve results using the <a +href="https://developer.chrome.com/docs/privacy-sandbox/attribution-reporting-debugging/part-1/#data-recovery">local testing +tool</a>.<br> +<br> +We are also working on features to allow for budget recovery in the +case of failures so ad techs can rerun their jobs.</td> + </tr> + </tbody> +</table> + +### Private Aggregation API + +<table> + <thead> + <tr> + <th><strong>Feedback Theme </strong></th> + <th><strong>Summary</strong></th> + <th><strong>Chrome Response</strong></th> + </tr> + </thead> + <tbody> + <tr> + <td style="vertical-align: top;">Blob Url</td> + <td style="vertical-align: top;">Request to support Blob Url in Shared Storage.</td> + <td style="vertical-align: top;">Support for Blob Url has been added in Chrome M116.</td> + </tr> + </tbody> +</table> + +## Limit Covert Tracking + +### User Agent Reduction and User Agent Client Hints + +<table> + <thead> + <tr> + <th><strong>Feedback Theme </strong></th> + <th><strong>Summary</strong></th> + <th><strong>Chrome Response</strong></th> + </tr> + </thead> + <tbody> + <tr> + <td style="vertical-align: top;">JavaScript API</td> + <td style="vertical-align: top;">Availability of the User Agent Client Hints JavaScript API.</td> + <td style="vertical-align: top;">There are no plans to remove this functionality as it is our core +solution for partners who want to actively access the high-entropy +data beyond what is available by default in the frozen and reduced +UA.</td> + </tr> + <tr> + <td style="vertical-align: top;">Device and Form Factor information</td> + <td style="vertical-align: top;">Ability for websites to understand input, output, and other +information the device visiting the website can support.</td> + <td style="vertical-align: top;">We have added <a +href="https://github.com/WICG/ua-client-hints/pull/343">support for this request</a> +following feedback from the ecosystem.</td> + </tr> + </tbody> +</table> + +### IP Protection (formerly Gnatcatcher) + +<table> + <thead> + <tr> + <th><strong>Feedback Theme </strong></th> + <th><strong>Summary</strong></th> + <th><strong>Chrome Response</strong></th> + </tr> + </thead> + <tbody> + <tr> + <td style="vertical-align: top;">Eligible Third Party Traffic</td> + <td style="vertical-align: top;">What is "eligible third-party traffic" referring to in the +explainer?</td> + <td style="vertical-align: top;">We understand the importance of this question and are actively +working to identify which third-party traffic will be eligible and +which will not. We welcome feedback on this topic.</td> + </tr> + <tr> + <td style="vertical-align: top;">Network Traffic Audits</td> + <td style="vertical-align: top;">Support for enterprises to perform network traffic audits for their +networks.</td> + <td style="vertical-align: top;">Only third-party traffic embedded in first-party sites will be +affected, which should limit the amount of traffic that requires +filtering. Additionally, we plan to give users the option of whether +or not to use IP Protection, and for enterprise-controlled Chrome, +there will be enterprise policies to disable IP Protection. Finally, +we're exploring what controls (if any) will be provided to network +operators to disable IP Protection. We welcome feedback on this +topic.</td> + </tr> + <tr> + <td style="vertical-align: top;">Access control</td> + <td style="vertical-align: top;">IP Protection may impact web services that use IP addresses for +access control.</td> + <td style="vertical-align: top;">We understand the importance of anti-fraud use cases and the possible +impact to those use cases. We are seeking ecosystem feedback on how +we can better support anti-fraud use cases that typically have relied +on IP addresses. </td> + </tr> + <tr> + <td style="vertical-align: top;">Communication between the 2-Hop proxies</td> + <td style="vertical-align: top;">How to ensure there is no information between proxies.</td> + <td style="vertical-align: top;">We are in the process of designing the proxy interactions. Our goal +is to minimize the chances for such information sharing via business, +process, and technical means.</td> + </tr> + <tr> + <td style="vertical-align: top;">Non-Google Authentications</td> + <td style="vertical-align: top;">Support for Non-Google Authentications.</td> + <td style="vertical-align: top;">We plan to publish more details about account authentication in the +future, though we have <a +href="https://github.com/GoogleChrome/ip-protection#anti-abuse">shared some initial considerations</a>.</td> + </tr> + <tr> + <td style="vertical-align: top;">Tracker classification</td> + <td style="vertical-align: top;">How will IP Protection determine what constitutes a tracker and its +variants?</td> + <td style="vertical-align: top;">We understand the importance of this question and are actively +working to identify which third-party traffic will be eligible and +which will not. We welcome feedback on this topic.</td> + </tr> + <tr> + <td style="vertical-align: top;">Analytics</td> + <td style="vertical-align: top;">IP Protection may impact the accuracy of analytics services.</td> + <td style="vertical-align: top;">We are looking to understand the impact of IP Protection further and +welcome additional feedback and examples from the ecosystem.</td> + </tr> + <tr> + <td style="vertical-align: top;">Proxy</td> + <td style="vertical-align: top;">If a user is using proxy or has manually defined a proxy, how will IP +Mask work in this case?</td> + <td style="vertical-align: top;">We are looking to understand the impact that IP Protection may have +on other proxies. We do not have any plans to share at the moment. We +welcome feedback on this topic.</td> + </tr> + <tr> + <td style="vertical-align: top;">Premium offering</td> + <td style="vertical-align: top;">Will IP Protection be a paid feature?</td> + <td style="vertical-align: top;">IP Protection will be available to Chrome users as part of the core +browser experience. It will not be a paid feature.</td> + </tr> + <tr> + <td style="vertical-align: top;">Proxy server</td> + <td style="vertical-align: top;">Will the same proxy servers be used during user sessions?</td> + <td style="vertical-align: top;">An HTTP/S connection will use a single pair of proxies and will +present a single masked IP address to the origin. Beyond that, there +are no hard constraints on different HTTP/S connections having to use +the same servers.</td> + </tr> + <tr> + <td style="vertical-align: top;">Platform support</td> + <td style="vertical-align: top;">On which platform will IP Protection be supported?</td> + <td style="vertical-align: top;">IP Protection will initially be available on Chrome for Android and +Desktop. We continue to evaluate how to expand the protection to +other platforms.</td> + </tr> + <tr> + <td style="vertical-align: top;">Opt-Out</td> + <td style="vertical-align: top;">Will users be able to disable IP Protection?</td> + <td style="vertical-align: top;">We plan to provide users the choice on whether they want to use IP +Protection or not.</td> + </tr> + <tr> + <td style="vertical-align: top;">Anonymization</td> + <td style="vertical-align: top;">What kinds of requests will be anonymized under IP Protection?</td> + <td style="vertical-align: top;">HTTP/S and DNS requests to eligible third-party domains are +anonymized via the privacy proxies. We will provide additional +details in an upcoming explainer on how we will determine which +domains will be included. The rest of the traffic (for example, the rest of +the DNS requests or other HTTP/S traffic) is unaffected.</td> + </tr> + <tr> + <td style="vertical-align: top;">Data Visibility</td> + <td style="vertical-align: top;">Network addresses may be accessed during the first hop in IP +Protection.</td> + <td style="vertical-align: top;">In the two-hop proxy model, the first hop (controlled by Google) only +sees the source client IP and a request to connect to the second hop, +while the second hop (controlled by an external CDN) only sees a +tuple on the first hop (proxy IP + port) and the destination IP. For +the response back from the origin, the second hop is able to forward +the response to the first hop proxy+port associated with the request +and doesn't need to learn anything about the original client IP (and +the first hop just returns the response to the client, without +learning anything about the destination IP). In this way, the first +hop only learns the client IP and the second hop, while the second +hop only learns the destination IP.</td> + </tr> + <tr> + <td style="vertical-align: top;">WebView</td> + <td style="vertical-align: top;">Will IP Protection be available to Android WebView in the +future?</td> + <td style="vertical-align: top;">We do not have any plans to share at the moment, but our vision is to +provide this protection as broadly as possible.</td> + </tr> + </tbody> +</table> + +### Bounce Tracking Mitigation + +<table> + <thead> + <tr> + <th><strong>Feedback Theme </strong></th> + <th><strong>Summary</strong></th> + <th><strong>Chrome Response</strong></th> + </tr> + </thead> + <tbody> + <tr> + <td style="vertical-align: top;">Interaction Tracking</td> + <td style="vertical-align: top;">How are user interactions tracked?</td> + <td style="vertical-align: top;">Bounce tracking mitigations track two types of user +interactions:<br> +<br> +<ul> +<li>User activations as defined by the <a +href="https://html.spec.whatwg.org/#tracking-user-activation">html +spec</a>. These are basically clicks, key presses, touch screen taps, etc.</li> + +<li>Successful <a href="https://w3c.github.io/webauthn/">webauth</a> +assertions. These are cases where a user taps a security key or uses a +passkey as form of authentication</li> +</ul> +<br> +These interactions are associated with the top-level site on pages +where they occur. For example, if a user clicks in an embedded iframe +the interaction is associated with the top-level site and not the +embedded site.<br> +<br> +The interactions are stored in a database containing the <a +href="https://github.com/GoogleChrome/web.dev/blob/main/src/site/content/en/secure/same-site-same-origin/index.md#schemeless-same-site">schemeless +etld+1</a> and the time of the interaction.<br> +<br> +Interactions protect the associated domain from bounce tracking +mitigation state deletion for 45 days.</td> + </tr> + <tr> + <td style="vertical-align: top;">Allowlisted Exemptions</td> + <td style="vertical-align: top;">Can domains be exempted?</td> + <td style="vertical-align: top;">We are considering this request and we welcome additional <a +href="https://github.com/privacycg/nav-tracking-mitigations/issues/64">feedback +from the ecosystem</a>. +</td> + </tr> + </tbody> +</table> + +### Privacy Budget + +No feedback received this quarter. + +## Strengthen cross-site privacy boundaries + +### Related Website Sets (formerly First-Party Sets) + +<table> + <thead> + <tr> + <th><strong>Feedback Theme </strong></th> + <th><strong>Summary</strong></th> + <th><strong>Chrome Response</strong></th> + </tr> + </thead> + <tbody> + <tr> + <td style="vertical-align: top;">Centralized Approach</td> + <td style="vertical-align: top;">Concern over the centralized repository approach for managing Related +Website Sets.</td> + <td style="vertical-align: top;">A public, easily accessible repository is key to the design of RWS as +it provides accountability for submissions. Third-party cookie +functionality is ultimately provided by the use of the Storage Access +API or the rSAFor API, with RWS membership providing auto-granted +access (as opposed to through prompts with the Storage Access API). +We believe that an approach like the RWS submission process is an +appropriate requirement for auto-granted third-party cookie +access.</td> + </tr> + <tr> + <td style="vertical-align: top;">Renaming json file</td> + <td style="vertical-align: top;">With the change in API name, does the hosted JSON file name need to +be changed?</td> + <td style="vertical-align: top;">Yes, the submission guidelines have been changed, and the primary +domain must serve a JSON file at +<code>/.well-known/related-website-set.json</code>. <br> +<br> +Existing sets in the RWS list do not need to be changed, but if there +are modifications submitted to existing sets, the JSON file must be +changed.</td> + </tr> + <tr> + <td style="vertical-align: top;">(Also reported in previous quarters) Domain Limit</td> + <td style="vertical-align: top;">Request to expand the number of associated domains</td> + <td style="vertical-align: top;">As announced in a blogpost on August 31, we have raised the +associated domain limit to five domains following feedback from the +ecosystem. We have decided to increase the associated domain limit to +five domains (plus one primary domain) which best matches the most +comparable implementation offered by another major browser.</td> + </tr> + <tr> + <td style="vertical-align: top;">Third Party Cookies</td> + <td style="vertical-align: top;">Will Related Website Sets only work with third-party cookies +disabled?</td> + <td style="vertical-align: top;">Related Website Sets will work even when a user has not blocked +third-party cookies; but there will be no observable effect since the +relevant cookies are available without any need for Related Website +Sets and Storage Access API.</td> + </tr> + <tr> + <td style="vertical-align: top;">Legitimate edits</td> + <td style="vertical-align: top;">How does the Related Website Sets repository prevent non-owners from +modifying sets?</td> + <td style="vertical-align: top;">Per the <a +href="https://github.com/GoogleChrome/first-party-sets/blob/main/FPS-Submission_Guidelines.md)">submission +guides</a>, anyone can submit a PR on GitHub to edit the +<code>first_party_sets.JSON</code> file. However, if the PR is approved (passes +technical validations, and so forth), it will be manually merged in batches +to the canonical FPS list once per week (Tuesdays at 12pm Eastern +Time) by Google.<br> +<br> +If a bad actor tries to modify a set they don't own, it shouldn't be +a problem since they won't be able to modify the <code>.well-known</code> files +and therefore the validations will fail.</td> + </tr> + <tr> + <td style="vertical-align: top;">Domain hijacking</td> + <td style="vertical-align: top;">Domain hijacking may expose related domain data to unauthorized +parties.</td> + <td style="vertical-align: top;">This is not possible, as discussed in <a +href="https://github.com/WICG/first-party-sets/issues/181">this Protected Audience GitHub issue</a>.</td> + </tr> + </tbody> +</table> + +### Fenced Frames API + +<table> + <thead> + <tr> + <th><strong>Feedback Theme </strong></th> + <th><strong>Summary</strong></th> + <th><strong>Chrome Response</strong></th> + </tr> + </thead> + <tbody> + <tr> + <td style="vertical-align: top;">Content Violation</td> + <td style="vertical-align: top;">Allow users to report suspicious ads.</td> + <td style="vertical-align: top;">Suspicious ad reporting is not prevented by Fenced Frames. Users can +still interact with the ad and report suspicious ads to the ad tech +in the usual way.</td> + </tr> + <tr> + <td style="vertical-align: top;">Interaction with surrounding sites</td> + <td style="vertical-align: top;">Allow interaction with the surrounding or top-level website.</td> + <td style="vertical-align: top;">We are looking to understand why this request is necessary and +welcome additional feedback from the ecosystem.</td> + </tr> + <tr> + <td style="vertical-align: top;">Native Advertising</td> + <td style="vertical-align: top;">Fenced Frame support for Native Advertising.</td> + <td style="vertical-align: top;">We are considering supporting the use case and are discussing +possible <a +href="https://github.com/WICG/turtledove/issues/741">workarounds and solutions</a>.</td> + </tr> + </tbody> +</table> + +### Shared Storage API + +<table> + <thead> + <tr> + <th><strong>Feedback Theme </strong></th> + <th><strong>Summary</strong></th> + <th><strong>Chrome Response</strong></th> + </tr> + </thead> + <tbody> + <tr> + <td style="vertical-align: top;">Cross domain</td> + <td style="vertical-align: top;">Allow communication across domains for local storage.</td> + <td style="vertical-align: top;">This use case is currently not in line with Shared Storage's +privacy-preserving output gates but we welcome <a +href="https://github.com/privacycg/storage-access/issues/102">additional context</a> +as we evolve proposals for non-partitioned storage.</td> + </tr> + <tr> + <td style="vertical-align: top;">Blob Url</td> + <td style="vertical-align: top;">Request to support Blob Url in Shared Storage.</td> + <td style="vertical-align: top;">Support for Blob Url has been added in Chrome M116.</td> + </tr> + </tbody> +</table> + +### CHIPs + +No feedback received this quarter. + +### FedCM + +<table> + <thead> + <tr> + <th><strong>Feedback Theme </strong></th> + <th><strong>Summary</strong></th> + <th><strong>Chrome Response</strong></th> + </tr> + </thead> + <tbody> + <tr> + <td style="vertical-align: top;">Third-party cookies</td> + <td style="vertical-align: top;">Is FedCM currently disabled if users enable "Block third-party +cookies" in the Chrome settings"?</td> + <td style="vertical-align: top;">Yes, FedCM is currently disabled. For testing, we recommend that you +additionally enable +<code>chrome://flags/#fedcm-<br>without-third-party-cookies</code>.<br> +<br> +We are looking to <a +href="http://github.com/GoogleChromeLabs/privacy-sandbox-dev-support/issues/141">support FedCM without third-party cookies</a> in the +future.</td> + </tr> + </tbody> +</table> + +## Fight spam and fraud + +### Private State Token API (and other APIs) + +<table> + <thead> + <tr> + <th><strong>Feedback Theme </strong></th> + <th><strong>Summary</strong></th> + <th><strong>Chrome Response</strong></th> + </tr> + </thead> + <tbody> + <tr> + <td style="vertical-align: top;">Token expiration</td> + <td style="vertical-align: top;">Once Google Chrome is uninstalled, will the Token be lost or will it +be cached?</td> + <td style="vertical-align: top;">The token will be lost if the user uninstalls Google Chrome.</td> + </tr> + <tr> + <td style="vertical-align: top;">Token Information</td> + <td style="vertical-align: top;">How can issuers keep issued information within the Private State +Token private?</td> + <td style="vertical-align: top;">Information is always kept private in the token and cannot be +unencrypted by external parties that do not have the keys.</td> + </tr> + <tr> + <td style="vertical-align: top;">Error in demo</td> + <td style="vertical-align: top;">Error when trying to run the Private State Token demo.</td> + <td style="vertical-align: top;">We have updated the demo and it should be working correctly now.</td> + </tr> + </tbody> +</table> From 006bf169038ba1bb620ecf97773f698bb326be30 Mon Sep 17 00:00:00 2001 From: amysteamdev <37001393+AmySteam@users.noreply.github.com> Date: Fri, 27 Oct 2023 09:02:30 -0500 Subject: [PATCH 982/982] Move policy related FAQs to webstore/program-policies/ (#7669) * Move pages Add redirects Adapt TOC Update links on policy landing page * Update links with changes --- redirects.yaml | 21 +++++++++++++++++++ site/_data/docs/webstore/toc.yml | 13 ++++++------ site/en/docs/webstore/best_listing/index.md | 2 +- .../cws-dashboard-distribution/index.md | 2 +- .../webstore/cws-dashboard-listing/index.md | 2 +- .../webstore/cws-dashboard-privacy/index.md | 2 +- .../affiliate-ads-faq/index.md | 0 .../index.md | 0 .../deceptive-installation-tactics/index.md | 2 +- .../docs/webstore/program-policies/index.njk | 8 +++---- .../play_edu_tos/index.md | 0 .../program-policies/privacy/index.md | 2 +- .../program-policies/spam-and-abuse/index.md | 2 +- .../{ => program-policies}/spam-faq/index.md | 0 .../{ => program-policies}/terms/index.md | 2 +- .../trader-disclosure/index.md | 0 .../user-data-faq}/index.md | 0 site/en/docs/webstore/set-up-account/index.md | 2 +- site/en/docs/webstore/update/index.md | 2 +- 19 files changed, 42 insertions(+), 20 deletions(-) rename site/en/docs/webstore/{ => program-policies}/affiliate-ads-faq/index.md (100%) rename site/en/docs/webstore/{deceptive_installation_tactics => program-policies/deceptive-installation-tactics-faq}/index.md (100%) rename site/en/docs/webstore/{ => program-policies}/play_edu_tos/index.md (100%) rename site/en/docs/webstore/{ => program-policies}/spam-faq/index.md (100%) rename site/en/docs/webstore/{ => program-policies}/terms/index.md (99%) rename site/en/docs/webstore/{ => program-policies}/trader-disclosure/index.md (100%) rename site/en/docs/webstore/{user_data => program-policies/user-data-faq}/index.md (100%) diff --git a/redirects.yaml b/redirects.yaml index 52f28377a..d6893f55d 100644 --- a/redirects.yaml +++ b/redirects.yaml @@ -477,6 +477,27 @@ redirects: - from: /docs/webstore/program_policies/ to: /docs/webstore/program-policies/ +- from: /docs/webstore/affiliate-ads-faq + to: /docs/webstore/program-policies/affiliate-ads-faq + +- from: /docs/webstore/deceptive_installation_tactics + to: /docs/webstore/program-policies/deceptive-installation-tactics-faq + +- from: /docs/webstore/play_edu_tos + to: /docs/webstore/program-policies/play_edu_tos + +- from: /docs/webstore/terms + to: /docs/webstore/program-policies/terms + +- from: /docs/webstore/user_data + to: /docs/webstore/program-policies/user-data-faq + +- from: /docs/webstore/trader-disclosure + to: /docs/webstore/program-policies/trader-disclosure + +- from: /docs/webstore/spam-faq + to: /docs/webstore/program-policies/spam-faq + - from: /webview/overview to: /docs/multidevice/android/overview/ diff --git a/site/_data/docs/webstore/toc.yml b/site/_data/docs/webstore/toc.yml index c4aaaebae..d743d0253 100644 --- a/site/_data/docs/webstore/toc.yml +++ b/site/_data/docs/webstore/toc.yml @@ -38,14 +38,15 @@ - url: /docs/webstore/discovery/ - title: i18n.docs.webstore.policies sections: - - url: /docs/webstore/terms/ - url: /docs/webstore/program-policies/ - - url: /docs/webstore/trader-disclosure/ - - url: /docs/webstore/spam-faq/ - - url: /docs/webstore/deceptive_installation_tactics/ - - url: /docs/webstore/user_data/ - - url: /docs/webstore/play_edu_tos/ + - url: /docs/webstore/program-policies/terms/ + - url: /docs/webstore/program-policies/affiliate-ads-faq/ + - url: /docs/webstore/program-policies/deceptive-installation-tactics-faq/ + - url: /docs/webstore/program-policies/spam-faq/ + - url: /docs/webstore/program-policies/user-data-faq/ - url: /docs/webstore/complaint-faq/ + - url: /docs/webstore/program-policies/trader-disclosure/ + - url: /docs/webstore/program-policies/play_edu_tos/ - title: i18n.docs.webstore.api sections: - url: /docs/webstore/using_webstore_api diff --git a/site/en/docs/webstore/best_listing/index.md b/site/en/docs/webstore/best_listing/index.md index 40a7d67b5..82cb8ec46 100644 --- a/site/en/docs/webstore/best_listing/index.md +++ b/site/en/docs/webstore/best_listing/index.md @@ -193,4 +193,4 @@ information about your item. [extension icon best practices]: /docs/webstore/images/#icon [i18n]: /docs/extensions/reference/i18n/ [i18n-your-screenshots]: /docs/webstore/i18n/#screenshots -[keyword-spam]: /docs/webstore/spam-faq/#keyword-spam +[keyword-spam]: /docs/webstore/policy-policies/spam-faq/#keyword-spam diff --git a/site/en/docs/webstore/cws-dashboard-distribution/index.md b/site/en/docs/webstore/cws-dashboard-distribution/index.md index e5ceeffde..6ddeab3d7 100644 --- a/site/en/docs/webstore/cws-dashboard-distribution/index.md +++ b/site/en/docs/webstore/cws-dashboard-distribution/index.md @@ -122,4 +122,4 @@ After filling out the [Listing][listing] tab and the [Privacy][privacy] tab, you [privacy]: /docs/webstore/cws-dashboard-privacy/ [private-google-groups]: #private-visibility-google-groups [publish]: /docs/webstore/publish/#publish-item -[repetitive-content]: /docs/webstore/spam-faq/#repetitive-content +[repetitive-content]: /docs/webstore/program-policies/spam-faq/#repetitive-content diff --git a/site/en/docs/webstore/cws-dashboard-listing/index.md b/site/en/docs/webstore/cws-dashboard-listing/index.md index 67262cba5..ce72b5f4f 100644 --- a/site/en/docs/webstore/cws-dashboard-listing/index.md +++ b/site/en/docs/webstore/cws-dashboard-listing/index.md @@ -128,7 +128,7 @@ If you haven't done so yet, complete your listing by [cws-branding]: /docs/webstore/branding [cws-images]: /docs/webstore/images [distribution]: /docs/webstore/cws-dashboard-distribution -[keyword-spam]: /docs/webstore/spam-faq/#keyword-spam +[keyword-spam]: /docs/webstore/program-policies/spam-faq/#keyword-spam [mature-guidelines]: /docs/webstore/rating/ [privacy]: /docs/webstore/cws-dashboard-privacy [user-support]: /docs/webstore/support-users/#provide-user-support diff --git a/site/en/docs/webstore/cws-dashboard-privacy/index.md b/site/en/docs/webstore/cws-dashboard-privacy/index.md index c352914ba..7749bae94 100644 --- a/site/en/docs/webstore/cws-dashboard-privacy/index.md +++ b/site/en/docs/webstore/cws-dashboard-privacy/index.md @@ -102,4 +102,4 @@ If you haven't done so yet, complete your listing by [remote-code]: /docs/extensions/mv3/intro/mv3-overview/#remotely-hosted-code [setup-account]: /docs/webstore/publish#setup-a-developer-account [upload-item]: /docs/webstore/publish/#upload-your-item -[user-data]: /docs/webstore/user_data/ +[user-data]: /docs/webstore//program-policies/user-data-faq/ diff --git a/site/en/docs/webstore/affiliate-ads-faq/index.md b/site/en/docs/webstore/program-policies/affiliate-ads-faq/index.md similarity index 100% rename from site/en/docs/webstore/affiliate-ads-faq/index.md rename to site/en/docs/webstore/program-policies/affiliate-ads-faq/index.md diff --git a/site/en/docs/webstore/deceptive_installation_tactics/index.md b/site/en/docs/webstore/program-policies/deceptive-installation-tactics-faq/index.md similarity index 100% rename from site/en/docs/webstore/deceptive_installation_tactics/index.md rename to site/en/docs/webstore/program-policies/deceptive-installation-tactics-faq/index.md diff --git a/site/en/docs/webstore/program-policies/deceptive-installation-tactics/index.md b/site/en/docs/webstore/program-policies/deceptive-installation-tactics/index.md index c0f1fc9d6..34081ef28 100644 --- a/site/en/docs/webstore/program-policies/deceptive-installation-tactics/index.md +++ b/site/en/docs/webstore/program-policies/deceptive-installation-tactics/index.md @@ -18,4 +18,4 @@ date: 2022-11-01 For more information about this policy, see the [Developer FAQ][faq]. -[faq]: /docs/webstore/deceptive_installation_tactics/ +[faq]: /docs/webstore/program-policies/deceptive-installation-tactics-faq diff --git a/site/en/docs/webstore/program-policies/index.njk b/site/en/docs/webstore/program-policies/index.njk index a9ae89e0e..12eb6b018 100644 --- a/site/en/docs/webstore/program-policies/index.njk +++ b/site/en/docs/webstore/program-policies/index.njk @@ -27,7 +27,7 @@ sections: - url: /docs/webstore/program-policies/disclosure-requirements/ - url: /docs/webstore/program-policies/data-handling/ user_privacy_related: - - url: /webstore/user_data/ + - url: /webstore/program-policies/user-data-faq title: User Data FAQ marketing: - url: /docs/webstore/program-policies/impersonation-and-intellectual-property/ @@ -37,9 +37,9 @@ sections: - url: /docs/webstore/program-policies/ads/ - url: /docs/webstore/program-policies/affiliate-ads/ marketing_related: - - url: /webstore/deceptive_installation_tactics/ + - url: /webstore/program-policies/deceptive-installation-tactics-faq/ title: Deceptive Installation Tactics FAQ - - url: /webstore/affiliate-ads-faq/ + - url: /webstore/program-policies/affiliate-ads-faq/ title: Affiliate Ads FAQ quality: - url: /docs/webstore/program-policies/featured-products/ @@ -51,7 +51,7 @@ sections: quality_related: - url: /docs/webstore/faq/#faq-gen-24 title: Product Ranking Info - - url: /webstore/spam-faq/ + - url: /webstore/program-policies/spam-faq/ title: Spam policy FAQ - url: /docs/extensions/mv3/quality_guidelines title: Extensions quality guidelines FAQ diff --git a/site/en/docs/webstore/play_edu_tos/index.md b/site/en/docs/webstore/program-policies/play_edu_tos/index.md similarity index 100% rename from site/en/docs/webstore/play_edu_tos/index.md rename to site/en/docs/webstore/program-policies/play_edu_tos/index.md diff --git a/site/en/docs/webstore/program-policies/privacy/index.md b/site/en/docs/webstore/program-policies/privacy/index.md index ddf3638dc..fee887601 100644 --- a/site/en/docs/webstore/program-policies/privacy/index.md +++ b/site/en/docs/webstore/program-policies/privacy/index.md @@ -16,4 +16,4 @@ date: 2022-11-01 For more information on this policy, see the Developer [FAQ][faq]. -[faq]: /docs/webstore/user_data/ +[faq]: /docs/webstore/program-policies/user-data-faq/ diff --git a/site/en/docs/webstore/program-policies/spam-and-abuse/index.md b/site/en/docs/webstore/program-policies/spam-and-abuse/index.md index c97d7af4f..b1ce6a6fc 100644 --- a/site/en/docs/webstore/program-policies/spam-and-abuse/index.md +++ b/site/en/docs/webstore/program-policies/spam-and-abuse/index.md @@ -16,5 +16,5 @@ date: 2022-11-01 For additional information about the spam policy, see the [Spam FAQ][faq]. -[faq]: /docs/webstore/spam-faq/ +[faq]: /docs/webstore/program-policies/spam-faq/ [webmaster]: https://support.google.com/webmasters/answer/35769#3 diff --git a/site/en/docs/webstore/spam-faq/index.md b/site/en/docs/webstore/program-policies/spam-faq/index.md similarity index 100% rename from site/en/docs/webstore/spam-faq/index.md rename to site/en/docs/webstore/program-policies/spam-faq/index.md diff --git a/site/en/docs/webstore/terms/index.md b/site/en/docs/webstore/program-policies/terms/index.md similarity index 99% rename from site/en/docs/webstore/terms/index.md rename to site/en/docs/webstore/program-policies/terms/index.md index ee156d985..d02191791 100644 --- a/site/en/docs/webstore/terms/index.md +++ b/site/en/docs/webstore/program-policies/terms/index.md @@ -438,4 +438,4 @@ Please print and retain a copy of this document and any linked documents for you [one-stop]: https://support.google.com/chrome_webstore/contact/one_stop_support [program-policies]: /docs/webstore/program-policies [rating]: /docs/webstore/rating -[user-data]: /docs/webstore/user_data +[user-data]: /docs/webstore/program-policies/user-data-faq diff --git a/site/en/docs/webstore/trader-disclosure/index.md b/site/en/docs/webstore/program-policies/trader-disclosure/index.md similarity index 100% rename from site/en/docs/webstore/trader-disclosure/index.md rename to site/en/docs/webstore/program-policies/trader-disclosure/index.md diff --git a/site/en/docs/webstore/user_data/index.md b/site/en/docs/webstore/program-policies/user-data-faq/index.md similarity index 100% rename from site/en/docs/webstore/user_data/index.md rename to site/en/docs/webstore/program-policies/user-data-faq/index.md diff --git a/site/en/docs/webstore/set-up-account/index.md b/site/en/docs/webstore/set-up-account/index.md index a0e28bbf0..fd4a3df74 100644 --- a/site/en/docs/webstore/set-up-account/index.md +++ b/site/en/docs/webstore/set-up-account/index.md @@ -63,7 +63,7 @@ Click the **Verify email** link to send the verification link to your email. [register]: /docs/webstore/register [review-times]: /docs/webstore/review-process/#review-time [update]: /docs/webstore/update -[user-data]: /docs/webstore/user_data/ +[user-data]: /docs/webstore/program-policies/user-data-faq/ [verified-publisher]: /docs/webstore/cws-dashboard-listing/#displaying-your-verified-publisher-status [version]: /docs/extensions/mv3/manifest/version diff --git a/site/en/docs/webstore/update/index.md b/site/en/docs/webstore/update/index.md index 6723567d3..7d0b68687 100644 --- a/site/en/docs/webstore/update/index.md +++ b/site/en/docs/webstore/update/index.md @@ -180,5 +180,5 @@ Changing the %rollout does *not* trigger a new review. [upgrade-item]: #upgrade-your-item [visibility]: /docs/webstore/cws-dashboard-distribution#setting-the-visibility [visibility-private]: /docs/webstore/cws-dashboard-distribution/#private-visibility-trusted-testers -[test-production-extension]: /docs/webstore/spam-faq/#test-version +[test-production-extension]: /docs/webstore/program-policies/spam-faq/#test-version