mirror of
				https://github.com/kevinveenbirkenbach/computer-playbook.git
				synced 2025-10-31 10:19:09 +00:00 
			
		
		
		
	Implemented category draft
This commit is contained in:
		| @@ -8,3 +8,6 @@ Cyber Master Infrastructure Solution documentation | ||||
|  | ||||
|    * | ||||
|    roles/index.rst | ||||
|  | ||||
|  | ||||
| .. roles-overview:: | ||||
| @@ -54,6 +54,7 @@ extensions = [ | ||||
|     "sphinx.ext.autodoc", | ||||
|     "myst_parser", | ||||
|     'local_md_files', | ||||
|     'roles_overview', | ||||
| ] | ||||
| autosummary_generate = True | ||||
|  | ||||
|   | ||||
							
								
								
									
										85
									
								
								sphinx/roles_overview.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										85
									
								
								sphinx/roles_overview.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,85 @@ | ||||
| import os | ||||
| import glob | ||||
| import yaml | ||||
| from docutils import nodes | ||||
| from docutils.parsers.rst import Directive | ||||
| from docutils.statemachine import ViewList | ||||
| from sphinx.util import logging | ||||
|  | ||||
| logger = logging.getLogger(__name__) | ||||
|  | ||||
| class RolesOverviewDirective(Directive): | ||||
|     """ | ||||
|     A directive to embed a roles overview as reStructuredText. | ||||
|      | ||||
|     It scans the roles directory (i.e. every folder under "roles") for a | ||||
|     "meta/main.yml" file, reads the category (if provided) and the role’s description | ||||
|     (from galaxy_info.description), and outputs a listing grouped by category. | ||||
|     """ | ||||
|     has_content = False | ||||
|  | ||||
|     def run(self): | ||||
|         env = self.state.document.settings.env | ||||
|         srcdir = env.srcdir | ||||
|         roles_dir = os.path.join(srcdir, 'roles') | ||||
|         if not os.path.isdir(roles_dir): | ||||
|             logger.warning(f"Roles directory not found: {roles_dir}") | ||||
|             error_node = self.state.document.reporter.error( | ||||
|                 "Roles directory not found.", line=self.lineno) | ||||
|             return [error_node] | ||||
|  | ||||
|         # Dictionary mapping categories to role entries. | ||||
|         categories = {} | ||||
|         for role_path in glob.glob(os.path.join(roles_dir, '*')): | ||||
|             if os.path.isdir(role_path): | ||||
|                 meta_path = os.path.join(role_path, 'meta', 'main.yml') | ||||
|                 if os.path.exists(meta_path): | ||||
|                     try: | ||||
|                         with open(meta_path, 'r', encoding='utf-8') as f: | ||||
|                             data = yaml.safe_load(f) | ||||
|                     except Exception as e: | ||||
|                         logger.warning(f"Error reading YAML file {meta_path}: {e}") | ||||
|                         continue | ||||
|  | ||||
|                     role_name = os.path.basename(role_path) | ||||
|                     category = data.get('category', 'uncategorized') | ||||
|                     role_description = data.get('galaxy_info', {}).get('description', '') | ||||
|                     role_entry = { | ||||
|                         'name': role_name, | ||||
|                         'description': role_description, | ||||
|                         'link': f'roles/{role_name}/README.md' | ||||
|                     } | ||||
|                     categories.setdefault(category, []).append(role_entry) | ||||
|                 else: | ||||
|                     logger.warning(f"meta/main.yml not found for role {role_path}") | ||||
|  | ||||
|         # Sort categories and roles alphabetically. | ||||
|         sorted_categories = sorted(categories.items(), key=lambda x: x[0].lower()) | ||||
|         for category, roles in sorted_categories: | ||||
|             roles.sort(key=lambda r: r['name'].lower()) | ||||
|  | ||||
|         # Build reStructuredText content. | ||||
|         lines = [] | ||||
|         for category, roles in sorted_categories: | ||||
|             lines.append(f".. rubric:: {category}") | ||||
|             lines.append("") | ||||
|             for role in roles: | ||||
|                 lines.append(f"* **[`{role['name']}`]({role['link']})**") | ||||
|                 if role['description']: | ||||
|                     lines.append(f"  - {role['description']}") | ||||
|             lines.append("") | ||||
|  | ||||
|         rst_content = "\n".join(lines) | ||||
|  | ||||
|         # Use a ViewList for nested_parse. | ||||
|         rst_lines = ViewList() | ||||
|         for i, line in enumerate(rst_content.splitlines()): | ||||
|             rst_lines.append(line, '<roles-overview>') | ||||
|  | ||||
|         container = nodes.container() | ||||
|         self.state.nested_parse(rst_lines, self.content_offset, container) | ||||
|         return [container] | ||||
|  | ||||
| def setup(app): | ||||
|     app.add_directive("roles-overview", RolesOverviewDirective) | ||||
|     return {'version': '0.1', 'parallel_read_safe': True} | ||||
		Reference in New Issue
	
	Block a user