From 3aae5954f2ebc69c5a163365ec999bc2a3ca43e3 Mon Sep 17 00:00:00 2001 From: Dave Kliczbor Date: Sat, 24 Nov 2018 17:20:35 +0100 Subject: [PATCH 1/2] Cleaned up git status, cleaned prepare_static_ui_sources.py, mentioned the latter in README --- .gitignore | 7 ++++ README.md | 2 +- examples/gui/data/index.min.htm | 1 + tools/prepare_static_ui_sources.py | 59 ++++++++++++++++++++++-------- 4 files changed, 52 insertions(+), 17 deletions(-) create mode 100644 examples/gui/data/index.min.htm diff --git a/.gitignore b/.gitignore index ad7d22a..fa842ad 100644 --- a/.gitignore +++ b/.gitignore @@ -26,3 +26,10 @@ Network Trash Folder Temporary Items .apdisk + +# Linux +# ========================= + +# Backup files produced by some editors +*~ +*.bak diff --git a/README.md b/README.md index f345ed2..952483b 100644 --- a/README.md +++ b/README.md @@ -159,7 +159,7 @@ The library is designed to be easy to use and can still be extended with a lot o # Notes for Development -All changes to the client side files can be made in the examples/gui/data directory. Using the file uploader thin can be used for development. After this you have to compress them and then you can gzip them. I wrote a little useful jsfiddle for this, [CHECK IT OUT](https://jsfiddle.net/s00500/yvLbhuuv/) +All changes to the client side files can be made in the `examples/gui/data` directory. Using the file uploader then can be used for development. After this you have to compress them and then you can gzip them. I wrote a little useful jsfiddle for this, [CHECK IT OUT](https://jsfiddle.net/s00500/yvLbhuuv/)... or there is the `prepare_static_ui_sources.py` script in the `tools` directory, if you have a python3 environment available (you also need the modules jsmin, htmlmin and csscompressor). # Contribute Liked this Library? You can **support** me by sending me a :coffee: [Coffee](https://paypal.me/lukasbachschwell/3). diff --git a/examples/gui/data/index.min.htm b/examples/gui/data/index.min.htm new file mode 100644 index 0000000..b135bf6 --- /dev/null +++ b/examples/gui/data/index.min.htm @@ -0,0 +1 @@ + Control

Control
Offline


