fix(bib/sync): wrap Zotero notes in zotero-note envelope
Without the <div class="zotero-note znv1"> wrapper, Zotero treats the note body as plain text on next launch and HTML-escapes every tag, turning rendered output into a wall of source. The envelope is Zotero's own sigil for "I already produced this HTML, leave it alone." Idempotent — wraps only if not already prefixed. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -539,7 +539,13 @@ def _sync_notes(
|
||||
title = row["title"] or ""
|
||||
if title in existing_titles:
|
||||
continue
|
||||
db.add_note(zot_parent_id, row["content"], title=title)
|
||||
# Zotero recognizes notes already in its envelope and leaves the
|
||||
# HTML alone; without it, on next launch Zotero treats the body
|
||||
# as plain text and HTML-escapes every tag.
|
||||
body = row["content"] or ""
|
||||
if not body.startswith('<div class="zotero-note'):
|
||||
body = f'<div class="zotero-note znv1">{body}</div>'
|
||||
db.add_note(zot_parent_id, body, title=title)
|
||||
existing_titles.add(title)
|
||||
count += 1
|
||||
return count
|
||||
|
||||
@@ -454,7 +454,12 @@ class TestSyncNotes:
|
||||
con = sqlite3.connect(zot_db)
|
||||
rows = con.execute("SELECT title, note FROM itemNotes").fetchall()
|
||||
con.close()
|
||||
assert rows == [("Comment text", "<h1>Body</h1><p>text</p>")]
|
||||
assert rows == [
|
||||
(
|
||||
"Comment text",
|
||||
'<div class="zotero-note znv1"><h1>Body</h1><p>text</p></div>',
|
||||
)
|
||||
]
|
||||
|
||||
def test_resync_is_idempotent(self, tmp_path):
|
||||
"""Second sync must not duplicate the note (dedup by parent + title)."""
|
||||
|
||||
Reference in New Issue
Block a user