Apparent bug in Ubuntu with LibreOffice causes citations to be unlinked on paste
I have a similar problem to that reported by others. I'm working in LibreOffice.
It's possible that I cut and pasted one section of my document from version saved as .docx but I don't think so, also the affected parts of my main document are too large for that to be the reason.
One possible cause is that I moved some sections around both by cutting and pasting and by using Navigator. My experience in the past, (and with a new test document) though is that this doesn't break links. However, due to the size of the current document, and perhaps corruption of the file, and bugs in the software, the cutting and pasting probably broke the links.
I attempted to cut and paste from a previous .odt version into the current document and the footnote references (Chicago note style) go from linked to unlinked when pasted.
On opening an older version I find that a few seemingly random citations in the footnotes are unlinked.
Cutting and pasting all content of the current document to an entirely new document allowed me to successfully cut and paste sections from an older version.
This suggests that possibly the Writer document had become corrupted.
However, Its likely this is a LibreOffice Ubuntu interaction bug.
See https://bugs.launchpad.net/ubuntu/+source/mutter/+bug/1852183
I downgraded to the more stable version 7.3.7.2 to be on the safe side.
Original issue while working with:
Zotero version: 6.0.18
LibreOffice Writer version: 7.4.2.3 / LibreOffice Community
Build ID: 40(Build:3)
Linux Mint 20.3 Cinnamon
Ubuntu package version: 1:7.4.2~rc3-0ubuntu0.20.04.1~lo1
Linux kernel 5.4.0-66-generic
It's possible that I cut and pasted one section of my document from version saved as .docx but I don't think so, also the affected parts of my main document are too large for that to be the reason.
One possible cause is that I moved some sections around both by cutting and pasting and by using Navigator. My experience in the past, (and with a new test document) though is that this doesn't break links. However, due to the size of the current document, and perhaps corruption of the file, and bugs in the software, the cutting and pasting probably broke the links.
I attempted to cut and paste from a previous .odt version into the current document and the footnote references (Chicago note style) go from linked to unlinked when pasted.
On opening an older version I find that a few seemingly random citations in the footnotes are unlinked.
Cutting and pasting all content of the current document to an entirely new document allowed me to successfully cut and paste sections from an older version.
This suggests that possibly the Writer document had become corrupted.
However, Its likely this is a LibreOffice Ubuntu interaction bug.
See https://bugs.launchpad.net/ubuntu/+source/mutter/+bug/1852183
I downgraded to the more stable version 7.3.7.2 to be on the safe side.
Original issue while working with:
Zotero version: 6.0.18
LibreOffice Writer version: 7.4.2.3 / LibreOffice Community
Build ID: 40(Build:3)
Linux Mint 20.3 Cinnamon
Ubuntu package version: 1:7.4.2~rc3-0ubuntu0.20.04.1~lo1
Linux kernel 5.4.0-66-generic
Is there a way to copy a citation code from here, paste it into a new footnote, and then turn the pasted text into a linked field?
One use case would be instances where there's a complex citation that needs to be made in multiple places (maybe even multiple documents). A copy-and-paste process would obviate the need to reconstruct the citation from scratch.
I've found how to turn text into field codes in Word. But I'm having trouble turning up the corresponding process for Writer.
Thanks so much for any suggestions you may have!
Unfortunately, it appears that libreoffice does not allow two reference marks to have the same attributes - a situation that would occur with copy and paste. Cut and paste, however, does work as the reference marks are not duplicated.
Hence, probably not a bug. But it certainly is a nuisance.
As to the proposal by dstark, a macro could be written. This would need probably to be in python using citeproc-py (code is languishing well behind) or javascipt using citeproc.js (this is what zotero uses). If somebody has nothing better to do.....
Am I just missing how to do this copy? Or is that not something that Writer supports?
1) select where you want to insert the reference
2) open Insert -> Cross-Reference -> Insert Reference
3) click on the reference you need in the right panel
4) click the mouse in the name panel and ctrl-a ctrl-c to copy the reference field
5) go to Insert -> Cross-Reference -> Set Reference
6) ctrl-v to paste the reference field into the name
7) change one of more of the last letters at the end of the string (you should already see the end of the string in the name field)
8) click on insert
9) refresh the document with Zotero and and No in the dialog.
After all that it would probably be quicker to insert the reference as usual from Zotero.
Thanks so much!
This has only been tested with Apa6 style of citations e.g. (name et al., 2023). It will not work with numbered styles. You may get it to work with square bracket styles if you change the line with the # comment.
It is written so that it should be easy to understand if you want to convert it to basic.The only problem may be checking in footnotes and endnotes which has to rely on an error generated when trying to compare text ranges (thrown when the ranges are in different text components), If you do not put references in footnotes or endnotes (who would?) then these sections can be omitted.
import random
import string
import json
def correct_references():
document = XSCRIPTCONTEXT.getDocument()
search_descriptor = document.createSearchDescriptor()
search_descriptor.SearchRegularExpression = True
reference_marks = document.ReferenceMarks
for reference_mark in reference_marks:
reference_mark_content = reference_mark.Name
reference_mark_json, _ = reference_mark_content.rsplit(" ", 1)
_, _, reference_mark_json = reference_mark_json.split(" ", 2)
data_dictionary = json.loads(reference_mark_json, strict=False)
plain_cite = data_dictionary["properties"]["plainCitation"]
search_descriptor.SearchString = "\(" + plain_cite[1:-1] + "\)" #have to escape the parentheses
search_found = document.findFirst(search_descriptor)
while search_found:
if not search_found.Start.ReferenceMark:
n = 10
characters = string.ascii_letters + string.digits
randomChars = ''.join(random.choice(characters) for i in range(n))
new_reference_mark_content = reference_mark_content[:-n] + randomChars
new_reference_mark = document.createInstance("com.sun.star.text.ReferenceMark")
new_reference_mark.Name = new_reference_mark_content
if search_found.getText().supportsService("com.sun.star.text.CellProperties"):
view_cursor = document.getCurrentController().getViewCursor()
_ = view_cursor.gotoRange(search_found, False)
table_name = view_cursor.TextTable.TableName
cell_name = view_cursor.Cell.CellName
table = document.TextTables.getByName(table_name)
cell = table.getCellByName(cell_name)
cell_cursor = cell.createTextCursorByRange(search_found)
cell.Text.insertTextContent(cell_cursor, new_reference_mark, True)
elif search_found.getText().supportsService("com.sun.star.text.Text"):
if search_found.getText().supportsService("com.sun.star.text.TextFrame"):
view_cursor = document.getCurrentController().getViewCursor()
_ = view_cursor.gotoRange(search_found, False)
frame_name = view_cursor.TextFrame.Name
frame = document.TextFrames.getByName(frame_name)
frame_cursor = frame.createTextCursorByRange(search_found)
frame.Text.insertTextContent(frame_cursor, new_reference_mark, True)
elif search_found.getText().supportsService("com.sun.star.text.Endnote"):
search_found_start = search_found.getStart()
endnotes = document.getEndnotes()
for i in range (endnotes.Count):
endnotes_found_start = endnotes.getByIndex(i).Start
try:
_ = endnotes.getByIndex(i).Text.compareRegionStarts(endnotes_found_start,search_found_start)
sucess = i
except:
pass
required_endnote = endnotes.getByIndex(sucess)
endnote_cursor = required_endnote.createTextCursorByRange(search_found)
required_endnote.Text.insertTextContent(endnote_cursor, new_reference_mark, True)
elif search_found.getText().supportsService("com.sun.star.text.Footnote") \
and not search_found.getText().supportsService("com.sun.star.text.Endnote"):
search_found_start = search_found.getStart()
footnotes = document.getFootnotes()
for i in range (footnotes.Count):
footnotes_found_start = footnotes.getByIndex(i).Start
try:
_ = footnotes.getByIndex(i).Text.compareRegionStarts(footnotes_found_start,search_found_start)
sucess = i
except:
pass
required_footnote = footnotes.getByIndex(sucess)
footnote_cursor = required_footnote.createTextCursorByRange(search_found)
required_footnote.Text.insertTextContent(footnote_cursor, new_reference_mark, True)
else:
document.Text.insertTextContent(search_found, new_reference_mark, True)
search_found = document.findNext(search_found, search_descriptor)
"Switch to a Different Word Processor …" button (in, say, a copy of the document we're actually working in). Combined with step 7 from your workflow above, this might also be a way of condensing steps 1–6 if one wanted to go with that workflow.
Thanks, again, for having a look.
In the meantime I have discovered a rather clumsy workaround. I installed OpenOffice, copied my whole (long) document to an OpenOffice Writer document and from there I was able to copy back (and hence successfully move) large sections of my original document while retaining the Zotero citation links.
OpenOffice is considered the more stable of the two, but without rapid development. I guess it has fewer bugs.
Sometimes I wish I had stuck with org-mode :-\
BTW thanks for your great work on Zotero.
LibreOffice plus Zotero is excellent for me except for the copy and paste issue.
Also, if I was able to use the Master Documents and sub-documents with Zotero, that would be great. But it seems they don't work together. Not a biggie.
I do like the innovation to have Zotero support installed automatically on supported word processors, making it more accessible.