diff --git a/zundler/__main__.py b/zundler/__main__.py index 8f370e6..e240235 100644 --- a/zundler/__main__.py +++ b/zundler/__main__.py @@ -2,13 +2,19 @@ def main(): from .args import parse_args args = parse_args() - from .embed import embed_assets - embed_assets( - args.input_path, - output_path=args.output_path, - append_pre=args.append_pre, - append_post=args.append_post, - ) + from .embed import embed_assets, extract_assets + if args.revert: + extract_assets( + args.input_path, + output_path=args.output_path, + ) + else: + embed_assets( + args.input_path, + output_path=args.output_path, + append_pre=args.append_pre, + append_post=args.append_post, + ) if __name__ == "__main__": diff --git a/zundler/args.py b/zundler/args.py index 874ea87..33dd538 100644 --- a/zundler/args.py +++ b/zundler/args.py @@ -25,6 +25,14 @@ parser.add_argument( version=__version__, ) +parser.add_argument( + '-R', '--revert', + default=False, + action='store_true', + help='set this flag for the reverse operation: deflate a Zundler file' + ' into its components (ouput_path must be a directory; "." by default)', +) + parser.add_argument( '-P', '--append-pre', default="", diff --git a/zundler/embed.py b/zundler/embed.py index 625c41d..4e92b75 100644 --- a/zundler/embed.py +++ b/zundler/embed.py @@ -22,6 +22,7 @@ import json import logging import os from pathlib import Path +import re import zlib SCRIPT_PATH = os.path.abspath(os.path.dirname(__file__)) @@ -211,7 +212,6 @@ def embed_css_resources(css, filename): Also, handle @import.""" # This uses some heuristics which will fail in general. # Eventually a library like tinycss2 might be preferable. - import re # First, make sure all @import's are using url(), because these are both valid: # @import url("foo.css"); @@ -307,3 +307,41 @@ def load_filetree(base_dir, before=None, after=None, exclude_pattern=None): logger.debug('Packed file %s [%d]' % (key, len(result[key]))) return result + + +def extract_assets(input_path, output_path=None): + """Split a file generated by Zundler into its constituents + + Import for debugging""" + + if not output_path: + output_path = '.' + + html = open(input_path, 'r').read() + + try: + # Find large base64 blob + m = re.search('.*.*', html) + blob = m['blob'] + blob = base64.b64decode(blob) + blob = zlib.decompress(blob).decode() + blob = json.loads(blob) + file_tree = blob['file_tree'] + except Exception as e: + logger.error(str(e)) + logger.error("Does not look like a Zundler output file: %s" % input_path) + exit(1) + + for filename, file in file_tree.items(): + filename = os.path.join(output_path, filename) + os.makedirs(os.path.dirname(filename) or '.', exist_ok=True) + data = file['data'] + if file['base64encoded']: + data = base64.b64decode(data) + else: + data = data.encode() + open(filename, 'wb').write(data) + file['data'] = file['data'][:100] + '...' + + with open(os.path.join(output_path, 'file_tree.json'), 'w') as fp: + json.dump(file_tree, fp, indent=2)