Skip to content

Commit

Permalink
Refactoring convert.py to improve code maintainability:
Browse files Browse the repository at this point in the history
* Removed global variable, instead used _output_dir.py to store default output location
* Separated getting options from config file and getting options from command-line into two respective functions
* Created get_html_after_body() and get_html_before_body() to get rid of duplicating code in markdown_to_html() and text_to_html()
* Added sys.exit(1) to quit the program after errors occur
  • Loading branch information
kliu57 committed Oct 13, 2023
1 parent d62c0b2 commit 3994512
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 65 deletions.
1 change: 1 addition & 0 deletions _output_dir.py
@@ -0,0 +1 @@
./til
133 changes: 68 additions & 65 deletions convert.py
Expand Up @@ -6,14 +6,12 @@
import shutil
from tomlkit.toml_file import TOMLFile

DEFAULT_OUTPUT = "til"

def print_version():
"""Function prints app version."""
with open("_version.py", "r", encoding="utf-8") as file:
print("go-go-web " + file.read())

def remake_til_folder(out=DEFAULT_OUTPUT):
def remake_til_folder(out):
"""Function removes existing default output folder and recreates it."""
# delete default output folder
if os.path.exists(out):
Expand All @@ -38,6 +36,26 @@ def load_config_file(config_file):
print("Error loading or parsing the config file:", exception)
sys.exit(1)

def get_html_before_body(title, css_url):
"""Function returns the html of the page before and up to the <body>"""
html = '<!doctype html>\n'
html += '<html lang="en">\n'
html += '<head>\n'
html += '\t<meta charset="utf-8">\n'
html += '\t<title>{title}</title>\n'
html += '\t<meta name="viewport" content="width=device-width, initial-scale=1">\n'
if css_url:
html += '\t<link rel="stylesheet" href="' + css_url + '">\n'
html += '</head>\n'
html += '<body>\n'
return html

def get_html_after_body():
"""Function returns the html of the page including and following </body>"""
html = '</body>\n'
html += '</html>'
return html

def convert_to_html(path, output_folder, css_url):
"""Function converts a file to html"""
# at slash at end of folder path if it is not there
Expand All @@ -47,7 +65,7 @@ def convert_to_html(path, output_folder, css_url):
# check if output folder is an existing folder
if not os.path.isdir(output_folder):
print("Error: output folder " + output_folder + " is not an existing folder")
return
sys.exit(1)

# split the root and file ext
path_tup = os.path.splitext(path)
Expand All @@ -61,6 +79,7 @@ def convert_to_html(path, output_folder, css_url):
text_to_html(path, file_name, output_folder, css_url)
else:
print("Error: " + path.replace(os.sep, '/') + " was not converted. File extension should be .md or .txt")
sys.exit(1)

def markdown_to_html(path, file_name, output_folder, css_url):
"""Function converts a markdown file to html"""
Expand All @@ -76,19 +95,7 @@ def markdown_to_html(path, file_name, output_folder, css_url):
# open input and output files
with open(path, mode='r', encoding="utf-8") as input_file, open(output_fpath, mode='w', encoding="utf-8") as output_file:

# write html head
output_file.write('<!doctype html>\n')
output_file.write('<html lang="en">\n')
output_file.write('<head>\n')
output_file.write('\t<meta charset="utf-8">\n')
output_file.write(f'\t<title>{title}</title>\n')
output_file.write('\t<meta name="viewport" content="width=device-width, initial-scale=1">\n')
if css_url:
output_file.write(f'\t<link rel="stylesheet" href="{css_url}">\n')
output_file.write('</head>\n')

# write html body
output_file.write('<body>\n')
output_file.write(get_html_before_body(title, css_url))

# read each line in input file
for line in input_file:
Expand Down Expand Up @@ -137,13 +144,11 @@ def markdown_to_html(path, file_name, output_folder, css_url):
# write an empty line to the output file
output_file.write('\n')

# write closing tags
output_file.write('</body>\n')
output_file.write('</html>')
output_file.write(get_html_after_body())

print(path.replace(os.sep, '/') + " converted to " + output_fpath + " successfully!")

