Last active
May 14, 2017 14:39
-
-
Save zealfire/15a3ad5b90f6ffa6724bf27e59da2d27 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
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