123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158 |
- '''
- KamitKami gives a smaller css to be included with html file for faster website loading times.
- Copyright (C) 2021 Sagar Acharya
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as
- published by the Free Software Foundation, either version 3 of the
- License.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <https://www.gnu.org/licenses/>.
- '''
- import sys, os, re
- from bs4 import BeautifulSoup
- from scrapy.selector import Selector
- from scrapy.http import HtmlResponse
- # changes working directory to script directory
- os.chdir(os.getcwd())
- # get arguments from terminal to list
- names = sys.argv[1:]
- # list which keeps some attributes as they are within css file
- nofilter = ["*", "html", "body", ":root", "head"]
- # checks whether number of arguments are correct
- if len(names)!=2:
- print("Please input only 2 arguments, css filename and html filename")
- sys.exit()
- with open(names[0]+'.css') as temp:
- css = temp.read()
- with open(names[1]+'.html') as temp:
- html = temp.read()
- def divide_elem_blocks(css_string):
- _import = ["@import" + x + ";" for x in re.findall(r'@import(.*?);', css_string)]
- for i in _import:
- css_string = css_string.replace(i, "")
-
- selectors = []
- blocks = []
- num_curly = 0
- start = False
-
- record = ["", ""]
- for i in css_string:
- if start:
- if (i == '{'):
- num_curly +=1
- record[1] +=i
- elif (i == '}' and num_curly == 0):
- selectors.append(record[0])
- blocks.append(record[1])
- record = ["", ""]
- start = False
- elif (i == '}' and num_curly > 0):
- num_curly -=1
- else:
- record[1]+=i
- else:
- if (i == '{'):
- start = True
- else:
- record[0]+=i
- if (i == '{' and num_curly == 0):
- start = True
- return _import, selectors, blocks
- # filters C type comments
- css = re.sub('\/\*(\*(?!\/)|[^*])*\*\/', '', css)
- css = css.replace("\n", "")
- # selectors and blocks have same length and correspond to each other
- _import, selectors, blocks = divide_elem_blocks(css)
- #Scrapy used here to check if a particular css selector is used in html
- response = HtmlResponse(url = 'http://mysite.com', body = html,encoding='utf-8')
- print(response.css('card-container').get()==None)
- def check_css_in_html(response,selector):
- try:
- if response.css(selector).get()!=None:
- return True
- except:pass
- return False
- # filters innermost content between { & }
- #css = re.sub('\{[^{}]*\}', '', css)
- #css = re.sub('\{[^{}]*\}', '', css)
- # skip everything till next comment, take html variable as input and using python-scrapy, find relevant css here, change things at if statement at end
- soup = BeautifulSoup(html, 'html.parser')
- classes = []
- tags = []
- type_elem = []
- for i in soup.find_all(True):
- tags.append(i.name)
- try:
- for j in i.attrs['class']:
- classes.append('.'+j)
- except:
- pass
- try:
- type_elem.append('[type="'+i.attrs['type']+'"')
- except:
- pass
- #found unique list of tags, classes, types used in document (id yet to do)
- classes = list(set(classes))
- tags = [e for e in list(set(tags)) if e not in ('br', 'meta', 'div', 'link', 'html', 'body', 'head')]
- type_elem = list(set(type_elem))
- #keep all selectors:blocks of nofilter list
- # https://www.w3schools.com/cssref/css_selectors.asp
- # Find relevant css tags and according to above formatting,
- # filter irrelevant ones and write keys:blocks to file below.
- # class,class .class.class
- # [hidden]
- # :: , :
- # [type="class"]
- # :hover, active, etc.
- # [^=] [*=]
- # :not(:something)
- with open(names[1]+"_"+names[0]+".css", 'w') as f:
- for i in _import:
- f.write(i)
- for i in selectors:
- #we split the selectors into individual and check them in html
- selector = i.split(',')
- for sel in selector:
- if (check_css_in_html(response,sel)):
- #if even one selector is present in html then we put entry into the output css
- print(i+" selected")
- f.write(i)
- f.write('{')
- f.write(blocks[selectors.index(i)])
- f.write("}\n")
- break
- #minify
|