mirror of
https://github.com/veekun/pokedex.git
synced 2024-08-20 18:16:34 +00:00
Make bad links in Markdown not fail
Links such as []{pokemon:mewthree} can come from users, so they should not crash the parser. So, when an object is not found (or more than one is found), call identifier_url() directly, instead of failing to get the object for object_url(). Essentially, treat the link as having an unknown category (like mechanic:, currently). The test that check the pokédex descriptions updated so that only links to known objects and "mechanic:" are allowed.
This commit is contained in:
parent
cdac374eed
commit
928eaca4a4
2 changed files with 49 additions and 32 deletions
|
@ -170,21 +170,27 @@ class PokedexLinkPattern(markdown.inlinepatterns.Pattern):
|
||||||
query = query.join(tables.Pokemon.species)
|
query = query.join(tables.Pokemon.species)
|
||||||
query = query.filter(
|
query = query.filter(
|
||||||
tables.PokemonSpecies.identifier == pokemon_ident)
|
tables.PokemonSpecies.identifier == pokemon_ident)
|
||||||
obj = query.one()
|
|
||||||
else:
|
else:
|
||||||
obj = util.get(self.session, table, target)
|
query = session.query(table)
|
||||||
url = self.factory.object_url(category, obj)
|
query = query.filter(table.identifier == target)
|
||||||
url = url or self.factory.identifier_url(category, target)
|
try:
|
||||||
name = None
|
obj = query.one()
|
||||||
# Translations can be incomplete; in which case we want to use a
|
except Exception:
|
||||||
# fallback.
|
obj = name = target
|
||||||
if table in [tables.Type] and self.string_language:
|
url = self.factory.identifier_url(category, obj)
|
||||||
# Type wants to be localized to the same language as the text
|
else:
|
||||||
name = obj.name_map.get(self.string_language)
|
url = self.factory.object_url(category, obj)
|
||||||
if not name and self.game_language:
|
url = url or self.factory.identifier_url(category, target)
|
||||||
name = obj.name_map.get(self.game_language)
|
name = None
|
||||||
if not name:
|
# Translations can be incomplete; in which case we want to use
|
||||||
name = obj.name
|
# a fallback.
|
||||||
|
if table in [tables.Type] and self.string_language:
|
||||||
|
# Type wants to be localized to the text language
|
||||||
|
name = obj.name_map.get(self.string_language)
|
||||||
|
if not name and self.game_language:
|
||||||
|
name = obj.name_map.get(self.game_language)
|
||||||
|
if not name:
|
||||||
|
name = obj.name
|
||||||
if url:
|
if url:
|
||||||
el = self.factory.make_link(category, obj, url, label or name)
|
el = self.factory.make_link(category, obj, url, label or name)
|
||||||
else:
|
else:
|
||||||
|
@ -222,12 +228,18 @@ class PokedexLinkExtension(markdown.Extension):
|
||||||
|
|
||||||
Returns None by default, which causes <span> to be used in place of
|
Returns None by default, which causes <span> to be used in place of
|
||||||
<a>.
|
<a>.
|
||||||
|
|
||||||
|
This method is also called for non-existent objects, e.g.
|
||||||
|
[]{pokemon:bogus}.
|
||||||
"""
|
"""
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def object_url(self, category, obj):
|
def object_url(self, category, obj):
|
||||||
"""Return the URL for the ORM object `obj`.
|
u"""Return the URL for the ORM object `obj`.
|
||||||
|
|
||||||
Returns None by default, which causes identifier_url to be tried.
|
Returns None by default, which causes identifier_url to be tried.
|
||||||
|
|
||||||
|
Note that obj may be a Pokémon form. Unlike other returned objects,
|
||||||
|
these do not have identifiers. Be sure to test this case.
|
||||||
"""
|
"""
|
||||||
return None
|
return None
|
||||||
|
|
|
@ -92,9 +92,9 @@ def test_markdown():
|
||||||
|
|
||||||
def test_markdown_string():
|
def test_markdown_string():
|
||||||
en = util.get(connection, tables.Language, 'en')
|
en = util.get(connection, tables.Language, 'en')
|
||||||
md = markdown.MarkdownString('[]{move:thunderbolt} [paralyzes]{mechanic:paralysis} []{form:sky shaymin}', connection, en)
|
md = markdown.MarkdownString('[]{move:thunderbolt} [paralyzes]{mechanic:paralysis} []{form:sky shaymin}. []{pokemon:mewthree} does not exist.', connection, en)
|
||||||
assert unicode(md) == 'Thunderbolt paralyzes Sky Shaymin'
|
assert unicode(md) == 'Thunderbolt paralyzes Sky Shaymin. mewthree does not exist.'
|
||||||
assert md.as_html() == '<p><span>Thunderbolt</span> <span>paralyzes</span> <span>Sky Shaymin</span></p>'
|
assert md.as_html() == '<p><span>Thunderbolt</span> <span>paralyzes</span> <span>Sky Shaymin</span>. <span>mewthree</span> does not exist.</p>'
|
||||||
|
|
||||||
class ObjectTestExtension(markdown.PokedexLinkExtension):
|
class ObjectTestExtension(markdown.PokedexLinkExtension):
|
||||||
def object_url(self, category, obj):
|
def object_url(self, category, obj):
|
||||||
|
@ -106,12 +106,12 @@ def test_markdown_string():
|
||||||
|
|
||||||
class IdentifierTestExtension(markdown.PokedexLinkExtension):
|
class IdentifierTestExtension(markdown.PokedexLinkExtension):
|
||||||
def identifier_url(self, category, ident):
|
def identifier_url(self, category, ident):
|
||||||
return "%s/%s" % (category, ident)
|
return "%s/%s" % (category, ident)
|
||||||
|
|
||||||
assert md.as_html(extension_cls=ObjectTestExtension) == (
|
assert md.as_html(extension_cls=ObjectTestExtension) == (
|
||||||
'<p><a href="move/thunderbolt">Thunderbolt</a> <span>paralyzes</span> <a href="form/sky shaymin">Sky Shaymin</a></p>')
|
'<p><a href="move/thunderbolt">Thunderbolt</a> <span>paralyzes</span> <a href="form/sky shaymin">Sky Shaymin</a>. <span>mewthree</span> does not exist.</p>')
|
||||||
assert md.as_html(extension_cls=IdentifierTestExtension) == (
|
assert md.as_html(extension_cls=IdentifierTestExtension) == (
|
||||||
'<p><a href="move/thunderbolt">Thunderbolt</a> <a href="mechanic/paralysis">paralyzes</a> <a href="form/sky shaymin">Sky Shaymin</a></p>')
|
'<p><a href="move/thunderbolt">Thunderbolt</a> <a href="mechanic/paralysis">paralyzes</a> <a href="form/sky shaymin">Sky Shaymin</a>. <a href="pokemon/mewthree">mewthree</a> does not exist.</p>')
|
||||||
|
|
||||||
def markdown_column_params():
|
def markdown_column_params():
|
||||||
"""Check all markdown values
|
"""Check all markdown values
|
||||||
|
@ -136,23 +136,28 @@ def test_markdown_values(parent_class, translation_class, column_name):
|
||||||
query = connection.query(parent_class)
|
query = connection.query(parent_class)
|
||||||
if translation_class:
|
if translation_class:
|
||||||
query = query.join(translation_class)
|
query = query.join(translation_class)
|
||||||
for item in query:
|
|
||||||
for language, markdown in getattr(item, column_name + '_map').items():
|
|
||||||
|
|
||||||
if markdown is None:
|
for item in query:
|
||||||
|
for language, md_text in getattr(item, column_name + '_map').items():
|
||||||
|
|
||||||
|
if md_text is None:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
key = u"Markdown in {0} #{1}'s {2} (lang={3})".format(
|
key = u"Markdown in {0} #{1}'s {2} (lang={3})".format(
|
||||||
parent_class.__name__, item.id, column_name, language.identifier)
|
parent_class.__name__, item.id, column_name, language.identifier)
|
||||||
|
|
||||||
try:
|
class TestExtension(markdown.PokedexLinkExtension):
|
||||||
text = markdown.as_text()
|
def object_url(self, category, obj):
|
||||||
except NoResultFound:
|
"Swallow good links"
|
||||||
assert False, u"{0} references something that doesn't exist:\n{1}".format(
|
return 'ok'
|
||||||
key, markdown.source_text)
|
|
||||||
except AttributeError:
|
def identifier_url(self, category, ident):
|
||||||
print markdown
|
"Only allow mechanic links here (good links handled in object_url)"
|
||||||
raise
|
assert category == 'mechanic', (
|
||||||
|
'%s: unknown link target: {%s:%s}' %
|
||||||
|
(key, category, ident))
|
||||||
|
|
||||||
|
text = md_text.as_html(extension_cls=TestExtension)
|
||||||
|
|
||||||
error_message = u"{0} leaves syntax cruft:\n{1}"
|
error_message = u"{0} leaves syntax cruft:\n{1}"
|
||||||
error_message = error_message.format(key, text)
|
error_message = error_message.format(key, text)
|
||||||
|
|
Loading…
Reference in a new issue