Download

site

Nicolas Mesnier

Mis à jour le 23/09/2019.

site est un script bash permettant de gérer un site web statique multi-auteurs depuis un répertoire partagé. C’est un logiciel libre, distribué sous licence GPL v3.

Motivation

J’ai développé site lorsque j’administrais un site pour les PTSI du lycée Jules Ferry de Versailles, hébergé par les pages personnelles du FAI FREE. Ce site sert à partager des ressources pédagogiques avec nos élèves. Les besoins que nous avons sont :

La fausse bonne solution (CMS)

Initialement écrit en SPIP 3.0.5 avec une base de données MYSQL, nous avions à peu près tous nos critères de remplis, bien qu’à l’usage (intensif), nous avons constaté :

Ces points étaient assez limitants mais nous nous en sommes accommodés jusqu’à ce que notre site, ou plus exactement la base de données MYSQL de notre site, ait été attaquée à deux reprises avec le remplacement du contenu des rubriques par un « iframe » affichant un message d’une stupidité confondante. C’est à l’issue de cette deuxième attaque que j’ai développé ce qui fût les prémices de site.

Des solutions techniques simples

Pour remettre en ligne rapidement la plupart des contenus que nous avions sur le site, j’ai créé un site statique en HTML avec des feuilles de style CSS. Dès la première version, la rapidité d’accès aux pages était édifiante par rapport au site avec SPIP. Par contre, je me suis retrouvé très vite à centraliser les demandes de mes collègues et il est devenu impératif de concevoir :

Les alternatives

Malgré une attention particulière portée aux outils libres, je n’en ai pas trouvé qui permette de faire ce genre de choses. En effet :

Ce sont donc les besoins et le cahier des charges spécifiques à un site de classe préparatoire qui ont conduit à la création de site. C’est un outil très bien adapté à ce besoin, mais il est probable, voire certain, qu’il ne sera pas pour d’autres.

Exemples

Création d’un site

Structure du site

Tout d’abord pour mettre au point un système multi-utilisateur, il faut une plateforme d’échange de fichiers. Pour le site des PTSI du lycée Jules Ferry de Versailles, nous avons choisi de partager un répertoire dropbox (appelé DistDir par la suite) qui contient un répertoire squelette et un répertoire web.

C’est à partir du répertoire partagé DistDir qu’est mis à jour le répertoire local, appelé LocalDir.

Fichier de configuration (site.config)

Le fichier de configuration site.config est un fichier texte formaté JSON qui sert « à sourcer » le script site. Il permet de renseigner les variables suivantes :

title

Titre du site, affiché en haut de toutes les pages ;

subtitle

Sous-titre du site, affiché sous le titre de toutes les pages ;

footer

Titulaire des droits du site, par exemple « Équipe de CPGE, du lycée XXX, XXX » ;

LocalDir

Chemin complet du répertoire local (~/..somewhere..)

DistDir

Chemin complet du répertoire partagé (~/Dropbox/somewhere)

pagesDir

Nom du répertoire du squelette (squelette)

pages

Liste de listes du type ["nomPage.html", "NOM de la page"] comprenant en premier élément le nom du fichier HTML de la page à synchroniser (sans espace) et son nom affiché dans le menu en haut de toutes les pages. L’ordre des pages correspond à celui du menu.

dirsDir

Nom du répertoire dont le répertoire distant sera l’image (web)

dirs

Liste des noms des répertoires locaux de dirsDir à synchroniser pour voir les nouveaux fichiers ajoutés ou mis à jour ;

FTPserver

URL du serveur hébergeur

FTPuser

Identifiant de l’utilisateur FTP

FTPpwd

Mot de passe de l’utilisation FTP

FTPdir

Répertoire du site sur le serveur, par défaut "/".

Exemple de fichier de configuration pour le site de démo :

{
    "title": "Filière, lycée XXX, XXX",
    "subtitle": "MATHS, PHYSIQUE, ET SCIENCES DE L'INGÉNIEUR",
    "footer": "Équipe de CPGE, du lycée XXX, XXX",
    "LocalDir": "~/site",
    "DistDir": "~/site/Dropbox-test",
    "pagesDir": "squelette",
    "pages": [
        ["filiere.html", "PTSI/PT"],
        ["PTSI1.html", "PTSI1"],
        ["PTSI2.html", "PTSI2"],
        ["Maths.html", "Maths"],
        ["Physique.html", "Physique-Chimie"],
        ["SII.html", "SII"],
        ["Informatique.html", "Info"],
        ["site.html", "À propos de site"]
    ],
    "dirsDir": "web",
    "dirs": [
        "files"
        ], 
    "FTPserver": "ftpperso.free.fr",
    "FTPuser": "",
    "FTPpwd": "",
    "FTPdir": "/"
}

Comme le fichier de configuration site.config contient vos identifiants de connexion, veillez à ce que tous les utilisateurs n’y aient pas accès en tapant dans le terminal

chmod 600 site.config

– Attention –
Il est impératif d’avoir bien renseigné les chemins complets :

Squelette

La structure du site telle qu’elle peut s’afficher est définie par les fichiers du squelette

header.txt (non mis à jour)

Contient l’en-tête HTML commun à toutes les pages et notamment la description du site, l’appel des feuilles de style CSS et l’ordre des pages dans le menu.

footer.txt (non mis à jour)

Contient le pied de page HTML commun à toutes les pages du site, faisant pointer sur la licence CC et les validateurs HTML et CSS de la W3C.

index.py (non mis à jour)

C’est la page chargée par défaut. Elle sert de porte d’entrée du site. Pour cette page on peut désactiver l’affichage classique avec

no_title
no_update
no_navigation

et définir le sien en HTML en le spécifiant entre 2 balises <html> et </html>.

En-tête d’une page

title

Permet d’afficher un nom en haut de la page

no_title

Préciser de ne pas afficher de nom en haut de la page

no_update

Préciser de ne pas afficher la date de mise à jour en haut de la page

no_navigation

Par défaut, un mini-menu permet de pointer vers les rubriques de la page. Cette option désactive son affichage.

docdir

Précise le répertoire du dossier web dans lequel trouver les documents.

Une page classique, par exemple physique.py, commence par :

title("Physique-chimie")
docdir("physique")

Structure d’une page

Une page peut être structurée sous la forme :

rubrique
|-- section
|   |-- subsection
rubrique(nom, open)

Crée une nouvelle rubrique. L’affichage est paramétré avec la classe rubrique. Par défaut, on a l’option open=True et le contenu est visible. Si open=False, le contenu n’est pas visible et il faut cliquer sur le titre pour le voir.

section(nom, open)

Crée une nouvelle section. L’affichage est paramétré avec la classe container-item-phys. Par défaut, on a l’option open=False et le contenu n’est pas visible et il faut cliquer sur le titre pour le voir. Si open=True, le contenu est visible.

section_open(nom)

Crée une nouvelle section. Par défaut, le contenu est visible.
Fonction obsolète, à remplacer par section(nom, True).

section_CI(nom)

Crée une nouvelle section, affichage tiers de page sur grand écran. L’affichage est paramétré avec la classe container-item.

section_TP(nom)

Crée une nouvelle section, affichage avec tableau pour TP. L’affichage est paramétré avec la classe container-item + tableau avec la classe TP.

subsection(nom)

Crée une nouvelle sous-section. L’affichage est paramétré avec un <h2> pour le titre et un petit séparateur de la classe floatreset.

subsection_CI(nom)

Crée une nouvelle sous-section, affichage tiers de page sur grand écran. L’affichage est paramétré avec la classe sub-container-item.

nav_rubrique()

Affiche les liens vers les sections de la rubrique en cours. À placer sous la définition d’une rubrique.
Les sections avec une étoile * avant la parenthèse, du genre

section*(nom)
section_open*(nom)
section_CI*(nom)
section_TP*(nom)

ne sont pas liées (comme en LaTeX).

Répertoire image (web)

Le répertoire dirsDir (aka web) reproduit l’arborescence des répertoires du site web réel.

style

C’est le répertoire qui contient les feuilles de style CSS des pages HTML et les images ou icones utilisées de façon standard sur le site.

password

Ce répertoire contient le fichier .htpasswd des couples (identifiant, mot de passe) des utilisateurs du site (voir la rubrique sécurité).

img

Ce répertoire peut être considéré comme public. L’accès à tous ses éléments peut se faire sans mot de passe. Il permet de stocker des fichiers auxquels n’importe quel utilisateur peut avoir accès.

Pour créer un répertoire et ses parents en même temps, taper :

mkdir -p $dirsDir/sii/ptsi1

Installation

Les outils développés sont :

site

Script bash permettant de mettre à jour le site à partir des contenus ajoutés ou modifiés dans le répertoire partagé DistDir (dropbox).

MakePage.py

Script python (plutôt version 3) permettant d’interpréter les pages textes du squelette pour générer les pages HTML du site. Il est appelé par le script site.

Pour utiliser les outils développés, il est nécessaire d’avoir :

Téléchargement

La dernière version est la 0.1.6 (23/09/2019).

Archive : site-0.1.6.tar.gz

Installation GNU/Linux (Debian et filles rebelles)

Installation Mac OS X

Installation MS Windows 7/8/10

Oups !

Configuration

Éditer le fichier de configuration site.config et notamment les variables "LocalDir" et "DistDir" qui correspondent respectivement aux chemins absolus du dossier local et du dossier partagé.

Il n’est pas nécessaire de copier les dossiers squelette et web dans le "DistDir", ils le seront à la première exécution, par précaution hors ligne :

site -o

Cette commande permet de générer toutes les pages.

Élements de style

Les feuilles de styles CSS du site sont base.css et mobile.css, dont les rôles sont explicites, et situées dans le répertoire web/style.

L’image du bandeau du haut commune à toutes les pages s’appelle bg.png et se trouve dans le répertoire web/style. Ses dimensions sont 849x135.

Le logo et la photo de la page index.html se situent dans le répertoire web/img.

Éléments de sécurité

N’ayant pas (forcément) la main sur les paramètres du serveur qui héberge notre site, les seuls éléments de sécurités sont :

Pour restreindre l’accès à un répertoire de web et à tout ce qu’il contient (fichiers, sous-répertoires), il suffit de placer à la racine (comprendre dans le répertoire que l’on veut protéger) un fichier .htaccess (propre aux serveurs apache) contenant :

PerlSetVar AuthFile /password/.htpasswd
AuthName "Acces Restreint"
AuthType Basic
require valid-user

Le fichier .htpasswd du répertoire password doit contenir la liste des couples (identifiant, mot de passe) valide. Si le répertoire n’existe pas, il suffit de le créer

mkdir -p web/password

puis de créer la liste des couples (identifiant, mot de passe) :

echo "user:pass">>web/password/.htpasswd

le >> pour ajouter au fichier, > écrase le contenu du fichier tel qu’il ne reste que ce dernier contenu. Évidemment, il convient que le répertoire password soit inaccessible par tous, de sorte que ces mots de passe ne soient pas {v,l,s}us. On peut le protéger avec un fichier .htaccess contenant deny from all généré avec :

echo "deny from all">web/password/.htaccess

Attention à ne pas mettre ce fichier dans le répertoire style ni dans le répertoire img que l’on gardera donc comme répertoires publics.

Administration

Administration au quotidien (site)

Au quotidien, l’administration du site peut être résumée en 2 commandes :

site -c

pour voir s’il y a eu des modifications de contenu (squelette et fichiers) ;

site -u

pour appliquer les modifications.

En cas de problème sur une page, par exemple un fichier manquant ou un nom de fichier erroné, il est possible d’éditer rapidement la page avec :

site -e <page>

pour éditer la page <page> avec l’éditeur spécifié par la commande editor. Si besoin jouer (en admin) du

update-alternatives --config editor

ou faire un export EDITOR=xxx avec xxx votre éditeur préféré, voire même remplacer la ligne editor ... avec votre éditeur préféré en mode graphique, comme gedit sur GNU/Linux ou /Applications/TextMate.app/Contents/Resources/mate sur Mac OS X.

site -p <page>

pour compiler la page <page> ;

site -e <page> -p

pour éditer puis compiler la page <page> ;

Les erreurs classiques sont :

site est muni de quelques autres options qui sont parfois utiles. Dans tous les cas :

site -h

pour voir l’aide !

Génération des pages web (MakePage.py)

La génération des pages HTML est réalisée, page après page, avec le script python MakePage.py, appelé par le script bash site. Vous n’avez normalement pas besoin de l’utiliser directement mais si vous le souhaitez, il est nécessaire de se placer dans le répertoire localDir et taper dans le terminal :

python3 MakePage.py <page>

ou encore plus simplement, si le fichier est exécutable,

./MakePage.py <page>

grâce au shebang #!/usr/bin/env python3 du début du fichier.

Il est aussi possible d’utiliser pyzo et de se placer le shell python dans ce même répertoire avec

import os
os.chdir(localDir)

Créer une nouvelle page

Pour créer une nouvelle page page.html, il faut :

Utilisation

Structure d’une page

Une page peut être structurée sous la forme :

rubrique
|-- section
|   |-- subsection
rubrique(nom)

Crée une nouvelle rubrique.

section(nom)

Crée une nouvelle section.

subsection(nom)

Crée une nouvelle sous-section.

Pour faciliter la lisibilité des fichiers du squelette, on indentera autant de fois que le niveau hiérarchique, par exemple :

rubrique("PTSI1")
    section("Section 1")
        pdf("Nom","fichier.pdf")
    section("Section 2")
        subsection("Sous-section 2.1")
            pdf("Nom","fichier.pdf")

Documents

Pour ajouter un document, il faut utiliser une des fonctions du tableau suivant.

Type de document Fonction Syntaxe
Fichier PDF pdf pdf(nom, fichier)
Présentation pres pres(nom, fichier)
Fichier texte text text(nom, fichier)
Document word docx docx(nom, fichier)
Archive zip zip(nom, fichier)
Image image image(nom, fichier)
Son son son(nom, fichier)
Vidéo video video(nom, fichier)
Code code code(nom, fichier)
Code python pycode pycode(nom, fichier)

Pour ajouter un fichier PDF, on écrira donc

pdf("Nom du document visible sur le site", "repertoire/fichier")

Bien vérifier que le document ajouté sur le fichier du squelette, figure bien dans :

web
|-- rep_page        >>> voir `docdir("rep_page")`
    |-- repertoire
        |-- fichier

HTML

Il est possible d’écrire en HTML dans les fichiers du squelette. Pour cela, il suffit de le spécifier entre 2 balises <html> et </html>, chacune seule sur une ligne.

subsection("Ressources bibliographiques")
<html>
<ul>
  <li><a href="http://arxiv.org/">arXiv</a></li>
  <li><a href="https://hal.archives-ouvertes.fr/">HAL</a></li>
  <li><a href="https://tel.archives-ouvertes.fr/">TEL</a></li>
</ul>
</html>
sep()

La fonction sep() permet de faire une coupure propre avec une remise à zéro des flottants (icônes des fichiers et noms).

Contenus spécifiques SII

section_CI(ID, nom)

Crée une nouvelle section, affichage tiers de page sur grand écran. Pour présenter les supports associés à un centre d’intérêt

subsection("Centres d'intérêts")
    section_CI("refCI","Nom et description du CI")
section_TP(ID, nom)

Crée une nouvelle section, affichage avec tableau pour TP.

SII_TP(systeme, sujet, DR="", sysML="", complement="")

Pour les sujets de TP, incluant les document ressources, modèle sysML et compléments éventuels.

SII_TP_Avenir()

Pour laisser le nom d’une série sans faire figurer de système et donc de document.

section_TP("TPxx","Série n°xx – Titre de la série")
    SII_TP("Nom du système","TPxx/sujet.pdf", \
        "TPxx/doc-ressources.pdf","TPxx/sysML.zip")
    SII_TP("Nom du système","TPxx/sujet.pdf", \
        "TPxx/doc-ressources.pdf","TPxx/sysML.zip", \
        ["TPxx/complement1.pdf", "TPxx/complement2.pdf"])
section_TP("TPxx","Série n°xx – Titre de la série")
    SII_TP_Avenir()
planche(nom, description, sujet, complement, corrige)

Pour les sujets et corrigés de préparation à l’épreuve de planche

rubrique("Planches")
    planche("Planche n°x","Titre de la planche", \
        "sujet.pdf","","corrige.pdf")
    planche("Planche n°x","Titre de la planche", \
        "sujet.pdf","complement.pdf","corrige.pdf")

Contenus spécifiques d’informatique

info_cours(nom, description, fichier)

Pour les cours d’informatique

rubrique("Cours")
    info_cours_init()
    info_cours("Nom","Description longue","fichier.pdf")
    info_cours_close()
info_TP(num, sujet, complement="",corrige="")

Pour les TP d’informatique où l’on veut souvent publier le sujet avant son corrigé, avec d’éventuels compléments. Les arguments complement (liste du type ["nom", "fichier"]) et corrige sont optionnels. Par exemple, on peut écrire :

rubrique("TP")
    info_TP_init()
    info_TP("01", "Info-TP01_sujet.pdf","","Info-TP01_corrige.pdf")
    info_TP("02", "Info-TP02_sujet.pdf",\
        ["Complément","Info-TP02_complement.zip"],Info-TP02_corrige.pdf")
    info_TP("03", "Info-TP03_sujet.pdf")
    info_TP_close()

Ressources

  1. lftp
    http://lftp.yar.ru/
  2. rsync
    https://rsync.samba.org/
  3. pyzo
    http://www.pyzo.org/
  4. GPL v3
    https://www.gnu.org/licenses/gpl-3.0.html