diff --git a/.gitignore b/.gitignore index 5d381cc..26e87e1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,162 +1,4 @@ -# ---> Python -# Byte-compiled / optimized / DLL files -__pycache__/ -*.py[cod] -*$py.class - -# C extensions -*.so - -# Distribution / packaging -.Python -build/ -develop-eggs/ -dist/ -downloads/ -eggs/ -.eggs/ -lib/ -lib64/ -parts/ -sdist/ -var/ -wheels/ -share/python-wheels/ -*.egg-info/ -.installed.cfg -*.egg -MANIFEST - -# PyInstaller -# Usually these files are written by a python script from a template -# before PyInstaller builds the exe, so as to inject date/other infos into it. -*.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 -*.py,cover -.hypothesis/ -.pytest_cache/ -cover/ - -# Translations -*.mo -*.pot - -# Django stuff: -*.log -local_settings.py -db.sqlite3 -db.sqlite3-journal - -# Flask stuff: -instance/ -.webassets-cache - -# Scrapy stuff: -.scrapy - -# Sphinx documentation -docs/_build/ - -# PyBuilder -.pybuilder/ -target/ - -# Jupyter Notebook -.ipynb_checkpoints - -# IPython -profile_default/ -ipython_config.py - -# pyenv -# For a library or package, you might want to ignore these files since the code is -# intended to run in multiple environments; otherwise, check them in: -# .python-version - -# pipenv -# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. -# However, in case of collaboration, if having platform-specific dependencies or dependencies -# having no cross-platform support, pipenv may install dependencies that don't work, or not -# install all needed dependencies. -#Pipfile.lock - -# poetry -# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. -# This is especially recommended for binary packages to ensure reproducibility, and is more -# commonly ignored for libraries. -# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control -#poetry.lock - -# pdm -# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. -#pdm.lock -# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it -# in version control. -# https://pdm.fming.dev/#use-with-ide -.pdm.toml - -# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm -__pypackages__/ - -# Celery stuff -celerybeat-schedule -celerybeat.pid - -# SageMath parsed files -*.sage.py - -# Environments -.env .venv -env/ -venv/ -ENV/ -env.bak/ -venv.bak/ - -# Spyder project settings -.spyderproject -.spyproject - -# Rope project settings -.ropeproject - -# mkdocs documentation -/site - -# mypy -.mypy_cache/ -.dmypy.json -dmypy.json - -# Pyre type checker -.pyre/ - -# pytype static type analyzer -.pytype/ - -# Cython debug symbols -cython_debug/ - -# PyCharm -# JetBrains specific template is maintained in a separate JetBrains.gitignore that can -# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore -# and can be added to the global gitignore or merged into this file. For a more nuclear -# option (not recommended) you can uncomment the following to ignore the entire idea folder. -#.idea/ - +build/ +*.egg-info +__pycache__ \ No newline at end of file diff --git a/README.md b/README.md index 4987ca0..06fe32a 100644 --- a/README.md +++ b/README.md @@ -2,5 +2,10 @@ This is a basic static site generator for my personal website. +To generate a site to: + +``` shell +dialann --build_dir $BUILD_DIR +``` diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..ac97a31 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,104 @@ +[project] +name = "dialann" +version = "0.0.0" +authors = [ + { name="James Grogan", email="james@jmsgrogan.com" }, +] +description = "Simple static site generator." +readme = "README.md" +requires-python = ">=3.8" +classifiers = [ + "Development Status :: 3 - Alpha", + "Programming Language :: Python :: 3", + "License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)", + "Operating System :: OS Independent", + "Topic :: System :: Distributed Computing" +] +keywords = ["Publishing", "Technical Reports"] + +dependencies = ["markdown-it-py", + "mdit_py_plugins", + "mdformat", + "beautifulsoup4", + "pyspelling"] + +[project.urls] +Repository = "https://git.jmsgrogan.com/jgrogan/dialann" +Homepage = "https://git.jmsgrogan.com/jgrogan/dialann" + +[project.optional-dependencies] +test = [ + "pytest", + "pytest-cov", + "pytest-sugar", + "black", + "mypy", + "flake8", + "pylint" +] + +[build-system] +requires = ["setuptools>=61.0", "wheel"] +build-backend = "setuptools.build_meta" + +[project.scripts] +dialann = "dialann.main_cli:main_cli" + +[tool.setuptools.package-data] +"dialann" = ["py.typed"] + +[tool.setuptools.packages.find] +where = ["src"] + +[tool.pytest.ini_options] +testpaths = ["test",] +log_cli = 1 +log_cli_level = "debug" +addopts = "--cov=dialann --cov-report term --cov-report xml:coverage.xml --cov-report html" + +[tool.mypy] +ignore_missing_imports = true + +[tool.tox] +legacy_tox_ini = """ +[tox] +requires = + tox>=4 +env_list = lint, type, style, py{311}, docs +skip_missing_interpreters = true + +[testenv] +description = run unit tests +deps = + pytest>=7 + pytest-cov + pytest-sugar +commands = + pytest {posargs:test} + +[testenv:lint] +description = run linters +skip_install = true +deps = + black +commands = black {posargs:src} + +[testenv:style] +description = run style check +skip_install = true +deps = + flake8 +commands = flake8 {posargs:src} + +[testenv:type] +description = run type checks +deps = + mypy>=0.991 +commands = + mypy {posargs:src test} + +[testenv:docs] +changedir = docs +deps = sphinx +commands = sphinx-build -W -b html -d {envtmpdir}/doctrees . {envtmpdir}/html +""" \ No newline at end of file diff --git a/src/dialann/main_cli.py b/src/dialann/main_cli.py new file mode 100644 index 0000000..1210337 --- /dev/null +++ b/src/dialann/main_cli.py @@ -0,0 +1,30 @@ +#!/usr/bin/env python3 +import argparse +import logging +from pathlib import Path + +from .site_generator import SiteGenerator + +logger = logging.getLogger(__name__) + +def generate(source_dir:Path, build_dir: Path): + + generator = SiteGenerator(source_dir, build_dir) + generator.run() + +def main_cli(): + parser = argparse.ArgumentParser() + parser.add_argument( + "--build_dir", + type=Path, + help="Path to the build output", + ) + parser.add_argument( + "--source_dir", type=Path, default=Path(), + help="Site source directory") + + args = parser.parse_args() + generate(args.source_dir, args.build_dir) + +if __name__ == "__main__": + main_cli() diff --git a/src/dialann/site_generator.py b/src/dialann/site_generator.py new file mode 100644 index 0000000..d509ffa --- /dev/null +++ b/src/dialann/site_generator.py @@ -0,0 +1,27 @@ +from pathlib import Path +import os + +from markdown_it import MarkdownIt + +class SiteGenerator(): + + def __init__(self, source_dir: Path, + build_dir: Path): + self.source_dir = source_dir + self.build_dir = build_dir + self.parser = MarkdownIt() + + def run(self): + + for md_file in self.source_dir.glob('**/*.md'): + with open(md_file, 'r', encoding='utf-8') as f: + md_src = f.read() + + html_path = self.build_dir / (str(md_file.stem) + ".html") + os.makedirs(html_path.parent, exist_ok=True) + + html_src = self.parser.render(md_src) + with open(html_path, 'w', encoding='utf-8') as f: + f.write(html_src) + +