nuxt / image

Plug-and-play image optimization for Nuxt applications.
https://image.nuxt.com
MIT License
1.31k stars 267 forks source link

Transparency not detected when image url doesn't contain an extension #368

Open narduin opened 3 years ago

narduin commented 3 years ago

Hello!

I'm using nuxt in full static mode with directus as a content source. Directus has a media library which provides a path to display the files. The path is built as follows: http://[directus-url]/assets/[FILE_ID] ex: http://localhost:8055/assets/db6b1d10-3ab0-4c20-a088-0f0246ae3145

When using nuxt-picture with that url as src, it renders a transparent webp as expected but the fallback generated is a .jpeg with a black background.

I tested with a local path to the file /assets/image.png and a distant path containing the .png extension and all is working fine.

Is it an expected behaviour? Thanks!

nuxt v2.15.7 nuxt-img v0.5.0

shadow81627 commented 3 years ago

I had a similar issue where my url doesn't have a mime type extension. eg. http://localhost/image-id when statically generated was getting a file path like /_nuxt/img/image-id.[ext].

I guess there should be a default format set in the provider or we need to pass in the format we want so the image generates using the correct mime type format.

See the nuxt-image format docs: https://image.nuxtjs.org/components/nuxt-img#format

narduin commented 3 years ago

Passing format="" works on <nuxt-img> and <nuxt-picture> but does it make sense to use <nuxt-picture> like this if we're using the original format? I usually use <nuxt-picture> to get .webp images with a fallback which, here, defaults to a .jpeg with a black background instead of transparency (in case of png files without extensions).

shadow81627 commented 3 years ago

There is an issue that is looking at adding a <nuxt-source> component that can be used in the default slot of <nuxt-picture> to control images sources. #309

There is a comment that mentions using legacy format in that issue thread as well https://github.com/nuxt/image/issues/309#issuecomment-876827549

narduin commented 3 years ago

Yes I've used the workaround from that issue somewhere else but it's not the same problem as my issue I believe.

shadow81627 commented 3 years ago

The code for nuxt-picture to define the legacy format uses the url and I guess that is returning null which is being calculated as not transparent. Do you have any suggestions on how the below code should handle the extension being null?

getFileExtension (url: string = '') {
  const extension = url.split(/[?#]/).shift()!.split('/').pop()!.split('.').pop()!
  return extension
}
originalFormat(): string {
  return getFileExtension(this.src)
},
isTransparent(): boolean {
  return ['png', 'webp', 'gif'].includes(this.originalFormat)
},
nLegacyFormat(): string {
  if (this.legacyFormat) {
    return this.legacyFormat
  }
  const formats: Record<string, string> = {
    webp: this.isTransparent ? 'png' : 'jpeg',
    svg: 'png'
  }
  return formats[this.nFormat] || this.originalFormat
},
const formats = this.nLegacyFormat !== this.nFormat
  ? [this.nLegacyFormat, this.nFormat]
  : [this.nFormat]
narduin commented 3 years ago

I'm really not an expert on this kind of logic. Would it be possible to test the mime type if the url has no extension?

shadow81627 commented 3 years ago

@pi0 I am thinking maybe a quick solution is to default to png when no extension is found in the url?

const formats: Record<string, string> = {
    webp: this.isTransparent || !this.originalFormat ? 'png' : 'jpeg',
    svg: 'png'
  }

There is also a more complicated solution of using a HEAD request to check mime type see stackoverflow for example.

getImgContentType (url) {
  return fetch(url, { method: 'HEAD' })
    .then(response => response.headers.get('Content-type'))
}
shadow81627 commented 3 years ago

@narduin on a side note I checked the directus docs and saw the thumbnail generation might have potential for first party provider support in @nuxt/image. I could maybe look into creating such a provider if I get a test url.

example.com/thumper/assets/pnw7s9lqy68048g0?w=200&h=200&f=crop&q=80
vanling commented 2 years ago

@shadow81627

. I could maybe look into creating such a provider if I get a test url.

I can provide you one and help/test if you are still up for it?

shadow81627 commented 2 years ago

@vanling having a test/example/demo URL would be great for setting up a Directus image provider.

vanling commented 2 years ago

@shadow81627 will send you some details to your mail (from gh profile)

shadow81627 commented 2 years ago

@vanling I have created a pull request to add Directus as an image provider. https://github.com/nuxt/image/pull/572#issue-1306685670