Skip to content

Instantly share code, notes, and snippets.

@zealfire
Last active May 14, 2017 14:39
Show Gist options
  • Save zealfire/15a3ad5b90f6ffa6724bf27e59da2d27 to your computer and use it in GitHub Desktop.
Save zealfire/15a3ad5b90f6ffa6724bf27e59da2d27 to your computer and use it in GitHub Desktop.
"""
Created by @SaurabhPrakash and @zealfire
Running the file process
In the brandsite virtual env run following command for bpm zips
python manage.py update_bonita_dir <dir>/<subdir>
python manage.py update_bonita_dir ops/cancer-care-proposal-form
By default this command concatenates and minifies js and css file, use a command in this format to disallow this
python manage.py update_bonita_dir <dir>/<subdir> --nooptimize
"""
from django.core.management.base import BaseCommand
from subprocess import call
from bs4 import BeautifulSoup
import os
import zipfile
import fileinput
CODEBASE_ROOT = 'webapp/static/bpm/'
JS_EXTENSION = '.js'
CSS_EXTENSION = '.css'
REPLACE_WORD_DICT = {
'<head>': '',
'</head>': '',
'<body': '<div',
'</body>': '</div>'
}
JS_FILES_NOT_TO_BE_MINIFIED = ['vendor.min.js', 'runtime.min.js']
CSS_FILES_NOT_TO_BE_MINIFIED = ['bootstrap.min.css']
PREFIXES_FOR_EXTERNAL_LINK = ['http', 'https', 'www']
class Command(BaseCommand):
help = 'To add fixtures into the site models'
optimize = True
def read_entirely(self, file):
"""
:param file(file object): file whose content needs to read
returns content of file
"""
if not os.path.isfile(file):
return ''
with open(file, 'r') as handle:
return handle.read()
def is_external_file(self, src):
"""
:param src(string): source to js file which will be parsed
:returns status whether a given file is an external or internal
"""
for prefix in PREFIXES_FOR_EXTERNAL_LINK:
if prefix in src:
return True
def to_be_minified_js_files(self, src):
"""
:param src(string): source to js file which will be parsed
:returns status whether a given needs to be minified or not
"""
for script_name in JS_FILES_NOT_TO_BE_MINIFIED:
if script_name in src:
return False
if JS_EXTENSION not in src or self.is_external_file(src):
return False
return True
def to_be_minified_css_files(self, src):
"""
:param src(string): link to css file which will be parsed
:returns status whether a given needs to be minified or not
"""
for css_file in CSS_FILES_NOT_TO_BE_MINIFIED:
if css_file in src:
return False
if CSS_EXTENSION not in src or self.is_external_file(src):
return False
return True
def concatenate_files(self, directory, folder_name, dest_file_name):
"""
:param directory(string): name of main directory to bonita form
:param folder_name(list): an array of sources to different file
:param dest_file_name(string): final destination to file where content of concatenated files need to written
utiliy function to concatenate files
"""
# over here custom widget related js content is being concatenated and written to a new file
result = '\n'.join(self.read_entirely(file) for file in folder_name)
file = 'webapp/static/bpm/' + directory + '/resources/' + dest_file_name
with open(file, 'w+') as handle:
handle.write(result)
def handle(self, *args, **options):
"""Does following operations:
Unzips the code
Parses html and add relevant static file paths
Removes unnecessary html tags
"""
# setting the optimize flag if user has passed it as argument
if not options['optimize']:
self.optimize = options['optimize']
# Extract the zip file
os.makedirs(CODEBASE_ROOT + options['dir'])
zip_ref = zipfile.ZipFile(CODEBASE_ROOT + options['dir'] + '.zip', 'r')
zip_ref.extractall(CODEBASE_ROOT + options['dir'])
zip_ref.close()
# Reads the html file to correct static paths
file_path = CODEBASE_ROOT + options['dir'] + '/resources/index.html'
BeautifulSoup(open(file_path), "html5lib")
try:
soup = BeautifulSoup(open(CODEBASE_ROOT + options['dir'] + '/resources/index.html'), "html5lib")
pass
except Exception as e:
print("file not found, please check if the location exist:%s%s/resources/index.html " %
(CODEBASE_ROOT, options['dir']))
return None
# performing links related actions
links = soup.find_all('link')
links_to_be_minified = []
for index, link in enumerate(links):
if link.get('href') and self.optimize and self.to_be_minified_css_files(link.get('href')):
link['href'] = 'webapp/static/bpm/' + options['dir'] + '/resources/' + link.get('href')
links_to_be_minified.append(link['href'])
link.extract()
elif link.get('href') and not self.is_external_file(link.get('href')):
link['href'] = '/static/bpm/' + options['dir'] + '/resources/' + link.get('href')
if self.optimize:
try:
self.concatenate_files(options['dir'], links_to_be_minified, 'assets/css/custom_widget_css.css')
# over here concatenated file is being minified
call(["grunt", "minifyBonitaCss", "--fileName=" + options['dir']])
# appending newly created minified custom widget css file
file = '/static/bpm/' + options['dir'] + '/resources/assets/css/custom_widget_css.min.css'
link_tag = soup.new_tag("link", href=file, rel="stylesheet")
soup.head.append(link_tag)
except Exception as e:
print("Error while concatenating and minifying custom widget css" + str(e))
# performing script related actions
scripts = soup.find_all('script')
scripts_to_be_minified = []
for index, script in enumerate(scripts):
if script.get('src') and '/static/bpm/' in script.get('src'):
print('Already updated page, please check')
return
# find custom widget related js file which have not been minified
if script.get('src') and self.to_be_minified_js_files(script['src']) and self.optimize:
script['src'] = 'webapp/static/bpm/' + options['dir'] + '/resources/' + script['src']
scripts_to_be_minified.append(script['src'])
script.extract()
elif script.get('src') and not self.is_external_file(script.get('src')):
script['src'] = '/static/bpm/' + options['dir'] + '/resources/' + script.get('src')
if self.optimize:
try:
self.concatenate_files(options['dir'], scripts_to_be_minified, 'widgets/custom_widget.js')
# over here concatenated file is being minified
call(["grunt", "minifyBonita", "--fileName=" + options['dir']])
# appending newly created minified custom widget js file
file = '/static/bpm/' + options['dir'] + '/resources/widgets/custom_widget.min.js'
script_tag = soup.new_tag("script", src=file)
soup.head.append(script_tag)
except Exception as e:
print("Error while concatenating and minifying custom widget js" + str(e))
soup.title.decompose()
soup.meta.decompose()
soup.meta.decompose()
# removing empty line added in index.html
modified_soup = '\n'.join([line for line in str(soup).split("\n") if line.strip() != ''])
soup = BeautifulSoup(modified_soup, "html5lib")
head = soup.head.extract()
body = soup.body.extract()
f = open(file_path, 'w+')
f.write('%s%s' % (head, body))
f.close()
for k, v in REPLACE_WORD_DICT.items():
with fileinput.FileInput(file_path, inplace=True, backup='.bak') as file:
for line in file:
print(line.replace(k, v), end='')
print("%s BPM file extracted successfully " % (options['dir']))
def add_arguments(self, parser):
parser.add_argument('dir', type=str)
parser.add_argument(
'--nooptimize',
action='store_false',
dest='optimize',
default=True,
help='Flag maintained to decide when to optimize',
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment