Créer une table des matières de façon dynamique

L'auteur de ce sujet a trouvé une solution à son problème.
Auteur du sujet

Bonjour,

j'aurai aimé savoir si quelqu'un connaissait un script/fonction pour créer une table des matières de façon dynamique. (En php)

(En piochant les <h1>, <h2>, ou encore les #, ## utilisé pour le markdown.)

Je sais qu'ici on est pas trop fan de donner des morceaux de code comme ça, je pourrais très probablement la faire moi même, mais je n'ai déjà pas le temps, et je ne sais pas trop comment m'y prendre. Et au final je ne souhaite pas réinventé la roue …

En vous remerciant, WinXaito

Édité par WinXaito

+0 -0

Ce n'est pas très compliqué. Tu parcours l'arbre XML en quête de H1-6 et tu construis la table au fur et à mesure. Pseudo-code vaguement ressemblant à python mais sans indentation (car c'est un code que j'écris en live dans le browser et je ne sais pas comment on fait).

Le code ne produit pas de HTML ou de XML valide, c'est juste un exemple rapide; à toi d'adapter.

1
2
3
4
5
6
7
8
9
lastLevel = 0
for h in domTree if h.tagName in ('h1', 'h2', 'h3', 'h4', 'h5', 'h6') {
level = int(h.tagName[1:])
if abs(lastLevel-level)>1: throw("Hiérarchie de titres invalide")
if level<lastLevel { } # On remonte d'un niveau, tu peux print </ul> par exemple
elif level>lastLevel { } # Un sous-niveau commence, tu peux print <ul> par exemple
# Ici tu peux print le titre, p.ex. <li> + h.text + </li>
lastLevel=level
}

Édité par QuentinC

Ma plateforme avec 23 jeux de société classiques en 6 langues et 13000 joueurs: http://qcsalon.net/ | Apprenez à faire des sites web accessibles http://www.openweb.eu.org/

+0 -0
Staff

Cette réponse a aidé l'auteur du sujet

Tu vas être content, c'est un problème que j'ai rencontré récemment et que j'ai traité sur mon blog. ^^

Tu trouveras l'article ici avec le code et quelques explications sur son fonctionnement.

Le fonctionnement est relativement basique, donc rien ne t'empêche de l'adapter selon tes propres besoins (en postant de préférence ton résultat pour que ça profite aux autres). ;)

Édité par viki53

Auteur du sujet

Merci beaucoup viki !

J'allais venir poser une deux questions, mais je pense que ma méthode n'était pas optimal. Je vais donc me pencher sur ton code.

Merci, je vous tiendrai au courant si j'ai encore des soucis

+0 -0
Auteur du sujet

Bonsoir à tous, j'ai un petit peu regarder le code à viki, je n'ai pas tout compris.

Sinon, je me dis qu'il serait peut-être mieux pour moi de quand même essayer de le faire tout seul.
J'ai pour le moment réussi à récuperer les <h1> mais je ne sait pas comment adapter mon preg_match pour qu'il récup les suivants…

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<?php
$source = '
    <h1>Yolo</h1>
        <h2>Hmmm</h2>

    <h1>Test ?</h1>

    <h1>Ou pas</h1>
        <h2>Test de 2</h2>
            <h3>Youpi</h3>
';

preg_match_all('#<h1>(.*)</h1>#i', $source, $liens);

var_dump($liens);

echo '<br><br>';

$nb = 0;
foreach($liens[0] as $complet) {
    $title = $liens[1][$nb];

    echo $title.'<hr/>';

    $nb++;
}

Édité par WinXaito

+0 -0
Staff

Je recommanderais pas d'utiliser des regex pour traiter du HTML, surtout quand tu peux utiliser des méthodes du DOM.

Mais tenter de faire ça par toi-même est une très bonne chose pour apprendre ! :)

Essaie plutôt de t'inspirer de ce qui existe ailleurs (que ce soit dans mon code où dans d'autres — c'est d'ailleurs ce que j'ai fait à la base) pour manipuler le DOM et récupérer les nœuds qui t'intéressent et boucler dessus, comme les autres te l'ont recommandé

Auteur du sujet

Merci,

j'ai regardé votre code, par contre j'ai vu que vous avez marqué:

À noter que certaines fonctions nécessitent d’être définie à l’avance (CodeIgniter les fourni, votre framework préféré a sans doute des équivalents) : url_title permet d’obtenir une version utilisable dans l’URL (pratique pour obtenir une ancre lisible)

Je n'utilise pas de framework, à quoi correspond cette fonction ? Et à quoi sert-elle ?

Merci

+0 -0
Staff

Ça sert à transformer une chaîne pour avoir une version URL de celle-ci.

Par exemple Une chaîne de caractères va devenir une-chaine-de-caractere.

Ça permet principalement de s'assurer que les ancres sont à peu près valides (même s'il faudrait théoriquement plus de vérifications, par exemple pour éviter les chiffres au début)

Auteur du sujet

