Full Code of getpelican/pelican for AI

main b5e20d7f6d85 cached
442 files
2.6 MB
706.7k tokens
806 symbols
1 requests
Download .txt
Showing preview only (2,816K chars total). Download the full file or copy to clipboard to get everything.
Repository: getpelican/pelican
Branch: main
Commit: b5e20d7f6d85
Files: 442
Total size: 2.6 MB

Directory structure:
gitextract_vbdoavsn/

├── .coveragerc
├── .editorconfig
├── .git-blame-ignore-revs
├── .gitattributes
├── .github/
│   ├── CODEOWNERS
│   ├── FUNDING.yml
│   ├── ISSUE_TEMPLATE/
│   │   ├── ---bug-report.md
│   │   ├── ---documentation.md
│   │   ├── ---enhancement-request.md
│   │   └── config.yml
│   ├── dependabot.yml
│   ├── pull_request_template.md
│   ├── stale.yml
│   └── workflows/
│       ├── github_pages.yml
│       └── main.yml
├── .gitignore
├── .mailmap
├── .pre-commit-config.yaml
├── .readthedocs.yaml
├── .vale.ini
├── CONTRIBUTING.rst
├── LICENSE
├── README.rst
├── THANKS
├── docs/
│   ├── Makefile
│   ├── _static/
│   │   └── theme_overrides.css
│   ├── _templates/
│   │   └── page.html
│   ├── changelog.rst
│   ├── conf.py
│   ├── content.rst
│   ├── contribute.rst
│   ├── faq.rst
│   ├── importer.rst
│   ├── index.rst
│   ├── install.rst
│   ├── internals.rst
│   ├── locale/
│   │   └── zh_CN/
│   │       └── LC_MESSAGES/
│   │           ├── changelog.po
│   │           ├── content.po
│   │           ├── contribute.po
│   │           ├── faq.po
│   │           ├── importer.po
│   │           ├── index.po
│   │           ├── install.po
│   │           ├── internals.po
│   │           ├── pelican-themes.po
│   │           ├── plugins.po
│   │           ├── publish.po
│   │           ├── quickstart.po
│   │           ├── report.po
│   │           ├── settings.po
│   │           ├── sphinx.po
│   │           ├── themes.po
│   │           └── tips.po
│   ├── pelican-themes.rst
│   ├── plugins.rst
│   ├── publish.rst
│   ├── quickstart.rst
│   ├── report.rst
│   ├── settings.rst
│   ├── themes.rst
│   └── tips.rst
├── pelican/
│   ├── __init__.py
│   ├── __main__.py
│   ├── cache.py
│   ├── contents.py
│   ├── generators.py
│   ├── log.py
│   ├── paginator.py
│   ├── plugins/
│   │   ├── _utils.py
│   │   └── signals.py
│   ├── readers.py
│   ├── rstdirectives.py
│   ├── server.py
│   ├── settings.py
│   ├── signals.py
│   ├── tests/
│   │   ├── TestPages/
│   │   │   ├── bad_page.rst
│   │   │   ├── draft_page.rst
│   │   │   ├── draft_page_markdown.md
│   │   │   ├── draft_page_with_template.rst
│   │   │   ├── hidden_page.rst
│   │   │   ├── hidden_page_markdown.md
│   │   │   ├── hidden_page_with_template.rst
│   │   │   ├── page.rst
│   │   │   ├── page_markdown.md
│   │   │   ├── page_used_for_sorting_test.rst
│   │   │   ├── page_with_category_and_tag_links.md
│   │   │   ├── page_with_static_links.md
│   │   │   └── page_with_template.rst
│   │   ├── __init__.py
│   │   ├── build_test/
│   │   │   ├── conftest.py
│   │   │   └── test_build_files.py
│   │   ├── content/
│   │   │   ├── 2012-11-29_rst_w_filename_meta#foo-bar.rst
│   │   │   ├── 2012-11-30_md_w_filename_meta#foo-bar.md
│   │   │   ├── TestCategory/
│   │   │   │   ├── article_with_category.rst
│   │   │   │   └── article_without_category.rst
│   │   │   ├── article.rst
│   │   │   ├── article_draft.md
│   │   │   ├── article_hidden.md
│   │   │   ├── article_skip.md
│   │   │   ├── article_with_attributes_containing_double_quotes.html
│   │   │   ├── article_with_capitalized_metadata.rst
│   │   │   ├── article_with_code_block.rst
│   │   │   ├── article_with_comments.html
│   │   │   ├── article_with_duplicate_tags_authors.md
│   │   │   ├── article_with_inline_svg.html
│   │   │   ├── article_with_keywords.html
│   │   │   ├── article_with_markdown_and_empty_tags.md
│   │   │   ├── article_with_markdown_and_footnote.md
│   │   │   ├── article_with_markdown_and_nested_metadata.md
│   │   │   ├── article_with_markdown_and_nonascii_summary.md
│   │   │   ├── article_with_markdown_and_summary_metadata_multi.md
│   │   │   ├── article_with_markdown_and_summary_metadata_single.md
│   │   │   ├── article_with_markdown_extension.markdown
│   │   │   ├── article_with_markdown_markup_extensions.md
│   │   │   ├── article_with_md_extension.md
│   │   │   ├── article_with_mdown_extension.mdown
│   │   │   ├── article_with_metadata.html
│   │   │   ├── article_with_metadata.rst
│   │   │   ├── article_with_metadata.unknownextension
│   │   │   ├── article_with_metadata_and_contents.html
│   │   │   ├── article_with_metadata_explicit_date_implicit_modified.html
│   │   │   ├── article_with_metadata_explicit_dates.html
│   │   │   ├── article_with_metadata_implicit_date_explicit_modified.html
│   │   │   ├── article_with_metadata_implicit_dates.html
│   │   │   ├── article_with_mkd_extension.mkd
│   │   │   ├── article_with_multiple_authors.html
│   │   │   ├── article_with_multiple_authors.rst
│   │   │   ├── article_with_multiple_authors_list.rst
│   │   │   ├── article_with_multiple_authors_semicolon.rst
│   │   │   ├── article_with_multiple_metadata_tags.html
│   │   │   ├── article_with_nonconformant_meta_tags.html
│   │   │   ├── article_with_null_attributes.html
│   │   │   ├── article_with_template.rst
│   │   │   ├── article_with_typogrify_dashes.md
│   │   │   ├── article_with_typogrify_dashes.rst
│   │   │   ├── article_with_uppercase_metadata.html
│   │   │   ├── article_with_uppercase_metadata.rst
│   │   │   ├── article_without_category.rst
│   │   │   ├── bad_extension.mmd
│   │   │   ├── bloggerexport.xml
│   │   │   ├── empty.md
│   │   │   ├── empty_with_bom.md
│   │   │   ├── medium_post_content.txt
│   │   │   ├── medium_posts/
│   │   │   │   └── 2017-04-21_-medium-post--d1bf01d62ba3.html
│   │   │   ├── wordpress_content_decoded
│   │   │   ├── wordpress_content_encoded
│   │   │   └── wordpressexport.xml
│   │   ├── cyclic_intersite_links/
│   │   │   ├── first-article.rst
│   │   │   ├── second-article.rst
│   │   │   └── third-article.rst
│   │   ├── default_conf.py
│   │   ├── dummy_plugins/
│   │   │   ├── namespace_plugin/
│   │   │   │   └── pelican/
│   │   │   │       └── plugins/
│   │   │   │           └── ns_plugin/
│   │   │   │               └── __init__.py
│   │   │   └── normal_plugin/
│   │   │       ├── normal_plugin/
│   │   │       │   ├── __init__.py
│   │   │       │   └── submodule.py
│   │   │       └── normal_submodule_plugin/
│   │   │           ├── __init__.py
│   │   │           ├── subpackage/
│   │   │           │   ├── __init__.py
│   │   │           │   └── subpackage.py
│   │   │           └── subplugin.py
│   │   ├── mixed_content/
│   │   │   └── short_page.md
│   │   ├── nested_content/
│   │   │   └── maindir/
│   │   │       ├── maindir.md
│   │   │       └── subdir/
│   │   │           └── subdir.md
│   │   ├── output/
│   │   │   ├── basic/
│   │   │   │   ├── a-markdown-powered-article.html
│   │   │   │   ├── archives.html
│   │   │   │   ├── article-1.html
│   │   │   │   ├── article-2.html
│   │   │   │   ├── article-3.html
│   │   │   │   ├── author/
│   │   │   │   │   └── alexis-metaireau.html
│   │   │   │   ├── authors.html
│   │   │   │   ├── categories.html
│   │   │   │   ├── category/
│   │   │   │   │   ├── bar.html
│   │   │   │   │   ├── cat1.html
│   │   │   │   │   ├── misc.html
│   │   │   │   │   └── yeah.html
│   │   │   │   ├── drafts/
│   │   │   │   │   ├── a-draft-article-without-date.html
│   │   │   │   │   └── a-draft-article.html
│   │   │   │   ├── feeds/
│   │   │   │   │   ├── alexis-metaireau.atom.xml
│   │   │   │   │   ├── alexis-metaireau.rss.xml
│   │   │   │   │   ├── all-en.atom.xml
│   │   │   │   │   ├── all-fr.atom.xml
│   │   │   │   │   ├── all.atom.xml
│   │   │   │   │   ├── bar.atom.xml
│   │   │   │   │   ├── cat1.atom.xml
│   │   │   │   │   ├── misc.atom.xml
│   │   │   │   │   └── yeah.atom.xml
│   │   │   │   ├── filename_metadata-example.html
│   │   │   │   ├── index.html
│   │   │   │   ├── oh-yeah-fr.html
│   │   │   │   ├── oh-yeah.html
│   │   │   │   ├── override/
│   │   │   │   │   └── index.html
│   │   │   │   ├── pages/
│   │   │   │   │   ├── this-is-a-test-hidden-page.html
│   │   │   │   │   └── this-is-a-test-page.html
│   │   │   │   ├── second-article-fr.html
│   │   │   │   ├── second-article.html
│   │   │   │   ├── tag/
│   │   │   │   │   ├── bar.html
│   │   │   │   │   ├── baz.html
│   │   │   │   │   ├── foo.html
│   │   │   │   │   ├── foobar.html
│   │   │   │   │   ├── oh.html
│   │   │   │   │   └── yeah.html
│   │   │   │   ├── tags.html
│   │   │   │   ├── theme/
│   │   │   │   │   ├── css/
│   │   │   │   │   │   ├── fonts.css
│   │   │   │   │   │   ├── main.css
│   │   │   │   │   │   ├── pygment.css
│   │   │   │   │   │   ├── reset.css
│   │   │   │   │   │   ├── typogrify.css
│   │   │   │   │   │   └── wide.css
│   │   │   │   │   └── fonts/
│   │   │   │   │       ├── Yanone_Kaffeesatz_LICENSE.txt
│   │   │   │   │       └── font.css
│   │   │   │   ├── this-is-a-super-article.html
│   │   │   │   └── unbelievable.html
│   │   │   ├── custom/
│   │   │   │   ├── a-markdown-powered-article.html
│   │   │   │   ├── archives.html
│   │   │   │   ├── article-1.html
│   │   │   │   ├── article-2.html
│   │   │   │   ├── article-3.html
│   │   │   │   ├── author/
│   │   │   │   │   ├── alexis-metaireau.html
│   │   │   │   │   ├── alexis-metaireau2.html
│   │   │   │   │   └── alexis-metaireau3.html
│   │   │   │   ├── authors.html
│   │   │   │   ├── categories.html
│   │   │   │   ├── category/
│   │   │   │   │   ├── bar.html
│   │   │   │   │   ├── cat1.html
│   │   │   │   │   ├── misc.html
│   │   │   │   │   └── yeah.html
│   │   │   │   ├── drafts/
│   │   │   │   │   ├── a-draft-article-without-date.html
│   │   │   │   │   └── a-draft-article.html
│   │   │   │   ├── feeds/
│   │   │   │   │   ├── alexis-metaireau.atom.xml
│   │   │   │   │   ├── alexis-metaireau.rss.xml
│   │   │   │   │   ├── all-en.atom.xml
│   │   │   │   │   ├── all-fr.atom.xml
│   │   │   │   │   ├── all.atom.xml
│   │   │   │   │   ├── all.rss.xml
│   │   │   │   │   ├── bar.atom.xml
│   │   │   │   │   ├── bar.rss.xml
│   │   │   │   │   ├── cat1.atom.xml
│   │   │   │   │   ├── cat1.rss.xml
│   │   │   │   │   ├── misc.atom.xml
│   │   │   │   │   ├── misc.rss.xml
│   │   │   │   │   ├── yeah.atom.xml
│   │   │   │   │   └── yeah.rss.xml
│   │   │   │   ├── filename_metadata-example.html
│   │   │   │   ├── index.html
│   │   │   │   ├── index2.html
│   │   │   │   ├── index3.html
│   │   │   │   ├── jinja2_template.html
│   │   │   │   ├── oh-yeah-fr.html
│   │   │   │   ├── oh-yeah.html
│   │   │   │   ├── override/
│   │   │   │   │   └── index.html
│   │   │   │   ├── pages/
│   │   │   │   │   ├── this-is-a-test-hidden-page.html
│   │   │   │   │   └── this-is-a-test-page.html
│   │   │   │   ├── robots.txt
│   │   │   │   ├── second-article-fr.html
│   │   │   │   ├── second-article.html
│   │   │   │   ├── tag/
│   │   │   │   │   ├── bar.html
│   │   │   │   │   ├── baz.html
│   │   │   │   │   ├── foo.html
│   │   │   │   │   ├── foobar.html
│   │   │   │   │   ├── oh.html
│   │   │   │   │   └── yeah.html
│   │   │   │   ├── tags.html
│   │   │   │   ├── theme/
│   │   │   │   │   ├── css/
│   │   │   │   │   │   ├── fonts.css
│   │   │   │   │   │   ├── main.css
│   │   │   │   │   │   ├── pygment.css
│   │   │   │   │   │   ├── reset.css
│   │   │   │   │   │   ├── typogrify.css
│   │   │   │   │   │   └── wide.css
│   │   │   │   │   └── fonts/
│   │   │   │   │       ├── Yanone_Kaffeesatz_LICENSE.txt
│   │   │   │   │       └── font.css
│   │   │   │   ├── this-is-a-super-article.html
│   │   │   │   └── unbelievable.html
│   │   │   └── custom_locale/
│   │   │       ├── archives.html
│   │   │       ├── author/
│   │   │       │   ├── alexis-metaireau.html
│   │   │       │   ├── alexis-metaireau2.html
│   │   │       │   └── alexis-metaireau3.html
│   │   │       ├── authors.html
│   │   │       ├── categories.html
│   │   │       ├── category/
│   │   │       │   ├── bar.html
│   │   │       │   ├── cat1.html
│   │   │       │   ├── misc.html
│   │   │       │   └── yeah.html
│   │   │       ├── drafts/
│   │   │       │   ├── a-draft-article-without-date.html
│   │   │       │   └── a-draft-article.html
│   │   │       ├── feeds/
│   │   │       │   ├── alexis-metaireau.atom.xml
│   │   │       │   ├── alexis-metaireau.rss.xml
│   │   │       │   ├── all-en.atom.xml
│   │   │       │   ├── all-fr.atom.xml
│   │   │       │   ├── all.atom.xml
│   │   │       │   ├── all.rss.xml
│   │   │       │   ├── bar.atom.xml
│   │   │       │   ├── bar.rss.xml
│   │   │       │   ├── cat1.atom.xml
│   │   │       │   ├── cat1.rss.xml
│   │   │       │   ├── misc.atom.xml
│   │   │       │   ├── misc.rss.xml
│   │   │       │   ├── yeah.atom.xml
│   │   │       │   └── yeah.rss.xml
│   │   │       ├── index.html
│   │   │       ├── index2.html
│   │   │       ├── index3.html
│   │   │       ├── jinja2_template.html
│   │   │       ├── oh-yeah-fr.html
│   │   │       ├── override/
│   │   │       │   └── index.html
│   │   │       ├── pages/
│   │   │       │   ├── this-is-a-test-hidden-page.html
│   │   │       │   └── this-is-a-test-page.html
│   │   │       ├── posts/
│   │   │       │   ├── 2010/
│   │   │       │   │   ├── décembre/
│   │   │       │   │   │   └── 02/
│   │   │       │   │   │       └── this-is-a-super-article/
│   │   │       │   │   │           └── index.html
│   │   │       │   │   └── octobre/
│   │   │       │   │       ├── 15/
│   │   │       │   │       │   └── unbelievable/
│   │   │       │   │       │       └── index.html
│   │   │       │   │       └── 20/
│   │   │       │   │           └── oh-yeah/
│   │   │       │   │               └── index.html
│   │   │       │   ├── 2011/
│   │   │       │   │   ├── avril/
│   │   │       │   │   │   └── 20/
│   │   │       │   │   │       └── a-markdown-powered-article/
│   │   │       │   │   │           └── index.html
│   │   │       │   │   └── février/
│   │   │       │   │       └── 17/
│   │   │       │   │           ├── article-1/
│   │   │       │   │           │   └── index.html
│   │   │       │   │           ├── article-2/
│   │   │       │   │           │   └── index.html
│   │   │       │   │           └── article-3/
│   │   │       │   │               └── index.html
│   │   │       │   └── 2012/
│   │   │       │       ├── février/
│   │   │       │       │   └── 29/
│   │   │       │       │       └── second-article/
│   │   │       │       │           └── index.html
│   │   │       │       └── novembre/
│   │   │       │           └── 30/
│   │   │       │               └── filename_metadata-example/
│   │   │       │                   └── index.html
│   │   │       ├── robots.txt
│   │   │       ├── second-article-fr.html
│   │   │       ├── tag/
│   │   │       │   ├── bar.html
│   │   │       │   ├── baz.html
│   │   │       │   ├── foo.html
│   │   │       │   ├── foobar.html
│   │   │       │   ├── oh.html
│   │   │       │   └── yeah.html
│   │   │       ├── tags.html
│   │   │       └── theme/
│   │   │           ├── css/
│   │   │           │   ├── fonts.css
│   │   │           │   ├── main.css
│   │   │           │   ├── pygment.css
│   │   │           │   ├── reset.css
│   │   │           │   ├── typogrify.css
│   │   │           │   └── wide.css
│   │   │           └── fonts/
│   │   │               ├── Yanone_Kaffeesatz_LICENSE.txt
│   │   │               └── font.css
│   │   ├── parse_error/
│   │   │   └── parse_error.rst
│   │   ├── support.py
│   │   ├── test_cache.py
│   │   ├── test_cli.py
│   │   ├── test_contents.py
│   │   ├── test_generators.py
│   │   ├── test_importer.py
│   │   ├── test_log.py
│   │   ├── test_paginator.py
│   │   ├── test_pelican.py
│   │   ├── test_plugins.py
│   │   ├── test_readers.py
│   │   ├── test_rstdirectives.py
│   │   ├── test_server.py
│   │   ├── test_settings.py
│   │   ├── test_testsuite.py
│   │   ├── test_theme.py
│   │   ├── test_urlwrappers.py
│   │   ├── test_utils.py
│   │   └── theme_overrides/
│   │       ├── level1/
│   │       │   └── article.html
│   │       └── level2/
│   │           ├── article.html
│   │           └── authors.html
│   ├── themes/
│   │   ├── notmyidea/
│   │   │   ├── static/
│   │   │   │   ├── css/
│   │   │   │   │   ├── fonts.css
│   │   │   │   │   ├── main.css
│   │   │   │   │   ├── pygment.css
│   │   │   │   │   ├── reset.css
│   │   │   │   │   ├── typogrify.css
│   │   │   │   │   └── wide.css
│   │   │   │   └── fonts/
│   │   │   │       ├── Yanone_Kaffeesatz_LICENSE.txt
│   │   │   │       └── font.css
│   │   │   └── templates/
│   │   │       ├── analytics.html
│   │   │       ├── archives.html
│   │   │       ├── article.html
│   │   │       ├── article_infos.html
│   │   │       ├── author.html
│   │   │       ├── authors.html
│   │   │       ├── base.html
│   │   │       ├── categories.html
│   │   │       ├── category.html
│   │   │       ├── comments.html
│   │   │       ├── disqus_script.html
│   │   │       ├── github.html
│   │   │       ├── index.html
│   │   │       ├── page.html
│   │   │       ├── period_archives.html
│   │   │       ├── tag.html
│   │   │       ├── taglist.html
│   │   │       ├── tags.html
│   │   │       ├── translations.html
│   │   │       └── twitter.html
│   │   └── simple/
│   │       └── templates/
│   │           ├── archives.html
│   │           ├── article.html
│   │           ├── author.html
│   │           ├── authors.html
│   │           ├── base.html
│   │           ├── categories.html
│   │           ├── category.html
│   │           ├── index.html
│   │           ├── page.html
│   │           ├── pagination.html
│   │           ├── period_archives.html
│   │           ├── tag.html
│   │           ├── tags.html
│   │           └── translations.html
│   ├── tools/
│   │   ├── __init__.py
│   │   ├── pelican_import.py
│   │   ├── pelican_quickstart.py
│   │   ├── pelican_themes.py
│   │   └── templates/
│   │       ├── Makefile.jinja2
│   │       ├── pelicanconf.py.jinja2
│   │       ├── publishconf.py.jinja2
│   │       └── tasks.py.jinja2
│   ├── urlwrappers.py
│   ├── utils.py
│   └── writers.py
├── pyproject.toml
├── requirements/
│   ├── developer.pip
│   ├── docs.pip
│   ├── owner.pip
│   └── test.pip
├── samples/
│   ├── content/
│   │   ├── 2012-11-30_filename-metadata.rst
│   │   ├── another_super_article-fr.rst
│   │   ├── another_super_article.rst
│   │   ├── article2-fr.rst
│   │   ├── article2.rst
│   │   ├── article_tag_baz.rst
│   │   ├── cat1/
│   │   │   ├── article1.rst
│   │   │   ├── article2.rst
│   │   │   ├── article3.rst
│   │   │   └── markdown-article.md
│   │   ├── draft_article without_date.rst
│   │   ├── draft_article.rst
│   │   ├── extra/
│   │   │   └── robots.txt
│   │   ├── pages/
│   │   │   ├── hidden_page.rst
│   │   │   ├── jinja2_template.html
│   │   │   ├── override_tag_oh.rst
│   │   │   ├── override_url_saveas.rst
│   │   │   └── test_page.rst
│   │   ├── super_article.rst
│   │   ├── unbelievable.rst
│   │   └── unwanted_file
│   ├── kinda/
│   │   └── exciting/
│   │       ├── new/
│   │       │   └── files/
│   │       │       └── zap!
│   │       └── old
│   ├── pelican.conf.py
│   ├── pelican.conf_FR.py
│   ├── theme_standard/
│   │   ├── a_stylesheet
│   │   └── a_template
│   └── very/
│       └── exciting/
│           └── new/
│               └── files/
│                   ├── bap!
│                   ├── boom!
│                   └── wow!
├── tasks.py
└── tox.ini

================================================
FILE CONTENTS
================================================

