Skip to content

Commit 7cb985d

Browse files
committed
fix(html): fix incorrect html class name truncation
1 parent 3c1ca32 commit 7cb985d

File tree

3 files changed

+7
-193
lines changed

3 files changed

+7
-193
lines changed

src/__tests__/html.test.ts

-31
Original file line numberDiff line numberDiff line change
@@ -3,40 +3,9 @@ import type { SelectorConversion } from '../types';
33
import { describe, it, expect } from "vitest";
44

55
import {
6-
findHtmlTagContentsByClass,
76
obfuscateHtmlClassNames,
87
} from "../handlers/html";
98

10-
11-
//! ================================
12-
//! findHtmlTagContentsByClass
13-
//! ================================
14-
15-
/**
16-
* @deprecated
17-
*/
18-
describe("findHtmlTagContentsByClass", () => {
19-
const content = `<body><div class="test1 test2">12345678<div class="test1">901234</div>56789</div><div class="test1 test3">0123456</div></body>`;
20-
21-
it("should return the correct content within the tag that with a given class", () => {
22-
const targetClass = "test1";
23-
24-
const expectedOutput = ['<div class="test1 test2">12345678<div class="test1">901234</div>56789</div>'];
25-
26-
const result = findHtmlTagContentsByClass(content, targetClass);
27-
expect(result).toEqual(expectedOutput);
28-
});
29-
30-
it("should return empty array if no content found", () => {
31-
const targetClass = "test5";
32-
33-
const expectedOutput: unknown[] = [];
34-
35-
const result = findHtmlTagContentsByClass(content, targetClass);
36-
expect(result).toEqual(expectedOutput);
37-
});
38-
});
39-
409
//! ================================
4110
//! obfuscateHtmlClassNames
4211
//! ================================

src/handlers/html.ts

+3-151
Original file line numberDiff line numberDiff line change
@@ -2,153 +2,11 @@ import type { SelectorConversion } from "../types";
22

33
import * as htmlparser2 from "htmlparser2";
44
import { escape as htmlEscape } from "html-escaper";
5-
import { log, obfuscateKeys } from "../utils";
5+
import { obfuscateKeys } from "../utils";
66
import { obfuscateJs } from "./js";
77
import { cssUnescape } from "css-seasoning";
88

