diff --git a/src/calibre/ebooks/metadata/book/render.py b/src/calibre/ebooks/metadata/book/render.py
index 0ccf37240d..11c5ba445d 100644
--- a/src/calibre/ebooks/metadata/book/render.py
+++ b/src/calibre/ebooks/metadata/book/render.py
@@ -12,6 +12,7 @@ from calibre import force_unicode, prepare_string_for_xml
from calibre.constants import filesystem_encoding
from calibre.db.constants import DATA_DIR_NAME
from calibre.ebooks.metadata import fmt_sidx, rating_to_stars
+from calibre.ebooks.metadata.book.formatter import SafeFormat
from calibre.ebooks.metadata.search_internet import DEFAULT_AUTHOR_SOURCE, name_for, qquote, url_for_author_search, url_for_book_search
from calibre.ebooks.metadata.sources.identify import urls_from_identifiers
from calibre.library.comments import comments_to_html, markdown
@@ -66,6 +67,19 @@ def search_action_with_data(search_term, value, book_id, field=None, **k):
return search_action(search_term, value, field=field, book_id=book_id, **k)
+def cc_search_action_with_data(search_term, value, book_id, fm, mi, field=None, **k):
+ if mi is not None and fm is not None:
+ template = fm.get('display', {}).get('web_search_template')
+ if template:
+ formatter = SafeFormat()
+ mi.set('item_value', value)
+ u = formatter.safe_format(template, mi, "BOOK DETAILS WEB LINK", mi)
+ if u:
+ v = prepare_string_for_xml(_('Click to browse to {0}').format(u), attribute=True)
+ return action('cc_url', url=u),v
+ t = _('Click to see books with {0}: {1}').format(mi.get('name', search_term), prepare_string_for_xml(value))
+ return search_action_with_data(search_term, value, book_id, **k), t
+
def notes_action(**keys):
return 'notes:' + as_hex_unicode(json_dumps(keys))
@@ -211,16 +225,16 @@ def mi_to_html(
ans.append((field, row % (name, comments_to_html(val))))
else:
if not metadata['is_multiple']:
- val = '{}'.format(
- search_action(field, val, book_id=book_id),
- _('Click to see books with {0}: {1}').format(metadata['name'], a(val)), p(val))
+ u,v = cc_search_action_with_data(field, val, book_id, metadata, mi, field)
+ val = '{}'.format(u, v, p(val))
else:
all_vals = [v.strip()
for v in val.split(metadata['is_multiple']['cache_to_list']) if v.strip()]
if show_links:
- links = ['{}'.format(
- search_action(field, x, book_id=book_id), _('Click to see books with {0}: {1}').format(
- metadata['name'], a(x)), p(x)) for x in all_vals]
+ links = []
+ for x in all_vals:
+ u,v = cc_search_action_with_data(field, x, book_id, metadata, mi, field)
+ links.append('{}'.format(u, v, p(x)))
else:
links = all_vals
val = value_list(metadata['is_multiple']['list_to_ui'], links)
@@ -349,12 +363,19 @@ def mi_to_html(
except Exception:
st = field
series = getattr(mi, field)
- val = _(
- '%(sidx)s of '
- '%(series)s') % dict(
- sidx=fmt_sidx(sidx, use_roman=use_roman_numbers), cls='series_name',
- series=p(series), href=search_action_with_data(st, series, book_id, field),
- tt=p(_('Click to see books in this series')))
+ if metadata.get('display', {}).get('web_search_template'):
+ u,v = cc_search_action_with_data(st, series, book_id, metadata, mi, field)
+ val = _('%(sidx)s of '
+ '%(series)s') % dict(
+ sidx=fmt_sidx(sidx, use_roman=use_roman_numbers), cls='series_name',
+ series=p(series), href=u, tt=v)
+ else:
+ val = _(
+ '%(sidx)s of '
+ '%(series)s') % dict(
+ sidx=fmt_sidx(sidx, use_roman=use_roman_numbers), cls='series_name',
+ series=p(series), href=search_action_with_data(st, series, book_id, field),
+ tt=p(_('Click to see books in this series')))
val += add_other_links(field, series)
elif metadata['datatype'] == 'datetime':
aval = getattr(mi, field)
@@ -371,32 +392,51 @@ def mi_to_html(
search_action_with_data(key, str(aval), book_id, None, original_value=val), a(
_('Click to see books with {0}: {1} (derived from {2})').format(
metadata['name'] or field, aval, val)), val)
- elif metadata['datatype'] == 'text' and metadata['is_multiple']:
- try:
- st = metadata['search_terms'][0]
- except Exception:
- st = field
- all_vals = mi.get(field)
- if not metadata.get('display', {}).get('is_names', False):
- all_vals = sorted(all_vals, key=sort_key)
- links = []
- for x in all_vals:
- v = '{}'.format(
- search_action_with_data(st, x, book_id, field), _('Click to see books with {0}: {1}').format(
- metadata['name'] or field, a(x)), p(x))
- v += add_other_links(field, x)
- links.append(v)
- val = value_list(metadata['is_multiple']['list_to_ui'], links)
- elif metadata['datatype'] == 'text' or metadata['datatype'] == 'enumeration':
- # text/is_multiple handled above so no need to add the test to the if
- try:
- st = metadata['search_terms'][0]
- except Exception:
- st = field
- v = '{}'.format(
- search_action_with_data(st, unescaped_val, book_id, field), a(
- _('Click to see books with {0}: {1}').format(metadata['name'] or field, val)), val)
- val = v + add_other_links(field, val)
+ elif metadata['datatype'] == 'text':
+ if metadata['is_multiple']:
+ try:
+ st = metadata['search_terms'][0]
+ except Exception:
+ st = field
+ all_vals = mi.get(field)
+ if not metadata.get('display', {}).get('is_names', False):
+ all_vals = sorted(all_vals, key=sort_key)
+ links = []
+ if show_links:
+ for x in all_vals:
+ if metadata['is_custom']:
+ u,v = cc_search_action_with_data(field, x, book_id, metadata, mi, field)
+ v = '{}'.format(u, v, p(x))
+ else:
+ v = '{}'.format(
+ search_action_with_data(st, x, book_id, field),
+ _('Click to see books with {0}: {1}').format(
+ metadata['name'] or field, a(x)), p(x))
+ v += add_other_links(field, x)
+ links.append(v)
+ else:
+ links = all_vals
+ val = value_list(metadata['is_multiple']['list_to_ui'], links)
+ else:
+ try:
+ st = metadata['search_terms'][0]
+ except Exception:
+ st = field
+ if show_links:
+ if metadata['is_custom']:
+ u,v = cc_search_action_with_data(st, x, book_id, metadata, mi, field)
+ v = '{}'.format(u, v, p(x))
+ else:
+ v = '{}'.format(
+ search_action_with_data(st, x, book_id, field),
+ _('Click to see books with {0}: {1}').format(
+ metadata['name'] or field, a(x)), p(x))
+ else:
+ v = val
+ val = v + add_other_links(field, val)
+ elif metadata['datatype'] == 'enumeration':
+ u,v = cc_search_action_with_data(field, x, book_id, metadata, mi, field)
+ val = '{}'.format(u, v, p(x)) + add_other_links(field, val)
elif metadata['datatype'] == 'bool':
val = '{}'.format(
search_action_with_data(field, val, book_id, None), a(