Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Improve indentation in HTML postprocessor.

Improve text postprocessor based on HTML one.
  • Loading branch information...
commit 8bc6768d2ac73a6709712e14d8ed0c7223d4e0a9 1 parent a30c1a0
Peter Potrowl authored April 26, 2012
11  README.rst
Source Rendered
@@ -108,6 +108,17 @@ If you just want to replace the templates in a given wikitext, you can just call
108 108
 The `output` string will contain the rendered wikitext.
109 109
 Put the templates names and content in the `templates` dict (e.g.: `{'my template': 'my template content'}`)
110 110
 
  111
+Postprocessors
  112
+--------------
  113
+
  114
+The parser produces an AST. In order to provide human readable output, three postprocessors are provided:
  115
+ * html.py, for HTML output
  116
+ * text.py, for text output
  117
+ * raw.py, for raw output
  118
+
  119
+For now, we mainly focused on HTML postprocessor. The text output might not be as cleaned as expected.
  120
+
  121
+You can adapt them according to your needs.
111 122
 
112 123
 Known bugs
113 124
 ==========
2  apostrophes.py
@@ -28,7 +28,7 @@
28 28
 
29 29
 
30 30
 def parse_one_line(text, tags=default_tags):
31  
-        arr = _quotePat.split(text.strip())
  31
+        arr = _quotePat.split(text)
32 32
         if len(arr) == 1:
33 33
             return text
34 34
 
50  article.htm
... ...
@@ -1,7 +1,7 @@
1 1
 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2 2
 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr">
3 3
 <head><title>Test!</title></head><body>
