Feat: Add personnal plugins
This commit is contained in:
parent
a8a6b862a6
commit
b188406fcc
75
plugins/hierarchy/README.md
Normal file
75
plugins/hierarchy/README.md
Normal file
@ -0,0 +1,75 @@
|
||||
Page Hierarchy
|
||||
==============
|
||||
*Author: Ahmad Khayyat (<akhayyat@gmail.com>)*
|
||||
|
||||
A [Pelican][1] plugin that creates a URL hierarchy for pages that
|
||||
matches the filesystem hierarchy of their sources.
|
||||
|
||||
For example, to have the following filesystem structure of page
|
||||
sources result in the URLs listed next to each file,
|
||||
|
||||
```text
|
||||
└── content/pages/ # PAGE_DIR
|
||||
├── about.md # URL: pages/about/
|
||||
├── projects.md # URL: pages/projects/
|
||||
├── projects/ # (directory)
|
||||
│ ├── p1.md # URL: pages/projects/p1/
|
||||
│ ├── p2.md # URL: pages/projects/p2/
|
||||
│ └── p2/ # (directory)
|
||||
│ └── features.md # URL: pages/projects/p2/features/
|
||||
└── contact.md # URL: pages/contact/
|
||||
```
|
||||
|
||||
you can use this plugin with the following Pelican settings:
|
||||
|
||||
```python
|
||||
# pelicanconf.py
|
||||
PAGE_URL = '{slug}/'
|
||||
PAGE_SAVE_AS = '{slug}/index.html'
|
||||
SLUGIFY_SOURCE = 'basename'
|
||||
```
|
||||
|
||||
When generating the `url` and `save_as` attributes, the plugin
|
||||
prefixes the page's `slug` by its relative path. Although the initial
|
||||
`slug` is generated from the page's `title` by default, it can be
|
||||
generated from the source file basename by setting the
|
||||
`SLUGIFY_SOURCE` setting to `'basename'`, as shown in the settings
|
||||
snippet above. The `slug` can also be set using [`PATH_METADATA`][2].
|
||||
|
||||
This plugin is compatible with [Pelican translations][3].
|
||||
|
||||
Parent and Children Pages
|
||||
-------------------------
|
||||
This plugin also adds three attributes to each page object:
|
||||
|
||||
- `parent`: the immediate parent page. `None` if the page is
|
||||
top-level. If a translated page has no parent, the default-language
|
||||
parent is used.
|
||||
|
||||
- `parents`: a list of all ancestor pages, starting from the top-level
|
||||
ancestor.
|
||||
|
||||
- `children`: a list of all immediate child pages, in no specific
|
||||
order.
|
||||
|
||||
These attributes can be used to generate breadcrumbs or nested
|
||||
navigation menus. For example, this is a template excerpt for
|
||||
breadcrumbs:
|
||||
|
||||
```html
|
||||
<ul class="breadcrumb">
|
||||
<li><a href="{{ SITEURL }}/" title="{{ SITENAME }}">
|
||||
<i class="fa fa-home fa-lg"></i>
|
||||
</a></li>
|
||||
{% for parent in page.parents %}
|
||||
<li><a href="{{ SITEURL }}/{{ parent.url }}">{{ parent.title }}</a></li>
|
||||
{% endfor %}
|
||||
<li class="active">{{ page.title }}</li>
|
||||
</ul>
|
||||
|
||||
```
|
||||
|
||||
|
||||
[1]: http://getpelican.com/
|
||||
[2]: http://docs.getpelican.com/en/latest/settings.html#path-metadata
|
||||
[3]: http://docs.getpelican.com/en/latest/settings.html#translations
|
2
plugins/hierarchy/__init__.py
Normal file
2
plugins/hierarchy/__init__.py
Normal file
@ -0,0 +1,2 @@
|
||||
#from .page_hierarchy import *
|
||||
from .article_hierarchy import *
|
88
plugins/hierarchy/article_hierarchy.py
Normal file
88
plugins/hierarchy/article_hierarchy.py
Normal file
@ -0,0 +1,88 @@
|
||||
from pelican import signals, contents
|
||||
import os.path
|
||||
from copy import copy
|
||||
from itertools import chain
|
||||
|
||||
'''
|
||||
This plugin creates a URL hierarchy for articles that matches the
|
||||
directory hierarchy of their sources.
|
||||
'''
|
||||
|
||||
class UnexpectedException(Exception): pass
|
||||
|
||||
def get_path(article, settings):
|
||||
''' Return the dirname relative to ARTICLE_PATHS prefix. '''
|
||||
path = os.path.split(article.get_relative_source_path())[0] + '/'
|
||||
path = path.replace( os.path.sep, '/' )
|
||||
# Try to lstrip the longest prefix first
|
||||
for prefix in sorted(settings['ARTICLE_PATHS'], key=len, reverse=True):
|
||||
if not prefix.endswith('/'): prefix += '/'
|
||||
if path.startswith(prefix):
|
||||
return path[len(prefix):-1]
|
||||
raise UnexpectedException('Article outside of ARTICLE_PATHS ?!?')
|
||||
|
||||
def in_default_lang(article):
|
||||
# article.in_default_lang property is undocumented (=unstable) interface
|
||||
return article.lang == article.settings['DEFAULT_LANG']
|
||||
|
||||
def override_metadata(content_object):
|
||||
if type(content_object) is not contents.Article:
|
||||
return
|
||||
article = content_object
|
||||
path = get_path(article, article.settings)
|
||||
|
||||
def _override_value(article, key):
|
||||
metadata = copy(article.metadata)
|
||||
# We override the slug to include the path up to the filename
|
||||
#metadata['slug'] = os.path.join(path, article.slug)
|
||||
metadata['slug'] = path
|
||||
# We have to account for non-default language and format either,
|
||||
# e.g., ARTICLE_SAVE_AS or ARTICLE_LANG_SAVE_AS
|
||||
#infix = '' if in_default_lang(article) else 'LANG_'
|
||||
infix = ''
|
||||
return article.settings['ARTICLE_' + infix + key.upper()].format(**metadata)
|
||||
|
||||
for key in ('save_as', 'url'):
|
||||
if not hasattr(article, 'override_' + key):
|
||||
setattr(article, 'override_' + key, _override_value(article, key))
|
||||
|
||||
def set_relationships(generator):
|
||||
def _all_articles():
|
||||
return chain(generator.articles, generator.translations)
|
||||
|
||||
# initialize parents and children lists
|
||||
for article in _all_articles():
|
||||
article.parent = None
|
||||
article.parents = []
|
||||
article.children = []
|
||||
|
||||
# set immediate parents and children
|
||||
for article in _all_articles():
|
||||
# Parent of /a/b/ is /a/, parent of /a/b.html is /a/
|
||||
parent_url = os.path.dirname(article.url[:-1])
|
||||
if parent_url: parent_url += '/'
|
||||
for article2 in _all_articles():
|
||||
if article2.url == parent_url and article2 != article:
|
||||
article.parent = article2
|
||||
article2.children.append(article)
|
||||
# If no parent found, try the parent of the default language article
|
||||
#if not article.parent and not in_default_lang(article):
|
||||
if not article.parent:
|
||||
for article2 in generator.articles:
|
||||
if (article.slug == article2.slug and
|
||||
os.path.dirname(article.source_path) ==
|
||||
os.path.dirname(article2.source_path)):
|
||||
# Only set the parent but not the children, obviously
|
||||
article.parent = article2.parent
|
||||
|
||||
# set all parents (ancestors)
|
||||
for article in _all_articles():
|
||||
p = article
|
||||
while p.parent:
|
||||
article.parents.insert(0, p.parent)
|
||||
p = p.parent
|
||||
|
||||
|
||||
def register():
|
||||
signals.content_object_init.connect(override_metadata)
|
||||
signals.article_generator_finalized.connect(set_relationships)
|
86
plugins/hierarchy/page_hierarchy.py
Normal file
86
plugins/hierarchy/page_hierarchy.py
Normal file
@ -0,0 +1,86 @@
|
||||
from pelican import signals, contents
|
||||
import os.path
|
||||
from copy import copy
|
||||
from itertools import chain
|
||||
|
||||
'''
|
||||
This plugin creates a URL hierarchy for pages that matches the
|
||||
directory hierarchy of their sources.
|
||||
'''
|
||||
|
||||
class UnexpectedException(Exception): pass
|
||||
|
||||
def get_path(page, settings):
|
||||
''' Return the dirname relative to PAGE_PATHS prefix. '''
|
||||
path = os.path.split(page.get_relative_source_path())[0] + '/'
|
||||
path = path.replace( os.path.sep, '/' )
|
||||
# Try to lstrip the longest prefix first
|
||||
for prefix in sorted(settings['PAGE_PATHS'], key=len, reverse=True):
|
||||
if not prefix.endswith('/'): prefix += '/'
|
||||
if path.startswith(prefix):
|
||||
return path[len(prefix):-1]
|
||||
raise UnexpectedException('Page outside of PAGE_PATHS ?!?')
|
||||
|
||||
def in_default_lang(page):
|
||||
# page.in_default_lang property is undocumented (=unstable) interface
|
||||
return page.lang == page.settings['DEFAULT_LANG']
|
||||
|
||||
def override_metadata(content_object):
|
||||
if type(content_object) is not contents.Page:
|
||||
return
|
||||
page = content_object
|
||||
path = get_path(page, page.settings)
|
||||
|
||||
def _override_value(page, key):
|
||||
metadata = copy(page.metadata)
|
||||
# We override the slug to include the path up to the filename
|
||||
#metadata['slug'] = os.path.join(path, page.slug)
|
||||
metadata['slug'] = path
|
||||
# We have to account for non-default language and format either,
|
||||
# e.g., PAGE_SAVE_AS or PAGE_LANG_SAVE_AS
|
||||
infix = '' if in_default_lang(page) else 'LANG_'
|
||||
return page.settings['PAGE_' + infix + key.upper()].format(**metadata)
|
||||
|
||||
for key in ('save_as', 'url'):
|
||||
if not hasattr(page, 'override_' + key):
|
||||
setattr(page, 'override_' + key, _override_value(page, key))
|
||||
|
||||
def set_relationships(generator):
|
||||
def _all_pages():
|
||||
return chain(generator.pages, generator.translations)
|
||||
|
||||
# initialize parents and children lists
|
||||
for page in _all_pages():
|
||||
page.parent = None
|
||||
page.parents = []
|
||||
page.children = []
|
||||
|
||||
# set immediate parents and children
|
||||
for page in _all_pages():
|
||||
# Parent of /a/b/ is /a/, parent of /a/b.html is /a/
|
||||
parent_url = os.path.dirname(page.url[:-1])
|
||||
if parent_url: parent_url += '/'
|
||||
for page2 in _all_pages():
|
||||
if page2.url == parent_url and page2 != page:
|
||||
page.parent = page2
|
||||
page2.children.append(page)
|
||||
# If no parent found, try the parent of the default language page
|
||||
if not page.parent and not in_default_lang(page):
|
||||
for page2 in generator.pages:
|
||||
if (page.slug == page2.slug and
|
||||
os.path.dirname(page.source_path) ==
|
||||
os.path.dirname(page2.source_path)):
|
||||
# Only set the parent but not the children, obviously
|
||||
page.parent = page2.parent
|
||||
|
||||
# set all parents (ancestors)
|
||||
for page in _all_pages():
|
||||
p = page
|
||||
while p.parent:
|
||||
page.parents.insert(0, p.parent)
|
||||
p = p.parent
|
||||
|
||||
|
||||
def register():
|
||||
signals.content_object_init.connect(override_metadata)
|
||||
signals.page_generator_finalized.connect(set_relationships)
|
1
plugins/list_files/__init__.py
Normal file
1
plugins/list_files/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
from .list_files import *
|
40
plugins/list_files/list_files.py
Normal file
40
plugins/list_files/list_files.py
Normal file
@ -0,0 +1,40 @@
|
||||
from pelican import signals, contents
|
||||
from os import listdir, getcwd
|
||||
from os.path import isfile, join, sep, split
|
||||
from copy import copy
|
||||
from itertools import chain
|
||||
|
||||
'''
|
||||
This plugin creates a URL hierarchy for articles that matches the
|
||||
directory hierarchy of their sources.
|
||||
'''
|
||||
|
||||
def lsfiles(path):
|
||||
return [f for f in listdir(path) if isfile(join(path, f))]
|
||||
|
||||
def save_files(content_object):
|
||||
if type(content_object) is not contents.Article:
|
||||
return
|
||||
article = content_object
|
||||
path = split(article.get_relative_source_path())[0] + '/'
|
||||
path = path.replace(sep, '/' )
|
||||
abs_path = getcwd() + "/content/" + path
|
||||
|
||||
files = {i:(path+i) for i in lsfiles(abs_path)}
|
||||
try:
|
||||
fig_files = lsfiles(abs_path+"/fig")
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
else:
|
||||
fig_files = {i:(path+"fig/"+i) for i in fig_files}
|
||||
files.update(fig_files)
|
||||
|
||||
article.link_files = []
|
||||
|
||||
for i in files.items():
|
||||
article.link_files.append(i)
|
||||
|
||||
article.link_files.sort()
|
||||
|
||||
def register():
|
||||
signals.content_object_init.connect(save_files)
|
Loading…
Reference in New Issue
Block a user