Repository: capjamesg/aurora Branch: main Commit: 597037eee3c9 Files: 93 Total size: 167.5 KB Directory structure: gitextract_c93td2o_/ ├── .github/ │ ├── ISSUE_TEMPLATE/ │ │ └── bug-report.yml │ ├── dependabot.yml │ └── workflows/ │ ├── benchmark.yml │ ├── docs.yml │ ├── full-site-tests.yml │ ├── release.yml │ ├── test.yml │ └── welcome.yml ├── .gitignore ├── .pre-commit-config.yaml ├── CHANGELOG.md ├── CITATION.cff ├── LICENSE ├── Makefile ├── README.md ├── aurora/ │ ├── __init__.py │ ├── cli.py │ ├── date_helpers.py │ ├── graph.py │ └── templates/ │ └── index.html ├── docs/ │ ├── assets/ │ │ ├── prism.css │ │ └── prism.js │ ├── config.py │ ├── highlighting.py │ ├── pages/ │ │ ├── _layouts/ │ │ │ └── default.html │ │ └── templates/ │ │ ├── 404.html │ │ ├── archives.md │ │ ├── blog.html │ │ ├── build-methods.md │ │ ├── collections-from-data.html │ │ ├── collections.md │ │ ├── configuration.html │ │ ├── dates.html │ │ ├── design.html │ │ ├── hooks.html │ │ ├── index.html │ │ ├── pagination.md │ │ ├── performance.html │ │ ├── permalinks.html │ │ ├── robots.html │ │ ├── sitemap.html │ │ ├── start.html │ │ ├── state.html │ │ ├── structure.html │ │ ├── templates.md │ │ ├── templating.md │ │ └── users.html │ └── state.json ├── requirements.txt ├── setup.py └── tests/ ├── fixtures/ │ ├── about.html │ ├── about_ISO-8859-1.html │ ├── about_UTF-16-BE.html │ ├── about_Windows-1252.html │ ├── book.html │ ├── book_list.html │ ├── category_archive.html │ ├── collection_pagination.html │ ├── date_year.html │ ├── date_year_month.html │ ├── date_year_month_day.html │ ├── index.html │ ├── new_site_config.py │ ├── post.html │ ├── review.html │ ├── robots.txt │ ├── styles.css │ └── tag_archive.html ├── library/ │ ├── assets/ │ │ ├── meta/ │ │ │ └── robots.txt │ │ └── styles.css │ ├── config.py │ ├── hooks.py │ ├── pages/ │ │ ├── _data/ │ │ │ ├── books.json │ │ │ └── reviews.csv │ │ ├── _layouts/ │ │ │ ├── book-template.html │ │ │ ├── category.html │ │ │ ├── date.html │ │ │ ├── default.html │ │ │ ├── post.html │ │ │ ├── reader-review.html │ │ │ ├── rooms.html │ │ │ └── tag.html │ │ ├── posts/ │ │ │ └── 2024-01-01-first-post.md │ │ ├── rooms/ │ │ │ ├── quiet-corner.html │ │ │ └── study-hall.html │ │ └── templates/ │ │ ├── about.html │ │ ├── about_ISO-8859-1.html │ │ ├── about_UTF-16-BE.html │ │ ├── about_Windows-1252.html │ │ ├── book_list.html │ │ └── index.html │ └── state.json └── state.py ================================================ FILE CONTENTS ================================================ ================================================ FILE: .github/ISSUE_TEMPLATE/bug-report.yml ================================================ name: Bug Report description: File a bug with Aurora. labels: [bug] body: - type: markdown attributes: value: | Thank you for submitting a bug report! - type: textarea attributes: label: Bug description: Provide a description of the bug you have encountered. If you are running into an error, please include the full error message. validations: required: true - type: textarea attributes: label: Minimal Reproducible Example description: > When asking a question, people will be better able to provide help if you provide code that they can easily understand and use to **reproduce** the problem. This is referred to by community members as creating a [minimal reproducible example](https://stackoverflow.com/help/minimal-reproducible-example). placeholder: | ``` # Code to reproduce your issue here ``` validations: required: false - type: textarea attributes: label: Additional description: Anything else you would like to share? ================================================ FILE: .github/dependabot.yml ================================================ version: 2 updates: - package-ecosystem: "github-actions" directory: "/" schedule: interval: "daily" - package-ecosystem: "pip" directory: "/" schedule: interval: "daily" ================================================ FILE: .github/workflows/benchmark.yml ================================================ name: Run benchmark (200k pages+) on: workflow_dispatch jobs: build: runs-on: ${{ matrix.os }} strategy: matrix: os: ["ubuntu-latest", "macos-latest"] python-version: ["3.13"] steps: - uses: actions/checkout@v6 - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v6 with: python-version: ${{ matrix.python-version }} cache: 'pip' - name: Install dependencies run: | python3 -m pip install --upgrade pip pip install -e . git clone https://github.com/capjamesg/aurora-hn-benchmark - name: Build main site env: SITE_ENV: ${{ secrets.SITE_ENV }} run: | cd aurora-hn-benchmark { time aurora build; } 2> time_output.txt echo "${{ matrix.os }} - Python ${{ matrix.python-version }}" > performance.txt echo "Commit: $(git rev-parse HEAD)" >> time_taken.txt cat time_output.txt | grep real | awk '{print $2}' >> performance.txt cat performance.txt ================================================ FILE: .github/workflows/docs.yml ================================================ name: Publish documentation on: push: branches: - main jobs: build: runs-on: ubuntu-latest strategy: matrix: python-version: [3.13] steps: - uses: actions/checkout@v6 - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v6 with: python-version: ${{ matrix.python-version }} cache: 'pip' - name: Install dependencies run: | python3 -m pip install --upgrade pip pip install -e . pip install pygments bs4 lxml cd docs - name: Build main site env: SITE_ENV: ${{ secrets.SITE_ENV }} run: | cd docs aurora build - name: rsync deployments uses: burnett01/rsync-deployments@7.1.0 with: switches: -avzr path: "docs/_site/*" remote_path: ${{ secrets.SITE_PATH }} remote_host: ${{ secrets.SERVER_HOST }} remote_user: ${{ secrets.SERVER_USERNAME }} remote_key: ${{ secrets.KEY }} ================================================ FILE: .github/workflows/full-site-tests.yml ================================================ name: Test several sites built with Aurora on: push: branches: - main jobs: build: runs-on: ${{ matrix.os }} strategy: matrix: os: ["ubuntu-latest", "macos-latest"] python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"] steps: - uses: actions/checkout@v6 - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v6 with: python-version: ${{ matrix.python-version }} cache: 'pip' - name: Install dependencies run: | python3 -m pip install --upgrade pip pip install -e . - name: Build airport pianos env: SITE_ENV: ${{ secrets.SITE_ENV }} run: | git clone https://github.com/capjamesg/airport-pianos cd airport-pianos aurora build - name: Build train station pianos env: SITE_ENV: ${{ secrets.SITE_ENV }} run: | git clone https://github.com/capjamesg/train-station-pianos cd train-station-pianos aurora build - name: Build blog example env: SITE_ENV: ${{ secrets.SITE_ENV }} run: | git clone https://github.com/capjamesg/aurora-blog-template cd aurora-blog-template aurora build - name: Build docs example env: SITE_ENV: ${{ secrets.SITE_ENV }} run: | git clone https://github.com/capjamesg/aurora-docs-template cd aurora-docs-template aurora build ================================================ FILE: .github/workflows/release.yml ================================================ name: Publish WorkFlow on: release: types: [created] jobs: build: runs-on: ubuntu-latest strategy: matrix: python-version: [3.8] steps: - name: 🛎️ Checkout uses: actions/checkout@v6 with: ref: ${{ github.head_ref }} - name: 🐍 Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v6 with: python-version: ${{ matrix.python-version }} - name: 🦾 Install dependencies run: | python -m pip install --upgrade pip twine wheel - name: 🚀 Publish to PyPi env: PYPI_USERNAME: ${{ secrets.PYPI_USERNAME }} PYPI_PASSWORD: ${{ secrets.PYPI_PASSWORD }} run: | python setup.py sdist bdist_wheel twine check dist/* twine upload dist/* -u ${PYPI_USERNAME} -p ${PYPI_PASSWORD} --verbose ================================================ FILE: .github/workflows/test.yml ================================================ name: Aurora Test Suite on: pull_request: branches: [main] push: branches: [main] jobs: build-dev-test: runs-on: ${{ matrix.os }} strategy: matrix: os: ["ubuntu-latest", "macos-latest"] python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"] steps: - name: 🛎️ Checkout uses: actions/checkout@v6 - name: 🐍 Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v6 with: python-version: ${{ matrix.python-version }} check-latest: true - name: 📦 Install dependencies run: | python -m pip install --upgrade pip pip install . pip install pytest - name: 🧪 Test env: SITE_ENV: production run: "python -m pytest ./tests/state.py" ================================================ FILE: .github/workflows/welcome.yml ================================================ name: Welcome on: [pull_request, issues] jobs: greeting: name: 👋 Welcome runs-on: ubuntu-latest steps: - uses: actions/first-interaction@v3 with: repo-token: ${{ secrets.GITHUB_TOKEN }} issue-message: "Thank you for creating an Issue on this repository! 🙌 We will get back to you shortly." pr-message: "Thank you for creating an PR on this repository! 🙌 We will get back to you shortly." ================================================ FILE: .gitignore ================================================ # env specific config.json .env # Byte-compiled / optimized / DLL files __pycache__/ *.py[cod] *$py.class .idea # C extensions *.so # Distribution / packaging .Python build/ develop-eggs/ dist/ downloads/ eggs/ .eggs/ lib/ lib64/ parts/ sdist/ var/ wheels/ share/python-wheels/ *.egg-info/ .installed.cfg *.egg MANIFEST .gptexecthread # PyInstaller # Usually these files are written by a python script from a template # before PyInstaller builds the exe, so as to inject date/other infos into it. *.manifest *.spec # Installer logs pip-log.txt pip-delete-this-directory.txt # Unit test / coverage reports htmlcov/ .tox/ .nox/ .coverage .coverage.* .cache nosetests.xml coverage.xml *.cover *.py,cover .hypothesis/ .pytest_cache/ cover/ # Translations *.mo *.pot # Django stuff: *.log local_settings.py db.sqlite3 db.sqlite3-journal # Flask stuff: instance/ .webassets-cache # Scrapy stuff: .scrapy # Sphinx documentation docs/_build/ # PyBuilder .pybuilder/ target/ # Jupyter Notebook .ipynb_checkpoints # IPython profile_default/ ipython_config.py # pyenv # For a library or package, you might want to ignore these files since the code is # intended to run in multiple environments; otherwise, check them in: # .python-version # pipenv # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. # However, in case of collaboration, if having platform-specific dependencies or dependencies # having no cross-platform support, pipenv may install dependencies that don't work, or not # install all needed dependencies. #Pipfile.lock # PEP 582; used by e.g. github.com/David-OConnor/pyflow __pypackages__/ # Celery stuff celerybeat-schedule celerybeat.pid # SageMath parsed files *.sage.py # Environments .env .venv env/ venv/ ENV/ env.bak/ venv.bak/ # Spyder project settings .spyderproject .spyproject # Rope project settings .ropeproject # mkdocs documentation /site # mypy .mypy_cache/ .dmypy.json dmypy.json # Pyre type checker .pyre/ # pytype static type analyzer .pytype/ # Cython debug symbols cython_debug/ #config stuff tests/config.json tests/manual/data #dataset download stuff # test/ # train/ # valid/ # data.yaml README.roboflow.txt *.zip .DS_Store _site/* docs/_site/* tests/library/_site/* ================================================ FILE: .pre-commit-config.yaml ================================================ ================================================ FILE: CHANGELOG.md ================================================ # Changelog All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [0.0.4] 2024-05-28 * Add support for data files ## [0.0.2] 2024-05-28 * Fix bug where `page` data was not available in parent templates. * Add `pages` variable that can be used to see a list of all pages in a template. * Small performance improvements. * Fix missing `click` dependency. ## [0.0.1] 2024-05-27 Initial release of Aurora. ================================================ FILE: CITATION.cff ================================================ # This CITATION.cff file was generated with cffinit. # Visit https://bit.ly/cffinit to generate yours today! cff-version: 1.2.0 title: Aurora message: >- If you use this software, please cite it using the metadata from this file. type: software authors: - given-names: James email: jamesg@jamesg.blog repository-code: 'https://github.com/capjamesg/aurora' url: 'https://github.com/capjamesg/aurora' abstract: >- A static site generator implemented in Python. keywords: - static site generator - website license: MIT ================================================ FILE: LICENSE ================================================ MIT License Copyright (c) 2024 James Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: Makefile ================================================ .PHONY: style check_code_quality export PYTHONPATH = . check_dirs := aurora style: black $(check_dirs) isort --profile black $(check_dirs) check_code_quality: black --check $(check_dirs) isort --check-only --profile black $(check_dirs) # stop the build if there are Python syntax errors or undefined names flake8 $(check_dirs) --count --select=E9,F63,F7,F82 --show-source --statistics # exit-zero treats all errors as warnings. E203 for black, E501 for docstring, W503 for line breaks before logical operators flake8 $(check_dirs) --count --max-line-length=88 --exit-zero --ignore=D --extend-ignore=E203,E501,W503 --statistics publish: python3 -m build twine check dist/* twine upload dist/* -u ${PYPI_USERNAME} -p ${PYPI_PASSWORD} --verbose ================================================ FILE: README.md ================================================ 
Below are some helpful links to get you started in making your site with Aurora.
================================================ FILE: docs/assets/prism.css ================================================ /* PrismJS 1.29.0 https://prismjs.com/download.html#themes=prism&languages=markup+bash+python */ code[class*=language-],pre[class*=language-]{color:#000;background:0 0;text-shadow:0 1px #fff;font-family:Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}code[class*=language-] ::-moz-selection,code[class*=language-]::-moz-selection,pre[class*=language-] ::-moz-selection,pre[class*=language-]::-moz-selection{text-shadow:none;background:#b3d4fc}code[class*=language-] ::selection,code[class*=language-]::selection,pre[class*=language-] ::selection,pre[class*=language-]::selection{text-shadow:none;background:#b3d4fc}@media print{code[class*=language-],pre[class*=language-]{text-shadow:none}}pre[class*=language-]{padding:1em;margin:.5em 0;overflow:auto}:not(pre)>code[class*=language-],pre[class*=language-]{background:#f5f2f0}:not(pre)>code[class*=language-]{padding:.1em;border-radius:.3em;white-space:normal}.token.cdata,.token.comment,.token.doctype,.token.prolog{color:#708090}.token.punctuation{color:#999}.token.namespace{opacity:.7}.token.boolean,.token.constant,.token.deleted,.token.number,.token.property,.token.symbol,.token.tag{color:#905}.token.attr-name,.token.builtin,.token.char,.token.inserted,.token.selector,.token.string{color:#690}.language-css .token.string,.style .token.string,.token.entity,.token.operator,.token.url{color:#9a6e3a;background:hsla(0,0%,100%,.5)}.token.atrule,.token.attr-value,.token.keyword{color:#07a}.token.class-name,.token.function{color:#dd4a68}.token.important,.token.regex,.token.variable{color:#e90}.token.bold,.token.important{font-weight:700}.token.italic{font-style:italic}.token.entity{cursor:help} ================================================ FILE: docs/assets/prism.js ================================================ /* PrismJS 1.29.0 https://prismjs.com/download.html#themes=prism&languages=markup+bash+python */ var _self="undefined"!=typeof window?window:"undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?self:{},Prism=function(e){var n=/(?:^|\s)lang(?:uage)?-([\w-]+)(?=\s|$)/i,t=0,r={},a={manual:e.Prism&&e.Prism.manual,disableWorkerMessageHandler:e.Prism&&e.Prism.disableWorkerMessageHandler,util:{encode:function e(n){return n instanceof i?new i(n.type,e(n.content),n.alias):Array.isArray(n)?n.map(e):n.replace(/&/g,"&").replace(/=g.reach);A+=w.value.length,w=w.next){var E=w.value;if(n.length>e.length)return;if(!(E instanceof i)){var P,L=1;if(y){if(!(P=l(b,A,e,m))||P.index>=e.length)break;var S=P.index,O=P.index+P[0].length,j=A;for(j+=w.value.length;S>=j;)j+=(w=w.next).value.length;if(A=j-=w.value.length,w.value instanceof i)continue;for(var C=w;C!==n.tail&&(jThis page does not exist. Go back to the homepage.
================================================ FILE: docs/pages/templates/archives.md ================================================ --- title: Date, Category, and Tag Archives layout: default permalink: /archives/ --- Aurora has support built-in for generating date, category, and tag archives. These are useful for blogs. ## Date Archives Aurora automatically generates date archives for blog posts. You do not need to configure any setting to use this feature. Date archives are generated as follows: - `https://example.com/2024/`: All posts published in 2024. - `https://example.com/2024/01/`: All posts published in January 2024. - `https://example.com/2024/01/01/`: All posts published on January 1, 2024. ## Category and Tag Archives Aurora automatically generates category and tag archives. These archives are generated if you specify `category` and/or `tag` attributes in your blog post front matters. Category archives are generated as follows: - `https://example.com/category/SITE_STATE = {
"category_slug_root": "categories",
"tag_slug_root": "tags",
}
The above example would change the category and tag paths to:
- `https://example.com/categories/Aurora has out-of-the-box features designed for use with blogs.
To use Aurora as a blog, create a markdown file with the following name structure in your pages/posts directory:
YYYY-MM-DD-title.md
For example, 2020-01-01-hello-world.md.
Within this file, you can specify front matter and, optionally, jinja2 templating.
Here is an example:
---
title: Hello, World!
layout: post
---
This is our first blog post.
This will be rendered as a blog post using the "pages/_layouts/post.html" file.
Aurora automatically turns your permalink into a URL. For example, the above file will be available at https://example.com/2020/01/01/hello-world/.
Aurora can automatically generate archive pages for categories and tags.
Categories and tags are treated as two separate collections.
To use this feature, you need to give at least one blog post a category or a tag, like so:
---
title: Hello, World!
layout: post
categories:
- Announcement
---
This is our first blog post.
Categories and tags are not case-sensitive.
You then need to specify either a category or tag layout file, depending on which you want to support.
To do so, create a file called category.html or tag.html in your pages/_layouts directory.
This file will have access to a page.posts variable that lists all posts in the category or tag.
Here is an example of a category layout file:
{% raw %}
---
layout: default
title: "Category Archive"
---
<ul>
{% for post in page.posts %}
<li>
<a href="{{ post.url }}">{{ post.title }}</a>
</li>
{% endfor %}
</ul>
{% endraw %}
In this example, a page at /category/announcement/index.html will be generated.
Aurora can automatically generate date pages for categories and tags.
Date archives show all posts published on a specific day.
There is not currently support for month-based or year-based archives.
To use this feature, you need to have at least one blog post.
You then need to specify a date archive layout.
To do so, create a file called date.html in your pages/_layouts directory.
This file will have access to a page.posts variable that lists all posts published on a specific day.
Here is an example of a category layout file:
{% raw %}
---
layout: default
title: "Date Archive"
---
<ul>
{% for post in page.posts %}
<li>
<a href="{{ post.url }}">{{ post.title }}</a>
</li>
{% endfor %}
</ul>
{% endraw %}
In this example, a page at /2024/01/01/index.html will be generated, which lists one entry: the hello world post we wrote earlier in this guide.
Now you have a blog set up with Aurora! 🎉
================================================ FILE: docs/pages/templates/build-methods.md ================================================ --- title: Build Methods permalink: /build-methods/ layout: default --- There are three ways you can build your Aurora site: 1. Full build 2. Incremental build 3. Interactive, incremental build ## Full Build A full build generates your entire website. Your site is saved in `_site`, ready for serving. To build your site, navigate to the root directory of your project (the folder with the `config.py` file in it), and run:aurora build
Your site will be saved in and ready to serve from the `_site` directory.
## Incremental Build
An incremental build generates only the files that have changed since the last build. This is faster than a full build.
If you have not fully built your site before, the incremental build will fully build your site first. Then, subsequent runs will only build the files that have changed since the last build.
For example, suppose you have 1,000 pages on your site. You have already built your site, and now you change one file. With the incremental build, option, only the page you changed -- and its dependencies -- will be regenerated.
Incremental builds are designed to speed up the build process, particularly for large sites with thousands or tens of thousands of pages.
To run an incremental build, navigate to the root directory of your project and run:
aurora build --incremental
Tip: Incremental builds support CSV and JSON data files.
## Interactive, Incremental Build An interactive, incremental build generates your full site. It starts a web server through which you can preview pages. When you make a change to any file, the changed file -- and its dependencies -- are re-built and made available over the server. Any open browser tabs that are viewing the site will automatically refresh to show the changes. This mode is intended for development. With interactive, incremental building, you can see changes to your site as you make them, without having to wait for your full site to build, and without having to manually refresh your browser. To run an interactive, incremental build, navigate to the root directory of your project and run:aurora serve
A server will start on `http://localhost:8000`. Open this URL in your browser to view your site.
Note: The interactive server should not be used in production.
================================================ FILE: docs/pages/templates/collections-from-data.html ================================================ --- title: Create a Collection from Data permalink: /collections-from-data/ layout: default ---You can turn data from JSON and CSV files into web pages.
This is useful if you have a data set that you want to turn into a website.
For example, you could export a list of coffee shops you have visited from a spreadsheet and turn the list into a static website.
To create a collection from a JSON file, add a new file to your site's
pages/_data directory. This file should have a
.json extension.
Within the file, create a list that contains JSON objects, like this:
[
{
"slug": "rosslyn-coffee",
"layout": "coffee",
"title": "Rosslyn Coffee in London is terrific."
}
]
This file is called
pages/_data/coffee.json.
Every entry must have a layout key. This corresponds
with the name of the template that will be used to render the page. For
example, the coffee layout will be rendered using the
pages/_layouts/coffee.html template.
Every entry must also have a slug key. This corresponds
with the name of the page that will be generated. In the case above, one
file will be created in the _site output directory:
_site/coffee/rosslyn-coffee/index.html.
To create a collection from a CSV file, add a new file to your site's
pages/_data directory. This file should have a
.json extension.
Here is an example CSV file:
slug,layout,title
rosslyn-coffee,coffee,Rosslyn Coffee in London is terrific.
Your CSV file must have a header row that contains the keys for each entry.
This file is called
pages/_data/coffee.csv.
Every entry must have a layout key. This corresponds
with the name of the template that will be used to render the page. For
example, the coffee layout will be rendered using the
pages/_layouts/coffee.html template.
Every entry must also have a slug key. This corresponds
with the name of the page that will be generated. In the case above, one
file will be created in the _site output directory:
_site/coffee/rosslyn-coffee/index.html.
To create a collection from a JSON file, add a new file to your site's
pages/_data directory. This file should have a
.json extension.
Within the file, create a list that contains JSON objects, like this:
[
{
"slug": "rosslyn-coffee",
"layout": "coffee",
"title": "Rosslyn Coffee in London is terrific."
}
]
This file is called
pages/_data/coffee.json.
Every entry must have a layout key. This corresponds
with the name of the template that will be used to render the page. For
example, the coffee layout will be rendered using the
pages/_layouts/coffee.html template.
Every entry must also have a slug key. This corresponds
with the name of the page that will be generated. In the case above, one
file will be created in the _site output directory:
_site/coffee/rosslyn-coffee/index.html.
To create a collection from a CSV file, add a new file to your site's
pages/_data directory. This file should have a
.csv extension.
Here is an example CSV file:
slug,layout,title
rosslyn-coffee,coffee,Rosslyn Coffee in London is terrific.
Your CSV file must have a header row that contains the keys for each entry.
This file is called
pages/_data/coffee.csv.
Every entry must have a layout key. This corresponds
with the name of the template that will be used to render the page. For
example, the coffee layout will be rendered using the
pages/_layouts/coffee.html template.
Every entry must also have a slug key. This corresponds
with the name of the page that will be generated. In the case above, one
file will be created in the _site output directory:
_site/coffee/rosslyn-coffee/index.html.
---
title: My Page
collections: coffee
---
You can then access the collection like so:
{% raw %}{% for item in coffee %}{% endraw %}
{{ item.title }}
{% raw %}{% endfor %}{% endraw %}
================================================
FILE: docs/pages/templates/configuration.html
================================================
---
title: Configure Your Website
layout: default
---
You need a config.py file in the directory in which you will
build your Aurora site. This file is automatically generated when you run
aurora new [site-name].
This configuration file defines a few values that Aurora will use when processing your website.
Here is the default config.py file, with accompanying comments:
import os
BASE_URLS = {
"local": os.getcwd(),
}
SITE_ENV = os.environ.get("SITE_ENV", "local")
BASE_URL = BASE_URLS[SITE_ENV]
ROOT_DIR = "pages" # where your site pages are
LAYOUTS_BASE_DIR = "_layouts" # where your site layouts are stored
SITE_DIR = "_site" # the directory in which your site will be saved
HOOKS = {} # used to register hooks (see Hooks documentation for details)
SITE_STATE = {}
The BASE_URLS dictionary is used to define the base URL for
your site. This is useful if you want to maintain multiple environments for
your site (e.g., local, staging, production).
Here is an example configuration of a site that has a local and staging environment:
BASE_URLS = {
"production": "https://jamesg.blog",
"staging": "https://staging.jamesg.blog",
"local": os.getcwd(),
}
Aurora has several default filters that you can use to handle dates.
These filters can be used like:
{% raw %}{{ date | long_date }}
{{ date | date_to_xml_string }}
{{ date | archive_date }}
{{ date | month_number_to_written_month }}{% endraw %}
================================================
FILE: docs/pages/templates/design.html
================================================
---
title: Aurora Design
permalink: /design/
layout: default
---
I have written several blog posts that explore the design, inspiration, and development of Aurora.
See a list of these posts below.
You can define custom functions that are run before a file is processed by Aurora. You can use this feature to save metadata about a page that can then be consumed by a template.
These functions are called "hooks".
There are three types of hooks, which run:
template_filters hook)pre_generation hook)post_build hook)
To define a hook, you need to:
HOOKS dictionary in your config.py file.
Below are instructions on how to define each type of hook.
Filter hooks are registered as a jinja2 filter.
These hooks are useful for manipulating specific values in a template (i.e. formatting dates, changing text).
The type signature of this hook is:
def hook_name(text: str) -> str:
return text.upper()
You can register this hook in the template_filter hook:
HOOKS = {
"template_filter": {
"example": ["hook_name"]
}
}
This hook can then be used in any template on your website:
<h1> "hello world" | hook_name </h1>
Pre-generation hooks run immediately before a page is generated.
These hooks are useful for adding state to a page for use in rendering (i.e. loading link prveiews from a cache, calculating reading times.)
The type signature of this hook is:
def hook_name(file_name: str, page_state: dict, site_state: dict) -> dict:
return page_state
You can register this hook in the template_filter hook:
HOOKS = {
"pre_generation": {
"example": ["hook_name"]
}
}
Post-build hooks run after your site has been built.
These hooks are useful for performing actions after your site has been built (i.e. saving a log of last generation time, invoking CSS/JS minification).
The type signature of this hook is:
def hook_name(site_state: str) -> None:
pass
You can register this hook in the template_filter hook:
HOOKS = {
"post_build": {
"example": ["hook_name"]
}
}
================================================
FILE: docs/pages/templates/index.html
================================================
---
title: Aurora
layout: default
---
Aurora is a static site generator implemented in Python.
With Aurora, you can generate thousands of static web pages in seconds.
Aurora supports:
Aurora is open source, and licensed under an MIT license.
Build your first website with Aurora.
SITE_STATE = {
"paginators": {
"books": {
"per_page": 10,
"template": "books"
}
}
}
================================================
FILE: docs/pages/templates/performance.html
================================================
---
title: Performance
layout: default
---
In a test generating 292,884 files from a CSV file with a single layer of inheritance in each template, Aurora built the website in 140.59 seconds (2m:20s).
In a test on a website with 1,763 files and multiple layers of inheritance, Aurora built the website in 3.149s. The files in this test were a combination of blog posts, static pages, and programmatic archives for blog posts (date pages, category pages).
In a test rendering 4,000 markdown files with a single layer of inheritance in each template, Aurora built the website in between 0.9 and 1.2 seconds.
In a test comparing 11ty to Aurora in generating the Airport Pianos website (~45 pages), 11ty took 1.36 seconds to start and generate the site, whereas Aurora took 0.034 seconds.
================================================ FILE: docs/pages/templates/permalinks.html ================================================ --- title: Set a Permalink layout: default permalink: /permalinks/ ---You can define custom permalinks for a page in its front matter.
To do so, specify the permalink key:
---
title: Book List
permalink: /books/
layout: default
---
The page above will be generated with the path /books/.
robots.txt files let you tell search engines which pages they can and can't index.
To define a robots.txt file, create a file called robots.txt in your pages/templates/ directory.
Here's an example of a robots.txt file that lets all bots crawl all pages, and points to your sitemap for reference:
User-agent: *
Allow: /
Sitemap: /sitemap.xml
To define a sitemap, create a file called sitemap.xml in your pages/templates/ directory and add the following code:
{% raw %}<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
{% for page in site.pages %}
{% if not page.noindex %}
<url>
<loc>
{{ page.url }}
</loc>
<lastmod>{{ site.build_time }}</lastmod>
</url>
{% endif %}
{% endfor %}
</urlset>{% endraw %}
================================================
FILE: docs/pages/templates/start.html
================================================
---
title: Start a Website
permalink: /start/
layout: default
---
Learn how to create a website with Aurora.
First, install Aurora:
pip3 install aurora-ssg
To create a new site, run the following command:
aurora new my-site
cd my-site
This will create a folder called
my-site with everything you need to start your Aurora site.
There are two ways to run Aurora:
_site, which you can view on your file system.http://localhost:8000 on which your site will run. This is ideal for development.To see your site locally, run:
aurora serve
This will start a local server at
http://localhost:8000 on which your site will run.
When you are ready to publish your site, you can run:
aurora build
This will build your site into a folder called _site, which you can then upload to a web server.
You have started an Aurora website 🎉.
Next up: Add a page to your website.
================================================ FILE: docs/pages/templates/state.html ================================================ --- title: State permalink: /state/ layout: default ---There are three types of state in Aurora: page, post and site.
Page state stores values that are only available on that page.
For example, consider the following template:
---
title: Hello, World!
layout: default
---
Welcome to the website!
Any value in the front matter is stored in the page state. This state can be accessed using:
{% raw %}{{ page.title }}{% endraw %}
Tip
You can access the name of the template from which a page was generated with:
{% raw %}{{ page.generated_from }}{% endraw %}
This is useful if you want to make a public edit page to a GitHub repository, like the one in the footer of this documentation.
Post state stores information about a blog post.
You can access post state on any template that is used by a post.
For example, consider the following template called pages/_layouts/post.html for rendering a blog post:
---
layout: default
---
<h1>{% raw %}{{ post.title }}{% endraw %}</h1>
<p>{% raw %}{{ post.content }}{% endraw %}</p>
Here, we access the title and content of the post using the post state.
This template (pages/_layouts/post.html) inherits from the default layout, and could be used on any blog post with:
---
layout: post
title: Hello, World!
---
...
Page state stores values that are global to the website.
You can access site state on any page.
By default, site state contains:
site.posts)site.root_url)site.build_date)site.pages)For example, consider the following template:
---
title: Blog Home
layout: default
---
{% raw %}
<ul>
{% for post in site.posts[:5] %}
<li>
<a href="{{ post.url }}">{{ post.title }}</a>
</li>
{% endfor %}
</ul>
{% endraw %}
Here, we iterate over the first five posts in the site state and display them on the page.
The above code could be used on a home page to display the most recent posts.
You can add custom values to your site state by adding to the SITE_STATE dictionary in your config.py file:
SITE_STATE = {
'site_version': os.getenv('SITE_VERSION', '1.0.0')
}
================================================
FILE: docs/pages/templates/structure.html
================================================
---
title: Website Structure
permalink: /structure/
layout: default
---
When you create a new Aurora site, some folders and files are created by default.
Below is a list of those files.
├── _site # where your generated site is stored
│ └── index.html
├── assets # where to store your CSS, JS, and images
├── config.py # your Aurora configuration
└── pages # any page in this directory is generated
├── _data # store JSON / CSV files to be used in generating pages
├── _layouts # page layouts
├── posts # blog posts
└── templates # store single pages to generate
└── index.html
Blog
Documentation
{{ post.content }}
{% endfor %} ``` ================================================ FILE: docs/pages/templates/users.html ================================================ --- title: Users layout: default ---The following sites are built with Aurora:
If you would like your site to be featured here, please submit a pull request to the Aurora GitHub repository.
================================================ FILE: docs/state.json ================================================ {"last_build": "2024-06-22T19:51:46.751675", "data_file_integrity": {"pages/test/apple/index.html": "542b47f9fbb9dca05694183f48c8fe925e193b45", "pages/test/banana/index.html": "f49e2e069c37a6fc12809ba2db409db23cccfba9", "apple": "542b47f9fbb9dca05694183f48c8fe925e193b45", "banana": "f49e2e069c37a6fc12809ba2db409db23cccfba9"}} ================================================ FILE: requirements.txt ================================================ jinja2 livereload toposort pyromark~=0.9.3 python-frontmatter requests progress click orjson tqdm chardet bs4 ================================================ FILE: setup.py ================================================ import re import setuptools from setuptools import find_packages with open("./aurora/__init__.py", "r") as f: content = f.read() # from https://www.py4u.net/discuss/139845 version = re.search(r'__version__\s*=\s*[\'"]([^\'"]*)[\'"]', content).group(1) with open("README.md", "r", encoding="UTF-8") as fh: long_description = fh.read() setuptools.setup( name="aurora-ssg", version=version, author="capjamesg", author_email="readers@jamesg.blog", description="A fast static site generator implemented in Python.", long_description=long_description, long_description_content_type="text/markdown", url="https://github.com/capjamesg/aurora", install_requires=[ "jinja2", "livereload", "toposort", "pyromark>=0.6,<0.10", "python-frontmatter", "requests", "progress", "click", "orjson", "tqdm", "python-dateutil", "chardet", "bs4" ], include_package_data=True, package_data={"": ["templates/index.html"]}, packages=find_packages(exclude=("tests",)), entry_points={ "console_scripts": [ "aurora = aurora.cli:main", ], }, extras_require={ "dev": [ "flake8", "black==25.11.0", "isort", "twine", "pytest", "wheel", "mkdocs-material", "mkdocs", ], }, classifiers=[ "Programming Language :: Python :: 3", "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", ], python_requires=">=3.7", ) ================================================ FILE: tests/fixtures/about.html ================================================We serve 100 readers every month.
================================================ FILE: tests/fixtures/about_ISO-8859-1.html ================================================A test of a file encoded with ISO-8859-1.
We serve 100 readers every month.
================================================ FILE: tests/fixtures/about_UTF-16-BE.html ================================================A test of a file encoded with UTF-16 BE.
We serve 100 readers every month.
================================================ FILE: tests/fixtures/about_Windows-1252.html ================================================A test of a file encoded with Windows-1252 .
We serve 100 readers every month.
================================================ FILE: tests/fixtures/book.html ================================================F. Scott Fitzgerald
================================================ FILE: tests/fixtures/book_list.html ================================================Below are the posts we wrote in 2024.
================================================ FILE: tests/fixtures/date_year_month.html ================================================Below are the posts we wrote in 2024/01.
================================================ FILE: tests/fixtures/date_year_month_day.html ================================================Below are the posts we wrote on January 01, 2024.
================================================ FILE: tests/fixtures/index.html ================================================This is our first blog post.
================================================ FILE: tests/fixtures/review.html ================================================An excellent book.
5/5 stars
================================================ FILE: tests/fixtures/robots.txt ================================================ User-Agent: * Allow: / ================================================ FILE: tests/fixtures/styles.css ================================================ * { font-family: San system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; } ================================================ FILE: tests/fixtures/tag_archive.html ================================================{{ page.author }}
================================================ FILE: tests/library/pages/_layouts/category.html ================================================ --- layout: default title: "Category Archive" ---Below are the posts we wrote in {{ page.date | year }}.
{% endif %} {% if page.date_type == "month" %}Below are the posts we wrote in {{ page.date | archive_date }}.
{% endif %} {% if page.date_type == "day" %}Below are the posts we wrote on {{ page.date | long_date }}.
{% endif %}{{ page.review }}
{{ page.star }}/5 stars
================================================ FILE: tests/library/pages/_layouts/rooms.html ================================================ --- layout: default title: Rooms ---We serve {{ page.visitors }} readers every month.
================================================ FILE: tests/library/pages/templates/about_ISO-8859-1.html ================================================ --- title: About ISO Test layout: default ---A test of a file encoded with ISO-8859-1.
We serve {{ page.visitors }} readers every month.
================================================ FILE: tests/library/pages/templates/about_Windows-1252.html ================================================ --- title: About Windows-1252 Test layout: default ---A test of a file encoded with Windows-1252 .
We serve {{ page.visitors }} readers every month.
================================================ FILE: tests/library/pages/templates/book_list.html ================================================ --- title: Book List permalink: /book-list/ layout: default ---