diff --git a/README.md b/README.md index 9242491..a3f6fd2 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,7 @@ Avec Anaconda: conda install ruamel conda install ruamel.yaml pip install docx2python + pip install Jinja2 Sans Anaconda, remplacer `conda` par `pip`. @@ -37,6 +38,11 @@ par exemple: cd python python export_yaml_to_latex.py -a +### Génération du Html + + cd html + python export_yaml_to_html.py + ### Génération de PDF cd latex @@ -47,6 +53,7 @@ Le résultat est `pn_formation.pdf`. ## Organisation des fichiers + html/export fichiers html générés par export_yaml_to_html.py à partir des yaml python/import fichiers docx à traiter python/export fichier yaml générés par export_docx_to_yaml.py à partir des docx yaml/ressources versions éditées manuellement ?? diff --git a/html/ACTemplate.html b/html/ACTemplate.html new file mode 100644 index 0000000..0f14866 --- /dev/null +++ b/html/ACTemplate.html @@ -0,0 +1,19 @@ +{% extends "base.html" %} +{% block title %}{{data["ac"]}}{% endblock %} +{% block content %} +{% include "navigation.html" %} + +
+

{{data["code"]}}

+

{{data["titre"]}}

+

Liste des SAÉs mobilisés

+ +
+ +{% include "navigation.html" %} + +{% endblock %} \ No newline at end of file diff --git a/html/CompetenceTemplate.html b/html/CompetenceTemplate.html new file mode 100644 index 0000000..008d262 --- /dev/null +++ b/html/CompetenceTemplate.html @@ -0,0 +1,47 @@ +{% extends "base.html" %} +{% block title %}{{rt}}{% endblock %} +{% block content %} +{% include "navigation.html" %} + + + + {% for categorie, valeur in data.items() %} + + + + + {% endfor %} + +
{{categorie.capitalize()}} + {%- if categorie == "composantes" or categorie == "situations" -%} +
+
    + {% for valeur in valeur %} +
  • {{valeur}}
  • + {% endfor %} +
+
+ {% elif categorie == "niveaux" -%} +
+
    + {% for nom, acs in valeur.items() %} +
  • {{nom}}
  • +
      + {% for ac in acs %} + {% if ac[:2] == "AC" %} +
    • {{ac}} - {{acs[ac]}}
    • + {% else %} +
    • {{ac}}
    • + {% endif %} + {% endfor %} +
    + {% endfor %} +
