@zaininnari/postcss-cachebuster 0.4.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/CHANGELOG.md +5 -0
- package/eslint.config.js +22 -0
- package/index.mjs +72 -14
- package/package.json +6 -1
- 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
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,6 +6,15 @@ 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 = [
|
|
@@ -56,10 +64,17 @@ const plugin = (opts = {}) => {
|
|
|
56
64
|
return cachebuster;
|
|
57
65
|
}
|
|
58
66
|
|
|
59
|
-
|
|
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) {
|
|
60
75
|
let assetPath = decodeURI(assetUrl.pathname);
|
|
61
76
|
|
|
62
|
-
if (
|
|
77
|
+
if (isRootRelativeButNotProtocolRelative) {
|
|
63
78
|
assetPath = path.join(imagesPath, assetPath);
|
|
64
79
|
} else {
|
|
65
80
|
assetPath = path.join(opts.cssPath || path.dirname(file), assetPath);
|
|
@@ -67,14 +82,22 @@ const plugin = (opts = {}) => {
|
|
|
67
82
|
return assetPath;
|
|
68
83
|
}
|
|
69
84
|
|
|
70
|
-
|
|
71
|
-
|
|
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);
|
|
72
92
|
|
|
73
93
|
// complete url with cachebuster
|
|
74
|
-
const
|
|
94
|
+
const originPath = isRootRelativeButNotProtocolRelative ? assetUrl.pathname : assetUrl.pathname.substring(1);
|
|
95
|
+
const cachebuster = createCachebuster(assetPath, originPath, opts.type);
|
|
75
96
|
if (!cachebuster) {
|
|
76
97
|
return;
|
|
77
|
-
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (typeof opts.type === 'function') {
|
|
78
101
|
assetUrl.pathname = cachebuster;
|
|
79
102
|
} else if (assetUrl.search && assetUrl.search.length > 1) {
|
|
80
103
|
assetUrl.search = assetUrl.search + '&' + opts.paramName + cachebuster;
|
|
@@ -83,6 +106,39 @@ const plugin = (opts = {}) => {
|
|
|
83
106
|
}
|
|
84
107
|
}
|
|
85
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
|
+
|
|
86
142
|
return {
|
|
87
143
|
postcssPlugin: 'postcss-cachebuster',
|
|
88
144
|
Once(root) {
|
|
@@ -96,10 +152,10 @@ const plugin = (opts = {}) => {
|
|
|
96
152
|
const quote = results[1] || '"';
|
|
97
153
|
const originalUrl = results[2];
|
|
98
154
|
|
|
99
|
-
const
|
|
100
|
-
updateAssetUrl(
|
|
155
|
+
const parsed = parseUrlPreserveRelative(originalUrl);
|
|
156
|
+
updateAssetUrl(parsed.u, inputFile, parsed.isRootRelativeButNotProtocolRelative, parsed.originalUrl);
|
|
101
157
|
|
|
102
|
-
atrule.params = 'url(' + quote +
|
|
158
|
+
atrule.params = 'url(' + quote + formatUrlPreserveRelative(parsed) + quote + ')';
|
|
103
159
|
});
|
|
104
160
|
|
|
105
161
|
root.walkDecls(function walkThroughtDeclarations(declaration) {
|
|
@@ -111,20 +167,22 @@ const plugin = (opts = {}) => {
|
|
|
111
167
|
declaration.value = declaration.value.replace(pattern, function (match, quote, originalUrl) {
|
|
112
168
|
quote = quote || '"';
|
|
113
169
|
|
|
114
|
-
const
|
|
170
|
+
const parsed = parseUrlPreserveRelative(originalUrl);
|
|
171
|
+
const assetUrl = parsed.u;
|
|
115
172
|
|
|
116
173
|
// only locals
|
|
117
174
|
if (
|
|
118
|
-
assetUrl.
|
|
175
|
+
assetUrl.toString().indexOf(DUMMY_BASE) !== 0 ||
|
|
176
|
+
parsed.isAbsolute ||
|
|
119
177
|
assetUrl.pathname.indexOf('//') === 0 ||
|
|
120
178
|
assetUrl.pathname.indexOf(';base64') !== -1
|
|
121
179
|
) {
|
|
122
180
|
return match;
|
|
123
181
|
}
|
|
124
182
|
|
|
125
|
-
updateAssetUrl(assetUrl, inputFile);
|
|
183
|
+
updateAssetUrl(assetUrl, inputFile, parsed.isRootRelativeButNotProtocolRelative);
|
|
126
184
|
|
|
127
|
-
return 'url(' + quote +
|
|
185
|
+
return 'url(' + quote + formatUrlPreserveRelative(parsed) + quote + ')';
|
|
128
186
|
});
|
|
129
187
|
});
|
|
130
188
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zaininnari/postcss-cachebuster",
|
|
3
|
-
"version": "0.4.
|
|
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",
|
|
@@ -50,6 +54,7 @@
|
|
|
50
54
|
"glob": "9.3.5"
|
|
51
55
|
},
|
|
52
56
|
"scripts": {
|
|
57
|
+
"lint": "eslint .",
|
|
53
58
|
"test": "gulp --gulpfile gulpfile.mjs"
|
|
54
59
|
}
|
|
55
60
|
}
|