""" Convert contribs' README files to proper documentation pages along with an index. """ from collections import defaultdict from glob import glob from os.path import abspath, dirname from os.path import join as pathjoin from os.path import sep _EVENNIA_PATH = pathjoin(dirname(dirname(dirname(abspath(__file__))))) _DOCS_PATH = pathjoin(_EVENNIA_PATH, "docs") _SOURCE_DIR = pathjoin(_EVENNIA_PATH, "evennia", "contrib") _OUT_DIR = pathjoin(_DOCS_PATH, "source", "Contribs") _OUT_INDEX_FILE = pathjoin(_OUT_DIR, "Contribs-Overview.md") _FILE_STRUCTURE = """{header} {categories} {footer}""" _CATEGORY_DESCS = { "base_systems": """ This category contains systems that are not necessarily tied to a specific in-game mechanic but is useful for the game as a whole. Examples include login systems, new command syntaxes, and build helpers. """, "full_systems": """ This category contains 'complete' game engines that can be used directly to start creating content without no further additions (unless you want to). """, "game_systems": """ This category holds code implementing in-game gameplay systems like crafting, mail, combat and more. Each system is meant to be adopted piecemeal and adopted for your game. This does not include roleplaying-specific systems, those are found in the `rpg` folder. """, "grid": """ Systems related to the game world's topology and structure. This has contribs related to rooms, exits and map building. """, "rpg": """ These are systems specifically related to roleplaying and rule implementation like character traits, dice rolling and emoting. """, "tutorials": """ Helper resources specifically meant to teach a development concept or to exemplify an Evennia system. Any extra resources tied to documentation tutorials are found here. Also the home of the Tutorial World demo adventure. """, "utils": """ Miscellaneous, optional tools for manipulating text, auditing connections and more. """, } _FILENAME_MAP = {"rpsystem": "RPSystem", "xyzgrid": "XYZGrid", "awsstorage": "AWSStorage"} HEADER = """# Contribs _Contribs_ are optional code snippets and systems contributed by the Evennia community. They vary in size and complexity and may be more specific about game types and styles than 'core' Evennia. This page is auto-generated and summarizes all contribs currently included. All contrib categories are imported from `evennia.contrib`, such as from evennia.contrib.base_systems import building_menu Each contrib contains installation instructions for how to integrate it with your other code. If you want to tweak the code of a contrib, just copy its entire folder to your game directory and modify/use it from there. > Hint: Additional (potentially un-maintained) code snippets from the community can be found in our discussion forum's [Community Contribs & Snippets](https://github.com/evennia/evennia/discussions/categories/community-contribs-snippets) category. If you want to contribute yourself, see [here](Contributing)! """ TOCTREE = """```{{toctree}} :maxdepth: 1 {listing} ```""" CATEGORY = """ ## {category} _{category_desc}_ {toctree} {blurbs} """ BLURB = """ ### Contrib: `{name}` _{credits}_ {blurb} [Read the documentation](./{filename}) - [Browse the Code](api:{code_location}) """ FOOTER = """ ---- This document page is generated from `{path}`. Changes to this file will be overwritten, so edit that file rather than this one. """ INDEX_FOOTER = """ ---- This document page is auto-generated. Manual changes will be overwritten. """ def readmes2docs(directory=_SOURCE_DIR): """ Parse directory for README files and convert them to doc pages. """ ncount = 0 categories = defaultdict(list) glob_path = f"{directory}{sep}*{sep}*{sep}README.md" for file_path in glob(glob_path): # paths are e.g. evennia/contrib/utils/auditing/README.md _, category, name, _ = file_path.rsplit(sep, 3) pypath = f"evennia.contrib.{category}.{name}" filename = ( "Contrib-" + "-".join( _FILENAME_MAP.get(part, part.capitalize() if part[0].islower() else part) for part in name.split("_") ) + ".md" ) outfile = pathjoin(_OUT_DIR, filename) with open(file_path) as fil: data = fil.read() clean_file_path = f"evennia{sep}contrib{file_path[len(directory):]}" data += FOOTER.format(path=clean_file_path) try: credits = data.split("\n\n", 3)[1] blurb = data.split("\n\n", 3)[2] except IndexError: blurb = name with open(outfile, "w") as fil: fil.write(data) categories[category].append((name, credits, blurb, filename, pypath)) ncount += 1 # build the index with blurbs category_sections = [] for category in sorted(categories): filenames = [] contrib_tups = categories[category] catlines = [] for tup in sorted(contrib_tups, key=lambda tup: tup[0].lower()): catlines.append( BLURB.format( name=tup[0], credits=tup[1], blurb=tup[2], filename=tup[3], code_location=tup[4] ) ) filenames.append(f"{tup[3]}") toctree = TOCTREE.format(listing="\n".join(filenames)) category_sections.append( CATEGORY.format( category=category, category_desc=_CATEGORY_DESCS[category].strip(), blurbs="\n".join(catlines), toctree=toctree, ) ) text = _FILE_STRUCTURE.format( header=HEADER, categories="\n".join(category_sections), footer=INDEX_FOOTER ) with open(_OUT_INDEX_FILE, "w") as fil: fil.write(text) print(f" -- Converted Contrib READMEs to {ncount} doc pages + index.") if __name__ == "__main__": readmes2docs(_SOURCE_DIR)