--- title: Markdown Overview Renderer --- # Specification: Markdown Overview Renderer This document defines the expected structure and content of the `Overview.md` artefact generated from GitLab project data. It complements the low-level [Table Rendering & UI](./spec_table_rendering_ui.md) rules and is independent from the Quarto output (see separate spec). --- ## 1. Top-level Layout The document is divided into **two major parts** – a summary and a detailed section – separated by an automatic table-of-contents marker. ```markdown # Overview over GitLab Readmes ## Summary ### ###
… (more groups) [[_TOC_]] ← literally this line, on its own, followed by a blank line ## Group ### ### … ## Group ### ``` Key points: 1. Static introduction (`# Overview over GitLab Readmes` followed by a blank line, followed by `## Summary` with another blank line). 2. Each summary group heading is level-3 (`###`). 3. After all summary tables, the literal `[[_TOC_]]` marker is emitted (without spaces), enabling Markdown processors to inject a Table of Contents. 4. The detailed part uses a level-2 heading `## Group ` (singular word *Group* included) and then level-3 headings `### ` for individual projects. --- ## 2. Summary Tables * The table follows all rules in [Table Rendering & UI](./spec_table_rendering_ui.md) (m-dash placeholder, custom labels …). * **Repository column** value is a Markdown link to the projects **web_url**. If an avatar is available the link text is preceded by `![Avatar](){width=16px}`. * Immediately below the table after a blank line a generic explanatory note is included: `Note: If no supervisors were found, authors of the README are named as supervisors.` (localised wording may vary but must convey the same information). * A blank line separates this note from the next group heading. --- ## 3. Project Detail Sections General: **Callout blocks** are using Obsidian-style syntax: `> [!tip] Block-Title`, `> [!warning] Block-Title`, `> [!note] Block-Title` … Each block may span multiple lines and include Markdown inside. All lines of this block must properly begin with `>` to make them part of the callout. The title are offset from the rest of the block by an empty line: `>` 1. **Description list** with up to three entries in this order – `Date`, `Status`, `Supervisors` – each on its own line in *definition-list* syntax: ```markdown Date : 2025-06-18 Supervisors : Marty McFly : Doctor Brown ``` If `Supervisors` are not Available it is substituded by `Authors` like so: ```markdown Date : 2025-06-18 Authors : Marty McFly : Doctor Brown ``` Missing entries from the Project-Info are omitted. When using `Readme.content` in a Description call-out, the renderer must: 1. Strip any YAML front-matter from the content 2. Include only the first 10 non-empty lines 3. If content was truncated, append "…continues…" on a new line Example: ```markdown > [!warning] Description > # My Project > > This is a great project that does many things. > It has multiple features: > > - Feature 1 > - Feature 2 > - Feature 3 > - Feature 4 > …continues… ``` 2. **Release badge** – image linking to `/-/releases`. 3. **Description callout** titled *Description* with (first applicable) * If frontmatter has a description-key: callout-type `tip` and content frontmatter["description"] * If `Readme.content` is not `None` or empty: callout-type `warning` and contend from `Readme.content` * If `Readme.content` is `None`: callout-type `danger` and content "No Readme found" 4. **Issues callout** titled *Open Issues* with (first applicable) * If `Project.issues` is not `None`: callout-type `tip` and content containing bullet list items of `opened` issues, each item is a link to the GitLab issue. After the list one `TOTAL:` line summarises `opened` and `closed` counts. If no issues are `opened`, content is "No issues open." * If `Readme.todo` is not `None` or empty: callout-type `warning` and content from `Readme.todo` * If `Readme.todo` is `None`: callout-type `danger` and content "No TODOs found." 5. Final paragraph: `[Link to full readme]()`. Blank lines separate each logical part; no extra thematic breaks. --- ## 4. Ordering Guarantees * Groups are ordered by the number of Projects rendered (alphabetically on a tie). * Summary project order mirror the incoming, already-sorted data (see [Table Sorting](./spec_table_sorting.md)). * In the detailed part, projects appear alphabetically by their name. --- ## 5. Relation to Other Specifications * Consumes sorted & grouped data from [Table Rendering & UI](./spec_table_rendering_ui.md). * Reuses placeholders and cell formatting rules defined there. * Reads metadata extracted by the [Model Mapping](./spec_model_mapping.md) and enriched by the [Data Collector](./spec_data_collector.md). --- ## 6. Out of Scope * Everything related to DataCollection, API or Network. This is only `model ~> markdown`. * No other renderer that output data on their own (i.e. `quarto`) --- ## 7. Implementation Interface (Class-based Contract) All Markdown renderers must implement a class-based interface as follows: - Inherit from the abstract base class `Renderer` (see `src/gitlab_overviewer/rendering/renderer_base.py`). - Implement the following methods: - `render(self, overview_data, ...) -> str`: Render the output as a string. - `write_files(self, overview_data, ...) -> None`: Write the rendered output to files as specified. - Render-agnostic helpers (e.g., placeholder handling, star rating, safe conversion) are provided as `@staticmethod`s on `Renderer` and should be used by all subclasses. **Rationale:** - This contract enforces consistency and extensibility for all renderers. - It enables robust testing, code reuse, and future support for additional output formats (e.g., HTML, PDF). - The interface is enforced in code and validated by the test suite. This is an internal code structure requirement and does not affect the output format, but all new renderers must comply. **Open Questions:** - Should future renderers (e.g., HTML, PDF) follow this interface? (TBD) - Are there additional common methods that should be included in the base interface? (TBD) - See TODOs in `Renderer` base class for possible candidates.