{ "translatorID": "897a81c2-9f60-4bec-ae6b-85a5030b8be5", "translatorType": 2, "label": "Note HTML", "creator": "Martynas Bagdonas", "target": "html", "minVersion": "5.0.97", "maxVersion": null, "priority": 50, "inRepository": true, "configOptions": { "noteTranslator": true }, "displayOptions": { "includeAppLinks": false }, "lastUpdated": "2024-07-11 09:05:00" } /* ***** BEGIN LICENSE BLOCK ***** Copyright © 2021 Corporation for Digital Scholarship Vienna, Virginia, USA http://digitalscholar.org/ This file is part of Zotero. Zotero is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Zotero is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with Zotero. If not, see . ***** END LICENSE BLOCK ***** */ // Based on https://github.com/zotero/zotero/blob/32a5826a1fdcb8095e0ff6789d06dcb190212de9/chrome/content/zotero/xpcom/quickCopy.js#L266-L419 function doExport() { Zotero.setCharacterSet('utf-8'); let item; let doc = new DOMParser().parseFromString('
', 'text/html'); let container = doc.body.firstChild; while ((item = Zotero.nextItem())) { if (item.itemType === 'note' || item.itemType === 'attachment') { let div = doc.createElement('div'); div.className = 'zotero-note'; div.innerHTML = item.note || ''; // Skip empty notes if (!div.textContent.trim()) { continue; } // Unwrap ProseMirror note metadata container let inner = div.firstElementChild; if (inner && inner.getAttribute('data-schema-version')) { inner.replaceWith(...inner.childNodes); } container.append(div); } } if (Zotero.getOption("includeAppLinks")) { // Insert a PDF link for highlight, underline and image annotation nodes doc.querySelectorAll('span[class="highlight"], span[class="underline"], img[data-annotation]').forEach(function (node) { try { var annotation = JSON.parse(decodeURIComponent(node.getAttribute('data-annotation'))); } catch (e) { } if (annotation) { // annotation.uri was used before note-editor v4 let uri = annotation.attachmentURI || annotation.uri; let position = annotation.position; if (typeof uri === 'string' && typeof position === 'object') { let openURI; let uriParts = uri.split('/'); let libraryType = uriParts[3]; let key = uriParts[uriParts.length - 1]; if (libraryType === 'users') { openURI = 'zotero://open-pdf/library/items/' + key; } // groups else { let groupID = uriParts[4]; openURI = 'zotero://open-pdf/groups/' + groupID + '/items/' + key; } let linkText; if (position.type === 'FragmentSelector') { openURI += '?cfi=' + encodeURIComponent(position.value); linkText = 'epub'; } else if (position.type === 'CssSelector') { openURI += '?sel=' + encodeURIComponent(position.value); linkText = 'snapshot'; } else { openURI += '?page=' + (position.pageIndex + 1); linkText = 'pdf'; } if (annotation.annotationKey) { openURI += '&annotation=' + annotation.annotationKey; } let a = doc.createElement('a'); a.href = openURI; a.append(linkText); let fragment = doc.createDocumentFragment(); fragment.append(' (', a, ') '); let nextNode = node.nextElementSibling; if (nextNode && nextNode.classList.contains('citation')) { nextNode.parentNode.insertBefore(fragment, nextNode.nextSibling); } else { node.parentNode.insertBefore(fragment, node.nextSibling); } } } }); // Transform citations to links doc.querySelectorAll('span[class="citation"]').forEach(function (span) { try { var citation = JSON.parse(decodeURIComponent(span.getAttribute('data-citation'))); } catch (e) { } if (citation && citation.citationItems && citation.citationItems.length) { let uris = []; for (let citationItem of citation.citationItems) { let uri = citationItem.uris[0]; if (typeof uri === 'string') { let uriParts = uri.split('/'); let libraryType = uriParts[3]; let key = uriParts[uriParts.length - 1]; if (libraryType === 'users') { uris.push('zotero://select/library/items/' + key); } // groups else { let groupID = uriParts[4]; uris.push('zotero://select/groups/' + groupID + '/items/' + key); } } } let items = Array.from(span.querySelectorAll('.citation-item')).map(x => x.textContent); // Fallback to pre v5 note-editor schema that was serializing citations as plain text i.e.: // (Jang et al., 2005, p. 14; Kongsgaard et al., 2009, p. 790) if (!items.length) { items = span.textContent.slice(1, -1).split('; '); } span.innerHTML = '(' + items.map((item, i) => `${item}`).join('; ') + ')'; } }); } // Remove annotation and citation data ZU.xpath(doc, '//span[@data-citation]').forEach(span => span.removeAttribute('data-citation')); ZU.xpath(doc, '//span[@data-annotation]').forEach(span => span.removeAttribute('data-annotation')); ZU.xpath(doc, '//img[@data-annotation]').forEach(img => img.removeAttribute('data-annotation')); // Add horizontal rules between notes Array.from(container.children).slice(1).forEach((element) => { container.insertBefore(doc.createElement('hr'), element); }); // Add quotes around blockquote paragraphs // Open quote ZU.xpath(doc, '//blockquote/p[1]').forEach((element) => { element.insertBefore(doc.createTextNode('\u201c'), element.firstChild); }); // End quote ZU.xpath(doc, '//blockquote/p[last()]').forEach((element) => { element.appendChild(doc.createTextNode('\u201d')); }); // Everything seems to like margin-left better than padding-left Zotero.Utilities.xpath(doc, 'p').forEach((p) => { if (p.style.paddingLeft) { p.style.marginLeft = p.style.paddingLeft; p.style.paddingLeft = ''; } }); // Word and TextEdit don't indent blockquotes on their own and need this // OO gets it right, so this results in an extra indent ZU.xpath(doc, '//blockquote/p').forEach(p => p.style.marginLeft = '30px'); let charsetMeta = doc.createElement('meta'); charsetMeta.setAttribute('charset', 'utf-8'); doc.head.append(charsetMeta); Zotero.write('' + doc.documentElement.outerHTML); }