diff --git a/.gitignore b/.gitignore
index f9720155956d16944e7c08a0b1a62d32a5268848..d8140ec3d2e487d051806e7976e9e9508248f949 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,6 +4,7 @@
 /dist
 /tmp
 /out-tsc
+/src/assets/docs-*
 
 # dependencies
 /node_modules
diff --git a/README.md b/README.md
index ac570727fdf5060fd9b44bda43ea8ffa68aba105..2af2e1c504bf0ba772f8d8c654ea305d23991c51 100644
--- a/README.md
+++ b/README.md
@@ -8,6 +8,15 @@ This can be done from the command line:
 
 `npm install -g typescript karma tslint`
 
+The documentation of Cassiopee needs to install MkDocs and some extensions:
+
+```sh
+sudo apt install python3-pip
+python3 -m pip install mkdocs
+python3 -m pip install python-markdown-math
+python3 -m pip install mkdocs-material
+```
+
 ### Install the necessary packages of the library:
 
 Clone or update the JalHyd project and in the JalHyd folder, run :
@@ -16,7 +25,7 @@ Clone or update the JalHyd project and in the JalHyd folder, run :
 
 Then, back to the ngHyd project folder, run :
 
-`npm install <path to the JalHyd folder>/jalhyd-<version>.tar.gz`
+`npm run jalhyd`
 
 and then :
 
@@ -141,7 +150,7 @@ and then :
 	- dans _src/app/calculators_ : créer un répertoire (par ex _ma-calculette_)
 
 	- dans _src/app/calculators/ma-calculette_ :
-	
+
 		Créer _ma-calculette.config.json_ sur le modèle des autres.
 		Les ids utilisés doivent correspondre au symbole fourni à classe _BaseParam_ (1er paramètre du constructeur)
 
@@ -151,7 +160,7 @@ and then :
 		- éventuellement le type de noeud de paramètres particuliers (objets comportant _"type":"input"_) avec le champ _"nodeType": "MaCalculetteBleue"_ (par défaut, "_ComputeNodeType.None_")
 
 	- dans _src/app/calculators/ma-calculette_ :
-	
+
 		Créer les fichiers d'internationalisation (_ma-calculette.&lt;langue&gt;.json_). Il doivent reprendre tous les ids utilisés dans le fichier de configuration et fournir leur traduction.
 
 * créer la classe du formulaire dans _src/app/formulaire/definition/concrete_
diff --git a/docs-fr/avant-propos.md b/docs-fr/avant-propos.md
new file mode 100644
index 0000000000000000000000000000000000000000..de56100f77a6fea591efe0429595a733dac0d78c
--- /dev/null
+++ b/docs-fr/avant-propos.md
@@ -0,0 +1,20 @@
+# Avant-Propos
+
+Concernant les passes à poissons, le logiciel CASSIOPEE doit être considéré comme un outil d'aide à la conception des passes à
+poissons.
+
+Son utilisateur doit être parfaitement familier de la technique de dimensionnement des passes à
+poissons.
+
+Dans le processus de mise au point d'une passe à poissons, la fonction de CASSIOPEE est de calculer
+certaines grandeurs caractérisant son fonctionnement et de présenter les résultats de façon claire et
+conviviale.
+
+Il ne peut évidemment répondre au problème de l'optimisation de l'implantation de l'ouvrage sur le
+site.
+
+Il convient à l'utilisateur de vérifier que le projet élaboré répond bien au problème posé et que toutes
+les conditions assurant sa franchissabilité sont satisfaites.
+
+En aucun cas l'AFB ou Irstea ne pourront être tenus responsables du mauvais fonctionnement
+d'un projet dimensionné avec CASSIOPEE.
diff --git a/src/app/calculators/regime-uniforme/regime-uniforme.fr.md b/docs-fr/calculators/hsl/regime_uniforme.md
similarity index 63%
rename from src/app/calculators/regime-uniforme/regime-uniforme.fr.md
rename to docs-fr/calculators/hsl/regime_uniforme.md
index 575281045929598b207dcb464a59e4cea8e4caab..09dc8c21024e562f994ad308c1183c5b30d8e793 100644
--- a/src/app/calculators/regime-uniforme/regime-uniforme.fr.md
+++ b/docs-fr/calculators/hsl/regime_uniforme.md
@@ -1,34 +1,37 @@
-Hydraulique à surface libre : le régime uniforme
-===
+# Le régime uniforme
+
 
 Le régime uniforme se caractérise par une hauteur d'eau appelée hauteur normale. La hauteur normale est atteinte quand la ligne d'eau est parallèle au fond, la charge est alors elle-même parallèle à la ligne d'eau et donc la perte de charge est égale à la pente du fond :
-$I_f = J$
+\(I_f = J\)
 
 Avec :
-- $I_f$ : la pente du fond en m/m
-- $J$ : la perte de charge en m/m
+
+- \(I_f\) : la pente du fond en m/m
+- \(J\) : la perte de charge en m/m
 
 La perte de charge {J} est ici calculée avec la formule de Manning-Strickler :
 
 $$J=\frac{U^2}{K^{2}R^{4/3}}=\frac{Q^2}{S^2K^{2}R^{4/3}}$$
 
 Avec :
-- $K$ : le coefficient de Strickler en m<sup>1/3</sup>/s
+
+- \(K\) : le coefficient de Strickler en m<sup>1/3</sup>/s
 
 En régime uniforme, on obtient la formule :
 
 $$Q=KR^{2/3}S\sqrt{I_f}$$
 
-A partir de laquelle, on peut calculer analytiquement le débit $Q$, la pente $I_f$ et le Strickler $K$ analytiquement.
+A partir de laquelle, on peut calculer analytiquement le débit \(Q\), la pente \(I_f\) et le Strickler \(K\) analytiquement.
 
