astro-lqip 1.5.0 → 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -13,6 +13,7 @@ Native extended Astro components for generating low quality image placeholders (
13
13
  - 🖼️ Supports both `<Image>` and `<Picture>` components.
14
14
  - 🎨 Multiple LQIP techniques: base64, solid color, CSS via gradients and SVG.
15
15
  - 🚀 Easy to use, just replace the native Astro components with the ones from [astro-lqip](https://astro-lqip.web.app/).
16
+ - ⚡️ Support images as static imports or using string paths.
16
17
  - 🔧 Fully compatible with [Astro's image optimization features](https://docs.astro.build/en/guides/images/).
17
18
  - 🌍 Supports both local and remote images.
18
19
  - ⚙️ Supports SSR mode with [Node Adapter](https://docs.astro.build/en/guides/integrations-guide/node/).
@@ -61,14 +62,53 @@ Example:
61
62
  ---
62
63
  import { Image, Picture } from 'astro-lqip/components';
63
64
 
64
- import image from './path/to/image.png';
65
- import otherImage from './path/to/other-image.png';
65
+ import image from '/src/assets/images/image.png';
66
+ import otherImage from '/src/assets/images/other-image.png';
66
67
  ---
67
68
 
68
69
  <Image src={image} alt="Cover Image" width={220} height={220} />
69
- <Picture src={otherImage} alt="Other cover Image" width={220} height={220} />
70
+ <Picture src={otherImage} alt="Other Image" width={220} height={220} />
70
71
  ```
71
72
 
73
+ > [!TIP]
74
+ > Since version `1.6.0`, you can also put the image path as string directly in the `src` prop. Support absolute paths in `src`, relative paths and alias.
75
+
76
+ Example with absolute path:
77
+
78
+ ```astro
79
+ ---
80
+ import { Image, Picture } from 'astro-lqip/components';
81
+ ---
82
+
83
+ <Image src="/src/assets/images/image.png" alt="Cover Image" width={220} height={220} />
84
+ <Picture src="/src/assets/images/other-image.png" alt="Other Image" width={220} height={220} />
85
+ ```
86
+
87
+ Example with relative path:
88
+
89
+ ```astro
90
+ ---
91
+ import { Image, Picture } from 'astro-lqip/components';
92
+ ---
93
+
94
+ <!-- assuming you are on the path `/src/pages/index.astro` -->
95
+ <Image src="../assets/images/image.png" alt="Cover Image" width={220} height={220} />
96
+ <Picture src="../assets/images/other-image.png" alt="Other Image" width={220} height={220} />
97
+ ```
98
+
99
+ Example with alias:
100
+
101
+ ```astro
102
+ ---
103
+ import { Image, Picture } from 'astro-lqip/components';
104
+ ---
105
+
106
+ <Image src="@/assets/images/image.png" alt="Cover Image" width={220} height={220} />
107
+ <Picture src="@/assets/images/other-image.png" alt="Other Image" width={220} height={220} />
108
+ ```
109
+
110
+ Learn how to configure path aliasing in the [Astro documentation](https://docs.astro.build/en/guides/typescript/#import-aliases). If you want more examples of uses you can see the [Usage Tips](https://astro-lqip.web.app/usage-tips/) page.
111
+
72
112
  ## ⚙️ Props
73
113
 
74
114
  Both `<Image>` and `<Picture>` components support all the props of the [native Astro components](https://docs.astro.build/en/reference/modules/astro-assets/), but adds a couple of props for LQIP management:
@@ -89,12 +129,12 @@ Example:
89
129
  ---
90
130
  import { Image, Picture } from 'astro-lqip/components';
91
131
 
92
- import image from './path/to/image.png';
93
- import otherImage from './path/to/other-image.png';
132
+ import image from '/src/assets/images/image.png';
133
+ import otherImage from '/src/assets/images/other-image.png';
94
134
  ---
95
135
 
96
136
  <Image src={image} alt="Cover Image" width={220} height={220} lqip="svg" lqipSize={10} />
97
- <Picture src={otherImage} alt="Other cover Image" width={220} height={220} lqip="css" lqipSize={7} />
137
+ <Picture src={otherImage} alt="Other Image" width={220} height={220} lqip="css" lqipSize={7} />
98
138
  ```
99
139
 
100
140
  > [!TIP]
@@ -104,6 +144,8 @@ import otherImage from './path/to/other-image.png';
104
144
 
105
145
  Since this integration is built on top of Astro native `<Image>` and `<Picture>` components, you can refer to the [Astro documentation](https://docs.astro.build/en/guides/images/) for more information on how to use it.
106
146
 
147
+ For some simple tips, visit the [Usage Tips](https://astro-lqip.web.app/usage-tips/) page.
148
+
107
149
  ## 🤝 Contributing
108
150
  If you wish to contribute to this project, you can do so by reading the [contribution guide](https://github.com/felixicaza/astro-lqip/blob/main/CONTRIBUTING.md).
109
151
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "astro-lqip",
3
- "version": "1.5.0",
3
+ "version": "1.7.0",
4
4
  "description": "Native extended Astro components for generating low quality image placeholders (LQIP).",
5
5
  "keywords": [
6
6
  "astro",
@@ -37,17 +37,17 @@
37
37
  "plaiceholder": "3.0.0"
38
38
  },
39
39
  "devDependencies": {
40
- "@eslint/js": "9.37.0",
41
- "@typescript-eslint/parser": "8.46.1",
42
- "astro": "5.14.5",
40
+ "@eslint/js": "9.39.1",
41
+ "@typescript-eslint/parser": "8.46.4",
42
+ "astro": "5.15.5",
43
43
  "bumpp": "10.3.1",
44
- "eslint": "9.37.0",
45
- "eslint-plugin-astro": "1.3.1",
44
+ "eslint": "9.39.1",
45
+ "eslint-plugin-astro": "1.5.0",
46
46
  "eslint-plugin-jsonc": "2.21.0",
47
47
  "eslint-plugin-jsx-a11y": "6.10.2",
48
- "eslint-plugin-package-json": "0.56.4",
48
+ "eslint-plugin-package-json": "0.71.0",
49
49
  "eslint-plugin-yml": "1.19.0",
50
- "globals": "16.4.0",
50
+ "globals": "16.5.0",
51
51
  "jiti": "2.6.1",
52
52
  "nano-staged": "0.8.0",
53
53
  "neostandard": "0.12.2",
@@ -16,17 +16,20 @@ type Props = (LocalImageProps | RemoteImageProps) & LqipProps & {
16
16
  const { class: className, lqip = 'base64', lqipSize = 4, parentAttributes = {}, ...props } = Astro.props as Props
17
17
 
18
18
  const isDevelopment = import.meta.env.MODE === 'development'
19
- const isPrerendered = Astro.isPrerendered
20
19
 
21
- const { combinedStyle } = await useLqipImage({
20
+ const { combinedStyle, resolvedSrc } = await useLqipImage({
22
21
  src: props.src,
23
22
  lqip,
24
23
  lqipSize,
25
- styleProps: parentAttributes.style ?? {},
26
- isDevelopment,
27
- isPrerendered
24
+ styleProps: (parentAttributes.style ?? {}) as Record<string, string | number | undefined>,
25
+ forbiddenVars: [],
26
+ isDevelopment
28
27
  })
29
28
 
29
+ const componentProps = {
30
+ ...props,
31
+ src: resolvedSrc ?? props.src
32
+ }
30
33
  const combinedParentAttributes = {
31
34
  ...parentAttributes,
32
35
  style: combinedStyle
@@ -35,7 +38,7 @@ const combinedParentAttributes = {
35
38
 
36
39
  <div class={className} data-astro-lqip {...combinedParentAttributes}>
37
40
  <ImageComponent
38
- {...props}
41
+ {...componentProps as LocalImageProps | RemoteImageProps}
39
42
  class={className}
40
43
  onload="parentElement.style.setProperty('--z-index', 1), parentElement.style.setProperty('--opacity', 0)"
41
44
  />
@@ -13,17 +13,20 @@ type Props = AstroPictureProps & LqipProps
13
13
  const { class: className, lqip = 'base64', lqipSize = 4, pictureAttributes = {}, ...props } = Astro.props as Props
14
14
 
15
15
  const isDevelopment = import.meta.env.MODE === 'development'
16
- const isPrerendered = Astro.isPrerendered
17
16
 
18
- const { combinedStyle } = await useLqipImage({
17
+ const { combinedStyle, resolvedSrc } = await useLqipImage({
19
18
  src: props.src,
20
19
  lqip,
21
20
  lqipSize,
22
- styleProps: pictureAttributes.style ?? {},
23
- isDevelopment,
24
- isPrerendered
21
+ styleProps: (pictureAttributes.style ?? {}) as Record<string, string | number | undefined>,
22
+ forbiddenVars: [],
23
+ isDevelopment
25
24
  })
26
25
 
26
+ const componentProps = {
27
+ ...props,
28
+ src: resolvedSrc ?? props.src
29
+ }
27
30
  const combinedPictureAttributes = {
28
31
  ...pictureAttributes,
29
32
  style: combinedStyle
@@ -31,7 +34,7 @@ const combinedPictureAttributes = {
31
34
  ---
32
35
 
33
36
  <PictureComponent
34
- {...props}
37
+ {...(componentProps as AstroPictureProps)}
35
38
  class={className}
36
39
  pictureAttributes={{ 'data-astro-lqip': '', ...combinedPictureAttributes }}
37
40
  onload="parentElement.style.setProperty('--z-index', 1), parentElement.style.setProperty('--opacity', 0)"
@@ -4,8 +4,7 @@ export type ComponentsOptions = {
4
4
  src: string | object
5
5
  lqip: LqipType
6
6
  lqipSize: number
7
- styleProps: Record<string, any>
7
+ styleProps: Record<string, string | number | undefined>
8
8
  forbiddenVars: string[]
9
9
  isDevelopment: boolean | undefined
10
- isPrerendered: boolean | undefined
11
10
  }
@@ -1 +1,4 @@
1
1
  export type ImagePath = string | { src: string } | Promise<{ default: { src: string } }>
2
+ export type ResolvedImage = { src: string, width?: number, height?: number, [k: string]: unknown }
3
+ export type ImportModule = Record<string, unknown> & { default?: unknown }
4
+ export type GlobMap = Record<string, () => Promise<ImportModule>>
@@ -6,6 +6,13 @@ import { PREFIX } from '../constants'
6
6
 
7
7
  import { getPlaiceholder } from 'plaiceholder'
8
8
 
9
+ function normalizeFsPath(path: string) {
10
+ if (process.platform === 'win32' && /^\/[A-Za-z]:\//.test(path)) {
11
+ return path.slice(1)
12
+ }
13
+ return path
14
+ }
15
+
9
16
  export async function generateLqip(
10
17
  imagePath: string,
11
18
  lqipType: LqipType,
@@ -13,7 +20,15 @@ export async function generateLqip(
13
20
  isDevelopment: boolean | undefined
14
21
  ) {
15
22
  try {
16
- const buffer = await readFile(imagePath)
23
+ const normalizedPath = normalizeFsPath(imagePath)
24
+
25
+ const buffer = await readFile(normalizedPath)
26
+
27
+ if (!buffer) {
28
+ console.warn(`${PREFIX} image not found for:`, imagePath)
29
+ return undefined
30
+ }
31
+
17
32
  const plaiceholderResult = await getPlaiceholder(buffer, { size: lqipSize })
18
33
  let lqipValue: string | GetSVGReturn | undefined
19
34
 
@@ -1,16 +1,22 @@
1
1
  import { join } from 'node:path'
2
- import { mkdir, writeFile, unlink } from 'node:fs/promises'
3
- import { existsSync } from 'node:fs'
2
+ import { mkdir, writeFile, unlink, readdir } from 'node:fs/promises'
3
+ import { existsSync, statSync } from 'node:fs'
4
4
 
5
5
  import type { LqipType } from '../types'
6
6
 
7
7
  import { generateLqip } from './generateLqip'
8
8
 
9
+ import { PREFIX } from '../constants'
10
+
9
11
  function isRemoteUrl(url: string) {
10
12
  return /^https?:\/\//.test(url)
11
13
  }
12
14
 
13
15
  const CACHE_DIR = join(process.cwd(), 'node_modules', '.cache', 'astro-lqip')
16
+ const EXTENSIONS = ['jpg', 'jpeg', 'png', 'webp', 'avif']
17
+ const SEARCH_ROOT = ['src']
18
+
19
+ const searchCache = new Map<string, string | null>()
14
20
 
15
21
  async function ensureCacheDir() {
16
22
  if (!existsSync(CACHE_DIR)) {
@@ -18,12 +24,80 @@ async function ensureCacheDir() {
18
24
  }
19
25
  }
20
26
 
27
+ function extractOriginalFileName(filename: string) {
28
+ const file = filename.split('/').pop() || ''
29
+
30
+ const match = file.match(/^(.+?)\.[A-Za-z0-9_-]{5,}\.[A-Za-z0-9]+$/)
31
+ if (match) return match[1]
32
+
33
+ const parts = file.split('.')
34
+ if (parts.length >= 3) return parts.slice(0, parts.length - 2).join('.')
35
+
36
+ return parts[0]
37
+ }
38
+
39
+ async function recursiveFind(basename: string): Promise<string | undefined> {
40
+ if (!basename) return
41
+
42
+ if (searchCache.has(basename)) {
43
+ const cached = searchCache.get(basename)
44
+ return cached || undefined
45
+ }
46
+
47
+ const ignoreDirs = new Set(['node_modules', 'dist', '.astro'])
48
+
49
+ async function walk(dir: string): Promise<string | undefined> {
50
+ let entries: string[]
51
+
52
+ try {
53
+ entries = await readdir(dir)
54
+ } catch {
55
+ return
56
+ }
57
+
58
+ for (const entry of entries) {
59
+ const full = join(dir, entry)
60
+ let st: ReturnType<typeof statSync>
61
+
62
+ try {
63
+ st = statSync(full)
64
+ } catch {
65
+ continue
66
+ }
67
+
68
+ if (st.isDirectory()) {
69
+ if (ignoreDirs.has(entry)) continue
70
+ const found = await walk(full)
71
+ if (found) return found
72
+ } else {
73
+ // match by basename and extension
74
+ if (EXTENSIONS.some((ext) => entry === `${basename}.${ext}`)) {
75
+ return full
76
+ }
77
+ }
78
+ }
79
+ }
80
+
81
+ for (const rootRel of SEARCH_ROOT) {
82
+ const rootAbs = join(process.cwd(), rootRel)
83
+
84
+ if (existsSync(rootAbs)) {
85
+ const found = await walk(rootAbs)
86
+ if (found) {
87
+ searchCache.set(basename, found)
88
+ return found
89
+ }
90
+ }
91
+ }
92
+
93
+ searchCache.set(basename, null)
94
+ }
95
+
21
96
  export async function getLqip(
22
97
  imagePath: { src: string },
23
98
  lqipType: LqipType,
24
99
  lqipSize: number,
25
- isDevelopment: boolean | undefined,
26
- isPrerendered: boolean | undefined
100
+ isDevelopment: boolean | undefined
27
101
  ) {
28
102
  if (!imagePath?.src) return undefined
29
103
 
@@ -39,8 +113,7 @@ export async function getLqip(
39
113
  await writeFile(tempPath, buffer)
40
114
 
41
115
  try {
42
- const lqip = await generateLqip(tempPath, lqipType, lqipSize, isDevelopment)
43
- return lqip
116
+ return await generateLqip(tempPath, lqipType, lqipSize, isDevelopment)
44
117
  } finally {
45
118
  await unlink(tempPath)
46
119
  }
@@ -51,14 +124,35 @@ export async function getLqip(
51
124
  return await generateLqip(filePath, lqipType, lqipSize, isDevelopment)
52
125
  }
53
126
 
54
- if (!isPrerendered && !isDevelopment) {
55
- const filePath = join(process.cwd(), 'dist', 'client', imagePath.src)
56
- return await generateLqip(filePath, lqipType, lqipSize, isDevelopment)
57
- }
127
+ if (!isDevelopment) {
128
+ const src = imagePath.src
129
+
130
+ const clean = src.replace(/^\//, '')
131
+
132
+ const candidatePaths = [
133
+ join(process.cwd(), 'dist', 'client', clean),
134
+ join(process.cwd(), 'dist', clean),
135
+ join(process.cwd(), 'dist', '_astro', clean.replace(/^_astro\//, ''))
136
+ ]
58
137
 
59
- if (!isDevelopment && imagePath.src.startsWith('/_astro/')) {
60
- const buildPath = join(process.cwd(), 'dist', imagePath.src)
61
- return await generateLqip(buildPath, lqipType, lqipSize, isDevelopment)
138
+ for (const path of candidatePaths) {
139
+ if (existsSync(path)) {
140
+ return await generateLqip(path, lqipType, lqipSize, isDevelopment)
141
+ }
142
+ }
143
+
144
+ // if not found, try to recursively find the original source
145
+ if (src.startsWith('/_astro/')) {
146
+ const originalBase = extractOriginalFileName(src)
147
+ const originalSource = await recursiveFind(originalBase)
148
+
149
+ if (originalSource) {
150
+ console.log(`${PREFIX} fallback recursive source found:`, originalSource)
151
+ return await generateLqip(originalSource, lqipType, lqipSize, isDevelopment)
152
+ } else {
153
+ console.warn(`${PREFIX} original source not found recursively for basename:`, originalBase)
154
+ }
155
+ }
62
156
  }
63
157
 
64
158
  return undefined
@@ -1,10 +1,128 @@
1
- import type { ImagePath } from '../types'
1
+ import { existsSync } from 'node:fs'
2
+ import { join } from 'node:path'
3
+
4
+ import type { GlobMap, ImagePath, ImportModule, ResolvedImage } from '../types'
5
+
6
+ import { PREFIX } from '../constants'
7
+
8
+ const PUBLIC_DIR = join(process.cwd(), 'public')
9
+
10
+ const globFilesInSrc: GlobMap = ({ ...import.meta.glob('/src/**/*.{png,jpg,jpeg,svg}') } as unknown) as GlobMap
11
+
12
+ function warnFiles(filePath: string | undefined) {
13
+ if (!filePath) return
14
+
15
+ const lowerPath = filePath.toLowerCase()
16
+
17
+ if (lowerPath.includes(`${join('/', 'public')}`) || lowerPath.includes('/public/') || filePath.startsWith(PUBLIC_DIR)) {
18
+ console.warn(
19
+ `${PREFIX} Warning: image resolved from /public. Images should not be placed in /public — move them to /src so Astro can process them correctly.`
20
+ )
21
+ }
22
+
23
+ if (lowerPath.endsWith('.webp') || lowerPath.endsWith('.avif')) {
24
+ const extension = lowerPath.endsWith('.webp') ? 'webp' : 'avif'
25
+ console.warn(
26
+ `${PREFIX} Warning: image is in ${extension} format. These formats are usually already optimized; using this component to re-process them may degrade quality.`
27
+ )
28
+ }
29
+ }
30
+
31
+ function isObject(v: unknown): v is Record<string, unknown> {
32
+ return typeof v === 'object' && v !== null
33
+ }
34
+
35
+ function isPromise(v: unknown): v is Promise<unknown> {
36
+ if (!isObject(v)) return false
37
+ const promise = v as { then?: unknown }
38
+ return typeof promise.then === 'function'
39
+ }
40
+
41
+ function hasSrc(v: unknown): v is ResolvedImage {
42
+ return isObject(v) && typeof (v as Record<string, unknown>)['src'] === 'string'
43
+ }
44
+
45
+ function isRemoteUrl(v: string) {
46
+ return /^https?:\/\//.test(v)
47
+ }
48
+
49
+ function findGlobMatch(keys: string[], path: string) {
50
+ const candidates = [path.replace(/^\//, ''), `/${path.replace(/^\//, '')}`]
51
+ const match = keys.find((k) => candidates.includes(k) || k.endsWith(path) || k.endsWith(path.replace(/^\//, '')))
52
+ if (match) return match
53
+
54
+ const fileName = path.split('/').pop()
55
+ if (!fileName) return null
56
+
57
+ return keys.find((k) => k.endsWith(`/${fileName}`) || k.endsWith(fileName)) ?? null
58
+ }
2
59
 
3
60
  export async function resolveImagePath(path: ImagePath) {
4
- // If it's a string, we can't resolve it here. ex: Remote images URLs
5
- if (typeof path === 'string') return null
6
- // Handle dynamic imports
7
- if ('then' in path && typeof path.then === 'function') return (await path).default
8
- if ('src' in path) return path
61
+ if (path == null) return null
62
+
63
+ // validate dynamic import (Promise-like)
64
+ if (isPromise(path)) {
65
+ const mod = (await (path as Promise<ImportModule>)) as ImportModule
66
+ const resolved = (mod.default ?? mod) as unknown
67
+ if (hasSrc(resolved)) {
68
+ warnFiles(resolved.src)
69
+ return resolved
70
+ }
71
+ if (typeof resolved === 'string') {
72
+ warnFiles(resolved)
73
+ return resolved
74
+ }
75
+ return null
76
+ }
77
+
78
+ // validate already-resolved object (import result or { src: ... })
79
+ if (isObject(path)) {
80
+ const obj = path as Record<string, unknown>
81
+ const objSrc = typeof obj['src'] === 'string' ? (obj['src'] as string) : undefined
82
+ warnFiles(objSrc)
83
+ return hasSrc(obj) ? (obj as ResolvedImage) : null
84
+ }
85
+
86
+ // validate string path
87
+ if (typeof path === 'string') {
88
+ if (isRemoteUrl(path)) return path
89
+
90
+ const keys = Object.keys(globFilesInSrc)
91
+ const matchKey = findGlobMatch(keys, path)
92
+
93
+ if (matchKey) {
94
+ try {
95
+ const mod = await globFilesInSrc[matchKey]()
96
+ const resolved = (mod.default ?? mod) as unknown
97
+
98
+ if (hasSrc(resolved)) {
99
+ warnFiles((resolved as ResolvedImage).src)
100
+ return resolved as ResolvedImage
101
+ }
102
+
103
+ if (typeof resolved === 'string') {
104
+ warnFiles(resolved)
105
+ return resolved
106
+ }
107
+ } catch (err) {
108
+ console.log(`${PREFIX} resolveImagePath: failed to import glob match "${matchKey}" — falling back to filesystem.`, err)
109
+ }
110
+ }
111
+
112
+ // If module doesn't expose a usable value, fall through to filesystem check
113
+ try {
114
+ const absCandidate = path.startsWith('/') ? join(process.cwd(), path) : join(process.cwd(), path)
115
+
116
+ if (existsSync(absCandidate)) {
117
+ warnFiles(absCandidate)
118
+ return { src: `/@fs${absCandidate}` }
119
+ }
120
+ } catch (err) {
121
+ console.debug(`${PREFIX} resolveImagePath: filesystem check failed for "${path}".`, err)
122
+ }
123
+
124
+ return null
125
+ }
126
+
9
127
  return null
10
128
  }
@@ -1,4 +1,4 @@
1
- import type { ComponentsOptions, SVGNode } from '../types'
1
+ import type { ComponentsOptions, ImagePath, SVGNode } from '../types'
2
2
 
3
3
  import { PREFIX } from '../constants'
4
4
 
@@ -13,23 +13,17 @@ export async function useLqipImage({
13
13
  lqipSize = 4,
14
14
  styleProps = {},
15
15
  forbiddenVars = ['--lqip-background', '--z-index', '--opacity'],
16
- isDevelopment,
17
- isPrerendered
16
+ isDevelopment
18
17
  }: ComponentsOptions) {
19
- let getImagePath: string | { src: string } | null
20
-
21
- if (typeof src === 'string') {
22
- getImagePath = src
23
- } else if (typeof src === 'object' && src !== null) {
24
- getImagePath = await resolveImagePath(src as unknown as string)
25
- } else {
26
- getImagePath = null
27
- }
18
+ // resolve any kind of src (string, alias, import result, dynamic import)
19
+ const resolved = await resolveImagePath(src as unknown as ImagePath)
20
+ // resolved may be an object (module-like), { src: '...' } or null
21
+ const resolvedSrc = resolved ?? null
28
22
 
29
23
  let lqipImage
30
- if (getImagePath) {
31
- const lqipInput = typeof getImagePath === 'string' ? { src: getImagePath } : getImagePath
32
- lqipImage = await getLqip(lqipInput, lqip, lqipSize, isDevelopment, isPrerendered)
24
+ if (resolvedSrc) {
25
+ const lqipInput = typeof resolvedSrc === 'string' ? { src: resolvedSrc } : resolvedSrc
26
+ lqipImage = await getLqip(lqipInput, lqip, lqipSize, isDevelopment)
33
27
  }
34
28
 
35
29
  let svgHTML = ''
@@ -52,5 +46,5 @@ export async function useLqipImage({
52
46
  ...lqipStyle
53
47
  }
54
48
 
55
- return { lqipImage, svgHTML, lqipStyle, combinedStyle }
49
+ return { lqipImage, svgHTML, lqipStyle, combinedStyle, resolvedSrc }
56
50
  }