astro-lqip 1.4.0 → 1.5.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 +9 -10
- package/package.json +10 -10
- package/src/components/Image.astro +3 -1
- package/src/components/Picture.astro +3 -1
- package/src/types/components-options.type.ts +6 -5
- package/src/types/image-path.type.ts +1 -0
- package/src/types/index.ts +1 -0
- package/src/utils/generateLqip.ts +6 -1
- package/src/utils/getLqip.ts +15 -4
- package/src/utils/resolveImagePath.ts +5 -1
- package/src/utils/useLqipImage.ts +3 -2
package/README.md
CHANGED
|
@@ -9,6 +9,14 @@
|
|
|
9
9
|
|
|
10
10
|
Native extended Astro components for generating low quality image placeholders (LQIP).
|
|
11
11
|
|
|
12
|
+
## ✨ Features
|
|
13
|
+
- 🖼️ Supports both `<Image>` and `<Picture>` components.
|
|
14
|
+
- 🎨 Multiple LQIP techniques: base64, solid color, CSS via gradients and SVG.
|
|
15
|
+
- 🚀 Easy to use, just replace the native Astro components with the ones from [astro-lqip](https://astro-lqip.web.app/).
|
|
16
|
+
- 🔧 Fully compatible with [Astro's image optimization features](https://docs.astro.build/en/guides/images/).
|
|
17
|
+
- 🌍 Supports both local and remote images.
|
|
18
|
+
- ⚙️ Supports SSR mode with [Node Adapter](https://docs.astro.build/en/guides/integrations-guide/node/).
|
|
19
|
+
|
|
12
20
|
## ⬇️ Installation
|
|
13
21
|
|
|
14
22
|
NPM:
|
|
@@ -73,7 +81,7 @@ Both `<Image>` and `<Picture>` components support all the props of the [native A
|
|
|
73
81
|
- `lqipSize`: The size of the LQIP image, which can be any number from `4` to `64`. (default is 4)
|
|
74
82
|
|
|
75
83
|
> [!WARNING]
|
|
76
|
-
> A
|
|
84
|
+
> A high value for `lqipSize` can significantly increase the total size of your website.
|
|
77
85
|
|
|
78
86
|
Example:
|
|
79
87
|
|
|
@@ -92,15 +100,6 @@ import otherImage from './path/to/other-image.png';
|
|
|
92
100
|
> [!TIP]
|
|
93
101
|
> For the `<Image>` component, a `parentAttributes` prop similar to `pictureAttributes` has been added.
|
|
94
102
|
|
|
95
|
-
## 📝 ToDo
|
|
96
|
-
|
|
97
|
-
- [x] Add support for Image component.
|
|
98
|
-
- [x] Add support for more lqip techniques.
|
|
99
|
-
- [x] Test for remote images.
|
|
100
|
-
- [x] Optimize current CSS usage.
|
|
101
|
-
- [x] Improve docs page.
|
|
102
|
-
- [ ] Test support for SSR mode.
|
|
103
|
-
|
|
104
103
|
## 💡 Knowledge
|
|
105
104
|
|
|
106
105
|
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.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "astro-lqip",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0",
|
|
4
4
|
"description": "Native extended Astro components for generating low quality image placeholders (LQIP).",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"astro",
|
|
@@ -37,18 +37,18 @@
|
|
|
37
37
|
"plaiceholder": "3.0.0"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
|
-
"@eslint/js": "9.
|
|
41
|
-
"@typescript-eslint/parser": "8.
|
|
42
|
-
"astro": "5.
|
|
43
|
-
"bumpp": "10.
|
|
44
|
-
"eslint": "9.
|
|
40
|
+
"@eslint/js": "9.37.0",
|
|
41
|
+
"@typescript-eslint/parser": "8.46.1",
|
|
42
|
+
"astro": "5.14.5",
|
|
43
|
+
"bumpp": "10.3.1",
|
|
44
|
+
"eslint": "9.37.0",
|
|
45
45
|
"eslint-plugin-astro": "1.3.1",
|
|
46
|
-
"eslint-plugin-jsonc": "2.
|
|
46
|
+
"eslint-plugin-jsonc": "2.21.0",
|
|
47
47
|
"eslint-plugin-jsx-a11y": "6.10.2",
|
|
48
|
-
"eslint-plugin-package-json": "0.56.
|
|
49
|
-
"eslint-plugin-yml": "1.
|
|
48
|
+
"eslint-plugin-package-json": "0.56.4",
|
|
49
|
+
"eslint-plugin-yml": "1.19.0",
|
|
50
50
|
"globals": "16.4.0",
|
|
51
|
-
"jiti": "2.6.
|
|
51
|
+
"jiti": "2.6.1",
|
|
52
52
|
"nano-staged": "0.8.0",
|
|
53
53
|
"neostandard": "0.12.2",
|
|
54
54
|
"simple-git-hooks": "2.13.1"
|
|
@@ -16,13 +16,15 @@ 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
|
|
19
20
|
|
|
20
21
|
const { combinedStyle } = await useLqipImage({
|
|
21
22
|
src: props.src,
|
|
22
23
|
lqip,
|
|
23
24
|
lqipSize,
|
|
24
25
|
styleProps: parentAttributes.style ?? {},
|
|
25
|
-
isDevelopment
|
|
26
|
+
isDevelopment,
|
|
27
|
+
isPrerendered
|
|
26
28
|
})
|
|
27
29
|
|
|
28
30
|
const combinedParentAttributes = {
|
|
@@ -13,13 +13,15 @@ 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
|
|
16
17
|
|
|
17
18
|
const { combinedStyle } = await useLqipImage({
|
|
18
19
|
src: props.src,
|
|
19
20
|
lqip,
|
|
20
21
|
lqipSize,
|
|
21
22
|
styleProps: pictureAttributes.style ?? {},
|
|
22
|
-
isDevelopment
|
|
23
|
+
isDevelopment,
|
|
24
|
+
isPrerendered
|
|
23
25
|
})
|
|
24
26
|
|
|
25
27
|
const combinedPictureAttributes = {
|
|
@@ -2,9 +2,10 @@ import type { LqipType } from './lqip.type'
|
|
|
2
2
|
|
|
3
3
|
export type ComponentsOptions = {
|
|
4
4
|
src: string | object
|
|
5
|
-
lqip
|
|
6
|
-
lqipSize
|
|
7
|
-
styleProps
|
|
8
|
-
forbiddenVars
|
|
9
|
-
isDevelopment
|
|
5
|
+
lqip: LqipType
|
|
6
|
+
lqipSize: number
|
|
7
|
+
styleProps: Record<string, any>
|
|
8
|
+
forbiddenVars: string[]
|
|
9
|
+
isDevelopment: boolean | undefined
|
|
10
|
+
isPrerendered: boolean | undefined
|
|
10
11
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export type ImagePath = string | { src: string } | Promise<{ default: { src: string } }>
|
package/src/types/index.ts
CHANGED
|
@@ -6,7 +6,12 @@ import { PREFIX } from '../constants'
|
|
|
6
6
|
|
|
7
7
|
import { getPlaiceholder } from 'plaiceholder'
|
|
8
8
|
|
|
9
|
-
export async function generateLqip(
|
|
9
|
+
export async function generateLqip(
|
|
10
|
+
imagePath: string,
|
|
11
|
+
lqipType: LqipType,
|
|
12
|
+
lqipSize: number,
|
|
13
|
+
isDevelopment: boolean | undefined
|
|
14
|
+
) {
|
|
10
15
|
try {
|
|
11
16
|
const buffer = await readFile(imagePath)
|
|
12
17
|
const plaiceholderResult = await getPlaiceholder(buffer, { size: lqipSize })
|
package/src/utils/getLqip.ts
CHANGED
|
@@ -18,7 +18,13 @@ async function ensureCacheDir() {
|
|
|
18
18
|
}
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
export async function getLqip(
|
|
21
|
+
export async function getLqip(
|
|
22
|
+
imagePath: { src: string },
|
|
23
|
+
lqipType: LqipType,
|
|
24
|
+
lqipSize: number,
|
|
25
|
+
isDevelopment: boolean | undefined,
|
|
26
|
+
isPrerendered: boolean | undefined
|
|
27
|
+
) {
|
|
22
28
|
if (!imagePath?.src) return undefined
|
|
23
29
|
|
|
24
30
|
if (isRemoteUrl(imagePath.src)) {
|
|
@@ -33,7 +39,7 @@ export async function getLqip(imagePath: { src: string }, isDevelopment: boolean
|
|
|
33
39
|
await writeFile(tempPath, buffer)
|
|
34
40
|
|
|
35
41
|
try {
|
|
36
|
-
const lqip = await generateLqip(tempPath,
|
|
42
|
+
const lqip = await generateLqip(tempPath, lqipType, lqipSize, isDevelopment)
|
|
37
43
|
return lqip
|
|
38
44
|
} finally {
|
|
39
45
|
await unlink(tempPath)
|
|
@@ -42,12 +48,17 @@ export async function getLqip(imagePath: { src: string }, isDevelopment: boolean
|
|
|
42
48
|
|
|
43
49
|
if (isDevelopment && imagePath.src.startsWith('/@fs/')) {
|
|
44
50
|
const filePath = imagePath.src.replace(/^\/@fs/, '').split('?')[0]
|
|
45
|
-
return await generateLqip(filePath,
|
|
51
|
+
return await generateLqip(filePath, lqipType, lqipSize, isDevelopment)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (!isPrerendered && !isDevelopment) {
|
|
55
|
+
const filePath = join(process.cwd(), 'dist', 'client', imagePath.src)
|
|
56
|
+
return await generateLqip(filePath, lqipType, lqipSize, isDevelopment)
|
|
46
57
|
}
|
|
47
58
|
|
|
48
59
|
if (!isDevelopment && imagePath.src.startsWith('/_astro/')) {
|
|
49
60
|
const buildPath = join(process.cwd(), 'dist', imagePath.src)
|
|
50
|
-
return await generateLqip(buildPath,
|
|
61
|
+
return await generateLqip(buildPath, lqipType, lqipSize, isDevelopment)
|
|
51
62
|
}
|
|
52
63
|
|
|
53
64
|
return undefined
|
|
@@ -1,6 +1,10 @@
|
|
|
1
|
-
|
|
1
|
+
import type { ImagePath } from '../types'
|
|
2
|
+
|
|
3
|
+
export async function resolveImagePath(path: ImagePath) {
|
|
2
4
|
// If it's a string, we can't resolve it here. ex: Remote images URLs
|
|
3
5
|
if (typeof path === 'string') return null
|
|
6
|
+
// Handle dynamic imports
|
|
7
|
+
if ('then' in path && typeof path.then === 'function') return (await path).default
|
|
4
8
|
if ('src' in path) return path
|
|
5
9
|
return null
|
|
6
10
|
}
|
|
@@ -13,7 +13,8 @@ export async function useLqipImage({
|
|
|
13
13
|
lqipSize = 4,
|
|
14
14
|
styleProps = {},
|
|
15
15
|
forbiddenVars = ['--lqip-background', '--z-index', '--opacity'],
|
|
16
|
-
isDevelopment
|
|
16
|
+
isDevelopment,
|
|
17
|
+
isPrerendered
|
|
17
18
|
}: ComponentsOptions) {
|
|
18
19
|
let getImagePath: string | { src: string } | null
|
|
19
20
|
|
|
@@ -28,7 +29,7 @@ export async function useLqipImage({
|
|
|
28
29
|
let lqipImage
|
|
29
30
|
if (getImagePath) {
|
|
30
31
|
const lqipInput = typeof getImagePath === 'string' ? { src: getImagePath } : getImagePath
|
|
31
|
-
lqipImage = await getLqip(lqipInput,
|
|
32
|
+
lqipImage = await getLqip(lqipInput, lqip, lqipSize, isDevelopment, isPrerendered)
|
|
32
33
|
}
|
|
33
34
|
|
|
34
35
|
let svgHTML = ''
|