diff --git a/apps/docs/.vitepress/config.ts b/apps/docs/.vitepress/config.ts
index 3a14b36dc..da18b7f23 100644
--- a/apps/docs/.vitepress/config.ts
+++ b/apps/docs/.vitepress/config.ts
@@ -24,6 +24,29 @@ export default defineConfig({
text: 'Image CDNs',
link: '/cdn/',
},
+
+ {
+ text: 'About',
+ // link: '/usage/concepts',
+ items: [
+ {
+ text: 'Releases',
+ link: 'https://github.com/simonihmig/responsive-image/releases',
+ },
+ {
+ text: 'Me',
+ link: '/me',
+ },
+ {
+ text: 'History',
+ link: '/history',
+ },
+ {
+ text: 'Credits',
+ link: '/credits',
+ },
+ ],
+ },
],
sidebar: [
diff --git a/apps/docs/src/api-examples.md b/apps/docs/src/api-examples.md
deleted file mode 100644
index 6bd8bb5c1..000000000
--- a/apps/docs/src/api-examples.md
+++ /dev/null
@@ -1,49 +0,0 @@
----
-outline: deep
----
-
-# Runtime API Examples
-
-This page demonstrates usage of some of the runtime APIs provided by VitePress.
-
-The main `useData()` API can be used to access site, theme, and page data for the current page. It works in both `.md` and `.vue` files:
-
-```md
-
-
-## Results
-
-### Theme Data
-
{{ theme }}
-
-### Page Data
-{{ page }}
-
-### Page Frontmatter
-{{ frontmatter }}
-```
-
-
-
-## Results
-
-### Theme Data
-{{ theme }}
-
-### Page Data
-{{ page }}
-
-### Page Frontmatter
-{{ frontmatter }}
-
-## More
-
-Check out the documentation for the [full list of runtime APIs](https://vitepress.dev/reference/runtime-api#usedata).
diff --git a/apps/docs/src/build/vite.md b/apps/docs/src/build/vite.md
index b4513087a..5a135d3bb 100644
--- a/apps/docs/src/build/vite.md
+++ b/apps/docs/src/build/vite.md
@@ -71,19 +71,25 @@ setupPlugins({
Besides global settings, you can also pass all the supported configuration options as query parameters when importimng an image:
```js
-import logo from './logo.jpg?responsive&w=32,64&quality=95';
+import logo from './logo.jpg?&w=32;64&quality=95&responsive';
```
-Query params alwas take precedence of global settings passed to `setupPlugins()`.
+Query params always take precedence over global settings passed to `setupPlugins()`.
### Configuration options
-| option | type | description | default |
-| --------- | ---------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------- |
-| `w` | `Array` | The image widths to be generated. For responsive images this should match the typical device sizes, eventually taking account when the image is not covering the full screen size, like `50vw`. For fixed size images this should be the intended size and twice of it for 2x displays. Pass this as a comma separated list when using query params. | `640, 750, 828, 1080, 1200, 1920, 2048, 3840` |
-| `format` | `Array<'original' \| 'png' \| 'jpeg' \| 'webp'\|'avif'>` | The image formats to generate. `original` refers to whatever the original image's type is. Pass this as a comma separated list when using query params. | `['original', 'webp']` |
-| `quality` | `number` | The image quality (0 - 100). | 80 |
-| `name` | `string` | The template for the generated image files. The placeholders `[name]`, `[ext]` and `[width]` are replaced with real values. | [name]-[width]w.[ext] |
-| `lqip` | `{ type: 'color' } \| {type: 'inline'; targetPixels?: number; } \| { type: 'blurhash'; targetPixels?: number; }` | Configuration for [Low Quality Image Placeholders](../usage/lqip.md). For passing this as a query param to your import, you can pass this as a string when you don't need to set anything beyond `type` (e.g. `image.jpg?responsive&lqip=inline`), or as a JSON stringified value (e.g. `image.jpg?responsive&lqip={"type":"blurhash","targetPixels":16}`). |
+All the general [image parameters](../usage/local-images.md#image-parameters-reference) for local images can be specified both as global options or as query params, as explained above.
----
+On top of that, there are the following Vite specific options, that you can customize the same way. In most cses, the existing defaults should be sufficient though.
+
+#### `name: string`
+
+The template for the generated image files. The placeholders `[name]`, `[ext]` and `[width]` are replaced with real values.
+
+Default: `[name]-[width]w.[ext]`
+
+```js
+setsetupPluginsupLoaders({
+ name: '[name]_[width].[ext]',
+});
+```
diff --git a/apps/docs/src/build/webpack.md b/apps/docs/src/build/webpack.md
index 2d46e3143..efc9b68a6 100644
--- a/apps/docs/src/build/webpack.md
+++ b/apps/docs/src/build/webpack.md
@@ -60,7 +60,7 @@ const config = {
### Global configuration
-The package comes with reasonable defaults, but if you want to customize these for all image imports globally, then you can pass an optional configuration object to `setupLoaders()`:
+The package comes with reasonable defaults, but if you want to customize these for all image imports globally, then you can pass an optional object with [configuration options](#configuration-options) to `setupLoaders()`:
```js
setupLoaders({
@@ -71,24 +71,44 @@ setupLoaders({
### Query params
-Besides global settings, you can also pass all the supported configuration options as query parameters when importimng an image:
+Besides global settings, you can also pass all the supported [configuration options](#configuration-options) as query parameters when importing an image:
```js
-import logo from './logo.jpg?responsive&w=32,64&quality=95';
+import logo from './logo.jpg?&w=32;64&quality=95&responsive';
```
-Query params alwas take precedence of global settings passed to `setupLoaders()`.
+Query params always take precedence over global settings passed to `setupLoaders()`.
### Configuration options
-| option | type | description | default |
-| ------------ | ---------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------- |
-| `w` | `Array` | The image widths to be generated. For responsive images this should match the typical device sizes, eventually taking account when the image is not covering the full screen size, like `50vw`. For fixed size images this should be the intended size and twice of it for 2x displays. Pass this as a comma separated list when using query params. | `640, 750, 828, 1080, 1200, 1920, 2048, 3840` |
-| `format` | `Array<'original' \| 'png' \| 'jpeg' \| 'webp'\|'avif'>` | The image formats to generate. `original` refers to whatever the original image's type is. Pass this as a comma separated list when using query params. | `['original', 'webp']` |
-| `quality` | `number` | The image quality (0 - 100). | 80 |
-| `name` | `string` | The template for the generated image files. Certains placeholders like `[ext]` and `[width]` and all the common Webpack placeholders are replaced with real values. | [name]-[width]w-[hash].[ext] |
-| `webPath` | `string` | The public URL the emitted files are referenced from. By default, this matches Webpacks public URL and the path generated from `outputPath`. |
-| `outputPath` | `string` | The file path where the public image files are emitted to. This is relative to the default folder configured for public asset files in Webpack. | images |
-| `lqip` | `{ type: 'color' } \| {type: 'inline'; targetPixels?: number; } \| { type: 'blurhash'; targetPixels?: number; }` | Configuration for [Low Quality Image Placeholders](../usage/lqip.md). For passing this as a query param to your import, you can pass this as a string when you don't need to set anything beyond `type` (e.g. `image.jpg?responsive&lqip=inline`), or as a JSON stringified value (e.g. `image.jpg?responsive&lqip={"type":"blurhash","targetPixels":16}`). |
-
----
+All the general [image parameters](../usage/local-images.md#image-parameters-reference) for local images can be specified both as global options or as query params, as explained above.
+
+On top of that, there are the following webpack specific options, that you can customize the same way. In most cses, the existing defaults should be sufficient though.
+
+#### `name: string`
+
+The template for the generated image files. Certains placeholders like `[ext]` and `[width]` and all the common Webpack placeholders are replaced with real values.
+
+Default: `[name]-[width]w-[hash].[ext]`
+
+```js
+setupLoaders({
+ name: '[name]_[width].[hash].[ext]',
+});
+```
+
+#### `webPath: string`
+
+The public URL the emitted files are referenced from. By default, this matches Webpacks public URL and the path generated from `outputPath`.
+
+```js
+setupLoaders({
+ webPath: 'https://images.example.com/',
+});
+```
+
+#### `outputPath: string`
+
+The file path where the public image files are emitted to. This is relative to the default folder configured for public asset files in Webpack.
+
+Default: `images`
diff --git a/apps/docs/src/credits.md b/apps/docs/src/credits.md
new file mode 100644
index 000000000..ddc56f34e
--- /dev/null
+++ b/apps/docs/src/credits.md
@@ -0,0 +1,11 @@
+# Credit where credit is due...
+
+I would like to thank the following people for their direct or indirect contributions to this project:
+
+- [Andreas Schacht](https://github.com/andreasschacht) for his fantastic work on the initial version of `ember-responsive-image`, the predecessor of this project.
+
+- [Malte Ubl](https://github.com/cramforce) for his blog post [Maximally optimizing image loading for the web in 2021](https://www.industrialempathy.com/posts/image-optimizations/) that inspired many of the image optimization techniques used here.
+
+- [Lovell Fuller](https://github.com/lovell) for [sharp](https://github.com/lovell/sharp), the library that is powering all image processing of local images.
+
+- [Jonas Kruckenberg](https://github.com/JonasKruckenberg) for [imagetools](https://github.com/JonasKruckenberg/imagetools) to support (query) parameter based image adjustments and effects.
diff --git a/apps/docs/src/frameworks/ember.md b/apps/docs/src/frameworks/ember.md
index 656c58150..7b660e578 100644
--- a/apps/docs/src/frameworks/ember.md
+++ b/apps/docs/src/frameworks/ember.md
@@ -163,3 +163,21 @@ declare module '@glint/environment-ember-loose/registry' {
}
}
```
+
+### Image imports
+
+To make TypeScript understand your image imports, we tag them using a `responsive` query parameter, that has to come _last_!
+
+> [!NOTE]
+> We cannot use something like `*.jpg*` that works with queries, as TS only supports a single wildcard.
+> See https://github.com/microsoft/TypeScript/issues/38638
+
+Add this declaration to a file, e.g. your app's `types/global.d.ts`:
+
+```ts
+declare module '*responsive' {
+ import { ImageData } from '@responsive-image/ember';
+ const value: ImageData;
+ export default value;
+}
+```
diff --git a/apps/docs/src/frameworks/index.md b/apps/docs/src/frameworks/index.md
index 2d3fddf6d..516772c3b 100644
--- a/apps/docs/src/frameworks/index.md
+++ b/apps/docs/src/frameworks/index.md
@@ -1 +1,8 @@
# Frontend frameworks
+
+The [image component](../usage/component.md) and other utilities are provided with framework specific packages:
+
+- [Ember](./ember.md)
+
+> [!NOTE]
+> Multi-framework support is still WIP. More supported frameworks will be added here over time...
diff --git a/apps/docs/src/history.md b/apps/docs/src/history.md
new file mode 100644
index 000000000..083bb4a27
--- /dev/null
+++ b/apps/docs/src/history.md
@@ -0,0 +1,17 @@
+# History of the project
+
+This project has its roots in late 2016, when Andreas Schacht, my then co-worker, and [me](./me.md) started to work on `ember-responsive-image`. This came out of the need to render optimized responsive images in our framkework of choice [Ember.js](https://emberjs.com/), for client projects at [kaliber5](https://www.kaliber5.de), the consultancy that I co-founded.
+
+As strong believers in open source software, and as this proved to be useful for others as well, we started the project in the open on GitHub, see the [first commit](https://github.com/simonihmig/responsive-image/commit/1718f0c6d113d21309cb3800338c944d5ba90943). Don't look too closely at the code though, 2016 was different! 😅
+
+Over time it matured and improved. Feature-wise by adding support for e.g. next-gen image formats, Image CDNs or SSR (aka FastBoot in Ember world). Also much of the underlying implementation evolved, moving from invoking `ImageMagick` to using [`sharp`](https://sharp.pixelplumbing.com/), adopting Ember's [Octane](https://blog.emberjs.com/octane-is-here/) patterns (native classes, Glimmer components) and TypeScript.
+
+But at some point it become obvious that we were running into a more fundamental technical problem, when [Embroider](https://github.com/embroider-build/embroider), Ember's next-gen build system, which is building a bridge towards adopting popular ecosystem build tools like webpack or Vite, was going to take over the very Ember-specific build system of Ember CLI. Alongside that came a new [v2 format](https://rfcs.emberjs.com/id/0507-embroider-v2-package-format/) to publish Ember addons. Previously, `ember-responsive-image` had the privilege of using the superpowers that v1 addons gave us, by being able to provide Ember runtime code (the component to render responsive images) _and_ plugging into the (legacy) Ember CLI build (for processing local images) _at the same time_. With the new v2 format, which are basically just static npm packages now that you import _runtime_ code from, this was not possible anymore. So what's next?
+
+As Embroider embraced off-the-shelve build tools like [webpack](https://webpack.js.org/) and later [Vite](https://vitejs.dev/), this project basically had to do the same. Instead of tying our image processing into the legacy build system, we started to offer native [build-plugins](./build/index.md) for what Embroider uses already: webpack and Vite. These are now doing the heavy lifting, albeit in a completely frontend framework agnostic way!
+
+This opened up the way to rethink the scope of this project: instead of being coupled to one specific framework, [Ember](https://emberjs.com/) (which I still love btw and encourage you to check out if you haven't lately!), this project started to move into a multi-framework project. Gone is the `ember-responsive-image` package, say hello to `@responsive-image/ember`, which is now a fully static lightweight v2 addon. Support for other frameworks is planned. Have ideas, or want to contribute? Feel free to raise an [issue](https://github.com/simonihmig/responsive-image/issues), [PR](https://github.com/simonihmig/responsive-image/pulls)'s are certainly very welcome as well! 😀
+
+So stay tuned, the future is hopefully bright!
+
+_PS. none of this would have been possible without the help of other people and building on the shoulders of giants, which I want to give [credit](credits.md) here!_
diff --git a/apps/docs/src/markdown-examples.md b/apps/docs/src/markdown-examples.md
deleted file mode 100644
index f9258a550..000000000
--- a/apps/docs/src/markdown-examples.md
+++ /dev/null
@@ -1,85 +0,0 @@
-# Markdown Extension Examples
-
-This page demonstrates some of the built-in markdown extensions provided by VitePress.
-
-## Syntax Highlighting
-
-VitePress provides Syntax Highlighting powered by [Shiki](https://github.com/shikijs/shiki), with additional features like line-highlighting:
-
-**Input**
-
-````md
-```js{4}
-export default {
- data () {
- return {
- msg: 'Highlighted!'
- }
- }
-}
-```
-````
-
-**Output**
-
-```js{4}
-export default {
- data () {
- return {
- msg: 'Highlighted!'
- }
- }
-}
-```
-
-## Custom Containers
-
-**Input**
-
-```md
-::: info
-This is an info box.
-:::
-
-::: tip
-This is a tip.
-:::
-
-::: warning
-This is a warning.
-:::
-
-::: danger
-This is a dangerous warning.
-:::
-
-::: details
-This is a details block.
-:::
-```
-
-**Output**
-
-::: info
-This is an info box.
-:::
-
-::: tip
-This is a tip.
-:::
-
-::: warning
-This is a warning.
-:::
-
-::: danger
-This is a dangerous warning.
-:::
-
-::: details
-This is a details block.
-:::
-
-## More
-
-Check out the documentation for the [full list of markdown extensions](https://vitepress.dev/guide/markdown).
diff --git a/apps/docs/src/me.md b/apps/docs/src/me.md
new file mode 100644
index 000000000..878394b1e
--- /dev/null
+++ b/apps/docs/src/me.md
@@ -0,0 +1,31 @@
+
+
+# About me
+
+This project is brought to you by... me! 🙃
+
+
diff --git a/apps/docs/src/usage/component.md b/apps/docs/src/usage/component.md
index 578a3ec1d..a948c9ce3 100644
--- a/apps/docs/src/usage/component.md
+++ b/apps/docs/src/usage/component.md
@@ -104,7 +104,7 @@ A fixed layout will render the image with the specific dimensions as specified.
::: code-group
```gjs [Ember]
-import logoImage from './hero.jpg?responsive&w=320;640';
+import logoImage from './hero.jpg?w=320;640&responsive';
diff --git a/apps/docs/src/usage/local-images.md b/apps/docs/src/usage/local-images.md
index 00c101203..79e47f2c9 100644
--- a/apps/docs/src/usage/local-images.md
+++ b/apps/docs/src/usage/local-images.md
@@ -23,7 +23,7 @@ The following example is using a `200px` wide [fixed layout](./component.md#fixe
```gjs [Ember]
import { ResponsiveImage } from '@responsive-image/ember';
-import image from './image.jpg?responsive&w=200,400&quality=90&lqip=inline';
+import image from './image.jpg?w=200;400&quality=90&lqip=inline&responsive';
@@ -34,6 +34,231 @@ import image from './image.jpg?responsive&w=200,400&quality=90&lqip=inline';
## Image parameters reference
-The following table lists all supported image parameters:
+### Core parameters
-TODO
+#### `w: number[]`
+
+The image widths to be generated. For responsive images this should match the typical device sizes, eventually taking account when the image is not covering the full screen size, like `50vw`. For fixed size images this should be the intended size and twice of it for 2x displays. Pass this as a semicolon separated list when using query params.
+
+Defaults: `[640, 750, 828, 1080, 1200, 1920, 2048, 3840]`
+
+```js
+import image from 'image.jpg?w=200;400&responsive';
+```
+
+#### `format: string[]`
+
+The [image formats](./image-formats.md) to generate. Pass this as a semicolon separated list when using query params. Supported formats are:
+
+- `original` refers to whatever the original image's type is.
+- `jpeg`
+- `png`
+- `webp`
+- `avif`
+
+Defaults: `['original', 'webp']`
+
+```js
+import image from 'image.jpg?format=original;webp;avif&responsive';
+```
+
+#### `lqip: string | json`
+
+Specify the options to render Low Quality Image Placeholders. Please refer to the [LQIP](./lqip.md) guide for details and examples.
+
+### Image processing parameters
+
+The following table lists all supported image parameters that apply image optional adjustments or effects.
+
+> [!Note]
+> These parameters are supported by the [imagetools](https://github.com/JonasKruckenberg/imagetools) library. The following section provides a brief summary, you can find its more detailed [documentation here](https://github.com/JonasKruckenberg/imagetools/blob/main/docs/parameters.md). Do not use any of its "output parameters" though, as they are not supported nor needed for ResponsiveImage.
+
+#### `background: string`
+
+This instructs other parameters (e.g. `rotate`) to use the specified color when filling empty spots in the image.
+
+```js
+import image from 'image.jpg?background=#FFFFFFAA&responsive';
+import image from 'image.jpg?background=hsl(360,100%,50%)&responsive';
+import image from 'image.jpg?background=rgb(200,200,200)&responsive';
+import image from 'image.jpg?background=blue&responsive';
+```
+
+#### `blur: number | boolean`
+
+Blurs the image. When no argument is provided it performs a fast blur, otherwise a more accurate gaussian blur.
+
+```js
+import image from 'image.jpg?blur&responsive';
+import image from 'image.jpg?blur=0.75&responsive';
+import image from 'image.jpg?blur=100&responsive';
+```
+
+#### `fit: 'cover' | 'contain' | 'fill' | 'inside' | 'outside'`
+
+When both width and height are provided, this parameter specifies the method to fit the image into the given dimensions.
+
+```js
+import image from 'image.jpg?fit=cover&responsive';
+```
+
+#### `flatten: boolean`
+
+Remove the alpha channel of the image, transparent pixels will be merged with the color set by [background](#background-string).
+
+#### `flip: boolean`
+
+Flip the image about the vertical axis. This step is always performed **after** any rotation.
+
+```js
+import image from 'image.jpg?flip&responsive';
+```
+
+#### `flop: boolean`
+
+Flop the image about the horizontal axis. This step is always performed **after** any rotation.
+
+```js
+import image from 'image.jpg?flop&responsive';
+```
+
+#### `grayscale: boolean`
+
+Converts the image to a grayscale image.
+
+```js
+import image from 'image.jpg?grayscale&responsive';
+```
+
+#### `hue: number`
+
+Adjusts the images hue rotation by the given number of degrees.
+
+#### `saturation: number`
+
+Adjusts the images saturation with the given saturation multiplier.
+
+#### `brightness: number`
+
+Adjusts the images brightness with the given brightness multiplier.
+
+#### `invert: boolean`
+
+Invert the image.
+
+```js
+import image from 'image.jpg?invert&responsive';
+```
+
+#### `lossless: boolean`
+
+Use lossless compression mode where supported (`avif` and `webp`).
+
+```js
+import image from 'image.jpg?format=webp&lossless&responsive';
+```
+
+#### `median: number | boolean`
+
+Applies a median filter. This is commonly used to remove noise from images.
+
+```js
+import image from 'image.jpg?median&responsive';
+import image from 'image.jpg?median=3&responsive';
+import image from 'image.jpg?median=50&responsive';
+```
+
+#### `normalize: boolean`
+
+Stretching its luminance to cover the full dynamic range enhancing its contrast.
+
+```js
+import image from 'image.jpg?normalize&responsive';
+```
+
+#### `position: string`
+
+When both `width` and `height` are provided AND the fit is one of `fit` of `cover` or `contain`, this parameter can be
+used to set the position of the image.
+
+See sharps [resize options](https://sharp.pixelplumbing.com/api-resize#resize) for a detailed explanation of each.
+
+#### `quality: number`
+
+Adjust the image quality (1 - 100). Higher number means better quality but also larger file size.
+
+```js
+import image from 'image.jpg?format=webp&quality=100&responsive';
+```
+
+
+
+#### `h: number`
+
+Set the height explicitly. Usually this is derived from the image's aspect ratio and the given width.
+
+```js
+import image from 'image.jpg?h=200&responsive';
+import image from 'image.jpg?h=200;400;700&responsive';
+```
+
+
+
+
+
+
+
+#### `rotate: number`
+
+Rotate the image by the specified number of degrees.
+
+> NOTE: You can change the background color the empty parts are filled with by setting the [background](#background-string) parameter.
+
+```js
+import image from 'image.jpg?rotate=90&responsive';
+```
+
+#### `tint: string`
+
+Tints the image using the provided chroma while preserving the image luminance.
+
+```js
+import image from 'image.jpg?tint=#ffaa22&responsive';
+import image from 'image.jpg?tint=rgba(10,33,127)&responsive';
+```
diff --git a/apps/docs/src/usage/lqip.md b/apps/docs/src/usage/lqip.md
index 8eadaa2dc..9defea434 100644
--- a/apps/docs/src/usage/lqip.md
+++ b/apps/docs/src/usage/lqip.md
@@ -74,7 +74,7 @@ The size of that placeholder image will be automatically calculated (taking into
::: code-group
```js [Import query params]
-import heroImage from './hero.jpg?responsive&lqip={"type":"inline","targetPixels":120}';
+import heroImage from './hero.jpg?lqip={"type":"inline","targetPixels":120}&responsive';
```
```js [Webpack global options]
@@ -107,7 +107,7 @@ You can opt into this LQIP mode either on a case by case basis by adding query p
::: code-group
```js [Import query params]
-import heroImage from './hero.jpg?responsive&lqip=blurhash';
+import heroImage from './hero.jpg?lqip=blurhash&responsive';
```
```js [Webpack global options]