Enectiva FAQ is using Hugo. In this site, we can view how to use Hugo: https://gohugo.io/overview/usage/ Actually, we are using Hugo v.0.20.6, lunrjs v2.0.3, horsey v4.2.2 and jQuery v3.2.1
For to install all dependencies, you must type in command line:
cd <folder-project>
[sudo] npm install --save-dev grunt toml string nodejs
We must open command line in your Linux distribution. If we have our web in the personal folder of hard disk, we must write into the black window
cd ~
After, if our folder named enectiva-faq
cd enectiva-faq
To start the server, we must type...
[sudo] hugo server
To create a new post (we explain it below). If you can create a new post, please, close hugo server first.
[sudo] hugo new <directory>/filename.md
The command to do this is the next:
[sudo] hugo new XX/1st-section/[2nd-section]/name-to-do.XX.md
You must to change the XX to the language what you can write the post (es: Spanish, cs: Czech, en: English, it: Italian, fr: French, de: German) So if you want to create a new english post, you need to write:
[sudo] hugo new XX/1st-section/[2nd-section]/filename.XX.md
When you have your empty file, you must go into the folder where you created the file.
- Open content/ folder.
- Open lang folder.
- Open 1st-section and 2nd-section if you have it.
- Open your file that you have created with a editor markdown. (recommend ghostwriter). You never must modify the date of the filename.
.
└── content
├── cs
| └── first-section
| └── nested-section
├── de
├── en
├── es
├── fr
├── it
├── ru
└── images (the root folder of images)
When you create a new post, automatically is created a file with a header. This header has the following labels by default, defined in your archetype:
+++
author = "Enectiva"
date = "2017-04-19T13:34:25+02:00"
oddily = "instrukce-k-instalaci"
url = "/cs/oddily/instrukce-k-instalaci/example-1"
tags = [
"slovo1",
"slovo2"
]
title = "Instrukce k instalaci #1"
toc = false
+++
+++
author = "Enectiva"
date = "2017-04-19T12:48:07+02:00"
abschnitte = "Handbucher"
tags = [
"Wort1",
"Wort2"
]
title = "Handbücher #1"
url = "/de/abschnitte/handbucher/example-1"
toc = false
+++
+++
author = "Enectiva"
date = "2017-04-25T13:22:46+02:00"
sections = "third-party-manuals/sensors"
url = "/en/sections/third-party-manuals/sensors/example-1"
tags = [
"word1",
"word2"
]
title = "title of file"
toc = false
+++
+++
author = "Enectiva"
date = "2017-05-31T12:32:37+02:00"
secciones = "manuales/medidores"
url = "/es/secciones/manuales/medidores/como-conectar-smartcoms-al-servidor"
tags = [
"manuales",
"smartcoms"
]
title = "Cómo conectar SmartComs al servidor"
toc = false
+++
+++
author = "Enectiva"
date = "2017-04-19T14:58:49+02:00"
sections = "instructions-d-installation"
url = "/fr/sections/instructions-d-installation/example-1"
tags = [
"mot1",
"mot2"
]
title = "Instructions d'installation #1"
toc = false
+++
+++
author = "Enectiva"
date = "2017-04-25T13:47:04+02:00"
sezioni = "istruzioni-di-installazione/calibri"
url = "/it/sezioni/istruzioni-di-installazione/calibri/example-1"
tags = [
"parola1",
"parola2"
]
title = "Calibri #1"
toc = false
+++
+++
author = "Enectiva"
date = "2017-04-19T13:13:16+02:00"
razdely = "Instruktsiya po ustanovke"
url = "/ru/razdely/instruktsiya-po-ustanovke/example-1"
tags = [
"слово1",
"слово2"
]
title = "Инструкция по установке #1"
toc = false
+++
Something to say:
- In sections we must enter the section of file.
- You must modify URL file, is important that redirect to file. If you don't enter the URL correctly, the search couldn't work.
- You must modify the tag words, if you want have related files.
You need know something before of continue. You must create a index file that you will put into static/json/ folder. For that, type in your command line into hugo folder:
WARNING: Don't to generate the index file with images into content folder or the grunt task will crash.
[sudo] grunt lunr-index
[sudo] cp static/json/ themes/enectiva-faq/static/json/
The gruntfile will get the files into the content/ folder and will create index file with the URL field. Start the server to see the changes in the search results.
In this case, the searching implementation needs of the followings files:
- Partial into layouts/partials/search.html that contents the searchbox and variable that indicates to the javascript, "ey, listen, this is the URL of the page".
- The partial is called if within the configuration the parameter search set true. Looks the file layouts/partials/menu.html
- The javascript is within layouts/base/metas.html
$.getJSON("/json/search.{{ .Site.Language.Lang }}.json")
This part calls to the index file by each language. Hugo detects that language is what are you using and, put the .Site.Language.Lang in the line above. The followings are the language codes:
cs = Czech
de = German
en = English
es = Spanish
fr = French
it = Italian
ru = Russian
All the original code included within of the file metas.html has been extracted of this gist and include, the official code and useful tools.
var lunrIndex,
$results,
pagesIndex;
// Initialize lunrjs using our generated index file
function initLunr() {
// First retrieve the index file
$.getJSON("js/lunr/PagesIndex.json")
.done(function(index) {
pagesIndex = index;
console.log("index:", pagesIndex);
// Set up lunrjs by declaring the fields we use
// Also provide their boost level for the ranking
lunrIndex = lunr(function() {
this.field("title", {
boost: 10
});
this.field("tags", {
boost: 5
});
this.field("content");
// ref is the result item identifier (I chose the page URL)
this.ref("href");
});
// Feed lunr with each file and let lunr actually index them
pagesIndex.forEach(function(page) {
lunrIndex.add(page);
});
})
.fail(function(jqxhr, textStatus, error) {
var err = textStatus + ", " + error;
console.error("Error getting Hugo index flie:", err);
});
}
// Nothing crazy here, just hook up a listener on the input field
function initUI() {
$results = $("#results");
$("#search").keyup(function() {
$results.empty();
// Only trigger a search when 2 chars. at least have been provided
var query = $(this).val();
if (query.length < 2) {
return;
}
var results = search(query);
renderResults(results);
});
}
/**
* Trigger a search in lunr and transform the result
*
* @param {String} query
* @return {Array} results
*/
function search(query) {
// Find the item in our index corresponding to the lunr one to have more info
// Lunr result:
// {ref: "/section/page1", score: 0.2725657778206127}
// Our result:
// {title:"Page1", href:"/section/page1", ...}
return lunrIndex.search(query).map(function(result) {
return pagesIndex.filter(function(page) {
return page.href === result.ref;
})[0];
});
}
/**
* Display the 10 first results
*
* @param {Array} results to display
*/
function renderResults(results) {
if (!results.length) {
return;
}
// Only show the ten first results
results.slice(0, 10).forEach(function(result) {
var $result = $("<li>");
$result.append($("<a>", {
href: result.href,
text: "» " + result.title
}));
$results.append($result);
});
}
// Let's get started
initLunr();
$(document).ready(function() {
initUI();
});
But, the modified code include horsey.js. Horsey is a library that provide a tool of autocompleted to the search. The file sizes in the normal version <200Kb and in the minified version about >=20Kb!! In the next link will find examples and the source code of project: https://bevacqua.github.io/horsey/
If you want change something of the code, you must open the grunt task.
The structure of search index:
[
{
"title": "title1",
"tags": [
"word1",
"word2"
],
"url": "/en/installation-instructions/convertors/example-1",
"content": "something"
}
]...
You needs know that the most important in above file is what the javascript calls to each file depending of language and consults the variables:
title,
tags,
url,
content
Therefore, you needs define them into of the frontmatter of your content.
.
├── static
| └── json
| ├── search.cs.json (index to search)
| ├── search.de.json (index to search)
| ├── search.en.json (index to search)
| ├── search.es.json (index to search)
| ├── search.fr.json (index to search)
| ├── search.it.json (index to search)
| └── search.ru.json (index to search)
├── themes
| └── enectiva-faq
| └── layouts
| └── partials
| ├── base
| | └── metas.html (contains the javascript necessary)
| ├── internal
| | └── search.html (contains the search box)
The gruntfile has several tasks inside. How each tasks something I must explain them, feel you free of modify them:
- Build index and open dev server.
- Build index and build hugo site production.
- Build all indexes.
[sudo] grunt test
[sudo] grunt build
[sudo] grunt all-indexes
The website is built with multilingual mode. Provide to a site the ability to be multilingual is awesome but this same can be a problem for the development. Before, I must explain you some things:
- I have used data files for word translations. Into themes/enectiva-faq/data/locales/
- All partials includes the followings variables, with which will map the datas. Then, only you will needs to use $l., very useful:
{{ $lang := .Site.Language.Lang }}
{{ $l := index .Site.Data.locales $lang }}
- You can add all levels of map-strings that you needs. Only, you adds as many points as needed after of each word, i.e.:
{{ $l.<string1>.<string2>.<string3... }}
Example of a data file:
meta_description: 'Enectiva представляет собой веб-информационную систему, предназначенную для управления энергопотреблением офисных зданий, торговых центров и других коммерческих недвижимостей.'
meta_keywords: 'Enectiva, управление энергией, мониторинг энергии, энергосберегающие проекты, энергосбережение, мониторинг энергии, смарт измерения, дистанционное считывание показаний счетчиков'
menu:
toggle:
cs: CS
de: DE
en: EN
es: ES
fr: FR
it: IT
ru: RU
title:
cs: Чешский
de: Немецкий
en: Aнглийский
es: испанский
fr: Французский
it: итальянский
ru: русский
read_more: 'Подробнее '
tags: 'Теги:'
pagination:
next: 'Cледующий '
prev: ' Предыдущая'
rel_title: 'Cтатьи по теме'
search_placeholder: 'Поиск...'
404:
error: '404 Не Найдено'
message: "Что вы ищете не здесь, извините!"
back_home: 'Нажмите здесь, чтобы вернуться домой'
footer:
author_message: 'Решение по управлению энергией Enectiva было разработано компанией'
street_address: 'Drtinova 557/10'
address_locality: 'Прага 5'
All the content and site is written in multilingual. This require some additional configurations on some files, I am talking about the menu data files. Must take into account that these files have certains settings. See examples:
main_menu:
installations_instructions:
name: "Инструкция по установке"
URL: /ru/razdely/instruktsiya-po-ustanovke/
hide: false
weight: 01
meters:
name: Шлюзы
URL: /ru/razdely/instruktsiya-po-ustanovke/shlyuzy/
hide: false
weight: 01
sensors:
name: Mанометры
URL: /ru/razdely/instruktsiya-po-ustanovke/manometry/
hide: false
weight: 02
gateways:
name: датчиков
URL: /ru/razdely/instruktsiya-po-ustanovke/datchikov/
hide: false
weight: 03
convertors:
name: Преобразователи
URL: /ru/razdely/instruktsiya-po-ustanovke/preobrazovateli/
hide: false
weight: 04
splitters:
name: Сплиттеры
URL: /ru/razdely/instruktsiya-po-ustanovke/razvetviteli/
hide: false
weight: 05
concentrators:
name: Концентраторы
URL: /ru/razdely/instruktsiya-po-ustanovke/kontsentratory/
hide: false
weight: 06
manuals:
name: Руководства
URL: /ru/razdely/rukovodstva/
hide: false
weight: 02
meters:
name: Шлюзы
URL: /ru/razdely/rukovodstva/shlyuzy/
hide: false
weight: 01
sensors:
name: Mанометры
URL: /ru/razdely/rukovodstva/manometry/
hide: false
weight: 02
gateways:
name: датчиков
URL: /ru/razdely/rukovodstva/datchikov/
hide: false
weight: 03
convertors:
name: Преобразователи
URL: /ru/razdely/rukovodstva/preobrazovateli/
hide: false
weight: 04
splitters:
name: Сплиттеры
URL: /ru/razdely/rukovodstva/razvetviteli/
hide: false
weight: 05
concentrators:
name: Концентраторы
URL: /ru/razdely/rukovodstva/kontsentratory/
hide: false
weight: 06
tp_manuals:
name: "Pуководства третьего"
URL: /ru/razdely/rukovodstva-tret-yego/
hide: false
weight: 03
meters:
name: Шлюзы
URL: /ru/razdely/rukovodstva-tret-yego/shlyuzy/
hide: false
weight: 01
sensors:
name: Mанометры
URL: /ru/razdely/rukovodstva-tret-yego/manometry/
hide: false
weight: 02
gateways:
name: датчиков
URL: /ru/razdely/rukovodstva-tret-yego/datchikov/
hide: false
weight: 03
convertors:
name: Преобразователи
URL: /ru/razdely/rukovodstva-tret-yego/preobrazovateli/
hide: false
weight: 04
splitters:
name: Сплиттеры
URL: /ru/razdely/rukovodstva-tret-yego/razvetviteli/
hide: false
weight: 05
concentrators:
name: Концентраторы
URL: /ru/razdely/rukovodstva-tret-yego/kontsentratory/
hide: false
weight: 06
footer_menu:
partner_program:
name: "Партнерская программа"
URL: https://www.enectiva.cz/ru/partnerskaya-programma
hide: false
weight: 01
enectiva_rules:
name: "Правила компании Enectiva"
URL: https://www.enectiva.cz/ru/pravila-enectivy/
hide: false
weight: 02
dev_blog:
name: "Блог развития"
URL: https://developing.enectiva.cz/
hide: false
weight: 03
contact_us:
name: "Контакт"
URL: https://www.enectiva.cz/ru/svyazhites-s-nami
hide: false
weight: 04
The data files its found into root directory in the data folder, and are separated by each language. You will find the main menu and footer menu inside the files, follow the above structure to put new menu entries:
.
└── data
| └── locales
| | ├── cs.yaml
| | ├── de.yaml
| | ├── en.yaml
| | ├── es.yaml
| | ├── fr.yaml
| | ├── it.yaml
| | └── ru.yaml
| └── menu
| ├── cs.yaml
| ├── de.yaml
| ├── en.yaml
| ├── es.yaml
| ├── fr.yaml
| ├── it.yaml
| └── ru.yaml
If you wants to implement a new menu entry, needs to follow the above structure. Remark the use of the hide parameter, you can use it for hide menu. Last one, and for to implement the menu entry correctly, you must add a new line into main-menu.html layout.
Use of the variables:
- $i_i = installations_instructions
- $m = manuals
- $tp_m = tp_manuals
- If you wants to create one top-level menu, adds variable:
$string := $l.main_menu.<reference map string>
<li class="sub-menu"><a href="{{- $<top-level>.URL -}}" hreflang="{{ $lang }}">{{- $<top-level>.name -}}</a>
<ul class="sub">
<li class="{{ if eq $<top-level>.<sub-level>.hide true }}hide{{ end }}"><a href="" hreflang="{{ $lang }}"></a></li>
...
...
...
</ul>
</li>
When you wants to sort the menu, have that to use weight parameter. You have one in each section into of the menu data files.