Docs As Code Platform Python

👤 Sharing: AI
```python
# Docs-As-Code Example using Python: Building a Simple Documentation Site

import os
import shutil
import markdown
from jinja2 import Environment, FileSystemLoader

# 1. Configuration (Project-Specific)
SOURCE_DIR = "content"  # Directory where your markdown content lives
TEMPLATE_DIR = "templates"  # Directory where your Jinja2 templates live
OUTPUT_DIR = "output"  # Directory where the generated HTML site will be placed
SITE_TITLE = "My Awesome Project Documentation" # Website Title

# 2. Helper Functions

def load_markdown(filepath):
    """Loads a markdown file and converts it to HTML."""
    with open(filepath, "r", encoding="utf-8") as f:
        markdown_text = f.read()
        html = markdown.markdown(markdown_text, extensions=['fenced_code', 'tables', 'mdx_math'])  # Common extensions
        return html


def render_template(template_name, context):
    """Renders a Jinja2 template with the given context."""
    env = Environment(loader=FileSystemLoader(TEMPLATE_DIR))
    template = env.get_template(template_name)
    return template.render(context)


def build_page(filename, template_name="page.html"):
    """Builds a single HTML page from a markdown file."""
    input_filepath = os.path.join(SOURCE_DIR, filename + ".md")
    output_filepath = os.path.join(OUTPUT_DIR, filename + ".html")

    html_content = load_markdown(input_filepath)

    context = {
        "site_title": SITE_TITLE,
        "page_title": filename.capitalize(), # Title displayed on the page
        "content": html_content
    }

    rendered_html = render_template(template_name, context)

    with open(output_filepath, "w", encoding="utf-8") as f:
        f.write(rendered_html)

    print(f"Built: {output_filepath}")


def copy_static_assets(source_dir, dest_dir):
    """Copies static assets (e.g., CSS, images) from source to destination."""
    try:
        shutil.copytree(source_dir, dest_dir, dirs_exist_ok=True)
        print(f"Copied static assets from {source_dir} to {dest_dir}")
    except FileNotFoundError:
        print(f"Static asset directory not found: {source_dir}.  Skipping.")


# 3. Main Build Process

def main():
    """Orchestrates the documentation build process."""

    # Create the output directory if it doesn't exist
    if not os.path.exists(OUTPUT_DIR):
        os.makedirs(OUTPUT_DIR)

    # 1. Build individual pages from markdown files
    for filename in ["index", "about", "api"]:  # List of your markdown files (without the .md extension)
        build_page(filename)

    # 2. Copy static assets (CSS, images, etc.)
    copy_static_assets("static", OUTPUT_DIR) # Copies a 'static' directory containing css, images, etc. to the output directory

    print("Documentation build complete!")


if __name__ == "__main__":
    main()



#  Directory Structure (Example):
#
#  my_docs_project/
#  ??? content/          # Markdown files go here
#  ?   ??? index.md
#  ?   ??? about.md
#  ?   ??? api.md
#  ??? templates/        # Jinja2 templates go here
#  ?   ??? page.html
#  ??? static/           # Static assets (CSS, images) go here
#  ?   ??? style.css
#  ??? docs_builder.py   # This script
#  ??? output/           # Output HTML files will be placed here (created by the script)

# ---
#  Content of example files (create these in the appropriate directories):

# content/index.md
# ```markdown
# # Welcome to My Awesome Project!
#
# This is the main documentation page.
#
# ```

# content/about.md
# ```markdown
# # About Us
#
# We are a team of developers dedicated to making awesome software.
# ```

# content/api.md
# ```markdown
# # API Documentation
#
# ```python
# def my_function(x, y):
#     """This function does something."""
#     return x + y
# ```

# templates/page.html
# ```html
# <!DOCTYPE html>
# <html lang="en">
# <head>
#     <meta charset="UTF-8">
#     <meta name="viewport" content="width=device-width, initial-scale=1.0">
#     <title>{{ site_title }} - {{ page_title }}</title>
#     <link rel="stylesheet" href="style.css">  <!-- Link to your stylesheet -->
# </head>
# <body>
#     <header>
#         <h1>{{ site_title }}</h1>
#     </header>
#     <nav>
#         <a href="index.html">Home</a> | <a href="about.html">About</a> | <a href="api.html">API</a>
#     </nav>
#     <main>
#         <h2>{{ page_title }}</h2>
#         {{ content | safe }}
#     </main>
#     <footer>
#         <p>&copy; 2023 My Awesome Project</p>
#     </footer>
# </body>
# </html>
# ```

# static/style.css (Optional - basic styling)
# ```css
# body {
#     font-family: sans-serif;
#     margin: 20px;
# }

# header {
#     background-color: #f0f0f0;
#     padding: 10px;
#     text-align: center;
# }

# nav {
#     margin-bottom: 10px;
# }

# main {
#     margin-top: 20px;
# }
# ```

# Explanation:

# 1. **Import Libraries:**
#    - `os`: For interacting with the operating system (creating directories, joining paths).
#    - `shutil`:  For high-level file operations like copying directories.
#    - `markdown`:  For converting Markdown to HTML.  Install with `pip install markdown`.
#    - `jinja2`: For templating.  Install with `pip install Jinja2`.  Jinja2 allows you to separate the structure of your HTML from the content.