\ No newline at end of file diff --git a/tools/prepare_static_ui_sources.py b/tools/prepare_static_ui_sources.py index 5be705e..dbac7ad 100755 --- a/tools/prepare_static_ui_sources.py +++ b/tools/prepare_static_ui_sources.py @@ -19,21 +19,27 @@ const uint8_t {constant}_GZIP[{gziplen}] PROGMEM = {{ {gzipdata} }}; def parse_arguments(args=None): parser = argparse.ArgumentParser( - description="Prepares ESPUI header files by minifying and gzipping JS and CSS source files.") - parser.add_argument("--sources", "-s", dest="sources", default="../examples/gui/data", - help="Sources directory containing CSS or JS files") - parser.add_argument("--target", "-t", dest="target", default="../src", - help="Target directory containing header files") + 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", + help="Automatically find all source files in examples/gui/data/ and write C header files to src/") + parser.add_argument("--source", "--sources", "-s", dest="sources", default=None, + help="Sources directory containing CSS or JS files OR one specific file to minify") + parser.add_argument("--target", "-t", dest="target", default=None, + help="Target directory containing C header files OR one C header file") parser.add_argument("--nostoremini", "-m", action="store_false", dest="storemini", - help="Store intermediate minified files") + help="Do not store intermediate minified (but not gzipped) files next to the originals") args = parser.parse_args(args) + if not args.auto and (not args.sources or not args.target): + print("ERROR: You need to specify either --auto or both --source and --target\n") + parser.print_help() + sys.exit(1) return args def get_context(infile, outfile): 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(".") - if dir == type: + type = type.strip(".").lower() + if dir.lower() == type: dir = os.path.basename(os.path.dirname(os.path.dirname(infile))) if type == "htm": type = 'html' @@ -60,7 +66,11 @@ def perform_gzip(c): def perform_minify(c): with open(c['infile']) as infile: - minifier = cssminify if c['type'] == 'css' else jsminify if c['type'] == 'js' else htmlminify + minifier = { + 'css': cssminify, + 'js': jsminify, + 'html': htmlminify + }.get(c['type']) or htmlminify print(" Using %s minifier" % c['type']) c['minidata'] = minifier(infile.read()) return perform_gzip(c) @@ -93,15 +103,32 @@ def process_dir(sourcedir, outdir, recursive=True, storemini=True): process_file(f, outdir, storemini) elif not os.path.isfile(f.replace(".min.", ".")): process_file(f, outdir, storemini) + +def check_args(args): + abort = 0 + if not os.path.exists(args.sources): + print("ERROR: Source %s does not exist" % args.sources) + abort += 2 + if not os.path.isdir(os.path.dirname(args.target)): + print("ERROR: Parent directory of target %s does not exist" % args.target) + abort += 4 + if os.path.isdir(args.sources) and not os.path.isdir(args.target): + print("ERROR: Source %s is a directory, target %s is not" % (args.sources, args.target)) + abort += 8 + if abort > 0: + print("Aborting.") + sys.exit(abort) def main(args): - if not args.sources is None: - if os.path.isfile(args.sources): - print("Source %s is a file, will process one file only." % args.sources) - process_file(args.sources, args.target, storemini = args.storemini) - elif os.path.isdir(args.sources): - print("Source %s is a directory, searching for files recursively..." % args.sources) - process_dir(args.sources, args.target, recursive = True, storemini = args.storemini) + args.sources = os.path.realpath(args.sources or os.sep.join((os.path.dirname(os.path.realpath(__file__)), "..", "examples", "gui", "data"))) + args.target = os.path.realpath(args.target or os.sep.join((os.path.dirname(os.path.realpath(__file__)), "..", "src"))) + check_args(args) + if os.path.isfile(args.sources): + print("Source %s is a file, will process one file only." % args.sources) + process_file(args.sources, args.target, storemini = args.storemini) + elif os.path.isdir(args.sources): + print("Source %s is a directory, searching for files recursively..." % args.sources) + process_dir(args.sources, args.target, recursive = True, storemini = args.storemini) if __name__ == "__main__" and "get_ipython" not in dir(): main(parse_arguments()) From 9b41a0f8b84f22ae80a556a9fb8acc659e44482d Mon Sep 17 00:00:00 2001 From: Dave Kliczbor Date: Sun, 25 Nov 2018 00:32:23 +0100 Subject: [PATCH 2/2] Clarified help strings and README --- README.md | 11 +++++++++-- tools/prepare_static_ui_sources.py | 2 +- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 952483b..8090091 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,7 @@ Download the [Repository](https://github.com/s00500/ESPUI/archive/master.zip), G ## Getting started -ESPUI serves several Files to the browser to build up its webinterface. This can be achieved in 2 wasy: +ESPUI serves several files to the browser to build up its webinterface. This can be achieved in 2 ways: *PROGMEM* or *SPIFFS* *When `ESPUI.begin()` is called the default is serving files from Memory and ESPUI should work out of the box!* @@ -159,7 +159,14 @@ The library is designed to be easy to use and can still be extended with a lot o # Notes for Development -All changes to the client side files can be made in the `examples/gui/data` directory. Using the file uploader then can be used for development. After this you have to compress them and then you can gzip them. I wrote a little useful jsfiddle for this, [CHECK IT OUT](https://jsfiddle.net/s00500/yvLbhuuv/)... or there is the `prepare_static_ui_sources.py` script in the `tools` directory, if you have a python3 environment available (you also need the modules jsmin, htmlmin and csscompressor). +If you want to work on the HTML/CSS/JS files, do make changes in the `examples/gui/data` directory. When you need to transfer that code to the ESP, run `tools/prepare_static_ui_sources.py -a` (this script needs python3 with the modules htmlmin, jsmin and csscompressor). +This will generate a) minified files next to the original files to be uploaded with the ESP32 sketch data uploader mentioned above and b) the C header files in `src` that contain the minified and gzipped HTML/CSS/JS data (which are used by the **prepareFileSystem** example sketch or when they are served from PROGMEM; see above in the section "Getting started"). +Alternatively, you can duplicate the `examples/gui` directory and work on the copy. Then specify the `--source` and `--target` arguments to the `prepare_static_ui_sources.py` script (run the script without arguments for help). + +If you don't have a python environment, you need to minify and gzip the HTML/CSS/JS files manually. I wrote a little useful jsfiddle for this, [see here](https://jsfiddle.net/s00500/yvLbhuuv/). + +If you change something in HTML/CSS/JS and want to create a pull request, please do include the minified versions and corresponding C header files in your commits. + # Contribute Liked this Library? You can **support** me by sending me a :coffee: [Coffee](https://paypal.me/lukasbachschwell/3). diff --git a/tools/prepare_static_ui_sources.py b/tools/prepare_static_ui_sources.py index dbac7ad..671dd12 100755 --- a/tools/prepare_static_ui_sources.py +++ b/tools/prepare_static_ui_sources.py @@ -27,7 +27,7 @@ def parse_arguments(args=None): parser.add_argument("--target", "-t", dest="target", default=None, help="Target directory containing C header files OR one C header file") parser.add_argument("--nostoremini", "-m", action="store_false", dest="storemini", - help="Do not store intermediate minified (but not gzipped) files next to the originals") + help="Do not store intermediate minified files next to the originals (i.e. only write to the C header files)") args = parser.parse_args(args) if not args.auto and (not args.sources or not args.target): print("ERROR: You need to specify either --auto or both --source and --target\n")