I now understand what you are trying to do. With a recent calibre 6 release it can be done with a template and a custom template function. The template constructs calibre search URLs. The template function is used to hex-encode the search parameters.
First, the template function: you add template functions in Preferences / Template functions. Click the second tab. Enter my_to_hex (or whatever you want, but don't use to_hex) in the function box. Enter 1 (one) in the argument count box. Enter the following in the program code box
Code:
def evaluate(self, formatter, kwargs, mi, locals, val):
return val.encode().hex()
This screen capture shows what I mean.
Assuming you used my_to_hex above, the template is
Code:
program:
j = '';
for i in $tags:
j = j & '<li><a href="' & 'calibre://search/_hex_-' &
my_to_hex(current_library_name()) & '?eq=' &
my_to_hex('tags:="""' & i & '"""') &
'">' & i & '</a></li>'
rof;
'<ul>' & j & '</ul>'
The template constructs a calibre search URL
as described in the calibre manual. The hex encoding is required because both the library name and the query string can contain almost anything, and trying to do HTML escapes is a losing proposition. The encoded search uses super-quotes to avoid needing to escape anything in the search string.
Example: for the tag "Fantasy & Magic" the template generates the URL
Code:
calibre://search/_hex_-4c6962726172792e746573745f736d616c6c?eq=746167733a3d22222246616e746173792026204d61676963222222
The links appear in calibre like this
Using calibre links isn't the fastest thing in the world, but they do work. And there isn't any other way I can think of to do it.
You may ask "Why not use to_hex()"? I am going to add that as a built-in template function. Have a custom function with the same name will make things break.