# 2. **Configuration:**
#    - `SOURCE_DIR`, `TEMPLATE_DIR`, `OUTPUT_DIR`:  Define the directories where your Markdown files, templates, and generated HTML files will be located.  These are project-specific settings.  Adjust them to match your project's structure.
#    - `SITE_TITLE`:  The title of your documentation site.

# 3. **Helper Functions:**
#    - `load_markdown(filepath)`:
#        - Takes the path to a Markdown file as input.
#        - Reads the Markdown content from the file.
#        - Uses the `markdown.markdown()` function to convert the Markdown to HTML.  The `extensions` argument adds support for common Markdown features like fenced code blocks, tables, and math equations (you might need to install `python-markdown-math` if you get errors related to `mdx_math`).
#        - Returns the generated HTML.
#    - `render_template(template_name, context)`:
#        - Takes the name of a Jinja2 template file and a `context` dictionary as input.
#        - Creates a Jinja2 environment using `FileSystemLoader` to specify where to load templates from.
#        - Loads the specified template using `env.get_template()`.
#        - Renders the template with the provided `context` using `template.render()`. The `context` is a dictionary of variables that will be available within the template.
#        - Returns the rendered HTML string.
#    - `build_page(filename, template_name="page.html")`:
#        - Takes the filename of the Markdown file (without the `.md` extension) and an optional template name as input.
#        - Constructs the input and output filepaths.
#        - Calls `load_markdown()` to convert the Markdown file to HTML.
#        - Creates a `context` dictionary containing the `site_title`, `page_title`, and the HTML content.  The `page_title` is derived from the filename.
#        - Calls `render_template()` to render the HTML using the specified template and context.
#        - Writes the rendered HTML to the output file.
#        - Prints a message to the console indicating that the page has been built.
#    - `copy_static_assets(source_dir, dest_dir)`:
#        - Copies static assets (CSS files, images, fonts, etc.) from a source directory to the output directory.  This is essential for making your documentation look good.
#        - Uses `shutil.copytree()` to recursively copy the directory.  `dirs_exist_ok=True` allows the function to continue if the destination directory already exists (it will merge the contents).
#        - Includes error handling to gracefully handle the case where the static asset directory doesn't exist.

# 4. **Main Function:**
#    - `main()`:  This function orchestrates the entire build process.
#    - Creates the `OUTPUT_DIR` if it doesn't exist.
#    - Iterates through a list of Markdown filenames (`["index", "about", "api"]`) and calls `build_page()` for each one to generate the corresponding HTML file.  **Modify this list to include all your documentation pages.**
#    - Calls `copy_static_assets()` to copy any static assets from the `static` directory to the `OUTPUT_DIR`.
#    - Prints a "Documentation build complete!" message.

# 5. **Execution:**
#    - `if __name__ == "__main__":`:  This ensures that the `main()` function is called only when the script is run directly (not when it's imported as a module).

# How to Run:

# 1. **Install Dependencies:**  `pip install markdown Jinja2`
# 2. **Create the Directory Structure:** Create the `content`, `templates`, and `static` directories (and their respective files) as shown in the example above.
# 3. **Customize:** Edit the Markdown files in the `content` directory to add your documentation content. Modify the template in the `templates` directory to customize the layout and styling of your documentation. Add your CSS, images, and other static assets to the `static` directory.  Update the list of filenames in the `main()` function to include all your documentation pages.
# 4. **Run the Script:**  `python docs_builder.py`
# 5. **View the Output:**  The generated HTML files will be in the `output` directory.  Open `output/index.html` in your web browser to view your documentation.

# Key Concepts of Docs-As-Code Demonstrated:

# * **Markdown as Source:**  The documentation content is written in Markdown, a lightweight and human-readable markup language.
# * **Version Control:**  Markdown files are plain text, making them easy to store in version control systems like Git. This allows you to track changes to your documentation, collaborate with others, and revert to previous versions if necessary.
# * **Automation:**  The Python script automates the process of building the documentation site from the Markdown files and templates. This makes it easy to regenerate the documentation whenever changes are made.
# * **Separation of Concerns:**  The content (Markdown), presentation (templates), and styling (CSS) are separated, making it easier to maintain and update the documentation.

# Further Enhancements:

# * **Table of Contents Generation:**  Automatically generate a table of contents for each page.
# * **Syntax Highlighting:**  Use a syntax highlighting library (e.g., Pygments) to improve the appearance of code blocks.
# * **Theme Support:**  Allow users to select different themes for the documentation site.
# * **Command-Line Arguments:**  Add command-line arguments to customize the build process (e.g., specify the input and output directories).
# * **Integration with CI/CD:**  Integrate the build process with a CI/CD pipeline to automatically generate and deploy the documentation whenever changes are pushed to your repository.
# * **Navigation:** Add a dynamic navigation system that automatically updates as you add or remove pages.
# * **Search:** Integrate a search functionality to make it easier for users to find information in your documentation.
# * **Error Handling:** Add more robust error handling to catch potential problems during the build process.
```
👁️ Viewed: 5

Comments