├── .github └── README.md ├── .gitignore ├── .prettierignore ├── .prettierrc.yml ├── .vitepress ├── config.ts └── theme │ ├── README.md │ ├── global-components │ └── NewsList.vue │ ├── index.ts │ ├── package-lock.json │ ├── package.json │ └── styles │ ├── custom.css │ └── layout.css ├── LICENSE ├── docs ├── adjustment.md ├── crop.md ├── fit.md ├── format.md ├── introduction.md ├── mask.md ├── orientation.md ├── quick-reference.md ├── size.md └── supported-colors.md ├── faq └── index.md ├── index.md ├── news ├── 2018 │ └── 07 │ │ └── 29 │ │ └── introducing-api-4.md ├── 2019 │ └── 09 │ │ └── 01 │ │ └── introducing-api-5.md └── index.md ├── package-lock.json ├── package.json └── public ├── android-chrome-192x192.png ├── android-chrome-512x512.png ├── api-resize-fit-dark.svg ├── api-resize-fit.svg ├── apple-touch-icon.png ├── banana.webp ├── browserconfig.xml ├── cloudflare-logo-dark.svg ├── cloudflare-logo.svg ├── favicon-16x16.png ├── favicon-32x32.png ├── favicon-48x48.png ├── favicon.ico ├── humans.txt ├── lichtenstein.jpg ├── logo-dark.svg ├── logo.svg ├── made-in-sneek.svg ├── mstile-144x144.png ├── mstile-150x150.png ├── mstile-310x150.png ├── mstile-310x310.png ├── mstile-70x70.png ├── placeholder.svg ├── puppy.jpg ├── robots.txt ├── safari-pinned-tab.svg ├── security.txt ├── site.webmanifest ├── transparency_demo.png └── zebra.jpg /.github/README.md: -------------------------------------------------------------------------------- 1 | # weserv/docs 2 | 3 | Documentation for [wsrv.nl](https://wsrv.nl/). 4 | 5 | ## Built with 6 | 7 | - [Node.js](https://nodejs.org/) 8 | - [VitePress](https://github.com/vuejs/vitepress) 9 | 10 | ## Getting started 11 | 12 | ```shell 13 | git clone https://github.com/weserv/docs.git 14 | cd docs 15 | yarn # OR npm install 16 | ``` 17 | 18 | ### As easy as 1, 2, 3 19 | 20 | ```shell 21 | # Create a markdown file and write something 22 | echo '# Hello World' > docs/Hello.md 23 | 24 | # Start writing 25 | yarn run dev # OR npm run dev 26 | 27 | # Build to static files 28 | yarn run build # OR npm run build 29 | 30 | # Serve dist/ 31 | docker run -d -p 8080:80 -v "$(pwd)/dist:/var/www/imagesweserv/public" --shm-size=1gb --name=weserv ghcr.io/weserv/images:5.x 32 | # Visit http://localhost:8080/ 33 | ``` 34 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | .temp 4 | dist 5 | 6 | # Log files 7 | npm-debug.log* 8 | yarn-debug.log* 9 | yarn-error.log* 10 | 11 | # Editor directories and files 12 | .idea 13 | .vscode 14 | *.suo 15 | *.ntvs* 16 | *.njsproj 17 | *.sln 18 | *.sw* 19 | 20 | # VitePress 21 | .vitepress/cache 22 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | *.md 2 | *.vue 3 | dist 4 | -------------------------------------------------------------------------------- /.prettierrc.yml: -------------------------------------------------------------------------------- 1 | semi: true 2 | singleQuote: true 3 | printWidth: 120 4 | trailingComma: none 5 | -------------------------------------------------------------------------------- /.vitepress/config.ts: -------------------------------------------------------------------------------- 1 | const version = 5; 2 | 3 | export default { 4 | lang: 'en-US', 5 | title: 'wsrv.nl', 6 | description: 'Image cache & resize service', 7 | head: [ 8 | ['link', { rel: 'apple-touch-icon', sizes: '180x180', href: '/apple-touch-icon.png' }], 9 | ['link', { rel: 'manifest', href: '/site.webmanifest' }], 10 | ['link', { rel: 'mask-icon', href: '/safari-pinned-tab.svg', color: '#a72376' }], 11 | ['meta', { name: 'msapplication-TileColor', content: '#a72376' }], 12 | ['meta', { name: 'theme-color', content: '#ffffff' }] 13 | ], 14 | themeConfig: { 15 | logo: { 16 | light: '/logo.svg', 17 | dark: '/logo-dark.svg', 18 | alt: 'Logo' 19 | }, 20 | nav: [ 21 | { text: 'Documentation', link: '/docs/introduction', activeMatch: '/docs/' }, 22 | { text: 'News', link: '/news/index', activeMatch: '/news/' }, 23 | { text: 'FAQ', link: '/faq/index', activeMatch: '/faq/' }, 24 | { 25 | text: `v${version}`, 26 | items: [ 27 | { 28 | text: 'Changelog', 29 | link: `https://github.com/weserv/images/blob/${version}.x/CHANGELOG.md` 30 | }, 31 | { 32 | text: 'Privacy Policy', 33 | link: `https://github.com/weserv/images/blob/${version}.x/Privacy-Policy.md` 34 | } 35 | ] 36 | } 37 | ], 38 | sidebar: { 39 | '/docs/': { 40 | base: '/docs/', 41 | items: [ 42 | { 43 | text: 'Documentation', 44 | items: [ 45 | { text: 'Introduction', link: 'introduction' }, 46 | { text: 'Quick reference', link: 'quick-reference' }, 47 | { text: 'Size', link: 'size' }, 48 | { text: 'Fit', link: 'fit' }, 49 | { text: 'Crop', link: 'crop' }, 50 | { text: 'Mask', link: 'mask' }, 51 | { text: 'Orientation', link: 'orientation' }, 52 | { text: 'Adjustment', link: 'adjustment' }, 53 | { text: 'Format', link: 'format' } 54 | ] 55 | } 56 | ] 57 | }, 58 | '/news/': { 59 | base: '/news/', 60 | items: [ 61 | { 62 | text: 'News', 63 | items: [ 64 | { text: 'Introducing API version 5', link: '2019/09/01/introducing-api-5' }, 65 | { text: 'Introducing API version 4', link: '2018/07/29/introducing-api-4' } 66 | ] 67 | } 68 | ] 69 | } 70 | }, 71 | editLink: { 72 | pattern: 'https://github.com/weserv/docs/edit/master/:path', 73 | text: 'Suggest changes to this page' 74 | }, 75 | socialLinks: [{ icon: 'github', link: 'https://github.com/weserv/images' }], 76 | footer: { 77 | message: `Released under the BSD 3-Clause License.`, 78 | copyright: 79 | 'Copyright © 2007-present wsrv.nl contributors.' 80 | }, 81 | search: { 82 | provider: 'algolia', 83 | options: { 84 | appId: 'FVJ36DNUJC', 85 | apiKey: '7563ec929d69f24be83776fd79b57a1b', 86 | indexName: 'images_weserv' 87 | } 88 | } 89 | }, 90 | markdown: { 91 | gfmAlerts: false 92 | }, 93 | vue: { 94 | template: { 95 | transformAssetUrls: { 96 | includeAbsolute: false 97 | } 98 | } 99 | }, 100 | outDir: 'dist' 101 | } 102 | -------------------------------------------------------------------------------- /.vitepress/theme/README.md: -------------------------------------------------------------------------------- 1 | # @weserv/docs-theme 2 | 3 | Default theme for [wsrv.nl](https://wsrv.nl/). 4 | -------------------------------------------------------------------------------- /.vitepress/theme/global-components/NewsList.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 24 | 25 | 38 | -------------------------------------------------------------------------------- /.vitepress/theme/index.ts: -------------------------------------------------------------------------------- 1 | import DefaultTheme, { VPImage } from 'vitepress/theme'; 2 | 3 | import NewsList from './global-components/NewsList.vue'; 4 | 5 | import './styles/custom.css'; 6 | import './styles/layout.css'; 7 | import 'line-awesome/dist/line-awesome/css/line-awesome.min.css'; 8 | 9 | export default { 10 | extends: DefaultTheme, 11 | enhanceApp({ app }) { 12 | app.component('NewsList', NewsList); 13 | // https://github.com/vuejs/vitepress/issues/2813#issuecomment-1683915241 14 | app.component('Image', VPImage); 15 | } 16 | }; 17 | -------------------------------------------------------------------------------- /.vitepress/theme/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@weserv/docs-theme", 3 | "version": "0.2.0", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "@weserv/docs-theme", 9 | "version": "0.2.0", 10 | "license": "MIT", 11 | "devDependencies": { 12 | "line-awesome": "^1.3.0" 13 | } 14 | }, 15 | "node_modules/line-awesome": { 16 | "version": "1.3.0", 17 | "resolved": "https://registry.npmjs.org/line-awesome/-/line-awesome-1.3.0.tgz", 18 | "integrity": "sha512-Y0YHksL37ixDsHz+ihCwOtF5jwJgCDxQ3q+zOVgaSW8VugHGTsZZXMacPYZB1/JULBi6BAuTCTek+4ZY/UIwcw==", 19 | "dev": true 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /.vitepress/theme/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@weserv/docs-theme", 3 | "version": "0.2.0", 4 | "description": "Default theme for wsrv.nl", 5 | "homepage": "https://github.com/weserv/docs#readme", 6 | "bugs": { 7 | "url": "https://github.com/weserv/images/issues" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/weserv/docs.git", 12 | "directory": ".vitepress/theme" 13 | }, 14 | "license": "MIT", 15 | "author": "Kleis Auke Wolthuizen", 16 | "type": "module", 17 | "main": "index.ts", 18 | "devDependencies": { 19 | "line-awesome": "^1.3.0" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /.vitepress/theme/styles/custom.css: -------------------------------------------------------------------------------- 1 | /** Base Styles */ 2 | :root { 3 | /** 4 | * Colors 5 | * --------------------------------------------------------------------- */ 6 | 7 | --vp-c-brand-1: #a72376; /* --vp-c-indigo-1 */ 8 | --vp-c-brand-2: #c02888; /* --vp-c-indigo-2 */ 9 | --vp-c-brand-3: #c63d93; /* --vp-c-indigo-3 */ 10 | --vp-c-brand-soft: rgba(167, 35, 118, 0.14); /* --vp-c-indigo-soft */ 11 | 12 | --vp-badge-info-text: var(--vp-c-white); 13 | --vp-badge-info-bg: var(--vp-c-brand); 14 | } 15 | 16 | .dark { 17 | --vp-badge-info-bg: var(--vp-c-brand-2); 18 | } 19 | -------------------------------------------------------------------------------- /.vitepress/theme/styles/layout.css: -------------------------------------------------------------------------------- 1 | .logo { 2 | height: 2.2rem !important; 3 | } 4 | 5 | .icon { 6 | justify-content: left !important; 7 | background-color: var(--vp-c-bg-soft) !important; 8 | width: auto !important; 9 | height: auto !important; 10 | font-size: 112px !important; 11 | transition: none !important; 12 | } 13 | 14 | .cloudflare-logo { 15 | padding: 15px; 16 | } 17 | 18 | .features { 19 | display: flex; 20 | flex-wrap: wrap; 21 | margin: -20px -24px; 22 | } 23 | 24 | .feature { 25 | flex-shrink: 0; 26 | padding: 20px 15px; 27 | width: 100%; 28 | text-align: center; 29 | margin: 40px auto; 30 | } 31 | 32 | .feature a { 33 | display: block; 34 | color: var(--vp-c-text-1); 35 | text-decoration: none; 36 | } 37 | 38 | .feature i { 39 | position: relative; 40 | margin: 0 auto; 41 | font-size: 5rem; 42 | color: var(--vp-c-text-1); 43 | } 44 | 45 | .feature:hover, 46 | .feature:hover i, 47 | .feature:hover a { 48 | color: var(--vp-c-brand-1); 49 | } 50 | 51 | @media (min-width: 420px) { 52 | .feature { 53 | width: calc(100% / 2); 54 | } 55 | } 56 | 57 | @media (max-width: 420px) { 58 | .cloudflare-logo { 59 | width: 100%; 60 | } 61 | } 62 | 63 | @media (min-width: 768px) { 64 | .feature { 65 | width: calc(100% / 4); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019-present Andries Louw Wolthuizen and Kleis Auke Wolthuizen. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /docs/adjustment.md: -------------------------------------------------------------------------------- 1 | # Adjustment 2 | 3 | Perform operations similar to those in image-editing applications. 4 | 5 | ## Background 6 | 7 | Sets the background color of the image. Supports a variety of color 8 | formats. In addition to the 140 color names supported by all modern browsers (listed [here](supported-colors.md)), 9 | it also accepts hexadecimal RGB and RBG alpha formats. 10 | 11 | **Valid hexadecimal formats:** 12 | 13 | - 3 digit RGB: `CCC` 14 | - 4 digit ARGB (alpha): `5CCC` 15 | - 6 digit RGB: `CCCCCC` 16 | - 8 digit ARGB (alpha): `55CCCCCC` 17 | 18 | More info: [Issue #81 - Background setting](https://github.com/weserv/images/issues/81). 19 | 20 | ::: code-group 21 | 22 | ```html [HTML] 23 | 24 | ``` 25 | 26 | ```md [Markdown] 27 | ![Background](https://wsrv.nl/?url=wsrv.nl/transparency_demo.png&w=400&bg=black) 28 | ``` 29 | 30 | ::: 31 | 32 | [![Background](/static/transparency_demo.png?w=400&bg=black)](/?url=wsrv.nl/transparency_demo.png&w=400&bg=black){target="_blank"} 33 | 34 | ## Blur 35 | 36 | Adds a blur effect to the image. When used without a value (`&blur`), performs a fast, mild blur of the 37 | output image. When a value is provided, performs a slower, more accurate Gaussian blur. 38 | 39 | Use values between `0.3` and `1000`, representing the sigma of the Gaussian mask, where `sigma = 1 + radius / 2`. 40 | 41 | More info: [Issue #69 - Allow blur transformation (with radius parameter)](https://github.com/weserv/images/issues/69). 42 | 43 | ::: code-group 44 | 45 | ```html [HTML] 46 | 47 | ``` 48 | 49 | ```md [Markdown] 50 | ![Blur](https://wsrv.nl/?url=wsrv.nl/lichtenstein.jpg&w=300&blur=5) 51 | ``` 52 | 53 | ::: 54 | 55 | [![Blur](/static/lichtenstein.jpg?w=300&blur=5)](/?url=wsrv.nl/lichtenstein.jpg&w=300&blur=5){target="_blank"} 56 | 57 | ## Contrast 58 | 59 | Adjusts the image contrast. Use values between `-100` and `+100`, where `0` represents no change. 60 | 61 | ::: code-group 62 | 63 | ```html [HTML] 64 | 65 | ``` 66 | 67 | ```md [Markdown] 68 | ![Contrast](https://wsrv.nl/?url=wsrv.nl/lichtenstein.jpg&w=300&con=25) 69 | ``` 70 | 71 | ::: 72 | 73 | [![Contrast](/static/lichtenstein.jpg?w=300&con=25)](/?url=wsrv.nl/lichtenstein.jpg&w=300&con=25){target="_blank"} 74 | 75 | ## Filter 76 | 77 | Applies a filter effect to the image. Accepts `greyscale`, `sepia`, `duotone` or `negate`. 78 | 79 | ::: tip 80 | You can use `&start` and `&stop` to define the duotone colors. By default, it will use 81 | &start=C83658 and 82 | &stop=D8E74F. 83 | ::: 84 | 85 | ::: code-group 86 | 87 | ```html [HTML] 88 | 89 | ``` 90 | 91 | ```md [Markdown] 92 | ![Filter](https://wsrv.nl/?url=wsrv.nl/zebra.jpg&w=300&h=300&fit=cover&a=focal&fpx=0.6&filt=duotone) 93 | ``` 94 | 95 | ::: 96 | 97 | [![Filter](/static/zebra.jpg?w=300&h=300&fit=cover&a=focal&fpx=0.6&filt=duotone)](/?url=wsrv.nl/zebra.jpg&w=300&h=300&fit=cover&a=focal&fpx=0.6&filt=duotone){target="_blank"} 98 | 99 | ## Gamma 100 | 101 | Adjusts the image gamma. Use values between `1.0` and `3.0`. The default value is `2.2`, a suitable 102 | approximation for sRGB images. 103 | 104 | ::: code-group 105 | 106 | ```html [HTML] 107 | 108 | ``` 109 | 110 | ```md [Markdown] 111 | ![Gamma](https://wsrv.nl/?url=wsrv.nl/lichtenstein.jpg&w=300&gam=3) 112 | ``` 113 | 114 | ::: 115 | 116 | [![Gamma](/static/lichtenstein.jpg?w=300&gam=3)](/?url=wsrv.nl/lichtenstein.jpg&w=300&gam=3){target="_blank"} 117 | 118 | ## Modulate 119 | 120 | Transforms the image using brightness, saturation and hue rotation. 121 | Use `&mod=[brightness multiplier],[saturation multiplier],[hue degrees]` to define the below adjustments at once. 122 | 123 | ### Brightness 124 | 125 | Adjusts the brightness of the image. A multiplier greater than 1 will increase brightness, while a 126 | multiplier less than 1 will decrease the brightness. 127 | 128 | ::: code-group 129 | 130 | ```html [HTML] 131 | 132 | ``` 133 | 134 | ```md [Markdown] 135 | ![Brightness](https://wsrv.nl/?url=wsrv.nl/lichtenstein.jpg&w=300&mod=2) 136 | ``` 137 | 138 | ::: 139 | 140 | [![Brightness](/static/lichtenstein.jpg?w=300&mod=2)](/?url=wsrv.nl/lichtenstein.jpg&w=300&mod=2){target="_blank"} 141 | 142 | ### Saturation 143 | 144 | Adjusts the saturation of the image. A multiplier greater than 1 will increase saturation, while a multiplier 145 | less than 1 will decrease the saturation. 146 | 147 | ::: code-group 148 | 149 | ```html [HTML] 150 | 151 | ``` 152 | 153 | ```md [Markdown] 154 | ![Saturation](https://wsrv.nl/?url=wsrv.nl/lichtenstein.jpg&w=300&sat=0.5) 155 | ``` 156 | 157 | ::: 158 | 159 | [![Saturation](/static/lichtenstein.jpg?w=300&sat=0.5)](/?url=wsrv.nl/lichtenstein.jpg&w=300&sat=0.5){target="_blank"} 160 | 161 | ### Hue rotation 162 | 163 | Applies a hue rotation to the image. A positive hue rotation increases the hue value, while a negative 164 | rotation decreases the hue value. 165 | 166 | Values are given in degrees, there is no minimum or maximum value; `&hue=N` evaluates to `N` modulo 360. 167 | 168 | ::: code-group 169 | 170 | ```html [HTML] 171 | 172 | ``` 173 | 174 | ```md [Markdown] 175 | ![Hue rotation](https://wsrv.nl/?url=wsrv.nl/lichtenstein.jpg&w=300&hue=90) 176 | ``` 177 | 178 | ::: 179 | 180 | [![Hue rotation](/static/lichtenstein.jpg?w=300&hue=90)](/?url=wsrv.nl/lichtenstein.jpg&w=300&hue=90){target="_blank"} 181 | 182 | ## Sharpen 183 | 184 | Sharpen the image. Performs an accurate sharpen of the L channel in the LAB color space. Use in combination with 185 | `&sharpf=` and `&sharpj=` to control the level of sharpening in "flat" and "jagged" areas. 186 | 187 | Use values between `0.000001` and `10`, representing the sigma of the Gaussian mask, 188 | where `sigma = 1 + radius / 2`. When used without parameters, performs a fast, mild 189 | sharpen of the output image. 190 | 191 | The level of sharpening to apply to "flat" (`&sharpf=`) and "jagged" (`&sharpj=`) areas needs 192 | to be given in the range of `0` and `1000000`. 193 | 194 | ::: code-group 195 | 196 | ```html [HTML] 197 | 198 | ``` 199 | 200 | ```md [Markdown] 201 | ![Sharpen](https://wsrv.nl/?url=wsrv.nl/lichtenstein.jpg&w=300&sharp=3) 202 | ``` 203 | 204 | ::: 205 | 206 | [![Sharpen](/static/lichtenstein.jpg?w=300&sharp=3)](/?url=wsrv.nl/lichtenstein.jpg&w=300&sharp=3){target="_blank"} 207 | 208 | ## Tint 209 | 210 | Tint the image using the provided chroma while preserving the image luminance. See [here](adjustment.md#background) 211 | for the supported color formats. 212 | 213 | ::: code-group 214 | 215 | ```html [HTML] 216 | 217 | ``` 218 | 219 | ```md [Markdown] 220 | ![Tint](https://wsrv.nl/?url=wsrv.nl/lichtenstein.jpg&w=300&tint=red) 221 | ``` 222 | 223 | ::: 224 | 225 | [![Tint](/static/lichtenstein.jpg?w=300&tint=red)](/?url=wsrv.nl/lichtenstein.jpg&w=300&tint=red){target="_blank"} 226 | -------------------------------------------------------------------------------- /docs/crop.md: -------------------------------------------------------------------------------- 1 | # Crop 2 | 3 | Controls how the image is aligned. 4 | 5 | ## Alignment position 6 | 7 | How the image should be aligned when `&fit=cover` or `&fit=contain` is set. The [`&w=`](size.md#width) and [`&h=`](size.md#height) 8 | parameters should also be specified. 9 | 10 | ### Position-based 11 | 12 | Controls the starting location of the crop. When `&fit=contain` is set, it determines how the image is positioned inside its box. 13 | 14 | **Valid positions:** 15 | 16 | - `center`: default 17 | - `top` 18 | - `right` 19 | - `bottom` 20 | - `left` 21 | - `top-left` 22 | - `bottom-left` 23 | - `bottom-right` 24 | - `top-right` 25 | 26 | For more information, please see the suggestion on our GitHub issue tracker: [Issue #24 - Aligning](https://github.com/weserv/images/issues/24). 27 | 28 | ::: code-group 29 | 30 | ```html [HTML] 31 | 32 | ``` 33 | 34 | ```md [Markdown] 35 | ![Alignment position](https://wsrv.nl/?url=wsrv.nl/lichtenstein.jpg&w=300&h=300&fit=cover&a=top) 36 | ``` 37 | 38 | ::: 39 | 40 | [![Alignment position](/static/lichtenstein.jpg?w=300&h=300&fit=cover&a=top)](/?url=wsrv.nl/lichtenstein.jpg&w=300&h=300&fit=cover&a=top){target="_blank"} 41 | 42 | ### Focal point 43 | 44 | You can be more specific about the alignment using a focal point. This can be set using a horizontal 45 | (`&fpx=`) and vertical (`&fpy=`) offset decimal value (a float between `0.0` and `1.0`, inclusive). The 46 | default value is `0.5`, or the center of the image. 47 | 48 | ::: code-group 49 | 50 | ```html [HTML] 51 | 52 | ``` 53 | 54 | ```md [Markdown] 55 | ![Focal point](https://wsrv.nl/?url=wsrv.nl/lichtenstein.jpg&w=300&h=300&fit=cover&a=focal&fpy=0.45) 56 | ``` 57 | 58 | ::: 59 | 60 | [![Focal point](/static/lichtenstein.jpg?w=300&h=300&fit=cover&a=focal&fpy=0.45)](/?url=wsrv.nl/lichtenstein.jpg&w=300&h=300&fit=cover&a=focal&fpy=0.45){target="_blank"} 61 | 62 | ### Smart crop 63 | 64 | An experimental strategy-based approach to crop the image by removing boring parts. This only works 65 | with `&fit=cover`. 66 | 67 | More info: [Issue #90 - Add support for smart crop](https://github.com/weserv/images/issues/90). 68 | 69 | **Valid strategies:** 70 | 71 | - `entropy`: focus on the region with the highest [Shannon entropy](https://en.wikipedia.org/wiki/Entropy_%28information_theory%29). 72 | - `attention`: focus on the region with the highest luminance frequency, color saturation and 73 | presence of skin tones. 74 | 75 | ::: code-group 76 | 77 | ```html [HTML] 78 | 79 | ``` 80 | 81 | ```md [Markdown] 82 | ![Smart crop](https://wsrv.nl/?url=wsrv.nl/puppy.jpg&w=300&h=300&fit=cover&a=attention) 83 | ``` 84 | 85 | ::: 86 | 87 | [![Smart crop](/static/puppy.jpg?w=300&h=300&fit=cover&a=attention)](/?url=wsrv.nl/puppy.jpg&w=300&h=300&fit=cover&a=attention){target="_blank"} 88 | 89 | ## Rectangle crop 90 | 91 | Crops the image to specific dimensions after any other resize operations. 92 | 93 | Use percentage values (denoted by a value ending with `%`) to crop a relative portion of the image. 94 | 95 | ::: tip 96 | You can use `&precrop`, for a pre-resize crop behaviour. 97 | See [Issue #176 - Combine cropping with resizing](https://github.com/weserv/images/issues/176) for more information. 98 | ::: 99 | 100 | ::: code-group 101 | 102 | ```html [HTML] 103 | 104 | ``` 105 | 106 | ```md [Markdown] 107 | ![Rectangle crop](https://wsrv.nl/?url=wsrv.nl/lichtenstein.jpg&cx=680&cy=500&cw=300&ch=300) 108 | ``` 109 | 110 | ::: 111 | 112 | [![Rectangle crop](/static/lichtenstein.jpg?cx=680&cy=500&cw=300&ch=300)](/?url=wsrv.nl/lichtenstein.jpg&cx=680&cy=500&cw=300&ch=300){target="_blank"} 113 | 114 | ## Trim 115 | 116 | Trim "boring" pixels from all edges that contain values within a similarity of the top-left pixel. Trimming 117 | occurs before any resize operation. Use values between `1` and `254` to define a tolerance level to trim 118 | away similar color values. You also can specify just `&trim`, which defaults to a tolerance level of `10`. 119 | 120 | More info: [Issue #39 - able to remove black/white whitespace](https://github.com/weserv/images/issues/39). 121 | 122 | ::: code-group 123 | 124 | ```html [HTML] 125 | 126 | ``` 127 | 128 | ```md [Markdown] 129 | ![Trim](https://wsrv.nl/?url=wsrv.nl/transparency_demo.png&w=300&trim=10) 130 | ``` 131 | 132 | ::: 133 | 134 | [![Trim](/static/transparency_demo.png?w=300&trim=10)](/?url=wsrv.nl/transparency_demo.png&w=300&trim=10){target="_blank"} 135 | -------------------------------------------------------------------------------- /docs/fit.md: -------------------------------------------------------------------------------- 1 | # Fit 2 | 3 | Controls how the image is fitted to its target dimensions. Below are a couple of examples. Some of these 4 | values are based on the [object-fit](https://developer.mozilla.org/en-US/docs/Web/CSS/object-fit) CSS property. 5 | 6 | Examples of various values for the fit property when resizing 10 | 11 | ## Inside 12 | 13 | Default. Preserving aspect ratio, resize the image to be as large as possible while ensuring its dimensions 14 | are less than or equal to both those specified. 15 | 16 | ::: code-group 17 | 18 | ```html [HTML] 19 | 20 | ``` 21 | 22 | ```md [Markdown] 23 | ![Inside](https://wsrv.nl/?url=wsrv.nl/lichtenstein.jpg&w=300&h=300&fit=inside) 24 | ``` 25 | 26 | ::: 27 | 28 | [![Inside](/static/lichtenstein.jpg?w=300&h=300&fit=inside)](/?url=wsrv.nl/lichtenstein.jpg&w=300&h=300&fit=inside){target="_blank"} 29 | 30 | ## Outside 31 | 32 | Preserving aspect ratio, resize the image to be as small as possible while ensuring its dimensions are 33 | greater than or equal to both those specified. 34 | 35 | ::: code-group 36 | 37 | ```html [HTML] 38 | 39 | ``` 40 | 41 | ```md [Markdown] 42 | ![Outside](https://wsrv.nl/?url=wsrv.nl/lichtenstein.jpg&w=300&h=300&fit=outside) 43 | ``` 44 | 45 | ::: 46 | 47 | [![Outside](/static/lichtenstein.jpg?w=300&h=300&fit=outside)](/?url=wsrv.nl/lichtenstein.jpg&w=300&h=300&fit=outside){target="_blank"} 48 | 49 | ## Cover 50 | 51 | Crop the image to cover both provided dimensions. 52 | 53 | ::: code-group 54 | 55 | ```html [HTML] 56 | 57 | ``` 58 | 59 | ```md [Markdown] 60 | ![Cover](https://wsrv.nl/?url=wsrv.nl/lichtenstein.jpg&w=300&h=300&fit=cover) 61 | ``` 62 | 63 | ::: 64 | 65 | [![Cover](/static/lichtenstein.jpg?w=300&h=300&fit=cover)](/?url=wsrv.nl/lichtenstein.jpg&w=300&h=300&fit=cover){target="_blank"} 66 | 67 | ## Fill 68 | 69 | Ignore the aspect ratio of the input and stretch to both provided dimensions. 70 | 71 | ::: code-group 72 | 73 | ```html [HTML] 74 | 75 | ``` 76 | 77 | ```md [Markdown] 78 | ![Fill](https://wsrv.nl/?url=wsrv.nl/lichtenstein.jpg&w=300&h=300&fit=fill) 79 | ``` 80 | 81 | ::: 82 | 83 | [![Fill](/static/lichtenstein.jpg?w=300&h=300&fit=fill)](/?url=wsrv.nl/lichtenstein.jpg&w=300&h=300&fit=fill){target="_blank"} 84 | 85 | ## Contain 86 | 87 | Embed within both provided dimensions. The remaining space can be filled with a background color by 88 | using `&cbg=`. See [here](adjustment.md#background) for the supported color formats. 89 | 90 | More info: [Issue #80 - letterbox images that need to fit](https://github.com/weserv/images/issues/80). 91 | 92 | ::: code-group 93 | 94 | ```html [HTML] 95 | 96 | ``` 97 | 98 | ```md [Markdown] 99 | ![Contain](https://wsrv.nl/?url=wsrv.nl/lichtenstein.jpg&w=300&h=300&fit=contain&cbg=black) 100 | ``` 101 | 102 | ::: 103 | 104 | [![Contain](/static/lichtenstein.jpg?w=300&h=300&fit=contain&cbg=black)](/?url=wsrv.nl/lichtenstein.jpg&w=300&h=300&fit=contain&cbg=black){target="_blank"} 105 | 106 | ## Without enlargement 107 | 108 | Do not enlarge if the width or height are already less than the specified dimensions. 109 | 110 | ::: code-group 111 | 112 | ```html [HTML] 113 | 114 | ``` 115 | 116 | ```md [Markdown] 117 | ![Without enlargement](https://wsrv.nl/?url=wsrv.nl/lichtenstein.jpg&w=300&h=300&fit=inside&we) 118 | ``` 119 | 120 | ::: 121 | -------------------------------------------------------------------------------- /docs/format.md: -------------------------------------------------------------------------------- 1 | # Format 2 | 3 | Controls the output properties of the image. 4 | 5 | ## Adaptive filter 6 | 7 | Use adaptive row filtering for reducing the PNG file size. This only works when the output image is `png`. 8 | 9 | ## Base64 (data URL) 10 | 11 | Encodes the image to be used directly in the src= of the ``-tag. 12 | Use [this link](/?url=wsrv.nl/lichtenstein.jpg&crop=100,100,720,530&encoding=base64){target="_blank"} to see the output result. 13 | 14 | More info: [Issue #59 - Return image base64 encoded](https://github.com/weserv/images/issues/59). 15 | 16 | ``` 17 | //wsrv.nl/?url=wsrv.nl/lichtenstein.jpg&crop=100,100,720,530&encoding=base64 18 | ``` 19 | 20 | ## Cache-Control 21 | 22 | Defines for how long an image should be cached by the browser. This will change the `max-age` of the 23 | `Cache-Control` HTTP-header. 24 | 25 | We define a "far-future expiration" of 1 year by default. The duration can be specified in days, weeks, 26 | months, and years using the following suffixes: 27 | 28 | - `d`: days 29 | - `w`: weeks, 7 days 30 | - `M`: months, 30 days 31 | - `y`: years, 365 days 32 | 33 | A duration must be in the range of `1d` (1 day) to `1y` (1 year), inclusive. Any other value will be ignored 34 | and fallback to the default value of 1 year. 35 | 36 | More info: [Issue #186 - Increase Cache-Control: max-age= to 1 year instead of 1 month](https://github.com/weserv/images/issues/186). 37 | 38 | ``` 39 | //wsrv.nl?url=wsrv.nl/lichtenstein.jpg&w=100&maxage=31d 40 | ``` 41 | 42 | ## Compression level 43 | 44 | The zlib compression level. Use a value between `0` (no Deflate) and `9` (maximum Deflate). The default 45 | value is `6`. This only works when the output image is `png`. 46 | 47 | ## Lossless compression 48 | 49 | Whether the resulting image should be lossless compressed. This only works when the output image is `webp`. 50 | 51 | More info: [Issue #386 - webP output is always lossy and cannot be requested as lossless](https://github.com/weserv/images/issues/386). 52 | 53 | ## Default image 54 | 55 | If there is a problem loading an image, then an error is shown. However, there might be a need where 56 | instead of giving a broken image to the user, you want a default image to be delivered. 57 | 58 | More info: [Issue #37 - Return default image if the image's URL not found](https://github.com/weserv/images/issues/37). 59 | 60 | The URL must not include a `default` querystring (if it does, it will be ignored). 61 | 62 | Use `&default=1` to redirect to the original URL specified in `?url=`. 63 | 64 | ::: code-group 65 | 66 | ```html [HTML] 67 | 68 | ``` 69 | 70 | ```md [Markdown] 71 | ![Default image](https://wsrv.nl/?url=example.org/noimage.jpg&default=wsrv.nl/placeholder.svg) 72 | ``` 73 | 74 | ::: 75 | 76 | [![Default image](/placeholder.svg)](/?url=example.org/noimage.jpg&default=wsrv.nl/placeholder.svg){target="_blank"} 77 | 78 | ## Filename 79 | 80 | To specify the filename returned in the `Content-Disposition` header. The filename must only contain 81 | alphanumeric characters. 82 | 83 | More info: [Issue #122 - Specify filename](https://github.com/weserv/images/issues/122). 84 | 85 | ## Interlace / progressive 86 | 87 | Adds interlacing to GIF and PNG. JPEGs become progressive. 88 | 89 | More info: [Issue #50 - Add parameter to use progressive JPEGs](https://github.com/weserv/images/issues/50). 90 | 91 | ::: code-group 92 | 93 | ```html [HTML] 94 | 95 | ``` 96 | 97 | ```md [Markdown] 98 | ![Interlace / progressive](https://wsrv.nl/?url=wsrv.nl/lichtenstein.jpg&w=300&il) 99 | ``` 100 | 101 | ::: 102 | 103 | [![Interlace / progressive](/static/lichtenstein.jpg?w=300&il)](/?url=wsrv.nl/lichtenstein.jpg&w=300&il){target="_blank"} 104 | 105 | ## Number of pages 106 | 107 | To select the number of pages to render. The default value is `1`. Set to `-1` to mean "until the end of 108 | the document". 109 | 110 | ::: tip 111 | `-1` will be useful if you need to resize an animated WebP or GIF image. 112 | ::: 113 | 114 | ::: code-group 115 | 116 | ```html [HTML] 117 | 118 | ``` 119 | 120 | ```md [Markdown] 121 | ![Number of pages](https://wsrv.nl/?url=wsrv.nl/banana.webp&h=300&output=gif&n=-1) 122 | ``` 123 | 124 | ::: 125 | 126 | [![Number of pages](/static/banana.webp?h=300&output=gif&n=-1)](/?url=wsrv.nl/banana.webp&h=300&output=gif&n=-1){target="_blank"} 127 | 128 | ## Output 129 | 130 | Encodes the image to a specific format. Accepts `jpg`, `png`, `gif`, `tiff`, `webp` or `json`. If none is 131 | given, it will honor the origin image format. 132 | 133 | More info: [Issue #62 - Format conversion](https://github.com/weserv/images/issues/62). 134 | 135 | ::: code-group 136 | 137 | ```html [HTML] 138 | 139 | ``` 140 | 141 | ```md [Markdown] 142 | ![Output](https://wsrv.nl/?url=wsrv.nl/lichtenstein.jpg&w=300&output=webp) 143 | ``` 144 | 145 | ::: 146 | 147 | [![Output](/static/lichtenstein.jpg?w=300&output=webp)](/?url=wsrv.nl/lichtenstein.jpg&w=300&output=webp){target="_blank"} 148 | 149 | ## Page 150 | 151 | To load a given page (for an PDF, TIFF and multi-size ICO file). The value is numbered from zero. For a 152 | multi-resolution image, you can use `-1` to get the largest page and `-2` to get the smallest page. 153 | 154 | ## Quality 155 | 156 | Defines the quality of the image. Use values between `1` and `100`. Defaults to `80`. This only works 157 | when the output image is `jpg`, `tiff` or `webp`. 158 | 159 | ::: code-group 160 | 161 | ```html [HTML] 162 | 163 | ``` 164 | 165 | ```md [Markdown] 166 | ![Quality](https://wsrv.nl/?url=wsrv.nl/lichtenstein.jpg&w=300&q=20) 167 | ``` 168 | 169 | ::: 170 | 171 | [![Quality](/static/lichtenstein.jpg?w=300&q=20)](/?url=wsrv.nl/lichtenstein.jpg&w=300&q=20){target="_blank"} 172 | -------------------------------------------------------------------------------- /docs/introduction.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | **wsrv**.nl is an image **cache** & **resize** service. Our servers resize your image, cache it worldwide, 4 | and display it. 5 | 6 | - We support a good range of image formats, including JPEG, PNG, BMP, GIF, TIFF, WebP, PDF and SVG. 7 | - There's even support for [animated WebP and GIF images](format.md#number-of-pages). 8 | - We support IPv6, [serving dual stack](https://ipv6-test.com/validate.php?url=wsrv.nl), and supporting [IPv6-only origin hosts](/?url=ipv6.google.com/logos/logo.gif){target="_blank"}. 9 | - For secure connections over TLS/SSL, you can use [https://wsrv.nl/](/). 10 | - This can be very useful for embedding HTTP images on HTTPS websites. HTTPS origin hosts can be 11 | used by [prefixing the hostname with https://](https://github.com/weserv/images/issues/33). 12 | - The CDN is provided by [Cloudflare](https://www.cloudflare.com/). Images are being cached and delivered straight from 13 | [300+ global datacenters](https://www.cloudflare.com/network/). This ensures the fastest load times and best performance. 14 | 15 | ## How it works 16 | 17 | You pass the image URL and a set of parameters. wsrv.nl will then fetch the image, resize it, 18 | cache it and display it. The next time the request comes, it will serve the cached version. 19 | 20 | ::: tip 21 | If the URL includes a querystring, you'll need to ensure that it's properly URL-encoded, replacing 22 | `?` with `%3F` and `&` with `%26`, respectively. 23 | ::: 24 | 25 | ::: code-group 26 | 27 | ```html [HTML] 28 | 29 | 30 | ``` 31 | 32 | ```md [Markdown] 33 | 34 | ![Lichtenstein](https://wsrv.nl/?url=wsrv.nl/lichtenstein.jpg&w=300&h=300) 35 | ``` 36 | 37 | ::: 38 | -------------------------------------------------------------------------------- /docs/mask.md: -------------------------------------------------------------------------------- 1 | # Mask 2 | 3 | Controls the visible and non-visible area of the image. 4 | 5 | ## Mask type 6 | 7 | Sets the mask type from a predefined list of shapes. 8 | 9 | More info: [Issue #49 - Add circle effect to photos](https://github.com/weserv/images/issues/49). 10 | 11 | **Valid shapes:** 12 | 13 | - `circle` 14 | - `ellipse` 15 | - `triangle` 16 | - `triangle-180`: Triangle tilted upside down 17 | - `pentagon` 18 | - `pentagon-180`: Pentagon tilted upside down 19 | - `hexagon` 20 | - `square`: Square tilted 45 degrees 21 | - `star`: 5-point star 22 | - `heart` 23 | 24 | ::: code-group 25 | 26 | ```html [HTML] 27 | 28 | ``` 29 | 30 | ```md [Markdown] 31 | ![Mask type](https://wsrv.nl/?url=wsrv.nl/lichtenstein.jpg&w=300&h=300&fit=cover&mask=circle) 32 | ``` 33 | 34 | ::: 35 | 36 | [![Mask type](/static/lichtenstein.jpg?w=300&h=300&fit=cover&mask=circle)](/?url=wsrv.nl/lichtenstein.jpg&w=300&h=300&fit=cover&mask=circle){target="_blank"} 37 | 38 | ## Mask trim 39 | 40 | Removes the remaining whitespace from the mask. 41 | 42 | ::: code-group 43 | 44 | ```html [HTML] 45 | 46 | ``` 47 | 48 | ```md [Markdown] 49 | ![Mask trim](https://wsrv.nl/?url=wsrv.nl/lichtenstein.jpg&w=300&h=900&fit=cover&a=crop-22-0&mask=circle&mtrim) 50 | ``` 51 | 52 | ::: 53 | 54 | [![Mask trim](/static/lichtenstein.jpg?w=300&h=900&fit=cover&a=crop-22-0&mask=circle&mtrim)](/?url=wsrv.nl/lichtenstein.jpg&w=300&h=900&fit=cover&a=crop-22-0&mask=circle&mtrim){target="_blank"} 55 | 56 | ## Mask background 57 | 58 | Sets the background color of the mask. See [here](adjustment.md#background) for the supported color formats. 59 | 60 | ::: code-group 61 | 62 | ```html [HTML] 63 | 64 | ``` 65 | 66 | ```md [Markdown] 67 | ![Mask background](https://wsrv.nl/?url=wsrv.nl/transparency_demo.png&w=400&bg=black&mask=heart&mbg=red) 68 | ``` 69 | 70 | ::: 71 | 72 | [![Mask background](/static/transparency_demo.png?w=400&bg=black&mask=heart&mbg=red)](/?url=wsrv.nl/transparency_demo.png&w=400&bg=black&mask=heart&mbg=red){target="_blank"} 73 | -------------------------------------------------------------------------------- /docs/orientation.md: -------------------------------------------------------------------------------- 1 | # Orientation 2 | 3 | Change the orientation of your image, by either flipping along its axes or rotating around the center. 4 | 5 | ## Flip 6 | 7 | Mirror the image vertically (up-down) about the x-axis. 8 | This always occurs after rotation, if any. 9 | 10 | ::: code-group 11 | 12 | ```html [HTML] 13 | 14 | ``` 15 | 16 | ```md [Markdown] 17 | ![Flip](https://wsrv.nl/?url=wsrv.nl/lichtenstein.jpg&h=300&flip) 18 | ``` 19 | 20 | ::: 21 | 22 | [![Flip](/static/lichtenstein.jpg?h=300&flip)](/?url=wsrv.nl/lichtenstein.jpg&h=300&flip){target="_blank"} 23 | 24 | ## Flop 25 | 26 | Mirror the image horizontally (left-right) about the y-axis. 27 | This always occurs after rotation, if any. 28 | 29 | ::: code-group 30 | 31 | ```html [HTML] 32 | 33 | ``` 34 | 35 | ```md [Markdown] 36 | ![Flop](https://wsrv.nl/?url=wsrv.nl/lichtenstein.jpg&h=300&flop) 37 | ``` 38 | 39 | ::: 40 | 41 | [![Flop](/static/lichtenstein.jpg?h=300&flop)](/?url=wsrv.nl/lichtenstein.jpg&h=300&flop){target="_blank"} 42 | 43 | ## Rotation 44 | 45 | Rotates the image by either an explicit angle or auto-orient based on the EXIF `Orientation` tag. 46 | 47 | If an angle is specified, it is converted to a valid positive degree rotation. For example, `-450` will 48 | produce a `270` degree rotation. When rotating by an angle other than a multiple of 90, the background 49 | color can be provided with the `&rbg=` parameter. See [here](adjustment.md#background) for the supported color formats. 50 | 51 | If no angle is provided, it is determined from the EXIF data. 52 | 53 | ::: code-group 54 | 55 | ```html [HTML] 56 | 57 | ``` 58 | 59 | ```md [Markdown] 60 | ![Rotation](https://wsrv.nl/?url=wsrv.nl/lichtenstein.jpg&h=300&ro=45&rbg=red) 61 | ``` 62 | 63 | ::: 64 | 65 | [![Rotation](/static/lichtenstein.jpg?h=300&ro=45&rbg=red)](/?url=wsrv.nl/lichtenstein.jpg&h=300&ro=45&rbg=red){target="_blank"} 66 | -------------------------------------------------------------------------------- /docs/quick-reference.md: -------------------------------------------------------------------------------- 1 | --- 2 | aside: false 3 | --- 4 | 5 | # Quick reference 6 | 7 | | Name | GET | Description | | 8 | | ----------------------- | ---------- | ----------------------------------------------------------------------- | ----------------------------: | 9 | | Width | `w` | Sets the width of the image, in pixels. | [info][width] | 10 | | Height | `h` | Sets the height of the image, in pixels. | [info][height] | 11 | | Device pixel ratio | `dpr` | Sets the output density of the image. | [info][dpr] | 12 | | Fit | `fit` | Sets how the image is fitted to its target dimensions. | [info][fit] | 13 | | Contain background | `cbg` | Sets the background color when using `&fit=contain`. | [info][contain-bg] | 14 | | Without enlargement | `we` | Do not enlarge the image. | [info][without-enlargement] | 15 | | Alignment position | `a` | Sets how the image is aligned. | [info][alignment-position] | 16 | | Rectangle crop | `crop` | Crops the image to specific dimensions. | [info][rectangle-crop] | 17 | | Pre-resize crop | `precrop` | A pre-resize crop behaviour. | [info][rectangle-crop] | 18 | | Trim | `trim` | Trim "boring" pixels from all edges. | [info][trim] | 19 | | Masking | `mask` | Sets the mask type from a predefined list. | [info][mask] | 20 | | Mask trim | `mtrim` | Removes the remaining whitespace from the mask. | [info][mask-trim] | 21 | | Mask background | `mbg` | Sets the background color of the mask. | [info][mask-bg] | 22 | | Flip | `flip` | Mirror the image vertically (up-down) about the x-axis. | [info][flip] | 23 | | Flop | `flop` | Mirror the image horizontally (left-right) about the y-axis. | [info][flop] | 24 | | Rotation | `ro` | Rotates the image. | [info][rotation] | 25 | | Rotation background | `rbg` | Sets the background color when rotating by arbitrary angles. | [info][rotation-bg] | 26 | | Background | `bg` | Sets the background color of the image. | [info][background] | 27 | | Blur | `blur` | Adds a blur effect to the image. | [info][blur] | 28 | | Contrast | `con` | Adjusts the image contrast. | [info][contrast] | 29 | | Filter | `filt` | Applies a filter effect to the image. | [info][filter] | 30 | | Gamma | `gam` | Adjusts the image gamma. | [info][gamma] | 31 | | Modulate | `mod` | Transforms the image using brightness, saturation and hue rotation. | [info][modulate] | 32 | | Saturation | `sat` | Adjusts the saturation of the image. | [info][saturation] | 33 | | Hue rotation | `hue` | Applies a hue rotation to the image. | [info][hue-rotation] | 34 | | Sharpen | `sharp` | Sharpen the image. | [info][sharpen] | 35 | | Tint | `tint` | Tint the image. | [info][tint] | 36 | | Adaptive filter | `af` | A filter algorithm that can be applied before compression. | [info][adaptive-filter] | 37 | | Base64 (data URL) | `encoding` | Encodes the image to be used directly in the `src=` of the ``-tag. | [info][base64] | 38 | | Cache-Control | `maxage` | How long an image should be cached by the browser. | [info][cache-control] | 39 | | Compression level | `l` | The zlib compression level. | [info][compression-level] | 40 | | Lossless compression | `ll` | Whether the resulting image should be lossless compressed. | [info][lossless-compression] | 41 | | Default image | `default` | Redirects to a default image when there is a problem loading an image. | [info][default] | 42 | | Filename | `filename` | To specify the filename. | [info][filename] | 43 | | Interlace / progressive | `il` | Adds interlacing to GIF and PNG. JPEG's become progressive. | [info][interlace-progressive] | 44 | | Number of pages | `n` | To select the the number of pages to render. | [info][n-pages] | 45 | | Output | `output` | Encodes the image to a specific format. | [info][output] | 46 | | Page | `page` | To load a given page. | [info][page] | 47 | | Quality | `q` | Defines the quality of the image. | [info][quality] | 48 | 49 | [width]: size.md#width 50 | [height]: size.md#height 51 | [dpr]: size.md#device-pixel-ratio 52 | [fit]: fit.md 53 | [contain-bg]: fit.md#contain 54 | [without-enlargement]: fit.md#without-enlargement 55 | [alignment-position]: crop.md#alignment-position 56 | [rectangle-crop]: crop.md#rectangle-crop 57 | [trim]: crop.md#trim 58 | [mask]: mask.md#mask-type 59 | [mask-trim]: mask.md#mask-trim 60 | [mask-bg]: mask.md#mask-background 61 | [flip]: orientation.md#flip 62 | [flop]: orientation.md#flop 63 | [rotation]: orientation.md#rotation 64 | [rotation-bg]: orientation.md#rotation 65 | [background]: adjustment.md#background 66 | [blur]: adjustment.md#blur 67 | [contrast]: adjustment.md#contrast 68 | [filter]: adjustment.md#filter 69 | [gamma]: adjustment.md#gamma 70 | [modulate]: adjustment.md#modulate 71 | [saturation]: adjustment.md#saturation 72 | [hue-rotation]: adjustment.md#hue-rotation 73 | [sharpen]: adjustment.md#sharpen 74 | [tint]: adjustment.md#tint 75 | [adaptive-filter]: format.md#adaptive-filter 76 | [base64]: format.md#base64-data-url 77 | [cache-control]: format.md#cache-control 78 | [compression-level]: format.md#compression-level 79 | [lossless-compression]: format.md#lossless-compression 80 | [default]: format.md#default-image 81 | [filename]: format.md#filename 82 | [interlace-progressive]: format.md#interlace-progressive 83 | [n-pages]: format.md#number-of-pages 84 | [output]: format.md#output 85 | [page]: format.md#page 86 | [quality]: format.md#quality 87 | -------------------------------------------------------------------------------- /docs/size.md: -------------------------------------------------------------------------------- 1 | # Size 2 | 3 | Controls how the image needs to be resized. You can use both `&w=` and `&h=` parameters or only one 4 | of them: the other dimension is automatically updated. 5 | 6 | ## Width 7 | 8 | Sets the width of the image, in pixels. 9 | 10 | ::: code-group 11 | 12 | ```html [HTML] 13 | 14 | ``` 15 | 16 | ```md [Markdown] 17 | ![Width](https://wsrv.nl/?url=wsrv.nl/lichtenstein.jpg&w=300) 18 | ``` 19 | 20 | ::: 21 | 22 | [![Width](/static/lichtenstein.jpg?w=300)](/?url=wsrv.nl/lichtenstein.jpg&w=300){target="_blank"} 23 | 24 | ## Height 25 | 26 | Sets the height of the image, in pixels. 27 | 28 | ::: code-group 29 | 30 | ```html [HTML] 31 | 32 | ``` 33 | 34 | ```md [Markdown] 35 | ![Height](https://wsrv.nl/?url=wsrv.nl/lichtenstein.jpg&h=300) 36 | ``` 37 | 38 | ::: 39 | 40 | [![Height](/static/lichtenstein.jpg?h=300)](/?url=wsrv.nl/lichtenstein.jpg&h=300){target="_blank"} 41 | 42 | ## Device pixel ratio 43 | 44 | The device pixel ratio is used to easily convert between CSS pixels and device pixels. This makes it 45 | possible to display images at the correct pixel density on a variety of devices such as Apple devices with 46 | Retina Displays and Android devices. You must specify either a width, a height, or both for this parameter 47 | to work. Use values between `1` and `8`. 48 | 49 | More info: [Issue #115 - DPI support](https://github.com/weserv/images/issues/115). 50 | 51 | ::: code-group 52 | 53 | ```html [HTML] 54 | 55 | ``` 56 | 57 | ```md [Markdown] 58 | ![Device pixel ratio](https://wsrv.nl/?url=wsrv.nl/lichtenstein.jpg&h=144&dpr=2) 59 | ``` 60 | 61 | ::: 62 | 63 | [![Device pixel ratio](/static/lichtenstein.jpg?h=144&dpr=2)](/?url=wsrv.nl/lichtenstein.jpg&h=144&dpr=2){target="_blank"} 64 | -------------------------------------------------------------------------------- /docs/supported-colors.md: -------------------------------------------------------------------------------- 1 | --- 2 | aside: false 3 | --- 4 | 5 | # Supported colors 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 419 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 | 431 | 432 | 433 | 434 | 435 | 436 | 437 | 438 | 439 | 440 | 441 | 442 | 443 | 444 | 445 | 446 | 447 | 448 | 449 | 450 | 451 | 452 | 453 | 454 | 455 | 456 | 457 | 458 | 459 | 460 | 461 | 462 | 463 | 464 | 465 | 466 | 467 | 468 | 469 | 470 | 471 | 472 | 473 | 474 | 475 | 476 | 477 | 478 | 479 | 480 | 481 | 482 | 483 | 484 | 485 | 486 | 487 | 488 | 489 | 490 | 491 | 492 | 493 | 494 | 495 | 496 | 497 | 498 | 499 | 500 | 501 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 509 | 510 | 511 | 512 | 513 | 514 | 515 | 516 | 517 | 518 | 519 | 520 | 521 | 522 | 523 | 524 | 525 | 526 | 527 | 528 | 529 | 530 | 531 | 532 | 533 | 534 | 535 | 536 | 537 | 538 | 539 | 540 | 541 | 542 | 543 | 544 | 545 | 546 | 547 | 548 | 549 | 550 | 551 | 552 | 553 | 554 | 555 | 556 | 557 | 558 | 559 | 560 | 561 | 562 | 563 | 564 | 565 | 566 | 567 | 568 | 569 | 570 | 571 | 572 | 573 | 574 | 575 | 576 | 577 | 578 | 579 | 580 |
NameColor
aliceblue 
antiquewhite 
aqua 
aquamarine 
azure 
beige 
bisque 
black 
blanchedalmond 
blue 
blueviolet 
brown 
burlywood 
cadetblue 
chartreuse 
chocolate 
coral 
cornflowerblue 
cornsilk 
crimson 
cyan 
darkblue 
darkcyan 
darkgoldenrod 
darkgray 
darkgreen 
darkkhaki 
darkmagenta 
darkolivegreen 
darkorange 
darkorchid 
darkred 
darksalmon 
darkseagreen 
darkslateblue 
darkslategray 
darkturquoise 
darkviolet 
deeppink 
deepskyblue 
dimgray 
dodgerblue 
firebrick 
floralwhite 
forestgreen 
fuchsia 
gainsboro 
ghostwhite 
gold 
goldenrod 
gray 
green 
greenyellow 
honeydew 
hotpink 
indianred 
indigo 
ivory 
khaki 
lavender 
lavenderblush 
lawngreen 
lemonchiffon 
lightblue 
lightcoral 
lightcyan 
lightgoldenrodyellow 
lightgray 
lightgreen 
lightpink 
lightsalmon 
lightseagreen 
lightskyblue 
lightslategray 
lightsteelblue 
lightyellow 
lime 
limegreen 
linen 
magenta 
maroon 
mediumaquamarine 
mediumblue 
mediumorchid 
mediumpurple 
mediumseagreen 
mediumslateblue 
mediumspringgreen 
mediumturquoise 
mediumvioletred 
midnightblue 
mintcream 
mistyrose 
moccasin 
navajowhite 
navy 
oldlace 
olive 
olivedrab 
orange 
orangered 
orchid 
palegoldenrod 
palegreen 
paleturquoise 
palevioletred 
papayawhip 
peachpuff 
peru 
pink 
plum 
powderblue 
purple 
rebeccapurple 
red 
rosybrown 
royalblue 
saddlebrown 
salmon 
sandybrown 
seagreen 
seashell 
sienna 
silver 
skyblue 
slateblue 
slategray 
snow 
springgreen 
steelblue 
tan 
teal 
thistle 
tomato 
turquoise 
violet 
wheat 
white 
whitesmoke 
yellow 
yellowgreen 
581 | -------------------------------------------------------------------------------- /faq/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar: false 3 | --- 4 | 5 | # FAQ 6 | 7 | ## What is wsrv.nl? 8 | 9 | wsrv.nl is an image service which is free for use to anyone, and we offer it as-is, it's just basic 10 | image resizing, available to anyone, easy to use. We try to keep everyone as happy as we can. 11 | 12 | ## What is this page? Where do I find my question? 13 | 14 | An FAQ is a list of frequently asked questions and answers. On this page we do our best to address 15 | concerns, and explain some inner workings of our service. 16 | 17 | You may scroll down to try to find your question. We also provide documentation you can read, and 18 | there is always our [GitHub][weserv-github] to assist you. 19 | 20 | ## What is the history of this project? 21 | 22 | The project started around 2007 on some spare servers. It was targeted at customers, to be used in 23 | websites, web applications and mobile applications. By making it freely available, it saved traffic (through 24 | compression) and offloaded the main servers, because customers didn't have to use poor self-written 25 | scripts for image resizing. We gained experience with different user cases, and the separation from the 26 | main servers enabled us to use the latest and greatest software stack. 27 | 28 | ## How are you funded? 29 | 30 | Since 2011 wsrv.nl is privately funded, and used as a testbed for new techniques in resizing, 31 | recognition and processing. Operating costs of the image service are very low. To prevent conflicts of 32 | interest, we never accepted any (financial) compensation or donation since we started, and we don't 33 | affiliate. Our intent is to keep the service running for many years to come. 34 | 35 | Try it for yourself, if you experience problems or if it doesn't meet expectations, contact us. 36 | 37 | ## Are there any limitations? 38 | 39 | There is a filter on the origin domain name. This means that we refuse to download images from certain 40 | websites, to prevent our service from being blocked by others. This filtering is handled by [OpenDNS 41 | domain tagging][opendns-domain-tagging]. 42 | 43 | Furthermore, there is a request limit per visitor IP for uncached requests, which is 2500 images per 10 44 | minutes, after which the IP-address will be blocked for 1 hour. 45 | 46 | We are not a fan of filtering or limitations, but even more so, we are not a fan of being filtered. It is 47 | always possible to use our open source code, without filtering and limitations, on your own server. 48 | 49 | ## Is the code open source? 50 | 51 | Yes, it is! It is distributed under the open source [BSD 3-Clause license][weserv-license], check our [GitHub][weserv-github] for more 52 | information. 53 | 54 | ## How do I use your source code? 55 | 56 | The easiest way is to use Docker. After you have installed Docker, follow the [Docker installation 57 | instructions][weserv-docker] on using our source code with Docker. 58 | 59 | ## Can I sell your service? 60 | 61 | Sure, the [BSD 3-Clause license][weserv-license] permits you to use our code in your product, but please don't use our 62 | name in your marketing materials. Using the free service provided on wsrv.nl in your products 63 | is also permitted, but be reminded that our support is best-effort. 64 | 65 | If you really mean to sell our free service to other people as-is; I guess you're an amazing salesman, or 66 | we are terrible at it, but we do enjoy some good competition! 67 | 68 | ## Do you keep any logs? 69 | 70 | Yes, we do, for 7 days, after which they will be deleted automatically. The log is kept only on the server 71 | that processes your request. We don't share these logs, or store them in any other place. More 72 | information on how we collect, store and use any data, can be found in our [privacy policy][weserv-privacy-policy]. 73 | 74 | ## Where are your servers located? 75 | 76 | Our servers are located near Paris (France) and Falkenstein (Germany). We also use Cloudflare, [Cloudflare 77 | has servers more close to your location][cloudflare-network], and they are fast. 78 | 79 | For now, our servers are with [OVH][ovh], [Scaleway][scaleway] and [Hetzner][hetzner] this may change in the future. We've 80 | always used servers located within the European Union, and continue to do so. 81 | 82 | ## What IP addresses does wsrv.nl use to fetch my images? 83 | 84 | A complete list of the IPs we use for outbound traffic can be found [here][ip-list]. 85 | 86 | ## How is your relationship with Cloudflare? 87 | 88 | Wonderful, thanks for asking! Seriously, they provide awesome service, and are amazing to work with. 89 | 90 | ## What is your relationship with Cloudflare? 91 | 92 | We've started this service in 2007, use [Cloudflare](https://www.cloudflare.com/) since early 2012, and are on the free-tier since 2015. 93 | Costs for the servers to support wsrv.nl are really low, and it serves as a great testbed for new 94 | technologies. Cloudflare is based on the same [principles to provide their services][cloudflare-cdn]. 95 | 96 | ## Is there any SLA or uptime guarantee for your service? 97 | 98 | Uptime guarantees buy you nothing but expensive insurance policies. We've had 99,993% uptime on 99 | average since 2007, all based on best-effort from all sides. Our service will not be the best fit for 100 | everyone: if you need more guarantees, anything besides best-effort, we encourage you to use our 101 | config and code as provided on our [GitHub][weserv-github], and build your own solution. We're always happy to help 102 | with questions that may arise if you do so. 103 | 104 | Besides, our service is free, so there is nothing to pay you back. If you want to help us, please do so by 105 | reporting any bugs, problems, and/or reviewing our code! 106 | 107 | ## What companies are using this service? 108 | 109 | Due to privacy concerns we're unable to share names, even if we were able to do so technically. 110 | 111 | Our service is mainly used by ISP's, dealerships, real estate agencies, shops, social networks and mobile 112 | app developers. Our reach is global, and we fetch images from 300.000 different unique domains. 113 | 114 | ## Are you passing any information to the origin server? 115 | 116 | We don't send any details to the server where the original image is kept. All requests for the original 117 | image are done anonymously from our servers. The only two things the request from our server has in 118 | common with your request is: 1. the address of the original image, and 2. the time you make the request. 119 | 120 | ## Will you see my images? Can others see my images? 121 | 122 | We are not interested in the images you ask us to process. 123 | 124 | The only exception is if there is a technical oddity in an image which causes strange behavior on our 125 | server(s). If you ask us to process such an image, we may try to copy the technical bits that causes the 126 | strange behavior. But we will never show others any (real) part of your image. 127 | 128 | Your images are private, and will not be shared, unless you tell us so. Other people can always use the 129 | same link (web address / URL) as you use, but we will not share any web addresses or logs. 130 | 131 | But please, always be careful of what you put on the internet, and who you trust online. If you don't trust 132 | our servers, or Cloudflare, you can use [our open source code][weserv-github] on your server(s). 133 | 134 | ## Are you saving images on your server(s)? 135 | 136 | We only save images to process them, only the processed images are kept for a short time (in cache). 137 | 138 | ## If images are modified, do you refresh them after a certain period of time? 139 | 140 | We do, but there is some caching. 141 | 142 | ## What is caching? 143 | 144 | A cache is a place where data (such as images) is temporary stored, to improve performance when the data 145 | is requested again. If the data is requested again, it may be served from the cache. For this service, 146 | the most important bits are our server cache, and your browser cache. 147 | 148 | ## How are images cached by your servers? 149 | 150 | We cache images in different ways, depending on the rate of requests, no more than 31 days, and most 151 | often at least 7 days. 152 | 153 | We utilize the [proxy cache in nginx][nginx-cache] to accomplish this, on top of that, [Cloudflare][cloudflare] caches the most 154 | frequently accessed images globally. 155 | 156 | Our servers only initiate a refresh when all caches have expired, and only when the image is still being 157 | requested by end users. 158 | 159 | The rules we use for server-side caching are different from the ones you see in the headers we provide 160 | for browsers. 161 | 162 | ## How are images cached by my browser? 163 | 164 | We ask the browser to cache images for 31536000 seconds, or 1 year. But it is up to the browser to do 165 | so. 166 | 167 | You can always clear your browser cache. Unfortunately, it is not possible for us (or our servers) to clear 168 | your browser cache. 169 | 170 | ## Can I remove an image from your server(s) cache? 171 | 172 | Not yet, a method to remove anything from our server side cache is still worked on. You can follow 173 | [Issue #14 - Remove cached images (by API/manual)][cache-removal-tool] for further updates. 174 | 175 | ## Why am I redirected to https:// even when I request http://? 176 | 177 | For added security we use [HSTS][hsts] to let modern browsers know that they can and should use HTTPS, we 178 | don't send any redirect headers ourselves, this is being done by your browser. It prevents any 179 | opportunistic MITM attacks. 180 | 181 | ## Are images compressed in any way? 182 | 183 | GZip compression is disabled, because it increases file sizes for JPEG-images, and it increases CPU-load 184 | on the client and server. 185 | 186 | JPEG-compression is honored, and is by default used when requesting BMP-images (they are converted 187 | to JPEG). If you want to modify compression for JPEG-images, you can do so by setting the [`&q=`][quality] 188 | parameter. 189 | 190 | ## Which file-extensions do you support? 191 | 192 | We "officially" support JPEG, PNG, GIF, TIFF, WebP, PDF and SVG as image input. "Unofficially" we're 193 | supporting all [libMagick image file types][magick-formats]. 194 | 195 | ## Do you support animated images? E.g. animated .gif? 196 | 197 | We support animated WebP and GIF images through the use of [`&n=-1`][n-pages]. By default, the first frame of 198 | each image is processed. We don't support APNG, since the official libpng reference implementation 199 | doesn't support this extension. 200 | 201 | ## Can I use my own (sub)domain? E.g. by using a CNAME to wsrv.nl? 202 | 203 | We offer this service only on the wsrv.nl domain, and we offer it as-is. However, if you want to 204 | use it under your own (sub)domain, please see our [GitHub][weserv-github] to use it on your own server(s). 205 | 206 | ## Why don't you support CNAME-ing? 207 | 208 | The goal of this service is reaching out to starting websites that don't have the skills nor resources to 209 | script and host something themselves. But we don't want to serve the whole internet, aside from the 210 | amount of traffic (we already handle millions of requests per hour, which is great), our opinion is that 211 | when sites grow, they probably want to host their own solution. This solution will probably integrate 212 | better with their site(s), and will offer many advantages we just can't. 213 | 214 | ## Why am I not seeing any HTTP 304 header when I request a cached image? 215 | 216 | This is because we don't use Last-Modified headers. 217 | 218 | ## Why don't you use ETag or Last-Modified headers? 219 | 220 | We disable 2 (default) settings regarding cache-control. These are the ETag header, and the Last- 221 | Modified header. 222 | 223 | We do set the Cache-Control header, which can be controlled via the [`&max-age=`][cache-control] parameter. Allow me 224 | to explain this decision, using nginx and Apache configuration. 225 | 226 | Consider the following nginx and Apache settings, these are identical to the settings we use: 227 | 228 | ::: code-group 229 | 230 | ```nginx 231 | http { 232 | etag off; # Disable ETag header 233 | expires 1y; # Far-future expiration 234 | } 235 | ``` 236 | 237 | ```apache [Apache] 238 | Header unset ETag 239 | FileETag None 240 | Header set Cache-Control "max-age=31536000" 241 | ``` 242 | 243 | ::: 244 | 245 | These directives completely disables ETags, so the browser is somewhat forced to listen to the Cache- 246 | Control header. It also tells the browser to cache the file 31536000 seconds, or 1 year. 247 | 248 | Optional, we use multiple servers to serve static content, and we are not sure about the last-modified 249 | times those servers report, because each has his own version of the cache, so we also use: 250 | 251 | ::: code-group 252 | 253 | ```nginx 254 | http { 255 | add_header Last-Modified "" always; # Always remove the Last-Modified header 256 | } 257 | ``` 258 | 259 | ```apache [Apache] 260 | Header unset Last-Modified 261 | ``` 262 | 263 | ::: 264 | 265 | Which tells the webservers to not serve any Last-Modified headers, so browsers can only listen to the 266 | Cache-Control max-age header. 267 | 268 | These settings are used by us on lots of high-traffic websites, and disabling the ETag and Last-Modified 269 | headers have certainly helped to reduce traffic to a fifth of what it used to be. Especially Internet Explorer 270 | is very sensitive to those settings. 271 | 272 | The Yahoo Developer Network recommends turning off ETags because of this misbehavior: 273 | [Best practices for speeding up your web site - Disable ETags][disable-etags]. 274 | 275 | Disabling Last-Modified will stop browsers from asking 304 Content Not Modified requests. In my 276 | experience this is positive, because the webserver has fewer requests to process, and browsers rely more 277 | on the Cache-Control settings you serve. But it may or may not suit you. Some browsers will try to 278 | validate assets every few minutes if you serve them a "Last-Modified" header, and that's why I would 279 | advise to disable the use of it completely. 280 | 281 | If you want more information about the headers we serve, consider using [REDbot.org][redbot] this will explain 282 | every header we serve, and why this is used. We also serve Cache-Control: public, this allows browsers to 283 | cache things even when accessing wsrv.nl over https://. 284 | 285 | Let us know if you need more info. We are open for comments about the caching policies we use. We do 286 | run complete tests on server load, bandwidth, and CPU-cycles, for each header we place. Enabling 304 287 | will generate 5 times more requests from browsers in our case, this could be different for your site, but I 288 | expect it to be the same. 289 | 290 | ## What if I still have a question? 291 | 292 | That means you're unique, and one of a kind! Did you also read our documentation? 293 | 294 | If your question is not within these frequently asked questions, or if there is still something not clear; 295 | [Please open an issue on our GitHub][weserv-issues]. We do our best to answer all questions, and we may even honor 296 | your question by featuring it on this page! 297 | 298 | [opendns-domain-tagging]: https://community.opendns.com/domaintagging/about/ 299 | [weserv-github]: https://github.com/weserv/images/ 300 | [weserv-issues]: https://github.com/weserv/images/issues 301 | [weserv-license]: https://github.com/weserv/images/blob/5.x/LICENSE 302 | [weserv-docker]: https://github.com/weserv/images/tree/5.x/docker#readme 303 | [weserv-privacy-policy]: https://github.com/weserv/images/blob/5.x/Privacy-Policy.md 304 | [cloudflare-network]: https://www.cloudflare.com/network/ 305 | [ovh]: https://www.ovh.com/ 306 | [scaleway]: https://www.scaleway.com/ 307 | [hetzner]: https://www.hetzner.com/ 308 | [ip-list]: /ips.txt 309 | [cloudflare]: https://www.cloudflare.com/ 310 | [cloudflare-cdn]: https://www.cloudflare.com/cdn/ 311 | [nginx-cache]: https://web.archive.org/web/20240404205848/https://www.nginx.com/blog/nginx-caching-guide/ 312 | [cache-removal-tool]: https://github.com/weserv/images/issues/14 313 | [hsts]: https://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security 314 | [magick-formats]: https://imagemagick.org/script/formats.php#supported 315 | [n-pages]: /docs/format.md#number-of-pages 316 | [quality]: /docs/format.md#quality 317 | [nginx]: https://nginx.org/ 318 | [cache-control]: /docs/format.md#cache-control 319 | [disable-etags]: https://developer.yahoo.com/performance/rules.html#etags 320 | [redbot]: https://redbot.org/ 321 | -------------------------------------------------------------------------------- /index.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: home 3 | title: wsrv.nl 4 | titleTemplate: wsrv.nl 5 | head: 6 | - - meta 7 | - name: twitter:title 8 | content: Image cache & resize service 9 | - - meta 10 | - name: twitter:description 11 | content: Manipulate images on-the-fly with a worldwide cache 12 | - - meta 13 | - property: og:title 14 | content: Image cache & resize service 15 | - - meta 16 | - property: og:description 17 | content: Manipulate images on-the-fly with a worldwide cache 18 | hero: 19 | image: 20 | light: /logo.svg 21 | dark: /logo-dark.svg 22 | name: wsrv.nl 23 | text: An image cache & resize service 24 | tagline: Manipulate images on-the-fly with a worldwide cache. 25 | actions: 26 | - theme: brand 27 | text: Read the documentation → 28 | link: /docs/introduction.html 29 | - theme: alt 30 | text: View on GitHub 31 | link: https://github.com/weserv/images 32 | features: 33 | - title: Crazy Fast 34 | icon: 35 | details: Performance is not just an afterthought, we baked it in from the start! 36 | - title: Awesome Technology 37 | icon: 38 | details: wsrv.nl employs best-in-class technologies such as nginx and libvips. 39 | - title: Free / Open Source 40 | icon: 41 | details: wsrv.nl is an open source project, so you can spend your money on other stuff. 42 | --- 43 | 44 | ### Your images unchained 45 | 46 | 47 | 55 | 56 | 57 | The CDN is provided by [Cloudflare](https://www.cloudflare.com/). Images are being cached and delivered straight from 58 | [300+ global datacenters](https://www.cloudflare.com/network/). This ensures the fastest load times and best performance. 59 | 60 | ### Widely used 61 | 62 | On average, we resize 6 million (6×106) images per hour, which generates around 400TB of outbound traffic per month. 63 | 64 | ### Features 65 | 66 | 92 | -------------------------------------------------------------------------------- /news/2018/07/29/introducing-api-4.md: -------------------------------------------------------------------------------- 1 | --- 2 | editLink: false 3 | --- 4 | 5 | # Introducing API version 4 6 | 7 | ## Preface 8 | 9 | As the amount of traffic increases, we come up with solutions to handle the traffic. Nowadays we handle 10 | 2 million requests per hour (4 million on peak), which is great, but it requires proper server capacity and 11 | effective software that scales with the amount of traffic that make this service reliable. 12 | 13 | ## OpenResty, LuaJIT and lua-vips 14 | 15 | With API version 4 we decided to rewrite to complete code base to Lua and switch to [OpenResty][openresty], 16 | which turns [nginx][nginx] and [LuaJIT][luajit] into a full-fledged scriptable web platform. For image handling and 17 | manipulation we still use the [libvips][libvips] image processing library under the hood. We have only moved 18 | from the [PHP-binding][php-vips] to the [Lua binding][lua-vips]. 19 | 20 | You may wonder why we did this; it's because OpenResty is robust, fast and scales with the amount of 21 | traffic we are processing nowadays. One of the core benefits of OpenResty is that it is fully asynchronous 22 | and that our code can be written directly inside Nginx without using PHP-FPM and FastCGI. The amazing 23 | just-in-time (JIT) compilation and the integrated foreign function interface (FFI) in LuaJIT have also been 24 | motives to move away from PHP. 25 | 26 | Perhaps you've already noticed, [https://wsrv.nl/](/) already states that API version 4 is 27 | running. This is not a mistake, our A/B testing went so well that we decided (on time of writing) to 28 | forward all traffic to API version 4. 29 | 30 | ## What has changed for the end user? 31 | 32 | Absolutely nothing, all parameters listed on API 3 still work on API 4. The only thing you might notice is 33 | when you process an image, that it will load faster. If you found something odd, don't hesitate to contact 34 | us. 35 | 36 | We track support tickets, issues and feature requests using the [GitHub issue tracker][issue-tracker]. 37 | 38 | ## What has been added? 39 | 40 | We introduced some new parameters and a more flexible URI parser. 41 | 42 | ### Masking 43 | 44 | Controls the visible and non-visible area of the image. Previously the [`&mask`][mask] and [`&mtrim`][mask-trim] parameter 45 | were named as `&shape` and `&strim`, it was renamed to make room for new mask features. 46 | 47 | - Mask type [`&mask`][mask]. Sets the mask type from a predefined list of shapes: 48 | - `circle` 49 | - `ellipse` 50 | - `triangle` 51 | - `triangle-180`: Triangle tilted upside down 52 | - `pentagon` 53 | - `pentagon-180`: Pentagon tilted upside down 54 | - `hexagon` 55 | - `square`: Square tilted 45 degrees 56 | - `star`: 5-point star 57 | - `heart` 58 | - Mask trim [`&mtrim`][mask-trim]. Removes the remaining whitespace from the mask. 59 | - Mask background [`&mbg`][mask-bg]. Sets the background color of the mask. 60 | 61 | ### Flexible URI parser 62 | 63 | With API 4 we are supporting URI's starting with `http://` and `https://`. Previously this would result in 64 | an error to prevent BBCode parsers to fail on the double `http(s)://`-part. Because Markdown is 65 | increasingly becoming the standard for user input, we decided to make the URI parser more flexible. 66 | Note that we will still support `?url=ssl:…` and `?url=//…`-requests for backwards compatibility. 67 | 68 | ## Where can I view the code? 69 | 70 | The code is available on the [4.x branch][4.x-branch], this will become the default branch in the future. 71 | 72 | [openresty]: https://openresty.org/en/ 73 | [nginx]: https://nginx.org/ 74 | [luajit]: https://luajit.org/luajit.html 75 | [libvips]: https://github.com/libvips/libvips 76 | [php-vips]: https://github.com/libvips/php-vips 77 | [lua-vips]: https://github.com/libvips/lua-vips 78 | [issue-tracker]: https://github.com/weserv/images/issues 79 | [mask]: /docs/mask.md#mask-type 80 | [mask-trim]: /docs/mask.md#mask-trim 81 | [mask-bg]: /docs/mask.md#mask-background 82 | [4.x-branch]: https://github.com/weserv/images/tree/4.x 83 | -------------------------------------------------------------------------------- /news/2019/09/01/introducing-api-5.md: -------------------------------------------------------------------------------- 1 | --- 2 | editLink: false 3 | --- 4 | 5 | # Introducing API version 5 6 | 7 | ## Introduction 8 | 9 | We've just released API version 5, which contains many enhancements and new features. Since the 10 | introduction of [API version 4][version-4-post], our website traffic has tripled. Nowadays we handle 6 million requests per 11 | hour. It's an accomplishment that we're very proud of, handling such large amounts of traffic is a great 12 | challenge. This service would not have been reliable without the CDN provided by [Cloudflare][cloudflare] and 13 | effective software (such as [nginx][nginx] and [libvips][libvips]). 14 | 15 | Here's a summary of the changes. To maintain backward compatibility, all parameters listed on API 4 still 16 | work on API 5. The source code is available on the [5.x branch][5.x-branch], this will become the default branch in 17 | the future. 18 | 19 | ## LuaJIT → C++ 20 | 21 | With API version 5 we've rewritten the entire codebase to C++ as a nginx module. The reason for this 22 | rewrite is to tighten the control over memory allocation. We found out that the current garbage collector 23 | (GC) in LuaJIT 2, which is essentially the same as the one in vanilla Lua 5.1, is not very fast for large 24 | workloads. [A new GC is already proposed][luajit-new-gc] for LuaJIT 3.0, but it has not yet been implemented. 25 | 26 | We also worried about the future of LuaJIT, given that [the author of LuaJIT is stepping down][luajit-maintenance]. It is 27 | doubtful whether anyone will fill his shoes. The new C++ codebase ensures that we can continue our 28 | service for many years to come. 29 | 30 | ## Revamped front-end 31 | 32 | The old single index page had to be improved. We've completely revamped the front-end using 33 | [VuePress][vuepress], which allows us to write the documentation as regular Markdown files. 34 | 35 | The documentation is available in our [weserv/docs][weserv-docs] GitHub repository. 36 | 37 | ## Improved rate limiter 38 | 39 | We have improved our [basic Redis rate limiter](https://redis.io/commands/incr#pattern-rate-limiter-2). Our new rate limiter is written in C and runs inside a 40 | Redis backed nginx module. The implementation is based on the [onsigntv/redis-rate-limiter][onsigntv/redis-rate-limiter] module, 41 | which offers a straightforward implementation of the fairly sophisticated [generic cell rate algorithm][gcra], 42 | in 130 lines of C, without external dependencies. 43 | 44 | An additional feature of this module is that it's easy to check your current rate limit quota: 45 | 46 | ```console 47 | $ curl -i https://wsrv.nl/quota 48 | HTTP/1.1 200 OK 49 | Date: Sun, 01 Sep 2019 00:00:00 GMT 50 | X-RateLimit-Limit: 2500 51 | X-RateLimit-Remaining: 2500 52 | X-RateLimit-Reset: 0 53 | 54 | {"X-RateLimit-Limit":2500, "X-RateLimit-Remaining":2500, "X-RateLimit-Reset":0} 55 | ``` 56 | 57 | ::: tip 58 | Our limit is around 2500 images per 10 minutes. Accessing this endpoint does not count against 59 | your rate limit. 60 | ::: 61 | 62 | The source code of the rate limiter can be viewed on GitHub: [weserv/rate-limit-nginx-module][rate-limit-nginx-module]. 63 | 64 | ## Support for animated images 65 | 66 | Thanks to [libvips 8.8][libvips-8.8], we've now enabled support for [animated WebP and GIF images][n-pages]. 67 | 68 | ::: code-group 69 | 70 | ```html [HTML] 71 | 72 | ``` 73 | 74 | ```md [Markdown] 75 | ![Animated image](https://wsrv.nl/?url=wsrv.nl/banana.webp&h=300&output=gif&n=-1) 76 | ``` 77 | 78 | ::: 79 | 80 | [![Animated image](/static/banana.webp?h=300&output=gif&n=-1)](/?url=wsrv.nl/banana.webp&h=300&output=gif&n=-1){target="_blank"} 81 | 82 | ## Support for loading HEIC images 83 | 84 | We've added support for loading HEIC-images. This is the new image compression standard being used by 85 | Apple and others. HEIC files are typically half the size of JPEG files at similar quality. 86 | 87 | ::: tip 88 | Saving to HEIC-images isn't supported due to patent issues. Hopefully the use of royalty-free 89 | encoding formats such as [AVIF][avif] will become more widely used in the future. 90 | ::: 91 | 92 | ## CSS-inspired fit parameters 93 | 94 | We've deprecated the confusing fit (`&t=`) parameters (`fit`, `fitup`, `square`, `squaredown`, `absolute` 95 | and `letterbox`) and aligned it with the CSS terminology. 96 | 97 | Here's a handy table to help users migrating to these new CSS-inspired parameters: 98 | 99 | | Before | After | 100 | | --------------- | ------------------------------ | 101 | | `&t=fit` | [`&fit=inside&we`][fit-inside] | 102 | | `&t=fitup` | [`&fit=inside`][fit-inside] | 103 | | `&t=square` | [`&fit=cover`][fit-cover] | 104 | | `&t=squaredown` | [`&fit=cover&we`][fit-cover] | 105 | | `&t=absolute` | [`&fit=fill`][fit-fill] | 106 | | `&t=letterbox` | [`&fit=contain`][fit-contain] | 107 | 108 | The new without enlargement parameter ([`&we`][without-enlargement]) can be used in combination with all [`&fit=`][fit] 109 | parameters. We also introduced a new parameter named [`&fit=outside`][fit-outside], which will resize an image to 110 | be as small as possible while ensuring its dimensions are greater than or equal to both those specified. 111 | 112 | ## Tinting images 113 | 114 | We introduced a new parameter named [`&tint`][tint] to tint an image using the provided chroma 115 | while preserving the image luminance. 116 | 117 | ::: code-group 118 | 119 | ```html [HTML] 120 | 121 | ``` 122 | 123 | ```md [Markdown] 124 | ![Tint](https://wsrv.nl/?url=wsrv.nl/lichtenstein.jpg&w=300&tint=red) 125 | ``` 126 | 127 | ::: 128 | 129 | [![Tint](/static/lichtenstein.jpg?w=300&tint=red)](/?url=wsrv.nl/lichtenstein.jpg&w=300&tint=red){target="_blank"} 130 | 131 | ## Arbitrary rotation angles 132 | 133 | Instead of only being able to rotate multiples of 90 degrees, any angle can now be given. The remaining 134 | space can be filled with a background color by using `&rbg=`. To reflect this change, the `&or=` 135 | parameter has been renamed to [`&ro=`][rotation]. 136 | 137 | ::: code-group 138 | 139 | ```html [HTML] 140 | 141 | ``` 142 | 143 | ```md [Markdown] 144 | ![Rotation](https://wsrv.nl/?url=wsrv.nl/lichtenstein.jpg&h=300&ro=45) 145 | ``` 146 | 147 | ::: 148 | 149 | [![Rotation](/static/lichtenstein.jpg?h=300&ro=45)](/?url=wsrv.nl/lichtenstein.jpg&h=300&ro=45){target="_blank"} 150 | 151 | ## Adaptive filter and compression level 152 | 153 | To minimize the size of PNG images and thus reduce their load time we've introduced some new 154 | parameters named [`&af`][adaptive-filter] and [`&l`][compression-level]. 155 | 156 | ## Metadata output 157 | 158 | To quickly view the metadata of an image, we've added support for [`&output=json`][output]. 159 | See [here](/?url=wsrv.nl/zebra.jpg&output=json){target="_blank"} for an example. 160 | 161 | ## Flip / flop an image 162 | 163 | We've added support for flipping an image [horizontally][flop] or [vertically][flip]. You can combine these parameters 164 | to flip along both axes. 165 | 166 | ## JSON for error messages 167 | 168 | Instead of returning our error messages as plain text, you'll now receive a JSON-formatted response with 169 | the appropriate `application/json` MIME-type. This makes it easier to integrate our service into any 170 | type of website or application. 171 | 172 | ## Other improvements 173 | 174 | - Improve Docker image and deployment ([#180](https://github.com/weserv/images/issues/180)). 175 | - A pre-resize crop behaviour ([`&precrop`][rectangle-crop] - [#176](https://github.com/weserv/images/issues/176)). 176 | - Letterboxing without oversampling ([`&fit=contain&we`][without-enlargement] - [#173](https://github.com/weserv/images/issues/173)). 177 | - Retrieving the largest/smallest page from a multi-resolution image ([`&page=-1`][page] / 178 | [`&page=-2`][page] - [#170](https://github.com/weserv/images/issues/170)). 179 | - Defining the `max-age` of the `Cache-Control` HTTP-header ([`&maxage=31d`][cache-control] - [#186](https://github.com/weserv/images/issues/186)). 180 | - Applying a duotone filter to an image ([`&filt=duotone`][filter]). 181 | - Background color when using `&fit=contain` ([`&cbg=`][fit-contain]). 182 | - `&a=crop-x%-y%` has been renamed to [`&a=focal-x%-y%`][focal-point]. 183 | - `&errorredirect=` has been renamed to [`&default=`][default-image]. 184 | 185 | [version-4-post]: /news/2018/07/29/introducing-api-4.md 186 | [cloudflare]: https://www.cloudflare.com/ 187 | [nginx]: https://nginx.org/ 188 | [libvips]: https://github.com/libvips/libvips 189 | [vuepress]: https://vuepress.vuejs.org/ 190 | [weserv-docs]: https://github.com/weserv/docs 191 | [5.x-branch]: https://github.com/weserv/images/tree/5.x 192 | [luajit-new-gc]: https://web.archive.org/web/20220826233802/http://wiki.luajit.org/New-Garbage-Collector 193 | [luajit-maintenance]: https://www.freelists.org/post/luajit/Looking-for-new-LuaJIT-maintainers 194 | [onsigntv/redis-rate-limiter]: https://github.com/onsigntv/redis-rate-limiter 195 | [gcra]: https://en.wikipedia.org/wiki/Generic_cell_rate_algorithm 196 | [rate-limit-nginx-module]: https://github.com/weserv/rate-limit-nginx-module 197 | [libvips-8.8]: https://www.libvips.org/2019/04/22/What's-new-in-8.8.html 198 | [n-pages]: /docs/format.md#number-of-pages 199 | [avif]: https://aomediacodec.github.io/av1-avif/ 200 | [fit]: /docs/fit.md 201 | [fit-inside]: /docs/fit.md#inside 202 | [fit-outside]: /docs/fit.md#outside 203 | [fit-cover]: /docs/fit.md#cover 204 | [fit-fill]: /docs/fit.md#fill 205 | [fit-contain]: /docs/fit.md#contain 206 | [without-enlargement]: /docs/fit.md#without-enlargement 207 | [tint]: /docs/adjustment.md#tint 208 | [rotation]: /docs/orientation.md#rotation 209 | [adaptive-filter]: /docs/format.md#adaptive-filter 210 | [compression-level]: /docs/format.md#compression-level 211 | [output]: /docs/format.md#output 212 | [flip]: /docs/orientation.md#flip 213 | [flop]: /docs/orientation.md#flop 214 | [filter]: /docs/adjustment.md#filter 215 | [focal-point]: /docs/crop.md#focal-point 216 | [default-image]: /docs/format.md#default-image 217 | [rectangle-crop]: /docs/crop.md#rectangle-crop 218 | [page]: /docs/format.md#page 219 | [cache-control]: /docs/format.md#cache-control 220 | -------------------------------------------------------------------------------- /news/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | aside: false 3 | editLink: false 4 | sidebar: false 5 | news: 6 | - title: Introducing API version 5 7 | date: 2019-09-01 8 | link: /news/2019/09/01/introducing-api-5.html 9 | summary: Rewrote the entire codebase to C++, support for animated WebP and GIF images, plus many more improvements. 10 | - title: Introducing API version 4 11 | date: 2018-07-29 12 | link: /news/2018/07/29/introducing-api-4.html 13 | summary: Switched to OpenResty and LuaJIT, introduced a friendlier URI parser, plus some new parameters were added. 14 | --- 15 | 16 | # News 17 | 18 | 19 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@weserv/docs", 3 | "version": "0.2.0", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "@weserv/docs", 9 | "version": "0.2.0", 10 | "hasInstallScript": true, 11 | "license": "MIT", 12 | "devDependencies": { 13 | "prettier": "^3.2.5", 14 | "vitepress": "^1.2.2" 15 | } 16 | }, 17 | "node_modules/@algolia/autocomplete-core": { 18 | "version": "1.9.3", 19 | "resolved": "https://registry.npmjs.org/@algolia/autocomplete-core/-/autocomplete-core-1.9.3.tgz", 20 | "integrity": "sha512-009HdfugtGCdC4JdXUbVJClA0q0zh24yyePn+KUGk3rP7j8FEe/m5Yo/z65gn6nP/cM39PxpzqKrL7A6fP6PPw==", 21 | "dev": true, 22 | "dependencies": { 23 | "@algolia/autocomplete-plugin-algolia-insights": "1.9.3", 24 | "@algolia/autocomplete-shared": "1.9.3" 25 | } 26 | }, 27 | "node_modules/@algolia/autocomplete-plugin-algolia-insights": { 28 | "version": "1.9.3", 29 | "resolved": "https://registry.npmjs.org/@algolia/autocomplete-plugin-algolia-insights/-/autocomplete-plugin-algolia-insights-1.9.3.tgz", 30 | "integrity": "sha512-a/yTUkcO/Vyy+JffmAnTWbr4/90cLzw+CC3bRbhnULr/EM0fGNvM13oQQ14f2moLMcVDyAx/leczLlAOovhSZg==", 31 | "dev": true, 32 | "dependencies": { 33 | "@algolia/autocomplete-shared": "1.9.3" 34 | }, 35 | "peerDependencies": { 36 | "search-insights": ">= 1 < 3" 37 | } 38 | }, 39 | "node_modules/@algolia/autocomplete-preset-algolia": { 40 | "version": "1.9.3", 41 | "resolved": "https://registry.npmjs.org/@algolia/autocomplete-preset-algolia/-/autocomplete-preset-algolia-1.9.3.tgz", 42 | "integrity": "sha512-d4qlt6YmrLMYy95n5TB52wtNDr6EgAIPH81dvvvW8UmuWRgxEtY0NJiPwl/h95JtG2vmRM804M0DSwMCNZlzRA==", 43 | "dev": true, 44 | "dependencies": { 45 | "@algolia/autocomplete-shared": "1.9.3" 46 | }, 47 | "peerDependencies": { 48 | "@algolia/client-search": ">= 4.9.1 < 6", 49 | "algoliasearch": ">= 4.9.1 < 6" 50 | } 51 | }, 52 | "node_modules/@algolia/autocomplete-shared": { 53 | "version": "1.9.3", 54 | "resolved": "https://registry.npmjs.org/@algolia/autocomplete-shared/-/autocomplete-shared-1.9.3.tgz", 55 | "integrity": "sha512-Wnm9E4Ye6Rl6sTTqjoymD+l8DjSTHsHboVRYrKgEt8Q7UHm9nYbqhN/i0fhUYA3OAEH7WA8x3jfpnmJm3rKvaQ==", 56 | "dev": true, 57 | "peerDependencies": { 58 | "@algolia/client-search": ">= 4.9.1 < 6", 59 | "algoliasearch": ">= 4.9.1 < 6" 60 | } 61 | }, 62 | "node_modules/@algolia/cache-browser-local-storage": { 63 | "version": "4.23.3", 64 | "resolved": "https://registry.npmjs.org/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.23.3.tgz", 65 | "integrity": "sha512-vRHXYCpPlTDE7i6UOy2xE03zHF2C8MEFjPN2v7fRbqVpcOvAUQK81x3Kc21xyb5aSIpYCjWCZbYZuz8Glyzyyg==", 66 | "dev": true, 67 | "dependencies": { 68 | "@algolia/cache-common": "4.23.3" 69 | } 70 | }, 71 | "node_modules/@algolia/cache-common": { 72 | "version": "4.23.3", 73 | "resolved": "https://registry.npmjs.org/@algolia/cache-common/-/cache-common-4.23.3.tgz", 74 | "integrity": "sha512-h9XcNI6lxYStaw32pHpB1TMm0RuxphF+Ik4o7tcQiodEdpKK+wKufY6QXtba7t3k8eseirEMVB83uFFF3Nu54A==", 75 | "dev": true 76 | }, 77 | "node_modules/@algolia/cache-in-memory": { 78 | "version": "4.23.3", 79 | "resolved": "https://registry.npmjs.org/@algolia/cache-in-memory/-/cache-in-memory-4.23.3.tgz", 80 | "integrity": "sha512-yvpbuUXg/+0rbcagxNT7un0eo3czx2Uf0y4eiR4z4SD7SiptwYTpbuS0IHxcLHG3lq22ukx1T6Kjtk/rT+mqNg==", 81 | "dev": true, 82 | "dependencies": { 83 | "@algolia/cache-common": "4.23.3" 84 | } 85 | }, 86 | "node_modules/@algolia/client-account": { 87 | "version": "4.23.3", 88 | "resolved": "https://registry.npmjs.org/@algolia/client-account/-/client-account-4.23.3.tgz", 89 | "integrity": "sha512-hpa6S5d7iQmretHHF40QGq6hz0anWEHGlULcTIT9tbUssWUriN9AUXIFQ8Ei4w9azD0hc1rUok9/DeQQobhQMA==", 90 | "dev": true, 91 | "dependencies": { 92 | "@algolia/client-common": "4.23.3", 93 | "@algolia/client-search": "4.23.3", 94 | "@algolia/transporter": "4.23.3" 95 | } 96 | }, 97 | "node_modules/@algolia/client-analytics": { 98 | "version": "4.23.3", 99 | "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-4.23.3.tgz", 100 | "integrity": "sha512-LBsEARGS9cj8VkTAVEZphjxTjMVCci+zIIiRhpFun9jGDUlS1XmhCW7CTrnaWeIuCQS/2iPyRqSy1nXPjcBLRA==", 101 | "dev": true, 102 | "dependencies": { 103 | "@algolia/client-common": "4.23.3", 104 | "@algolia/client-search": "4.23.3", 105 | "@algolia/requester-common": "4.23.3", 106 | "@algolia/transporter": "4.23.3" 107 | } 108 | }, 109 | "node_modules/@algolia/client-common": { 110 | "version": "4.23.3", 111 | "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.23.3.tgz", 112 | "integrity": "sha512-l6EiPxdAlg8CYhroqS5ybfIczsGUIAC47slLPOMDeKSVXYG1n0qGiz4RjAHLw2aD0xzh2EXZ7aRguPfz7UKDKw==", 113 | "dev": true, 114 | "dependencies": { 115 | "@algolia/requester-common": "4.23.3", 116 | "@algolia/transporter": "4.23.3" 117 | } 118 | }, 119 | "node_modules/@algolia/client-personalization": { 120 | "version": "4.23.3", 121 | "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-4.23.3.tgz", 122 | "integrity": "sha512-3E3yF3Ocr1tB/xOZiuC3doHQBQ2zu2MPTYZ0d4lpfWads2WTKG7ZzmGnsHmm63RflvDeLK/UVx7j2b3QuwKQ2g==", 123 | "dev": true, 124 | "dependencies": { 125 | "@algolia/client-common": "4.23.3", 126 | "@algolia/requester-common": "4.23.3", 127 | "@algolia/transporter": "4.23.3" 128 | } 129 | }, 130 | "node_modules/@algolia/client-search": { 131 | "version": "4.23.3", 132 | "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-4.23.3.tgz", 133 | "integrity": "sha512-P4VAKFHqU0wx9O+q29Q8YVuaowaZ5EM77rxfmGnkHUJggh28useXQdopokgwMeYw2XUht49WX5RcTQ40rZIabw==", 134 | "dev": true, 135 | "dependencies": { 136 | "@algolia/client-common": "4.23.3", 137 | "@algolia/requester-common": "4.23.3", 138 | "@algolia/transporter": "4.23.3" 139 | } 140 | }, 141 | "node_modules/@algolia/logger-common": { 142 | "version": "4.23.3", 143 | "resolved": "https://registry.npmjs.org/@algolia/logger-common/-/logger-common-4.23.3.tgz", 144 | "integrity": "sha512-y9kBtmJwiZ9ZZ+1Ek66P0M68mHQzKRxkW5kAAXYN/rdzgDN0d2COsViEFufxJ0pb45K4FRcfC7+33YB4BLrZ+g==", 145 | "dev": true 146 | }, 147 | "node_modules/@algolia/logger-console": { 148 | "version": "4.23.3", 149 | "resolved": "https://registry.npmjs.org/@algolia/logger-console/-/logger-console-4.23.3.tgz", 150 | "integrity": "sha512-8xoiseoWDKuCVnWP8jHthgaeobDLolh00KJAdMe9XPrWPuf1by732jSpgy2BlsLTaT9m32pHI8CRfrOqQzHv3A==", 151 | "dev": true, 152 | "dependencies": { 153 | "@algolia/logger-common": "4.23.3" 154 | } 155 | }, 156 | "node_modules/@algolia/recommend": { 157 | "version": "4.23.3", 158 | "resolved": "https://registry.npmjs.org/@algolia/recommend/-/recommend-4.23.3.tgz", 159 | "integrity": "sha512-9fK4nXZF0bFkdcLBRDexsnGzVmu4TSYZqxdpgBW2tEyfuSSY54D4qSRkLmNkrrz4YFvdh2GM1gA8vSsnZPR73w==", 160 | "dev": true, 161 | "dependencies": { 162 | "@algolia/cache-browser-local-storage": "4.23.3", 163 | "@algolia/cache-common": "4.23.3", 164 | "@algolia/cache-in-memory": "4.23.3", 165 | "@algolia/client-common": "4.23.3", 166 | "@algolia/client-search": "4.23.3", 167 | "@algolia/logger-common": "4.23.3", 168 | "@algolia/logger-console": "4.23.3", 169 | "@algolia/requester-browser-xhr": "4.23.3", 170 | "@algolia/requester-common": "4.23.3", 171 | "@algolia/requester-node-http": "4.23.3", 172 | "@algolia/transporter": "4.23.3" 173 | } 174 | }, 175 | "node_modules/@algolia/requester-browser-xhr": { 176 | "version": "4.23.3", 177 | "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.23.3.tgz", 178 | "integrity": "sha512-jDWGIQ96BhXbmONAQsasIpTYWslyjkiGu0Quydjlowe+ciqySpiDUrJHERIRfELE5+wFc7hc1Q5hqjGoV7yghw==", 179 | "dev": true, 180 | "dependencies": { 181 | "@algolia/requester-common": "4.23.3" 182 | } 183 | }, 184 | "node_modules/@algolia/requester-common": { 185 | "version": "4.23.3", 186 | "resolved": "https://registry.npmjs.org/@algolia/requester-common/-/requester-common-4.23.3.tgz", 187 | "integrity": "sha512-xloIdr/bedtYEGcXCiF2muajyvRhwop4cMZo+K2qzNht0CMzlRkm8YsDdj5IaBhshqfgmBb3rTg4sL4/PpvLYw==", 188 | "dev": true 189 | }, 190 | "node_modules/@algolia/requester-node-http": { 191 | "version": "4.23.3", 192 | "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-4.23.3.tgz", 193 | "integrity": "sha512-zgu++8Uj03IWDEJM3fuNl34s746JnZOWn1Uz5taV1dFyJhVM/kTNw9Ik7YJWiUNHJQXcaD8IXD1eCb0nq/aByA==", 194 | "dev": true, 195 | "dependencies": { 196 | "@algolia/requester-common": "4.23.3" 197 | } 198 | }, 199 | "node_modules/@algolia/transporter": { 200 | "version": "4.23.3", 201 | "resolved": "https://registry.npmjs.org/@algolia/transporter/-/transporter-4.23.3.tgz", 202 | "integrity": "sha512-Wjl5gttqnf/gQKJA+dafnD0Y6Yw97yvfY8R9h0dQltX1GXTgNs1zWgvtWW0tHl1EgMdhAyw189uWiZMnL3QebQ==", 203 | "dev": true, 204 | "dependencies": { 205 | "@algolia/cache-common": "4.23.3", 206 | "@algolia/logger-common": "4.23.3", 207 | "@algolia/requester-common": "4.23.3" 208 | } 209 | }, 210 | "node_modules/@babel/parser": { 211 | "version": "7.24.6", 212 | "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.6.tgz", 213 | "integrity": "sha512-eNZXdfU35nJC2h24RznROuOpO94h6x8sg9ju0tT9biNtLZ2vuP8SduLqqV+/8+cebSLV9SJEAN5Z3zQbJG/M+Q==", 214 | "dev": true, 215 | "bin": { 216 | "parser": "bin/babel-parser.js" 217 | }, 218 | "engines": { 219 | "node": ">=6.0.0" 220 | } 221 | }, 222 | "node_modules/@docsearch/css": { 223 | "version": "3.6.0", 224 | "resolved": "https://registry.npmjs.org/@docsearch/css/-/css-3.6.0.tgz", 225 | "integrity": "sha512-+sbxb71sWre+PwDK7X2T8+bhS6clcVMLwBPznX45Qu6opJcgRjAp7gYSDzVFp187J+feSj5dNBN1mJoi6ckkUQ==", 226 | "dev": true 227 | }, 228 | "node_modules/@docsearch/js": { 229 | "version": "3.6.0", 230 | "resolved": "https://registry.npmjs.org/@docsearch/js/-/js-3.6.0.tgz", 231 | "integrity": "sha512-QujhqINEElrkIfKwyyyTfbsfMAYCkylInLYMRqHy7PHc8xTBQCow73tlo/Kc7oIwBrCLf0P3YhjlOeV4v8hevQ==", 232 | "dev": true, 233 | "dependencies": { 234 | "@docsearch/react": "3.6.0", 235 | "preact": "^10.0.0" 236 | } 237 | }, 238 | "node_modules/@docsearch/react": { 239 | "version": "3.6.0", 240 | "resolved": "https://registry.npmjs.org/@docsearch/react/-/react-3.6.0.tgz", 241 | "integrity": "sha512-HUFut4ztcVNmqy9gp/wxNbC7pTOHhgVVkHVGCACTuLhUKUhKAF9KYHJtMiLUJxEqiFLQiuri1fWF8zqwM/cu1w==", 242 | "dev": true, 243 | "dependencies": { 244 | "@algolia/autocomplete-core": "1.9.3", 245 | "@algolia/autocomplete-preset-algolia": "1.9.3", 246 | "@docsearch/css": "3.6.0", 247 | "algoliasearch": "^4.19.1" 248 | }, 249 | "peerDependencies": { 250 | "@types/react": ">= 16.8.0 < 19.0.0", 251 | "react": ">= 16.8.0 < 19.0.0", 252 | "react-dom": ">= 16.8.0 < 19.0.0", 253 | "search-insights": ">= 1 < 3" 254 | }, 255 | "peerDependenciesMeta": { 256 | "@types/react": { 257 | "optional": true 258 | }, 259 | "react": { 260 | "optional": true 261 | }, 262 | "react-dom": { 263 | "optional": true 264 | }, 265 | "search-insights": { 266 | "optional": true 267 | } 268 | } 269 | }, 270 | "node_modules/@esbuild/aix-ppc64": { 271 | "version": "0.20.2", 272 | "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz", 273 | "integrity": "sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==", 274 | "cpu": [ 275 | "ppc64" 276 | ], 277 | "dev": true, 278 | "optional": true, 279 | "os": [ 280 | "aix" 281 | ], 282 | "engines": { 283 | "node": ">=12" 284 | } 285 | }, 286 | "node_modules/@esbuild/android-arm": { 287 | "version": "0.20.2", 288 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.20.2.tgz", 289 | "integrity": "sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==", 290 | "cpu": [ 291 | "arm" 292 | ], 293 | "dev": true, 294 | "optional": true, 295 | "os": [ 296 | "android" 297 | ], 298 | "engines": { 299 | "node": ">=12" 300 | } 301 | }, 302 | "node_modules/@esbuild/android-arm64": { 303 | "version": "0.20.2", 304 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.20.2.tgz", 305 | "integrity": "sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==", 306 | "cpu": [ 307 | "arm64" 308 | ], 309 | "dev": true, 310 | "optional": true, 311 | "os": [ 312 | "android" 313 | ], 314 | "engines": { 315 | "node": ">=12" 316 | } 317 | }, 318 | "node_modules/@esbuild/android-x64": { 319 | "version": "0.20.2", 320 | "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.20.2.tgz", 321 | "integrity": "sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==", 322 | "cpu": [ 323 | "x64" 324 | ], 325 | "dev": true, 326 | "optional": true, 327 | "os": [ 328 | "android" 329 | ], 330 | "engines": { 331 | "node": ">=12" 332 | } 333 | }, 334 | "node_modules/@esbuild/darwin-arm64": { 335 | "version": "0.20.2", 336 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.20.2.tgz", 337 | "integrity": "sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==", 338 | "cpu": [ 339 | "arm64" 340 | ], 341 | "dev": true, 342 | "optional": true, 343 | "os": [ 344 | "darwin" 345 | ], 346 | "engines": { 347 | "node": ">=12" 348 | } 349 | }, 350 | "node_modules/@esbuild/darwin-x64": { 351 | "version": "0.20.2", 352 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.20.2.tgz", 353 | "integrity": "sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==", 354 | "cpu": [ 355 | "x64" 356 | ], 357 | "dev": true, 358 | "optional": true, 359 | "os": [ 360 | "darwin" 361 | ], 362 | "engines": { 363 | "node": ">=12" 364 | } 365 | }, 366 | "node_modules/@esbuild/freebsd-arm64": { 367 | "version": "0.20.2", 368 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.2.tgz", 369 | "integrity": "sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==", 370 | "cpu": [ 371 | "arm64" 372 | ], 373 | "dev": true, 374 | "optional": true, 375 | "os": [ 376 | "freebsd" 377 | ], 378 | "engines": { 379 | "node": ">=12" 380 | } 381 | }, 382 | "node_modules/@esbuild/freebsd-x64": { 383 | "version": "0.20.2", 384 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.20.2.tgz", 385 | "integrity": "sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==", 386 | "cpu": [ 387 | "x64" 388 | ], 389 | "dev": true, 390 | "optional": true, 391 | "os": [ 392 | "freebsd" 393 | ], 394 | "engines": { 395 | "node": ">=12" 396 | } 397 | }, 398 | "node_modules/@esbuild/linux-arm": { 399 | "version": "0.20.2", 400 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.20.2.tgz", 401 | "integrity": "sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==", 402 | "cpu": [ 403 | "arm" 404 | ], 405 | "dev": true, 406 | "optional": true, 407 | "os": [ 408 | "linux" 409 | ], 410 | "engines": { 411 | "node": ">=12" 412 | } 413 | }, 414 | "node_modules/@esbuild/linux-arm64": { 415 | "version": "0.20.2", 416 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.20.2.tgz", 417 | "integrity": "sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==", 418 | "cpu": [ 419 | "arm64" 420 | ], 421 | "dev": true, 422 | "optional": true, 423 | "os": [ 424 | "linux" 425 | ], 426 | "engines": { 427 | "node": ">=12" 428 | } 429 | }, 430 | "node_modules/@esbuild/linux-ia32": { 431 | "version": "0.20.2", 432 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.20.2.tgz", 433 | "integrity": "sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==", 434 | "cpu": [ 435 | "ia32" 436 | ], 437 | "dev": true, 438 | "optional": true, 439 | "os": [ 440 | "linux" 441 | ], 442 | "engines": { 443 | "node": ">=12" 444 | } 445 | }, 446 | "node_modules/@esbuild/linux-loong64": { 447 | "version": "0.20.2", 448 | "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.20.2.tgz", 449 | "integrity": "sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==", 450 | "cpu": [ 451 | "loong64" 452 | ], 453 | "dev": true, 454 | "optional": true, 455 | "os": [ 456 | "linux" 457 | ], 458 | "engines": { 459 | "node": ">=12" 460 | } 461 | }, 462 | "node_modules/@esbuild/linux-mips64el": { 463 | "version": "0.20.2", 464 | "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.20.2.tgz", 465 | "integrity": "sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==", 466 | "cpu": [ 467 | "mips64el" 468 | ], 469 | "dev": true, 470 | "optional": true, 471 | "os": [ 472 | "linux" 473 | ], 474 | "engines": { 475 | "node": ">=12" 476 | } 477 | }, 478 | "node_modules/@esbuild/linux-ppc64": { 479 | "version": "0.20.2", 480 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.20.2.tgz", 481 | "integrity": "sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==", 482 | "cpu": [ 483 | "ppc64" 484 | ], 485 | "dev": true, 486 | "optional": true, 487 | "os": [ 488 | "linux" 489 | ], 490 | "engines": { 491 | "node": ">=12" 492 | } 493 | }, 494 | "node_modules/@esbuild/linux-riscv64": { 495 | "version": "0.20.2", 496 | "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.20.2.tgz", 497 | "integrity": "sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==", 498 | "cpu": [ 499 | "riscv64" 500 | ], 501 | "dev": true, 502 | "optional": true, 503 | "os": [ 504 | "linux" 505 | ], 506 | "engines": { 507 | "node": ">=12" 508 | } 509 | }, 510 | "node_modules/@esbuild/linux-s390x": { 511 | "version": "0.20.2", 512 | "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.20.2.tgz", 513 | "integrity": "sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==", 514 | "cpu": [ 515 | "s390x" 516 | ], 517 | "dev": true, 518 | "optional": true, 519 | "os": [ 520 | "linux" 521 | ], 522 | "engines": { 523 | "node": ">=12" 524 | } 525 | }, 526 | "node_modules/@esbuild/linux-x64": { 527 | "version": "0.20.2", 528 | "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.20.2.tgz", 529 | "integrity": "sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==", 530 | "cpu": [ 531 | "x64" 532 | ], 533 | "dev": true, 534 | "optional": true, 535 | "os": [ 536 | "linux" 537 | ], 538 | "engines": { 539 | "node": ">=12" 540 | } 541 | }, 542 | "node_modules/@esbuild/netbsd-x64": { 543 | "version": "0.20.2", 544 | "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.20.2.tgz", 545 | "integrity": "sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==", 546 | "cpu": [ 547 | "x64" 548 | ], 549 | "dev": true, 550 | "optional": true, 551 | "os": [ 552 | "netbsd" 553 | ], 554 | "engines": { 555 | "node": ">=12" 556 | } 557 | }, 558 | "node_modules/@esbuild/openbsd-x64": { 559 | "version": "0.20.2", 560 | "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.20.2.tgz", 561 | "integrity": "sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==", 562 | "cpu": [ 563 | "x64" 564 | ], 565 | "dev": true, 566 | "optional": true, 567 | "os": [ 568 | "openbsd" 569 | ], 570 | "engines": { 571 | "node": ">=12" 572 | } 573 | }, 574 | "node_modules/@esbuild/sunos-x64": { 575 | "version": "0.20.2", 576 | "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.20.2.tgz", 577 | "integrity": "sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==", 578 | "cpu": [ 579 | "x64" 580 | ], 581 | "dev": true, 582 | "optional": true, 583 | "os": [ 584 | "sunos" 585 | ], 586 | "engines": { 587 | "node": ">=12" 588 | } 589 | }, 590 | "node_modules/@esbuild/win32-arm64": { 591 | "version": "0.20.2", 592 | "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.20.2.tgz", 593 | "integrity": "sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==", 594 | "cpu": [ 595 | "arm64" 596 | ], 597 | "dev": true, 598 | "optional": true, 599 | "os": [ 600 | "win32" 601 | ], 602 | "engines": { 603 | "node": ">=12" 604 | } 605 | }, 606 | "node_modules/@esbuild/win32-ia32": { 607 | "version": "0.20.2", 608 | "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.20.2.tgz", 609 | "integrity": "sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==", 610 | "cpu": [ 611 | "ia32" 612 | ], 613 | "dev": true, 614 | "optional": true, 615 | "os": [ 616 | "win32" 617 | ], 618 | "engines": { 619 | "node": ">=12" 620 | } 621 | }, 622 | "node_modules/@esbuild/win32-x64": { 623 | "version": "0.20.2", 624 | "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.20.2.tgz", 625 | "integrity": "sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==", 626 | "cpu": [ 627 | "x64" 628 | ], 629 | "dev": true, 630 | "optional": true, 631 | "os": [ 632 | "win32" 633 | ], 634 | "engines": { 635 | "node": ">=12" 636 | } 637 | }, 638 | "node_modules/@jridgewell/sourcemap-codec": { 639 | "version": "1.4.15", 640 | "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", 641 | "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", 642 | "dev": true 643 | }, 644 | "node_modules/@rollup/rollup-android-arm-eabi": { 645 | "version": "4.18.0", 646 | "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.18.0.tgz", 647 | "integrity": "sha512-Tya6xypR10giZV1XzxmH5wr25VcZSncG0pZIjfePT0OVBvqNEurzValetGNarVrGiq66EBVAFn15iYX4w6FKgQ==", 648 | "cpu": [ 649 | "arm" 650 | ], 651 | "dev": true, 652 | "optional": true, 653 | "os": [ 654 | "android" 655 | ] 656 | }, 657 | "node_modules/@rollup/rollup-android-arm64": { 658 | "version": "4.18.0", 659 | "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.18.0.tgz", 660 | "integrity": "sha512-avCea0RAP03lTsDhEyfy+hpfr85KfyTctMADqHVhLAF3MlIkq83CP8UfAHUssgXTYd+6er6PaAhx/QGv4L1EiA==", 661 | "cpu": [ 662 | "arm64" 663 | ], 664 | "dev": true, 665 | "optional": true, 666 | "os": [ 667 | "android" 668 | ] 669 | }, 670 | "node_modules/@rollup/rollup-darwin-arm64": { 671 | "version": "4.18.0", 672 | "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.18.0.tgz", 673 | "integrity": "sha512-IWfdwU7KDSm07Ty0PuA/W2JYoZ4iTj3TUQjkVsO/6U+4I1jN5lcR71ZEvRh52sDOERdnNhhHU57UITXz5jC1/w==", 674 | "cpu": [ 675 | "arm64" 676 | ], 677 | "dev": true, 678 | "optional": true, 679 | "os": [ 680 | "darwin" 681 | ] 682 | }, 683 | "node_modules/@rollup/rollup-darwin-x64": { 684 | "version": "4.18.0", 685 | "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.18.0.tgz", 686 | "integrity": "sha512-n2LMsUz7Ynu7DoQrSQkBf8iNrjOGyPLrdSg802vk6XT3FtsgX6JbE8IHRvposskFm9SNxzkLYGSq9QdpLYpRNA==", 687 | "cpu": [ 688 | "x64" 689 | ], 690 | "dev": true, 691 | "optional": true, 692 | "os": [ 693 | "darwin" 694 | ] 695 | }, 696 | "node_modules/@rollup/rollup-linux-arm-gnueabihf": { 697 | "version": "4.18.0", 698 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.18.0.tgz", 699 | "integrity": "sha512-C/zbRYRXFjWvz9Z4haRxcTdnkPt1BtCkz+7RtBSuNmKzMzp3ZxdM28Mpccn6pt28/UWUCTXa+b0Mx1k3g6NOMA==", 700 | "cpu": [ 701 | "arm" 702 | ], 703 | "dev": true, 704 | "optional": true, 705 | "os": [ 706 | "linux" 707 | ] 708 | }, 709 | "node_modules/@rollup/rollup-linux-arm-musleabihf": { 710 | "version": "4.18.0", 711 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.18.0.tgz", 712 | "integrity": "sha512-l3m9ewPgjQSXrUMHg93vt0hYCGnrMOcUpTz6FLtbwljo2HluS4zTXFy2571YQbisTnfTKPZ01u/ukJdQTLGh9A==", 713 | "cpu": [ 714 | "arm" 715 | ], 716 | "dev": true, 717 | "optional": true, 718 | "os": [ 719 | "linux" 720 | ] 721 | }, 722 | "node_modules/@rollup/rollup-linux-arm64-gnu": { 723 | "version": "4.18.0", 724 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.18.0.tgz", 725 | "integrity": "sha512-rJ5D47d8WD7J+7STKdCUAgmQk49xuFrRi9pZkWoRD1UeSMakbcepWXPF8ycChBoAqs1pb2wzvbY6Q33WmN2ftw==", 726 | "cpu": [ 727 | "arm64" 728 | ], 729 | "dev": true, 730 | "optional": true, 731 | "os": [ 732 | "linux" 733 | ] 734 | }, 735 | "node_modules/@rollup/rollup-linux-arm64-musl": { 736 | "version": "4.18.0", 737 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.18.0.tgz", 738 | "integrity": "sha512-be6Yx37b24ZwxQ+wOQXXLZqpq4jTckJhtGlWGZs68TgdKXJgw54lUUoFYrg6Zs/kjzAQwEwYbp8JxZVzZLRepQ==", 739 | "cpu": [ 740 | "arm64" 741 | ], 742 | "dev": true, 743 | "optional": true, 744 | "os": [ 745 | "linux" 746 | ] 747 | }, 748 | "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { 749 | "version": "4.18.0", 750 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.18.0.tgz", 751 | "integrity": "sha512-hNVMQK+qrA9Todu9+wqrXOHxFiD5YmdEi3paj6vP02Kx1hjd2LLYR2eaN7DsEshg09+9uzWi2W18MJDlG0cxJA==", 752 | "cpu": [ 753 | "ppc64" 754 | ], 755 | "dev": true, 756 | "optional": true, 757 | "os": [ 758 | "linux" 759 | ] 760 | }, 761 | "node_modules/@rollup/rollup-linux-riscv64-gnu": { 762 | "version": "4.18.0", 763 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.18.0.tgz", 764 | "integrity": "sha512-ROCM7i+m1NfdrsmvwSzoxp9HFtmKGHEqu5NNDiZWQtXLA8S5HBCkVvKAxJ8U+CVctHwV2Gb5VUaK7UAkzhDjlg==", 765 | "cpu": [ 766 | "riscv64" 767 | ], 768 | "dev": true, 769 | "optional": true, 770 | "os": [ 771 | "linux" 772 | ] 773 | }, 774 | "node_modules/@rollup/rollup-linux-s390x-gnu": { 775 | "version": "4.18.0", 776 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.18.0.tgz", 777 | "integrity": "sha512-0UyyRHyDN42QL+NbqevXIIUnKA47A+45WyasO+y2bGJ1mhQrfrtXUpTxCOrfxCR4esV3/RLYyucGVPiUsO8xjg==", 778 | "cpu": [ 779 | "s390x" 780 | ], 781 | "dev": true, 782 | "optional": true, 783 | "os": [ 784 | "linux" 785 | ] 786 | }, 787 | "node_modules/@rollup/rollup-linux-x64-gnu": { 788 | "version": "4.18.0", 789 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.18.0.tgz", 790 | "integrity": "sha512-xuglR2rBVHA5UsI8h8UbX4VJ470PtGCf5Vpswh7p2ukaqBGFTnsfzxUBetoWBWymHMxbIG0Cmx7Y9qDZzr648w==", 791 | "cpu": [ 792 | "x64" 793 | ], 794 | "dev": true, 795 | "optional": true, 796 | "os": [ 797 | "linux" 798 | ] 799 | }, 800 | "node_modules/@rollup/rollup-linux-x64-musl": { 801 | "version": "4.18.0", 802 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.18.0.tgz", 803 | "integrity": "sha512-LKaqQL9osY/ir2geuLVvRRs+utWUNilzdE90TpyoX0eNqPzWjRm14oMEE+YLve4k/NAqCdPkGYDaDF5Sw+xBfg==", 804 | "cpu": [ 805 | "x64" 806 | ], 807 | "dev": true, 808 | "optional": true, 809 | "os": [ 810 | "linux" 811 | ] 812 | }, 813 | "node_modules/@rollup/rollup-win32-arm64-msvc": { 814 | "version": "4.18.0", 815 | "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.18.0.tgz", 816 | "integrity": "sha512-7J6TkZQFGo9qBKH0pk2cEVSRhJbL6MtfWxth7Y5YmZs57Pi+4x6c2dStAUvaQkHQLnEQv1jzBUW43GvZW8OFqA==", 817 | "cpu": [ 818 | "arm64" 819 | ], 820 | "dev": true, 821 | "optional": true, 822 | "os": [ 823 | "win32" 824 | ] 825 | }, 826 | "node_modules/@rollup/rollup-win32-ia32-msvc": { 827 | "version": "4.18.0", 828 | "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.18.0.tgz", 829 | "integrity": "sha512-Txjh+IxBPbkUB9+SXZMpv+b/vnTEtFyfWZgJ6iyCmt2tdx0OF5WhFowLmnh8ENGNpfUlUZkdI//4IEmhwPieNg==", 830 | "cpu": [ 831 | "ia32" 832 | ], 833 | "dev": true, 834 | "optional": true, 835 | "os": [ 836 | "win32" 837 | ] 838 | }, 839 | "node_modules/@rollup/rollup-win32-x64-msvc": { 840 | "version": "4.18.0", 841 | "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.18.0.tgz", 842 | "integrity": "sha512-UOo5FdvOL0+eIVTgS4tIdbW+TtnBLWg1YBCcU2KWM7nuNwRz9bksDX1bekJJCpu25N1DVWaCwnT39dVQxzqS8g==", 843 | "cpu": [ 844 | "x64" 845 | ], 846 | "dev": true, 847 | "optional": true, 848 | "os": [ 849 | "win32" 850 | ] 851 | }, 852 | "node_modules/@shikijs/core": { 853 | "version": "1.6.1", 854 | "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-1.6.1.tgz", 855 | "integrity": "sha512-CqYyepN4SnBopaoXYwng4NO8riB5ask/LTCkhOFq+GNGtr2X+aKeD767eYdqYukeixEUvv4bXdyTYVaogj7KBw==", 856 | "dev": true 857 | }, 858 | "node_modules/@shikijs/transformers": { 859 | "version": "1.6.1", 860 | "resolved": "https://registry.npmjs.org/@shikijs/transformers/-/transformers-1.6.1.tgz", 861 | "integrity": "sha512-m/h2Dh99XWvTzHL8MUQmEnrB+/gxDljIfgDNR00Zg941KENqORx8Hi9sKpGYjCgXoEJKASZlEMQdPnkHj9/8aQ==", 862 | "dev": true, 863 | "dependencies": { 864 | "shiki": "1.6.1" 865 | } 866 | }, 867 | "node_modules/@types/estree": { 868 | "version": "1.0.5", 869 | "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", 870 | "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", 871 | "dev": true 872 | }, 873 | "node_modules/@types/linkify-it": { 874 | "version": "5.0.0", 875 | "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-5.0.0.tgz", 876 | "integrity": "sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==", 877 | "dev": true 878 | }, 879 | "node_modules/@types/markdown-it": { 880 | "version": "14.1.1", 881 | "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-14.1.1.tgz", 882 | "integrity": "sha512-4NpsnpYl2Gt1ljyBGrKMxFYAYvpqbnnkgP/i/g+NLpjEUa3obn1XJCur9YbEXKDAkaXqsR1LbDnGEJ0MmKFxfg==", 883 | "dev": true, 884 | "dependencies": { 885 | "@types/linkify-it": "^5", 886 | "@types/mdurl": "^2" 887 | } 888 | }, 889 | "node_modules/@types/mdurl": { 890 | "version": "2.0.0", 891 | "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-2.0.0.tgz", 892 | "integrity": "sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==", 893 | "dev": true 894 | }, 895 | "node_modules/@types/web-bluetooth": { 896 | "version": "0.0.20", 897 | "resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.20.tgz", 898 | "integrity": "sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow==", 899 | "dev": true 900 | }, 901 | "node_modules/@vitejs/plugin-vue": { 902 | "version": "5.0.5", 903 | "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-5.0.5.tgz", 904 | "integrity": "sha512-LOjm7XeIimLBZyzinBQ6OSm3UBCNVCpLkxGC0oWmm2YPzVZoxMsdvNVimLTBzpAnR9hl/yn1SHGuRfe6/Td9rQ==", 905 | "dev": true, 906 | "engines": { 907 | "node": "^18.0.0 || >=20.0.0" 908 | }, 909 | "peerDependencies": { 910 | "vite": "^5.0.0", 911 | "vue": "^3.2.25" 912 | } 913 | }, 914 | "node_modules/@vue/compiler-core": { 915 | "version": "3.4.27", 916 | "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.4.27.tgz", 917 | "integrity": "sha512-E+RyqY24KnyDXsCuQrI+mlcdW3ALND6U7Gqa/+bVwbcpcR3BRRIckFoz7Qyd4TTlnugtwuI7YgjbvsLmxb+yvg==", 918 | "dev": true, 919 | "dependencies": { 920 | "@babel/parser": "^7.24.4", 921 | "@vue/shared": "3.4.27", 922 | "entities": "^4.5.0", 923 | "estree-walker": "^2.0.2", 924 | "source-map-js": "^1.2.0" 925 | } 926 | }, 927 | "node_modules/@vue/compiler-dom": { 928 | "version": "3.4.27", 929 | "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.4.27.tgz", 930 | "integrity": "sha512-kUTvochG/oVgE1w5ViSr3KUBh9X7CWirebA3bezTbB5ZKBQZwR2Mwj9uoSKRMFcz4gSMzzLXBPD6KpCLb9nvWw==", 931 | "dev": true, 932 | "dependencies": { 933 | "@vue/compiler-core": "3.4.27", 934 | "@vue/shared": "3.4.27" 935 | } 936 | }, 937 | "node_modules/@vue/compiler-sfc": { 938 | "version": "3.4.27", 939 | "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.4.27.tgz", 940 | "integrity": "sha512-nDwntUEADssW8e0rrmE0+OrONwmRlegDA1pD6QhVeXxjIytV03yDqTey9SBDiALsvAd5U4ZrEKbMyVXhX6mCGA==", 941 | "dev": true, 942 | "dependencies": { 943 | "@babel/parser": "^7.24.4", 944 | "@vue/compiler-core": "3.4.27", 945 | "@vue/compiler-dom": "3.4.27", 946 | "@vue/compiler-ssr": "3.4.27", 947 | "@vue/shared": "3.4.27", 948 | "estree-walker": "^2.0.2", 949 | "magic-string": "^0.30.10", 950 | "postcss": "^8.4.38", 951 | "source-map-js": "^1.2.0" 952 | } 953 | }, 954 | "node_modules/@vue/compiler-ssr": { 955 | "version": "3.4.27", 956 | "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.4.27.tgz", 957 | "integrity": "sha512-CVRzSJIltzMG5FcidsW0jKNQnNRYC8bT21VegyMMtHmhW3UOI7knmUehzswXLrExDLE6lQCZdrhD4ogI7c+vuw==", 958 | "dev": true, 959 | "dependencies": { 960 | "@vue/compiler-dom": "3.4.27", 961 | "@vue/shared": "3.4.27" 962 | } 963 | }, 964 | "node_modules/@vue/devtools-api": { 965 | "version": "7.2.1", 966 | "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-7.2.1.tgz", 967 | "integrity": "sha512-6oNCtyFOrNdqm6GUkFujsCgFlpbsHLnZqq7edeM/+cxAbMyCWvsaCsIMUaz7AiluKLccCGEM8fhOsjaKgBvb7g==", 968 | "dev": true, 969 | "dependencies": { 970 | "@vue/devtools-kit": "^7.2.1" 971 | } 972 | }, 973 | "node_modules/@vue/devtools-kit": { 974 | "version": "7.2.1", 975 | "resolved": "https://registry.npmjs.org/@vue/devtools-kit/-/devtools-kit-7.2.1.tgz", 976 | "integrity": "sha512-Wak/fin1X0Q8LLIfCAHBrdaaB+R6IdpSXsDByPHbQ3BmkCP0/cIo/oEGp9i0U2+gEqD4L3V9RDjNf1S34DTzQQ==", 977 | "dev": true, 978 | "dependencies": { 979 | "@vue/devtools-shared": "^7.2.1", 980 | "hookable": "^5.5.3", 981 | "mitt": "^3.0.1", 982 | "perfect-debounce": "^1.0.0", 983 | "speakingurl": "^14.0.1" 984 | }, 985 | "peerDependencies": { 986 | "vue": "^3.0.0" 987 | } 988 | }, 989 | "node_modules/@vue/devtools-shared": { 990 | "version": "7.2.1", 991 | "resolved": "https://registry.npmjs.org/@vue/devtools-shared/-/devtools-shared-7.2.1.tgz", 992 | "integrity": "sha512-PCJF4UknJmOal68+X9XHyVeQ+idv0LFujkTOIW30+GaMJqwFVN9LkQKX4gLqn61KkGMdJTzQ1bt7EJag3TI6AA==", 993 | "dev": true, 994 | "dependencies": { 995 | "rfdc": "^1.3.1" 996 | } 997 | }, 998 | "node_modules/@vue/reactivity": { 999 | "version": "3.4.27", 1000 | "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.4.27.tgz", 1001 | "integrity": "sha512-kK0g4NknW6JX2yySLpsm2jlunZJl2/RJGZ0H9ddHdfBVHcNzxmQ0sS0b09ipmBoQpY8JM2KmUw+a6sO8Zo+zIA==", 1002 | "dev": true, 1003 | "dependencies": { 1004 | "@vue/shared": "3.4.27" 1005 | } 1006 | }, 1007 | "node_modules/@vue/runtime-core": { 1008 | "version": "3.4.27", 1009 | "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.4.27.tgz", 1010 | "integrity": "sha512-7aYA9GEbOOdviqVvcuweTLe5Za4qBZkUY7SvET6vE8kyypxVgaT1ixHLg4urtOlrApdgcdgHoTZCUuTGap/5WA==", 1011 | "dev": true, 1012 | "dependencies": { 1013 | "@vue/reactivity": "3.4.27", 1014 | "@vue/shared": "3.4.27" 1015 | } 1016 | }, 1017 | "node_modules/@vue/runtime-dom": { 1018 | "version": "3.4.27", 1019 | "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.4.27.tgz", 1020 | "integrity": "sha512-ScOmP70/3NPM+TW9hvVAz6VWWtZJqkbdf7w6ySsws+EsqtHvkhxaWLecrTorFxsawelM5Ys9FnDEMt6BPBDS0Q==", 1021 | "dev": true, 1022 | "dependencies": { 1023 | "@vue/runtime-core": "3.4.27", 1024 | "@vue/shared": "3.4.27", 1025 | "csstype": "^3.1.3" 1026 | } 1027 | }, 1028 | "node_modules/@vue/server-renderer": { 1029 | "version": "3.4.27", 1030 | "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.4.27.tgz", 1031 | "integrity": "sha512-dlAMEuvmeA3rJsOMJ2J1kXU7o7pOxgsNHVr9K8hB3ImIkSuBrIdy0vF66h8gf8Tuinf1TK3mPAz2+2sqyf3KzA==", 1032 | "dev": true, 1033 | "dependencies": { 1034 | "@vue/compiler-ssr": "3.4.27", 1035 | "@vue/shared": "3.4.27" 1036 | }, 1037 | "peerDependencies": { 1038 | "vue": "3.4.27" 1039 | } 1040 | }, 1041 | "node_modules/@vue/shared": { 1042 | "version": "3.4.27", 1043 | "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.27.tgz", 1044 | "integrity": "sha512-DL3NmY2OFlqmYYrzp39yi3LDkKxa5vZVwxWdQ3rG0ekuWscHraeIbnI8t+aZK7qhYqEqWKTUdijadunb9pnrgA==", 1045 | "dev": true 1046 | }, 1047 | "node_modules/@vueuse/core": { 1048 | "version": "10.10.0", 1049 | "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-10.10.0.tgz", 1050 | "integrity": "sha512-vexJ/YXYs2S42B783rI95lMt3GzEwkxzC8Hb0Ndpd8rD+p+Lk/Za4bd797Ym7yq4jXqdSyj3JLChunF/vyYjUw==", 1051 | "dev": true, 1052 | "dependencies": { 1053 | "@types/web-bluetooth": "^0.0.20", 1054 | "@vueuse/metadata": "10.10.0", 1055 | "@vueuse/shared": "10.10.0", 1056 | "vue-demi": ">=0.14.7" 1057 | }, 1058 | "funding": { 1059 | "url": "https://github.com/sponsors/antfu" 1060 | } 1061 | }, 1062 | "node_modules/@vueuse/core/node_modules/vue-demi": { 1063 | "version": "0.14.8", 1064 | "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.8.tgz", 1065 | "integrity": "sha512-Uuqnk9YE9SsWeReYqK2alDI5YzciATE0r2SkA6iMAtuXvNTMNACJLJEXNXaEy94ECuBe4Sk6RzRU80kjdbIo1Q==", 1066 | "dev": true, 1067 | "hasInstallScript": true, 1068 | "bin": { 1069 | "vue-demi-fix": "bin/vue-demi-fix.js", 1070 | "vue-demi-switch": "bin/vue-demi-switch.js" 1071 | }, 1072 | "engines": { 1073 | "node": ">=12" 1074 | }, 1075 | "funding": { 1076 | "url": "https://github.com/sponsors/antfu" 1077 | }, 1078 | "peerDependencies": { 1079 | "@vue/composition-api": "^1.0.0-rc.1", 1080 | "vue": "^3.0.0-0 || ^2.6.0" 1081 | }, 1082 | "peerDependenciesMeta": { 1083 | "@vue/composition-api": { 1084 | "optional": true 1085 | } 1086 | } 1087 | }, 1088 | "node_modules/@vueuse/integrations": { 1089 | "version": "10.10.0", 1090 | "resolved": "https://registry.npmjs.org/@vueuse/integrations/-/integrations-10.10.0.tgz", 1091 | "integrity": "sha512-vHGeK7X6mkdkpcm1eE9t3Cpm21pNVfZRwrjwwbrEs9XftnSgszF4831G2rei8Dt9cIYJIfFV+iyx/29muimJPQ==", 1092 | "dev": true, 1093 | "dependencies": { 1094 | "@vueuse/core": "10.10.0", 1095 | "@vueuse/shared": "10.10.0", 1096 | "vue-demi": ">=0.14.7" 1097 | }, 1098 | "funding": { 1099 | "url": "https://github.com/sponsors/antfu" 1100 | }, 1101 | "peerDependencies": { 1102 | "async-validator": "*", 1103 | "axios": "*", 1104 | "change-case": "*", 1105 | "drauu": "*", 1106 | "focus-trap": "*", 1107 | "fuse.js": "*", 1108 | "idb-keyval": "*", 1109 | "jwt-decode": "*", 1110 | "nprogress": "*", 1111 | "qrcode": "*", 1112 | "sortablejs": "*", 1113 | "universal-cookie": "*" 1114 | }, 1115 | "peerDependenciesMeta": { 1116 | "async-validator": { 1117 | "optional": true 1118 | }, 1119 | "axios": { 1120 | "optional": true 1121 | }, 1122 | "change-case": { 1123 | "optional": true 1124 | }, 1125 | "drauu": { 1126 | "optional": true 1127 | }, 1128 | "focus-trap": { 1129 | "optional": true 1130 | }, 1131 | "fuse.js": { 1132 | "optional": true 1133 | }, 1134 | "idb-keyval": { 1135 | "optional": true 1136 | }, 1137 | "jwt-decode": { 1138 | "optional": true 1139 | }, 1140 | "nprogress": { 1141 | "optional": true 1142 | }, 1143 | "qrcode": { 1144 | "optional": true 1145 | }, 1146 | "sortablejs": { 1147 | "optional": true 1148 | }, 1149 | "universal-cookie": { 1150 | "optional": true 1151 | } 1152 | } 1153 | }, 1154 | "node_modules/@vueuse/integrations/node_modules/vue-demi": { 1155 | "version": "0.14.8", 1156 | "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.8.tgz", 1157 | "integrity": "sha512-Uuqnk9YE9SsWeReYqK2alDI5YzciATE0r2SkA6iMAtuXvNTMNACJLJEXNXaEy94ECuBe4Sk6RzRU80kjdbIo1Q==", 1158 | "dev": true, 1159 | "hasInstallScript": true, 1160 | "bin": { 1161 | "vue-demi-fix": "bin/vue-demi-fix.js", 1162 | "vue-demi-switch": "bin/vue-demi-switch.js" 1163 | }, 1164 | "engines": { 1165 | "node": ">=12" 1166 | }, 1167 | "funding": { 1168 | "url": "https://github.com/sponsors/antfu" 1169 | }, 1170 | "peerDependencies": { 1171 | "@vue/composition-api": "^1.0.0-rc.1", 1172 | "vue": "^3.0.0-0 || ^2.6.0" 1173 | }, 1174 | "peerDependenciesMeta": { 1175 | "@vue/composition-api": { 1176 | "optional": true 1177 | } 1178 | } 1179 | }, 1180 | "node_modules/@vueuse/metadata": { 1181 | "version": "10.10.0", 1182 | "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-10.10.0.tgz", 1183 | "integrity": "sha512-UNAo2sTCAW5ge6OErPEHb5z7NEAg3XcO9Cj7OK45aZXfLLH1QkexDcZD77HBi5zvEiLOm1An+p/4b5K3Worpug==", 1184 | "dev": true, 1185 | "funding": { 1186 | "url": "https://github.com/sponsors/antfu" 1187 | } 1188 | }, 1189 | "node_modules/@vueuse/shared": { 1190 | "version": "10.10.0", 1191 | "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-10.10.0.tgz", 1192 | "integrity": "sha512-2aW33Ac0Uk0U+9yo3Ypg9s5KcR42cuehRWl7vnUHadQyFvCktseyxxEPBi1Eiq4D2yBGACOnqLZpx1eMc7g5Og==", 1193 | "dev": true, 1194 | "dependencies": { 1195 | "vue-demi": ">=0.14.7" 1196 | }, 1197 | "funding": { 1198 | "url": "https://github.com/sponsors/antfu" 1199 | } 1200 | }, 1201 | "node_modules/@vueuse/shared/node_modules/vue-demi": { 1202 | "version": "0.14.8", 1203 | "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.8.tgz", 1204 | "integrity": "sha512-Uuqnk9YE9SsWeReYqK2alDI5YzciATE0r2SkA6iMAtuXvNTMNACJLJEXNXaEy94ECuBe4Sk6RzRU80kjdbIo1Q==", 1205 | "dev": true, 1206 | "hasInstallScript": true, 1207 | "bin": { 1208 | "vue-demi-fix": "bin/vue-demi-fix.js", 1209 | "vue-demi-switch": "bin/vue-demi-switch.js" 1210 | }, 1211 | "engines": { 1212 | "node": ">=12" 1213 | }, 1214 | "funding": { 1215 | "url": "https://github.com/sponsors/antfu" 1216 | }, 1217 | "peerDependencies": { 1218 | "@vue/composition-api": "^1.0.0-rc.1", 1219 | "vue": "^3.0.0-0 || ^2.6.0" 1220 | }, 1221 | "peerDependenciesMeta": { 1222 | "@vue/composition-api": { 1223 | "optional": true 1224 | } 1225 | } 1226 | }, 1227 | "node_modules/algoliasearch": { 1228 | "version": "4.23.3", 1229 | "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-4.23.3.tgz", 1230 | "integrity": "sha512-Le/3YgNvjW9zxIQMRhUHuhiUjAlKY/zsdZpfq4dlLqg6mEm0nL6yk+7f2hDOtLpxsgE4jSzDmvHL7nXdBp5feg==", 1231 | "dev": true, 1232 | "dependencies": { 1233 | "@algolia/cache-browser-local-storage": "4.23.3", 1234 | "@algolia/cache-common": "4.23.3", 1235 | "@algolia/cache-in-memory": "4.23.3", 1236 | "@algolia/client-account": "4.23.3", 1237 | "@algolia/client-analytics": "4.23.3", 1238 | "@algolia/client-common": "4.23.3", 1239 | "@algolia/client-personalization": "4.23.3", 1240 | "@algolia/client-search": "4.23.3", 1241 | "@algolia/logger-common": "4.23.3", 1242 | "@algolia/logger-console": "4.23.3", 1243 | "@algolia/recommend": "4.23.3", 1244 | "@algolia/requester-browser-xhr": "4.23.3", 1245 | "@algolia/requester-common": "4.23.3", 1246 | "@algolia/requester-node-http": "4.23.3", 1247 | "@algolia/transporter": "4.23.3" 1248 | } 1249 | }, 1250 | "node_modules/csstype": { 1251 | "version": "3.1.3", 1252 | "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", 1253 | "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", 1254 | "dev": true 1255 | }, 1256 | "node_modules/entities": { 1257 | "version": "4.5.0", 1258 | "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", 1259 | "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", 1260 | "dev": true, 1261 | "engines": { 1262 | "node": ">=0.12" 1263 | }, 1264 | "funding": { 1265 | "url": "https://github.com/fb55/entities?sponsor=1" 1266 | } 1267 | }, 1268 | "node_modules/esbuild": { 1269 | "version": "0.20.2", 1270 | "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.2.tgz", 1271 | "integrity": "sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==", 1272 | "dev": true, 1273 | "hasInstallScript": true, 1274 | "bin": { 1275 | "esbuild": "bin/esbuild" 1276 | }, 1277 | "engines": { 1278 | "node": ">=12" 1279 | }, 1280 | "optionalDependencies": { 1281 | "@esbuild/aix-ppc64": "0.20.2", 1282 | "@esbuild/android-arm": "0.20.2", 1283 | "@esbuild/android-arm64": "0.20.2", 1284 | "@esbuild/android-x64": "0.20.2", 1285 | "@esbuild/darwin-arm64": "0.20.2", 1286 | "@esbuild/darwin-x64": "0.20.2", 1287 | "@esbuild/freebsd-arm64": "0.20.2", 1288 | "@esbuild/freebsd-x64": "0.20.2", 1289 | "@esbuild/linux-arm": "0.20.2", 1290 | "@esbuild/linux-arm64": "0.20.2", 1291 | "@esbuild/linux-ia32": "0.20.2", 1292 | "@esbuild/linux-loong64": "0.20.2", 1293 | "@esbuild/linux-mips64el": "0.20.2", 1294 | "@esbuild/linux-ppc64": "0.20.2", 1295 | "@esbuild/linux-riscv64": "0.20.2", 1296 | "@esbuild/linux-s390x": "0.20.2", 1297 | "@esbuild/linux-x64": "0.20.2", 1298 | "@esbuild/netbsd-x64": "0.20.2", 1299 | "@esbuild/openbsd-x64": "0.20.2", 1300 | "@esbuild/sunos-x64": "0.20.2", 1301 | "@esbuild/win32-arm64": "0.20.2", 1302 | "@esbuild/win32-ia32": "0.20.2", 1303 | "@esbuild/win32-x64": "0.20.2" 1304 | } 1305 | }, 1306 | "node_modules/estree-walker": { 1307 | "version": "2.0.2", 1308 | "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", 1309 | "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", 1310 | "dev": true 1311 | }, 1312 | "node_modules/focus-trap": { 1313 | "version": "7.5.4", 1314 | "resolved": "https://registry.npmjs.org/focus-trap/-/focus-trap-7.5.4.tgz", 1315 | "integrity": "sha512-N7kHdlgsO/v+iD/dMoJKtsSqs5Dz/dXZVebRgJw23LDk+jMi/974zyiOYDziY2JPp8xivq9BmUGwIJMiuSBi7w==", 1316 | "dev": true, 1317 | "dependencies": { 1318 | "tabbable": "^6.2.0" 1319 | } 1320 | }, 1321 | "node_modules/fsevents": { 1322 | "version": "2.3.3", 1323 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", 1324 | "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", 1325 | "dev": true, 1326 | "hasInstallScript": true, 1327 | "optional": true, 1328 | "os": [ 1329 | "darwin" 1330 | ], 1331 | "engines": { 1332 | "node": "^8.16.0 || ^10.6.0 || >=11.0.0" 1333 | } 1334 | }, 1335 | "node_modules/hookable": { 1336 | "version": "5.5.3", 1337 | "resolved": "https://registry.npmjs.org/hookable/-/hookable-5.5.3.tgz", 1338 | "integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==", 1339 | "dev": true 1340 | }, 1341 | "node_modules/magic-string": { 1342 | "version": "0.30.10", 1343 | "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.10.tgz", 1344 | "integrity": "sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==", 1345 | "dev": true, 1346 | "dependencies": { 1347 | "@jridgewell/sourcemap-codec": "^1.4.15" 1348 | } 1349 | }, 1350 | "node_modules/mark.js": { 1351 | "version": "8.11.1", 1352 | "resolved": "https://registry.npmjs.org/mark.js/-/mark.js-8.11.1.tgz", 1353 | "integrity": "sha512-1I+1qpDt4idfgLQG+BNWmrqku+7/2bi5nLf4YwF8y8zXvmfiTBY3PV3ZibfrjBueCByROpuBjLLFCajqkgYoLQ==", 1354 | "dev": true 1355 | }, 1356 | "node_modules/minisearch": { 1357 | "version": "6.3.0", 1358 | "resolved": "https://registry.npmjs.org/minisearch/-/minisearch-6.3.0.tgz", 1359 | "integrity": "sha512-ihFnidEeU8iXzcVHy74dhkxh/dn8Dc08ERl0xwoMMGqp4+LvRSCgicb+zGqWthVokQKvCSxITlh3P08OzdTYCQ==", 1360 | "dev": true 1361 | }, 1362 | "node_modules/mitt": { 1363 | "version": "3.0.1", 1364 | "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz", 1365 | "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==", 1366 | "dev": true 1367 | }, 1368 | "node_modules/nanoid": { 1369 | "version": "3.3.7", 1370 | "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", 1371 | "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", 1372 | "dev": true, 1373 | "funding": [ 1374 | { 1375 | "type": "github", 1376 | "url": "https://github.com/sponsors/ai" 1377 | } 1378 | ], 1379 | "bin": { 1380 | "nanoid": "bin/nanoid.cjs" 1381 | }, 1382 | "engines": { 1383 | "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" 1384 | } 1385 | }, 1386 | "node_modules/perfect-debounce": { 1387 | "version": "1.0.0", 1388 | "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-1.0.0.tgz", 1389 | "integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==", 1390 | "dev": true 1391 | }, 1392 | "node_modules/picocolors": { 1393 | "version": "1.0.1", 1394 | "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", 1395 | "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==", 1396 | "dev": true 1397 | }, 1398 | "node_modules/postcss": { 1399 | "version": "8.4.38", 1400 | "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz", 1401 | "integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==", 1402 | "dev": true, 1403 | "funding": [ 1404 | { 1405 | "type": "opencollective", 1406 | "url": "https://opencollective.com/postcss/" 1407 | }, 1408 | { 1409 | "type": "tidelift", 1410 | "url": "https://tidelift.com/funding/github/npm/postcss" 1411 | }, 1412 | { 1413 | "type": "github", 1414 | "url": "https://github.com/sponsors/ai" 1415 | } 1416 | ], 1417 | "dependencies": { 1418 | "nanoid": "^3.3.7", 1419 | "picocolors": "^1.0.0", 1420 | "source-map-js": "^1.2.0" 1421 | }, 1422 | "engines": { 1423 | "node": "^10 || ^12 || >=14" 1424 | } 1425 | }, 1426 | "node_modules/preact": { 1427 | "version": "10.22.0", 1428 | "resolved": "https://registry.npmjs.org/preact/-/preact-10.22.0.tgz", 1429 | "integrity": "sha512-RRurnSjJPj4rp5K6XoP45Ui33ncb7e4H7WiOHVpjbkvqvA3U+N8Z6Qbo0AE6leGYBV66n8EhEaFixvIu3SkxFw==", 1430 | "dev": true, 1431 | "funding": { 1432 | "type": "opencollective", 1433 | "url": "https://opencollective.com/preact" 1434 | } 1435 | }, 1436 | "node_modules/prettier": { 1437 | "version": "3.2.5", 1438 | "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.5.tgz", 1439 | "integrity": "sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==", 1440 | "dev": true, 1441 | "bin": { 1442 | "prettier": "bin/prettier.cjs" 1443 | }, 1444 | "engines": { 1445 | "node": ">=14" 1446 | }, 1447 | "funding": { 1448 | "url": "https://github.com/prettier/prettier?sponsor=1" 1449 | } 1450 | }, 1451 | "node_modules/rfdc": { 1452 | "version": "1.3.1", 1453 | "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.1.tgz", 1454 | "integrity": "sha512-r5a3l5HzYlIC68TpmYKlxWjmOP6wiPJ1vWv2HeLhNsRZMrCkxeqxiHlQ21oXmQ4F3SiryXBHhAD7JZqvOJjFmg==", 1455 | "dev": true 1456 | }, 1457 | "node_modules/rollup": { 1458 | "version": "4.18.0", 1459 | "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.18.0.tgz", 1460 | "integrity": "sha512-QmJz14PX3rzbJCN1SG4Xe/bAAX2a6NpCP8ab2vfu2GiUr8AQcr2nCV/oEO3yneFarB67zk8ShlIyWb2LGTb3Sg==", 1461 | "dev": true, 1462 | "dependencies": { 1463 | "@types/estree": "1.0.5" 1464 | }, 1465 | "bin": { 1466 | "rollup": "dist/bin/rollup" 1467 | }, 1468 | "engines": { 1469 | "node": ">=18.0.0", 1470 | "npm": ">=8.0.0" 1471 | }, 1472 | "optionalDependencies": { 1473 | "@rollup/rollup-android-arm-eabi": "4.18.0", 1474 | "@rollup/rollup-android-arm64": "4.18.0", 1475 | "@rollup/rollup-darwin-arm64": "4.18.0", 1476 | "@rollup/rollup-darwin-x64": "4.18.0", 1477 | "@rollup/rollup-linux-arm-gnueabihf": "4.18.0", 1478 | "@rollup/rollup-linux-arm-musleabihf": "4.18.0", 1479 | "@rollup/rollup-linux-arm64-gnu": "4.18.0", 1480 | "@rollup/rollup-linux-arm64-musl": "4.18.0", 1481 | "@rollup/rollup-linux-powerpc64le-gnu": "4.18.0", 1482 | "@rollup/rollup-linux-riscv64-gnu": "4.18.0", 1483 | "@rollup/rollup-linux-s390x-gnu": "4.18.0", 1484 | "@rollup/rollup-linux-x64-gnu": "4.18.0", 1485 | "@rollup/rollup-linux-x64-musl": "4.18.0", 1486 | "@rollup/rollup-win32-arm64-msvc": "4.18.0", 1487 | "@rollup/rollup-win32-ia32-msvc": "4.18.0", 1488 | "@rollup/rollup-win32-x64-msvc": "4.18.0", 1489 | "fsevents": "~2.3.2" 1490 | } 1491 | }, 1492 | "node_modules/search-insights": { 1493 | "version": "2.14.0", 1494 | "resolved": "https://registry.npmjs.org/search-insights/-/search-insights-2.14.0.tgz", 1495 | "integrity": "sha512-OLN6MsPMCghDOqlCtsIsYgtsC0pnwVTyT9Mu6A3ewOj1DxvzZF6COrn2g86E/c05xbktB0XN04m/t1Z+n+fTGw==", 1496 | "dev": true, 1497 | "peer": true 1498 | }, 1499 | "node_modules/shiki": { 1500 | "version": "1.6.1", 1501 | "resolved": "https://registry.npmjs.org/shiki/-/shiki-1.6.1.tgz", 1502 | "integrity": "sha512-1Pu/A1rtsG6HZvQm4W0NExQ45e02og+rPog7PDaFDiMumZgOYnZIu4JtGQeAIfMwdbKSjJQoCUr79vDLKUUxWA==", 1503 | "dev": true, 1504 | "dependencies": { 1505 | "@shikijs/core": "1.6.1" 1506 | } 1507 | }, 1508 | "node_modules/source-map-js": { 1509 | "version": "1.2.0", 1510 | "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", 1511 | "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", 1512 | "dev": true, 1513 | "engines": { 1514 | "node": ">=0.10.0" 1515 | } 1516 | }, 1517 | "node_modules/speakingurl": { 1518 | "version": "14.0.1", 1519 | "resolved": "https://registry.npmjs.org/speakingurl/-/speakingurl-14.0.1.tgz", 1520 | "integrity": "sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==", 1521 | "dev": true, 1522 | "engines": { 1523 | "node": ">=0.10.0" 1524 | } 1525 | }, 1526 | "node_modules/tabbable": { 1527 | "version": "6.2.0", 1528 | "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.2.0.tgz", 1529 | "integrity": "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==", 1530 | "dev": true 1531 | }, 1532 | "node_modules/vite": { 1533 | "version": "5.2.12", 1534 | "resolved": "https://registry.npmjs.org/vite/-/vite-5.2.12.tgz", 1535 | "integrity": "sha512-/gC8GxzxMK5ntBwb48pR32GGhENnjtY30G4A0jemunsBkiEZFw60s8InGpN8gkhHEkjnRK1aSAxeQgwvFhUHAA==", 1536 | "dev": true, 1537 | "dependencies": { 1538 | "esbuild": "^0.20.1", 1539 | "postcss": "^8.4.38", 1540 | "rollup": "^4.13.0" 1541 | }, 1542 | "bin": { 1543 | "vite": "bin/vite.js" 1544 | }, 1545 | "engines": { 1546 | "node": "^18.0.0 || >=20.0.0" 1547 | }, 1548 | "funding": { 1549 | "url": "https://github.com/vitejs/vite?sponsor=1" 1550 | }, 1551 | "optionalDependencies": { 1552 | "fsevents": "~2.3.3" 1553 | }, 1554 | "peerDependencies": { 1555 | "@types/node": "^18.0.0 || >=20.0.0", 1556 | "less": "*", 1557 | "lightningcss": "^1.21.0", 1558 | "sass": "*", 1559 | "stylus": "*", 1560 | "sugarss": "*", 1561 | "terser": "^5.4.0" 1562 | }, 1563 | "peerDependenciesMeta": { 1564 | "@types/node": { 1565 | "optional": true 1566 | }, 1567 | "less": { 1568 | "optional": true 1569 | }, 1570 | "lightningcss": { 1571 | "optional": true 1572 | }, 1573 | "sass": { 1574 | "optional": true 1575 | }, 1576 | "stylus": { 1577 | "optional": true 1578 | }, 1579 | "sugarss": { 1580 | "optional": true 1581 | }, 1582 | "terser": { 1583 | "optional": true 1584 | } 1585 | } 1586 | }, 1587 | "node_modules/vitepress": { 1588 | "version": "1.2.2", 1589 | "resolved": "https://registry.npmjs.org/vitepress/-/vitepress-1.2.2.tgz", 1590 | "integrity": "sha512-uZ3nXR5NY4nYj3RJWCo5jev9qlNZAQo5SUXu1U0QSUx84cUm/o7hCTDVjZ4njVSVui+PsV1oAbdQOg8ygbaf4w==", 1591 | "dev": true, 1592 | "dependencies": { 1593 | "@docsearch/css": "^3.6.0", 1594 | "@docsearch/js": "^3.6.0", 1595 | "@shikijs/core": "^1.5.2", 1596 | "@shikijs/transformers": "^1.5.2", 1597 | "@types/markdown-it": "^14.1.1", 1598 | "@vitejs/plugin-vue": "^5.0.4", 1599 | "@vue/devtools-api": "^7.2.0", 1600 | "@vue/shared": "^3.4.27", 1601 | "@vueuse/core": "^10.9.0", 1602 | "@vueuse/integrations": "^10.9.0", 1603 | "focus-trap": "^7.5.4", 1604 | "mark.js": "8.11.1", 1605 | "minisearch": "^6.3.0", 1606 | "shiki": "^1.5.2", 1607 | "vite": "^5.2.11", 1608 | "vue": "^3.4.27" 1609 | }, 1610 | "bin": { 1611 | "vitepress": "bin/vitepress.js" 1612 | }, 1613 | "peerDependencies": { 1614 | "markdown-it-mathjax3": "^4", 1615 | "postcss": "^8" 1616 | }, 1617 | "peerDependenciesMeta": { 1618 | "markdown-it-mathjax3": { 1619 | "optional": true 1620 | }, 1621 | "postcss": { 1622 | "optional": true 1623 | } 1624 | } 1625 | }, 1626 | "node_modules/vue": { 1627 | "version": "3.4.27", 1628 | "resolved": "https://registry.npmjs.org/vue/-/vue-3.4.27.tgz", 1629 | "integrity": "sha512-8s/56uK6r01r1icG/aEOHqyMVxd1bkYcSe9j8HcKtr/xTOFWvnzIVTehNW+5Yt89f+DLBe4A569pnZLS5HzAMA==", 1630 | "dev": true, 1631 | "dependencies": { 1632 | "@vue/compiler-dom": "3.4.27", 1633 | "@vue/compiler-sfc": "3.4.27", 1634 | "@vue/runtime-dom": "3.4.27", 1635 | "@vue/server-renderer": "3.4.27", 1636 | "@vue/shared": "3.4.27" 1637 | }, 1638 | "peerDependencies": { 1639 | "typescript": "*" 1640 | }, 1641 | "peerDependenciesMeta": { 1642 | "typescript": { 1643 | "optional": true 1644 | } 1645 | } 1646 | } 1647 | } 1648 | } 1649 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@weserv/docs", 3 | "version": "0.2.0", 4 | "description": "Documentation for wsrv.nl", 5 | "homepage": "https://github.com/weserv/docs#readme", 6 | "bugs": { 7 | "url": "https://github.com/weserv/images/issues" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/weserv/docs.git" 12 | }, 13 | "license": "MIT", 14 | "author": "Kleis Auke Wolthuizen", 15 | "type": "module", 16 | "scripts": { 17 | "postinstall": "cd .vitepress/theme && npm install", 18 | "build": "vitepress build", 19 | "dev": "vitepress", 20 | "preview": "vitepress preview", 21 | "lint": "prettier --check --write ." 22 | }, 23 | "devDependencies": { 24 | "prettier": "^3.2.5", 25 | "vitepress": "^1.2.2" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /public/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weserv/docs/d02db3950e85675a04417f215e6d0f9789d66292/public/android-chrome-192x192.png -------------------------------------------------------------------------------- /public/android-chrome-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weserv/docs/d02db3950e85675a04417f215e6d0f9789d66292/public/android-chrome-512x512.png -------------------------------------------------------------------------------- /public/api-resize-fit-dark.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | cover 41 | 42 | 43 | 44 | contain 45 | 46 | 47 | 48 | fill 49 | 50 | 51 | 52 | 53 | inside 54 | 55 | 56 | 57 | 58 | outside 59 | 60 | 61 | -------------------------------------------------------------------------------- /public/api-resize-fit.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | cover 41 | 42 | 43 | 44 | contain 45 | 46 | 47 | 48 | fill 49 | 50 | 51 | 52 | 53 | inside 54 | 55 | 56 | 57 | 58 | outside 59 | 60 | 61 | -------------------------------------------------------------------------------- /public/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weserv/docs/d02db3950e85675a04417f215e6d0f9789d66292/public/apple-touch-icon.png -------------------------------------------------------------------------------- /public/banana.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weserv/docs/d02db3950e85675a04417f215e6d0f9789d66292/public/banana.webp -------------------------------------------------------------------------------- /public/browserconfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | #a72376 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /public/cloudflare-logo-dark.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /public/cloudflare-logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /public/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weserv/docs/d02db3950e85675a04417f215e6d0f9789d66292/public/favicon-16x16.png -------------------------------------------------------------------------------- /public/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weserv/docs/d02db3950e85675a04417f215e6d0f9789d66292/public/favicon-32x32.png -------------------------------------------------------------------------------- /public/favicon-48x48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weserv/docs/d02db3950e85675a04417f215e6d0f9789d66292/public/favicon-48x48.png -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weserv/docs/d02db3950e85675a04417f215e6d0f9789d66292/public/favicon.ico -------------------------------------------------------------------------------- /public/humans.txt: -------------------------------------------------------------------------------- 1 | ############################################# 2 | ############################################# 3 | #### #### 4 | #### #### #### 5 | #### ###### #### 6 | #### ###### #### 7 | #### # #### #### 8 | #### ##### #### 9 | #### ######### ## #### 10 | #### ############# ###### #### 11 | #### ####### ####### ########## #### 12 | ########### ##################### #### 13 | ######### ########## ########### 14 | ####### ####### ######### 15 | ##### ####### ####### 16 | #### ####### ##### 17 | ############################################# 18 | ############################################# 19 | 20 | /* ABOUT THIS FILE */ 21 | Description: We Are People, Not Machines 22 | More information: https://humanstxt.org/ 23 | 24 | /* TEAM */ 25 | Administrator: Andries Louw Wolthuizen 26 | Contact: admin [at] weserv.nl 27 | From: Sneek, Friesland, Netherlands 28 | 29 | Developer: Kleis Auke Wolthuizen 30 | Contact: info [at] kleisauke.nl 31 | From: Sneek, Friesland, Netherlands 32 | 33 | /* THANKS */ 34 | Contributors: 35 | https://github.com/weserv/images/contributors 36 | 37 | /* SITE */ 38 | Language: English 39 | Coded with: C / C++ 40 | Software: nginx, libvips, Redis 41 | Services: Cloudflare, OpenDNS 42 | 43 | /* SECURITY */ 44 | Information: 45 | https://wsrv.nl/security.txt 46 | 47 | /* BUGS */ 48 | Found a bug? Open a new issue on GitHub: 49 | https://github.com/weserv/images/issues 50 | -------------------------------------------------------------------------------- /public/lichtenstein.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weserv/docs/d02db3950e85675a04417f215e6d0f9789d66292/public/lichtenstein.jpg -------------------------------------------------------------------------------- /public/logo-dark.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /public/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /public/made-in-sneek.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /public/mstile-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weserv/docs/d02db3950e85675a04417f215e6d0f9789d66292/public/mstile-144x144.png -------------------------------------------------------------------------------- /public/mstile-150x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weserv/docs/d02db3950e85675a04417f215e6d0f9789d66292/public/mstile-150x150.png -------------------------------------------------------------------------------- /public/mstile-310x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weserv/docs/d02db3950e85675a04417f215e6d0f9789d66292/public/mstile-310x150.png -------------------------------------------------------------------------------- /public/mstile-310x310.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weserv/docs/d02db3950e85675a04417f215e6d0f9789d66292/public/mstile-310x310.png -------------------------------------------------------------------------------- /public/mstile-70x70.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weserv/docs/d02db3950e85675a04417f215e6d0f9789d66292/public/mstile-70x70.png -------------------------------------------------------------------------------- /public/placeholder.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /public/puppy.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weserv/docs/d02db3950e85675a04417f215e6d0f9789d66292/public/puppy.jpg -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: /*?* 3 | Allow: /$ 4 | -------------------------------------------------------------------------------- /public/safari-pinned-tab.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /public/security.txt: -------------------------------------------------------------------------------- 1 | # If you would like to report a security issue 2 | # you may report it privately by email. 3 | Contact: mailto:admin@weserv.nl 4 | Preferred-Languages: en, nl 5 | Canonical: https://wsrv.nl/security.txt 6 | -------------------------------------------------------------------------------- /public/site.webmanifest: -------------------------------------------------------------------------------- 1 | { 2 | "name": "", 3 | "short_name": "", 4 | "icons": [ 5 | { 6 | "src": "/android-chrome-192x192.png", 7 | "sizes": "192x192", 8 | "type": "image/png" 9 | }, 10 | { 11 | "src": "/android-chrome-512x512.png", 12 | "sizes": "512x512", 13 | "type": "image/png" 14 | } 15 | ], 16 | "theme_color": "#ffffff", 17 | "background_color": "#ffffff", 18 | "display": "standalone" 19 | } 20 | -------------------------------------------------------------------------------- /public/transparency_demo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weserv/docs/d02db3950e85675a04417f215e6d0f9789d66292/public/transparency_demo.png -------------------------------------------------------------------------------- /public/zebra.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weserv/docs/d02db3950e85675a04417f215e6d0f9789d66292/public/zebra.jpg --------------------------------------------------------------------------------