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

Le problème exposé dans ce sujet a été résolu.

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

+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
}
+0 -0

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). ;)

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++;
}
+0 -0

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é

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

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

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.

+0 -0

Ç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.

+0 -1

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.

Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

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