This commit is contained in:
Kovid Goyal 2024-03-03 09:05:25 +05:30
commit 5517f188f4
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
3 changed files with 38 additions and 7 deletions

View File

@ -25,6 +25,10 @@ def parse_html(raw):
def export_note(note_doc: str, get_resource) -> str: def export_note(note_doc: str, get_resource) -> str:
root = parse_html(note_doc) root = parse_html(note_doc)
return html.tostring(expand_note_resources(root, get_resource), encoding='unicode')
def expand_note_resources(root, get_resource):
for img in root.xpath('//img[@src]'): for img in root.xpath('//img[@src]'):
img.attrib.pop('data-pre-import-src', None) img.attrib.pop('data-pre-import-src', None)
try: try:
@ -38,8 +42,6 @@ def export_note(note_doc: str, get_resource) -> str:
img.set('src', data_url(guess_type(x['name'])[0], x['data'])) img.set('src', data_url(guess_type(x['name'])[0], x['data']))
img.set('data-filename', x['name']) img.set('data-filename', x['name'])
return html.tostring(root, encoding='unicode')
def import_note(shtml: str | bytes, basedir: str, add_resource) -> tuple[str, str, set[str]]: def import_note(shtml: str | bytes, basedir: str, add_resource) -> tuple[str, str, set[str]]:
shtml = xml_to_unicode(shtml, strip_encoding_pats=True, assume_utf8=True)[0] shtml = xml_to_unicode(shtml, strip_encoding_pats=True, assume_utf8=True)[0]

View File

@ -375,6 +375,13 @@ def render_jacket(mi, output_profile,
else: else:
val = comments_to_html(val) val = comments_to_html(val)
args[dkey] = val args[dkey] = val
elif dt == 'composite':
val = val or ''
# if the column is marked as containing html, use it
# unchanged. Otherwise treat it as a comment.
if not m.get('display', {}).get('contains_html', False):
val = comments_to_html(val)
args[dkey] = val
else: else:
args[dkey] = escape(val) args[dkey] = escape(val)
args[dkey+'_label'] = escape(display_name) args[dkey+'_label'] = escape(display_name)

View File

@ -20,11 +20,13 @@ from contextlib import suppress
from datetime import datetime, timedelta from datetime import datetime, timedelta
from enum import Enum, auto from enum import Enum, auto
from functools import partial from functools import partial
from lxml import html
from math import ceil, floor, modf, trunc from math import ceil, floor, modf, trunc
from calibre import human_readable, prepare_string_for_xml, prints from calibre import human_readable, prepare_string_for_xml, prints
from calibre.constants import DEBUG from calibre.constants import DEBUG
from calibre.db.constants import DATA_DIR_NAME, DATA_FILE_PATTERN from calibre.db.constants import DATA_DIR_NAME, DATA_FILE_PATTERN
from calibre.db.notes.exim import parse_html, expand_note_resources
from calibre.ebooks.metadata import title_sort from calibre.ebooks.metadata import title_sort
from calibre.utils.config import tweaks from calibre.utils.config import tweaks
from calibre.utils.date import UNDEFINED_DATE, format_date, now, parse_date from calibre.utils.date import UNDEFINED_DATE, format_date, now, parse_date
@ -2581,14 +2583,34 @@ class BuiltinGetNote(BuiltinFormatterFunction):
def evaluate(self, formatter, kwargs, mi, locals, field_name, field_value, plain_text): def evaluate(self, formatter, kwargs, mi, locals, field_name, field_value, plain_text):
db = self.get_database(mi).new_api db = self.get_database(mi).new_api
try: try:
note = ''
item_id = db.get_item_id(field_name, field_value) item_id = db.get_item_id(field_name, field_value)
if item_id is not None: if item_id is not None:
note = db.notes_data_for(field_name, item_id) note_data = db.notes_data_for(field_name, item_id)
if note is not None: if note_data is not None:
if plain_text: if plain_text == '1':
return note['searchable_text'].partition('\n')[2] return note['searchable_text'].partition('\n')[2]
return note['doc'] # Return the full HTML of the note, including all images as
return '' # data: URLs. Reason: non-exported note html contains
# "calres://" URLs for images. These images won't render
# outside the context of the library where the note "lives".
# For example, they don't work in book jackets and book
# details from a different library. They also don't work in
# tooltips.
# This code depends on the note being wrapped in <body> tags
# by parse_html. The body is changed to a <div>. That means
# we often end up with <div><div> or some such, but that is
# OK
root = parse_html(note_data['doc'])
# There should be only one <body>
root = root.xpath('//body')[0]
# Change the body to a div
root.tag = 'div'
# Expand all the resources in the note
expand_note_resources(root, db.get_notes_resource)
note = html.tostring(root, encoding='unicode')
return note
except Exception as e: except Exception as e:
traceback.print_exc() traceback.print_exc()
raise ValueError(e) raise ValueError(e)