Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(common): add NgOptimizedImage directive #47082

Closed
wants to merge 63 commits into from
Closed

Conversation

AndrewKushnir
Copy link
Contributor

This PR brings the code of the NgOptimizedImage directive into the main branch.

The development happened in a separate image-directive branch and all incoming code was reviewed by both Aurora and Angular teams. Before merging the code, we are conducting one more round of code reviews in this PR.

Notes:

  • all public APIs are marked as "Developer Preview", we expect to stabilize the API based on the initial feedback and announce the directive as stable later
  • the NgOptimizedImage directive is marked as standalone, so it can be imported and used directly
  • while NgOptimizedImage directive is a part of the @angular/common NPM package, it would NOT be included into the CommonModule for some time (we'll consider doing that later once all APIs are stabilized)
  • this PR contains documentation for all public API symbols and there will be a followup PR with a guide for angular.io, which would contain more information about the directive (including installation instructions)

// cc @pkozlowski-opensource @kara @khempenius

PR Type

What kind of change does this PR introduce?

  • Feature

Does this PR introduce a breaking change?

  • Yes
  • No

AndrewKushnir and others added 30 commits August 3, 2022 11:27
This commit adds Image directive skeleton as well as a set of basic tests.
This commit exports experimental `NgImage` directive via a private API of the `@angular/common` package, so that it can be used acorss other Angular packages for testing purposes.
This commit adds a simple app that uses the `NgImage` directive to simplify further investigation and tests.
…dImage

We want it to be clear what benefits the image directive
confers over a normal <img> tag, and the `NgImage` name
didn't provide much information. `NgOptimizedImage` makes
it obvious that the new directive is intended to improve
performance.
…token

This commit updates the `NgOptimizedImage` directive to drop the `loader` input. Component-specific loaders can still be configured via `IMAGE_LOADER` token and the `loader` input was only useful in case different loaders have to be present in a single template, which doesn't seem to be a common case. We'll be able to re-introduce the input later if needed.
This commit changes the `NgOptimizedImage` directive selector from `raw-src` to `rawSrc` to better align with the styleguide.
…directive

This commit updates the `NgOptimizedImage` directive to throw an error when `data:` and `blob:` inputs are used.
…tandalone

This commit updates the `NgOptimizedImage` directive as standalone, so it's easier to import it in
 an app (without importing any NgModules). The `NgOptimizedImageModule` is removed as no longer needed.
This commit updates the `NgOptimizeImage` directive to add asserts to make sure no inputs are changed after directive initialization.
…ssing or invalid

This commit updates the `NgOptimizeImage` directive to add asserts to make sure the `width` and `height` inputs are set and have correct values (numbers only).
…different hook

Currently, the logic that sets the `src` on the host `<img>` element is located in the `ngOnChanges` lifecycle hook and guarded by the dev-mode checks that the inputs do not change. However, those checks would be tree-shaken in prod mode and the `src` would be set each time the `ngOnChanges` hook is invoked. This is undesirable and may potentially lead to performance issues.

This commit moves the `src`-related logic to the `ngOnInit` hook instead, which would have the same effect (executed only once, after all inputs are set) and would behave consistently in dev and prod modes.
…age` test app

This commit adds the necessary e2e testing infrastructure to the `NgOptimizedImage` test app, so that the test coverage can be extended and extra scenarios can be tested in a browser.
…priority` is set

This commit adds extra logic into the `NgOptimizedImage` experimental directive to detect an LCP image and assert whether the `priority` attribute is applied.
…age` directive

This commit adds e2e tests for the LCP check logic. Those tests are needed to verify the behavior in a real browser (vs relying on a Node environment).
This commit optimizes the logic that monitors whether a give image is an LCP element. If an image has the `priority` attribute set, there is no need to include it into monitoring. Also, if we already warned about a particular image (via a `console.warn`) - there is no need to warn again later (to avoid spamming a console).
Previously NgOptimizedImage would default to requesting
an image at the width matching the width attribute in
the image HTML. While this works for width attrs that
match the intrinsic size of the image (e.g. responsive
images or images sized with CSS), this can be a sharp
edge for developers who use the width/height attributes
to set rendered size (i.e. instead of CSS, which one can
do for a fixed size image). In this case, defaulting to
the width attribute for the requested image would mean
requesting always at 1x quality, so screens with a DPR
 of 2+ get an image that is too small. Without a default
request width, the image served by the CDN would likely
be at intrinsic size, so 2x images would look correct.

This PR also updates the NgOptimizedImage sandbox and tests.
The CI failed to run on the last PR, so we didn't catch
that there were web tests failing due to absolute/relative
URL issues. This commit should fix the issue.
…tests

This commit updates the e2e folder to separate e2e tests and playground scripts (so it's clear where files are used).
This commit enables publishing of snapshots for the `image-directive`
feature branch. The artifacts can be accessed with the following steps:

1. Land your change in `image-directive`
2. Go to the corresponding snapshot repo (e.g. `angular/common-builds`)
3. Go to the `image-directive` branch
4. Copy the SHA of the latest commit in that branch
5. Use that SHA to install via NPM. e.g.
   `https://github.com/angular/common-builds.git#SHA`.
…tive

This commit updates the `NgOptimizedImage` directive to drop the `standalone` flag and create a new NgModule which declares and exports it, so that the directive can be used in apps that use pre-v14 version of Angular.
Currently if you use a static `srcset` with the image directive,
lazy loading no longer works because the image would start to
load before the loading attribute could be set to "lazy". This
commit throws an error if you try to use `srcset` this way.

In a follow-up commit, a new attribute will be added to support
responsive images in a lazy-loading-friendly way.
This commit adds a `rawSrcset` attribute as a replacement for the
`srcset` attribute. The `srcset` attribute cannot be set statically
on the image directive because it would cause images to start
downloading before the "loading" attribute could be set to "lazy".

Changing the name to `rawSrcset` allows the directive to control
the timing of image loading. It also makes it possible to support
custom loaders for `srcset` file names. Rather than having to repeat
the image origin for each image, the existing `rawSrc` value and
image loader can be composed to generate each full URL string. The
developer must only provide the necessary widths for the `srcset`.

For example, the developer might write:

```markup
<img rawSrc="hermes.jpg" rawSrcset="100w, 200w" ... />
```

with a loader like:

```js
const loader = (config) => `path/${config.src}?w=${config.width}`;
```

and the img tag will ultimately be set up as something like:

```markup
<img src="path/hermes.jpg?w=100" srcset="path/hermes.jpg?w=100 100w, path/hermes.jpg?w=200 200w" .../>
```
Add loading attribute to NgOptimizedImage.
This commit updates the error codes used in the `NgOptimizedImage` tests. The error codes got u[dated recently in a PR that got merged earlier.
This commit adds a built-in Imgix loader for the
NgOptimizedImage directive. If you provide the
desired Imgix hostname, an ImageLoader will be
generated with the correct options.

Usage looks like this:

```ts
providers: [
  provideImgixLoader('https://some.imgix.net')
]
```

It sets the "auto=format" flag by default, which
ensures that the smallest image format supported
by the browser is served.

This change also moves the IMAGE_LOADER, ImageLoader,
and ImageLoaderConfig into a new directory that will
be shared by all built-in image loaders.
This commit updates the `NgOptimizedImage` directive to add a logic to detect whether an image, marked with the "priority" attribute has a corresponding `<link rel="preconnect">` tag in the `document.head` for better performance.
…hecks in NgOptimizedImage

This commit adds an extra logic to add an ability to exclude origins from preconnect checks in NgOptimizedImage by configuring the `PRECONNECT_CHECK_BLOCKLIST` multi-provider.
pkozlowski-opensource pushed a commit that referenced this pull request Aug 16, 2022
…47082)

This commit adds the missing `formatRuntimeError` function to the code that makes sure there is no image distortion.

PR Close #47082
pkozlowski-opensource added a commit that referenced this pull request Aug 16, 2022
A small refactor that removes explicit toString calls when not needed.

PR Close #47082
pkozlowski-opensource added a commit that referenced this pull request Aug 16, 2022
This refactoring pulls url-related error reporting into one place.
It also makes sure that error messages and the related error
reporting logic are tree-shakable.

PR Close #47082
pkozlowski-opensource pushed a commit that referenced this pull request Aug 16, 2022
…timizedImage directive" (#47082)

This reverts commit a0fdb8c.

The `src` and `srcset` attributes don't pose security threats in modern browser, so sanitization is not really necessary.

PR Close #47082
pkozlowski-opensource pushed a commit that referenced this pull request Aug 16, 2022
…e Loaders (#47082)

This commit updates the logic of Image Loaders to throw an error in case an absolute URL is provided an an input to the loader function. The loaders can construct URLs based on image paths relative to the bas URL configured for a loader.

PR Close #47082
pkozlowski-opensource added a commit that referenced this pull request Aug 16, 2022
This commit moves the URL normalization logic in loaders to
the common loader logic.

PR Close #47082
pkozlowski-opensource added a commit that referenced this pull request Aug 16, 2022
This commit simplifies the URL construction logic by capturing
the base path and loader config argumnets in one function.

PR Close #47082
pkozlowski-opensource pushed a commit that referenced this pull request Aug 16, 2022
With this commit, the NgOptimizedImage directive will throw
a runtime error if it detects that one of the density descriptors
in rawSrcset is higher than 3x. It's generally not recommended
to use density descriptors higher than ~2, as it causes image to
download at very large sizes on mobile screens (thus slowing down
LCP). The density max is set conservatively to 3 in case apps
expect users to zoom in.

In future commits, we may want to throw even at densities >
than 2 and provide a configuration override for the zoom case.

PR Close #47082
pkozlowski-opensource pushed a commit that referenced this pull request Aug 16, 2022
…calls in tests (#47082)

This commit updates the `createEnvironmentInjector` calls to pass parent injector, which became required as an argument.

PR Close #47082
pkozlowski-opensource pushed a commit that referenced this pull request Aug 16, 2022
Update error message text to explain why width & height are required
attributes.

PR Close #47082
pkozlowski-opensource pushed a commit that referenced this pull request Aug 16, 2022
…#47082)

This commit updates error messages that the NgOptimizedImage directive throws or logs into a console.

PR Close #47082
pkozlowski-opensource pushed a commit that referenced this pull request Aug 16, 2022
This commit updates the NgOptimizedImage directive to become standalone and removes no longer needed NgOptimizedImageModule class.

PR Close #47082
pkozlowski-opensource pushed a commit that referenced this pull request Aug 16, 2022
#47082)

This commit annotates a set of symbols exposed by the NgOptimizedImage directive as a public API.

PR Close #47082
pkozlowski-opensource pushed a commit that referenced this pull request Aug 16, 2022
…ve (#47082)

This commit adds the docs for the NgOptimizedImage directive.
As a part of this commit, we also remove an export of directive-related symbols previously exposed as public APIs (i.e. APIs can not be used directly).

PR Close #47082
pkozlowski-opensource pushed a commit that referenced this pull request Aug 16, 2022
…ight error message (#47082)

This commit updates the error message thrown at runtime when an `<img>` doesn't contain width and/or height attributes.

PR Close #47082
pkozlowski-opensource pushed a commit that referenced this pull request Aug 16, 2022
This commit fixes a bug in NgOptimizedImage where
if you bound the width or height attribute (e.g.
`[width]=width`), the attribute would only be
reflected as "ng-reflect-x". The actual "width" or
"height" attribute would not be set on the host
element. This is a problem because the exact named
attribute must be set on the element for the
browser to detect it and use it to reserve space
for the image (and thus prevent CLS).

PR Close #47082
pkozlowski-opensource pushed a commit that referenced this pull request Aug 16, 2022
…47082)

This commit cleans up some stylistic nits and
moves functions out of util.ts into files that
are more specifically named (url.ts and error.ts).

PR Close #47082
pkozlowski-opensource pushed a commit that referenced this pull request Aug 16, 2022
This commit contains a set of small changes based on the feedback received in #47082.

PR Close #47082
pkozlowski-opensource added a commit that referenced this pull request Aug 16, 2022
Addresses part of the review feedback for the NgOptimizedImage directive.

PR Close #47082
pkozlowski-opensource pushed a commit that referenced this pull request Aug 16, 2022
…47082)

This commit adds a console warning in development mode
if the ultimate rendered size of the image is much
smaller than the dimensions of the requested image.
In this case, the warning recommends adjusting the
size of the source image or using the `rawSrcset`
attribute to implement responsive sizing.

PR Close #47082
pkozlowski-opensource pushed a commit that referenced this pull request Aug 16, 2022
This commit contains a set of small changes based on the feedback received in #47082.

PR Close #47082
* RegExpr to determine whether a src in a srcset is using density descriptors.
* Should match something like: "1x, 2x".
*/
const VALID_DENSITY_DESCRIPTOR_SRCSET = /^((\s*\d(\.\d)?x\s*(,|$)){1,})$/;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about density descriptors with more that one digits (in the integer or fractional part) or omitting the integer part. For example, the current regex will not match the following:

  • 1.25x
  • 10x
  • .9x

From what I understand by reading the spec, these are valid density descriptors.

Copy link
Contributor

@kara kara Aug 19, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

10x

  • This one, we intentionally don't support because we have a max density of 3 that we enforce with a warning/error.

.9x

  • While technically correct, I don't know of any devices that actually have 0.9x DPR? I don't think we need to support this. Curious what Katie/Alex think on this one though.

1.25x

  • Ah, I think we are missing multiple digit support for decimals (our existing test just looks for 1.5). Will fix this in a follow-up! Thanks for catching.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we need to support DPRs < 1. Although it's technically possible for devices have that DPR, I think it would imply the existence of a common display format "slightly worse than a CRT display" (which AFAIK is not a thing).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

10x

This one, we intentionally don't support because we have a max density of 3 that we enforce with a warning/error.

That's the point. Without properly detecting 10x as a valid density descriptor, we throw a confusing error (that the descriptor is not in a valid format) instead of throwing the intended error that the density is too high 😃

Notice in the code below that isValidDensityDescriptor will be false for 10x, which will skip the assertUnderDensityCap() check and throw the INVALID_INPUT error instead:

const isValidDensityDescriptor = VALID_DENSITY_DESCRIPTOR_SRCSET.test(stringVal);
if (isValidDensityDescriptor) {
assertUnderDensityCap(dir, stringVal);
}
const isValidSrcset = isValidWidthDescriptor || isValidDensityDescriptor;
if (!isValidSrcset) {
throw new RuntimeError(
RuntimeErrorCode.INVALID_INPUT,
`${imgDirectiveDetails(dir.rawSrc)} \`rawSrcset\` has an invalid value (\`${value}\`). ` +
`To fix this, supply \`rawSrcset\` using a comma-separated list of one or more width ` +
`descriptors (e.g. "100w, 200w") or density descriptors (e.g. "1x, 2x").`);
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ohh I see. Yeah, that's definitely not what we want. Will fix that in a follow-up too 👍

crapStone pushed a commit to Calciumdibromid/CaBr2 that referenced this pull request Sep 1, 2022
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [@angular/animations](https://github.com/angular/angular) | dependencies | minor | [`14.1.3` -> `14.2.0`](https://renovatebot.com/diffs/npm/@angular%2fanimations/14.1.3/14.2.0) |
| [@angular/common](https://github.com/angular/angular) | dependencies | minor | [`14.1.3` -> `14.2.0`](https://renovatebot.com/diffs/npm/@angular%2fcommon/14.1.3/14.2.0) |
| [@angular/compiler](https://github.com/angular/angular) | dependencies | minor | [`14.1.3` -> `14.2.0`](https://renovatebot.com/diffs/npm/@angular%2fcompiler/14.1.3/14.2.0) |
| [@angular/compiler-cli](https://github.com/angular/angular/tree/main/packages/compiler-cli) ([source](https://github.com/angular/angular)) | devDependencies | minor | [`14.1.3` -> `14.2.0`](https://renovatebot.com/diffs/npm/@angular%2fcompiler-cli/14.1.3/14.2.0) |
| [@angular/core](https://github.com/angular/angular) | dependencies | minor | [`14.1.3` -> `14.2.0`](https://renovatebot.com/diffs/npm/@angular%2fcore/14.1.3/14.2.0) |
| [@angular/forms](https://github.com/angular/angular) | dependencies | minor | [`14.1.3` -> `14.2.0`](https://renovatebot.com/diffs/npm/@angular%2fforms/14.1.3/14.2.0) |
| [@angular/platform-browser](https://github.com/angular/angular) | dependencies | minor | [`14.1.3` -> `14.2.0`](https://renovatebot.com/diffs/npm/@angular%2fplatform-browser/14.1.3/14.2.0) |
| [@angular/platform-browser-dynamic](https://github.com/angular/angular) | dependencies | minor | [`14.1.3` -> `14.2.0`](https://renovatebot.com/diffs/npm/@angular%2fplatform-browser-dynamic/14.1.3/14.2.0) |

---

### Release Notes

<details>
<summary>angular/angular</summary>

### [`v14.2.0`](https://github.com/angular/angular/blob/HEAD/CHANGELOG.md#&#8203;1420-2022-08-25)

[Compare Source](angular/angular@14.1.3...14.2.0)

##### animations

| Commit | Type | Description |
| -- | -- | -- |
| [b96e571897](angular/angular@b96e571) | fix | fix stagger timing not handling params ([#&#8203;47208](angular/angular#47208)) |

##### common

| Commit | Type | Description |
| -- | -- | -- |
| [b380fdd59e](angular/angular@b380fdd) | feat | add a density cap for image srcsets ([#&#8203;47082](angular/angular#47082)) |
| [7ce497e5bc](angular/angular@7ce497e) | feat | add built-in Imgix loader ([#&#8203;47082](angular/angular#47082)) |
| [bff870db61](angular/angular@bff870d) | feat | add cloudflare loader ([#&#8203;47082](angular/angular#47082)) |
| [86e77a5d55](angular/angular@86e77a5) | feat | add Image directive skeleton ([#&#8203;45627](angular/angular#45627)) ([#&#8203;47082](angular/angular#47082)) |
| [0566205a02](angular/angular@0566205) | feat | Add image lazy loading and fetchpriority ([#&#8203;47082](angular/angular#47082)) |
| [4e952ba216](angular/angular@4e952ba) | feat | add loaders for cloudinary & imagekit ([#&#8203;47082](angular/angular#47082)) |
| [e854a8cdde](angular/angular@e854a8c) | feat | add loading attr to NgOptimizedImage ([#&#8203;47082](angular/angular#47082)) |
| [8d3701cb4c](angular/angular@8d3701c) | feat | add warnings re: image distortion ([#&#8203;47082](angular/angular#47082)) |
| [d5f7da2120](angular/angular@d5f7da2) | feat | define public API surface for NgOptimizedImage directive ([#&#8203;47082](angular/angular#47082)) |
| [d3c3426aa4](angular/angular@d3c3426) | feat | detect LCP images in `NgOptimizedImage` and assert if `priority` is set ([#&#8203;47082](angular/angular#47082)) |
| [451b85ca17](angular/angular@451b85c) | feat | explain why width/height is required ([#&#8203;47082](angular/angular#47082)) |
| [586274fe65](angular/angular@586274f) | feat | provide an ability to exclude origins from preconnect checks in NgOptimizedImage ([#&#8203;47082](angular/angular#47082)) |
| [57f3386e5b](angular/angular@57f3386) | feat | support custom srcset attributes in NgOptimizedImage ([#&#8203;47082](angular/angular#47082)) |
| [7baf9a46cd](angular/angular@7baf9a4) | feat | verify that priority images have preconnect links ([#&#8203;47082](angular/angular#47082)) |
| [f81765b333](angular/angular@f81765b) | feat | warn if rendered size is much smaller than intrinsic ([#&#8203;47082](angular/angular#47082)) |
| [e2ab99b95e](angular/angular@e2ab99b) | fix | allow null/undefined to be passed to ngClass input ([#&#8203;39280](angular/angular#39280)) ([#&#8203;46906](angular/angular#46906)) |
| [bedf537951](angular/angular@bedf537) | fix | allow null/undefined to be passed to ngStyle input ([#&#8203;47069](angular/angular#47069)) |
| [f9511bf6e8](angular/angular@f9511bf) | fix | avoid interacting with a destroyed injector ([#&#8203;47243](angular/angular#47243)) |
| [dc29e21b14](angular/angular@dc29e21) | fix | consider density descriptors with multiple digits as valid ([#&#8203;47230](angular/angular#47230)) |
| [801daf82d1](angular/angular@801daf8) | fix | detect `data:` and `blob:` inputs in `NgOptimizedImage` directive ([#&#8203;47082](angular/angular#47082)) |
| [fff8056e7f](angular/angular@fff8056) | fix | fix formatting on oversized image error ([#&#8203;47188](angular/angular#47188)) ([#&#8203;47232](angular/angular#47232)) |
| [1ca2ce19ab](angular/angular@1ca2ce1) | fix | remove default for image width ([#&#8203;47082](angular/angular#47082)) |
| [c5db867ddc](angular/angular@c5db867) | fix | remove duplicate deepForEach ([#&#8203;47189](angular/angular#47189)) |
| [1cf43deb18](angular/angular@1cf43de) | fix | sanitize `rawSrc` and `rawSrcset` values in NgOptimizedImage directive ([#&#8203;47082](angular/angular#47082)) |
| [d71dfe931f](angular/angular@d71dfe9) | fix | set bound width and height onto host element ([#&#8203;47082](angular/angular#47082)) |
| [32caa8b669](angular/angular@32caa8b) | fix | support density descriptors with 2+ decimals ([#&#8203;47197](angular/angular#47197)) ([#&#8203;47232](angular/angular#47232)) |
| [ae4405f0bf](angular/angular@ae4405f) | fix | throw if srcset is used with rawSrc ([#&#8203;47082](angular/angular#47082)) |
| [0c8eb8bc82](angular/angular@0c8eb8b) | perf | monitor LCP only for images without `priority` attribute ([#&#8203;47082](angular/angular#47082)) |

##### compiler-cli

| Commit | Type | Description |
| -- | -- | -- |
| [ea89677c12](angular/angular@ea89677) | feat | support more recent version of `tsickle` ([#&#8203;47018](angular/angular#47018)) |

##### core

| Commit | Type | Description |
| -- | -- | -- |
| [d1e83e1b30](angular/angular@d1e83e1) | feat | add `createComponent` function ([#&#8203;46685](angular/angular#46685)) |
| [10becab70e](angular/angular@10becab) | feat | add `reflectComponentType` function ([#&#8203;46685](angular/angular#46685)) |
| [4b377d3a6d](angular/angular@4b377d3) | feat | introduce createApplication API ([#&#8203;46475](angular/angular#46475)) |
| [31429eaccc](angular/angular@31429ea) | feat | support TypeScript 4.8 ([#&#8203;47038](angular/angular#47038)) |
| [796840209c](angular/angular@7968402) | fix | align TestBed interfaces and implementation ([#&#8203;46635](angular/angular#46635)) |

##### forms

| Commit | Type | Description |
| -- | -- | -- |
| [426af91a42](angular/angular@426af91) | feat | add `FormBuilder.record()` method ([#&#8203;46485](angular/angular#46485)) |
| [b302797de4](angular/angular@b302797) | fix | Correctly infer `FormBuilder` types involving `[value, validators]` shorthand in more cases. ([#&#8203;47034](angular/angular#47034)) |

##### language-service

| Commit | Type | Description |
| -- | -- | -- |
| [598b72bd05](angular/angular@598b72b) | feat | support fix the component missing member ([#&#8203;46764](angular/angular#46764)) |

##### platform-browser

| Commit | Type | Description |
| -- | -- | -- |
| [07606e3181](angular/angular@07606e3) | feat | add `isEmpty` method to the `TransferState` class ([#&#8203;46915](angular/angular#46915)) |

##### platform-server

| Commit | Type | Description |
| -- | -- | -- |
| [2b4d7f6733](angular/angular@2b4d7f6) | feat | support document reference in render functions ([#&#8203;47032](angular/angular#47032)) |

##### router

| Commit | Type | Description |
| -- | -- | -- |
| [0abb67af59](angular/angular@0abb67a) | feat | allow guards and resolvers to be plain functions ([#&#8203;46684](angular/angular#46684)) |
| [75df404467](angular/angular@75df404) | feat | Create APIs for using Router without RouterModule ([#&#8203;47010](angular/angular#47010)) |
| [10289f1f6e](angular/angular@10289f1) | feat | expose resolved route title ([#&#8203;46826](angular/angular#46826)) |
| [8600732b09](angular/angular@8600732) | feat | Expose the default matcher for `Routes` used by the `Router` ([#&#8203;46913](angular/angular#46913)) |
| [422323cee0](angular/angular@422323c) | feat | improve typings for RouterLink boolean inputs ([#&#8203;47101](angular/angular#47101)) |
| [26ea97688c](angular/angular@26ea976) | feat | Make router directives standalone ([#&#8203;46758](angular/angular#46758)) |
| [2a43beec15](angular/angular@2a43bee) | fix | Fix route recognition behavior with some versions of rxjs ([#&#8203;47098](angular/angular#47098)) |

##### service-worker

| Commit | Type | Description |
| -- | -- | -- |
| [383090858c](angular/angular@3830908) | feat | support `sendRequest` as a `notificationclick` action ([#&#8203;46912](angular/angular#46912)) |
| [3f548610dd](angular/angular@3f54861) | fix | export NoNewVersionDetectedEvent ([#&#8203;47044](angular/angular#47044)) |
| [482b6119c2](angular/angular@482b611) | fix | update golden `index.md` ([#&#8203;47044](angular/angular#47044)) |

#### Special Thanks

Alex Rickabaugh, Andrew Kushnir, Andrew Scott, Bob Watson, Cédric Exbrayat, Dylan Hunn, Emmanuel Roux, FatalMerlin, George Kalpakas, Ilia Mirkin, Jan Kuehle, Jeremy Elbourn, Jessica Janiuk, JiaLiPassion, Kalbarczyk, Kara Erickson, Katie Hempenius, Kristiyan Kostadinov, Merlin, Paul Gschwendtner, Pawel Kozlowski, Tristan Sprößer, Victor Porof, angular-robot\[bot], dario-piotrowicz, ivanwonder and vyom

<!-- CHANGELOG SPLIT MARKER -->

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about these updates again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, click this checkbox.

---

This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzMi4xNzQuMiIsInVwZGF0ZWRJblZlciI6IjMyLjE3Ny4xIn0=-->

Co-authored-by: cabr2-bot <cabr2.help@gmail.com>
Reviewed-on: https://codeberg.org/Calciumdibromid/CaBr2/pulls/1523
Reviewed-by: Epsilon_02 <epsilon_02@noreply.codeberg.org>
Co-authored-by: Calciumdibromid Bot <cabr2_bot@noreply.codeberg.org>
Co-committed-by: Calciumdibromid Bot <cabr2_bot@noreply.codeberg.org>
@angular-automatic-lock-bot
Copy link

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Sep 21, 2022
@josephperrott josephperrott deleted the image-directive branch January 18, 2024 18:59
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
action: merge The PR is ready for merge by the caretaker area: common Issues related to APIs in the @angular/common package feature Issue that requests a new feature target: minor This PR is targeted for the next minor release
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Provide image component similar to next/image