This repository contains our official Documentation Rendering Engine.
Based on flat markdown content from Github OVH.Docs, we build docs.ovh.com and template all markdown with our rendering engine. Our build contains a bunch of static HTML files, deployed in ours front webfarms.
Our CI Pipe is managed by CDS All modifications to this repository, will automatically trigger a new build to docs.ovh.com.
Test if with our developer environment docs-developer-env
docs.ovh.com is entirely generated with Pelican from markdown
files
In this repository, you will find all configurations, themes and plugins that we use in the context of the continuous delivery of docs.ovh.com illustrated in the diagram below (green
part).
Description from the Pelican repository:
Pelican is a static site generator, written in Python
- Write content in Markdown using your editor of choice
- Includes a simple command line tool to (re)generate site files
- Easy to interface with version control systems and web hooks
- Completely static output is simple to host anywhere
The choice of Pelican was done for its great extensible capabilities.
- We could easily create plugins that manage our hierachical files structure:
- for custom url generation.
- for entity linking.
- We took advantage of the python's awesome and extensible implementation of markdown for handling our custom content.
- We could in a next step, quickly change the look of the site thanks to a theme powered by jinja2 template.
extends pelican-entities
in order to suit our needs.
Because of our docs repository is structured in a hierarchical manner, we needed to easily define search path for entity using regexp instead of just a folder name.
More info about entity naming and hierarchy can be found here
# repository stucture example
.
├── pages
| ├── web
| | ├── domains
| | | ├── glue-registry
| | | | ├── guide.en-gb.md (title: Glue Registry)
| | | | └── guide.fr-fr.md (title: Activer le Glue Registry sur son domaine)
| | | ├── product.en-gb.md (title: Domains and DNS)
| | | └── product.fr-fr.md (title: Domaines et DNS)
| | ├── hosting
| | | ├── 24-days
| | | | ├── day01
| | | | | └── guide.fr-fr.md (title: Les bases des sites web)
| | | | ├── day02
| | | | | └── guide.fr-fr.md (title: Choisir et configurer un nom de domaine)
| | | | └── guide.fr-fr.md (title: Développer votre projet pas à pas avec l'hébergement web OVH)
| | | ├── product.en-gb.md (title: Domains and DNS)
| | | └── product.fr-fr.md (title: Domaines et DNS)
| | ├── universe.en-gb.md (title: Web)
| | └── universe.fr-fr.md (title: Web)
| ├── home.en-gb.md (title: OVH - Documentation)
| └── home.fr-fr.md (title: OVH - Guides)
└── README.md
# entities search path regexp configuration in pelicanconf.py
ENTITY_TYPES = {
"Home": {
"PATHS": ["home.*.md"],
},
"Universe": {
"PATHS": ["**/universe.*.md"],
},
"Product": {
"PATHS": ["**/product.*.md"],
},
"Guide": {
"PATHS": ["**/guide.*.md"],
},
}
When needed, for each entity, we add a children property that lists all authorized children (useful in jinja2 templates for children list rendering).
# entities children configuration in pelicanconf.py
ENTITY_TYPES = {
"Home": {
"CHILDREN": ["Universe"],
},
"Universe": {
"CHILDREN": ["Universe", "Product"],
},
"Product": {
"CHILDREN": ["Guide"],
},
"Guide": {
"CHILDREN": ["Guide"],
},
}
We needed to exclude some part of the default generated url by pelican without the need to include
the override_url
and override_save_as
properties in each file.
Those properties are generated for each entity using the config property EXCLUDE_SLUGS
.
# entities slug exclusion configuration in pelicanconf.py
ENTITY_TYPES = {
"Universe": {
"EXCLUDE_SLUGS": ["Home"], # generate universe url without home part
},
"Product": {
"EXCLUDE_SLUGS": ["Home", "Universe"], # generate product url without home and universe part
},
"Guide": {
"EXCLUDE_SLUGS": ["Home", "Universe"], # generate product url without home and universe part
},
}
This plugin contains all custom processors for rendering content like notices
that markdown parser
does not handle by default.
BlockCalloutProcessor
for noticesBlockApiProcessor
for ovh api callsBlockCarouselProcessor
for carouselsBlockFaqProcessor
for FAQ sections
see markdown usages here
Contains Jinja2 filters used in templates.
get an array of (title, url) from parents of an OVH Entity
<!-- usage example -->
<ul>
{%for text, url in entity|breadcrumbs%}
<li>
<a href="/{{url}}"{{' class="home"' if loop.index == 1}} >
<span{{' class="show-for-sr"' if loop.index == 1}}>{{text}}</span></a>
</li>
{% endfor %}
</ul>
get an array of related guides for a given guide
<!-- usage example -->
{% set related_entities = entity|related %}
...
{% for related_entity in related_entities %}
<div class="column">
<a href="/{{ related_entity.url }}">
<span class='parent'>{{ related_entity.parent.title }}</span><br />
<span class='title'>{{ related_entity.title }}</span>
</a>
</div>
{% endfor %}
filter visible entities (visible property of entity == True)
<!-- usage example -->
{% for section, guides in entity.sections['odd'].items() %}
{% set visible_guides = guides|visible %}
{% if visible_guides|length > 0 %}
<div class="columns">
<h3>{{section|translate(entity.global)}}</h3>
<ul class="doc-list">
{% for guide in visible_guides|sort(attribute='order') %}
<li><a href="/{{guide.url}}">{{guide.title}}</a></li>
{% endfor %}
</ul>
</div>
{% endif %}
{% endfor %}
translate a content according to a given language. Dictionary defined in config/translations.yml
<!-- usage example -->
<h3>{{section|translate(entity.global)}}</h3>
stored in the folder themes/ovh
# structure
.
├── static (will be copied as folder `theme` at root level during build)
| └── ... (images, css, js, ...)
└── templates
└── ... (jinja2 templates)
base template containing all common css, js and jinja blocks
entity base template (extends base.html) containing all elements shared between all ovh entities
- title
- meta
- hreflang
- menu
- footer
- breadcrumb
- excerpt
- search bar
- analytics
Template for Home entity. Generate Universe > Products
list using children property
Template for Universe entity. Generate Products
list using children property
Template for Product entity. Generate Guides
list grouped by section
.
The section meta is defined in each guide file (default value: Misc)
Template for Guide entity
Generate sitemap of docs.ovh.com
defined in config as direct template
DIRECT_TEMPLATES = ['sitemap']
SITEMAP_SAVE_AS = 'sitemap.xml'