├── .codecov.yaml ├── .djlintrc ├── .github ├── dependabot.yml └── workflows │ └── ci.yml ├── .gitignore ├── .pre-commit-config.yaml ├── .readthedocs.yml ├── .rtd-environment.yml ├── .stylelintrc.json ├── LICENSE.rst ├── Makefile ├── README.rst ├── ablog-conda-test-env.yml ├── conftest.py ├── docs ├── Makefile ├── _static │ ├── ablog.ico │ ├── ablog.png │ └── ablog.svg ├── conf.py ├── index.rst ├── make.bat ├── manual │ ├── ablog-commands.rst │ ├── ablog-configuration-options.rst │ ├── ablog-i18n.rst │ ├── ablog-quick-start.rst │ ├── api.rst │ ├── cross-referencing-blog-pages.rst │ ├── deploy-to-github-pages.rst │ ├── external-post.rst │ ├── forever-draft.rst │ ├── images │ │ └── notebook_cells.png │ ├── markdown.md │ ├── notebook_support.ipynb │ ├── post-excerpts-and-images.rst │ ├── posting-and-listing.rst │ ├── templates-themes.rst │ └── watch-yourself-blogging.rst ├── nitpick-exceptions └── release │ ├── ablog-v0.1-released.rst │ ├── ablog-v0.10-released.rst │ ├── ablog-v0.11-released.rst │ ├── ablog-v0.2-released.rst │ ├── ablog-v0.3-released.rst │ ├── ablog-v0.4-released.rst │ ├── ablog-v0.5-released.rst │ ├── ablog-v0.6-released.rst │ ├── ablog-v0.7-released.rst │ ├── ablog-v0.8-released.rst │ └── ablog-v0.9-released.rst ├── pyproject.toml ├── roots ├── test-build │ ├── conf.py │ ├── foo-empty-post.rst │ ├── index.rst │ └── post.rst ├── test-canonical │ ├── canonical.rst │ ├── conf.py │ ├── index.rst │ ├── post.rst │ └── postlist.rst ├── test-external │ ├── conf.py │ ├── external.rst │ ├── index.rst │ └── postlist.rst ├── test-parallel │ ├── conf.py │ ├── index.rst │ ├── post1.rst │ ├── post2.rst │ ├── post3.rst │ ├── post4.rst │ └── postlist.rst ├── test-postlist │ ├── conf.py │ ├── index.rst │ ├── post.rst │ └── postlist.rst └── test-templates │ ├── _templates │ └── ablog │ │ └── postcard.html │ ├── _themes │ └── test_theme │ │ ├── ablog │ │ └── postcard.html │ │ └── theme.toml │ ├── conf.py │ ├── index.rst │ ├── post.rst │ └── postlist.rst ├── setup.cfg ├── setup.py ├── src └── ablog │ ├── __init__.py │ ├── blog.py │ ├── commands.py │ ├── locales │ ├── ca │ │ └── LC_MESSAGES │ │ │ ├── sphinx.mo │ │ │ └── sphinx.po │ ├── de │ │ └── LC_MESSAGES │ │ │ ├── sphinx.mo │ │ │ └── sphinx.po │ ├── es │ │ └── LC_MESSAGES │ │ │ ├── sphinx.mo │ │ │ └── sphinx.po │ ├── et │ │ └── LC_MESSAGES │ │ │ ├── sphinx.mo │ │ │ └── sphinx.po │ ├── fr │ │ └── LC_MESSAGES │ │ │ ├── sphinx.mo │ │ │ └── sphinx.po │ ├── it │ │ └── LC_MESSAGES │ │ │ ├── sphinx.mo │ │ │ └── sphinx.po │ ├── pt │ │ └── LC_MESSAGES │ │ │ ├── sphinx.mo │ │ │ └── sphinx.po │ ├── ru │ │ └── LC_MESSAGES │ │ │ ├── sphinx.mo │ │ │ └── sphinx.po │ ├── sphinx.pot │ ├── tr │ │ └── LC_MESSAGES │ │ │ ├── sphinx.mo │ │ │ └── sphinx.po │ └── zh_CN │ │ └── LC_MESSAGES │ │ ├── sphinx.mo │ │ └── sphinx.po │ ├── post.py │ ├── start.py │ ├── stylesheets │ └── ablog │ │ └── tagcloud.css │ ├── templates │ ├── ablog │ │ ├── archives.html │ │ ├── authors.html │ │ ├── catalog.html │ │ ├── categories.html │ │ ├── collection.html │ │ ├── languages.html │ │ ├── locations.html │ │ ├── postcard.html │ │ ├── postcard2.html │ │ ├── postnavy.html │ │ ├── recentposts.html │ │ ├── redirect.html │ │ └── tagcloud.html │ ├── archives.html │ ├── authors.html │ ├── catalog.html │ ├── categories.html │ ├── collection.html │ ├── languages.html │ ├── locations.html │ ├── page.html │ ├── postcard.html │ ├── postcard2.html │ ├── postnavy.html │ ├── recentposts.html │ ├── redirect.html │ └── tagcloud.html │ ├── tests │ ├── __init__.py │ ├── test_build.py │ ├── test_canonical.py │ ├── test_external.py │ ├── test_parallel.py │ ├── test_postlist.py │ └── test_templates.py │ └── version.py └── tox.ini /.codecov.yaml: -------------------------------------------------------------------------------- 1 | codecov: 2 | token: a0dfd87f-8eb9-4a41-9e4e-a06919f216cd 3 | comment: off 4 | coverage: 5 | status: 6 | project: 7 | default: 8 | threshold: 0.2% 9 | -------------------------------------------------------------------------------- /.djlintrc: -------------------------------------------------------------------------------- 1 | { 2 | "profile": "jinja", 3 | "extension": "html", 4 | "indent": "2", 5 | "max_line_length": "120", 6 | "use_gitignore": "True", 7 | "format_js": "True", 8 | "format_css": "True", 9 | "ignore": "H006,J018,T003,H025" 10 | } 11 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "github-actions" 4 | directory: "/" 5 | schedule: 6 | interval: "monthly" 7 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: 6 | - "main" 7 | - "*.*" 8 | - "!*backport*" 9 | tags: 10 | - "v*" 11 | - "!*dev*" 12 | - "!*pre*" 13 | - "!*post*" 14 | pull_request: 15 | # Allow manual runs through the web UI 16 | workflow_dispatch: 17 | schedule: 18 | # ┌───────── minute (0 - 59) 19 | # │ ┌───────── hour (0 - 23) 20 | # │ │ ┌───────── day of the month (1 - 31) 21 | # │ │ │ ┌───────── month (1 - 12 or JAN-DEC) 22 | # │ │ │ │ ┌───────── day of the week (0 - 6 or SUN-SAT) 23 | - cron: "0 7 * * *" # Every day at 07:00 UTC 24 | 25 | concurrency: 26 | group: ${{ github.workflow }}-${{ github.ref }} 27 | cancel-in-progress: true 28 | 29 | jobs: 30 | core: 31 | uses: OpenAstronomy/github-actions-workflows/.github/workflows/tox.yml@main 32 | with: 33 | submodules: false 34 | coverage: codecov 35 | libraries: | 36 | apt: 37 | - pandoc 38 | - graphviz 39 | envs: | 40 | - linux: py313-sphinx8 41 | secrets: 42 | CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} 43 | 44 | test: 45 | needs: [core] 46 | uses: OpenAstronomy/github-actions-workflows/.github/workflows/tox.yml@main 47 | with: 48 | submodules: false 49 | libraries: | 50 | brew: 51 | - pandoc 52 | - graphviz 53 | choco: 54 | - pandoc 55 | - graphviz 56 | apt: 57 | - pandoc 58 | - graphviz 59 | envs: | 60 | - macos: py312-sphinx8 61 | - windows: py311-sphinx8 62 | - linux: py310-sphinx8 63 | - linux: py312-pydata-sphinx-theme 64 | - linux: py313-devdeps 65 | 66 | extra_tests: 67 | needs: [test] 68 | uses: OpenAstronomy/github-actions-workflows/.github/workflows/tox.yml@main 69 | with: 70 | submodules: false 71 | libraries: | 72 | apt: 73 | - pandoc 74 | - graphviz 75 | envs: | 76 | - linux: py312-pydata-sphinx-theme 77 | - linux: py313-devdeps 78 | 79 | docs: 80 | needs: [core] 81 | uses: OpenAstronomy/github-actions-workflows/.github/workflows/tox.yml@main 82 | with: 83 | submodules: false 84 | pytest: false 85 | libraries: | 86 | apt: 87 | - pandoc 88 | - graphviz 89 | envs: | 90 | - linux: py313-docs 91 | - linux: py313-linkcheck 92 | 93 | sdist_verify: 94 | runs-on: ubuntu-latest 95 | steps: 96 | - uses: actions/checkout@v4 97 | - uses: actions/setup-python@v5 98 | with: 99 | python-version: "3.13" 100 | - run: python -m pip install -U --user build 101 | - run: python -m build . --sdist 102 | - run: python -m pip install -U --user twine 103 | - run: python -m twine check dist/* 104 | 105 | conda: 106 | needs: [test] 107 | runs-on: ubuntu-latest 108 | steps: 109 | - uses: actions/checkout@v4 110 | with: 111 | fetch-depth: 0 112 | lfs: true 113 | - uses: conda-incubator/setup-miniconda@v3 114 | with: 115 | activate-environment: ablog-test 116 | environment-file: ablog-conda-test-env.yml 117 | python-version: "3.13" 118 | - name: Install ablog 119 | shell: bash -el {0} 120 | run: | 121 | pip install --no-deps --no-build-isolation . 122 | - name: Run test 123 | shell: bash -el {0} 124 | run: | 125 | conda list 126 | cd /tmp 127 | pytest -vvv -r a --pyargs ablog 128 | make tests 129 | 130 | publish: 131 | # Build wheels on PRs only when labelled. Releases will only be published if tagged ^v.* 132 | # see https://github-actions-workflows.openastronomy.org/en/latest/publish.html#upload-to-pypi 133 | if: | 134 | github.event_name != 'pull_request' || 135 | ( 136 | github.event_name == 'pull_request' && 137 | contains(github.event.pull_request.labels.*.name, 'Run publish') 138 | ) 139 | needs: [test, docs, sdist_verify] 140 | uses: OpenAstronomy/github-actions-workflows/.github/workflows/publish_pure_python.yml@main 141 | with: 142 | python-version: "3.13" 143 | submodules: false 144 | secrets: 145 | pypi_token: ${{ secrets.PYPI_TOKEN }} 146 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ### Python: https://raw.githubusercontent.com/github/gitignore/master/Python.gitignore 2 | 3 | # Byte-compiled / optimized / DLL files 4 | __pycache__/ 5 | *.py[cod] 6 | *$py.class 7 | 8 | # C extensions 9 | *.so 10 | 11 | # Distribution / packaging 12 | .Python 13 | pip-wheel-metadata/ 14 | build/ 15 | develop-eggs/ 16 | dist/ 17 | downloads/ 18 | eggs/ 19 | .eggs/ 20 | lib/ 21 | lib64/ 22 | parts/ 23 | sdist/ 24 | var/ 25 | wheels/ 26 | *.egg-info/ 27 | .installed.cfg 28 | *.egg 29 | MANIFEST 30 | 31 | # PyInstaller 32 | # Usually these files are written by a python script from a template 33 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 34 | *.manifest 35 | *.spec 36 | 37 | # Installer logs 38 | pip-log.txt 39 | pip-delete-this-directory.txt 40 | 41 | # Unit test / coverage reports 42 | htmlcov/ 43 | .tox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *.cover 50 | .hypothesis/ 51 | .pytest_cache/ 52 | junit/ 53 | 54 | # Django stuff: 55 | *.log 56 | local_settings.py 57 | db.sqlite3 58 | 59 | # Flask stuff: 60 | instance/ 61 | .webassets-cache 62 | 63 | # Scrapy stuff: 64 | .scrapy 65 | 66 | # PyBuilder 67 | target/ 68 | 69 | # Jupyter Notebook 70 | .ipynb_checkpoints 71 | 72 | # pyenv 73 | .python-version 74 | 75 | # celery beat schedule file 76 | celerybeat-schedule 77 | 78 | # SageMath parsed files 79 | *.sage.py 80 | 81 | # Environments 82 | .env 83 | .venv 84 | env/ 85 | venv/ 86 | ENV/ 87 | env.bak/ 88 | venv.bak/ 89 | 90 | # Spyder project settings 91 | .spyderproject 92 | .spyproject 93 | 94 | # Rope project settings 95 | .ropeproject 96 | 97 | # mkdocs documentation 98 | /site 99 | 100 | # mypy 101 | .mypy_cache/ 102 | 103 | ### https://raw.github.com/github/gitignore/master/Global/OSX.gitignore 104 | 105 | .DS_Store 106 | .AppleDouble 107 | .LSOverride 108 | 109 | # Icon must ends with two \r. 110 | Icon 111 | 112 | 113 | # Thumbnails 114 | ._* 115 | 116 | # Files that might appear on external disk 117 | .Spotlight-V100 118 | .Trashes 119 | 120 | ### Linux: https://raw.githubusercontent.com/github/gitignore/master/Global/Linux.gitignore 121 | 122 | *~ 123 | 124 | # temporary files which can be created if a process still has a handle open of a deleted file 125 | .fuse_hidden* 126 | 127 | # KDE directory preferences 128 | .directory 129 | 130 | # Linux trash folder which might appear on any partition or disk 131 | .Trash-* 132 | 133 | # .nfs files are created when an open file is removed but is still being accessed 134 | .nfs* 135 | 136 | ### MacOS: https://raw.githubusercontent.com/github/gitignore/master/Global/macOS.gitignore 137 | 138 | # Files that might appear in the root of a volume 139 | .DocumentRevisions-V100 140 | .fseventsd 141 | .TemporaryItems 142 | .VolumeIcon.icns 143 | .com.apple.timemachine.donotpresent 144 | 145 | # Directories potentially created on remote AFP share 146 | .AppleDB 147 | .AppleDesktop 148 | Network Trash Folder 149 | Temporary Items 150 | .apdisk 151 | 152 | ### Windows: https://raw.githubusercontent.com/github/gitignore/master/Global/Windows.gitignore 153 | 154 | # Windows thumbnail cache files 155 | Thumbs.db 156 | ehthumbs.db 157 | ehthumbs_vista.db 158 | 159 | # Dump file 160 | *.stackdump 161 | 162 | # Folder config file 163 | [Dd]esktop.ini 164 | 165 | # Recycle Bin used on file shares 166 | $RECYCLE.BIN/ 167 | 168 | # Windows Installer files 169 | *.cab 170 | *.msi 171 | *.msix 172 | *.msm 173 | *.msp 174 | 175 | # Windows shortcuts 176 | *.lnk 177 | 178 | ### VScode: https://raw.githubusercontent.com/github/gitignore/master/Global/VisualStudioCode.gitignore 179 | .vscode/* 180 | 181 | ### Pycharm(?) 182 | .idea 183 | 184 | # Ablog 185 | .github_cache 186 | src/ablog/version.py 187 | docs/_build/ 188 | docs/api/ 189 | docs/.doctrees/ 190 | docs/_website/ 191 | docs/_latex/ 192 | test/ 193 | *.orig 194 | .history/ 195 | pydata-sphinx-theme/ 196 | _build 197 | demo/ 198 | src/ablog/_version.py 199 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | ci: 2 | autofix_prs: false 3 | autoupdate_schedule: "quarterly" 4 | repos: 5 | - repo: https://github.com/PyCQA/docformatter 6 | rev: HEAD 7 | hooks: 8 | - id: docformatter 9 | args: ["--in-place", "--pre-summary-newline", "--make-summary-multi"] 10 | - repo: https://github.com/PyCQA/autoflake 11 | rev: v2.3.1 12 | hooks: 13 | - id: autoflake 14 | args: 15 | [ 16 | "--in-place", 17 | "--remove-all-unused-imports", 18 | "--remove-unused-variable", 19 | ] 20 | exclude: ".*(.fits|.fts|.fit|.txt|tca.*|extern.*|.rst|.md|docs/conf.py)$" 21 | - repo: https://github.com/astral-sh/ruff-pre-commit 22 | rev: "v0.11.4" 23 | hooks: 24 | - id: ruff 25 | args: ["--fix", "--unsafe-fixes"] 26 | - id: ruff-format 27 | - repo: https://github.com/pre-commit/pre-commit-hooks 28 | rev: v5.0.0 29 | hooks: 30 | - id: check-ast 31 | - id: check-case-conflict 32 | - id: trailing-whitespace 33 | exclude: ".*(.fits|.fts|.fit|.txt|.csv)$" 34 | - id: mixed-line-ending 35 | exclude: ".*(.fits|.fts|.fit|.txt|.csv)$" 36 | - id: end-of-file-fixer 37 | exclude: ".*(.fits|.fts|.fit|.txt|.csv)$" 38 | - id: check-yaml 39 | - id: debug-statements 40 | - repo: https://github.com/codespell-project/codespell 41 | rev: v2.4.1 42 | hooks: 43 | - id: codespell 44 | additional_dependencies: 45 | - tomli 46 | - repo: https://github.com/rbubley/mirrors-prettier 47 | rev: v3.5.3 48 | hooks: 49 | - id: prettier 50 | - repo: https://github.com/Riverside-Healthcare/djLint 51 | rev: v1.36.4 52 | hooks: 53 | - id: djlint-jinja 54 | types_or: ["html"] 55 | -------------------------------------------------------------------------------- /.readthedocs.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | build: 3 | os: ubuntu-lts-latest 4 | tools: 5 | python: "mambaforge-latest" 6 | jobs: 7 | pre_install: 8 | - git update-index --assume-unchanged .rtd-environment.yml docs/conf.py 9 | conda: 10 | environment: .rtd-environment.yml 11 | sphinx: 12 | builder: html 13 | configuration: docs/conf.py 14 | fail_on_warning: false 15 | python: 16 | install: 17 | - method: pip 18 | extra_requirements: 19 | - all 20 | - docs 21 | path: . 22 | -------------------------------------------------------------------------------- /.rtd-environment.yml: -------------------------------------------------------------------------------- 1 | name: rtd_ablog 2 | channels: 3 | - conda-forge 4 | dependencies: 5 | - python=3.12 6 | - pip 7 | - graphviz 8 | - make 9 | - nbsphinx 10 | - pandoc 11 | -------------------------------------------------------------------------------- /.stylelintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "stylelint-config-standard" 3 | } 4 | -------------------------------------------------------------------------------- /LICENSE.rst: -------------------------------------------------------------------------------- 1 | ABlog for blogging with Sphinx 2 | 3 | Copyright (C) 2014-2022 Ahmet Bakan and The SunPy Developers 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: demo rebuild tests 2 | 3 | demo: 4 | rm -rf demo && mkdir demo 5 | printf "demo\nABlog\nABlog Team\nhttps://ablog.readthedocs.io/" | ablog start 6 | 7 | rebuild: 8 | cd docs; watchmedo shell-command --patterns='*.rst' --command='ablog build' --recursive 9 | 10 | test: 11 | set -e; cd docs; git clean -xfd; ablog build -T -W; git clean -xfd; cd .. 12 | 13 | test1: 14 | set -e; cd docs; git clean -xfd; ablog build -T -W -b json; git clean -xfd; cd .. 15 | 16 | test2: 17 | set -e; cd docs; git clean -xfd; ablog build -T -W -b pickle; git clean -xfd; cd .. 18 | 19 | test3: 20 | set -e; mkdir -p test; cd test; git clean -xfd; printf "\nABlog\nABlog Team\nhttps://ablog.readthedocs.io/" | ablog start; ablog build -W; cd ..; rm -rf test 21 | 22 | test4: 23 | set -e; mkdir -p testablog; cd testablog; git clean -xfd; printf "\nABlog\nABlog Team\nhttps://ablog.readthedocs.io/" | ablog start; ablog build -W; cd ..; rm -rf testablog 24 | 25 | test5: 26 | set -e; cd docs; git clean -xfd; ablog build -W -b latex -T -d .doctrees -w _latex; git clean -xfd; cd .. 27 | 28 | tests: test test1 test2 test3 test4 test5 29 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | ABlog for Sphinx 2 | ================ 3 | 4 | |CI| |Upload Python Package| 5 | 6 | .. |CI| image:: https://github.com/sunpy/ablog/actions/workflows/ci.yml/badge.svg 7 | :target: https://github.com/sunpy/ablog/actions/workflows/ci.yml 8 | .. |Upload Python Package| image:: https://github.com/sunpy/ablog/actions/workflows/pythonpublish.yml/badge.svg 9 | :target: https://github.com/sunpy/ablog/actions/workflows/pythonpublish.yml 10 | 11 | ABlog is a Sphinx extension that converts any documentation or personal website project into a full-fledged blog. 12 | 13 | `Please check our documentation for information on how to get started. `__ 14 | 15 | Note 16 | ---- 17 | 18 | This is the new home of `Ahmet Bakan's Ablog Sphinx extension `__. 19 | The original project is no longer maintained and the `SunPy Project `__ has taken over maintenance. 20 | 21 | Warning 22 | ------- 23 | 24 | **This version is maintained with the aim to keep it working for SunPy Project website and thus new features or bugfixes are highly unlikely unless they directly impact the SunPy Project** 25 | 26 | **We strongly encourage users and interested in parties in submitting patches to ablog** 27 | -------------------------------------------------------------------------------- /ablog-conda-test-env.yml: -------------------------------------------------------------------------------- 1 | name: ablog-conda-test-env 2 | channels: 3 | - conda-forge 4 | dependencies: 5 | - docutils 6 | - feedgen 7 | - graphviz 8 | - invoke 9 | - make 10 | - myst-parser 11 | - nbsphinx 12 | - packaging 13 | - pandoc 14 | - pip 15 | - pytest 16 | - python-dateutil 17 | - setuptools 18 | - setuptools-scm 19 | - sphinx 20 | - sphinx-automodapi 21 | - watchdog 22 | - pip: 23 | - sunpy-sphinx-theme 24 | -------------------------------------------------------------------------------- /conftest.py: -------------------------------------------------------------------------------- 1 | from pathlib import Path 2 | 3 | import docutils 4 | import pytest 5 | import sphinx 6 | 7 | # Load app, status and warning fixtures. 8 | pytest_plugins = ["sphinx.testing.fixtures"] 9 | 10 | 11 | # inspired from sphinx's conftest.py 12 | def pytest_report_header(config): 13 | header = f"libraries: Sphinx-{sphinx.__display_version__}, docutils-{docutils.__version__}" 14 | if hasattr(config, "_tmp_path_factory"): 15 | header += f"\nbase tempdir: {config._tmp_path_factory.getbasetemp()}" 16 | 17 | return header 18 | 19 | 20 | @pytest.fixture(scope="session") 21 | def rootdir(): 22 | return Path(__file__).parent.absolute() / "roots" 23 | 24 | 25 | @pytest.fixture(scope="function", autouse=True) 26 | def reset_blog_config(): 27 | # Reset cached configurations to enable confoverrides 28 | from ablog.blog import Blog 29 | 30 | Blog._dict = {} 31 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = -v 6 | SPHINXBUILD = sphinx-build 7 | SOURCEDIR = . 8 | BUILDDIR = _build 9 | 10 | # Put it first so that "make" without argument is like "make help". 11 | help: 12 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 13 | 14 | .PHONY: help Makefile 15 | 16 | # Catch-all target: route all unknown targets to Sphinx using the new 17 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 18 | %: Makefile 19 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 20 | -------------------------------------------------------------------------------- /docs/_static/ablog.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunpy/ablog/95610aad20e3e290ca82776f6132a62d8fc2fbcb/docs/_static/ablog.ico -------------------------------------------------------------------------------- /docs/_static/ablog.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunpy/ablog/95610aad20e3e290ca82776f6132a62d8fc2fbcb/docs/_static/ablog.png -------------------------------------------------------------------------------- /docs/conf.py: -------------------------------------------------------------------------------- 1 | import re 2 | from pathlib import Path 3 | 4 | from packaging.version import parse as _parse 5 | from sphinx import addnodes 6 | 7 | import ablog 8 | 9 | ablog_builder = "dirhtml" 10 | ablog_website = "_website" 11 | extensions = [ 12 | "sphinx.ext.autodoc", 13 | "sphinx.ext.doctest", 14 | "sphinx.ext.intersphinx", 15 | "sphinx.ext.todo", 16 | "sphinx.ext.ifconfig", 17 | "sphinx.ext.extlinks", 18 | "sphinx_automodapi.automodapi", 19 | "ablog", 20 | "alabaster", 21 | "nbsphinx", 22 | "myst_parser", 23 | ] 24 | 25 | version = str(_parse(ablog.__version__)) 26 | project = "ABlog" 27 | copyright = "2014-2022, ABlog Team" 28 | master_doc = "index" 29 | source_suffix = { 30 | ".rst": "restructuredtext", 31 | ".md": "markdown", 32 | } 33 | exclude_patterns = ["_build", "docs/manual/.ipynb_checkpoints"] 34 | html_title = "ABlog" 35 | html_use_index = True 36 | html_domain_indices = False 37 | html_show_sourcelink = True 38 | html_favicon = "_static/ablog.ico" 39 | blog_title = "ABlog" 40 | blog_baseurl = "https://ablog.readthedocs.io/" 41 | blog_locations = { 42 | "Pittsburgh": ("Pittsburgh, PA", "https://en.wikipedia.org/wiki/Pittsburgh"), 43 | "San Fran": ("San Francisco, CA", "https://en.wikipedia.org/wiki/San_Francisco"), 44 | "Denizli": ("Denizli, Turkey", "https://en.wikipedia.org/wiki/Denizli"), 45 | } 46 | blog_languages = { 47 | "en": ("English", None), 48 | "nl": ("Nederlands", None), 49 | "zh_CN": ("Chinese", None), 50 | } 51 | blog_default_language = "en" 52 | language = "en" 53 | blog_authors = { 54 | "Ahmet": ("Ahmet Bakan", "https://ahmetbakan.com"), 55 | "Luc": ("Luc Saffre", "https://saffre-rumma.net/luc/"), 56 | "Mehmet": ("Mehmet Gerçeker", "https://github.com/mehmetg"), 57 | "Libor": ("Libor Jelínek", "https://liborjelinek.github.io/"), 58 | } 59 | blog_feed_archives = True 60 | blog_feed_fulltext = True 61 | blog_feed_templates = { 62 | "atom": { 63 | "content": "{{ title }}{% for tag in post.tags %} #{{ tag.name|trim()|replace(' ', '') }}{% endfor %}", 64 | }, 65 | "social": { 66 | "content": "{{ title }}{% for tag in post.tags %} #{{ tag.name|trim()|replace(' ', '') }}{% endfor %}", 67 | }, 68 | } 69 | disqus_shortname = "https-ablog-readthedocs-io" 70 | disqus_pages = True 71 | fontawesome_link_cdn = "https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.1/css/all.min.css" 72 | html_theme = "alabaster" 73 | html_sidebars = { 74 | "**": [ 75 | "about.html", # Comes from alabaster 76 | "searchfield.html", # Comes from alabaster 77 | "ablog/postcard.html", 78 | "ablog/recentposts.html", 79 | "ablog/tagcloud.html", 80 | "ablog/categories.html", 81 | "ablog/archives.html", 82 | "ablog/authors.html", 83 | "ablog/languages.html", 84 | "ablog/locations.html", 85 | ] 86 | } 87 | html_theme_options = { 88 | "travis_button": False, 89 | "github_user": "sunpy", 90 | "github_repo": "ablog", 91 | "description": "ABlog for blogging with Sphinx", 92 | "logo": "ablog.png", 93 | } 94 | intersphinx_mapping = { 95 | "python": ("https://docs.python.org/", None), 96 | "sphinx": ("https://www.sphinx-doc.org/en/master/", None), 97 | } 98 | extlinks = { 99 | "wiki": ("https://en.wikipedia.org/wiki/%s", "%s"), 100 | "issue": ("https://github.com/sunpy/ablog/issues/%s", "issue %s"), 101 | "pull": ("https://github.com/sunpy/ablog/pull/%s", "pull request %s"), 102 | } 103 | rst_epilog = """ 104 | .. _Sphinx: http://sphinx-doc.org/ 105 | .. _Python: https://python.org 106 | .. _Disqus: https://disqus.com/ 107 | .. _GitHub: https://github.com/sunpy/ablog 108 | .. _PyPI: https://pypi.python.org/pypi/ablog 109 | .. _Read The Docs: https://readthedocs.org/ 110 | .. _Alabaster: https://github.com/bitprophet/alabaster 111 | """ 112 | locale_dirs = [str(Path(ablog.__file__).parent / Path("locales"))] 113 | nitpicky = True 114 | nitpick_ignore = [] 115 | for line in open("nitpick-exceptions"): 116 | if line.strip() == "" or line.startswith("#"): 117 | continue 118 | dtype, target = line.split(None, 1) 119 | target = target.strip() 120 | nitpick_ignore.append((dtype, target)) 121 | 122 | 123 | def parse_event(env, sig, signode): 124 | event_sig_re = re.compile(r"([a-zA-Z-]+)\s*\((.*)\)") 125 | m = event_sig_re.match(sig) 126 | if not m: 127 | signode += addnodes.desc_name(sig, sig) 128 | return sig 129 | name, args = m.groups() 130 | signode += addnodes.desc_name(name, name) 131 | plist = addnodes.desc_parameterlist() 132 | for arg in args.split(","): 133 | arg = arg.strip() 134 | plist += addnodes.desc_parameter(arg, arg) 135 | signode += plist 136 | return name 137 | 138 | 139 | def setup(app): 140 | from sphinx.ext.autodoc import cut_lines 141 | from sphinx.util.docfields import GroupedField 142 | 143 | app.connect("autodoc-process-docstring", cut_lines(4, what=["module"])) 144 | app.add_object_type( 145 | "confval", 146 | "confval", 147 | objname="configuration value", 148 | indextemplate="pair: %s; configuration value", 149 | ) 150 | fdesc = GroupedField("parameter", label="Parameters", names=["param"], can_collapse=True) 151 | app.add_object_type("event", "event", "pair: %s; event", parse_event, doc_field_types=[fdesc]) 152 | -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | ABlog for Sphinx 2 | ================ 3 | 4 | ABlog is a Sphinx extension that converts any documentation or personal website project into a full-fledged blog with: 5 | 6 | * :ref:`Atom feeds ` 7 | * :ref:`Archive pages ` 8 | * :ref:`sidebars` 9 | * :ref:`disqus-integration` 10 | * :ref:`Font-Awesome integration ` 11 | * :doc:`manual/markdown` 12 | 13 | Ablog is part of the `SunPy Project `__. 14 | 15 | .. _installation: 16 | 17 | Installation 18 | ------------ 19 | 20 | You can install ABlog using `pip `__:: 21 | 22 | pip install -U ablog 23 | 24 | or `miniforge `__:: 25 | 26 | conda install ablog 27 | 28 | This will also install `Sphinx `__, `feedgen `__, and `Invoke `__ respectively required for building your website, making it look good, generating feeds, and running deploy commands. 29 | 30 | Getting Started 31 | --------------- 32 | 33 | If you are starting a new project, see the :ref:`quick-start` guide. 34 | If you already have a project, enable blogging by making following changes in ``conf.py``: 35 | 36 | .. code-block:: python 37 | 38 | # 1. Add 'ablog' and 'sphinx.ext.intersphinx' to the list of extensions 39 | extensions = [ 40 | '...', 41 | 'ablog', 42 | 'sphinx.ext.intersphinx', 43 | ] 44 | 45 | How it works 46 | ------------ 47 | 48 | If you are new to Sphinx_ and reStructuredText markup language, you might find `reStructuredText Primer`_ useful. 49 | Once you have content (in ``.rst`` files), you can post *any page* using the :rst:dir:`post` directive as follows: 50 | 51 | .. _reStructuredText Primer: https://www.sphinx-doc.org/en/master/ 52 | 53 | .. code-block:: rst 54 | 55 | .. post:: Apr 15, 2014 56 | :tags: earth, love, peace 57 | :category: python 58 | :author: me 59 | :location: SF 60 | :language: en 61 | 62 | An alternative method is: 63 | 64 | .. code-block:: rst 65 | 66 | :blogpost: true 67 | :date: Oct 10, 2020 68 | :author: Nabil Freij 69 | :location: World 70 | :category: Manual 71 | :language: English 72 | 73 | at the top of the file. 74 | 75 | ABlog will index all files posted as above and list them in archives and feeds specified in ``:tag:``, ``:category:``, etc. options. 76 | 77 | You can also include a list of posts using :rst:dir:`postlist` directive: 78 | 79 | .. code-block:: rst 80 | 81 | .. postlist:: 82 | :list-style: circle 83 | :category: Manual 84 | :format: {title} 85 | :sort: 86 | 87 | For ABlog documentation, this converts to the following where you can find more about configuring and using ABlog: 88 | 89 | .. postlist:: 90 | :category: Manual 91 | :list-style: circle 92 | :format: {title} 93 | :sort: 94 | 95 | .. only:: html 96 | 97 | .. image:: https://readthedocs.org/projects/ablog/badge/?version=latest 98 | :target: https://ablog.readthedocs.io 99 | 100 | .. toctree:: 101 | :hidden: 102 | :glob: 103 | 104 | */* 105 | -------------------------------------------------------------------------------- /docs/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | pushd %~dp0 4 | 5 | REM Command file for Sphinx documentation 6 | 7 | if "%SPHINXBUILD%" == "" ( 8 | set SPHINXBUILD=sphinx-build 9 | ) 10 | set SOURCEDIR=. 11 | set BUILDDIR=_build 12 | 13 | if "%1" == "" goto help 14 | 15 | %SPHINXBUILD% >NUL 2>NUL 16 | if errorlevel 9009 ( 17 | echo. 18 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx 19 | echo.installed, then set the SPHINXBUILD environment variable to point 20 | echo.to the full path of the 'sphinx-build' executable. Alternatively you 21 | echo.may add the Sphinx directory to PATH. 22 | echo. 23 | echo.If you don't have Sphinx installed, grab it from 24 | echo.https://sphinx-doc.org/ 25 | exit /b 1 26 | ) 27 | 28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% 29 | goto end 30 | 31 | :help 32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% 33 | 34 | :end 35 | popd 36 | -------------------------------------------------------------------------------- /docs/manual/ablog-commands.rst: -------------------------------------------------------------------------------- 1 | .. _commands: 2 | 3 | ABlog Commands 4 | ============== 5 | 6 | .. post:: Mar 1, 2015 7 | :tags: config, commands 8 | :author: Ahmet, Mehmet 9 | :category: Manual 10 | :location: SF 11 | 12 | 13 | ``ablog`` commands are for streamlining blog operations, i.e. building, serving, and viewing blog pages, as well as starting a new blog:: 14 | 15 | $ ablog 16 | usage: ablog [-h] [-v] {start,build,clean,serve,post,deploy} ... 17 | 18 | ABlog for blogging with Sphinx 19 | 20 | optional arguments: 21 | -h, --help show this help message and exit 22 | -v, --version print ABlog version and exit 23 | 24 | subcommands: 25 | {start,build,clean,serve,post,deploy} 26 | start start a new blog project 27 | build build your blog project 28 | clean clean your blog build files 29 | serve serve and view your project 30 | post create a blank post 31 | deploy deploy your website build files 32 | 33 | See 'ablog -h' for more information on a specific command. 34 | 35 | .. contents:: Here are all the things you can do: 36 | :local: 37 | :backlinks: top 38 | 39 | .. _start: 40 | 41 | Start a New Project 42 | ------------------- 43 | 44 | ``ablog start`` command is for quickly setting up a blog project. 45 | See :ref:`quick-start` for how it works and what it prepares for you:: 46 | 47 | $ ablog start -h 48 | usage: ablog start [-h] 49 | 50 | Start a new blog project by answering a few questions. You will end up with a 51 | configuration file and sample pages. 52 | 53 | optional arguments: 54 | -h, --help show this help message and exit 55 | 56 | .. _build: 57 | 58 | Build your Website 59 | ------------------ 60 | 61 | Running ``ablog build`` in your project folder builds your website HTML pages:: 62 | 63 | $ ablog build -h 64 | usage: ablog build [-h] [-a] [-b BUILDER] [-s SOURCEDIR] [-w WEBSITE] 65 | [-d DOCTREES] [-T] [-P] 66 | 67 | Path options can be set in conf.py. Default values of paths are relative to 68 | conf.py. 69 | 70 | optional arguments: 71 | -h, --help show this help message and exit 72 | -a write all files; default is to only write new and changed 73 | files 74 | -b BUILDER builder to use, default `ablog_builder` or dirhtml 75 | -s SOURCEDIR root path for source files, default is path to the folder that 76 | contains conf.py 77 | -w WEBSITE path for website, default is _website when `ablog_website` is 78 | not set in conf.py 79 | -d DOCTREES path for the cached environment and doctree files, default 80 | .doctrees when `ablog_doctrees` is not set in conf.py 81 | -T show full traceback on exception 82 | -P run pdb on exception 83 | 84 | Serve and View Locally 85 | ---------------------- 86 | 87 | Running ``ablog serve``, after building your website, will start a Python server and open up browser tab to view your website:: 88 | 89 | $ ablog serve -h 90 | usage: ablog serve [-h] [-w WEBSITE] [-p PORT] [-n] [-r] [--patterns] 91 | 92 | Serve options can be set in conf.py. Default values of paths are relative to 93 | conf.py. 94 | 95 | optional arguments: 96 | -h, --help show this help message and exit 97 | -w WEBSITE path for website, default is _website when `ablog_website` is 98 | not set in conf.py 99 | -p PORT port number for HTTP server; default is 8000 100 | -n do not open website in a new browser tab 101 | -r rebuild when a file matching patterns change or get added 102 | --patterns patterns for triggering rebuilds 103 | 104 | .. _deploy: 105 | 106 | Deploy to GitHub Pages 107 | ---------------------- 108 | 109 | Running ``ablog deploy`` will push your website to GitHub:: 110 | 111 | $ ablog deploy -h 112 | usage: ablog deploy [-h] [-w WEBSITE] [-p REPODIR] [-g GITHUB_PAGES] 113 | [-m MESSAGE] [-f] [--push-quietly] 114 | [--github-branch GITHUB_BRANCH] [--github-ssh] 115 | [--github-token GITHUB_TOKEN] [--github-url GITHUB_URL] 116 | 117 | Path options can be set in conf.py. Default values of paths are relative to 118 | conf.py. 119 | 120 | options: 121 | -h, --help show this help message and exit 122 | -w WEBSITE path for website, default is _website when 123 | `ablog_website` is not set in conf.py 124 | -p REPODIR path to the location of repository to be deployed, e.g. 125 | `../username.github.io`, default is folder containing 126 | `conf.py` 127 | -g GITHUB_PAGES GitHub username for deploying to GitHub pages 128 | -m MESSAGE commit message 129 | -f overwrite last commit, i.e. `commit --amend; push -f` 130 | --push-quietly be more quiet when pushing changes 131 | --github-branch GITHUB_BRANCH 132 | Branch to use. Default is 'master'. 133 | --github-ssh use ssh when cloning website 134 | --github-token GITHUB_TOKEN 135 | environment variable name storing GitHub access token 136 | --github-url GITHUB_URL 137 | Custom GitHub URL. Useful when multiple accounts are 138 | configured on the same machine. Default is: 139 | git@github.com 140 | 141 | 142 | Create a Post 143 | ------------- 144 | 145 | Finally, ``ablog post`` will make a new post template file:: 146 | 147 | $ ablog post -h 148 | usage: ablog post [-h] [-t TITLE] filename 149 | 150 | positional arguments: 151 | filename filename, e.g. my-nth-post (.rst appended) 152 | 153 | optional arguments: 154 | -h, --help show this help message and exit 155 | -t TITLE post title; default is formed from filename 156 | 157 | Clean Build Files 158 | ----------------- 159 | 160 | In case you needed, running ``ablog clean`` will remove build files and do a deep clean with ``-D`` option:: 161 | 162 | $ ablog clean -h 163 | usage: ablog clean [-h] [-d DOCTREES] [-w WEBSITE] [-D] 164 | 165 | Path options can be set in conf.py. Default values of paths are relative to 166 | conf.py. 167 | 168 | optional arguments: 169 | -h, --help show this help message and exit 170 | -d DOCTREES path for the cached environment and doctree files, default 171 | .doctrees when `ablog_doctrees` is not set in conf.py 172 | -w WEBSITE path for website, default is _website when `ablog_website` is 173 | not set in conf.py 174 | -D deep clean, remove cached environment and doctree files 175 | 176 | .. update:: Apr 7, 2015 177 | 178 | Added ``ablog clean`` and ``ablog deploy`` commands. 179 | -------------------------------------------------------------------------------- /docs/manual/ablog-i18n.rst: -------------------------------------------------------------------------------- 1 | ABlog Internationalization 2 | ========================== 3 | 4 | .. post:: Aug 30, 2014 5 | :tags: i18n 6 | :category: Manual 7 | :author: Luc, Ahmet 8 | :language: Chinese 9 | 10 | ABlog automatically generates certain labels like :ref:`blog-posts` and :ref:`blog-categories`. 11 | If these labels appear in English on your blog although you specified another language, then this page is for you. 12 | 13 | ABlog needs your help for translation of these labels. 14 | Translation process involves the following steps: 15 | 16 | * Update translatable messages: 17 | 18 | Execute extract_messages_ each time a translatable message text is changed or added:: 19 | 20 | $ python setup.py extract_messages -o ablog/locales/sphinx.pot 21 | ... 22 | 23 | This will create or update :file:`ablog/locales/sphinx.pot` file, the central messages catalog used by the different translations. 24 | 25 | Either: 26 | 27 | * Create new translation catalog: 28 | 29 | Execute init_catalog_ once for each *new* language, e.g.:: 30 | 31 | $ python setup.py init_catalog -l de -i ablog/locales/sphinx.pot -o ablog/locales/de/LC_MESSAGES/sphinx.po 32 | 33 | This will create a file :file:`ablog/locales/de/LC_MESSAGES/sphinx.po` in which translations needs to be placed. 34 | 35 | * Update translation catalog: 36 | 37 | Execute update_catalog_ for each *existing* language, e.g.:: 38 | 39 | $ python setup.py update_catalog -l de -i ablog/locales/sphinx.pot -o ablog/locales/de/LC_MESSAGES/sphinx.po 40 | 41 | This will update file :file:`ablog/locales/de/LC_MESSAGES/sphinx.po` where translations of new text needs to be placed. 42 | 43 | Finally: 44 | 45 | * Compile catalogs: 46 | 47 | Execute compile_catalog_ for each existing language, e.g:: 48 | 49 | $ python setup.py compile_catalog --directory ablog/locales/ --domain sphinx --locale de 50 | 51 | If you remove ``--locale de`` then all catalogs will be compiled. 52 | 53 | .. _extract_messages: https://babel.pocoo.org/en/latest/setup.html#extract-messages 54 | .. _init_catalog: https://babel.pocoo.org/en/latest/setup.html#init-catalog 55 | .. _update_catalog: https://babel.pocoo.org/en/latest/setup.html#update-catalog 56 | .. _compile_catalog: https://babel.pocoo.org/en/latest/setup.html#compile-catalog 57 | -------------------------------------------------------------------------------- /docs/manual/ablog-quick-start.rst: -------------------------------------------------------------------------------- 1 | .. _quick-start: 2 | 3 | 4 | ABlog Quick Start 5 | ================= 6 | 7 | .. post:: Mar 1, 2015 8 | :tags: config, tips 9 | :author: Mehmet, Ahmet 10 | :category: Manual 11 | :location: SF 12 | 13 | This short walk through of blogging work flow assumes that you have already installed ABlog. If not, see :ref:`installation` guide. 14 | 15 | *Note that this post is a working draft. Feel free to revise it on GitHub.* 16 | 17 | Start a Project 18 | --------------- 19 | 20 | To start a new project, run ``ablog start`` command in a directory where you want to keep your project source files. 21 | This command will ask you a few questions and create the following files: 22 | 23 | * :file:`conf.py` that contains project configuration for building HTML pages. 24 | 25 | * :file:`first-post.rst`, a blog post example. 26 | 27 | * :file:`index.rst` that contains content for the *landing* page of your website. 28 | 29 | * :file:`about.rst`, another non-post page example. 30 | 31 | 32 | Build and View 33 | -------------- 34 | 35 | With no further delay, let's see what your project will look like. 36 | First run ``ablog build``, in your project folder, to have HTML pages built in :file:`_website` folder. 37 | Then, call ``ablog serve`` to view them in your default web browser. 38 | See :ref:`commands` for more information about these commands. 39 | 40 | Your landing page is built from :file:`index.rst` and contains links to your first post and about page. 41 | Take a look at :file:`index.rst` for some tips on navigation links within the project. 42 | 43 | Write Content 44 | ------------- 45 | 46 | If you are new to Sphinx_ and reStructuredText markup language, you might find `reStructuredText Primer `__ useful. 47 | 48 | Pages 49 | ^^^^^ 50 | 51 | Pages in your project are :file:`.rst` files that are only a :rst:dir:`post` directive short of becoming blog posts. 52 | To make regular pages accessible from the navigation bar, you need to list them in a :rst:dir:`toctree`. 53 | This is shown for *about* page into :file:`index.rst`. 54 | 55 | Posts 56 | ^^^^^ 57 | 58 | You can convert any page to a post with a :rst:dir:`post` directive. 59 | ABlog will take care of listing posts in specified archives and sidebars. 60 | 61 | Blog posts 62 | ^^^^^^^^^^ 63 | 64 | You can start new blog posts with either a front-matter or a directive using ABlog. 65 | Simply use something based on the following template as the front-matter:: 66 | 67 | :blogpost: true 68 | :date: January 1, 2020 69 | :author: A. Author 70 | :location: World 71 | :category: Blog 72 | :language: English 73 | :tags: blog 74 | 75 | Simply use something based on the following template as the directive for ABlog:: 76 | 77 | .. post:: January 1, 2020 78 | 79 | :author: A. Author 80 | :location: World 81 | :category: Blog 82 | :language: English 83 | :tags: blog 84 | 85 | For more information, see :ref:`posting-directive` and :ref:`posting-front-matter`. 86 | 87 | Comments 88 | -------- 89 | 90 | You can enable comments in your website by creating a Disqus_ account and obtaining a unique identifier, i.e. :confval:`disqus_shortname`. 91 | See :ref:`disqus-integration` for configuration options. 92 | 93 | Analytics 94 | --------- 95 | 96 | ABlog uses Alabaster_ theme by default. You can use theme options to set your `Google Analytics`__ identifier to enable tracking. 97 | 98 | __ https://www.google.com/analytics/ 99 | 100 | Configuration 101 | ------------- 102 | 103 | There are four major groups of configuration options that can help you customize how your website looks: 104 | 105 | * :ref:`config` - add blog authors, post locations and languages to your blog, adjust archive and feed content, etc. 106 | 107 | * `General configuration `__ and `project information `__ 108 | 109 | * :ref:`html-options` - configure appearance of your website. 110 | 111 | * Alabaster_ theme options - link to your GitHub account and project, set up tracking, etc. 112 | 113 | Other Folders 114 | ------------- 115 | 116 | You might have noticed that your project contains three folders that we have not mention yet. 117 | Here they are: 118 | 119 | * :file:`_static` is for keeping image, :file:`.js`, and :file:`.css` files. 120 | :confval:`html_static_path` Sphinx option for more information. 121 | 122 | * :file:`_templates` is for custom HTML templates. 123 | See :confval:`templates_path` for more information. 124 | 125 | * :file:`.doctree` folder, created after build command is called, is where Sphinx_ stores the state of your project. 126 | Files in this folder saves time when you rebuild your project. 127 | -------------------------------------------------------------------------------- /docs/manual/api.rst: -------------------------------------------------------------------------------- 1 | .. api: 2 | 3 | ABlog API 4 | ========= 5 | 6 | .. post:: Feb 17, 2018 7 | :tags: api 8 | :author: Nabil Freij 9 | :category: Manual 10 | :location: World 11 | 12 | .. automodapi:: ablog 13 | 14 | .. automodapi:: ablog.blog 15 | 16 | .. automodapi:: ablog.commands 17 | 18 | .. automodapi:: ablog.post 19 | 20 | .. automodapi:: ablog.start 21 | -------------------------------------------------------------------------------- /docs/manual/cross-referencing-blog-pages.rst: -------------------------------------------------------------------------------- 1 | Cross-referencing Blog Pages 2 | ============================ 3 | 4 | .. post:: May 11, 2014 5 | :tags: tips, Sphinx 6 | :category: Manual 7 | :location: Pittsburgh 8 | :author: Ahmet 9 | 10 | ABlog creates references to all post and archive pages. 11 | Posts can be cross-referenced using the name of the file, or when the file is named :file:`index`, the name of the folder that contains the file. 12 | 13 | This page, :ref:`cross-referencing-blog-pages`, for example is referenced as ``:ref:`cross-referencing-blog-pages``` using :rst:role:`ref` role. 14 | 15 | When posts have long file names, it may be inconvenient to use them repeatedly for cross-referencing. 16 | An alternative that Sphinx_ offers is creating your own short and unique labels for cross-referencing to posts. See :ref:`xref-syntax` for details. 17 | 18 | .. _archives: 19 | 20 | Archive pages 21 | ------------- 22 | 23 | Archive pages, on the other hand, can be cross-referenced by combining archive type and archive name as follows: 24 | 25 | ============== ========================== =============================== 26 | Archive Example reStructured Text 27 | ============== ========================== =============================== 28 | Posts :ref:`blog-posts` ``:ref:`blog-posts``` 29 | Drafts :ref:`blog-drafts` ``:ref:`blog-drafts``` 30 | Blog Feed :ref:`blog-feed` ``:ref:`blog-feed``` 31 | Author :ref:`author-ahmet` ``:ref:`author-ahmet``` 32 | Language :ref:`language-en` ``:ref:`language-en``` 33 | Location :ref:`location-pittsburgh` ``:ref:`location-pittsburgh``` 34 | ============== ========================== =============================== 35 | 36 | Following archive pages list all posts by grouping them: 37 | 38 | ============== ========================== =============================== 39 | Archive Example reStructured Text 40 | ============== ========================== =============================== 41 | By tag :ref:`blog-tags` ``:ref:`blog-tags``` 42 | By author :ref:`blog-authors` ``:ref:`blog-authors``` 43 | By language :ref:`blog-languages` ``:ref:`blog-languages``` 44 | By location :ref:`blog-locations` ``:ref:`blog-locations``` 45 | By category :ref:`blog-categories` ``:ref:`blog-categories``` 46 | By archive :ref:`blog-archives` ``:ref:`blog-archives``` 47 | ============== ========================== =============================== 48 | -------------------------------------------------------------------------------- /docs/manual/deploy-to-github-pages.rst: -------------------------------------------------------------------------------- 1 | 2 | Deploy to GitHub Pages 3 | ====================== 4 | 5 | 6 | .. post:: Apr 07, 2015 7 | :tags: deploy 8 | :author: Ahmet 9 | :category: Manual 10 | :location: SF 11 | 12 | If you are looking for a place to publish your blog, `GitHub Pages`__ might be the place for you. 13 | 14 | __ https://pages.github.com/ 15 | 16 | Assuming that you have a GitHub account, here are what you need to do to get published: 17 | 18 | 1. Head over to GitHub_ and create a new repository named ``username.github.io``, where username is your username (or organization name) on GitHub. 19 | 20 | 2. (optional) If you followed the link, you might as well give a star to ABlog ;) 21 | 22 | 3. Set :confval:`github_pages` configuration variable in :file:`conf.py` file. 23 | 24 | 4. Run ``ablog build`` in your project folder. 25 | 26 | 5. Run ``ablog deploy``. This command will 27 | 28 | i. clone your GitHub pages repository to project folder, 29 | 30 | ii. copy all files from build folder (:file:`_website`) to :file:`username.github.io`, 31 | 32 | iii. add and commit copied files, 33 | 34 | iv. add `.nojekyll `_ 35 | file, since this ain't no Jekyll_ 36 | 37 | v. and finally push the changes to publish. 38 | 39 | Let us know how this works for you! 40 | 41 | .. _Jekyll: https://jekyllrb.com/ 42 | -------------------------------------------------------------------------------- /docs/manual/external-post.rst: -------------------------------------------------------------------------------- 1 | :blogpost: true 2 | :date: September 01, 2021 3 | :author: Chris 4 | :category: Manual 5 | :external_link: https://www.sphinx-doc.org/en/master/ 6 | 7 | External post 8 | ============= 9 | 10 | This text will be in auto-generated post previews, but links to the post will direct to ``external_link``. 11 | -------------------------------------------------------------------------------- /docs/manual/forever-draft.rst: -------------------------------------------------------------------------------- 1 | Draft Example 2 | ============= 3 | 4 | .. post:: 5 | :tags: draft 6 | :category: Manual 7 | 8 | 9 | As the title suggests, this is a draft example and shall remain so until the end of time or internet. 10 | 11 | How do you draft a post? 12 | ------------------------ 13 | 14 | Just indicate that the page is a post using :rst:dir:`post` directive, but do not provide give a published date: 15 | 16 | .. code-block:: rst 17 | 18 | .. post:: 19 | :tags: draft 20 | :category: Manual 21 | 22 | You can still label a post you are drafting with tags and categories, but the post will not be listed in corresponding archive pages until it is published. 23 | 24 | How can you see a list of drafts? 25 | --------------------------------- 26 | 27 | See :ref:`blog-drafts` archive page, which can be referred to as ``:ref:`blog-drafts```. 28 | 29 | Why would you make a post draft? 30 | -------------------------------- 31 | 32 | Let's say you are using Disqus_ on your website, and allowing non-post pages to be discussed as well, but you don't want a draft to be discussed before it is published. 33 | By adding :rst:dir:`post` directive without published date and keeping configuration variable :confval:`disqus_drafts` as ``False``, you can achieve that. 34 | -------------------------------------------------------------------------------- /docs/manual/images/notebook_cells.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunpy/ablog/95610aad20e3e290ca82776f6132a62d8fc2fbcb/docs/manual/images/notebook_cells.png -------------------------------------------------------------------------------- /docs/manual/markdown.md: -------------------------------------------------------------------------------- 1 | --- 2 | blogpost: true 3 | date: Oct 10, 2020 4 | author: Nabil Freij 5 | location: World 6 | category: Manual 7 | language: English 8 | --- 9 | 10 | # Markdown Support 11 | 12 | ABlog can support markdown pages using [myst-parser](https://pypi.org/project/myst-parser/). 13 | This page is a markdown file underneath. 14 | 15 | You will need to do a few things to get setup. 16 | 17 | 1. Install [myst-parser](https://pypi.org/project/myst-parser/) 18 | 2. Add these options to your config, `conf.py` 19 | 20 | ```python 21 | extensions = [ 22 | ... 23 | "myst_parser", 24 | ... 25 | ] 26 | myst_update_mathjax = False 27 | ``` 28 | 29 | Then use the new blogpost metadata format (with a slight twist): 30 | 31 | ``` 32 | --- 33 | blogpost: true 34 | date: Oct 10, 2020 35 | author: Nabil Freij 36 | location: World 37 | category: Manual 38 | language: English 39 | --- 40 | ``` 41 | 42 | Notice here we do not have a ":" at the start since the markdown metadata format is different from rst. 43 | 44 | Please be aware that adding "myst-parser" will mean it will read all markdown files and try to parse them. 45 | You will need to use the following in your `conf.py` to prevent this: 46 | 47 | ```python 48 | exclude_patterns = [ 49 | "posts/*/.ipynb_checkpoints/*", 50 | ".github/*", 51 | ".history", 52 | "github_submodule/*", 53 | "LICENSE.md", 54 | "README.md", 55 | ] 56 | ``` 57 | -------------------------------------------------------------------------------- /docs/manual/notebook_support.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Jupyter Notebook Posting" 8 | ] 9 | }, 10 | { 11 | "cell_type": "raw", 12 | "metadata": { 13 | "raw_mimetype": "text/restructuredtext" 14 | }, 15 | "source": [ 16 | ".. post:: 27 Oct 2018\n", 17 | " :author: Nabil Freij, Second Author\n", 18 | " :tags: posting\n", 19 | " :category: Manual" 20 | ] 21 | }, 22 | { 23 | "cell_type": "markdown", 24 | "metadata": {}, 25 | "source": [ 26 | "To add support for Notebooks to your Ablog instance, you need to configure your `docs/conf.py` (or wherever your `conf.py` is located.\n", 27 | "\n", 28 | "You will need to add\n", 29 | "\n", 30 | "```\n", 31 | " extensions = [..., 'nbsphinx', ...]\n", 32 | " exclude_patterns = ['docs/manual/.ipynb_checkpoints/*'] (To exclude the notebook autosaves)\n", 33 | "```\n", 34 | "\n", 35 | "You will need to install [nbsphinx](https://nbsphinx.readthedocs.io/) either from `Anaconda` or `pip`. You might need to install [ipython](https://ipython.org/) to make sure the notebook can be run." 36 | ] 37 | }, 38 | { 39 | "cell_type": "markdown", 40 | "metadata": {}, 41 | "source": [ 42 | "Within the notebook you need to make sure the cells are in this order: Titlte cell, post cell. So for this notebook, it looks like this: ![posting](images/notebook_cells.png)" 43 | ] 44 | }, 45 | { 46 | "cell_type": "markdown", 47 | "metadata": {}, 48 | "source": [ 49 | "So the information is similar to how you create a normal RST post." 50 | ] 51 | }, 52 | { 53 | "cell_type": "markdown", 54 | "metadata": {}, 55 | "source": [ 56 | "Another working example is SunPy's website which runs [Ablog](https://sunpy.org/blog.html). The Pull Request that added support can be found [here](https://github.com/sunpy/sunpy.org/pull/131) and how to link them to a [Binder](https://mybinder.org/) instance [here](https://github.com/sunpy/sunpy.org/pull/134)." 57 | ] 58 | } 59 | ], 60 | "metadata": { 61 | "kernelspec": { 62 | "display_name": "Python 3", 63 | "language": "python", 64 | "name": "python3" 65 | }, 66 | "language_info": { 67 | "codemirror_mode": { 68 | "name": "ipython", 69 | "version": 3 70 | }, 71 | "file_extension": ".py", 72 | "mimetype": "text/x-python", 73 | "name": "python", 74 | "nbconvert_exporter": "python", 75 | "pygments_lexer": "ipython3", 76 | "version": "3.6.6" 77 | } 78 | }, 79 | "nbformat": 4, 80 | "nbformat_minor": 2 81 | } 82 | -------------------------------------------------------------------------------- /docs/manual/post-excerpts-and-images.rst: -------------------------------------------------------------------------------- 1 | Post Excerpts and Images 2 | ======================== 3 | 4 | .. post:: May 12, 2014 5 | :tags: directive 6 | :category: Manual 7 | :location: Pittsburgh 8 | :author: Ahmet 9 | :exclude: 10 | :image: 2 11 | 12 | This post describes how to choose an excerpt and an image image for a post to be displayed in archive pages. 13 | 14 | Excerpts 15 | -------- 16 | 17 | ABlog, by default, uses first paragraph of the document as post excerpt. 18 | Default number of paragraphs to use in excerpts is controlled via :confval:`post_auto_excerpt` configuration variable. 19 | This option can be overwritten using ``:excerpt:`` option in :rst:dir:`post` directive. 20 | 21 | Alternatively, you can provide some content in a post directive as follows:: 22 | 23 | .. post:: Apr 15, 2014 24 | 25 | This is all of the excerpt for this post. 26 | 27 | This content is going to be used as excerpt in archive pages. 28 | Furthermore, if you do not want the excerpt to be included in the post, you can use ``:exclude:`` option as follows:: 29 | 30 | .. post:: Apr 15, 2014 31 | :exclude: 32 | 33 | This is all of the excerpt for this post. 34 | It will be displayed in archive pages and excluded from the post page. 35 | 36 | Images 37 | ------ 38 | 39 | Let's first include a local and a non-local image in this post. 40 | 41 | .. image:: /_static/ablog.png 42 | .. image:: https://www.python.org/static/community_logos/python-logo.png 43 | 44 | To link the second one of these, we add ``:image: 2`` option in :rst:dir:`post` directive. 45 | -------------------------------------------------------------------------------- /docs/manual/posting-and-listing.rst: -------------------------------------------------------------------------------- 1 | Posting and Listing 2 | =================== 3 | 4 | .. post:: May 9, 2014 5 | :tags: directive 6 | :category: Manual 7 | :location: Pittsburgh 8 | :author: Ahmet 9 | 10 | This post describes :rst:dir:`post`, :rst:dir:`update`, and :rst:dir:`postlist` directives. 11 | 12 | .. _posting-directive: 13 | 14 | Posting with a Directive 15 | ------------------------ 16 | 17 | Any page in a Sphinx_ project can be converted to a post using the following directive: 18 | 19 | .. rst:directive:: post 20 | 21 | All possible directive options are shown below:: 22 | 23 | .. post:: 15 Apr, 2013 24 | :tags: tips, ablog, directive 25 | :category: Example, How To 26 | :author: Ahmet, Durden 27 | :location: Pittsburgh, SF 28 | :redirect: blog/old-page-name-for-the-post 29 | :excerpt: 2 30 | :image: 1 31 | :external_link: https://anexternalwebsite.org 32 | :nocomments: 33 | 34 | **Drafts & Posts** 35 | 36 | Posts without dates or with future dates are considered as drafts and are published only in :ref:`blog-drafts` archive page. 37 | 38 | Posts with dates that are older than the day Sphinx project is built are published in :ref:`blog-posts` page. 39 | 40 | Post date format must follow the format specified with confval:`post_date_format` configuration option. 41 | 42 | **Tags & Categories** 43 | 44 | You can specify multiple tags and categories by separating them with commas. 45 | Posts will be listed in archive pages generated for each unique tag and category. 46 | 47 | **Authors, Languages, & Locations** 48 | 49 | Likewise, you can specify authors, languages, and locations of a post using ``:author:``, ``:language:``, and ``:location:`` options. 50 | All of these option names are in their singular form, but multiple values separated by commas are accepted. 51 | 52 | Using :confval:`blog_authors`, :confval:`blog_languages`, and :confval:`blog_locations` configuration variables, you can also provide home pages and/or full display names of authors, languages, and locations, which will be displayed in archive pages generated for all unique authors, languages, and locations. 53 | 54 | **Redirections** 55 | 56 | You can make ABlog create pages that will redirect to current post using ``:redirect:`` option. It takes a comma separated list of paths, relative to the root folder. 57 | The redirect page waits for :confval:`post_redirect_refresh` seconds before redirection occurs. 58 | 59 | **Disable comments** 60 | 61 | You can disable comments for the current post using the ``:nocomments:`` option. 62 | Currently there is no way to disable comments in a specific page. 63 | 64 | **Excerpts & Images** 65 | 66 | By default, ABlog uses the first paragraph of a page as post excerpt. 67 | You can change this behavior and also add an image to the excerpt. 68 | To find out how, see :ref:`post-excerpts-and-images`. 69 | 70 | **Canonical links** 71 | 72 | If you re-publish content already existing on another URL (e.g., if you re-publish content from an employer's blog your personal one), use the ``canonical_link`` parameter to create a [canonical link relation](https://datatracker.ietf.org/doc/html/rfc6596) to the original version. 73 | 74 | **External links** 75 | 76 | If you'd like a post to point to an external website (e.g., if you host your posts on a blogging platform like Medium but wish to maintain a list of posts on your ``Ablog`` site), use the ``external_link`` parameter and this will be used instead. 77 | 78 | **Update Notes** 79 | 80 | .. rst:directive:: update 81 | 82 | Update in a post can be noted anywhere in the post as follows:: 83 | 84 | .. update:: 20 Apr, 2014 85 | 86 | Added :rst:dir:`update` directive and :ref:`posting-sections` section. 87 | Also revised the text here and there. 88 | 89 | Update date format must follow the format specified with :confval:`post_date_format` configuration option. 90 | 91 | Update directive renders like the updates that are at the end of this post. 92 | 93 | .. _posting-front-matter: 94 | 95 | Posting with page front-matter 96 | ------------------------------ 97 | 98 | If you'd prefer to use `page front matter `__ instead of using a directive, you may mark a page as a "blog post" by adding the following front-matter at the top: 99 | 100 | .. code-block:: rst 101 | 102 | :blogpost: true 103 | 104 | ``ABlog`` will treat any pages with this front-matter as a blog post. 105 | All fields that are available to the :ref:`posting directive ` can be given as page-level front-matter as well. 106 | 107 | .. admonition:: Automatically detect blog posts with a ``glob`` pattern 108 | :class: tip 109 | 110 | Instead of adding ``blogpost: true`` to each page, you may also provide a pattern (or list of patterns) in your ``conf.py`` file using the ``blog_post_pattern`` option. 111 | Any filenames that match this pattern will be treated as blog posts (and page front-matter will be used to classify the blog post). 112 | For example, the following configuration would match all ``rst`` files in the ``posts/`` folder: 113 | 114 | .. code-block:: python 115 | 116 | blog_post_pattern = "posts/*.rst" 117 | 118 | and this configuration will match all blog posts that match either ``rst`` or ``md``: 119 | 120 | .. code-block:: python 121 | 122 | blog_post_pattern = ["posts/*.rst", "posts/*.md"] 123 | 124 | .. _posting-sections: 125 | 126 | Posting Sections 127 | ---------------- 128 | 129 | .. post:: Aug 20, 2014 130 | :tags: directive 131 | :category: Manual 132 | :location: SF 133 | :author: Ahmet 134 | 135 | :rst:dir:`post` directive can be used multiple times in a single page to create multiple posts of different sections of the document. 136 | 137 | When :rst:dir:`post` is used more than once, post titles and excerpts are extracted from the sections that contain the directives. 138 | This behavior can also be set as the default behavior using :confval:`post_always_section` configuration options. 139 | 140 | Some caveats and differences from posting a document once are: 141 | 142 | * Next and previous links at the bottom will only regard the first post in the document. 143 | * Information displayed on the sidebar will belong to the first post. 144 | * References for section posts is not automatically created. Labels for cross-referencing needs to be created manually, e.g., ``.. _posting-sections``. See :ref:`xref-syntax` for details. 145 | 146 | Multiple use of :rst:dir:`post` may be suitable for major additions to a previous post. For minor changes, :rst:dir:`update` directive may be preferred. 147 | 148 | Listing 149 | ------- 150 | 151 | A list of posts can be displayed in any page using the following directive: 152 | 153 | .. rst:directive:: postlist 154 | 155 | Following example display all the options the directive takes:: 156 | 157 | .. postlist:: 5 158 | :author: Ahmet 159 | :category: Manual 160 | :location: Pittsburgh 161 | :language: en 162 | :tags: tips 163 | :date: %A, %B %d, %Y 164 | :format: {title} by {author} on {date} 165 | :list-style: circle 166 | :excerpts: 167 | :sort: 168 | :expand: Read more ... 169 | 170 | This will result in a bullet list of up to 5 posts (default is all) authored by `:ref:`author-ahmet`` in `:ref:`language-en`` when he was in `:ref:`location-pittsburgh`` and posted in `:ref:`category-manual`` with tags `:ref:`tag-tips``. 171 | Posts will be in ``:sort:``\ed to appear in chronological order and listed with their ``:excerpts:``. 172 | Here are those posts: 173 | 174 | .. postlist:: 5 175 | :author: Ahmet 176 | :category: Manual 177 | :location: Pittsburgh 178 | :language: en 179 | :tags: tips 180 | :date: %A, %B %d, %Y 181 | :format: {title} by {author} on {date} 182 | :list-style: circle 183 | :excerpts: 184 | :sort: 185 | :expand: Read more ... 186 | 187 | When no options are given all posts will be considered and they will be ordered by recency. 188 | Also, note that if the current post is one of the most recent posts, it will be omitted. 189 | 190 | .. update:: Aug 21, 2014 191 | 192 | Added :rst:dir:`update` directive and 193 | :ref:`posting-sections` section. 194 | Also revised the text here and there. 195 | 196 | .. update:: Sep 15, 2014 197 | 198 | * :rst:dir:`post` directive has ``:language:`` option. 199 | * :rst:dir:`postlist` directive takes arguments to filter posts. 200 | 201 | .. update:: Mar 28, 2015 202 | 203 | Added ``:excerpts:`` option to :rst:dir:`postlist` to list posts with their excerpts. 204 | 205 | .. update:: Apr 14, 2015 206 | 207 | Added ``:list-style:`` option to :rst:dir:`postlist` to control bullet list style. 208 | *circle*, *disc*, and *none* (default) are recognized. 209 | 210 | .. update:: May 25, 2021 211 | 212 | Added ``:expand:`` option to :rst:dir:`postlist` to add a call to action to continue reading the post. 213 | -------------------------------------------------------------------------------- /docs/manual/templates-themes.rst: -------------------------------------------------------------------------------- 1 | Templating and Themes Support 2 | ============================= 3 | 4 | .. post:: Oct 26, 2024 5 | :tags: themes 6 | :category: Manual 7 | :author: Libor 8 | 9 | Ablog, being a Sphinx extension, has highly customizable HTML output. The generated HTML files are based on `Sphinx templates`_. You, or Sphinx themes, can partially or completely override these templates to customize the resulting HTML. 10 | 11 | .. _Sphinx templates: https://www.sphinx-doc.org/en/master/development/html_themes/templating.html 12 | 13 | .. versionchanged:: 0.11 14 | The :doc:`Ablog 0.11 ` has changed and improved the way you can customize templates and themes. Please note that this document describes the new way of customizing templates and themes support. 15 | 16 | .. _sidebars: 17 | 18 | Blog sidebars 19 | ------------- 20 | 21 | Sidebars are a common way to provide additional information to the reader. There are seven Ablog sidebars you can include in your HTML output using the Sphinx_ :confval:`html_sidebars` configuration option (in addition to your theme sidebars). 22 | 23 | - ``ablog/postcard.html`` provides information regarding the current post (when on a post page). 24 | - ``ablog/recentposts.html`` lists the most recent five posts. 25 | - ``ablog/tagcloud.html`` provides links to archive pages generated for each tag. 26 | - ``ablog/category.html``, ``ablog/authors.html``, ``ablog/languages.html``, and ``ablog/locations.html`` sidebars generate lists of links to respective archive pages with the number of matching posts (e.g., "Manual (14)", "2023 (8)", "English (22)"). 27 | 28 | For example, the sidebars that you see on this website on the left are: 29 | 30 | .. code-block:: python 31 | 32 | html_sidebars = { 33 | "**": [ 34 | # Comes from Alabaster theme 35 | "about.html", 36 | "searchfield.html", 37 | # Ablog sidebars 38 | "ablog/postcard.html", 39 | "ablog/recentposts.html", 40 | "ablog/tagcloud.html", 41 | "ablog/categories.html", 42 | "ablog/archives.html", 43 | "ablog/authors.html", 44 | "ablog/languages.html", 45 | "ablog/locations.html", 46 | ] 47 | } 48 | 49 | Styling default Ablog sidebars 50 | ------------------------------ 51 | 52 | Ablog standard sidebars are wrapped in ``
`` with CSS classes like :samp:`ablog-sidebar-item ablog__{}`, making them easier to style. 53 | 54 | For example, the ``recentposts.html`` template is wrapped in ``
``. 55 | 56 | .. seealso:: 57 | 58 | Built-in sidebars can be found in the ``ablog/`` folder in the `Ablog source code `_. 59 | 60 | If styling is not enough, you can override the Ablog templates in your Sphinx project or in the Sphinx theme. 61 | 62 | Partial or complete override of Ablog templates 63 | ----------------------------------------------- 64 | 65 | To control whether Ablog injects its own templates into the Sphinx build, you can use the following ``conf.py`` configuration option: 66 | 67 | .. confval:: skip_injecting_base_ablog_templates 68 | 69 | If set to ``True``, Ablog will not inject its own templates into the Sphinx build. This is useful if you want to completely override Ablog templates in your Sphinx project or in the Sphinx theme. The default is ``False``. 70 | 71 | Customizing templates in the project 72 | ------------------------------------ 73 | 74 | All Ablog templates are under the ``ablog/`` folder space. For example, ``ablog/postcard.html``. You can override these templates by placing them in the ``ablog/`` folder in your project templates folder. 75 | 76 | #. Add the :confval:`templates_path` option in your ``conf.py`` file: 77 | 78 | .. code-block:: python 79 | 80 | templates_path = ["_templates"] 81 | 82 | #. Create a folder ``_templates/`` next to your ``conf.py`` file. It will hold your custom templates. 83 | #. Create a folder ``ablog/`` inside the ``_templates/`` folder. 84 | #. Create a file here with the same name as the template you want to override. For example, ``postcard.html``. This file will be used as a custom template for the sidebar. You can copy the content of the original template from the Ablog source code and modify it as you need. 85 | #. Optionally: if you want to completely override all Ablog templates, set the :confval:`skip_injecting_base_ablog_templates` option to ``True``, copy all Ablog templates here, and customize them as you need. 86 | 87 | Customizing templates in the theme 88 | ---------------------------------- 89 | 90 | If you are a Sphinx theme author, you can ship customized Ablog templates in your theme. You can override Ablog templates by placing them in the ``ablog/`` folder in your theme templates, e.g., ``ablog/postcard.html``. 91 | 92 | #. In the theme root (where the ``theme.toml`` (or ``theme.ini`` in older Sphinx themes) file is), create a folder ``ablog/``. 93 | #. Create a file here with the same name as the template you want to override. For example, ``postcard.html``. 94 | #. This file will be used as a custom template for the sidebar. You can copy the content of the original template from the Ablog source code and modify it as you need. 95 | #. In your ``theme.toml`` file, add the following (under the ``[options]`` section): 96 | 97 | .. code-block:: toml 98 | 99 | ablog_inject_templates_after_theme = true 100 | 101 | This will ensure that Ablog templates are injected *after* the theme templates, so you can override them while still using the Ablog templates as a fallback. 102 | -------------------------------------------------------------------------------- /docs/manual/watch-yourself-blogging.rst: -------------------------------------------------------------------------------- 1 | 2 | Watch Yourself Blogging 3 | ======================= 4 | 5 | .. post:: Apr 19, 2015 6 | :tags: commands, tips 7 | :category: Manual 8 | :author: Ahmet 9 | :location: SF 10 | :language: en 11 | 12 | Wouldn't you like your blog being rebuilt and served to you automatically as you are blogging on a sunny Sunday afternoon? 13 | It's now possible with the improved ``ablog serve`` command. 14 | 15 | First, you need to install Watchdog_ Python package, e.g. `pip install watchdog`. 16 | Then, you need to run ``ablog serve -r``. 17 | Regardless of the weather being sunny or the day of the week, your project will be rebuilt when you change a page or add a new one. 18 | This won't refresh your browser page though. 19 | Unless you want to hit refresh once in a while, you can easily find an auto refresher extension for you browser. 20 | 21 | .. _Watchdog: https://github.com/gorakhargosh/watchdog 22 | -------------------------------------------------------------------------------- /docs/nitpick-exceptions: -------------------------------------------------------------------------------- 1 | py:class docutils.nodes.Node 2 | py:class docutils.nodes.General 3 | py:class docutils.nodes.Body 4 | py:class docutils.nodes.admonition 5 | py:class docutils.parsers.rst.directives.admonitions.BaseAdmonition 6 | py:class docutils.transforms.Transform 7 | py:class docutils.nodes.Element 8 | py:class docutils.nodes.Admonition 9 | -------------------------------------------------------------------------------- /docs/release/ablog-v0.1-released.rst: -------------------------------------------------------------------------------- 1 | :blogpost: true 2 | :tags: tips 3 | :author: Ahmet 4 | :category: Release 5 | :location: SF 6 | :date: May 14, 2014 7 | 8 | ABlog v0.1 released 9 | =================== 10 | 11 | ABlog v0.1 is released. 12 | 13 | This is the very first release, so there are no release notes in this post. 14 | 15 | Yes, this page is also a post and it resides in a folder different from 16 | most other posts in this blogumentation. 17 | 18 | The idea is to enable making any page in a Sphinx_ project a post so that 19 | users of a software package can subscribe to feeds and follow new releases 20 | as well as code examples added to the documentation. 21 | -------------------------------------------------------------------------------- /docs/release/ablog-v0.10-released.rst: -------------------------------------------------------------------------------- 1 | ABlog v0.10 released 2 | ==================== 3 | 4 | .. post:: Nov 17, 2019 5 | :author: Nabil Freij 6 | :category: Release 7 | :location: World 8 | 9 | ABlog v0.10 is released with the main focus being to support the latest version of Sphinx as well as Python 3 only support. 10 | 11 | Ablog V0.9.X will no longer be supported as Python 2 comes to an end in a few months and it is time people upgraded. 12 | 13 | Pull Requests merged in: 14 | 15 | `Overhaul of package underneath for python3 only `__ from `nabobalis `__. 16 | 17 | `Add validation for conf.py entries `__ from `rayalan `__. 18 | 19 | `Deploy improve `__ from `rayalan `__. 20 | 21 | `Get ablog ready for 0.10 `__ from `nabobalis `__. 22 | 23 | ABlog v0.10.1 released 24 | ---------------------- 25 | 26 | Pull Requests merged in: 27 | 28 | `Change StopIteration to return `__ from `remyabel2 `__. 29 | 30 | ABlog v0.10.2 released 31 | ---------------------- 32 | 33 | Pull Requests merged in: 34 | 35 | `Fix unclosed span tag `__ from `ykrods `__. 36 | 37 | ABlog v0.10.3 released 38 | ---------------------- 39 | 40 | Pull Requests merged in: 41 | 42 | `Pin werkzeug to < 1 `__ from `dstansby `__. 43 | 44 | `MNT: Fix Giles URL `__ from `pllim `__. 45 | 46 | ABlog v0.10.4 released 47 | ---------------------- 48 | 49 | Pull Requests merged in: 50 | 51 | `Add zh_CN locale `__ from `daimon99 `__. 52 | 53 | `Add intersphinx to the extension list `__ from `plaindocs `__. 54 | 55 | `Fix "test5" `__ and `Use "dirhtml" builder on Read The Docs `__ from `blueyed `__. 56 | 57 | ABlog v0.10.5 released 58 | ---------------------- 59 | 60 | Pull Requests merged in: 61 | 62 | `Add custom GitHub URL support `__ from `tg-m `__. 63 | 64 | ABlog v0.10.6 released 65 | ---------------------- 66 | 67 | Pull Requests merged in: 68 | 69 | `Add french locale `__ from `kujiu `__. 70 | 71 | ABlog v0.10.7 released 72 | ---------------------- 73 | 74 | Pull Requests merged in: 75 | 76 | `Automatically add templates path to documentation `__ from `choldgraf `__. 77 | 78 | ABlog v0.10.8 released 79 | ---------------------- 80 | 81 | Removed the hard dependencies on alabaster and sphinx-automodapi. 82 | 83 | Replaced `werkzeug `__ with `feedgen `__ due to the former removing ATOM support. 84 | 85 | Version pin of nbsphinx has been removed. 86 | 87 | ABlog v0.10.9 released 88 | ---------------------- 89 | 90 | Pull Requests merged in: 91 | 92 | `frontmatter and blog post matching `__ from `choldgraf `__. 93 | 94 | ABlog v0.10.10 released 95 | ----------------------- 96 | 97 | Pull Requests merged in: 98 | 99 | `Various Issues `__. 100 | 101 | `Fix missing reference caused by ref with title `__ from `ykrods `__. 102 | 103 | `Add instructions for starting new blog posts with front-matter `__ from `kakirastern `__. 104 | 105 | ABlog v0.10.11 released 106 | ----------------------- 107 | 108 | Pull Requests merged in: 109 | 110 | `improving glob matching and documenting it `__ from `choldgraf `__. 111 | 112 | 113 | ABlog v0.10.12 released 114 | ----------------------- 115 | 116 | Pull Requests merged in: 117 | 118 | `id of feed is now blog.blog_baseurl `__. 119 | 120 | ABlog v0.10.13 released 121 | ----------------------- 122 | 123 | Pull Requests merged in: 124 | 125 | `updated CI and py39 tests `__. 126 | `Add test #87 `__. 127 | `Some minor fixes `__. 128 | `Ensure blog_post_pattern are relative to srcdir `__. 129 | 130 | ABlog v0.10.14 released 131 | ----------------------- 132 | 133 | Pull Requests merged in: 134 | 135 | `feat(feeds): Add missing Atom entry metadata `__. 136 | `feat(feeds): Add entry element template support `__. 137 | `misc update `__. 138 | 139 | 140 | ABlog v0.10.15 released 141 | ----------------------- 142 | 143 | Fixed `Index Out of Range with Atom Feeds `__. 144 | 145 | ABlog v0.10.16 released 146 | ----------------------- 147 | 148 | Pull Requests merged in: 149 | 150 | `fix(feeds): Feed validation, templates regression `__. 151 | 152 | ABlog v0.10.17 released 153 | ----------------------- 154 | 155 | Pull Requests merged in: 156 | 157 | `Correct draft URL `__. 158 | 159 | ABlog v0.10.18 released 160 | ----------------------- 161 | 162 | Pull Requests merged in: 163 | 164 | `Correct posts URL `__. 165 | `Add isso integration `__. 166 | 167 | ABlog v0.10.19 released 168 | ----------------------- 169 | 170 | Pull Requests merged in: 171 | 172 | `Add expand option `__. 173 | 174 | 175 | ABlog v0.10.20 released 176 | ----------------------- 177 | 178 | Pull Requests merged in: 179 | 180 | `fix documentation typo in blog-drafts `__. 181 | `Fix typo `__. 182 | `Catalan translation `__. 183 | `Fix ablog post `__. 184 | 185 | ABlog v0.10.21 released 186 | ----------------------- 187 | 188 | Pull Requests merged in: 189 | 190 | `Fix/multilang feed links `__. 191 | 192 | BREAKING CHANGE - DROPPED PYTHON 3.6 SUPPORT 193 | 194 | ABlog v0.10.22 released 195 | ----------------------- 196 | 197 | Pull Requests merged in: 198 | 199 | `Fix tags field for myst_parser `__. 200 | 201 | ABlog v0.10.23 released 202 | ----------------------- 203 | 204 | Pull Requests merged in: 205 | 206 | `optionally show previous / next links on post page `__. 207 | `add classes to post elements `__. 208 | 209 | 210 | ABlog v0.10.24 released 211 | ----------------------- 212 | 213 | Breaking Changes: 214 | 215 | Minimum versions of packages increased: 216 | 217 | .. code-block:: bash 218 | 219 | feedgen>=0.9.0 220 | invoke>=1.6.0 221 | python-dateutil>=2.8.0 222 | sphinx>=4.0.0 223 | watchdog>=2.0.0 224 | myst-parser>=0.17.0 225 | pytest>=6.0.0 226 | 227 | Pull Requests merged in: 228 | 229 | `Get rid of eval and fix #128 `__. 230 | `CI Tweak `__. 231 | 232 | ABlog v0.10.25 released 233 | ----------------------- 234 | 235 | Pull Requests merged in: 236 | 237 | `Normalise path to posix as sphinx expects `__. 238 | 239 | ABlog v0.10.26 released 240 | ----------------------- 241 | 242 | Pull Requests merged in: 243 | 244 | `docs: Fix format of sphinx.ext.extlink for Sphinx 5.x `__. 245 | `docs: Use ref link rather than hardcode link `__. 246 | `Ci and Warnings Fix `__. 247 | 248 | ABlog v0.10.27 released 249 | ----------------------- 250 | 251 | Pull Requests merged in: 252 | 253 | `Improve conditional check for author metadata `__. 254 | 255 | ABlog v0.10.28 released 256 | ----------------------- 257 | 258 | Pull Requests merged in: 259 | 260 | `findall -> traverse for older versions of docutils `__. 261 | 262 | ABlog v0.10.29 released 263 | ----------------------- 264 | 265 | Pull Requests merged in: 266 | 267 | `Fix the error on some empty option value of post directive `__. 268 | 269 | ABlog v0.10.30 released 270 | ----------------------- 271 | 272 | Pull Requests merged in: 273 | 274 | `Sort Feed posts by date `__. 275 | `Fix sidebars ablog translations `__. 276 | 277 | ABlog v0.10.31 released 278 | ----------------------- 279 | 280 | Pull Requests merged in: 281 | 282 | `Add external links for posts `__. 283 | -------------------------------------------------------------------------------- /docs/release/ablog-v0.11-released.rst: -------------------------------------------------------------------------------- 1 | ABlog v0.11 released 2 | ==================== 3 | 4 | .. post:: March 23, 2023 5 | :author: Nabil Freij 6 | :category: Release 7 | :location: World 8 | 9 | ABlog v0.11 is released with the main focus being to update and tweak the HTML templates allow themes to override the default templates. 10 | In addition, all ablog elements in the templates wrapped in ``ablog__*`` divs to allow custom CSS rules. 11 | 12 | We also adopt `NEP29 `__ and drop support for older versions of Python and package versions that are 24 months old or older at time of release. 13 | 14 | Added support for external links to be posts. 15 | 16 | There are several breaking changes: 17 | 18 | - 1. The template files are now in the ``templates/ablog`` folder. 19 | Older templates are still in the old location but will raise a warning. 20 | These will be removed in a future version, please do not use them anymore. 21 | You will need to update any paths to them to add "ablog/" to the path. 22 | - 2. ``ablog`` has support for not injecting its own templates into the Sphinx build. 23 | This is supported by add ``skip_injecting_base_ablog_templates = True`` to your configuration file. 24 | - 3. Minimum version of Python is >=3.9 and Sphinx is >=5.0. 25 | 26 | Pull Requests merged in: 27 | 28 | `Template rework `__. 29 | 30 | `Add external links for posts `__ from `Chris Holdgraf `__. 31 | 32 | Unreleased 33 | ---------- 34 | 35 | Pull Requests merged in: 36 | 37 | `Fix theme support for Ablog `__ from `Libor Jelínek `__. 38 | 39 | ABlog v0.11.1 released 40 | ---------------------- 41 | 42 | Pull Requests merged in: 43 | 44 | `Update version handling to remove use of pkg_resources `__ 45 | 46 | ABlog v0.11.2 released 47 | ---------------------- 48 | 49 | Pull Requests merged in: 50 | 51 | `append posts to atom feed to keep post order from new to old `__ from `lexming `__. 52 | `avoid spurious warning about posts with front-matter and post directive `__ from `lexming `__. 53 | 54 | ABlog v0.11.3 released 55 | ---------------------- 56 | 57 | Pull Requests merged in: 58 | 59 | `use fully qualified URLs for images in atom feed `__ from `lexming `__. 60 | 61 | ABlog v0.11.4 released 62 | ---------------------- 63 | 64 | Pull Requests merged in: 65 | 66 | `Use paragraph instead of container for blog post excerpts `__ from `dstansby `__. 67 | 68 | ABlog v0.11.5 released 69 | ---------------------- 70 | 71 | Pull Requests merged in: 72 | 73 | `Fix incorrect /div when using discuss `__ from `Cadair `__. 74 | 75 | ABlog v0.11.6 released 76 | ---------------------- 77 | 78 | Pull Requests merged in: 79 | 80 | `Adds IT locale `__ from `Stefano David `__. 81 | 82 | `Enables configuring a canonical_link for individual posts `__ from `Hendrik Makait `__. 83 | 84 | ABlog v0.11.7 released 85 | ---------------------- 86 | 87 | Pull Requests merged in: 88 | 89 | `Add stylesheet for tagcloud `__ from `Shengyu Zhang `__. 90 | 91 | `Create demo/ before running ablog start `__ from `Shengyu Zhang `__. 92 | 93 | 94 | `Add span to more items in templates `__ from `Nabil Freij `__. 95 | 96 | ABlog v0.11.8 released 97 | ---------------------- 98 | 99 | Added support for ``sphinx`` >=7.3.0 100 | 101 | ABlog v0.11.9 released 102 | ---------------------- 103 | 104 | `Make '_strip' function return as list not set. `__ from `Joe Ziminski `__. 105 | 106 | ABlog v0.11.10 released 107 | ----------------------- 108 | 109 | Fixed wrong branch in the release process. 110 | 111 | ABlog v0.11.11 released 112 | ----------------------- 113 | 114 | Mark Ablog parallel safe. 115 | 116 | Dropped support for Python 3.9, Sphinx less than 6.2. 117 | This mirrors the requirements for alabaster 1.0.0. 118 | 119 | ABlog v0.11.12 released 120 | ----------------------- 121 | 122 | `Improve ablog-configuration-options.rst. `__ from `Libor Jelínek `__. 123 | 124 | `Fix sidebars CSS naming. `__ from `Libor Jelínek `__. 125 | 126 | `Ablog is NOT safe for parallel read. `__ from `Libor Jelínek `__. 127 | 128 | `Fix theme support for ablog. `__ from `Libor Jelínek `__. 129 | -------------------------------------------------------------------------------- /docs/release/ablog-v0.2-released.rst: -------------------------------------------------------------------------------- 1 | ABlog v0.2 released 2 | =================== 3 | 4 | .. post:: Aug 31, 2014 5 | :author: Ahmet 6 | :category: Release 7 | :location: SF 8 | 9 | ABlog v0.2 is released. This version comes with several new features: 10 | 11 | * You can post a document multiple times, see :ref:`posting-sections` 12 | for details. 13 | 14 | * You can make note of updates in a post using :rst:dir:`update` 15 | directive. 16 | 17 | * Blog feeds for authors, locations, categories, tags, and years 18 | can be enabled using :confval:`blog_feed_archives` configuration 19 | variable. 20 | 21 | * Blog Feeds can be made full text using :confval:`blog_feed_fulltext` 22 | configuration variable. 23 | 24 | * Recent posts side bar includes month and day of the posts. 25 | 26 | ABlog v0.2.1 released 27 | --------------------- 28 | 29 | ABlog v0.2.1 is a bug fix release that solves duplicated content 30 | problem in full text atom feeds. 31 | 32 | ABlog v0.2.2 released 33 | --------------------- 34 | 35 | ABlog v0.2.2 is a bug fix release that solves broken links problem 36 | in post lists (:issue:`12`). 37 | 38 | ABlog v0.2.3 released 39 | --------------------- 40 | 41 | ABlog v0.2.3 is a bug fix release that solves broken links (:issue:`13`) 42 | and non-unique post IDs problems atom feeds. 43 | -------------------------------------------------------------------------------- /docs/release/ablog-v0.3-released.rst: -------------------------------------------------------------------------------- 1 | ABlog v0.3 released 2 | =================== 3 | 4 | ABlog v0.3 is released. This version comes with the following core 5 | improvements: 6 | 7 | * You can now specify language of a post with ``:language:`` option, 8 | and an archive page will be created for each language. 9 | See :confval:`blog_languages` and :confval:`blog_default_language` 10 | if you are posting in multiple languages. 11 | 12 | * You can list language archives on your website by adding 13 | ``languages.html`` to :confval:`html_sidebars` configuration option. 14 | 15 | * :rst:dir:`postlist` directive takes options to filter posts. 16 | 17 | ABlog v0.3.1 released 18 | --------------------- 19 | 20 | ABlog v0.3.1 is a minor release to fix two issues in templates: 21 | 22 | * Links to collection (archive) feeds is displayed only on collection page 23 | (e.g. `:ref:`category-manual``), not on a catalog page that lists posts 24 | for multiple collections (e.g. `:ref:`blog-categories``). 25 | 26 | * Links to collection feeds is displayed only when they are generated 27 | (see :confval:`blog_feed_archives`). Previously, links would be generated 28 | to feeds that did not exist. 29 | -------------------------------------------------------------------------------- /docs/release/ablog-v0.4-released.rst: -------------------------------------------------------------------------------- 1 | ABlog v0.4 released 2 | =================== 3 | 4 | .. post:: Dec 20, 2014 5 | :author: Ahmet 6 | :category: Release 7 | :location: SF 8 | 9 | ABlog v0.4 is released. This version comes with the following improvements 10 | and bug fixes: 11 | 12 | * Added :confval:`blog_feed_titles`, :confval:`blog_feed_length`, and 13 | :confval:`blog_archive_titles` configuration options (see :issue:`24`). 14 | 15 | * Set the default for :confval:`blog_feed_archives` to ``False``, which 16 | was set to ``True`` although documented to be otherwise. 17 | 18 | * Fixed issues with :confval:`post_auto_excerpt` and 19 | :confval:`post_auto_image` configuration options. 20 | 21 | * Fixed :issue:`2`, relative size of tags being the minimum size when 22 | all tags have the same number of posts. Now, mean size is 23 | used, and max/min size can be controlled from template. 24 | 25 | * Fixed :issue:`19`. Yearly archives are ordered by recency. 26 | 27 | * Fixed duplicated post title in feeds, :issue:`21`. 28 | 29 | * Fixed :issue:`22`, :rst:dir:`postlist` directive listing more than 30 | specified number of posts. 31 | 32 | * :rst:dir:`postlist` directive accepts arguments to format list items 33 | (:issue:`20`). 34 | -------------------------------------------------------------------------------- /docs/release/ablog-v0.5-released.rst: -------------------------------------------------------------------------------- 1 | ABlog v0.5 released 2 | =================== 3 | 4 | .. post:: Mar 25, 2015 5 | :author: Ahmet, Mehmet 6 | :category: Release 7 | :location: SF 8 | 9 | ABlog v0.5 is released. This version comes with :ref:`ablog-commands` and 10 | a :ref:`quick-start` guide. 11 | 12 | ABlog v0.5.1 released 13 | --------------------- 14 | 15 | Added ``:excerpts:`` option to :rst:dir:`postlist` directive. 16 | -------------------------------------------------------------------------------- /docs/release/ablog-v0.6-released.rst: -------------------------------------------------------------------------------- 1 | ABlog v0.6 released 2 | =================== 3 | 4 | .. post:: Apr 8, 2015 5 | :author: Ahmet 6 | :category: Release 7 | :location: SF 8 | 9 | ABlog v0.6 is released with new :ref:`ablog-commands`. You can use 10 | ``ablog deploy`` to :ref:`deploy-to-github-pages`, and also ``ablog clean`` 11 | to do spring cleaning every once in a while. 12 | 13 | ABlog v0.6.1 released 14 | --------------------- 15 | 16 | ABlog v0.6.1 is released with improvements to ``ablog deploy`` command. 17 | It will add ``.nojekyll`` file when needed to deployments to GitHub pages. 18 | 19 | ABlog v0.6.2 released 20 | --------------------- 21 | 22 | ABlog v0.6.2 is released to fix an issue with loading of Disqus comments 23 | (:issue:`33`) and interpreting non-ascii characters (:issue:`34`). 24 | 25 | ABlog v0.6.3 released 26 | --------------------- 27 | 28 | ABlog v0.6.3 comes with Russian localisation and following enhancements: 29 | 30 | * Added ``:list-style:`` option to :rst:dir:`postlist` to enable 31 | controlling bullet list style. 32 | 33 | * ``ablog post`` command de-slugifies filename to make the title 34 | when it's not given. 35 | 36 | ABlog v0.6.4 released 37 | --------------------- 38 | 39 | ABlog v0.6.4 comes with improved ``ablog serve`` command that helps you 40 | :ref:`watch-yourself-blogging`. 41 | 42 | ABlog v0.6.5 released 43 | --------------------- 44 | 45 | ABlog v0.6.5 is a bug fix release to resolve :issue:`38`, an exception raised 46 | when using :rst:dir:`postlist` without specifying number of posts. 47 | -------------------------------------------------------------------------------- /docs/release/ablog-v0.7-released.rst: -------------------------------------------------------------------------------- 1 | ABlog v0.7 released 2 | =================== 3 | 4 | .. post:: May 3, 2015 5 | :author: Ahmet 6 | :category: Release 7 | :location: Denizli 8 | 9 | ABlog v0.7.0 is released to fix the long standing :issue:`1` related to 10 | pickling of Sphinx build environment on Read The Docs. Improvements 11 | also resolved issues with using LaTeX builder, improved cross-referencing 12 | for non-html builders. 13 | 14 | ABlog v0.7.1 released 15 | --------------------- 16 | 17 | ABlog v0.7.1 is released to fix Python 3 import issues in :command:`ablog serve` 18 | command. 19 | 20 | ABlog v0.7.2 released 21 | --------------------- 22 | 23 | ABlog v0.7.2 is released to prevent potential issues with Disqus thread URLs 24 | by requiring :confval:`disqus_shortname` and :confval:`blog_baseurl` 25 | to be specified together for Disqus integration. 26 | 27 | ABlog v0.7.3 released 28 | --------------------- 29 | 30 | ABlog v0.7.3 makes use of `python-dateutil`__ for parsing post dates, so now you 31 | can be flexible with the format you use in posts. Thanks to `Andy Maloney`__ 32 | for this improvement. 33 | 34 | __ https://pypi.python.org/pypi/python-dateutil 35 | __ https://github.com/amaloney 36 | 37 | ABlog v0.7.5 released 38 | --------------------- 39 | 40 | ABlog v0.7.5 is released to fix Windows specific path resolving issue with 41 | archive pages. Thanks to Peter Mills for reporting this issue. 42 | 43 | ABlog v0.7.6 released 44 | --------------------- 45 | 46 | ABlog v0.7.6 is released to fix path resolving issue that arose when 47 | ``:excerpts:`` is used in :rst:dir:`postlist` directive. Once again, thanks 48 | to Peter Mills for reporting this issue. Other minor changes are: 49 | 50 | * ``-P`` argument is added to :ref:`ablog build ` command to enable running pdb 51 | on exceptions. 52 | 53 | * ``conf.py`` file created by :ref:`ablog start ` updated to include 54 | ``about.html`` sidebar that comes with Alabaster_ theme. 55 | 56 | ABlog v0.7.7 released 57 | --------------------- 58 | 59 | ABlog v0.7.7 is released to fix path resolving :issue:`41` that arose when 60 | cross-references were used in post excerpts, and also post redirect 61 | issue in templates. 62 | 63 | ABlog v0.7.8 released 64 | --------------------- 65 | 66 | ABlog v0.7.8 is released to fix a Python 2 issue that appears when creating 67 | collection pages that contain non-ascii characters in their names (:issue:`45`) 68 | and filename escaping issue when committing changes using 69 | :ref:`ablog deploy ` command (:pull:`44`). 70 | Thanks to `uralbash`_ for these contributions. 71 | 72 | .. _uralbash: https://github.com/uralbash 73 | 74 | ABlog v0.7.9 released 75 | --------------------- 76 | 77 | ABlog v0.7.9 is released to fix Windows specific file renaming issue in 78 | :ref:`ablog deploy ` command (:issue:`46`). Thanks to `Velimir`_ 79 | for the fix. 80 | 81 | .. _Velimir: https://github.com/montyvesselinov 82 | 83 | ABlog v0.7.10 released 84 | ---------------------- 85 | 86 | ABlog v0.7.10 is released to resolve Sphinx JSON/Pickle builder issues 87 | related to serialization. 88 | 89 | ABlog v0.7.12 released 90 | ---------------------- 91 | 92 | ABlog v0.7.12 (and also v0.7.11) maintenance release are available. 93 | -------------------------------------------------------------------------------- /docs/release/ablog-v0.8-released.rst: -------------------------------------------------------------------------------- 1 | ABlog v0.8 released 2 | =================== 3 | 4 | .. post:: Oct 12, 2015 5 | :author: Ahmet 6 | :category: Release 7 | :location: SF 8 | 9 | ABlog v0.8.0 is released with additions and changes: 10 | 11 | * Added ``-a`` argument to :ref:`ablog build ` command, with which 12 | you can force rewriting all pages when rebuilding your project. Default is 13 | writing only pages that have changed. 14 | 15 | * Added ``-f`` argument to :ref:`ablog deploy ` command, with which 16 | you can amend to latest commit to keep GitHub pages repository small. 17 | Thanks to `uralbash`_ for this contribution. 18 | 19 | * Added ``-p`` argument to :ref:`ablog deploy ` command, with which 20 | you can specify the path to your GitHub pages repository, i.e. 21 | ``username.github.io``. 22 | 23 | * Changed :confval:`fontawesome_link_cdn` to be a string argument to enable 24 | linking to desired version of `Font Awesome`_. Thanks to `Albert Mietus`_ 25 | for this contribution. 26 | 27 | * Post lists font style is now controlled through CSS. Thanks to 28 | `Albert Mietus`_ for this contribution as well. 29 | 30 | * Fixed internal link resolution issue that affected atom feeds of 31 | collections, i.e. feeds of posts under a category, tag, or author. 32 | 33 | .. _Font Awesome: https://fontawesome.com/ 34 | .. _Albert Mietus: https://github.com/AlbertMietus 35 | .. _uralbash: https://github.com/uralbash 36 | 37 | ABlog v0.8.1 released 38 | --------------------- 39 | 40 | ABlog v0.8.1 is released to fix atom feed linking in HTML header (:issue:`54`). 41 | 42 | ABlog v0.8.2 released 43 | --------------------- 44 | 45 | ABlog v0.8.2 is released to fix date parsing (:issue:`58`) and Python 2.6 46 | installation (:issue:`59`) issues. 47 | 48 | ABlog v0.8.3 released 49 | --------------------- 50 | 51 | ABlog v0.8.3 is released to bring you recent enhancements: 52 | 53 | * `ninmesara`_ added ``:nocomments:`` argument to :rst:dir:`post` directive 54 | to disable comments per post. 55 | * `José Carlos García`_ added Spanish translations. 56 | 57 | .. _ninmesara: https://github.com/ninmesara 58 | .. _José Carlos García: https://github.com/quobit 59 | -------------------------------------------------------------------------------- /docs/release/ablog-v0.9-released.rst: -------------------------------------------------------------------------------- 1 | ABlog v0.9 released 2 | =================== 3 | 4 | .. post:: Feb 17, 2018 5 | :author: Nabil Freij 6 | :category: Release 7 | :location: World 8 | 9 | ABlog v0.9.0 is released with the main focus being to support the latest version of Sphinx. 10 | This also moves the main development from `Abakan`_ to `SunPy`_. 11 | 12 | This has merged in all current (at time of writing, 6) open PRs to the original repository. 13 | 14 | These are: 15 | 16 | `fix(commands): Update command arguments so patterns works correctly `__ from `rayalan `__. 17 | 18 | `Fix couple of bugs with latest stable Sphinx `__ from `tadeboro `__. 19 | 20 | `don't use fancy quotes in the conf.py template `__ from `tiwo `__. 21 | 22 | `Pass through additional Sphinx options and fix a typo `__ from `ahrbel `__. 23 | 24 | `fix #78 (ImportError: cannot import name make_admonition in Sphinx 1.6) `_ from `lsaffre `__. 25 | 26 | `Raise exception when title is missing `__ from `rgrinberg `__. 27 | 28 | .. _Abakan: https://github.com/abakan/ablog 29 | .. _SunPy: https://github.com/sunpy/ablog 30 | 31 | ABlog v0.9.1 released 32 | --------------------- 33 | 34 | Minor update to remove Ablog{}.format(python_number) exes 35 | 36 | ABlog v0.9.2 released 37 | --------------------- 38 | 39 | Fixed Windows String issue. 40 | 41 | ABlog v0.9.3 released 42 | --------------------- 43 | 44 | Added example on how to use writing blog posts in Jupyter notebooks. 45 | 46 | `show when if fa `__, `Add create file encoding `__ and `fix serve command path `__ from `anzawatta `__. 47 | 48 | Sorry I was late to release these! 49 | 50 | ABlog v0.9.4 released 51 | --------------------- 52 | 53 | Fixes for gettext break and some pathing issues. 54 | 55 | ABlog v0.9.5 released 56 | --------------------- 57 | 58 | v0.9.5 is the that supports Python 2 and Sphinx <2. 59 | v0.10.0 on main now, will not. 60 | 61 | `Define an auto-orphan option `__, `Repair update directive `__ and `Fix sidebar and blog_baseurl misconfig during quick start `__ from `rayalan `__. 62 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["setuptools", "setuptools_scm", "wheel"] 3 | build-backend = 'setuptools.build_meta' 4 | 5 | [tool.black] 6 | line-length = 120 7 | include = '\.pyi?$' 8 | exclude = ''' 9 | ( 10 | /( 11 | \.eggs 12 | | \.git 13 | | \.mypy_cache 14 | | \.tox 15 | | \.venv 16 | | _build 17 | | buck-out 18 | | build 19 | | dist 20 | | astropy_helpers 21 | | docs 22 | | .history 23 | )/ 24 | | ah_bootstrap.py 25 | ) 26 | ''' 27 | target-version = ['py310'] 28 | 29 | [tool.ruff] 30 | # Enable Pyflakes `E` and `F` codes by default. 31 | select = ["E", "F"] 32 | ignore = ["E501", "E741"] 33 | 34 | # Allow autofix for all enabled rules (when `--fix`) is provided. 35 | fixable = ["A", "B", "C", "D", "E", "F"] 36 | 37 | exclude = [ 38 | ".eggs", 39 | ".git", 40 | ".mypy_cache", 41 | ".ruff_cache", 42 | ".tox", 43 | ".venv", 44 | "__pypackages__", 45 | "_build", 46 | "build", 47 | "dist", 48 | "node_modules", 49 | "venv", 50 | ] 51 | 52 | # Same as Black. 53 | line-length = 120 54 | target-version = "py310" 55 | 56 | # Allow unused variables when underscore-prefixed. 57 | dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$" 58 | 59 | [tool.codespell] 60 | skip = "*cache*,*egg*,*extern*,.git,.idea,.tox,*.svg,.history,*sphinx.po" 61 | ignore-words-list = "THIRDPARTY," 62 | 63 | [tool.djlint] 64 | files=["*.html"] 65 | -------------------------------------------------------------------------------- /roots/test-build/conf.py: -------------------------------------------------------------------------------- 1 | extensions = ["ablog"] 2 | 3 | # Enable Atom feed generation 4 | blog_baseurl = "https://blog.example.com/" 5 | # Include full post in feeds 6 | blog_feed_fulltext = True 7 | # Add a social media Atom feed 8 | blog_feed_templates = { 9 | # Use defaults, no templates 10 | "atom": {}, 11 | # Create content text suitable posting to micro-bogging 12 | "social": { 13 | # Format tags as hashtags and append to the content 14 | "content": "{{ title }}{% for tag in post.tags %} #{{ tag.name|trim()|replace(' ', '') }}{% endfor %}", 15 | }, 16 | } 17 | -------------------------------------------------------------------------------- /roots/test-build/foo-empty-post.rst: -------------------------------------------------------------------------------- 1 | .. post:: 2021-03-23 2 | 3 | ############## 4 | Foo Empty Post 5 | ############## 6 | -------------------------------------------------------------------------------- /roots/test-build/index.rst: -------------------------------------------------------------------------------- 1 | test-build 2 | ============ 3 | -------------------------------------------------------------------------------- /roots/test-build/post.rst: -------------------------------------------------------------------------------- 1 | .. post:: 2022-12-01 2 | :tags: Foo Tag, BarTag 3 | 4 | Foo Post Title 5 | ============== 6 | 7 | Foo post description `with link`_. 8 | 9 | Foo post content. 10 | 11 | .. _`with link`: https://example.com 12 | -------------------------------------------------------------------------------- /roots/test-canonical/canonical.rst: -------------------------------------------------------------------------------- 1 | .. post:: 2021-12-01 2 | :tags: Canonical 3 | :canonical_link: https://canonical.example.org/foo.html 4 | 5 | Canonical post 6 | ============= 7 | 8 | This post will get generated, but its [canonical link](https://datatracker.ietf.org/doc/html/rfc6596) 9 | in the header will point to ``canonical_link``. 10 | -------------------------------------------------------------------------------- /roots/test-canonical/conf.py: -------------------------------------------------------------------------------- 1 | extensions = ["ablog"] 2 | 3 | # Enable Atom feed generation 4 | blog_baseurl = "https://blog.example.com/" 5 | # Include full post in feeds 6 | blog_feed_fulltext = True 7 | # Add a social media Atom feed 8 | blog_feed_templates = { 9 | # Use defaults, no templates 10 | "atom": {}, 11 | # Create content text suitable posting to micro-bogging 12 | "social": { 13 | # Format tags as hashtags and append to the content 14 | "content": "{{ title }}{% for tag in post.tags %} #{{ tag.name|trim()|replace(' ', '') }}{% endfor %}", 15 | }, 16 | } 17 | # Sphinx creates canonical links pointing to this base URL by default 18 | html_baseurl = blog_baseurl 19 | -------------------------------------------------------------------------------- /roots/test-canonical/index.rst: -------------------------------------------------------------------------------- 1 | test-external 2 | ============= 3 | -------------------------------------------------------------------------------- /roots/test-canonical/post.rst: -------------------------------------------------------------------------------- 1 | .. post:: 2022-12-01 2 | :tags: Foo Tag, BarTag 3 | 4 | Foo Post Title 5 | ============== 6 | 7 | Foo post description `with link`_. 8 | 9 | Foo post content. 10 | 11 | .. _`with link`: https://example.com 12 | -------------------------------------------------------------------------------- /roots/test-canonical/postlist.rst: -------------------------------------------------------------------------------- 1 | postlist 2 | ======== 3 | 4 | .. postlist:: 5 | -------------------------------------------------------------------------------- /roots/test-external/conf.py: -------------------------------------------------------------------------------- 1 | extensions = ["ablog"] 2 | 3 | # Enable Atom feed generation 4 | blog_baseurl = "https://blog.example.com/" 5 | # Include full post in feeds 6 | blog_feed_fulltext = True 7 | # Add a social media Atom feed 8 | blog_feed_templates = { 9 | # Use defaults, no templates 10 | "atom": {}, 11 | # Create content text suitable posting to micro-bogging 12 | "social": { 13 | # Format tags as hashtags and append to the content 14 | "content": "{{ title }}{% for tag in post.tags %} #{{ tag.name|trim()|replace(' ', '') }}{% endfor %}", 15 | }, 16 | } 17 | -------------------------------------------------------------------------------- /roots/test-external/external.rst: -------------------------------------------------------------------------------- 1 | .. post:: 2021-12-01 2 | :tags: External 3 | :external_link: https://www.sphinx-doc.org/en/master/ 4 | 5 | External post 6 | ============= 7 | 8 | This text will be in auto-generated post previews, but links to the post will direct to ``external_link``. 9 | -------------------------------------------------------------------------------- /roots/test-external/index.rst: -------------------------------------------------------------------------------- 1 | test-external 2 | ============= 3 | -------------------------------------------------------------------------------- /roots/test-external/postlist.rst: -------------------------------------------------------------------------------- 1 | postlist 2 | ======== 3 | 4 | .. postlist:: 5 | -------------------------------------------------------------------------------- /roots/test-parallel/conf.py: -------------------------------------------------------------------------------- 1 | extensions = ["ablog"] 2 | -------------------------------------------------------------------------------- /roots/test-parallel/index.rst: -------------------------------------------------------------------------------- 1 | test-postlist 2 | =============== 3 | 4 | .. toctree:: 5 | :maxdepth: 1 6 | 7 | postlist 8 | -------------------------------------------------------------------------------- /roots/test-parallel/post1.rst: -------------------------------------------------------------------------------- 1 | .. post:: 2020-12-01 2 | 3 | post 1 4 | ======= 5 | -------------------------------------------------------------------------------- /roots/test-parallel/post2.rst: -------------------------------------------------------------------------------- 1 | .. post:: 2020-12-01 2 | 3 | post 2 4 | ======= 5 | -------------------------------------------------------------------------------- /roots/test-parallel/post3.rst: -------------------------------------------------------------------------------- 1 | .. post:: 2020-12-01 2 | 3 | post 3 4 | ======= 5 | -------------------------------------------------------------------------------- /roots/test-parallel/post4.rst: -------------------------------------------------------------------------------- 1 | .. post:: 2020-12-01 2 | 3 | post 4 4 | ======= 5 | -------------------------------------------------------------------------------- /roots/test-parallel/postlist.rst: -------------------------------------------------------------------------------- 1 | postlist 2 | ========== 3 | 4 | .. postlist:: 5 | -------------------------------------------------------------------------------- /roots/test-postlist/conf.py: -------------------------------------------------------------------------------- 1 | extensions = ["ablog"] 2 | -------------------------------------------------------------------------------- /roots/test-postlist/index.rst: -------------------------------------------------------------------------------- 1 | test-postlist 2 | =============== 3 | 4 | .. toctree:: 5 | :maxdepth: 1 6 | 7 | postlist 8 | -------------------------------------------------------------------------------- /roots/test-postlist/post.rst: -------------------------------------------------------------------------------- 1 | .. post:: 2020-12-01 2 | 3 | post 4 | ======= 5 | -------------------------------------------------------------------------------- /roots/test-postlist/postlist.rst: -------------------------------------------------------------------------------- 1 | postlist 2 | ========== 3 | 4 | .. postlist:: 5 | -------------------------------------------------------------------------------- /roots/test-templates/_templates/ablog/postcard.html: -------------------------------------------------------------------------------- 1 | custom postcard.html 2 | -------------------------------------------------------------------------------- /roots/test-templates/_themes/test_theme/ablog/postcard.html: -------------------------------------------------------------------------------- 1 | custom postcard.html from theme 2 | -------------------------------------------------------------------------------- /roots/test-templates/_themes/test_theme/theme.toml: -------------------------------------------------------------------------------- 1 | [theme] 2 | inherit = "basic" 3 | 4 | [options] 5 | ablog_inject_templates_after_theme = true 6 | -------------------------------------------------------------------------------- /roots/test-templates/conf.py: -------------------------------------------------------------------------------- 1 | extensions = ["ablog"] 2 | -------------------------------------------------------------------------------- /roots/test-templates/index.rst: -------------------------------------------------------------------------------- 1 | test-postlist 2 | =============== 3 | 4 | .. toctree:: 5 | :maxdepth: 1 6 | 7 | postlist 8 | -------------------------------------------------------------------------------- /roots/test-templates/post.rst: -------------------------------------------------------------------------------- 1 | .. post:: 2020-12-01 2 | :author: Durden 3 | 4 | post 5 | ======= 6 | -------------------------------------------------------------------------------- /roots/test-templates/postlist.rst: -------------------------------------------------------------------------------- 1 | postlist 2 | ========== 3 | 4 | .. postlist:: 5 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [metadata] 2 | name = ablog 3 | author = The SunPy Community 4 | author_email = sunpy@googlegroups.com 5 | description = A Sphinx extension that converts any documentation or personal website project into a full-fledged blog. 6 | long_description = file: README.rst 7 | long_description_content_type = text/x-rst 8 | license = MIT 9 | url = https://ablog.readthedocs.io/ 10 | edit_on_github = True 11 | github_project = sunpy/ablog 12 | 13 | [options] 14 | python_requires = >=3.10 15 | package_dir= 16 | =src 17 | packages=find: 18 | include_package_data = True 19 | setup_requires = 20 | setuptools_scm 21 | install_requires = 22 | docutils>=0.18 23 | feedgen>=0.9.0 24 | invoke>=1.6.0 25 | packaging>=19.0 26 | python-dateutil>=2.8.2 27 | sphinx>=6.2.0 28 | watchdog>=2.1.0 29 | 30 | [options.packages.find] 31 | where=src 32 | 33 | [options.extras_require] 34 | notebook = 35 | ipython>=7.30.0 36 | nbsphinx>=0.8.0 37 | markdown = 38 | myst-parser>=0.17.0 39 | docs = 40 | alabaster>=1.0.0 41 | sphinx-automodapi 42 | tests = 43 | pytest 44 | defusedxml>=0.8.0rc2 45 | 46 | [options.entry_points] 47 | console_scripts = 48 | ablog = ablog.commands:ablog_main 49 | 50 | [tool:pytest] 51 | testpaths = "tests" 52 | norecursedirs = ".tox" "build" "docs[\/]_build" "docs[\/]generated" "*.egg-info" ".history" 53 | markers = 54 | sphinx 55 | addopts = -p no:unraisableexception -p no:threadexception 56 | filterwarnings = 57 | error 58 | # Do not fail on pytest config issues (i.e. missing plugins) but do show them 59 | always::pytest.PytestConfigWarning 60 | # Sphinx and other packages raise these 61 | ignore:'imghdr' is deprecated and slated for removal in Python 3.13:DeprecationWarning 62 | # python-datetuil 63 | ignore:datetime.datetime.utcfromtimestamp:DeprecationWarning 64 | 65 | [pycodestyle] 66 | max_line_length = 120 67 | 68 | [flake8] 69 | max-line-length = 120 70 | 71 | [isort] 72 | default_section = THIRDPARTY 73 | force_grid_wrap = 0 74 | include_trailing_comma = true 75 | known_first_party = ablog 76 | length_sort = False 77 | length_sort_sections = stdlib 78 | line_length = 120 79 | multi_line_output = 3 80 | skip = .history 81 | sections = FUTURE, STDLIB, THIRDPARTY, FIRSTPARTY, LOCALFOLDER 82 | 83 | [coverage:run] 84 | omit = 85 | */ablog/__init__* 86 | */ablog/*/tests/* 87 | */ablog/*setup* 88 | */ablog/conftest.py 89 | */ablog/cython_version* 90 | */ablog/extern/* 91 | */ablog/version* 92 | ablog/__init__* 93 | ablog/*/tests/* 94 | ablog/*setup* 95 | ablog/conftest.py 96 | ablog/cython_version* 97 | ablog/extern/* 98 | ablog/version* 99 | 100 | [coverage:report] 101 | exclude_lines = 102 | # Have to re-enable the standard pragma 103 | pragma: no cover 104 | # Don't complain about packages we have installed 105 | except ImportError 106 | # Don't complain if tests don't hit assertions 107 | raise AssertionError 108 | raise NotImplementedError 109 | # Don't complain about script hooks 110 | def main\(.*\): 111 | # Ignore branches that don't pertain to this version of Python 112 | pragma: py{ignore_python_version} 113 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | from setuptools import setup # isort:skip 3 | import os 4 | from itertools import chain 5 | 6 | try: 7 | # Recommended for setuptools 61.0.0+ 8 | # (though may disappear in the future) 9 | from setuptools.config.setupcfg import read_configuration 10 | except ImportError: 11 | from setuptools.config import read_configuration 12 | 13 | ################################################################################ 14 | # Programmatically generate some extras combos. 15 | ################################################################################ 16 | extras = read_configuration("setup.cfg")["options"]["extras_require"] 17 | 18 | # Dev is everything 19 | extras["dev"] = list(chain(*extras.values())) 20 | 21 | # All is everything but tests and docs 22 | exclude_keys = ("tests", "docs", "dev") 23 | ex_extras = dict(filter(lambda i: i[0] not in exclude_keys, extras.items())) 24 | # Concatenate all the values together for 'all' 25 | extras["all"] = list(chain.from_iterable(ex_extras.values())) 26 | 27 | setup( 28 | extras_require=extras, 29 | use_scm_version={"write_to": os.path.join("src", "ablog", "_version.py")}, 30 | ) 31 | -------------------------------------------------------------------------------- /src/ablog/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | ABlog for Sphinx. 3 | """ 4 | 5 | import os 6 | from glob import glob 7 | from pathlib import PurePath 8 | 9 | from sphinx.builders.html import StandaloneHTMLBuilder 10 | from sphinx.errors import ThemeError 11 | from sphinx.jinja2glue import BuiltinTemplateLoader, SphinxFileSystemLoader 12 | from sphinx.locale import get_translation 13 | 14 | from .blog import CONFIG, Blog 15 | from .post import ( 16 | CheckFrontMatter, 17 | PostDirective, 18 | PostListDirective, 19 | UpdateDirective, 20 | UpdateNode, 21 | generate_archive_pages, 22 | generate_atom_feeds, 23 | missing_reference, 24 | process_postlist, 25 | process_posts, 26 | purge_posts, 27 | ) 28 | from .version import version as __version__ 29 | 30 | __all__ = ["setup", "__version__"] 31 | 32 | PKGDIR = os.path.abspath(os.path.dirname(__file__)) 33 | # Name used for the *.pot, *.po and *.mo files 34 | MESSAGE_CATALOG_NAME = "sphinx" 35 | _ = get_translation(MESSAGE_CATALOG_NAME) # NOQA 36 | 37 | 38 | def get_html_templates_path(): 39 | """ 40 | Return path to ABlog templates folder. 41 | """ 42 | pkgdir = os.path.abspath(os.path.dirname(__file__)) 43 | return os.path.join(pkgdir, "templates") 44 | 45 | 46 | def anchor(post): 47 | """ 48 | Return anchor string for posts that are page sections. 49 | """ 50 | if post.section: 51 | return "#" + post.section 52 | else: 53 | return "" 54 | 55 | 56 | def builder_support(builder): 57 | """ 58 | Return True when builder is supported. 59 | 60 | Supported builders output in html format, but exclude 61 | `PickleHTMLBuilder` and `JSONHTMLBuilder`, which run into issues 62 | when serializing blog objects. 63 | """ 64 | if hasattr(builder, "builder"): 65 | builder = builder.builder 66 | not_supported = {"json", "pickle"} 67 | return builder.format == "html" and builder.name not in not_supported 68 | 69 | 70 | def html_page_context(app, pagename, templatename, context, doctree): 71 | if builder_support(app): 72 | context["ablog"] = blog = Blog(app) 73 | context["anchor"] = anchor 74 | if pagename in blog and blog[pagename].canonical_link: 75 | context["pageurl"] = blog[pagename].canonical_link 76 | # following is already available for archive pages 77 | if blog.blog_baseurl and "feed_path" not in context: 78 | context["feed_path"] = blog.blog_path 79 | context["feed_title"] = blog.blog_title 80 | 81 | 82 | def config_inited(app, config): 83 | # Automatically identify any blog posts if a pattern is specified in the config 84 | if isinstance(config.blog_post_pattern, str): 85 | config.blog_post_pattern = [config.blog_post_pattern] 86 | matched_patterns = [] 87 | for pattern in config.blog_post_pattern: 88 | pattern = os.path.join(app.srcdir, pattern) 89 | # make sure that blog post paths have forward slashes even on windows 90 | matched_patterns.extend( 91 | PurePath(ii).relative_to(app.srcdir).with_suffix("").as_posix() for ii in glob(pattern, recursive=True) 92 | ) 93 | app.config.matched_blog_posts = matched_patterns 94 | 95 | # Add ablog stylesheets to static_path. 96 | static_path = os.path.abspath(os.path.join(os.path.dirname(__file__), "stylesheets")) 97 | app.config.html_static_path.append(static_path) 98 | 99 | 100 | def builder_inited(app): 101 | if not isinstance(app.builder, StandaloneHTMLBuilder) or app.config.skip_injecting_base_ablog_templates: 102 | return 103 | if not isinstance(app.builder.templates, BuiltinTemplateLoader): 104 | raise Exception( 105 | "Ablog does not know how to inject templates into with custom " 106 | "template bridges. You can use `ablog.get_html_templates_path()` to " 107 | "get the path to add in your custom template bridge and set " 108 | "`skip_injecting_base_ablog_templates = False` in your " 109 | "`conf.py` file." 110 | ) 111 | if get_html_templates_path() in app.config.templates_path: 112 | raise Exception( 113 | "Found the path from `ablog.get_html_templates_path()` in the " 114 | "`templates_path` variable from `conf.py`. Doing so interferes " 115 | "with Ablog's ability to stay compatible with Sphinx themes that " 116 | "support it out of the box. Please remove `get_html_templates_path` " 117 | "from `templates_path` in your `conf.py` to resolve this." 118 | ) 119 | theme = app.builder.theme 120 | loaders = app.builder.templates.loaders 121 | templatepathlen = app.builder.templates.templatepathlen 122 | try: 123 | # Modern Sphinx now errors instead of returning the default if there is not a value 124 | # in any of the config files. 125 | after_theme = theme.get_config("options", "ablog_inject_templates_after_theme", False) 126 | except ThemeError: 127 | after_theme = False 128 | if after_theme: 129 | # Inject *after* the user templates and the theme templates, 130 | # allowing themes to override the templates provided by this 131 | # extension while those templates still serve as a fallback. 132 | loaders.append(SphinxFileSystemLoader(get_html_templates_path())) 133 | else: 134 | # Inject *after* the user templates and *before* the theme 135 | # templates. This enables ablog to provide support for themes 136 | # that don't support it out-of-the-box, like alabaster. 137 | loaders.insert(templatepathlen, SphinxFileSystemLoader(get_html_templates_path())) 138 | 139 | 140 | def setup(app): 141 | """ 142 | Setup ABlog extension. 143 | """ 144 | app.require_sphinx("6.2") 145 | for args in CONFIG: 146 | app.add_config_value(*args[:3]) 147 | app.add_directive("post", PostDirective) 148 | app.add_directive("postlist", PostListDirective) 149 | app.connect("config-inited", config_inited) 150 | app.connect("builder-inited", builder_inited) 151 | app.connect("doctree-read", process_posts) 152 | app.connect("env-purge-doc", purge_posts) 153 | app.connect("doctree-resolved", process_postlist) 154 | app.connect("missing-reference", missing_reference) 155 | app.connect("html-collect-pages", generate_archive_pages) 156 | app.connect("html-collect-pages", generate_atom_feeds) 157 | app.connect("html-page-context", html_page_context) 158 | app.add_transform(CheckFrontMatter) 159 | app.add_directive("update", UpdateDirective) 160 | app.add_node( 161 | UpdateNode, 162 | html=(lambda s, n: s.visit_admonition(n), lambda s, n: s.depart_admonition(n)), 163 | latex=(lambda s, n: s.visit_admonition(n), lambda s, n: s.depart_admonition(n)), 164 | ) 165 | pkgdir = os.path.abspath(os.path.dirname(__file__)) 166 | locale_dir = os.path.join(pkgdir, "locales") 167 | app.add_message_catalog(MESSAGE_CATALOG_NAME, locale_dir) 168 | return { 169 | "version": __version__, 170 | "parallel_read_safe": False, 171 | "parallel_write_safe": True, 172 | } 173 | -------------------------------------------------------------------------------- /src/ablog/locales/ca/LC_MESSAGES/sphinx.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunpy/ablog/95610aad20e3e290ca82776f6132a62d8fc2fbcb/src/ablog/locales/ca/LC_MESSAGES/sphinx.mo -------------------------------------------------------------------------------- /src/ablog/locales/ca/LC_MESSAGES/sphinx.po: -------------------------------------------------------------------------------- 1 | # Catalan translations for ablog. 2 | # Copyright (C) 2021 ORGANIZATION 3 | # This file is distributed under the same license as the ablog project. 4 | # FIRST AUTHOR , 2021. 5 | # 6 | msgid "" 7 | msgstr "" 8 | "Project-Id-Version: ablog 0.10.12\n" 9 | "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" 10 | "POT-Creation-Date: 2022-11-14 16:46-0800\n" 11 | "PO-Revision-Date: 2021-09-18 18:57+0200\n" 12 | "Last-Translator: Francesc Vilardell Sallés \n" 13 | "Language: ca\n" 14 | "Language-Team: ca \n" 15 | "Plural-Forms: nplurals=2; plural=(n != 1);\n" 16 | "MIME-Version: 1.0\n" 17 | "Content-Type: text/plain; charset=utf-8\n" 18 | "Content-Transfer-Encoding: 8bit\n" 19 | "Generated-By: Babel 2.11.0\n" 20 | 21 | #: ablog/post.py:272 22 | msgid "Updated on " 23 | msgstr "Actualitzat el " 24 | 25 | #: ablog/post.py:564 ablog/templates/ablog/authors.html:3 26 | #: ablog/templates/authors.html:4 27 | msgid "Authors" 28 | msgstr "Autors" 29 | 30 | #: ablog/post.py:564 ablog/post.py:631 31 | msgid "Posts by" 32 | msgstr "Publicacions de" 33 | 34 | #: ablog/post.py:565 ablog/templates/ablog/locations.html:4 35 | #: ablog/templates/locations.html:5 36 | msgid "Locations" 37 | msgstr "Ubicacions" 38 | 39 | #: ablog/post.py:565 ablog/post.py:632 40 | msgid "Posts from" 41 | msgstr "Publicacions des de" 42 | 43 | #: ablog/post.py:566 ablog/templates/ablog/languages.html:4 44 | #: ablog/templates/languages.html:5 45 | msgid "Languages" 46 | msgstr "Idiomes" 47 | 48 | #: ablog/post.py:566 ablog/post.py:567 ablog/post.py:633 ablog/post.py:634 49 | msgid "Posts in" 50 | msgstr "Publicacions en" 51 | 52 | #: ablog/post.py:567 ablog/templates/ablog/categories.html:4 53 | #: ablog/templates/categories.html:5 54 | msgid "Categories" 55 | msgstr "Categories" 56 | 57 | #: ablog/post.py:568 58 | msgid "All posts" 59 | msgstr "Totes les publicacions" 60 | 61 | #: ablog/post.py:568 ablog/post.py:635 62 | msgid "Posted in" 63 | msgstr "Publicat al" 64 | 65 | #: ablog/post.py:569 ablog/templates/ablog/postcard2.html:117 66 | #: ablog/templates/ablog/tagcloud.html:3 ablog/templates/postcard2.html:118 67 | #: ablog/templates/tagcloud.html:4 68 | msgid "Tags" 69 | msgstr "Etiquetes" 70 | 71 | #: ablog/post.py:569 ablog/post.py:636 72 | msgid "Posts tagged" 73 | msgstr "Publicacions amb etiqueta" 74 | 75 | #: ablog/post.py:594 76 | msgid "All Posts" 77 | msgstr "Totes les publicacions" 78 | 79 | #: ablog/post.py:595 80 | msgid "All" 81 | msgstr "Totes les" 82 | 83 | #: ablog/post.py:603 84 | msgid "Drafts" 85 | msgstr "Borradors" 86 | 87 | #: ablog/templates/ablog/archives.html:4 ablog/templates/archives.html:5 88 | msgid "Archives" 89 | msgstr "Arxius" 90 | 91 | #: ablog/templates/ablog/collection.html:56 ablog/templates/collection.html:57 92 | msgid "Read more ..." 93 | msgstr "Llegir-ne més ..." 94 | 95 | #: ablog/templates/ablog/postcard2.html:8 ablog/templates/postcard2.html:9 96 | msgid "Update" 97 | msgstr "Actualització" 98 | 99 | #: ablog/templates/ablog/postcard2.html:20 ablog/templates/postcard2.html:21 100 | msgid "Author" 101 | msgstr "Autor" 102 | 103 | #: ablog/templates/ablog/postcard2.html:44 ablog/templates/postcard2.html:45 104 | msgid "Location" 105 | msgstr "Ubicació" 106 | 107 | #: ablog/templates/ablog/postcard2.html:68 ablog/templates/postcard2.html:69 108 | msgid "Language" 109 | msgstr "Idioma" 110 | 111 | #: ablog/templates/ablog/postcard2.html:92 ablog/templates/postcard2.html:93 112 | msgid "Category" 113 | msgstr "Categoria" 114 | 115 | #: ablog/templates/ablog/postcard2.html:123 ablog/templates/postcard2.html:124 116 | msgid "Tag" 117 | msgstr "Etiqueta" 118 | 119 | #: ablog/templates/ablog/postnavy.html:8 ablog/templates/postnavy.html:9 120 | msgid "Previous" 121 | msgstr "Anterior" 122 | 123 | #: ablog/templates/ablog/postnavy.html:22 ablog/templates/postnavy.html:23 124 | msgid "Next" 125 | msgstr "Següent" 126 | 127 | #: ablog/templates/ablog/recentposts.html:4 ablog/templates/recentposts.html:5 128 | msgid "Recent Posts" 129 | msgstr "Publicacions recents" 130 | -------------------------------------------------------------------------------- /src/ablog/locales/de/LC_MESSAGES/sphinx.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunpy/ablog/95610aad20e3e290ca82776f6132a62d8fc2fbcb/src/ablog/locales/de/LC_MESSAGES/sphinx.mo -------------------------------------------------------------------------------- /src/ablog/locales/de/LC_MESSAGES/sphinx.po: -------------------------------------------------------------------------------- 1 | # German translations for ablog. 2 | # Copyright (C) 2014 ORGANIZATION 3 | # This file is distributed under the same license as the ablog project. 4 | # FIRST AUTHOR , 2014. 5 | # 6 | msgid "" 7 | msgstr "" 8 | "Project-Id-Version: ablog 0.1\n" 9 | "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" 10 | "POT-Creation-Date: 2022-11-14 16:46-0800\n" 11 | "PO-Revision-Date: 2014-07-25 20:46+0300\n" 12 | "Last-Translator: Luc Saffre \n" 13 | "Language: de\n" 14 | "Language-Team: de \n" 15 | "Plural-Forms: nplurals=2; plural=(n != 1);\n" 16 | "MIME-Version: 1.0\n" 17 | "Content-Type: text/plain; charset=utf-8\n" 18 | "Content-Transfer-Encoding: 8bit\n" 19 | "Generated-By: Babel 2.11.0\n" 20 | 21 | #: ablog/post.py:272 22 | #, fuzzy 23 | msgid "Updated on " 24 | msgstr "Aktualisiert am" 25 | 26 | #: ablog/post.py:564 ablog/templates/ablog/authors.html:3 27 | #: ablog/templates/authors.html:4 28 | msgid "Authors" 29 | msgstr "Autoren" 30 | 31 | #: ablog/post.py:564 ablog/post.py:631 32 | msgid "Posts by" 33 | msgstr "Einträge von" 34 | 35 | #: ablog/post.py:565 ablog/templates/ablog/locations.html:4 36 | #: ablog/templates/locations.html:5 37 | msgid "Locations" 38 | msgstr "Orte" 39 | 40 | #: ablog/post.py:565 ablog/post.py:632 41 | msgid "Posts from" 42 | msgstr "Einträge aus" 43 | 44 | #: ablog/post.py:566 ablog/templates/ablog/languages.html:4 45 | #: ablog/templates/languages.html:5 46 | msgid "Languages" 47 | msgstr "Sprachen" 48 | 49 | #: ablog/post.py:566 ablog/post.py:567 ablog/post.py:633 ablog/post.py:634 50 | msgid "Posts in" 51 | msgstr "Einträge in" 52 | 53 | #: ablog/post.py:567 ablog/templates/ablog/categories.html:4 54 | #: ablog/templates/categories.html:5 55 | msgid "Categories" 56 | msgstr "Kategorien" 57 | 58 | #: ablog/post.py:568 59 | msgid "All posts" 60 | msgstr "Alle Einträge" 61 | 62 | #: ablog/post.py:568 ablog/post.py:635 63 | msgid "Posted in" 64 | msgstr "Einträge in" 65 | 66 | #: ablog/post.py:569 ablog/templates/ablog/postcard2.html:117 67 | #: ablog/templates/ablog/tagcloud.html:3 ablog/templates/postcard2.html:118 68 | #: ablog/templates/tagcloud.html:4 69 | msgid "Tags" 70 | msgstr "Schlagworte" 71 | 72 | #: ablog/post.py:569 ablog/post.py:636 73 | msgid "Posts tagged" 74 | msgstr "Einträge mit Schlagwort" 75 | 76 | #: ablog/post.py:594 77 | #, fuzzy 78 | msgid "All Posts" 79 | msgstr "Alle Einträge" 80 | 81 | #: ablog/post.py:595 82 | msgid "All" 83 | msgstr "" 84 | 85 | #: ablog/post.py:603 86 | msgid "Drafts" 87 | msgstr "Entwurf" 88 | 89 | #: ablog/templates/ablog/archives.html:4 ablog/templates/archives.html:5 90 | msgid "Archives" 91 | msgstr "Archive" 92 | 93 | #: ablog/templates/ablog/collection.html:56 ablog/templates/collection.html:57 94 | msgid "Read more ..." 95 | msgstr "Weiter..." 96 | 97 | #: ablog/templates/ablog/postcard2.html:8 ablog/templates/postcard2.html:9 98 | msgid "Update" 99 | msgstr "Aktualisierung" 100 | 101 | #: ablog/templates/ablog/postcard2.html:20 ablog/templates/postcard2.html:21 102 | msgid "Author" 103 | msgstr "Autor" 104 | 105 | #: ablog/templates/ablog/postcard2.html:44 ablog/templates/postcard2.html:45 106 | msgid "Location" 107 | msgstr "Ort" 108 | 109 | #: ablog/templates/ablog/postcard2.html:68 ablog/templates/postcard2.html:69 110 | msgid "Language" 111 | msgstr "Sprache" 112 | 113 | #: ablog/templates/ablog/postcard2.html:92 ablog/templates/postcard2.html:93 114 | msgid "Category" 115 | msgstr "Kategorie" 116 | 117 | #: ablog/templates/ablog/postcard2.html:123 ablog/templates/postcard2.html:124 118 | msgid "Tag" 119 | msgstr "Schlagwort" 120 | 121 | #: ablog/templates/ablog/postnavy.html:8 ablog/templates/postnavy.html:9 122 | msgid "Previous" 123 | msgstr "Vorige" 124 | 125 | #: ablog/templates/ablog/postnavy.html:22 ablog/templates/postnavy.html:23 126 | msgid "Next" 127 | msgstr "Nächste" 128 | 129 | #: ablog/templates/ablog/recentposts.html:4 ablog/templates/recentposts.html:5 130 | msgid "Recent Posts" 131 | msgstr "Neue Einträge" 132 | -------------------------------------------------------------------------------- /src/ablog/locales/es/LC_MESSAGES/sphinx.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunpy/ablog/95610aad20e3e290ca82776f6132a62d8fc2fbcb/src/ablog/locales/es/LC_MESSAGES/sphinx.mo -------------------------------------------------------------------------------- /src/ablog/locales/es/LC_MESSAGES/sphinx.po: -------------------------------------------------------------------------------- 1 | # Spanish translations for ablog. 2 | # Copyright (C) 2014 ORGANIZATION 3 | # This file is distributed under the same license as the ablog project. 4 | # FIRST AUTHOR , 2014. 5 | # 6 | msgid "" 7 | msgstr "" 8 | "Project-Id-Version: ablog 0.2.3\n" 9 | "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" 10 | "POT-Creation-Date: 2022-11-14 16:46-0800\n" 11 | "PO-Revision-Date: 2016-04-21 14:26+0200\n" 12 | "Last-Translator: José Carlos García \n" 13 | "Language: es\n" 14 | "Language-Team: es \n" 15 | "Plural-Forms: nplurals=2; plural=(n != 1);\n" 16 | "MIME-Version: 1.0\n" 17 | "Content-Type: text/plain; charset=utf-8\n" 18 | "Content-Transfer-Encoding: 8bit\n" 19 | "Generated-By: Babel 2.11.0\n" 20 | 21 | #: ablog/post.py:272 22 | #, fuzzy 23 | msgid "Updated on " 24 | msgstr "Actualizado el" 25 | 26 | #: ablog/post.py:564 ablog/templates/ablog/authors.html:3 27 | #: ablog/templates/authors.html:4 28 | msgid "Authors" 29 | msgstr "Autores" 30 | 31 | #: ablog/post.py:564 ablog/post.py:631 32 | msgid "Posts by" 33 | msgstr "Entradas por" 34 | 35 | #: ablog/post.py:565 ablog/templates/ablog/locations.html:4 36 | #: ablog/templates/locations.html:5 37 | msgid "Locations" 38 | msgstr "Lugares" 39 | 40 | #: ablog/post.py:565 ablog/post.py:632 41 | msgid "Posts from" 42 | msgstr "Entradas desde" 43 | 44 | #: ablog/post.py:566 ablog/templates/ablog/languages.html:4 45 | #: ablog/templates/languages.html:5 46 | msgid "Languages" 47 | msgstr "Idiomas" 48 | 49 | #: ablog/post.py:566 ablog/post.py:567 ablog/post.py:633 ablog/post.py:634 50 | msgid "Posts in" 51 | msgstr "Entradas en" 52 | 53 | #: ablog/post.py:567 ablog/templates/ablog/categories.html:4 54 | #: ablog/templates/categories.html:5 55 | msgid "Categories" 56 | msgstr "Categorías" 57 | 58 | #: ablog/post.py:568 59 | msgid "All posts" 60 | msgstr "Todas las entradas" 61 | 62 | #: ablog/post.py:568 ablog/post.py:635 63 | msgid "Posted in" 64 | msgstr "Publicado en" 65 | 66 | #: ablog/post.py:569 ablog/templates/ablog/postcard2.html:117 67 | #: ablog/templates/ablog/tagcloud.html:3 ablog/templates/postcard2.html:118 68 | #: ablog/templates/tagcloud.html:4 69 | msgid "Tags" 70 | msgstr "Etiquetas" 71 | 72 | #: ablog/post.py:569 ablog/post.py:636 73 | msgid "Posts tagged" 74 | msgstr "Entradas etiquetadas" 75 | 76 | #: ablog/post.py:594 77 | #, fuzzy 78 | msgid "All Posts" 79 | msgstr "Todas las entradas" 80 | 81 | #: ablog/post.py:595 82 | msgid "All" 83 | msgstr "" 84 | 85 | #: ablog/post.py:603 86 | msgid "Drafts" 87 | msgstr "Borradores" 88 | 89 | #: ablog/templates/ablog/archives.html:4 ablog/templates/archives.html:5 90 | msgid "Archives" 91 | msgstr "Archivos" 92 | 93 | #: ablog/templates/ablog/collection.html:56 ablog/templates/collection.html:57 94 | msgid "Read more ..." 95 | msgstr "Leer más ..." 96 | 97 | #: ablog/templates/ablog/postcard2.html:8 ablog/templates/postcard2.html:9 98 | msgid "Update" 99 | msgstr "Actualizado" 100 | 101 | #: ablog/templates/ablog/postcard2.html:20 ablog/templates/postcard2.html:21 102 | msgid "Author" 103 | msgstr "Autor" 104 | 105 | #: ablog/templates/ablog/postcard2.html:44 ablog/templates/postcard2.html:45 106 | msgid "Location" 107 | msgstr "Lugar" 108 | 109 | #: ablog/templates/ablog/postcard2.html:68 ablog/templates/postcard2.html:69 110 | msgid "Language" 111 | msgstr "Idioma" 112 | 113 | #: ablog/templates/ablog/postcard2.html:92 ablog/templates/postcard2.html:93 114 | msgid "Category" 115 | msgstr "Categoría" 116 | 117 | #: ablog/templates/ablog/postcard2.html:123 ablog/templates/postcard2.html:124 118 | msgid "Tag" 119 | msgstr "Etiqueta" 120 | 121 | #: ablog/templates/ablog/postnavy.html:8 ablog/templates/postnavy.html:9 122 | msgid "Previous" 123 | msgstr "Anterior" 124 | 125 | #: ablog/templates/ablog/postnavy.html:22 ablog/templates/postnavy.html:23 126 | msgid "Next" 127 | msgstr "Siguiente" 128 | 129 | #: ablog/templates/ablog/recentposts.html:4 ablog/templates/recentposts.html:5 130 | msgid "Recent Posts" 131 | msgstr "Entradas recientes" 132 | -------------------------------------------------------------------------------- /src/ablog/locales/et/LC_MESSAGES/sphinx.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunpy/ablog/95610aad20e3e290ca82776f6132a62d8fc2fbcb/src/ablog/locales/et/LC_MESSAGES/sphinx.mo -------------------------------------------------------------------------------- /src/ablog/locales/et/LC_MESSAGES/sphinx.po: -------------------------------------------------------------------------------- 1 | # Estonian translations for ablog. 2 | # Copyright (C) 2014 ORGANIZATION 3 | # This file is distributed under the same license as the ablog project. 4 | # FIRST AUTHOR , 2014. 5 | # 6 | msgid "" 7 | msgstr "" 8 | "Project-Id-Version: ablog 0.1\n" 9 | "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" 10 | "POT-Creation-Date: 2022-11-14 16:46-0800\n" 11 | "PO-Revision-Date: 2014-07-31 09:13+0300\n" 12 | "Last-Translator: Luc Saffre \n" 13 | "Language: et\n" 14 | "Language-Team: et \n" 15 | "Plural-Forms: nplurals=2; plural=(n != 1);\n" 16 | "MIME-Version: 1.0\n" 17 | "Content-Type: text/plain; charset=utf-8\n" 18 | "Content-Transfer-Encoding: 8bit\n" 19 | "Generated-By: Babel 2.11.0\n" 20 | 21 | #: ablog/post.py:272 22 | #, fuzzy 23 | msgid "Updated on " 24 | msgstr "Uuendus" 25 | 26 | #: ablog/post.py:564 ablog/templates/ablog/authors.html:3 27 | #: ablog/templates/authors.html:4 28 | msgid "Authors" 29 | msgstr "Autorid" 30 | 31 | #: ablog/post.py:564 ablog/post.py:631 32 | msgid "Posts by" 33 | msgstr "Postitused autorilt" 34 | 35 | #: ablog/post.py:565 ablog/templates/ablog/locations.html:4 36 | #: ablog/templates/locations.html:5 37 | msgid "Locations" 38 | msgstr "Kohad" 39 | 40 | #: ablog/post.py:565 ablog/post.py:632 41 | msgid "Posts from" 42 | msgstr "" 43 | 44 | #: ablog/post.py:566 ablog/templates/ablog/languages.html:4 45 | #: ablog/templates/languages.html:5 46 | msgid "Languages" 47 | msgstr "Keeltes" 48 | 49 | #: ablog/post.py:566 ablog/post.py:567 ablog/post.py:633 ablog/post.py:634 50 | msgid "Posts in" 51 | msgstr "" 52 | 53 | #: ablog/post.py:567 ablog/templates/ablog/categories.html:4 54 | #: ablog/templates/categories.html:5 55 | msgid "Categories" 56 | msgstr "Kategooriad" 57 | 58 | #: ablog/post.py:568 59 | msgid "All posts" 60 | msgstr "Kõik postitused" 61 | 62 | #: ablog/post.py:568 ablog/post.py:635 63 | msgid "Posted in" 64 | msgstr "Postitused kategoorias" 65 | 66 | #: ablog/post.py:569 ablog/templates/ablog/postcard2.html:117 67 | #: ablog/templates/ablog/tagcloud.html:3 ablog/templates/postcard2.html:118 68 | #: ablog/templates/tagcloud.html:4 69 | msgid "Tags" 70 | msgstr "Märksõnad" 71 | 72 | #: ablog/post.py:569 ablog/post.py:636 73 | msgid "Posts tagged" 74 | msgstr "Postitused märksõnaga" 75 | 76 | #: ablog/post.py:594 77 | #, fuzzy 78 | msgid "All Posts" 79 | msgstr "Kõik postitused" 80 | 81 | #: ablog/post.py:595 82 | msgid "All" 83 | msgstr "" 84 | 85 | #: ablog/post.py:603 86 | msgid "Drafts" 87 | msgstr "Eelnõu" 88 | 89 | #: ablog/templates/ablog/archives.html:4 ablog/templates/archives.html:5 90 | msgid "Archives" 91 | msgstr "Arhiiv" 92 | 93 | #: ablog/templates/ablog/collection.html:56 ablog/templates/collection.html:57 94 | msgid "Read more ..." 95 | msgstr "Edasi..." 96 | 97 | #: ablog/templates/ablog/postcard2.html:8 ablog/templates/postcard2.html:9 98 | msgid "Update" 99 | msgstr "Ajakohastama" 100 | 101 | #: ablog/templates/ablog/postcard2.html:20 ablog/templates/postcard2.html:21 102 | msgid "Author" 103 | msgstr "Autor" 104 | 105 | #: ablog/templates/ablog/postcard2.html:44 ablog/templates/postcard2.html:45 106 | msgid "Location" 107 | msgstr "Koht" 108 | 109 | #: ablog/templates/ablog/postcard2.html:68 ablog/templates/postcard2.html:69 110 | msgid "Language" 111 | msgstr "Keel" 112 | 113 | #: ablog/templates/ablog/postcard2.html:92 ablog/templates/postcard2.html:93 114 | msgid "Category" 115 | msgstr "Kategooria" 116 | 117 | #: ablog/templates/ablog/postcard2.html:123 ablog/templates/postcard2.html:124 118 | msgid "Tag" 119 | msgstr "Märksõna" 120 | 121 | #: ablog/templates/ablog/postnavy.html:8 ablog/templates/postnavy.html:9 122 | msgid "Previous" 123 | msgstr "Eelmine" 124 | 125 | #: ablog/templates/ablog/postnavy.html:22 ablog/templates/postnavy.html:23 126 | msgid "Next" 127 | msgstr "Järgmine" 128 | 129 | #: ablog/templates/ablog/recentposts.html:4 ablog/templates/recentposts.html:5 130 | msgid "Recent Posts" 131 | msgstr "Viimased postitused" 132 | -------------------------------------------------------------------------------- /src/ablog/locales/fr/LC_MESSAGES/sphinx.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunpy/ablog/95610aad20e3e290ca82776f6132a62d8fc2fbcb/src/ablog/locales/fr/LC_MESSAGES/sphinx.mo -------------------------------------------------------------------------------- /src/ablog/locales/fr/LC_MESSAGES/sphinx.po: -------------------------------------------------------------------------------- 1 | # French translations for ablog. 2 | # Copyright (C) 2020 ORGANIZATION 3 | # This file is distributed under the same license as the ablog project. 4 | # FIRST AUTHOR , 2020. 5 | # 6 | msgid "" 7 | msgstr "" 8 | "Project-Id-Version: ablog 0.10.5\n" 9 | "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" 10 | "POT-Creation-Date: 2022-11-14 16:46-0800\n" 11 | "PO-Revision-Date: 2020-05-22 20:04+0200\n" 12 | "Last-Translator: \n" 13 | "Language: fr\n" 14 | "Language-Team: fr \n" 15 | "Plural-Forms: nplurals=2; plural=(n > 1);\n" 16 | "MIME-Version: 1.0\n" 17 | "Content-Type: text/plain; charset=utf-8\n" 18 | "Content-Transfer-Encoding: 8bit\n" 19 | "Generated-By: Babel 2.11.0\n" 20 | 21 | #: ablog/post.py:272 22 | #, fuzzy 23 | msgid "Updated on " 24 | msgstr "Mis à jour" 25 | 26 | #: ablog/post.py:564 ablog/templates/ablog/authors.html:3 27 | #: ablog/templates/authors.html:4 28 | msgid "Authors" 29 | msgstr "Auteurs" 30 | 31 | #: ablog/post.py:564 ablog/post.py:631 32 | msgid "Posts by" 33 | msgstr "Billets par" 34 | 35 | #: ablog/post.py:565 ablog/templates/ablog/locations.html:4 36 | #: ablog/templates/locations.html:5 37 | msgid "Locations" 38 | msgstr "Lieux" 39 | 40 | #: ablog/post.py:565 ablog/post.py:632 41 | msgid "Posts from" 42 | msgstr "Billets depuis" 43 | 44 | #: ablog/post.py:566 ablog/templates/ablog/languages.html:4 45 | #: ablog/templates/languages.html:5 46 | msgid "Languages" 47 | msgstr "Langues" 48 | 49 | #: ablog/post.py:566 ablog/post.py:567 ablog/post.py:633 ablog/post.py:634 50 | msgid "Posts in" 51 | msgstr "Billets dans" 52 | 53 | #: ablog/post.py:567 ablog/templates/ablog/categories.html:4 54 | #: ablog/templates/categories.html:5 55 | msgid "Categories" 56 | msgstr "Catégories" 57 | 58 | #: ablog/post.py:568 59 | msgid "All posts" 60 | msgstr "Tous les billets" 61 | 62 | #: ablog/post.py:568 ablog/post.py:635 63 | msgid "Posted in" 64 | msgstr "Publié dans" 65 | 66 | #: ablog/post.py:569 ablog/templates/ablog/postcard2.html:117 67 | #: ablog/templates/ablog/tagcloud.html:3 ablog/templates/postcard2.html:118 68 | #: ablog/templates/tagcloud.html:4 69 | msgid "Tags" 70 | msgstr "Tags" 71 | 72 | #: ablog/post.py:569 ablog/post.py:636 73 | msgid "Posts tagged" 74 | msgstr "Billets tagués" 75 | 76 | #: ablog/post.py:594 77 | msgid "All Posts" 78 | msgstr "Tous les billets" 79 | 80 | #: ablog/post.py:595 81 | msgid "All" 82 | msgstr "Tous les billets" 83 | 84 | #: ablog/post.py:603 85 | msgid "Drafts" 86 | msgstr "Brouillons" 87 | 88 | #: ablog/templates/ablog/archives.html:4 ablog/templates/archives.html:5 89 | msgid "Archives" 90 | msgstr "Archives" 91 | 92 | #: ablog/templates/ablog/collection.html:56 ablog/templates/collection.html:57 93 | msgid "Read more ..." 94 | msgstr "Lire plus…" 95 | 96 | #: ablog/templates/ablog/postcard2.html:8 ablog/templates/postcard2.html:9 97 | msgid "Update" 98 | msgstr "Mis à jour" 99 | 100 | #: ablog/templates/ablog/postcard2.html:20 ablog/templates/postcard2.html:21 101 | msgid "Author" 102 | msgstr "Auteur" 103 | 104 | #: ablog/templates/ablog/postcard2.html:44 ablog/templates/postcard2.html:45 105 | msgid "Location" 106 | msgstr "Lieu" 107 | 108 | #: ablog/templates/ablog/postcard2.html:68 ablog/templates/postcard2.html:69 109 | msgid "Language" 110 | msgstr "Langue" 111 | 112 | #: ablog/templates/ablog/postcard2.html:92 ablog/templates/postcard2.html:93 113 | msgid "Category" 114 | msgstr "Catégorie" 115 | 116 | #: ablog/templates/ablog/postcard2.html:123 ablog/templates/postcard2.html:124 117 | msgid "Tag" 118 | msgstr "Tag" 119 | 120 | #: ablog/templates/ablog/postnavy.html:8 ablog/templates/postnavy.html:9 121 | msgid "Previous" 122 | msgstr "Précédent" 123 | 124 | #: ablog/templates/ablog/postnavy.html:22 ablog/templates/postnavy.html:23 125 | msgid "Next" 126 | msgstr "Suivant" 127 | 128 | #: ablog/templates/ablog/recentposts.html:4 ablog/templates/recentposts.html:5 129 | msgid "Recent Posts" 130 | msgstr "Billets récents" 131 | -------------------------------------------------------------------------------- /src/ablog/locales/it/LC_MESSAGES/sphinx.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunpy/ablog/95610aad20e3e290ca82776f6132a62d8fc2fbcb/src/ablog/locales/it/LC_MESSAGES/sphinx.mo -------------------------------------------------------------------------------- /src/ablog/locales/it/LC_MESSAGES/sphinx.po: -------------------------------------------------------------------------------- 1 | # Translations template for ablog. 2 | # Copyright (C) 2022 ORGANIZATION 3 | # This file is distributed under the same license as the ablog project. 4 | # FIRST AUTHOR , 2022. 5 | # 6 | msgid "" 7 | msgstr "" 8 | "Project-Id-Version: ablog 0.10.30.dev19+gb9b1a31\n" 9 | "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" 10 | "POT-Creation-Date: 2022-11-14 16:46-0800\n" 11 | "PO-Revision-Date: 2023-09-15 11:32+0200\n" 12 | "Last-Translator: Stefano David \n" 13 | "Language-Team: \n" 14 | "Language: it\n" 15 | "MIME-Version: 1.0\n" 16 | "Content-Type: text/plain; charset=UTF-8\n" 17 | "Content-Transfer-Encoding: 8bit\n" 18 | "Plural-Forms: nplurals=2; plural=(n != 1);\n" 19 | "Generated-By: Babel 2.11.0\n" 20 | "X-Generator: Poedit 3.3.2\n" 21 | 22 | #: ablog/post.py:272 23 | msgid "Updated on " 24 | msgstr "Aggiornato il " 25 | 26 | #: ablog/post.py:564 ablog/templates/ablog/authors.html:3 27 | #: ablog/templates/authors.html:4 28 | msgid "Authors" 29 | msgstr "Autori" 30 | 31 | #: ablog/post.py:564 ablog/post.py:631 32 | msgid "Posts by" 33 | msgstr "Articoli di" 34 | 35 | #: ablog/post.py:565 ablog/templates/ablog/locations.html:4 36 | #: ablog/templates/locations.html:5 37 | msgid "Locations" 38 | msgstr "Località" 39 | 40 | #: ablog/post.py:565 ablog/post.py:632 41 | msgid "Posts from" 42 | msgstr "Articolo da" 43 | 44 | #: ablog/post.py:566 ablog/templates/ablog/languages.html:4 45 | #: ablog/templates/languages.html:5 46 | msgid "Languages" 47 | msgstr "Lingue" 48 | 49 | #: ablog/post.py:566 ablog/post.py:567 ablog/post.py:633 ablog/post.py:634 50 | msgid "Posts in" 51 | msgstr "Articoli in" 52 | 53 | #: ablog/post.py:567 ablog/templates/ablog/categories.html:4 54 | #: ablog/templates/categories.html:5 55 | msgid "Categories" 56 | msgstr "Categorie" 57 | 58 | #: ablog/post.py:568 59 | msgid "All posts" 60 | msgstr "Tutti gli articoli" 61 | 62 | #: ablog/post.py:568 ablog/post.py:635 63 | msgid "Posted in" 64 | msgstr "Pubblicato in" 65 | 66 | #: ablog/post.py:569 ablog/templates/ablog/postcard2.html:117 67 | #: ablog/templates/ablog/tagcloud.html:3 ablog/templates/postcard2.html:118 68 | #: ablog/templates/tagcloud.html:4 69 | msgid "Tags" 70 | msgstr "Tag" 71 | 72 | #: ablog/post.py:569 ablog/post.py:636 73 | msgid "Posts tagged" 74 | msgstr "Articoli con tag" 75 | 76 | #: ablog/post.py:594 77 | msgid "All Posts" 78 | msgstr "Tutti gli articoli" 79 | 80 | #: ablog/post.py:595 81 | msgid "All" 82 | msgstr "Tutti" 83 | 84 | #: ablog/post.py:603 85 | msgid "Drafts" 86 | msgstr "Bozze" 87 | 88 | #: ablog/templates/ablog/archives.html:4 ablog/templates/archives.html:5 89 | msgid "Archives" 90 | msgstr "Archivi" 91 | 92 | #: ablog/templates/ablog/collection.html:56 ablog/templates/collection.html:57 93 | msgid "Read more ..." 94 | msgstr "Leggi di più..." 95 | 96 | #: ablog/templates/ablog/postcard2.html:8 ablog/templates/postcard2.html:9 97 | msgid "Update" 98 | msgstr "Aggiornamento" 99 | 100 | #: ablog/templates/ablog/postcard2.html:20 ablog/templates/postcard2.html:21 101 | msgid "Author" 102 | msgstr "Autore" 103 | 104 | #: ablog/templates/ablog/postcard2.html:44 ablog/templates/postcard2.html:45 105 | msgid "Location" 106 | msgstr "Località" 107 | 108 | #: ablog/templates/ablog/postcard2.html:68 ablog/templates/postcard2.html:69 109 | msgid "Language" 110 | msgstr "Lingua" 111 | 112 | #: ablog/templates/ablog/postcard2.html:92 ablog/templates/postcard2.html:93 113 | msgid "Category" 114 | msgstr "Categoria" 115 | 116 | #: ablog/templates/ablog/postcard2.html:123 ablog/templates/postcard2.html:124 117 | msgid "Tag" 118 | msgstr "Tag" 119 | 120 | #: ablog/templates/ablog/postnavy.html:8 ablog/templates/postnavy.html:9 121 | msgid "Previous" 122 | msgstr "Precedente" 123 | 124 | #: ablog/templates/ablog/postnavy.html:22 ablog/templates/postnavy.html:23 125 | msgid "Next" 126 | msgstr "Successivo" 127 | 128 | #: ablog/templates/ablog/recentposts.html:4 ablog/templates/recentposts.html:5 129 | msgid "Recent Posts" 130 | msgstr "Articoli recenti" 131 | -------------------------------------------------------------------------------- /src/ablog/locales/pt/LC_MESSAGES/sphinx.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunpy/ablog/95610aad20e3e290ca82776f6132a62d8fc2fbcb/src/ablog/locales/pt/LC_MESSAGES/sphinx.mo -------------------------------------------------------------------------------- /src/ablog/locales/pt/LC_MESSAGES/sphinx.po: -------------------------------------------------------------------------------- 1 | # Portuguese translations for ablog. 2 | # Copyright (C) 2022 ORGANIZATION 3 | # This file is distributed under the same license as the ablog project. 4 | # Luís Henriques , 2022. 5 | # 6 | msgid "" 7 | msgstr "" 8 | "Project-Id-Version: ablog 0.10.30.dev7+g9a43710e3a7d\n" 9 | "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" 10 | "POT-Creation-Date: 2022-11-14 16:46-0800\n" 11 | "PO-Revision-Date: 2022-10-02 20:41+0100\n" 12 | "Last-Translator: Luís Henriques \n" 13 | "Language: pt\n" 14 | "Language-Team: pt \n" 15 | "Plural-Forms: nplurals=2; plural=(n != 1);\n" 16 | "MIME-Version: 1.0\n" 17 | "Content-Type: text/plain; charset=utf-8\n" 18 | "Content-Transfer-Encoding: 8bit\n" 19 | "Generated-By: Babel 2.11.0\n" 20 | 21 | #: ablog/post.py:272 22 | msgid "Updated on " 23 | msgstr "Actualizado em " 24 | 25 | #: ablog/post.py:564 ablog/templates/ablog/authors.html:3 26 | #: ablog/templates/authors.html:4 27 | msgid "Authors" 28 | msgstr "Autores" 29 | 30 | #: ablog/post.py:564 ablog/post.py:631 31 | msgid "Posts by" 32 | msgstr "Entradas por" 33 | 34 | #: ablog/post.py:565 ablog/templates/ablog/locations.html:4 35 | #: ablog/templates/locations.html:5 36 | msgid "Locations" 37 | msgstr "Localizações" 38 | 39 | #: ablog/post.py:565 ablog/post.py:632 40 | msgid "Posts from" 41 | msgstr "Entradas de" 42 | 43 | #: ablog/post.py:566 ablog/templates/ablog/languages.html:4 44 | #: ablog/templates/languages.html:5 45 | msgid "Languages" 46 | msgstr "Linguagens" 47 | 48 | #: ablog/post.py:566 ablog/post.py:567 ablog/post.py:633 ablog/post.py:634 49 | msgid "Posts in" 50 | msgstr "Entradas em" 51 | 52 | #: ablog/post.py:567 ablog/templates/ablog/categories.html:4 53 | #: ablog/templates/categories.html:5 54 | msgid "Categories" 55 | msgstr "Categorias" 56 | 57 | #: ablog/post.py:568 58 | msgid "All posts" 59 | msgstr "Todas as entradas" 60 | 61 | #: ablog/post.py:568 ablog/post.py:635 62 | msgid "Posted in" 63 | msgstr "Publicado em" 64 | 65 | #: ablog/post.py:569 ablog/templates/ablog/postcard2.html:117 66 | #: ablog/templates/ablog/tagcloud.html:3 ablog/templates/postcard2.html:118 67 | #: ablog/templates/tagcloud.html:4 68 | msgid "Tags" 69 | msgstr "Etiquetas" 70 | 71 | #: ablog/post.py:569 ablog/post.py:636 72 | msgid "Posts tagged" 73 | msgstr "Entradas com etiqueta" 74 | 75 | #: ablog/post.py:594 76 | msgid "All Posts" 77 | msgstr "Todas as Entradas" 78 | 79 | #: ablog/post.py:595 80 | msgid "All" 81 | msgstr "Todas" 82 | 83 | #: ablog/post.py:603 84 | msgid "Drafts" 85 | msgstr "Rascunhos" 86 | 87 | #: ablog/templates/ablog/archives.html:4 ablog/templates/archives.html:5 88 | msgid "Archives" 89 | msgstr "Arquivos" 90 | 91 | #: ablog/templates/ablog/collection.html:56 ablog/templates/collection.html:57 92 | msgid "Read more ..." 93 | msgstr "Ler mais ..." 94 | 95 | #: ablog/templates/ablog/postcard2.html:8 ablog/templates/postcard2.html:9 96 | msgid "Update" 97 | msgstr "Actualizado" 98 | 99 | #: ablog/templates/ablog/postcard2.html:20 ablog/templates/postcard2.html:21 100 | msgid "Author" 101 | msgstr "Autor" 102 | 103 | #: ablog/templates/ablog/postcard2.html:44 ablog/templates/postcard2.html:45 104 | msgid "Location" 105 | msgstr "Localização" 106 | 107 | #: ablog/templates/ablog/postcard2.html:68 ablog/templates/postcard2.html:69 108 | msgid "Language" 109 | msgstr "Idioma" 110 | 111 | #: ablog/templates/ablog/postcard2.html:92 ablog/templates/postcard2.html:93 112 | msgid "Category" 113 | msgstr "Categoria" 114 | 115 | #: ablog/templates/ablog/postcard2.html:123 ablog/templates/postcard2.html:124 116 | msgid "Tag" 117 | msgstr "Etiqueta" 118 | 119 | #: ablog/templates/ablog/postnavy.html:8 ablog/templates/postnavy.html:9 120 | msgid "Previous" 121 | msgstr "Anterior" 122 | 123 | #: ablog/templates/ablog/postnavy.html:22 ablog/templates/postnavy.html:23 124 | msgid "Next" 125 | msgstr "Próximo" 126 | 127 | #: ablog/templates/ablog/recentposts.html:4 ablog/templates/recentposts.html:5 128 | msgid "Recent Posts" 129 | msgstr "Entradas Recentes" 130 | -------------------------------------------------------------------------------- /src/ablog/locales/ru/LC_MESSAGES/sphinx.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunpy/ablog/95610aad20e3e290ca82776f6132a62d8fc2fbcb/src/ablog/locales/ru/LC_MESSAGES/sphinx.mo -------------------------------------------------------------------------------- /src/ablog/locales/ru/LC_MESSAGES/sphinx.po: -------------------------------------------------------------------------------- 1 | # Russian translations for ablog. 2 | # Copyright (C) 2014 ORGANIZATION 3 | # This file is distributed under the same license as the ablog project. 4 | # uralbash , 2014. 5 | # 6 | msgid "" 7 | msgstr "" 8 | "Project-Id-Version: ablog 0.2.3\n" 9 | "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" 10 | "POT-Creation-Date: 2022-11-14 16:46-0800\n" 11 | "PO-Revision-Date: 2015-04-14 17:10+0500\n" 12 | "Last-Translator: uralbash \n" 13 | "Language: ru\n" 14 | "Language-Team: Russian\n" 15 | "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && " 16 | "n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" 17 | "MIME-Version: 1.0\n" 18 | "Content-Type: text/plain; charset=utf-8\n" 19 | "Content-Transfer-Encoding: 8bit\n" 20 | "Generated-By: Babel 2.11.0\n" 21 | 22 | #: ablog/post.py:272 23 | #, fuzzy 24 | msgid "Updated on " 25 | msgstr "Обновлено" 26 | 27 | #: ablog/post.py:564 ablog/templates/ablog/authors.html:3 28 | #: ablog/templates/authors.html:4 29 | msgid "Authors" 30 | msgstr "Авторы" 31 | 32 | #: ablog/post.py:564 ablog/post.py:631 33 | msgid "Posts by" 34 | msgstr "Опубликовано" 35 | 36 | #: ablog/post.py:565 ablog/templates/ablog/locations.html:4 37 | #: ablog/templates/locations.html:5 38 | msgid "Locations" 39 | msgstr "" 40 | 41 | #: ablog/post.py:565 ablog/post.py:632 42 | msgid "Posts from" 43 | msgstr "Сообщения из" 44 | 45 | #: ablog/post.py:566 ablog/templates/ablog/languages.html:4 46 | #: ablog/templates/languages.html:5 47 | msgid "Languages" 48 | msgstr "Языки" 49 | 50 | #: ablog/post.py:566 ablog/post.py:567 ablog/post.py:633 ablog/post.py:634 51 | msgid "Posts in" 52 | msgstr "Сообщений в" 53 | 54 | #: ablog/post.py:567 ablog/templates/ablog/categories.html:4 55 | #: ablog/templates/categories.html:5 56 | msgid "Categories" 57 | msgstr "Категории" 58 | 59 | #: ablog/post.py:568 60 | msgid "All posts" 61 | msgstr "Все записи" 62 | 63 | #: ablog/post.py:568 ablog/post.py:635 64 | msgid "Posted in" 65 | msgstr "Опубликовано в" 66 | 67 | #: ablog/post.py:569 ablog/templates/ablog/postcard2.html:117 68 | #: ablog/templates/ablog/tagcloud.html:3 ablog/templates/postcard2.html:118 69 | #: ablog/templates/tagcloud.html:4 70 | msgid "Tags" 71 | msgstr "Теги" 72 | 73 | #: ablog/post.py:569 ablog/post.py:636 74 | msgid "Posts tagged" 75 | msgstr "Сообщения с тегом" 76 | 77 | #: ablog/post.py:594 78 | #, fuzzy 79 | msgid "All Posts" 80 | msgstr "Все записи" 81 | 82 | #: ablog/post.py:595 83 | msgid "All" 84 | msgstr "" 85 | 86 | #: ablog/post.py:603 87 | msgid "Drafts" 88 | msgstr "Черновик" 89 | 90 | #: ablog/templates/ablog/archives.html:4 ablog/templates/archives.html:5 91 | msgid "Archives" 92 | msgstr "Архив" 93 | 94 | #: ablog/templates/ablog/collection.html:56 ablog/templates/collection.html:57 95 | msgid "Read more ..." 96 | msgstr "Читать ..." 97 | 98 | #: ablog/templates/ablog/postcard2.html:8 ablog/templates/postcard2.html:9 99 | msgid "Update" 100 | msgstr "Обновить" 101 | 102 | #: ablog/templates/ablog/postcard2.html:20 ablog/templates/postcard2.html:21 103 | msgid "Author" 104 | msgstr "Автор" 105 | 106 | #: ablog/templates/ablog/postcard2.html:44 ablog/templates/postcard2.html:45 107 | msgid "Location" 108 | msgstr "Расположение" 109 | 110 | #: ablog/templates/ablog/postcard2.html:68 ablog/templates/postcard2.html:69 111 | msgid "Language" 112 | msgstr "Язык" 113 | 114 | #: ablog/templates/ablog/postcard2.html:92 ablog/templates/postcard2.html:93 115 | msgid "Category" 116 | msgstr "Категория" 117 | 118 | #: ablog/templates/ablog/postcard2.html:123 ablog/templates/postcard2.html:124 119 | msgid "Tag" 120 | msgstr "Тег" 121 | 122 | #: ablog/templates/ablog/postnavy.html:8 ablog/templates/postnavy.html:9 123 | msgid "Previous" 124 | msgstr "Предыдущий" 125 | 126 | #: ablog/templates/ablog/postnavy.html:22 ablog/templates/postnavy.html:23 127 | msgid "Next" 128 | msgstr "Следующий" 129 | 130 | #: ablog/templates/ablog/recentposts.html:4 ablog/templates/recentposts.html:5 131 | msgid "Recent Posts" 132 | msgstr "Недавние Записи" 133 | -------------------------------------------------------------------------------- /src/ablog/locales/sphinx.pot: -------------------------------------------------------------------------------- 1 | # Translations template for ablog. 2 | # Copyright (C) 2022 ORGANIZATION 3 | # This file is distributed under the same license as the ablog project. 4 | # FIRST AUTHOR , 2022. 5 | # 6 | #, fuzzy 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: ablog 0.10.30.dev19+gb9b1a31\n" 10 | "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" 11 | "POT-Creation-Date: 2022-11-14 16:46-0800\n" 12 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 13 | "Last-Translator: FULL NAME \n" 14 | "Language-Team: LANGUAGE \n" 15 | "MIME-Version: 1.0\n" 16 | "Content-Type: text/plain; charset=utf-8\n" 17 | "Content-Transfer-Encoding: 8bit\n" 18 | "Generated-By: Babel 2.11.0\n" 19 | 20 | #: ablog/post.py:272 21 | msgid "Updated on " 22 | msgstr "" 23 | 24 | #: ablog/post.py:564 ablog/templates/ablog/authors.html:3 25 | #: ablog/templates/authors.html:4 26 | msgid "Authors" 27 | msgstr "" 28 | 29 | #: ablog/post.py:564 ablog/post.py:631 30 | msgid "Posts by" 31 | msgstr "" 32 | 33 | #: ablog/post.py:565 ablog/templates/ablog/locations.html:4 34 | #: ablog/templates/locations.html:5 35 | msgid "Locations" 36 | msgstr "" 37 | 38 | #: ablog/post.py:565 ablog/post.py:632 39 | msgid "Posts from" 40 | msgstr "" 41 | 42 | #: ablog/post.py:566 ablog/templates/ablog/languages.html:4 43 | #: ablog/templates/languages.html:5 44 | msgid "Languages" 45 | msgstr "" 46 | 47 | #: ablog/post.py:566 ablog/post.py:567 ablog/post.py:633 ablog/post.py:634 48 | msgid "Posts in" 49 | msgstr "" 50 | 51 | #: ablog/post.py:567 ablog/templates/ablog/categories.html:4 52 | #: ablog/templates/categories.html:5 53 | msgid "Categories" 54 | msgstr "" 55 | 56 | #: ablog/post.py:568 57 | msgid "All posts" 58 | msgstr "" 59 | 60 | #: ablog/post.py:568 ablog/post.py:635 61 | msgid "Posted in" 62 | msgstr "" 63 | 64 | #: ablog/post.py:569 ablog/templates/ablog/postcard2.html:117 65 | #: ablog/templates/ablog/tagcloud.html:3 ablog/templates/postcard2.html:118 66 | #: ablog/templates/tagcloud.html:4 67 | msgid "Tags" 68 | msgstr "" 69 | 70 | #: ablog/post.py:569 ablog/post.py:636 71 | msgid "Posts tagged" 72 | msgstr "" 73 | 74 | #: ablog/post.py:594 75 | msgid "All Posts" 76 | msgstr "" 77 | 78 | #: ablog/post.py:595 79 | msgid "All" 80 | msgstr "" 81 | 82 | #: ablog/post.py:603 83 | msgid "Drafts" 84 | msgstr "" 85 | 86 | #: ablog/templates/ablog/archives.html:4 ablog/templates/archives.html:5 87 | msgid "Archives" 88 | msgstr "" 89 | 90 | #: ablog/templates/ablog/collection.html:56 ablog/templates/collection.html:57 91 | msgid "Read more ..." 92 | msgstr "" 93 | 94 | #: ablog/templates/ablog/postcard2.html:8 ablog/templates/postcard2.html:9 95 | msgid "Update" 96 | msgstr "" 97 | 98 | #: ablog/templates/ablog/postcard2.html:20 ablog/templates/postcard2.html:21 99 | msgid "Author" 100 | msgstr "" 101 | 102 | #: ablog/templates/ablog/postcard2.html:44 ablog/templates/postcard2.html:45 103 | msgid "Location" 104 | msgstr "" 105 | 106 | #: ablog/templates/ablog/postcard2.html:68 ablog/templates/postcard2.html:69 107 | msgid "Language" 108 | msgstr "" 109 | 110 | #: ablog/templates/ablog/postcard2.html:92 ablog/templates/postcard2.html:93 111 | msgid "Category" 112 | msgstr "" 113 | 114 | #: ablog/templates/ablog/postcard2.html:123 ablog/templates/postcard2.html:124 115 | msgid "Tag" 116 | msgstr "" 117 | 118 | #: ablog/templates/ablog/postnavy.html:8 ablog/templates/postnavy.html:9 119 | msgid "Previous" 120 | msgstr "" 121 | 122 | #: ablog/templates/ablog/postnavy.html:22 ablog/templates/postnavy.html:23 123 | msgid "Next" 124 | msgstr "" 125 | 126 | #: ablog/templates/ablog/recentposts.html:4 ablog/templates/recentposts.html:5 127 | msgid "Recent Posts" 128 | msgstr "" 129 | -------------------------------------------------------------------------------- /src/ablog/locales/tr/LC_MESSAGES/sphinx.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunpy/ablog/95610aad20e3e290ca82776f6132a62d8fc2fbcb/src/ablog/locales/tr/LC_MESSAGES/sphinx.mo -------------------------------------------------------------------------------- /src/ablog/locales/tr/LC_MESSAGES/sphinx.po: -------------------------------------------------------------------------------- 1 | # Turkish translations for ablog. 2 | # Copyright (C) 2014 ORGANIZATION 3 | # This file is distributed under the same license as the ablog project. 4 | # FIRST AUTHOR , 2014. 5 | # 6 | msgid "" 7 | msgstr "" 8 | "Project-Id-Version: ablog 0.1\n" 9 | "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" 10 | "POT-Creation-Date: 2022-11-14 16:46-0800\n" 11 | "PO-Revision-Date: 2014-08-01 21:43-0700\n" 12 | "Last-Translator: FULL NAME \n" 13 | "Language: tr\n" 14 | "Language-Team: tr \n" 15 | "Plural-Forms: nplurals=1; plural=0;\n" 16 | "MIME-Version: 1.0\n" 17 | "Content-Type: text/plain; charset=utf-8\n" 18 | "Content-Transfer-Encoding: 8bit\n" 19 | "Generated-By: Babel 2.11.0\n" 20 | 21 | #: ablog/post.py:272 22 | #, fuzzy 23 | msgid "Updated on " 24 | msgstr "Güncelleme" 25 | 26 | #: ablog/post.py:564 ablog/templates/ablog/authors.html:3 27 | #: ablog/templates/authors.html:4 28 | msgid "Authors" 29 | msgstr "Yazarlar" 30 | 31 | #: ablog/post.py:564 ablog/post.py:631 32 | msgid "Posts by" 33 | msgstr "Yazar" 34 | 35 | #: ablog/post.py:565 ablog/templates/ablog/locations.html:4 36 | #: ablog/templates/locations.html:5 37 | msgid "Locations" 38 | msgstr "Mevkiler" 39 | 40 | #: ablog/post.py:565 ablog/post.py:632 41 | msgid "Posts from" 42 | msgstr "Mevki" 43 | 44 | #: ablog/post.py:566 ablog/templates/ablog/languages.html:4 45 | #: ablog/templates/languages.html:5 46 | msgid "Languages" 47 | msgstr "Diller" 48 | 49 | #: ablog/post.py:566 ablog/post.py:567 ablog/post.py:633 ablog/post.py:634 50 | msgid "Posts in" 51 | msgstr "Kategori" 52 | 53 | #: ablog/post.py:567 ablog/templates/ablog/categories.html:4 54 | #: ablog/templates/categories.html:5 55 | msgid "Categories" 56 | msgstr "Kategoriler" 57 | 58 | #: ablog/post.py:568 59 | msgid "All posts" 60 | msgstr "Bütün yazılar" 61 | 62 | #: ablog/post.py:568 ablog/post.py:635 63 | msgid "Posted in" 64 | msgstr "Sene" 65 | 66 | #: ablog/post.py:569 ablog/templates/ablog/postcard2.html:117 67 | #: ablog/templates/ablog/tagcloud.html:3 ablog/templates/postcard2.html:118 68 | #: ablog/templates/tagcloud.html:4 69 | msgid "Tags" 70 | msgstr "Etiketler" 71 | 72 | #: ablog/post.py:569 ablog/post.py:636 73 | msgid "Posts tagged" 74 | msgstr "Etiket" 75 | 76 | #: ablog/post.py:594 77 | #, fuzzy 78 | msgid "All Posts" 79 | msgstr "Bütün yazılar" 80 | 81 | #: ablog/post.py:595 82 | msgid "All" 83 | msgstr "" 84 | 85 | #: ablog/post.py:603 86 | msgid "Drafts" 87 | msgstr "Taslaklar" 88 | 89 | #: ablog/templates/ablog/archives.html:4 ablog/templates/archives.html:5 90 | msgid "Archives" 91 | msgstr "Arşiv" 92 | 93 | #: ablog/templates/ablog/collection.html:56 ablog/templates/collection.html:57 94 | msgid "Read more ..." 95 | msgstr "Okumaya devam et ..." 96 | 97 | #: ablog/templates/ablog/postcard2.html:8 ablog/templates/postcard2.html:9 98 | msgid "Update" 99 | msgstr "Güncelleme" 100 | 101 | #: ablog/templates/ablog/postcard2.html:20 ablog/templates/postcard2.html:21 102 | msgid "Author" 103 | msgstr "Yazar" 104 | 105 | #: ablog/templates/ablog/postcard2.html:44 ablog/templates/postcard2.html:45 106 | msgid "Location" 107 | msgstr "Mevki" 108 | 109 | #: ablog/templates/ablog/postcard2.html:68 ablog/templates/postcard2.html:69 110 | msgid "Language" 111 | msgstr "Dil" 112 | 113 | #: ablog/templates/ablog/postcard2.html:92 ablog/templates/postcard2.html:93 114 | msgid "Category" 115 | msgstr "Kategori" 116 | 117 | #: ablog/templates/ablog/postcard2.html:123 ablog/templates/postcard2.html:124 118 | msgid "Tag" 119 | msgstr "Etiket" 120 | 121 | #: ablog/templates/ablog/postnavy.html:8 ablog/templates/postnavy.html:9 122 | msgid "Previous" 123 | msgstr "Önceki" 124 | 125 | #: ablog/templates/ablog/postnavy.html:22 ablog/templates/postnavy.html:23 126 | msgid "Next" 127 | msgstr "Sonraki" 128 | 129 | #: ablog/templates/ablog/recentposts.html:4 ablog/templates/recentposts.html:5 130 | msgid "Recent Posts" 131 | msgstr "Yeni Yazılar" 132 | -------------------------------------------------------------------------------- /src/ablog/locales/zh_CN/LC_MESSAGES/sphinx.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunpy/ablog/95610aad20e3e290ca82776f6132a62d8fc2fbcb/src/ablog/locales/zh_CN/LC_MESSAGES/sphinx.mo -------------------------------------------------------------------------------- /src/ablog/locales/zh_CN/LC_MESSAGES/sphinx.po: -------------------------------------------------------------------------------- 1 | # Chinese (Simplified, China) translations for ablog. 2 | # Copyright (C) 2020 ORGANIZATION 3 | # This file is distributed under the same license as the ablog project. 4 | # FIRST AUTHOR , 2020. 5 | # 6 | msgid "" 7 | msgstr "" 8 | "Project-Id-Version: ablog 0.10.4.dev6+g5473a00.d20200325\n" 9 | "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" 10 | "POT-Creation-Date: 2022-11-14 16:46-0800\n" 11 | "PO-Revision-Date: 2020-03-25 16:35+0800\n" 12 | "Last-Translator: FULL NAME \n" 13 | "Language: zh_Hans_CN\n" 14 | "Language-Team: zh_Hans_CN \n" 15 | "Plural-Forms: nplurals=1; plural=0;\n" 16 | "MIME-Version: 1.0\n" 17 | "Content-Type: text/plain; charset=utf-8\n" 18 | "Content-Transfer-Encoding: 8bit\n" 19 | "Generated-By: Babel 2.11.0\n" 20 | 21 | #: ablog/post.py:272 22 | #, fuzzy 23 | msgid "Updated on " 24 | msgstr "更新" 25 | 26 | #: ablog/post.py:564 ablog/templates/ablog/authors.html:3 27 | #: ablog/templates/authors.html:4 28 | msgid "Authors" 29 | msgstr "作者" 30 | 31 | #: ablog/post.py:564 ablog/post.py:631 32 | msgid "Posts by" 33 | msgstr "文章" 34 | 35 | #: ablog/post.py:565 ablog/templates/ablog/locations.html:4 36 | #: ablog/templates/locations.html:5 37 | msgid "Locations" 38 | msgstr "地点" 39 | 40 | #: ablog/post.py:565 ablog/post.py:632 41 | msgid "Posts from" 42 | msgstr "文章自" 43 | 44 | #: ablog/post.py:566 ablog/templates/ablog/languages.html:4 45 | #: ablog/templates/languages.html:5 46 | msgid "Languages" 47 | msgstr "语言" 48 | 49 | #: ablog/post.py:566 ablog/post.py:567 ablog/post.py:633 ablog/post.py:634 50 | msgid "Posts in" 51 | msgstr "文章:" 52 | 53 | #: ablog/post.py:567 ablog/templates/ablog/categories.html:4 54 | #: ablog/templates/categories.html:5 55 | msgid "Categories" 56 | msgstr "类别" 57 | 58 | #: ablog/post.py:568 59 | msgid "All posts" 60 | msgstr "所有文章" 61 | 62 | #: ablog/post.py:568 ablog/post.py:635 63 | msgid "Posted in" 64 | msgstr "文章:" 65 | 66 | #: ablog/post.py:569 ablog/templates/ablog/postcard2.html:117 67 | #: ablog/templates/ablog/tagcloud.html:3 ablog/templates/postcard2.html:118 68 | #: ablog/templates/tagcloud.html:4 69 | msgid "Tags" 70 | msgstr "标签" 71 | 72 | #: ablog/post.py:569 ablog/post.py:636 73 | msgid "Posts tagged" 74 | msgstr "文章标签" 75 | 76 | #: ablog/post.py:594 77 | msgid "All Posts" 78 | msgstr "所有文章" 79 | 80 | #: ablog/post.py:595 81 | msgid "All" 82 | msgstr "所有" 83 | 84 | #: ablog/post.py:603 85 | msgid "Drafts" 86 | msgstr "草稿" 87 | 88 | #: ablog/templates/ablog/archives.html:4 ablog/templates/archives.html:5 89 | msgid "Archives" 90 | msgstr "归档" 91 | 92 | #: ablog/templates/ablog/collection.html:56 ablog/templates/collection.html:57 93 | msgid "Read more ..." 94 | msgstr "更多 ..." 95 | 96 | #: ablog/templates/ablog/postcard2.html:8 ablog/templates/postcard2.html:9 97 | msgid "Update" 98 | msgstr "更新" 99 | 100 | #: ablog/templates/ablog/postcard2.html:20 ablog/templates/postcard2.html:21 101 | msgid "Author" 102 | msgstr "作者" 103 | 104 | #: ablog/templates/ablog/postcard2.html:44 ablog/templates/postcard2.html:45 105 | msgid "Location" 106 | msgstr "地点" 107 | 108 | #: ablog/templates/ablog/postcard2.html:68 ablog/templates/postcard2.html:69 109 | msgid "Language" 110 | msgstr "语言" 111 | 112 | #: ablog/templates/ablog/postcard2.html:92 ablog/templates/postcard2.html:93 113 | msgid "Category" 114 | msgstr "类别" 115 | 116 | #: ablog/templates/ablog/postcard2.html:123 ablog/templates/postcard2.html:124 117 | msgid "Tag" 118 | msgstr "标签" 119 | 120 | #: ablog/templates/ablog/postnavy.html:8 ablog/templates/postnavy.html:9 121 | msgid "Previous" 122 | msgstr "上一篇" 123 | 124 | #: ablog/templates/ablog/postnavy.html:22 ablog/templates/postnavy.html:23 125 | msgid "Next" 126 | msgstr "下一篇" 127 | 128 | #: ablog/templates/ablog/recentposts.html:4 ablog/templates/recentposts.html:5 129 | msgid "Recent Posts" 130 | msgstr "最近文章" 131 | -------------------------------------------------------------------------------- /src/ablog/stylesheets/ablog/tagcloud.css: -------------------------------------------------------------------------------- 1 | ul.ablog-cloud { 2 | list-style: none; 3 | overflow: auto; 4 | } 5 | 6 | ul.ablog-cloud li { 7 | float: left; 8 | height: 20pt; 9 | line-height: 18pt; 10 | margin-right: 5px; 11 | } 12 | 13 | ul.ablog-cloud a { 14 | text-decoration: none; 15 | vertical-align: middle; 16 | } 17 | 18 | li.ablog-cloud-1 { 19 | font-size: 80%; 20 | } 21 | 22 | li.ablog-cloud-2 { 23 | font-size: 95%; 24 | } 25 | 26 | li.ablog-cloud-3 { 27 | font-size: 110%; 28 | } 29 | 30 | li.ablog-cloud-4 { 31 | font-size: 125%; 32 | } 33 | 34 | li.ablog-cloud-5 { 35 | font-size: 140%; 36 | } 37 | -------------------------------------------------------------------------------- /src/ablog/templates/ablog/archives.html: -------------------------------------------------------------------------------- 1 | {% if ablog.archive %} 2 |
3 |