Très bien merci, j'ai essayé et effectivement ta solution marche bien.
Mais étant donné que je n'ai jamais utilisé les dom je ne sais pas trop comment m'y prendre. Donc j'ai quand même continuer sur mon idée pour enfin avoir un résultat =D.

Le code est un peu loin et fais à la va-vite il y a surement moyen de l'amélioré (Surtout qu'ici je ne gère seulement jusqu'à h3.)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
<?php
$source = '
    <h1 class="title">Yolo</h1>
        <h2 class="title">Hmmm</h2>
            <h3 class="title">Yolo</h3>
            <h3 class="title">Yolo</h3>
            <h3 class="title">Yolo</h3>
            <h3 class="title">Yolo</h3>
        <h2 class="title">Et bim dans les dents</h2>

    <h1 class="title">Test ?</h1>
        <h2 class="title">Test de 2</h2>
        <h2 class="title">Et bim dans les dents</h2>
            <h3 class="title">Yolo</h3>
            <h3 class="title">Yolo</h3>
            <h3 class="title">Yolo</h3>
        <h2 class="title">Et bim dans les dents</h2>
        <h2 class="title">Et bim dans les dents</h2>
            <h3 class="title">Yolo</h3>
            <h3 class="title">Yolo</h3>
        <h2 class="title">Et bim dans les dents</h2>

    <h1 class="title">Ou pas</h1>
        <h2 class="title">Test de 2</h2>
        <h2 class="title">Et bim dans les dents</h2>
            <h3 class="title">Yolo</h3>
        <h2 class="title">Et bim dans les dents</h2>
';

preg_match_all('#<h([1-6]) class="title">(.*)</h[1-6]>#i', $source, $liens);


$nb = $h1 = $h2 = $h3 = $h4 = $h5 = $h6 = 0;

foreach($liens[0] as $complet) {
    if($liens[1][$nb] == 2){
        $h2++;
    }
    else if($liens[1][$nb] > 2){
        #rien
    }
    else{
        $h2 = 0;
    }

    if($liens[1][$nb] == 3){
        $h3++;
    }
    else if($liens[1][$nb] > 3){
        #Rien
    }
    else{
        $h3 = 0;
    }


    switch($liens[1][$nb]){
        case 1:
            $margin = '0';
            $prefix = $h1;
            $h1++;

            $title = $liens[2][$nb];
            echo '<div style="margin-left:'.$margin.'px">'.$h1.' '.$title.'</div><hr/>';
            break;
        case '2':
            $margin = '30';

            $title = $liens[2][$nb];
            echo '<div style="margin-left:'.$margin.'px">'.$h1.'.'.$h2.' '.$title.'</div><hr/>';
            break;
        case '3':
            $margin = '60';

            $title = $liens[2][$nb];
            echo '<div style="margin-left:'.$margin.'px">'.$h1.'.'.$h2.'.'.$h3.' '.$title.'</div><hr/>';
            break;
        default:
            $margin = '0';
    }
    $nb++;
}

Résultat

+0 -0

C'est sémantiquement plus que médiocre de faire une table des matières sans utiliser ol ou ul.

ET bon, les versions parcourant le DOM sont quand même largement plus efficaces. Pas de regex et parcours en une seule fois. ON peut aussi se passer allègrement de cet horrible switch.

Ma plateforme avec 23 jeux de société classiques en 6 langues et 13000 joueurs: http://qcsalon.net/ | Apprenez à faire des sites web accessibles http://www.openweb.eu.org/

+0 -0
Staff

@QuentinC : Comme dans toute tentative de code, le premier résultat n'est pas définitif, donc son HTML a peut être déjà été modifié pour être plus sémantique. Ça ne t'autorise pas à être insultant.

Pour le reste c'est des choses qui ont déjà été dites, mais pour apprendre il faut bien commencer quelque part.

Ça ne t'autorise pas à être insultant.

Désolé si quelqu'un a mal pris ce que j'ai dit, mais je n'ai vraiment pas l'impression d'avoir été insultant.

Bref, rien ne sert de troller. Je n'interviendrai plus sur ce topic pour éviter de nouveau de vous froisser.

Édité par QuentinC

Ma plateforme avec 23 jeux de société classiques en 6 langues et 13000 joueurs: http://qcsalon.net/ | Apprenez à faire des sites web accessibles http://www.openweb.eu.org/

+0 -1
Auteur du sujet

C'est sémantiquement plus que médiocre de faire une table des matières sans utiliser ol ou ul.

Je confirme ce qu'a dit Viki, pour le moment je me concentre sur le php et non le html … Je ne suis pas fou au point de laisser quelque chose comme ça !

ET bon, les versions parcourant le DOM sont quand même largement plus efficaces. Pas de regex et parcours en une seule fois. ON peut aussi se passer allègrement de cet horrible switch.

Comme dit, je ne suis pas expert. Il faut que j'apprenne.
J'ai bien dit que j'allais m'intéresser à ce que vous me dites, mais j'avais tout de même envie de réussir avec mes connaissances.

Une grand merci à vous !
WinXaito.

+0 -0
Vous devez être connecté pour pouvoir poster un message.
Connexion

Pas encore inscrit ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte