Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 96 additions & 0 deletions .github/workflows/wheel.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
name: create wheels

on:
workflow_dispatch:
pull_request:
push:
branches:
- main
tags:
- "v*"

env:
FORCE_COLOR: 3

concurrency:
group: github.workflow−{{ github.workflow }}-{{ github.ref }}
cancel-in-progress: true

jobs:
build_wheels:
name: Build universal wheels
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
with:
submodules: false

- uses: actions/setup-python@v4
with:
python-version: "3.x"

- name: Install build dependencies
run: |
python -m pip install --upgrade pip
pip install build

- name: Build universal wheels
run: python -m build --wheel

- name: Verify clean directory
run: git diff --exit-code
shell: bash

- uses: actions/upload-artifact@v4
with:
name: wheelhouse
path: dist/*.whl
overwrite: true


release:
name: Release Assets and Upload to PyPI
needs: [build_wheels]
runs-on: ubuntu-latest

steps:
# Determine release type
- name: Determine release type
id: release_type
run: |
if [[ "${{ github.ref }}" =~ ^refs/tags/v.*$ ]]; then
echo "RELEASE_NAME=${GITHUB_REF#refs/tags/}" >> $GITHUB_ENV
echo "IS_TAG=true" >> $GITHUB_ENV
else
echo "RELEASE_NAME=__beta__" >> $GITHUB_ENV
echo "IS_TAG=false" >> $GITHUB_ENV
fi
shell: bash # Use bash for all platforms

- uses: actions/download-artifact@v4
with:
path: dist
merge-multiple: true


- name: List dist directory
run: tree --du -shaC . # Ensure the directory is not empty

- name: Create or update release
id: create_release
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ env.RELEASE_NAME }}
name: ${{ env.RELEASE_NAME }}
draft: false
prerelease: ${{ env.IS_TAG == 'false' }}
files: dist/*
token: ${{ secrets.GITHUB_TOKEN }}

- name: Publishing to PyPi
uses: pypa/gh-action-pypi-publish@release/v1
if: startsWith(github.ref, 'refs/tags/')
with:
password: ${{ secrets.PYPI_PASSWORD }}
user: ${{ secrets.PYPI_USERNAME }}
65 changes: 65 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,68 @@ docs/html

node_modules
*.tgz

# Python
__pycache__/
*.py[cod]
*$py.class
*.so
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

# PyInstaller
*.manifest
*.spec

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
.hypothesis/
.pytest_cache/

# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/

# IDE
.vscode/
.ropeproject

# mypy
.mypy_cache/
.dmypy.json
dmypy.json

# Hatch
.hatch/
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,24 @@ Similarly, in the [xPack](https://xpack.github.io) ecosystem, this project can b
as a development dependency to an [`xpm`](https://xpack.github.io/xpm/)
managed project.

### Python

For Python projects, you can install the theme as a Python package:

```sh
# Install the package
pip install doxygen-awesome-css

# Install files to your project directory
python -m doxygen_awesome_css --install .
# Install with verbose output
python -m doxygen_awesome_css --install ./docs --verbose
# Quiet mode (minimal output)
python -m doxygen_awesome_css --install ./docs --quiet
```

This method provides a clean way to manage the theme as a dependency and easily install the files where needed.

### System-wide

You can even install the theme system-wide by running `make install`.
Expand Down
4 changes: 4 additions & 0 deletions doxygen_awesome_css/__about__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
"""Package metadata for Doxygen Awesome CSS."""

__version__ = "2.4.1.beta"
__license__ = "MIT"
82 changes: 82 additions & 0 deletions doxygen_awesome_css/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
"""Doxygen Awesome CSS - A custom CSS theme for Doxygen HTML documentation."""

import logging
import shutil
import sys
from pathlib import Path
from typing import List

from .__about__ import __version__, __license__


class Installer:
"""Handles installation of Doxygen Awesome CSS files."""

def __init__(self):
self.logger = logging.getLogger(__name__)
self.package_dir = Path(__file__).parent
self.files_to_copy = [
"doxygen-awesome.css",
"doxygen-awesome-darkmode-toggle.js",
"doxygen-awesome-fragment-copy-button.js",
"doxygen-awesome-interactive-toc.js",
"doxygen-awesome-paragraph-link.js",
"doxygen-awesome-sidebar-only-darkmode-toggle.css",
"doxygen-awesome-sidebar-only.css",
"doxygen-awesome-tabs.js",
]

def get_package_files(self) -> List[Path]:
"""Get list of package files that exist."""
package_files = []
for filename in self.files_to_copy:
file_path = self.package_dir / filename
if file_path.exists():
package_files.append(file_path)
else:
self.logger.warning(f"{filename} not found in package")
return package_files

def install(self, target_dir: Path) -> None:
"""Install CSS/JS files to target directory."""
if not target_dir.exists():
try:
target_dir.mkdir(parents=True, exist_ok=True)
self.logger.info(f"Successfully created directory '{target_dir}'")
except Exception as e:
self.logger.error(f"Failed to create directory '{target_dir}': {e}")
sys.exit(1)

if not target_dir.is_dir():
self.logger.error(f"'{target_dir}' is not a directory")
sys.exit(1)

package_files = self.get_package_files()

if not package_files:
self.logger.error("No Doxygen Awesome CSS files found in package")
sys.exit(1)

self.logger.info(f"Installing Doxygen Awesome CSS files to '{target_dir}'...")

copied_count = 0
for source_file in package_files:
target_file = target_dir / source_file.name
try:
shutil.copy2(source_file, target_file)
self.logger.debug(f"Copied: {source_file.name}")
copied_count += 1
except Exception as e:
self.logger.error(f"Error copying {source_file.name}: {e}")
sys.exit(1)

self.logger.info(f"Successfully installed {copied_count} files to '{target_dir}'")

# Show installation summary
if logging.getLogger().getEffectiveLevel() == logging.DEBUG:
self.logger.debug("Installed files:")
for source_file in package_files:
self.logger.debug(f" - {source_file.name}")


__all__ = ["Installer", "__version__"]
90 changes: 90 additions & 0 deletions doxygen_awesome_css/__main__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
"""Main entry point for Doxygen Awesome CSS CLI."""

import argparse
import logging
from pathlib import Path

from . import Installer
from .__about__ import __version__


def setup_logging(verbose: bool = False, quiet: bool = False) -> None:
"""Setup logging configuration based on verbosity."""
if quiet:
level = logging.WARNING
elif verbose:
level = logging.DEBUG
else:
level = logging.INFO

logging.basicConfig(
level=level,
format="%(message)s",
handlers=[logging.StreamHandler()]
)


def create_parser() -> argparse.ArgumentParser:
"""Create argument parser for CLI."""
parser = argparse.ArgumentParser(
description="Doxygen Awesome CSS - A custom CSS theme for Doxygen HTML documentation",
epilog="""
Examples:
# Install files to current directory
python -m doxygen_awesome_css --install .

# Install files with verbose output
python -m doxygen_awesome_css --install ./docs --verbose

# Show version
python -m doxygen_awesome_css --version
""",
formatter_class=argparse.RawDescriptionHelpFormatter,
)

parser.add_argument(
"--install",
type=str,
metavar="DIR",
help="Install CSS/JS files to the specified directory",
)

parser.add_argument(
"--verbose", "-v",
action="store_true",
help="Enable verbose output (DEBUG level)",
)

parser.add_argument(
"--quiet", "-q",
action="store_true",
help="Enable quiet output (WARNING level)",
)

parser.add_argument(
"--version",
action="version",
version=f"doxygen-awesome-css {__version__}",
)

return parser


def main() -> None:
"""Main entry point for CLI."""
parser = create_parser()
args = parser.parse_args()

setup_logging(verbose=args.verbose, quiet=args.quiet)
logger = logging.getLogger(__name__)

if args.install:
installer = Installer()
installer.install(Path(args.install))
else:
logger.info("Doxygen Awesome CSS - A custom CSS theme for Doxygen HTML documentation")
logger.info("Use --help for usage information")


if __name__ == "__main__":
main()
Loading