diff --git a/src/runtime/providers/ipx.ts b/src/runtime/providers/ipx.ts
index 684ef6a52..7810939b0 100644
--- a/src/runtime/providers/ipx.ts
+++ b/src/runtime/providers/ipx.ts
@@ -57,6 +57,7 @@ export const operationsGenerator = createOperationsGenerator({
background: 'b',
position: 'pos',
},
+ joinWith: encodeURIComponent('&'),
formatter: (key, val: string | number | boolean) => encodeParam(key) + '_' + encodeParam(val.toString()),
})
diff --git a/test/e2e/ssr.test.ts b/test/e2e/ssr.test.ts
index cab6c08de..ad7158494 100644
--- a/test/e2e/ssr.test.ts
+++ b/test/e2e/ssr.test.ts
@@ -80,7 +80,7 @@ describe('browser (ssr: true)', () => {
expect(await $fetch('/api/image' as any)).toMatchInlineSnapshot(`
{
"format": "webp",
- "url": "/_ipx/f_webp&q_75/image.jpg",
+ "url": "/_ipx/f_webp%26q_75/image.jpg",
}
`)
})
diff --git a/test/nuxt/image.test.ts b/test/nuxt/image.test.ts
index 862fd95e2..b7ebad4f4 100644
--- a/test/nuxt/image.test.ts
+++ b/test/nuxt/image.test.ts
@@ -233,7 +233,7 @@ describe('Renders placeholder image', () => {
let domSrc = wrapper.find('img').element.getAttribute('src')
- expect(domSrc).toMatchInlineSnapshot('"/_ipx/q_50&blur_3&s_10x10/image.png"')
+ expect(domSrc).toMatchInlineSnapshot(`"/_ipx/q_50%26blur_3%26s_10x10/image.png"`)
expect(placeholderImage.src).toMatchInlineSnapshot('"/_ipx/s_200x200/image.png"')
resolveImage()
@@ -296,7 +296,7 @@ describe('Renders placeholder image', () => {
"other",
]
`)
- expect(wrapper.element.getAttribute('src')).toMatchInlineSnapshot('"/_ipx/q_50&blur_3&s_10x10/image.png"')
+ expect(wrapper.element.getAttribute('src')).toMatchInlineSnapshot(`"/_ipx/q_50%26blur_3%26s_10x10/image.png"`)
resolveImage()
await nextTick()
expect([...wrapper.element.classList]).toMatchInlineSnapshot(`
@@ -525,7 +525,7 @@ describe('Renders image, applies module config', () => {
sizes: '200,500:500,900:900',
},
})
- expect(img.html()).toMatchInlineSnapshot(`"
"`)
+ expect(img.html()).toMatchInlineSnapshot(`"
"`)
})
it('Module config .quality + props.quality => props.quality applies', () => {
@@ -539,7 +539,7 @@ describe('Renders image, applies module config', () => {
quality: 90,
},
})
- expect(img.html()).toMatchInlineSnapshot(`"
"`)
+ expect(img.html()).toMatchInlineSnapshot(`"
"`)
})
it('Without quality config => default image', () => {
diff --git a/test/nuxt/picture.test.ts b/test/nuxt/picture.test.ts
index 86c21406e..07629666d 100644
--- a/test/nuxt/picture.test.ts
+++ b/test/nuxt/picture.test.ts
@@ -49,7 +49,7 @@ describe('Renders simple image', () => {
it('Matches snapshot', () => {
expect(wrapper.html()).toMatchInlineSnapshot(`
"
-
+
"
`)
})
@@ -66,13 +66,13 @@ describe('Renders simple image', () => {
})
expect(img.html()).toMatchInlineSnapshot(`
"
-
+
"
`)
})
it('props.src is picked up by getImage()', () => {
- [['source', 'srcset', '/_ipx/f_webp&s_500x500/image.png'], ['img', 'src']].forEach(([element, attribute, customSrc]) => {
+ [['source', 'srcset', '/_ipx/f_webp%26s_500x500/image.png'], ['img', 'src']].forEach(([element, attribute, customSrc]) => {
const domSrc = wrapper.find(element!).element.getAttribute(attribute!)
expect(domSrc).toContain(customSrc || src)
})
@@ -129,7 +129,7 @@ describe('Renders simple image', () => {
await nextTick()
- ;[['source', 'srcset', '/_ipx/f_webp&s_500x500/image.jpeg'], ['img', 'src']].forEach(([element, attribute, src]) => {
+ ;[['source', 'srcset', '/_ipx/f_webp%26s_500x500/image.jpeg'], ['img', 'src']].forEach(([element, attribute, src]) => {
const domSrc = wrapper.find(element!).element.getAttribute(attribute!)
expect(domSrc).toContain(src || newSource)
})
@@ -161,7 +161,7 @@ describe('Renders simple image', () => {
})
expect(img.html()).toMatchInlineSnapshot(`
"
-
+
"
`)
})
@@ -197,7 +197,7 @@ describe('Renders image, applies module config', () => {
})
expect(picture.html()).toMatchInlineSnapshot(`
"
-
+
"
`)
})
@@ -221,7 +221,7 @@ describe('Renders image, applies module config', () => {
})
expect(picture.html()).toMatchInlineSnapshot(`
"
-
+
"
`)
})
@@ -245,8 +245,8 @@ describe('Renders image, applies module config', () => {
})
expect(picture.html()).toMatchInlineSnapshot(`
"
-
-
+
+
"
`)
})
@@ -271,7 +271,7 @@ describe('Renders image, applies module config', () => {
})
expect(picture.html()).toMatchInlineSnapshot(`
"
-
+
"
`)
})
@@ -316,7 +316,7 @@ describe('Renders image, applies module config', () => {
expect(picture.html()).toMatchInlineSnapshot(`
"
-
+
"
`)
})
diff --git a/test/nuxt/providers.test.ts b/test/nuxt/providers.test.ts
index 7ac564e65..fcc619d98 100644
--- a/test/nuxt/providers.test.ts
+++ b/test/nuxt/providers.test.ts
@@ -75,6 +75,24 @@ describe('Providers', () => {
url: '/_ipx/_/images/test.png',
})
})
+
+ it('ipx encodes reserved URI characters', () => {
+ const context = { ...emptyContext }
+
+ const src = '/images/test.png'
+ const generated = ipx().getImage(src, {
+ modifiers: {
+ fit: 'inside',
+ format: 'png',
+ width: 1200,
+ height: 630,
+ },
+ }, context)
+ expect(generated).toMatchObject({
+ url: '/_ipx/fit_inside%26f_png%26s_1200x630/images/test.png',
+ })
+ })
+
it('aliyun', () => {
const providerOptions = {
baseURL: '/',
diff --git a/test/providers.ts b/test/providers.ts
index c092b1ddd..51110a653 100644
--- a/test/providers.ts
+++ b/test/providers.ts
@@ -152,7 +152,7 @@ export const images = [
{
args: ['/test.png', { width: 200, height: 200, fit: 'contain' }],
none: { url: '/test.png' },
- ipx: { url: '/_ipx/fit_contain&s_200x200/test.png' },
+ ipx: { url: '/_ipx/fit_contain%26s_200x200/test.png' },
aliyun: { url: '/test.png?image_process=fit,contain/resize,fw_200,fh_200' },
awsAmplify: { url: '/?url=%2Ftest.png&w=640&h=200&fit=contain&q=100' },
cloudflare: { url: '/cdn-cgi/image/w=200,h=200,fit=contain/test.png' },
@@ -189,7 +189,7 @@ export const images = [
{
args: ['/test.png', { width: 200, height: 200, fit: 'contain', format: 'jpeg' }],
none: { url: '/test.png' },
- ipx: { url: '/_ipx/fit_contain&f_jpeg&s_200x200/test.png' },
+ ipx: { url: '/_ipx/fit_contain%26f_jpeg%26s_200x200/test.png' },
aliyun: { url: '/test.png?image_process=fit,contain/format,jpeg/resize,fw_200,fh_200' },
awsAmplify: { url: '/?url=%2Ftest.png&w=640&h=200&fit=contain&format=jpeg&q=100' },
cloudflare: { url: '/cdn-cgi/image/w=200,h=200,fit=contain,f=jpeg/test.png' },