9-
/**
10-
* @deprecated
11-
*/
12-
function findHtmlTagContentsRecursive(
13-
content: string,
14-
targetTag: string,
15-
targetClass: string | null = null,
16-
foundTagContents: string[] = [],
17-
deep = 0,
18-
maxDeep = -1,
19-
) {
20-
let contentAfterTag = content;
21-
const startTagWithClassRegexStr = targetClass
22-
? // ref: https://stackoverflow.com/a/16559544
23-
`(<\\w+?\\s+?class\\s*=\\s*['\"][^'\"]*?\\b${targetClass}\\b)`
24-
: "";
25-
const startTagRegexStr = `(<${targetTag}[\\s|>])`;
26-
const endTagRegexStr = `(<\/${targetTag}>)`;
27-
28-
// clear content before the start tag
29-
const clearContentBeforeStartTagRegex = new RegExp(
30-
`${startTagWithClassRegexStr ? startTagWithClassRegexStr + ".*|" + startTagRegexStr : startTagRegexStr + ".*"}`,
31-
"i",
32-
);
33-
const contentAfterStartTagMatch = contentAfterTag.match(
34-
clearContentBeforeStartTagRegex,
35-
);
36-
if (contentAfterStartTagMatch) {
37-
contentAfterTag = contentAfterStartTagMatch[0];
38-
}
39-
40-
let endTagCont = 0;
41-
42-
const endTagContRegex = new RegExp(endTagRegexStr, "gi");
43-
const endTagContMatch = contentAfterTag.match(endTagContRegex);
44-
if (endTagContMatch) {
45-
endTagCont = endTagContMatch.length;
46-
}
47-
48-
let closeTagPoition = 0;
49-
50-
const tagPatternRegex = new RegExp(
51-
`${startTagWithClassRegexStr ? startTagWithClassRegexStr + "|" + startTagRegexStr : startTagRegexStr}|${endTagRegexStr}`,
52-
"gi",
53-
);
54-
const tagPatternMatch = contentAfterTag.match(tagPatternRegex);
55-
if (tagPatternMatch) {
56-
let tagCount = 0;
57-
let markedPosition = false;
58-
for (let i = 0; i < tagPatternMatch.length; i++) {
59-
if (tagPatternMatch[i].startsWith("</")) {
60-
if (!markedPosition) {
61-
closeTagPoition = endTagCont - tagCount;
62-
markedPosition = true;
63-
}
64-
tagCount--;
65-
} else {
66-
tagCount++;
67-
}
68-
if (tagCount == 0) {
69-
break;
70-
}
71-
}
72-
}
73-
74-
// match the last html end tag of all content and all content before it
75-
const tagEndRegex = new RegExp(`(.*)${endTagRegexStr}`, "i");
76-
77-
for (let i = 0; i < closeTagPoition; i++) {
78-
const tagCloseMatch = contentAfterTag.match(tagEndRegex);
79-
if (tagCloseMatch) {
80-
contentAfterTag = tagCloseMatch[1];
81-
}
82-
}
83-
84-
const clearContentAfterCloseTagRegex = new RegExp(`.*${endTagRegexStr}`, "i");
85-
const clearContentAfterCloseTagMatch = contentAfterTag.match(
86-
clearContentAfterCloseTagRegex,
87-
);
88-
if (clearContentAfterCloseTagMatch) {
89-
contentAfterTag = clearContentAfterCloseTagMatch[0];
90-
foundTagContents.push(contentAfterTag);
91-
}
92-
93-
// replace the contentAfterTag in content with ""
94-
// only replace the first match
95-
const remainingHtmlRegex = new RegExp(
96-
contentAfterTag.replace(/[-\/\\^$*+?.()|[\]{}]/g, "\\$&") + "(.*)",
97-
"i",
98-
);
99-
const remainingHtmlMatch = content.match(remainingHtmlRegex);
100-
if (remainingHtmlMatch) {
101-
const remainingHtml = remainingHtmlMatch[1];
102-
// check if any html tag is left
103-
const remainingHtmlTagRegex = new RegExp(`(<\\w+?>)`, "i");
104-
const remainingHtmlTagMatch = remainingHtml.match(remainingHtmlTagRegex);
105-
if (remainingHtmlTagMatch) {
106-
if (maxDeep === -1 || deep < maxDeep) {
107-
return findHtmlTagContentsRecursive(
108-
remainingHtml,
109-
targetTag,
110-
targetClass,
111-
foundTagContents,
112-
deep + 1,
113-
maxDeep,
114-
);
115-
}
116-
log("warn", "HTML search:", "Max deep reached, recursive break");
117-
return foundTagContents;
118-
}
119-
}
120-
121-
return foundTagContents;
122-
}
123-
124-
/**
125-
* @deprecated
126-
*/
127-
function findHtmlTagContents(
128-
content: string,
129-
targetTag: string,
130-
targetClass: string | null = null,
131-
) {
132-
return findHtmlTagContentsRecursive(content, targetTag, targetClass);
133-
}
134-
135-
/**
136-
* @deprecated
137-
*/
138-
function findHtmlTagContentsByClass(content: string, targetClass: string) {
139-
const regex = new RegExp(
140-
`(<(\\w+)\\s+class\\s*=\\s*['\"][^'\"]*?\\b${targetClass}\\b)`,
141-
"i",
142-
);
143-
const match = content.match(regex);
144-
if (match) {
145-
const tag = match[2];
146-
return findHtmlTagContents(content, tag, targetClass);
147-
}
148-
return [];
149-
}
150-
151-
function obfuscateHtmlClassNames({
9+
export const obfuscateHtmlClassNames = ({
15210
html,
15311
selectorConversion,
15412
obfuscateMarkerClass = "",
@@ -158,7 +16,7 @@ function obfuscateHtmlClassNames({
15816
selectorConversion: SelectorConversion;
15917
obfuscateMarkerClass?: string;
16018
contentIgnoreRegexes?: RegExp[];
161-
}) {
19+
}) => {
16220
const voidTags = [
16321
"area",
16422
"base",
@@ -295,9 +153,3 @@ function obfuscateHtmlClassNames({
295153
usedKeys: Array.from(new Set(usedKeys)),
296154
};
297155
}
298-
299-
export {
300-
findHtmlTagContents,
301-
findHtmlTagContentsByClass,
302-
obfuscateHtmlClassNames,
303-
};

src/utils.ts

+4-11
Original file line numberDiff line numberDiff line change
@@ -267,12 +267,12 @@ const replaceJsonKeysInFiles = (
267267
// });
268268
}
269269

270-
function obfuscateKeys(
270+
const obfuscateKeys = (
271271
selectorConversion: SelectorConversion,
272272
fileContent: string,
273273
contentIgnoreRegexes: RegExp[] = [],
274274
useHtmlEntity: boolean = false
275-
) {
275+
) => {
276276
//ref: https://github.com/n4j1Br4ch1D/postcss-obfuscator/blob/main/utils.js
277277

278278
const usedKeys = new Set<string>();
@@ -281,20 +281,13 @@ function obfuscateKeys(
281281
// let keyUse = escapeRegExp(key.slice(1).replace(/\\/g, ""));
282282
let keyUse = cssUnescape(key).slice(1);
283283

284-
//! deprecated
285-
// if (useHtmlEntity) {
286-
// const regex = new RegExp(`(${Object.keys(HTML_CHARACTER_ENTITY_CONVERSION).join("|")})`, "g");
287-
// keyUse = keyUse.replace(regex, (m: string) => {
288-
// return HTML_CHARACTER_ENTITY_CONVERSION[m]
289-
// });
290-
// }
291-
keyUse = escapeRegExp(keyUse.replace(/\\/g, ""));
284+
keyUse = escapeRegExp(keyUse.replace(/\\/g, "")); // escape the key
292285

293286
//? sample: "text-sm w-full\n text-right\n p-2 flex gap-2 hover:bg-gray-100 dark:hover:bg-red-700 text-right"
294287
let exactMatchRegex = new RegExp(`([\\s"'\\\`]|^)(${keyUse})(?=$|[\\s"'\\\`]|\\\\n|\\\\",|\\\\"})`, 'g'); // match exact wording & avoid ` ' ""
295288
// exactMatchRegex = new RegExp(`([\\s"'\\\`]|^)(${keyUse})(?=$|[\\s"'\\\`])`, 'g'); // match exact wording & avoid ` ' ""
296289

297-
const replacement = `$1` + selectorConversion[key].slice(1).replace(/\\/g, "");
290+
const replacement = `$1` + selectorConversion[key].slice(1).replace(/\\/g, "").slice(1);
298291

299292
const matches = fileContent.match(exactMatchRegex);
300293
const originalObscuredContentPairs = matches?.map((match) => {

0 commit comments

Comments
 (0)