4 | {{ gettext('Archives') }} 5 |

6 | 13 |
14 | {% endif %} 15 | -------------------------------------------------------------------------------- /src/ablog/templates/ablog/authors.html: -------------------------------------------------------------------------------- 1 | {% if ablog.author %} 2 |
3 |

4 | {{ gettext('Authors') }} 5 |

6 | 13 |
14 | {% endif %} 15 | -------------------------------------------------------------------------------- /src/ablog/templates/ablog/catalog.html: -------------------------------------------------------------------------------- 1 | {%- extends "page.html" %} {% macro postlink(post) -%} {% if post.external_link 2 | -%} {{- post.external_link -}} {% else %} {{- pathto(post.docname) }}{{ 3 | anchor(post) -}} {%- endif %} {%- endmacro %} {% block body %} {% for collection 4 | in catalog %} {% if collection %} 5 |
6 |

7 | {{ header }} 9 | {{ collection }} 10 | 11 |

12 | {% for post in collection %} 13 |
14 |

15 | {% if post.published %} 16 | {{ post.date.strftime(ablog.post_date_format) }} 17 | {% else %} 18 | Draft 19 | {% endif %} - 20 | {{ post.title }} 21 |

22 |
23 | {% endfor %} 24 |
25 | {% endif %} {% endfor %} {% endblock body %} 26 | -------------------------------------------------------------------------------- /src/ablog/templates/ablog/categories.html: -------------------------------------------------------------------------------- 1 | {% if ablog.category %} 2 |
3 |

