mirror of
				https://github.com/s00500/ESPUI.git
				synced 2025-10-30 00:13:23 +00:00 
			
		
		
		
	Add code comments in prepare_static_ui_sources.py
This commit is contained in:
		| @@ -1,11 +1,13 @@ | ||||
| #!/usr/bin/env python3 | ||||
|  | ||||
| ### import always available modules | ||||
| import sys | ||||
| import os.path | ||||
| import argparse | ||||
| import re | ||||
| from glob import glob | ||||
|  | ||||
| ### import not always installed modules | ||||
| missing = [] | ||||
| try: | ||||
|     from jsmin import jsmin as jsminify | ||||
| @@ -24,6 +26,7 @@ try: | ||||
| except ModuleNotFoundError as e: | ||||
|     missing.append(e) | ||||
| if len(missing) > 0: | ||||
|     # ERROR: at least one module is missing | ||||
|     for m in missing: | ||||
|         print("Cannot find module '%s'." % m.name) | ||||
|     print("Can't find %s required python module%s. Please install %s. If you're not sure how, a web search" % (len(missing), "s" if len(missing) > 1 else "", "them" if len(missing) > 1 else "it")) | ||||
| @@ -32,6 +35,8 @@ if len(missing) > 0: | ||||
|     print("Here's the long documentation: https://packaging.python.org/tutorials/installing-packages/") | ||||
|     sys.exit(0) | ||||
|  | ||||
|  | ||||
| ### String template for C header files | ||||
| TARGET_TEMPLATE = '''const char {constant}[] PROGMEM = R"=====( | ||||
| {minidata} | ||||
| )====="; | ||||
| @@ -39,7 +44,9 @@ TARGET_TEMPLATE = '''const char {constant}[] PROGMEM = R"=====( | ||||
| const uint8_t {constant}_GZIP[{gziplen}] PROGMEM = {{ {gzipdata} }}; | ||||
| ''' | ||||
|  | ||||
|  | ||||
| def parse_arguments(args=None): | ||||
|     """ Command line argument parser definitions """ | ||||
|     parser = argparse.ArgumentParser( | ||||
|         description="Prepares ESPUI header files by minifying and gzipping HTML, JS and CSS source files.") | ||||
|     parser.add_argument("--auto", "--all", "-a", dest="auto", action="store_true", | ||||
| @@ -58,6 +65,20 @@ def parse_arguments(args=None): | ||||
|     return args | ||||
|  | ||||
| def get_context(infile, outfile): | ||||
|     """ This function creates a 'context object': a dictionary containing all the data needed.  | ||||
|     Dictionary members: | ||||
|         infile:		Full path to the input file or directory as given or autodetected | ||||
|         indir:		Full path to the infile parent. | ||||
|         dir:		Full path to the input directory tree (indir or parent of indir). | ||||
|         name:		Filename of infile excluding extension (i.e. filename up until the first dot) | ||||
|         type:		Lowercase extension of infile; one of: html, js, css. | ||||
|         outfile:	Full path to the output file or directory as given or autodetected. | ||||
|         outdir:		Full path to output directory. | ||||
|         outfilename:	Filename of outfile. | ||||
|         minifile:	Full path and filename of the intermediary minified file. | ||||
|         constant:	C header file constant name derived from infile. | ||||
|     If infile == minifile, the input file already is minified (contains ".min.") | ||||
|     """ | ||||
|     infile	= os.path.realpath(infile) | ||||
|     dir, name, type 	= (os.path.basename(os.path.dirname(infile)), os.path.basename(infile).split(os.path.extsep)[0], os.path.basename(infile).split(os.path.extsep)[-1] ) | ||||
|     type = type.strip(".").lower() | ||||
| @@ -80,6 +101,11 @@ def get_context(infile, outfile): | ||||
|     return locals() | ||||
|      | ||||
| def perform_gzip(c): | ||||
|     """ Performs GZIP on c['minidata']. | ||||
|     The returned context object will contain additional fields: | ||||
|         gzipdata:	Comma-separated string of decimal byte values representing gzipped data. | ||||
|         gziplen:	Count of decimal byte values in gzipdata. | ||||
|     """ | ||||
|     compressed = gzip.compress(bytes(c['minidata'], 'utf-8')) | ||||
|     c['gzipdata'] = ','.join([ str(b) for b in compressed ]) | ||||
|     c['gziplen'] = len(compressed) | ||||
| @@ -87,6 +113,9 @@ def perform_gzip(c): | ||||
|     return c | ||||
|      | ||||
| def perform_minify(c): | ||||
|     """ Performs minification on c['infile']. | ||||
|     The returned context object contains the additional field minidata: A string of minified file contents. | ||||
|     """ | ||||
|     with open(c['infile']) as infile: | ||||
|         minifier = { | ||||
|             'css': cssminify,  | ||||
| @@ -95,19 +124,27 @@ def perform_minify(c): | ||||
|         }.get(c['type']) or htmlminify | ||||
|         print("  Using %s minifier" % c['type']) | ||||
|         c['minidata'] = minifier(infile.read()) | ||||
|     return perform_gzip(c) | ||||
|     return c | ||||
|  | ||||
| def process_file(infile, outdir, storemini=True): | ||||
|     """ Processes one file """ | ||||
|     print("Processing file %s" % infile) | ||||
|     # Evaluate file and target context | ||||
|     c = get_context(infile, outdir) | ||||
|     # Minify file data | ||||
|     c = perform_minify(c) | ||||
|     # Gzip minified data | ||||
|     c = perform_gzip(c) | ||||
|      | ||||
|     if storemini: | ||||
|         # Write intermediary minified file | ||||
|         if c['infile'] == c['minifile']: | ||||
|             print("  Original file is already minified, refusing to overwrite it") | ||||
|         else: | ||||
|             print("  Writing minified file %s" % c['minifile']) | ||||
|             with open(c['minifile'], 'w+') as minifile: | ||||
|                 minifile.write(c['minidata']) | ||||
|     # Write minified and gzipped data to C header file | ||||
|     with open(c['outfile'], 'w+') as outfile: | ||||
|         print("  Using C constant names %s and %s_GZIP" % (c['constant'], c['constant'])) | ||||
|         print("  Writing C header file %s" % c['outfile']) | ||||
| @@ -117,6 +154,10 @@ def filenamefilter(pattern, strings): | ||||
|     return filter(re.compile(pattern).search, strings)         | ||||
|          | ||||
| def process_dir(sourcedir, outdir, recursive=True, storemini=True): | ||||
|     """ Processes a directory tree, recursively. Calls process_file on each HTML/CSS/JS file found. | ||||
|     Skips intermediary minified files. Standalone minified files (i.e. files containing ".min." that | ||||
|     do not have a full version) are processed without minifying again. | ||||
|     """ | ||||
|     pattern = r'/*\.(css|js|htm|html)$' | ||||
|     files = glob(sourcedir + "/**/*", recursive=True)+glob(sourcedir + "/*") if recursive else glob(sourcedir + "/*") | ||||
|     files = filenamefilter(pattern, files) | ||||
| @@ -127,6 +168,7 @@ def process_dir(sourcedir, outdir, recursive=True, storemini=True): | ||||
|             process_file(f, outdir, storemini) | ||||
|              | ||||
| def check_args(args): | ||||
|     """ Checks argumental sanity and exits if the arguments are insane. """ | ||||
|     abort = 0 | ||||
|     if not os.path.exists(args.sources): | ||||
|         print("ERROR: Source %s does not exist" % args.sources) | ||||
| @@ -142,8 +184,12 @@ def check_args(args): | ||||
|         sys.exit(abort) | ||||
|  | ||||
| def main(args): | ||||
|     """ main entry point. """ | ||||
|     # default source if not given: realpath(../examples/gui/data) | ||||
|     args.sources = os.path.realpath(args.sources or os.sep.join((os.path.dirname(os.path.realpath(__file__)), "..", "examples", "gui", "data"))) | ||||
|     # default target if not given: realpath(../src) | ||||
|     args.target  = os.path.realpath(args.target  or os.sep.join((os.path.dirname(os.path.realpath(__file__)), "..", "src"))) | ||||
|     # check arguments | ||||
|     check_args(args) | ||||
|     if os.path.isfile(args.sources): | ||||
|         print("Source %s is a file, will process one file only." % args.sources) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Dave Kliczbor
					Dave Kliczbor