kamitkami.py 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. '''
  2. KamitKami gives a smaller css to be included with html file for faster website loading times.
  3. Copyright (C) 2021 Sagar Acharya
  4. This program is free software: you can redistribute it and/or modify
  5. it under the terms of the GNU Affero General Public License as
  6. published by the Free Software Foundation, either version 3 of the
  7. License.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU Affero General Public License for more details.
  12. You should have received a copy of the GNU Affero General Public License
  13. along with this program. If not, see <https://www.gnu.org/licenses/>.
  14. '''
  15. import sys, os, re
  16. #import soupsieve
  17. from bs4 import BeautifulSoup
  18. # changes working directory to script directory
  19. os.chdir(os.getcwd())
  20. # get arguments from terminal to list
  21. names = sys.argv[1:]
  22. # list which keeps some attributes as they are within css file
  23. nofilter = ["*", "html", "body", ":root", "head"]
  24. # checks whether number of arguments are correct
  25. if len(names)!=2:
  26. print("Please input only 2 arguments, css filename and html filename")
  27. sys.exit()
  28. # checks if files exist in current directory
  29. if not (os.path.isfile(names[0]+'.css') and os.path.isfile(names[1]+'.html')):
  30. print("Please input correct names of css and html files. Files do not exist.")
  31. sys.exit()
  32. with open(names[0]+'.css') as temp:
  33. css = temp.read()
  34. with open(names[1]+'.html') as temp:
  35. html = temp.read()
  36. soup = BeautifulSoup(html, 'html.parser')
  37. def divide_elem_blocks(css_string):
  38. _import = ["@import" + x + ";" for x in re.findall(r'@import(.*?);', css_string)]
  39. for i in _import:
  40. css_string = css_string.replace(i, "")
  41. selectors = []
  42. blocks = []
  43. num_curly = 0
  44. start = False
  45. record = ["", ""]
  46. for i in css_string:
  47. if start:
  48. if (i == '{'):
  49. num_curly +=1
  50. record[1] +=i
  51. elif (i == '}' and num_curly == 0):
  52. selectors.append(record[0])
  53. blocks.append(record[1])
  54. record = ["", ""]
  55. start = False
  56. elif (i == '}' and num_curly > 0):
  57. num_curly -=1
  58. else:
  59. record[1]+=i
  60. else:
  61. if (i == '{'):
  62. start = True
  63. else:
  64. record[0]+=i
  65. if (i == '{' and num_curly == 0):
  66. start = True
  67. return _import, selectors, blocks
  68. # filters C type comments
  69. css = re.sub('\/\*(\*(?!\/)|[^*])*\*\/', '', css)
  70. css = css.replace("\n", "")
  71. # selectors and blocks have same length and correspond to each other
  72. _import, selectors, blocks = divide_elem_blocks(css)
  73. notImplemented = 0
  74. syntaxError = 0
  75. other = 0
  76. noFind = 0
  77. with open(names[1]+"_"+names[0]+".css", 'w') as f:
  78. for i in _import:
  79. f.write(i)
  80. for i in range(len(selectors)):
  81. if i in nofilter:
  82. f.write(selectors[i]+'{'+blocks[i]+'}\n')
  83. continue
  84. try:
  85. temp = soup.select(selectors[i])
  86. if len(temp)>0:
  87. f.write(selectors[i]+'{'+blocks[i]+'}\n')
  88. else:
  89. noFind +=1
  90. #print("Didn't find "+selectors[i])
  91. pass
  92. except:
  93. f.write(selectors[i]+'{'+blocks[i]+'}\n')
  94. other +=1
  95. '''
  96. print(selectors[i])
  97. print(soup.select(selectors[i]))
  98. except NotImplementedError:
  99. notImplemented +=1
  100. f.write(selectors[i]+'{'+blocks[i]+'}\n')
  101. except soupsieve.util.SelectorSyntaxError:
  102. syntaxError +=1
  103. f.write(selectors[i]+'{'+blocks[i]+'}\n')
  104. '''
  105. #Lines which Beautiful soup cannot detect as css
  106. print("Error : "+str((notImplemented + syntaxError + other)*100/len(selectors))+ "%")
  107. #Number of lines of css selectors removed as a % of all css selector lines
  108. print("Removed : "+str(noFind*100/len(selectors))+ "% lines from css file.")
  109. #minify