4 | {{ gettext('Categories') }} 5 |

6 | 13 |
14 | {% endif %} 15 | -------------------------------------------------------------------------------- /src/ablog/templates/ablog/collection.html: -------------------------------------------------------------------------------- 1 | {%- extends "page.html" %} {% block body %} {% macro postlink(post) -%} {% if 2 | post.external_link -%} {{- post.external_link -}} {% else %} {{- 3 | pathto(post.docname) }}{{ anchor(post) -}} {%- endif %} {%- endmacro %} 4 |
5 |

6 | {% if archive_feed and fa %} 7 | 8 | 10 | {% endif %} 11 | {{ header }} {% if collection.href %} 13 | {{ collection }} 14 | {% else %} {{ collection }} {% endif %} 15 | 16 |

17 | {% if ablog.blog_archive_titles %} {% for post in collection %} 18 |
19 |

20 | {% if post.published %} 21 | {{ post.date.strftime(ablog.post_date_format) }} 22 | {% else %} 23 | Draft 24 | {% endif %} - 25 | {{ post.title }} 26 |

27 |
28 | {% endfor %} {% else %} {% for post in collection %} 29 |
30 |

31 | {{ post.title }} 32 |

33 |
    34 |
  • 35 | {% if post.published %} {% if fa %} 36 | 37 | {% endif %} 38 | {{ post.date.strftime(ablog.post_date_format) }} 39 | {% else %} {% if fa %} 40 | 41 | {% endif %} {% if post.date %} 42 | {{ post.date.strftime(ablog.post_date_format) }} 43 | {% else %} 44 | Draft 45 | {% endif %} {% endif %} 46 |
  • 47 | {% include "ablog/postcard2.html" %} 48 |
