Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

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.