@zaininnari/postcss-cachebuster 0.3.0 → 0.4.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/.github/workflows/lint.yml +28 -0
- package/.github/workflows/test-latest.yml +1 -1
- package/.github/workflows/test.yml +1 -1
- package/.idea/jsLibraryMappings.xml +6 -0
- package/CHANGELOG.md +24 -0
- package/eslint.config.js +22 -0
- package/index.mjs +76 -17
- package/package.json +10 -3
- package/.eslintrc.json +0 -13
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
name: Lint
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
pull_request:
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
test:
|
|
9
|
+
runs-on: ubuntu-latest
|
|
10
|
+
|
|
11
|
+
strategy:
|
|
12
|
+
matrix:
|
|
13
|
+
node-version: [20, 22, 24]
|
|
14
|
+
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v4
|
|
17
|
+
|
|
18
|
+
- name: Use Node.js
|
|
19
|
+
uses: actions/setup-node@v4
|
|
20
|
+
with:
|
|
21
|
+
node-version: ${{ matrix.node-version }}
|
|
22
|
+
cache: 'npm'
|
|
23
|
+
|
|
24
|
+
- name: Install dependencies
|
|
25
|
+
run: npm ci
|
|
26
|
+
|
|
27
|
+
- name: Run tests
|
|
28
|
+
run: npm run lint
|
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,27 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.4.1 (2026-01-02)
|
|
4
|
+
- Add ESLint
|
|
5
|
+
- @eslint/js recommended
|
|
6
|
+
- eslint-plugin-n recommended
|
|
7
|
+
|
|
8
|
+
## 0.4.0 (2025-12-30)
|
|
9
|
+
- update dependencies
|
|
10
|
+
- update support node version 20+
|
|
11
|
+
|
|
12
|
+
## 0.3.0 (2025-12-29)
|
|
13
|
+
- update npm package
|
|
14
|
+
- update support node version 18+
|
|
15
|
+
|
|
16
|
+
## Before fork
|
|
17
|
+
|
|
18
|
+
## 0.1.6 (2018-12-07)
|
|
19
|
+
|
|
20
|
+
## 0.1.5 (2018-12-07)
|
|
21
|
+
|
|
22
|
+
## 0.1.4 (2017-01-07)
|
|
23
|
+
Fix multiple css imports in single css file.
|
|
24
|
+
|
|
1
25
|
## 0.1.3 (2016-05-27)
|
|
2
26
|
|
|
3
27
|
- `type` can be defined as function.
|
package/eslint.config.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import js from "@eslint/js";
|
|
2
|
+
import globals from "globals";
|
|
3
|
+
import n from "eslint-plugin-n";
|
|
4
|
+
import {defineConfig} from "eslint/config";
|
|
5
|
+
|
|
6
|
+
export default defineConfig([
|
|
7
|
+
{
|
|
8
|
+
files: ["**/*.{js,mjs,cjs}"],
|
|
9
|
+
languageOptions: {
|
|
10
|
+
ecmaVersion: "latest",
|
|
11
|
+
sourceType: "module",
|
|
12
|
+
globals: {
|
|
13
|
+
...globals.node,
|
|
14
|
+
...globals.mocha,
|
|
15
|
+
myCustomGlobal: "readonly",
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
plugins: {js, n},
|
|
19
|
+
extends: ["js/recommended", "n/recommended"],
|
|
20
|
+
ignores: ['eslint.config.js'],
|
|
21
|
+
},
|
|
22
|
+
]);
|
package/index.mjs
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import url from 'url';
|
|
2
1
|
import fs from 'fs';
|
|
3
2
|
import crypto from 'crypto';
|
|
4
3
|
import chalk from 'chalk';
|
|
@@ -7,9 +6,18 @@ import path from 'canonical-path';
|
|
|
7
6
|
|
|
8
7
|
const checksums = {};
|
|
9
8
|
|
|
9
|
+
/**
|
|
10
|
+
* parsed
|
|
11
|
+
* @typedef {Object} parsed
|
|
12
|
+
* @property {URL} u
|
|
13
|
+
* @property {boolean} isAbsolute
|
|
14
|
+
* @property {boolean} isRootRelativeButNotProtocolRelative
|
|
15
|
+
* @property {string} originalUrl
|
|
16
|
+
*/
|
|
17
|
+
|
|
10
18
|
const plugin = (opts = {}) => {
|
|
11
19
|
const pattern = /url\((['"])?([^'")]+)(['"])?\)/g;
|
|
12
|
-
|
|
20
|
+
const supportedPropsDefault = [
|
|
13
21
|
'background',
|
|
14
22
|
'background-image',
|
|
15
23
|
'border-image',
|
|
@@ -22,8 +30,9 @@ const plugin = (opts = {}) => {
|
|
|
22
30
|
opts.type = opts.type || 'mtime';
|
|
23
31
|
opts.paramName = opts.paramName || 'v';
|
|
24
32
|
opts.hashAlgorithm = opts.hashAlgorithm || 'md5';
|
|
25
|
-
supportedProps = opts.supportedProps ||
|
|
26
|
-
|
|
33
|
+
opts.supportedProps = opts.supportedProps || supportedPropsDefault;
|
|
34
|
+
opts.additionalProps = opts.additionalProps || [];
|
|
35
|
+
const supportedProps = opts.supportedProps.concat(opts.additionalProps);
|
|
27
36
|
|
|
28
37
|
function createCachebuster(assetPath, origPath, type) {
|
|
29
38
|
let cachebuster;
|
|
@@ -55,10 +64,17 @@ const plugin = (opts = {}) => {
|
|
|
55
64
|
return cachebuster;
|
|
56
65
|
}
|
|
57
66
|
|
|
58
|
-
|
|
67
|
+
/**
|
|
68
|
+
* @param assetUrl {URL}
|
|
69
|
+
* @param file {string}
|
|
70
|
+
* @param imagesPath {string}
|
|
71
|
+
* @param isRootRelativeButNotProtocolRelative {boolean}
|
|
72
|
+
* @returns {string}
|
|
73
|
+
*/
|
|
74
|
+
function resolveUrl(assetUrl, file, imagesPath, isRootRelativeButNotProtocolRelative) {
|
|
59
75
|
let assetPath = decodeURI(assetUrl.pathname);
|
|
60
76
|
|
|
61
|
-
if (
|
|
77
|
+
if (isRootRelativeButNotProtocolRelative) {
|
|
62
78
|
assetPath = path.join(imagesPath, assetPath);
|
|
63
79
|
} else {
|
|
64
80
|
assetPath = path.join(opts.cssPath || path.dirname(file), assetPath);
|
|
@@ -66,14 +82,22 @@ const plugin = (opts = {}) => {
|
|
|
66
82
|
return assetPath;
|
|
67
83
|
}
|
|
68
84
|
|
|
69
|
-
|
|
70
|
-
|
|
85
|
+
/**
|
|
86
|
+
* @param assetUrl {URL}
|
|
87
|
+
* @param inputFile {string}
|
|
88
|
+
* @param isRootRelativeButNotProtocolRelative {boolean}
|
|
89
|
+
*/
|
|
90
|
+
function updateAssetUrl(assetUrl, inputFile, isRootRelativeButNotProtocolRelative) {
|
|
91
|
+
const assetPath = resolveUrl(assetUrl, inputFile, opts.imagesPath, isRootRelativeButNotProtocolRelative);
|
|
71
92
|
|
|
72
93
|
// complete url with cachebuster
|
|
73
|
-
const
|
|
94
|
+
const originPath = isRootRelativeButNotProtocolRelative ? assetUrl.pathname : assetUrl.pathname.substring(1);
|
|
95
|
+
const cachebuster = createCachebuster(assetPath, originPath, opts.type);
|
|
74
96
|
if (!cachebuster) {
|
|
75
97
|
return;
|
|
76
|
-
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (typeof opts.type === 'function') {
|
|
77
101
|
assetUrl.pathname = cachebuster;
|
|
78
102
|
} else if (assetUrl.search && assetUrl.search.length > 1) {
|
|
79
103
|
assetUrl.search = assetUrl.search + '&' + opts.paramName + cachebuster;
|
|
@@ -82,6 +106,39 @@ const plugin = (opts = {}) => {
|
|
|
82
106
|
}
|
|
83
107
|
}
|
|
84
108
|
|
|
109
|
+
const DUMMY_BASE = 'http://localhost';
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* @param input {string}
|
|
113
|
+
* @returns {parsed}
|
|
114
|
+
*/
|
|
115
|
+
function parseUrlPreserveRelative(input) {
|
|
116
|
+
const isAbsolute = /^[a-zA-Z][a-zA-Z\d+\-.]*:/.test(input);
|
|
117
|
+
const isRootRelativeButNotProtocolRelative = /^\/(?!\/)/.test(input);
|
|
118
|
+
const u = isAbsolute ? new URL(input) : new URL(input, DUMMY_BASE);
|
|
119
|
+
return {u, isAbsolute, isRootRelativeButNotProtocolRelative, originalUrl: input};
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* @param parsed {parsed}
|
|
124
|
+
* @returns {string|string}
|
|
125
|
+
*/
|
|
126
|
+
function formatUrlPreserveRelative(parsed) {
|
|
127
|
+
const u = parsed.u;
|
|
128
|
+
const isAbsolute = parsed.isAbsolute;
|
|
129
|
+
const isRootRelativeButNotProtocolRelative = parsed.isRootRelativeButNotProtocolRelative;
|
|
130
|
+
|
|
131
|
+
if (isAbsolute) {
|
|
132
|
+
return u.toString();
|
|
133
|
+
}
|
|
134
|
+
const url = `${u.pathname}${u.search}${u.hash}`;
|
|
135
|
+
if (!isRootRelativeButNotProtocolRelative) {
|
|
136
|
+
// remove start slash
|
|
137
|
+
return url.substring(1);
|
|
138
|
+
}
|
|
139
|
+
return url;
|
|
140
|
+
}
|
|
141
|
+
|
|
85
142
|
return {
|
|
86
143
|
postcssPlugin: 'postcss-cachebuster',
|
|
87
144
|
Once(root) {
|
|
@@ -95,10 +152,10 @@ const plugin = (opts = {}) => {
|
|
|
95
152
|
const quote = results[1] || '"';
|
|
96
153
|
const originalUrl = results[2];
|
|
97
154
|
|
|
98
|
-
const
|
|
99
|
-
updateAssetUrl(
|
|
155
|
+
const parsed = parseUrlPreserveRelative(originalUrl);
|
|
156
|
+
updateAssetUrl(parsed.u, inputFile, parsed.isRootRelativeButNotProtocolRelative, parsed.originalUrl);
|
|
100
157
|
|
|
101
|
-
atrule.params = 'url(' + quote +
|
|
158
|
+
atrule.params = 'url(' + quote + formatUrlPreserveRelative(parsed) + quote + ')';
|
|
102
159
|
});
|
|
103
160
|
|
|
104
161
|
root.walkDecls(function walkThroughtDeclarations(declaration) {
|
|
@@ -110,20 +167,22 @@ const plugin = (opts = {}) => {
|
|
|
110
167
|
declaration.value = declaration.value.replace(pattern, function (match, quote, originalUrl) {
|
|
111
168
|
quote = quote || '"';
|
|
112
169
|
|
|
113
|
-
const
|
|
170
|
+
const parsed = parseUrlPreserveRelative(originalUrl);
|
|
171
|
+
const assetUrl = parsed.u;
|
|
114
172
|
|
|
115
173
|
// only locals
|
|
116
174
|
if (
|
|
117
|
-
assetUrl.
|
|
175
|
+
assetUrl.toString().indexOf(DUMMY_BASE) !== 0 ||
|
|
176
|
+
parsed.isAbsolute ||
|
|
118
177
|
assetUrl.pathname.indexOf('//') === 0 ||
|
|
119
178
|
assetUrl.pathname.indexOf(';base64') !== -1
|
|
120
179
|
) {
|
|
121
180
|
return match;
|
|
122
181
|
}
|
|
123
182
|
|
|
124
|
-
updateAssetUrl(assetUrl, inputFile);
|
|
183
|
+
updateAssetUrl(assetUrl, inputFile, parsed.isRootRelativeButNotProtocolRelative);
|
|
125
184
|
|
|
126
|
-
return 'url(' + quote +
|
|
185
|
+
return 'url(' + quote + formatUrlPreserveRelative(parsed) + quote + ')';
|
|
127
186
|
});
|
|
128
187
|
});
|
|
129
188
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zaininnari/postcss-cachebuster",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"description": "Fork of postcss-cachebuster. Cachebusting all local files in css",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"postcss",
|
|
@@ -38,7 +38,11 @@
|
|
|
38
38
|
"path": "^0.12.7"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
|
+
"@eslint/js": "^9.39.2",
|
|
41
42
|
"chai": "^6.2.2",
|
|
43
|
+
"eslint": "^9.39.2",
|
|
44
|
+
"eslint-plugin-n": "^17.23.1",
|
|
45
|
+
"globals": "^16.5.0",
|
|
42
46
|
"gulp": "^5.0.1",
|
|
43
47
|
"gulp-mocha": "^10.0.1",
|
|
44
48
|
"gulp-postcss": "^10.0.0",
|
|
@@ -46,8 +50,11 @@
|
|
|
46
50
|
"sinon": "^21.0.1",
|
|
47
51
|
"sinon-chai": "^4.0.1"
|
|
48
52
|
},
|
|
53
|
+
"overrides": {
|
|
54
|
+
"glob": "9.3.5"
|
|
55
|
+
},
|
|
49
56
|
"scripts": {
|
|
50
|
-
"
|
|
51
|
-
"
|
|
57
|
+
"lint": "eslint .",
|
|
58
|
+
"test": "gulp --gulpfile gulpfile.mjs"
|
|
52
59
|
}
|
|
53
60
|
}
|