49 | {{ post.to_html(collection.docname) }} 50 |

51 | {{ _("Read more ...") }} 52 |

53 |
54 |
55 | {% endfor %} {% endif %} 56 |
57 | {% endblock body %} 58 | -------------------------------------------------------------------------------- /src/ablog/templates/ablog/languages.html: -------------------------------------------------------------------------------- 1 | {% if ablog.language %} 2 |
3 |

4 | {{ gettext('Languages') }} 5 |

6 | 13 |
14 | {% endif %} 15 | -------------------------------------------------------------------------------- /src/ablog/templates/ablog/locations.html: -------------------------------------------------------------------------------- 1 | {% if ablog.location %} 2 |
3 |

4 | {{ gettext('Locations') }} 5 |

6 | 13 |
14 | {% endif %} 15 | -------------------------------------------------------------------------------- /src/ablog/templates/ablog/postcard.html: -------------------------------------------------------------------------------- 1 | {% if pagename in ablog %} 2 |
3 | {% set fa = ablog.fontawesome %} {% set post = ablog[pagename] %} 4 |

5 | {% if post.published %} {% if fa %} 6 | 7 | {% endif %} 8 | {{ post.date.strftime(ablog.post_date_format) }} 9 | {% else %} {% if fa %} 10 | 11 | {% endif %} {% if post.date %} 12 | {{ post.date.strftime(ablog.post_date_format) }} 13 | {% else %} 14 | Draft 15 | {% endif %} {% endif %} 16 |

