astro-lqip 1.2.2 → 1.3.1
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 +32 -14
- package/package.json +12 -11
- package/src/components/Image.astro +64 -0
- package/src/components/Picture.astro +7 -33
- package/src/index.ts +1 -0
- package/src/styles/lqip.css +30 -0
- package/src/types/props.type.ts +1 -3
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<a href="https://
|
|
1
|
+
<a href="https://astro-lqip.web.app/">
|
|
2
2
|
<img src="./assets/logo.png" alt="Astro LQIP Logo" width="200" height="200" />
|
|
3
3
|
</a>
|
|
4
4
|
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
[](https://www.npmjs.com/package/astro-lqip)
|
|
8
8
|
[](https://github.com/felixicaza/astro-lqip/blob/main/LICENSE)
|
|
9
9
|
|
|
10
|
-
Native extended Astro
|
|
10
|
+
Native extended Astro components for generating low quality image placeholders (LQIP).
|
|
11
11
|
|
|
12
12
|
## ⬇️ Installation
|
|
13
13
|
|
|
@@ -31,7 +31,16 @@ yarn add astro-lqip
|
|
|
31
31
|
|
|
32
32
|
## 🚀 Usage
|
|
33
33
|
|
|
34
|
-
In your current Astro project, just replace the import of the native Astro `<Picture
|
|
34
|
+
In your current Astro project, just replace the import of the native Astro `<Image>` or `<Picture>` components with the ones provided by [astro-lqip](https://astro-lqip.web.app/).
|
|
35
|
+
|
|
36
|
+
### Image
|
|
37
|
+
|
|
38
|
+
```diff
|
|
39
|
+
- import { Image } from 'astro:assets';
|
|
40
|
+
+ import { Image } from 'astro-lqip/components';
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Picture
|
|
35
44
|
|
|
36
45
|
```diff
|
|
37
46
|
- import { Picture } from 'astro:assets';
|
|
@@ -42,16 +51,19 @@ Example:
|
|
|
42
51
|
|
|
43
52
|
```astro
|
|
44
53
|
---
|
|
45
|
-
import { Picture } from 'astro-lqip/components'
|
|
46
|
-
|
|
54
|
+
import { Image, Picture } from 'astro-lqip/components';
|
|
55
|
+
|
|
56
|
+
import image from './path/to/image.png';
|
|
57
|
+
import otherImage from './path/to/other-image.png';
|
|
47
58
|
---
|
|
48
59
|
|
|
49
|
-
<
|
|
60
|
+
<Image src={image} alt="Cover Image" width={220} height={220} />
|
|
61
|
+
<Picture src={otherImage} alt="Other cover Image" width={220} height={220} />
|
|
50
62
|
```
|
|
51
63
|
|
|
52
64
|
## ⚙️ Props
|
|
53
65
|
|
|
54
|
-
|
|
66
|
+
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:
|
|
55
67
|
|
|
56
68
|
- `lqip`: The LQIP type to use. It can be one of the following:
|
|
57
69
|
- `base64`: Generates a Base64-encoded LQIP image. (default option)
|
|
@@ -61,31 +73,37 @@ This `<Picture />` component supports all the props of the [native Astro compone
|
|
|
61
73
|
- `lqipSize`: The size of the LQIP image, which can be any number from `4` to `64`. (default is 4)
|
|
62
74
|
|
|
63
75
|
> [!WARNING]
|
|
64
|
-
> A major size in the lqipSize prop can significantly impact the performance of your application.
|
|
76
|
+
> A major size in the `lqipSize` prop can significantly impact the performance of your application.
|
|
65
77
|
|
|
66
78
|
Example:
|
|
67
79
|
|
|
68
80
|
```astro
|
|
69
81
|
---
|
|
70
|
-
import { Picture } from 'astro-lqip/components'
|
|
71
|
-
|
|
82
|
+
import { Image, Picture } from 'astro-lqip/components';
|
|
83
|
+
|
|
84
|
+
import image from './path/to/image.png';
|
|
85
|
+
import otherImage from './path/to/other-image.png';
|
|
72
86
|
---
|
|
73
87
|
|
|
74
|
-
<
|
|
88
|
+
<Image src={image} alt="Cover Image" width={220} height={220} lqip="svg" lqipSize={10} />
|
|
89
|
+
<Picture src={otherImage} alt="Other cover Image" width={220} height={220} lqip="css" lqipSize={7} />
|
|
75
90
|
```
|
|
76
91
|
|
|
92
|
+
> [!TIP]
|
|
93
|
+
> For the `<Image>` component, a `parentAttributes` prop similar to `pictureAttributes` has been added.
|
|
94
|
+
|
|
77
95
|
## 📝 ToDo
|
|
78
96
|
|
|
79
|
-
- [
|
|
97
|
+
- [x] Add support for Image component.
|
|
80
98
|
- [x] Add support for more lqip techniques.
|
|
81
99
|
- [ ] Test for remote images.
|
|
82
|
-
- [
|
|
100
|
+
- [x] Optimize current CSS usage.
|
|
83
101
|
- [x] Improve docs page.
|
|
84
102
|
- [ ] Test support for SSR mode.
|
|
85
103
|
|
|
86
104
|
## 💡 Knowledge
|
|
87
105
|
|
|
88
|
-
Since this integration is built on top of Astro
|
|
106
|
+
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.
|
|
89
107
|
|
|
90
108
|
## 🤝 Contributing
|
|
91
109
|
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).
|
package/package.json
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "astro-lqip",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "Native extended Astro
|
|
3
|
+
"version": "1.3.1",
|
|
4
|
+
"description": "Native extended Astro components for generating low quality image placeholders (LQIP).",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"astro",
|
|
7
7
|
"astro-component",
|
|
8
8
|
"astro-integration",
|
|
9
9
|
"image",
|
|
10
|
+
"picture",
|
|
10
11
|
"lqip"
|
|
11
12
|
],
|
|
12
|
-
"homepage": "https://
|
|
13
|
+
"homepage": "https://astro-lqip.web.app",
|
|
13
14
|
"bugs": {
|
|
14
15
|
"url": "https://github.com/felixicaza/astro-lqip/issues"
|
|
15
16
|
},
|
|
@@ -36,21 +37,21 @@
|
|
|
36
37
|
"plaiceholder": "3.0.0"
|
|
37
38
|
},
|
|
38
39
|
"devDependencies": {
|
|
39
|
-
"@eslint/js": "9.
|
|
40
|
-
"@typescript-eslint/parser": "8.
|
|
41
|
-
"astro": "5.
|
|
42
|
-
"bumpp": "10.2.
|
|
43
|
-
"eslint": "9.
|
|
40
|
+
"@eslint/js": "9.33.0",
|
|
41
|
+
"@typescript-eslint/parser": "8.39.1",
|
|
42
|
+
"astro": "5.12.9",
|
|
43
|
+
"bumpp": "10.2.3",
|
|
44
|
+
"eslint": "9.33.0",
|
|
44
45
|
"eslint-plugin-astro": "1.3.1",
|
|
45
46
|
"eslint-plugin-jsonc": "2.20.1",
|
|
46
47
|
"eslint-plugin-jsx-a11y": "6.10.2",
|
|
47
|
-
"eslint-plugin-package-json": "0.
|
|
48
|
+
"eslint-plugin-package-json": "0.53.0",
|
|
48
49
|
"eslint-plugin-yml": "1.18.0",
|
|
49
50
|
"globals": "16.3.0",
|
|
50
|
-
"jiti": "2.
|
|
51
|
+
"jiti": "2.5.1",
|
|
51
52
|
"nano-staged": "0.8.0",
|
|
52
53
|
"neostandard": "0.12.2",
|
|
53
|
-
"simple-git-hooks": "2.13.
|
|
54
|
+
"simple-git-hooks": "2.13.1"
|
|
54
55
|
},
|
|
55
56
|
"peerDependencies": {
|
|
56
57
|
"astro": ">=3.3.0"
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
---
|
|
2
|
+
import type { LocalImageProps, RemoteImageProps } from 'astro:assets'
|
|
3
|
+
import type { HTMLAttributes } from 'astro/types'
|
|
4
|
+
import type { Props as LqipProps } from '../types'
|
|
5
|
+
|
|
6
|
+
import { PREFIX } from '../constants'
|
|
7
|
+
|
|
8
|
+
import { resolveImageMetadata } from '../utils/resolveImageMetadata'
|
|
9
|
+
import { renderSVGNode } from '../utils/renderSVGNode'
|
|
10
|
+
import { getLqipStyle } from '../utils/getLqipStyle'
|
|
11
|
+
import { getLqip } from '../utils/getLqip'
|
|
12
|
+
|
|
13
|
+
import { Image as ImageComponent } from 'astro:assets'
|
|
14
|
+
|
|
15
|
+
import '../styles/lqip.css'
|
|
16
|
+
|
|
17
|
+
type Props = (LocalImageProps | RemoteImageProps) & LqipProps & {
|
|
18
|
+
parentAttributes?: HTMLAttributes<'div'>
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const { class: className, lqip = 'base64', lqipSize = 4, parentAttributes = {}, ...props } = Astro.props as Props
|
|
22
|
+
|
|
23
|
+
const isDevelopment = import.meta.env.MODE === 'development'
|
|
24
|
+
|
|
25
|
+
const imageMetadata = await resolveImageMetadata(props.src)
|
|
26
|
+
const lqipImage = await getLqip(imageMetadata, isDevelopment, lqip, lqipSize)
|
|
27
|
+
|
|
28
|
+
let svgHTML = ''
|
|
29
|
+
|
|
30
|
+
if (lqip === 'svg' && Array.isArray(lqipImage)) {
|
|
31
|
+
svgHTML = renderSVGNode(lqipImage as [string, Record<string, any>, any[]])
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const lqipStyle = getLqipStyle(lqip, lqipImage, svgHTML)
|
|
35
|
+
|
|
36
|
+
const forbiddenVars = ['--lqip-background', '--z-index', '--opacity']
|
|
37
|
+
const styleProps = parentAttributes.style ?? {}
|
|
38
|
+
|
|
39
|
+
for (const key of Object.keys(styleProps)) {
|
|
40
|
+
if (forbiddenVars.includes(key)) {
|
|
41
|
+
console.warn(
|
|
42
|
+
`${PREFIX} The CSS variable “${key}” should not be passed in \`parentAttributes.style\` because it can override the functionality of LQIP.`
|
|
43
|
+
)
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const combinedStyle = {
|
|
48
|
+
...styleProps,
|
|
49
|
+
...lqipStyle
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const combinedParentAttributes = {
|
|
53
|
+
...parentAttributes,
|
|
54
|
+
style: combinedStyle
|
|
55
|
+
}
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
<div class={className} data-astro-lqip {...combinedParentAttributes}>
|
|
59
|
+
<ImageComponent
|
|
60
|
+
{...props}
|
|
61
|
+
class={className}
|
|
62
|
+
onload="parentElement.style.setProperty('--z-index', 1), parentElement.style.setProperty('--opacity', 0)"
|
|
63
|
+
/>
|
|
64
|
+
</div>
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
---
|
|
2
|
-
import type { Props } from '
|
|
2
|
+
import type { Props as AstroPictureProps } from 'astro/components/Picture.astro'
|
|
3
|
+
import type { Props as LqipProps } from '../types'
|
|
3
4
|
|
|
4
5
|
import { PREFIX } from '../constants'
|
|
5
6
|
|
|
@@ -10,6 +11,10 @@ import { getLqip } from '../utils/getLqip'
|
|
|
10
11
|
|
|
11
12
|
import { Picture as PictureComponent } from 'astro:assets'
|
|
12
13
|
|
|
14
|
+
import '../styles/lqip.css'
|
|
15
|
+
|
|
16
|
+
type Props = AstroPictureProps & LqipProps
|
|
17
|
+
|
|
13
18
|
const { class: className, lqip = 'base64', lqipSize = 4, pictureAttributes = {}, ...props } = Astro.props as Props
|
|
14
19
|
|
|
15
20
|
const isDevelopment = import.meta.env.MODE === 'development'
|
|
@@ -47,40 +52,9 @@ const combinedPictureAttributes = {
|
|
|
47
52
|
}
|
|
48
53
|
---
|
|
49
54
|
|
|
50
|
-
<style is:inline>
|
|
51
|
-
picture {
|
|
52
|
-
--opacity: 1;
|
|
53
|
-
--z-index: 0;
|
|
54
|
-
|
|
55
|
-
position: relative;
|
|
56
|
-
display: inline-block;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
picture::after {
|
|
60
|
-
content: "";
|
|
61
|
-
inset: 0;
|
|
62
|
-
width: 100%;
|
|
63
|
-
height: 100%;
|
|
64
|
-
position: absolute;
|
|
65
|
-
pointer-events: none;
|
|
66
|
-
transition: opacity 1s;
|
|
67
|
-
opacity: var(--opacity);
|
|
68
|
-
z-index: var(--z-index);
|
|
69
|
-
background: var(--lqip-background);
|
|
70
|
-
background-size: cover;
|
|
71
|
-
background-position: 50% 50%;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
picture img {
|
|
75
|
-
z-index: 1;
|
|
76
|
-
position: relative;
|
|
77
|
-
overflow: hidden;
|
|
78
|
-
}
|
|
79
|
-
</style>
|
|
80
|
-
|
|
81
55
|
<PictureComponent
|
|
82
56
|
{...props}
|
|
83
57
|
class={className}
|
|
84
|
-
pictureAttributes={{ ...combinedPictureAttributes }}
|
|
58
|
+
pictureAttributes={{ 'data-astro-lqip': '', ...combinedPictureAttributes }}
|
|
85
59
|
onload="parentElement.style.setProperty('--z-index', 1), parentElement.style.setProperty('--opacity', 0)"
|
|
86
60
|
/>
|
package/src/index.ts
CHANGED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
[data-astro-lqip] {
|
|
2
|
+
--opacity: 1;
|
|
3
|
+
--z-index: 0;
|
|
4
|
+
|
|
5
|
+
position: relative;
|
|
6
|
+
display: inline-block;
|
|
7
|
+
width: fit-content;
|
|
8
|
+
height: fit-content;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
[data-astro-lqip]::after {
|
|
12
|
+
content: "";
|
|
13
|
+
inset: 0;
|
|
14
|
+
width: 100%;
|
|
15
|
+
height: 100%;
|
|
16
|
+
position: absolute;
|
|
17
|
+
pointer-events: none;
|
|
18
|
+
transition: opacity 1s;
|
|
19
|
+
opacity: var(--opacity);
|
|
20
|
+
z-index: var(--z-index);
|
|
21
|
+
background: var(--lqip-background);
|
|
22
|
+
background-size: cover;
|
|
23
|
+
background-position: 50% 50%;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
[data-astro-lqip] img {
|
|
27
|
+
z-index: 1;
|
|
28
|
+
position: relative;
|
|
29
|
+
overflow: hidden;
|
|
30
|
+
}
|
package/src/types/props.type.ts
CHANGED