|
1 |
| -# docs-rendering |
2 |
| -OVH Docs rendering engine |
| 1 | +# OVH - Docs rendering engine |
3 | 2 |
|
4 |
| -> Repository building in progress |
| 3 | +[docs.ovh.com](https://docs.ovh.com/) is entirely generated with [Pelican](https://github.com/getpelican/pelican) from `markdown` [files](https://github.com/ovh/docs) |
| 4 | + |
| 5 | +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](https://docs.ovh.com/) illustrated in the diagram below (`green` part). |
| 6 | + |
| 7 | + |
| 8 | + |
| 9 | +## Pelican |
| 10 | + |
| 11 | +Description from the Pelican repository: |
| 12 | +> [Pelican](https://github.com/getpelican/pelican) is a static site generator, written in Python |
| 13 | +> |
| 14 | +> - Write content in Markdown using your editor of choice |
| 15 | +> - Includes a simple command line tool to (re)generate site files |
| 16 | +> - Easy to interface with version control systems and web hooks |
| 17 | +> - Completely static output is simple to host anywhere |
| 18 | +
|
| 19 | +The choice of Pelican was done for its great extensible capabilities. |
| 20 | + |
| 21 | +1. We could easily create plugins that manage our hierachical files structure: |
| 22 | + - for custom url generation. |
| 23 | + - for entity linking. |
| 24 | +2. We took advantage of the python's awesome and extensible implementation of markdown for handling |
| 25 | +our custom content. |
| 26 | +3. We could in a next step, quickly change the look of the site thanks to a theme powered by jinja2 template. |
| 27 | + |
| 28 | + |
| 29 | + |
| 30 | +## Plugins |
| 31 | + |
| 32 | +### OVH Entities (`plugins/ovh_entities`) |
| 33 | +extends [`pelican-entities`](https://github.com/AlexJF/pelican-entities) in order to suit our needs. |
| 34 | + |
| 35 | +#### Entity matching |
| 36 | + |
| 37 | +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. |
| 38 | + |
| 39 | +More info about entity naming and hierarchy can be found [here](https://github.com/ovh/docs/blob/master/docs-guideline/docs-guideline.md) |
| 40 | + |
| 41 | +``` |
| 42 | +# repository stucture example |
| 43 | +. |
| 44 | +├── pages |
| 45 | +| ├── web |
| 46 | +| | ├── domains |
| 47 | +| | | ├── glue-registry |
| 48 | +| | | | ├── guide.en-gb.md (title: Glue Registry) |
| 49 | +| | | | └── guide.fr-fr.md (title: Activer le Glue Registry sur son domaine) |
| 50 | +| | | ├── product.en-gb.md (title: Domains and DNS) |
| 51 | +| | | └── product.fr-fr.md (title: Domaines et DNS) |
| 52 | +| | ├── hosting |
| 53 | +| | | ├── 24-days |
| 54 | +| | | | ├── day01 |
| 55 | +| | | | | └── guide.fr-fr.md (title: Les bases des sites web) |
| 56 | +| | | | ├── day02 |
| 57 | +| | | | | └── guide.fr-fr.md (title: Choisir et configurer un nom de domaine) |
| 58 | +| | | | └── guide.fr-fr.md (title: Développer votre projet pas à pas avec l'hébergement web OVH) |
| 59 | +| | | ├── product.en-gb.md (title: Domains and DNS) |
| 60 | +| | | └── product.fr-fr.md (title: Domaines et DNS) |
| 61 | +| | ├── universe.en-gb.md (title: Web) |
| 62 | +| | └── universe.fr-fr.md (title: Web) |
| 63 | +| ├── home.en-gb.md (title: OVH - Documentation) |
| 64 | +| └── home.fr-fr.md (title: OVH - Guides) |
| 65 | +└── README.md |
| 66 | +``` |
| 67 | + |
| 68 | +```py |
| 69 | +# entities search path regexp configuration in pelicanconf.py |
| 70 | +ENTITY_TYPES = { |
| 71 | + "Home": { |
| 72 | + "PATHS": ["home.*.md"], |
| 73 | + }, |
| 74 | + "Universe": { |
| 75 | + "PATHS": ["**/universe.*.md"], |
| 76 | + }, |
| 77 | + "Product": { |
| 78 | + "PATHS": ["**/product.*.md"], |
| 79 | + }, |
| 80 | + "Guide": { |
| 81 | + "PATHS": ["**/guide.*.md"], |
| 82 | + }, |
| 83 | +} |
| 84 | +``` |
| 85 | + |
| 86 | +#### Entity children |
| 87 | +When needed, for each entity, we add a children property that lists all authorized children (useful in jinja2 templates for children list rendering). |
| 88 | + |
| 89 | +```py |
| 90 | +# entities children configuration in pelicanconf.py |
| 91 | +ENTITY_TYPES = { |
| 92 | + "Home": { |
| 93 | + "CHILDREN": ["Universe"], |
| 94 | + }, |
| 95 | + "Universe": { |
| 96 | + "CHILDREN": ["Universe", "Product"], |
| 97 | + }, |
| 98 | + "Product": { |
| 99 | + "CHILDREN": ["Guide"], |
| 100 | + }, |
| 101 | + "Guide": { |
| 102 | + "CHILDREN": ["Guide"], |
| 103 | + }, |
| 104 | +} |
| 105 | +``` |
| 106 | + |
| 107 | +#### url building |
| 108 | +We needed to exclude some part of the default generated url by pelican without the need to include |
| 109 | +the `override_url` and `override_save_as` properties in each file. |
| 110 | + |
| 111 | +Those properties are generated for each entity using the config property `EXCLUDE_SLUGS`. |
| 112 | + |
| 113 | +```py |
| 114 | +# entities slug exclusion configuration in pelicanconf.py |
| 115 | +ENTITY_TYPES = { |
| 116 | + "Universe": { |
| 117 | + "EXCLUDE_SLUGS": ["Home"], # generate universe url without home part |
| 118 | + }, |
| 119 | + "Product": { |
| 120 | + "EXCLUDE_SLUGS": ["Home", "Universe"], # generate product url without home and universe part |
| 121 | + }, |
| 122 | + "Guide": { |
| 123 | + "EXCLUDE_SLUGS": ["Home", "Universe"], # generate product url without home and universe part |
| 124 | + }, |
| 125 | +} |
| 126 | +``` |
| 127 | + |
| 128 | +### OVH markdown (`plugins/ovh_markdown`) |
| 129 | +This plugin contains all custom processors for rendering content like `notices` that `markdown parser` does not handle by default. |
| 130 | + |
| 131 | +- `BlockCalloutProcessor` for notices |
| 132 | +- `BlockApiProcessor` for ovh api calls |
| 133 | +- `BlockCarouselProcessor` for carousels |
| 134 | +- `BlockFaqProcessor` for FAQ sections |
| 135 | + |
| 136 | +see markdown usages [here](https://github.com/ovh/docs/blob/master/docs-guideline/markdown-custom.md) |
| 137 | + |
| 138 | +### OVH Filters (`plugins/ovh_filters`) |
| 139 | + |
| 140 | +Contains Jinja2 filters used in templates. |
| 141 | + |
| 142 | +#### breadcrumbs |
| 143 | +get an array of (title, url) from parents of an OVH Entity |
| 144 | + |
| 145 | +```jinja |
| 146 | +<!-- usage example --> |
| 147 | +<ul> |
| 148 | + {%for text, url in entity|breadcrumbs%} |
| 149 | + <li> |
| 150 | + <a href="/{{url}}"{{' class="home"' if loop.index == 1}} > |
| 151 | + <span{{' class="show-for-sr"' if loop.index == 1}}>{{text}}</span></a> |
| 152 | + </li> |
| 153 | + {% endfor %} |
| 154 | +</ul> |
| 155 | +``` |
| 156 | + |
| 157 | +#### related |
| 158 | +get an array of related guides for a given guide |
| 159 | + |
| 160 | +```jinja |
| 161 | +<!-- usage example --> |
| 162 | +{% set related_entities = entity|related %} |
| 163 | +... |
| 164 | +{% for related_entity in related_entities %} |
| 165 | +<div class="column"> |
| 166 | + <a href="/{{ related_entity.url }}"> |
| 167 | + <span class='parent'>{{ related_entity.parent.title }}</span><br /> |
| 168 | + <span class='title'>{{ related_entity.title }}</span> |
| 169 | + </a> |
| 170 | +</div> |
| 171 | +{% endfor %} |
| 172 | +``` |
| 173 | + |
| 174 | +#### visible |
| 175 | +filter visible entities (visible property of entity == True) |
| 176 | + |
| 177 | +```jinja |
| 178 | +<!-- usage example --> |
| 179 | +{% for section, guides in entity.sections['odd'].items() %} |
| 180 | + {% set visible_guides = guides|visible %} |
| 181 | + {% if visible_guides|length > 0 %} |
| 182 | + <div class="columns"> |
| 183 | + <h3>{{section|translate(entity.global)}}</h3> |
| 184 | + <ul class="doc-list"> |
| 185 | + {% for guide in visible_guides|sort(attribute='order') %} |
| 186 | + <li><a href="/{{guide.url}}">{{guide.title}}</a></li> |
| 187 | + {% endfor %} |
| 188 | + </ul> |
| 189 | + </div> |
| 190 | + {% endif %} |
| 191 | +{% endfor %} |
| 192 | +``` |
| 193 | + |
| 194 | +#### translate |
| 195 | +translate a content according to a given language. Dictionary defined in [config/translations.yml](./config/translation.yml) |
| 196 | + |
| 197 | +```jinja |
| 198 | +<!-- usage example --> |
| 199 | +<h3>{{section|translate(entity.global)}}</h3> |
| 200 | +``` |
| 201 | + |
| 202 | +## Themes - OVH |
| 203 | + |
| 204 | +stored in the folder `themes/ovh` |
| 205 | +``` |
| 206 | +# structure |
| 207 | +. |
| 208 | +├── static (will be copied as folder `theme` at root level during build) |
| 209 | +| └── ... (images, css, js, ...) |
| 210 | +└── templates |
| 211 | + └── ... (jinja2 templates) |
| 212 | +``` |
| 213 | +### Templates |
| 214 | + |
| 215 | +#### base.html |
| 216 | +base template containing all common css, js and jinja blocks |
| 217 | + |
| 218 | +#### entity.html |
| 219 | +entity base template (extends base.html) containing all elements shared between all ovh entities |
| 220 | +- title |
| 221 | +- meta |
| 222 | +- hreflang |
| 223 | +- menu |
| 224 | +- footer |
| 225 | +- breadcrumb |
| 226 | +- excerpt |
| 227 | +- search bar |
| 228 | +- analytics |
| 229 | + |
| 230 | + |
| 231 | + |
| 232 | + |
| 233 | + |
| 234 | +#### home.html |
| 235 | +Template for Home entity. Generate `Universe > Products` list using children property |
| 236 | + |
| 237 | + |
| 238 | + |
| 239 | +#### universe.html |
| 240 | +Template for Universe entity. Generate `Products` list using children property |
| 241 | + |
| 242 | + |
| 243 | + |
| 244 | +#### product.html |
| 245 | +Template for Product entity. Generate `Guides` list grouped by `section`. |
| 246 | +The section meta is defined in each guide file (default value: Misc) |
| 247 | + |
| 248 | + |
| 249 | + |
| 250 | +#### guide.html |
| 251 | +Template for Guide entity |
| 252 | + |
| 253 | + |
| 254 | + |
| 255 | +#### sitemap.html |
| 256 | +Generate sitemap of `docs.ovh.com` |
| 257 | + |
| 258 | +defined in config as direct template |
| 259 | +```py |
| 260 | +DIRECT_TEMPLATES = ['sitemap'] |
| 261 | +SITEMAP_SAVE_AS = 'sitemap.xml' |
| 262 | +``` |
0 commit comments