17 |
    18 | {% include "ablog/postcard2.html" %} 19 |
20 |
21 | {% endif %} 22 | -------------------------------------------------------------------------------- /src/ablog/templates/ablog/postcard2.html: -------------------------------------------------------------------------------- 1 |
2 | {% if post.published and post.date != post.update %} 3 |
  • 4 | 5 | {% if fa %} 6 | 7 | {% else %} {{ gettext('Update') }}: {% endif %} 8 | 9 | {{ post.update.strftime(ablog.post_date_format) }} 10 |
  • 11 | {% endif %} {% if post.author %} 12 |
  • 13 | 14 | {% if fa %} 15 | 16 | {% else %} {{ gettext('Author') }}: {% endif %} 17 | 18 | {% for coll in post.author %} {% if coll|length %} 19 | {{ coll }} 20 | {% if loop.index < post.author|length %} , {% endif %} {% else %} {{ coll }} 21 | {% if loop.index < post.author|length %} , {% endif %} {% endif %} {% endfor 22 | %} 23 |
  • 24 | {% endif %} {% if post.location %} 25 |
  • 26 | 27 | {% if fa %} 28 | 29 | {% else %} {{ gettext('Location') }}: {% endif %} 30 | 31 | {% for coll in post.location %} {% if coll|length %} 32 | {{ coll }} 33 | {% if loop.index < post.location|length %} , {% endif %} {% else %} {{ coll 34 | }} {% if loop.index < post.location|length %} , {% endif %} {% endif %} {% 35 | endfor %} 36 |
  • 37 | {% endif %} {% if post.language %} 38 |
  • 39 | 40 | {% if fa %} 41 | 42 | {% else %} {{ gettext('Language') }}: {% endif %} 43 | 44 | {% for coll in post.language %} {% if coll|length %} 45 | {{ coll }} 46 | {% if loop.index < post.language|length %} , {% endif %} {% else %} {{ coll 47 | }} {% if loop.index < post.language|length %} , {% endif %} {% endif %} {% 48 | endfor %} 49 |
  • 50 | {% endif %} {% if post.category %} 51 |
  • 52 | 53 | {% if fa %} 54 | 55 | {% else %} {{ gettext('Category') }}: {% endif %} 56 | 57 | {% for coll in post.category %} {% if coll|length %} 58 | {{ coll }} 59 | {% if loop.index < post.category|length %} , {% endif %} {% else %} {{ coll 60 | }} {% if loop.index < post.category|length %} , {% endif %} {% endif %} {% 61 | endfor %} 62 |
  • 63 | {% endif %} {% if post.tags %} 64 |
  • 65 | 66 | {% if post.tags|length > 1 %} {% if fa %} 67 | 68 | {% else %} {{ gettext('Tags') }}: {% endif %} {% else %} {% if fa %} 69 | 70 | {% else %} {{ gettext('Tag') }}: {% endif %}{% endif %} 71 | 72 | {% for coll in post.tags %} {% if coll|length %} 73 | {{ coll }} 74 | {% if loop.index < post.tags|length %} {% endif %} {% else %} {{ coll }} {% 75 | if loop.index < post.tags|length %} {% endif %} {% endif %} {% endfor %} 76 |
  • 77 | {% endif %} {% if ablog.disqus_shortname and (ablog[pagename].published or 78 | ablog.disqus_drafts) %} 79 |
  • 80 | 94 | {% if fa %} 95 | 96 | {% endif %} 97 | 101 | {% if not fa %} Comments {% endif %} 102 | 103 |
  • 104 | {% endif %} 105 |
    106 | -------------------------------------------------------------------------------- /src/ablog/templates/ablog/postnavy.html: -------------------------------------------------------------------------------- 1 | {# prev/next are not set for drafts #} {% set post = ablog[pagename] %} {% if 2 | post.published and ablog.post_show_prev_next %} 3 |
    4 | 5 | {% if post.prev %} {% if not ablog.fontawesome %} {{ gettext('Previous') }}: 6 | {% endif %} 7 | 8 | {% if ablog.fontawesome %} 9 | 10 | {% endif %} 11 | {{ post.prev.title }} 12 | 13 | {% endif %} 14 | 15 |   16 | 17 | {% if post.next %} {% if not ablog.fontawesome %} {{ gettext('Next') }}: {% 18 | endif %} 19 | 20 | {{ post.next.title }} 21 | {% if ablog.fontawesome %} 22 | 23 | {% endif %} 24 | 25 | {% endif %} 26 | 27 |
    28 | {% endif %} 29 | -------------------------------------------------------------------------------- /src/ablog/templates/ablog/recentposts.html: -------------------------------------------------------------------------------- 1 | {% if ablog %} 2 |
    3 |

    4 | {{ gettext('Recent Posts') }} 5 |

    6 | 16 |
    17 | {% endif %} 18 | -------------------------------------------------------------------------------- /src/ablog/templates/ablog/redirect.html: -------------------------------------------------------------------------------- 1 | {%- extends "!layout.html" %} {%- block extrahead %} {{ super() }} 2 | 6 | {% endblock extrahead %} {% block body %} You are being redirected to 7 | {{ post.title }} in {{ 8 | ablog.post_redirect_refresh }} seconds; {% endblock body %} 9 | -------------------------------------------------------------------------------- /src/ablog/templates/ablog/tagcloud.html: -------------------------------------------------------------------------------- 1 | {% if ablog.tags %} 2 |
    3 | 8 |

    {{ gettext('Tags') }}

    9 |
      10 | {% for coll in ablog.tags %} {% if coll %} 11 |
    • 12 | {{ coll }} 13 |
    • 14 | {% endif %} {% endfor %} 15 |
    16 |
    17 | {% endif %} 18 | -------------------------------------------------------------------------------- /src/ablog/templates/archives.html: -------------------------------------------------------------------------------- 1 | {{ warning("archives.html is an old template path, that is no longer used by 2 | ablog. Please use ablog/archives.html instead.") }} {% if ablog.archive %} 3 |
    4 |

    5 | {{ gettext('Archives') }} 6 |

    7 | 14 |
    15 | {% endif %} 16 | -------------------------------------------------------------------------------- /src/ablog/templates/authors.html: -------------------------------------------------------------------------------- 1 | {{ warning("authors.html is an old template path, that is no longer used by 2 | ablog. Please use ablog/authors.html instead.") }} {% if ablog.author %} 3 |
    4 |

    5 | {{ gettext('Authors') }} 6 |

    7 | 14 |
    15 | {% endif %} 16 | -------------------------------------------------------------------------------- /src/ablog/templates/catalog.html: -------------------------------------------------------------------------------- 1 | {{ warning("catalog.html is an old template path, that is no longer used by 2 | ablog. Please use ablog/catalog.html instead.") }} {%- extends "page.html" %} {% 3 | macro postlink(post) -%} {% if post.external_link -%} {{- post.external_link -}} 4 | {% else %} {{- pathto(post.docname) }}{{ anchor(post) -}} {%- endif %} {%- 5 | endmacro %} {% block body %} {% for collection in catalog %} {% if collection %} 6 |
    7 |

    8 | {{ header }} 10 | {{ collection }} 12 |

    13 | {% for post in collection %} 14 |
    15 |

    16 | {% if post.published %} 17 | {{ post.date.strftime(ablog.post_date_format) }} 18 | {% else %} 19 | Draft 20 | {% endif %} - 21 | {{ post.title }} 22 |

    23 |
    24 | {% endfor %} 25 |
    26 | {% endif %} {% endfor %} {% endblock body %} 27 | -------------------------------------------------------------------------------- /src/ablog/templates/categories.html: -------------------------------------------------------------------------------- 1 | {{ warning("category.html is an old template path, that is no longer used by 2 | ablog. Please use ablog/category.html instead.") }} {% if ablog.category %} 3 |
    4 |

    5 | {{ gettext('Categories') }} 6 |

    7 | 14 |
    15 | {% endif %} 16 | -------------------------------------------------------------------------------- /src/ablog/templates/collection.html: -------------------------------------------------------------------------------- 1 | {{ warning("collection.html is an old template path, that is no longer used by 2 | ablog. Please use ablog/collection.html instead.") }} {%- extends "page.html" %} 3 | {% block body %} {% macro postlink(post) -%} {% if post.external_link -%} {{- 4 | post.external_link -}} {% else %} {{- pathto(post.docname) }}{{ anchor(post) -}} 5 | {%- endif %} {%- endmacro %} {% endmacro %} 6 |
    7 |

    8 | {% if archive_feed and fa %} 9 | 10 | 12 | {% endif %} 13 | {{ header }} {% if collection.href %} 15 | {{ collection }} 16 | {% else %} {{ collection }} {% endif %} 17 | 18 |

    19 | {% if ablog.blog_archive_titles %} {% for post in collection %} 20 |
    21 |

    22 | {% if post.published %} 23 | {{ post.date.strftime(ablog.post_date_format) }} 24 | {% else %} 25 | Draft 26 | {% endif %} - 27 | {{ post.title }} 28 |

    29 |
    30 | {% endfor %} {% else %} {% for post in collection %} 31 |
    32 |

    33 | {{ post.title }} 34 |

    35 |
      36 |
    • 37 | {% if post.published %} {% if fa %} 38 | 39 | {% endif %} 40 | {{ post.date.strftime(ablog.post_date_format) }} 41 | {% else %} {% if fa %} 42 | 43 | {% endif %} {% if post.date %} 44 | {{ post.date.strftime(ablog.post_date_format) }} 45 | {% else %} 46 | Draft 47 | {% endif %} {% endif %} 48 |
    • 49 | {% include "ablog/postcard2.html" %} 50 |
    51 | {{ post.to_html(collection.docname) }} 52 |

    53 | {{ _("Read more ...") }} 54 |

    55 |
    56 |
    57 | {% endfor %} {% endif %} 58 |
    59 | {% endblock body %} 60 | -------------------------------------------------------------------------------- /src/ablog/templates/languages.html: -------------------------------------------------------------------------------- 1 | {{ warning("languages.html is an old template path, that is no longer used by 2 | ablog. Please use ablog/languages.html instead.") }} {% if ablog.language %} 3 |
    4 |

    5 | {{ gettext('Languages') }} 6 |

    7 | 14 |
    15 | {% endif %} 16 | -------------------------------------------------------------------------------- /src/ablog/templates/locations.html: -------------------------------------------------------------------------------- 1 | {{ warning("locations.html is an old template path, that is no longer used by 2 | ablog. Please use ablog/locations.html instead.") }} {% if ablog.location %} 3 |
    4 |

    5 | {{ gettext('Locations') }} 6 |

    7 | 14 |
    15 | {% endif %} 16 | -------------------------------------------------------------------------------- /src/ablog/templates/page.html: -------------------------------------------------------------------------------- 1 | {%- extends "layout.html" %} {% set fa = ablog.fontawesome %} {%- block 2 | extrahead %} {{ super() }} {% if feed_path %} 3 | 9 | {% endif %} {% if ablog.fontawesome_link_cdn %} 10 | 11 | {% elif ablog.fontawesome_css_file %} 12 | 17 | {% endif %} {% endblock extrahead %} {% block body %} {{ body }} 18 |
    19 | {% if pagename in ablog %} {% include "ablog/postnavy.html" %} {% endif %} {% 20 | if ablog.disqus_shortname and ablog.blog_baseurl and (not 21 | ablog[pagename].nocomments) and ((pagename in ablog and 22 | (ablog[pagename].published or ablog.disqus_drafts)) or (not pagename in ablog 23 | and ablog.disqus_pages)) %} 24 |
    25 |

    Comments

    26 |
    27 | 44 | 50 | 51 | comments powered by Disqus 52 | 53 |
    54 | {% endif %} 55 |
    56 | {% endblock body %} 57 | -------------------------------------------------------------------------------- /src/ablog/templates/postcard.html: -------------------------------------------------------------------------------- 1 | {{ warning("postcard.html is an old template path, that is no longer used by 2 | ablog. Please use ablog/postcard.html instead.") }} {% if pagename in ablog %} 3 |
    4 | {% set fa = ablog.fontawesome %} {% set post = ablog[pagename] %} 5 |

    6 | {% if post.published %} {% if fa %} 7 | 8 | {% endif %} 9 | {{ post.date.strftime(ablog.post_date_format) }} 10 | {% else %} {% if fa %} 11 | 12 | {% endif %} {% if post.date %} 13 | {{ post.date.strftime(ablog.post_date_format) }} 14 | {% else %} 15 | Draft 16 | {% endif %} {% endif %} 17 |

    18 |
      19 | {% include "ablog/postcard2.html" %} 20 |
    21 |
    22 | {% endif %} 23 | -------------------------------------------------------------------------------- /src/ablog/templates/postcard2.html: -------------------------------------------------------------------------------- 1 | {{ warning("postcard2.html is an old template path, that is no longer used by 2 | ablog. Please use ablog/postcard2.html instead.") }} 3 |
    4 | {% if post.published and post.date != post.update %} 5 |
  • 6 | 7 | {% if fa %} 8 | 9 | {% else %} {{ gettext('Update') }}: {% endif %} 10 | 11 | {{ post.update.strftime(ablog.post_date_format) }} 12 |
  • 13 | {% endif %} {% if post.author %} 14 |
  • 15 | 16 | {% if fa %} 17 | 18 | {% else %} {{ gettext('Author') }}: {% endif %} 19 | 20 | {% for coll in post.author %} {% if coll|length %} 21 | {{ coll }} 22 | {% if loop.index < post.author|length %} , {% endif %} {% else %} {{ coll }} 23 | {% if loop.index < post.author|length %} , {% endif %} {% endif %} {% endfor 24 | %} 25 |
  • 26 | {% endif %} {% if post.location %} 27 |
  • 28 | 29 | {% if fa %} 30 | 31 | {% else %} {{ gettext('Location') }}: {% endif %} 32 | 33 | {% for coll in post.location %} {% if coll|length %} 34 | {{ coll }} 35 | {% if loop.index < post.location|length %} , {% endif %} {% else %} {{ coll 36 | }} {% if loop.index < post.location|length %} , {% endif %} {% endif %} {% 37 | endfor %} 38 |
  • 39 | {% endif %} {% if post.language %} 40 |
  • 41 | 42 | {% if fa %} 43 | 44 | {% else %} {{ gettext('Language') }}: {% endif %} 45 | 46 | {% for coll in post.language %} {% if coll|length %} 47 | {{ coll }} 48 | {% if loop.index < post.language|length %} , {% endif %} {% else %} {{ coll 49 | }} {% if loop.index < post.language|length %} , {% endif %} {% endif %} {% 50 | endfor %} 51 |
  • 52 | {% endif %} {% if post.category %} 53 |
  • 54 | 55 | {% if fa %} 56 | 57 | {% else %} {{ gettext('Category') }}: {% endif %} 58 | 59 | {% for coll in post.category %} {% if coll|length %} 60 | {{ coll }} 61 | {% if loop.index < post.category|length %} , {% endif %} {% else %} {{ coll 62 | }} {% if loop.index < post.category|length %} , {% endif %} {% endif %} {% 63 | endfor %} 64 |
  • 65 | {% endif %} {% if post.tags %} 66 |
  • 67 | 68 | {% if post.tags|length > 1 %} {% if fa %} 69 | 70 | {% else %} {{ gettext('Tags') }}: {% endif %} {% else %} {% if fa %} 71 | 72 | {% else %} {{ gettext('Tag') }}: {% endif %}{% endif %} 73 | 74 | {% for coll in post.tags %} {% if coll|length %} 75 | {{ coll }} 76 | {% if loop.index < post.tags|length %} {% endif %} {% else %} {{ coll }} {% 77 | if loop.index < post.tags|length %} {% endif %} {% endif %} {% endfor %} 78 |
  • 79 | {% endif %} {% if ablog.disqus_shortname and (ablog[pagename].published or 80 | ablog.disqus_drafts) %} 81 |
  • 82 | 96 | {% if fa %} 97 | 98 | {% endif %} 99 | 103 | {% if not fa %} Comments {% endif %} 104 | 105 |
  • 106 | {% endif %} 107 |
    108 | -------------------------------------------------------------------------------- /src/ablog/templates/postnavy.html: -------------------------------------------------------------------------------- 1 | {{ warning("postnavy.html is an old template path, that is no longer used by 2 | ablog. Please use ablog/postnavy.html instead.") }} {# prev/next are not set for 3 | drafts #} {% set post = ablog[pagename] %} {% if post.published and 4 | ablog.post_show_prev_next %} 5 |
    6 | 7 | {% if post.prev %} {% if not ablog.fontawesome %} {{ gettext('Previous') }}: 8 | {% endif %} 9 | 10 | {% if ablog.fontawesome %} 11 | 12 | {% endif %} 13 | {{ post.prev.title }} 14 | 15 | {% endif %} 16 | 17 |   18 | 19 | {% if post.next %} {% if not ablog.fontawesome %} {{ gettext('Next') }}: {% 20 | endif %} 21 | 22 | {{ post.next.title }} 23 | {% if ablog.fontawesome %} 24 | 25 | {% endif %} 26 | 27 | {% endif %} 28 | 29 |
    30 | {% endif %} 31 | -------------------------------------------------------------------------------- /src/ablog/templates/recentposts.html: -------------------------------------------------------------------------------- 1 | {{ warning("recentposts.html is an old template path, that is no longer used by 2 | ablog. Please use ablog/recentposts.html instead.") }} {% if ablog %} 3 |
    4 |

    5 | {{ gettext('Recent Posts') }} 6 |

    7 | 17 |
    18 | {% endif %} 19 | -------------------------------------------------------------------------------- /src/ablog/templates/redirect.html: -------------------------------------------------------------------------------- 1 | {{ warning("redirect.html is an old template path, that is no longer used by 2 | ablog. Please use ablog/redirect.html instead.") }} {%- extends "!layout.html" 3 | %} {%- block extrahead %} {{ super() }} 4 | 8 | {% endblock extrahead %} {% block body %} You are being redirected to 9 | {{ post.title }} in {{ 10 | ablog.post_redirect_refresh }} seconds; {% endblock body %} 11 | -------------------------------------------------------------------------------- /src/ablog/templates/tagcloud.html: -------------------------------------------------------------------------------- 1 | {{ warning("tagcloud.html is an old template path, that is no longer used by 2 | ablog. Please use ablog/tagcloud.html instead.") }} {% if ablog.tags %} 3 |
    4 | 9 |

    {{ gettext('Tags') }}

    10 |
      11 | {% for coll in ablog.tags %} {% if coll %} 12 |
    • 13 | {{ coll }} 14 |
    • 15 | {% endif %} {% endfor %} 16 |
    17 |
    18 | {% endif %} 19 | -------------------------------------------------------------------------------- /src/ablog/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunpy/ablog/95610aad20e3e290ca82776f6132a62d8fc2fbcb/src/ablog/tests/__init__.py -------------------------------------------------------------------------------- /src/ablog/tests/test_build.py: -------------------------------------------------------------------------------- 1 | from datetime import datetime 2 | 3 | import lxml 4 | import pytest 5 | 6 | POST_DATETIME_FMT = "%Y-%m-%dT%H:%M:%S%z" 7 | 8 | 9 | @pytest.mark.sphinx("html", testroot="build") # using roots/test-build 10 | def test_build(app, status, warning): 11 | app.build() 12 | 13 | assert app.statuscode == 0 14 | assert (app.outdir / "index.html").exists() 15 | assert (app.outdir / "blog/archive.html").exists() 16 | assert (app.outdir / "post.html").exists() 17 | 18 | 19 | @pytest.mark.sphinx("html", testroot="build") # using roots/test-build 20 | def test_feed(app, status, warning): 21 | """ 22 | Atom syndication feeds are built correctly. 23 | """ 24 | app.build() 25 | assert app.statuscode == 0 26 | 27 | feed_path = app.outdir / "blog/atom.xml" 28 | assert (feed_path).exists() 29 | 30 | with feed_path.open() as feed_opened: 31 | feed_tree = lxml.etree.parse(feed_opened) 32 | entries = feed_tree.findall("{http://www.w3.org/2005/Atom}entry") 33 | assert len(entries) == 2 34 | 35 | entry = entries[0] 36 | title = entry.find("{http://www.w3.org/2005/Atom}title") 37 | assert title.text == "Foo Post Title" 38 | summary = entry.find("{http://www.w3.org/2005/Atom}summary") 39 | assert summary.text == "Foo post description with link." 40 | categories = entry.findall("{http://www.w3.org/2005/Atom}category") 41 | assert len(categories) == 2 42 | assert categories[0].attrib["label"] == "BarTag" 43 | assert categories[0].attrib["term"] == "BarTag" 44 | assert categories[1].attrib["label"] == "Foo Tag" 45 | assert categories[1].attrib["term"] == "FooTag" 46 | content = entry.find("{http://www.w3.org/2005/Atom}content") 47 | assert "Foo post content." in content.text 48 | update_time = entry.find("{http://www.w3.org/2005/Atom}updated") 49 | first_entry_date = datetime.strptime(update_time.text, POST_DATETIME_FMT) 50 | 51 | empty_entry = entries[1] 52 | title = empty_entry.find("{http://www.w3.org/2005/Atom}title") 53 | assert title.text == "Foo Empty Post" 54 | summary = empty_entry.find("{http://www.w3.org/2005/Atom}summary") 55 | assert summary is None 56 | categories = empty_entry.findall("{http://www.w3.org/2005/Atom}category") 57 | assert len(categories) == 0 58 | content = empty_entry.find("{http://www.w3.org/2005/Atom}content") 59 | assert 'id="foo-empty-post"' in content.text 60 | update_time = empty_entry.find("{http://www.w3.org/2005/Atom}updated") 61 | second_entry_date = datetime.strptime(update_time.text, POST_DATETIME_FMT) 62 | 63 | # check order of post based on their dates 64 | assert first_entry_date > second_entry_date 65 | 66 | social_path = app.outdir / "blog/social.xml" 67 | assert (social_path).exists() 68 | 69 | with social_path.open() as social_opened: 70 | social_tree = lxml.etree.parse(social_opened) 71 | social_entries = social_tree.findall("{http://www.w3.org/2005/Atom}entry") 72 | assert len(social_entries) == len(entries) 73 | 74 | social_entry = social_entries[0] 75 | title = social_entry.find("{http://www.w3.org/2005/Atom}title") 76 | assert title.text == "Foo Post Title" 77 | summary = social_entry.find("{http://www.w3.org/2005/Atom}summary") 78 | assert summary.text == "Foo post description with link." 79 | categories = social_entry.findall("{http://www.w3.org/2005/Atom}category") 80 | assert len(categories) == 2 81 | assert categories[0].attrib["label"] == "BarTag" 82 | assert categories[1].attrib["label"] == "Foo Tag" 83 | content = social_entry.find("{http://www.w3.org/2005/Atom}content") 84 | assert "Foo Post Title" in content.text 85 | -------------------------------------------------------------------------------- /src/ablog/tests/test_canonical.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | 4 | def read_text(path): 5 | """ 6 | Support function to give backward compatibility with older sphinx (v2). 7 | """ 8 | if hasattr(path, "read_text"): 9 | return path.read_text() 10 | return path.text() 11 | 12 | 13 | @pytest.mark.sphinx("html", testroot="canonical") # using roots/test-canonical 14 | def test_canonical(app, status, warning): 15 | app.build() 16 | 17 | assert app.statuscode == 0 18 | assert (app.outdir / "post.html").exists() 19 | assert (app.outdir / "canonical.html").exists() 20 | 21 | html = read_text(app.outdir / "post.html") 22 | assert '' in html 23 | 24 | html = read_text(app.outdir / "canonical.html") 25 | assert '' in html 26 | -------------------------------------------------------------------------------- /src/ablog/tests/test_external.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | 4 | def read_text(path): 5 | """ 6 | Support function to give backward compatibility with older sphinx (v2). 7 | """ 8 | if hasattr(path, "read_text"): 9 | return path.read_text() 10 | return path.text() 11 | 12 | 13 | @pytest.mark.sphinx("html", testroot="external") # using roots/test-external 14 | def test_external(app, status, warning): 15 | app.build() 16 | 17 | assert app.statuscode == 0 18 | assert (app.outdir / "external.html").exists() 19 | assert (app.outdir / "postlist.html").exists() 20 | 21 | html = read_text(app.outdir / "external.html") 22 | url = "https://www.sphinx-doc.org/en/master/" 23 | text = "This text will be in auto-generated post previews" 24 | # The page itself lacks the URL 25 | assert url not in html 26 | # It does have the text we added 27 | assert text in html 28 | 29 | html = read_text(app.outdir / "postlist.html") 30 | assert ( 31 | 'External post

    ' in html 32 | ) 33 | -------------------------------------------------------------------------------- /src/ablog/tests/test_parallel.py: -------------------------------------------------------------------------------- 1 | from pathlib import Path 2 | from subprocess import run 3 | import sys 4 | import pytest 5 | 6 | 7 | @pytest.mark.xfail("win" in sys.platform, reason="Passes on Windows") 8 | def test_not_safe_for_parallel_read(rootdir: Path, tmp_path: Path): 9 | """ 10 | Ablog is NOT safe for parallel read. 11 | 12 | In such case, it doesn't collect any posts. 13 | """ 14 | # https://github.com/sunpy/ablog/issues/297 15 | # Very ugly hack to change the parallel_read_safe value to True 16 | good_read_safe = '"parallel_read_safe": False' 17 | bad_read_safe = '"parallel_read_safe": True' 18 | init_py_path = Path(__file__).parent.parent / "__init__.py" 19 | assert good_read_safe in init_py_path.read_text(encoding="utf-8") 20 | bad_init_py = init_py_path.read_text().replace(good_read_safe, bad_read_safe) 21 | init_py_path.write_text(bad_init_py, encoding="utf-8") 22 | 23 | # liborjelinek: I wasn't able to demonstrate the issue with the `parallel` argument to the `sphinx` fixture 24 | # @pytest.mark.sphinx("html", testroot="parallel", parallel=2) 25 | # therefore running sphinx-build externally 26 | indir = rootdir / "test-parallel" 27 | run(["sphinx-build", "-b", "html", indir.as_posix(), tmp_path.as_posix(), "-j", "auto"], check=True) 28 | 29 | # And posts are not collected by Ablog... 30 | html = (tmp_path / "postlist.html").read_text(encoding="utf-8") 31 | assert "post 1" not in html 32 | assert "post 2" not in html 33 | assert "post 3" not in html 34 | assert "post 4" not in html 35 | -------------------------------------------------------------------------------- /src/ablog/tests/test_postlist.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | 4 | def read_text(path): 5 | """ 6 | Support function to give backward compatibility with older sphinx (v2). 7 | """ 8 | if hasattr(path, "read_text"): 9 | return path.read_text() 10 | return path.text() 11 | 12 | 13 | @pytest.mark.sphinx("html", testroot="postlist") # using roots/test-postlist 14 | def test_postlist(app, status, warning): 15 | app.build() 16 | 17 | assert app.statuscode == 0 18 | assert (app.outdir / "postlist.html").exists() 19 | 20 | html = read_text(app.outdir / "postlist.html") 21 | assert '
      ' in html 22 | assert ( 23 | '
    • 01 December - post

    • ' 24 | in html 25 | ) 26 | 27 | 28 | @pytest.mark.sphinx("html", testroot="postlist", confoverrides={"post_date_format_short": "%Y-%m-%d"}) 29 | def test_postlist_date_format_conf(app, status, warning): 30 | app.build() 31 | 32 | assert app.statuscode == 0 33 | 34 | html = read_text(app.outdir / "postlist.html") 35 | assert ( 36 | '
    • 2020-12-01 - post

    • ' 37 | in html 38 | ) 39 | -------------------------------------------------------------------------------- /src/ablog/tests/test_templates.py: -------------------------------------------------------------------------------- 1 | from pathlib import Path 2 | import pytest 3 | from sphinx.application import Sphinx 4 | from sphinx.errors import ThemeError 5 | 6 | 7 | @pytest.mark.sphinx("html", testroot="templates", confoverrides={"skip_injecting_base_ablog_templates": True}) 8 | def test_skip_ablog_templates_but_missing_templates(app: Sphinx): 9 | """ 10 | Completely override the templates used by ablog, but not provide them. 11 | """ 12 | with pytest.raises( 13 | ThemeError, 14 | match=r"An error happened in rendering the page blog/author\.\nReason: TemplateNotFound\(\"'ablog/catalog.html' not found in *.", 15 | ): 16 | app.build() 17 | 18 | 19 | @pytest.mark.sphinx( 20 | "html", 21 | testroot="templates", 22 | confoverrides={ 23 | "templates_path": ["_templates"], 24 | "skip_injecting_base_ablog_templates": False, # default value 25 | "html_sidebars": { 26 | "**": [ 27 | # overridden by user 28 | "ablog/postcard.html", 29 | # fallback to builtin 30 | "ablog/authors.html", 31 | ] 32 | }, 33 | }, 34 | ) 35 | def test_override_template_but_fallback_missing(app: Sphinx, rootdir: Path): 36 | """ 37 | Partially override the only some Ablog templates, but use the Ablog ones 38 | for missing as fallback. 39 | """ 40 | app.build() 41 | 42 | # is the customized template it in the output? 43 | customized = (rootdir / "test-templates" / "_templates" / "ablog" / "postcard.html").read_text() 44 | source = (app.outdir / "post.html").read_text() 45 | assert customized in source 46 | 47 | # is builtin template in the output? 48 | builtin = '
      ' 49 | assert builtin in source 50 | 51 | 52 | @pytest.mark.sphinx( 53 | "html", 54 | testroot="templates", 55 | confoverrides={ 56 | "html_sidebars": { 57 | "**": [ 58 | # overridden by theme 59 | "ablog/postcard.html", 60 | # fallback to builtin 61 | "ablog/authors.html", 62 | ] 63 | }, 64 | "html_theme_path": "_themes", 65 | "html_theme": "test_theme", 66 | }, 67 | ) 68 | def test_themes_templates_come_first(app: Sphinx, rootdir: Path): 69 | """ 70 | Ensures that if theme supplies own Ablog template, it is used over the 71 | builtin one, but fallback to builtin for missing ones. 72 | """ 73 | app.build() 74 | 75 | # is the customized template it in the output? 76 | customized = (rootdir / "test-templates" / "_themes" / "test_theme" / "ablog" / "postcard.html").read_text() 77 | source = (app.outdir / "post.html").read_text() 78 | assert customized in source 79 | 80 | # is builtin template in the output? 81 | builtin = '
      ' 82 | assert builtin in source 83 | -------------------------------------------------------------------------------- /src/ablog/version.py: -------------------------------------------------------------------------------- 1 | try: 2 | from ._version import version 3 | except Exception: 4 | import warnings 5 | 6 | warnings.warn(f"could not determine {__name__.split('.')[0]} package version; this indicates a broken installation") 7 | del warnings 8 | 9 | version = "0.0.0" 10 | 11 | from packaging.version import parse as _parse 12 | 13 | _version = _parse(version) 14 | major, minor, bugfix = [*_version.release, 0][:3] 15 | release = not _version.is_devrelease 16 | 17 | __all__ = ["version", "major", "minor", "bugfix", "release"] 18 | -------------------------------------------------------------------------------- /tox.ini: -------------------------------------------------------------------------------- 1 | [tox] 2 | envlist = 3 | py{39,310,311,312}{-sphinx6,-sphinx7,-sphinx8,-sphinx9,-devdeps,-docs,-linkcheck,-pydata-sphinx-theme} 4 | 5 | [testenv] 6 | allowlist_externals = 7 | make 8 | git 9 | extras = 10 | dev 11 | commands = 12 | # Have to do this here as myst-parser in the install step forces the version. 13 | sphinx6: pip install -U "sphinx>=6.0,<7.0" 14 | sphinx7: pip install -U "sphinx>=7.0,<8.0" 15 | sphinx8: pip install -U "sphinx>=8.0,<9.0" 16 | sphinx9: pip install -U "sphinx>=9.0,<10.0" 17 | devdeps: pip install -U "docutils @ git+https://github.com/docutils/docutils.git\#\&subdirectory=docutils" 18 | devdeps: pip install -U "git+https://github.com/sphinx-doc/sphinx" 19 | pip freeze --all --no-input 20 | pytest -vvv -r a --pyargs ablog 21 | make tests 22 | 23 | [testenv:docs] 24 | changedir = docs 25 | description = Invoke sphinx-build to build the HTML docs 26 | commands = 27 | sphinx-build -j auto --color -W --keep-going -b html -d _build/.doctrees . _build/html {posargs} 28 | python -c 'import pathlib; print("Documentation available under file://\{0\}".format(pathlib.Path(r"{toxinidir}") / "docs" / "_build" / "index.html"))' 29 | 30 | [testenv:pydata-sphinx-theme] 31 | commands = 32 | rm -rf pydata-sphinx-theme || true 33 | git clone git@github.com:pydata/pydata-sphinx-theme.git --depth 1 pydata-sphinx-theme 34 | pip install -e "pydata-sphinx-theme/.[dev]" 35 | pip freeze --all --no-input 36 | sphinx-build --color -W --keep-going -b html -d _build/.doctrees pydata-sphinx-theme/docs pydata-sphinx-theme/docs/_build/html {posargs} 37 | 38 | [testenv:linkcheck] 39 | changedir = docs 40 | description = Invoke sphinx-build to check linkcheck works 41 | commands = 42 | sphinx-build --color -W --keep-going -b linkcheck . _build/html {posargs} 43 | --------------------------------------------------------------------------------