mirror of
https://github.com/veekun/pokedex.git
synced 2024-08-20 18:16:34 +00:00
Autofill empty labels in Markdown links
- as_text() is now a function that takes the session as an argument - likewise as_html(), which also takes URL makers and the language - since there should be only one link extension, it is registered by setting default_link_extension, not appending to markdown_extensions. This only affects the __html__ attribute.
This commit is contained in:
parent
051d6563a4
commit
059f7dfc55
1 changed files with 130 additions and 20 deletions
|
@ -11,6 +11,8 @@ spline-pokedex.
|
||||||
"""
|
"""
|
||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
|
|
||||||
|
import re
|
||||||
|
|
||||||
import markdown
|
import markdown
|
||||||
import sqlalchemy.types
|
import sqlalchemy.types
|
||||||
|
|
||||||
|
@ -18,16 +20,14 @@ class MarkdownString(object):
|
||||||
"""Wraps a Markdown string. Stringifies to the original text, but .as_html
|
"""Wraps a Markdown string. Stringifies to the original text, but .as_html
|
||||||
will return an HTML rendering.
|
will return an HTML rendering.
|
||||||
|
|
||||||
To add extensions to the rendering (which is necessary for rendering links
|
To make the __html__ property work, you must set this class's
|
||||||
correctly, and which spline-pokedex does), you must append to this class's
|
`default_link_extension` to a PokedexLinkExtension. Yep, that's gross.
|
||||||
`markdown_extensions` list. Yep, that's gross.
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
markdown_extensions = ['extra']
|
default_link_extension = None
|
||||||
|
|
||||||
def __init__(self, source_text):
|
def __init__(self, source_text):
|
||||||
self.source_text = source_text
|
self.source_text = source_text
|
||||||
self._as_html = None
|
|
||||||
|
|
||||||
def __unicode__(self):
|
def __unicode__(self):
|
||||||
return self.source_text
|
return self.source_text
|
||||||
|
@ -36,32 +36,40 @@ class MarkdownString(object):
|
||||||
return unicode(self.source_text).encode()
|
return unicode(self.source_text).encode()
|
||||||
|
|
||||||
def __html__(self):
|
def __html__(self):
|
||||||
return self.as_html
|
return self.as_html(extension=self.default_link_extension)
|
||||||
|
|
||||||
@property
|
def as_html(self, session=None, object_url=None, identifier_url=None, language=None, extension=None):
|
||||||
def as_html(self):
|
"""Returns the string as HTML.
|
||||||
"""Returns the string as HTML4."""
|
|
||||||
|
|
||||||
if self._as_html is not None:
|
Pass in current session, and optionally URL-making functions and the
|
||||||
return self._as_html
|
language. See PokedexLinkExtension for how they work.
|
||||||
|
|
||||||
|
Alternatively, pass in a PokedexLinkExtension instance.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if not extension:
|
||||||
|
extension = ParametrizedLinkExtension(session, object_url, identifier_url, language)
|
||||||
|
|
||||||
md = markdown.Markdown(
|
md = markdown.Markdown(
|
||||||
extensions=self.markdown_extensions,
|
extensions=['extra', extension],
|
||||||
safe_mode='escape',
|
safe_mode='escape',
|
||||||
output_format='xhtml1',
|
output_format='xhtml1',
|
||||||
)
|
)
|
||||||
|
|
||||||
self._as_html = md.convert(self.source_text)
|
return md.convert(self.source_text)
|
||||||
|
|
||||||
return self._as_html
|
def as_text(self, session):
|
||||||
|
|
||||||
@property
|
|
||||||
def as_text(self):
|
|
||||||
"""Returns the string in a plaintext-friendly form.
|
"""Returns the string in a plaintext-friendly form.
|
||||||
|
|
||||||
At the moment, this is just the original source text.
|
|
||||||
"""
|
"""
|
||||||
return self.source_text
|
# Since Markdown is pretty readable by itself, we just have to replace
|
||||||
|
# the links by their text.
|
||||||
|
# XXX: The tables get unaligned
|
||||||
|
extension = ParametrizedLinkExtension(session)
|
||||||
|
pattern = extension.link_pattern
|
||||||
|
regex = '()%s()' % pattern.regex
|
||||||
|
def handleMatch(m):
|
||||||
|
return pattern.handleMatch(m).text
|
||||||
|
return re.sub(regex, handleMatch, self.source_text)
|
||||||
|
|
||||||
def _markdownify_effect_text(move, effect_text):
|
def _markdownify_effect_text(move, effect_text):
|
||||||
if effect_text is None:
|
if effect_text is None:
|
||||||
|
@ -129,3 +137,105 @@ class MarkdownColumn(sqlalchemy.types.TypeDecorator):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
return MarkdownString(value)
|
return MarkdownString(value)
|
||||||
|
|
||||||
|
class PokedexLinkPattern(markdown.inlinepatterns.Pattern):
|
||||||
|
"""Matches [label]{category:target}.
|
||||||
|
"""
|
||||||
|
regex = ur'(?x) \[ ([^]]*) \] \{ ([-a-z0-9]+) : ([-a-z0-9]+) \}'
|
||||||
|
|
||||||
|
def __init__(self, extension):
|
||||||
|
markdown.inlinepatterns.Pattern.__init__(self, self.regex)
|
||||||
|
self.extension = extension
|
||||||
|
|
||||||
|
def handleMatch(self, m):
|
||||||
|
from pokedex.db import tables, util
|
||||||
|
start, label, category, target, end = m.groups()
|
||||||
|
try:
|
||||||
|
table = dict(
|
||||||
|
ability=tables.Ability,
|
||||||
|
item=tables.Item,
|
||||||
|
location=tables.Location,
|
||||||
|
move=tables.Move,
|
||||||
|
pokemon=tables.Pokemon,
|
||||||
|
type=tables.Type,
|
||||||
|
)[category]
|
||||||
|
except KeyError:
|
||||||
|
obj = name = target
|
||||||
|
url = self.extension.identifier_url(category, obj)
|
||||||
|
else:
|
||||||
|
session = self.extension.session
|
||||||
|
obj = util.get(self.extension.session, table, target)
|
||||||
|
url = self.extension.object_url(category, obj)
|
||||||
|
if table in [tables.Type]:
|
||||||
|
# Type wants to be localized to the same language as the text
|
||||||
|
language = self.extension.language
|
||||||
|
name = None
|
||||||
|
try:
|
||||||
|
name = obj.name_map[language]
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
if not name:
|
||||||
|
name = obj.name
|
||||||
|
else:
|
||||||
|
name = obj.name
|
||||||
|
if url:
|
||||||
|
el = self.extension.make_link(category, obj, url, label or name)
|
||||||
|
else:
|
||||||
|
el = markdown.etree.Element('span')
|
||||||
|
el.text = markdown.AtomicString(label or name)
|
||||||
|
return el
|
||||||
|
|
||||||
|
class PokedexLinkExtension(markdown.Extension):
|
||||||
|
"""Plugs the [foo]{bar:baz} syntax into the markdown parser.
|
||||||
|
|
||||||
|
Subclases need to set the `session` attribute to the current session,
|
||||||
|
and `language` to the language of the strings.
|
||||||
|
|
||||||
|
To get links, subclasses must override object_url and/or identifier_url.
|
||||||
|
If these return None, <span>s are used instead of <a>.
|
||||||
|
"""
|
||||||
|
language = None
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
markdown.Extension.__init__(self)
|
||||||
|
self.link_pattern = PokedexLinkPattern(self)
|
||||||
|
|
||||||
|
def extendMarkdown(self, md, md_globals):
|
||||||
|
md.inlinePatterns['pokedex-link'] = self.link_pattern
|
||||||
|
|
||||||
|
def make_link(self, category, obj, url, text):
|
||||||
|
"""Make an <a> element
|
||||||
|
|
||||||
|
Override this to set custom attributes, e.g. title.
|
||||||
|
"""
|
||||||
|
el = markdown.etree.Element('a')
|
||||||
|
el.set('href', url)
|
||||||
|
el.text = markdown.AtomicString(text)
|
||||||
|
return el
|
||||||
|
|
||||||
|
def identifier_url(self, category, identifier):
|
||||||
|
"""Return the URL for the given {category:identifier} link
|
||||||
|
|
||||||
|
For ORM objects, object_url is used instead (but may fall back to
|
||||||
|
identifier_url).
|
||||||
|
|
||||||
|
Returns None by default, which causes <span> to be used in place of <a>
|
||||||
|
"""
|
||||||
|
return None
|
||||||
|
|
||||||
|
def object_url(self, category, obj):
|
||||||
|
"""Return the URL for the ORM object obj
|
||||||
|
|
||||||
|
Calls identifier_url by default.
|
||||||
|
"""
|
||||||
|
return self.identifier_url(category, obj.identifier)
|
||||||
|
|
||||||
|
class ParametrizedLinkExtension(PokedexLinkExtension):
|
||||||
|
def __init__(self, session, object_url=None, identifier_url=None, language=None):
|
||||||
|
PokedexLinkExtension.__init__(self)
|
||||||
|
self.language = language
|
||||||
|
self.session = session
|
||||||
|
if object_url:
|
||||||
|
self.object_url = object_url
|
||||||
|
if identifier_url:
|
||||||
|
self.identifier_url = identifier_url
|
||||||
|
|
Loading…
Reference in a new issue