The idea of pelican is simple:
- two types of content: pages and articles.
- inside articles, there are plenty of metadata, e.g. title, date and tag.
- pelican analysis articles and pages, get all the those informations in memory.
- pelican use corresponding template to render those informations in memory.
- e.g. page.html for pages, article.html for article
- e.g. archives.html for archive of articles.
- this means pelican can only handle pre-defined contracts.
- in conclusion:
- pelican gets variables form markdown files and setting file.
- a lot of contracts have been made on theme structure and metadata.
- pelican applys all these variables on theme templates and generate htmls.
/usr/local/bin/pelican:
#!/usr/local/bin/python3.5
# -*- coding: utf-8 -*-
import re
import sys
from pelican import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script.pyw|.exe)?$', '', sys.argv[0])
sys.exit(main())
main()
is in /usr/local/lib/python3.5/site-packages/pelican/__init__.py.
def main():
args = parse_arguments()
...
pelican, settings = get_instance(args)
...
pelican.run()
...
pelican.run()
is in /usr/local/lib/python3.5/site-packages/pelican/__init__.py.
def run(self):
...
for p in generators:
if hasattr(p, 'generate_context'):
p.generate_context()
...
for p in generators:
if hasattr(p, 'generate_output'):
p.generate_output(writer)
...
Normally, 3 generators are used:
ArticlesGenerator
PagesGenerator
StaticGenerator
ArticlesGenerator.generate_context()
:
def generate_context(self):
...
for f in self.get_files( self.settings['ARTICLE_PATHS'], exclude=self.settings['ARTICLE_EXCLUDES']):
...
article_or_draft = self.readers.read_file(
base_path=self.path, path=f, content_class=Article,
context=self.context,
preread_signal=signals.article_generator_preread,
preread_sender=self,
context_signal=signals.article_generator_context,
context_sender=self)
...
all_articles.append(article_or_draft)
...
self.articles, self.translations = process_translations(
all_articles,
order_by=self.settings['ARTICLE_ORDER_BY'])
self.drafts, self.drafts_translations =
process_translations(all_drafts)
...
for article in self.articles:
self.categories[article.category].append(article)
if hasattr(article, 'tags'):
for tag in article.tags:
self.tags[tag].append(article)
for author in getattr(article, 'authors', []):
self.authors[author].append(article)
self.dates = list(self.articles)
self.dates.sort(key=attrgetter('date'),
reverse=self.context['NEWEST_FIRST_ARCHIVES'])
self.categories = list(self.categories.items())
self.categories.sort(
reverse=self.settings['REVERSE_CATEGORY_ORDER'])
self.authors = list(self.authors.items())
self.authors.sort()
self._update_context(('articles', 'dates', 'tags', 'categories',
'authors', 'related_posts', 'drafts'))
...
Basically, ArticlesGenerator.generate_context()
reads file and puts all the data into context.
ArticlesGenerator.generate_output()
:
def generate_output(self, writer):
...
self.generate_pages(writer)
...
def generate_pages(self, writer):
...
write = partial(writer.write_file, relative_urls=self.settings['RELATIVE_URLS'])
self.generate_articles(write)
self.generate_period_archives(write)
self.generate_tags(write)
self.generate_categories(write)
...
def generate_articles(self, write):
for article in chain(self.translations, self.articles):
...
write(article.save_as, self.get_template(article.template),
self.context, article=article, category=article.category,
override_output=hasattr(article, 'override_save_as'),
blog=True)
write
is Writer.write_file()
in /usr/local/lib/python3.5/site-packages/pelican/writers.py.
def write_file(self, name, template, context, relative_urls=False,
paginated=None, override_output=False, **kwargs):
...
def _write_file(template, localcontext, output_path, name, override):
...
output = template.render(localcontext)
path = os.path.join(output_path, name)
...
with self._open_w(path, 'utf-8', override=override) as f:
f.write(output)
...
if paginated:
...
localcontext = _get_localcontext( context, page.save_as, paginated_kwargs, relative_urls)
_write_file(template, localcontext, self.output_path, page.save_as, override_output)
...
Jobs done.
近期评论