4  
-<p>Contenu soumis à la licence CC-BY-SA 3.0 (<a href="http://creativecommons.org/licenses/by-sa/3.0/deed.fr)">http://creativecommons.org/licenses/by-sa/3.0/deed.fr)</a> Source : Article Berceuse de Wikipédia en français (<a href="http://fr.wikipedia.org/wiki/Berceuse).">http://fr.wikipedia.org/wiki/Berceuse).</a> </p>
  4
+<p>Contenu soumis à la licence CC-BY-SA 3.0 (<a href="http://creativecommons.org/licenses/by-sa/3.0/deed.fr">[1]</a>)<br />Source : Article Berceuse de Wikipédia en français (<a href="http://fr.wikipedia.org/wiki/Berceuse">[2]</a>).</p>
5 5
 <p><a href="Template:Voir homonymes">Template:Voir homonymes</a><a href="Template:ébauche">Template:ébauche</a><div class="thumbnail"><img src="William-Adolphe Bouguereau (1825-1905) - Lullaby (1875).jpg" style="float:right;width:250px;" alt="" /><p><em>La Berceuse</em> (œuvre de <a href="William Bouguereau">William Bouguereau</a> - <a href="Template:XIXe siècle">Template:XIXe siècle</a>)</p></div>
6 6
 Une <strong>berceuse</strong> est une <a href="chanson">chanson</a> douce destinée à aider les <a href="enfant">enfant</a>s à <a href="Sommeil">s'endormir</a>. Il existe des berceuses chantées dans toutes les langues du monde.</p>
7 7
 <h2>Berceuses françaises</h2>
@@ -20,61 +20,61 @@
20 20
 </table>
21 21
 <ul>
22 22
 	<li> <a href="Jean-Sébastien Bach">Bach</a><ul>
23  
-	<li> Menuet pour clavier Nº1 en sol majeur (Carnets intimes d'Anna Magdalena II/1), BWV Anh. 114</li>
24  
-	<li> « <a href="Jésus que ma joie demeure">Jésus, que ma joie demeure</a> », (<a href="Liste des cantates de Johann Sebastian Bach">Cantate Nº147</a>), BWV 147</li>
25  
-	<li> Suite pour orchestre n°3 en re majeur, BWV 1068</li>
  23
+		<li> Menuet pour clavier Nº1 en sol majeur (Carnets intimes d'Anna Magdalena II/1), BWV Anh. 114</li>
  24
+		<li> « <a href="Jésus que ma joie demeure">Jésus, que ma joie demeure</a> », (<a href="Liste des cantates de Johann Sebastian Bach">Cantate Nº147</a>), BWV 147</li>
  25
+		<li> Suite pour orchestre n°3 en re majeur, BWV 1068</li>
26 26
 </ul>
27 27
 </li>
28 28
 	<li> <a href="Ludwig van Beethoven">Beethoven</a><ul>
29  
-	<li> « <a href="Sonate pour piano nº 14 de Beethoven">Sonate au clair de lune</a> » (Sonate pour piano n° 14 en do dièse mineur), op. 27/2</li>
30  
-	<li> « <a href="La Lettre à Élise">Lettre à Élise</a> » (La Bagatelle en la mineur), WoO 59</li>
31  
-	<li> « <a href="Sonate pour piano nº 8 de Beethoven">Sonate Pathétique</a> » (Sonate pour piano nº 8 de Beethoven), op. 13/2, Adagio cantabile</li>
  29
+		<li> « <a href="Sonate pour piano nº 14 de Beethoven">Sonate au clair de lune</a> » (Sonate pour piano n° 14 en do dièse mineur), op. 27/2</li>
  30
+		<li> « <a href="La Lettre à Élise">Lettre à Élise</a> » (La Bagatelle en la mineur), WoO 59</li>
  31
+		<li> « <a href="Sonate pour piano nº 8 de Beethoven">Sonate Pathétique</a> » (Sonate pour piano nº 8 de Beethoven), op. 13/2, Adagio cantabile</li>
32 32
 </ul>
33 33
 </li>
34 34
 	<li> <a href="Johannes Brahms">Brahms</a><ul>
35  
-	<li> « Bonsoir et bonne nuit », berceuse ("Guten Abend, gut Nacht", Wiegenlied), op. 49/4</li>
  35
+		<li> « Bonsoir et bonne nuit », berceuse ("Guten Abend, gut Nacht", Wiegenlied), op. 49/4</li>
36 36
 </ul>
37 37
 </li>
38 38
 	<li> <a href="Frédéric Chopin">Chopin</a><ul>
39  
-	<li> « <a href="Berceuse (Chopin)">Berceuse en ré bémol majeur</a> », op.57</li>
  39
+		<li> « <a href="Berceuse (Chopin)">Berceuse en ré bémol majeur</a> », op.57</li>
40 40
 </ul>
41 41
 </li>
42 42
 	<li> <a href="Claude Debussy">Debussy</a><ul>
43  
-	<li> « <a href="Suite Bergamasque">Clair de lune</a> » ("Suite Bergamasque" pour piano), L. 75/3</li>
  43
+		<li> « <a href="Suite Bergamasque">Clair de lune</a> » ("Suite Bergamasque" pour piano), L. 75/3</li>
44 44
 </ul>
45 45
 </li>
46 46
 	<li> <a href="Antonín Dvořák">Dvořák</a><ul>
47  
-	<li> « <a href="Symphonie nº 9 de Dvořák">Sonate du Nouveau Monde</a> » (Symphonie n° 9 en mi mineur, B. 178), op. 95</li>
  47
+		<li> « <a href="Symphonie nº 9 de Dvořák">Sonate du Nouveau Monde</a> » (Symphonie n° 9 en mi mineur, B. 178), op. 95</li>
48 48
 </ul>
49 49
 </li>
50 50
 	<li> <a href="Gabriel Fauré">Fauré</a><ul>
51  
-	<li> « <a href="Dolly (Fauré)">Berceuse</a> » (première pièce de la suite Dolly, pour piano à quatre mains), op. 56</li>
  51
+		<li> « <a href="Dolly (Fauré)">Berceuse</a> » (première pièce de la suite Dolly, pour piano à quatre mains), op. 56</li>
52 52
 </ul>
53 53
 </li>
54 54
 	<li> <a href="Felix Mendelssohn Bartholdy">Mendelssohn</a><ul>
55  
-	<li> « <a href="Romances sans paroles (Mendelssohn)">Chant du printemps</a> » (Romances sans paroles pour piano), op. 62/6</li>
  55
+		<li> « <a href="Romances sans paroles (Mendelssohn)">Chant du printemps</a> » (Romances sans paroles pour piano), op. 62/6</li>
56 56
 </ul>
57 57
 </li>
58 58
 	<li> <a href="Wolfgang Amadeus Mozart">Mozart</a><ul>
59  
-	<li> « <a href="Ah ! vous dirai-je, maman">Ah ! vous dirai-je, maman</a> » (Douze variations), K. 265</li>
60  
-	<li> « <a href="Sonate pour piano n° 16 de Mozart">Sonate facile</a> » (Sonate pour piano nº 16 en do majeur), K. 545</li>
61  
-	<li> « La Chasse » (Sonate pour piano n° 18 en ré majeur), K. 576, 3ème mouvement</li>
  59
+		<li> « <a href="Ah ! vous dirai-je, maman">Ah ! vous dirai-je, maman</a> » (Douze variations), K. 265</li>
  60
+		<li> « <a href="Sonate pour piano n° 16 de Mozart">Sonate facile</a> » (Sonate pour piano nº 16 en do majeur), K. 545</li>
  61
+		<li> « La Chasse » (Sonate pour piano n° 18 en ré majeur), K. 576, 3ème mouvement</li>
62 62
 </ul>
63 63
 </li>
64 64
 	<li> <a href="Johann Pachelbel">Pachelbel</a><ul>
65  
-	<li> « <a href="Canon de Pachelbel">Canon en ré majeur sur une basse obstinée</a> »</li>
  65
+		<li> « <a href="Canon de Pachelbel">Canon en ré majeur sur une basse obstinée</a> »</li>
66 66
 </ul>
67 67
 </li>
68 68
 	<li> <a href="Robert Schumann">Schumann</a><ul>
69  
-	<li> « <a href="Scènes d'enfants (Schumann)">Gens et pays étrangers</a> » (Les Scènes d'enfants, "Kinderszenen"), op. 15</li>
  69
+		<li> « <a href="Scènes d'enfants (Schumann)">Gens et pays étrangers</a> » (Les Scènes d'enfants, "Kinderszenen"), op. 15</li>
70 70
 </ul>
71 71
 </li>
72 72
 	<li> <a href="Bedřich Smetana">Smetana</a><ul>
73  
-	<li> « <a href="Má Vlast">La Moldau</a> » (Second poèmes symphoniques de "Ma Patrie")</li>
  73
+		<li> « <a href="Má Vlast">La Moldau</a> » (Second poèmes symphoniques de "Ma Patrie")</li>
74 74
 </ul>
75 75
 </li>
76 76
 	<li> <a href="Antonio Vivaldi">Vivaldi</a><ul>
77  
-	<li> « <a href="Les Quatre Saisons">L'Hiver</a> » (Les Quatre Saisons, Opus 8/4)</li>
  77
+		<li> « <a href="Les Quatre Saisons">L'Hiver</a> » (Les Quatre Saisons, Opus 8/4)</li>
78 78
 </ul>
79 79
 </li>
80 80
 </ul>
@@ -82,17 +82,17 @@
82 82
 <h2>Dans la musique populaire</h2>
83 83
 <h3>Dans la chanson française</h3>
84 84
 <ul>
85  
-	<li><a href="Bénabar">Bénabar</a> : « La berceuse », de l'album <em><a href="Reprise des négociations">Reprise des négociations</a></em>, 2005</li>
86  
-	<li><a href="Henri Salvador">Henri Salvador</a> : « Une chanson douce » (Le Loup, la Biche et le Chevalier), de l'album <em>Rigolo</em>, 1968</li>
  85
+	<li> <a href="Bénabar">Bénabar</a> : « La berceuse », de l'album <em><a href="Reprise des négociations">Reprise des négociations</a></em>, 2005</li>
  86
+	<li> <a href="Henri Salvador">Henri Salvador</a> : « Une chanson douce » (Le Loup, la Biche et le Chevalier), de l'album <em>Rigolo</em>, 1968</li>
87 87
 </ul>
88 88
 <h3>Dans la musique pop</h3>
89 89
 <ul>
90  
-	<li><a href="Beatles">Beatles</a> : « <a href="Good Night (chanson)">Good Night</a> », de l'<em><a href="The Beatles (album)">album blanc</a></em>, 1968</li>
  90
+	<li> <a href="Beatles">Beatles</a> : « <a href="Good Night (chanson)">Good Night</a> », de l'<em><a href="The Beatles (album)">album blanc</a></em>, 1968</li>
91 91
 </ul>
92 92
 <h3>Dans le jazz</h3>
93 93
 <ul>
94  
-	<li><a href="Baden Powell de Aquino">Baden Powell</a> : « Berceuse a Jussara », de l'album <em>Le Monde Musical</em>, 1964</li>
95  
-	<li><a href="Henri Salvador">Henri Salvador</a> : « Une chanson douce » (Le Loup, la Biche et le Chevalier), de l'album <em>Rigolo</em>, 1968</li>
  94
+	<li> <a href="Baden Powell de Aquino">Baden Powell</a> : « Berceuse a Jussara », de l'album <em>Le Monde Musical</em>, 1964</li>
  95
+	<li> <a href="Henri Salvador">Henri Salvador</a> : « Une chanson douce » (Le Loup, la Biche et le Chevalier), de l'album <em>Rigolo</em>, 1968</li>
96 96
 </ul>
97 97
 <h2> Voir aussi </h2>
98 98
 <ul>
107  article.txt
... ...
@@ -0,0 +1,107 @@
  1
+Contenu soumis à la licence CC-BY-SA 3.0 ([1])
  2
+Source : Article Berceuse de Wikipédia en français ([2]).
  3
+Template:Voir homonymes (link: Template:Voir homonymes)Template:ébauche (link: Template:ébauche)Image: William-Adolphe Bouguereau (1825-1905) - Lullaby (1875).jpg, style: float:right;width:250px;, legend:_La Berceuse_ (œuvre de William Bouguereau (link: William Bouguereau) - Template:XIXe siècle (link: Template:XIXe siècle))
  4
+Une *berceuse* est une chanson (link: chanson) douce destinée à aider les enfant (link: enfant)s à s'endormir (link: Sommeil). Il existe des berceuses chantées dans toutes les langues du monde.
  5
+Berceuses françaises
  6
+Les berceuses françaises traditionnelles les plus connues sont « Dodo, l'enfant do / l'enfant dormira peut-être » et « Fais dodo, Colas mon p'tit frère ». Une berceuse du Nord, « P'tit Quinquin (link: P'tit Quinquin (chanson)) » est également devenue célèbre.
  7
+Dans la musique classique
  8
+Les berceuses en musique classique obéissent souvent à une forme nommée aussi "berceuse" dans les langues étrangères. Elles sont généralement à trois temps (link: Temps (solfège)), à tonalité (link: tonalité) simple, alternant des harmonies dominante (link: dominante) et tonique (link: Tonique (musique)).
  9
+*Berceuses célèbres classées par compositeurs :*
  10
+----------
  11
+ Fichier audio	
  12
+<span style="height:20px; width:100%; padding:4pt; padding-left:0.3em; line-height:2em;" cellspacing="0">*_Wiegenlied_ (Berceuse, op 49/4) (link: Media:Brahms_-_Schumann-Heink_-_Wiegenlied_(Berceuse)_(1915).ogg‎)* _(info (link: Fichier:Brahms_-_Schumann-Heink_-_Wiegenlied_(Berceuse)_(1915).ogg‎))_
  13
+<small>_Wiegenlied_ interprété par Ernestine Schumann-Heink (link: Ernestine Schumann-Heink)<center>Image: Brahms_-_Schumann-Heink_-_Wiegenlied_(Berceuse)_(1915).ogg‎, style: 
  14
+<span style="height:20px; width:100%; padding-left:0.3em;" cellspacing="0"><span title="Des difficultés pour écouter le fichier ?">Image: Circle question mark.png, style: width:14px; _Des problèmes pour écouter le fichier ? (link: Aide:Écouter des sons ogg)_
  15
+	
  16
+----------
  17
+
  18
+	*  Bach (link: Jean-Sébastien Bach)
  19
+		*  Menuet pour clavier Nº1 en sol majeur (Carnets intimes d'Anna Magdalena II/1), BWV Anh. 114
  20
+		*  « Jésus, que ma joie demeure (link: Jésus que ma joie demeure) », (Cantate Nº147 (link: Liste des cantates de Johann Sebastian Bach)), BWV 147
  21
+		*  Suite pour orchestre n°3 en re majeur, BWV 1068
  22
+
  23
+	*  Beethoven (link: Ludwig van Beethoven)
  24
+		*  « Sonate au clair de lune (link: Sonate pour piano nº 14 de Beethoven) » (Sonate pour piano n° 14 en do dièse mineur), op. 27/2
  25
+		*  « Lettre à Élise (link: La Lettre à Élise) » (La Bagatelle en la mineur), WoO 59
  26
+		*  « Sonate Pathétique (link: Sonate pour piano nº 8 de Beethoven) » (Sonate pour piano nº 8 de Beethoven), op. 13/2, Adagio cantabile
  27
+
  28
+	*  Brahms (link: Johannes Brahms)
  29
+		*  « Bonsoir et bonne nuit », berceuse ("Guten Abend, gut Nacht", Wiegenlied), op. 49/4
  30
+
  31
+	*  Chopin (link: Frédéric Chopin)
  32
+		*  « Berceuse en ré bémol majeur (link: Berceuse (Chopin)) », op.57
  33
+
  34
+	*  Debussy (link: Claude Debussy)
  35
+		*  « Clair de lune (link: Suite Bergamasque) » ("Suite Bergamasque" pour piano), L. 75/3
  36
+
  37
+	*  Dvořák (link: Antonín Dvořák)
  38
+		*  « Sonate du Nouveau Monde (link: Symphonie nº 9 de Dvořák) » (Symphonie n° 9 en mi mineur, B. 178), op. 95
  39
+
  40
+	*  Fauré (link: Gabriel Fauré)
  41
+		*  « Berceuse (link: Dolly (Fauré)) » (première pièce de la suite Dolly, pour piano à quatre mains), op. 56
  42
+
  43
+	*  Mendelssohn (link: Felix Mendelssohn Bartholdy)
  44
+		*  « Chant du printemps (link: Romances sans paroles (Mendelssohn)) » (Romances sans paroles pour piano), op. 62/6
  45
+
  46
+	*  Mozart (link: Wolfgang Amadeus Mozart)
  47
+		*  « Ah ! vous dirai-je, maman (link: Ah ! vous dirai-je, maman) » (Douze variations), K. 265
  48
+		*  « Sonate facile (link: Sonate pour piano n° 16 de Mozart) » (Sonate pour piano nº 16 en do majeur), K. 545
  49
+		*  « La Chasse » (Sonate pour piano n° 18 en ré majeur), K. 576, 3ème mouvement
  50
+
  51
+	*  Pachelbel (link: Johann Pachelbel)
  52
+		*  « Canon en ré majeur sur une basse obstinée (link: Canon de Pachelbel) »
  53
+
  54
+	*  Schumann (link: Robert Schumann)
  55
+		*  « Gens et pays étrangers (link: Scènes d'enfants (Schumann)) » (Les Scènes d'enfants, "Kinderszenen"), op. 15
  56
+
  57
+	*  Smetana (link: Bedřich Smetana)
  58
+		*  « La Moldau (link: Má Vlast) » (Second poèmes symphoniques de "Ma Patrie")
  59
+
  60
+	*  Vivaldi (link: Antonio Vivaldi)
  61
+		*  « L'Hiver (link: Les Quatre Saisons) » (Les Quatre Saisons, Opus 8/4)
  62
+
  63
+Les plus connues sont la berceuse « _Bonsoir et bonne nuit_ » de Brahms et la « _Berceuse en ré bémol majeur_ » de Chopin (link: Chopin). Des compositeurs comme Franz Liszt (link: Franz Liszt), Gabriel Fauré (link: Gabriel Fauré), Maurice Ravel (link: Maurice Ravel), Mili Balakirev (link: Mili Balakirev), Igor Stravinski (link: Igor Stravinski) (_Berceuses du chat (link: Berceuses du chat)_) et George Gershwin (link: George Gershwin) ont aussi écrit des berceuses.
  64
+Dans la musique populaire
  65
+Dans la chanson française
  66
+
  67
+	*  Bénabar (link: Bénabar) : « La berceuse », de l'album _Reprise des négociations (link: Reprise des négociations)_, 2005
  68
+	*  Henri Salvador (link: Henri Salvador) : « Une chanson douce » (Le Loup, la Biche et le Chevalier), de l'album _Rigolo_, 1968
  69
+Dans la musique pop
  70
+
  71
+	*  Beatles (link: Beatles) : « Good Night (link: Good Night (chanson)) », de l'_album blanc (link: The Beatles (album))_, 1968
  72
+Dans le jazz
  73
+
  74
+	*  Baden Powell (link: Baden Powell de Aquino) : « Berceuse a Jussara », de l'album _Le Monde Musical_, 1964
  75
+	*  Henri Salvador (link: Henri Salvador) : « Une chanson douce » (Le Loup, la Biche et le Chevalier), de l'album _Rigolo_, 1968
  76
+ Voir aussi 
  77
+
  78
+	*  Lullaby (link: Lullaby) dans la section anglaise et italienne où il y a une description d'une bonne partie des berceuses européennes.
  79
+Template:Wiktionnaire (link: Template:Wiktionnaire)
  80
+Bibliographie
  81
+
  82
+	* Claudine Antoine, _La Berceuse populaire dans le contexte de la petite enfance_, Université Strasbourg 2, 1988, 2 vol., 358 + 333 p. (thèse de Musiocologie)
  83
+	* Marina Altmann de Litvan (dir.), _La berceuse : jeux d'amour et de magie_, Erès, Ramonville Saint-Agne, 2008, 151 p. Template:ISBN (link: Template:ISBN)
  84
+Template:portail musique (link: Template:portail musique)
  85
+
  86
+
  87
+
  88
+Links:
  89
+[1] http://creativecommons.org/licenses/by-sa/3.0/deed.fr
  90
+[2] http://fr.wikipedia.org/wiki/Berceuse
  91
+
  92
+Categories:
  93
+* Berceuse
  94
+* Musique par genre
  95
+* Musique traditionnelle
  96
+
  97
+Interwiki:
  98
+* http://ar.wikipedia.org/wiki/تهويدة
  99
+* http://az.wikipedia.org/wiki/Layla
  100
+* http://br.wikipedia.org/wiki/Luskellerez
  101
+* http://ca.wikipedia.org/wiki/Cançó de bressol
  102
+* http://cs.wikipedia.org/wiki/Ukolébavka
  103
+* http://da.wikipedia.org/wiki/Berceuse
  104
+* http://de.wikipedia.org/wiki/Wiegenlied
  105
+* http://en.wikipedia.org/wiki/Lullaby
  106
+* http://eo.wikipedia.org/wiki/Lulkanto
  107
+* http://es.wikipedia.org/wiki/Nana (canción de cuna)
38  html.py
@@ -242,31 +242,35 @@ def render_preformatted(node):
242 242
     def render_hr(node):
243 243
         node.value = '<hr />\n'
244 244
 
245  
-    def render_ul(list):
  245
+    def render_ul(list, level):
  246
+        indent = level * '\t'
246 247
         result = '<ul>\n'
247 248
         for i in range(len(list)):
248  
-            result += '\t<li>' + content(list[i]) +  '</li>\n'
  249
+            result += indent + '<li>' + content(list[i]) +  '</li>\n'
249 250
         result += '</ul>\n'
250 251
         return result
251 252
 
252  
-    def render_ol(list):
  253
+    def render_ol(list, level):
  254
+        indent = level * '\t'
253 255
         result = '<ol>\n'
254 256
         for i in range(len(list)):
255  
-            result += '\t<li>' + content(list[i]) +  '</li>\n'
  257
+            result += indent + '<li>' + content(list[i]) +  '</li>\n'
256 258
         result += '</ol>\n'
257 259
         return result
258 260
 
259  
-    def render_dd(list):
  261
+    def render_dd(list, level):
  262
+        indent = level * '\t'
260 263
         result = '<dl>\n'
261 264
         for i in range(len(list)):
262  
-            result += '\t<dd>' + content(list[i]) +  '</dd>\n'
  265
+            result += indent + '<dd>' + content(list[i]) +  '</dd>\n'
263 266
         result += '</dl>\n'
264 267
         return result
265 268
 
266  
-    def render_dt(list):
  269
+    def render_dt(list, level):
  270
+        indent = level * '\t'
267 271
         result = '<dl>\n'
268 272
         for i in range(len(list)):
269  
-            result += '\t<dt>' + content(list[i]) +  '</dt>\n'
  273
+            result += indent + '<dt>' + content(list[i]) +  '</dt>\n'
270 274
         result += '</dl>\n'
271 275
         return result
272 276
 
@@ -285,35 +289,35 @@ def collapse_list(list):
285 289
             if isinstance(list[i].value, Nodes):
286 290
                 collapse_list(list[i].value)
287 291
 
288  
-    def select_items(nodes, i, value):
  292
+    def select_items(nodes, i, value, level):
289 293
         list_tags = ['bullet_list_leaf', 'number_list_leaf', 'colon_list_leaf', 'semi_colon_list_leaf']
290 294
         list_tags.remove(value)
291 295
         if isinstance(nodes[i].value, Nodes):
292  
-            render_lists(nodes[i].value)
  296
+            render_lists(nodes[i].value, level + 1)
293 297
         items = [nodes[i]]
294 298
         while i + 1 < len(nodes) and nodes[i+1].tag not in list_tags:
295 299
             if isinstance(nodes[i+1].value, Nodes):
296  
-                render_lists(nodes[i+1].value)
  300
+                render_lists(nodes[i+1].value, level + 1)
297 301
             items.append(nodes.pop(i+1))
298 302
         return items
299 303
 
300  
-    def render_lists(list):
  304
+    def render_lists(list, level):
301 305
         i = 0
302 306
         while i < len(list):
303 307
             if list[i].tag == 'bullet_list_leaf' or list[i].tag == '@bullet_sub_list@':
304  
-                list[i].value = render_ul(select_items(list, i, 'bullet_list_leaf'))
  308
+                list[i].value = render_ul(select_items(list, i, 'bullet_list_leaf', level), level)
305 309
             elif list[i].tag == 'number_list_leaf' or list[i].tag == '@number_sub_list@':
306  
-                list[i].value = render_ol(select_items(list, i, 'number_list_leaf'))
  310
+                list[i].value = render_ol(select_items(list, i, 'number_list_leaf', level), level)
307 311
             elif list[i].tag == 'colon_list_leaf' or list[i].tag == '@colon_sub_list@':
308  
-                list[i].value = render_dd(select_items(list, i, 'colon_list_leaf'))
  312
+                list[i].value = render_dd(select_items(list, i, 'colon_list_leaf', level), level)
309 313
             elif list[i].tag == 'semi_colon_list_leaf' or list[i].tag == '@semi_colon_sub_list@':
310  
-                list[i].value = render_dt(select_items(list, i, 'semi_colon_list_leaf'))
  314
+                list[i].value = render_dt(select_items(list, i, 'semi_colon_list_leaf', level), level)
311 315
             i += 1
312 316
 
313 317
     def render_list(node):
314 318
         assert isinstance(node.value, Nodes), "Bad AST shape!"
315 319
         collapse_list(node.value)
316  
-        render_lists(node.value)
  320
+        render_lists(node.value, 1)
317 321
 
318 322
     def render_url(node):
319 323
         node.value = '<a href="%s">%s</a>' % (node.leaf(), node.leaf())
33  parser.py
... ...
@@ -1,6 +1,10 @@
1 1
 # -*- coding: utf8 -*-
2 2
 
3 3
 import time
  4
+import codecs
  5
+
  6
+print "*** Parsing to HTML ***"
  7
+
4 8
 start_time = time.time()
5 9
 
6 10
 # get the parser
@@ -48,14 +52,13 @@
48 52
 parser = make_parser(allowed_tags, allowed_autoclose_tags, allowed_parameters, interwiki, namespaces)
49 53
 
50 54
 # import the source in a utf-8 string
51  
-import codecs
52 55
 fileObj = codecs.open("wikitext.txt", "r", "utf-8")
53 56
 source = fileObj.read()
54 57
 
55 58
 # The last line of the file will not be parsed correctly if
56 59
 # there is no newline at the end of file, so, we add one.
57 60
 if source[-1] != '\n':
58  
-  source += '\n'
  61
+    source += '\n'
59 62
 
60 63
 preprocessed_text = preprocessor.parse(source)
61 64
 tree = parser.parse(preprocessed_text.leaves())
@@ -67,4 +70,30 @@
67 70
 file("article.htm", "w").write(output.encode('UTF-8'))
68 71
 
69 72
 end_time = time.time()
  73
+print "Parsed and rendered in", end_time - start_time, "s."
  74
+
  75
+print "*** Parsing to text ***"
  76
+
  77
+start_time = time.time()
  78
+
  79
+from text import make_parser
  80
+parser = make_parser(interwiki, namespaces)
  81
+
  82
+# import the source in a utf-8 string
  83
+fileObj = codecs.open("wikitext.txt", "r", "utf-8")
  84
+source = fileObj.read()
  85
+
  86
+# The last line of the file will not be parsed correctly if
  87
+# there is no newline at the end of file, so, we add one.
  88
+if source[-1] != '\n':
  89
+    source += '\n'
  90
+
  91
+preprocessed_text = preprocessor.parse(source)
  92
+tree = parser.parse(preprocessed_text.leaves())
  93
+
  94
+output = tree.leaves()
  95
+
  96
+file("article.txt", "w").write(output.encode('UTF-8'))
  97
+
  98
+end_time = time.time()
70 99
 print "Parsed and rendered in", end_time - start_time, "s."
80  tests/test_html_postprocessor.py
@@ -145,8 +145,8 @@ def test_wikitext_in_table(self):
145 145
 <hr />
146 146
 <dl>
147 147
 \t<dd><dl>
148  
-\t<dd><dl>
149  
-\t<dd> lists</dd>
  148
+\t\t<dd><dl>
  149
+\t\t\t<dd> lists</dd>
150 150
 </dl>
151 151
 </dd>
152 152
 </dl>
@@ -355,11 +355,11 @@ def test_simple_bullet_list(self):
355 355
 """
356 356
         result = """<ul>
357 357
 \t<li> item 1<ul>
358  
-\t<li> item 2<ul>
359  
-\t<li> item 3</li>
  358
+\t\t<li> item 2<ul>
  359
+\t\t\t<li> item 3</li>
360 360
 </ul>
361 361
 </li>
362  
-\t<li> item 2</li>
  362
+\t\t<li> item 2</li>
363 363
 </ul>
364 364
 </li>
365 365
 </ul>
@@ -374,23 +374,23 @@ def test_simple_numbered_list(self):
374 374
 """
375 375
         result = """<ol>
376 376
 \t<li><ol>
377  
-\t<li> item 2</li>
  377
+\t\t<li> item 2</li>
378 378
 </ol>
379 379
 </li>
380 380
 \t<li><ol>
381  
-\t<li><ol>
382  
-\t<li> item 3</li>
  381
+\t\t<li><ol>
  382
+\t\t\t<li> item 3</li>
383 383
 </ol>
384 384
 </li>
385 385
 </ol>
386 386
 </li>
387 387
 \t<li><ol>
388  
-\t<li> item 2</li>
  388
+\t\t<li> item 2</li>
389 389
 </ol>
390 390
 </li>
391 391
 \t<li><ol>
392  
-\t<li><ol>
393  
-\t<li> item 3</li>
  392
+\t\t<li><ol>
  393
+\t\t\t<li> item 3</li>
394 394
 </ol>
395 395
 </li>
396 396
 </ol>
@@ -409,14 +409,14 @@ def test_simple_semicolon_list(self):
409 409
 """
410 410
         result = """<dl>
411 411
 \t<dt> item 1<dl>
412  
-\t<dt> item 2</dt>
413  
-\t<dt> item 2</dt>
  412
+\t\t<dt> item 2</dt>
  413
+\t\t<dt> item 2</dt>
414 414
 </dl>
415 415
 </dt>
416 416
 \t<dt> item 1</dt>
417 417
 \t<dt> item 1<dl>
418  
-\t<dt><dl>
419  
-\t<dt> item 3</dt>
  418
+\t\t<dt><dl>
  419
+\t\t\t<dt> item 3</dt>
420 420
 </dl>
421 421
 </dt>
422 422
 </dl>
@@ -435,16 +435,16 @@ def test_simple_colon_list(self):
435 435
 """
436 436
         result = """<dl>
437 437
 \t<dd> item 1<dl>
438  
-\t<dd><dl>
439  
-\t<dd> item 3</dd>
  438
+\t\t<dd><dl>
  439
+\t\t\t<dd> item 3</dd>
440 440
 </dl>
441 441
 </dd>
442  
-\t<dd> item 2</dd>
  442
+\t\t<dd> item 2</dd>
443 443
 </dl>
444 444
 </dd>
445 445
 \t<dd> item 1<dl>
446  
-\t<dd> item 2</dd>
447  
-\t<dd> item 2</dd>
  446
+\t\t<dd> item 2</dd>
  447
+\t\t<dd> item 2</dd>
448 448
 </dl>
449 449
 </dd>
450 450
 </dl>
@@ -462,10 +462,10 @@ def test_formatted_mixed_list(self):
462 462
 \t<dd> item 1</dd>
463 463
 </dl>
464 464
 <dl>
465  
-\t<dt>this is <em>italic</em></dt>
  465
+\t<dt> this is <em>italic</em></dt>
466 466
 </dl>
467 467
 <ul>
468  
-\t<li>and <strong>bold</strong> here</li>
  468
+\t<li> and <strong>bold</strong> here</li>
469 469
 </ul>
470 470
 <ol>
471 471
 \t<li> a <a href="link">link</a></li>
@@ -495,35 +495,35 @@ def test_complex_mixed_list(self):
495 495
         result = """<ul>
496 496
 \t<li>level 1</li>
497 497
 \t<li>level 1<ul>
498  
-\t<li>level 2<ol>
499  
-\t<li>level 3</li>
  498
+\t\t<li>level 2<ol>
  499
+\t\t\t<li>level 3</li>
500 500
 </ol>
501 501
 </li>
502  
-\t<li>level 2</li>
  502
+\t\t<li>level 2</li>
503 503
 </ul>
504 504
 </li>
505 505
 \t<li><dl>
506  
-\t<dd> level 2</dd>
  506
+\t\t<dd> level 2</dd>
507 507
 </dl>
508 508
 </li>
509 509
 </ul>
510 510
 <dl>
511 511
 \t<dt> level 1</dt>
512 512
 \t<dt><ol>
513  
-\t<li>level 2</li>
  513
+\t\t<li>level 2</li>
514 514
 </ol>
515 515
 </dt>
516 516
 \t<dt><ol>
517  
-\t<li><dl>
518  
-\t<dt>level 3</dt>
  517
+\t\t<li><dl>
  518
+\t\t\t<dt>level 3</dt>
519 519
 </dl>
520 520
 </li>
521 521
 </ol>
522 522
 </dt>
523 523
 \t<dt><ol>
524  
-\t<li><ol>
525  
-\t<li><ol>
526  
-\t<li>level 4</li>
  524
+\t\t<li><ol>
  525
+\t\t\t<li><ol>
  526
+\t\t\t\t<li>level 4</li>
527 527
 </ol>
528 528
 </li>
529 529
 </ol>
@@ -531,9 +531,9 @@ def test_complex_mixed_list(self):
531 531
 </ol>
532 532
 </dt>
533 533
 \t<dt><ul>
534  
-\t<li><ul>
535  
-\t<li><ol>
536  
-\t<li>level 4</li>
  534
+\t\t<li><ul>
  535
+\t\t\t<li><ol>
  536
+\t\t\t\t<li>level 4</li>
537 537
 </ol>
538 538
 </li>
539 539
 </ul>
@@ -541,11 +541,11 @@ def test_complex_mixed_list(self):
541 541
 </ul>
542 542
 </dt>
543 543
 \t<dt><ul>
544  
-\t<li><dl>
545  
-\t<dt><ol>
546  
-\t<li><ul>
547  
-\t<li><dl>
548  
-\t<dd> weird syntax</dd>
  544
+\t\t<li><dl>
  545
+\t\t\t<dt><ol>
  546
+\t\t\t\t<li><ul>
  547
+\t\t\t\t\t<li><dl>
  548
+\t\t\t\t\t\t<dd> weird syntax</dd>
549 549
 </dl>
550 550
 </li>
551 551
 </ul>
173  tests/test_text_postprocessor.py
@@ -169,3 +169,176 @@ def test_styles_in_template(self):
169 169
         result = "Here, we have *text* and _more text_ and _*still more text*_.\n"
170 170
         templates = {'template': "'''text''' and ''more text'' and '''''still more text'''''"}
171 171
         self.parsed_equal_string(source, result, None, templates, 'text')
  172
+
  173
+    def test_simple_bullet_list(self):
  174
+        source = """* item 1
  175
+** item 2
  176
+*** item 3
  177
+** item 2
  178
+"""
  179
+        result = """
  180
+\t*  item 1
  181
+\t\t*  item 2
  182
+\t\t\t*  item 3
  183
+
  184
+\t\t*  item 2
  185
+
  186
+"""
  187
+        self.parsed_equal_string(source, result, 'wikitext', {}, 'text')
  188
+
  189
+    def test_simple_numbered_list(self):
  190
+        source = """## item 2
  191
+### item 3
  192
+## item 2
  193
+### item 3
  194
+"""
  195
+        result = """
  196
+\t1. 
  197
+\t\t1.  item 2
  198
+
  199
+\t2. 
  200
+\t\t1. 
  201
+\t\t\t1.  item 3
  202
+
  203
+
  204
+\t3. 
  205
+\t\t1.  item 2
  206
+
  207
+\t4. 
  208
+\t\t1. 
  209
+\t\t\t1.  item 3
  210
+
  211
+
  212
+"""
  213
+        self.parsed_equal_string(source, result, 'wikitext', {}, 'text')
  214
+
  215
+    def test_simple_semicolon_list(self):
  216
+        source = """; item 1
  217
+;; item 2
  218
+;; item 2
  219
+; item 1
  220
+; item 1
  221
+;;; item 3
  222
+"""
  223
+        result = """
  224
+\t*  item 1
  225
+\t\t*  item 2
  226
+\t\t*  item 2
  227
+
  228
+\t*  item 1
  229
+\t*  item 1
  230
+\t\t* 
  231
+\t\t\t*  item 3
  232
+
  233
+
  234
+"""
  235
+        self.parsed_equal_string(source, result, 'wikitext', {}, 'text')
  236
+
  237
+    def test_simple_colon_list(self):
  238
+        source = """: item 1
  239
+::: item 3
  240
+:: item 2
  241
+: item 1
  242
+:: item 2
  243
+:: item 2
  244
+"""
  245
+        result = """
  246
+\t*  item 1
  247
+\t\t* 
  248
+\t\t\t*  item 3
  249
+
  250
+\t\t*  item 2
  251
+
  252
+\t*  item 1
  253
+\t\t*  item 2
  254
+\t\t*  item 2
  255
+
  256
+"""
  257
+        self.parsed_equal_string(source, result, 'wikitext', {}, 'text')
  258
+
  259
+    def test_formatted_mixed_list(self):
  260
+        source = """: item 1
  261
+; this is ''italic''
  262
+* and '''bold''' here
  263
+# a [[link]]
  264
+: a {{template}}
  265
+"""
  266
+        result = """
  267
+\t*  item 1
  268
+
  269
+\t*  this is _italic_
  270
+
  271
+\t*  and *bold* here
  272
+
  273
+\t1.  a link (link: link)
  274
+
  275
+\t*  a template!
  276
+"""
  277
+        templates = {'template': 'template!'}
  278
+        self.parsed_equal_string(source, result, 'wikitext', templates, 'text')
  279
+
  280
+    def test_complex_mixed_list(self):
  281
+        source = """*level 1
  282
+*level 1
  283
+**level 2
  284
+**#level 3
  285
+**level 2
  286
+:: level 2
  287
+; level 1
  288
+##level 2
  289
+##;level 3
  290
+####level 4
  291
+#**#level 4
  292
+:*;#*: weird syntax
  293
+* end
  294
+"""
  295
+        result = """
  296
+\t* level 1
  297
+\t* level 1
  298
+\t\t* level 2
  299
+\t\t\t1. level 3
  300
+
  301
+\t\t* level 2
  302
+
  303
+\t* 
  304
+\t\t*  level 2
  305
+
  306
+
  307
+\t*  level 1
  308
+\t* 
  309
+\t\t1. level 2
  310
+
  311
+\t* 
  312
+\t\t1. 
  313
+\t\t\t* level 3
  314
+
  315
+
  316
+\t* 
  317
+\t\t1. 
  318
+\t\t\t1. 
  319
+\t\t\t\t1. level 4
  320
+
  321
+
  322
+
  323
+\t* 
  324
+\t\t* 
  325
+\t\t\t* 
  326
+\t\t\t\t1. level 4
  327
+
  328
+
  329
+
  330
+\t* 
  331
+\t\t* 
  332
+\t\t\t* 
  333
+\t\t\t\t1. 
  334
+\t\t\t\t\t* 
  335
+\t\t\t\t\t\t*  weird syntax
  336
+
  337
+
  338
+
  339
+
  340
+
  341
+
  342
+\t*  end
  343
+"""
  344
+        self.parsed_equal_string(source, result, 'wikitext', {}, 'text')
304  text.py
... ...
@@ -1,8 +1,51 @@
1 1
 from constants import html_entities
  2
+from pijnu.library.node import Nil, Nodes, Node
2 3
 from mediawiki_parser import wikitextParser
3 4
 import apostrophes
4 5
 
5  
-def toolset():
  6
+def toolset(interwiki, namespaces):
  7
+    tags_stack = []
  8
+
  9
+    external_autonumber = []
  10
+    """ This is for the autonumbering of external links.
  11
+    e.g.: "[http://www.mozilla.org] [http://fr.wikipedia.org] text"
  12
+    is rendered as: "[1] [2] text
  13
+    Links:
  14
+    [1] http://www.mozilla.org
  15
+    [2] http://fr.wikipedia.org
  16
+    """
  17
+
  18
+    external_links = []
  19
+    """ This will contain the external links of the article. """
  20
+    category_links = []
  21
+    """ This will contain the links to the categories of the article. """
  22
+    interwiki_links = []
  23
+    """ This will contain the links to the foreign versions of the article. """
  24
+
  25
+    style_tags = {'bold': '*', 'bold_close': '*', 'italic': '_', 'italic_close': '_'}
  26
+
  27
+    for namespace, value in namespaces.iteritems():
  28
+        assert value in range(16), "Incorrect value for namespaces"
  29
+    """
  30
+    Predefined namespaces; source: includes/Defines.php of MediaWiki-1.17.0
  31
+    'NS_MAIN', 0
  32
+    'NS_TALK', 1
  33
+    'NS_USER', 2
  34
+    'NS_USER_TALK', 3
  35
+    'NS_PROJECT', 4
  36
+    'NS_PROJECT_TALK', 5
  37
+    'NS_FILE', 6
  38
+    'NS_FILE_TALK', 7
  39
+    'NS_MEDIAWIKI', 8
  40
+    'NS_MEDIAWIKI_TALK', 9
  41
+    'NS_TEMPLATE', 10
  42
+    'NS_TEMPLATE_TALK', 11
  43
+    'NS_HELP', 12
  44
+    'NS_HELP_TALK', 13
  45
+    'NS_CATEGORY', 14
  46
+    'NS_CATEGORY_TALK', 15 
  47
+    """
  48
+
6 49
     def render_tag_p(attributes):
7 50
         return '\n'
8 51
 
@@ -12,6 +55,9 @@ def render_tag_br(attributes):
12 55
     allowed_tags = {'p': render_tag_p,
13 56
                     'br': render_tag_br}
14 57
 
  58
+    def content(node):
  59
+        return apostrophes.parse('%s' % node.leaf(), style_tags)
  60
+
15 61
     def render_title1(node):
16 62
         node.value = '%s\n' % node.leaf()
17 63
 
@@ -40,21 +86,27 @@ def render_wikitext(node):
40 86
         pass
41 87
 
42 88
     def render_body(node):
43  
-        tags = {'bold': '*', 'bold_close': '*', 'italic': '_', 'italic_close': '_'}
44  
-        node.value = apostrophes.parse('%s' % node.leaves(), tags)
  89
+        metadata = ''
  90
+        if external_links != []:
  91
+            metadata += '\nLinks:\n' + '\n'.join(external_links) + '\n'
  92
+        if category_links != []:
  93
+            metadata += '\nCategories:\n' + '\n'.join(category_links) + '\n'
  94
+        if interwiki_links != []:
  95
+            metadata += '\nInterwiki:\n' + '\n'.join(interwiki_links) + '\n'
  96
+        node.value = apostrophes.parse('%s' % node.leaves(), style_tags) + metadata
45 97
 
46 98
     def render_entity(node):
47 99
         value = '%s' % node.leaf()
48 100
         if value in html_entities:
49 101
             node.value = '%s' % unichr(html_entities[value])
50 102
         else:
51  
-            node.value = '&%s;' % value
  103
+            node.value = '&amp;%s;' % value
52 104
 
53 105
     def render_lt(node):
54  
-        pass
  106
+        node.value = '<'
55 107
 
56 108
     def render_gt(node):
57  
-        pass
  109
+        node.value = '>'
58 110
 
59 111
     def process_attribute(node, allowed_tag):
60 112
         assert len(node.value) == 2, "Bad AST shape!"
@@ -103,45 +155,251 @@ def render_tag_autoclose(node):
103 155
             node.value = '<%s%s />' % (tag_name, attributes)
104 156
 
105 157
     def render_table(node):
106  
-        pass
107  
-
108  
-    def render_table_line_break(node):
109  
-        node.value = '\n'
  158
+        table_content = ''
  159
+        if isinstance(node.value, Nodes) and node.value[0].tag == 'table_begin':
  160
+            contents = node.value[1].value
  161
+            for item in contents:
  162
+                table_content += content(item)
  163
+        else:
  164
+            table_content = content(node)
  165
+        node.value = '----------\n%s\n----------\n' % table_content
  166
+
  167
+    def render_cell_content(node):
  168
+        if isinstance(node.value, Nil):
  169
+            return None
  170
+        cell_content = ''
  171
+        if len(node.value) > 1:
  172
+            values = node.value[0].value
  173
+            for value in values:
  174
+                if isinstance(value, Node):
  175
+                    if not (value.tag == 'HTML_attribute' and value.value != ''):
  176
+                        cell_content += value.leaf()
  177
+                else:
  178
+                    cell_content += value
  179
+            cell_content += content(node.value[1])
  180
+        else:
  181
+            cell_content = content(node)
  182
+        return cell_content
110 183
 
111 184
     def render_table_header_cell(node):
112  
-        pass
  185
+        result = ''
  186
+        if isinstance(node.value, Nodes):
  187
+            for i in range(len(node.value)):
  188
+                content = render_cell_content(node.value[i])
  189
+                result += '%s\t' % content
  190
+        else:
  191
+            content = render_cell_content(node)
  192
+            result = '%s\t' % content            
  193
+        if result != '':
  194
+            node.value = result
113 195
 
114 196
     def render_table_normal_cell(node):
115  
-        pass
  197
+        result = ''
  198
+        if isinstance(node.value, Nodes):
  199
+            for i in range(len(node.value)):
  200
+                content = render_cell_content(node.value[i])
  201
+                result += '%s\t' % content
  202
+        else:
  203
+            content = render_cell_content(node)
  204
+            result = '%s\t' % content            
  205
+        if result != '':
  206
+            node.value = result
116 207
 
117 208
     def render_table_empty_cell(node):
118  
-        pass
  209
+        node.value = '\t'
119 210
 
120 211
     def render_table_caption(node):
121  
-        pass
  212
+        content = render_cell_content(node)
  213
+        if content is not None:
  214
+            node.value = '\t%s\n' % content
  215
+
  216
+    def render_table_line_break(node):
  217
+        node.value = '\n'
122 218
 
123 219
     def render_preformatted(node):
124  
-        pass
  220
+        node.value = content(node) + '\n'
125 221
 
126 222
     def render_hr(node):
127 223
         node.value = '------'
128 224
 
129  
-    def render_li(node):
130  
-        pass
  225
+    def render_ul(list, level):
  226
+        indent = level * '\t'
  227
+        result = '\n'
  228
+        for i in range(len(list)):
  229
+            result += indent + '* ' + content(list[i]) + '\n'
  230
+        return result
  231
+
  232
+    def render_ol(list, level):
  233
+        indent = level * '\t'
  234
+        result = '\n'
  235
+        for i in range(len(list)):
  236
+            result += indent + '%i. %s\n' % (i + 1, content(list[i]))
  237
+        return result
  238
+
  239
+    def render_dd(list, level):
  240
+        indent = level * '\t'
  241
+        result = '\n'
  242
+        for i in range(len(list)):
  243
+            result += indent + '* ' + content(list[i]) + '\n'
  244
+        return result
  245
+
  246
+    def render_dt(list, level):
  247
+        indent = level * '\t'
  248
+        result = '\n'
  249
+        for i in range(len(list)):
  250
+            result += indent + '* ' + content(list[i]) + '\n'
  251
+        return result
  252
+
  253
+    def collapse_list(list):
  254
+        i = 0
  255
+        while i+1 < len(list):
  256
+            if list[i].tag == 'bullet_list_leaf' and list[i+1].tag == '@bullet_sub_list@' or \
  257
+               list[i].tag == 'number_list_leaf' and list[i+1].tag == '@number_sub_list@' or \
  258
+               list[i].tag == 'colon_list_leaf' and list[i+1].tag == '@colon_sub_list@' or \
  259
+               list[i].tag == 'semi_colon_list_leaf' and list[i+1].tag == '@semi_colon_sub_list@':
  260
+                list[i].value.append(list[i+1].value[0])
  261
+                list.pop(i+1)
  262
+            else:
  263
+                i += 1
  264
+        for i in range(len(list)):
  265
+            if isinstance(list[i].value, Nodes):
  266
+                collapse_list(list[i].value)
  267
+
  268
+    def select_items(nodes, i, value, level):
  269
+        list_tags = ['bullet_list_leaf', 'number_list_leaf', 'colon_list_leaf', 'semi_colon_list_leaf']
  270
+        list_tags.remove(value)
  271
+        if isinstance(nodes[i].value, Nodes):
  272
+            render_lists(nodes[i].value, level + 1)
  273
+        items = [nodes[i]]
  274
+        while i + 1 < len(nodes) and nodes[i+1].tag not in list_tags:
  275
+            if isinstance(nodes[i+1].value, Nodes):
  276
+                render_lists(nodes[i+1].value, level + 1)
  277
+            items.append(nodes.pop(i+1))
  278
+        return items
  279
+
  280
+    def render_lists(list, level):
  281
+        i = 0
  282
+        while i < len(list):
  283
+            if list[i].tag == 'bullet_list_leaf' or list[i].tag == '@bullet_sub_list@':
  284
+                list[i].value = render_ul(select_items(list, i, 'bullet_list_leaf', level), level)
  285
+            elif list[i].tag == 'number_list_leaf' or list[i].tag == '@number_sub_list@':
  286
+                list[i].value = render_ol(select_items(list, i, 'number_list_leaf', level), level)
  287
+            elif list[i].tag == 'colon_list_leaf' or list[i].tag == '@colon_sub_list@':
  288
+                list[i].value = render_dd(select_items(list, i, 'colon_list_leaf', level), level)
  289
+            elif list[i].tag == 'semi_colon_list_leaf' or list[i].tag == '@semi_colon_sub_list@':
  290
+                list[i].value = render_dt(select_items(list, i, 'semi_colon_list_leaf', level), level)
  291
+            i += 1
131 292
 
132 293
     def render_list(node):
133  
-        pass
  294
+        assert isinstance(node.value, Nodes), "Bad AST shape!"
  295
+        collapse_list(node.value)
  296
+        render_lists(node.value, 1)
134 297
 
135 298
     def render_url(node):
136  
-        pass
  299
+        node.value = '<a href="%s">%s</a>' % (node.leaf(), node.leaf())
137 300
 
138 301
     def render_external_link(node):
139  
-        pass
  302
+        if len(node.value) == 1:
  303
+            external_autonumber.append(node.leaf())
  304
+            url = node.leaf()
  305
+            text = len(external_autonumber)
  306
+        else:
  307
+            url = node.value[0].leaf()
  308
+            text = node.value[1].leaf()
  309
+        node.value = '[%s]' % (text)
  310
+        external_links.append('[%s] %s' % (text, url))
  311
+
  312
+    def render_interwiki(prefix, page):
  313
+        link = '* %s' % (interwiki[prefix] + page)
  314
+        if link not in interwiki_links:
  315
+            interwiki_links.append(link)
  316
+
  317
+    def render_category(category_name):
  318
+        link = '* %s' % (category_name)
  319
+        if link not in category_links:
  320
+            category_links.append(link)
  321
+
  322
+    def render_file(file_name, arguments):
  323
+        """ This implements a basic handling of images.
  324
+        MediaWiki supports much more parameters (see includes/Parser.php).
  325
+        """
  326
+        style = ''
  327
+        thumbnail = False
  328
+        legend = ''
  329
+        if arguments != []:
  330
+            parameters = arguments[0].value
  331
+            for parameter in parameters:
  332
+                parameter = '%s' % parameter.leaf()
  333
+                if parameter[-2:] == 'px':
  334
+                    size = parameter[0:-2]
  335
+                    if 'x' in size:
  336
+                        size_x, size_y = size.split('x', 1)
  337
+                        try:
  338
+                            size_x = int(size_x)
  339
+                            size_y = int(size_y)
  340
+                            style += 'width:%spx;height:%spx' % (size_x, size_y)
  341
+                        except:
  342
+                            legend = parameter
  343
+                    else:
  344
+                        try:
  345
+                            size_x = int(size)
  346
+                            style += 'width:%spx;' % size_x
  347
+                        except:
  348
+                            legend = parameter
  349
+                elif parameter in ['left', 'right', 'center']:
  350
+                    style += 'float:%s;' % parameter
  351
+                elif parameter in ['thumb', 'thumbnail']:
  352
+                    thumbnail = True
  353
+                elif parameter == 'border':
  354
+                    style += 'border:1px solid grey'
  355
+                else:
  356
+                    legend = parameter
  357
+        result = 'Image: %s, style: %s' % (file_name, style)
  358
+        if thumbnail:
  359
+            result = '%s, legend:%s\n' % (result, legend)
  360
+        return result
140 361
 
141 362
     def render_internal_link(node):
142  
-        pass
  363
+        force_link = False
  364
+        url = ''
  365
+        page_name = node.value.pop(0).value
  366
+        if page_name[0] == ':':
  367
+            force_link = True
  368
+            page_name = page_name[1:]
  369
+        if ':' in page_name:
  370
+            namespace, page_name = page_name.split(':', 1)
  371
+            if namespace in interwiki and not force_link:
  372
+                render_interwiki(namespace, page_name)
  373
+                node.value = ''
  374
+                return
  375
+            elif namespace in interwiki:
  376
+                url = interwiki[namespace]
  377
+                namespace = ''
  378
+            if namespace in namespaces:
  379
+                if namespaces[namespace] == 6 and not force_link:  # File
  380
+                    node.value = render_file(page_name, node.value)
  381
+                    return
  382
+                elif namespaces[namespace] == 14 and not force_link:  # Category
  383
+                    render_category(page_name)
  384
+                    node.value = ''
  385
+                    return
  386
+            if namespace:
  387
+                page_name = namespace + ':' + page_name
  388
+        if len(node.value) == 0:
  389
+            text = page_name
  390
+        else:
  391
+            text = '|'.join('%s' % item.leaf() for item in node.value[0])
  392
+        node.value = '%s (link: %s%s)' % (text, url, page_name)
143 393
 
144 394
     return locals()
145 395
 
146  
-def make_parser():
147  
-    return wikitextParser.make_parser(toolset())
  396
+def make_parser(interwiki={}, namespaces={}):
  397
+    """Constructs the parser for the text backend.
  398
+
  399
+    :arg interwiki: List of the allowed interwiki prefixes (en, fr, es, commons, etc.)
  400
+    :arg namespaces: List of the namespaces of the wiki (File, Category, Template, etc.),
  401
+            including the localized version of those strings (Modele, Categorie, etc.),
  402
+            associated to the corresponding namespace code.
  403
+    """
  404
+    tools = toolset(interwiki, namespaces)
  405
+    return wikitextParser.make_parser(tools)
3  wikitext.txt
... ...
@@ -1,4 +1,5 @@
1  
-Contenu soumis à la licence CC-BY-SA 3.0 (http://creativecommons.org/licenses/by-sa/3.0/deed.fr) Source : Article Berceuse de Wikipédia en français (http://fr.wikipedia.org/wiki/Berceuse). 
  1
+Contenu soumis à la licence CC-BY-SA 3.0 ([http://creativecommons.org/licenses/by-sa/3.0/deed.fr])<br />
  2
+Source : Article Berceuse de Wikipédia en français ([http://fr.wikipedia.org/wiki/Berceuse]).
2 3
 
3 4
 {{Voir homonymes|Berceuse (homonymie)}}
4 5
 {{ébauche|musique}}

0 notes on commit 8bc6768

Please sign in to comment.
Something went wrong with that request. Please try again.