jonaskruckenberg / imagetools Goto Github PK
View Code? Open in Web Editor NEWLoad and transform images using a toolbox :toolbox: of custom import directives!
License: MIT License
Load and transform images using a toolbox :toolbox: of custom import directives!
License: MIT License
Hey so I've tried the next branch today and whilst I was trying to find the easiest and least painful way of importing a directory full of images in different sizes and formats.
There are 2 issues:
build
doesn't generate any images at alldev
generates only the last imported image and uses it as src in all other images (but other data such as width or height are correct)Here is the repo with the issue: https://github.com/YamiteruXYZ/imagetools-workbench
BTW I'm gonna use this repo to experiment with imagetools and it might be a source of some demos or starters.
This library is great! Thanks so much for providing it!
One small idea - it might be helpful to include the mimetype in the output. It's something all users will need to add in order to use <picture>
tag. While I can build a map between formats and mimetypes, it seems potentially useful to include here so that each user doesn't have to rebuild that map
I am trying to use vite-imagetools with React and Typescript. Image imports with query params in them are marked as unknown imports. I understand why it is the case, my question is, do you know of any good solution to deal with this apart from manually typing all my assets?
I find myself wanting to resize images to multiple different sizes and formats for responsive and lazy loaded images, but always want to keep the same aspect ratio.
Ideally I could do something like this:
./assets/awesome-image.jpg?width=300;600;900&height=169;338;506
and imagetools would magically know I want that to be three 16:9 images. Not surprisingly, I actually get back 9 images with all permutations of widths and heights.
It'd be nice if we could specify either an aspect ratio and either width or height along the lines of
./assets/awesome-image.jpg?width=300;600;900&aspect=1.77777777
There is a workaround here so this is more of a convenience request than anything else. I can just split this out into three separate imports each specifying exactly one width and height.
Hey, another one from me ;)
I discovered a serious bug that actually completely breaks the source set generation. If you generate multiple images by chaining multiple widths together (e.g. import srcsetAvif from '../example.jpg?w=500;700;900;1200&avif&srcset'
, as per your example), it actually only applies the last width on every image in the whole set!
To reproduce:
cd
into examples/vite-simple
main.js
and add ridiculously low widths as the last params:// ...
import srcsetAvif from '../example.jpg?w=500;700;900;1200;20&avif&srcset'
import srcsetWebp from '../example.jpg?w=500;700;900;1200;20&webp&srcset'
// ...
yarn && yarn dev
e78e253f7e1877238273f8472026215d31af4221
(you guessed it: it's only 20px wide ๐)/@imagetools/e78e253f7e1877238273f8472026215d31af4221 1200w,
. The one with 20px has an entirely different ID.So, even though the 20px wide image was not selected by the browser, it still only received a 20px wide one. It looks like it's always the last argument that decides the size of all the images in the set. All of the metadata is still generated according to the parameters. Each URL is just pointing to an image the size of the last parameter.
Currently, imagetools-core
0.1.0-next.8 uses ||=
which is only available in Node 15.
This makes vite-imagetools
unusable below Node 15 (can you even shim a Vite plugin with Babel?)
C:\Users\GrygrFlzr\Documents\projects\sk-64b\node_modules\.pnpm\imagetools-core@0.1.0-next.8\node_modules\imagetools-core\dist\index.cjs:30
blur ||= config.blur === 'true';
^^^
SyntaxError: Unexpected token '||='
at wrapSafe (internal/modules/cjs/loader.js:979:16)
at Module._compile (internal/modules/cjs/loader.js:1027:27)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1092:10)
at Module.load (internal/modules/cjs/loader.js:928:32)
at Function.Module._load (internal/modules/cjs/loader.js:769:14)
at Module.require (internal/modules/cjs/loader.js:952:19)
at require (internal/modules/cjs/helpers.js:88:18)
at Object.<anonymous> (C:\Users\GrygrFlzr\Documents\projects\sk-64b\node_modules\.pnpm\[email protected]\node_modules\vite-imagetools\dist\index.cjs:3:22)
at Module._compile (internal/modules/cjs/loader.js:1063:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1092:10)
Tested on:
Currently, we can't import inlined images using the ?inline
suffix. But it's a necessary feature to have and also the current behavior is breaking a native functionality. So, I think it should be implemented.
Will it be possible in the v3 to use import("./image.jpg?width=100")
?
Why would this be useful? Let's say I create imageLoader function like this:
const imageLoader = (sizes: number[]) => {
return (src: string) => {
const res = {};
sizes.forEach((size: number) =>
res[size] = import(`${src}?width=${size}`)
);
return res;
};
};
I then use it to create image loader with predefined widths like this:
const img = imageLoader([100, 200, 300]);
Then when I need to import images anywhere in my app I do it like this:
{
main: img("./main.jpg"),
other: [
img("./01.jpg"),
img("./02.jpg"),
img("./03.jpg")
]
}
The value of the main
prop would be something along the lines of this:
{
aspectRatio: 0.6,
original: "./main.jpg",
variants: {
jpg: {
100: "cache/main.jpg?width=100",
200: "cache/main.jpg?width=200",
300: "cache/main.jpg?width=300"
}
}
}
I could then use it in JSX like this:
return (
<div>
<div style={`height:0;padding-bottom:${image.main.aspectRatio*100}%;`} />
<img src={image.main.variants.jpg[parentWidth]} />
</div>
);
Thanks to tree-shaking the resulting code would be minimal.
All of this is not possible using normal imports like:
import main from "/image.jpg?width=100";
Here is my package.json:
{
"scripts": {
"dev": "vite",
"build": "vite build",
"serve": "vite preview"
},
"devDependencies": {
"vite": "^2.0.5",
"vite-plugin-solid": "^1.3.0",
"vite-imagetools": "^3.0.1"
},
"dependencies": {
"sass": "^1.32.8",
"solid-app-router": "^0.0.34",
"solid-js": "^0.24.13",
"solid-meta": "^0.24.13",
"solid-styled-components": "^0.24.13"
}
}
I import an image like this:
import { width } from "./images/main.jpg?webp";
I'm getting this error in console:
Uncaught (in promise) SyntaxError: The requested module '/data/portfolio/work-01/images/main.jpg?import&webp' does not provide an export named 'width'
I really love the idea of this plugin and I'm planning on heavily using it in production. I have a few feature requests:
import { width, height, src } from "./image.jpg?format=webp&width=1000";
Thanks to this we could create rectangles with exact aspect ratio of the images so the page wouldn't jump as the images load. This would be extremely useful.
{
input: ["jpg", "jpeg"],
output: ["jpg", "webp"],
quality: 80,
sizes: [500, 1000, 2000, 4000],
include: "./images"
}
This would take a folder from include
, look for images from input
and generate different sizes
in different formats from output
in a given quality
. This is useful when image loading is dynamic (eg. dependant on user device resolution and format support).
I know this could be achieved by a library like gulp or webpack, but it would be nice to have it all in one vite plugin.
I ran this:
sudo apt install git-lfs
yarn install
yarn build
yarn test
I got:
Test Suites: 14 failed, 11 passed, 25 total
Tests: 71 failed, 173 passed, 244 total
They were all failing with the message Input file contains unsupported image format
Is there some step I might be missing?
It'd be awesome if we could leverage glob import to for example import all images in a directory AND apply transformations on all of them.
I image it'd be used just like this:
const images = import.meta.glob("./images/*.jpg?width=200;400&format=webp;jpg&meta");
The exported object might look like this:
{
"./images/01.jpg": {
"width=200&format=webp&meta": () => Promise<metadata>,
"width=200&format=jpg&meta": () => Promise<metadata>,
"width=400&format=webp&meta": () => Promise<metadata>,
"width=400&format=jpg&meta": () => Promise<metadata>
}
}
If we use globEager
instead of glob
we would get the metadata
object instead of () => Promise<metadata>
.
As the title, e.g. I need to extend transforms:
const extendTransforms = (builtins) => {
const getBase64 = async (image) => {
const img = image.resize({ width: 10 });
const buf = await img.toBuffer();
const mt = await img.metadata();
return `data:image/${mt.format};base64,${buf.toString("base64")}`;
};
function base64(config, ctx) {
if (config.width != "10") return;
return async (image) => {
setMetadata(image, "base64", await getBase64(image));
return image;
};
}
return [base64, ...builtins];
};
imagetools({ extendTransforms })
I'm using vite-imagetools
version 4.0.3
with SvelteKit.
This code...
const { default: srcset } = await import(`./${slug}/cover.jpg?width=1344;672;336&srcset`);
...works as expected in dev mode, but build fails with error:
Error: Unknown variable dynamic import: ./article1/cover.jpg?width=1344;672;336&srcset
at file:///Users/arggh/Develop/testapp/.svelte-kit/output/server/entries/pages/index.svelte.js:15:96
at new Promise (<anonymous>)
at __variableDynamicImportRuntime1__ (file:///Users/arggh/Develop/testapp/.svelte-kit/output/server/entries/pages/index.svelte.js:14:14)
...
If I remove the query string from my import statement the build doesn't fail, but obviously any transformations don't take place.
Rollup, Vite, and SvelteKit all use pnpm. It would be easier to test changes to this library in conjunction with those if it used pnpm as well. Is that something you might be open to?
Starting from a fresh svelte kit skeleton project (npm init svelte@next
) and only installing vite-imagetools I edited:
svelte.cfg.js:
import adapter from '@sveltejs/adapter-auto';
import preprocess from 'svelte-preprocess';
import { imagetools } from 'vite-imagetools';
/** @type {import('@sveltejs/kit').Config} */
const config = {
// Consult https://github.com/sveltejs/svelte-preprocess
// for more information about preprocessors
preprocess: preprocess(),
kit: {
adapter: adapter()
},
vite: {
plugins: [imagetools()]
}
};
export default config;
and src/routes/index.svelte:
<script>
import Image from '../../static/test.jpg?w=400';
console.log(Image);
</script>
<h1>Welcome to SvelteKit</h1>
<p>Visit <a href="https://kit.svelte.dev">kit.svelte.dev</a> to read the documentation</p>
<img src="{Image.src}">
This won't show any image. In fact Image.src is undefined since Image is strangely just a string (/static/test.jpg?w=400). If I set just Image to the src attribute the original image is shown without any transformations (i.e. the width is not 400).
What am I doing wrong here?
I just tried the experimental srcset
option
For my example, it created one large srcset
:
/@imagetools/af1896684ba60c3fa5b12a0609e28b3fce179657 1440w, /@imagetools/d9f7937f7986fa94eac8fbdcd50acb2ec8db14a2 1440w, /@imagetools/0f418c158ad24a2c7a101f8847a727731a0c1b55 1440w, /@imagetools/c6ee3dba26e4ad983a4ae2ea2a69076492153ffc 800w, /@imagetools/84620b40939e5c4ca0a61b4724c29a8ee2057f95 800w, /@imagetools/91bce48b94bc945a6df13919b8ec4b7ed8521c17 800w
But really what I need is something much more complex:
<picture class="s-Ou-fLRYjMacr">
<source type="image/avif" srcset="/@imagetools/425c37d1844269144a629fd6607654a047acb328 2x, /@imagetools/0ac134d9b8e160cc8352e48344071d15855e0868 1x" class="s-Ou-fLRYjMacr">
<source type="image/webp" srcset="/@imagetools/9b27e371177bb36997e6b36e9d0ebee369889fa6 2x, /@imagetools/ddc6d76b452971e6f9b5ac6e5f921b04c2b8b54d 1x" class="s-Ou-fLRYjMacr">
<source type="image/png" srcset="/@imagetools/2e89026d6e552fae215d9952d95d67ff974960fa 2x, /@imagetools/ef93de319f4f4f4ad4f7b555ab260d4ffd31d7c4 1x" class="s-Ou-fLRYjMacr">
<img src="/@imagetools/2e89026d6e552fae215d9952d95d67ff974960fa" alt="SvelteKit illustration" class="s-Ou-fLRYjMacr">
</picture>
A couple things would be helpful here:
type
attribute (always return jpeg
instead of sometimes jpg
and sometimes jpeg
)We could fallback to the largest image of the user-provided type.
If the srcset
could be generated that would be great as well. Ideally it could include the 1x
/2x
for retina screens as well as the resolution switching based on screen width. This is the hardest one for me to understand what the API should look like as I don't have a ton of understanding of responsive images. It may be interesting to see what Next does here: https://github.com/vercel/next.js/blob/bd82f690e5a2adebdf715e0e4406c1f29e93ff6a/packages/next/client/image.tsx#L288. Also, for further reading: https://ericportis.com/posts/2014/srcset-sizes
On the Svelte side, we'd need the ability to create a <picture>
tag and possibly the ability to create a <source>
tag (for art direction). Maybe also the ability to create an <image>
tag for users who use a CDN.
How do I use 'import' with typescript?
Hello ๐
My collaborator and I are trying to use vite-imagetools to transition a project from the Gatsby ecosystem. We weren't able to use a meta
format directive from within the defaultDirectives
override, as the actual import's parameters are checked for output formats.
I assume allowing this would be as simple as changing srcURL.searchParams.has(key)
to directives.has(key)
here:
imagetools/packages/vite/src/index.ts
Lines 97 to 106 in 58eabc9
Is there a reason this isn't permitted, or is this an oversight? Thanks for any info!
(And, before you ask, yes, I can think of ways in which our use of defaultDirectives in some cases rubs up against the spirit of some of the comments in #160, but we aren't able to make use of query parameters with dynamic import vars without hacking the rollup plugin, and I feel fine using defaultDirectives in this spot.)
Hi @JonasKruckenberg ,
I'm trying the plugin with a basic Vite + Svelte setup, scaffolded with @vite/create-app.
Thank you for your work, it's wonderful and it works well.
I encountered this issue using the metadata directive.
With this code:
import {src, width, height} from "$assets/images/usgs-AQ9-jKmebjM-unsplash.jpg?width=375&meta";
I get this error in console:
Uncaught SyntaxError: The requested module '/src/assets/images/usgs-AQ9-jKmebjM-unsplash.jpg?import&width=375&meta' does not provide an export named 'height'
Nonetheless, if I import as a single module the image:
import Meta from "$assets/images/usgs-AQ9-jKmebjM-unsplash.jpg?width=375&meta";
I get the correct metadata object.
//console.log(Meta);
{ "format": "jpeg", "width": 375, "height": 375, "channels": 3, "premultiplied": false, "size": 49715, "src": "node_modules/.cache/vite-imagetools/tmp/47fa4256/usgs-AQ9-jKmebjM-unsplash.jpeg" }
It's not a big deal, but it's something worth knowing, or maybe you have any hint about it.
I'm using the plugin with the force option as true, and the silent option as false.
โ๏ธ
I'm trying to use vite-imagetools
in a SvelteKit project, but am having difficulty because the background of my images is turning to black
Compare to the live version: https://c3.ventures/
I've created a repo to reproduce this issue: https://github.com/benmccann/vite-imagetools-bug
Run npm install
followed by npm run dev
The entry point is src/routes/index.svelte
it looks like webp is not one of the supported formats in the spec. Is this intentional (if so, curious why?), or just an accidental omission?
https://github.com/JonasKruckenberg/imagetools/blob/main/docs/spec.md?plain=1#L154
I encountered errors that sharp not accepted width/height number such like 10.475xxxx. I think this two lines should use Math.round
too:
https://github.com/JonasKruckenberg/imagetools/blob/main/packages/core/src/transforms/resize.ts#L82
https://github.com/JonasKruckenberg/imagetools/blob/main/packages/core/src/transforms/resize.ts#L87
(I intended to contribute but has no time to write tests, sorry).
Hi, disclaimer: I am new to vite.
All the examples / docs I could find are using something like: import Img from 'some/local/path'
.
In many real-world projects, assets are actually fetched from somewhere remote. Is it possible to use vite-imagetools for remote images e.g. fetched from an API when the actual source is a url over https?
Should something like vite-plugin-remote-assets be used for that?
Hi
Anyone knows if there is a way to call imagetools transformation directly from the html?
Like <img src="./image.jpg?width=300;500;700&format=webp;avif;png" />
cheers
So, gotz me an image, like so, imported into a svelte component from an aliased relative path:
import image from '$images/arrow-event-factory-1920x1200.jpg?width=480'
...which I then use in the page, like so:
<img src={image} alt='A fun event'/>
...and it works fine like that. Image is resized and displayed properly.
BUT!
...when I add another width for a second image to be generated and potentially served, like this:
import image from '$images/arrow-event-factory-1920x1200.jpg?width=480;960'
...it does not work anymore and I get the following vite error:
[vite] Internal server error: Cannot read property 'Symbol(image metadata)' of undefined
at Object.getMetadata (/Users/rchrdnsh/Code/Svelte/Arrow-kit/node_modules/imagetools-core/dist/index.cjs:18:23)
at /Users/rchrdnsh/Code/Svelte/Arrow-kit/node_modules/vite-imagetools/dist/index.cjs:87:75
at call (/Users/rchrdnsh/Code/Svelte/Arrow-kit/node_modules/vite/dist/node/chunks/dep-5c642f9e.js:49389:7)
at next (/Users/rchrdnsh/Code/Svelte/Arrow-kit/node_modules/vite/dist/node/chunks/dep-5c642f9e.js:49333:5)
at Function.handle (/Users/rchrdnsh/Code/Svelte/Arrow-kit/node_modules/vite/dist/node/chunks/dep-5c642f9e.js:49336:3)
at Object.app [as middlewares] (/Users/rchrdnsh/Code/Svelte/Arrow-kit/node_modules/vite/dist/node/chunks/dep-5c642f9e.js:49201:37)
at Server.<anonymous> (file:///Users/rchrdnsh/Code/Svelte/Arrow-kit/node_modules/@sveltejs/kit/dist/chunks/index.js:3276:14)
at Server.emit (node:events:378:20)
at Server.EventEmitter.emit (node:domain:470:12)
at parserOnIncoming (node:_http_server:933:12) (x2)
...do you think I am doing something wrong in the code? Do you think it's something wrong with svelte and sveltekit? Do you think it's a vite issue? or maybe a bug in imagetools? I dunno where to start myself, but maybe you have a thought as to qhat might be going on?
Thanks!
Hey @JonasKruckenberg,
thanks for the great project! Probably like most people, I want to use this plugin to create a bunch of differently sized images that are later served as an image with a srcset
tag. Because I don't want to specify all of the breakpoints individually for each image, I found out that there's the defaultDirectives
setting in the Vite plugin options. So the idea is to store a variable containing all of the breakpoints, which is then picked up by the Vite config and automatically applied to every imported image.
However, the setting doesn't seem to support more than one value for each property at a time -- I tried passing the string exactly like you would in an import statement (width=3840;2560;1920
etc.), but the plugin only seems to accept the first number it gets. The exact config I used looks like this:
plugins: [
imagetools({
defaultDirectives: { width: imageWidths.join(";"), format: 'webp' },
}),
],
Is there any way to solve this? I also thought about using dynamic import statements, but I never really got them to work properly. I really like your project, but the design decision to make everything a directive you have to spell out for each individual import makes it quite hard to outsource a common configuration.
Your help would be appreciated :)
After finally figuring out how to upload multiple images from a folder, I wanted to implement your Image-tools.
How I multi-upload is
const gallery = ref([{}])
const modules = import.meta.glob('../assets/**/*.jpg')
for (const path in modules) {
modules[path]().then(() => {
const p = new URL(p2, import.meta.url)
gallery.value.push(p)
})
}
The problem is, I can't manage to add a query parameter anywhere to use your tool.
I have tried on the back of glob:
import.meta.glob('../assets/**/*.jpg?<Search params>')
or onto the path on new URL, but it either will break the search, or just append the image src without actually changing anything.
First off this library is really great, thanks for creating it! ๐
I would like to be able to create a "presets" that returns an object with a predefined shape. For example in a blog every cover image would be the same so a single import that returned the following would be great:
const obj = {
sources: [
{
source: "example-700.webp 500w, example-700.webp 700w, example-900.webp 900w, example-1200.webp 1200w",
type: "image/webp",
},
{
source:"example-700.avif 500w, example-700.avif 700w, example-900.avif 900w, example-1200.avif 1200w",
type: "image/avif",
},
],
base64Placeholder: "data:image/svg+xml;base64,<long string here>",
};
I could use it like this (svelte syntax)
<script lang="ts">
import {
sources,
base64Placeholder,
} from "./cover.png?img-tools-preset=cover-image";
</script>
<picture>
{#each sources as { srcset, type }}
<source {srcset} {type} />
{/each}
<img src={base64Placeholder} alt="logo" />
</picture>
Since the shape will always be the same for each preset then we can type them:
declare module "*?img-tools-preset=cover-image" {
export const sources: { srcset: string; type: string }[];
export const base64TraceSVG: string;
export default { sources, base64TraceSVG };
}
Is it possible to do this with custom directive already?
I import image like this:
import imageUrl from "./01.jpg?webp";
I run the app in dev mode via vite
.
When I log the imageUrl
I see:
/Users/yamiteru/dev/yamiteru.xyz/data/portfolio/12345sestak/01.jpg
instead of something like this:
/assets/01.c74cd79a.webp
Having full functionality in dev mode is crucial since building and serving takes too much time for creating fast iterations of design/development. Moreover the absolute path returned in the current version in dev mode doesn't even load the original image.
I'm using vite-imagetools
.
Here's a JS output file from my site: https://c3.ventures/_app/pages/index.svelte-77e56e84.js
I imported a file like this:
import Ben from '$img/ben-mccann-cf.jpg?format=avif;webp;jpg&meta';
And then it ends up in the JS as a very large object due to a sizable icc
property
{format:"webp",width:450,height:450,space:"srgb",channels:3,depth:"uchar",density:300,chromaSubsampling:"4:4:4",isProgressive:!0,hasProfile:!0,hasAlpha:!1,orientation:1,icc:{"0":0,"1":0,"2":12,"3":72,"4":76,"5":105,"6":110,"7":111,"8":2,"9":16,"10":0,"11":0,"12":109,"13":110,"14":116,"15":114,"16":82,"17":71,"18":66,"19":32,"20":88,"21":89,"22":90,"23":32,"24":7,"25":206,"26":0,"27":2,"28":0,"29":9,"30":0,"31":6,"32":0,"33":49,"34":0,"35":0,"36":97,"37":99,"38":115,"39":112,"40":77,"41":83,"42":70,"43":84,"44":0,"45":0,"46":0,"47":0,"48":73,"49":69,"50":67,"51":32,"52":115,"53":82,"54":71,"55":66,"56":0,"57":0,"58":0,"59":0,"60":0,"61":0,"62":0,"63":0,"64":0,"65":0,"66":0,"67":0,"68":0,"69":0,"70":246,"71":214,"72":0,"73":1,"74":0,"75":0,"76":0,"77":0,"78":211,"79":45,"80":72,"81":80,"82":32,"83":32,"84":0,"85":0,"86":0,"87":0,"88":0,"89":0,"90":0,"91":0,"92":0,"93":0,"94":0,"95":0,"96":0,"97":0,"98":0,"99":0,"100":0,"101":0,"102":0,"103":0,"104":0,"105":0,"106":0,"107":0,"108":0,"109":0,"110":0,"111":0,"112":0,"113":0,"114":0,"115":0,"116":0,"117":0,"118":0,"119":0,"120":0,"121":0,"122":0,"123":0,"124":0,"125":0,"126":0,"127":0,"128":0,"129":0,"130":0,"131":17,"132":99,"133":112,"134":114,"135":116,"136":0,"137":0,"138":1,"139":80,"140":0,"141":0,"142":0,"143":51,"144":100,"145":101,"146":115,"147":99,"148":0,"149":0,"150":1,"151":132,"152":0,"153":0,"154":0,"155":108,"156":119,"157":116,"158":112,"159":116,"160":0,"161":0,"162":1,"163":240,"164":0,"165":0,"166":0,"167":20,"168":98,"169":107,"170":112,"171":116,"172":0,"173":0,"174":2,"175":4,"176":0,"177":0,"178":0,"179":20,"180":114,"181":88,"182":89,"183":90,"184":0,"185":0,"186":2,"187":24,"188":0,"189":0,"190":0,"191":20,"192":103,"193":88,"194":89,"195":90,"196":0,"197":0,"198":2,"199":44,"200":0,"201":0,"202":0,"203":20,"204":98,"205":88,"206":89,"207":90,"208":0,"209":0,"210":2,"211":64,"212":0,"213":0,"214":0,"215":20,"216":100,"217":109,"218":110,"219":100,"220":0,"221":0,"222":2,"223":84,"224":0,"225":0,"226":0,"227":112,"228":100,"229":109,"230":100,"231":100,"232":0,"233":0,"234":2,"235":196,"236":0,"237":0,"238":0,"239":136,"240":118,"241":117,"242":101,"243":100,"244":0,"245":0,"246":3,"247":76,"248":0,"249":0,"250":0,"251":134,"252":118,"253":105,"254":101,"255":119,"256":0,"257":0,"258":3,"259":212,"260":0,"261":0,"262":0,"263":36,"264":108,"265":117,"266":109,"267":105,"268":0,"269":0,"270":3,"271":248,"272":0,"273":0,"274":0,"275":20,"276":109,"277":101,"278":97,"279":115,"280":0,"281":0,"282":4,"283":12,"284":0,"285":0,"286":0,"287":36,"288":116,"289":101,"290":99,"291":104,"292":0,"293":0,"294":4,"295":48,"296":0,"297":0,"298":0,"299":12,"300":114,"301":84,"302":82,"303":67,"304":0,"305":0,"306":4,"307":60,"308":0,"309":0,"310":8,"311":12,"312":103,"313":84,"314":82,"315":67,"316":0,"317":0,"318":4,"319":60,"320":0,"321":0,"322":8,"323":12,"324":98,"325":84,"326":82,"327":67,"328":0,"329":0,"330":4,"331":60,"332":0,"333":0,"334":8,"335":12,"336":116,"337":101,"338":120,"339":116,"340":0,"341":0,"342":0,"343":0,"344":67,"345":111,"346":112,"347":121,"348":114,"349":105,"350":103,"351":104,"352":116,"353":32,"354":40,"355":99,"356":41,"357":32,"358":49,"359":57,"360":57,"361":56,"362":32,"363":72,"364":101,"365":119,"366":108,"367":101,"368":116,"369":116,"370":45,"371":80,"372":97,"373":99,"374":107,"375":97,"376":114,"377":100,"378":32,"379":67,"380":111,"381":109,"382":112,"383":97,"384":110,"385":121,"386":0,"387":0,"388":100,"389":101,"390":115,"391":99,"392":0,"393":0,"394":0,"395":0,"396":0,"397":0,"398":0,"399":18,"400":115,"401":82,"402":71,"403":66,"404":32,"405":73,"406":69,"407":67,"408":54,"409":49,"410":57,"411":54,"412":54,"413":45,"414":50,"415":46,"416":49,"417":0,"418":0,"419":0,"420":0,"421":0,"422":0,"423":0,"424":0,"425":0,"426":0,"427":0,"428":18,"429":115,"430":82,"431":71,"432":66,"433":32,"434":73,"435":69,"436":67,"437":54,"438":49,"439":57,"440":54,"441":54,"442":45,"443":50,"444":46,"445":49,"446":0,"447":0,"448":0,"449":0,"450":0,"451":0,"452":0,"453":0,"454":0,"455":0,"456":0,"457":0,"458":0,"459":0,"460":0,"461":0,"462":0,"463":0,"464":0,"465":0,"466":0,"467":0,"468":0,"469":0,"470":0,"471":0,"472":0,"473":0,"474":0,"475":0,"476":0,"477":0,"478":0,"479":0,"480":0,"481":0,"482":0,"483":0,"484":0,"485":0,"486":0,"487":0,"488":0,"489":0,"490":0,"491":0,"492":0,"493":0,"494":0,"495":0,"496":88,"497":89,"498":90,"499":32,"500":0,"501":0,"502":0,"503":0,"504":0,"505":0,"506":243,"507":81,"508":0,"509":1,"510":0,"511":0,"512":0,"513":1,"514":22,"515":204,"516":88,"517":89,"518":90,"519":32,"520":0,"521":0,"522":0,"523":0,"524":0,"525":0,"526":0,"527":0,"528":0,"529":0,"530":0,"531":0,"532":0,"533":0,"534":0,"535":0,"536":88,"537":89,"538":90,"539":32,"540":0,"541":0,"542":0,"543":0,"544":0,"545":0,"546":111,"547":162,"548":0,"549":0,"550":56,"551":245,"552":0,"553":0,"554":3,"555":144,"556":88,"557":89,"558":90,"559":32,"560":0,"561":0,"562":0,"563":0,"564":0,"565":0,"566":98,"567":153,"568":0,"569":0,"570":183,"571":133,"572":0,"573":0,"574":24,"575":218,"576":88,"577":89,"578":90,"579":32,"580":0,"581":0,"582":0,"583":0,"584":0,"585":0,"586":36,"587":160,"588":0,"589":0,"590":15,"591":132,"592":0,"593":0,"594":182,"595":207,"596":100,"597":101,"598":115,"599":99,"600":0,"601":0,"602":0,"603":0,"604":0,"605":0,"606":0,"607":22,"608":73,"609":69,"610":67,"611":32,"612":104,"613":116,"614":116,"615":112,"616":58,"617":47,"618":47,"619":119,"620":119,"621":119,"622":46,"623":105,"624":101,"625":99,"626":46,"627":99,"628":104,"629":0,"630":0,"631":0,"632":0,"633":0,"634":0,"635":0,"636":0,"637":0,"638":0,"639":0,"640":22,"641":73,"642":69,"643":67,"644":32,"645":104,"646":116,"647":116,"648":112,"649":58,"650":47,"651":47,"652":119,"653":119,"654":119,"655":46,"656":105,"657":101,"658":99,"659":46,"660":99,"661":104,"662":0,"663":0,"664":0,"665":0,"666":0,"667":0,"668":0,"669":0,"670":0,"671":0,"672":0,"673":0,"674":0,"675":0,"676":0,"677":0,"678":0,"679":0,"680":0,"681":0,"682":0,"683":0,"684":0,"685":0,"686":0,"687":0,"688":0,"689":0,"690":0,"691":0,"692":0,"693":0,"694":0,"695":0,"696":0,"697":0,"698":0,"699":0,"700":0,"701":0,"702":0,"703":0,"704":0,"705":0,"706":0,"707":0,"708":100,"709":101,"710":115,"711":99,"712":0,"713":0,"714":0,"715":0,"716":0,"717":0,"718":0,"719":46,"720":73,"721":69,"722":67,"723":32,"724":54,"725":49,"726":57,"727":54,"728":54,"729":45,"730":50,"731":46,"732":49,"733":32,"734":68,"735":101,"736":102,"737":97,"738":117,"739":108,"740":116,"741":32,"742":82,"743":71,"744":66,"745":32,"746":99,"747":111,"748":108,"749":111,"750":117,"751":114,"752":32,"753":115,"754":112,"755":97,"756":99,"757":101,"758":32,"759":45,"760":32,"761":115,"762":82,"763":71,"764":66,"765":0,"766":0,"767":0,"768":0,"769":0,"770":0,"771":0,"772":0,"773":0,"774":0,"775":0,"776":46,"777":73,"778":69,"779":67,"780":32,"781":54,"782":49,"783":57,"784":54,"785":54,"786":45,"787":50,"788":46,"789":49,"790":32,"791":68,"792":101,"793":102,"794":97,"795":117,"796":108,"797":116,"798":32,"799":82,"800":71,"801":66,"802":32,"803":99,"804":111,"805":108,"806":111,"807":117,"808":114,"809":32,"810":115,"811":112,"812":97,"813":99,"814":101,"815":32,"816":45,"817":32,"818":115,"819":82,"820":71,"821":66,"822":0,"823":0,"824":0,"825":0,"826":0,"827":0,"828":0,"829":0,"830":0,"831":0,"832":0,"833":0,"834":0,"835":0,"836":0,"837":0,"838":0,"839":0,"840":0,"841":0,"842":0,"843":0,"844":100,"845":101,"846":115,"847":99,"848":0,"849":0,"850":0,"851":0,"852":0,"853":0,"854":0,"855":44,"856":82,"857":101,"858":102,"859":101,"860":114,"861":101,"862":110,"863":99,"864":101,"865":32,"866":86,"867":105,"868":101,"869":119,"870":105,"871":110,"872":103,"873":32,"874":67,"875":111,"876":110,"877":100,"878":105,"879":116,"880":105,"881":111,"882":110,"883":32,"884":105,"885":110,"886":32,"887":73,"888":69,"889":67,"890":54,"891":49,"892":57,"893":54,"894":54,"895":45,"896":50,"897":46,"898":49,"899":0,"900":0,"901":0,"902":0,"903":0,"904":0,"905":0,"906":0,"907":0,"908":0,"909":0,"910":44,"911":82,"912":101,"913":102,"914":101,"915":114,"916":101,"917":110,"918":99,"919":101,"920":32,"921":86,"922":105,"923":101,"924":119,"925":105,"926":110,"927":103,"928":32,"929":67,"930":111,"931":110,"932":100,"933":105,"934":116,"935":105,"936":111,"937":110,"938":32,"939":105,"940":110,"941":32,"942":73,"943":69,"944":67,"945":54,"946":49,"947":57,"948":54,"949":54,"950":45,"951":50,"952":46,"953":49,"954":0,"955":0,"956":0,"957":0,"958":0,"959":0,"960":0,"961":0,"962":0,"963":0,"964":0,"965":0,"966":0,"967":0,"968":0,"969":0,"970":0,"971":0,"972":0,"973":0,"974":0,"975":0,"976":0,"977":0,"978":0,"979":0,"980":118,"981":105,"982":101,"983":119,"984":0,"985":0,"986":0,"987":0,"988":0,"989":19,"990":164,"991":254,"992":0,"993":20,"994":95,"995":46,"996":0,"997":16,"998":207,"999":20,"1000":0,"1001":3,"1002":237,"1003":204,"1004":0,"1005":4,"1006":19,"1007":11,"1008":0,"1009":3,"1010":92,"1011":158,"1012":0,"1013":0,"1014":0,"1015":1,"1016":88,"1017":89,"1018":90,"1019":32,"1020":0,"1021":0,"1022":0,"1023":0,"1024":0,"1025":76,"1026":9,"1027":86,"1028":0,"1029":80,"1030":0,"1031":0,"1032":0,"1033":87,"1034":31,"1035":231,"1036":109,"1037":101,"1038":97,"1039":115,"1040":0,"1041":0,"1042":0,"1043":0,"1044":0,"1045":0,"1046":0,"1047":1,"1048":0,"1049":0,"1050":0,"1051":0,"1052":0,"1053":0,"1054":0,"1055":0,"1056":0,"1057":0,"1058":0,"1059":0,"1060":0,"1061":0,"1062":0,"1063":0,"1064":0,"1065":0,"1066":2,"1067":143,"1068":0,"1069":0,"1070":0,"1071":2,"1072":115,"1073":105,"1074":103,"1075":32,"1076":0,"1077":0,"1078":0,"1079":0,"1080":67,"1081":82,"1082":84,"1083":32,"1084":99,"1085":117,"1086":114,"1087":118,"1088":0,"1089":0,"1090":0,"1091":0,"1092":0,"1093":0,"1094":4,"1095":0,"1096":0,"1097":0,"1098":0,"1099":5,"1100":0,"1101":10,"1102":0,"1103":15,"1104":0,"1105":20,"1106":0,"1107":25,"1108":0,"1109":30,"1110":0,"1111":35,"1112":0,"1113":40,"1114":0,"1115":45,"1116":0,"1117":50,"1118":0,"1119":55,"1120":0,"1121":59,"1122":0,"1123":64,"1124":0,"1125":69,"1126":0,"1127":74,"1128":0,"1129":79,"1130":0,"1131":84,"1132":0,"1133":89,"1134":0,"1135":94,"1136":0,"1137":99,"1138":0,"1139":104,"1140":0,"1141":109,"1142":0,"1143":114,"1144":0,"1145":119,"1146":0,"1147":124,"1148":0,"1149":129,"1150":0,"1151":134,"1152":0,"1153":139,"1154":0,"1155":144,"1156":0,"1157":149,"1158":0,"1159":154,"1160":0,"1161":159,"1162":0,"1163":164,"1164":0,"1165":169,"1166":0,"1167":174,"1168":0,"1169":178,"1170":0,"1171":183,"1172":0,"1173":188,"1174":0,"1175":193,"1176":0,"1177":198,"1178":0,"1179":203,"1180":0,"1181":208,"1182":0,"1183":213,"1184":0,"1185":219,"1186":0,"1187":224,"1188":0,"1189":229,"1190":0,"1191":235,"1192":0,"1193":240,"1194":0,"1195":246,"1196":0,"1197":251,"1198":1,"1199":1,"1200":1,"1201":7,"1202":1,"1203":13,"1204":1,"1205":19,"1206":1,"1207":25,"1208":1,"1209":31,"1210":1,"1211":37,"1212":1,"1213":43,"1214":1,"1215":50,"1216":1,"1217":56,"1218":1,"1219":62,"1220":1,"1221":69,"1222":1,"1223":76,"1224":1,"1225":82,"1226":1,"1227":89,"1228":1,"1229":96,"1230":1,"1231":103,"1232":1,"1233":110,"1234":1,"1235":117,"1236":1,"1237":124,"1238":1,"1239":131,"1240":1,"1241":139,"1242":1,"1243":146,"1244":1,"1245":154,"1246":1,"1247":161,"1248":1,"1249":169,"1250":1,"1251":177,"1252":1,"1253":185,"1254":1,"1255":193,"1256":1,"1257":201,"1258":1,"1259":209,"1260":1,"1261":217,"1262":1,"1263":225,"1264":1,"1265":233,"1266":1,"1267":242,"1268":1,"1269":250,"1270":2,"1271":3,"1272":2,"1273":12,"1274":2,"1275":20,"1276":2,"1277":29,"1278":2,"1279":38,"1280":2,"1281":47,"1282":2,"1283":56,"1284":2,"1285":65,"1286":2,"1287":75,"1288":2,"1289":84,"1290":2,"1291":93,"1292":2,"1293":103,"1294":2,"1295":113,"1296":2,"1297":122,"1298":2,"1299":132,"1300":2,"1301":142,"1302":2,"1303":152,"1304":2,"1305":162,"1306":2,"1307":172,"1308":2,"1309":182,"1310":2,"1311":193,"1312":2,"1313":203,"1314":2,"1315":213,"1316":2,"1317":224,"1318":2,"1319":235,"1320":2,"1321":245,"1322":3,"1323":0,"1324":3,"1325":11,"1326":3,"1327":22,"1328":3,"1329":33,"1330":3,"1331":45,"1332":3,"1333":56,"1334":3,"1335":67,"1336":3,"1337":79,"1338":3,"1339":90,"1340":3,"1341":102,"1342":3,"1343":114,"1344":3,"1345":126,"1346":3,"1347":138,"1348":3,"1349":150,"1350":3,"1351":162,"1352":3,"1353":174,"1354":3,"1355":186,"1356":3,"1357":199,"1358":3,"1359":211,"1360":3,"1361":224,"1362":3,"1363":236,"1364":3,"1365":249,"1366":4,"1367":6,"1368":4,"1369":19,"1370":4,"1371":32,"1372":4,"1373":45,"1374":4,"1375":59,"1376":4,"1377":72,"1378":4,"1379":85,"1380":4,"1381":99,"1382":4,"1383":113,"1384":4,"1385":126,"1386":4,"1387":140,"1388":4,"1389":154,"1390":4,"1391":168,"1392":4,"1393":182,"1394":4,"1395":196,"1396":4,"1397":211,"1398":4,"1399":225,"1400":4,"1401":240,"1402":4,"1403":254,"1404":5,"1405":13,"1406":5,"1407":28,"1408":5,"1409":43,"1410":5,"1411":58,"1412":5,"1413":73,"1414":5,"1415":88,"1416":5,"1417":103,"1418":5,"1419":119,"1420":5,"1421":134,"1422":5,"1423":150,"1424":5,"1425":166,"1426":5,"1427":181,"1428":5,"1429":197,"1430":5,"1431":213,"1432":5,"1433":229,"1434":5,"1435":246,"1436":6,"1437":6,"1438":6,"1439":22,"1440":6,"1441":39,"1442":6,"1443":55,"1444":6,"1445":72,"1446":6,"1447":89,"1448":6,"1449":106,"1450":6,"1451":123,"1452":6,"1453":140,"1454":6,"1455":157,"1456":6,"1457":175,"1458":6,"1459":192,"1460":6,"1461":209,"1462":6,"1463":227,"1464":6,"1465":245,"1466":7,"1467":7,"1468":7,"1469":25,"1470":7,"1471":43,"1472":7,"1473":61,"1474":7,"1475":79,"1476":7,"1477":97,"1478":7,"1479":116,"1480":7,"1481":134,"1482":7,"1483":153,"1484":7,"1485":172,"1486":7,"1487":191,"1488":7,"1489":210,"1490":7,"1491":229,"1492":7,"1493":248,"1494":8,"1495":11,"1496":8,"1497":31,"1498":8,"1499":50,"1500":8,"1501":70,"1502":8,"1503":90,"1504":8,"1505":110,"1506":8,"1507":130,"1508":8,"1509":150,"1510":8,"1511":170,"1512":8,"1513":190,"1514":8,"1515":210,"1516":8,"1517":231,"1518":8,"1519":251,"1520":9,"1521":16,"1522":9,"1523":37,"1524":9,"1525":58,"1526":9,"1527":79,"1528":9,"1529":100,"1530":9,"1531":121,"1532":9,"1533":143,"1534":9,"1535":164,"1536":9,"1537":186,"1538":9,"1539":207,"1540":9,"1541":229,"1542":9,"1543":251,"1544":10,"1545":17,"1546":10,"1547":39,"1548":10,"1549":61,"1550":10,"1551":84,"1552":10,"1553":106,"1554":10,"1555":129,"1556":10,"1557":152,"1558":10,"1559":174,"1560":10,"1561":197,"1562":10,"1563":220,"1564":10,"1565":243,"1566":11,"1567":11,"1568":11,"1569":34,"1570":11,"1571":57,"1572":11,"1573":81,"1574":11,"1575":105,"1576":11,"1577":128,"1578":11,"1579":152,"1580":11,"1581":176,"1582":11,"1583":200,"1584":11,"1585":225,"1586":11,"1587":249,"1588":12,"1589":18,"1590":12,"1591":42,"1592":12,"1593":67,"1594":12,"1595":92,"1596":12,"1597":117,"1598":12,"1599":142,"1600":12,"1601":167,"1602":12,"1603":192,"1604":12,"1605":217,"1606":12,"1607":243,"1608":13,"1609":13,"1610":13,"1611":38,"1612":13,"1613":64,"1614":13,"1615":90,"1616":13,"1617":116,"1618":13,"1619":142,"1620":13,"1621":169,"1622":13,"1623":195,"1624":13,"1625":222,"1626":13,"1627":248,"1628":14,"1629":19,"1630":14,"1631":46,"1632":14,"1633":73,"1634":14,"1635":100,"1636":14,"1637":127,"1638":14,"1639":155,"1640":14,"1641":182,"1642":14,"1643":210,"1644":14,"1645":238,"1646":15,"1647":9,"1648":15,"1649":37,"1650":15,"1651":65,"1652":15,"1653":94,"1654":15,"1655":122,"1656":15,"1657":150,"1658":15,"1659":179,"1660":15,"1661":207,"1662":15,"1663":236,"1664":16,"1665":9,"1666":16,"1667":38,"1668":16,"1669":67,"1670":16,"1671":97,"1672":16,"1673":126,"1674":16,"1675":155,"1676":16,"1677":185,"1678":16,"1679":215,"1680":16,"1681":245,"1682":17,"1683":19,"1684":17,"1685":49,"1686":17,"1687":79,"1688":17,"1689":109,"1690":17,"1691":140,"1692":17,"1693":170,"1694":17,"1695":201,"1696":17,"1697":232,"1698":18,"1699":7,"1700":18,"1701":38,"1702":18,"1703":69,"1704":18,"1705":100,"1706":18,"1707":132,"1708":18,"1709":163,"1710":18,"1711":195,"1712":18,"1713":227,"1714":19,"1715":3,"1716":19,"1717":35,"1718":19,"1719":67,"1720":19,"1721":99,"1722":19,"1723":131,"1724":19,"1725":164,"1726":19,"1727":197,"1728":19,"1729":229,"1730":20,"1731":6,"1732":20,"1733":39,"1734":20,"1735":73,"1736":20,"1737":106,"1738":20,"1739":139,"1740":20,"1741":173,"1742":20,"1743":206,"1744":20,"1745":240,"1746":21,"1747":18,"1748":21,"1749":52,"1750":21,"1751":86,"1752":21,"1753":120,"1754":21,"1755":155,"1756":21,"1757":189,"1758":21,"1759":224,"1760":22,"1761":3,"1762":22,"1763":38,"1764":22,"1765":73,"1766":22,"1767":108,"1768":22,"1769":143,"1770":22,"1771":178,"1772":22,"1773":214,"1774":22,"1775":250,"1776":23,"1777":29,"1778":23,"1779":65,"1780":23,"1781":101,"1782":23,"1783":137,"1784":23,"1785":174,"1786":23,"1787":210,"1788":23,"1789":247,"1790":24,"1791":27,"1792":24,"1793":64,"1794":24,"1795":101,"1796":24,"1797":138,"1798":24,"1799":175,"1800":24,"1801":213,"1802":24,"1803":250,"1804":25,"1805":32,"1806":25,"1807":69,"1808":25,"1809":107,"1810":25,"1811":145,"1812":25,"1813":183,"1814":25,"1815":221,"1816":26,"1817":4,"1818":26,"1819":42,"1820":26,"1821":81,"1822":26,"1823":119,"1824":26,"1825":158,"1826":26,"1827":197,"1828":26,"1829":236,"1830":27,"1831":20,"1832":27,"1833":59,"1834":27,"1835":99,"1836":27,"1837":138,"1838":27,"1839":178,"1840":27,"1841":218,"1842":28,"1843":2,"1844":28,"1845":42,"1846":28,"1847":82,"1848":28,"1849":123,"1850":28,"1851":163,"1852":28,"1853":204,"1854":28,"1855":245,"1856":29,"1857":30,"1858":29,"1859":71,"1860":29,"1861":112,"1862":29,"1863":153,"1864":29,"1865":195,"1866":29,"1867":236,"1868":30,"1869":22,"1870":30,"1871":64,"1872":30,"1873":106,"1874":30,"1875":148,"1876":30,"1877":190,"1878":30,"1879":233,"1880":31,"1881":19,"1882":31,"1883":62,"1884":31,"1885":105,"1886":31,"1887":148,"1888":31,"1889":191,"1890":31,"1891":234,"1892":32,"1893":21,"1894":32,"1895":65,"1896":32,"1897":108,"1898":32,"1899":152,"1900":32,"1901":196,"1902":32,"1903":240,"1904":33,"1905":28,"1906":33,"1907":72,"1908":33,"1909":117,"1910":33,"1911":161,"1912":33,"1913":206,"1914":33,"1915":251,"1916":34,"1917":39,"1918":34,"1919":85,"1920":34,"1921":130,"1922":34,"1923":175,"1924":34,"1925":221,"1926":35,"1927":10,"1928":35,"1929":56,"1930":35,"1931":102,"1932":35,"1933":148,"1934":35,"1935":194,"1936":35,"1937":240,"1938":36,"1939":31,"1940":36,"1941":77,"1942":36,"1943":124,"1944":36,"1945":171,"1946":36,"1947":218,"1948":37,"1949":9,"1950":37,"1951":56,"1952":37,"1953":104,"1954":37,"1955":151,"1956":37,"1957":199,"1958":37,"1959":247,"1960":38,"1961":39,"1962":38,"1963":87,"1964":38,"1965":135,"1966":38,"1967":183,"1968":38,"1969":232,"1970":39,"1971":24,"1972":39,"1973":73,"1974":39,"1975":122,"1976":39,"1977":171,"1978":39,"1979":220,"1980":40,"1981":13,"1982":40,"1983":63,"1984":40,"1985":113,"1986":40,"1987":162,"1988":40,"1989":212,"1990":41,"1991":6,"1992":41,"1993":56,"1994":41,"1995":107,"1996":41,"1997":157,"1998":41,"1999":208,"2000":42,"2001":2,"2002":42,"2003":53,"2004":42,"2005":104,"2006":42,"2007":155,"2008":42,"2009":207,"2010":43,"2011":2,"2012":43,"2013":54,"2014":43,"2015":105,"2016":43,"2017":157,"2018":43,"2019":209,"2020":44,"2021":5,"2022":44,"2023":57,"2024":44,"2025":110,"2026":44,"2027":162,"2028":44,"2029":215,"2030":45,"2031":12,"2032":45,"2033":65,"2034":45,"2035":118,"2036":45,"2037":171,"2038":45,"2039":225,"2040":46,"2041":22,"2042":46,"2043":76,"2044":46,"2045":130,"2046":46,"2047":183,"2048":46,"2049":238,"2050":47,"2051":36,"2052":47,"2053":90,"2054":47,"2055":145,"2056":47,"2057":199,"2058":47,"2059":254,"2060":48,"2061":53,"2062":48,"2063":108,"2064":48,"2065":164,"2066":48,"2067":219,"2068":49,"2069":18,"2070":49,"2071":74,"2072":49,"2073":130,"2074":49,"2075":186,"2076":49,"2077":242,"2078":50,"2079":42,"2080":50,"2081":99,"2082":50,"2083":155,"2084":50,"2085":212,"2086":51,"2087":13,"2088":51,"2089":70,"2090":51,"2091":127,"2092":51,"2093":184,"2094":51,"2095":241,"2096":52,"2097":43,"2098":52,"2099":101,"2100":52,"2101":158,"2102":52,"2103":216,"2104":53,"2105":19,"2106":53,"2107":77,"2108":53,"2109":135,"2110":53,"2111":194,"2112":53,"2113":253,"2114":54,"2115":55,"2116":54,"2117":114,"2118":54,"2119":174,"2120":54,"2121":233,"2122":55,"2123":36,"2124":55,"2125":96,"2126":55,"2127":156,"2128":55,"2129":215,"2130":56,"2131":20,"2132":56,"2133":80,"2134":56,"2135":140,"2136":56,"2137":200,"2138":57,"2139":5,"2140":57,"2141":66,"2142":57,"2143":127,"2144":57,"2145":188,"2146":57,"2147":249,"2148":58,"2149":54,"2150":58,"2151":116,"2152":58,"2153":178,"2154":58,"2155":239,"2156":59,"2157":45,"2158":59,"2159":107,"2160":59,"2161":170,"2162":59,"2163":232,"2164":60,"2165":39,"2166":60,"2167":101,"2168":60,"2169":164,"2170":60,"2171":227,"2172":61,"2173":34,"2174":61,"2175":97,"2176":61,"2177":161,"2178":61,"2179":224,"2180":62,"2181":32,"2182":62,"2183":96,"2184":62,"2185":160,"2186":62,"2187":224,"2188":63,"2189":33,"2190":63,"2191":97,"2192":63,"2193":162,"2194":63,"2195":226,"2196":64,"2197":35,"2198":64,"2199":100,"2200":64,"2201":166,"2202":64,"2203":231,"2204":65,"2205":41,"2206":65,"2207":106,"2208":65,"2209":172,"2210":65,"2211":238,"2212":66,"2213":48,"2214":66,"2215":114,"2216":66,"2217":181,"2218":66,"2219":247,"2220":67,"2221":58,"2222":67,"2223":125,"2224":67,"2225":192,"2226":68,"2227":3,"2228":68,"2229":71,"2230":68,"2231":138,"2232":68,"2233":206,"2234":69,"2235":18,"2236":69,"2237":85,"2238":69,"2239":154,"2240":69,"2241":222,"2242":70,"2243":34,"2244":70,"2245":103,"2246":70,"2247":171,"2248":70,"2249":240,"2250":71,"2251":53,"2252":71,"2253":123,"2254":71,"2255":192,"2256":72,"2257":5,"2258":72,"2259":75,"2260":72,"2261":145,"2262":72,"2263":215,"2264":73,"2265":29,"2266":73,"2267":99,"2268":73,"2269":169,"2270":73,"2271":240,"2272":74,"2273":55,"2274":74,"2275":125,"2276":74,"2277":196,"2278":75,"2279":12,"2280":75,"2281":83,"2282":75,"2283":154,"2284":75,"2285":226,"2286":76,"2287":42,"2288":76,"2289":114,"2290":76,"2291":186,"2292":77,"2293":2,"2294":77,"2295":74,"2296":77,"2297":147,"2298":77,"2299":220,"2300":78,"2301":37,"2302":78,"2303":110,"2304":78,"2305":183,"2306":79,"2307":0,"2308":79,"2309":73,"2310":79,"2311":147,"2312":79,"2313":221,"2314":80,"2315":39,"2316":80,"2317":113,"2318":80,"2319":187,"2320":81,"2321":6,"2322":81,"2323":80,"2324":81,"2325":155,"2326":81,"2327":230,"2328":82,"2329":49,"2330":82,"2331":124,"2332":82,"2333":199,"2334":83,"2335":19,"2336":83,"2337":95,"2338":83,"2339":170,"2340":83,"2341":246,"2342":84,"2343":66,"2344":84,"2345":143,"2346":84,"2347":219,"2348":85,"2349":40,"2350":85,"2351":117,"2352":85,"2353":194,"2354":86,"2355":15,"2356":86,"2357":92,"2358":86,"2359":169,"2360":86,"2361":247,"2362":87,"2363":68,"2364":87,"2365":146,"2366":87,"2367":224,"2368":88,"2369":47,"2370":88,"2371":125,"2372":88,"2373":203,"2374":89,"2375":26,"2376":89,"2377":105,"2378":89,"2379":184,"2380":90,"2381":7,"2382":90,"2383":86,"2384":90,"2385":166,"2386":90,"2387":245,"2388":91,"2389":69,"2390":91,"2391":149,"2392":91,"2393":229,"2394":92,"2395":53,"2396":92,"2397":134,"2398":92,"2399":214,"2400":93,"2401":39,"2402":93,"2403":120,"2404":93,"2405":201,"2406":94,"2407":26,"2408":94,"2409":108,"2410":94,"2411":189,"2412":95,"2413":15,"2414":95,"2415":97,"2416":95,"2417":179,"2418":96,"2419":5,"2420":96,"2421":87,"2422":96,"2423":170,"2424":96,"2425":252,"2426":97,"2427":79,"2428":97,"2429":162,"2430":97,"2431":245,"2432":98,"2433":73,"2434":98,"2435":156,"2436":98,"2437":240,"2438":99,"2439":67,"2440":99,"2441":151,"2442":99,"2443":235,"2444":100,"2445":64,"2446":100,"2447":148,"2448":100,"2449":233,"2450":101,"2451":61,"2452":101,"2453":146,"2454":101,"2455":231,"2456":102,"2457":61,"2458":102,"2459":146,"2460":102,"2461":232,"2462":103,"2463":61,"2464":103,"2465":147,"2466":103,"2467":233,"2468":104,"2469":63,"2470":104,"2471":150,"2472":104,"2473":236,"2474":105,"2475":67,"2476":105,"2477":154,"2478":105,"2479":241,"2480":106,"2481":72,"2482":106,"2483":159,"2484":106,"2485":247,"2486":107,"2487":79,"2488":107,"2489":167,"2490":107,"2491":255,"2492":108,"2493":87,"2494":108,"2495":175,"2496":109,"2497":8,"2498":109,"2499":96,"2500":109,"2501":185,"2502":110,"2503":18,"2504":110,"2505":107,"2506":110,"2507":196,"2508":111,"2509":30,"2510":111,"2511":120,"2512":111,"2513":209,"2514":112,"2515":43,"2516":112,"2517":134,"2518":112,"2519":224,"2520":113,"2521":58,"2522":113,"2523":149,"2524":113,"2525":240,"2526":114,"2527":75,"2528":114,"2529":166,"2530":115,"2531":1,"2532":115,"2533":93,"2534":115,"2535":184,"2536":116,"2537":20,"2538":116,"2539":112,"2540":116,"2541":204,"2542":117,"2543":40,"2544":117,"2545":133,"2546":117,"2547":225,"2548":118,"2549":62,"2550":118,"2551":155,"2552":118,"2553":248,"2554":119,"2555":86,"2556":119,"2557":179,"2558":120,"2559":17,"2560":120,"2561":110,"2562":120,"2563":204,"2564":121,"2565":42,"2566":121,"2567":137,"2568":121,"2569":231,"2570":122,"2571":70,"2572":122,"2573":165,"2574":123,"2575":4,"2576":123,"2577":99,"2578":123,"2579":194,"2580":124,"2581":33,"2582":124,"2583":129,"2584":124,"2585":225,"2586":125,"2587":65,"2588":125,"2589":161,"2590":126,"2591":1,"2592":126,"2593":98,"2594":126,"2595":194,"2596":127,"2597":35,"2598":127,"2599":132,"2600":127,"2601":229,"2602":128,"2603":71,"2604":128,"2605":168,"2606":129,"2607":10,"2608":129,"2609":107,"2610":129,"2611":205,"2612":130,"2613":48,"2614":130,"2615":146,"2616":130,"2617":244,"2618":131,"2619":87,"2620":131,"2621":186,"2622":132,"2623":29,"2624":132,"2625":128,"2626":132,"2627":227,"2628":133,"2629":71,"2630":133,"2631":171,"2632":134,"2633":14,"2634":134,"2635":114,"2636":134,"2637":215,"2638":135,"2639":59,"2640":135,"2641":159,"2642":136,"2643":4,"2644":136,"2645":105,"2646":136,"2647":206,"2648":137,"2649":51,"2650":137,"2651":153,"2652":137,"2653":254,"2654":138,"2655":100,"2656":138,"2657":202,"2658":139,"2659":48,"2660":139,"2661":150,"2662":139,"2663":252,"2664":140,"2665":99,"2666":140,"2667":202,"2668":141,"2669":49,"2670":141,"2671":152,"2672":141,"2673":255,"2674":142,"2675":102,"2676":142,"2677":206,"2678":143,"2679":54,"2680":143,"2681":158,"2682":144,"2683":6,"2684":144,"2685":110,"2686":144,"2687":214,"2688":145,"2689":63,"2690":145,"2691":168,"2692":146,"2693":17,"2694":146,"2695":122,"2696":146,"2697":227,"2698":147,"2699":77,"2700":147,"2701":182,"2702":148,"2703":32,"2704":148,"2705":138,"2706":148,"2707":244,"2708":149,"2709":95,"2710":149,"2711":201,"2712":150,"2713":52,"2714":150,"2715":159,"2716":151,"2717":10,"2718":151,"2719":117,"2720":151,"2721":224,"2722":152,"2723":76,"2724":152,"2725":184,"2726":153,"2727":36,"2728":153,"2729":144,"2730":153,"2731":252,"2732":154,"2733":104,"2734":154,"2735":213,"2736":155,"2737":66,"2738":155,"2739":175,"2740":156,"2741":28,"2742":156,"2743":137,"2744":156,"2745":247,"2746":157,"2747":100,"2748":157,"2749":210,"2750":158,"2751":64,"2752":158,"2753":174,"2754":159,"2755":29,"2756":159,"2757":139,"2758":159,"2759":250,"2760":160,"2761":105,"2762":160,"2763":216,"2764":161,"2765":71,"2766":161,"2767":182,"2768":162,"2769":38,"2770":162,"2771":150,"2772":163,"2773":6,"2774":163,"2775":118,"2776":163,"2777":230,"2778":164,"2779":86,"2780":164,"2781":199,"2782":165,"2783":56,"2784":165,"2785":169,"2786":166,"2787":26,"2788":166,"2789":139,"2790":166,"2791":253,"2792":167,"2793":110,"2794":167,"2795":224,"2796":168,"2797":82,"2798":168,"2799":196,"2800":169,"2801":55,"2802":169,"2803":169,"2804":170,"2805":28,"2806":170,"2807":143,"2808":171,"2809":2,"2810":171,"2811":117,"2812":171,"2813":233,"2814":172,"2815":92,"2816":172,"2817":208,"2818":173,"2819":68,"2820":173,"2821":184,"2822":174,"2823":45,"2824":174,"2825":161,"2826":175,"2827":22,"2828":175,"2829":139,"2830":176,"2831":0,"2832":176,"2833":117,"2834":176,"2835":234,"2836":177,"2837":96,"2838":177,"2839":214,"2840":178,"2841":75,"2842":178,"2843":194,"2844":179,"2845":56,"2846":179,"2847":174,"2848":180,"2849":37,"2850":180,"2851":156,"2852":181,"2853":19,"2854":181,"2855":138,"2856":182,"2857":1,"2858":182,"2859":121,"2860":182,"2861":240,"2862":183,"2863":104,"2864":183,"2865":224,"2866":184,"2867":89,"2868":184,"2869":209,"2870":185,"2871":74,"2872":185,"2873":194,"2874":186,"2875":59,"2876":186,"2877":181,"2878":187,"2879":46,"2880":187,"2881":167,"2882":188,"2883":33,"2884":188,"2885":155,"2886":189,"2887":21,"2888":189,"2889":143,"2890":190,"2891":10,"2892":190,"2893":132,"2894":190,"2895":255,"2896":191,"2897":122,"2898":191,"2899":245,"2900":192,"2901":112,"2902":192,"2903":236,"2904":193,"2905":103,"2906":193,"2907":227,"2908":194,"2909":95,"2910":194,"2911":219,"2912":195,"2913":88,"2914":195,"2915":212,"2916":196,"2917":81,"2918":196,"2919":206,"2920":197,"2921":75,"2922":197,"2923":200,"2924":198,"2925":70,"2926":198,"2927":195,"2928":199,"2929":65,"2930":199,"2931":191,"2932":200,"2933":61,"2934":200,"2935":188,"2936":201,"2937":58,"2938":201,"2939":185,"2940":202,"2941":56,"2942":202,"2943":183,"2944":203,"2945":54,"2946":203,"2947":182,"2948":204,"2949":53,"2950":204,"2951":181,"2952":205,"2953":53,"2954":205,"2955":181,"2956":206,"2957":54,"2958":206,"2959":182,"2960":207,"2961":55,"2962":207,"2963":184,"2964":208,"2965":57,"2966":208,"2967":186,"2968":209,"2969":60,"2970":209,"2971":190,"2972":210,"2973":63,"2974":210,"2975":193,"2976":211,"2977":68,"2978":211,"2979":198,"2980":212,"2981":73,"2982":212,"2983":203,"2984":213,"2985":78,"2986":213,"2987":209,"2988":214,"2989":85,"2990":214,"2991":216,"2992":215,"2993":92,"2994":215,"2995":224,"2996":216,"2997":100,"2998":216,"2999":232,"3000":217,"3001":108,"3002":217,"3003":241,"3004":218,"3005":118,"3006":218,"3007":251,"3008":219,"3009":128,"3010":220,"3011":5,"3012":220,"3013":138,"3014":221,"3015":16,"3016":221,"3017":150,"3018":222,"3019":28,"3020":222,"3021":162,"3022":223,"3023":41,"3024":223,"3025":175,"3026":224,"3027":54,"3028":224,"3029":189,"3030":225,"3031":68,"3032":225,"3033":204,"3034":226,"3035":83,"3036":226,"3037":219,"3038":227,"3039":99,"3040":227,"3041":235,"3042":228,"3043":115,"3044":228,"3045":252,"3046":229,"3047":132,"3048":230,"3049":13,"3050":230,"3051":150,"3052":231,"3053":31,"3054":231,"3055":169,"3056":232,"3057":50,"3058":232,"3059":188,"3060":233,"3061":70,"3062":233,"3063":208,"3064":234,"3065":91,"3066":234,"3067":229,"3068":235,"3069":112,"3070":235,"3071":251,"3072":236,"3073":134,"3074":237,"3075":17,"3076":237,"3077":156,"3078":238,"3079":40,"3080":238,"3081":180,"3082":239,"3083":64,"3084":239,"3085":204,"3086":240,"3087":88,"3088":240,"3089":229,"3090":241,"3091":114,"3092":241,"3093":255,"3094":242,"3095":140,"3096":243,"3097":25,"3098":243,"3099":167,"3100":244,"3101":52,"3102":244,"3103":194,"3104":245,"3105":80,"3106":245,"3107":222,"3108":246,"3109":109,"3110":246,"3111":251,"3112":247,"3113":138,"3114":248,"3115":25,"3116":248,"3117":168,"3118":249,"3119":56,"3120":249,"3121":199,"3122":250,"3123":87,"3124":250,"3125":231,"3126":251,"3127":119,"3128":252,"3129":7,"3130":252,"3131":152,"3132":253,"3133":41,"3134":253,"3135":186,"3136":254,"3137":75,"3138":254,"3139":220,"3140":255,"3141":109,"3142":255,"3143":255},src:"/_app/assets/ben-mccann-cf-e62380ba.webp"}
Perhaps some of this information could be filtered out? I don't think I'd be likely to use something like this icc
property or many of the others and it results in a much larger download size. I really just need the src
, width
, height
, and format
.
I feel like vite-imagetools has potential to grow beyond vite and possibly have rollup, webpack, cli, etc. versions.
This is why I'm looking to split off the directives and core logic into it's own repository.
And this issue will keep track of progress towards that goal
Hi there I've been trying to figure out why avif imports through an srcset isn't working without success.
I've set up an example at https://avif-test-imagetools.netlify.app/, with the code on https://github.com/bronze/avif-test
What is happening is this:
Making a
Under network, on the inspector, there are 3 .avif files and one .jpg.
Anyone got an idea here?
-cheers
<template lang="pug">
div.flex.flex-row.overflow-hidden(data-testid="rogues-gallery")
img(v-for="i in Array(3).fill('')" :src="`${moreImage}`").more-image.w-40.m-3.inline
</template>
<script lang="ts">
// @ts-expect-error
import image from '../img/export/man.png?h=250;500'
export default {
computed: {
moreImage: () => image,
},
}
</script>
2 images, one 250px
wide and the other 500px
.
vite-imagetools cannot find image with id "99e660ff1a09e8cfe50c4085fd715e2f41d69980," this is likely an internal error
is printed to the console (and also to the error overlay on the dev server).
any ideas?
At the moment it is not possible to do (e.g.) defaultDirectives: { width: "10;100" }
since this is only applied after the configs have been resolved, and so cannot generate multiple images.
As far as I can tell the v3 will become the best image compression plugin for vite. So I'd like to support this plugin via donation. I think nowadays the best place for that is https://opencollective.com.
These two links are broken:
โข **extendTransforms**: [*Directive*](docs/modules/types.md#transformFactory)<{}\>[]
...
โข **extendOutputFormats**: [*OutputFormat*](docs/modules/types.md#outputformat)[]
On the page https://raw.githubusercontent.com/JonasKruckenberg/imagetools/main/packages/vite/README.md
Hello fellow developer!
As you may have noticed this plugin is lacking a few features at the moment,
but don't worry!
I will address most of the current problems in the next version that I'm actively working on right now!
It will be much easier to use, easier to extend and way faster(!)
This issue will track the progress towards version 3 so that you know what to expect:
Custom directives
Do all the image transformations you want! With this feature you can extend the builtin set of directives with your own ones.
This allows you to alias import directives that you commonly use like ?width=800&webp
to ?myDirective
Or transform your images in ways that are impossible with the builtins by leveraging the full power of sharp itself.
Better image caching
At the moment old images will not be deleted from the cache. This results in cache sizes in the gigabytes, but fear not, with v3 this will be gone for good.
Metadata output (see #3) for details
Will allow you to import the image plus all its metadata like width, height, color channels etc instead of just the plain url.
Srcset output
Creating srcsets is traditionally a complex task, you first generate the images with some tool, then you have to specify all the sizes in the srcset and the you realize the sizes don't fit!
But this is a thing of the past now, with the srcset directive you can generate responsive images and the correct srcset without ever leaving your code!
Full test coverage
Work in progress
And waaay more directives (no more TODOs in the Readme ๐)
Full list of directives to be added:
format
and it's shorthands)It seems the plugin is not triggered when including images from css. For example, in a vue single file component, I am setting a background image and the original image is getting loaded.
I know vite does process these urls to some degree, but unclear how it interacts with plugins...
// ...rest of single file component
<style>
.my-component {
background: url('./my-component-bg.png?webp');
}
</style>
Maybe we can switch the underlying library from sharp to wasm-vips witch would increase memory safety, expose more functionality and enable live in-browser transformations.
This issue will track further investigations.
In your directive examples, it seems like the tint
option is not working in vite-imagetool.
The example says
import Image from 'example.jpg?tint=#ffaa22'
import Image from 'example.jpg?tint=rgba(10,33,127)'
But it looks like vite-imagetools prefixes the expected color with a #
anyway. The result is, that when using a rgb color, it fails with
Unable to parse color from string: #rgba(10,33,127)
also the hex example does fail with
Unable to parse color from string: ##ffaa22
It works when no leading #
is provided, but rgb is impossible to achieve.
Thanks for the great library!
Is there a way to specify a list of metadata fields that we care to be exported, instead of being a boolean?
We import like this import metadata from '$static/image.png?w=400;800;1200&format=avif;webp;png&metadata';
in order to use the metadata array to build our responsive <picture>
element. The problem is that the each metatada object ends up in the final JS bundle ๐
I would prefer a syntax like '....&metadata=width;height;format';
if possible.
Hey,
Firstly thanks for making this, it's great! It wasn't working for me first since there was a space in my project folder e.g. Personal Site
which is then turned into Personal%20Site
which sharp dosn't seem able to find giving me
Input file is missing
Not sure if there's anything that can be done about this. It would have to take into account different operating systems. Anyway just wanted to make an issue to make this problem know and maybe help someone else trying to figure it out :)
This has been a requested feature and one that I'd argue is a wothwhile addition to the library.
I'm not quite sure on the specific syntax though and would like to get some feedback!
My proposal would be:
lqip
Where lqip invokes the following steps:
The question is wether these values should be customizeable on if so how? An integer that scales the values accordingly?
I don't want this directive to do too much since stuff like blurring can and should be added by the user to their liking.
i would like to use vite imagetools to generate my favicons. i have a singe favion.svg and want to generate all the other files from it. it would be very useful if you could add a directive to rename the file like e.g.
favicon.svg?w=180&h=180&name=apple-touch-icon&png
favicon.svg?w=192&h=192&name=favicon-192&png
favicon.svg?w=512&h=512&name=favicon-512&png
The current version of Sharp does not work on WSL, but upgrading to 0.29 seems to fix it (sveltejs/sites#230). We're starting to use imagetools on svelte.dev and kit.svelte.dev and one of the core maintainers uses WSL, so it would be nice to fix this. For now, we're probably just going to use pnpm overrides as a workaround
I took a quick stab at upgrading, but it looks like a few tests fail because a couple of them had saved output that it compared against and the output slightly differed. I guess the saved files would need to be updated to match the new version of Sharp
I feel like withe the number of directives already implemented (which is only going to increase with time) it's easy to get lost.
Most directives would also benefit from a visual representation of what they do.
This issue is to keep track of research & progress towards a docs/demo/playground website that shows off vite-imagetools capabilities.
If you're looking to contribute, this is a great place to start, as I don't have the time right now to create a whole website!
so get in touch!
Hi,
I see that it is possible for Sharp to convert Gif to animated Webp files in their doc. Is it possible in image tools? currently, the conversion works but only to a static image.
Thanks!
I've installed this plugin and added it in my vite config. I import image as ./01.jpeg?format=webp
and when I do vite build
it doesn't generate webp version of that image. Any ideas why it doesn't work?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.