This commit is contained in:
Kovid Goyal 2025-02-12 22:00:02 +05:30
commit 08cb4f7eae
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
3 changed files with 144 additions and 5 deletions

View File

@ -189,6 +189,7 @@ The following functions are usable in Single Function Mode because their first p
* :ffsum:`cmp`
* :ffsum:`contains`
* :ffsum:`date_arithmetic`
* :ffsum:`encode_for_url`
* :ffsum:`floor`
* :ffsum:`format_date`
* :ffsum:`format_number`
@ -532,6 +533,140 @@ The output in :guilabel:`Book details` looks like this:
:alt: E-book conversion dialog
:class: half-width-img
.. _templates_and_urls:
Templates and URLs
----------------------
You can use templates to construct URLs. Two cases are described here:
* Custom column book details search URLs
* The calibre URL scheme
**Custom column book details search URLs**
When you create a custom column you can provide a URL to be used in :guilabel:`Book details` using a template. For example, if you have a custom column for `Translators` you can define a URL to take you to a site for translators. Book details search URLs can be provided for `Text`, `Enumerated`, `Series`, and `Column built from other column` column types.
When an item with a `search template` is clicked in :guilabel:`Book details` the template is evaluated. It is provided the normal book metadata. It is also provided three additional fields:
* ``item_value``: the value of the clicked item.
* ``item_value_quoted``: the value of clicked item, URL-encoded. Special characters are replaced by their numeric equivalent and spaces are replaced by the ``'+'`` (plus) signs.
* ``item_value_no_plus``: the value of clicked item, URL-encoded. Special characters are replaced by their numeric equivalent and spaces are replaced by the ``%20``, not plus.
There are several ways to construct the URL. THe following use Wikipedia as an example.
The simplest is a basic template::
https://en.wikipedia.org/w/index.php?search={item_value_encoded}
In some cases you might want to do more processing. There are four template functions you can use, depending on the complexity of the processing.
* :ffsum:`make_url`
* :ffsum:`make_url_extended`
* :ffsum:`query_string`
* :ffsum:`encode_for_url`
For example, assume you have a custom column `Translators` (``#translators``) where the names are `Last name, First name`. You might need to convert the name to `First name Last name` when creating the URL. You can use the :ref:`make_url` function to do this::
program: make_url('https://en.wikipedia.org/w/index.php', 'search', swap_around_comma($item_value))
If we assume that the translator's name is `Boy-Żeleński, Tadeusz` then the above template produces the link::
https://en.wikipedia.org/w/index.php?search=Tadeusz+Boy-%C5%BBele%C5%84ski
Note that the person's first name is now first, the space is now a plus, and that the special characters in person's last name are URL-encoded.
The functions :ref:`make_url_extended`, :ref:`query_string`, and :ref:`encode_for_url` might be useful depending upon any additional processing complexity.
**The calibre URL scheme**
Calibre supports several different URLs to navigate your calibre libraries. This section shows how to use templates
to construct some of the URLs. See :ref:`The calibre:// URL scheme <url_scheme>` for more detail on the
URLs available.
* Switch to a specific library. The syntax of this URL is::
calibre://switch-library/Library_Name
``Library_Name`` must be replaced with the name of the calibre library you wish to open. The library name is
shown in the title bar of the window. It is a simple name, not the file path to the library. You must spell
it as shown in the title bar, including letter case. The character ``_``
(underscore) stands for the current library. If the name contains any spaces or special characters then it
must be hex encoded using the :ref:`to_hex` function, as in the following example::
program: strcat('calibre://switch-library/_hex_-', to_hex(current_library_name()))
The template generates the URL::
calibre://switch-library/_hex_-4c6962726172792e746573745f736d616c6c
You can replace the ``current_library_name() function with the actual name of the library, as in::
program: strcat('calibre://switch-library/_hex_-', to_hex('Library.test_small'))
* Links to show books. These links select a book in the calibre library. The syntax for this URL is::
calibre://show-book/Library_Name/book_id
The ``book id`` is the numeric calibre id for the book, available to templates as ``$id``. As above,
the library name might need to be hex encoded. Here is an example::
program: strcat('calibre://show-book/_hex_-', to_hex(current_library_name()), '/', $id)
It produces the URL::
calibre://show-book/_hex_-4c6962726172792e746573745f736d616c6c/1353
* Searching for books. These links search for books in the specified calibre library. The syntax for this URL is::
calibre://search/Library_Name?q=query
calibre://search/Library_Name?eq=hex_encoded_query
where `query` is any valid calibre search expression. You must hex encode any query containing spaces or special
characters, which generally means all of them. For example, the calibre search expression for searching for a
hierarchical tag beginning with 'AA' is ``tags:"=.AA"``. This template constructs a search URL for that expression::
program: strcat('calibre://search/_hex_-', to_hex(current_library_name()), '?eq=', to_hex('tags:"=.AA"'))
The resulting URL is::
calibre://search/_hex_-4c6962726172792e746573745f736d616c6c?eq=746167733a223d2e414122
Here is an example of the same URL built using the :ref:``make_url_extended`` function instead of :ref:`strcat`()::
program: make_url_extended('calibre', '', 'search/_hex_-' & to_hex(current_library_name()),
'eq', to_hex('tags:"=.AA"'))
* Open a book details window on a book in some library. The syntax for this URL is::
calibre://book-details/Library_Name/book_id
An example template is::
program: strcat('calibre://book-details/_hex_-', to_hex(current_library_name()), '/', $id)
which produces the URL::
calibre://book-details/_hex_-4c6962726172792e746573745f736d616c6c/1353
* Open the notes associated with an author/series/etc. The syntax of the URL is::
calibre://book-details/Library_Name/Field_Name/id_Item_Id
calibre://book-details/Library_Name/Field_Name/hex_Hex_Encoded_Item_Name
``Field_Name`` is the lookup name of the field. If the field is a custom column then replace the ``#`` character
with an underscore (``_``). ``Item_Id`` is the internal numeric ID of the value in the field. There isn't a template
function that returns the ``Item_Id``, so templates will normally use the second form, ``Hex_Encoded_Item_Name``.
Here is a sample template that opens the note for the person `Boy-Żeleński, Tadeusz` in the field ``#authtest``::
program: strcat('calibre://show-note/_hex_-', to_hex(current_library_name()),
'/_authtest/hex_', to_hex('Boy-Żeleński, Tadeusz'))
which produces the URL::
calibre://show-note/_hex_-4c6962726172792e746573745f736d616c6c/_authtest/hex_426f792dc5bb656c65c584736b692c205461646575737a
Stored templates
----------------------------------------

View File

@ -620,6 +620,8 @@ def create_copy_links(menu, data=None):
sep = menu.addSeparator() # Note: separators are really actions
if data and data.get('type', '') == 'cc_url' and (u := data.get('url', '')):
link_action(_('Custom web search link'), u)
link_action(_('Link to show book in calibre'), f'calibre://show-book/{library_id}/{book_id}')
link_action(_('Link to show book details in a popup window'),
f'calibre://book-details/{library_id}/{book_id}')

View File

@ -3225,7 +3225,7 @@ r'''
to construct a query URL. It uses a ``path``, the web site and page you want to
query, and ``query_name``, ``query_value`` pairs from which the query is built.
In general, the ``query_value`` must be URL-encoded. With this function it is always
encoded and spaces are always replaced with ``'+'`` signs.
encoded and spaces are always replaced with ``'+'`` signs.[/]
At least one ``query_name, query_value`` pair must be provided.
@ -3283,6 +3283,7 @@ make_url_extended(scheme, authority, path, query_string)
[/]
This function returns a URL constructed from the ``scheme``, ``authority``, ``path``,
and either the ``query_string`` or a query string constructed from the query argument pairs.
The ``authority`` can be empty, which is the case for ``calibre`` scheme URLs.
You must supply either a ``query_string`` or at least one ``query_name, query_value`` pair.
If you supply ``query_string`` and it is empty then the resulting URL will not have a query string section.
@ -3307,7 +3308,7 @@ make_url_extended('https', 'en.wikipedia.org', '/w/index.php', 'search', $item_n
See also the functions :ref:`make_url`, :ref:`query_string` and :ref:`encode_for_url`.
''')
def evaluate(self, formatter, kwargs, mi, locals, scheme, host, path, *args):
def evaluate(self, formatter, kwargs, mi, locals, scheme, authority, path, *args):
if len(args) != 1:
if (len(args) % 2) != 0:
raise ValueError(_('{} requires an odd number of arguments').format('make_url_extended'))
@ -3321,7 +3322,8 @@ See also the functions :ref:`make_url`, :ref:`query_string` and :ref:`encode_for
qs = args[0]
if qs:
qs = '?' + qs
return f"{scheme}://{host}/{path[1:] if path.startswith('/') else path}{qs}"
return (f"{scheme}://{authority}{'/' if authority else ''}"
f"{path[1:] if path.startswith('/') else path}{qs}")
class BuiltinQueryString(BuiltinFormatterFunction):
@ -3334,7 +3336,7 @@ r'''
constructed from the ``query_name, query_value, how_to_encode`` triads.
A query string is a series of items where each item looks like ``query_name=query_value``
where ``query_value`` is URL-encoded as instructed. The query items are separated by
``'&'`` (ampersand) characters.
``'&'`` (ampersand) characters.[/]
If ``how_to_encode`` is ``0`` then ``query_value`` is encoded and spaces are replaced
with ``'+'`` (plus) signs. If ``how_to_encode`` is ``1`` then ``query_value`` is
@ -3397,7 +3399,7 @@ class BuiltinEncodeForURL(BuiltinFormatterFunction):
r'''
``encode_for_url(value, use_plus)`` -- returns the ``value`` encoded for use in a URL as
specified by ``use_plus``. The value is first URL-encoded. Next, if ``use_plus`` is ``0`` then
spaces are replaced by ``'+'`` (plus) signs. If it is ``1`` then spaces are replaced by ``%20``.
spaces are replaced by ``'+'`` (plus) signs. If it is ``1`` then spaces are replaced by ``%20``.[/]
If you do not want the value to be encoding but to have spaces replaced then use the
:ref:`re` function, as in ``re($series, ' ', '%20')``