Skip to content

Commit f659975

Browse files
committed
feat: allow options to customize pattern and hash length
1 parent 4543dfd commit f659975

2 files changed

Lines changed: 90 additions & 46 deletions

File tree

src/plugin.ts

Lines changed: 40 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -4,60 +4,62 @@ import { PostHTML } from "posthtml";
44
import hasha from "hasha";
55

66
const DEFAULT_HASH_LENGTH = 20;
7-
const REGEX_HASH = new RegExp(/\[hash.*]/g);
7+
const DEFAULT_PATTERN = new RegExp(/\[hash.*]/g);
88

9-
export function replaceHash(str: string, buffer: Buffer) {
10-
const match = str.match(REGEX_HASH);
9+
export function replaceHash(
10+
str: string,
11+
buffer: Buffer,
12+
exp: RegExp,
13+
hashLength: number
14+
) {
15+
const match = str.match(exp);
1116
const [_, len] = match![0].replace(/\[|]/g, "").split(":");
1217

13-
return str.replace(
14-
REGEX_HASH,
15-
hasha(buffer).slice(0, Number(len) || DEFAULT_HASH_LENGTH)
16-
);
18+
return str.replace(exp, hasha(buffer).slice(0, Number(len) || hashLength));
1719
}
1820

1921
type NodeWithHashRegex = { attrs: { href?: string; src?: string } };
2022

21-
function plugin(options?: { path?: string }) {
23+
function plugin(options?: {
24+
path?: string;
25+
hashLength?: number;
26+
pattern?: RegExp;
27+
}) {
2228
return function posthtmlHash(tree: PostHTML.Node) {
23-
tree.match(
24-
[{ attrs: { href: REGEX_HASH } }, { attrs: { src: REGEX_HASH } }],
25-
(node) => {
26-
const _node = (node as unknown) as NodeWithHashRegex;
27-
const { href, src } = _node.attrs;
29+
const exp = options?.pattern || DEFAULT_PATTERN;
30+
const hashLength = options?.hashLength || DEFAULT_HASH_LENGTH;
2831

29-
let fileName = "";
32+
tree.match([{ attrs: { href: exp } }, { attrs: { src: exp } }], (node) => {
33+
const _node = (node as unknown) as NodeWithHashRegex;
34+
const { href, src } = _node.attrs;
3035

31-
if (href) {
32-
fileName = href;
33-
} else if (src) {
34-
fileName = src;
35-
}
36+
let fileName = "";
3637

37-
const pathToFile = options?.path || "";
38-
const file = path.join(process.cwd(), pathToFile, fileName);
38+
if (href) {
39+
fileName = href;
40+
} else if (src) {
41+
fileName = src;
42+
}
3943

40-
if (fs.existsSync(file)) {
41-
const buffer = fs.readFileSync(file);
42-
const hashedFileName = replaceHash(fileName, buffer);
43-
const hashedFile = path.join(
44-
process.cwd(),
45-
pathToFile,
46-
hashedFileName
47-
);
44+
const pathToFile = options?.path || "";
45+
const file = path.join(process.cwd(), pathToFile, fileName);
4846

49-
fs.renameSync(file, hashedFile);
47+
if (fs.existsSync(file)) {
48+
const buffer = fs.readFileSync(file);
49+
const hashedFileName = replaceHash(fileName, buffer, exp, hashLength);
50+
const hashedFile = path.join(process.cwd(), pathToFile, hashedFileName);
5051

51-
if (href) {
52-
_node.attrs.href = hashedFileName;
53-
} else if (src) {
54-
_node.attrs.src = hashedFileName;
55-
}
56-
}
52+
fs.renameSync(file, hashedFile);
5753

58-
return node;
54+
if (href) {
55+
_node.attrs.href = hashedFileName;
56+
} else if (src) {
57+
_node.attrs.src = hashedFileName;
58+
}
5959
}
60-
);
60+
61+
return node;
62+
});
6163
};
6264
}
6365

src/tests/plugin.test.ts

Lines changed: 50 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,24 +4,66 @@ import fs from "fs";
44
import path from "path";
55
import posthtml from "posthtml";
66

7+
if (!fs.existsSync("src/tests/__fixtures__/processed")) {
8+
fs.mkdirSync("src/tests/__fixtures__/processed");
9+
}
10+
711
const buffer = fs.readFileSync(
812
path.resolve(__dirname, "__fixtures__/original/bundle.min.[hash].js")
913
);
1014

11-
test.equal(replaceHash("[hash].js", buffer), "b0dcc67ffc1fd562f212.js");
15+
const DEFAULT_HASH_LENGTH = 20;
16+
const DEFAULT_PATTERN = new RegExp(/\[hash.*]/g);
17+
18+
test.equal(
19+
replaceHash("[hash].js", buffer, DEFAULT_PATTERN, DEFAULT_HASH_LENGTH),
20+
"b0dcc67ffc1fd562f212.js"
21+
);
1222
test.equal(
13-
replaceHash("script.[hash].js", buffer),
23+
replaceHash("script.[hash].js", buffer, DEFAULT_PATTERN, DEFAULT_HASH_LENGTH),
1424
"script.b0dcc67ffc1fd562f212.js"
1525
);
1626
test.equal(
17-
replaceHash("script.[hash:20].js", buffer),
27+
replaceHash(
28+
"script.[hash:20].js",
29+
buffer,
30+
DEFAULT_PATTERN,
31+
DEFAULT_HASH_LENGTH
32+
),
1833
"script.b0dcc67ffc1fd562f212.js"
1934
);
20-
test.equal(replaceHash("script.[hash:8].js", buffer), "script.b0dcc67f.js");
21-
test.throws(() => replaceHash("script.js", buffer));
22-
test.throws(() => replaceHash("script[].js", buffer));
23-
test.throws(() => replaceHash("script.[has:8].js", buffer));
24-
test.throws(() => replaceHash("script.js", buffer));
35+
test.equal(
36+
replaceHash(
37+
"script.[hash:8].js",
38+
buffer,
39+
DEFAULT_PATTERN,
40+
DEFAULT_HASH_LENGTH
41+
),
42+
"script.b0dcc67f.js"
43+
);
44+
test.throws(() =>
45+
replaceHash("script.js", buffer, DEFAULT_PATTERN, DEFAULT_HASH_LENGTH)
46+
);
47+
test.throws(() =>
48+
replaceHash("script[].js", buffer, DEFAULT_PATTERN, DEFAULT_HASH_LENGTH)
49+
);
50+
test.throws(() =>
51+
replaceHash("script.[has:8].js", buffer, DEFAULT_PATTERN, DEFAULT_HASH_LENGTH)
52+
);
53+
test.throws(() =>
54+
replaceHash("script.js", buffer, DEFAULT_PATTERN, DEFAULT_HASH_LENGTH)
55+
);
56+
57+
const CUSTOM_EXP = new RegExp(/\[oh-my-hash.*]/g);
58+
59+
test.equal(
60+
replaceHash("[oh-my-hash].js", buffer, CUSTOM_EXP, DEFAULT_HASH_LENGTH),
61+
"b0dcc67ffc1fd562f212.js"
62+
);
63+
test.equal(
64+
replaceHash("script.[oh-my-hash].js", buffer, CUSTOM_EXP, 8),
65+
"script.b0dcc67f.js"
66+
);
2567

2668
function copyFixture(fileName: string) {
2769
const file = path.join(__dirname, "__fixtures__/original", fileName);

0 commit comments

Comments
 (0)