Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Add HTML rendering for internal links.

This includes rendering for categories, interwiki links and media files.

Also: add a full test: parsing an article from the French Wikipedia. To
run it, launch "python parser.py" and look at article.htm
  • Loading branch information...
commit 4f58bb3314918d6432bde0839dc8828dbdb07e5f 1 parent e2b6293
@peter17 peter17 authored
View
102 article.htm
@@ -0,0 +1,102 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr">
+<head><title>Test!</title></head><body>
+<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>
+<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;" /><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>
+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>
+<h2>Berceuses françaises</h2>
+<p>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, « <a href="P'tit Quinquin (chanson)">P'tit Quinquin</a> » est également devenue célèbre.</p>
+<h2>Dans la musique classique</h2>
+<p>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 <a href="Temps (solfège)">temps</a>, à <a href="tonalité">tonalité</a> simple, alternant des harmonies <a href="dominante">dominante</a> et <a href="Tonique (musique)">tonique</a>.</p>
+<p><strong>Berceuses célèbres classées par compositeurs :</strong></p>
+{| style="text-align:center; background: #f9f9f9; color: #000;font-size:90%; line-height:1.1em; float:right;clear:right; margin:1em 1.5em 1em 1em; width:300px; border: 1px solid #aaa; padding: 0.1em;" cellspacing="7"<p>! class="media audio" style="background-color:#ccf; line-height:3.1em" | Fichier audio|-|<span style="height:20px; width:100%; padding:4pt; padding-left:0.3em; line-height:2em;"><strong>[[Media:{{{filename|{{{nomfichier|{<a href="Template:2">Template:2</a>}}}}}}}|{{{title|{{{titre|{<a href="Template:1">Template:1</a>}}}}}}}]]</strong> <em>([[:Fichier:{{{filename|{{{nomfichier|{<a href="Template:2">Template:2</a>}}}}}}}|info]])</em><br />&lt;small&gt;{{{suitetexte|{<a href="Template:description">Template:description</a>}}}}&lt;/small&gt;&lt;center&gt;[[Fichier:{{{filename|{{{nomfichier|{<a href="Template:2">Template:2</a>}}}}}}}|noicon]]&lt;/center&gt;</span><br /><span style="height:20px; width:100%; padding-left:0.3em;"><span><img src="Circle question mark.png" style="width:14px;" /> <em><a href="Aide:Écouter des sons ogg">Des problèmes pour écouter le fichier ?</a></em></span>|}</span></p>
+<ul>
+ <li> <a href="Jean-Sébastien Bach">Bach</a><ul>
+ <li> Menuet pour clavier Nº1 en sol majeur (Carnets intimes d'Anna Magdalena II/1), BWV Anh. 114</li>
+ <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>
+ <li> Suite pour orchestre n°3 en re majeur, BWV 1068</li>
+</ul>
+</li>
+ <li> <a href="Ludwig van Beethoven">Beethoven</a><ul>
+ <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>
+ <li> « <a href="La Lettre à Élise">Lettre à Élise</a> » (La Bagatelle en la mineur), WoO 59</li>
+ <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>
+</ul>
+</li>
+ <li> <a href="Johannes Brahms">Brahms</a><ul>
+ <li> « Bonsoir et bonne nuit », berceuse ("Guten Abend, gut Nacht", Wiegenlied), op. 49/4</li>
+</ul>
+</li>
+ <li> <a href="Frédéric Chopin">Chopin</a><ul>
+ <li> « <a href="Berceuse (Chopin)">Berceuse en ré bémol majeur</a> », op.57</li>
+</ul>
+</li>
+ <li> <a href="Claude Debussy">Debussy</a><ul>
+ <li> « <a href="Suite Bergamasque">Clair de lune</a> » ("Suite Bergamasque" pour piano), L. 75/3</li>
+</ul>
+</li>
+ <li> <a href="Antonín Dvořák">Dvořák</a><ul>
+ <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>
+</ul>
+</li>
+ <li> <a href="Gabriel Fauré">Fauré</a><ul>
+ <li> « <a href="Dolly (Fauré)">Berceuse</a> » (première pièce de la suite Dolly, pour piano à quatre mains), op. 56</li>
+</ul>
+</li>
+ <li> <a href="Felix Mendelssohn Bartholdy">Mendelssohn</a><ul>
+ <li> « <a href="Romances sans paroles (Mendelssohn)">Chant du printemps</a> » (Romances sans paroles pour piano), op. 62/6</li>
+</ul>
+</li>
+ <li> <a href="Wolfgang Amadeus Mozart">Mozart</a><ul>
+ <li> « <a href="Ah ! vous dirai-je, maman">Ah ! vous dirai-je, maman</a> » (Douze variations), K. 265</li>
+ <li> « <a href="Sonate pour piano n° 16 de Mozart">Sonate facile</a> » (Sonate pour piano nº 16 en do majeur), K. 545</li>
+ <li> « La Chasse » (Sonate pour piano n° 18 en ré majeur), K. 576, 3ème mouvement</li>
+</ul>
+</li>
+ <li> <a href="Johann Pachelbel">Pachelbel</a><ul>
+ <li> « <a href="Canon de Pachelbel">Canon en ré majeur sur une basse obstinée</a> »</li>
+</ul>
+</li>
+ <li> <a href="Robert Schumann">Schumann</a><ul>
+ <li> « <a href="Scènes d'enfants (Schumann)">Gens et pays étrangers</a> » (Les Scènes d'enfants, "Kinderszenen"), op. 15</li>
+</ul>
+</li>
+ <li> <a href="Bedřich Smetana">Smetana</a><ul>
+ <li> « <a href="Má Vlast">La Moldau</a> » (Second poèmes symphoniques de "Ma Patrie")</li>
+</ul>
+</li>
+ <li> <a href="Antonio Vivaldi">Vivaldi</a><ul>
+ <li> « <a href="Les Quatre Saisons">L'Hiver</a> » (Les Quatre Saisons, Opus 8/4)</li>
+</ul>
+</li>
+</ul>
+<p>Les plus connues sont la berceuse « <em>Bonsoir et bonne nuit</em> » de Brahms et la « <em>Berceuse en ré bémol majeur</em> » de <a href="Chopin">Chopin</a>. Des compositeurs comme <a href="Franz Liszt">Franz Liszt</a>, <a href="Gabriel Fauré">Gabriel Fauré</a>, <a href="Maurice Ravel">Maurice Ravel</a>, <a href="Mili Balakirev">Mili Balakirev</a>, <a href="Igor Stravinski">Igor Stravinski</a> (<em><a href="Berceuses du chat">Berceuses du chat</a></em>) et <a href="George Gershwin">George Gershwin</a> ont aussi écrit des berceuses.</p>
+<h2>Dans la musique populaire</h2>
+<h3>Dans la chanson française</h3>
+<ul>
+ <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>
+ <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>
+</ul>
+<h3>Dans la musique pop</h3>
+<ul>
+ <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>
+</ul>
+<h3>Dans le jazz</h3>
+<ul>
+ <li> <a href="Baden Powell de Aquino">Baden Powell</a> : « Berceuse a Jussara », de l'album <em>Le Monde Musical</em>, 1964</li>
+ <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>
+</ul>
+<h2> Voir aussi </h2>
+<ul>
+ <li> <a href="Lullaby">Lullaby</a> dans la section anglaise et italienne où il y a une description d'une bonne partie des berceuses européennes.</li>
+</ul>
+<p><a href="Template:Wiktionnaire">Template:Wiktionnaire</a></p>
+<h3>Bibliographie</h3>
+<ul>
+ <li>Claudine Antoine, <em>La Berceuse populaire dans le contexte de la petite enfance</em>, Université Strasbourg 2, 1988, 2 vol., 358 + 333 p. (thèse de Musiocologie)</li>
+ <li>Marina Altmann de Litvan (dir.), <em>La berceuse : jeux d'amour et de magie</em>, Erès, Ramonville Saint-Agne, 2008, 151 p. <a href="Template:ISBN">Template:ISBN</a></li>
+</ul>
+<p><a href="Template:portail musique">Template:portail musique</a></p>
+<p>Categories: <a href="Berceuse">Berceuse</a>, <a href="Musique par genre">Musique par genre</a>, <a href="Musique traditionnelle">Musique traditionnelle</a></p>
+<p>Interwiki: <a href="http://ar.wikipedia.org/wiki/تهويدة">تهويدة</a>, <a href="http://az.wikipedia.org/wiki/Layla">Layla</a>, <a href="http://br.wikipedia.org/wiki/Luskellerez">Luskellerez</a>, <a href="http://ca.wikipedia.org/wiki/Cançó de bressol">Cançó de bressol</a>, <a href="http://cs.wikipedia.org/wiki/Ukolébavka">Ukolébavka</a>, <a href="http://da.wikipedia.org/wiki/Berceuse">Berceuse</a>, <a href="http://de.wikipedia.org/wiki/Wiegenlied">Wiegenlied</a>, <a href="http://en.wikipedia.org/wiki/Lullaby">Lullaby</a>, <a href="http://eo.wikipedia.org/wiki/Lulkanto">Lulkanto</a>, <a href="http://es.wikipedia.org/wiki/Nana (canción de cuna)">Nana (canción de cuna)</a></p>
+</body></html>
View
133 html.py
@@ -1,8 +1,9 @@
from constants import html_entities
from pijnu.library.node import Nil, Nodes
from mediawiki_parser import wikitextParser
+from mutagen import Metadata
-def toolset(allowed_tags, allowed_autoclose_tags, allowed_attributes):
+def toolset(allowed_tags, allowed_autoclose_tags, allowed_attributes, interwiki, namespaces):
tags_stack = []
external_autonumber = []
@@ -11,6 +12,33 @@ def toolset(allowed_tags, allowed_autoclose_tags, allowed_attributes):
is rendered as: "<a href="...">[1]</a> <a href="...">[2]</a>
"""
+ category_links = []
+ """ This will contain the links to the categories of the article. """
+ interwiki_links = []
+ """ This will contain the links to the foreign versions of the article. """
+
+ for namespace, value in namespaces.iteritems():
+ assert value in range(16), "Incorrect value for namespaces"
+ """
+ Predefined namespaces; source: includes/Defines.php of MediaWiki-1.17.0
+ 'NS_MAIN', 0
+ 'NS_TALK', 1
+ 'NS_USER', 2
+ 'NS_USER_TALK', 3
+ 'NS_PROJECT', 4
+ 'NS_PROJECT_TALK', 5
+ 'NS_FILE', 6
+ 'NS_FILE_TALK', 7
+ 'NS_MEDIAWIKI', 8
+ 'NS_MEDIAWIKI_TALK', 9
+ 'NS_TEMPLATE', 10
+ 'NS_TEMPLATE_TALK', 11
+ 'NS_HELP', 12
+ 'NS_HELP_TALK', 13
+ 'NS_CATEGORY', 14
+ 'NS_CATEGORY_TALK', 15
+ """
+
def balance_tags(tag=None):
i = 0
if tag is not None:
@@ -48,11 +76,18 @@ def render_raw_text(node):
node.value = "%s" % node.leaf()
def render_paragraph(node):
- node.value = '<p>' + content(node) + '</p>\n'
+ value = content(node)
+ if value != '':
+ node.value = '<p>' + value + '</p>\n'
def render_body(node):
from apostrophes import parseAllQuotes
- node.value = '<body>\n' + parseAllQuotes(content(node)) + '</body>'
+ metadata = ''
+ if category_links != []:
+ metadata += '<p>Categories: ' + ', '.join(category_links) + '</p>\n'
+ if interwiki_links != []:
+ metadata += '<p>Interwiki: ' + ', '.join(interwiki_links) + '</p>\n'
+ node.value = '<body>\n' + parseAllQuotes(content(node)) + metadata + '</body>'
def render_entity(node):
value = '%s' % node.leaf()
@@ -269,9 +304,91 @@ def render_external_link(node):
text = node.value[1].leaf()
node.value = '<a href="%s">%s</a>' % (node.value[0].leaf(), text)
+ def render_interwiki(prefix, page):
+ link = '<a href="%s">%s</a>' % (interwiki[prefix] + page, page)
+ if link not in interwiki_links:
+ interwiki_links.append(link)
+
+ def render_category(category_name):
+ link = '<a href="%s">%s</a>' % (category_name, category_name)
+ if link not in category_links:
+ category_links.append(link)
+
+ def render_file(file_name, arguments):
+ """ This implements a basic handling of images.
+ MediaWiki supports much more parameters (see includes/Parser.php).
+ """
+ style = ''
+ thumbnail = False
+ legend = ''
+ if arguments != []:
+ parameters = arguments[0].value
+ for parameter in parameters:
+ parameter = '%s' % parameter.leaf()
+ if parameter[-2:] == 'px':
+ size = parameter[0:-2]
+ if 'x' in size:
+ size_x, size_y = size.split('x', 1)
+ try:
+ size_x = int(size_x)
+ size_y = int(size_y)
+ style += 'width:%spx;height:%spx' % (size_x, size_y)
+ except:
+ legend = parameter
+ else:
+ try:
+ size_x = int(size)
+ style += 'width:%spx;' % size_x
+ except:
+ legend = parameter
+ elif parameter in ['left', 'right', 'center']:
+ style += 'float:%s;' % parameter
+ elif parameter in ['thumb', 'thumbnail']:
+ thumbnail = True
+ elif parameter == 'border':
+ style += 'border:1px solid grey'
+ else:
+ legend = parameter
+ result = '<img src="%s" style="%s" />' % (file_name, style)
+ if thumbnail:
+ result = '<div class="thumbnail">%s<p>%s</p></div>\n' % (result, legend)
+ return result
+
+ def render_internal_link(node):
+ force_link = False
+ url = ''
+ page_name = node.value.pop(0).value
+ if page_name[0] == ':':
+ force_link = True
+ page_name = page_name[1:]
+ if ':' in page_name:
+ namespace, page_name = page_name.split(':', 1)
+ if namespace in interwiki and not force_link:
+ render_interwiki(namespace, page_name)
+ node.value = ''
+ return
+ elif namespace in interwiki:
+ url = interwiki[namespace]
+ namespace = ''
+ if namespace in namespaces:
+ if namespaces[namespace] == 6 and not force_link: # File
+ node.value = render_file(page_name, node.value)
+ return
+ elif namespaces[namespace] == 14 and not force_link: # Category
+ render_category(page_name)
+ node.value = ''
+ return
+ if namespace:
+ page_name = namespace + ':' + page_name
+ if len(node.value) == 0:
+ text = page_name
+ else:
+ text = '|'.join('%s' % item.leaf() for item in node.value[0])
+ node.value = '<a href="%s%s">%s</a>' % (url, page_name, text)
+
return locals()
-def make_parser(allowed_tags=[], allowed_autoclose_tags=[], allowed_attributes=[]):
+def make_parser(allowed_tags=[], allowed_autoclose_tags=[], allowed_attributes=[], interwiki={}, namespaces={}):
"""Constructs the parser for the HTML backend.
:arg allowed_tags: List of the HTML tags that should be allowed in the parsed wikitext.
@@ -281,7 +398,11 @@ def make_parser(allowed_tags=[], allowed_autoclose_tags=[], allowed_attributes=[
parsed wikitext. All the other self-closing tags will be output as &lt;tag /&gt;
:arg allowed_attributes: List of the HTML attributes that should be allowed in the parsed
tags (e.g.: class="", style=""). All the other attributes (e.g.: onclick="") will
- be removed.
+ be removed.
+ :arg interwiki: List of the allowed interwiki prefixes (en, fr, es, commons, etc.)
+ :arg namespaces: List of the namespaces of the wiki (File, Category, Template, etc.),
+ including the localized version of those strings (Modele, Categorie, etc.),
+ associated to the corresponding namespace code.
"""
- tools = toolset(allowed_tags, allowed_autoclose_tags, allowed_attributes)
+ tools = toolset(allowed_tags, allowed_autoclose_tags, allowed_attributes, interwiki, namespaces)
return wikitextParser.make_parser(tools)
View
4 mediawiki.pijnu
@@ -113,6 +113,7 @@ def replace_by_space(node):
# TODO: allow IPv6 addresses (http://[::1]/etc)
address : (!(QUOTE/R_BRACKET) [\x21..\xff])+ : liftValue
url : protocol address : join
+ inline_url : url{1} : render_url
# Links
@@ -120,7 +121,7 @@ def replace_by_space(node):
link_text : (clean_inline / allowed_in_link)* : liftValue
link_argument : PIPE link_text : liftValue
link_arguments : link_argument*
- internal_link : LINK_BEGIN page_name link_arguments LINK_END : liftValue
+ internal_link : LINK_BEGIN page_name link_arguments LINK_END : render_internal_link
optional_link_text : SPACETAB+ link_text : liftValue
external_link : L_BRACKET url optional_link_text? R_BRACKET : render_external_link
link : internal_link / external_link
@@ -137,7 +138,6 @@ def replace_by_space(node):
# Text types
- inline_url : url{1} : render_url
styled_text : link / inline_url / html_comment / tag / entity
not_styled_text : preformatted / nowiki
allowed_char : ESC_CHAR{1} : restore liftValue
View
42 parser.py
@@ -8,15 +8,41 @@
mediawikiGrammar = file("mediawiki.pijnu").read()
makeParser(mediawikiGrammar)
-templates = {'template1': 'Content of template1.',
- 'template 2': '"Template 2" has 2 parameters: {{{1}}} and: {{{name|default}}}!',
- 'Template with': 'test {{{1}}} {{{2}}}'}
+allowed_tags = ['p', 'span', 'b', 'i']
+allowed_autoclose_tags = ['br', 'hr']
+allowed_parameters = ['class', 'style', 'name', 'id', 'scope']
+interwiki = {'ar': 'http://ar.wikipedia.org/wiki/',
+ 'az': 'http://az.wikipedia.org/wiki/',
+ 'br': 'http://br.wikipedia.org/wiki/',
+ 'ca': 'http://ca.wikipedia.org/wiki/',
+ 'cs': 'http://cs.wikipedia.org/wiki/',
+ 'da': 'http://da.wikipedia.org/wiki/',
+ 'de': 'http://de.wikipedia.org/wiki/',
+ 'en': 'http://en.wikipedia.org/wiki/',
+ 'eo': 'http://eo.wikipedia.org/wiki/',
+ 'es': 'http://es.wikipedia.org/wiki/',
+ 'fr': 'http://fr.wikipedia.org/wiki/'}
+
+namespaces = {'Template': 10,
+ u'Catégorie': 14,
+ 'Category': 14,
+ 'File': 6,
+ 'Fichier': 6,
+ 'Image': 6}
+templates = {'listen': u"""{| style="text-align:center; background: #f9f9f9; color: #000;font-size:90%; line-height:1.1em; float:right;clear:right; margin:1em 1.5em 1em 1em; width:300px; border: 1px solid #aaa; padding: 0.1em;" cellspacing="7"
+! class="media audio" style="background-color:#ccf; line-height:3.1em" | Fichier audio
+|-
+|<span style="height:20px; width:100%; padding:4pt; padding-left:0.3em; line-height:2em;" cellspacing="0">'''[[Media:{{{filename|{{{nomfichier|{{{2|}}}}}}}}}|{{{title|{{{titre|{{{1|}}}}}}}}}]]''' ''([[:Fichier:{{{filename|{{{nomfichier|{{{2|}}}}}}}}}|info]])''<br /><small>{{{suitetexte|{{{description|}}}}}}</small>
+<center>[[Fichier:{{{filename|{{{nomfichier|{{{2|}}}}}}}}}|noicon]]</center></span><br /><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|14px|link=Aide:Écouter des sons ogg|Des difficultés pour écouter le fichier ?]] ''[[Aide:Écouter des sons ogg|Des problèmes pour écouter le fichier ?]]''</span>
+|}
+""",
+ '3e': '3<sup>e</sup>'}
from preprocessor import make_parser
preprocessor = make_parser(templates)
from html import make_parser
-parser = make_parser()
+parser = make_parser(allowed_tags, allowed_autoclose_tags, allowed_parameters, interwiki, namespaces)
# import the source in a utf-8 string
import codecs
@@ -29,8 +55,10 @@
source += '\n'
preprocessed_text = preprocessor.parse(source)
+tree = parser.parse(preprocessed_text.leaves())
-print preprocessed_text.treeView()
+output = """<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr">
+<head><title>Test!</title></head>""" + tree.leaves() + "</html>"
-tree = parser.parse(preprocessed_text.leaves())
-print tree.leaves()
+file("article.htm", "w").write(output.encode('UTF-8'))
View
3  raw.py
@@ -90,6 +90,9 @@ def render_url(node):
def render_external_link(node):
pass
+ def render_internal_link(node):
+ pass
+
return locals()
def make_parser():
View
9 tests/__init__.py
@@ -63,7 +63,14 @@ def _grammar(self, method_name, postprocessor_name):
allowed_tags = ['p', 'span', 'b', 'i']
allowed_autoclose_tags = ['br', 'hr']
allowed_parameters = ['class', 'style', 'name', 'id', 'scope']
- parser = html.make_parser(allowed_tags, allowed_autoclose_tags, allowed_parameters)
+ interwiki = {'en': 'http://en.wikipedia.org/wiki/',
+ 'fr': 'http://fr.wikipedia.org/wiki/'}
+ namespaces = {'Template': 10,
+ u'Catégorie': 14,
+ 'Category': 14,
+ 'File': 6,
+ 'Image': 6}
+ parser = html.make_parser(allowed_tags, allowed_autoclose_tags, allowed_parameters, interwiki, namespaces)
elif postprocessor_name == 'text':
parser = text.make_parser()
else:
View
37 tests/test_html_postprocessor.py
@@ -113,7 +113,7 @@ def test_complex_table(self):
<tr>
\t<th scope="row"> Line 2</th>
\t<td>data L2.A</td>
-\t<td>data Template:template</td>
+\t<td>data <a href="Template:template">Template:template</a></td>
</tr>
</table>
</body>"""
@@ -197,7 +197,7 @@ def test_preformatted_paragraph(self):
templates = {'template': 'content'}
result = """<body>
<pre>test
-Template:template
+<a href="Template:template">Template:template</a>
test
</pre>
</body>"""
@@ -394,7 +394,7 @@ def test_formatted_mixed_list(self):
\t<li> and <strong>bold</strong> here</li>
</ul>
<ol>
-\t<li> a link</li>
+\t<li> a <a href="link">link</a></li>
</ol>
<dl>
\t<dd> a template!</dd>
@@ -540,3 +540,34 @@ def test_external_links(self):
source = "text [http://www.mozilla.org], [http://www.github.com] and [http://fr.wikipedia.org ''French'' Wikipedia] text\n"
result = '<body>\n<p>text <a href="http://www.mozilla.org">[1]</a>, <a href="http://www.github.com">[2]</a> and <a href="http://fr.wikipedia.org"><em>French</em> Wikipedia</a> text</p>\n</body>'
self.parsed_equal_string(source, result, None, {}, 'html')
+
+ def test_internal_links(self):
+ source = "Links: [[page]], [[page|alternate]], [[page|alternate|alternate2]] and [[Page name|a{{test}}c]]\n"
+ result = '<p>Links: <a href="page">page</a>, <a href="page">alternate</a>, <a href="page">alternate|alternate2</a> and <a href="Page name">abc</a></p>\n'
+ templates = {'test': 'b'}
+ self.parsed_equal_string(source, result, 'wikitext', templates, 'html')
+
+ def test_categories_links(self):
+ source = u"[[:Category:Cat name|a ''text'']]\n[[Catégorie:Ma catégorie]]\n[[Category:My category|sort key]]\n"
+ result = u'<body>\n<p><a href="Category:Cat name">a <em>text</em></a></p>\n<p>Categories: <a href="Ma catégorie">Ma catégorie</a>, <a href="My category">My category</a></p>\n</body>'
+ self.parsed_equal_string(source, result, None, {}, 'html')
+
+ def test_interwiki_links(self):
+ source = u"[[:fr:Un lien...|texte]]\n[[fr:Mon article]]\n[[en:My article]]\n"
+ result = u'<body>\n<p><a href="http://fr.wikipedia.org/wiki/Un lien...">texte</a></p>\n<p>Interwiki: <a href="http://fr.wikipedia.org/wiki/Mon article">Mon article</a>, <a href="http://en.wikipedia.org/wiki/My article">My article</a></p>\n</body>'
+ self.parsed_equal_string(source, result, None, {}, 'html')
+
+ def test_files(self):
+ source = """[[Image:File.png|thumb|right|200px|Legend]]
+[[Image:File.png|thumb|right|200x100px|'''Formatted''' [[legend]]!]]
+[[File:Name.png]]
+[[:File:Name.png|link to a file]]
+[[File:Test.jpg|left|thumbnail]]
+"""
+ result = """<body>
+<p><div class="thumbnail"><img src="File.png" style="float:right;width:200px;" /><p>Legend</p></div>
+<div class="thumbnail"><img src="File.png" style="float:right;width:200px;height:100px" /><p><strong>Formatted</strong> <a href="legend">legend</a>!</p></div>
+<img src="Name.png" style="" /><a href="File:Name.png">link to a file</a><div class="thumbnail"><img src="Test.jpg" style="float:left;" /><p></p></div>
+</p>
+</body>"""
+ self.parsed_equal_string(source, result, None, {}, 'html')
View
6 tests/test_links.py
@@ -6,7 +6,7 @@
class LinksTests(ParserTestCase):
def test_simple_internal_link(self):
source = '[[article]]'
- result = "[internal_link:'article']"
+ result = "[internal_link:[page_name:'article']]"
self.parsed_equal_string(source, result, 'inline')
def test_advanced_internal_link(self):
@@ -37,12 +37,12 @@ def test_link_to_category(self):
def test_category_foreign_language(self):
source = u'[[Catégorie:Nom de catégorie]]'
- result = u"[internal_link:'Catégorie:Nom de catégorie']"
+ result = u"[internal_link:[page_name:'Catégorie:Nom de catégorie']]"
self.parsed_equal_string(source, result, 'inline')
def test_image(self):
source = '[[File:Filename.png]]'
- result = "[internal_link:'File:Filename.png']"
+ result = "[internal_link:[page_name:'File:Filename.png']]"
self.parsed_equal_string(source, result, 'inline')
def test_image_with_parameter(self):
View
6 tests/test_lists.py
@@ -47,12 +47,12 @@ def test_4_colon_list(self):
def test_1_semicolon_list(self):
source = '; still more [[text]]\n'
- result = "[list:[semi_colon_list_leaf:[raw_text:' still more ' internal_link:'text']]]"
+ result = "[list:[semi_colon_list_leaf:[raw_text:' still more ' internal_link:[page_name:'text']]]]"
self.parsed_equal_string(source, result, None)
def test_2_semicolon_list(self):
source = ';; still more [[text]]\n'
- result = "[list:[@semi_colon_sub_list@:[semi_colon_list_leaf:[raw_text:' still more ' internal_link:'text']]]]"
+ result = "[list:[@semi_colon_sub_list@:[semi_colon_list_leaf:[raw_text:' still more ' internal_link:[page_name:'text']]]]]"
self.parsed_equal_string(source, result, None)
def test_1_colon_1_bullet_list(self):
@@ -72,7 +72,7 @@ def test_2_semicolon_2_bullet_list(self):
def test_composed_list(self):
source = "*:*;#*: this is {{correct}} syntax!\n"
- result = "[list:[@bullet_sub_list@:[@colon_sub_list@:[@bullet_sub_list@:[@semi_colon_sub_list@:[@number_sub_list@:[@bullet_sub_list@:[colon_list_leaf:[raw_text:' this is ' internal_link:'Template:correct' raw_text:' syntax!']]]]]]]]]"
+ result = "[list:[@bullet_sub_list@:[@colon_sub_list@:[@bullet_sub_list@:[@semi_colon_sub_list@:[@number_sub_list@:[@bullet_sub_list@:[colon_list_leaf:[raw_text:' this is ' internal_link:[page_name:'Template:correct'] raw_text:' syntax!']]]]]]]]]"
self.parsed_equal_string(source, result, None)
def test_multiline_bullet_list(self):
View
2  tests/test_nowiki.py
@@ -12,7 +12,7 @@ def test_nowiki_section(self):
def test_nested_nowiki(self):
# This looks weird but is the actual behavior of MediaWiki
source = '<nowiki>some [[text]] <nowiki>that should </nowiki>{{not}} be changed</nowiki>\n'
- result = "[paragraphs:[paragraph:[nowiki:'some [[text]] <nowiki>that should ' internal_link:'Template:not' raw_text:' be changed' tag_close:[tag_name:'nowiki']]]]"
+ result = "[paragraphs:[paragraph:[nowiki:'some [[text]] <nowiki>that should ' internal_link:[page_name:'Template:not'] raw_text:' be changed' tag_close:[tag_name:'nowiki']]]]"
self.parsed_equal_string(source, result, None)
def test_multiline_nowiki(self):
View
3  tests/test_paragraphs.py
@@ -60,7 +60,8 @@ def test_styled_text_in_paragraph(self):
paragraphs:
paragraph:
raw_text:Styled text such as ''italic'', '''bold''',
- internal_link:Template:templates
+ internal_link:
+ page_name:Template:templates
raw_text: and
allowed_char:{
allowed_char:{
View
3  tests/test_preformatted_paragraphs.py
@@ -57,7 +57,8 @@ def test_style_in_preformatted_paragraph(self):
preformatted_line:
@inline@:
raw_text:Styled text such as ''italic'', '''bold''',
- internal_link:Template:templates
+ internal_link:
+ page_name:Template:templates
raw_text: also work.
EOL_KEEP:
"""
View
2  tests/test_rules.py
@@ -24,6 +24,6 @@ def test_rule_too_long(self):
def test_inline_after_rule(self):
# In this case, it is a paragraph!
source = '------ {{template|arg=[[link]]}}\n'
- result = u"[horizontal_rule:[@inline@:[raw_text:' test: ' internal_link:'link']]]"
+ result = u"[horizontal_rule:[@inline@:[raw_text:' test: ' internal_link:[page_name:'link']]]]"
templates = {'template': 'test: {{{arg}}}'}
self.parsed_equal_string(source, result, None, templates)
View
6 tests/test_special_chars.py
@@ -107,7 +107,7 @@ def test_dash(self):
def test_double_r_bracket_with_link(self):
source = 'This should be a [[link]] and [[plain text'
- result = "[raw_text:'This should be a ' internal_link:'link' raw_text:' and ' allowed_char:'[' allowed_char:'[' raw_text:'plain text']"
+ result = "[raw_text:'This should be a ' internal_link:[page_name:'link'] raw_text:' and ' allowed_char:'[' allowed_char:'[' raw_text:'plain text']"
self.parsed_equal_string(source, result, 'inline')
def test_valid_named_entities(self):
@@ -132,7 +132,7 @@ def test_invalid_numbered_entities(self):
def test_valid_entities_in_links(self):
source = 'a [[test&copy;test]] and two other: [[&diams;]] [[&#8212;]]'
- result = u"[raw_text:'a ' internal_link:'test©test' raw_text:' and two other: ' internal_link:'♦' raw_text:' ' internal_link:'—']"
+ result = u"[raw_text:'a ' internal_link:[page_name:'test©test'] raw_text:' and two other: ' internal_link:[page_name:'♦'] raw_text:' ' internal_link:[page_name:'—']]"
self.parsed_equal_string(source, result, 'inline')
def test_invalid_entities_in_links(self):
@@ -142,7 +142,7 @@ def test_invalid_entities_in_links(self):
def test_valid_entities_in_template_calls(self):
source = 'a {{test&copy;test}} and another: {{&diams;}}'
- result = u"[raw_text:'a ' internal_link:'Template:test©test' raw_text:' and another: ' internal_link:'Template:♦']"
+ result = u"[raw_text:'a ' internal_link:[page_name:'Template:test©test'] raw_text:' and another: ' internal_link:page_name['Template:♦']]"
#self.parsed_equal_string(source, result, 'inline')
import nose
raise nose.SkipTest
View
4 tests/test_titles.py
@@ -43,7 +43,7 @@ def test_title7(self):
def test_link_in_title(self):
source = '= [[a link]] =\n'
- result = "[title1:[raw_text:' ' internal_link:'a link' raw_text:' ']]"
+ result = "[title1:[raw_text:' ' internal_link:[page_name:'a link'] raw_text:' ']]"
self.parsed_equal_string(source, result, None)
def test_italic_in_title(self):
@@ -63,7 +63,7 @@ def test_formatted_link_in_title(self):
def test_simple_template_in_title(self):
source = '===== {{Title 5}} =====\n'
- result = "[title5:[raw_text:' ' internal_link:'Template:Title 5' raw_text:' ']]"
+ result = "[title5:[raw_text:' ' internal_link:[page_name:'Template:Title 5'] raw_text:' ']]"
self.parsed_equal_string(source, result, None)
def test_braces_in_title(self):
View
3  text.py
@@ -130,6 +130,9 @@ def render_url(node):
def render_external_link(node):
pass
+ def render_internal_link(node):
+ pass
+
return locals()
def make_parser():
View
129 wikitext.txt
@@ -1,37 +1,92 @@
-== Title ==
-This is a paragraph.
-
-This is a [[link#Title|link test]], '''bold and ''italic'' texts'''.
-
-An http://www.mozilla.org URL.
-
-[[Image:Test.png|thumb|150px|Legend]]
-
-{{template1}}
-
-a comment <!-- comment --> (ignored)... < > <<< >>>
-
-a <pre>preformatted {{section}} {{{parameter|default}}} </pre>
-
-a <nowiki>nowiki {{section}} {{{parameter|default}}} </nowiki>
-
- preformatted line
- with a {{template}}
-
-parameters: {{{parameter|default}}} {{{parameter}}}
-
-{{Template with|1=parameter| 2 = parameters }}
-
-another {{template 2|1=Value1|name=[[Value for name]]}} successfully substituted template
-
-----
-
-here, we use templates inside template parameters: {{template 2|1=Value1|name={{template 2|1=Value1|name=Value for name}}}}
-
-here, we specify no value so the default value is used when it exists: {{template 2|1=test}} or {{template 2|name=test}}
-
-links in templates: {{template 2|1=[http://www.mozilla.org Value1]|name=[[Value|for name]]}}
-
-unknown templates are replaced by a link: {{template 3|param|param2=[[link]] | param3 = [[the|parameters]]|test={{template}}|test2={{other template|param=[[link]]}}}}
-
-a [[Category:Tests|Text]]
+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).
+
+{{Voir homonymes|Berceuse (homonymie)}}
+{{ébauche|musique}}
+[[Fichier:William-Adolphe Bouguereau (1825-1905) - Lullaby (1875).jpg|thumb|right|250px|''La Berceuse'' (œuvre de [[William Bouguereau]] - {{XIXe siècle}})]]
+Une '''berceuse''' est une [[chanson]] douce destinée à aider les [[enfant]]s à [[Sommeil|s'endormir]]. Il existe des berceuses chantées dans toutes les langues du monde.
+
+==Berceuses françaises==
+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 (chanson)|P'tit Quinquin]] » est également devenue célèbre.
+
+==Dans la musique classique==
+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 (solfège)|temps]], à [[tonalité]] simple, alternant des harmonies [[dominante]] et [[Tonique (musique)|tonique]].
+
+'''Berceuses célèbres classées par compositeurs :'''
+{{listen
+|title=''Wiegenlied'' (Berceuse, op 49/4)
+|filename=Brahms_-_Schumann-Heink_-_Wiegenlied_(Berceuse)_(1915).ogg‎
+|description= ''Wiegenlied'' interprété par [[Ernestine Schumann-Heink]]
+}}
+* [[Jean-Sébastien Bach|Bach]]
+** Menuet pour clavier Nº1 en sol majeur (Carnets intimes d'Anna Magdalena II/1), BWV Anh. 114
+** « [[Jésus que ma joie demeure|Jésus, que ma joie demeure]] », ([[Liste des cantates de Johann Sebastian Bach|Cantate Nº147]]), BWV 147
+** Suite pour orchestre n°3 en re majeur, BWV 1068
+* [[Ludwig van Beethoven|Beethoven]]
+** « [[Sonate pour piano nº 14 de Beethoven|Sonate au clair de lune]] » (Sonate pour piano n° 14 en do dièse mineur), op. 27/2
+** « [[La Lettre à Élise|Lettre à Élise]] » (La Bagatelle en la mineur), WoO 59
+** « [[Sonate pour piano nº 8 de Beethoven|Sonate Pathétique]] » (Sonate pour piano nº 8 de Beethoven), op. 13/2, Adagio cantabile
+* [[Johannes Brahms|Brahms]]
+** « Bonsoir et bonne nuit », berceuse ("Guten Abend, gut Nacht", Wiegenlied), op. 49/4
+* [[Frédéric Chopin|Chopin]]
+** « [[Berceuse (Chopin)|Berceuse en ré bémol majeur]] », op.57
+* [[Claude Debussy|Debussy]]
+** « [[Suite Bergamasque|Clair de lune]] » ("Suite Bergamasque" pour piano), L. 75/3
+* [[Antonín Dvořák|Dvořák]]
+** « [[Symphonie nº 9 de Dvořák|Sonate du Nouveau Monde]] » (Symphonie n° 9 en mi mineur, B. 178), op. 95
+* [[Gabriel Fauré|Fauré]]
+** « [[Dolly (Fauré)|Berceuse]] » (première pièce de la suite Dolly, pour piano à quatre mains), op. 56
+* [[Felix Mendelssohn Bartholdy|Mendelssohn]]
+** « [[Romances sans paroles (Mendelssohn)|Chant du printemps]] » (Romances sans paroles pour piano), op. 62/6
+* [[Wolfgang Amadeus Mozart|Mozart]]
+** « [[Ah ! vous dirai-je, maman]] » (Douze variations), K. 265
+** « [[Sonate pour piano n° 16 de Mozart|Sonate facile]] » (Sonate pour piano nº 16 en do majeur), K. 545
+** « La Chasse » (Sonate pour piano n° 18 en ré majeur), K. 576, 3ème mouvement
+* [[Johann Pachelbel|Pachelbel]]
+** « [[Canon de Pachelbel|Canon en ré majeur sur une basse obstinée]] »
+* [[Robert Schumann|Schumann]]
+** « [[Scènes d'enfants (Schumann)|Gens et pays étrangers]] » (Les Scènes d'enfants, "Kinderszenen"), op. 15
+* [[Bedřich Smetana|Smetana]]
+** « [[Má Vlast|La Moldau]] » (Second poèmes symphoniques de "Ma Patrie")
+* [[Antonio Vivaldi|Vivaldi]]
+** « [[Les Quatre Saisons|L'Hiver]] » (Les Quatre Saisons, Opus 8/4)
+
+
+Les plus connues sont la berceuse « ''Bonsoir et bonne nuit'' » de Brahms et la « ''Berceuse en ré bémol majeur'' » de [[Chopin]]. Des compositeurs comme [[Franz Liszt]], [[Gabriel Fauré]], [[Maurice Ravel]], [[Mili Balakirev]], [[Igor Stravinski]] (''[[Berceuses du chat]]'') et [[George Gershwin]] ont aussi écrit des berceuses.
+
+==Dans la musique populaire==
+
+===Dans la chanson française===
+* [[Bénabar]] : « La berceuse », de l'album ''[[Reprise des négociations]]'', 2005
+* [[Henri Salvador]] : « Une chanson douce » (Le Loup, la Biche et le Chevalier), de l'album ''Rigolo'', 1968
+
+===Dans la musique pop===
+* [[Beatles]] : « [[Good Night (chanson)|Good Night]] », de l'''[[The Beatles (album)|album blanc]]'', 1968
+
+===Dans le jazz===
+* [[Baden Powell de Aquino|Baden Powell]] : « Berceuse a Jussara », de l'album ''Le Monde Musical'', 1964
+* [[Henri Salvador]] : « Une chanson douce » (Le Loup, la Biche et le Chevalier), de l'album ''Rigolo'', 1968
+
+== Voir aussi ==
+* [[Lullaby]] dans la section anglaise et italienne où il y a une description d'une bonne partie des berceuses européennes.
+{{Wiktionnaire|berceuse}}
+
+===Bibliographie===
+*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)
+*Marina Altmann de Litvan (dir.), ''La berceuse : jeux d'amour et de magie'', Erès, Ramonville Saint-Agne, 2008, 151 p. {{ISBN|978-2-7492-0925-8}}
+
+{{portail musique}}
+
+[[Catégorie:Berceuse|*]]
+[[Catégorie:Musique par genre]]
+[[Catégorie:Musique traditionnelle]]
+
+[[ar:تهويدة]]
+[[az:Layla]]
+[[br:Luskellerez]]
+[[ca:Cançó de bressol]]
+[[cs:Ukolébavka]]
+[[da:Berceuse]]
+[[de:Wiegenlied]]
+[[en:Lullaby]]
+[[eo:Lulkanto]]
+[[es:Nana (canción de cuna)]]
View
8 wikitextParser.py
@@ -109,6 +109,7 @@
# TODO: allow IPv6 addresses (http://[::1]/etc)
address : (!(QUOTE/R_BRACKET) [\x21..\xff])+ : liftValue
url : protocol address : join
+ inline_url : url{1} : render_url
# Links
@@ -116,7 +117,7 @@
link_text : (clean_inline / allowed_in_link)* : liftValue
link_argument : PIPE link_text : liftValue
link_arguments : link_argument*
- internal_link : LINK_BEGIN page_name link_arguments LINK_END : liftValue
+ internal_link : LINK_BEGIN page_name link_arguments LINK_END : render_internal_link
optional_link_text : SPACETAB+ link_text : liftValue
external_link : L_BRACKET url optional_link_text? R_BRACKET : render_external_link
link : internal_link / external_link
@@ -133,7 +134,6 @@
# Text types
- inline_url : url{1} : render_url
styled_text : link / inline_url / html_comment / tag / entity
not_styled_text : preformatted / nowiki
allowed_char : ESC_CHAR{1} : restore liftValue
@@ -379,6 +379,7 @@ def replace_by_space(node):
# TODO: allow IPv6 addresses (http://[::1]/etc)
address = Repetition(Sequence([NextNot(Choice([QUOTE, R_BRACKET], expression='QUOTE/R_BRACKET'), expression='!(QUOTE/R_BRACKET)'), Klass(u'!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff', expression='[\\x21..\\xff]')], expression='!(QUOTE/R_BRACKET) [\\x21..\\xff]'), numMin=1, numMax=False, expression='(!(QUOTE/R_BRACKET) [\\x21..\\xff])+', name='address')(toolset['liftValue'])
url = Sequence([protocol, address], expression='protocol address', name='url')(toolset['join'])
+ inline_url = Repetition(url, numMin=1, numMax=1, expression='url{1}', name='inline_url')(toolset['render_url'])
# Links
@@ -386,7 +387,7 @@ def replace_by_space(node):
link_text = Repetition(Choice([clean_inline, allowed_in_link], expression='clean_inline / allowed_in_link'), numMin=False, numMax=False, expression='(clean_inline / allowed_in_link)*', name='link_text')(toolset['liftValue'])
link_argument = Sequence([PIPE, link_text], expression='PIPE link_text', name='link_argument')(toolset['liftValue'])
link_arguments = Repetition(link_argument, numMin=False, numMax=False, expression='link_argument*', name='link_arguments')
- internal_link = Sequence([LINK_BEGIN, page_name, link_arguments, LINK_END], expression='LINK_BEGIN page_name link_arguments LINK_END', name='internal_link')(toolset['liftValue'])
+ internal_link = Sequence([LINK_BEGIN, page_name, link_arguments, LINK_END], expression='LINK_BEGIN page_name link_arguments LINK_END', name='internal_link')(toolset['render_internal_link'])
optional_link_text = Sequence([Repetition(SPACETAB, numMin=1, numMax=False, expression='SPACETAB+'), link_text], expression='SPACETAB+ link_text', name='optional_link_text')(toolset['liftValue'])
external_link = Sequence([L_BRACKET, url, Option(optional_link_text, expression='optional_link_text?'), R_BRACKET], expression='L_BRACKET url optional_link_text? R_BRACKET', name='external_link')(toolset['render_external_link'])
link = Choice([internal_link, external_link], expression='internal_link / external_link', name='link')
@@ -403,7 +404,6 @@ def replace_by_space(node):
# Text types
- inline_url = Repetition(url, numMin=1, numMax=1, expression='url{1}', name='inline_url')(toolset['render_url'])
styled_text = Choice([link, inline_url, html_comment, tag, entity], expression='link / inline_url / html_comment / tag / entity', name='styled_text')
not_styled_text = Choice([preformatted, nowiki], expression='preformatted / nowiki', name='not_styled_text')
allowed_char = Repetition(ESC_CHAR, numMin=1, numMax=1, expression='ESC_CHAR{1}', name='allowed_char')(toolset['restore'], toolset['liftValue'])
Please sign in to comment.
Something went wrong with that request. Please try again.