change template replacement behaviour

Previously {{field}} wrapped the field in a span with the field's font
properties. This wasn't obvious, and caused frequent problems with people
trying to combine field and template text, or use field content in dictionary
links.

Now that AnkiWeb has a wizard for configuring the front & back layout, we can
just put the formatting in the template instead.
This commit is contained in:
Damien Elmes 2011-11-18 02:50:47 +09:00
parent 770f402905
commit c76c08069e
4 changed files with 38 additions and 9 deletions

View file

@ -413,11 +413,6 @@ select id from facts where id in %s and id not in (select fid from cards)""" %
model = self.models.get(data[2]) model = self.models.get(data[2])
for (name, (idx, conf)) in self.models.fieldMap(model).items(): for (name, (idx, conf)) in self.models.fieldMap(model).items():
fields[name] = flist[idx] fields[name] = flist[idx]
if fields[name]:
fields[name] = '<span class="fm%s-%s">%s</span>' % (
hexifyID(data[2]), hexifyID(idx), fields[name])
else:
fields[name] = ""
fields['Tags'] = data[5] fields['Tags'] = data[5]
fields['Model'] = model['name'] fields['Model'] = model['name']
fields['Group'] = self.groups.name(data[3]) fields['Group'] = self.groups.name(data[3])

View file

@ -135,13 +135,13 @@ class Template(object):
return template return template
# {{{ functions just like {{ in anki
@modifier('{') @modifier('{')
def render_tag(self, tag_name, context): def render_tag(self, tag_name, context):
"""Given a tag name and context, finds, escapes, and renders the tag."""
raw = get_or_attr(context, tag_name, '') raw = get_or_attr(context, tag_name, '')
if not raw and raw is not 0: if not raw and raw is not 0:
return '' return ''
return re.sub("^<span.+?>(.*)</span>", "\\1", raw) return raw
@modifier('!') @modifier('!')
def render_comment(self, tag_name=None, context=None): def render_comment(self, tag_name=None, context=None):
@ -188,7 +188,7 @@ class Template(object):
ans = ["<span class=cloze>"+a[0]+"</span>" for a in ans] ans = ["<span class=cloze>"+a[0]+"</span>" for a in ans]
ans = ", ".join(ans) ans = ", ".join(ans)
# but we want to preserve the outer field styling # but we want to preserve the outer field styling
return re.sub("(^<span.+?>)(.*)</span>", "\\1"+ans+"</span>", txt) return ans
# and display other clozes normally # and display other clozes normally
return re.sub(reg%".*?", "\\1", txt) return re.sub(reg%".*?", "\\1", txt)

View file

@ -416,6 +416,39 @@ order by ordinal""", mid)):
tmpls.append(conf) tmpls.append(conf)
return tmpls return tmpls
# Template upgrading
######################################################################
# {{field}} no longer inserts an implicit span, so we make the span
# explicit on upgrade.
def _upgradeTemplates(self):
d = self.deck
for m in d.models.all():
# cache field styles
styles = {}
for f in m['flds']:
attrs = [
"font-family:%s" % f['font'],
"font-size:%spx" % f['qsize'],
"color:%s" % f['qcol']]
if f['rtl']:
attrs.append("direction:rtl;unicode-bidi:embed")
if f['pre']:
attrs.append("white-space:pre-wrap")
styles[f['name']] = '<span style="%s">\n{{%s}}\n</span>' % (
";".join(attrs), f['name'])
# then for each template
for t in m['tmpls']:
def repl(match):
field = match.group(1)
if field in styles:
return styles[field]
# special or non-existant field; leave alone
return match.group(0)
for k in 'qfmt', 'afmt':
t[k] = re.sub("(?:^|[^{]){{([^{}]+)?}}", repl, t[k])
# save model
d.models.save(m)
# Media references # Media references
###################################################################### ######################################################################
# In 2.0 we drop support for media and latex references in the template, # In 2.0 we drop support for media and latex references in the template,
@ -519,6 +552,8 @@ and ord = ? limit 1""", m['id'], t['ord']):
self._removeInactive() self._removeInactive()
# rewrite media references in card template # rewrite media references in card template
self._rewriteMediaRefs() self._rewriteMediaRefs()
# template handling has changed
self._upgradeTemplates()
# regenerate css, and set new card order # regenerate css, and set new card order
for m in deck.models.all(): for m in deck.models.all():
m['newOrder'] = deck.conf['oldNewOrder'] m['newOrder'] = deck.conf['oldNewOrder']

View file

@ -19,7 +19,6 @@ def test_upgrade():
dst = getUpgradeDeckPath() dst = getUpgradeDeckPath()
csum = checksum(open(dst).read()) csum = checksum(open(dst).read())
u = Upgrader() u = Upgrader()
print "upgrade to", dst
deck = u.upgrade(dst) deck = u.upgrade(dst)
# src file must not have changed # src file must not have changed
assert csum == checksum(open(dst).read()) assert csum == checksum(open(dst).read())