#!/usr/bin/env python3 # # MIT License # # Copyright (c) 2020 Victor Gama de Oliveira <hey@vito.io> # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in all # copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. import re from pathlib import Path def ignorable(file): return file.name.endswith(".story.jsx") or \ file.name.endswith(".style.jsx") def extract_exports(file): txt = file.read_text() simple_exports = re.findall(r"export const ([^\s]*)", txt) complex_exports = re.findall(r"export {([^}]+)}", txt) complex_exports = [re.findall(r"([^\s,\n]+)", p) for p in complex_exports] complex_exports = [i for l in complex_exports for i in l] return [exp for exp in simple_exports + complex_exports if re.match(r"^[A-Z]", exp)] def split_noindex_definitions(defs): ignored = {f.parent for f in defs if f.stat().st_size == 0} top_only = {f.parent for f in defs if f.parent not in ignored and f.read_text().strip() == "top-only"} return (ignored, top_only) def compile_exports(exports): outputs = exports.items() outputs = [(k, ", ".join(v)) for k, v in outputs] outputs = [f"import {{ {v} }} from \"{k}\"" for k, v in outputs] exp = ", ".join([i for l in exports.values() for i in l]) outputs.append(f"export {{{exp}}};") return outputs def run(): target_dir = Path("./app/javascript/components") target = target_dir / "index.jsx" if target.exists(): target.unlink() no_index = list(target_dir.rglob(".no-index")) ignored, top_only = split_noindex_definitions(no_index) exports = {} for file in target_dir.rglob("*.jsx"): if ignorable(file): continue parent = file.parent if parent in ignored or parent in top_only: continue f_name = f"/{file.name}" if f_name == "/index.jsx": f_name = "" exports[f"./{parent.name}{f_name}"] = extract_exports(file) for parent in top_only: file = parent / "index.jsx" exp = extract_exports(file) if len(exp) > 0: exports[f"./{parent.name}"] = exp outputs = [ "/* eslint-disable */", "// Generated by index-react-components. DO NOT EDIT.", "// This file was generated automatically by a tool. Any changes", "// will be lost when it gets regenerated!", ] + compile_exports(exports) + [""] target.write_text("\n".join(outputs)) if __name__ == "__main__": run()