-Pour calculer la hauteur normale $h_n$, on peut résoudre $f(h_n)=Q-KR^{2/3}S\sqrt{I_f}=0$
+Pour calculer la hauteur normale \(h_n\) , on peut résoudre \(f(h_n)=Q-KR^{2/3}S\sqrt{I_f}=0\)
 
 en utilisant la méthode de Newton :
 
 $$h_{k+1} = h_k - \frac{f(h_k)}{f'(h_k)}$$
 
  avec :
-- $f(h_k) = Q-KR^{2/3}S\sqrt{I_f}$
-- $f'(h_k) = -K \sqrt{I_f}(\frac{2}{3}R'R^{-1/3}S+R^{2/3}S')$
 
-Pour calculer les paramètres géométriques de la section, la calculette utilise l'équation de calcul du débit et résout le problème par dichotomie.
\ No newline at end of file
+- \(f(h_k) = Q-KR^{2/3}S\sqrt{I_f}\)
+- \(f'(h_k) = -K \sqrt{I_f}(\frac{2}{3}R'R^{-1/3}S+R^{2/3}S')\)
+
+Pour calculer les paramètres géométriques de la section, la calculette utilise l'équation de calcul du débit et résout le problème par dichotomie.
diff --git a/docs-fr/calculators/hyd_en_charge/cond_distri.md b/docs-fr/calculators/hyd_en_charge/cond_distri.md
new file mode 100644
index 0000000000000000000000000000000000000000..c89d7e8d85eb55865775a5656aed8fcff58b0322
--- /dev/null
+++ b/docs-fr/calculators/hyd_en_charge/cond_distri.md
@@ -0,0 +1,41 @@
+# Relation analytique pour le calcul direct des pertes de charge en conduite distribuant un débit de façon homogène établi à partir de la formule de Blasius.
+
+## Hypothèses
+
+![Schéma conduite](cond_distri.png)
+
+On suppose une conduite de longueur \(L\), diamètre intérieur \(D\), avec un débit en tête \(Q\). On calcule la perte de charge \(\Delta H\) entre les 2 extrémités de la conduite. Dans une section de débit \(q\) constant, on évalue le coefficient de frottement avec la formule de Blasius, valide pour des nombres de Reynolds modérés pour des parois lisses:
+$$\lambda \simeq a Re^{-0.25}$$
+
+## Développement analytique
+
+On note \(x\) la position depuis l'aval de la conduite. Le débit est supposé varier linéairement avec \(x\), et s'écrit alors:
+$$q(x)=Q x/L$$
+Notons \(S=\pi D^2/4\) la surface intérieure de la conduite.
+On obtient la perte de charge en intégrant la relation de Darcy-Weisbach:
+$$\Delta H=\int_{x=0}^{L} a Re^{-0.25} \frac{u^2(x)}{2gD}dx$$
+Notons \(\nu\) la viscosité cinématique. On remplace alors \(Re\) par \(u D/\nu\), ce qui donne
+$$\Delta H=\int_{x=0}^{L} a u(x)^{-0.25}D^{-0.25}\nu ^{0.25} \frac{u^2(x)}{2gD}dx$$
+En réarrangeant, on obtient:
+$$\Delta H=\int_{x=0}^{L} a \nu ^{0.25} \frac{u^{1.75}(x)}{2gD^{1.25}}dx$$
+Utilisons l'équation du débit pour faire apparaître le débit ($u(x)=q(x)/S$):
+$$\Delta H=\int_{x=0}^{L} a \nu ^{0.25} \frac{(Qx/(LS))^{1.75}}{2gD^{1.25}}dx$$
+puis le diamètre \(D\) :
+$$\Delta H=\int_{x=0}^{L} a \nu ^{0.25} \frac{(4Qx/(L\pi D^2))^{1.75}}{2gD^{1.25}}dx$$
+On réarrange pour obtenir
+$$\Delta H=a \nu ^{0.25} \frac{(4/\pi)^{1.75}Q^{1.75}}{2g D^{4.75}} \int_{x=0}^{L} (x/L)^{1.75}dx$$
+En intégrant, on obtient
+$$\Delta H=a \nu ^{0.25} \frac{(4/\pi)^{1.75}Q^{1.75}}{2g D^{4.75}}\frac{L}{2.75}$$
+$$\Delta H=a \nu ^{0.25} \frac{4^{1.75}}{5.5g \pi^{1.75}}\frac{Q^{1.75}L}{D^{4.75}}$$
+
+## Application numérique
+
+Pour une  eau à 20°C: \(\nu\simeq 10^{-6}\) m<sup>2</sup>/s, ce qui donne
+
+$$\Delta H=0.323\ 10^{-3}\frac{Q^{1.75}}{D^{4.75}}L$$
+
+avec \(\Delta H\) en mètres.
+
+Pour une eau à 50°C, \(\nu\simeq 0.556 10^{-6}\)  m<sup>2</sup>/s, ce qui implique que la perte de charge est réduite d'environ 14%, soit
+
+$$\Delta H= 0.28\ 10^{-3}\frac{Q^{1.75}}{D^{4.75}}L$$
diff --git a/src/assets/doc/cond-distri-1.png b/docs-fr/calculators/hyd_en_charge/cond_distri.png
similarity index 100%
rename from src/assets/doc/cond-distri-1.png
rename to docs-fr/calculators/hyd_en_charge/cond_distri.png
diff --git a/docs-fr/calculators/hyd_en_charge/lechapt-calmon.md b/docs-fr/calculators/hyd_en_charge/lechapt-calmon.md
new file mode 100644
index 0000000000000000000000000000000000000000..99c72fd492d16472e7584c02cfde57bf64294791
--- /dev/null
+++ b/docs-fr/calculators/hyd_en_charge/lechapt-calmon.md
@@ -0,0 +1,29 @@
+# Pertes de charge dans une conduite circulaire : abaques de Lechapt et Calmon
+
+La formule de Lechapt et Calmon est basée sur des ajustements de la formule de  [Cyril Frank Colebrook](http://fr.wikipedia.org/wiki/Cyril_Frank_Colebrook) :
+
+$$J=L.Q^M.D^{-N}$$
+
+Avec :
+
+- \(J\) : la perte de charge en mm/m ou m/km;
+- \(Q\) : le débit en L/s;
+- \(D\) : le diamètre de la conduite en m;
+- \(L\), \(M\) et \(N\) des coefficients dépendants de la rugosité {&#x3F5;}.
+
+L'erreur commise par rapport à la formule de Colebrook est inférieure à 3&nbsp;% pour des vitesses comprises entre 0,4 et 2 m/s.
+
+Le tableau de correspondance des coefficients est le suivant :
+
+
+| Matériau | &#x3F5; (mm) | \(L\) | \(M\) | \(N\) |
+|----------|-------------:|----:|----:|-----:|
+| Fonte ou acier non revêtus - Béton grossier (eau corrosive) | 2 | 1.863 | 2 | 5.33 |
+| Fonte ou acier non revêtus - Béton grossier (eau peu corrosive) | 1 | 1.601 | 1.975 | 5.25 |
+| Fonte ou acier revêtement ciment | 0.5 | 1.40 | 1.96 | 5.19 |
+| Fonte ou acier revêtement bitume - béton centrifugé | 0.25 | 1.16 | 1.93 | 5.11 |
+| Acier laminé - béton lisse | 0.1 | 1.10 | 1.89 | 5.01 |
+| Fonte ou acier revêtement centrifugé | 0.05 | 1.049 | 1.86 | 4.93 |
+| PVC - polyéthylène | 0.025 | 1.01 | 1.84 | 4.88 |
+| Tuyau hydrauliquement lisse - 0.05 &le; D &le; 0.2 | 0.00 | 0.916 | 1.78 | 4.78 |
+| Tuyau hydrauliquement lisse - 0.25 &le; D &le; 1 | 0.00 | 0.971 | 1.81 | 4.81 |
diff --git a/docs-fr/calculators/pab/cloisons.md b/docs-fr/calculators/pab/cloisons.md
new file mode 100644
index 0000000000000000000000000000000000000000..3d42b86118ac0699e4744217f47af56080a02219
--- /dev/null
+++ b/docs-fr/calculators/pab/cloisons.md
@@ -0,0 +1,41 @@
+# Cloisons
+
+Cet outil est une aide au prédimensionnement hydraulique d'une passe à bassins : il
+est utilisé le plus souvent pour le dimensionnement des échancrures, fentes, orifices
+caractérisant les cloisons d'une passe ainsi que pour le calage en altitude des échancrures,
+fentes et radier du bassin amont d'une passe.
+
+Il permet de calculer la valeur manquante des 7 valeurs caractérisant la chute, la surface
+de l'orifice noyé, la largeur de la fente, la charge sur la fente, la largeur de l'échancrure,
+la charge sur l'échancrure et le débit.
+
+Les données à fournir obligatoirement sont les dimensions des bassins (largeur et longueur) ainsi que le
+tirant d'eau moyen en mètres. Ces données associées à la chute entre bassins permettent de calculer [la puissance volumique dissipée](volume.md).
+
+## Ouvrages hydrauliques pouvant constituer la cloison
+
+L'outil permet de placer un ou plusieurs ouvrages en parallèle parmi les types d'ouvrages suivants:
+
+### Orifice noyé
+
+![Schéma orifice noyé](../structures/orifice_noye_schema.png)
+
+*Extrait de Larinier, M., Travade, F., Porcher, J.-P., Gosset, C., 1992. Passes à poissons : expertise et conception des ouvrages de franchissement. CSP. (page 94)*
+
+L'équation de l'orifice noyé est décrite sur [la page de la formule de l'orifice noyé](../structures/orifice_noye.md).
+
+### Fente noyée
+
+![Schéma de la fente noyée](../structures/fente_noyee_schema.png)
+
+*Extrait de Larinier, M., Travade, F., Porcher, J.-P., Gosset, C., 1992. Passes à poissons : expertise et conception des ouvrages de franchissement. CSP. (page 94)*
+
+L'équation de la fente noyée est décrite sur [la page de la formule de la fente noyée](../structures/fente_noyee.md).
+
+### Echancrure
+
+![Schéma de l'échancrure](../structures/echancrure_schema.png)
+
+*Extrait de Larinier, M., Travade, F., Porcher, J.-P., Gosset, C., 1992. Passes à poissons : expertise et conception des ouvrages de franchissement. CSP. (page 94)*
+
+L'équation utilisée pour l'échancrure est [celle de Kindsvater-Carter et Villemonte](../structures/kivi.md).
diff --git a/docs-fr/calculators/pab/dimensions.md b/docs-fr/calculators/pab/dimensions.md
new file mode 100644
index 0000000000000000000000000000000000000000..3d10d66add33a80a85f520dcee27b90a9b14e82c
--- /dev/null
+++ b/docs-fr/calculators/pab/dimensions.md
@@ -0,0 +1,13 @@
+# Passes à bassins : Dimensions
+
+Cet outil est une aide au dimensionnement des bassins d'une passe : il permet de
+calculer la valeur manquante des quatre grandeurs :
+
+- le volume d'eau (\(V\)) en m<sup>3</sup>;
+- le tirant d'eau moyen (\(Y_{moy}\)) en m;
+- la longueur du bassin (\(L\)) en m;
+- la largeur du bassin (\(B\)) en m.
+
+Le calcul est effectué en appliquant la formule :
+
+$$V = Y_{moy} \times L \times B$$
diff --git a/docs-fr/calculators/pab/volume.md b/docs-fr/calculators/pab/volume.md
new file mode 100644
index 0000000000000000000000000000000000000000..3f58f774b06cf7628d5752da1fc02f2b3ede7123
--- /dev/null
+++ b/docs-fr/calculators/pab/volume.md
@@ -0,0 +1,17 @@
+# Passes à bassins : Puissance dissipée
+
+Cet outil est une aide au prédimensionnement d'une passe à bassins : il permet de calculer la valeur manquante des quatre grandeurs :
+
+- la chute entre les bassins (\(\Delta H\)) en m;
+- le débit (\(Q\)) en m<sup>3</sup>/s;
+- le volume des bassins (\(V\)) en m<sup>3</sup>;
+- la puissance volumique dissipée (\(P_v\)) en W/m<sup>3</sup>.
+
+La formule de calcul de la puissance dissipée est alors :
+
+$$P_v = \frac{\rho \mathrm{g} Q \Delta H}{V}$$
+
+avec :
+
+- \(\rho\) : la masse volumique de l'eau;
+- \(\mathrm{g}\) : l'accélération de la gravité terrestre = 9,81 m.s<sup>-2</sup>
diff --git a/docs-fr/calculators/structures/echancrure_schema.png b/docs-fr/calculators/structures/echancrure_schema.png
new file mode 100644
index 0000000000000000000000000000000000000000..0c59f6160d1038653faf70c63b24b020df0d75c0
Binary files /dev/null and b/docs-fr/calculators/structures/echancrure_schema.png differ
diff --git a/docs-fr/calculators/structures/fente_noyee.md b/docs-fr/calculators/structures/fente_noyee.md
new file mode 100644
index 0000000000000000000000000000000000000000..d316dcf8798a0344b1b5f509bcd9f0e9949d8fca
--- /dev/null
+++ b/docs-fr/calculators/structures/fente_noyee.md
@@ -0,0 +1,19 @@
+# Formule de la fente noyée
+
+![Schéma de la fente noyée](fente_noyee_schema.png)
+
+*Extrait de Larinier, M., Travade, F., Porcher, J.-P., Gosset, C., 1992. Passes à poissons : expertise et conception des ouvrages de franchissement. CSP. (page 94)*
+
+Larinier (1992) propose l'équation suivante :
+
+$$Q = \mu b H_1\sqrt{2g \Delta H}$$
+
+Avec :
+
+* *b* la largeur de la fente en m&nbsp;
+* *H<sub>1</sub>* la charge sur la fente m&nbsp;
+* *μ* le coefficient de débit (égal à 0.65 par défaut).
+
+N.B. : la littérature propose plutôt la formule suivante:
+
+$$Q = \mu b H_2\sqrt{2g \Delta H}$$
diff --git a/docs-fr/calculators/structures/fente_noyee_schema.png b/docs-fr/calculators/structures/fente_noyee_schema.png
new file mode 100644
index 0000000000000000000000000000000000000000..66af5027ef1c910321ab5195f2c821a505563937
Binary files /dev/null and b/docs-fr/calculators/structures/fente_noyee_schema.png differ
diff --git a/docs-fr/calculators/structures/kivi.md b/docs-fr/calculators/structures/kivi.md
new file mode 100644
index 0000000000000000000000000000000000000000..fd2f16ef91c16e1abf74951946d735f4468e9756
--- /dev/null
+++ b/docs-fr/calculators/structures/kivi.md
@@ -0,0 +1,40 @@
+# Formule de Kindsvater-Carter et Villemonte
+
+
+La calculette permet d'effectuer des calculs hydrauliques pour plusieurs ouvrages en parallèle.
+
+## Formule de Kindsvater-Carter (1957)
+
+![Schéma déversoir](kivi_schema_seuil.png)
+
+La formule de Kindsvater-Carter correspond à la formule classique du déversoir :
+
+$$Q = \mu L \sqrt{2g}h_1^{1.5}$$
+
+Avec :
+
+- \(\mu\) le coefficient de débit \(\mu = \alpha + \beta h_1/p\)
+- \(L\) la largeur du déversoir
+- \(h_1\) la hauteur d'eau au dessus de la crête du déversoir
+- \(p\) la pelle ou hauteur de la crête du déversoir
+
+Les coefficient \(\alpha\) et \(\beta\) dépendent du rapport entre la largeur du déversoir (\(L\)) et la largeur du bassin (\(B\)). Leurs valeurs sont données par les abaques ci dessous (extrait de Larinier, M., Porcher, J.-P., 1986. Programmes de calcul sur HP86 : hydraulique et passes à poissons) :
+
+![Schéma déveroir](kivi_abaques_alpha_beta.png)
+
+## Écoulement noyé : formule de Villemonte (1947)
+
+![Schéma déversoir](kivi_villemonte_schema_seuil_noye.png)
+
+Pour une cote de l'eau aval supérieur à la cote de la crête du déversoir, l'écoulement est noyé et un coefficient de noyage s'applique sur le coefficient de débit.
+
+Villemonte propose la formule suivante :
+
+$$K = \frac{Q_{noyé}}{Q_{dénoyé}} = \left [ 1- \left ( \frac{h2}{h1} \right)^n \right]^{0.385}$$
+
+Avec :
+- \(h_1\)la hauteur d'eau amont au dessus de la crête du déversoir
+- \(h_2\)la hauteur d'eau aval au dessus de la crête du déversoir
+- \(n\)l'exposant dans les relations d'écoulement dénoyé (rectangulaire=1.5, triangulaire=2.5, parabolique=2)
+
+
diff --git a/src/assets/doc/structure_kivi_abaques_alpha_beta.png b/docs-fr/calculators/structures/kivi_abaques_alpha_beta.png
similarity index 100%
rename from src/assets/doc/structure_kivi_abaques_alpha_beta.png
rename to docs-fr/calculators/structures/kivi_abaques_alpha_beta.png
diff --git a/src/assets/doc/structure_kivi_schema_seuil.png b/docs-fr/calculators/structures/kivi_schema_seuil.png
similarity index 100%
rename from src/assets/doc/structure_kivi_schema_seuil.png
rename to docs-fr/calculators/structures/kivi_schema_seuil.png
diff --git a/src/assets/doc/structure_villemonte_schema_seuil_noye.png b/docs-fr/calculators/structures/kivi_villemonte_schema_seuil_noye.png
similarity index 100%
rename from src/assets/doc/structure_villemonte_schema_seuil_noye.png
rename to docs-fr/calculators/structures/kivi_villemonte_schema_seuil_noye.png
diff --git a/docs-fr/calculators/structures/orifice_noye.md b/docs-fr/calculators/structures/orifice_noye.md
new file mode 100644
index 0000000000000000000000000000000000000000..e8c11452e057a1a45e577d7144d385ce2afa6329
--- /dev/null
+++ b/docs-fr/calculators/structures/orifice_noye.md
@@ -0,0 +1,16 @@
+# Formule de l'orifice noyé
+
+![Schéma orifice noyé](orifice_noye_schema.png)
+
+*Extrait de Larinier, M., Travade, F., Porcher, J.-P., Gosset, C., 1992. Passes à poissons : expertise et conception des ouvrages de franchissement. CSP. (page 94)*
+
+L'équation correspond à peu de chose près à celle de la calculette de la vanne rectangulaire noyée à la différence près que la surface de l'orifice est donnée directement plutôt que par le rapport de la largeur avec la hauteur :
+
+$$Q = \mu S \sqrt{2g \Delta H}$$
+
+Avec :
+
+* *Q* le débit en m<sup>3</sup>/s&nbsp;;
+* *μ* le coefficient de débit (égal à 0.7 par défaut);
+* *S* la surface de l'orifice en m<sup>2</sup>&nbsp;;
+* *ΔH* La perte de charge *H<sub>1</sub> - H<sub>2</sub>* en m&nbsp;(noté "Chute" dans Cassiopée).
diff --git a/docs-fr/calculators/structures/orifice_noye_schema.png b/docs-fr/calculators/structures/orifice_noye_schema.png
new file mode 100644
index 0000000000000000000000000000000000000000..0c736b6cb07771451422ad1aa4d444a7bf45190e
Binary files /dev/null and b/docs-fr/calculators/structures/orifice_noye_schema.png differ
diff --git a/docs-fr/general/parametres_application.md b/docs-fr/general/parametres_application.md
new file mode 100644
index 0000000000000000000000000000000000000000..a86840fb856e3de11a2ca2741d879f4afaeb7e31
--- /dev/null
+++ b/docs-fr/general/parametres_application.md
@@ -0,0 +1,7 @@
+# Paramètres de l'application
+
+Accessible depuis le menu latéral gauche, les paramètres de l'application modifiables par l'utilisateur sont les suivants :
+
+- Précision d'affichage : Nombre de décimales affichées pour les résultats des calculs;
+- Précision de calcul : précision de calcul utilisée par défaut lors de la création d'un module de calcul;
+- Nombre d'itération de l'algorithme de résolution : pour les calculs résolus avec un algorithme de résolution, nombre d'itération maximum de l'algorithme.
diff --git a/docs-fr/general/principe_fonctionnement.md b/docs-fr/general/principe_fonctionnement.md
new file mode 100644
index 0000000000000000000000000000000000000000..702a1d9bca3410b23fa6d278b4f39179094ce23b
--- /dev/null
+++ b/docs-fr/general/principe_fonctionnement.md
@@ -0,0 +1,3 @@
+# Principe de fonctionnement du module de calcul
+
+Les modules de calcul de Cassiopée permettent chacun de résoudre une équation qui relie des paramètres entre eux.
\ No newline at end of file
diff --git a/docs-fr/index.md b/docs-fr/index.md
new file mode 100644
index 0000000000000000000000000000000000000000..4857c3de013c41789c3f95d0675df82b897163ef
--- /dev/null
+++ b/docs-fr/index.md
@@ -0,0 +1,12 @@
+# Présentation du logiciel Cassiopée
+
+## Caractéristiques générales
+
+Cassiopée est un logiciel consacré à l'hydraulique des rivières avec notamment l'aide au dimensionnement des passes à poissons, l'hydraulique agricole et l'hydraulique à surface libre en général. Il se présente sous la forme de modules de calcul indépendants permettant chacun de résoudre un problème donné. Les modules de calcul peuvent être enchaînés (des paramètres ou des résultats de calcul peuvent être "liés" entre modules) afin de réaliser des enchaînements de calculs complexe. L'utilisateur peut enregistrer localement les modules utilisés afin de les réutiliser ultérieurement.
+
+## Pré-requis - installation
+
+Cassiopée ne nécessite aucune installation. Il est disponible en ligne à partir d'un navigateur récent (testé sous Firefox, Chrome et Chromium) en se rendant à l'adresse suivante : [http://cassiopee.g-eau.net](http://cassiopee.g-eau.net)
+
+
+
diff --git a/mkdocs.yml b/mkdocs.yml
new file mode 100644
index 0000000000000000000000000000000000000000..49160968803b799412254dd3ecc515ca38cf01b9
--- /dev/null
+++ b/mkdocs.yml
@@ -0,0 +1,32 @@
+site_name: Documentation de Cassiopée
+site_author: Irstea
+docs_dir: docs-fr
+site_dir: src/assets/docs-fr/
+copyright: CC BY-NC-ND, Irstea 2018
+theme: material
+extra_javascript:
+    - ../mathjax/MathJax.js?config=TeX-AMS_CHTML
+markdown_extensions:
+    - mdx_math
+nav:
+    - avant-propos.md
+    - Présentation de Cassiopée:
+        - index.md
+        - general/principe_fonctionnement.md
+        - general/parametres_application.md
+    - Modules de calcul:
+        - Hydraulique en charge:
+            - Lechapt et Calmon: calculators/hyd_en_charge/lechapt-calmon.md
+            - Conduite distributrice: calculators/hyd_en_charge/cond_distri.md
+        - Hydraulique à surface libre:
+            - calculators/hsl/regime_uniforme.md
+        - Equations d'ouvrages:
+            - calculators/structures/kivi.md
+            - calculators/structures/orifice_noye.md
+            - calculators/structures/fente_noyee.md
+        - Passes à bassins:
+            - Volume: calculators/pab/volume.md
+            - Dimensions: calculators/pab/dimensions.md
+            - Cloisons: calculators/pab/cloisons.md
+
+
diff --git a/package-lock.json b/package-lock.json
index 43f4146dec4d3c6e85369b75fc169ed96337cb94..9af0d4098f6bf58fcb415e4d2bc95aa4dd1a859e 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -4624,7 +4624,7 @@
     },
     "jalhyd": {
       "version": "file:../jalhyd/jalhyd-1.0.0.tgz",
-      "integrity": "sha1-mc8VVFiB+OWUy8RNmswEUzFqIY0="
+      "integrity": "sha1-gdfKMrlkaftahQjkqq3syx0wRq0="
     },
     "jasmine": {
       "version": "2.8.0",
diff --git a/package.json b/package.json
index f60580ba3e15dfb4003f3411c32482b3ea0b23f9..27c899b8cbc62414165e839d3c2ea9a57f08c3d6 100644
--- a/package.json
+++ b/package.json
@@ -12,7 +12,8 @@
     "e2e": "ng e2e",
     "jalhyd": "rm -rf node_modules/jalhyd; cd ../jalhyd; npm run package; cd ../nghyd; npm install ../jalhyd/jalhyd-1.0.0.tgz;",
     "mathjax": "rsync -az --delete node_modules/mathjax src/assets;",
-    "preprocess": "node preprocessors.js; npm run mathjax;"
+    "mkdocs": "python3 -m mkdocs build",
+    "preprocess": "node preprocessors.js; npm run mathjax; npm run mkdocs;"
   },
   "private": true,
   "dependencies": {
diff --git a/src/app/app.component.html b/src/app/app.component.html
index 363c0282d1d747b5f7c1516afb875a37b6f642b9..3b1cd9241b28bf2965144f246e0cd758f90c7714 100644
--- a/src/app/app.component.html
+++ b/src/app/app.component.html
@@ -39,6 +39,7 @@
         <a (click)="newCalc()">{{uitextSidenavNewCalc}}</a>
         <a (click)="loadSession()">{{uitextSidenavLoadSession}}</a>
         <a (click)="params()">{{uitextSidenavParams}}</a>
+        <a target="_blank" href="assets/docs-fr/">Aide</a>
         <div class="hyd_fillvertical"></div>
         <div class="hyd_version">
           JaLHyd version: {{getDateRevision()[0]}}<br/>
diff --git a/src/app/app.component.ts b/src/app/app.component.ts
index 0b99edebc8b27883d40cd50854fe8842a96b0ea3..c77905939e8e8f0300f0a338f52e7979d3f4338d 100644
--- a/src/app/app.component.ts
+++ b/src/app/app.component.ts
@@ -14,8 +14,6 @@ import { ServiceFactory } from "./services/service-factory";
 import { ParamService } from "./services/param/param.service";
 import { ApplicationSetupService } from "./services/app-setup/app-setup.service";
 import { HttpService } from "./services/http/http.service";
-import { HelpService } from "./services/help/help.service";
-import { HelpComponent } from "./components/help/help.component";
 import { LoadCalcDialogAnchorDirective } from "./components/load-calculator/load-calculator-anchor.directive";
 import { LoadCalculatorComponent } from "./components/load-calculator/load-calculator.component";
 import { SaveCalcDialogAnchorDirective } from "./components/save-calculator/save-calculator-anchor.directive";
@@ -64,14 +62,13 @@ export class AppComponent implements OnInit, OnDestroy, Observer {
     private route: ActivatedRoute,
     private formulaireService: FormulaireService,
     private httpService: HttpService,
-    private helpService: HelpService
+
   ) {
     ServiceFactory.instance.applicationSetupService = appSetupService;
     ServiceFactory.instance.paramService = paramService;
     ServiceFactory.instance.internationalisationService = intlService;
     ServiceFactory.instance.formulaireService = formulaireService;
     ServiceFactory.instance.httpService = httpService;
-    ServiceFactory.instance.helpService = helpService;
   }
 
   // process.on('unhandledRejection', (reason, p) => {
@@ -182,9 +179,6 @@ export class AppComponent implements OnInit, OnDestroy, Observer {
         case "nameChanged":
           this.updateCalculatorTitle(sender, data["name"]);
           break;
-
-        case "requestHelp":
-          this.toHelp(sender);
       }
     }
   }
@@ -304,14 +298,6 @@ export class AppComponent implements OnInit, OnDestroy, Observer {
     this.router.navigate(["/calculator", id]);
   }
 
-  private toHelp(form: FormulaireDefinition) {
-    // Activated.firstChild.component : type du composant actuellement affiché par le router outlet
-    this.router.navigate(["/help"]).then(_ => {
-      const helpComp = this._routerCurrentComponent as HelpComponent;
-      helpComp.formHelp = form;
-    });
-  }
-
   /**
    * récupération du composant affiché par le routeur
    */
diff --git a/src/app/app.module.ts b/src/app/app.module.ts
index e321e272cf02f8ba7ee16b95e8c7bd361c370e5a..eb63671d15c121775de4ba6f5cc5e8717bfc8d05 100644
--- a/src/app/app.module.ts
+++ b/src/app/app.module.ts
@@ -48,8 +48,6 @@ import { ResultElementBaseComponent } from "./components/result-element/result-e
 import { HorizontalResultElementComponent } from "./components/result-element/horizontal-result-element.component";
 import { VerticalResultElementComponent } from "./components/result-element/vertical-result-element.component";
 import { LogEntryComponent } from "./components/log-entry/log-entry.component";
-import { HelpService } from "./services/help/help.service";
-import { HelpComponent } from "./components/help/help.component";
 import { LoadCalculatorComponent } from "./components/load-calculator/load-calculator.component";
 import { LoadCalcDialogAnchorDirective } from "./components/load-calculator/load-calculator-anchor.directive";
 import { SaveCalculatorComponent } from "./components/save-calculator/save-calculator.component";
@@ -60,7 +58,6 @@ const appRoutes: Routes = [
   { path: "list", component: CalculatorListComponent },
   { path: "calculator/:uid", component: GenericCalculatorComponent },
   { path: "setup", component: ApplicationSetupComponent },
-  { path: "help", component: HelpComponent },
   { path: "**", component: CalculatorListComponent }
 ];
 
@@ -100,7 +97,6 @@ const appRoutes: Routes = [
     CalcCanvasComponent, SectionCanvasComponent,
     ResultElementBaseComponent, HorizontalResultElementComponent, VerticalResultElementComponent,
     FixedResultsComponent, VarResultsComponent,
-    HelpComponent,
     LoadCalculatorComponent, LoadCalcDialogAnchorDirective,
     SaveCalculatorComponent, SaveCalcDialogAnchorDirective,
     ParamLinkComponent
@@ -108,7 +104,7 @@ const appRoutes: Routes = [
   // entryComponents: [AlertDialog],
   entryComponents: [LoadCalculatorComponent, SaveCalculatorComponent],
   providers: [ // services
-    ParamService, InternationalisationService, HttpService, FormulaireService, ApplicationSetupService, HelpService
+    ParamService, InternationalisationService, HttpService, FormulaireService, ApplicationSetupService
   ],
   schemas: [NO_ERRORS_SCHEMA],
   bootstrap: [AppComponent]
diff --git a/src/app/calculators/cloisons/cloisons.config.json b/src/app/calculators/cloisons/cloisons.config.json
index cbb86479f40cc9e266a1369375eb776bdc0ef2e8..958fb294bb8cdd912ebb25719735fcd06216e485 100644
--- a/src/app/calculators/cloisons/cloisons.config.json
+++ b/src/app/calculators/cloisons/cloisons.config.json
@@ -199,6 +199,7 @@
     {
         "type": "options",
         "ouvrageSelectId": "select_ouvrage",
-        "idCal": "Q"
+        "idCal": "Q",
+        "help": "pab/cloisons"
     }
 ]
\ No newline at end of file
diff --git a/src/app/calculators/cond_distri/cond_distri.config.json b/src/app/calculators/cond_distri/cond_distri.config.json
index 81b10e531eba426c57bfd5f6b8d4e5206d8ab3b5..2ff24f844f130da9af660a321b0813c116931e06 100644
--- a/src/app/calculators/cond_distri/cond_distri.config.json
+++ b/src/app/calculators/cond_distri/cond_distri.config.json
@@ -44,6 +44,7 @@
     },
     {
         "type": "options",
-        "idCal": "J"
+        "idCal": "J",
+        "help": "hyd_en_charge/cond_distri"
     }
 ]
\ No newline at end of file
diff --git a/src/app/calculators/cond_distri/cond_distri.fr.md b/src/app/calculators/cond_distri/cond_distri.fr.md
deleted file mode 100644
index 79a816b34705c86574e68a05289b5eba51c4f9fe..0000000000000000000000000000000000000000
--- a/src/app/calculators/cond_distri/cond_distri.fr.md
+++ /dev/null
@@ -1,39 +0,0 @@
-Relation analytique pour le calcul direct des pertes de charge en conduite distribuant un débit de façon homogène établi à partir de la formule de Blasius.
-===
-
-Hypothèses
----
-
-![Schéma conduite](assets/doc/cond-distri-1.png)
-
-On suppose une conduite de longueur $L$, diamètre intérieur $D$, avec un débit en tête $Q$. On calcule la perte de charge $\Delta H$ entre les 2 extrémités de la conduite. Dans une section de débit $q$ constant, on évalue le coefficient de frottement avec la formule de Blasius, valide pour des nombres de Reynolds modérés pour des parois lisses:
-$$\lambda \simeq a Re^{-0.25}$$
-
-Développement analytique
----
-On note $x$ la position depuis l'aval de la conduite. Le débit est supposé varier linéairement avec $x$, et s'écrit alors:
-$$q(x)=Q x/L$$
-Notons $S=\pi D^2/4$ la surface intérieure de la conduite.
-On obtient la perte de charge en intégrant la relation de Darcy-Weisbach:
-$$\Delta H=\int_{x=0}^{L} a Re^{-0.25} \frac{u^2(x)}{2gD}dx$$
-Notons $\nu$ la viscosité cinématique. On remplace alors $Re$ par $u D/\nu$, ce qui donne
-$$\Delta H=\int_{x=0}^{L} a u(x)^{-0.25}D^{-0.25}\nu ^{0.25} \frac{u^2(x)}{2gD}dx$$
-En réarrangeant, on obtient:
-$$\Delta H=\int_{x=0}^{L} a \nu ^{0.25} \frac{u^{1.75}(x)}{2gD^{1.25}}dx$$
-Utilisons l'équation du débit pour faire apparaître le débit ($u(x)=q(x)/S$):
-$$\Delta H=\int_{x=0}^{L} a \nu ^{0.25} \frac{(Qx/(LS))^{1.75}}{2gD^{1.25}}dx$$
-puis le diamètre $D$:
-$$\Delta H=\int_{x=0}^{L} a \nu ^{0.25} \frac{(4Qx/(L\pi D^2))^{1.75}}{2gD^{1.25}}dx$$
-On réarrange pour obtenir
-$$\Delta H=a \nu ^{0.25} \frac{(4/\pi)^{1.75}Q^{1.75}}{2g D^{4.75}} \int_{x=0}^{L} (x/L)^{1.75}dx$$
-En intégrant, on obtient
-$$\Delta H=a \nu ^{0.25} \frac{(4/\pi)^{1.75}Q^{1.75}}{2g D^{4.75}}\frac{L}{2.75} $$
-$$\Delta H=a \nu ^{0.25} \frac{4^{1.75}}{5.5g \pi^{1.75}}\frac{Q^{1.75}L}{D^{4.75}} $$
-
-Application numérique
----
-Pour une  eau à 20°C: $\nu\simeq 10^{-6}m^2/s$, ce qui donne
-$$\Delta H=0.323\ 10^{-3}\frac{Q^{1.75}}{D^{4.75}}L $$
-avec $\Delta H$ en mètres.
-Pour une eau à 50°C, $\nu\simeq 0.556 10^{-6}m^2/s$, ce qui implique que la perte de charge est réduite d'environ 14%, soit
-$$\Delta H= 0.28\ 10^{-3}\frac{Q^{1.75}}{D^{4.75}}L $$
diff --git a/src/app/calculators/lechapt-calmon/lechapt-calmon.config.json b/src/app/calculators/lechapt-calmon/lechapt-calmon.config.json
index 1fecb054d02f6716279b7920a5118f6e1b7f320c..b2bf6dac92a98fac7570a238c91511713b3c4902 100644
--- a/src/app/calculators/lechapt-calmon/lechapt-calmon.config.json
+++ b/src/app/calculators/lechapt-calmon/lechapt-calmon.config.json
@@ -235,6 +235,7 @@
     },
     {
         "type": "options",
-        "idCal": "J"
+        "idCal": "J",
+        "help": "hyd_en_charge/lechapt-calmon"
     }
 ]
\ No newline at end of file
diff --git a/src/app/calculators/pab-dimensions/pab-dimensions.config.json b/src/app/calculators/pab-dimensions/pab-dimensions.config.json
index 55dd4639c80a5305aad102d0bf019687f368444f..a199a643e2bbc121ee4aecfe009231d85a13b773 100644
--- a/src/app/calculators/pab-dimensions/pab-dimensions.config.json
+++ b/src/app/calculators/pab-dimensions/pab-dimensions.config.json
@@ -28,6 +28,7 @@
     },
     {
         "type": "options",
-        "idCal": "V"
+        "idCal": "V",
+        "help": "pab/dimensions"
     }
 ]