+
+ {% else -%} +
{{valeur}}
+ {% endif %} +
+{% include "navigation.html" %} + +{% endblock %} \ No newline at end of file diff --git a/html/InfoTemplate.html b/html/InfoTemplate.html new file mode 100644 index 0000000..a8a465c --- /dev/null +++ b/html/InfoTemplate.html @@ -0,0 +1,42 @@ +{% extends "base.html" %} +{% block title %}{{data.code}} - {{data.nom}}{{data.titre}}{% endblock %} +{% block content %} +{% include "navigation.html" %} + + + + {% for categorie, valeur in data.items() %} + + + + + {% endfor %} + +
{% if rename and rename[categorie] %}{{rename[categorie]}}{% else %}{{categorie.capitalize()}}{% endif %} + {#- Gestion des tableaux #} + {% if categorie == "motscles" -%} +
{% for mot in valeur %}{{mot}}{% endfor %}
+ {#- Gestion des saes #} + {% elif categorie == "sae" or categorie == "ressources" -%} +
{% for val in valeur %}{{val}}{% endfor %}
+ {#- Gestion des ACS #} + {% elif categorie == "acs" -%} +
{% for rt,acs in valeur.items() %}{% for ac in acs %}{{ac}}{% endfor %}{% endfor %}
+ {#- Gestion des coeffs #} + {% elif categorie == "coeffs" -%} +
{% for rt, coeff in valeur.items() %}{{rt}} : {{coeff}}{% endfor %}
+ {#- Gestion des exemples #} + {% elif categorie == "exemples" -%} + {% for exemple in valeur %}Exemple{{loop.index}}{% if not loop.last %} - {% endif %}{% endfor %} + {#- Gestion des prerequis #} + {% elif categorie == "prerequis" -%} + {% if valeur != "Aucun" %}
{% for rt in valeur %}{{rt}}{% endfor %}
+ {%- else %}{{valeur}}{% endif %} + {#- Gestion des autres catégories #} + {% else -%} +
{{valeur}}
+ {%- endif -%} +
+{% include "navigation.html" %} + +{% endblock %} \ No newline at end of file diff --git a/html/ListACsTemplate.html b/html/ListACsTemplate.html new file mode 100644 index 0000000..da09111 --- /dev/null +++ b/html/ListACsTemplate.html @@ -0,0 +1,13 @@ +{% extends "base.html" %} +{% block title %}Liste des {{title}}{% endblock %} +{% block content %} +
+ +
+{% endblock %} \ No newline at end of file diff --git a/html/ListRessourceTemplate.html b/html/ListRessourceTemplate.html new file mode 100644 index 0000000..7f5d925 --- /dev/null +++ b/html/ListRessourceTemplate.html @@ -0,0 +1,11 @@ +{% extends "base.html" %} +{% block title %}Liste des Ressources du semestre {{sem}}{% endblock %} +{% block content %} +
+ +
+{% endblock %} \ No newline at end of file diff --git a/html/ListTemplate.html b/html/ListTemplate.html new file mode 100644 index 0000000..7f8489c --- /dev/null +++ b/html/ListTemplate.html @@ -0,0 +1,13 @@ +{% extends "base.html" %} +{% block title %}Liste des {{title}}{% endblock %} +{% block content %} +
+ +
+{% endblock %} \ No newline at end of file diff --git a/html/base.html b/html/base.html new file mode 100644 index 0000000..db1a38e --- /dev/null +++ b/html/base.html @@ -0,0 +1,80 @@ + + + + + + {% block title %}{% endblock %} + + + + + + {% block head %}{% endblock %} + + + + + + + +
+
+ {% block content %} + {% endblock %} +
+
+ + + + diff --git a/html/baseTemplate.js b/html/baseTemplate.js new file mode 100644 index 0000000..a7c2298 --- /dev/null +++ b/html/baseTemplate.js @@ -0,0 +1,77 @@ +$("document").ready(function() { + // Affichage mobile du menu | affiche/cache le menu contenant la liste des catégories + // en appuyant sur le burger/les trois traits + $(".navbar-burger").click(function() { + $(".navbar-burger").toggleClass("is-active"); + $(".navbar-menu").toggleClass("is-active"); + // Détails visuel du bouton recherche + $("#rechercheBouton").toggleClass("is-rounded is-fullwidth is-primary") + }); + // Bouton suivant et précédent qui s'affiche en loading lorsque l'utilisateur change de page + $("a.button").click(function() { + $(this).addClass("is-loading"); + }); + // Redirige vers la page tapé dans la barre de recherche | recheche brut, possible d'amélioration avec + // auto-complétion, créer une page web "page n'existe pas", recherche par motsclés, page avec une liste des + // pages web possibles en fonction de ce que entre l'utilisateur + // ex: "R101" -> ./HTML/R101.html + $("#rechercheBouton").click(function() { + $("#rechercheBoite").addClass("is-active") + }); + + // Gestion de la fermeture de la boite de recherche + $(".modal-background").click(function() { + $("#rechercheBoite").removeClass("is-active") + }); + $("#rechercheBoite-fermer").click(function() { + $("#rechercheBoite").removeClass("is-active") + }); + + $("#rechercher").keyup(function(e) { + var recherche = $(this).val().trim(); + if(recherche.length != 0) { + recherche = "+" + recherche.replace(/\s+/g," +"); + console.log(recherche) + var resultats = idx.search(recherche); + if(resultats.length != 0) { + $("#rechercheResultats").empty(); + resultats.forEach(function(res) { + $("#rechercheResultats").append('

' + documents[res.ref]["titre"] + '

') + $("#rechercheResultats").append('

' + documents[res.ref]["code"] + '

') + }); + } else {$("#rechercheResultats").html('

Pas de résultats

')} + } else { + $("#rechercheResultats").html('

Pas de résultats

') + } + + }); +}); + +// Documents avec toutes les informations nécessaire pour la recherche +var documents = {{documents}} + +var idx = lunr(function() { + this.ref("code") + this.field("code", { boost: 10}) + this.field("motscles") + this.field("diminutif", { boost: 10}) + this.field("titre") + this.field("description") + this.field("contenu") + this.field("contexte") + + for(var cle in documents) { + this.add(documents[cle]) + } +}) + +// Permet l'affichage du LaTeX avec comme balise délimiteur "$" +// Le menu contextuel de MathJax a été désactivé +MathJax = { + tex: { + inlineMath: [['$', '$']] + }, + options: { + enableMenu: false + } + }; \ No newline at end of file diff --git a/html/export_yaml_to_html.py b/html/export_yaml_to_html.py new file mode 100644 index 0000000..09ee08b --- /dev/null +++ b/html/export_yaml_to_html.py @@ -0,0 +1,386 @@ +import os +import sys +import argparse +import glob + +sys.path.insert(0,"../python") +from config import Config +from jinja2 import Template, Environment, FileSystemLoader + +# Description des arguments possibles du programme +parser = argparse.ArgumentParser(description="Conversion des YAML en HTML") +parser.add_argument( + "-r", + "--root", + default="..", + help="repertoire de base (racine) pour chercher les fichiers de données" +) +args = parser.parse_args() +Config.ROOT = args.root + +import ressource +from ressource import * + +# Chemins des différents dossiers +REPERTOIRE_TEMP = Config.ROOT + "/python/export" +REPERTOIRE_RESSOURCES_DEFINITIVES = Config.ROOT + "/yaml/ressources" +REPERTOIRE_SAE_DEFINITIVES = Config.ROOT + "/yaml/saes" +REPERTOIRE_COMPETENCES_DEFINITIVES = Config.ROOT + "/yaml/competences" +REPERTOIRE_ACS = Config.ROOT + "/python/pn" +REPERTOIRE_HTML = Config.ROOT + "/html/export" +REPERTOIRE_JS = REPERTOIRE_HTML + "/js" +CHEMIN_TEMPLATE = Config.ROOT + "/html" + +# Créer le dossier html/export et html/export/js s'il n'existe pas +if not os.path.exists(REPERTOIRE_HTML): + os.makedirs(REPERTOIRE_HTML) +if not os.path.exists(REPERTOIRE_JS): + os.makedirs(REPERTOIRE_JS) + +# Chargement des ressources : depuis les versions définitives du répertoire yaml d'abord, +# puis dans python/export si manquantes +fichiers_definitifs = [ os.path.split(x)[1] for x in glob.glob(REPERTOIRE_RESSOURCES_DEFINITIVES+'/*.yml') ] #nom fichier dans yaml/ressources +fichiers_temp = [ os.path.split(x)[1] for x in glob.glob(REPERTOIRE_TEMP+'/*.yml') ] #nom fichier dans python/export +fichiers_ressources = [REPERTOIRE_RESSOURCES_DEFINITIVES + "/" + f for f in fichiers_definitifs] # chemins de fichier ressources YAML +for f in fichiers_temp: + if f not in fichiers_definitifs and f.startswith("R"): + fichiers_ressources.append(REPERTOIRE_TEMP + "/" + f) +fichiers_ressources = sorted(fichiers_ressources) # tri par ordre alphabétique + +ressources = {"S1": [], "S2": []} +for fichieryaml in fichiers_ressources: + r = Ressource(fichieryaml) # lecture du fichier + sem = "S" + str(r.ressource["semestre"]) + ressources[sem].append(r) +# tri par code croissant +for sem in ressources: + ressources[sem] = sorted(ressources[sem], key=lambda r: r.ressource["code"]) + +# Chargement des saé et des exemples +fichiers_definitifs = [ os.path.split(x)[1] for x in glob.glob(REPERTOIRE_SAE_DEFINITIVES+'/*.yml') ] +fichiers_temp = [ os.path.split(x)[1] for x in glob.glob(REPERTOIRE_TEMP+'/*.yml') ] +fichiers_saes = [REPERTOIRE_SAE_DEFINITIVES + "/" + f for f in fichiers_definitifs if "exemple" not in f] +fichiers_exemples = [REPERTOIRE_SAE_DEFINITIVES + "/" + f for f in fichiers_definitifs if "exemple" in f] +for f in fichiers_temp: + if f not in fichiers_definitifs and f.startswith("S"): + if "exemple" not in f: + fichiers_saes.append(REPERTOIRE_TEMP + "/" + f) + elif "exemple" in f: + fichiers_exemples.append(REPERTOIRE_TEMP + "/" + f) +fichiers_saes = sorted(fichiers_saes) # tri par ordre alphabétique +fichiers_exemples = sorted(fichiers_exemples) + +saes = {"S1": [], "S2": []} +for fichieryaml in fichiers_saes: + s = SAE(fichieryaml) + sem = "S" + str(s.sae["semestre"]) + saes[sem].append(s) + +for sem in saes: + saes[sem] = sorted(saes[sem], key=lambda s: s.sae["code"]) + +exemples = {"S1" : {}, "S2" : {} } + +for fichieryaml in fichiers_exemples: + e = ExempleSAE(fichieryaml) + sem = "S" + str(e.exemple["semestre"]) + sae = e.exemple["code"] + if sae not in exemples[sem]: + exemples[sem][sae] = [] + exemples[sem][sae].append(e) + +#Liste de string pour renommer certaines catégories (les autres qui n'ont pas besoins ont la première lettre en majuscule) +rename = { + "heures_encadrees": "Heures encadrées", + "heures_formation": "Heures formation", + "heures_tp": "Heures TP", + "tp": "Heures TP", + "coeffs": "Coef.", + "acs": "ACs", + "motscles": "Mots clés", + "sae": "SAÉ", + "prerequis": "Prérequis", + "problematique": "Problématique", + "modalite": "Modalité" +} + +# Création de l'environnement pour charger les templates +env = Environment(trim_blocks=True, lstrip_blocks=True, loader=FileSystemLoader(CHEMIN_TEMPLATE)) + +# Template de la page index et génération de la page +template_index = env.get_template("indexTemplate.html") +template_index.stream().dump(REPERTOIRE_HTML + "/index.html") + +# Template de chaque pages ressources, saes, exemples (doit contenir datas,rename,precedent,suivant) +template = env.get_template("InfoTemplate.html") + +# Template de chaque pages de compétences (doit contenir data,rt,precedent,suivant) +template_Competence = env.get_template("CompetenceTemplate.html") + +# Template de chaque pages de ACs (doit contenir data, precedent, suivant) +template_AC = env.get_template("ACTemplate.html") + +# Template de la liste des ACs +template_List_ACs = env.get_template("ListACsTemplate.html") + +# Template de la liste des ressources par semestre (doit contenir data,sem) +template_List_Ressource = env.get_template("ListRessourceTemplate.html") + +# Template de la liste des acs ou saes ou ressources (doit contenir data,titre) +template_List = env.get_template("ListTemplate.html") + +def motscles(mc): + """ Retourne un tableau de mots clés en prenant en compte les parenthèses """ + motscles = [] + mot = "" + i = 0 + while i < len(mc): + if mc[i] == "(": + while mc[i] != ")": + mot += mc[i] + i += 1 + elif mc[i] == "," and mc[i+1] == " ": + motscles.append(mot) + mot = "" + i += 2 + mot += mc[i] + i += 1 + motscles.append(mot) + return motscles + +def formatHTML(string): + """ Retourne un string avec les balises