================================================
FILE: .coveragerc
================================================
[report]
omit =
       pelican/tests/*
       pelican/signals.py


================================================
FILE: .editorconfig
================================================
root = true

[*]
charset = utf-8
end_of_line = lf
indent_size = 4
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true

[*.py]
max_line_length = 88

[*.{yml,yaml}]
indent_size = 2


================================================
FILE: .git-blame-ignore-revs
================================================
# .git-blame-ignore-revs
# Apply code style to project via: ruff format .
cabdb26cee66e1173cf16cb31d3fe5f9fa4392e7
# Upgrade code base for Python 3.8 and above
ecd598f293161a52564aa6e8dfdcc8284dc93970
# Apply Ruff and pyupgrade to Jinja templates
db241feaa445375dc05e189e69287000ffe5fa8e
# Change pre-commit to run ruff and ruff-format with fixes
6d8597addb17d5fa3027ead91427939e8e4e89ec
# Upgrade Ruff from 0.1.x to 0.4.x
0bd02c00c078fe041b65fbf4eab13601bb42676d
# Apply more Ruff checks to code
9d30c5608a58d202b1c02d55651e6ac746bfb173
# Apply yet more Ruff checks to code
7577dd7603f7cb3a09922d1edb65b6eafb6e2ac7
# Indent Jinja templates, HTML, CSS, and JS via DjHTML
4af40e80772a58eac8969360e5caeb99e3e26e78
# Ruff UP031: Use F-string format specifiers instead of percent format
30bde3823f50b9ba8ac5996c1c46bb72031aa6b8
# Upgrade Ruff to 0.12.x & comply with new rules
4dedf1795831db99d18941c707923ba48cc28ce7


================================================
FILE: .gitattributes
================================================
# Auto detect text files and perform LF normalization
* text=auto

# Improve accuracy of GitHub's Linguist-powered language statistics
pelican/tests/content/* linguist-vendored
pelican/tests/output/* linguist-vendored
pelican/tests/theme_overrides/* linguist-vendored
pelican/themes/notmyidea/templates/*.html linguist-language=Jinja
pelican/themes/simple/templates/*.html linguist-language=Jinja
samples/* linguist-vendored
*.html linguist-vendored


================================================
FILE: .github/CODEOWNERS
================================================
.github/workflows/github_pages.yml @seanh


================================================
FILE: .github/FUNDING.yml
================================================
---

github: justinmayer
custom: https://donate.getpelican.com
liberapay: pelican


================================================
FILE: .github/ISSUE_TEMPLATE/---bug-report.md
================================================
---
name: "\U0001F41E Bug Report"
about: Did you find a bug?
title: ''
labels: bug
assignees: ''

---

<!--
  Hi there! Thank you for discovering and submitting an issue.

  Before you submit this, let’s make sure of a few things.
  Please make sure the following boxes are ticked if they are correct.
  If not, please try and fulfill them first.
-->

<!-- Checked checkbox should look like this: [x] -->
- [ ] I have read the [Filing Issues](https://docs.getpelican.com/en/latest/contribute.html#filing-issues) and subsequent “How to Get Help” sections of the documentation.
- [ ] I can reproduce this problem with stock/default settings file, theme, and sample content (as described in above “How to Get Help” sections of the documentation).
- [ ] I have searched the [issues](https://github.com/getpelican/pelican/issues?q=is%3Aissue) (including closed ones) and believe that this is not a duplicate.

<!--
  If you cannot reproduce the problem with stock/default settings file, theme, and sample content,
  please close this tab and ask your question in the Discussions area instead:
  <https://github.com/getpelican/pelican/discussions>
  Otherwise, once the above boxes are checked, please fill out the following list
  of information, which would be very helpful for maintainers.
-->

- **OS version and name**: <!-- Replace with version + name -->
- **Python version**: <!-- Replace with version -->
- **Pelican version**: <!-- Replace with version -->
- **Link to theme**: <!-- Replace with link to the theme you are using -->
- **Links to plugins**: <!-- Replace with list of links to plugins you are using -->
- **Link to your site**: <!-- If available, replace with link to your site -->
- **Link to your source**: <!-- If available, replace with link to relevant source repository -->
- **Link to a [Gist](https://gist.github.com/) with the contents of your settings file**: <!-- If your source is not accessible, put Gist link here -->

## Issue
<!--
  Now feel free to write your issue. Please avoid vague phrases like “[…] doesn’t work”.
  Be descriptive! Thanks again 🙌 ❤️
-->


================================================
FILE: .github/ISSUE_TEMPLATE/---documentation.md
================================================
---
name: "\U0001F4DA Documentation"
about: Did you find errors, problems, or anything unclear in the docs (https://docs.getpelican.com/)?
title: ''
labels: docs
assignees: ''

---

<!--
  Hi there! Thank you for discovering and submitting an issue with our documentation.

  Before you submit this, let’s make sure of a few things.
  Please make sure the following boxes are ticked if they are correct.
  If not, please try and fulfill them first.
-->

<!-- Checked checkbox should look like this: [x] -->
- [ ] I have searched the [issues](https://github.com/getpelican/pelican/issues?q=is%3Aissue) (including closed ones) and believe that this is not a duplicate.

## Issue
<!-- Now feel free to write your issue, but please be descriptive! Thanks again 🙌 ❤️ -->


================================================
FILE: .github/ISSUE_TEMPLATE/---enhancement-request.md
================================================
---
name: "\U0001F381 Feature Request"
about: Do you have ideas for new features and improvements?
title: ''
labels: enhancement
assignees: ''

---

<!--
  Hi there! Thank you for wanting to make Pelican better.

  Before you submit this, let’s make sure of a few things.
  Please make sure the following boxes are ticked if they are correct.
  If not, please try and fulfill them first. The last one is optional but encouraged.
-->

<!-- Checked checkbox should look like this: [x] -->
- [ ] I have searched the [issues](https://github.com/getpelican/pelican/issues?q=is%3Aissue) (including closed ones) and believe that this is not a duplicate.
- [ ] I have searched the [documentation](https://docs.getpelican.com/) and believe that my question is not covered.
- [ ] I am willing to lend a hand to help implement this feature. <!-- optional but encouraged -->

## Feature Request
<!-- Now feel free to write your idea for improvement. Thanks again 🙌 ❤️ -->


================================================
FILE: .github/ISSUE_TEMPLATE/config.yml
================================================
---
# Ref: https://help.github.com/en/github/building-a-strong-community/configuring-issue-templates-for-your-repository#configuring-the-template-chooser
blank_issues_enabled: false
contact_links:
- name: '🗃️ Everything Else'
  url: https://github.com/getpelican/pelican/discussions
  about: |
    Do you have a question/issue that does not fall into any of the other categories?
- name: '💬 Pelican IRC Channel'
  url: https://web.libera.chat/?#pelican
  about: |
    Chat with the community, ask questions, and learn about best practices.


================================================
FILE: .github/dependabot.yml
================================================
# See https://docs.github.com/en/free-pro-team@latest/
#  github/administering-a-repository/enabling-and-disabling-version-updates
---
version: 2
updates:
  - package-ecosystem: "github-actions"
    directory: "/"
    schedule:
      interval: "monthly"
    open-pull-requests-limit: 0


================================================
FILE: .github/pull_request_template.md
================================================
# Pull Request Checklist

Resolves: #issue-number-here <!-- Only if related issue *already* exists — otherwise remove this line -->

<!-- This is just a reminder about the most common mistakes. Please make sure that you tick all *appropriate* boxes. Also, please read our [contribution guide](https://docs.getpelican.com/en/latest/contribute.html#contributing-code) at least once — it will save you unnecessary review cycles! -->

- [ ] Ensured **tests pass** and (if applicable) updated functional test output
- [ ] Conformed to **code style guidelines** by running appropriate linting tools
- [ ] Added **tests** for changed code
- [ ] Updated **documentation** for changed code

<!-- If you have *any* questions to *any* of the points above, just **submit and ask**! This checklist is here to *help* you, not to deter you from contributing! -->


================================================
FILE: .github/stale.yml
================================================
# Configuration for probot-stale - https://github.com/probot/stale

# Number of days of inactivity before an Issue or Pull Request becomes stale
daysUntilStale: 60

# Number of days of inactivity before an Issue or Pull Request with the stale label is closed.
daysUntilClose: 30

# Set to true to ignore issues in a project (defaults to false)
exemptProjects: true

# Set to true to ignore issues in a milestone (defaults to false)
exemptMilestones: true

# Set to true to ignore issues with an assignee (defaults to false)
exemptAssignees: true

# Label to use when marking as stale
staleLabel: stale

# Comment to post when marking as stale. Set to `false` to disable
markComment: >
  This issue has been automatically marked as stale because it has not had
  recent activity. It will be closed if no further activity occurs. Thank you
  for your participation and understanding.

# Limit the number of actions per hour, from 1-30. Default is 30
limitPerRun: 1

# Limit to only `issues` or `pulls`
only: issues


================================================
FILE: .github/workflows/github_pages.yml
================================================
# Workflow for building the site and (optionally) publishing it to GitHub Pages.
name: Deploy to GitHub Pages
on:
  workflow_call:
    inputs:
      settings:
        required: true
        description: "The path to your Pelican settings file (`pelican`'s `--settings` option), for example: 'publishconf.py'"
        type: string
      requirements:
        required: false
        default: "pelican"
        description: "The Python requirements to install, for example to enable markdown and typogrify use: 'pelican[markdown] typogrify' or if you have a requirements file use: '-r requirements.txt'"
        type: string
      output-path:
        required: false
        default: "output/"
        description: "Where to output the generated files (`pelican`'s `--output` option)"
        type: string
      theme:
        required: false
        default: ""
        description: "The GitHub repo URL of a custom theme to use, for example: 'https://github.com/seanh/sidecar.git'"
        type: string
      theme-checkout:
        required: false
        default: ""
        description: "Git ref (branch, tag or commit) of the theme repo to checkout. This can be used to pin the version of your theme. If not specified defaults to the theme repo's default branch."
        type: string
      python:
        required: false
        default: "3.14"
        description: "The version of Python to use, for example: '3.14' (to use the most recent version of Python 3.14, this is faster) or '3.14.0' (to use an exact version, slower)"
        type: string
      siteurl:
        required: false
        default: ""
        description: "The base URL of your web site (Pelican's SITEURL setting). If not passed this will default to the URL of your GitHub Pages site, which is correct in most cases."
        type: string
      feed_domain:
        required: false
        default: ""
        description: "The domain to be prepended to feed URLs (Pelican's FEED_DOMAIN setting). If not passed this will default to the URL of your GitHub Pages site, which is correct in most cases."
        type: string
      deploy:
        required: false
        default: true
        description: "Whether to deploy the site. If true then build the site and deploy it. If false then just test that the site builds successfully but don't deploy anything."
        type: boolean
      stork:
        required: false
        default: false
        description: "Whether to add Stork search tool. If true, it will be installed on runner."
        type: boolean
permissions:
  contents: read
  pages: write
  id-token: write
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v6
      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: ${{ inputs.python }}
      - name: Clone theme
        if: ${{ inputs.theme }}
        run: git clone '${{ inputs.theme }}' .theme
      - name: Checkout theme ref
        if: ${{ inputs.theme && inputs.theme-checkout }}
        run: git -C .theme checkout '${{ inputs.theme-checkout }}'
      - name: Configure GitHub Pages
        id: pages
        uses: actions/configure-pages@v5
      - name: Install Stork
        if: ${{ inputs.stork }}
        run: cargo install stork-search --locked
      - name: Install requirements
        run: pip install ${{ inputs.requirements }}
      - name: Build Pelican site
        shell: python
        run: |
          import subprocess

          cmd = "pelican"
          cmd += " --settings ${{ inputs.settings }}"
          cmd += " --extra-settings"
          cmd += """ SITEURL='"${{ inputs.siteurl || steps.pages.outputs.base_url }}"'"""
          cmd += """ FEED_DOMAIN='"${{ inputs.feed_domain || steps.pages.outputs.base_url }}"'"""
          cmd += " --output ${{ inputs.output-path }}"

          if "${{ inputs.theme }}":
              cmd += " --theme-path .theme"

          subprocess.run(cmd, shell=True, check=True)
      - name: Fix permissions
        run: |
          chmod -c -R +rX "${{ inputs.output-path }}" | while read -r line; do
            echo "::warning title=Invalid file permissions automatically fixed::$line"
          done
      - name: Archive artifact
        shell: sh
        run: |
          echo "::group::Archive artifact"
          tar \
            --dereference \
            --hard-dereference \
            --directory "$OUTPUT_PATH" \
            -cvf "$RUNNER_TEMP/artifact.tar" \
            --exclude=.git \
            --exclude=.github \
            .
          echo "::endgroup::"
        env:
          OUTPUT_PATH: ${{ inputs.output-path }}
      - name: Upload artifact
        uses: actions/upload-artifact@v5
        with:
          name: github-pages
          path: ${{ runner.temp }}/artifact.tar
          retention-days: 1
          if-no-files-found: error
  deploy:
    concurrency:
      group: "pages"
      cancel-in-progress: false
    if: ${{ inputs.deploy }}
    environment:
      name: github-pages
      url: ${{ steps.deployment.outputs.page_url }}
    runs-on: ubuntu-latest
    needs: build
    steps:
      - name: Deploy to GitHub Pages
        id: deployment
        uses: actions/deploy-pages@v4


================================================
FILE: .github/workflows/main.yml
================================================
name: build

on: [push, pull_request]

env:
  # color output for pytest and tox
  PYTEST_ADDOPTS: "--color=yes"
  PY_COLORS: 1

jobs:
  test:
    name: Test - ${{ matrix.python }} - ${{ matrix.os }}
    runs-on: ${{ matrix.os }}-latest

    strategy:
      matrix:
        os: [ubuntu, macos, windows]
        python: ["3.10", "3.11", "3.12", "3.13", "3.14"]

    steps:
      - uses: actions/checkout@v6
      - name: Set up Python ${{ matrix.python }}
        uses: actions/setup-python@v6
        with:
          python-version: ${{ matrix.python }}
          cache: "pip"
          cache-dependency-path: "**/requirements/*"
      - name: Install locale (Linux)
        if: startsWith(runner.os, 'Linux')
        run: sudo locale-gen fr_FR.UTF-8 tr_TR.UTF-8
      - name: Install pandoc
        uses: r-lib/actions/setup-pandoc@v2
        with:
          pandoc-version: "2.9.2"
      - name: Install tox
        run: python -m pip install -U pip tox
      - name: Info
        run: |
          echo "=====  PYTHON  ====="
          python --version
          echo "=====  PANDOC  ====="
          pandoc --version | head -2
      - name: Run tests
        run: tox -e py${{ matrix.python }}

  lint:
    name: Lint
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
      - uses: pdm-project/setup-pdm@v4
        with:
          python-version: "3.11"
          cache: true
          cache-dependency-path: ./pyproject.toml
      - name: Install dependencies
        run: |
          pdm install --no-default --dev
      - name: Run linters
        run: pdm lint --diff
      - name: Run pre-commit checks on all files
        uses: pre-commit/action@v3.0.1

  build:
    name: Test build
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
      - uses: pdm-project/setup-pdm@v4
        with:
          python-version: "3.11"
          cache: true
          cache-dependency-path: ./pyproject.toml
      - name: Install dependencies
        run: pdm install --dev
      - name: Build package
        run: pdm build
      - name: Test build
        run: pdm run pytest --check-build=dist  pelican/tests/build_test

  docs:
    name: Build docs
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v6
      - name: Set up Python
        uses: actions/setup-python@v6
        with:
          python-version: "3.11"
          cache: "pip"
          cache-dependency-path: "**/requirements/*"
      - name: Install tox
        run: python -m pip install -U pip tox
      - name: Check
        run: tox -e docs
      - name: cache the docs for inspection
        uses: actions/upload-artifact@v5
        with:
          name: docs
          path: docs/_build/html/

  deploy:
    name: Deploy
    environment: Deployment
    needs: [test, lint, docs, build]
    runs-on: ubuntu-latest
    if: github.ref=='refs/heads/main' && github.event_name!='pull_request' && github.repository == 'getpelican/pelican'

    permissions:
      contents: write
      id-token: write

    steps:
      - uses: actions/checkout@v6
        with:
          token: ${{ secrets.GH_TOKEN }}

      - name: Set up Python
        uses: actions/setup-python@v6
        with:
          python-version: "3.11"

      - name: Check release
        id: check_release
        run: |
          python -m pip install --upgrade pip
          python -m pip install autopub[github]
          autopub check

      - name: Publish
        if: ${{ steps.check_release.outputs.autopub_release=='true' }}
        env:
          GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}
        run: |
          autopub prepare
          autopub commit
          autopub build
          autopub githubrelease

      - name: Upload package to PyPI
        if: ${{ steps.check_release.outputs.autopub_release=='true' }}
        uses: pypa/gh-action-pypi-publish@release/v1


================================================
FILE: .gitignore
================================================
*.egg-info
.*.swp
.*.swo
*.pyc
.DS_Store
docs/_build
docs/*/_build
build
dist
tags
.tox
.coverage
htmlcov
*.orig
venv
samples/output
*.pem
*.lock
.pdm-python
.vale
.venv
**/LC_MESSAGES/*.mo

# direnv
.envrc

# IDE cruft
.idea
.vscode


================================================
FILE: .mailmap
================================================
Alexis Métaireau <alexis@notmyidea.org>
Alexis Métaireau <alexis@notmyidea.org> <alexis, notmyidea, org>
Alexis Métaireau <alexis@notmyidea.org> <ametaireau@gmail.com>
Axel Haustant <noirbizarre@gmail.com> <axel.haustant.ext@mappy.com>
Axel Haustant <noirbizarre@gmail.com> <axel.haustant@valtech.fr>
Dave Mankoff <mankyd@gmail.com>
Feth Arezki <feth@tuttu.info>
Guillaume <guillaume@lame.homelinux.com>
Guillaume <guillaume@lame.homelinux.com> <guillaume@mint.(none)>
Guillaume B <guitreize@gmail.com>
Guillermo López <guilan70@hotmail.com>
Guillermo López <guilan70@hotmail.com> <guillermo.lopez@outlook.com>
Jomel Imperio <jimperio@gmail.com>
Justin Mayer <entrop@gmail.com>
Justin Mayer <entrop@gmail.com> <entroP@gmail.com>
Marco Milanesi <kpanic@gnufunk.org> <marcom@openquake.org>
Massimo Santini <santini@dsi.unimi.it> <santini@spillane.docenti.dsi.unimi.it>
Rémy HUBSCHER <hubscher.remy@gmail.com> <remy.hubscher@ionyse.com>
Simon Conseil <contact@saimon.org>
Simon Liedtke <liedtke.simon@googlemail.com>
Skami18 <skami@skami-laptop.dyndns.org>
Stuart Colville <muffinresearchlabs@gmail.com> <muffinresearch@gmail.com>
Stéphane Bunel <stephane@lutetium.(none)>
tBunnyMan <WagThatTail@Me.com>


================================================
FILE: .pre-commit-config.yaml
================================================
---
# See https://pre-commit.com/hooks.html for info on hooks
repos:
  - repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v5.0.0
    hooks:
      - id: check-added-large-files
      - id: check-ast
      - id: check-toml
      - id: check-yaml
      - id: debug-statements
      - id: detect-private-key
      - id: end-of-file-fixer
      - id: forbid-new-submodules
      - id: trailing-whitespace

  - repo: https://github.com/astral-sh/ruff-pre-commit
    # ruff version should match the one in pyproject.toml
    rev: v0.12.7
    hooks:
      - id: ruff-check
        args: [--fix, --exit-non-zero-on-fix]
      - id: ruff-format

  - repo: https://github.com/rtts/djhtml
    rev: '3.0.8'
    hooks:
      - id: djhtml
      - id: djcss
      - id: djjs


================================================
FILE: .readthedocs.yaml
================================================
---
# Read the Docs configuration file
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details

# Required
version: 2

# Set the OS, Python version, and any other needed tools
build:
  os: ubuntu-22.04
  tools:
    python: "3.10"

# Build HTML & PDF formats
formats:
  - htmlzip
  - pdf

# Build documentation in the docs/ directory with Sphinx
sphinx:
  configuration: docs/conf.py

# Version of Python and requirements required to build the docs
python:
  install:
    - requirements: requirements/developer.pip
    - method: pip
      path: .


================================================
FILE: .vale.ini
================================================
StylesPath = .vale/styles

Vocab = Pelican

MinAlertLevel = suggestion

Packages = proselint, alex

[*]
BasedOnStyles = Vale, proselint, alex


================================================
FILE: CONTRIBUTING.rst
================================================
Filing issues
=============

* Before you submit a new issue, try `asking for help`_ first.
* If determined to create a new issue, first search `Pelican Discussions`_
  and `existing issues`_ (open and closed) to see if your question has already
  been answered previously.

.. _`asking for help`: `How to get help`_
.. _`Pelican Discussions`: https://github.com/getpelican/pelican/discussions
.. _`existing issues`: https://github.com/getpelican/pelican/issues

How to get help
===============

Before you ask for help, please make sure you do the following:

1. Read the documentation_ thoroughly. If in a hurry, at least use the search
   field that is provided at top-left on the documentation_ pages. Make sure
   you read the docs for the Pelican version you are using.
2. Use a search engine (e.g., DuckDuckGo, Google) to search for a solution to
   your problem. Someone may have already found a solution, perhaps in the
   form of a ':pelican-doc:`plugins` or a specific combination of settings.

3. Try reproducing the issue in a clean environment, ensuring you are using:

* latest Pelican release (or an up-to-date Git clone of Pelican ``main`` branch)
* latest releases of libraries used by Pelican
* no plugins or only those related to the issue

**NOTE:** The most common sources of problems are anomalies in (1) themes, (2)
plugins, (3) settings files, and (4) ``make``/``invoke`` automation wrappers.
If you can't reproduce your problem when using the following steps to generate
your site, then the problem is almost certainly with one of the above-listed
elements (and not Pelican itself)::

    cd ~/projects/your-site
    git clone https://github.com/getpelican/pelican ~/projects/pelican
    pelican content -s ~/projects/pelican/samples/pelican.conf.py -t ~/projects/pelican/pelican/themes/notmyidea

If you can generate your site without problems using the steps above, then your
problem is unlikely to be caused by Pelican itself, and therefore please
consider reaching out to the maintainers of the plugins/theme you are using
instead of raising the topic with the Pelican core community.

If despite the above efforts you still cannot resolve your problem, be sure to
include in your inquiry the following information, preferably in the form of
links to content uploaded to a `paste service`_, GitHub repository, or other
publicly-accessible location:

* Describe what version of Pelican you are running (output of ``pelican --version``
  or the HEAD commit hash if you cloned the repo) and how exactly you installed
  it (the full command you used, e.g. ``python -m pip install pelican``).
* If you are looking for a way to get some end result, prepare a detailed
  description of what the end result should look like (preferably in the form of
  an image or a mock-up page) and explain in detail what you have done so far to
  achieve it.
* If you are trying to solve some issue, prepare a detailed description of how
  to reproduce the problem. If the issue cannot be easily reproduced, it cannot
  be debugged by developers or volunteers. Describe only the **minimum steps**
  necessary to reproduce it (no extra plugins, etc.).
* Upload your settings file or any other custom code that would enable people to
  reproduce the problem or to see what you have already tried to achieve the
  desired end result.
* Upload detailed and **complete** output logs and backtraces (remember to add
  the ``--debug`` flag: ``pelican --debug content [...]``)

.. _documentation: https://docs.getpelican.com/
.. _`paste service`: https://dpaste.com

Once the above preparation is ready, you can post your query as a new thread in
`Pelican Discussions`_. Remember to include all the information you prepared.

Contributing code
=================

Before you submit a contribution, please ask whether it is desired so that you
don't spend a lot of time working on something that would be rejected for a
known reason. Consider also whether your new feature might be better suited as
a ':pelican-doc:`plugins` — you can `ask for help`_  to make that determination.

Also, if you intend to submit a pull request to address something for which there
is no existing issue, there is no need to create a new issue and then immediately
submit a pull request that closes it. You can submit the pull request by itself.

Using Git and GitHub
--------------------

* `Create a new branch`_ specific to your change (as opposed to making
  your commits in the ``main`` branch).
* **Don't put multiple unrelated fixes/features in the same branch / pull request.**
  For example, if you're working on a new feature and find a bugfix that
  doesn't *require* your new feature, **make a new distinct branch and pull
  request** for the bugfix. Similarly, any proposed changes to code style
  formatting should be in a completely separate pull request.
* Add a ``RELEASE.md`` file in the root of the project that contains the
  release type (major, minor, patch) and a summary of the changes that will be
  used as the release changelog entry. For example::

       Release type: minor

       Reload browser window upon changes to content, settings, or theme

* Check for unnecessary whitespace via ``git diff --check`` before committing.
* First line of your commit message should start with present-tense verb, be 50
  characters or less, and include the relevant issue number(s) if applicable.
  *Example:* ``Ensure proper PLUGIN_PATH behavior. Refs #428.`` If the commit
  *completely fixes* an existing bug report, please use ``Fixes #585`` or ``Fix
  #585`` syntax (so the relevant issue is automatically closed upon PR merge).
* After the first line of the commit message, add a blank line and then a more
  detailed explanation (when relevant).
* `Squash your commits`_ to eliminate merge commits and ensure a clean and
  readable commit history.
* After you have issued a pull request, the continuous integration (CI) system
  will run the test suite on all supported Python versions and check for code style
  compliance. If any of these checks fail, you should fix them. (If tests fail
  on the CI system but seem to pass locally, ensure that local test runs aren't
  skipping any tests.)

Contribution quality standards
------------------------------

* Adhere to the project's code style standards. See: `Development Environment`_
* Ensure your code is compatible with the `officially-supported Python releases`_.
* Add docs and tests for your changes. Undocumented and untested features will
  not be accepted.
* :pelican-doc:`Run all the tests <contribute>` **on all versions of Python
  supported by Pelican** to ensure nothing was accidentally broken.

Check out our `Git Tips`_ page or `ask for help`_ if you
need assistance or have any questions about these guidelines.

.. _`plugin`: https://docs.getpelican.com/en/latest/plugins.html
.. _`Create a new branch`: https://github.com/getpelican/pelican/wiki/Git-Tips#making-your-changes
.. _`Squash your commits`: https://github.com/getpelican/pelican/wiki/Git-Tips#squashing-commits
.. _`Git Tips`: https://github.com/getpelican/pelican/wiki/Git-Tips
.. _`ask for help`: `How to get help`_
.. _`Development Environment`: https://docs.getpelican.com/en/latest/contribute.html#setting-up-the-development-environment
.. _`officially-supported Python releases`: https://devguide.python.org/versions/#versions


================================================
FILE: LICENSE
================================================
                    GNU AFFERO GENERAL PUBLIC LICENSE
                       Version 3, 19 November 2007

 Copyright (C) 2007 Free Software Foundation, Inc. <https://www.fsf.org/>
 Everyone is permitted to copy and distribute verbatim copies
 of this license document, but changing it is not allowed.

                            Preamble

  The GNU Affero General Public License is a free, copyleft license for
software and other kinds of works, specifically designed to ensure
cooperation with the community in the case of network server software.

  The licenses for most software and other practical works are designed
to take away your freedom to share and change the works.  By contrast,
our General Public Licenses are intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users.

  When we speak of free software, we are referring to freedom, not
price.  Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.

  Developers that use our General Public Licenses protect your rights
with two steps: (1) assert copyright on the software, and (2) offer
you this License which gives you legal permission to copy, distribute
and/or modify the software.

  A secondary benefit of defending all users' freedom is that
improvements made in alternate versions of the program, if they
receive widespread use, become available for other developers to
incorporate.  Many developers of free software are heartened and
encouraged by the resulting cooperation.  However, in the case of
software used on network servers, this result may fail to come about.
The GNU General Public License permits making a modified version and
letting the public access it on a server without ever releasing its
source code to the public.

  The GNU Affero General Public License is designed specifically to
ensure that, in such cases, the modified source code becomes available
to the community.  It requires the operator of a network server to
provide the source code of the modified version running there to the
users of that server.  Therefore, public use of a modified version, on
a publicly accessible server, gives the public access to the source
code of the modified version.

  An older license, called the Affero General Public License and
published by Affero, was designed to accomplish similar goals.  This is
a different license, not a version of the Affero GPL, but Affero has
released a new version of the Affero GPL which permits relicensing under
this license.

  The precise terms and conditions for copying, distribution and
modification follow.

                       TERMS AND CONDITIONS

  0. Definitions.

  "This License" refers to version 3 of the GNU Affero General Public License.

  "Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.

  "The Program" refers to any copyrightable work licensed under this
License.  Each licensee is addressed as "you".  "Licensees" and
"recipients" may be individuals or organizations.

  To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy.  The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.

  A "covered work" means either the unmodified Program or a work based
on the Program.

  To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy.  Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.

  To "convey" a work means any kind of propagation that enables other
parties to make or receive copies.  Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.

  An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License.  If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.

  1. Source Code.

  The "source code" for a work means the preferred form of the work
for making modifications to it.  "Object code" means any non-source
form of a work.

  A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.

  The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form.  A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.

  The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities.  However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work.  For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.

  The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.

  The Corresponding Source for a work in source code form is that
same work.

  2. Basic Permissions.

  All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met.  This License explicitly affirms your unlimited
permission to run the unmodified Program.  The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work.  This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.

  You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force.  You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright.  Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.

  Conveying under any other circumstances is permitted solely under
the conditions stated below.  Sublicensing is not allowed; section 10
makes it unnecessary.

  3. Protecting Users' Legal Rights From Anti-Circumvention Law.

  No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.

  When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.

  4. Conveying Verbatim Copies.

  You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.

  You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.

  5. Conveying Modified Source Versions.

  You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:

    a) The work must carry prominent notices stating that you modified
    it, and giving a relevant date.

    b) The work must carry prominent notices stating that it is
    released under this License and any conditions added under section
    7.  This requirement modifies the requirement in section 4 to
    "keep intact all notices".

    c) You must license the entire work, as a whole, under this
    License to anyone who comes into possession of a copy.  This
    License will therefore apply, along with any applicable section 7
    additional terms, to the whole of the work, and all its parts,
    regardless of how they are packaged.  This License gives no
    permission to license the work in any other way, but it does not
    invalidate such permission if you have separately received it.

    d) If the work has interactive user interfaces, each must display
    Appropriate Legal Notices; however, if the Program has interactive
    interfaces that do not display Appropriate Legal Notices, your
    work need not make them do so.

  A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit.  Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.

  6. Conveying Non-Source Forms.

  You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:

    a) Convey the object code in, or embodied in, a physical product
    (including a physical distribution medium), accompanied by the
    Corresponding Source fixed on a durable physical medium
    customarily used for software interchange.

    b) Convey the object code in, or embodied in, a physical product
    (including a physical distribution medium), accompanied by a
    written offer, valid for at least three years and valid for as
    long as you offer spare parts or customer support for that product
    model, to give anyone who possesses the object code either (1) a
    copy of the Corresponding Source for all the software in the
    product that is covered by this License, on a durable physical
    medium customarily used for software interchange, for a price no
    more than your reasonable cost of physically performing this
    conveying of source, or (2) access to copy the
    Corresponding Source from a network server at no charge.

    c) Convey individual copies of the object code with a copy of the
    written offer to provide the Corresponding Source.  This
    alternative is allowed only occasionally and noncommercially, and
    only if you received the object code with such an offer, in accord
    with subsection 6b.

    d) Convey the object code by offering access from a designated
    place (gratis or for a charge), and offer equivalent access to the
    Corresponding Source in the same way through the same place at no
    further charge.  You need not require recipients to copy the
    Corresponding Source along with the object code.  If the place to
    copy the object code is a network server, the Corresponding Source
    may be on a different server (operated by you or a third party)
    that supports equivalent copying facilities, provided you maintain
    clear directions next to the object code saying where to find the
    Corresponding Source.  Regardless of what server hosts the
    Corresponding Source, you remain obligated to ensure that it is
    available for as long as needed to satisfy these requirements.

    e) Convey the object code using peer-to-peer transmission, provided
    you inform other peers where the object code and Corresponding
    Source of the work are being offered to the general public at no
    charge under subsection 6d.

  A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.

  A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling.  In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage.  For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product.  A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.

  "Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source.  The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.

  If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information.  But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).

  The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed.  Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.

  Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.

  7. Additional Terms.

  "Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law.  If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.

  When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it.  (Additional permissions may be written to require their own
removal in certain cases when you modify the work.)  You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.

  Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:

    a) Disclaiming warranty or limiting liability differently from the
    terms of sections 15 and 16 of this License; or

    b) Requiring preservation of specified reasonable legal notices or
    author attributions in that material or in the Appropriate Legal
    Notices displayed by works containing it; or

    c) Prohibiting misrepresentation of the origin of that material, or
    requiring that modified versions of such material be marked in
    reasonable ways as different from the original version; or

    d) Limiting the use for publicity purposes of names of licensors or
    authors of the material; or

    e) Declining to grant rights under trademark law for use of some
    trade names, trademarks, or service marks; or

    f) Requiring indemnification of licensors and authors of that
    material by anyone who conveys the material (or modified versions of
    it) with contractual assumptions of liability to the recipient, for
    any liability that these contractual assumptions directly impose on
    those licensors and authors.

  All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10.  If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term.  If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.

  If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.

  Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.

  8. Termination.

  You may not propagate or modify a covered work except as expressly
provided under this License.  Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).

  However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.

  Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.

  Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License.  If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.

  9. Acceptance Not Required for Having Copies.

  You are not required to accept this License in order to receive or
run a copy of the Program.  Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance.  However,
nothing other than this License grants you permission to propagate or
modify any covered work.  These actions infringe copyright if you do
not accept this License.  Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.

  10. Automatic Licensing of Downstream Recipients.

  Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License.  You are not responsible
for enforcing compliance by third parties with this License.

  An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations.  If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.

  You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License.  For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.

  11. Patents.

  A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based.  The
work thus licensed is called the contributor's "contributor version".

  A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version.  For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.

  Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.

  In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement).  To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.

  If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients.  "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.

  If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.

  A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License.  You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.

  Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.

  12. No Surrender of Others' Freedom.

  If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License.  If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all.  For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.

  13. Remote Network Interaction; Use with the GNU General Public License.

  Notwithstanding any other provision of this License, if you modify the
Program, your modified version must prominently offer all users
interacting with it remotely through a computer network (if your version
supports such interaction) an opportunity to receive the Corresponding
Source of your version by providing access to the Corresponding Source
from a network server at no charge, through some standard or customary
means of facilitating copying of software.  This Corresponding Source
shall include the Corresponding Source for any work covered by version 3
of the GNU General Public License that is incorporated pursuant to the
following paragraph.

  Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU General Public License into a single
combined work, and to convey the resulting work.  The terms of this
License will continue to apply to the part which is the covered work,
but the work with which it is combined will remain governed by version
3 of the GNU General Public License.

  14. Revised Versions of this License.

  The Free Software Foundation may publish revised and/or new versions of
the GNU Affero General Public License from time to time.  Such new versions
will be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.

  Each version is given a distinguishing version number.  If the
Program specifies that a certain numbered version of the GNU Affero General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation.  If the Program does not specify a version number of the
GNU Affero General Public License, you may choose any version ever published
by the Free Software Foundation.

  If the Program specifies that a proxy can decide which future
versions of the GNU Affero General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.

  Later license versions may give you additional or different
permissions.  However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.

  15. Disclaimer of Warranty.

  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.

  16. Limitation of Liability.

  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.

  17. Interpretation of Sections 15 and 16.

  If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.

                     END OF TERMS AND CONDITIONS

            How to Apply These Terms to Your New Programs

  If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.

  To do so, attach the following notices to the program.  It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.

    <one line to give the program's name and a brief idea of what it does.>
    Copyright (C) <year>  <name of author>

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with this program.  If not, see <https://www.gnu.org/licenses/>.

Also add information on how to contact you by electronic and paper mail.

  If your software can interact with users remotely through a computer
network, you should also make sure that it provides a way for users to
get its source.  For example, if your program is a web application, its
interface could display a "Source" link that leads users to an archive
of the code.  There are many ways you could offer source, and different
solutions will be better for different programs; see section 13 for the
specific requirements.

  You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU AGPL, see
<https://www.gnu.org/licenses/>.


================================================
FILE: README.rst
================================================
Pelican |build-status| |pypi-version| |downloads| |repology|
============================================================

Pelican is a static site generator, written in Python_, that allows you to create
web sites by composing text files in formats such as Markdown, reStructuredText, and HTML.

With Pelican, you can create web sites without worrying about databases or server-side programming.
Pelican generates static sites that can be served via any web server or hosting service.

You can perform the following functions with Pelican:

* Compose content in Markdown_ or reStructuredText_ using your editor of choice
* Simple command-line tool (re)generates HTML, CSS, and JS from your source content
* Easy to interface with version control systems and web hooks
* Completely static output is simple to host anywhere


Features
--------

Pelican’s feature highlights include:

* Chronological content (e.g., articles, blog posts) as well as static pages
* Integration with external services
* Site themes (created using Jinja2_ templates)
* Publication of articles in multiple languages
* Generation of Atom and RSS feeds
* Code syntax highlighting via Pygments_
* Import existing content from WordPress, Dotclear, or RSS feeds
* Fast rebuild times due to content caching and selective output writing
* Extensible via a rich plugin ecosystem: `Pelican Plugins`_

Check out the `Pelican documentation`_ for further information.


How to get help, contribute, or provide feedback
------------------------------------------------

See our `contribution submission and feedback guidelines <CONTRIBUTING.rst>`_.


Source code
-----------

Pelican’s source code is `hosted on GitHub`_. For information on how it works,
have a look at `Pelican's internals`_.


Why the name “Pelican”?
-----------------------

“Pelican” is an anagram of *calepin*, which means “notebook” in French.


.. Links

.. _Python: https://www.python.org/
.. _reStructuredText: http://docutils.sourceforge.net/rst.html
.. _Markdown: https://daringfireball.net/projects/markdown/
.. _Jinja2: https://palletsprojects.com/p/jinja/
.. _Pygments: https://pygments.org/
.. _`Pelican Plugins`: https://github.com/pelican-plugins
.. _`Pelican documentation`: https://docs.getpelican.com/
.. _`Pelican's internals`: https://docs.getpelican.com/en/latest/internals.html
.. _`hosted on GitHub`: https://github.com/getpelican/pelican

.. |build-status| image:: https://img.shields.io/github/actions/workflow/status/getpelican/pelican/main.yml?branch=main
   :target: https://github.com/getpelican/pelican/actions/workflows/main.yml?query=branch%3Amain
   :alt: GitHub Actions CI: continuous integration status
.. |pypi-version| image:: https://img.shields.io/pypi/v/pelican.svg
   :target: https://pypi.org/project/pelican/
   :alt: PyPI: the Python Package Index
.. |downloads| image:: https://img.shields.io/pypi/dm/pelican.svg
   :target: https://pypi.org/project/pelican/
   :alt: Monthly Downloads from PyPI
.. |repology| image:: https://repology.org/badge/tiny-repos/pelican.svg
   :target: https://repology.org/project/pelican/versions
   :alt: Repology: the packaging hub


================================================
FILE: THANKS
================================================
Pelican is a project led by Justin Mayer <https://justinmayer.com/>
and originally created by Alexis Métaireau <https://blog.notmyidea.org/>, but
there are a large number of people that have contributed or implemented key
features over time. We do our best to keep this list up-to-date, but you can
also have a look at the nice contributor graphs produced by GitHub:
https://github.com/getpelican/pelican/graphs/contributors

If you want to contribute, check the documentation section about how to do so:
<https://docs.getpelican.com/en/latest/contribute.html>

Aaron Kavlie
Abhishek L
Albrecht Mühlenschulte
Aldiantoro Nugroho
Alen Mujezinovic
Alessandro Martin
Alexander Artemenko
Alexandre RODIERE
Alexis Daboville
Alexis Métaireau
Allan Whatmough
Andrea Crotti
Andrew Laski
Andrew Spiers
Arnaud BOS
asselinpaul
Axel Haustant
Ben Rosser (TC01)
Ben Sturmfels
Benoît HERVIER
Bernhard Scheirle
Borgar
Brandon W Maister
Brendan Wholihan
Brian C. Lane
Brian Hsu
Brian St. Pierre
Bruno Binet
BunnyMan
Chenguang Wang
Chris Elston
Chris McDonald (Wraithan)
Chris Streeter
Christophe Chauvet
Clint Howarth
Colin Dunklau
Dafydd Crosby
Dana Woodman
Dave King
Dave Mankoff
David Beitey
David Marble
Deniz Turgut (Avaris)
derdon
Dirkjan Ochtman
Dirk Makowski
draftcode
Edward Delaporte
Emily Strickland
epatters
Eric Case
Erik Hetzner
FELD Boris
Feth Arezki
Florian Jacob
Florian Preinstorfer
Félix Delval
Frederik Ring
Freeculture
George V. Reilly
Guillaume
Guillaume B
Guillermo López
guillermooo
Ian Cordasco
Igor Kalnitsky
Irfan Ahmad
Iuri de Silvio
Ivan Dyedov
James King
James Rowe
Jason K. Moore
jawher
Jered Boxman
Jerome
Jiachen Yang
Jochen Breuer
joe di castro
John Kristensen
John Mastro
Jökull Sólberg Auðunsson
Jomel Imperio
Jonas Borges
Joseph Reagle
Joshua Adelman
Julian Berman
Justin Mayer
Kevin Deldycke
Kevin Yap
Kyle Fuller
Laureline Guerin
Leonard Huang
Leonardo Giordani
Leroy Jiang
Lucas Cimon
Marcel Hellkamp
Marco Milanesi
Marcus Fredriksson
Mario Rodas
Mark Caudill
Martin Brochhaus
Massimo Santini
Matt Bowcock
Matt Layman
Meir Kriheli
Michael Guntsche
Michael Reneer
Michael Yanovich
Mike Yumatov
Mikhail Korobov
Mirek Długosz
m-r-r
mviera
Nam Nguyen
NianQing Yao
Nico Di Rocco
Nicolas Duhamel
Nicolas Perriault
Nicolas Steinmetz
Paolo Melchiorre
Paul Asselin
Pavel Puchkin
Perry Roper
Peter Desmet
Peter Sabaini
Petr Viktorin
Philippe Pepiot
Rachid Belaid
Randall Degges
Ranjhith Kalisamy
Remi Rampin
Rémy HUBSCHER
renhbo
Richard Duivenvoorde
Rogdham
Romain Porte
Roman Skvazh
Ronny Pfannschmidt
Rory McCann
Rıdvan Örsvuran
saghul
sam
Samrat Man Singh
Simon Conseil
Simon Liedtke
Skami18
solsTiCe d'Hiver
Steve Schwarz
Stéphane Bunel
Stéphane Raimbault
Stuart Colville
Talha Mansoor
Tarek Ziade
Thanos Lefteris
Thomas Thurman
Tobias
Tom Adler
Tomi Pieviläinen
Trae Blain
Tristan Miller
Tshepang Lekhonkhobe
Valentin-Costel Hăloiu
Vlad Niculae
William Light
William Minchin
Wladislaw Merezhko
W. Trevor King
Zoresvit


================================================
FILE: docs/Makefile
================================================
# Makefile for Sphinx documentation
#

# You can set these variables from the command line.
SPHINXOPTS    =
SPHINXBUILD   = sphinx-build
PAPER         =
BUILDDIR      = _build

# Internal variables.
PAPEROPT_a4     = -D latex_paper_size=a4
PAPEROPT_letter = -D latex_paper_size=letter
ALLSPHINXOPTS   = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .

.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest

help:
	@echo "Please use \`make <target>' where <target> is one of"
	@echo "  html       to make standalone HTML files"
	@echo "  dirhtml    to make HTML files named index.html in directories"
	@echo "  singlehtml to make a single large HTML file"
	@echo "  pickle     to make pickle files"
	@echo "  json       to make JSON files"
	@echo "  htmlhelp   to make HTML files and a HTML help project"
	@echo "  qthelp     to make HTML files and a qthelp project"
	@echo "  devhelp    to make HTML files and a Devhelp project"
	@echo "  epub       to make an epub"
	@echo "  latex      to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
	@echo "  latexpdf   to make LaTeX files and run them through pdflatex"
	@echo "  text       to make text files"
	@echo "  man        to make manual pages"
	@echo "  changes    to make an overview of all changed/added/deprecated items"
	@echo "  linkcheck  to check all external links for integrity"
	@echo "  doctest    to run all doctests embedded in the documentation (if enabled)"

clean:
	-rm -rf $(BUILDDIR)/*

html:
	$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
	@echo
	@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."

dirhtml:
	$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
	@echo
	@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."

singlehtml:
	$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
	@echo
	@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."

pickle:
	$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
	@echo
	@echo "Build finished; now you can process the pickle files."

json:
	$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
	@echo
	@echo "Build finished; now you can process the JSON files."

htmlhelp:
	$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
	@echo
	@echo "Build finished; now you can run HTML Help Workshop with the" \
	      ".hhp project file in $(BUILDDIR)/htmlhelp."

qthelp:
	$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
	@echo
	@echo "Build finished; now you can run "qcollectiongenerator" with the" \
	      ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
	@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/Raclette.qhcp"
	@echo "To view the help file:"
	@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/Raclette.qhc"

devhelp:
	$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
	@echo
	@echo "Build finished."
	@echo "To view the help file:"
	@echo "# mkdir -p $$HOME/.local/share/devhelp/Raclette"
	@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/Raclette"
	@echo "# devhelp"

epub:
	$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
	@echo
	@echo "Build finished. The epub file is in $(BUILDDIR)/epub."

latex:
	$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
	@echo
	@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
	@echo "Run \`make' in that directory to run these through (pdf)latex" \
	      "(use \`make latexpdf' here to do that automatically)."

latexpdf:
	$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
	@echo "Running LaTeX files through pdflatex..."
	make -C $(BUILDDIR)/latex all-pdf
	@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."

text:
	$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
	@echo
	@echo "Build finished. The text files are in $(BUILDDIR)/text."

man:
	$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
	@echo
	@echo "Build finished. The manual pages are in $(BUILDDIR)/man."

changes:
	$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
	@echo
	@echo "The overview file is in $(BUILDDIR)/changes."

linkcheck:
	$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
	@echo
	@echo "Link check complete; look for any errors in the above output " \
	      "or in $(BUILDDIR)/linkcheck/output.txt."

doctest:
	$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
	@echo "Testing of doctests in the sources finished, look at the " \
	      "results in $(BUILDDIR)/doctest/output.txt."


================================================
FILE: docs/_static/theme_overrides.css
================================================

/* override table width restrictions */
.wy-table-responsive table td, .wy-table-responsive table th {
    /* !important prevents the common CSS stylesheets from
       overriding this as on RTD they are loaded after this stylesheet */
    white-space: normal !important;
}

.wy-table-responsive {
    overflow: visible !important;
}


================================================
FILE: docs/_templates/page.html
================================================
{% extends "base.html" %}