\ No newline at end of file
diff --git a/src/app/calculators/pab-puissance/pab-puissance.config.json b/src/app/calculators/pab-puissance/pab-puissance.config.json
index 5806d41c5c7acc2524cb23aa96a08fb1ed5e11b9..02be79b11ba132980d988ec2f5b2d2db680e99a3 100644
--- a/src/app/calculators/pab-puissance/pab-puissance.config.json
+++ b/src/app/calculators/pab-puissance/pab-puissance.config.json
@@ -39,6 +39,7 @@
     },
     {
         "type": "options",
-        "idCal": "PV"
+        "idCal": "PV",
+        "help": "pab/volume"
     }
 ]
\ No newline at end of file
diff --git a/src/app/calculators/parallel-structures/parallel-structures.fr.md b/src/app/calculators/parallel-structures/parallel-structures.fr.md
deleted file mode 100644
index 5b9f5c17db18810bb85f3600532149851091e91b..0000000000000000000000000000000000000000
--- a/src/app/calculators/parallel-structures/parallel-structures.fr.md
+++ /dev/null
@@ -1,38 +0,0 @@
-# Lois de débit sur les ouvrages
-
-La calculette permet d'effectuer des calculs hydrauliques pour plusieurs ouvrages en parallèle.
-
-## Formule de Kindsvater-Carter et Villemonte (1957)
-
-![Schéma déversoir](assets/doc/structure_kivi_schema_seuil.png)
-
-La formule de Kindsvater-Carter correspond à la formule classique du déversoir :
-
-$$Q = \mu L \sqrt{2g}h_1^{1.5}$$
-
-Avec :
-- $\mu$ le coefficient de débit $\mu = \alpha + \beta h_1/p$
-- $L$ la largeur du déversoir
-- $h_1$ la hauteur d'eau au dessus de la crête du déversoir
-- $p$ la pelle ou hauteur de la crête du déversoir
-
-Les coefficient $\alpha$ et $\beta$ dépendent du rapport entre la largeur du déversoir ($L$) et la largeur du bassin ($B$). Leurs valeurs sont données par les abaques ci dessous (extrait de Larinier, M., Porcher, J.-P., 1986. Programmes de calcul sur HP86 : hydraulique et passes à poissons) :
-
-![Schéma déveroir](assets/doc/structure_kivi_abaques_alpha_beta.png)
-
-## Écoulement noyé : formule de Villemonte (1947)
-
-![Schéma déversoir](assets/doc/structure_villemonte_schema_seuil_noye.png)
-
-Pour une cote de l'eau aval supérieur à la cote de la crête du déversoir, l'écoulement est noyé et un coefficient de noyage s'applique sur le coefficient de débit.
-
-Villemonte propose la formule suivante :
-
-$$ K = \frac{Q_{noyé}}{Q_{dénoyé}} = \left [ 1- \left ( \frac{h2}{h1} \right)^n \right]^{0.385} $$
-
-Avec :
-- $h_1$ la hauteur d'eau amont au dessus de la crête du déversoir
-- $h_2$ la hauteur d'eau aval au dessus de la crête du déversoir
-- $n$ l'exposant dans les relations d'écoulement dénoyé (rectangulaire=1.5, triangulaire=2.5, parabolique=2)
-
-
diff --git a/src/app/calculators/regime-uniforme/regime-uniforme.config.json b/src/app/calculators/regime-uniforme/regime-uniforme.config.json
index 32b228708f7e6cf71005f670a1e06626f8f53244..4fa4f5f2537ab10da492fd033f8e8e2aca373663 100644
--- a/src/app/calculators/regime-uniforme/regime-uniforme.config.json
+++ b/src/app/calculators/regime-uniforme/regime-uniforme.config.json
@@ -154,6 +154,7 @@
         "type": "options",
         "defaultNodeType": "SectionRectangle",
         "idCal": "Q",
-        "sectionSourceId": "fs_section"
+        "sectionSourceId": "fs_section",
+        "help": "regime_uniforme"
     }
 ]
\ No newline at end of file
diff --git a/src/app/components/generic-calculator/calculator.component.ts b/src/app/components/generic-calculator/calculator.component.ts
index 33b638a8dc90a97b694f4105128826d2725a668f..27f97b259263fcfe81cecbec93eca802f2ec02f2 100644
--- a/src/app/components/generic-calculator/calculator.component.ts
+++ b/src/app/components/generic-calculator/calculator.component.ts
@@ -15,7 +15,6 @@ import { CalculatorNameComponent } from "./calc-name.component";
 import { FormulaireElement } from "../../formulaire/formulaire-element";
 import { FieldsetContainer } from "../../formulaire/fieldset-container";
 import { FieldsetContainerComponent } from "../fieldset-container/fieldset-container.component";
-import { HelpService } from "../../services/help/help.service";
 import { ServiceFactory } from "../../services/service-factory";
 
 @Component({
@@ -85,13 +84,11 @@ export class GenericCalculatorComponent extends BaseComponent implements OnInit,
 
     private intlService: InternationalisationService;
     private formulaireService: FormulaireService;
-    private helpService: HelpService;
 
     constructor(private route: ActivatedRoute) {
         super();
         this.intlService = ServiceFactory.instance.internationalisationService;
         this.formulaireService = ServiceFactory.instance.formulaireService;
-        this.helpService = ServiceFactory.instance.helpService;
     }
 
     private get formElements(): FormulaireElement[] {
@@ -120,15 +117,16 @@ export class GenericCalculatorComponent extends BaseComponent implements OnInit,
     }
 
     private get hasResults() {
-        if (this.hasForm)
+        if (this.hasForm) {
             return this._formulaire.hasResults;
+        }
         return false;
     }
 
     private get uitextTitre() {
-        if (this.hasForm)
+        if (this.hasForm) {
             return this.formulaireService.getLocalisedTitleFromCalculatorType(this._formulaire.calculatorType);
-
+        }
         return undefined;
     }
 
@@ -246,8 +244,9 @@ export class GenericCalculatorComponent extends BaseComponent implements OnInit,
 
     private scrollToResults() {
         const element = document.getElementById("resultsComp");
-        if (element)
+        if (element) {
             element.scrollIntoView();
+        }
     }
 
     private getFieldsetStyleDisplay(id: string) {
@@ -256,16 +255,19 @@ export class GenericCalculatorComponent extends BaseComponent implements OnInit,
     }
 
     private setForm(f: FormulaireDefinition) {
-        if (this._formulaire !== undefined)
+        if (this._formulaire !== undefined) {
             this._formulaire.removeObserver(this);
+        }
         this._formulaire = f;
-        if (this._formulaire !== undefined)
+        if (this._formulaire !== undefined) {
             this._formulaire.addObserver(this);
+        }
     }
 
     private updateFormulaireResults(uid: number) {
-        if (this._formulaire.uid === uid)
+        if (this._formulaire.uid === uid) {
             this.resultsComponent.updateView();
+        }
     }
 
     // interface Observer
@@ -273,7 +275,6 @@ export class GenericCalculatorComponent extends BaseComponent implements OnInit,
     update(sender: any, data: any): void {
         if (sender instanceof InternationalisationService) {
             this.formulaireService.updateLocalisation();
-            this._formulaire.updateHelp();
         } else if (sender instanceof FormulaireService) {
             switch (data["action"]) {
                 case "currentFormChanged":
@@ -312,7 +313,7 @@ export class GenericCalculatorComponent extends BaseComponent implements OnInit,
     private updateUIValidity() {
         this._isUIValid = false;
 
-        if (this._fieldsetComponents !== undefined)
+        if (this._fieldsetComponents !== undefined) {
             this._isUIValid = this._fieldsetComponents.reduce(
                 // callback
                 (
@@ -329,8 +330,8 @@ export class GenericCalculatorComponent extends BaseComponent implements OnInit,
                 }
                 // valeur initiale
                 , this._fieldsetComponents.length > 0);
-
-        if (this._fieldsetContainerComponents !== undefined)
+        }
+        if (this._fieldsetContainerComponents !== undefined) {
             this._isUIValid = this._isUIValid && this._fieldsetContainerComponents.reduce(
                 // callback
                 (
@@ -347,6 +348,7 @@ export class GenericCalculatorComponent extends BaseComponent implements OnInit,
                 }
                 // valeur initiale
                 , true);
+        }
     }
 
     /**
@@ -374,13 +376,14 @@ export class GenericCalculatorComponent extends BaseComponent implements OnInit,
      * flag d'affichage du bouton d'aide
      */
     private get enableHelpButton() {
-        if (this._formulaire)
-            return this._formulaire.helpText !== undefined;
+        if (this._formulaire) {
+            return this._formulaire.helpLink !== undefined;
+        }
         return false;
     }
 
     private openHelp() {
-        this._formulaire.requestHelp();
+        window.open("assets/docs-fr/calculators/" + this._formulaire.helpLink + "/", "_blank");
     }
 
     private saveCalculator() {
diff --git a/src/app/components/help/help.component.html b/src/app/components/help/help.component.html
deleted file mode 100644
index 797719a05539a2aa3e081a6dc29bb26a6f05f085..0000000000000000000000000000000000000000
--- a/src/app/components/help/help.component.html
+++ /dev/null
@@ -1,7 +0,0 @@
-<div class="container-fluid">
-    <div class="row">
-        <div class="col">
-            <markdown> {{textData}} </markdown>
-        </div>
-    </div>
-</div>
\ No newline at end of file
diff --git a/src/app/components/help/help.component.ts b/src/app/components/help/help.component.ts
deleted file mode 100644
index 81e968eb8b6355675d469e7dbf3496aa6d72b7d4..0000000000000000000000000000000000000000
--- a/src/app/components/help/help.component.ts
+++ /dev/null
@@ -1,40 +0,0 @@
-import { Component, AfterViewInit } from "@angular/core";
-
-/*
-  tient lieu d'import quand on n'installe pas de paquet npm pour MathJax et qu'on le récupère
-  par l'index.html :
-   <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js?config=TeX-AMS_CHTML"></script>
-*/
-declare var MathJax: any;
-
-import { FormulaireDefinition } from "../../formulaire/definition/form-definition";
-
-@Component({
-    selector: 'help',
-    templateUrl: "./help.component.html",
-})
-export class HelpComponent implements AfterViewInit {
-    /**
-     * texte de l'aide
-     */
-    private textData: string;
-
-    /**
-     * fixe le texte de l'aide d'après un formulaire
-     */
-    public set formHelp(f: FormulaireDefinition) {
-        this.textData = f.helpText;
-    }
-
-    /**
-     * MAJ des expressions LateX présentes dans le composant par MathJax
-     */
-    private updateMathjax() {
-        //     MathJax.Hub.Queue(["Typeset", MathJax.Hub]);
-        MathJax.Hub.Typeset();
-    }
-
-    public ngAfterViewInit() {
-        this.updateMathjax();
-    }
-}
diff --git a/src/app/formulaire/definition/form-definition.ts b/src/app/formulaire/definition/form-definition.ts
index d499c62bc9fa7702d78a7f5d8ad96348b3e63c33..b18706b2a4b539282dcb5072a62932ea4468d4e7 100644
--- a/src/app/formulaire/definition/form-definition.ts
+++ b/src/app/formulaire/definition/form-definition.ts
@@ -42,7 +42,7 @@ export abstract class FormulaireDefinition extends FormulaireNode implements Obs
     /**
      * aide en ligne
      */
-    private _helpText: string;
+    private _helpLink: string;
 
     protected _paramService: ParamService;
 
@@ -71,7 +71,7 @@ export abstract class FormulaireDefinition extends FormulaireNode implements Obs
             "action": "nameChanged",
             "name": name
         },
-            this)
+            this);
     }
 
     public get jsonConfig(): {} {
@@ -91,8 +91,11 @@ export abstract class FormulaireDefinition extends FormulaireNode implements Obs
     }
 
     public set currentSessionNub(n: SessionNub) {
-        if (this._props["calcType"] !== n.properties.getPropValue("calcType"))
-            throw new Error(`Nub ${n.properties["calcType"]} incompatible avec le formulaire ${this._calculatorName} (${this._props["calcType"]})`);
+        if (this._props["calcType"] !== n.properties.getPropValue("calcType")) {
+            throw new Error(
+                `Nub ${n.properties["calcType"]} incompatible avec le formulaire ${this._calculatorName} (${this._props["calcType"]})`
+            );
+        }
         this._currentSessionNub = n;
     }
 
@@ -110,8 +113,9 @@ export abstract class FormulaireDefinition extends FormulaireNode implements Obs
      */
     protected getSessionNub(params: Props | {}): SessionNub {
         let res = this.findNub(params);
-        if (!res)
+        if (!res) {
             res = this.createSessionNub(params);
+        }
         return res;
     }
 
@@ -129,12 +133,13 @@ export abstract class FormulaireDefinition extends FormulaireNode implements Obs
      * @param params paramètres de contexte de création du nub
      */
     protected getNubParamFromSymbol(symbol: string, params: Props | {}): ParamDefinition {
-        let sessionNub: SessionNub = this.getSessionNub(params);
+        const sessionNub: SessionNub = this.getSessionNub(params);
 
-        if (sessionNub)
+        if (sessionNub) {
             return sessionNub.nub.getParameter(symbol);
+        }
 
-        throw new Error(`FormulaireDefinition.getNubParamFromSymbol() : pas de Nub trouvé pour ${params}`)
+        throw new Error(`FormulaireDefinition.getNubParamFromSymbol() : pas de Nub trouvé pour ${params}`);
     }
 
     protected deleteSessionNub(sn: SessionNub) {
@@ -147,14 +152,16 @@ export abstract class FormulaireDefinition extends FormulaireNode implements Obs
     protected parseOptions(json: {}) {
         const dnt = json["defaultNodeType"];
         this._props["nodeType"] = dnt === undefined ? ComputeNodeType.None : ComputeNodeType[dnt];
+        this.helpLink = json["help"];
     }
 
     protected completeParse(json: {}) {
     }
 
     public getOption(json: {}, option: string): string {
-        if (json["type"] === "options")
+        if (json["type"] === "options") {
             return json[option];
+        }
 
         return undefined;
     }
@@ -191,7 +198,8 @@ export abstract class FormulaireDefinition extends FormulaireNode implements Obs
     }
 
     public parseDependencies(json: {}) {
-        for (let conf_index in json) {
+        // tslint:disable-next-line:forin
+        for (const conf_index in json) {
             const conf = json[conf_index];
             const type: string = conf["type"];
 
@@ -199,17 +207,20 @@ export abstract class FormulaireDefinition extends FormulaireNode implements Obs
                 // field set
                 case "fieldset":
                 case "template_container":
-                    for (const k of this.kids)
-                        if (k.id == conf["id"]) {
+                    for (const k of this.kids) {
+                        if (k.id === conf["id"]) {
                             k.parseDependencies(conf);
                             break;
                         }
+                    }
                     break;
 
                 case "fieldset_template":
-                    for (const k of this.kids)
-                        if (k instanceof FieldsetContainer)
+                    for (const k of this.kids) {
+                        if (k instanceof FieldsetContainer) {
                             k.parseDependencies(conf);
+                        }
+                    }
                     break;
             }
         }
@@ -224,9 +235,11 @@ export abstract class FormulaireDefinition extends FormulaireNode implements Obs
         this.initParse();
 
         // analyse des options globales
-        // il est utile de le faire avant le reste pour les calculettes utilisant des sections (id des selects type de section/variable à calculer)
+        // il est utile de le faire avant le reste pour les calculettes utilisant
+        // des sections (id des selects type de section/variable à calculer)
 
-        for (let conf_index in json) {
+        // tslint:disable-next-line:forin
+        for (const conf_index in json) {
             const conf = json[conf_index];
             const type: string = conf["type"];
 
@@ -241,14 +254,15 @@ export abstract class FormulaireDefinition extends FormulaireNode implements Obs
      * 2ème passe d'analyse de la configuration
      */
     public parseConfig(json: {}) {
-        if (json !== undefined)
+        if (json !== undefined) {
             this._jsonConfig = json;
+        }
 
         // analyse des éléments du formulaire
-
         const templates: any[] = [];
 
-        for (let conf_index in this._jsonConfig) {
+        // tslint:disable-next-line:forin
+        for (const conf_index in this._jsonConfig) {
             const conf = this._jsonConfig[conf_index];
             const type: string = conf["type"];
 
@@ -292,50 +306,59 @@ export abstract class FormulaireDefinition extends FormulaireNode implements Obs
 
     public hasParameter(symbol: string): boolean {
         for (const p of this.allFormElements) {
-            if (p instanceof NgParameter)
-                if (p.symbol === symbol)
+            if (p instanceof NgParameter) {
+                if (p.symbol === symbol) {
                     return true;
+                }
+            }
         }
         return false;
     }
 
     public getParamFromSymbol(symbol: string): NgParameter {
         for (const p of this.allFormElements) {
-            if (p instanceof NgParameter)
-                if (p.symbol === symbol)
+            if (p instanceof NgParameter) {
+                if (p.symbol === symbol) {
                     return p;
+                }
+            }
         }
         return undefined;
     }
 
     public getDisplayedParamFromState(st: ParamRadioConfig): NgParameter {
         for (const p of this.allFormElements) {
-            if (p.isDisplayed && p instanceof NgParameter)
-                if (p.radioState == st)
+            if (p.isDisplayed && p instanceof NgParameter) {
+                if (p.radioState === st) {
                     return p;
+                }
+            }
         }
         return undefined;
     }
 
     public getDisplayedParamListFromState(st: ParamRadioConfig): NgParameter[] {
         const res = [];
-        for (const p of this.allFormElements)
-            if (p.isDisplayed && p instanceof NgParameter && p.radioState == st)
-                res.push(p)
+        for (const p of this.allFormElements) {
+            if (p.isDisplayed && p instanceof NgParameter && p.radioState === st) {
+                res.push(p);
+            }
+        }
         return res;
     }
 
     public getFieldById(id: string): Field {
-        let res = this.getFormulaireNodeById(id);
-        if (res instanceof Field)
+        const res = this.getFormulaireNodeById(id);
+        if (res instanceof Field) {
             return res;
+        }
         return undefined;
     }
 
     public getParameterValue(symbol: string): number {
         for (const fs of this.allFieldsets) {
             const p = fs.getNodeParameter(symbol);
-            if (p != undefined)
+            if (p !== undefined) {
                 switch (p.radioState) {
                     case ParamRadioConfig.FIX:
                         return p.getValue();
@@ -344,6 +367,7 @@ export abstract class FormulaireDefinition extends FormulaireNode implements Obs
                     case ParamRadioConfig.CAL:
                         return undefined;
                 }
+            }
         }
 
         throw new Error(`Formulaire.getNodeParameterValue() : pas de paramètre ${symbol} trouvé`);
@@ -373,7 +397,7 @@ export abstract class FormulaireDefinition extends FormulaireNode implements Obs
      * @returns valeur courante du select sans le préfixe
      */
     public getSelectedValue(selectFieldId: string): any {
-        let select: SelectField = <SelectField>this.getFieldById(selectFieldId);
+        const select: SelectField = <SelectField>this.getFieldById(selectFieldId);
         return select.getValue().value;
     }
 
@@ -383,13 +407,14 @@ export abstract class FormulaireDefinition extends FormulaireNode implements Obs
      * @returns label courant du select
      */
     public getSelectedLabel(selectFieldId: string): string {
-        let select: SelectField = <SelectField>this.getFieldById(selectFieldId);
+        const select: SelectField = <SelectField>this.getFieldById(selectFieldId);
         return select.getValue().label;
     }
 
     public applyDependencies() {
-        for (const fe of this.topFormElements)
+        for (const fe of this.topFormElements) {
             fe.applyDependencies();
+        }
     }
 
     public abstract resetResults();
@@ -398,28 +423,21 @@ export abstract class FormulaireDefinition extends FormulaireNode implements Obs
     public abstract get results(): CalculatorResults[];
 
     public updateLocalisation(localisation: StringMap) {
-        for (let fe of this.topFormElements)
+        for (const fe of this.topFormElements) {
             fe.updateLocalisation(localisation);
+        }
 
-        if (this.hasResults)
+        if (this.hasResults) {
             this.doCompute(); // pour mettre à jour la langue
+        }
     }
 
-
-    public updateHelp() {
-        ServiceFactory.instance.helpService.loadFormHelp(this, ServiceFactory.instance.internationalisationService.currentLanguage);
-    }
-
-    public get helpText(): string {
-        return this._helpText;
-    }
-
-    public set helpText(h: string) {
-        this._helpText = h;
+    public get helpLink(): string {
+        return this._helpLink;
     }
 
-    public requestHelp() {
-        this.notifyObservers({ "action": "requestHelp" }, this);
+    public set helpLink(h: string) {
+        this._helpLink = h;
     }
 
     public isDisplayed(id: string) {
@@ -427,10 +445,12 @@ export abstract class FormulaireDefinition extends FormulaireNode implements Obs
     }
 
     public get isValid(): boolean {
-        let res: boolean = true;
-        for (let fs of this.allFieldsets)
-            if (fs.isDisplayed)
+        let res = true;
+        for (const fs of this.allFieldsets) {
+            if (fs.isDisplayed) {
                 res = res && fs.isValid;
+            }
+        }
         return res;
     }
 
@@ -466,7 +486,7 @@ export abstract class FormulaireDefinition extends FormulaireNode implements Obs
      * sérialisation en JSON
      */
     public JSONserialise(): {} {
-        let res = {};
+        const res = {};
         res["id"] = this.calculatorName;
         res["uid"] = this.uid;
         res["props"] = this._currentSessionNub.properties.props;
@@ -488,8 +508,9 @@ export abstract class FormulaireDefinition extends FormulaireNode implements Obs
 
     private deserialiseElement(element: {}) {
         const keys = Object.keys(element);
-        if (keys.length !== 1)
+        if (keys.length !== 1) {
             throw new Error(`session file : invalid form object '${element}'`);
+        }
 
         switch (keys[0]) {
             case "fieldset":
@@ -509,6 +530,7 @@ export abstract class FormulaireDefinition extends FormulaireNode implements Obs
      * désérialisation depuis JSON
      */
     public deserialiseJSON(elements: {}) {
+        // tslint:disable-next-line:forin
         for (const k in elements) {
             switch (k) {
                 case "id":
@@ -520,8 +542,9 @@ export abstract class FormulaireDefinition extends FormulaireNode implements Obs
                     break;
 
                 case "elements":
-                    for (const e of elements[k])
+                    for (const e of elements[k]) {
                         this.deserialiseElement(e);
+                    }
                     break;
 
                 default:
diff --git a/src/app/services/formulaire/formulaire.service.ts b/src/app/services/formulaire/formulaire.service.ts
index f3d76cd39bc650aca9c2347cefbf963eafa0b4dc..1146f4a962ec8b8165d64168913ddb6dff302782 100644
--- a/src/app/services/formulaire/formulaire.service.ts
+++ b/src/app/services/formulaire/formulaire.service.ts
@@ -66,23 +66,12 @@ export class FormulaireService extends Observable {
      * @param localisation ensemble id-message traduit
      */
     private updateFormulaireLocalisation(formId: number, localisation: StringMap) {
-        for (let f of this._formulaires)
+        for (let f of this._formulaires) {
             if (f.uid === formId) {
                 f.updateLocalisation(localisation);
                 break;
             }
-    }
-
-    /**
-     * met à jour l'aide du formulaire
-     * @param formId id unique du formulaire
-     */
-    private updateFormulaireHelp(formId: number) {
-        for (let f of this._formulaires)
-            if (f.uid === formId) {
-                f.updateHelp();
-                break;
-            }
+        }
     }
 
     /**
@@ -92,7 +81,6 @@ export class FormulaireService extends Observable {
         return this.loadLocalisation(f.calculatorType)
             .then(localisation => {
                 this.updateFormulaireLocalisation(f.uid, localisation);
-                this.updateFormulaireHelp(f.uid);
                 return f;
             });
     }
diff --git a/src/app/services/help/help.service.ts b/src/app/services/help/help.service.ts
deleted file mode 100644
index c4325c00a1f0571b7b01b519f8ffd185e79a46ef..0000000000000000000000000000000000000000
--- a/src/app/services/help/help.service.ts
+++ /dev/null
@@ -1,30 +0,0 @@
-import { Injectable } from "@angular/core";
-import { Response } from "@angular/http";
-
-import { CalculatorType } from "jalhyd";
-import { Language } from "../internationalisation/internationalisation.service";
-import { ServiceFactory } from "../service-factory";
-import { FormulaireDefinition } from "../../formulaire/definition/form-definition";
-
-@Injectable()
-export class HelpService {
-    /**
-     * charge l'aide en ligne d'un formulaire
-     * @param form formulaire dont on veut l'aide
-     * @param lang langue souhaitée
-     */
-    public loadFormHelp(form: FormulaireDefinition, lang: Language): Promise<Response> {
-        const processData = function (s: string) {
-            form.helpText = s;
-        }
-        const processError = function (err: any) {
-            form.helpText = undefined;
-        }
-
-        const prefix = ServiceFactory.instance.formulaireService.getConfigPathPrefix(form.calculatorType);
-        const helpFile: string = `${prefix}${lang.tag}.md`;
-        // const headers = { "Content-Type": "application/octet-stream" };
-        // return ServiceFactory.instance.httpService.httpGetRequest(undefined, undefined, undefined, helpFile, processData, processError, headers);
-        return ServiceFactory.instance.httpService.httpGetRequest(undefined, undefined, undefined, helpFile, processData, processError);
-    }
-}
diff --git a/src/app/services/service-factory.ts b/src/app/services/service-factory.ts
index 40457c4f6fa0ccbf99089b565b2a8c26dd3f839f..f40bf9a5ce449e8326ea39237b133b4f5f8db343 100644
--- a/src/app/services/service-factory.ts
+++ b/src/app/services/service-factory.ts
@@ -3,7 +3,6 @@ import { ParamService } from "./param/param.service";
 import { FormulaireService } from "./formulaire/formulaire.service";
 import { InternationalisationService } from "./internationalisation/internationalisation.service";
 import { HttpService } from "./http/http.service";
-import { HelpService } from "./help/help.service";
 
 export class ServiceFactory {
     private static _instance: ServiceFactory; // instance pour le pattern singleton
@@ -20,11 +19,10 @@ export class ServiceFactory {
 
     public httpService: HttpService;
 
-    public helpService: HelpService;
-
     public static get instance() {
-        if (ServiceFactory._instance == undefined)
+        if (ServiceFactory._instance == undefined) {
             ServiceFactory._instance = new ServiceFactory();
+        }
         return ServiceFactory._instance;
     }
 }
diff --git a/src/index.html b/src/index.html
index 5d093f8fc0c9b0326c0eea3201dbd948b6d1e8bc..3f118aead63915bdeb163647acea383a103f96a6 100644
--- a/src/index.html
+++ b/src/index.html
@@ -31,21 +31,6 @@
     }
   </style>
 -->
-
-  <!-- MathJax-->
-  <!-- config locale qui s'ajoute à la config par défaut (ajoute les expressions LateX inline avec $....$) -->
-  <script type="text/x-mathjax-config">
-  MathJax.Hub.Config({
-    tex2jax: {
-      inlineMath: [['$','$'], ['\\(','\\)']],
-      skipTags: ['script', 'noscript', 'style', 'textarea', 'pre']
-    }
-  });
-  </script>
-
-  <!-- récupération du code + configuration par défaut -->
-  <script type="text/javascript" src="assets/mathjax/MathJax.js?config=TeX-AMS_CHTML"></script>
-  <!-- /MathJax-->
 </head>
 
 <body>