def text_to_html(path,file_name, output_folder, css_url):
def text_to_html(path, file_name, output_folder, css_url):
"""Function converts a txt file to html"""
# check if input file has a valid extension
title = os.path.basename(file_name)
Expand All @@ -155,19 +160,7 @@ def text_to_html(path,file_name, output_folder, css_url):
# open input and output files
with open(path, mode='r', encoding="utf-8") as input_file, open(output_fpath, mode='w', encoding="utf-8") as output_file:

# write html head
output_file.write('<!doctype html>\n')
output_file.write('<html lang="en">\n')
output_file.write('<head>\n')
output_file.write('\t<meta charset="utf-8">\n')
output_file.write(f'\t<title>{title}</title>\n')
output_file.write('\t<meta name="viewport" content="width=device-width, initial-scale=1">\n')
if css_url:
output_file.write(f'\t<link rel="stylesheet" href="{css_url}">\n')
output_file.write('</head>\n')

# write html body
output_file.write('<body>\n')
output_file.write(get_html_before_body(title, css_url))

# read each line in input file
for line in input_file:
Expand All @@ -185,15 +178,37 @@ def text_to_html(path,file_name, output_folder, css_url):
# write an empty line to the output file
output_file.write('\n')

# write closing tags
output_file.write('</body>\n')
output_file.write('</html>')
output_file.write(get_html_after_body())

print(path.replace(os.sep, '/') + " converted to " + output_fpath + " successfully!")

def get_default_output_dir():
"""Function returns default output dir specified in _output_dir.py"""
try:
with open("_output_dir.py", "r", encoding="utf-8") as file:
return file.read()
except Exception as error:
print(error)
sys.exit(1)

def parse_config():
"""Function parses config file to return options"""
# Load and parse the TOML configuration file
config = load_config_file(args.config)
return {
"output": config["output"] if "output" in config else get_default_output_dir(),
"stylesheet": config["stylesheet"] if "stylesheet" in config else ""
}

def parse_cmdline():
"""Function parses command-line arguments to return options"""
return {
"output": str(args.output) if args.output else get_default_output_dir(),
"stylesheet": args.stylesheet if args.stylesheet else ""
}

# only triggered when we call this .py file and not during imports
if __name__ == '__main__':

formatter = lambda prog: argparse.HelpFormatter(prog, max_help_position=52)
parser = argparse.ArgumentParser(formatter_class=formatter, description="convert txt or md file or folder of files to html")
parser.add_argument("-v", "--version", action="store_true", help="display the app version")
Expand All @@ -207,40 +222,26 @@ def text_to_html(path,file_name, output_folder, css_url):
print_version()
else:
if args.fname:
# default output folder path and css url
output_folder = DEFAULT_OUTPUT
css_url = None

# get input file path from user input
path = str(args.fname)

# get options from either config file or command line args
if args.config:
# Load and parse the TOML configuration file
config_data = load_config_file(args.config)

# Extract configuration options from the parsed data
if "output" in config_data:
output_folder = str(config_data["output"])
remake_til_folder(output_folder)
if "stylesheet" in config_data:
css_url = str(config_data["stylesheet"])
options = parse_config()
else:
if args.stylesheet:
# get css url from user input
css_url = args.stylesheet

if args.output:
# get output folder path from user input
output_folder = str(args.output)
remake_til_folder(output_folder)
else:
# remove and recreate default output folder
remake_til_folder()
options = parse_cmdline()

# remove and recreate default output folder
try:
remake_til_folder(options["output"])
except Exception as error:
print(f"{error}\n_output_dir.py contains an invalid path")
sys.exit()

# check if the input file or folder path EXISTS
if os.path.isfile(path):
# convert file to html
convert_to_html(path, output_folder, css_url)
convert_to_html(path, options["output"], options["stylesheet"])
elif os.path.isdir(path):
# get each item in the folder
for item in os.listdir(path):
Expand All @@ -250,10 +251,12 @@ def text_to_html(path,file_name, output_folder, css_url):
# check if item is a file
if os.path.isfile(file_path):
# convert file to html
convert_to_html(file_path, output_folder, css_url)
convert_to_html(file_path, options["output"], options["stylesheet"])
else:
print(f"Error: File {path} does not exist\n")
parser.print_help()
sys.exit(1)
else:
print("Error: no file or folder name specified")
parser.print_help()
parser.print_help()
sys.exit(1)

0 comments on commit 3994512

Please sign in to comment.