{% block body -%}
  {{ super() }}
  {% include "partials/icons.html" %}

  <input type="checkbox" class="sidebar-toggle" name="__navigation" id="__navigation" aria-label="Toggle site navigation sidebar">
  <input type="checkbox" class="sidebar-toggle" name="__toc" id="__toc" aria-label="Toggle table of contents sidebar">
  <label class="overlay sidebar-overlay" for="__navigation"></label>
  <label class="overlay toc-overlay" for="__toc"></label>

  <a class="skip-to-content muted-link" href="#furo-main-content">
    {%- trans -%}
      Skip to content
    {%- endtrans -%}
  </a>

  {% if theme_announcement -%}
    <div class="announcement">
      <aside class="announcement-content">
        {% block announcement %} {{ theme_announcement }} {% endblock announcement %}
      </aside>
    </div>
  {%- endif %}

  <div class="page">
    <header class="mobile-header">
      <div class="header-left">
        <label class="nav-overlay-icon" for="__navigation">
          <span class="icon"><svg><use href="#svg-menu"></use></svg></span>
        </label>
      </div>
      <div class="header-center">
        <a href="{{ pathto(master_doc) }}"><div class="brand">{{ docstitle if docstitle else project }}</div></a>
      </div>
      <div class="header-right">
        <div class="theme-toggle-container theme-toggle-header">
          <button class="theme-toggle" aria-label="Toggle Light / Dark / Auto color theme">
            <svg class="theme-icon-when-auto-light"><use href="#svg-sun-with-moon"></use></svg>
            <svg class="theme-icon-when-auto-dark"><use href="#svg-moon-with-sun"></use></svg>
            <svg class="theme-icon-when-dark"><use href="#svg-moon"></use></svg>
            <svg class="theme-icon-when-light"><use href="#svg-sun"></use></svg>
          </button>
        </div>
        <label class="toc-overlay-icon toc-header-icon{% if furo_hide_toc %} no-toc{% endif %}" for="__toc">
          <span class="icon"><svg><use href="#svg-toc"></use></svg></span>
        </label>
      </div>
    </header>
    <aside class="sidebar-drawer">
      <div class="sidebar-container">
        {% block left_sidebar %}
          <div class="sidebar-sticky">
            {%- for sidebar_section in sidebars %}
              {%- include sidebar_section %}
            {%- endfor %}
          </div>
        {% endblock left_sidebar %}
      </div>
    </aside>
    <div class="main">
      <div class="content">
        <div class="article-container">
          <a href="#" class="back-to-top muted-link">
            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
              <path d="M13 20h-2V8l-5.5 5.5-1.42-1.42L12 4.16l7.92 7.92-1.42 1.42L13 8v12z"></path>
            </svg>
            <span>{% trans %}Back to top{% endtrans %}</span>
          </a>
          <div class="content-icon-container">
            {% if theme_top_of_page_button != "edit" -%}
              {{ warning("Got configuration for 'top_of_page_button': this is deprecated.") }}
            {%- endif -%}

            {%- if theme_top_of_page_buttons == "" -%}
              {% if theme_top_of_page_button == None -%}
              {#- We respect the old configuration of disabling all the buttons -#}
                {%- set theme_top_of_page_buttons = [] -%}
              {% else %}
                {%- set theme_top_of_page_buttons = ["view", "edit"] -%}
              {%- endif -%}
            {% else -%}
              {% if theme_top_of_page_button != "edit" -%}
                {%- set theme_top_of_page_buttons = [] -%}
                {{ warning("Got configuration for both 'top_of_page_button' and 'top_of_page_buttons', ignoring both and removing all top of page buttons.") }}
              {%- endif -%}
            {%- endif -%}
            {% for button in theme_top_of_page_buttons -%}
              {% if button == "view" %}
                {%- include "components/view-this-page.html" with context -%}
              {% elif button == "edit" %}
                {%- include "components/edit-this-page.html" with context -%}
              {% else %}
                {{ warning("Got an unsupported value in 'top_of_page_buttons' for theme configuration") }}
              {% endif %}
            {%- endfor -%}
          {#- Theme toggle -#}
            <div class="theme-toggle-container theme-toggle-content">
              <button class="theme-toggle" aria-label="Toggle Light / Dark / Auto color theme">
                <svg class="theme-icon-when-auto-light"><use href="#svg-sun-with-moon"></use></svg>
                <svg class="theme-icon-when-auto-dark"><use href="#svg-moon-with-sun"></use></svg>
                <svg class="theme-icon-when-dark"><use href="#svg-moon"></use></svg>
                <svg class="theme-icon-when-light"><use href="#svg-sun"></use></svg>
              </button>
            </div>
            <label class="toc-overlay-icon toc-content-icon{% if furo_hide_toc %} no-toc{% endif %}" for="__toc">
              <span class="icon"><svg><use href="#svg-toc"></use></svg></span>
            </label>
          </div>
          <article role="main" id="furo-main-content">
            {% block content %}{{ body }}{% endblock %}
          </article>
        </div>
        <footer>
          {% block footer %}
            <div class="related-pages">
              {% if next -%}
                <a class="next-page" href="{{ next.link }}">
                  <div class="page-info">
                    <div class="context">
                      <span>{{ _("Next") }}</span>
                    </div>
                    <div class="title">{{ next.title }}</div>
                  </div>
                  <svg class="furo-related-icon"><use href="#svg-arrow-right"></use></svg>
                </a>
              {%- endif %}
              {% if prev -%}
                <a class="prev-page" href="{{ prev.link }}">
                  <svg class="furo-related-icon"><use href="#svg-arrow-right"></use></svg>
                  <div class="page-info">
                    <div class="context">
                      <span>{{ _("Previous") }}</span>
                    </div>
                    {% if prev.link == pathto(master_doc) %}
                      <div class="title">{{ _("Home") }}</div>
                    {% else %}
                      <div class="title">{{ prev.title }}</div>
                    {% endif %}
                  </div>
                </a>
              {%- endif %}
            </div>
            <div class="bottom-of-page">
              <div class="left-details">
                {%- if show_copyright %}
                  <div class="copyright">
                    {%- if hasdoc('copyright') %}
                      {% trans path=pathto('copyright'), copyright=copyright|e -%}
                        <a href="{{ path }}">Copyright</a> &#169; {{ copyright }}
                      {%- endtrans %}
                    {%- else %}
                      {% trans copyright=copyright|e -%}
                        Copyright &#169; {{ copyright }}, <a href="https://justinmayer.com">Justin Mayer</a>, Alexis Metaireau, and contributors
                      {%- endtrans %}
                    {%- endif %}
                  </div>
                {%- endif %}
                {%- if last_updated -%}
                  <div class="last-updated">
                    {% trans last_updated=last_updated|e -%}
                      Last updated on {{ last_updated }}
                    {%- endtrans -%}
                  </div>
                {%- endif %}
              </div>
              <div class="right-details">
                {% if theme_footer_icons or READTHEDOCS -%}
                  <div class="icons">
                    {% if theme_footer_icons -%}
                      {% for icon_dict in theme_footer_icons -%}
                        <a class="muted-link {{ icon_dict.class }}" href="{{ icon_dict.url }}" aria-label="{{ icon_dict.name }}">
                          {{- icon_dict.html -}}
                        </a>
                      {% endfor %}
                    {%- else -%}
              {#- Show Read the Docs project -#}
                      {%- if READTHEDOCS and slug -%}
                        <a class="muted-link" href="https://readthedocs.org/projects/{{ slug }}" aria-label="On Read the Docs">
                          <svg x="0px" y="0px" viewBox="-125 217 360 360" xml:space="preserve">
                            <path fill="currentColor" d="M39.2,391.3c-4.2,0.6-7.1,4.4-6.5,8.5c0.4,3,2.6,5.5,5.5,6.3 c0,0,18.5,6.1,50,8.7c25.3,2.1,54-1.8,54-1.8c4.2-0.1,7.5-3.6,7.4-7.8c-0.1-4.2-3.6-7.5-7.8-7.4c-0.5,0-1,0.1-1.5,0.2 c0,0-28.1,3.5-50.9,1.6c-30.1-2.4-46.5-7.9-46.5-7.9C41.7,391.3,40.4,391.1,39.2,391.3z M39.2,353.6c-4.2,0.6-7.1,4.4-6.5,8.5 c0.4,3,2.6,5.5,5.5,6.3c0,0,18.5,6.1,50,8.7c25.3,2.1,54-1.8,54-1.8c4.2-0.1,7.5-3.6,7.4-7.8c-0.1-4.2-3.6-7.5-7.8-7.4 c-0.5,0-1,0.1-1.5,0.2c0,0-28.1,3.5-50.9,1.6c-30.1-2.4-46.5-7.9-46.5-7.9C41.7,353.6,40.4,353.4,39.2,353.6z M39.2,315.9 c-4.2,0.6-7.1,4.4-6.5,8.5c0.4,3,2.6,5.5,5.5,6.3c0,0,18.5,6.1,50,8.7c25.3,2.1,54-1.8,54-1.8c4.2-0.1,7.5-3.6,7.4-7.8 c-0.1-4.2-3.6-7.5-7.8-7.4c-0.5,0-1,0.1-1.5,0.2c0,0-28.1,3.5-50.9,1.6c-30.1-2.4-46.5-7.9-46.5-7.9 C41.7,315.9,40.4,315.8,39.2,315.9z M39.2,278.3c-4.2,0.6-7.1,4.4-6.5,8.5c0.4,3,2.6,5.5,5.5,6.3c0,0,18.5,6.1,50,8.7 c25.3,2.1,54-1.8,54-1.8c4.2-0.1,7.5-3.6,7.4-7.8c-0.1-4.2-3.6-7.5-7.8-7.4c-0.5,0-1,0.1-1.5,0.2c0,0-28.1,3.5-50.9,1.6 c-30.1-2.4-46.5-7.9-46.5-7.9C41.7,278.2,40.4,278.1,39.2,278.3z M-13.6,238.5c-39.6,0.3-54.3,12.5-54.3,12.5v295.7 c0,0,14.4-12.4,60.8-10.5s55.9,18.2,112.9,19.3s71.3-8.8,71.3-8.8l0.8-301.4c0,0-25.6,7.3-75.6,7.7c-49.9,0.4-61.9-12.7-107.7-14.2 C-8.2,238.6-10.9,238.5-13.6,238.5z M19.5,257.8c0,0,24,7.9,68.3,10.1c37.5,1.9,75-3.7,75-3.7v267.9c0,0-19,10-66.5,6.6 C59.5,536.1,19,522.1,19,522.1L19.5,257.8z M-3.6,264.8c4.2,0,7.7,3.4,7.7,7.7c0,4.2-3.4,7.7-7.7,7.7c0,0-12.4,0.1-20,0.8 c-12.7,1.3-21.4,5.9-21.4,5.9c-3.7,2-8.4,0.5-10.3-3.2c-2-3.7-0.5-8.4,3.2-10.3c0,0,0,0,0,0c0,0,11.3-6,27-7.5 C-16,264.9-3.6,264.8-3.6,264.8z M-11,302.6c4.2-0.1,7.4,0,7.4,0c4.2,0.5,7.2,4.3,6.7,8.5c-0.4,3.5-3.2,6.3-6.7,6.7 c0,0-12.4,0.1-20,0.8c-12.7,1.3-21.4,5.9-21.4,5.9c-3.7,2-8.4,0.5-10.3-3.2c-2-3.7-0.5-8.4,3.2-10.3c0,0,11.3-6,27-7.5 C-20.5,302.9-15.2,302.7-11,302.6z M-3.6,340.2c4.2,0,7.7,3.4,7.7,7.7s-3.4,7.7-7.7,7.7c0,0-12.4-0.1-20,0.7 c-12.7,1.3-21.4,5.9-21.4,5.9c-3.7,2-8.4,0.5-10.3-3.2c-2-3.7-0.5-8.4,3.2-10.3c0,0,11.3-6,27-7.5C-16,340.1-3.6,340.2-3.6,340.2z" />
                          </svg>
                        </a>
                      {%- endif -%}
              {#- Show GitHub repository home -#}
                      {%- if READTHEDOCS and display_github and github_user != "None" and github_repo != "None" -%}
                        <a class="muted-link" href="https://github.com/{{ github_user }}/{{ github_repo }}" aria-label="On GitHub">
                          <svg stroke="currentColor" fill="currentColor" stroke-width="0" viewBox="0 0 16 16">
                            <path fill-rule="evenodd" d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0 0 16 8c0-4.42-3.58-8-8-8z"></path>
                          </svg>
                        </a>
                      {%- endif -%}
                    {%- endif %}
                  </div>
                {%- endif %}
              </div>
            </div>
          {% endblock footer %}
        </footer>
      </div>
      <aside class="toc-drawer{% if furo_hide_toc %} no-toc{% endif %}">
        {% block right_sidebar %}
          {% if not furo_hide_toc %}
            <div class="toc-sticky toc-scroll">
              <div class="toc-title-container">
                <span class="toc-title">
                  {{ _("On this page") }}
                </span>
              </div>
              <div class="toc-tree-container">
                <div class="toc-tree">
                  {{ toc }}
                </div>
              </div>
            </div>
          {% endif %}
        {% endblock right_sidebar %}
      </aside>
    </div>
  </div>
{%- endblock %}


================================================
FILE: docs/changelog.rst
================================================
Release history
###############

4.11.0 - 2025-01-15
===================

- Add setting to selectively omit Typogrify filters `(#3439) <https://github.com/getpelican/pelican/pull/3439>`_
- Add more blocks to the Simple theme’s base template, making it easier to create new themes by inheriting from the Simple theme `(#3405) <https://github.com/getpelican/pelican/pull/3405>`_
- Fix auto-reload behavior upon changes to the theme, content or settings. Make default ``IGNORE_FILES`` recursively ignore all hidden files as well as the `default filters <https://watchfiles.helpmanual.io/api/filters/#watchfiles.DefaultFilter.ignore_dirs>`_ from ``watchfiles.DefaultFilter``. `(#3441) <https://github.com/getpelican/pelican/pull/3441>`_
- Get current year from the ``SOURCE_DATE_EPOCH`` environment variable, if available `(#3430) <https://github.com/getpelican/pelican/pull/3430>`_
- Add Python 3.13 to test matrix and remove Python 3.8 `(#3435) <https://github.com/getpelican/pelican/pull/3435>`_
- Require Typogrify 2.1+ and Pygments <2.19

4.10.2 - 2024-11-27
===================

- Change ``IGNORE_FILES`` setting default to ignore all hidden files
- Fix ``SUMMARY_MAX_PARAGRAPHS`` not being respected in some combinations with ``SUMMARY_MAX_LENGTH``

4.10.1 - 2024-09-28
===================

- Fix error when running ``pelican -r -l``
- Fix symlink handling in ``pelican-themes``

4.10.0 - 2024-09-16
===================

- Add setting to specify summary via paragraph count
- Add new status to skip generation of a post
- Add setting to append ``ref`` parameter to links in feeds
- Configure logging handler via ``--log-handler`` CLI option
- Resolve intra-site links in summaries
- Warn when files are not processed due to disabled readers
- Add Medium post importer
- Improve GitHub Pages workflow
- Improve code test coverage
- Translate documentation into Simplified Chinese

4.9.1 - 2023-11-15
==================

* Ensure ``tzdata`` dependency is installed on Windows

4.9.0 - 2023-11-12
==================

* Upgrade code to new minimum supported Python version: 3.8
* Settings support for ``pathlib.Path`` `(#2758) <https://github.com/getpelican/pelican/pull/2758>`_
* Various improvements to Simple theme (`#2976 <https://github.com/getpelican/pelican/pull/2976>`_ & `#3234 <https://github.com/getpelican/pelican/pull/3234>`_)
* Use Furo as Sphinx documentation theme `(#3023) <https://github.com/getpelican/pelican/pull/3023>`_
* Default to 100 articles maximum in feeds `(#3127) <https://github.com/getpelican/pelican/pull/3127>`_
* Add ``period_archives common context`` variable `(#3148) <https://github.com/getpelican/pelican/pull/3148>`_
* Use ``watchfiles`` as the file-watching backend `(#3151) <https://github.com/getpelican/pelican/pull/3151>`_
* Add GitHub Actions workflow for GitHub Pages `(#3189) <https://github.com/getpelican/pelican/pull/3189>`_
* Allow dataclasses in settings `(#3204) <https://github.com/getpelican/pelican/pull/3204>`_
* Switch build tool to PDM instead of Setuptools/Poetry `(#3220) <https://github.com/getpelican/pelican/pull/3220>`_
* Provide a ``plugin_enabled`` Jinja test for themes `(#3235) <https://github.com/getpelican/pelican/pull/3235>`_
* Preserve connection order in Blinker `(#3238) <https://github.com/getpelican/pelican/pull/3238>`_
* Remove social icons from default ``notmyidea`` theme `(#3240) <https://github.com/getpelican/pelican/pull/3240>`_
* Remove unreliable ``WRITE_SELECTED`` feature `(#3243) <https://github.com/getpelican/pelican/pull/3243>`_
* Importer: Report broken embedded video links when importing from Tumblr `(#3177) <https://github.com/getpelican/pelican/issues/3177>`_
* Importer: Remove newline addition when iterating Photo post types `(#3178) <https://github.com/getpelican/pelican/issues/3178>`_
* Importer: Force timestamp conversion in Tumblr importer to be UTC with offset `(#3221) <https://github.com/getpelican/pelican/pull/3221>`_
* Importer: Use tempfile for intermediate HTML file for Pandoc `(#3221) <https://github.com/getpelican/pelican/pull/3221>`_
* Switch linters to Ruff `(#3223) <https://github.com/getpelican/pelican/pull/3223>`_

4.8.0 - 2022-07-11
==================

* Use JSON values for extra settings in Invoke tasks template `(#2994) <https://github.com/getpelican/pelican/pull/2994>`_
* Add content tag for links, which can help with things like Twitter social cards `(#3001) <https://github.com/getpelican/pelican/pull/3001>`_
* Improve word count behavior when generating summary `(#3002) <https://github.com/getpelican/pelican/pull/3002>`_

4.7.2 - 2022-02-09
==================

* Fix incorrect parsing of parameters specified via `-e` / `--extra-settings` option flags `(#2938) <https://github.com/getpelican/pelican/pull/2938>`_
* Add ``categories.html`` template to default theme `(#2973) <https://github.com/getpelican/pelican/pull/2973>`_
* Document how to use plugins to inject content `(#2922) <https://github.com/getpelican/pelican/pull/2922>`_

4.7.1 - 2021-10-12
==================

* Extend rich logging to server component `(#2927) <https://github.com/getpelican/pelican/pull/2927>`_
* Fix an issue where metadata flagged to be discarded was being cached `(#2926) <https://github.com/getpelican/pelican/pull/2926>`_
* Adjust suffix in server to allow redirection when needed `(#2931) <https://github.com/getpelican/pelican/pull/2931>`_
* Add MIME types for web fonts `(#2929) <https://github.com/getpelican/pelican/pull/2929>`_
* Distribute sample data used to run tests `(#2935) <https://github.com/getpelican/pelican/pull/2935>`_
* Add Python 3.10 to test matrix

4.7.0 - 2021-10-01
==================

* Improve default theme rendering on mobile and other small screen devices `(#2914) <https://github.com/getpelican/pelican/pull/2914>`_
* Add support for hidden articles `(#2866) <https://github.com/getpelican/pelican/pull/2866>`_
* Improve word count behavior when generating summary CJK & other locales `(#2864) <https://github.com/getpelican/pelican/pull/2864>`_
* Add progress spinner during generation `(#2869) <https://github.com/getpelican/pelican/pull/2869>`_
  and richer logging `(#2897) <https://github.com/getpelican/pelican/pull/2897>`_, both via `Rich <https://github.com/willmcgugan/rich>`_
* Invoke tasks ``serve`` and ``livereload`` now auto-open a web browser pointing to the locally-served web site `(#2764) <https://github.com/getpelican/pelican/pull/2764>`_
* Support some date format codes used by ISO dates `(#2902) <https://github.com/getpelican/pelican/pull/2902>`_
* Document how to add a new writer `(#2901) <https://github.com/getpelican/pelican/pull/2901>`_

4.6.0 - 2021-03-23
==================

* Add new URL pattern to ``PAGINATION_PATTERNS`` for the last page in the list `(#1401) <https://github.com/getpelican/pelican/issues/1401>`_
* Speed up ``livereload`` Invoke task via caching `(#2847) <https://github.com/getpelican/pelican/pull/2847>`_
* Ignore ``None`` return value from ``get_generators`` signal `(#2850) <https://github.com/getpelican/pelican/pull/2850>`_
* Relax dependency minimum versions and remove upper bounds

4.5.4 - 2021-01-04
==================

Replace plugin definitions in settings with string representations after registering, so they can be cached correctly `(#2828) <https://github.com/getpelican/pelican/issues/2828>`_.

4.5.3 - 2020-12-01
==================

Fix a mistake made in PR #2821

4.5.2 - 2020-11-22
==================

Improve logging of generators and writer loaders

4.5.1 - 2020-11-02
==================

* Refactor intra-site link discovery in order to match more permissively `(#2646) <https://github.com/getpelican/pelican/issues/2646>`_
* Fix plugins running twice in auto-reload mode `(#2817) <https://github.com/getpelican/pelican/issues/2817>`_
* Add notice to use ``from pelican import signals`` instead of ``import pelican.signals`` `(#2805) <https://github.com/getpelican/pelican/issues/2805>`_

4.5.0 - 2020-08-20
==================

* Add namespace plugin support; list plugins via ``pelican-plugins`` command
* Override settings via ``-e`` / ``--extra-settings`` CLI option flags
* Add settings for custom Jinja globals and tests
* Customize article summary ellipsis via ``SUMMARY_END_SUFFIX`` setting
* Customize Typogrify dash handling via new ``TYPOGRIFY_DASHES`` setting
* Support Unicode when generating slugs
* Support Asciidoc ``.adoc`` file generation in Pelican importer
* Improve user experience when ``pelican --listen`` web server is quit
* Improve Invoke tasks template
* Include tests in source distributions
* Switch CI from Travis to GitHub Actions
* Remove support for Python 2.7

4.2.0 - 2019-10-17
==================

* Support inline SVGs; don't treat titles in SVGs as HTML titles
* Add category to feeds (in addition to tags)
* Improve content metadata field docs
* Add docs for including other Markdown/reST files in content

4.1.3 - 2019-10-09
==================

* Fix quick-start docs regarding ``pelican --listen``
* Set default listen address to 127.0.0.1
* Add extra/optional Markdown dependency to setup.py
* Use correct SSH port syntax for rsync in tasks.py
* Place all deprecated settings handling together
* Add related project URLs for display on PyPI
* Skip some tests on Windows that can't pass due to filesystem differences

4.1.2 - 2019-09-23
==================

Fix pelican.settings.load_source to avoid caching issues - PR #2621

4.1.1 - 2019-08-23
==================

* Add AutoPub to auto-publish releases on PR merge
* Add CSS classes for reStructuredText figures
* Pass ``argv`` to Pelican ``main`` entrypoint
* Set default content status to a blank string rather than ``None``

4.1.0 - 2019-07-14
==================

* Live browser reload upon changed files (provided via Invoke task)
* Add ``pyproject.toml``, managed by Poetry
* Support for invoking ``python -m pelican``
* Add relative source path attribute to content
* Allow directories in ``EXTRA_PATH_METADATA``
* Add ``all_articles`` variable to period pages (for recent posts functionality)
* Improve debug mode output
* Remove blank or duplicate summaries from Atom feed
* Fix bugs in pagination, pelican-import, pelican-quickstart, and feed importer

4.0.1 (2018-11-30)
==================

* Refactor ``pelican.server`` logging
* Fix bug in which all static files were processed as "draft"
* Bug fixes for Invoke/Makefile automation, Importer, and other miscellanea

If upgrading from 3.7.x or earlier, please note that slug-related settings in
4.0+ use ``{slug}`` and/or ``{lang}`` rather than ``%s``. If ``%s``-style
settings are encountered, Pelican will emit a warning and fall back to the
default setting. Some user-submitted themes might try to format setting values
but fail upon site build with a ``TypeError``. In such cases, the theme needs
to be updated. For example, instead of ``TAG_FEED_ATOM|format(tag.slug)``, use
``TAG_FEED_ATOM.format(slug=tag.slug)``

4.0.0 (2018-11-13)
==================

* Replace ``develop_server.sh`` script with ``pelican --listen``
* Improved copy/link behavior for large static files (e.g., videos)
* New ``{static}`` syntax to link to static content; content linked to by
  ``{static}`` and ``{attach}`` is automatically copied over even if not in
  ``STATIC_PATHS``
* Pages can now have ``draft`` status
* Show current settings via new ``--print-settings`` flag
* All settings for slugs now use ``{slug}`` and/or ``{lang}`` rather than
  ``%s``. If ``%s``-style settings are encountered, Pelican will emit a warning
  and fallback to the default setting.
* New signals: ``feed_generated`` and ``page_generated_write_page``
* Replace Fabric with Invoke and ``fabfile.py`` template with ``tasks.py``
* Replace ``PAGINATED_DIRECT_TEMPLATES`` by ``PAGINATED_TEMPLATES``, extending
  control over pagination to all templates and making page size variable
* Replace ``SLUG_SUBSTITUTIONS`` (and friends) by ``SLUG_REGEX_SUBSTITUTIONS``
  for more finegrained control
* ``'{base_name}'`` value in ``PAGINATION_PATTERNS`` setting no longer strips
  ``'bar'`` from ``'foo/bar.html'`` (unless ``'bar' == 'index'``).
* ``ARTICLE_ORDER_BY`` and ``PAGE_ORDER_BY`` now also affect 1) category, tag
  and author pages 2) feeds 3) draft and hidden articles and pages
* New ``ARTICLE_TRANSLATION_ID`` and ``PAGE_TRANSLATION_ID`` settings to
  specify metadata attributes used to identify/disable translations
* Make the HTML reader parse multiple occurrences of metadata tags as a list
* New Blogger XML backup importer
* Wordpress importer now updates file links to point to local copies if the
  files were downloaded with ``--wp-attach``.
* Importer no longer inserts extra newlines, to prevent breaking of HTML
  attributes.
* Pelican server now prioritises ``foo.html`` and ``foo/index.html`` over
  ``foo/`` when resolving ``foo``.

3.7.1 (2017-01-10)
==================

* Fix locale issues in Quickstart script
* Specify encoding for README and CHANGELOG in setup.py

3.7.0 (2016-12-12)
==================

* Atom feeds output ``<content>`` in addition to ``<summary>``
* Atom feeds use ``<published>`` for the original publication date and
  ``<updated>`` for modifications
* Simplify Atom feed ID generation and support URL fragments
* Produce category feeds with category-specific titles
* RSS feeds now default to summary instead of full content;
  set ``RSS_FEED_SUMMARY_ONLY = False`` to revert to previous behavior
* Replace ``MD_EXTENSIONS`` with ``MARKDOWN`` setting
* Replace ``JINJA_EXTENSIONS`` with more-robust ``JINJA_ENVIRONMENT`` setting
* Improve summary truncation logic to handle special characters and tags that
  span multiple lines, using HTML parser instead of regular expressions
* Include summary when looking for intra-site link substitutions
* Link to authors and index via ``{author}name`` and ``{index}`` syntax
* Override widget names via ``LINKS_WIDGET_NAME`` and ``SOCIAL_WIDGET_NAME``
* Add ``INDEX_SAVE_AS`` option to override default ``index.html`` value
* Remove ``PAGES`` context variable for themes in favor of ``pages``
* ``SLUG_SUBSTITUTIONS`` now accepts 3-tuple elements, allowing URL slugs to
  contain non-alphanumeric characters
* Tag and category slugs can be controlled with greater precision using the
  ``TAG_SUBSTITUTIONS`` and ``CATEGORY_SUBSTITUTIONS`` settings
* Author slugs can be controlled with greater precision using the
  ``AUTHOR_SUBSTITUTIONS`` setting
* ``DEFAULT_DATE`` can be defined as a string
* Use ``mtime`` instead of ``ctime`` when ``DEFAULT_DATE = 'fs'``
* Add ``--fatal=errors|warnings`` option for use with continuous integration
* When using generator-level caching, ensure previously-cached files are
  processed instead of just new files.
* Add Python and Pelican version information to debug output
* Improve compatibility with Python 3.5
* Comply with and enforce PEP8 guidelines
* Replace tables in settings documentation with ``data::`` directives

3.6.3 (2015-08-14)
==================

* Fix permissions issue in release tarball

3.6.2 (2015-08-01)
==================

* Fix installation errors related to Unicode in tests
* Don't show pagination in ``notmyidea`` theme if there's only one page
* Make hidden pages available in context
* Improve URLWrapper comparison

3.6.0 (2015-06-15)
==================

* Disable caching by default in order to prevent potential confusion
* Improve caching behavior, replacing ``pickle`` with ``cpickle``
* Allow Markdown or reST content in metadata fields other than ``summary``
* Support semicolon-separated author/tag lists
* Improve flexibility of article sorting
* Add ``--relative-urls`` argument
* Support devserver listening on addresses other than localhost
* Unify HTTP server handlers to ``pelican.server`` throughout
* Handle intra-site links to draft posts
* Move ``tag_cloud`` from core to plugin
* Load default theme's external resources via HTTPS
* Import drafts from WordPress XML
* Improve support for Windows users
* Enhance logging and test suite
* Clean up and refactor codebase
* New signals: ``all_generators_finalized`` and ``page_writer_finalized``

3.5.0 (2014-11-04)
==================

* Introduce ``ARTICLE_ORDER_BY`` and ``PAGE_ORDER_BY`` settings to control the
  order of articles and pages.
* Include time zone information in dates rendered in templates.
* Expose the reader name in the metadata for articles and pages.
* Add the ability to store static files along with content in the same
  directory as articles and pages using ``{attach}`` in the path.
* Prevent Pelican from raising an exception when there are duplicate pieces of
  metadata in a Markdown file.
* Introduce the ``TYPOGRIFY_IGNORE_TAGS`` setting to add HTML tags to be
  ignored by Typogrify.
* Add the ability to use ``-`` in date formats to strip leading zeros. For
  example, ``%-d/%-m/%y`` will now result in the date ``9/8/12``.
* Ensure feed generation is correctly disabled during quickstart configuration.
* Fix ``PAGE_EXCLUDES`` and ``ARTICLE_EXCLUDES`` from incorrectly matching
  sub-directories.
* Introduce ``STATIC_EXCLUDE`` setting to add static file excludes.
* Fix an issue when using ``PAGINATION_PATTERNS`` while ``RELATIVE_URLS``
  is enabled.
* Fix feed generation causing links to use the wrong language for month
  names when using other locales.
* Fix an issue where the authors list in the simple template wasn't correctly
  formatted.
* Fix an issue when parsing non-string URLs from settings.
* Improve consistency of debug and warning messages.

3.4.0 (2014-07-01)
==================

* Speed up content generation via new caching mechanism
* Add selective post generation (instead of always building entire site)
* Many documentation improvements, including switching to prettier RtD theme
* Add support for multiple content and plugin paths
* Add ``:modified:`` metadata field to complement ``:date:``.
  Used to specify the last date and time an article was updated independently
  from the date and time it was published.
* Add support for multiple authors via new ``:authors:`` metadata field
* Watch for changes in static directories when in auto-regeneration mode
* Add filters to limit log output when desired
* Add language support to drafts
* Add ``SLUGIFY_SOURCE`` setting to control how post slugs are generated
* Fix many issues relating to locale and encoding
* Apply Typogrify filter to post summary
* Preserve file metadata (e.g. time stamps) when copying static files to output
* Move AsciiDoc support from Pelican core into separate plugin
* Produce inline links instead of reference-style links when importing content
* Improve handling of ``IGNORE_FILES`` setting behavior
* Properly escape symbol characters in tag names (e.g., ``C++``)
* Minor tweaks for Python 3.4 compatibility
* Add several new signals

3.3.0 (2013-09-24)
==================

* Drop Python 3.2 support in favor of Python 3.3
* Add ``Fabfile`` so Fabric can be used for workflow automation instead of Make
* ``OUTPUT_RETENTION`` setting can be used to preserve metadata (e.g., VCS
  data such as ``.hg`` and ``.git``) from being removed from output directory
* Tumblr import
* Improve logic and consistency when cleaning output folder
* Improve documentation versioning and release automation
* Improve pagination flexibility
* Rename signals for better consistency (some plugins may need to be updated)
* Move metadata extraction from generators to readers; metadata extraction no
  longer article-specific
* Deprecate ``FILES_TO_COPY`` in favor of ``STATIC_PATHS`` and
  ``EXTRA_PATH_METADATA``
* Summaries in Markdown posts no longer include footnotes
* Remove unnecessary whitespace in output via ``lstrip_blocks`` Jinja parameter
* Move PDF generation from core to plugin
* Replace ``MARKUP`` setting with ``READERS``
* Add warning if img tag is missing ``alt`` attribute
* Add support for ``{}`` in relative links syntax, besides ``||``
* Add support for ``{tag}`` and ``{category}`` relative links
* Add a ``content_written`` signal

3.2.1 and 3.2.2
===============

* Facilitate inclusion in FreeBSD Ports Collection

3.2 (2013-04-24)
================

* Support for Python 3!
* Override page save-to location from meta-data (enables using a static page as
  the site's home page, for example)
* Time period archives (per-year, per-month, and per-day archives of posts)
* Posterous blog import
* Improve WordPress blog import
* Migrate plugins to separate repository
* Improve HTML parser
* Provide ability to show or hide categories from menu using
  ``DISPLAY_CATEGORIES_ON_MENU`` option
* Auto-regeneration can be told to ignore files via ``IGNORE_FILES`` setting
* Improve post-generation feedback to user
* For multilingual posts, use meta-data to designate which is the original
  and which is the translation
* Add ``.mdown`` to list of supported Markdown file extensions
* Document-relative URL generation (``RELATIVE_URLS``) is now off by default

3.1 (2012-12-04)
================

* Importer now stores slugs within files by default. This can be disabled with
  the ``--disable-slugs`` option.
* Improve handling of links to intra-site resources
* Ensure WordPress import adds paragraphs for all types of line endings
  in post content
* Decode HTML entities within WordPress post titles on import
* Improve appearance of LinkedIn icon in default theme
* Add GitHub and Google+ social icons support in default theme
* Optimize social icons
* Add ``FEED_ALL_ATOM`` and ``FEED_ALL_RSS`` to generate feeds containing all
  posts regardless of their language
* Split ``TRANSLATION_FEED`` into ``TRANSLATION_FEED_ATOM`` and
  ``TRANSLATION_FEED_RSS``
* Different feeds can now be enabled/disabled individually
* Allow for blank author: if ``AUTHOR`` setting is not set, author won't
  default to ``${USER}`` anymore, and a post won't contain any author
  information if the post author is empty
* Move LESS and Webassets support from Pelican core to plugin
* The ``DEFAULT_DATE`` setting now defaults to ``None``, which means that
  articles won't be generated unless date metadata is specified
* Add ``FILENAME_METADATA`` setting to support metadata extraction from
  filename
* Add ``gzip_cache`` plugin to compress common text files into a ``.gz``
  file within the same directory as the original file, preventing the server
  (e.g. Nginx) from having to compress files during an HTTP call
* Add support for AsciiDoc-formatted content
* Add ``USE_FOLDER_AS_CATEGORY`` setting so that feature can be toggled on/off
* Support arbitrary Jinja template files
* Restore basic functional tests
* New signals: ``generator_init``, ``get_generators``, and
  ``article_generate_preread``

3.0 (2012-08-08)
================

* Refactored the way URLs are handled
* Improved the English documentation
* Fixed packaging using ``setuptools`` entrypoints
* Added ``typogrify`` support
* Added a way to disable feed generation
* Added support for ``DIRECT_TEMPLATES``
* Allow multiple extensions for content files
* Added LESS support
* Improved the import script
* Added functional tests
* Rsync support in the generated Makefile
* Improved feed support (easily pluggable with Feedburner for instance)
* Added support for ``abbr`` in reST
* Fixed a bunch of bugs :-)

2.8 (2012-02-28)
==================

* Dotclear importer
* Allow the usage of Markdown extensions
* Themes are now easily extensible
* Don't output pagination information if there is only one page
* Add a page per author, with all their articles
* Improved the test suite
* Made the themes easier to extend
* Removed Skribit support
* Added a ``pelican-quickstart`` script
* Fixed timezone-related issues
* Added some scripts for Windows support
* Date can be specified in seconds
* Never fail when generating posts (skip and continue)
* Allow the use of future dates
* Support having different timezones per language
* Enhanced the documentation

2.7 (2011-06-11)
==================

* Use ``logging`` rather than echoing to stdout
* Support custom Jinja filters
* Compatibility with Python 2.5
* Added a theme manager
* Packaged for Debian
* Added draft support

2.6 (2011-03-08)
==================

* Changes in the output directory structure
* Makes templates easier to work with / create
* Added RSS support (was Atom-only)
* Added tag support for the feeds
* Enhance the documentation
* Added another theme (brownstone)
* Added translations
* Added a way to use cleaner URLs with a rewrite url module (or equivalent)
* Added a tag cloud
* Added an autoreloading feature: the blog is automatically regenerated each
  time a modification is detected
* Translate the documentation into French
* Import a blog from an RSS feed
* Pagination support
* Added Skribit support

2.5 (2010-11-20)
==================

* Import from WordPress
* Added some new themes (martyalchin / wide-notmyidea)
* First bug report!
* Linkedin support
* Added a FAQ
* Google Analytics support
* Twitter support
* Use relative URLs, not static ones

2.4 (2010-11-06)
================

* Minor themes changes
* Add Disqus support (so we have comments)
* Another code refactoring
* Added config settings about pages
* Blog entries can also be generated in PDF

2.3 (2010-10-31)
================

* Markdown support

2.2 (2010-10-30)
================

* Prettify output
* Manages static pages as well

2.1 (2010-10-30)
================

* Make notmyidea the default theme

2.0 (2010-10-30)
================

* Refactoring to be more extensible
* Change into the setting variables

1.2 (2010-09-28)
================

* Added a debug option
* Added per-category feeds
* Use filesystem to get dates if no metadata is provided
* Add Pygments support

1.1 (2010-08-19)
================

* First working version


================================================
FILE: docs/conf.py
================================================
import datetime
import os
import sys
import time

if sys.version_info >= (3, 11):
    import tomllib
else:
    import tomli as tomllib


sys.path.append(os.path.abspath(os.pardir))


with open("../pyproject.toml", "rb") as f:
    project_data = tomllib.load(f).get("project")
    if project_data is None:
        raise KeyError("project data is not found")


# -- General configuration ----------------------------------------------------
templates_path = ["_templates"]
locale_dirs = ["locale/"]
gettext_compact = False
gettext_uuid = True
extensions = [
    "sphinx.ext.autodoc",
    "sphinx.ext.extlinks",
    "sphinxext.opengraph",
]
source_suffix = ".rst"
master_doc = "index"
project = project_data.get("name").upper()
year = datetime.datetime.fromtimestamp(
    int(os.environ.get("SOURCE_DATE_EPOCH", time.time())), datetime.timezone.utc
).year
project_copyright = f"2010–{year}"  # noqa: RUF001
exclude_patterns = ["_build"]
release = project_data.get("version")
version = ".".join(release.split(".")[:1])
last_stable = project_data.get("version")
rst_prolog = f"""
.. |last_stable| replace:: :pelican-doc:`{last_stable}`
.. |min_python| replace:: {project_data.get("requires-python").split(",")[0]}
"""

extlinks = {"pelican-doc": ("https://docs.getpelican.com/en/latest/%s.html", "%s")}

# -- Options for HTML output --------------------------------------------------

html_theme = "furo"
html_title = f"<strong>{project}</strong> <i>{release}</i>"
html_static_path = ["_static"]
html_theme_options = {
    "light_logo": "pelican-logo.svg",
    "dark_logo": "pelican-logo.svg",
    "navigation_with_keys": True,
}

# Output file base name for HTML help builder.
htmlhelp_basename = "Pelicandoc"

html_use_smartypants = True

# If false, no module index is generated.
html_use_modindex = False

# If false, no index is generated.
html_use_index = False

# If true, links to the reST sources are added to the pages.
html_show_sourcelink = False


def setup(app):
    # overrides for wide tables in RTD theme
    app.add_css_file("theme_overrides.css")  # path relative to _static


# -- Options for LaTeX output -------------------------------------------------
latex_documents = [
    ("index", "Pelican.tex", "Pelican Documentation", "Justin Mayer", "manual"),
]

# -- Options for manual page output -------------------------------------------
man_pages = [
    ("index", "pelican", "pelican documentation", ["Justin Mayer"], 1),
    (
        "pelican-themes",
        "pelican-themes",
        "A theme manager for Pelican",
        ["Mickaël Raybaud"],
        1,
    ),
    (
        "themes",
        "pelican-theming",
        "How to create themes for Pelican",
        ["The Pelican contributors"],
        1,
    ),
]


================================================
FILE: docs/content.rst
================================================
Writing content
###############

Articles and pages
==================

Pelican considers "articles" to be chronological content, such as posts on a
blog, and thus associated with a date.

The idea behind "pages" is that they are usually not temporal in nature and are
used for content that does not change very often (e.g., "About" or "Contact"
pages).

You can find sample content in the repository at ``samples/content/``.

.. _internal_metadata:

File metadata
=============

Pelican tries to be smart enough to get the information it needs from the
file system (for instance, about the category of your articles), but some
information you need to provide in the form of metadata inside your files.

If you are writing your content in reStructuredText format, you can provide
this metadata in text files via the following syntax (give your file the
``.rst`` extension)::

    My super title
    ##############

    :date: 2010-10-03 10:20
    :modified: 2010-10-04 18:40
    :tags: thats, awesome
    :category: yeah
    :slug: my-super-post
    :authors: Alexis Metaireau, Conan Doyle
    :summary: Short version for index and feeds

Author and tag lists may be semicolon-separated instead, which allows
you to write authors and tags containing commas::

    :tags: pelican, publishing tool; pelican, bird
    :authors: Metaireau, Alexis; Doyle, Conan

Pelican implements an extension to reStructuredText to enable support for the
``abbr`` HTML tag. To use it, write something like this in your post::

    This will be turned into :abbr:`HTML (HyperText Markup Language)`.

You can also use Markdown syntax (with a file ending in ``.md``, ``.markdown``,
``.mkd``, or ``.mdown``). Markdown generation requires that you first
explicitly install the Python-Markdown_ package, which can be done via ``pip
install Markdown``.

Pelican also supports `Markdown Extensions`_, which might have to be installed
separately if they are not included in the default ``Markdown`` package and can
be configured and loaded via the ``MARKDOWN`` setting.

Metadata syntax for Markdown posts should follow this pattern::

    Title: My super title
    Date: 2010-12-03 10:20
    Modified: 2010-12-05 19:30
    Category: Python
    Tags: pelican, publishing
    Slug: my-super-post
    Authors: Alexis Metaireau, Conan Doyle
    Summary: Short version for index and feeds

    This is the content of my super blog post.

You can also have your own metadata keys (so long as they don't conflict with
reserved metadata keywords) for use in your templates. The following table
contains a list of reserved metadata keywords:

=============== ===============================================================
    Metadata                              Description
=============== ===============================================================
``title``       Title of the article or page
``date``        Publication date (e.g., ``YYYY-MM-DD HH:SS``)
``modified``    Modification date (e.g., ``YYYY-MM-DD HH:SS``)
``tags``        Content tags, separated by commas
``keywords``    Content keywords, separated by commas (HTML content only)
``category``    Content category (one only — not multiple)
``slug``        Identifier used in URLs and translations
``author``      Content author, when there is only one
``authors``     Content authors, when there are multiple
``summary``     Brief description of content for index pages
``lang``        Content language ID (``en``, ``fr``, etc.)
``translation`` If content is a translation of another (``true`` or ``false``)
``status``      Content status: ``draft``, ``hidden``, ``skip``, or ``published``
``template``    Name of template to use to generate content (without extension)
``save_as``     Save content to this relative file path
``url``         URL to use for this article/page
=============== ===============================================================

Readers for additional formats (such as AsciiDoc_) are available via plugins,
which you can find via the `Pelican Plugins`_ collection as well as the legacy
`pelican-plugins`_ repository.

Pelican can also process HTML files ending in ``.html`` and ``.htm``. Pelican
interprets the HTML in a very straightforward manner, reading metadata from
``meta`` tags, the title from the ``title`` tag, and the body out from the
``body`` tag::

    <html>
        <head>
            <title>My super title</title>
            <meta name="tags" content="thats, awesome" />
            <meta name="date" content="2012-07-09 22:28" />
            <meta name="modified" content="2012-07-10 20:14" />
            <meta name="category" content="yeah" />
            <meta name="authors" content="Alexis Métaireau, Conan Doyle" />
            <meta name="summary" content="Short version for index and feeds" />
        </head>
        <body>
            This is the content of my super blog post.
        </body>
    </html>

With HTML, there is one simple exception to the standard metadata: tags can be
specified either via the ``tags`` metadata, as is standard in Pelican, or via
the ``keywords`` metadata, as is standard in HTML. The two can be used
interchangeably.

Note that, aside from the title, none of this content metadata is mandatory:
if the date is not specified and ``DEFAULT_DATE`` is set to ``'fs'``, Pelican
will rely on the file's "mtime" timestamp, and the category can be determined
by the directory in which the file resides. For example, a file located at
``python/foobar/myfoobar.rst`` will have a category of ``foobar``. If you would
like to organize your files in other ways where the name of the subfolder would
not be a good category name, you can set the setting ``USE_FOLDER_AS_CATEGORY``
to ``False``.  When parsing dates given in the page metadata, Pelican supports
the W3C's `suggested subset ISO 8601`__.

So the title is the only required metadata. If that bothers you, worry not.
Instead of manually specifying a title in your metadata each time, you can use
the source content file name as the title. For example, a Markdown source file
named ``Publishing via Pelican.md`` would automatically be assigned a title of
*Publishing via Pelican*. If you would prefer this behavior, add the following
line to your settings file::

    FILENAME_METADATA = '(?P<title>.*)'

.. note::

   When experimenting with different settings (especially the metadata
   ones) caching may interfere and the changes may not be visible. In
   such cases disable caching with ``LOAD_CONTENT_CACHE = False`` or
   use the ``--ignore-cache`` command-line switch.

__ `W3C ISO 8601`_

``modified`` should be last time you updated the article, and defaults to
``date`` if not specified. Besides you can show ``modified`` in the templates,
feed entries in feed readers will be updated automatically when you set
``modified`` to the current date after you modified your article.

``authors`` is a comma-separated list of article authors. If there's only one
author you can use ``author`` field.

If you do not explicitly specify summary metadata for a given post, the
``SUMMARY_MAX_LENGTH`` setting can be used to specify how many words from the
beginning of an article are used as the summary. You can also use an article's
first N paragraphs as its summary using the ``SUMMARY_MAX_PARAGRAPHS`` setting.
If both settings are in use, the specified number of paragraphs will
be used but may be truncated to respect the specified maximum length.

You can also extract any metadata from the filename through a regular
expression to be set in the ``FILENAME_METADATA`` setting. All named groups
that are matched will be set in the metadata object. The default value for the
``FILENAME_METADATA`` setting will only extract the date from the filename. For
example, if you would like to extract both the date and the slug, you could set
something like: ``'(?P<date>\d{4}-\d{2}-\d{2})_(?P<slug>.*)'``

Please note that the metadata available inside your files takes precedence over
the metadata extracted from the filename.

Pages
=====

If you create a folder named ``pages`` inside the content folder, all the
files in it will be used to generate static pages, such as **About** or
**Contact** pages. (See example filesystem layout below.)

You can use the ``DISPLAY_PAGES_ON_MENU`` setting to control whether all those
pages are displayed in the primary navigation menu. (Default is ``True``.)

If you want to exclude any pages from being linked to or listed in the menu,
then add a ``status: hidden`` attribute to its metadata. This is useful for
things like making error pages that fit the generated theme of your site.

Static content
==============

Static files are files other than articles and pages that are copied to the
output folder as-is, without processing. You can control which static files
are copied over with the ``STATIC_PATHS`` setting of the project's
``pelicanconf.py`` file. Pelican's default configuration includes the
``images`` directory for this, but others must be added manually. In addition,
static files that are explicitly linked to are included (see below).

.. note::

   In the default configuration, all files with a valid content file suffix
   (``.html``, ``.rst``, ``.md``, ...) get processed by the article and page
   generators *before* the static generator. This is avoided by altering the
   ``*_EXCLUDE`` settings appropriately.

Mixed content in the same directory
-----------------------------------

Starting with Pelican 3.5, static files can safely share a source directory
with page source files, without exposing the page sources in the generated
site. Any such directory must be added to both ``STATIC_PATHS`` and
``PAGE_PATHS`` (or ``STATIC_PATHS`` and ``ARTICLE_PATHS``). Pelican will
identify and process the page source files normally, and copy the remaining
files as if they lived in a separate directory reserved for static files.

Note: Placing static and content source files together in the same source
directory does not guarantee that they will end up in the same place in the
generated site. The easiest way to do this is by using the ``{attach}`` link
syntax (described below). Alternatively, the ``STATIC_SAVE_AS``,
``PAGE_SAVE_AS``, and ``ARTICLE_SAVE_AS`` settings (and the corresponding
``*_URL`` settings) can be configured to place files of different types
together, just as they could in earlier versions of Pelican.

.. _ref-linking-to-internal-content:

Linking to internal content
===========================

From Pelican 3.1 onwards, it is now possible to specify intra-site links to
files in the *source content* hierarchy instead of files in the *generated*
hierarchy. This makes it easier to link from the current post to other content
that may be sitting alongside that post (instead of having to determine where
the other content will be placed after site generation).

To link to internal content (files in the ``content`` directory), use the
following syntax for the link target: ``{filename}path/to/file``.
Note: forward slashes, ``/``,
are the required path separator in the ``{filename}`` directive
on all operating systems, including Windows.

For example, a Pelican project might be structured like this::

    website/
    ├── content
    │   ├── category/
    │   │   └── article1.rst
    │   ├── article2.md
    │   └── pages
    │       └── about.md
    └── pelican.conf.py

In this example, ``article1.rst`` could look like this::

    The first article
    #################

    :date: 2012-12-01 10:02

    See below intra-site link examples in reStructuredText format.

    `a link relative to the current file <{filename}../article2.md>`_
    `a link relative to the content root <{filename}/article2.md>`_

and ``article2.md``::

    Title: The second article
    Date: 2012-12-01 10:02

    See below intra-site link examples in Markdown format.

    [a link relative to the current file]({filename}category/article1.rst)
    [a link relative to the content root]({filename}/category/article1.rst)

Linking to static files
-----------------------

You can link to static content using ``{static}path/to/file``. Files linked to
with this syntax will automatically be copied to the output directory, even if
the source directories containing them are not included in the ``STATIC_PATHS``
setting of the project's ``pelicanconf.py`` file.

For example, a project's content directory might be structured like this::

    content
    ├── images
    │   └── han.jpg
    ├── pdfs
    │   └── menu.pdf
    └── pages
        └── test.md

``test.md`` would include::

    ![Alt Text]({static}/images/han.jpg)
    [Our Menu]({static}/pdfs/menu.pdf)

Site generation would then copy ``han.jpg`` to ``output/images/han.jpg``,
``menu.pdf`` to ``output/pdfs/menu.pdf``, and write the appropriate links
in ``test.md``.

If you use ``{static}`` to link to an article or a page, this will be turned
into a link to its source code.

Attaching static files
----------------------

Starting with Pelican 3.5, static files can be "attached" to a page or article
using this syntax for the link target: ``{attach}path/to/file``. This works
like the ``{static}`` syntax, but also relocates the static file into the
linking document's output directory. If the static file originates from a
subdirectory beneath the linking document's source, that relationship will be
preserved on output. Otherwise, it will become a sibling of the linking
document.

This only works for linking to static files.

For example, a project's content directory might be structured like this::

    content
    ├── blog
    │   ├── icons
    │   │   └── icon.png
    │   ├── photo.jpg
    │   └── testpost.md
    └── downloads
        └── archive.zip

``pelicanconf.py`` would include::

    PATH = 'content'
    ARTICLE_PATHS = ['blog']
    ARTICLE_SAVE_AS = '{date:%Y}/{slug}.html'
    ARTICLE_URL = '{date:%Y}/{slug}.html'

``testpost.md`` would include::

    Title: Test Post
    Category: test
    Date: 2014-10-31

    ![Icon]({attach}icons/icon.png)
    ![Photo]({attach}photo.jpg)
    [Downloadable File]({attach}/downloads/archive.zip)

Site generation would then produce an output directory structured like this::

    output
    └── 2014
        ├── archive.zip
        ├── icons
        │   └── icon.png
        ├── photo.jpg
        └── test-post.html

Notice that all the files linked using ``{attach}`` ended up in or beneath
the article's output directory.

If a static file is linked multiple times, the relocating feature of
``{attach}`` will only work in the first of those links to be processed.
After the first link, Pelican will treat ``{attach}`` like ``{static}``.
This avoids breaking the already-processed links.

**Be careful when linking to a file from multiple documents:**
Since the first link to a file finalizes its location and Pelican does
not define the order in which documents are processed, using ``{attach}`` on a
file linked by multiple documents can cause its location to change from one
site build to the next. (Whether this happens in practice will depend on the
operating system, file system, version of Pelican, and documents being added,
modified, or removed from the project.) Any external sites linking to the
file's old location might then find their links broken. **It is therefore
advisable to use {attach} only if you use it in all links to a file, and only
if the linking documents share a single directory.** Under these conditions,
the file's output location will not change in future builds. In cases where
these precautions are not possible, consider using ``{static}`` links instead
of ``{attach}``, and letting the file's location be determined by the project's
``STATIC_SAVE_AS`` and ``STATIC_URL`` settings. (Per-file ``save_as`` and
``url`` overrides can still be set in ``EXTRA_PATH_METADATA``.)

.. note::
    When using ``{attach}``, any parent directory in ``*_URL`` / ``*_SAVE_AS``
    settings should match each other. See also: :ref:`url-settings`

Linking to authors, categories, index and tags
----------------------------------------------

You can link to authors, categories, index and tags using the ``{author}name``,
``{category}foobar``, ``{index}`` and ``{tag}tagname`` syntax.

Deprecated internal link syntax
-------------------------------

To remain compatible with earlier versions, Pelican still supports vertical
bars (``||``) in addition to curly braces (``{}``) for internal links. For
example: ``|filename|an_article.rst``, ``|tag|tagname``, ``|category|foobar``.
The syntax was changed from ``||`` to ``{}`` to avoid collision with Markdown
extensions or reST directives. Similarly, Pelican also still supports linking
to static content with ``{filename}``. The syntax was changed to ``{static}``
to allow linking to both generated articles and pages and their static sources.

Support for the old syntax may eventually be removed.

Including other files
---------------------
Both Markdown and reStructuredText syntaxes provide mechanisms for this.

Following below are some examples for **reStructuredText** using `the include directive`_:

    .. code-block:: rst

        .. include:: file.rst

Include a fragment of a file delimited by two identifiers, highlighted as C++ (slicing based on line numbers is also possible):

    .. code-block:: rst

        .. include:: main.cpp
            :code: c++
            :start-after: // begin
            :end-before: // end

Include a raw HTML file (or an inline SVG) and put it directly into the output without any processing:

    .. code-block:: rst

        .. raw:: html
            :file: table.html

For **Markdown**, one must rely on an extension. For example, using the `mdx_include plugin`_:

    .. code-block:: none

        ```html
        {! template.html !}
        ```


Importing an existing site
==========================

It is possible to import your site from several other blogging sites
(like WordPress, Tumblr, ..) using a simple script. See :ref:`import`.

Translations
============

It is possible to translate articles. To do so, you need to add a ``lang`` meta
attribute to your articles/pages and set a ``DEFAULT_LANG`` setting (which is
English [en] by default). With those settings in place, only articles with the
default language will be listed, and each article will be accompanied by a list
of available translations for that article.

.. note::

   This core Pelican functionality does not create sub-sites
   (e.g. ``example.com/de``) with translated templates for each
   language. For such advanced functionality the `i18n_subsites
   plugin`_ can be used.

By default, Pelican uses the article's URL "slug" to determine if two or more
articles are translations of one another. (This can be changed with the
``ARTICLE_TRANSLATION_ID`` setting.) The slug can be set manually in the file's
metadata; if not set explicitly, Pelican will auto-generate the slug from the
title of the article.

Here is an example of two articles, one in English and the other in French.

The English article::

    Foobar is not dead
    ##################

    :slug: foobar-is-not-dead
    :lang: en

    That's true, foobar is still alive!

And the French version::

    Foobar n'est pas mort !
    #######################

    :slug: foobar-is-not-dead
    :lang: fr

    Oui oui, foobar est toujours vivant !

Post content quality notwithstanding, you can see that only item in common
between the two articles is the slug, which is functioning here as an
identifier. If you'd rather not explicitly define the slug this way, you must
then instead ensure that the translated article titles are identical, since the
slug will be auto-generated from the article title.

If you do not want the original version of one specific article to be detected
by the ``DEFAULT_LANG`` setting, use the ``translation`` metadata to specify
which posts are translations::

    Foobar is not dead
    ##################

    :slug: foobar-is-not-dead
    :lang: en
    :translation: true

    That's true, foobar is still alive!


.. _internal_pygments_options:

Syntax highlighting
===================

Pelican can provide colorized syntax highlighting for your code blocks.
To do so, you must use the following conventions inside your content files.

For reStructuredText, use the ``code-block`` directive to specify the type
of code to be highlighted (in these examples, we'll use ``python``)::

    .. code-block:: python

       print("Pelican is a static site generator.")

For Markdown, which utilizes the `CodeHilite extension`_ to provide syntax
highlighting, include the language identifier just above the code block,
indenting both the identifier and the code::

    There are two ways to specify the identifier:

        :::python
        print("The triple-colon syntax will *not* show line numbers.")

    To display line numbers, use a path-less shebang instead of colons:

        #!python
        print("The path-less shebang syntax *will* show line numbers.")

The specified identifier (e.g. ``python``, ``ruby``) should be one that
appears on the `list of available lexers <https://pygments.org/docs/lexers/>`_.

When using reStructuredText the following options are available in the
`code-block` directive:

=============   ============  =========================================
Option          Valid values  Description
=============   ============  =========================================
anchorlinenos   N/A           If present, wrap line numbers in ``<a>`` tags.
classprefix     string        String to prepend to token class names
hl_lines        numbers       List of lines to be highlighted, where
                              line numbers to highlight are separated
                              by a space. This is similar to
                              ``emphasize-lines`` in Sphinx, but it
                              does not support a range of line numbers
                              separated by a hyphen, or comma-separated
                              line numbers.
lineanchors     string        Wrap each line in an anchor using this
                              string and -linenumber.
linenos         string        If present or set to "table", output line
                              numbers in a table; if set to
                              "inline", output them inline. "none" means
                              do not output the line numbers for this
                              table.
linenospecial   number        If set, every nth line will be given the
                              'special' CSS class.
linenostart     number        Line number for the first line.
linenostep      number        Print every nth line number.
lineseparator   string        String to print between lines of code,
                              '\n' by default.
linespans       string        Wrap each line in a span using this and
                              -linenumber.
nobackground    N/A           If set, do not output background color for
                              the wrapping element
nowrap          N/A           If set, do not wrap the tokens at all.
tagsfile        string        ctags file to use for name definitions.
tagurlformat    string        format for the ctag links.
=============   ============  =========================================

Note that, depending on the version, your Pygments module might not have
all of these options available. Refer to the *HtmlFormatter* section of the
`Pygments documentation <https://pygments.org/docs/formatters/>`_ for more
details on each of the options.

For example, the following code block enables line numbers, starting at 153,
and prefixes the Pygments CSS classes with *pgcss* to make the names
more unique and avoid possible CSS conflicts::

    .. code-block:: identifier
        :classprefix: pgcss
        :linenos: table
        :linenostart: 153

       <indented code block goes here>

It is also possible to specify the ``PYGMENTS_RST_OPTIONS`` variable in your
Pelican settings file to include options that will be automatically applied to
every code block.

For example, if you want to have line numbers displayed for every code block
and a CSS prefix, you would set this variable to::

    PYGMENTS_RST_OPTIONS = {'classprefix': 'pgcss', 'linenos': 'table'}

If specified, settings for individual code blocks will override the defaults in
your settings file.

Publishing drafts
=================

If you want to publish an article or a page as a draft (for friends to review
before publishing, for example), you can add a ``Status: draft`` attribute to
its metadata. That article will then be output to the ``drafts`` folder and not
listed on the index page nor on any category or tag page.

If your articles should be automatically published as a draft (to not
accidentally publish an article before it is finished), include the status in
the ``DEFAULT_METADATA``::

    DEFAULT_METADATA = {
        'status': 'draft',
    }

To publish a post when the default status is ``draft``, update the post's
metadata to include ``Status: published``.

Hidden Posts
============

Like pages, posts can also be marked as ``hidden`` with the ``Status: hidden``
attribute. Hidden posts will be output to ``ARTICLE_SAVE_AS`` as expected, but
are not included by default in tag, category, and author indexes, nor in the
main article feed. This has the effect of creating an "unlisted" post.

Skip Posts
==========

Posts marked with ``skip`` status are ignored entirely. They are not processed
nor output to the ``ARTICLE_SAVE_AS`` path. Such posts will similarly not be
included in indexes or feeds.

.. _W3C ISO 8601: https://www.w3.org/TR/NOTE-datetime
.. _AsciiDoc: https://asciidoc.org
.. _Pelican Plugins: https://github.com/pelican-plugins
.. _pelican-plugins: https://github.com/getpelican/pelican-plugins
.. _Python-Markdown: https://github.com/Python-Markdown/markdown
.. _Markdown Extensions: https://python-markdown.github.io/extensions/
.. _CodeHilite extension: https://python-markdown.github.io/extensions/code_hilite/#syntax
.. _i18n_subsites plugin: https://github.com/getpelican/pelican-plugins/tree/master/i18n_subsites
.. _the include directive: http://docutils.sourceforge.net/docs/ref/rst/directives.html#include
.. _mdx_include plugin: https://github.com/neurobin/mdx_include


================================================
FILE: docs/contribute.rst
================================================
Contributing and feedback guidelines
####################################

There are many ways to contribute to Pelican. You can improve the
documentation, add missing features, and fix bugs (or just report them). You
can also help out by reviewing and commenting on
`existing issues <https://github.com/getpelican/pelican/issues>`_.

Don't hesitate to fork Pelican and submit an issue or pull request on GitHub.
When doing so, please consider the following guidelines.

.. include:: ../CONTRIBUTING.rst

Setting up the development environment
======================================

While there are many ways to set up one's development environment, the following
instructions will utilize Pip_ and PDM_. These tools facilitate managing
virtual environments for separate Python projects that are isolated from one
another, so you can use different packages (and package versions) for each.

Please note that Python |min_python| is required for Pelican development.

*(Optional)* If you prefer to `install PDM <https://pdm.fming.dev/latest/#installation>`_ once for use with multiple projects,
you can install it via::

    curl -sSL https://pdm.fming.dev/install-pdm.py | python3 -

Point your web browser to the `Pelican repository`_ and tap the **Fork** button
at top-right. Then clone the source for your fork and add the upstream project
as a Git remote::

    mkdir ~/projects
    git clone https://github.com/YOUR_USERNAME/pelican.git ~/projects/pelican
    cd ~/projects/pelican
    git remote add upstream https://github.com/getpelican/pelican.git

While PDM can dynamically create and manage virtual environments, we're going
to manually create and activate a virtual environment::

    mkdir ~/virtualenvs && cd ~/virtualenvs
    python3 -m venv pelican
    source ~/virtualenvs/pelican/*/activate

Install the needed dependencies and set up the project::

    python -m pip install invoke
    invoke setup

Your local environment should now be ready to go!

.. _Pip: https://pip.pypa.io/
.. _PDM: https://pdm.fming.dev/latest/
.. _Pelican repository: https://github.com/getpelican/pelican

Development
===========

Once Pelican has been set up for local development, create a topic branch for
your bug fix or feature::

    git checkout -b name-of-your-bugfix-or-feature

Now you can make changes to Pelican, its documentation, and/or other aspects of
the project.

Setting up ``git blame`` (optional)
-----------------------------------

``git blame`` annotates lines in a file with information about the pull request
that last modified it. Sweeping shallow changes (like formatting) can make that
information less useful, so we keep a list of such changes to be ignored. Run the
following command to set this up in your repository, adding ``--global`` if you
want this setting to apply to all repositories::

    git config blame.ignoreRevsFile .git-blame-ignore-revs

As noted in a `useful article`_ about ``git blame``, there are other related
settings you may find to be beneficial::

    # Add `?` to any lines that have had a commit skipped using --ignore-rev
    git config --global blame.markIgnoredLines true
    # Add `*` to any lines that were added in a skipped commit and can not be attributed
    git config --global blame.markUnblamableLines true

.. _useful article: https://www.michaelheap.com/git-ignore-rev/

Running the test suite
----------------------

Each time you make changes to Pelican, there are two things to do regarding
tests: check that the existing tests pass, and add tests for any new features
or bug fixes. The tests are located in ``pelican/tests``, and you can run them
via::

    invoke tests

(For more on Invoke, see ``invoke -l`` to list tasks, or
https://pyinvoke.org for documentation.)

In addition to running the test suite, it is important to also ensure that any
lines you changed conform to code style guidelines. You can check that via::

    invoke lint

If style violations are found, many of them can be addressed automatically via::

    invoke lint --fix
    invoke format

If code style violations are found in lines you changed, correct those lines
and re-run the ``invoke lint`` command until they have all been fixed. You do
not need to address style violations, if any, for code lines you did not touch.

After making your changes and running the tests, you may see a test failure
mentioning that "some generated files differ from the expected functional tests
output." If you have made changes that affect the HTML output generated by
Pelican, and the changes to that output are expected and deemed correct given
the nature of your changes, then you should update the output used by the
functional tests. To do so, **make sure you have both** ``en_EN.utf8`` **and**
``fr_FR.utf8`` **locales installed**, and then run the following command::

    invoke update-functional-tests

You may also find that some tests are skipped because some dependency (e.g.,
Pandoc) is not installed. This does not automatically mean that these tests
have passed; you should at least verify that any skipped tests are not affected
by your changes.

You should run the test suite under each of the supported versions of Python.
This is best done by creating a separate Python environment for each version.
Tox_ is a useful tool to automate running tests inside ``virtualenv``
environments.

.. _Tox: https://tox.readthedocs.io/en/latest/

Running a code coverage report
------------------------------

Code is more likely to stay robust if it is tested. Coverage_ is a library that
measures how much of the code is tested. To run it::

    invoke coverage

This will show overall coverage, coverage per file, and even line-by-line coverage.
There is also an HTML report available::

    open htmlcov/index.html

.. _Coverage: https://github.com/nedbat/coveragepy

Building the docs
-----------------

If you make changes to the documentation, you should build and inspect your
changes before committing them::

    invoke docserve

Open http://localhost:8000 in your browser to review the documentation. While
the above task is running, any changes you make and save to the documentation
should automatically appear in the browser, as it live-reloads when it detects
changes to the documentation source files.

Plugin development
------------------

To create a *new* Pelican plugin, please refer to the `plugin template`_
repository for detailed instructions.

If you want to contribute to an *existing* Pelican plugin, follow the steps
above to set up Pelican for local development, and then create a directory to
store cloned plugin repositories::

   mkdir -p ~/projects/pelican-plugins

Assuming you wanted to contribute to the Simple Footnotes plugin, you would
first browse to the `Simple Footnotes`_ repository on GitHub and tap the **Fork**
button at top-right. Then clone the source for your fork and add the upstream
project as a Git remote::

    git clone https://github.com/YOUR_USERNAME/simple-footnotes.git ~/projects/pelican-plugins/simple-footnotes
    cd ~/projects/pelican-plugins/simple-footnotes
    git remote add upstream https://github.com/pelican-plugins/simple-footnotes.git

Install the needed dependencies and set up the project::

    invoke setup

Create a topic branch for your plugin bug fix or feature::

    git checkout -b name-of-your-bugfix-or-feature

After writing new tests for your plugin changes, run the plugin test suite and
check for code style compliance via::

    invoke tests
    invoke lint

If style violations are found, many of them can be addressed automatically via::

    invoke lint --fix
    invoke format

If style violations are found even after running the above auto-formatters,
you will need to make additional manual changes until ``invoke lint`` no longer
reports any code style violations.

.. _plugin template: https://github.com/getpelican/cookiecutter-pelican-plugin
.. _Simple Footnotes: https://github.com/pelican-plugins/simple-footnotes

Submitting your changes
-----------------------

Assuming linting validation and tests pass, add a ``RELEASE.md`` file in the root
of the project that contains the release type (major, minor, patch) and a
summary of the changes that will be used as the release changelog entry.
For example::

    Release type: patch

    Fix browser reloading upon changes to content, settings, or theme

Commit your changes and push your topic branch::

    git add .
    git commit -m "Your detailed description of your changes"
    git push origin name-of-your-bugfix-or-feature

Finally, browse to your repository fork on GitHub and submit a pull request.


Logging tips
============

Try to use logging with appropriate levels.

For logging messages that are not repeated, use the usual Python way::

    # at top of file
    import logging
    logger = logging.getLogger(__name__)

    # when needed
    logger.warning("A warning with %s formatting", arg_to_be_formatted)

Do not format log messages yourself. Use ``%s`` formatting in messages and pass
arguments to logger. This is important, because the Pelican logger will
preprocess some arguments, such as exceptions.

Limiting extraneous log messages
--------------------------------

If the log message can occur several times, you may want to limit the log to
prevent flooding. In order to do that, use the ``extra`` keyword argument for
the logging message in the following format::

    logger.warning("A warning with %s formatting", arg_to_be_formatted,
        extra={'limit_msg': 'A generic message for too many warnings'})

Optionally, you can also set ``'limit_args'`` as a tuple of arguments in
``extra`` dict if your generic message needs formatting.

Limit is set to ``5``, i.e, first four logs with the same ``'limit_msg'`` are
outputted normally but the fifth one will be logged using ``'limit_msg'`` (and
``'limit_args'`` if present). After the fifth, corresponding log messages will
be ignored.

For example, if you want to log missing resources, use the following code::

    for resource in resources:
        if resource.is_missing:
            logger.warning(
                'The resource %s is missing', resource.name,
                extra={'limit_msg': 'Other resources were missing'})

The log messages will be displayed as follows::

    WARNING: The resource prettiest_cat.jpg is missing
    WARNING: The resource best_cat_ever.jpg is missing
    WARNING: The resource cutest_cat.jpg is missing
    WARNING: The resource lolcat.jpg is missing
    WARNING: Other resources were missing


Outputting traceback in the logs
--------------------------------

If you're logging inside an ``except`` block, you may want to provide the
traceback information as well. You can do that by setting ``exc_info`` keyword
argument to ``True`` during logging. However, doing so by default can be
undesired because tracebacks are long and can be confusing to regular users.
Try to limit them to ``--debug`` mode like the following::

    try:
        some_action()
    except Exception as e:
        logger.error('Exception occurred: %s', e,
            exc_info=settings.get('DEBUG', False))


================================================
FILE: docs/faq.rst
================================================
Frequently Asked Questions (FAQ)
################################

Here are some frequently asked questions about Pelican.

What's the best way to communicate a problem, question, or suggestion?
======================================================================

Please read our :doc:`feedback guidelines <contribute>`.

How can I help?
===============

There are several ways to help out. First, you can communicate any Pelican
suggestions or problems you might have via `Pelican Discussions
<https://github.com/getpelican/pelican/discussions>`_. Please first check the
existing list of discussions and issues (both open and closed) in order to
avoid submitting topics that have already been covered before.

If you want to contribute, please fork `the Git repository
<https://github.com/getpelican/pelican/>`_, create a new feature branch, make
your changes, and issue a pull request. Someone will review your changes as
soon as possible. Please refer to the :doc:`How to Contribute <contribute>`
section for more details.

You can also contribute by creating themes and improving the documentation.

Is the Pelican settings file mandatory?
=======================================

Configuration files are optional and are just an easy way to configure Pelican.
For basic operations, it's possible to specify options while invoking Pelican
via the command line. See ``pelican --help`` for more information.

Changes to the settings file take no effect
===========================================

When experimenting with different settings (especially the metadata ones)
caching may interfere and the changes may not be visible. In such cases, ensure
that caching is disabled via ``LOAD_CONTENT_CACHE = False`` or use the
``--ignore-cache`` command-line switch.

I'm creating my own theme. How do I use Pygments for syntax highlighting?
=========================================================================

Pygments adds some classes to the generated content. These classes are used by
themes to style code syntax highlighting via CSS. Specifically, you can
customize the appearance of your syntax highlighting via the ``.highlight pre``
class in your theme's CSS file. To see how various styles can be used to render
Django code, for example, use the style selector drop-down at top-right on the
`Pygments project demo site <https://pygments.org/demo/>`_.

You can use the following example commands to generate a starting CSS file from
a Pygments built-in style (in this case, "monokai") and then copy the generated
CSS file to your new theme::

    pygmentize -S monokai -f html -a .highlight > pygment.css
    cp pygment.css path/to/theme/static/css/

Don't forget to import your ``pygment.css`` file from your main CSS file.

How do I create my own theme?
=============================

Please refer to :ref:`theming-pelican`.

Can I override individual templates without forking the whole theme?
====================================================================

Yes, you can override existing templates of the theme that you are using, or
add new templates, via the ``THEME_TEMPLATES_OVERRIDES`` variable. For example,
to override the page template, you can define the location for your templates
like this::

    THEME_TEMPLATES_OVERRIDES = ["templates"]

You can then define a custom template in ``templates/page.html``.
See :ref:`settings/themes` for details.

I want to use Markdown, but I got an error.
===========================================

If you try to generate Markdown content without first installing the Markdown
library, you may see a message that says ``No valid files found in content``.
Markdown is not a hard dependency for Pelican, so if you have content in
Markdown format, you will need to explicitly install the Markdown library. You
can do so by typing the following command, prepending ``sudo`` if permissions
require it::

    python -m pip install markdown

Can I use arbitrary metadata in my templates?
=============================================

Yes. For example, to include a modified date in a Markdown post, one could
include the following at the top of the article::

    Modified: 2012-08-08

For reStructuredText, this metadata should of course be prefixed with a colon::

    :Modified: 2012-08-08

This metadata can then be accessed in templates such as ``article.html`` via::

    {% if article.modified %}
    Last modified: {{ article.modified }}
    {% endif %}

If you want to include metadata in templates outside the article context (e.g.,
``base.html``), the ``if`` statement should instead be::

    {% if article and article.modified %}

.. note::

    Because the colon symbol (``:``) is used as a separator, be aware that
    metadata field names *containing* a colon will probably not work.

How do I make my output folder structure identical to my content hierarchy?
===========================================================================

Try these settings::

    USE_FOLDER_AS_CATEGORY = False
    PATH_METADATA = r"(?P<path_no_ext>.*)\..*"
    ARTICLE_URL = ARTICLE_SAVE_AS = PAGE_URL = PAGE_SAVE_AS = "{path_no_ext}.html"

How do I assign custom templates on a per-page basis?
=====================================================

It's as simple as adding an extra line of metadata to any page or article that
you want to have its own template. For example, this is how it would be handled
for content in reST format::

    :template: template_name

For content in Markdown format::

    Template: template_name

Then just make sure your theme contains the relevant template file (e.g.
``template_name.html``). If you just want to add a new custom template to an
existing theme, you can also provide it in a directory specified by ``THEME_TEMPLATES_OVERRIDES`` (see :ref:`settings/themes`).

How can I override the generated URL of a specific page or article?
===================================================================

Include ``url`` and ``save_as`` metadata in any pages or articles that you want
to override the generated URL. Here is an example page in reST format::

    Override url/save_as page
    #########################

    :url: override/url/
    :save_as: override/url/index.html

With this metadata, the page will be written to ``override/url/index.html``
and Pelican will use the URL ``override/url/`` to link to this page.

How can I use a static page as my home page?
============================================

The override feature mentioned above can be used to specify a static page as
your home page. The following Markdown example could be stored in
``content/pages/home.md``::

    Title: Welcome to My Site
    URL:
    save_as: index.html

    Thank you for visiting. Welcome!

If the original blog index is still wanted, it can then be saved in a
different location by setting ``INDEX_SAVE_AS = 'blog_index.html'`` for
the ``'index'`` direct template.

What if I want to disable feed generation?
==========================================

To disable feed generation, all feed settings should be set to ``None``. All
but three feed settings already default to ``None``, so if you want to disable
all feed generation, you only need to specify the following settings::

    FEED_ALL_ATOM = None
    CATEGORY_FEED_ATOM = None
    TRANSLATION_FEED_ATOM = None
    AUTHOR_FEED_ATOM = None
    AUTHOR_FEED_RSS = None

The word ``None`` should not be surrounded by quotes. Please note that ``None``
and ``''`` are not the same thing.

I'm getting a warning about feeds generated without SITEURL being set properly
==============================================================================

`RSS and Atom feeds require all URL links to be absolute
<https://validator.w3.org/feed/docs/rss2.html#comments>`_. In order to properly
generate links in Pelican you will need to set ``SITEURL`` to the full path of
your site.

Feeds are still generated when this warning is displayed, but links within may
be malformed and thus the feed may not validate.

Can I force Atom feeds to show only summaries instead of article content?
=========================================================================

Instead of having to open a separate browser window to read articles, the
overwhelming majority of folks who use feed readers prefer to read content
within the feed reader itself. Mainly for that reason, Pelican does not support
restricting Atom feeds to only contain summaries. Unlike Atom feeds, the RSS
feed specification does not include a separate ``content`` field, so by default
Pelican publishes RSS feeds that only contain summaries (but can optionally be
set to instead publish full content RSS feeds). So the default feed generation
behavior provides users with a choice: subscribe to Atom feeds for full content
or to RSS feeds for just the summaries.

Is Pelican only suitable for blogs?
===================================

No. Pelican can be easily configured to create and maintain any type of static
site. This may require a little customization of your theme and Pelican
configuration. For example, if you are building a launch site for your product
and do not need tags on your site, you could remove the relevant HTML code from
your theme. You can also disable generation of tag-related pages via::

    TAGS_SAVE_AS = ''
    TAG_SAVE_AS = ''

Why does Pelican always write all HTML files even with content caching enabled?
===============================================================================

In order to reliably determine whether the HTML output is different before
writing it, a large part of the generation environment including the template
contexts, imported plugins, etc. would have to be saved and compared, at least
in the form of a hash (which would require special handling of unhashable
types), because of all the possible combinations of plugins, pagination, etc.
which may change in many different ways. This would require a lot more
processing time and memory and storage space. Simply writing the files each
time is a lot faster and a lot more reliable.

However, this means that the modification time of the files changes every time,
so a ``rsync`` based upload will transfer them even if their content hasn't
changed. A simple solution is to make ``rsync`` use the ``--checksum`` option,
which will make it compare the file checksums in a much faster way than Pelican
would.

How to process only a subset of all articles?
=============================================

It is often useful to process only e.g. 10 articles for debugging purposes.
This can be achieved by explicitly specifying only the filenames of those
articles in ``ARTICLE_PATHS``. A list of such filenames could be found using a
command similar to ``cd content; find -name '*.md' | head -n 10``.

My tag cloud is missing/broken since I upgraded Pelican
=======================================================

In an ongoing effort to streamline Pelican, tag cloud generation has been
moved out of Pelican core and into a separate `plugin
<https://github.com/pelican-plugins/tag-cloud>`_. See the :ref:`plugins`
documentation for further information about the Pelican plugin system.

Since I upgraded Pelican my pages are no longer rendered
========================================================

Pages were available to themes as lowercase ``pages`` and uppercase ``PAGES``.
To bring this inline with the :ref:`templates-variables` section, ``PAGES`` has
been removed. This is quickly resolved by updating your theme to iterate over
``pages`` instead of ``PAGES``. Just replace::

    {% for pg in PAGES %}

with something like::

    {% for pg in pages %}

How can I stop Pelican from trying to parse my static files as content?
=======================================================================

Pelican's article and page generators run before it's static generator. That
means if you use a setup similar to the default configuration, where a static
source directory is defined inside a ``*_PATHS`` setting, all files that have a
valid content file ending (``.html``, ``.rst``, ``.md``, ...) will be treated
as articles or pages before they get treated as static files.

To circumvent this issue either use the appropriate ``*_EXCLUDES`` setting or
disable the offending reader via ``READERS`` if you don't need it.

Why is [arbitrary Markdown syntax] not supported?
=================================================

Pelican does not directly handle Markdown processing and instead delegates that
task to the Python-Markdown_ project, the core of which purposefully follows
the original Markdown syntax rules and not the myriad Markdown "flavors" that
have subsequently propagated. That said, Python-Markdown_ is quite modular, and
the syntax you are looking for may be provided by one of the many available
`Markdown Extensions`_. Alternatively, some folks have created Pelican plugins
that support Markdown variants, so that may be your best choice if there is a
particular variant you want to use when writing your content.


.. _Python-Markdown: https://github.com/Python-Markdown/markdown
.. _Markdown Extensions: https://python-markdown.github.io/extensions/


================================================
FILE: docs/importer.rst
================================================
.. _import:

Importing an existing site
##########################

Description
===========

``pelican-import`` is a command-line tool for converting articles from other
software to reStructuredText or Markdown. The supported import formats are:

- Blogger XML export
- Dotclear export
- Medium export
- Tumblr API
- WordPress XML export
- RSS/Atom feed

The conversion from HTML to reStructuredText or Markdown relies on `Pandoc`_.
For Dotclear, if the source posts are written with Markdown syntax, they will
not be converted (as Pelican also supports Markdown).

.. note::

   Unlike Pelican, Wordpress supports multiple categories per article. These
   are imported as a comma-separated string. You have to resolve these
   manually, or use a plugin such as `More Categories`_ that enables multiple
   categories per article.

.. note::

   Imported pages may contain links to images that still point to the original site.
   So you might want to download those images into your local content and manually
   re-link them from the relevant pages of your site.

Dependencies
============

``pelican-import`` has some dependencies not required by the rest of Pelican:

- *BeautifulSoup4* and *lxml*, for WordPress and Dotclear import. Can be
  installed like any other Python package (``pip install BeautifulSoup4
  lxml``).
- *Feedparser*, for feed import (``pip install feedparser``).
- *Pandoc*, see the `Pandoc site`_ for installation instructions on your
  operating system.

.. _Pandoc: https://pandoc.org/
.. _Pandoc site: https://pandoc.org/installing.html


Usage
=====

::

    pelican-import [-h] [--blogger] [--dotclear] [--tumblr] [--wpfile] [--feed]
                   [-o OUTPUT] [-m MARKUP] [--dir-cat] [--dir-page] [--strip-raw] [--wp-custpost]
                   [--wp-attach] [--disable-slugs] [-b BLOGNAME]
                   input|api_key

Positional arguments
--------------------
  =============         ============================================================================
  ``input``             The input file to read
  ``api_key``           (Tumblr only) api_key can be obtained from https://www.tumblr.com/oauth/apps
  =============         ============================================================================

Optional arguments
------------------

  -h, --help            Show this help message and exit
  --blogger             Blogger XML export (default: False)
  --dotclear            Dotclear export (default: False)
  --medium              Medium export (default: False)
  --tumblr              Tumblr API (default: False)
  --wpfile              WordPress XML export (default: False)
  --feed                Feed to parse (default: False)
  -o OUTPUT, --output OUTPUT
                        Output path (default: content)
  -m MARKUP, --markup MARKUP
                        Output markup format: ``rst``, ``markdown``, or ``asciidoc``
                        (default: ``rst``)
  --dir-cat             Put files in directories with categories name
                        (default: False)
  --dir-page            Put files recognised as pages in "pages/" sub-
                          directory (blogger and wordpress import only)
                          (default: False)
  --filter-author       Import only post from the specified author
  --strip-raw           Strip raw HTML code that can't be converted to markup
                        such as flash embeds or iframes (default: False)
  --wp-custpost         Put wordpress custom post types in directories. If
                        used with --dir-cat option directories will be created
                        as "/post_type/category/" (wordpress import only)
  --wp-attach           Download files uploaded to wordpress as attachments.
                        Files will be added to posts as a list in the post
                        header and links to the files within the post will be
                        updated. All files will be downloaded, even if they
                        aren't associated with a post. Files will be downloaded
                        with their original path inside the output directory,
                        e.g. "output/wp-uploads/date/postname/file.jpg".
                        (wordpress import only) (requires an internet
                        connection)
  --disable-slugs       Disable storing slugs from imported posts within
                        output. With this disabled, your Pelican URLs may not
                        be consistent with your original posts. (default:
                        False)
  -b BLOGNAME, --blogname=BLOGNAME
                        Blog name used in Tumblr API


Examples
========

For Blogger::

    $ pelican-import --blogger -o ~/output ~/posts.xml

For Dotclear::

    $ pelican-import --dotclear -o ~/output ~/backup.txt

For Medium::

    $ pelican-import --medium -o ~/output ~/medium-export/posts/

The Medium export is a zip file.  Unzip it, and point this tool to the
"posts" subdirectory.  For more information on how to export, see
https://help.medium.com/hc/en-us/articles/115004745787-Export-your-account-data.

For Tumblr::

    $ pelican-import --tumblr -o ~/output --blogname=<blogname> <api_key>

For WordPress::

    $ pelican-import --wpfile -o ~/output ~/posts.xml

For Medium (an example of using an RSS feed):

    $ python -m pip install feedparser
    $ pelican-import --feed https://medium.com/feed/@username

.. note::

   The RSS feed may only return the most recent posts — not all of them.

Tests
=====

To test the module, one can use sample files:

- for WordPress: https://www.wpbeginner.com/wp-themes/how-to-add-dummy-content-for-theme-development-in-wordpress/
- for Dotclear: http://media.dotaddict.org/tda/downloads/lorem-backup.txt

.. _More Categories: https://github.com/pelican-plugins/more-categories


================================================
FILE: docs/index.rst
================================================
Pelican |release|
=================

Pelican is a static site generator, written in Python_. Highlights include:

* Write your content directly with your editor of choice in reStructuredText_
  or Markdown_ formats
* Includes a simple CLI tool to (re)generate your site
* Easy to interface with distributed version control systems and web hooks
* Completely static output is easy to host anywhere

Ready to get started? Check out the :doc:`Quickstart<quickstart>` guide.

Features
--------

Pelican’s feature highlights include:

* Articles (e.g., blog posts) and pages (e.g., "About", "Projects", "Contact")
* Integration with external services
* Site themes (created using Jinja2_ templates)
* Publication of articles in multiple languages
* Generation of Atom and RSS feeds
* Code syntax highlighting
* Import existing content from WordPress, Dotclear, or RSS feeds
* Fast rebuild times thanks to content caching and selective output writing
* Extensible via a rich plugin ecosystem: `Pelican Plugins`_

Why the name "Pelican"?
-----------------------

"Pelican" is an anagram for *calepin*, which means "notebook" in French. ;)

Source code
-----------

You can access the source code at: https://github.com/getpelican/pelican

How to get help, contribute, or provide feedback
------------------------------------------------

See our :doc:`feedback and contribution submission guidelines <contribute>`.

Documentation
-------------

.. toctree::
   :maxdepth: 2

   quickstart
   install
   content
   publish
   settings
   plugins
   themes
   pelican-themes
   importer
   faq
   tips
   contribute
   internals
   report
   changelog

.. Links

.. _Python: https://www.python.org/
.. _reStructuredText: http://docutils.sourceforge.net/rst.html
.. _Markdown: https://daringfireball.net/projects/markdown/
.. _Jinja2: https://palletsprojects.com/p/jinja/
.. _`Pelican documentation`: https://docs.getpelican.com/latest/
.. _`Pelican's internals`: https://docs.getpelican.com/en/latest/internals.html
.. _`Pelican Plugins`: https://github.com/pelican-plugins


================================================
FILE: docs/install.rst
================================================
Installing Pelican
##################

Pelican currently runs best on |min_python|; earlier versions of Python are not supported.

You can install Pelican via several different methods. The simplest is via Pip_::

    python -m pip install pelican

Or, if you plan on using Markdown::

    python -m pip install "pelican[markdown]"

(Keep in mind that some operating systems will require you to prefix the above
command with ``sudo`` in order to install Pelican system-wide.)

While the above is the simplest method, the recommended approach is to create a
virtual environment for Pelican via virtualenv_ before installing Pelican.
Assuming you have virtualenv_ installed, you can then open a new terminal
session and create a new virtual environment for Pelican::

    virtualenv ~/virtualenvs/pelican
    cd ~/virtualenvs/pelican
    source bin/activate

Once the virtual environment has been created and activated, Pelican can be
installed via ``python -m pip install pelican`` as noted above. Alternatively, if you
have the project source, you can install Pelican using the setuptools method::

    cd path-to-Pelican-source
    python -m pip install .

If you have Git installed and prefer to install the latest bleeding-edge
version of Pelican rather than a stable release, use the following command::

    python -m pip install -e "git+https://github.com/getpelican/pelican.git#egg=pelican"

Once Pelican is installed, you can run ``pelican --help`` to see basic usage
options. For more detail, refer to the :doc:`Publish<publish>` section.

Optional packages
-----------------

If you plan on using `Markdown <https://pypi.org/project/Markdown/>`_ as a
markup format, you can install Pelican with Markdown support::

    python -m pip install "pelican[markdown]"

Typographical enhancements can be enabled in your settings file, but first the
requisite `Typogrify <https://pypi.org/project/typogrify/>`_ library must be
installed::

    python -m pip install typogrify

Dependencies
------------

When Pelican is installed, the following dependent Python packages should be
automatically installed without any action on your part:

* `feedgenerator <https://pypi.org/project/feedgenerator/>`_, to generate the
  Atom feeds
* `jinja2 <https://pypi.org/project/Jinja2/>`_, for templating support
* `pygments <https://pypi.org/project/Pygments/>`_, for syntax highlighting
* `docutils <https://pypi.org/project/docutils/>`_, for supporting
  reStructuredText as an input format
* `blinker <https://pypi.org/project/blinker/>`_, an object-to-object and
  broadcast signaling system
* `unidecode <https://pypi.org/project/Unidecode/>`_, for ASCII
  transliterations of Unicode text
  utilities
* `MarkupSafe <https://pypi.org/project/MarkupSafe/>`_, for a markup-safe
  string implementation
* `python-dateutil <https://pypi.org/project/python-dateutil/>`_, to read
  the date metadata

Upgrading
---------

If you installed a stable Pelican release via Pip_ and wish to upgrade to
the latest stable release, you can do so by adding ``--upgrade``::

    python -m pip install --upgrade pelican

If you installed Pelican via distutils or the bleeding-edge method, simply
perform the same step to install the most recent version.

Kickstart your site
-------------------

Once Pelican has been installed, you can create a skeleton project via the
``pelican-quickstart`` command, which begins by asking some questions about
your site::

    pelican-quickstart

If run inside an activated virtual environment, ``pelican-quickstart`` will
look for an associated project path inside ``$VIRTUAL_ENV/.project``. If that
file exists and contains a valid directory path, the new Pelican project will
be saved at that location. Otherwise, the default is the current working
directory. To set the new project path on initial invocation, use:
``pelican-quickstart --path /your/desired/directory``

Once you finish answering all the questions, your project will consist of the
following hierarchy (except for *pages* — shown in parentheses below — which
you can optionally add yourself if you plan to create non-chronological
content)::

    yourproject/
    ├── content
    │   └── (pages)
    ├── output
    ├── tasks.py
    ├── Makefile
    ├── pelicanconf.py       # Main settings file
    └── publishconf.py       # Settings to use when ready to publish

The next step is to begin to adding content to the *content* folder that has
been created for you.

.. _Pip: https://pip.pypa.io/
.. _virtualenv: https://virtualenv.pypa.io/en/latest/


================================================
FILE: docs/internals.rst
================================================
Pelican internals
#################

This section describe how Pelican works internally. As you'll see, it's quite
simple, but a bit of documentation doesn't hurt.  :)

You can also find in the :doc:`report` section an excerpt of a report the
original author wrote with some software design information.

.. _report: :doc:`report`

Overall structure
=================

What Pelican does is take a list of files and process them into some sort of
output. Usually, the input files are reStructuredText and Markdown files, and
the output is a blog, but both input and output can be anything you want.

The logic is separated into different classes and concepts:

* **Writers** are responsible for writing files: .html files, RSS feeds, and so
  on. Since those operations are commonly used, the object is created once and
  then passed to the generators.

* **Readers** are used to read from various formats (HTML, Markdown and
  reStructuredText for now, but the system is extensible). Given a file, they
  return metadata (author, tags, category, etc.) and content (HTML-formatted).

* **Generators** generate the different outputs. For instance, Pelican comes
  with ``ArticlesGenerator`` and ``PageGenerator``. Given a configuration, they
  can do whatever they want. Most of the time, it's generating files from
  inputs.

* Pelican also uses templates, so it's easy to write your own theme. The
  syntax is `Jinja2 <https://palletsprojects.com/p/jinja/>`_ and is very easy to learn, so
  don't hesitate to jump in and build your own theme.

How to implement a new reader?
==============================

Is there an awesome markup language you want to add to Pelican? Well, the only
thing you have to do is to create a class with a ``read`` method that returns
HTML content and some metadata.

Take a look at the Markdown reader::

    from pelican.readers import BaseReader
    from pelican.utils import pelican_open
    from markdown import Markdown

    class MarkdownReader(BaseReader):
        enabled = True

        def read(self, source_path):
            """Parse content and metadata of markdown files"""

            with pelican_open(source_path) as text:
                md_extensions = {'markdown.extensions.meta': {},
                                 'markdown.extensions.codehilite': {}}
                md = Markdown(extensions=md_extensions.keys(),
                              extension_configs=md_extensions)
                content = md.convert(text)

            metadata = {}
            for name, value in md.Meta.items():
                name = name.lower()
                meta = self.process_metadata(name, value[0])
                metadata[name] = meta
            return content, metadata

Simple, isn't it?

If your new reader requires additional Python dependencies, then you should
wrap their ``import`` statements in a ``try...except`` block.  Then inside the
reader's class, set the ``enabled`` class attribute to mark import success or
failure. This makes it possible for users to continue using their favourite
markup method without needing to install modules for formats they don't use.

How to implement a new generator?
=================================

Generators have two important methods. You're not forced to create both; only
the existing ones will be called.

* ``generate_context``, that is called first, for all the generators.
  Do whatever you have to do, and update the global context if needed. This
  context is shared between all generators, and will be passed to the
  templates. For instance, the ``PageGenerator`` ``generate_context`` method
  finds all the pages, transforms them into objects, and populates the context
  with them. Be careful *not* to output anything using this context at this
  stage, as it is likely to change by the effect of other generators.

* ``generate_output`` is then called. And guess what is it made for? Oh,
  generating the output.  :) It's here that you may want to look at the context
  and call the methods of the ``writer`` object that is passed as the first
  argument of this function. In the ``PageGenerator`` example, this method will
  look at all the pages recorded in the global context and output a file on the
  disk (using the writer method ``write_file``) for each page encountered.


================================================
FILE: docs/locale/zh_CN/LC_MESSAGES/changelog.po
================================================
# SOME DESCRIPTIVE TITLE.
# Copyright (C) 2010–2024
# This file is distributed under the same license as the PELICAN package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2024.
#
msgid ""
msgstr ""
"Project-Id-Version: PELICAN 4\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-07-13 11:46+0800\n"
"PO-Revision-Date: 2024-06-27 19:00+0800\n"
"Last-Translator: GeorgeHu <dhxxhch@163.com>\n"
"Language: zh_CN\n"
"Language-Team: \n"
"Plural-Forms: nplurals=1; plural=0;\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.17.0\n"

#: ../../changelog.rst:2 0742e96cabd04fc99355bbfa66fcb719
msgid "Release history"
msgstr "更新日志"

#: ../../changelog.rst:5 2a6b4d6833884393bf6eb0f664f07027
msgid "4.11.0 - 2025-01-15"
msgstr ""

#: ../../changelog.rst:7 eb554022ed4445b4886e5fb7b1ffda48
msgid ""
"Add setting to selectively omit Typogrify filters `(#3439) "
"<https://github.com/getpelican/pelican/pull/3439>`_"
msgstr ""

#: ../../changelog.rst:8 b4296b7abe7a411faedd991310af951f
msgid ""
"Add more blocks to the Simple theme’s base template, making it easier to "
"create new themes by inheriting from the Simple theme `(#3405) "
"<https://github.com/getpelican/pelican/pull/3405>`_"
msgstr ""

#: ../../changelog.rst:9 da7911e453434d5fa2a24bb9bad85d5f
msgid ""
"Fix auto-reload behavior upon changes to the theme, content or settings. "
"Make default ``IGNORE_FILES`` recursively ignore all hidden files as well"
" as the `default filters "
"<https://watchfiles.helpmanual.io/api/filters/#watchfiles.DefaultFilter.ignore_dirs>`_"
" from ``watchfiles.DefaultFilter``. `(#3441) "
"<https://github.com/getpelican/pelican/pull/3441>`_"
msgstr ""

#: ../../changelog.rst:10 ad022a2dbbe74c28ab78757f64791daa
msgid ""
"Get current year from the ``SOURCE_DATE_EPOCH`` environment variable, if "
"available `(#3430) <https://github.com/getpelican/pelican/pull/3430>`_"
msgstr ""

#: ../../changelog.rst:11 c7270f10045541f992ea76f9b8f938bc
msgid ""
"Add Python 3.13 to test matrix and remove Python 3.8 `(#3435) "
"<https://github.com/getpelican/pelican/pull/3435>`_"
msgstr ""

#: ../../changelog.rst:12 c913ff7038e2445e831be08ce7a2d95f
msgid "Require Typogrify 2.1+ and Pygments <2.19"
msgstr ""

#: ../../changelog.rst:15 47b916504e6c4a33a499718574212ed2
msgid "4.10.2 - 2024-11-27"
msgstr ""

#: ../../changelog.rst:17 6ccca5efc34c43fc9e6549ce27d07b1a
msgid "Change ``IGNORE_FILES`` setting default to ignore all hidden files"
msgstr ""

#: ../../changelog.rst:18 b541de728f0d4480bf6a3cb93a331134
msgid ""
"Fix ``SUMMARY_MAX_PARAGRAPHS`` not being respected in some combinations "
"with ``SUMMARY_MAX_LENGTH``"
msgstr ""

#: ../../changelog.rst:21 47b916504e6c4a33a499718574212ed2
msgid "4.10.1 - 2024-09-28"
msgstr ""

#: ../../changelog.rst:23 33731d204a8f42d6972a5b41035bf6fa
msgid "Fix error when running ``pelican -r -l``"
msgstr ""

#: ../../changelog.rst:24 0c82e22bd70f497880747a23445a279e
msgid "Fix symlink handling in ``pelican-themes``"
msgstr ""

#: ../../changelog.rst:27 2a6b4d6833884393bf6eb0f664f07027
msgid "4.10.0 - 2024-09-16"
msgstr ""

#: ../../changelog.rst:29 c5b7388ced0246df9383968b896cee1d
msgid "Add setting to specify summary via paragraph count"
msgstr ""

#: ../../changelog.rst:30 55bef71482124d7ba15dcc13def666b4
msgid "Add new status to skip generation of a post"
msgstr ""

#: ../../changelog.rst:31 74aa099718c64ec3864fb4b54e8c7e7b
msgid "Add setting to append ``ref`` parameter to links in feeds"
msgstr ""

#: ../../changelog.rst:32 be0d21b2ffd648f9aad935e95fa2e9b2
msgid "Configure logging handler via ``--log-handler`` CLI option"
msgstr ""

#: ../../changelog.rst:33 f582b79f9b19462988607337626e92e8
msgid "Resolve intra-site links in summaries"
msgstr ""

#: ../../changelog.rst:34 00e8752d88364591a1e7844b3605963c
msgid "Warn when files are not processed due to disabled readers"
msgstr ""

#: ../../changelog.rst:35 0de52c3ba40b44f0816cc8dabf7913ab
msgid "Add Medium post importer"
msgstr ""

#: ../../changelog.rst:36 051bf922a7304dd798e894ddcfb64635
msgid "Improve GitHub Pages workflow"
msgstr ""

#: ../../changelog.rst:37 7db880406e9540de9b2d5b023cc10147
msgid "Improve code test coverage"
msgstr ""

#: ../../changelog.rst:38 c4327d2df9e34af384a4b0c96031e7e1
msgid "Translate documentation into Simplified Chinese"
msgstr ""

#: ../../changelog.rst:41 75bd952da32744868b68714fa89d62ec
msgid "4.9.1 - 2023-11-15"
msgstr ""

#: ../../changelog.rst:43 f896a982ada348e3bf763a9cf620d432
msgid "Ensure ``tzdata`` dependency is installed on Windows"
msgstr ""

#: ../../changelog.rst:46 f7893a294e2c4c44bd82d68283421096
msgid "4.9.0 - 2023-11-12"
msgstr ""

#: ../../changelog.rst:48 3fc89471c16044349176c6bf58daef61
msgid "Upgrade code to new minimum supported Python version: 3.8"
msgstr ""

#: ../../changelog.rst:49 361eb8523ae54e6c965c4957d5af9a0b
msgid ""
"Settings support for ``pathlib.Path`` `(#2758) "
"<https://github.com/getpelican/pelican/pull/2758>`_"
msgstr ""

#: ../../changelog.rst:50 7ea2147f8b6c4bc1af0e926b897fbbc7
msgid ""
"Various improvements to Simple theme (`#2976 "
"<https://github.com/getpelican/pelican/pull/2976>`_ & `#3234 "
"<https://github.com/getpelican/pelican/pull/3234>`_)"
msgstr ""

#: ../../changelog.rst:51 fc0e0bb6fd8a49bca130f352208d4e65
msgid ""
"Use Furo as Sphinx documentation theme `(#3023) "
"<https://github.com/getpelican/pelican/pull/3023>`_"
msgstr ""

#: ../../changelog.rst:52 1767e84116304b62bff9c66576c8b530
msgid ""
"Default to 100 articles maximum in feeds `(#3127) "
"<https://github.com/getpelican/pelican/pull/3127>`_"
msgstr ""

#: ../../changelog.rst:53 1f42290cb97f4c22b71b49bfd4e1d763
msgid ""
"Add ``period_archives common context`` variable `(#3148) "
"<https://github.com/getpelican/pelican/pull/3148>`_"
msgstr ""

#: ../../changelog.rst:54 8e70999f32d743d8be9d7a09a7b8440e
msgid ""
"Use ``watchfiles`` as the file-watching backend `(#3151) "
"<https://github.com/getpelican/pelican/pull/3151>`_"
msgstr ""

#: ../../changelog.rst:55 eb554022ed4445b4886e5fb7b1ffda48
msgid ""
"Add GitHub Actions workflow for GitHub Pages `(#3189) "
"<https://github.com/getpelican/pelican/pull/3189>`_"
msgstr ""

#: ../../changelog.rst:56 aee78c33fc074a5aa2a3e7b6b074a2d1
msgid ""
"Allow dataclasses in settings `(#3204) "
"<https://github.com/getpelican/pelican/pull/3204>`_"
msgstr ""

#: ../../changelog.rst:57 b302dcfa9ab347c7a4190e35a2fec468
msgid ""
"Switch build tool to PDM instead of Setuptools/Poetry `(#3220) "
"<https://github.com/getpelican/pelican/pull/3220>`_"
msgstr ""

#: ../../changelog.rst:58 39c35ce577d6418ebe1bdb8bd83855da
msgid ""
"Provide a ``plugin_enabled`` Jinja test for themes `(#3235) "
"<https://github.com/getpelican/pelican/pull/3235>`_"
msgstr ""

#: ../../changelog.rst:59 10520c5ebec34d02996410cc1d611162
msgid ""
"Preserve connection order in Blinker `(#3238) "
"<https://github.com/getpelican/pelican/pull/3238>`_"
msgstr ""

#: ../../changelog.rst:60 e3e01fbe72ff48578ee636044d930861
msgid ""
"Remove social icons from default ``notmyidea`` theme `(#3240) "
"<https://github.com/getpelican/pelican/pull/3240>`_"
msgstr ""

#: ../../changelog.rst:61 0e0d4fc6f77947a79bc3864dbcfd3025
msgid ""
"Remove unreliable ``WRITE_SELECTED`` feature `(#3243) "
"<https://github.com/getpelican/pelican/pull/3243>`_"
msgstr ""

#: ../../changelog.rst:62 3945b50f56c849e8b756418a049e8bd5
msgid ""
"Importer: Report broken embedded video links when importing from Tumblr "
"`(#3177) <https://github.com/getpelican/pelican/issues/3177>`_"
msgstr ""

#: ../../changelog.rst:63 91a65ac386d64de293807b14a1ee66c1
msgid ""
"Importer: Remove newline addition when iterating Photo post types "
"`(#3178) <https://github.com/getpelican/pelican/issues/3178>`_"
msgstr ""

#: ../../changelog.rst:64 5965fc057a0a4c94a2507956a2227789
msgid ""
"Importer: Force timestamp conversion in Tumblr importer to be UTC with "
"offset `(#3221) <https://github.com/getpelican/pelican/pull/3221>`_"
msgstr ""

#: ../../changelog.rst:65 f4a79028bfa946debc9a6924670e5456
msgid ""
"Importer: Use tempfile for intermediate HTML file for Pandoc `(#3221) "
"<https://github.com/getpelican/pelican/pull/3221>`_"
msgstr ""

#: ../../changelog.rst:66 ac3ff1ef109f49898c54eb75bb9d4bf3
msgid ""
"Switch linters to Ruff `(#3223) "
"<https://github.com/getpelican/pelican/pull/3223>`_"
msgstr ""

#: ../../changelog.rst:69 87b5ee37dea84dce9c75361f533e8057
msgid "4.8.0 - 2022-07-11"
msgstr ""

#: ../../changelog.rst:71 858d9945de86466eb1507d7859efc304
msgid ""
"Use JSON values for extra settings in Invoke tasks template `(#2994) "
"<https://github.com/getpelican/pelican/pull/2994>`_"
msgstr ""

#: ../../changelog.rst:72 ad022a2dbbe74c28ab78757f64791daa
msgid ""
"Add content tag for links, which can help with things like Twitter social"
" cards `(#3001) <https://github.com/getpelican/pelican/pull/3001>`_"
msgstr ""

#: ../../changelog.rst:73 889f590d0fda46dbb6a14336644f265e
msgid ""
"Improve word count behavior when generating summary `(#3002) "
"<https://github.com/getpelican/pelican/pull/3002>`_"
msgstr ""

#: ../../changelog.rst:76 c6c9bfd44396439c8e3a04b083dfc9b3
msgid "4.7.2 - 2022-02-09"
msgstr ""

#: ../../changelog.rst:78 21432dcec96e438c8f21de585540e9b9
msgid ""
"Fix incorrect parsing of parameters specified via `-e` / `--extra-"
"settings` option flags `(#2938) "
"<https://github.com/getpelican/pelican/pull/2938>`_"
msgstr ""

#: ../../changelog.rst:79 250cb0b205ea4bc091bcbfa18a688398
msgid ""
"Add ``categories.html`` template to default theme `(#2973) "
"<https://github.com/getpelican/pelican/pull/2973>`_"
msgstr ""

#: ../../changelog.rst:80 f404aaef8abe40d89a8394f71043767b
msgid ""
"Document how to use plugins to inject content `(#2922) "
"<https://github.com/getpelican/pelican/pull/2922>`_"
msgstr ""

#: ../../changelog.rst:83 ea47463991054e678639e2d5afee8733
msgid "4.7.1 - 2021-10-12"
msgstr ""

#: ../../changelog.rst:85 52f38102dca542dcaa5e901ba9cff484
msgid ""
"Extend rich logging to server component `(#2927) "
"<https://github.com/getpelican/pelican/pull/2927>`_"
msgstr ""

#: ../../changelog.rst:86 e2f47cedaac946b6b3877063c1531849
msgid ""
"Fix an issue where metadata flagged to be discarded was being cached "
"`(#2926) <https://github.com/getpelican/pelican/pull/2926>`_"
msgstr ""

#: ../../changelog.rst:87 c7270f10045541f992ea76f9b8f938bc
msgid ""
"Adjust suffix in server to allow redirection when needed `(#2931) "
"<https://github.com/getpelican/pelican/pull/2931>`_"
msgstr ""

#: ../../changelog.rst:88 25eecc81230442e8be149c26afebcba8
msgid ""
"Add MIME types for web fonts `(#2929) "
"<https://github.com/getpelican/pelican/pull/2929>`_"
msgstr ""

#: ../../changelog.rst:89 28bdcfa53bcf4bf5908acd39b88b1264
msgid ""
"Distribute sample data used to run tests `(#2935) "
"<https://github.com/getpelican/pelican/pull/2935>`_"
msgstr ""

#: ../../changelog.rst:90 90855b72a6744760a57195ca0566401c
msgid "Add Python 3.10 to test matrix"
msgstr ""

#: ../../changelog.rst:93 a5d1ee359c9a472bac01a3c953358994
msgid "4.7.0 - 2021-10-01"
msgstr ""

#: ../../changelog.rst:95 1b28838f5000456aa396f8768c307102
msgid ""
"Improve default theme rendering on mobile and other small screen devices "
"`(#2914) <https://github.com/getpelican/pelican/pull/2914>`_"
msgstr ""

#: ../../changelog.rst:96 e080e2f741464f92b7d988da7e3dba5d
msgid ""
"Add support for hidden articles `(#2866) "
"<https://github.com/getpelican/pelican/pull/2866>`_"
msgstr ""

#: ../../changelog.rst:97 71036c834cc4480ba38566d039d9b50a
msgid ""
"Improve word count behavior when generating summary CJK & other locales "
"`(#2864) <https://github.com/getpelican/pelican/pull/2864>`_"
msgstr ""

#: ../../changelog.rst:98 dad2c8c0f0d84a4db5b0139e8dc4bec8
msgid ""
"Add progress spinner during generation `(#2869) "
"<https://github.com/getpelican/pelican/pull/2869>`_ and richer logging "
"`(#2897) <https://github.com/getpelican/pelican/pull/2897>`_, both via "
"`Rich <https://github.com/willmcgugan/rich>`_"
msgstr ""

#: ../../changelog.rst:100 ad420f41f0fb44809f0f88d2638ed6b9
msgid ""
"Invoke tasks ``serve`` and ``livereload`` now auto-open a web browser "
"pointing to the locally-served web site `(#2764) "
"<https://github.com/getpelican/pelican/pull/2764>`_"
msgstr ""

#: ../../changelog.rst:101 34794ceaec054ec4b47706297e65a498
msgid ""
"Support some date format codes used by ISO dates `(#2902) "
"<https://github.com/getpelican/pelican/pull/2902>`_"
msgstr ""

#: ../../changelog.rst:102 cd9520f44e004be6a7d7fb27032d37a6
msgid ""
"Document how to add a new writer `(#2901) "
"<https://github.com/getpelican/pelican/pull/2901>`_"
msgstr ""

#: ../../changelog.rst:105 278990583126431793bd184ef69e4315
msgid "4.6.0 - 2021-03-23"
msgstr ""

#: ../../changelog.rst:107 a7a02445adbd4dd58d066f6f8fa5810b
msgid ""
"Add new URL pattern to ``PAGINATION_PATTERNS`` for the last page in the "
"list `(#1401) <https://github.com/getpelican/pelican/issues/1401>`_"
msgstr ""

#: ../../changelog.rst:108 e5e2fd04bc8a40edb8a0d1c088a95708
msgid ""
"Speed up ``livereload`` Invoke task via caching `(#2847) "
"<https://github.com/getpelican/pelican/pull/2847>`_"
msgstr ""

#: ../../changelog.rst:109 e37a383072324f98a8f5698edab71384
msgid ""
"Ignore ``None`` return value from ``get_generators`` signal `(#2850) "
"<https://github.com/getpelican/pelican/pull/2850>`_"
msgstr ""

#: ../../changelog.rst:110 ea446fad671d4e1e8b3220a35ffe170b
msgid "Relax dependency minimum versions and remove upper bounds"
msgstr ""

#: ../../changelog.rst:113 3e38341f147e414ba7b10c339d28a0d4
msgid "4.5.4 - 2021-01-04"
msgstr ""

#: ../../changelog.rst:115 b4296b7abe7a411faedd991310af951f
msgid ""
"Replace plugin definitions in settings with string representations after "
"registering, so they can be cached correctly `(#2828) "
"<https://github.com/getpel
Download .txt
gitextract_vbdoavsn/

├── .coveragerc
├── .editorconfig
├── .git-blame-ignore-revs
├── .gitattributes
├── .github/
│   ├── CODEOWNERS
│   ├── FUNDING.yml
│   ├── ISSUE_TEMPLATE/
│   │   ├── ---bug-report.md
│   │   ├── ---documentation.md
│   │   ├── ---enhancement-request.md
│   │   └── config.yml
│   ├── dependabot.yml
│   ├── pull_request_template.md
│   ├── stale.yml
│   └── workflows/
│       ├── github_pages.yml
│       └── main.yml
├── .gitignore
├── .mailmap
├── .pre-commit-config.yaml
├── .readthedocs.yaml
├── .vale.ini
├── CONTRIBUTING.rst
├── LICENSE
├── README.rst
├── THANKS
├── docs/
│   ├── Makefile
│   ├── _static/
│   │   └── theme_overrides.css
│   ├── _templates/
│   │   └── page.html
│   ├── changelog.rst
│   ├── conf.py
│   ├── content.rst
│   ├── contribute.rst
│   ├── faq.rst
│   ├── importer.rst
│   ├── index.rst
│   ├── install.rst
│   ├── internals.rst
│   ├── locale/
│   │   └── zh_CN/
│   │       └── LC_MESSAGES/
│   │           ├── changelog.po
│   │           ├── content.po
│   │           ├── contribute.po
│   │           ├── faq.po
│   │           ├── importer.po
│   │           ├── index.po
│   │           ├── install.po
│   │           ├── internals.po
│   │           ├── pelican-themes.po
│   │           ├── plugins.po
│   │           ├── publish.po
│   │           ├── quickstart.po
│   │           ├── report.po
│   │           ├── settings.po
│   │           ├── sphinx.po
│   │           ├── themes.po
│   │           └── tips.po
│   ├── pelican-themes.rst
│   ├── plugins.rst
│   ├── publish.rst
│   ├── quickstart.rst
│   ├── report.rst
│   ├── settings.rst
│   ├── themes.rst
│   └── tips.rst
├── pelican/
│   ├── __init__.py
│   ├── __main__.py
│   ├── cache.py
│   ├── contents.py
│   ├── generators.py
│   ├── log.py
│   ├── paginator.py
│   ├── plugins/
│   │   ├── _utils.py
│   │   └── signals.py
│   ├── readers.py
│   ├── rstdirectives.py
│   ├── server.py
│   ├── settings.py
│   ├── signals.py
│   ├── tests/
│   │   ├── TestPages/
│   │   │   ├── bad_page.rst
│   │   │   ├── draft_page.rst
│   │   │   ├── draft_page_markdown.md
│   │   │   ├── draft_page_with_template.rst
│   │   │   ├── hidden_page.rst
│   │   │   ├── hidden_page_markdown.md
│   │   │   ├── hidden_page_with_template.rst
│   │   │   ├── page.rst
│   │   │   ├── page_markdown.md
│   │   │   ├── page_used_for_sorting_test.rst
│   │   │   ├── page_with_category_and_tag_links.md
│   │   │   ├── page_with_static_links.md
│   │   │   └── page_with_template.rst
│   │   ├── __init__.py
│   │   ├── build_test/
│   │   │   ├── conftest.py
│   │   │   └── test_build_files.py
│   │   ├── content/
│   │   │   ├── 2012-11-29_rst_w_filename_meta#foo-bar.rst
│   │   │   ├── 2012-11-30_md_w_filename_meta#foo-bar.md
│   │   │   ├── TestCategory/
│   │   │   │   ├── article_with_category.rst
│   │   │   │   └── article_without_category.rst
│   │   │   ├── article.rst
│   │   │   ├── article_draft.md
│   │   │   ├── article_hidden.md
│   │   │   ├── article_skip.md
│   │   │   ├── article_with_attributes_containing_double_quotes.html
│   │   │   ├── article_with_capitalized_metadata.rst
│   │   │   ├── article_with_code_block.rst
│   │   │   ├── article_with_comments.html
│   │   │   ├── article_with_duplicate_tags_authors.md
│   │   │   ├── article_with_inline_svg.html
│   │   │   ├── article_with_keywords.html
│   │   │   ├── article_with_markdown_and_empty_tags.md
│   │   │   ├── article_with_markdown_and_footnote.md
│   │   │   ├── article_with_markdown_and_nested_metadata.md
│   │   │   ├── article_with_markdown_and_nonascii_summary.md
│   │   │   ├── article_with_markdown_and_summary_metadata_multi.md
│   │   │   ├── article_with_markdown_and_summary_metadata_single.md
│   │   │   ├── article_with_markdown_extension.markdown
│   │   │   ├── article_with_markdown_markup_extensions.md
│   │   │   ├── article_with_md_extension.md
│   │   │   ├── article_with_mdown_extension.mdown
│   │   │   ├── article_with_metadata.html
│   │   │   ├── article_with_metadata.rst
│   │   │   ├── article_with_metadata.unknownextension
│   │   │   ├── article_with_metadata_and_contents.html
│   │   │   ├── article_with_metadata_explicit_date_implicit_modified.html
│   │   │   ├── article_with_metadata_explicit_dates.html
│   │   │   ├── article_with_metadata_implicit_date_explicit_modified.html
│   │   │   ├── article_with_metadata_implicit_dates.html
│   │   │   ├── article_with_mkd_extension.mkd
│   │   │   ├── article_with_multiple_authors.html
│   │   │   ├── article_with_multiple_authors.rst
│   │   │   ├── article_with_multiple_authors_list.rst
│   │   │   ├── article_with_multiple_authors_semicolon.rst
│   │   │   ├── article_with_multiple_metadata_tags.html
│   │   │   ├── article_with_nonconformant_meta_tags.html
│   │   │   ├── article_with_null_attributes.html
│   │   │   ├── article_with_template.rst
│   │   │   ├── article_with_typogrify_dashes.md
│   │   │   ├── article_with_typogrify_dashes.rst
│   │   │   ├── article_with_uppercase_metadata.html
│   │   │   ├── article_with_uppercase_metadata.rst
│   │   │   ├── article_without_category.rst
│   │   │   ├── bad_extension.mmd
│   │   │   ├── bloggerexport.xml
│   │   │   ├── empty.md
│   │   │   ├── empty_with_bom.md
│   │   │   ├── medium_post_content.txt
│   │   │   ├── medium_posts/
│   │   │   │   └── 2017-04-21_-medium-post--d1bf01d62ba3.html
│   │   │   ├── wordpress_content_decoded
│   │   │   ├── wordpress_content_encoded
│   │   │   └── wordpressexport.xml
│   │   ├── cyclic_intersite_links/
│   │   │   ├── first-article.rst
│   │   │   ├── second-article.rst
│   │   │   └── third-article.rst
│   │   ├── default_conf.py
│   │   ├── dummy_plugins/
│   │   │   ├── namespace_plugin/
│   │   │   │   └── pelican/
│   │   │   │       └── plugins/
│   │   │   │           └── ns_plugin/
│   │   │   │               └── __init__.py
│   │   │   └── normal_plugin/
│   │   │       ├── normal_plugin/
│   │   │       │   ├── __init__.py
│   │   │       │   └── submodule.py
│   │   │       └── normal_submodule_plugin/
│   │   │           ├── __init__.py
│   │   │           ├── subpackage/
│   │   │           │   ├── __init__.py
│   │   │           │   └── subpackage.py
│   │   │           └── subplugin.py
│   │   ├── mixed_content/
│   │   │   └── short_page.md
│   │   ├── nested_content/
│   │   │   └── maindir/
│   │   │       ├── maindir.md
│   │   │       └── subdir/
│   │   │           └── subdir.md
│   │   ├── output/
│   │   │   ├── basic/
│   │   │   │   ├── a-markdown-powered-article.html
│   │   │   │   ├── archives.html
│   │   │   │   ├── article-1.html
│   │   │   │   ├── article-2.html
│   │   │   │   ├── article-3.html
│   │   │   │   ├── author/
│   │   │   │   │   └── alexis-metaireau.html
│   │   │   │   ├── authors.html
│   │   │   │   ├── categories.html
│   │   │   │   ├── category/
│   │   │   │   │   ├── bar.html
│   │   │   │   │   ├── cat1.html
│   │   │   │   │   ├── misc.html
│   │   │   │   │   └── yeah.html
│   │   │   │   ├── drafts/
│   │   │   │   │   ├── a-draft-article-without-date.html
│   │   │   │   │   └── a-draft-article.html
│   │   │   │   ├── feeds/
│   │   │   │   │   ├── alexis-metaireau.atom.xml
│   │   │   │   │   ├── alexis-metaireau.rss.xml
│   │   │   │   │   ├── all-en.atom.xml
│   │   │   │   │   ├── all-fr.atom.xml
│   │   │   │   │   ├── all.atom.xml
│   │   │   │   │   ├── bar.atom.xml
│   │   │   │   │   ├── cat1.atom.xml
│   │   │   │   │   ├── misc.atom.xml
│   │   │   │   │   └── yeah.atom.xml
│   │   │   │   ├── filename_metadata-example.html
│   │   │   │   ├── index.html
│   │   │   │   ├── oh-yeah-fr.html
│   │   │   │   ├── oh-yeah.html
│   │   │   │   ├── override/
│   │   │   │   │   └── index.html
│   │   │   │   ├── pages/
│   │   │   │   │   ├── this-is-a-test-hidden-page.html
│   │   │   │   │   └── this-is-a-test-page.html
│   │   │   │   ├── second-article-fr.html
│   │   │   │   ├── second-article.html
│   │   │   │   ├── tag/
│   │   │   │   │   ├── bar.html
│   │   │   │   │   ├── baz.html
│   │   │   │   │   ├── foo.html
│   │   │   │   │   ├── foobar.html
│   │   │   │   │   ├── oh.html
│   │   │   │   │   └── yeah.html
│   │   │   │   ├── tags.html
│   │   │   │   ├── theme/
│   │   │   │   │   ├── css/
│   │   │   │   │   │   ├── fonts.css
│   │   │   │   │   │   ├── main.css
│   │   │   │   │   │   ├── pygment.css
│   │   │   │   │   │   ├── reset.css
│   │   │   │   │   │   ├── typogrify.css
│   │   │   │   │   │   └── wide.css
│   │   │   │   │   └── fonts/
│   │   │   │   │       ├── Yanone_Kaffeesatz_LICENSE.txt
│   │   │   │   │       └── font.css
│   │   │   │   ├── this-is-a-super-article.html
│   │   │   │   └── unbelievable.html
│   │   │   ├── custom/
│   │   │   │   ├── a-markdown-powered-article.html
│   │   │   │   ├── archives.html
│   │   │   │   ├── article-1.html
│   │   │   │   ├── article-2.html
│   │   │   │   ├── article-3.html
│   │   │   │   ├── author/
│   │   │   │   │   ├── alexis-metaireau.html
│   │   │   │   │   ├── alexis-metaireau2.html
│   │   │   │   │   └── alexis-metaireau3.html
│   │   │   │   ├── authors.html
│   │   │   │   ├── categories.html
│   │   │   │   ├── category/
│   │   │   │   │   ├── bar.html
│   │   │   │   │   ├── cat1.html
│   │   │   │   │   ├── misc.html
│   │   │   │   │   └── yeah.html
│   │   │   │   ├── drafts/
│   │   │   │   │   ├── a-draft-article-without-date.html
│   │   │   │   │   └── a-draft-article.html
│   │   │   │   ├── feeds/
│   │   │   │   │   ├── alexis-metaireau.atom.xml
│   │   │   │   │   ├── alexis-metaireau.rss.xml
│   │   │   │   │   ├── all-en.atom.xml
│   │   │   │   │   ├── all-fr.atom.xml
│   │   │   │   │   ├── all.atom.xml
│   │   │   │   │   ├── all.rss.xml
│   │   │   │   │   ├── bar.atom.xml
│   │   │   │   │   ├── bar.rss.xml
│   │   │   │   │   ├── cat1.atom.xml
│   │   │   │   │   ├── cat1.rss.xml
│   │   │   │   │   ├── misc.atom.xml
│   │   │   │   │   ├── misc.rss.xml
│   │   │   │   │   ├── yeah.atom.xml
│   │   │   │   │   └── yeah.rss.xml
│   │   │   │   ├── filename_metadata-example.html
│   │   │   │   ├── index.html
│   │   │   │   ├── index2.html
│   │   │   │   ├── index3.html
│   │   │   │   ├── jinja2_template.html
│   │   │   │   ├── oh-yeah-fr.html
│   │   │   │   ├── oh-yeah.html
│   │   │   │   ├── override/
│   │   │   │   │   └── index.html
│   │   │   │   ├── pages/
│   │   │   │   │   ├── this-is-a-test-hidden-page.html
│   │   │   │   │   └── this-is-a-test-page.html
│   │   │   │   ├── robots.txt
│   │   │   │   ├── second-article-fr.html
│   │   │   │   ├── second-article.html
│   │   │   │   ├── tag/
│   │   │   │   │   ├── bar.html
│   │   │   │   │   ├── baz.html
│   │   │   │   │   ├── foo.html
│   │   │   │   │   ├── foobar.html
│   │   │   │   │   ├── oh.html
│   │   │   │   │   └── yeah.html
│   │   │   │   ├── tags.html
│   │   │   │   ├── theme/
│   │   │   │   │   ├── css/
│   │   │   │   │   │   ├── fonts.css
│   │   │   │   │   │   ├── main.css
│   │   │   │   │   │   ├── pygment.css
│   │   │   │   │   │   ├── reset.css
│   │   │   │   │   │   ├── typogrify.css
│   │   │   │   │   │   └── wide.css
│   │   │   │   │   └── fonts/
│   │   │   │   │       ├── Yanone_Kaffeesatz_LICENSE.txt
│   │   │   │   │       └── font.css
│   │   │   │   ├── this-is-a-super-article.html
│   │   │   │   └── unbelievable.html
│   │   │   └── custom_locale/
│   │   │       ├── archives.html
│   │   │       ├── author/
│   │   │       │   ├── alexis-metaireau.html
│   │   │       │   ├── alexis-metaireau2.html
│   │   │       │   └── alexis-metaireau3.html
│   │   │       ├── authors.html
│   │   │       ├── categories.html
│   │   │       ├── category/
│   │   │       │   ├── bar.html
│   │   │       │   ├── cat1.html
│   │   │       │   ├── misc.html
│   │   │       │   └── yeah.html
│   │   │       ├── drafts/
│   │   │       │   ├── a-draft-article-without-date.html
│   │   │       │   └── a-draft-article.html
│   │   │       ├── feeds/
│   │   │       │   ├── alexis-metaireau.atom.xml
│   │   │       │   ├── alexis-metaireau.rss.xml
│   │   │       │   ├── all-en.atom.xml
│   │   │       │   ├── all-fr.atom.xml
│   │   │       │   ├── all.atom.xml
│   │   │       │   ├── all.rss.xml
│   │   │       │   ├── bar.atom.xml
│   │   │       │   ├── bar.rss.xml
│   │   │       │   ├── cat1.atom.xml
│   │   │       │   ├── cat1.rss.xml
│   │   │       │   ├── misc.atom.xml
│   │   │       │   ├── misc.rss.xml
│   │   │       │   ├── yeah.atom.xml
│   │   │       │   └── yeah.rss.xml
│   │   │       ├── index.html
│   │   │       ├── index2.html
│   │   │       ├── index3.html
│   │   │       ├── jinja2_template.html
│   │   │       ├── oh-yeah-fr.html
│   │   │       ├── override/
│   │   │       │   └── index.html
│   │   │       ├── pages/
│   │   │       │   ├── this-is-a-test-hidden-page.html
│   │   │       │   └── this-is-a-test-page.html
│   │   │       ├── posts/
│   │   │       │   ├── 2010/
│   │   │       │   │   ├── décembre/
│   │   │       │   │   │   └── 02/
│   │   │       │   │   │       └── this-is-a-super-article/
│   │   │       │   │   │           └── index.html
│   │   │       │   │   └── octobre/
│   │   │       │   │       ├── 15/
│   │   │       │   │       │   └── unbelievable/
│   │   │       │   │       │       └── index.html
│   │   │       │   │       └── 20/
│   │   │       │   │           └── oh-yeah/
│   │   │       │   │               └── index.html
│   │   │       │   ├── 2011/
│   │   │       │   │   ├── avril/
│   │   │       │   │   │   └── 20/
│   │   │       │   │   │       └── a-markdown-powered-article/
│   │   │       │   │   │           └── index.html
│   │   │       │   │   └── février/
│   │   │       │   │       └── 17/
│   │   │       │   │           ├── article-1/
│   │   │       │   │           │   └── index.html
│   │   │       │   │           ├── article-2/
│   │   │       │   │           │   └── index.html
│   │   │       │   │           └── article-3/
│   │   │       │   │               └── index.html
│   │   │       │   └── 2012/
│   │   │       │       ├── février/
│   │   │       │       │   └── 29/
│   │   │       │       │       └── second-article/
│   │   │       │       │           └── index.html
│   │   │       │       └── novembre/
│   │   │       │           └── 30/
│   │   │       │               └── filename_metadata-example/
│   │   │       │                   └── index.html
│   │   │       ├── robots.txt
│   │   │       ├── second-article-fr.html
│   │   │       ├── tag/
│   │   │       │   ├── bar.html
│   │   │       │   ├── baz.html
│   │   │       │   ├── foo.html
│   │   │       │   ├── foobar.html
│   │   │       │   ├── oh.html
│   │   │       │   └── yeah.html
│   │   │       ├── tags.html
│   │   │       └── theme/
│   │   │           ├── css/
│   │   │           │   ├── fonts.css
│   │   │           │   ├── main.css
│   │   │           │   ├── pygment.css
│   │   │           │   ├── reset.css
│   │   │           │   ├── typogrify.css
│   │   │           │   └── wide.css
│   │   │           └── fonts/
│   │   │               ├── Yanone_Kaffeesatz_LICENSE.txt
│   │   │               └── font.css
│   │   ├── parse_error/
│   │   │   └── parse_error.rst
│   │   ├── support.py
│   │   ├── test_cache.py
│   │   ├── test_cli.py
│   │   ├── test_contents.py
│   │   ├── test_generators.py
│   │   ├── test_importer.py
│   │   ├── test_log.py
│   │   ├── test_paginator.py
│   │   ├── test_pelican.py
│   │   ├── test_plugins.py
│   │   ├── test_readers.py
│   │   ├── test_rstdirectives.py
│   │   ├── test_server.py
│   │   ├── test_settings.py
│   │   ├── test_testsuite.py
│   │   ├── test_theme.py
│   │   ├── test_urlwrappers.py
│   │   ├── test_utils.py
│   │   └── theme_overrides/
│   │       ├── level1/
│   │       │   └── article.html
│   │       └── level2/
│   │           ├── article.html
│   │           └── authors.html
│   ├── themes/
│   │   ├── notmyidea/
│   │   │   ├── static/
│   │   │   │   ├── css/
│   │   │   │   │   ├── fonts.css
│   │   │   │   │   ├── main.css
│   │   │   │   │   ├── pygment.css
│   │   │   │   │   ├── reset.css
│   │   │   │   │   ├── typogrify.css
│   │   │   │   │   └── wide.css
│   │   │   │   └── fonts/
│   │   │   │       ├── Yanone_Kaffeesatz_LICENSE.txt
│   │   │   │       └── font.css
│   │   │   └── templates/
│   │   │       ├── analytics.html
│   │   │       ├── archives.html
│   │   │       ├── article.html
│   │   │       ├── article_infos.html
│   │   │       ├── author.html
│   │   │       ├── authors.html
│   │   │       ├── base.html
│   │   │       ├── categories.html
│   │   │       ├── category.html
│   │   │       ├── comments.html
│   │   │       ├── disqus_script.html
│   │   │       ├── github.html
│   │   │       ├── index.html
│   │   │       ├── page.html
│   │   │       ├── period_archives.html
│   │   │       ├── tag.html
│   │   │       ├── taglist.html
│   │   │       ├── tags.html
│   │   │       ├── translations.html
│   │   │       └── twitter.html
│   │   └── simple/
│   │       └── templates/
│   │           ├── archives.html
│   │           ├── article.html
│   │           ├── author.html
│   │           ├── authors.html
│   │           ├── base.html
│   │           ├── categories.html
│   │           ├── category.html
│   │           ├── index.html
│   │           ├── page.html
│   │           ├── pagination.html
│   │           ├── period_archives.html
│   │           ├── tag.html
│   │           ├── tags.html
│   │           └── translations.html
│   ├── tools/
│   │   ├── __init__.py
│   │   ├── pelican_import.py
│   │   ├── pelican_quickstart.py
│   │   ├── pelican_themes.py
│   │   └── templates/
│   │       ├── Makefile.jinja2
│   │       ├── pelicanconf.py.jinja2
│   │       ├── publishconf.py.jinja2
│   │       └── tasks.py.jinja2
│   ├── urlwrappers.py
│   ├── utils.py
│   └── writers.py
├── pyproject.toml
├── requirements/
│   ├── developer.pip
│   ├── docs.pip
│   ├── owner.pip
│   └── test.pip
├── samples/
│   ├── content/
│   │   ├── 2012-11-30_filename-metadata.rst
│   │   ├── another_super_article-fr.rst
│   │   ├── another_super_article.rst
│   │   ├── article2-fr.rst
│   │   ├── article2.rst
│   │   ├── article_tag_baz.rst
│   │   ├── cat1/
│   │   │   ├── article1.rst
│   │   │   ├── article2.rst
│   │   │   ├── article3.rst
│   │   │   └── markdown-article.md
│   │   ├── draft_article without_date.rst
│   │   ├── draft_article.rst
│   │   ├── extra/
│   │   │   └── robots.txt
│   │   ├── pages/
│   │   │   ├── hidden_page.rst
│   │   │   ├── jinja2_template.html
│   │   │   ├── override_tag_oh.rst
│   │   │   ├── override_url_saveas.rst
│   │   │   └── test_page.rst
│   │   ├── super_article.rst
│   │   ├── unbelievable.rst
│   │   └── unwanted_file
│   ├── kinda/
│   │   └── exciting/
│   │       ├── new/
│   │       │   └── files/
│   │       │       └── zap!
│   │       └── old
│   ├── pelican.conf.py
│   ├── pelican.conf_FR.py
│   ├── theme_standard/
│   │   ├── a_stylesheet
│   │   └── a_template
│   └── very/
│       └── exciting/
│           └── new/
│               └── files/
│                   ├── bap!
│                   ├── boom!
│                   └── wow!
├── tasks.py
└── tox.ini
Download .txt
SYMBOL INDEX (806 symbols across 44 files)

FILE: docs/conf.py
  function setup (line 75) | def setup(app):

FILE: pelican/__init__.py
  class Pelican (line 47) | class Pelican:
    method __init__ (line 48) | def __init__(self, settings):
    method init_path (line 68) | def init_path(self):
    method init_plugins (line 73) | def init_plugins(self):
    method run (line 92) | def run(self):
    method _get_generator_classes (line 199) | def _get_generator_classes(self):
    method _get_writer (line 236) | def _get_writer(self):
  class PrintSettings (line 252) | class PrintSettings(argparse.Action):
    method __call__ (line 253) | def __call__(self, parser, namespace, values, option_string):
  class ParseOverrides (line 288) | class ParseOverrides(argparse.Action):
    method __call__ (line 289) | def __call__(self, parser, namespace, values, option_string=None):
  function parse_arguments (line 317) | def parse_arguments(argv=None):
  function get_config (line 520) | def get_config(args):
  function get_instance (line 548) | def get_instance(args):
  function autoreload (line 565) | def autoreload(args, excqueue=None):
  function listen (line 603) | def listen(server, port, output, excqueue=None):
  function main (line 633) | def main(argv=None):

FILE: pelican/cache.py
  class FileDataCacher (line 12) | class FileDataCacher:
    method __init__ (line 15) | def __init__(self, settings, cache_name, caching_policy, load_policy):
    method cache_data (line 54) | def cache_data(self, filename, data):
    method get_cached_data (line 59) | def get_cached_data(self, filename, default=None):
    method save_cache (line 66) | def save_cache(self):
  class FileStampDataCacher (line 79) | class FileStampDataCacher(FileDataCacher):
    method __init__ (line 82) | def __init__(self, settings, cache_name, caching_policy, load_policy):
    method cache_data (line 106) | def cache_data(self, filename, data):
    method _get_file_stamp (line 111) | def _get_file_stamp(self, filename):
    method get_cached_data (line 127) | def get_cached_data(self, filename, default=None):

FILE: pelican/contents.py
  class Content (line 37) | class Content:
    method filename (line 52) | def filename():
    method __init__ (line 55) | def __init__(
    method __str__ (line 168) | def __str__(self) -> str:
    method _has_valid_mandatory_properties (line 171) | def _has_valid_mandatory_properties(self) -> bool:
    method _has_valid_save_as (line 181) | def _has_valid_save_as(self) -> bool:
    method _has_valid_status (line 202) | def _has_valid_status(self) -> bool:
    method is_valid (line 216) | def is_valid(self) -> bool:
    method url_format (line 228) | def url_format(self) -> dict[str, Any]:
    method _expand_settings (line 244) | def _expand_settings(self, key: str, klass: str | None = None) -> str:
    method get_url_setting (line 250) | def get_url_setting(self, key: str) -> str:
    method _link_replacer (line 256) | def _link_replacer(self, siteurl: str, m: re.Match) -> str:
    method _get_intrasite_link_regex (line 371) | def _get_intrasite_link_regex(self) -> re.Pattern:
    method _update_content (line 382) | def _update_content(self, content: str, siteurl: str) -> str:
    method get_static_links (line 398) | def get_static_links(self) -> set[str]:
    method get_siteurl (line 418) | def get_siteurl(self) -> str:
    method get_content (line 422) | def get_content(self, siteurl: str) -> str:
    method content (line 430) | def content(self) -> str:
    method get_summary (line 434) | def get_summary(self, _siteurl: str) -> str:
    method summary (line 458) | def summary(self) -> str:
    method _get_summary (line 461) | def _get_summary(self) -> str:
    method summary (line 471) | def summary(self, value: str):
    method status (line 475) | def status(self) -> str:
    method status (line 479) | def status(self, value: str) -> None:
    method url (line 484) | def url(self) -> str:
    method save_as (line 488) | def save_as(self) -> str:
    method _get_template (line 491) | def _get_template(self) -> str:
    method get_relative_source_path (line 497) | def get_relative_source_path(self, source_path: str | None = None) -> ...
    method relative_dir (line 517) | def relative_dir(self) -> str:
    method refresh_metadata_intersite_links (line 527) | def refresh_metadata_intersite_links(self) -> None:
  class SkipStub (line 547) | class SkipStub(Content):
    method __init__ (line 550) | def __init__(
    method is_valid (line 556) | def is_valid(self):
    method content (line 560) | def content(self):
    method save_as (line 564) | def save_as(self):
  class Page (line 568) | class Page(Content):
    method _expand_settings (line 574) | def _expand_settings(self, key: str) -> str:
  class Article (line 579) | class Article(Content):
    method __init__ (line 585) | def __init__(self, *args, **kwargs):
    method _expand_settings (line 601) | def _expand_settings(self, key: str) -> str:
  class Static (line 606) | class Static(Content):
    method __init__ (line 611) | def __init__(self, *args, **kwargs) -> None:
    method filepath (line 616) | def filepath():
    method src (line 620) | def src():
    method dst (line 624) | def dst():
    method url (line 628) | def url(self) -> str:
    method save_as (line 634) | def save_as(self) -> str:
    method attach_to (line 639) | def attach_to(self, content: Content) -> None:

FILE: pelican/generators.py
  class PelicanTemplateNotFound (line 37) | class PelicanTemplateNotFound(Exception):
  class Generator (line 41) | class Generator:
    method __init__ (line 44) | def __init__(
    method get_template (line 113) | def get_template(self, name):
    method _include_path (line 137) | def _include_path(self, path, extensions=None):
    method get_files (line 159) | def get_files(
    method add_source_path (line 209) | def add_source_path(self, content, static=False):
    method _add_failed_source_path (line 217) | def _add_failed_source_path(self, path, static=False):
    method _is_potential_source_path (line 225) | def _is_potential_source_path(self, path, static=False):
    method add_static_links (line 234) | def add_static_links(self, content):
    method _update_context (line 240) | def _update_context(self, items):
    method __str__ (line 251) | def __str__(self):
    method _check_disabled_readers (line 255) | def _check_disabled_readers(self, paths, exclude: list[str] | None) ->...
  class CachingGenerator (line 263) | class CachingGenerator(Generator, FileStampDataCacher):
    method __init__ (line 269) | def __init__(self, *args, **kwargs):
    method _get_file_stamp (line 286) | def _get_file_stamp(self, filename):
  class _FileLoader (line 292) | class _FileLoader(BaseLoader):
    method __init__ (line 293) | def __init__(self, path, basedir):
    method get_source (line 297) | def get_source(self, environment, template):
  class TemplatePagesGenerator (line 307) | class TemplatePagesGenerator(Generator):
    method generate_output (line 308) | def generate_output(self, writer):
  class ArticlesGenerator (line 321) | class ArticlesGenerator(CachingGenerator):
    method __init__ (line 324) | def __init__(self, *args, **kwargs):
    method generate_feeds (line 344) | def generate_feeds(self, writer):
    method generate_articles (line 501) | def generate_articles(self, write):
    method generate_period_archives (line 521) | def generate_period_archives(self, write):
    method generate_direct_templates (line 546) | def generate_direct_templates(self, write):
    method generate_tags (line 568) | def generate_tags(self, write):
    method generate_categories (line 587) | def generate_categories(self, write):
    method generate_authors (line 606) | def generate_authors(self, write):
    method generate_drafts (line 625) | def generate_drafts(self, write):
    method generate_pages (line 640) | def generate_pages(self, writer):
    method check_disabled_readers (line 656) | def check_disabled_readers(self) -> None:
    method generate_context (line 661) | def generate_context(self):
    method _build_period_archives (line 774) | def _build_period_archives(self, sorted_articles, articles, settings):
    method generate_output (line 841) | def generate_output(self, writer):
    method refresh_metadata_intersite_links (line 846) | def refresh_metadata_intersite_links(self):
  class PagesGenerator (line 859) | class PagesGenerator(CachingGenerator):
    method __init__ (line 862) | def __init__(self, *args, **kwargs):
    method check_disabled_readers (line 872) | def check_disabled_readers(self) -> None:
    method generate_context (line 877) | def generate_context(self):
    method generate_output (line 945) | def generate_output(self, writer):
    method refresh_metadata_intersite_links (line 966) | def refresh_metadata_intersite_links(self):
  class StaticGenerator (line 978) | class StaticGenerator(Generator):
    method __init__ (line 982) | def __init__(self, *args, **kwargs):
    method check_disabled_readers (line 987) | def check_disabled_readers(self) -> None:
    method generate_context (line 992) | def generate_context(self):
    method generate_output (line 1022) | def generate_output(self, writer):
    method _copy_paths (line 1037) | def _copy_paths(self, paths, source, destination, output_path, final_p...
    method _file_update_required (line 1056) | def _file_update_required(self, staticfile):
    method _source_is_newer (line 1075) | def _source_is_newer(self, staticfile):
    method _link_or_copy_staticfile (line 1082) | def _link_or_copy_staticfile(self, sc):
    method _copy_staticfile (line 1088) | def _copy_staticfile(self, sc):
    method _link_staticfile (line 1095) | def _link_staticfile(self, sc):
    method _mkdir (line 1117) | def _mkdir(self, path):
  class SourceFileGenerator (line 1123) | class SourceFileGenerator(Generator):
    method generate_context (line 1124) | def generate_context(self):
    method _create_source (line 1127) | def _create_source(self, obj):
    method generate_output (line 1132) | def generate_output(self, writer=None):

FILE: pelican/log.py
  class LimitFilter (line 13) | class LimitFilter(logging.Filter):
    method filter (line 30) | def filter(self, record):
  class LimitLogger (line 67) | class LimitLogger(logging.Logger):
    method __init__ (line 74) | def __init__(self, *args, **kwargs):
    method disable_filter (line 78) | def disable_filter(self):
    method enable_filter (line 81) | def enable_filter(self):
  class FatalLogger (line 85) | class FatalLogger(LimitLogger):
    method warning (line 89) | def warning(self, *args, stacklevel=1, **kwargs):
    method error (line 107) | def error(self, *args, stacklevel=1, **kwargs):
  function init (line 133) | def init(
  function log_warnings (line 159) | def log_warnings():

FILE: pelican/paginator.py
  class Paginator (line 14) | class Paginator:
    method __init__ (line 15) | def __init__(self, name, url, object_list, settings, per_page=None):
    method page (line 29) | def page(self, number):
    method _get_count (line 44) | def _get_count(self):
    method _get_num_pages (line 52) | def _get_num_pages(self):
    method _get_page_range (line 61) | def _get_page_range(self):
  class Page (line 71) | class Page:
    method __init__ (line 72) | def __init__(self, name, url, object_list, number, paginator, settings):
    method __repr__ (line 83) | def __repr__(self):
    method has_next (line 86) | def has_next(self):
    method has_previous (line 89) | def has_previous(self):
    method has_other_pages (line 92) | def has_other_pages(self):
    method next_page_number (line 95) | def next_page_number(self):
    method previous_page_number (line 98) | def previous_page_number(self):
    method start_index (line 101) | def start_index(self):
    method end_index (line 111) | def end_index(self):
    method _from_settings (line 121) | def _from_settings(self, key):

FILE: pelican/plugins/_utils.py
  function iter_namespace (line 12) | def iter_namespace(ns_pkg):
  function get_namespace_plugins (line 20) | def get_namespace_plugins(ns_pkg=None):
  function list_plugins (line 31) | def list_plugins(ns_pkg=None):
  function plugin_enabled (line 42) | def plugin_enabled(name, plugin_list=None):
  function load_legacy_plugin (line 58) | def load_legacy_plugin(plugin, plugin_paths):
  function load_plugins (line 95) | def load_plugins(settings):
  function get_plugin_name (line 126) | def get_plugin_name(plugin):

FILE: pelican/readers.py
  function ensure_metadata_list (line 62) | def ensure_metadata_list(text):
  function _process_if_nonempty (line 83) | def _process_if_nonempty(processor, name, settings):
  function _filter_discardable_metadata (line 91) | def _filter_discardable_metadata(metadata):
  class BaseReader (line 96) | class BaseReader:
    method __init__ (line 114) | def __init__(self, settings):
    method process_metadata (line 117) | def process_metadata(self, name, value):
    method read (line 122) | def read(self, source_path):
    method disabled_message (line 129) | def disabled_message(self) -> str:
  class _FieldBodyTranslator (line 134) | class _FieldBodyTranslator(HTMLTranslator):
    method __init__ (line 135) | def __init__(self, document):
    method astext (line 139) | def astext(self):
    method visit_field_body (line 142) | def visit_field_body(self, node):
    method depart_field_body (line 145) | def depart_field_body(self, node):
  function render_node_to_html (line 149) | def render_node_to_html(document, node, field_body_translator_class):
  class PelicanHTMLWriter (line 155) | class PelicanHTMLWriter(Writer):
    method __init__ (line 156) | def __init__(self):
  class PelicanHTMLTranslator (line 161) | class PelicanHTMLTranslator(HTMLTranslator):
    method visit_abbreviation (line 162) | def visit_abbreviation(self, node):
    method depart_abbreviation (line 168) | def depart_abbreviation(self, node):
    method visit_image (line 172) | def visit_image(self, node):
  class RstReader (line 179) | class RstReader(BaseReader):
    method __init__ (line 200) | def __init__(self, *args, **kwargs):
    method _parse_metadata (line 213) | def _parse_metadata(self, document, source_path):
    method _get_publisher (line 255) | def _get_publisher(self, source_path):
    method read (line 281) | def read(self, source_path):
  class MarkdownReader (line 293) | class MarkdownReader(BaseReader):
    method __init__ (line 299) | def __init__(self, *args, **kwargs):
    method _parse_metadata (line 311) | def _parse_metadata(self, meta):
    method read (line 344) | def read(self, source_path):
    method disabled_message (line 358) | def disabled_message(self) -> str:
  class HTMLReader (line 365) | class HTMLReader(BaseReader):
    class _HTMLParser (line 371) | class _HTMLParser(HTMLParser):
      method __init__ (line 372) | def __init__(self, settings, filename):
      method handle_starttag (line 388) | def handle_starttag(self, tag, attrs):
      method handle_endtag (line 405) | def handle_endtag(self, tag):
      method handle_startendtag (line 420) | def handle_startendtag(self, tag, attrs):
      method handle_comment (line 426) | def handle_comment(self, data):
      method handle_data (line 429) | def handle_data(self, data):
      method handle_entityref (line 432) | def handle_entityref(self, data):
      method handle_charref (line 435) | def handle_charref(self, data):
      method build_tag (line 438) | def build_tag(self, tag, attrs, close_tag):
      method _handle_meta_tag (line 453) | def _handle_meta_tag(self, attrs):
      method _attr_value (line 496) | def _attr_value(cls, attrs, name, default=None):
    method read (line 499) | def read(self, filename):
  class Readers (line 512) | class Readers(FileStampDataCacher):
    method __init__ (line 522) | def __init__(self, settings=None, cache_name=""):
    method extensions (line 566) | def extensions(self):
    method disabled_extensions (line 571) | def disabled_extensions(self):
    method read_file (line 574) | def read_file(
    method check_file (line 699) | def check_file(self, source_path: str) -> None:
  function find_empty_alt (line 706) | def find_empty_alt(content, path):
  function default_metadata (line 742) | def default_metadata(settings=None, process=None):
  function path_metadata (line 762) | def path_metadata(full_path, source_path, settings=None):
  function parse_path_metadata (line 787) | def parse_path_metadata(source_path, settings=None, process=None):

FILE: pelican/rstdirectives.py
  class Pygments (line 12) | class Pygments(Directive):
    method run (line 36) | def run(self):
  class abbreviation (line 77) | class abbreviation(nodes.Inline, nodes.TextElement):
  function abbr_role (line 81) | def abbr_role(typ, rawtext, text, lineno, inliner, options=None, content...

FILE: pelican/server.py
  function parse_arguments (line 21) | def parse_arguments():
  class ComplexHTTPRequestHandler (line 51) | class ComplexHTTPRequestHandler(server.SimpleHTTPRequestHandler):
    method translate_path (line 64) | def translate_path(self, path):
    method do_GET (line 84) | def do_GET(self):
    method get_path_that_exists (line 95) | def get_path_that_exists(self, original_path):
    method guess_type (line 115) | def guess_type(self, path):
    method log_message (line 125) | def log_message(self, msg_format, *args):
  class RootedHTTPServer (line 129) | class RootedHTTPServer(server.HTTPServer):
    method __init__ (line 130) | def __init__(self, base_path, *args, **kwargs):

FILE: pelican/settings.py
  function load_source (line 18) | def load_source(name: str, path: str) -> ModuleType:
  function read_settings (line 187) | def read_settings(
  function get_settings_from_module (line 233) | def get_settings_from_module(module: ModuleType | None = None) -> Settings:
  function get_settings_from_file (line 242) | def get_settings_from_file(path: str) -> Settings:
  function get_jinja_environment (line 250) | def get_jinja_environment(settings: Settings) -> Settings:
  function _printf_s_to_format_field (line 265) | def _printf_s_to_format_field(printf_string: str, format_field: str) -> ...
  function handle_deprecated_settings (line 279) | def handle_deprecated_settings(settings: Settings) -> Settings:
  function configure_settings (line 570) | def configure_settings(settings: Settings) -> Settings:

FILE: pelican/tests/build_test/conftest.py
  function pytest_addoption (line 1) | def pytest_addoption(parser):

FILE: pelican/tests/build_test/test_build_files.py
  function test_wheel_contents (line 16) | def test_wheel_contents(pytestconfig):
  function test_sdist_contents (line 52) | def test_sdist_contents(pytestconfig, expected_file):

FILE: pelican/tests/dummy_plugins/namespace_plugin/pelican/plugins/ns_plugin/__init__.py
  function register (line 4) | def register():

FILE: pelican/tests/dummy_plugins/normal_plugin/normal_plugin/__init__.py
  function register (line 4) | def register():

FILE: pelican/tests/dummy_plugins/normal_plugin/normal_plugin/submodule.py
  function noop (line 1) | def noop():

FILE: pelican/tests/dummy_plugins/normal_plugin/normal_submodule_plugin/subpackage/subpackage.py
  function register (line 1) | def register():

FILE: pelican/tests/dummy_plugins/normal_plugin/normal_submodule_plugin/subplugin.py
  function register (line 1) | def register():

FILE: pelican/tests/support.py
  function temporary_folder (line 26) | def temporary_folder():
  function isplit (line 41) | def isplit(s, sep=None):
  function mute (line 73) | def mute(returns_output=False):
  function get_article (line 114) | def get_article(title, content, **extra_metadata):
  function skipIfNoExecutable (line 122) | def skipIfNoExecutable(executable):
  function module_exists (line 141) | def module_exists(module_name):
  function locale_available (line 152) | def locale_available(locale_):
  function can_symlink (line 164) | def can_symlink():
  function get_settings (line 174) | def get_settings(**kwargs):
  function get_context (line 185) | def get_context(settings=None, **kwargs):
  class LogCountHandler (line 194) | class LogCountHandler(BufferingHandler):
    method __init__ (line 197) | def __init__(self, capacity=1000):
    method count_logs (line 200) | def count_logs(self, msg=None, level=None):
    method count_formatted_logs (line 210) | def count_formatted_logs(self, msg=None, level=None):
  function diff_subproc (line 221) | def diff_subproc(first, second):
  class LoggedTestCase (line 247) | class LoggedTestCase(unittest.TestCase):
    method setUp (line 250) | def setUp(self):
    method tearDown (line 255) | def tearDown(self):
    method assertLogCountEqual (line 259) | def assertLogCountEqual(self, count=None, msg=None, **kwargs):
  class TestCaseWithCLocale (line 268) | class TestCaseWithCLocale(unittest.TestCase):
    method setUp (line 274) | def setUp(self):
    method tearDown (line 278) | def tearDown(self):

FILE: pelican/tests/test_cache.py
  class TestCache (line 13) | class TestCache(unittest.TestCase):
    method setUp (line 14) | def setUp(self):
    method tearDown (line 17) | def tearDown(self):
    method _get_cache_enabled_settings (line 20) | def _get_cache_enabled_settings(self):
    method test_generator_caching (line 27) | def test_generator_caching(self):
    method test_reader_caching (line 94) | def test_reader_caching(self):
    method test_article_object_caching (line 158) | def test_article_object_caching(self):
    method test_article_reader_content_caching (line 197) | def test_article_reader_content_caching(self):
    method test_article_ignore_cache (line 227) | def test_article_ignore_cache(self):
    method test_page_object_caching (line 259) | def test_page_object_caching(self):
    method test_page_reader_content_caching (line 292) | def test_page_reader_content_caching(self):
    method test_page_ignore_cache (line 323) | def test_page_ignore_cache(self):

FILE: pelican/tests/test_cli.py
  class TestParseOverrides (line 6) | class TestParseOverrides(unittest.TestCase):
    method test_flags (line 7) | def test_flags(self):
    method test_parse_multiple_items (line 12) | def test_parse_multiple_items(self):
    method test_parse_valid_json (line 16) | def test_parse_valid_json(self):
    method test_parse_invalid_syntax (line 27) | def test_parse_invalid_syntax(self):
    method test_parse_invalid_json (line 33) | def test_parse_invalid_json(self):
  class TestGetConfigFromArgs (line 48) | class TestGetConfigFromArgs(unittest.TestCase):
    method test_overrides_known_keys (line 49) | def test_overrides_known_keys(self):
    method test_overrides_non_default_type (line 66) | def test_overrides_non_default_type(self):

FILE: pelican/tests/test_contents.py
  class TestBase (line 25) | class TestBase(LoggedTestCase):
    method setUp (line 26) | def setUp(self):
    method tearDown (line 47) | def tearDown(self):
    method _disable_limit_filter (line 51) | def _disable_limit_filter(self):
    method _enable_limit_filter (line 54) | def _enable_limit_filter(self):
    method _copy_page_kwargs (line 57) | def _copy_page_kwargs(self):
  class TestPage (line 68) | class TestPage(TestBase):
    method test_use_args (line 69) | def test_use_args(self):
    method test_mandatory_properties (line 83) | def test_mandatory_properties(self):
    method test_summary_from_metadata (line 95) | def test_summary_from_metadata(self):
    method test_summary_max_length (line 100) | def test_summary_max_length(self):
    method test_summary_paragraph (line 117) | def test_summary_paragraph(self):
    method test_summary_paragraph_max_length (line 129) | def test_summary_paragraph_max_length(self):
    method test_summary_paragraph_long_max_length (line 144) | def test_summary_paragraph_long_max_length(self):
    method test_summary_end_suffix (line 160) | def test_summary_end_suffix(self):
    method test_summary_get_summary_warning (line 175) | def test_summary_get_summary_warning(self):
    method test_slug (line 188) | def test_slug(self):
    method test_defaultlang (line 224) | def test_defaultlang(self):
    method test_save_as (line 238) | def test_save_as(self):
    method test_relative_source_path (line 255) | def test_relative_source_path(self):
    method test_metadata_url_format (line 281) | def test_metadata_url_format(self):
    method test_datetime (line 289) | def test_datetime(self):
    method test_template (line 326) | def test_template(self):
    method test_signal (line 335) | def test_signal(self):
    method test_get_content (line 348) | def test_get_content(self):
    method test_intrasite_link (line 379) | def test_intrasite_link(self):
    method test_intrasite_link_more (line 458) | def test_intrasite_link_more(self):
    method test_intrasite_link_absolute (line 522) | def test_intrasite_link_absolute(self):
    method test_intrasite_link_escape (line 570) | def test_intrasite_link_escape(self):
    method test_intrasite_link_markdown_spaces (line 622) | def test_intrasite_link_markdown_spaces(self):
    method test_intrasite_link_source_and_generated (line 642) | def test_intrasite_link_source_and_generated(self):
    method test_intrasite_link_to_static_content_with_filename (line 669) | def test_intrasite_link_to_static_content_with_filename(self):
    method test_multiple_authors (line 690) | def test_multiple_authors(self):
  class TestArticle (line 705) | class TestArticle(TestBase):
    method test_template (line 706) | def test_template(self):
    method test_slugify_category_author (line 715) | def test_slugify_category_author(self):
    method test_slugify_with_author_substitutions (line 735) | def test_slugify_with_author_substitutions(self):
    method test_slugify_category_with_dots (line 755) | def test_slugify_category_with_dots(self):
    method test_valid_save_as_detects_breakout (line 768) | def test_valid_save_as_detects_breakout(self):
    method test_valid_save_as_detects_breakout_to_root (line 776) | def test_valid_save_as_detects_breakout_to_root(self):
    method test_valid_save_as_passes_valid (line 784) | def test_valid_save_as_passes_valid(self):
  class TestStatic (line 793) | class TestStatic(LoggedTestCase):
    method setUp (line 794) | def setUp(self):
    method tearDown (line 814) | def tearDown(self):
    method test_attach_to_same_dir (line 817) | def test_attach_to_same_dir(self):
    method test_attach_to_parent_dir (line 831) | def test_attach_to_parent_dir(self):
    method test_attach_to_other_dir (line 845) | def test_attach_to_other_dir(self):
    method test_attach_to_ignores_subsequent_calls (line 859) | def test_attach_to_ignores_subsequent_calls(self):
    method test_attach_to_does_nothing_after_save_as_referenced (line 890) | def test_attach_to_does_nothing_after_save_as_referenced(self):
    method test_attach_to_does_nothing_after_url_referenced (line 907) | def test_attach_to_does_nothing_after_url_referenced(self):
    method test_attach_to_does_not_override_an_override (line 924) | def test_attach_to_does_not_override_an_override(self):
    method test_attach_link_syntax (line 948) | def test_attach_link_syntax(self):
    method test_tag_link_syntax (line 968) | def test_tag_link_syntax(self):
    method test_category_link_syntax (line 983) | def test_category_link_syntax(self):
    method test_author_link_syntax (line 998) | def test_author_link_syntax(self):
    method test_index_link_syntax (line 1013) | def test_index_link_syntax(self):
    method test_unknown_link_syntax (line 1035) | def test_unknown_link_syntax(self):
    method test_link_to_unknown_file (line 1056) | def test_link_to_unknown_file(self):
    method test_index_link_syntax_with_spaces (line 1076) | def test_index_link_syntax_with_spaces(self):
    method test_not_save_as_draft (line 1099) | def test_not_save_as_draft(self):

FILE: pelican/tests/test_generators.py
  class TestGenerator (line 27) | class TestGenerator(TestCaseWithCLocale):
    method setUp (line 28) | def setUp(self):
    method test_include_path (line 36) | def test_include_path(self):
    method test_get_files_exclude (line 48) | def test_get_files_exclude(self):
    method test_custom_jinja_environment (line 103) | def test_custom_jinja_environment(self):
    method test_theme_overrides (line 121) | def test_theme_overrides(self):
    method test_simple_prefix (line 154) | def test_simple_prefix(self):
    method test_theme_prefix (line 165) | def test_theme_prefix(self):
    method test_bad_prefix (line 176) | def test_bad_prefix(self):
  class TestArticlesGenerator (line 185) | class TestArticlesGenerator(unittest.TestCase):
    method setUpClass (line 187) | def setUpClass(cls):
    method setUp (line 207) | def setUp(self):
    method tearDown (line 210) | def tearDown(self):
    method distill_articles (line 214) | def distill_articles(articles):
    method test_generate_feeds (line 220) | def test_generate_feeds(self):
    method test_generate_feeds_override_url (line 247) | def test_generate_feeds_override_url(self):
    method test_generate_context (line 264) | def test_generate_context(self):
    method test_articles_draft (line 375) | def test_articles_draft(self):
    method test_articles_hidden (line 381) | def test_articles_hidden(self):
    method test_generate_categories (line 387) | def test_generate_categories(self):
    method test_do_not_use_folder_as_category (line 414) | def test_do_not_use_folder_as_category(self):
    method test_direct_templates_save_as_url_default (line 445) | def test_direct_templates_save_as_url_default(self):
    method test_direct_templates_save_as_url_modified (line 470) | def test_direct_templates_save_as_url_modified(self):
    method test_direct_templates_save_as_false (line 497) | def test_direct_templates_save_as_false(self):
    method test_per_article_template (line 513) | def test_per_article_template(self):
    method test_period_archives_context (line 527) | def test_period_archives_context(self):
    method test_period_in_timeperiod_archive (line 665) | def test_period_in_timeperiod_archive(self):
    method test_nonexistent_template (line 780) | def test_nonexistent_template(self):
    method test_generate_authors (line 793) | def test_generate_authors(self):
    method test_standard_metadata_in_default_metadata (line 817) | def test_standard_metadata_in_default_metadata(self):
    method test_article_order_by (line 869) | def test_article_order_by(self):
  class TestPageGenerator (line 951) | class TestPageGenerator(unittest.TestCase):
    method setUp (line 957) | def setUp(self):
    method tearDown (line 960) | def tearDown(self):
    method distill_pages (line 963) | def distill_pages(self, pages):
    method test_generate_context (line 966) | def test_generate_context(self):
    method test_generate_sorted (line 1020) | def test_generate_sorted(self):
    method test_tag_and_category_links_on_generated_pages (line 1091) | def test_tag_and_category_links_on_generated_pages(self):
    method test_static_and_attach_links_on_generated_pages (line 1116) | def test_static_and_attach_links_on_generated_pages(self):
  class TestTemplatePagesGenerator (line 1140) | class TestTemplatePagesGenerator(TestCaseWithCLocale):
    method setUp (line 1143) | def setUp(self):
    method tearDown (line 1148) | def tearDown(self):
    method test_generate_output (line 1152) | def test_generate_output(self):
  class TestStaticGenerator (line 1185) | class TestStaticGenerator(unittest.TestCase):
    method setUp (line 1186) | def setUp(self):
    method tearDown (line 1205) | def tearDown(self):
    method set_ancient_mtime (line 1209) | def set_ancient_mtime(self, path, timestamp=1):
    method test_theme_static_paths_dirs (line 1212) | def test_theme_static_paths_dirs(self):
    method test_theme_static_paths_files (line 1231) | def test_theme_static_paths_files(self):
    method test_static_excludes (line 1285) | def test_static_excludes(self):
    method test_static_exclude_sources (line 1315) | def test_static_exclude_sources(self):
    method test_static_links (line 1362) | def test_static_links(self):
    method test_copy_one_file (line 1407) | def test_copy_one_file(self):
    method test_file_update_required_when_dest_does_not_exist (line 1415) | def test_file_update_required_when_dest_does_not_exist(self):
    method test_dest_and_source_mtimes_are_equal (line 1424) | def test_dest_and_source_mtimes_are_equal(self):
    method test_source_is_newer (line 1436) | def test_source_is_newer(self):
    method test_skip_file_when_source_is_not_newer (line 1448) | def test_skip_file_when_source_is_not_newer(self):
    method test_dont_link_by_default (line 1461) | def test_dont_link_by_default(self):
    method test_output_file_is_linked_to_source (line 1468) | def test_output_file_is_linked_to_source(self):
    method test_output_file_exists_and_is_newer (line 1476) | def test_output_file_exists_and_is_newer(self):
    method test_can_symlink_when_hardlink_not_possible (line 1488) | def test_can_symlink_when_hardlink_not_possible(self):
    method test_existing_symlink_is_considered_up_to_date (line 1499) | def test_existing_symlink_is_considered_up_to_date(self):
    method test_invalid_symlink_is_overwritten (line 1512) | def test_invalid_symlink_is_overwritten(self):
    method test_delete_existing_file_before_mkdir (line 1531) | def test_delete_existing_file_before_mkdir(self):
  class TestJinja2Environment (line 1542) | class TestJinja2Environment(TestCaseWithCLocale):
    method setUp (line 1543) | def setUp(self):
    method tearDown (line 1547) | def tearDown(self):
    method _test_jinja2_helper (line 1551) | def _test_jinja2_helper(self, additional_settings, content, expected):
    method test_jinja2_filter (line 1584) | def test_jinja2_filter(self):
    method test_jinja2_filter_plugin_enabled (line 1592) | def test_jinja2_filter_plugin_enabled(self):
    method test_jinja2_test (line 1617) | def test_jinja2_test(self):
    method test_jinja2_global (line 1625) | def test_jinja2_global(self):
    method test_jinja2_extension (line 1633) | def test_jinja2_extension(self):

FILE: pelican/tests/test_importer.py
  class TestBloggerXmlImporter (line 54) | class TestBloggerXmlImporter(TestCaseWithCLocale):
    method setUp (line 55) | def setUp(self):
    method test_recognise_kind_and_title (line 59) | def test_recognise_kind_and_title(self):
    method test_recognise_status_with_correct_filename (line 77) | def test_recognise_status_with_correct_filename(self):
  class TestWordpressXmlImporter (line 101) | class TestWordpressXmlImporter(TestCaseWithCLocale):
    method setUp (line 102) | def setUp(self):
    method test_ignore_empty_posts (line 107) | def test_ignore_empty_posts(self):
    method test_recognise_page_kind (line 123) | def test_recognise_page_kind(self):
    method test_dirpage_directive_for_page_kind (line 146) | def test_dirpage_directive_for_page_kind(self):
    method test_dircat (line 153) | def test_dircat(self):
    method test_unless_custom_post_all_items_should_be_pages_or_posts (line 174) | def test_unless_custom_post_all_items_should_be_pages_or_posts(self):
    method test_recognise_custom_post_type (line 195) | def test_recognise_custom_post_type(self):
    method test_custom_posts_put_in_own_dir (line 221) | def test_custom_posts_put_in_own_dir(self):
    method test_custom_posts_put_in_own_dir_and_catagory_sub_dir (line 242) | def test_custom_posts_put_in_own_dir_and_catagory_sub_dir(self):
    method test_wp_custpost_true_dirpage_false (line 267) | def test_wp_custpost_true_dirpage_false(self):
    method test_can_toggle_raw_html_code_parsing (line 290) | def test_can_toggle_raw_html_code_parsing(self):
    method test_decode_html_entities_in_titles (line 314) | def test_decode_html_entities_in_titles(self):
    method test_decode_wp_content_returns_empty (line 327) | def test_decode_wp_content_returns_empty(self):
    method test_decode_wp_content (line 331) | def test_decode_wp_content(self):
    method test_preserve_verbatim_formatting (line 341) | def test_preserve_verbatim_formatting(self):
    method test_code_in_list (line 357) | def test_code_in_list(self):
    method test_dont_use_smart_quotes (line 370) | def test_dont_use_smart_quotes(self):
    method test_convert_caption_to_figure (line 382) | def test_convert_caption_to_figure(self):
  class TestBuildHeader (line 408) | class TestBuildHeader(unittest.TestCase):
    method test_build_header (line 409) | def test_build_header(self):
    method test_build_header_with_fields (line 413) | def test_build_header_with_fields(self):
    method test_build_header_with_east_asian_characters (line 451) | def test_build_header_with_east_asian_characters(self):
    method test_galleries_added_to_header (line 470) | def test_galleries_added_to_header(self):
    method test_galleries_added_to_markdown_header (line 484) | def test_galleries_added_to_markdown_header(self):
  class TestWordpressXMLAttachements (line 501) | class TestWordpressXMLAttachements(TestCaseWithCLocale):
    method setUp (line 502) | def setUp(self):
    method test_recognise_attachments (line 506) | def test_recognise_attachments(self):
    method test_attachments_associated_with_correct_post (line 510) | def test_attachments_associated_with_correct_post(self):
    method test_download_attachments (line 538) | def test_download_attachments(self):
  class TestTumblrImporter (line 552) | class TestTumblrImporter(TestCaseWithCLocale):
    method test_posts (line 554) | def test_posts(self, get):
    method test_video_embed (line 605) | def test_video_embed(self, get):
    method test_broken_video_embed (line 659) | def test_broken_video_embed(self, get):
  class TestMediumImporter (line 715) | class TestMediumImporter(TestCaseWithCLocale):
    method setUp (line 716) | def setUp(self):
    method test_mediumpost2field (line 743) | def test_mediumpost2field(self):
    method test_mediumposts2field (line 749) | def test_mediumposts2field(self):
    method test_strip_content (line 755) | def test_strip_content(self):
    method test_medium_slug (line 767) | def test_medium_slug(self):

FILE: pelican/tests/test_log.py
  class TestLog (line 10) | class TestLog(unittest.TestCase):
    method setUp (line 11) | def setUp(self):
    method tearDown (line 17) | def tearDown(self):
    method _reset_limit_filter (line 21) | def _reset_limit_filter(self):
    method reset_logger (line 28) | def reset_logger(self):
    method test_log_filter (line 35) | def test_log_filter(self):

FILE: pelican/tests/test_paginator.py
  class TestPage (line 15) | class TestPage(unittest.TestCase):
    method setUp (line 16) | def setUp(self):
    method tearDown (line 32) | def tearDown(self):
    method test_save_as_preservation (line 35) | def test_save_as_preservation(self):
    method test_custom_pagination_pattern (line 56) | def test_custom_pagination_pattern(self):
    method test_custom_pagination_pattern_last_page (line 79) | def test_custom_pagination_pattern_last_page(self):

FILE: pelican/tests/test_pelican.py
  function recursiveDiff (line 39) | def recursiveDiff(dcmp):
  class TestPelican (line 51) | class TestPelican(LoggedTestCase):
    method setUp (line 55) | def setUp(self):
    method tearDown (line 63) | def tearDown(self):
    method assertDirsEqual (line 70) | def assertDirsEqual(self, left_path, right_path, msg=None):
    method test_order_of_generators (line 84) | def test_order_of_generators(self):
    method test_basic_generation_works (line 103) | def test_basic_generation_works(self):
    method test_custom_generation_works (line 125) | def test_custom_generation_works(self):
    method test_custom_locale_generation_works (line 145) | def test_custom_locale_generation_works(self):
    method test_theme_static_paths_copy (line 165) | def test_theme_static_paths_copy(self):
    method test_theme_static_paths_copy_single_file (line 191) | def test_theme_static_paths_copy_single_file(self):
    method test_cyclic_intersite_links_no_warnings (line 210) | def test_cyclic_intersite_links_no_warnings(self):
    method test_md_extensions_deprecation (line 237) | def test_md_extensions_deprecation(self):
    method test_parse_errors (line 256) | def test_parse_errors(self):
    method test_module_load (line 273) | def test_module_load(self):
    method test_main_version (line 280) | def test_main_version(self):
    method test_main_help (line 288) | def test_main_help(self):
    method test_main_on_content (line 296) | def test_main_on_content(self):
    method test_main_on_content_markdown_disabled (line 308) | def test_main_on_content_markdown_disabled(self):

FILE: pelican/tests/test_plugins.py
  function tmp_namespace_path (line 16) | def tmp_namespace_path(path):
  class PluginTest (line 36) | class PluginTest(unittest.TestCase):
    method test_namespace_path_modification (line 43) | def test_namespace_path_modification(self):
    method test_get_namespace_plugins (line 72) | def test_get_namespace_plugins(self):
    method test_load_plugins (line 89) | def test_load_plugins(self):
    method test_get_plugin_name (line 174) | def test_get_plugin_name(self):
    method test_plugin_enabled (line 193) | def test_plugin_enabled(self):
    method test_blinker_is_ordered (line 268) | def test_blinker_is_ordered(self):

FILE: pelican/tests/test_readers.py
  function _path (line 12) | def _path(*args):
  class ReaderTest (line 16) | class ReaderTest(unittest.TestCase):
    method read_file (line 17) | def read_file(self, path, **kwargs):
    method assertDictHasSubset (line 23) | def assertDictHasSubset(self, dictionary, subset):
    method test_markdown_disabled (line 35) | def test_markdown_disabled(self):
  class TestAssertDictHasSubset (line 49) | class TestAssertDictHasSubset(ReaderTest):
    method setUp (line 50) | def setUp(self):
    method tearDown (line 53) | def tearDown(self):
    method test_subset (line 56) | def test_subset(self):
    method test_equal (line 59) | def test_equal(self):
    method test_fail_not_set (line 62) | def test_fail_not_set(self):
    method test_fail_wrong_val (line 71) | def test_fail_wrong_val(self):
  class DefaultReaderTest (line 81) | class DefaultReaderTest(ReaderTest):
    method test_readfile_unknown_extension (line 82) | def test_readfile_unknown_extension(self):
    method test_readfile_path_metadata_implicit_dates (line 86) | def test_readfile_path_metadata_implicit_dates(self):
    method test_readfile_path_metadata_explicit_dates (line 96) | def test_readfile_path_metadata_explicit_dates(self):
    method test_readfile_path_metadata_implicit_date_explicit_modified (line 106) | def test_readfile_path_metadata_implicit_date_explicit_modified(self):
    method test_readfile_path_metadata_explicit_date_implicit_modified (line 116) | def test_readfile_path_metadata_explicit_date_implicit_modified(self):
    method test_find_empty_alt (line 126) | def test_find_empty_alt(self):
  class RstReaderTest (line 143) | class RstReaderTest(ReaderTest):
    method test_article_with_metadata (line 144) | def test_article_with_metadata(self):
    method test_article_with_capitalized_metadata (line 162) | def test_article_with_capitalized_metadata(self):
    method test_article_with_filename_metadata (line 180) | def test_article_with_filename_metadata(self):
    method test_article_with_optional_filename_metadata (line 224) | def test_article_with_optional_filename_metadata(self):
    method test_article_metadata_key_lowercase (line 244) | def test_article_metadata_key_lowercase(self):
    method test_article_extra_path_metadata (line 252) | def test_article_extra_path_metadata(self):
    method test_article_extra_path_metadata_dont_overwrite (line 295) | def test_article_extra_path_metadata_dont_overwrite(self):
    method test_article_extra_path_metadata_recurse (line 322) | def test_article_extra_path_metadata_recurse(self):
    method test_typogrify (line 358) | def test_typogrify(self):
    method test_typogrify_summary (line 385) | def test_typogrify_summary(self):
    method test_typogrify_ignore_filters (line 412) | def test_typogrify_ignore_filters(self):
    method test_typogrify_ignore_tags (line 496) | def test_typogrify_ignore_tags(self):
    method test_article_with_multiple_authors (line 558) | def test_article_with_multiple_authors(self):
    method test_article_with_multiple_authors_semicolon (line 564) | def test_article_with_multiple_authors_semicolon(self):
    method test_article_with_multiple_authors_list (line 570) | def test_article_with_multiple_authors_list(self):
    method test_default_date_formats (line 576) | def test_default_date_formats(self):
    method test_parse_error (line 582) | def test_parse_error(self):
    method test_typogrify_dashes_config (line 588) | def test_typogrify_dashes_config(self):
  class MdReaderTest (line 627) | class MdReaderTest(ReaderTest):
    method test_article_with_metadata (line 628) | def test_article_with_metadata(self):
    method test_article_with_footnote (line 655) | def test_article_with_footnote(self):
    method test_article_with_file_extensions (line 699) | def test_article_with_file_extensions(self):
    method test_article_with_markdown_markup_extension (line 740) | def test_article_with_markdown_markup_extension(self):
    method test_article_with_filename_metadata (line 768) | def test_article_with_filename_metadata(self):
    method test_article_with_optional_filename_metadata (line 806) | def test_article_with_optional_filename_metadata(self):
    method test_duplicate_tags_or_authors_are_removed (line 826) | def test_duplicate_tags_or_authors_are_removed(self):
    method test_metadata_not_parsed_for_metadata (line 835) | def test_metadata_not_parsed_for_metadata(self):
    method test_empty_file (line 849) | def test_empty_file(self):
    method test_empty_file_with_bom (line 856) | def test_empty_file_with_bom(self):
    method test_typogrify_dashes_config (line 863) | def test_typogrify_dashes_config(self):
    method test_metadata_has_no_discarded_data (line 900) | def test_metadata_has_no_discarded_data(self):
  class HTMLReaderTest (line 916) | class HTMLReaderTest(ReaderTest):
    method test_article_with_comments (line 917) | def test_article_with_comments(self):
    method test_article_with_keywords (line 928) | def test_article_with_keywords(self):
    method test_article_with_metadata (line 936) | def test_article_with_metadata(self):
    method test_article_with_multiple_similar_metadata_tags (line 950) | def test_article_with_multiple_similar_metadata_tags(self):
    method test_article_with_multiple_authors (line 958) | def test_article_with_multiple_authors(self):
    method test_article_with_metadata_and_contents_attrib (line 964) | def test_article_with_metadata_and_contents_attrib(self):
    method test_article_with_null_attributes (line 977) | def test_article_with_null_attributes(self):
    method test_article_with_attributes_containing_double_quotes (line 988) | def test_article_with_attributes_containing_double_quotes(self):
    method test_article_metadata_key_lowercase (line 1003) | def test_article_metadata_key_lowercase(self):
    method test_article_with_nonconformant_meta_tags (line 1013) | def test_article_with_nonconformant_meta_tags(self):
    method test_article_with_inline_svg (line 1022) | def test_article_with_inline_svg(self):

FILE: pelican/tests/test_rstdirectives.py
  class Test_abbr_role (line 7) | class Test_abbr_role(unittest.TestCase):
    method call_it (line 8) | def call_it(self, text):
    method test (line 17) | def test(self):
    method test_newlines_in_explanation (line 22) | def test_newlines_in_explanation(self):
    method test_newlines_in_abbr (line 27) | def test_newlines_in_abbr(self):

FILE: pelican/tests/test_server.py
  class MockRequest (line 10) | class MockRequest:
    method makefile (line 11) | def makefile(self, *_args, **_kwargs):
  class MockServer (line 15) | class MockServer:
  class TestServer (line 19) | class TestServer(unittest.TestCase):
    method setUp (line 20) | def setUp(self):
    method tearDown (line 26) | def tearDown(self):
    method test_get_path_that_exists (line 30) | def test_get_path_that_exists(self):

FILE: pelican/tests/test_settings.py
  class TestSettingsConfiguration (line 17) | class TestSettingsConfiguration(unittest.TestCase):
    method setUp (line 23) | def setUp(self):
    method tearDown (line 30) | def tearDown(self):
    method test_overwrite_existing_settings (line 33) | def test_overwrite_existing_settings(self):
    method test_keep_default_settings (line 37) | def test_keep_default_settings(self):
    method test_dont_copy_small_keys (line 43) | def test_dont_copy_small_keys(self):
    method test_read_empty_settings (line 47) | def test_read_empty_settings(self):
    method test_settings_return_independent (line 58) | def test_settings_return_independent(self):
    method test_defaults_not_overwritten (line 68) | def test_defaults_not_overwritten(self):
    method test_static_path_settings_safety (line 74) | def test_static_path_settings_safety(self):
    method test_configure_settings (line 91) | def test_configure_settings(self):
    method test_theme_settings_exceptions (line 111) | def test_theme_settings_exceptions(self):
    method test_deprecated_dir_setting (line 123) | def test_deprecated_dir_setting(self):
    method test_default_encoding (line 138) | def test_default_encoding(self):
    method test_invalid_settings_throw_exception (line 152) | def test_invalid_settings_throw_exception(self):
    method test__printf_s_to_format_field (line 170) | def test__printf_s_to_format_field(self):
    method test_deprecated_extra_templates_paths (line 178) | def test_deprecated_extra_templates_paths(self):
    method test_deprecated_paginated_direct_templates (line 187) | def test_deprecated_paginated_direct_templates(self):
    method test_deprecated_paginated_direct_templates_from_file (line 198) | def test_deprecated_paginated_direct_templates_from_file(self):
    method test_theme_and_extra_templates_exception (line 216) | def test_theme_and_extra_templates_exception(self):
    method test_slug_and_slug_regex_substitutions_exception (line 223) | def test_slug_and_slug_regex_substitutions_exception(self):
    method test_deprecated_slug_substitutions (line 230) | def test_deprecated_slug_substitutions(self):
    method test_deprecated_slug_substitutions_from_file (line 313) | def test_deprecated_slug_substitutions_from_file(self):

FILE: pelican/tests/test_testsuite.py
  class TestSuiteTest (line 6) | class TestSuiteTest(unittest.TestCase):
    method test_error_on_warning (line 7) | def test_error_on_warning(self):

FILE: pelican/tests/test_theme.py
  class TestTemplateInheritance (line 14) | class TestTemplateInheritance(LoggedTestCase):
    method setUp (line 15) | def setUp(self):
    method tearDown (line 40) | def tearDown(self):
    method test_simple_theme (line 48) | def test_simple_theme(self):
    method test_theme_inheritance (line 92) | def test_theme_inheritance(self):

FILE: pelican/tests/test_urlwrappers.py
  class TestURLWrapper (line 5) | class TestURLWrapper(unittest.TestCase):
    method test_ordering (line 6) | def test_ordering(self):
    method test_equality (line 31) | def test_equality(self):
    method test_slugify_with_substitutions_and_dots (line 57) | def test_slugify_with_substitutions_and_dots(self):
    method test_author_slug_substitutions (line 78) | def test_author_slug_substitutions(self):

FILE: pelican/tests/test_utils.py
  class ClassDeprAttr (line 28) | class ClassDeprAttr:
    method _old_attribute (line 34) | def _old_attribute():
  class TestUtils (line 38) | class TestUtils(LoggedTestCase):
    method setUp (line 39) | def setUp(self):
    method tearDown (line 43) | def tearDown(self):
    method test_deprecated_attribute (line 47) | def test_deprecated_attribute(self):
    method test_get_date (line 60) | def test_get_date(self):
    method test_slugify (line 166) | def test_slugify(self):
    method test_slugify_use_unicode (line 196) | def test_slugify_use_unicode(self):
    method test_slugify_substitute (line 233) | def test_slugify_substitute(self):
    method test_slugify_substitute_and_keeping_non_alphanum (line 249) | def test_slugify_substitute_and_keeping_non_alphanum(self):
    method test_get_relative_path (line 264) | def test_get_relative_path(self):
    method test_truncate_html_words (line 283) | def test_truncate_html_words(self):
    method test_truncate_html_paragraphs (line 406) | def test_truncate_html_paragraphs(self):
    method test_process_translations (line 423) | def test_process_translations(self):
    method test_clean_output_dir (line 574) | def test_clean_output_dir(self):
    method test_clean_output_dir_not_there (line 584) | def test_clean_output_dir_not_there(self):
    method test_clean_output_dir_is_file (line 590) | def test_clean_output_dir_is_file(self):
    method test_strftime (line 599) | def test_strftime(self):
    method test_strftime_locale_dependent_turkish (line 649) | def test_strftime_locale_dependent_turkish(self):
    method test_strftime_locale_dependent_french (line 679) | def test_strftime_locale_dependent_french(self):
    method test_maybe_pluralize (line 699) | def test_maybe_pluralize(self):
    method test_temporary_locale (line 704) | def test_temporary_locale(self):
  class TestCopy (line 722) | class TestCopy(unittest.TestCase):
    method setUp (line 725) | def setUp(self):
    method tearDown (line 730) | def tearDown(self):
    method _create_file (line 734) | def _create_file(self, *path):
    method _create_dir (line 738) | def _create_dir(self, *path):
    method _exist_file (line 741) | def _exist_file(self, *path):
    method _exist_dir (line 745) | def _exist_dir(self, *path):
    method test_copy_file_same_path (line 749) | def test_copy_file_same_path(self):
    method test_copy_file_different_path (line 756) | def test_copy_file_different_path(self):
    method test_copy_file_create_dirs (line 767) | def test_copy_file_create_dirs(self):
    method test_copy_dir_same_path (line 779) | def test_copy_dir_same_path(self):
    method test_copy_dir_different_path (line 786) | def test_copy_dir_different_path(self):
    method test_copy_dir_create_dirs (line 798) | def test_copy_dir_create_dirs(self):
  class TestDateFormatter (line 813) | class TestDateFormatter(unittest.TestCase):
    method setUp (line 817) | def setUp(self):
    method tearDown (line 830) | def tearDown(self):
    method test_french_strftime (line 840) | def test_french_strftime(self):
    method test_french_locale (line 870) | def test_french_locale(self):
    method test_turkish_locale (line 905) | def test_turkish_locale(self):
  class TestSanitisedJoin (line 937) | class TestSanitisedJoin(unittest.TestCase):
    method test_detect_parent_breakout (line 938) | def test_detect_parent_breakout(self):
    method test_detect_root_breakout (line 945) | def test_detect_root_breakout(self):
    method test_pass_deep_subpaths (line 952) | def test_pass_deep_subpaths(self):
  class TestMemoized (line 959) | class TestMemoized(unittest.TestCase):
    method test_memoized (line 960) | def test_memoized(self):
  class TestStringUtils (line 990) | class TestStringUtils(unittest.TestCase):
    method test_file_suffix (line 991) | def test_file_suffix(self):
  class TestFileChangeFilter (line 997) | class TestFileChangeFilter(unittest.TestCase):
    method test_regular_files_not_filtered (line 1000) | def test_regular_files_not_filtered(self):
    method test_dotfiles_filtered (line 1011) | def test_dotfiles_filtered(self):
    method test_default_filters (line 1023) | def test_default_filters(self):
    method test_custom_ignore_pattern (line 1050) | def test_custom_ignore_pattern(self):

FILE: pelican/tools/pelican_import.py
  function decode_wp_content (line 31) | def decode_wp_content(content, br=True):
  function _import_bs4 (line 121) | def _import_bs4():
  function file_to_soup (line 134) | def file_to_soup(xml, features="xml"):
  function get_filename (line 143) | def get_filename(post_name, post_id):
  function wp2fields (line 150) | def wp2fields(xml, wp_custpost=False):
  function blogger2fields (line 220) | def blogger2fields(xml):
  function dc2fields (line 275) | def dc2fields(file):
  function _get_tumblr_posts (line 423) | def _get_tumblr_posts(api_key, blogname, offset=0):
  function tumblr2fields (line 434) | def tumblr2fields(api_key, blogname):
  function strip_medium_post_content (line 547) | def strip_medium_post_content(soup) -> str:
  function mediumpost2fields (line 596) | def mediumpost2fields(filepath: str) -> tuple:
  function medium_slug (line 651) | def medium_slug(filepath: str) -> str:
  function mediumposts2fields (line 667) | def mediumposts2fields(medium_export_dir: str):
  function feed2fields (line 674) | def feed2fields(file):
  function build_header (line 705) | def build_header(
  function build_asciidoc_header (line 729) | def build_asciidoc_header(
  function build_markdown_header (line 753) | def build_markdown_header(
  function get_ext (line 776) | def get_ext(out_markup, in_markup="html"):
  function get_out_filename (line 786) | def get_out_filename(
  function get_attachments (line 843) | def get_attachments(xml):
  function download_attachments (line 876) | def download_attachments(output_path, urls):
  function is_pandoc_needed (line 911) | def is_pandoc_needed(in_markup):
  function get_pandoc_version (line 915) | def get_pandoc_version():
  function update_links_to_attached_files (line 926) | def update_links_to_attached_files(content, attachments):
  function fields2pelican (line 936) | def fields2pelican(
  function main (line 1106) | def main():

FILE: pelican/tools/pelican_quickstart.py
  class _DEFAULT_PATH_TYPE (line 82) | class _DEFAULT_PATH_TYPE(str):  # noqa: SLOT000
  function ask (line 89) | def ask(question, answer=str, default=None, length=None):
  function ask_timezone (line 161) | def ask_timezone(question, default, tzurl):
  function render_jinja_template (line 175) | def render_jinja_template(tmpl_name: str, tmpl_vars: Mapping, target_pat...
  function main (line 186) | def main():

FILE: pelican/tools/pelican_themes.py
  function err (line 9) | def err(msg, die=None):
  function main (line 33) | def main():
  function themes (line 156) | def themes():
  function list_themes (line 168) | def list_themes(v=False):
  function remove (line 182) | def remove(theme_name, v=False):
  function install (line 208) | def install(path, v=False, u=False):
  function symlink (line 248) | def symlink(path, v=False):
  function is_broken_link (line 269) | def is_broken_link(path):
  function clean (line 275) | def clean(v=False):

FILE: pelican/urlwrappers.py
  class URLWrapper (line 12) | class URLWrapper:
    method __init__ (line 13) | def __init__(self, name, settings):
    method name (line 20) | def name(self):
    method name (line 24) | def name(self, name):
    method slug (line 32) | def slug(self):
    method slug (line 48) | def slug(self, slug):
    method as_dict (line 53) | def as_dict(self):
    method __hash__ (line 59) | def __hash__(self):
    method _normalize_key (line 62) | def _normalize_key(self, key):
    method __eq__ (line 76) | def __eq__(self, other):
    method __ne__ (line 83) | def __ne__(self, other):
    method __lt__ (line 90) | def __lt__(self, other):
    method __str__ (line 97) | def __str__(self):
    method __repr__ (line 100) | def __repr__(self):
    method _from_settings (line 103) | def _from_settings(self, key, get_page_name=False):
  class Category (line 130) | class Category(URLWrapper):
  class Tag (line 134) | class Tag(URLWrapper):
    method __init__ (line 135) | def __init__(self, name, *args, **kwargs):
  class Author (line 139) | class Author(URLWrapper):

FILE: pelican/utils.py
  function sanitised_join (line 51) | def sanitised_join(base_directory: str, *parts: str) -> str:
  function strftime (line 60) | def strftime(date: datetime.datetime, date_format: str) -> str:
  class SafeDatetime (line 111) | class SafeDatetime(datetime.datetime):
    method strftime (line 114) | def strftime(self, fmt, safe=True):
  class DateFormatter (line 122) | class DateFormatter:
    method __init__ (line 129) | def __init__(self) -> None:
    method __call__ (line 136) | def __call__(self, date: datetime.datetime, date_format: str) -> str:
  class memoized (line 148) | class memoized:
    method __init__ (line 156) | def __init__(self, func: Callable) -> None:
    method __call__ (line 160) | def __call__(self, *args) -> Any:
    method __repr__ (line 172) | def __repr__(self) -> str | None:
    method __get__ (line 175) | def __get__(self, obj: Any, objtype):
  function deprecated_attribute (line 182) | def deprecated_attribute(
  function get_date (line 229) | def get_date(string: str) -> datetime.datetime:
  function pelican_open (line 243) | def pelican_open(filename: str, mode: str = "r") -> Generator[str]:
  function slugify (line 252) | def slugify(
  function copy (line 295) | def copy(source: str, destination: str, ignores: Iterable[str] | None = ...
  function copy_file (line 367) | def copy_file(source: str, destination: str) -> None:
  function clean_output_dir (line 377) | def clean_output_dir(path: str, retention: Iterable[str]) -> None:
  function get_relative_path (line 414) | def get_relative_path(path: str) -> str:
  function path_to_url (line 424) | def path_to_url(path: str) -> str:
  function posixize_path (line 431) | def posixize_path(rel_path: str) -> str:
  class _HTMLWordTruncator (line 438) | class _HTMLWordTruncator(HTMLParser):
    class TruncationCompleted (line 459) | class TruncationCompleted(Exception):
      method __init__ (line 460) | def __init__(self, truncate_at: int) -> None:
    method __init__ (line 464) | def __init__(self, max_words: int) -> None:
    method feed (line 473) | def feed(self, *args, **kwargs) -> None:
    method getoffset (line 481) | def getoffset(self) -> int:
    method add_word (line 488) | def add_word(self, word_end: int) -> None:
    method add_last_word (line 494) | def add_last_word(self) -> None:
    method handle_starttag (line 498) | def handle_starttag(self, tag: str, attrs: Any) -> None:
    method handle_endtag (line 504) | def handle_endtag(self, tag: str) -> None:
    method handle_data (line 515) | def handle_data(self, data: str) -> None:
    method _handle_ref (line 533) | def _handle_ref(self, name: str, char: str) -> None:
    method handle_entityref (line 576) | def handle_entityref(self, name: str) -> None:
    method handle_charref (line 589) | def handle_charref(self, name: str) -> None:
  function truncate_html_words (line 607) | def truncate_html_words(s: str, num: int, end_text: str = "…") -> str:
  function truncate_html_paragraphs (line 633) | def truncate_html_paragraphs(s, count):
  function process_translations (line 652) | def process_translations(
  function get_original_items (line 713) | def get_original_items(items: list[Content], with_str: str) -> list[Cont...
  function order_content (line 753) | def order_content(
  class FileChangeFilter (line 815) | class FileChangeFilter(watchfiles.DefaultFilter):
    method __init__ (line 816) | def __init__(self, ignore_file_patterns: Sequence[str], *args, **kwargs):
    method __call__ (line 820) | def __call__(self, change: watchfiles.Change, path: str) -> bool:
  function wait_for_changes (line 832) | def wait_for_changes(
  function set_date_tzinfo (line 869) | def set_date_tzinfo(
  function mkdir_p (line 882) | def mkdir_p(path: str) -> None:
  function split_all (line 886) | def split_all(path: str | pathlib.Path | None) -> Sequence[str] | None:
  function path_to_file_url (line 917) | def path_to_file_url(path: str) -> str:
  function maybe_pluralize (line 922) | def maybe_pluralize(count: int, singular: str, plural: str) -> str:
  function temporary_locale (line 939) | def temporary_locale(
  function file_suffix (line 960) | def file_suffix(path: str) -> str:

FILE: pelican/writers.py
  class Writer (line 21) | class Writer:
    method __init__ (line 22) | def __init__(self, output_path, settings=None):
    method _create_new_feed (line 37) | def _create_new_feed(self, feed_type, feed_title, context):
    method _add_item_to_the_feed (line 51) | def _add_item_to_the_feed(self, feed, item):
    method _open_w (line 102) | def _open_w(self, filename, encoding, override=False):
    method write_feed (line 123) | def write_feed(
    method write_file (line 173) | def write_file(

FILE: tasks.py
  function docbuild (line 25) | def docbuild(c):
  function docserve (line 31) | def docserve(c):
  function tests (line 41) | def tests(c):
  function coverage (line 47) | def coverage(c):
  function formatcode (line 58) | def formatcode(c, check=False, diff=False):
  function ruff (line 71) | def ruff(c, fix=False, diff=False):
  function lint (line 82) | def lint(c, fix=False, diff=False):
  function tools (line 89) | def tools(c):
  function precommit (line 97) | def precommit(c):
  function setup (line 103) | def setup(c):
  function update_functional_tests (line 111) | def update_functional_tests(c):
Condensed preview — 442 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (2,885K chars).
[
  {
    "path": ".coveragerc",
    "chars": 65,
    "preview": "[report]\nomit =\n       pelican/tests/*\n       pelican/signals.py\n"
  },
  {
    "path": ".editorconfig",
    "chars": 208,
    "preview": "root = true\n\n[*]\ncharset = utf-8\nend_of_line = lf\nindent_size = 4\nindent_style = space\ninsert_final_newline = true\ntrim_"
  },
  {
    "path": ".git-blame-ignore-revs",
    "chars": 914,
    "preview": "# .git-blame-ignore-revs\n# Apply code style to project via: ruff format .\ncabdb26cee66e1173cf16cb31d3fe5f9fa4392e7\n# Upg"
  },
  {
    "path": ".gitattributes",
    "chars": 450,
    "preview": "# Auto detect text files and perform LF normalization\n* text=auto\n\n# Improve accuracy of GitHub's Linguist-powered langu"
  },
  {
    "path": ".github/CODEOWNERS",
    "chars": 42,
    "preview": ".github/workflows/github_pages.yml @seanh\n"
  },
  {
    "path": ".github/FUNDING.yml",
    "chars": 82,
    "preview": "---\n\ngithub: justinmayer\ncustom: https://donate.getpelican.com\nliberapay: pelican\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/---bug-report.md",
    "chars": 2094,
    "preview": "---\nname: \"\\U0001F41E Bug Report\"\nabout: Did you find a bug?\ntitle: ''\nlabels: bug\nassignees: ''\n\n---\n\n<!--\n  Hi there! "
  },
  {
    "path": ".github/ISSUE_TEMPLATE/---documentation.md",
    "chars": 766,
    "preview": "---\nname: \"\\U0001F4DA Documentation\"\nabout: Did you find errors, problems, or anything unclear in the docs (https://docs"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/---enhancement-request.md",
    "chars": 960,
    "preview": "---\nname: \"\\U0001F381 Feature Request\"\nabout: Do you have ideas for new features and improvements?\ntitle: ''\nlabels: enh"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "chars": 540,
    "preview": "---\n# Ref: https://help.github.com/en/github/building-a-strong-community/configuring-issue-templates-for-your-repository"
  },
  {
    "path": ".github/dependabot.yml",
    "chars": 286,
    "preview": "# See https://docs.github.com/en/free-pro-team@latest/\n#  github/administering-a-repository/enabling-and-disabling-versi"
  },
  {
    "path": ".github/pull_request_template.md",
    "chars": 848,
    "preview": "# Pull Request Checklist\n\nResolves: #issue-number-here <!-- Only if related issue *already* exists — otherwise remove th"
  },
  {
    "path": ".github/stale.yml",
    "chars": 1013,
    "preview": "# Configuration for probot-stale - https://github.com/probot/stale\n\n# Number of days of inactivity before an Issue or Pu"
  },
  {
    "path": ".github/workflows/github_pages.yml",
    "chars": 5243,
    "preview": "# Workflow for building the site and (optionally) publishing it to GitHub Pages.\nname: Deploy to GitHub Pages\non:\n  work"
  },
  {
    "path": ".github/workflows/main.yml",
    "chars": 3867,
    "preview": "name: build\n\non: [push, pull_request]\n\nenv:\n  # color output for pytest and tox\n  PYTEST_ADDOPTS: \"--color=yes\"\n  PY_COL"
  },
  {
    "path": ".gitignore",
    "chars": 234,
    "preview": "*.egg-info\n.*.swp\n.*.swo\n*.pyc\n.DS_Store\ndocs/_build\ndocs/*/_build\nbuild\ndist\ntags\n.tox\n.coverage\nhtmlcov\n*.orig\nvenv\nsa"
  },
  {
    "path": ".mailmap",
    "chars": 1201,
    "preview": "Alexis Métaireau <alexis@notmyidea.org>\nAlexis Métaireau <alexis@notmyidea.org> <alexis, notmyidea, org>\nAlexis Métairea"
  },
  {
    "path": ".pre-commit-config.yaml",
    "chars": 772,
    "preview": "---\n# See https://pre-commit.com/hooks.html for info on hooks\nrepos:\n  - repo: https://github.com/pre-commit/pre-commit-"
  },
  {
    "path": ".readthedocs.yaml",
    "chars": 566,
    "preview": "---\n# Read the Docs configuration file\n# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details\n\n# Re"
  },
  {
    "path": ".vale.ini",
    "chars": 142,
    "preview": "StylesPath = .vale/styles\n\nVocab = Pelican\n\nMinAlertLevel = suggestion\n\nPackages = proselint, alex\n\n[*]\nBasedOnStyles = "
  },
  {
    "path": "CONTRIBUTING.rst",
    "chars": 7371,
    "preview": "Filing issues\n=============\n\n* Before you submit a new issue, try `asking for help`_ first.\n* If determined to create a "
  },
  {
    "path": "LICENSE",
    "chars": 34527,
    "preview": "                    GNU AFFERO GENERAL PUBLIC LICENSE\n                       Version 3, 19 November 2007\n\n Copyright (C)"
  },
  {
    "path": "README.rst",
    "chars": 3141,
    "preview": "Pelican |build-status| |pypi-version| |downloads| |repology|\n==========================================================="
  },
  {
    "path": "THANKS",
    "chars": 2937,
    "preview": "Pelican is a project led by Justin Mayer <https://justinmayer.com/>\nand originally created by Alexis Métaireau <https://"
  },
  {
    "path": "docs/Makefile",
    "chars": 4598,
    "preview": "# Makefile for Sphinx documentation\n#\n\n# You can set these variables from the command line.\nSPHINXOPTS    =\nSPHINXBUILD "
  },
  {
    "path": "docs/_static/theme_overrides.css",
    "chars": 335,
    "preview": "\n/* override table width restrictions */\n.wy-table-responsive table td, .wy-table-responsive table th {\n    /* !importan"
  },
  {
    "path": "docs/_templates/page.html",
    "chars": 12619,
    "preview": "{% extends \"base.html\" %}\n\n{% block body -%}\n  {{ super() }}\n  {% include \"partials/icons.html\" %}\n\n  <input type=\"check"
  },
  {
    "path": "docs/changelog.rst",
    "chars": 25670,
    "preview": "Release history\n###############\n\n4.11.0 - 2025-01-15\n===================\n\n- Add setting to selectively omit Typogrify fi"
  },
  {
    "path": "docs/conf.py",
    "chars": 2738,
    "preview": "import datetime\nimport os\nimport sys\nimport time\n\nif sys.version_info >= (3, 11):\n    import tomllib\nelse:\n    import to"
  },
  {
    "path": "docs/content.rst",
    "chars": 26290,
    "preview": "Writing content\n###############\n\nArticles and pages\n==================\n\nPelican considers \"articles\" to be chronological"
  },
  {
    "path": "docs/contribute.rst",
    "chars": 11113,
    "preview": "Contributing and feedback guidelines\n####################################\n\nThere are many ways to contribute to Pelican."
  },
  {
    "path": "docs/faq.rst",
    "chars": 13117,
    "preview": "Frequently Asked Questions (FAQ)\n################################\n\nHere are some frequently asked questions about Pelica"
  },
  {
    "path": "docs/importer.rst",
    "chars": 5845,
    "preview": ".. _import:\n\nImporting an existing site\n##########################\n\nDescription\n===========\n\n``pelican-import`` is a com"
  },
  {
    "path": "docs/index.rst",
    "chars": 2065,
    "preview": "Pelican |release|\n=================\n\nPelican is a static site generator, written in Python_. Highlights include:\n\n* Writ"
  },
  {
    "path": "docs/install.rst",
    "chars": 4533,
    "preview": "Installing Pelican\n##################\n\nPelican currently runs best on |min_python|; earlier versions of Python are not s"
  },
  {
    "path": "docs/internals.rst",
    "chars": 4295,
    "preview": "Pelican internals\n#################\n\nThis section describe how Pelican works internally. As you'll see, it's quite\nsimpl"
  },
  {
    "path": "docs/locale/zh_CN/LC_MESSAGES/changelog.po",
    "chars": 55606,
    "preview": "# SOME DESCRIPTIVE TITLE.\n# Copyright (C) 2010–2024\n# This file is distributed under the same license as the PELICAN pac"
  },
  {
    "path": "docs/locale/zh_CN/LC_MESSAGES/content.po",
    "chars": 43312,
    "preview": "# SOME DESCRIPTIVE TITLE.\n# Copyright (C) 2010–2024\n# This file is distributed under the same license as the PELICAN pac"
  },
  {
    "path": "docs/locale/zh_CN/LC_MESSAGES/contribute.po",
    "chars": 28013,
    "preview": "# SOME DESCRIPTIVE TITLE.\n# Copyright (C) 2010–2024\n# This file is distributed under the same license as the PELICAN pac"
  },
  {
    "path": "docs/locale/zh_CN/LC_MESSAGES/faq.po",
    "chars": 21008,
    "preview": "# SOME DESCRIPTIVE TITLE.\n# Copyright (C) 2010–2024\n# This file is distributed under the same license as the PELICAN pac"
  },
  {
    "path": "docs/locale/zh_CN/LC_MESSAGES/importer.po",
    "chars": 10882,
    "preview": "# SOME DESCRIPTIVE TITLE.\n# Copyright (C) 2010–2024\n# This file is distributed under the same license as the PELICAN pac"
  },
  {
    "path": "docs/locale/zh_CN/LC_MESSAGES/index.po",
    "chars": 4380,
    "preview": "# SOME DESCRIPTIVE TITLE.\n# Copyright (C) 2010–2024\n# This file is distributed under the same license as the PELICAN pac"
  },
  {
    "path": "docs/locale/zh_CN/LC_MESSAGES/install.po",
    "chars": 8508,
    "preview": "# SOME DESCRIPTIVE TITLE.\n# Copyright (C) 2010–2024\n# This file is distributed under the same license as the PELICAN pac"
  },
  {
    "path": "docs/locale/zh_CN/LC_MESSAGES/internals.po",
    "chars": 6949,
    "preview": "# SOME DESCRIPTIVE TITLE.\n# Copyright (C) 2010–2024\n# This file is distributed under the same license as the PELICAN pac"
  },
  {
    "path": "docs/locale/zh_CN/LC_MESSAGES/pelican-themes.po",
    "chars": 7183,
    "preview": "# SOME DESCRIPTIVE TITLE.\n# Copyright (C) 2010–2024\n# This file is distributed under the same license as the PELICAN pac"
  },
  {
    "path": "docs/locale/zh_CN/LC_MESSAGES/plugins.po",
    "chars": 25252,
    "preview": "# SOME DESCRIPTIVE TITLE.\n# Copyright (C) 2010–2024\n# This file is distributed under the same license as the PELICAN pac"
  },
  {
    "path": "docs/locale/zh_CN/LC_MESSAGES/publish.po",
    "chars": 12919,
    "preview": "# SOME DESCRIPTIVE TITLE.\n# Copyright (C) 2010–2024\n# This file is distributed under the same license as the PELICAN pac"
  },
  {
    "path": "docs/locale/zh_CN/LC_MESSAGES/quickstart.po",
    "chars": 5162,
    "preview": "# SOME DESCRIPTIVE TITLE.\n# Copyright (C) 2010–2024\n# This file is distributed under the same license as the PELICAN pac"
  },
  {
    "path": "docs/locale/zh_CN/LC_MESSAGES/report.po",
    "chars": 10115,
    "preview": "# SOME DESCRIPTIVE TITLE.\n# Copyright (C) 2010–2024\n# This file is distributed under the same license as the PELICAN pac"
  },
  {
    "path": "docs/locale/zh_CN/LC_MESSAGES/settings.po",
    "chars": 87007,
    "preview": "# SOME DESCRIPTIVE TITLE.\n# Copyright (C) 2010–2024\n# This file is distributed under the same license as the PELICAN pac"
  },
  {
    "path": "docs/locale/zh_CN/LC_MESSAGES/sphinx.po",
    "chars": 1920,
    "preview": "# SOME DESCRIPTIVE TITLE.\n# Copyright (C) 2010–2024\n# This file is distributed under the same license as the PELICAN pac"
  },
  {
    "path": "docs/locale/zh_CN/LC_MESSAGES/themes.po",
    "chars": 45660,
    "preview": "# SOME DESCRIPTIVE TITLE.\n# Copyright (C) 2010–2024\n# This file is distributed under the same license as the PELICAN pac"
  },
  {
    "path": "docs/locale/zh_CN/LC_MESSAGES/tips.po",
    "chars": 29221,
    "preview": "# SOME DESCRIPTIVE TITLE.\n# Copyright (C) 2010–2024\n# This file is distributed under the same license as the PELICAN pac"
  },
  {
    "path": "docs/pelican-themes.rst",
    "chars": 5111,
    "preview": "pelican-themes\n##############\n\n\n\nDescription\n===========\n\n``pelican-themes`` is a command line tool for managing themes "
  },
  {
    "path": "docs/plugins.rst",
    "chars": 16217,
    "preview": ".. _plugins:\n\nPlugins\n#######\n\nBeginning with version 3.0, Pelican supports plugins. Plugins are a way to add\nfeatures t"
  },
  {
    "path": "docs/publish.rst",
    "chars": 7411,
    "preview": "Publish your site\n#################\n\n.. _site_generation:\n\nSite generation\n===============\n\nOnce Pelican is installed an"
  },
  {
    "path": "docs/quickstart.rst",
    "chars": 2508,
    "preview": "Quickstart\n##########\n\nReading through all the documentation is highly recommended, but for the truly\nimpatient, followi"
  },
  {
    "path": "docs/report.rst",
    "chars": 5247,
    "preview": "Some history about Pelican\n##########################\n\n.. warning::\n\n    This page comes from a report the original auth"
  },
  {
    "path": "docs/settings.rst",
    "chars": 52884,
    "preview": "Settings\n########\n\nPelican is configurable thanks to a settings file you can pass to the command\nline::\n\n    pelican con"
  },
  {
    "path": "docs/themes.rst",
    "chars": 27360,
    "preview": ".. _theming-pelican:\n\nThemes\n######\n\nThere is a community-managed repository of `Pelican Themes`_ for people to share\nan"
  },
  {
    "path": "docs/tips.rst",
    "chars": 19361,
    "preview": "Tips\n####\n\nHere are some tips about Pelican that you might find useful.\n\nCustom 404 Pages\n================\n\nWhen a brows"
  },
  {
    "path": "pelican/__init__.py",
    "chars": 22202,
    "preview": "import argparse\nimport importlib.metadata\nimport json\nimport logging\nimport multiprocessing\nimport os\nimport pprint\nimpo"
  },
  {
    "path": "pelican/__main__.py",
    "chars": 125,
    "preview": "\"\"\"\npython -m pelican module entry point to run via python -m\n\"\"\"\n\nfrom . import main\n\nif __name__ == \"__main__\":\n    ma"
  },
  {
    "path": "pelican/cache.py",
    "chars": 4947,
    "preview": "import gzip\nimport hashlib\nimport logging\nimport os\nimport pickle\n\nfrom pelican.utils import mkdir_p\n\nlogger = logging.g"
  },
  {
    "path": "pelican/contents.py",
    "chars": 25191,
    "preview": "import copy\nimport datetime\nimport locale\nimport logging\nimport os\nimport re\nfrom html import unescape\nfrom typing impor"
  },
  {
    "path": "pelican/generators.py",
    "chars": 42518,
    "preview": "import calendar\nimport errno\nimport fnmatch\nimport logging\nimport os\nfrom collections import defaultdict\nfrom functools "
  },
  {
    "path": "pelican/log.py",
    "chars": 5131,
    "preview": "import logging\nimport warnings\nfrom collections import defaultdict\n\nfrom rich.console import Console\nfrom rich.logging i"
  },
  {
    "path": "pelican/paginator.py",
    "chars": 5551,
    "preview": "import functools\nimport logging\nimport os\nfrom collections import namedtuple\nfrom math import ceil\n\nlogger = logging.get"
  },
  {
    "path": "pelican/plugins/_utils.py",
    "chars": 4466,
    "preview": "import importlib\nimport importlib.machinery\nimport importlib.util\nimport inspect\nimport logging\nimport pkgutil\nimport sy"
  },
  {
    "path": "pelican/plugins/signals.py",
    "chars": 1839,
    "preview": "from blinker import Signal, signal\nfrom ordered_set import OrderedSet\n\n# Signals will call functions in the order of con"
  },
  {
    "path": "pelican/readers.py",
    "chars": 29583,
    "preview": "import datetime\nimport logging\nimport os\nimport re\nfrom collections import OrderedDict\nfrom html import escape\nfrom html"
  },
  {
    "path": "pelican/rstdirectives.py",
    "chars": 3018,
    "preview": "import re\n\nfrom docutils import nodes, utils\nfrom docutils.parsers.rst import Directive, directives, roles\nfrom pygments"
  },
  {
    "path": "pelican/server.py",
    "chars": 5576,
    "preview": "import argparse\nimport logging\nimport os\nimport posixpath\nimport ssl\nimport sys\nimport urllib\nfrom http import server\n\nt"
  },
  {
    "path": "pelican/settings.py",
    "chars": 25970,
    "preview": "import copy\nimport importlib.util\nimport inspect\nimport locale\nimport logging\nimport os\nimport re\nimport sys\nfrom os.pat"
  },
  {
    "path": "pelican/signals.py",
    "chars": 161,
    "preview": "raise ImportError(\n    \"Importing from `pelican.signals` is deprecated. \"\n    \"Use `from pelican import signals` or `imp"
  },
  {
    "path": "pelican/tests/TestPages/bad_page.rst",
    "chars": 177,
    "preview": "This is a test bad page\n#######################\n\n:status: invalid\n\nThe quick brown fox jumped over the lazy dog's back.\n"
  },
  {
    "path": "pelican/tests/TestPages/draft_page.rst",
    "chars": 115,
    "preview": "This is a test draft page\n##########################\n\n:status: draft\n\nThe quick brown fox .\n\nThis page is a draft.\n"
  },
  {
    "path": "pelican/tests/TestPages/draft_page_markdown.md",
    "chars": 199,
    "preview": "title: This is a markdown test draft page\nstatus: draft\n\nTest Markdown File Header\n=========================\n\nUsed for p"
  },
  {
    "path": "pelican/tests/TestPages/draft_page_with_template.rst",
    "chars": 238,
    "preview": "This is a test draft page with a custom template\n#################################################\n\n:status: draft\n:temp"
  },
  {
    "path": "pelican/tests/TestPages/hidden_page.rst",
    "chars": 146,
    "preview": "This is a test hidden page\n##########################\n\n:status: hidden\n\nThe quick brown fox jumped over the lazy dog's b"
  },
  {
    "path": "pelican/tests/TestPages/hidden_page_markdown.md",
    "chars": 231,
    "preview": "title: This is a markdown test hidden page\nstatus: hidden\n\nTest Markdown File Header\n=========================\n\nUsed for"
  },
  {
    "path": "pelican/tests/TestPages/hidden_page_with_template.rst",
    "chars": 270,
    "preview": "This is a test hidden page with a custom template\n#################################################\n\n:status: hidden\n:te"
  },
  {
    "path": "pelican/tests/TestPages/page.rst",
    "chars": 94,
    "preview": "This is a test page\n###################\n\nThe quick brown fox jumped over the lazy dog's back.\n"
  },
  {
    "path": "pelican/tests/TestPages/page_markdown.md",
    "chars": 188,
    "preview": "title: This is a markdown test page\n\nTest Markdown File Header\n=========================\n\nUsed for pelican test\n--------"
  },
  {
    "path": "pelican/tests/TestPages/page_used_for_sorting_test.rst",
    "chars": 134,
    "preview": "A Page (Test) for sorting\n#########################\n\n:slug: zzzz\n\nWhen using title, should be first. When using slug, sh"
  },
  {
    "path": "pelican/tests/TestPages/page_with_category_and_tag_links.md",
    "chars": 91,
    "preview": "Title: Page with a bunch of links\n\nMy links:\n\n[Link 1]({tag}マック)\n\n[Link 2]({category}Yeah)\n"
  },
  {
    "path": "pelican/tests/TestPages/page_with_static_links.md",
    "chars": 101,
    "preview": "Title: Page with static links\n\nMy links:\n\n[Link 0]({static}image0.jpg)\n\n[Link 1]({attach}image1.jpg)\n"
  },
  {
    "path": "pelican/tests/TestPages/page_with_template.rst",
    "chars": 222,
    "preview": "This is a test page with a preset template\n##########################################\n\n:template: custom\n\nThe quick brow"
  },
  {
    "path": "pelican/tests/__init__.py",
    "chars": 461,
    "preview": "import logging\nimport warnings\n\nfrom pelican.log import log_warnings\n\n# redirect warnings module to use logging instead\n"
  },
  {
    "path": "pelican/tests/build_test/conftest.py",
    "chars": 168,
    "preview": "def pytest_addoption(parser):\n    parser.addoption(\n        \"--check-build\",\n        action=\"store\",\n        default=Fal"
  },
  {
    "path": "pelican/tests/build_test/test_build_files.py",
    "chars": 2201,
    "preview": "import importlib.metadata\nimport tarfile\nfrom pathlib import Path\nfrom re import match\nfrom zipfile import ZipFile\n\nimpo"
  },
  {
    "path": "pelican/tests/content/2012-11-29_rst_w_filename_meta#foo-bar.rst",
    "chars": 98,
    "preview": "\nRst with filename metadata\n##########################\n\n:category: yeah\n:author: Alexis Métaireau\n"
  },
  {
    "path": "pelican/tests/content/2012-11-30_md_w_filename_meta#foo-bar.md",
    "chars": 105,
    "preview": "category: yeah\nauthor: Alexis Métaireau\n\nMarkdown with filename metadata\n===============================\n"
  },
  {
    "path": "pelican/tests/content/TestCategory/article_with_category.rst",
    "chars": 149,
    "preview": "This is an article with category !\n##################################\n\n:category: yeah\n:date: 1970-01-01\n\nThis article s"
  },
  {
    "path": "pelican/tests/content/TestCategory/article_without_category.rst",
    "chars": 128,
    "preview": "This is an article without category !\n#####################################\n\nThis article should be in 'TestCategory' ca"
  },
  {
    "path": "pelican/tests/content/article.rst",
    "chars": 149,
    "preview": "Article title\n#############\n\nTHIS is some content. With some stuff to \"typogrify\"...\n\nNow with added support for :abbr:`"
  },
  {
    "path": "pelican/tests/content/article_draft.md",
    "chars": 75,
    "preview": "Title: Draft article\nDate: 2012-10-31\nStatus: draft\n\nThis is some content.\n"
  },
  {
    "path": "pelican/tests/content/article_hidden.md",
    "chars": 86,
    "preview": "Title: Hidden article\nDate: 2012-10-31\nStatus: hidden\n\nThis is some unlisted content.\n"
  },
  {
    "path": "pelican/tests/content/article_skip.md",
    "chars": 89,
    "preview": "Title: Skipped article\nDate: 2024-06-30\nStatus: skip\n\nThis content will not be rendered.\n"
  },
  {
    "path": "pelican/tests/content/article_with_attributes_containing_double_quotes.html",
    "chars": 409,
    "preview": "<html>\n    <head>\n    </head>\n    <body>\n        Ensure that if an attribute value contains a double quote, it is\n      "
  },
  {
    "path": "pelican/tests/content/article_with_capitalized_metadata.rst",
    "chars": 456,
    "preview": "\nThis is a super article !\n#########################\n\n:TAGS: foo, bar, foobar\n:DATE: 2010-12-02 10:14\n:MODIFIED: 2010-12"
  },
  {
    "path": "pelican/tests/content/article_with_code_block.rst",
    "chars": 206,
    "preview": "An Article With Code Block To Test Typogrify Ignore\n###################################################\n\nAn article with"
  },
  {
    "path": "pelican/tests/content/article_with_comments.html",
    "chars": 156,
    "preview": "<html>\n    <head>\n    </head>\n    <body>\n        Body content\n        <!--  This comment is included (including extra wh"
  },
  {
    "path": "pelican/tests/content/article_with_duplicate_tags_authors.md",
    "chars": 366,
    "preview": "Title: Test metadata duplicates\nCategory: test\nTags: foo, bar, foobar, foo, bar\nAuthors: Author, First; Author, Second; "
  },
  {
    "path": "pelican/tests/content/article_with_inline_svg.html",
    "chars": 1054,
    "preview": "<html>\n    <head>\n        <title>Article with an inline SVG</title>\n    </head>\n    <body>\n        Ensure that the title"
  },
  {
    "path": "pelican/tests/content/article_with_keywords.html",
    "chars": 147,
    "preview": "<html>\n    <head>\n        <title>This is a super article !</title>\n        <meta name=\"keywords\" content=\"foo, bar, foob"
  },
  {
    "path": "pelican/tests/content/article_with_markdown_and_empty_tags.md",
    "chars": 73,
    "preview": "Title: Article with markdown and empty tags\nTags:\n\nThis is some content.\n"
  },
  {
    "path": "pelican/tests/content/article_with_markdown_and_footnote.md",
    "chars": 568,
    "preview": "Title: Article with markdown containing footnotes\nDate: 2012-10-31\nModified: 2012-11-01\nSummary: Summary with **inline**"
  },
  {
    "path": "pelican/tests/content/article_with_markdown_and_nested_metadata.md",
    "chars": 152,
    "preview": "Title: Article with markdown and nested summary metadata\nDate: 2012-10-30\nSummary: Test: This metadata value looks like "
  },
  {
    "path": "pelican/tests/content/article_with_markdown_and_nonascii_summary.md",
    "chars": 380,
    "preview": "Title: マックOS X 10.8でパイソンとVirtualenvをインストールと設定\nSlug: python-virtualenv-on-mac-osx-mountain-lion-10.8\nDate: 2012-12-20\nMod"
  },
  {
    "path": "pelican/tests/content/article_with_markdown_and_summary_metadata_multi.md",
    "chars": 316,
    "preview": "Title: Article with markdown and summary metadata multi\nDate: 2012-10-31\nSummary:\n    A multi-line summary should be sup"
  },
  {
    "path": "pelican/tests/content/article_with_markdown_and_summary_metadata_single.md",
    "chars": 178,
    "preview": "Title: Article with markdown and summary metadata single\nDate: 2012-10-30\nSummary: A single-line summary should be suppo"
  },
  {
    "path": "pelican/tests/content/article_with_markdown_extension.markdown",
    "chars": 206,
    "preview": "title: Test markdown File\ncategory: test\n\nTest Markdown File Header\n=========================\n\nUsed for pelican test\n---"
  },
  {
    "path": "pelican/tests/content/article_with_markdown_markup_extensions.md",
    "chars": 62,
    "preview": "Title: Test Markdown extensions\n\n[TOC]\n\n## Level1\n\n### Level2\n"
  },
  {
    "path": "pelican/tests/content/article_with_md_extension.md",
    "chars": 290,
    "preview": "Title: Test md File\nCategory: test\nTags: foo, bar, foobar\nDate: 2010-12-02 10:14\nModified: 2010-12-02 10:20\nSummary: I h"
  },
  {
    "path": "pelican/tests/content/article_with_mdown_extension.mdown",
    "chars": 200,
    "preview": "title: Test mdown File\ncategory: test\n\nTest Markdown File Header\n=========================\n\nUsed for pelican test\n------"
  },
  {
    "path": "pelican/tests/content/article_with_metadata.html",
    "chars": 555,
    "preview": "<html>\n    <head>\n        <title>This is a super article !</title>\n        <meta name=\"tags\" content=\"foo, bar, foobar\" "
  },
  {
    "path": "pelican/tests/content/article_with_metadata.rst",
    "chars": 456,
    "preview": "\nThis is a super article !\n#########################\n\n:tags: foo, bar, foobar\n:date: 2010-12-02 10:14\n:modified: 2010-12"
  },
  {
    "path": "pelican/tests/content/article_with_metadata.unknownextension",
    "chars": 268,
    "preview": "\nThis is a super article !\n#########################\n\n:tags: foo, bar, foobar\n:date: 2010-12-02 10:14\n:category: yeah\n:a"
  },
  {
    "path": "pelican/tests/content/article_with_metadata_and_contents.html",
    "chars": 561,
    "preview": "<html>\n    <head>\n        <title>This is a super article !</title>\n        <meta name=\"tags\" contents=\"foo, bar, foobar\""
  },
  {
    "path": "pelican/tests/content/article_with_metadata_explicit_date_implicit_modified.html",
    "chars": 555,
    "preview": "<html>\n    <head>\n        <title>This is a super article !</title>\n        <meta name=\"tags\" content=\"foo, bar, foobar\" "
  },
  {
    "path": "pelican/tests/content/article_with_metadata_explicit_dates.html",
    "chars": 615,
    "preview": "<html>\n    <head>\n        <title>This is a super article !</title>\n        <meta name=\"tags\" content=\"foo, bar, foobar\" "
  },
  {
    "path": "pelican/tests/content/article_with_metadata_implicit_date_explicit_modified.html",
    "chars": 559,
    "preview": "<html>\n    <head>\n        <title>This is a super article !</title>\n        <meta name=\"tags\" content=\"foo, bar, foobar\" "
  },
  {
    "path": "pelican/tests/content/article_with_metadata_implicit_dates.html",
    "chars": 499,
    "preview": "<html>\n    <head>\n        <title>This is a super article !</title>\n        <meta name=\"tags\" content=\"foo, bar, foobar\" "
  },
  {
    "path": "pelican/tests/content/article_with_mkd_extension.mkd",
    "chars": 196,
    "preview": "title: Test mkd File\ncategory: test\n\nTest Markdown File Header\n=========================\n\nUsed for pelican test\n--------"
  },
  {
    "path": "pelican/tests/content/article_with_multiple_authors.html",
    "chars": 173,
    "preview": "<html>\n    <head>\n        <title>This is an article with multiple authors!</title>\n        <meta name=\"authors\" content="
  },
  {
    "path": "pelican/tests/content/article_with_multiple_authors.rst",
    "chars": 175,
    "preview": "This is an article with multiple authors!\n#########################################\n\n:date: 2014-02-09 02:20\n:modified: "
  },
  {
    "path": "pelican/tests/content/article_with_multiple_authors_list.rst",
    "chars": 319,
    "preview": "This is an article with multiple authors in list format!\n########################################################\n\n:date"
  },
  {
    "path": "pelican/tests/content/article_with_multiple_authors_semicolon.rst",
    "chars": 237,
    "preview": "This is an article with multiple authors in lastname, firstname format!\n################################################"
  },
  {
    "path": "pelican/tests/content/article_with_multiple_metadata_tags.html",
    "chars": 347,
    "preview": "<html>\n    <head>\n        <title>Metadata tags as list!</title>\n        <meta name=\"custom_field\" content=\"https://getpe"
  },
  {
    "path": "pelican/tests/content/article_with_nonconformant_meta_tags.html",
    "chars": 463,
    "preview": "<html>\n    <head>\n        <meta charset=\"utf-8\" />\n        <meta name=\"viewport\" content=\"width=device-width, initial-sc"
  },
  {
    "path": "pelican/tests/content/article_with_null_attributes.html",
    "chars": 167,
    "preview": "<html>\n    <head>\n    </head>\n    <body>\n        Ensure that empty attributes are copied properly.\n        <input name=\""
  },
  {
    "path": "pelican/tests/content/article_with_template.rst",
    "chars": 181,
    "preview": "Article with template\n#####################\n\n:template: custom\n\nThis article has a custom template to be called when ren"
  },
  {
    "path": "pelican/tests/content/article_with_typogrify_dashes.md",
    "chars": 69,
    "preview": "Title: One -, two --, three --- dashes!\n\nOne: -; Two: --; Three: ---\n"
  },
  {
    "path": "pelican/tests/content/article_with_typogrify_dashes.rst",
    "chars": 95,
    "preview": "One -, two --, three --- dashes!\n################################\n\nOne: -; Two: --; Three: ---\n"
  },
  {
    "path": "pelican/tests/content/article_with_uppercase_metadata.html",
    "chars": 135,
    "preview": "<html>\n    <head>\n        <title>This is a super article !</title>\n        <meta name=\"Category\" content=\"Yeah\" />\n    <"
  },
  {
    "path": "pelican/tests/content/article_with_uppercase_metadata.rst",
    "chars": 70,
    "preview": "\nThis is a super article !\n#########################\n\n:Category: Yeah\n"
  },
  {
    "path": "pelican/tests/content/article_without_category.rst",
    "chars": 126,
    "preview": "\nThis is an article without category !\n#####################################\n\nThis article should be in the DEFAULT_CATE"
  },
  {
    "path": "pelican/tests/content/bad_extension.mmd",
    "chars": 92,
    "preview": "Title: Bad Extension\n\nThis file shouldn't be included because its file extension is `.mmd`.\n"
  },
  {
    "path": "pelican/tests/content/bloggerexport.xml",
    "chars": 72884,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<?xml-stylesheet href=\"https://www.blogger.com/styles/atom.css\" type=\"text/css\"?>"
  },
  {
    "path": "pelican/tests/content/empty.md",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "pelican/tests/content/empty_with_bom.md",
    "chars": 2,
    "preview": "\n"
  },
  {
    "path": "pelican/tests/content/medium_post_content.txt",
    "chars": 1275,
    "preview": "\n<hr/><h3>Title header</h3><p>A paragraph of content.</p><p>Paragraph number two.</p><p>A list:</p><ol><li>One.</li><li>"
  },
  {
    "path": "pelican/tests/content/medium_posts/2017-04-21_-medium-post--d1bf01d62ba3.html",
    "chars": 4471,
    "preview": "<!DOCTYPE html><html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"><title>A title</title><sty"
  },
  {
    "path": "pelican/tests/content/wordpress_content_decoded",
    "chars": 3170,
    "preview": "<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod\ntempor incididunt ut labore et dolore magna "
  },
  {
    "path": "pelican/tests/content/wordpress_content_encoded",
    "chars": 3141,
    "preview": "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod\ntempor incididunt ut labore et dolore magna ali"
  },
  {
    "path": "pelican/tests/content/wordpressexport.xml",
    "chars": 64130,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<!-- This is a WordPress eXtended RSS file generated by WordPress as an export o"
  },
  {
    "path": "pelican/tests/cyclic_intersite_links/first-article.rst",
    "chars": 218,
    "preview": "First article\n#############\n\n:date: 2018-11-10\n:summary: Here's the `second <{filename}/second-article.rst>`_,\n    `thir"
  },
  {
    "path": "pelican/tests/cyclic_intersite_links/second-article.rst",
    "chars": 218,
    "preview": "Second article\n##############\n\n:date: 2018-11-10\n:summary: Here's the `first <{filename}/first-article.rst>`_,\n    `thir"
  },
  {
    "path": "pelican/tests/cyclic_intersite_links/third-article.rst",
    "chars": 218,
    "preview": "Third article\n#############\n\n:date: 2018-11-10\n:summary: Here's the `first <{filename}/first-article.rst>`_,\n    `second"
  },
  {
    "path": "pelican/tests/default_conf.py",
    "chars": 1261,
    "preview": "AUTHOR = \"Alexis Métaireau\"\nSITENAME = \"Alexis' log\"\nSITEURL = \"http://blog.notmyidea.org\"\nTIMEZONE = \"UTC\"\n\nGITHUB_URL "
  },
  {
    "path": "pelican/tests/dummy_plugins/namespace_plugin/pelican/plugins/ns_plugin/__init__.py",
    "chars": 53,
    "preview": "NAME = \"namespace plugin\"\n\n\ndef register():\n    pass\n"
  },
  {
    "path": "pelican/tests/dummy_plugins/normal_plugin/normal_plugin/__init__.py",
    "chars": 69,
    "preview": "from .submodule import noop  # noqa: F401\n\n\ndef register():\n    pass\n"
  },
  {
    "path": "pelican/tests/dummy_plugins/normal_plugin/normal_plugin/submodule.py",
    "chars": 21,
    "preview": "def noop():\n    pass\n"
  },
  {
    "path": "pelican/tests/dummy_plugins/normal_plugin/normal_submodule_plugin/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "pelican/tests/dummy_plugins/normal_plugin/normal_submodule_plugin/subpackage/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "pelican/tests/dummy_plugins/normal_plugin/normal_submodule_plugin/subpackage/subpackage.py",
    "chars": 25,
    "preview": "def register():\n    pass\n"
  },
  {
    "path": "pelican/tests/dummy_plugins/normal_plugin/normal_submodule_plugin/subplugin.py",
    "chars": 25,
    "preview": "def register():\n    pass\n"
  },
  {
    "path": "pelican/tests/mixed_content/short_page.md",
    "chars": 52,
    "preview": "Title: Short Page\n\nThis is a page with little text.\n"
  },
  {
    "path": "pelican/tests/nested_content/maindir/maindir.md",
    "chars": 50,
    "preview": "Title: Main Dir Page\n\nThis page lives in maindir.\n"
  },
  {
    "path": "pelican/tests/nested_content/maindir/subdir/subdir.md",
    "chars": 55,
    "preview": "Title: Subdir Page\n\nThis page lives in maindir/subdir.\n"
  },
  {
    "path": "pelican/tests/output/basic/a-markdown-powered-article.html",
    "chars": 4040,
    "preview": "<!DOCTYPE html>\n<html lang=\"en\">\n        <head>\n                <meta charset=\"utf-8\" />\n                <meta name=\"vie"
  },
  {
    "path": "pelican/tests/output/basic/archives.html",
    "chars": 4171,
    "preview": "<!DOCTYPE html>\n<html lang=\"en\">\n        <head>\n                <meta charset=\"utf-8\" />\n                <meta name=\"vie"
  },
  {
    "path": "pelican/tests/output/basic/article-1.html",
    "chars": 3633,
    "preview": "<!DOCTYPE html>\n<html lang=\"en\">\n        <head>\n                <meta charset=\"utf-8\" />\n                <meta name=\"vie"
  },
  {
    "path": "pelican/tests/output/basic/article-2.html",
    "chars": 3633,
    "preview": "<!DOCTYPE html>\n<html lang=\"en\">\n        <head>\n                <meta charset=\"utf-8\" />\n                <meta name=\"vie"
  },
  {
    "path": "pelican/tests/output/basic/article-3.html",
    "chars": 3633,
    "preview": "<!DOCTYPE html>\n<html lang=\"en\">\n        <head>\n                <meta charset=\"utf-8\" />\n                <meta name=\"vie"
  },
  {
    "path": "pelican/tests/output/basic/author/alexis-metaireau.html",
    "chars": 7375,
    "preview": "<!DOCTYPE html>\n<html lang=\"en\">\n        <head>\n                <meta charset=\"utf-8\" />\n                <meta name=\"vie"
  },
  {
    "path": "pelican/tests/output/basic/authors.html",
    "chars": 2752,
    "preview": "<!DOCTYPE html>\n<html lang=\"en\">\n        <head>\n                <meta charset=\"utf-8\" />\n                <meta name=\"vie"
  },
  {
    "path": "pelican/tests/output/basic/categories.html",
    "chars": 2987,
    "preview": "<!DOCTYPE html>\n<html lang=\"en\">\n        <head>\n                <meta charset=\"utf-8\" />\n                <meta name=\"vie"
  },
  {
    "path": "pelican/tests/output/basic/category/bar.html",
    "chars": 4151,
    "preview": "<!DOCTYPE html>\n<html lang=\"en\">\n        <head>\n                <meta charset=\"utf-8\" />\n                <meta name=\"vie"
  },
  {
    "path": "pelican/tests/output/basic/category/cat1.html",
    "chars": 7388,
    "preview": "<!DOCTYPE html>\n<html lang=\"en\">\n        <head>\n                <meta charset=\"utf-8\" />\n                <meta name=\"vie"
  },
  {
    "path": "pelican/tests/output/basic/category/misc.html",
    "chars": 9338,
    "preview": "<!DOCTYPE html>\n<html lang=\"en\">\n        <head>\n                <meta charset=\"utf-8\" />\n                <meta name=\"vie"
  },
  {
    "path": "pelican/tests/output/basic/category/yeah.html",
    "chars": 4742,
    "preview": "<!DOCTYPE html>\n<html lang=\"en\">\n        <head>\n                <meta charset=\"utf-8\" />\n                <meta name=\"vie"
  },
  {
    "path": "pelican/tests/output/basic/drafts/a-draft-article-without-date.html",
    "chars": 3928,
    "preview": "<!DOCTYPE html>\n<html lang=\"en\">\n        <head>\n                <meta charset=\"utf-8\" />\n                <meta name=\"vie"
  },
  {
    "path": "pelican/tests/output/basic/drafts/a-draft-article.html",
    "chars": 3885,
    "preview": "<!DOCTYPE html>\n<html lang=\"en\">\n        <head>\n                <meta charset=\"utf-8\" />\n                <meta name=\"vie"
  },
  {
    "path": "pelican/tests/output/basic/feeds/alexis-metaireau.atom.xml",
    "chars": 2277,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<feed xmlns=\"http://www.w3.org/2005/Atom\"><title>A Pelican Blog - Alexis Métairea"
  },
  {
    "path": "pelican/tests/output/basic/feeds/alexis-metaireau.rss.xml",
    "chars": 1555,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<rss version=\"2.0\" xmlns:atom=\"http://www.w3.org/2005/Atom\"><channel><title>A Pel"
  },
  {
    "path": "pelican/tests/output/basic/feeds/all-en.atom.xml",
    "chars": 21365,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<feed xmlns=\"http://www.w3.org/2005/Atom\"><title>A Pelican Blog</title><link href"
  },
  {
    "path": "pelican/tests/output/basic/feeds/all-fr.atom.xml",
    "chars": 1047,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<feed xmlns=\"http://www.w3.org/2005/Atom\"><title>A Pelican Blog</title><link href"
  },
  {
    "path": "pelican/tests/output/basic/feeds/all.atom.xml",
    "chars": 22157,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<feed xmlns=\"http://www.w3.org/2005/Atom\"><title>A Pelican Blog</title><link href"
  },
  {
    "path": "pelican/tests/output/basic/feeds/bar.atom.xml",
    "chars": 948,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<feed xmlns=\"http://www.w3.org/2005/Atom\"><title>A Pelican Blog - bar</title><lin"
  },
  {
    "path": "pelican/tests/output/basic/feeds/cat1.atom.xml",
    "chars": 1819,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<feed xmlns=\"http://www.w3.org/2005/Atom\"><title>A Pelican Blog - cat1</title><li"
  },
  {
    "path": "pelican/tests/output/basic/feeds/misc.atom.xml",
    "chars": 17812,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<feed xmlns=\"http://www.w3.org/2005/Atom\"><title>A Pelican Blog - misc</title><li"
  },
  {
    "path": "pelican/tests/output/basic/feeds/yeah.atom.xml",
    "chars": 1560,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<feed xmlns=\"http://www.w3.org/2005/Atom\"><title>A Pelican Blog - yeah</title><li"
  },
  {
    "path": "pelican/tests/output/basic/filename_metadata-example.html",
    "chars": 3711,
    "preview": "<!DOCTYPE html>\n<html lang=\"en\">\n        <head>\n                <meta charset=\"utf-8\" />\n                <meta name=\"vie"
  },
  {
    "path": "pelican/tests/output/basic/index.html",
    "chars": 19138,
    "preview": "<!DOCTYPE html>\n<html lang=\"en\">\n        <head>\n                <meta charset=\"utf-8\" />\n                <meta name=\"vie"
  },
  {
    "path": "pelican/tests/output/basic/oh-yeah-fr.html",
    "chars": 3913,
    "preview": "<!DOCTYPE html>\n<html lang=\"fr\">\n        <head>\n                <meta charset=\"utf-8\" />\n                <meta name=\"vie"
  },
  {
    "path": "pelican/tests/output/basic/oh-yeah.html",
    "chars": 4871,
    "preview": "<!DOCTYPE html>\n<html lang=\"en\">\n        <head>\n                <meta charset=\"utf-8\" />\n                <meta name=\"vie"
  },
  {
    "path": "pelican/tests/output/basic/override/index.html",
    "chars": 2776,
    "preview": "<!DOCTYPE html>\n<html lang=\"en\">\n        <head>\n                <meta charset=\"utf-8\" />\n                <meta name=\"vie"
  },
  {
    "path": "pelican/tests/output/basic/pages/this-is-a-test-hidden-page.html",
    "chars": 2778,
    "preview": "<!DOCTYPE html>\n<html lang=\"en\">\n        <head>\n                <meta charset=\"utf-8\" />\n                <meta name=\"vie"
  },
  {
    "path": "pelican/tests/output/basic/pages/this-is-a-test-page.html",
    "chars": 2934,
    "preview": "<!DOCTYPE html>\n<html lang=\"en\">\n        <head>\n                <meta charset=\"utf-8\" />\n                <meta name=\"vie"
  },
  {
    "path": "pelican/tests/output/basic/second-article-fr.html",
    "chars": 4063,
    "preview": "<!DOCTYPE html>\n<html lang=\"fr\">\n        <head>\n                <meta charset=\"utf-8\" />\n                <meta name=\"vie"
  },
  {
    "path": "pelican/tests/output/basic/second-article.html",
    "chars": 4058,
    "preview": "<!DOCTYPE html>\n<html lang=\"en\">\n        <head>\n                <meta charset=\"utf-8\" />\n                <meta name=\"vie"
  },
  {
    "path": "pelican/tests/output/basic/tag/bar.html",
    "chars": 8348,
    "preview": "<!DOCTYPE html>\n<html lang=\"en\">\n        <head>\n                <meta charset=\"utf-8\" />\n                <meta name=\"vie"
  },
  {
    "path": "pelican/tests/output/basic/tag/baz.html",
    "chars": 3767,
    "preview": "<!DOCTYPE html>\n<html lang=\"en\">\n        <head>\n                <meta charset=\"utf-8\" />\n                <meta name=\"vie"
  },
  {
    "path": "pelican/tests/output/basic/tag/foo.html",
    "chars": 5998,
    "preview": "<!DOCTYPE html>\n<html lang=\"en\">\n        <head>\n                <meta charset=\"utf-8\" />\n                <meta name=\"vie"
  },
  {
    "path": "pelican/tests/output/basic/tag/foobar.html",
    "chars": 4729,
    "preview": "<!DOCTYPE html>\n<html lang=\"en\">\n        <head>\n                <meta charset=\"utf-8\" />\n                <meta name=\"vie"
  },
  {
    "path": "pelican/tests/output/basic/tag/oh.html",
    "chars": 2697,
    "preview": "<!DOCTYPE html>\n<html lang=\"en\">\n        <head>\n                <meta charset=\"utf-8\" />\n                <meta name=\"vie"
  },
  {
    "path": "pelican/tests/output/basic/tag/yeah.html",
    "chars": 4137,
    "preview": "<!DOCTYPE html>\n<html lang=\"en\">\n        <head>\n                <meta charset=\"utf-8\" />\n                <meta name=\"vie"
  },
  {
    "path": "pelican/tests/output/basic/tags.html",
    "chars": 3109,
    "preview": "<!DOCTYPE html>\n<html lang=\"en\">\n        <head>\n                <meta charset=\"utf-8\" />\n                <meta name=\"vie"
  }
]

// ... and 242 more files (download for full content)

About this extraction

This page contains the full source code of the getpelican/pelican GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 442 files (2.6 MB), approximately 706.7k tokens, and a symbol index with 806 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!