Skip to content

Instantly share code, notes, and snippets.

@heyvito
Last active December 16, 2020 15:13
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save heyvito/d084a6321ce9e663deb6991f2de6a6e0 to your computer and use it in GitHub Desktop.
Save heyvito/d084a6321ce9e663deb6991f2de6a6e0 to your computer and use it in GitHub Desktop.
#!/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()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment