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