forked from x4nth055/pythoncode-tutorials
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathminimize.py
119 lines (99 loc) · 3.51 KB
/
minimize.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
import cssutils
import re
import logging
import os
import time
cssutils.log.setLevel(logging.CRITICAL)
startTime = time.time()
os.system('cls')
def getFilesByExtension(ext, root):
foundFiles = []
for root, directories, files in os.walk(root):
for f in files:
if f.endswith(ext):
# os.path.join(root, f) is the full path to the file
foundFiles.append(os.path.join(root, f))
return foundFiles
def flattenStyleSheet(sheet):
ruleList = []
for rule in sheet.cssRules:
if rule.typeString == 'MEDIA_RULE':
ruleList += rule.cssRules
elif rule.typeString == 'STYLE_RULE':
ruleList.append(rule)
return ruleList
def findAllCSSClasses():
usedClasses = {}
# Find all used classes
for htmlFile in htmlFiles:
with open(htmlFile, 'r') as f:
htmlContent = f.read()
regex = r'class="(.*?)"'
# re.DOTALL is needed to match newlines
matched = re.finditer(regex, htmlContent, re.MULTILINE | re.DOTALL)
# matched is a list of re.Match objects
for i in matched:
for className in i.groups()[0].split(' '): # i.groups()[0] is the first group in the regex
usedClasses[className] = ''
return list(usedClasses.keys())
def translateUsedClasses(classList):
for i, usedClass in enumerate(classList):
for translation in translations:
# If the class is found in the translations list, replace it
regex = translation[0]
subst = translation[1]
if re.search(regex, usedClass):
# re.sub() replaces the regex with the subst
result = re.sub(regex, subst, usedClass, 1, re.MULTILINE) # 1 is the max number of replacements
# Replace the class in the list
classList[i] = result
return classList
htmlFiles = getFilesByExtension('.html', '.')
cssFiles = getFilesByExtension('.css', 'style')
# Use Translations if the class names in the Markup dont exactly
# match the CSS Selector ( Except for the dot at the begining. )
translations = [
[
'@',
'\\@'
],
[
r"(.*?):(.*)",
r"\g<1>\\:\g<2>:\g<1>",
],
[
r"child(.*)",
"child\\g<1> > *",
],
]
usedClasses = findAllCSSClasses()
usedClasses = translateUsedClasses(usedClasses)
output = 'min.css'
newCSS = ''
for cssFile in cssFiles:
# Parse the CSS File
sheet = cssutils.parseFile(cssFile)
rules = flattenStyleSheet(sheet)
noClassSelectors = []
for rule in rules:
for usedClass in usedClasses:
if '.' + usedClass == rule.selectorText:
# If the class is used in the HTML, add it to the new CSS
usedClasses.remove(usedClass) # Remove the class from the list
if rule.parentRule:
newCSS += str(rule.parentRule.cssText)
else:
newCSS += str(rule.cssText)
if rule.selectorText[0] != '.' and not rule.selectorText in noClassSelectors:
# If the selector doesnt start with a dot and is not already in the list,
# add it
noClassSelectors.append(rule.selectorText)
if rule.parentRule:
newCSS += str(rule.parentRule.cssText)
else:
newCSS += str(rule.cssText)
newCSS = newCSS.replace('\n', '')
newCSS = newCSS.replace(' ', '')
with open(output, 'w') as f:
f.write(newCSS)
print('TIME TOOK: ', time.time() - startTime)