astro-lqip 1.7.0 → 1.7.2
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/package.json +12 -9
- package/src/utils/generateLqip.ts +14 -1
- package/src/utils/getLqip.ts +46 -16
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "astro-lqip",
|
|
3
|
-
"version": "1.7.
|
|
3
|
+
"version": "1.7.2",
|
|
4
4
|
"description": "Native extended Astro components for generating low quality image placeholders (LQIP).",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"astro",
|
|
@@ -38,18 +38,18 @@
|
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"@eslint/js": "9.39.1",
|
|
41
|
-
"@typescript-eslint/parser": "8.
|
|
42
|
-
"astro": "5.
|
|
43
|
-
"bumpp": "10.3.
|
|
41
|
+
"@typescript-eslint/parser": "8.48.0",
|
|
42
|
+
"astro": "5.16.1",
|
|
43
|
+
"bumpp": "10.3.2",
|
|
44
44
|
"eslint": "9.39.1",
|
|
45
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.
|
|
48
|
+
"eslint-plugin-package-json": "0.85.0",
|
|
49
49
|
"eslint-plugin-yml": "1.19.0",
|
|
50
50
|
"globals": "16.5.0",
|
|
51
51
|
"jiti": "2.6.1",
|
|
52
|
-
"nano-staged": "0.
|
|
52
|
+
"nano-staged": "0.9.0",
|
|
53
53
|
"neostandard": "0.12.2",
|
|
54
54
|
"simple-git-hooks": "2.13.1"
|
|
55
55
|
},
|
|
@@ -57,11 +57,14 @@
|
|
|
57
57
|
"astro": ">=3.3.0"
|
|
58
58
|
},
|
|
59
59
|
"scripts": {
|
|
60
|
-
"build": "pnpm -r build",
|
|
61
|
-
"dev": "pnpm -r dev",
|
|
60
|
+
"build:docs": "pnpm --filter ./docs -r build",
|
|
61
|
+
"dev": "pnpm --filter=!./docs -r dev",
|
|
62
|
+
"dev:docs": "pnpm --filter ./docs -r dev",
|
|
62
63
|
"lint": "eslint --cache .",
|
|
63
64
|
"lint:fix": "eslint --cache --fix .",
|
|
64
65
|
"preview": "pnpm -r preview",
|
|
65
|
-
"release": "bumpp
|
|
66
|
+
"release": "bumpp",
|
|
67
|
+
"test:fixtures": "pnpm --filter \"./tests/fixtures/**\" -r build",
|
|
68
|
+
"test:fixtures:preview": "pnpm --filter \"./tests/fixtures/**\" -r preview"
|
|
66
69
|
}
|
|
67
70
|
}
|
|
@@ -13,6 +13,19 @@ function normalizeFsPath(path: string) {
|
|
|
13
13
|
return path
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
+
function isNode() {
|
|
17
|
+
return typeof process !== 'undefined' && !!process.versions?.node
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
async function readIfExists(path: string): Promise<Buffer | undefined> {
|
|
21
|
+
if (!isNode()) return undefined
|
|
22
|
+
try {
|
|
23
|
+
return await readFile(path)
|
|
24
|
+
} catch {
|
|
25
|
+
return undefined
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
16
29
|
export async function generateLqip(
|
|
17
30
|
imagePath: string,
|
|
18
31
|
lqipType: LqipType,
|
|
@@ -22,7 +35,7 @@ export async function generateLqip(
|
|
|
22
35
|
try {
|
|
23
36
|
const normalizedPath = normalizeFsPath(imagePath)
|
|
24
37
|
|
|
25
|
-
const buffer = await
|
|
38
|
+
const buffer = await readIfExists(normalizedPath)
|
|
26
39
|
|
|
27
40
|
if (!buffer) {
|
|
28
41
|
console.warn(`${PREFIX} image not found for:`, imagePath)
|
package/src/utils/getLqip.ts
CHANGED
|
@@ -15,9 +15,38 @@ function isRemoteUrl(url: string) {
|
|
|
15
15
|
const CACHE_DIR = join(process.cwd(), 'node_modules', '.cache', 'astro-lqip')
|
|
16
16
|
const EXTENSIONS = ['jpg', 'jpeg', 'png', 'webp', 'avif']
|
|
17
17
|
const SEARCH_ROOT = ['src']
|
|
18
|
+
const HASHED_FILENAME_REGEX = /\.[A-Za-z0-9_-]{5,}\.[A-Za-z0-9]+$/
|
|
19
|
+
const HASHED_FILENAME_CAPTURE_REGEX = /^(.+?)\.[A-Za-z0-9_-]{5,}\.[A-Za-z0-9]+$/
|
|
20
|
+
|
|
21
|
+
const BASE_URL = (() => {
|
|
22
|
+
try {
|
|
23
|
+
const base = (import.meta.env?.BASE_URL ?? '/') as string
|
|
24
|
+
if (!base || base === '/') return '/'
|
|
25
|
+
return base.endsWith('/') ? base.slice(0, -1) : base
|
|
26
|
+
} catch {
|
|
27
|
+
return '/'
|
|
28
|
+
}
|
|
29
|
+
})()
|
|
18
30
|
|
|
19
31
|
const searchCache = new Map<string, string | null>()
|
|
20
32
|
|
|
33
|
+
function stripBasePath(src: string) {
|
|
34
|
+
if (typeof src !== 'string') return src
|
|
35
|
+
|
|
36
|
+
const queryIndex = src.indexOf('?')
|
|
37
|
+
let pathOnly = queryIndex >= 0 ? src.slice(0, queryIndex) : src
|
|
38
|
+
|
|
39
|
+
if (BASE_URL !== '/' && pathOnly.startsWith(BASE_URL)) {
|
|
40
|
+
pathOnly = pathOnly.slice(BASE_URL.length) || '/'
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (!pathOnly.startsWith('/')) {
|
|
44
|
+
pathOnly = `/${pathOnly}`
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return pathOnly
|
|
48
|
+
}
|
|
49
|
+
|
|
21
50
|
async function ensureCacheDir() {
|
|
22
51
|
if (!existsSync(CACHE_DIR)) {
|
|
23
52
|
await mkdir(CACHE_DIR, { recursive: true })
|
|
@@ -27,7 +56,7 @@ async function ensureCacheDir() {
|
|
|
27
56
|
function extractOriginalFileName(filename: string) {
|
|
28
57
|
const file = filename.split('/').pop() || ''
|
|
29
58
|
|
|
30
|
-
const match = file.match(
|
|
59
|
+
const match = file.match(HASHED_FILENAME_CAPTURE_REGEX)
|
|
31
60
|
if (match) return match[1]
|
|
32
61
|
|
|
33
62
|
const parts = file.split('.')
|
|
@@ -126,24 +155,25 @@ export async function getLqip(
|
|
|
126
155
|
|
|
127
156
|
if (!isDevelopment) {
|
|
128
157
|
const src = imagePath.src
|
|
129
|
-
|
|
130
|
-
const clean =
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
158
|
+
const normalizedSrc = stripBasePath(src)
|
|
159
|
+
const clean = normalizedSrc.replace(/^\//, '')
|
|
160
|
+
|
|
161
|
+
if (clean) {
|
|
162
|
+
const candidatePaths = [
|
|
163
|
+
join(process.cwd(), 'dist', 'client', clean),
|
|
164
|
+
join(process.cwd(), 'dist', clean)
|
|
165
|
+
]
|
|
166
|
+
|
|
167
|
+
for (const path of candidatePaths) {
|
|
168
|
+
if (existsSync(path)) {
|
|
169
|
+
return await generateLqip(path, lqipType, lqipSize, isDevelopment)
|
|
170
|
+
}
|
|
141
171
|
}
|
|
142
172
|
}
|
|
143
173
|
|
|
144
|
-
|
|
145
|
-
if (
|
|
146
|
-
const originalBase = extractOriginalFileName(
|
|
174
|
+
const fileName = normalizedSrc.split('/').pop() ?? ''
|
|
175
|
+
if (HASHED_FILENAME_REGEX.test(fileName)) {
|
|
176
|
+
const originalBase = extractOriginalFileName(normalizedSrc)
|
|
147
177
|
const originalSource = await recursiveFind(originalBase)
|
|
148
178
|
|
|
149
179
|
if (originalSource) {
|