2010-05-31 22:13:34 +00:00
|
|
|
# encoding: utf8
|
|
|
|
u"""Implements the markup used for description and effect text in the database.
|
|
|
|
|
|
|
|
The language used is a variation of Markdown and Markdown Extra. There are
|
|
|
|
docs for each at http://daringfireball.net/projects/markdown/ and
|
|
|
|
http://michelf.com/projects/php-markdown/extra/ respectively.
|
|
|
|
|
|
|
|
Pokédex links are represented with the extended syntax `[name]{type}`, e.g.,
|
|
|
|
`[Eevee]{pokemon}`. The actual code that parses these is in spline-pokedex.
|
|
|
|
"""
|
2010-06-01 00:06:33 +00:00
|
|
|
from __future__ import absolute_import
|
2010-05-31 22:13:34 +00:00
|
|
|
|
|
|
|
import markdown
|
|
|
|
import sqlalchemy.types
|
|
|
|
|
|
|
|
class MarkdownString(object):
|
|
|
|
"""Wraps a Markdown string. Stringifies to the original text, but .as_html
|
|
|
|
will return an HTML rendering.
|
|
|
|
|
|
|
|
To add extensions to the rendering (which is necessary for rendering links
|
|
|
|
correctly, and which spline-pokedex does), you must append to this class's
|
|
|
|
`markdown_extensions` list. Yep, that's gross.
|
|
|
|
"""
|
|
|
|
|
|
|
|
markdown_extensions = ['extra']
|
|
|
|
|
|
|
|
def __init__(self, source_text):
|
|
|
|
self.source_text = source_text
|
|
|
|
self._as_html = None
|
|
|
|
|
|
|
|
def __unicode__(self):
|
|
|
|
return self.source_text
|
|
|
|
|
2011-03-31 20:51:19 +00:00
|
|
|
def __str__(self):
|
|
|
|
return unicode(self.source_text).encode()
|
|
|
|
|
|
|
|
def __html__(self):
|
|
|
|
return self.as_html
|
|
|
|
|
2010-05-31 22:13:34 +00:00
|
|
|
@property
|
|
|
|
def as_html(self):
|
|
|
|
"""Returns the string as HTML4."""
|
|
|
|
|
2011-03-31 20:51:19 +00:00
|
|
|
if self._as_html is not None:
|
2010-05-31 22:13:34 +00:00
|
|
|
return self._as_html
|
|
|
|
|
|
|
|
md = markdown.Markdown(
|
|
|
|
extensions=self.markdown_extensions,
|
|
|
|
safe_mode='escape',
|
|
|
|
output_format='xhtml1',
|
|
|
|
)
|
|
|
|
|
|
|
|
self._as_html = md.convert(self.source_text)
|
|
|
|
|
|
|
|
return self._as_html
|
|
|
|
|
|
|
|
@property
|
|
|
|
def as_text(self):
|
|
|
|
"""Returns the string in a plaintext-friendly form.
|
|
|
|
|
|
|
|
At the moment, this is just the original source text.
|
|
|
|
"""
|
|
|
|
return self.source_text
|
|
|
|
|
2011-03-24 05:17:02 +00:00
|
|
|
def _markdownify_effect_text(move, effect_text):
|
|
|
|
effect_text = effect_text.replace(
|
|
|
|
u'$effect_chance',
|
|
|
|
unicode(move.effect_chance),
|
|
|
|
)
|
2010-05-31 22:13:34 +00:00
|
|
|
|
2011-03-24 05:17:02 +00:00
|
|
|
return MarkdownString(effect_text)
|
2011-02-04 04:22:44 +00:00
|
|
|
|
2011-03-24 05:17:02 +00:00
|
|
|
class MoveEffectProperty(object):
|
2011-02-04 04:22:44 +00:00
|
|
|
"""Property that wraps move effects. Used like this:
|
|
|
|
|
2011-03-24 05:17:02 +00:00
|
|
|
MoveClass.effect = MoveEffectProperty('effect')
|
|
|
|
|
|
|
|
some_move.effect # returns a MarkdownString
|
|
|
|
some_move.effect.as_html # returns a chunk of HTML
|
2011-02-04 04:22:44 +00:00
|
|
|
|
|
|
|
This class also performs simple substitution on the effect, replacing
|
|
|
|
`$effect_chance` with the move's actual effect chance.
|
2011-04-03 08:25:59 +00:00
|
|
|
|
|
|
|
Use `MoveEffectPropertyMap` for dict-like association proxies.
|
2011-02-04 04:22:44 +00:00
|
|
|
"""
|
|
|
|
|
|
|
|
def __init__(self, effect_column):
|
|
|
|
self.effect_column = effect_column
|
|
|
|
|
2011-03-24 05:17:02 +00:00
|
|
|
def __get__(self, obj, cls):
|
|
|
|
prop = getattr(obj.move_effect, self.effect_column)
|
|
|
|
return _markdownify_effect_text(obj, prop)
|
2010-05-31 22:13:34 +00:00
|
|
|
|
2011-04-03 08:25:59 +00:00
|
|
|
class MoveEffectPropertyMap(MoveEffectProperty):
|
|
|
|
"""Similar to `MoveEffectProperty`, but works on dict-like association
|
|
|
|
proxies.
|
|
|
|
"""
|
|
|
|
def __get__(self, obj, cls):
|
|
|
|
prop = getattr(obj.move_effect, self.effect_column)
|
|
|
|
newdict = dict(prop)
|
|
|
|
for key in newdict:
|
|
|
|
newdict[key] = _markdownify_effect_text(obj, newdict[key])
|
|
|
|
return newdict
|
|
|
|
|
2010-05-31 22:13:34 +00:00
|
|
|
class MarkdownColumn(sqlalchemy.types.TypeDecorator):
|
|
|
|
"""Generic SQLAlchemy column type for Markdown text.
|
|
|
|
|
|
|
|
Do NOT use this for move effects! They need to know what move they belong
|
|
|
|
to so they can fill in, e.g., effect chances. Use the MoveEffectProperty
|
|
|
|
property class above.
|
|
|
|
"""
|
|
|
|
impl = sqlalchemy.types.Unicode
|
|
|
|
|
|
|
|
def process_bind_param(self, value, dialect):
|
|
|
|
if not isinstance(value, basestring):
|
|
|
|
# Can't assign, e.g., MarkdownString objects yet
|
|
|
|
raise NotImplementedError
|
|
|
|
|
|
|
|
return unicode(value)
|
|
|
|
|
|
|
|
def process_result_value(self, value, dialect):
|
|
|
|
return MarkdownString(value)
|