--- File: README.md --- # WingTip A minimal static site generator for documentation.  Live demo: [semanticentity.github.io/WingTip-Static-Site-Generator](https://semanticentity.github.io/WingTip-Static-Site-Generator) WingTip turns a `README.md` and a `docs/` folder into a polished static site — no config required, now with built-in client-side search. Write in Markdown, hit build, and ship to GitHub Pages in minutes. --- ## Features * Converts `README.md` → `index.html` * Converts `docs/*.md` → standalone `.html` pages * Adds GitHub "Edit this page" links * Responsive sidebar + TOC toggle * Pygments syntax highlighting for code blocks * Copy-to-clipboard on all code snippets * SEO optimized with canonical URLs + sitemap.xml * Open Graph and Twitter meta support * Dark/light mode toggle with auto detection * Admonition support with custom titles and nested content ([learn more](docs/admonitions.md)) * Live dev server with auto-reload (`serve.py`) * Built-in Open Graph image generator * GitHub Actions deployment support * Custom 404 error page handling * Built-in client-side search with keyboard navigation ([learn more](docs/search-features.md)) * Basic theme overrides for fonts and colors via `theme.json` ([learn more](docs/theming.md)) * LaTeX math rendering with KaTeX ([examples](docs/math-examples.md)) * Enhanced dark mode for GFM and KaTeX * Screen reader and keyboard accessibility * Automatic cleanup of obsolete files during build * Smart port handling for development server --- ## Quickstart ```bash pip install markdown beautifulsoup4 livereload pillow PyYAML # Alternatively, using uv (a fast Python package installer) uv pip install markdown beautifulsoup4 livereload pillow PyYAML # Build site and start dev server in one command python main.py --serve # Or build only python main.py # Or start dev server separately python serve.py ``` To stop the development server, press `Ctrl+C` in the terminal where it's running. If you encounter issues stopping the server or get a "port in use" error, a utility script `killDocs.sh` is provided to help. The development server will attempt to use this script automatically if needed, or you can run it manually: ```bash bash wingtip/killDocs.sh ``` This script will attempt to forcefully stop any processes related to the WingTip development server. Then open [http://localhost:8000](http://localhost:8000) You can change the output folder with `--output`. See `python wingtip/main.py --help` for all CLI options. --- ## File Structure ``` your-project/ ├── README.md # Becomes index.html ├── docs/ # Additional Markdown files │ ├── guide.md │ └── api.md ├── wingtip/ # Generator source │ ├── main.py │ ├── serve.py │ ├── generate_card.py │ ├── template.html ├── pygments.css └── config.json # Required if using social cards or favicon (see below) ``` --- ## Configuration A `config.json` file is required if you use social cards or a custom favicon. It is also recommended for SEO and deployment. Fields marked optional can be omitted if not needed. To generate SEO-friendly output and enable GitHub deployment, add a `config.json` file in the project root: ```json { "base_url": "https://yourusername.github.io/yourrepo", "project_name": "WingTip", "version": "0.1.0", "description": "Minimal static site generator for GitHub Pages", "author": "Your Name", "repo_url": "https://github.com/yourusername/yourrepo", "og_image": "social-card.png", "favicon": "https://yourcdn.com/favicon.png", "twitter_handle": "@yourhandle", "github": { "repo": "yourusername/yourrepo", "branch": "main" }, "social_card": { "title": "WingTip", "tagline": "Make your docs fly.", "theme": "light", "font": "Poppins", "image": "social-card.png" } } ``` --- ## GitHub Pages Deployment (via Actions) WingTip includes a GitHub Actions workflow that builds and deploys your site automatically when you push to the `main` branch. ### Setup 1. Push your repository to GitHub 2. Ensure Pages is enabled under **Settings > Pages** 3. Add your `config.json` with a correct `base_url` 4. Your documentation will deploy to: `https://yourusername.github.io/yourrepo/` ### Included Workflow `.github/workflows/static.yml`: ```yaml name: Deploy static content to Pages on: push: branches: ["main"] workflow_dispatch: permissions: contents: read pages: write id-token: write concurrency: group: "pages" cancel-in-progress: false jobs: deploy: environment: name: Pages url: ${{ steps.deployment.outputs.page_url }} runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 - name: Set up Python uses: actions/setup-python@v5 with: python-version: '3.x' cache: 'pip' - name: Install dependencies run: | python -m pip install --upgrade pip pip install markdown Pygments Pillow beautifulsoup4 PyYAML - name: Build site run: python main.py - name: Setup Pages uses: actions/configure-pages@v5 - name: Upload artifact uses: actions/upload-pages-artifact@v3 with: path: docs/site - name: Deploy to GitHub Pages id: deployment uses: actions/deploy-pages@v4 ``` --- ## Social Card Generate a shareable Open Graph image: ```bash python wingtip/main.py --regen-card ``` - This command requires a properly configured `config.json` (with a `social_card` section and related fields). - Output: `docs/site/social-card.png` - If no `og_image` is set in your config, the social card will also be copied to `./social-card.png` in the project root. - Values pulled from `config.json`: supports title, tagline, theme, font, and emoji or image. --- ## Custom 404 Page WingTip supports a custom "Page Not Found" page that works both locally during development and when deployed to GitHub Pages. To use this feature: 1. Create a `404.md` file in the root of your project directory (the same directory where your `README.md` and `config.json` are located). 2. Add the following YAML front matter at the top of your 404.md file (this is required for GitHub Pages): ``` permalink: /404.html ``` Note: In the actual 404.md file, this should be wrapped with triple-dash lines, but we're omitting them here to avoid breaking the markdown formatting. 3. Write your desired content for the 404 page in Markdown format below the front matter. * The title for the generated `404.html` page will be taken from the first H1 heading (e.g., `# Page Not Found`) in your `404.md`. * If no H1 heading is found, the title will default to "404.md". 4. When you build your site with `python main.py`, WingTip will automatically: * Detect `404.md` and process its front matter * Convert it into a `404.html` file in your output directory (e.g., `docs/site/404.html`) * Apply the same template and styling as your other pages 5. During local development with `python serve.py`: * The development server will automatically serve your custom 404 page when a non-existent URL is accessed * This allows you to preview and test your 404 page locally 6. When deployed to GitHub Pages: * GitHub Pages will automatically use your custom 404.html file for any non-existent URLs * The permalink in the front matter ensures proper routing This implementation ensures a consistent user experience both during development and in production. --- ## Theming and UX * Auto light/dark theme based on system preference * Manual toggle in navigation bar * Sidebar navigation with collapsible TOC * Scroll position preserved during live reload --- ## Limitations & Roadmap - Mermaid diagrams and some advanced Markdown features are not yet supported (planned for a future release). - Math rendering is supported via KaTeX! --- ## Build Output ``` . ├── sitemap.xml ├── robots.txt └── docs/site/ ├── index.html ├── guide.html ├── api.html ├── 404.html └── social-card.png ``` --- ## Requirements ```bash pip install markdown beautifulsoup4 pillow livereload PyYAML ``` To regenerate code highlight styles: The file `syntax.css` is generated in `docs/site/` by `main.py` and is the one used by the site. The `pygments.css` file in the root directory might be for reference or manual generation using a command like `pygmentize -S monokai -f html -O full,cssclass=highlight > pygments.css` (using monokai as an example, to match one of the themes). --- ## License MIT. Use freely. Modify ruthlessly. --- File: docs/admonitions.md --- # Admonition Examples WingTip supports admonition blocks to highlight important information. These are special callout blocks that can be used to draw attention to specific content. ## Basic Usage Use `!!!` followed by the type of admonition to create a block: !!! note This is a simple note admonition. It can contain multiple paragraphs and other Markdown elements. - Lists - Code blocks - etc. ## Available Types ### Note !!! note This is a note admonition. Use it for general information. ### Warning !!! warning This is a warning admonition. Use it to warn users about potential issues. ### Danger !!! danger This is a danger admonition. Use it for critical warnings or dangerous operations. ### Tip !!! tip This is a tip admonition. Use it for helpful suggestions and best practices. ### Info !!! info This is an info admonition. Use it for additional context or background information. ### Success !!! success This is a success admonition. Use it to highlight positive outcomes or completion states. ## Advanced Usage ### Nested Content Admonitions can contain any Markdown content: !!! note ### A Header Inside an Admonition 1. Ordered lists work great 2. Code blocks work too: ```python def hello(): print("Hello from an admonition!") ``` Tables work when not nested in lists: | Column 1 | Column 2 | |----------|----------| | Cell 1 | Cell 2 | ### Custom Titles You can add custom titles to admonitions: !!! tip "Custom Title" This tip has a custom title! ## Dark Mode Support All admonitions automatically adapt to dark mode when the theme is switched, maintaining readability and consistent styling with the rest of the content. --- File: docs/changelog.md --- # WingTip Changelog ## [v0.4.0] ### ✨ Features #### GitHub-Flavored Markdown (GFM) - Added comprehensive GFM support with markdown-it-py plugins: - Task lists with checkboxes - Footnotes and references - Tables with full styling - Strikethrough text - Better autolinking - Definition lists #### Math & Diagrams - Added LaTeX math rendering with KaTeX: - Inline math with `$...$` - Display math with `$$...$$` - Fast client-side rendering - See [Math Examples](./math-examples.md) #### Document Versioning - Added version management system: - CLI support for versioned builds - Version selector dropdown in UI - Version-aware sitemap and links - "Latest" version redirect #### Plugin System - Introduced extensible plugin architecture: - Custom Python plugins in `plugins/` directory - Build process hooks for customization - Sample banner plugin included #### Admonitions - Added support for admonition blocks: - Multiple types (note, warning, danger, tip) - Custom styling for each type - Full dark mode support #### Search Enhancements - Enhanced search functionality: - `/` to focus search - Arrow keys to navigate results - Enter to select - Esc to clear - Added result highlighting in search matches - Improved search UI with theme integration - Fixed search index path handling for GitHub Pages ### 🎨 UI & Accessibility - Comprehensive dark mode support: - GFM elements (tables, task lists, footnotes) - Admonition blocks with distinct themes - KaTeX math expressions - Code syntax highlighting - Enhanced mobile responsiveness: - Improved tablet breakpoints (768px) - Full-width search on mobile - Better nav layout on small screens - Added ARIA labels and roles for better screen reader support - Improved nav-container styling and transitions - Consolidated and optimized CSS ### 🛠 Infrastructure - Added automatic .md to .html link conversion - Improved GitHub Pages compatibility - Enhanced build system for versioned docs - Optimized asset loading and paths ### 📚 Documentation - Added new guides: - Math rendering examples and usage - Versioning system setup - Plugin development guide - Admonition syntax reference - Updated existing docs: - Search features with keyboard shortcuts - Accessibility guidelines - Mobile-responsive design - Dark mode support ## [v0.3.0] ### ✨ Features - Added client-side search functionality to allow users to quickly find relevant documentation. See [Search Features](./search-features.md) for more details. - Implemented various improvements to mobile responsiveness for a better user experience on smaller devices. ### 🛠 Fixes & Improvements - General stability and performance improvements. ### 📚 Documentation - Updated roadmap and changelog to reflect recent feature additions and version changes. ## [v0.2.0] ### ✨ Features - Added support for custom 404 pages: Users can create a `404.md` in the project root, which will be converted to `docs/site/404.html` and included in the sitemap. ### 🛠 Fixes & Improvements - Corrected path handling in `main.py` and `serve.py` to ensure proper functionality when WingTip is used as a nested module (e.g., running `python wingtip/main.py` from a parent project directory). - Refined `killDocs.sh` script: - Now attempts a graceful process termination (SIGTERM) before resorting to a forceful one (SIGKILL). - Removed obsolete PID file handling logic. - Removed an unused internal function (`write_docs_index`) from `main.py`. - Removed a duplicate inclusion of `clipboard.js` in `template.html`. ### 📚 Documentation - Updated `README.md` to accurately reflect nested project structure usage (e.g., `wingtip/main.py` for commands and file paths). - Clarified `syntax.css` (generated) vs. `pygments.css` (manual reference) in `README.md`. - Corrected the GitHub Actions workflow example in `README.md` to use `python wingtip/main.py`. - Added `uv` pip install instructions as an alternative in `README.md`. - Documented the new custom 404 page feature in `README.md`. - Documented how to stop the development server (Ctrl+C) and the purpose/usage of `killDocs.sh` in `README.md`. - Corrected `main.py` help text for sitemap generation and removed outdated notes. - Removed mention of a non-implemented "TOC keyboard shortcut (`Alt+D`)" from this changelog (v0.1.0 entry). ## [v0.1.0](#v010) ### ✨ Features - Converts `README.md` and `docs/*.md` to static HTML - Dark/light mode with system theme detection - Slideout nav with project logo - Code syntax highlighting for both themes - Copy-to-clipboard buttons for all code blocks - Previous/next navigation links - GitHub "Edit this page" links - SEO optimization with meta tags and `sitemap.xml` - Built-in Open Graph social card generator (via Pillow) - Live reload development server with scroll state preservation - GitHub Actions workflow for automatic Pages deployment - Configurable `favicon`, `og_image`, and `twitter_handle` in `config.json` ### 🛠 Technical - Markdown to HTML conversion with Pygments highlighting - Clean Python codebase with minimal dependencies - JSON config with fallback defaults - CLI support for `--output` and `--regen-card` - Auto social card fallback and copy to root if `og_image` is unset - Auto-download of Google Fonts for social card rendering - Customizable navigation + dynamic Table of Contents ### 📚 Documentation - Full quickstart and config guide - GitHub Pages deployment with prebuilt `pages.yml` - Example `config.json` for SEO and appearance - Theme toggle and favicon support --- File: docs/configuration.md --- # Configuration WingTip uses a `config.json` file in your project root to control metadata, theming, GitHub integration, and social card generation. This file is **required** if you use: * A custom favicon * Social card generation (`--regen-card`) * SEO-friendly `base_url`, `og_image`, or `twitter_handle` * GitHub "Edit this page" links --- ## Example `config.json` ```json { "base_url": "https://yourusername.github.io/yourrepo", "project_name": "WingTip", "version": "0.1.0", "description": "SEO-friendly Markdown-to-HTML static site generator for GitHub Pages", "author": "Your Name", "repo_url": "https://github.com/yourusername/yourrepo/", "og_image": "social-card.png", "favicon": "https://yourcdn.com/favicon.png", "twitter_handle": "@yourhandle", "github": { "repo": "yourusername/yourrepo", "branch": "main" }, "social_card": { "title": "WingTip", "tagline": "Make your docs fly.", "theme": "light", "font": "Poppins", "image": "social-card.png" } } ``` --- ## Top-Level Fields | Key | Required | Description | | ---------------- | -------- | ------------------------------------------------------------- | | `base_url` | ✔︎ | Your GitHub Pages URL (used in canonical links, sitemap, etc) | | `project_name` | ✔︎ | Name of your project (shown in nav and footer) | | `version` | ✱ | Optional version string shown in footer | | `description` | ✔︎ | Used in meta tags, Open Graph, Twitter | | `author` | ✱ | Used in meta tags | | `repo_url` | ✱ | Used in footer GitHub link | | `og_image` | ✱ | Open Graph image (used unless generated) | | `favicon` | ✱ | PNG favicon shown in nav | | `twitter_handle` | ✱ | Shown in meta tags | --- ## GitHub Integration | Key | Required | Description | | --------------- | -------- | -------------------- | | `github.repo` | ✔︎ | e.g. `username/repo` | | `github.branch` | ✱ | Defaults to `main` | Used to generate **"Edit this page on GitHub"** links. --- ## Social Card Settings | Key | Required | Description | | --------------------- | -------- | --------------------- | | `social_card.title` | ✔︎ | Large text on card | | `social_card.tagline` | ✔︎ | Subtitle text | | `social_card.theme` | ✱ | `"light"` or `"dark"` | | `social_card.font` | ✱ | Any Google Font | | `social_card.image` | ✱ | Path to output PNG | To generate the card, run: ```bash python wingtip/main.py --regen-card ``` If no `og_image` is set, the PNG is also copied to `./social-card.png`. --- ## Font Notes * WingTip uses the Google Fonts API to fetch and cache fonts * If unavailable, it will fall back to `Arial` or a system font * Fonts are stored in `wingtip/fonts/` if downloaded --- ## Fallback Behavior | Scenario | Behavior | | --------------------- | ------------------------------------------------------------------------------ | | `config.json` missing | Falls back to hardcoded defaults (but no favicon/social card support) | | `og_image` unset | Falls back to generated `docs/site/social-card.png` and copies to project root | | `favicon` unset | Default browser icon will be used | --- ## Theming Your Site WingTip offers ways to customize the visual appearance of your documentation. ### Basic Theme Overrides (`theme.json`) You can easily customize global fonts and key colors for both light and dark modes by creating a `theme.json` file in your project's root directory. This allows for quick branding changes without needing to write custom CSS. For detailed instructions on how to structure `theme.json`, available customization options (fonts, colors for light/dark modes), and examples, please see the comprehensive **[Theming Guide](theming.md)**. ### Advanced CSS Customization For more fine-grained control or styles not covered by `theme.json`, you can incorporate your own custom CSS. Refer to the [Advanced CSS Customization section in the Theming Guide](theming.md#advanced-css-customization) for details. --- File: docs/external-links.md --- # External Link Handling WingTip provides flexible control over how external links (links to other websites) are handled in your documentation. ## Configuration External link behavior is controlled through the `external_links` section in your `config.json`: ```json { "external_links": { "open_in_new_tab": true, "exclude_domains": ["example.com", "mycompany.com"], "include_domains": ["external-docs.example.com"], "exclude_paths": ["/docs/internal/*"], "attributes": { "rel": "noopener noreferrer", "class": "external-link" } } } ``` ### Options * `open_in_new_tab` (boolean): Global setting that determines if external links should open in a new tab by default. * `exclude_domains` (array): List of domains that should NOT open in a new tab, even if `open_in_new_tab` is true. * `include_domains` (array): List of domains that should ALWAYS open in a new tab, regardless of other settings. * `exclude_paths` (array): URL path patterns (using glob syntax) that should NOT open in a new tab. * `attributes` (object): Additional HTML attributes to add to external links: * `rel`: Relationship attributes (default: "noopener noreferrer" for security) * `class`: CSS class to apply to external links (default: "external-link") ## Examples ### Basic Configuration The simplest configuration is to make all external links open in new tabs: ```json { "external_links": { "open_in_new_tab": true } } ``` ### Selective Control You can exempt certain domains from opening in new tabs while keeping the default behavior for others: ```json { "external_links": { "open_in_new_tab": true, "exclude_domains": ["trusted-site.com", "internal-docs.com"] } } ``` Or force specific domains to always open in new tabs while leaving others as regular links: ```json { "external_links": { "open_in_new_tab": false, "include_domains": ["external-api-docs.com", "github.com"] } } ``` ### Path-Based Control You can use path patterns to control behavior for specific URL paths: ```json { "external_links": { "open_in_new_tab": true, "exclude_paths": [ "/docs/internal/*", "*/preview/*" ] } } ``` ### Custom Attributes Add custom attributes to external links for styling or tracking: ```json { "external_links": { "open_in_new_tab": true, "attributes": { "rel": "noopener noreferrer", "class": "external-link branded", "data-track": "external-click" } } } ``` ## Default Behavior If no configuration is provided, WingTip will: 1. Open external links in new tabs 2. Add `rel="noopener noreferrer"` for security 3. Add `class="external-link"` for styling ## Styling External Links The default `external-link` class allows you to style external links differently. For example, in your custom CSS: ```css .external-link { /* Add an external link indicator */ background-image: url('data:image/svg+xml;utf8,'); background-position: right 3px center; background-repeat: no-repeat; background-size: 12px; padding-right: 20px; } ``` This will add a small external link icon to visually indicate links that open in new tabs. --- File: docs/live-reload.md --- # Live Reload in WingTip WingTip includes a development server with automatic rebuild and browser refresh on save. This makes local authoring fast and seamless. ## How It Works * `wingtip/serve.py` runs a `livereload` server on port 8000 * It watches these files: * `README.md` * All `docs/*.md` * `template.html` * `main.py` * When a change is detected: * It runs `main.py` in a temporary output folder first * If the build succeeds, it re-runs the actual build * If the build fails, the current site is preserved * The browser auto-refreshes via WebSocket connection * Scroll position is preserved after reload ## Run the Dev Server ```bash pip install livereload python wingtip/serve.py ``` This will: * Open `http://localhost:8000` in your browser * Rebuild the site automatically when you save `.md` or `.html` files * Refresh the browser instantly, even retaining scroll ## Notes * Temporary build directory: `docs/site_tmp` * Live output directory: `docs/site` * Scroll restoration is built-in via the injected livereload client * Errors during rebuild are logged but do not overwrite the current site --- File: docs/math-examples.md --- # Math Examples WingTip supports LaTeX math rendering using KaTeX. You can write both inline and display math expressions. ## Inline Math Use `\(...\)` for inline math. For example: The area of a circle is \(A = \pi r^2\) and its circumference is \(C = 2\pi r\). The quadratic formula is \(x = \frac{-b \pm \sqrt{b^2 - 4ac}}{2a}\). ## Display Math Use `\[...\]` for display math. For example: The Pythagorean theorem: \[a^2 + b^2 = c^2\] Maxwell's equations in differential form: \[ \begin{aligned} \nabla \cdot \mathbf{E} &= \frac{\rho}{\varepsilon_0} \\ \nabla \cdot \mathbf{B} &= 0 \\ \nabla \times \mathbf{E} &= -\frac{\partial \mathbf{B}}{\partial t} \\ \nabla \times \mathbf{B} &= \mu_0\left(\mathbf{J} + \varepsilon_0\frac{\partial \mathbf{E}}{\partial t}\right) \end{aligned} \] ## Matrix Examples A 2x2 matrix: \[ \begin{pmatrix} a & b \\ c & d \end{pmatrix} \] ## Chemical Equations Chemical equations can be written using math mode: \[\ce{CO2 + H2O \rightleftharpoons H2CO3}\] ## Accessibility Math expressions are rendered with proper semantic markup for screen readers. When using a screen reader: 1. Inline math is announced naturally within the text flow 2. Display math is treated as a distinct block with appropriate ARIA labels 3. Complex expressions are broken down into meaningful parts ## Dark Mode Support Math expressions automatically adapt to dark mode when the theme is switched, maintaining readability and consistent styling with the rest of the content. --- File: docs/plugins.md --- # Plugin Development Guide WingTip includes a plugin system that allows you to extend and customize the build process. This guide explains how to create and use plugins. ## Plugin Basics A WingTip plugin is a Python module that defines a class with specific hook methods. The plugin class can modify content at various stages of the build process. ### Plugin Structure Here's the basic structure of a plugin: ```python class MyPlugin: def __init__(self, config=None): """Initialize plugin with optional configuration.""" self.config = config or {} def before_markdown_conversion(self, md_content, metadata, filepath): """Called before markdown is converted to HTML.""" return md_content def after_html_generation(self, html_content, metadata, filepath): """Called after markdown is converted but before page assembly.""" return html_content def after_full_page_assembly(self, final_html, metadata, output_filepath): """Called after the full page HTML is assembled.""" return final_html # Required: Plugin class must be named 'Plugin' Plugin = MyPlugin ``` ### Hook Points Plugins can hook into three points in the build process: 1. **before_markdown_conversion**: Modify raw markdown before it's converted to HTML 2. **after_html_generation**: Modify generated HTML before it's inserted into the page template 3. **after_full_page_assembly**: Modify the complete HTML page before it's written to disk ## Sample Plugin WingTip includes a sample banner plugin that demonstrates the plugin system. You can find it in `plugins/sample_banner_plugin.py`: ```python class BannerPlugin: def __init__(self, config=None): self.config = config or {} self.banner_text = config.get('text', 'This is a sample banner!') self.banner_type = config.get('type', 'info') def after_html_generation(self, html_content, metadata, filepath): banner_html = f'
' h1_end = html_content.find('') if h1_end != -1: return html_content[:h1_end + 5] + banner_html + html_content[h1_end + 5:] return html_content Plugin = BannerPlugin ``` ## Using Plugins To use a plugin: 1. Place your plugin file in the `plugins/` directory 2. Update your `config.json` to enable and configure the plugin: ```json { "plugins": { "banner": { "enabled": true, "config": { "text": "Welcome to my docs!", "type": "info" } } } } ``` ## Creating Your Own Plugin 1. Create a new Python file in the `plugins/` directory 2. Define your plugin class with the desired hook methods 3. Assign your class to `Plugin` at the module level 4. Configure the plugin in `config.json` ### Example: Code Stats Plugin Here's an example plugin that counts lines of code in code blocks: ```python class CodeStatsPlugin: def after_html_generation(self, html_content, metadata, filepath): import re code_blocks = re.findall(r'', html_content, re.DOTALL) total_lines = sum(block.count('\n') + 1 for block in code_blocks) stats_html = f'(.*?)
This page contains {total_lines} lines of code.
' return html_content + stats_html Plugin = CodeStatsPlugin ``` ## Best Practices 1. **Documentation**: Include docstrings and comments explaining your plugin's purpose and configuration options 2. **Error Handling**: Gracefully handle errors and edge cases 3. **Performance**: Keep modifications efficient, especially for large sites 4. **Testing**: Test your plugin with various content types and edge cases ## Plugin API Reference ### Hook Methods #### before_markdown_conversion - **Parameters**: - `md_content`: Raw markdown content - `metadata`: Page metadata from frontmatter - `filepath`: Source markdown file path - **Returns**: Modified markdown content #### after_html_generation - **Parameters**: - `html_content`: Generated HTML content - `metadata`: Page metadata - `filepath`: Source file path - **Returns**: Modified HTML content #### after_full_page_assembly - **Parameters**: - `final_html`: Complete page HTML - `metadata`: Page metadata - `output_filepath`: Output file path - **Returns**: Modified page HTML ### Configuration Plugins can access their configuration through `self.config` in the plugin class. The configuration is loaded from `config.json`. --- File: docs/quickstart.md --- # Quick Start Add beautiful documentation to your project in under 5 minutes. ## 1. Install WingTip (2 min) ```bash # In your project directory: git clone https://github.com/SemanticEntity/WingTip.git pip install -r WingTip/requirements.txt ``` ## 2. Add Your Docs (1 min) ``` your-project/ ├── README.md # Becomes the homepage └── docs/ # Add .md files for documentation └── guide.md ``` ## 3. Configure (Optional, 30s) Create `config.json` in your project root: ```json { "project": "Your Project", "description": "Your project description", "github": { "repo": "username/repo", "branch": "main" } } ``` ## 4. Generate and Preview (10s) ```bash python wingtip/main.py # Build the site python wingtip/serve.py # Start local dev server with live reload ``` Visit `http://localhost:8000` in your browser. ## 5. Deploy to GitHub Pages (1 min) 1. Push your changes to GitHub 2. Go to **Settings → Pages** 3. Set branch to `main` and folder to `/docs/site` 4. Your documentation will be published to `https://username.github.io/repo` --- Your docs now include: * Responsive layout with light/dark mode * Mobile-friendly sidebar and TOC * SEO-optimized output and social cards * GitHub "Edit this page" links * Instant preview with live reload No build tools. No config lock-in. Just Markdown in, HTML out. --- File: docs/roadmap.md --- # WingTip Roadmap ## Feature Comparison | Feature | WingTip v1 | MkDocs | Docusaurus | VitePress | | ----------------------- | ---------------------------- | ------ | ---------- | --------- | | **Markdown Support** | Advanced (GFM + extras) | Good | Advanced | Advanced | | **Code Highlighting** | Pygments (themed) | Good | Advanced | Advanced | | **Dark Mode** | Auto + toggle + CSS vars | Basic | Advanced | Advanced | | **Live Reload** | Full (w/ scroll restore) | Good | Advanced | Advanced | | **Auto Sidebar** | Yes | Yes | Advanced | Advanced | | **Search** | Client-side (JSON) | Basic | Advanced | Good | | **TOC Navigation** | Yes + keyboard shortcuts | Good | Advanced | Good | | **Prev/Next Links** | Yes | Basic | Good | Good | | **Social Cards** | Built-in (Pillow) | None | Basic | None | | **SEO** | Canonical + sitemap + meta | Basic | Advanced | Good | | **Theme System** | CSS vars + JSON config | Basic | Advanced | Good | | **External Links** | Configurable + new tab | Basic | Basic | Basic | | **Math Support** | KaTeX | Plugin | MDX | Plugin | | **Admonitions** | Yes (Material style) | Plugin | MDX | Plugin | | **Analytics** | Not yet | Basic | Advanced | Good | | **Versioning** | Not yet | No | Yes | No | ## Planned Features ### Navigation * Nested sidebar sections (grouping by folder or heading) * ~~Search with local JSON index~~ (Implemented in v0.3.0) * Collapsible sidebar sections * ~~Keyboard shortcuts for navigation and toggles~~ (Implemented in v0.4.0) ### Markdown Enhancements * ~~Basic admonition support~~ (Implemented in v0.4.1) * Advanced admonition features: * Support for nested content (lists, code blocks) * Basic icon support via Material Icons * Theme-aware styling with CSS variables * Future enhancements (deferred): * Support for pymdownx.admonition extension * Custom icons via FontAwesome * Nested admonitions * Custom admonition types * Collapsible admonitions * Icon customization per theme * Support for tables inside list items (Python-Markdown limitation) * Mermaid diagram rendering * ~~LaTeX/math support via KaTeX~~ (Implemented in v0.4.0) * Image captioning syntax ### Developer Experience * True HMR (hot module reload) without full page refresh * Build errors shown in browser overlay * CLI scaffolding (`wingtip new my-docs`) * ~~Local theme overrides via custom CSS~~ (Basic theming via `theme.json` implemented in v0.4.0 - [Learn more](theming.md)) * ~~Combined build and serve command~~ (Implemented in v0.4.1 via `--serve` flag) * ~~Smart port handling for dev server~~ (Implemented in v0.4.1 with auto-retry and port cleanup) * Automatic cleanup of obsolete files (deferred to future release) ### SEO & Output Polish * JSON-LD structured data for articles * Author/date metadata in frontmatter * RSS feed generation * Animated copy-to-clipboard feedback * Custom 404 page ### Longer-Term Ideas * Documentation Versioning & Categories * **Category Support:** * Auto-generate categories from docs/ subfolders * Category metadata via _category.json (name, description, icon, order) * Category-based navigation and breadcrumbs * Category-specific themes and templates * Category-based search filtering * Cross-category linking and references * **Versioning Options:** * File-level versioning (most granular, complex navigation) * Category-level versioning (logical grouping, easier navigation) * Repository-level versioning (simple but all-or-nothing) * Version aliases (latest, stable, dev) * Version-aware navigation and search * Cross-version linking support * i18n / localization * Offline mode (PWA shell) * Plugin system (before/after hooks, Markdown extensions, theme plugins) * *Theme plugins could allow for entirely new site structures, custom JavaScript, advanced CSS processing (Sass, PostCSS), and template overrides, offering a much deeper level of customization than `theme.json`.* ## Future: Theme Plugins We envision a more powerful **Plugin System** for WingTip in the future. A key part of this system would be **Theme Plugins**. Unlike the `theme.json` file, which is for simple value overrides (fonts, colors), theme plugins would offer much deeper customization capabilities, potentially including: * **Custom HTML Templates:** Providing entirely different HTML structures for pages. * **Custom JavaScript:** Adding new client-side functionalities or interactions. * **Advanced CSS Processing:** Integrating tools like Sass or PostCSS for more complex stylesheets. * **New Asset Types:** Managing and including different types of static assets. * **Complete Visual Overhauls:** Creating unique themes that go far beyond color and font changes. This plugin system would provide a structured way for developers to create and share complete themes, transforming the look, feel, and even functionality of a WingTip site. ## Accessibility * ~~Enhanced ARIA attributes for interactive elements~~ (Implemented in v0.4.0) * WCAG 2.1 AA compliance audit and necessary improvements * ~~Keyboard navigation improvements~~ (Implemented in v0.4.0 for search, more to come) ## Performance Optimization * Advanced asset optimization (e.g., image compression, code splitting). * Lazy loading for images and other offscreen content. * Performance budget and monitoring. ## Security Considerations * Implement Content Security Policy (CSP) by default. * Regular dependency audits and updates for security vulnerabilities. * Guidance on securing user-generated content if applicable. ## Community & Contribution * Detailed `CONTRIBUTING.md` guide. * Automated PR checks for linting and tests. * Consider a "Good first issue" program for new contributors. ## Deployment * Guides for deploying to popular platforms (e.g., GitHub Pages, Netlify, Vercel). * CLI command or integration for easier deployment. --- File: docs/search-features.md --- # Client-Side Search Functionality WingTip includes a powerful and lightweight client-side search feature that allows users to quickly find relevant information within the documentation. ## How it Works The search functionality is designed to be fast and entirely client-side, making it suitable for static hosting environments like GitHub Pages. Here's a brief overview: 1. **Search Index (`search_index.json`)**: When the site is built, WingTip generates a file named `search_index.json`. This file contains a structured list of all the pages in your documentation (excluding special pages like 404). For each page, the index stores: * The page title. * The plain text content of the page (with HTML tags and frontmatter removed). * The relative URL to the page. 2. **Client-Side Processing**: When a user types into the search bar: * The browser fetches the `search_index.json` file (this happens only once, on the first search interaction typically). * JavaScript running in the browser then filters this index based on the search query. * It matches the query against both the titles and the text content of the pages. * Matching results are displayed dynamically below the search bar as a list of links. ## Using the Search Bar - The search bar is located in the main navigation header for easy access. - Simply type your search terms into the input field. - Results will appear as you type (minimum 2 characters required). - Use keyboard navigation: - Press `/` to focus the search bar - Use `↑` and `↓` arrows to navigate results - Press `Enter` to go to the selected result - Press `Esc` to clear the search - Clicking on a search result will take you directly to the relevant page. - Search results highlight matching text for better visibility. ## Benefits - **Fast**: Since the search happens in the user's browser with a local index, it's very responsive. - **No Server-Side Dependencies**: Works perfectly on static hosting platforms. - **Comprehensive**: Searches both page titles and full text content. - **Accessible**: Full keyboard navigation and screen reader support. - **User-Friendly**: Results highlight matches and update in real-time. This approach ensures that your documentation remains easy to navigate and user-friendly without requiring complex backend infrastructure. --- File: docs/theming.md --- # Theming in WingTip WingTip provides a flexible way to customize the appearance of your documentation site. You can start with basic overrides for fonts and colors, and for more advanced needs, standard CSS practices can be employed. ## Basic Theme Overrides (`theme.json`) The primary way to customize your site's look and feel is by creating a `theme.json` file in the root of your project (the same directory as your `config.json`). This file allows you to define global font choices and specify colors for both light and dark modes. If `theme.json` is not present, or if specific keys within it are missing, WingTip will use its default styles, which are based on Water.css and predefined font stacks. ### Structure of `theme.json` The `theme.json` file has three main top-level keys: * `"fonts"`: For defining global font families. * `"light_mode"`: For defining colors specific to the light theme. * `"dark_mode"`: For defining colors specific to the dark theme. ### Example `theme.json` ```json { "fonts": { "sans_serif": "\"Inter\", -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Oxygen, Ubuntu, Cantarell, \"Fira Sans\", \"Droid Sans\", \"Helvetica Neue\", sans-serif", "monospace": "\"JetBrains Mono\", Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace" }, "light_mode": { "background_body": "#FCFCFC", "background_element": "#FFFFFF", "text_main": "#333333", "text_bright": "#000000", "links_or_primary": "#005FB8", "border": "#E0E0E0" }, "dark_mode": { "background_body": "#1E1E1E", "background_element": "#2C2C2C", "text_main": "#E0E0E0", "text_bright": "#FFFFFF", "links_or_primary": "#3391FF", "border": "#4A4A4A" } } ``` ### Detailed Configuration #### 1. Fonts The `fonts` object accepts two keys: * **`sans_serif`**: (String) A CSS `font-family` stack for the main body text. * _Default_: `system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 'Segoe UI Emoji', 'Apple Color Emoji', 'Noto Color Emoji', sans-serif` * _Example_: `"Inter", sans-serif` * **`monospace`**: (String) A CSS `font-family` stack for code blocks (``) and inline code (``).
* _Default_: `Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace`
* _Example_: `"Fira Code", monospace`
WingTip will use these values to set the `--theme-font-family-sans-serif` and `--theme-font-family-monospace` CSS variables. The `body` and code elements are styled to use these variables.
#### 2. Light Mode & Dark Mode Colors
The `light_mode` and `dark_mode` objects accept the same set of keys to define colors for their respective themes. All values should be valid CSS color strings (e.g., hex codes like `#RRGGBB`, color names like `blue`, `rgb(...)`, `hsl(...)`).
| Key | Corresponding Water.css Variable | Description |
| -------------------- | -------------------------------- | ---------------------------------------------------------------------------------------- |
| `background_body` | `--background-body` | The main background color of the page. |
| `background_element` | `--background` | Background for elements like inline code, inputs, default buttons, even-numbered table rows. |
| `text_main` | `--text-main` | The primary color for most body text. |
| `text_bright` | `--text-bright` | Color for headings (``-``) and bold/strong text. |
| `links_or_primary` | `--links` | Color for hyperlinks. This often serves as the site's primary accent color. |
| `border` | `--border` | Color for table borders, `
` elements, fieldset borders, etc. |
_You can also add other keys if you wish to define additional theme-specific color variables (e.g., `"secondary_accent": "#value"`), which would generate `--theme-color-secondary-accent-light` and `--theme-color-secondary-accent-dark`. These would then need to be used in your own custom CSS._
When you define these color keys, WingTip generates CSS variables that override the default Water.css styles. For example, `light_mode.background_body = "#FAF7F0"` will set the `--background-body` CSS variable to `#FAF7F0` when the light theme is active.
This system allows for quick and easy visual customization of your documentation.
### Tips for Choosing Colors and Fonts
* **Contrast:** Ensure sufficient contrast between text colors and background colors for readability, especially for accessibility (WCAG AA guidelines are a good reference).
* **Font Legibility:** Choose fonts that are clear and easy to read for body text and code. Consider fonts designed for UIs or reading.
* **Consistency:** Try to maintain a consistent feel between your light and dark mode themes, even if colors are inverted.
* **Test:** Always preview your changes in both light and dark modes to ensure they look as expected. Use tools like [Color Contrast Analyzer](https://webaim.org/resources/contrastchecker/) to check contrast ratios.
## Advanced CSS Customization
While `theme.json` provides a straightforward way to change common visual elements, you might have more specific styling needs. For these scenarios, you can:
1. **Create a `custom.css` file:** Place this file in your `static/css/` directory (e.g., `static/css/custom.css`).
2. **Link it in `template.html`:** You would need to modify your local `template.html` (if you've ejected or copied it for customization) to include a link to this stylesheet. Make sure to link it *after* the Water.css link and after the injected theme variables style block if you want your custom CSS to override them.
```html
...
...
```
*(Note: The `${base_url}` part is important if your site is not served from the root of a domain).*