Help for web.static.collect

Sample CLI

gway web.static collect

References

Full Code

def collect(*, css="global", js="global", root="data/static", target="work/shared"):
    enabled = getattr(gw.web.app, "enabled_projects", lambda: set())()
    static_root = gw.resource(root)

    def find_files(kind, proj):
        found = []
        seen = set()
        parts = proj.split('.')
        # Recursively walk project path
        if parts:
            proj_path = os.path.join(static_root, *parts)
            for rootdir, dirs, files in os.walk(proj_path):
                rel_root = os.path.relpath(rootdir, static_root)
                for fname in files:
                    if kind == "css" and fname.endswith(".css"):
                        rel = os.path.join(rel_root, fname)
                    elif kind == "js" and fname.endswith(".js"):
                        rel = os.path.join(rel_root, fname)
                    else:
                        continue
                    if rel not in seen:
                        seen.add(rel)
                        found.append((proj, rel, os.path.join(rootdir, fname)))
        # Ancestors, only direct files
        for i in range(len(parts)-1, -1, -1):
            ancestor_path = os.path.join(static_root, *parts[:i])
            if not os.path.isdir(ancestor_path):
                continue
            rel_ancestor = os.path.relpath(ancestor_path, static_root)
            for fname in os.listdir(ancestor_path):
                fpath = os.path.join(ancestor_path, fname)
                if not os.path.isfile(fpath):
                    continue
                if kind == "css" and fname.endswith(".css"):
                    rel = os.path.join(rel_ancestor, fname) if rel_ancestor != "." else fname
                elif kind == "js" and fname.endswith(".js"):
                    rel = os.path.join(rel_ancestor, fname) if rel_ancestor != "." else fname
                else:
                    continue
                if rel not in seen:
                    seen.add(rel)
                    found.append((proj, rel, fpath))
        return found

    report = {"css": [], "js": []}
    # --- Collect CSS ---
    if css:
        all_css = []
        for proj in enabled:
            all_css.extend(find_files("css", proj))
        seen_css = set()
        for entry in all_css:
            if entry[1] not in seen_css:
                seen_css.add(entry[1])
                report["css"].append(entry)
        if isinstance(css, str):
            bundle_path = gw.resource(target, f"{css}.css")
            with open(bundle_path, "w", encoding="utf-8") as out:
                for proj, rel, full in report["css"]:
                    with open(full, "r", encoding="utf-8") as f:
                        out.write(f"/* --- {proj}:{rel} --- */\n")
                        out.write(f.read() + "\n\n")
            report["css_bundle"] = bundle_path

    # --- Collect JS ---
    if js:
        all_js = []
        for proj in enabled:
            all_js.extend(find_files("js", proj))
        seen_js = set()
        for entry in all_js:
            if entry[1] not in seen_js:
                seen_js.add(entry[1])
                report["js"].append(entry)
        if isinstance(js, str):
            bundle_path = gw.resource(target, f"{js}.js")
            with open(bundle_path, "w", encoding="utf-8") as out:
                for proj, rel, full in report["js"]:
                    with open(full, "r", encoding="utf-8") as f:
                        out.write(f"// --- {proj}:{rel} ---\n")
                        out.write(f.read() + "\n\n")
            report["js_bundle"] = bundle_path

    return report