Feat: Add personnal plugins
This commit is contained in:
		
							
								
								
									
										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) | ||||
		Reference in New Issue
	
	Block a user