Improve annotations insertion into notes:
- Properly transform HTML tags flavored plain-text into actual HTML - Add support for multiline comments and highlights - Insert newline before citation/comment when necessary
This commit is contained in:
parent
f2a440185b
commit
ab200cc60b
4 changed files with 81 additions and 8 deletions
|
@ -239,6 +239,74 @@ class EditorInstance {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform plain text, containing some supported HTML tags, into actual HTML.
|
||||
* A similar code is also used in pdf-reader mini editor for annotation text and comments.
|
||||
* It basically creates a text node and then parses and wraps specific parts
|
||||
* of it into supported HTML tags
|
||||
*
|
||||
* @param text Plain text flavored with some HTML tags
|
||||
* @returns {string} HTML
|
||||
* @private
|
||||
*/
|
||||
_transformTextToHTML(text) {
|
||||
const supportedFormats = ['i', 'b', 'sub', 'sup'];
|
||||
|
||||
function getFormatter(str) {
|
||||
let results = supportedFormats.map(format => str.toLowerCase().indexOf('<' + format + '>'));
|
||||
results = results.map((offset, idx) => [supportedFormats[idx], offset]);
|
||||
results.sort((a, b) => a[1] - b[1]);
|
||||
for (let result of results) {
|
||||
let format = result[0];
|
||||
let offset = result[1];
|
||||
if (offset < 0) continue;
|
||||
let lastIndex = str.toLowerCase().indexOf('</' + format + '>', offset);
|
||||
if (lastIndex >= 0) {
|
||||
let parts = [];
|
||||
parts.push(str.slice(0, offset));
|
||||
parts.push(str.slice(offset + format.length + 2, lastIndex));
|
||||
parts.push(str.slice(lastIndex + format.length + 3));
|
||||
return {
|
||||
format,
|
||||
parts
|
||||
};
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function walkFormat(parent) {
|
||||
let child = parent.firstChild;
|
||||
while (child) {
|
||||
if (child.nodeType === 3) {
|
||||
let text = child.nodeValue;
|
||||
let formatter = getFormatter(text);
|
||||
if (formatter) {
|
||||
let nodes = [];
|
||||
nodes.push(doc.createTextNode(formatter.parts[0]));
|
||||
let midNode = doc.createElement(formatter.format);
|
||||
midNode.appendChild(doc.createTextNode(formatter.parts[1]));
|
||||
nodes.push(midNode);
|
||||
nodes.push(doc.createTextNode(formatter.parts[2]));
|
||||
child.replaceWith(...nodes);
|
||||
child = midNode;
|
||||
}
|
||||
}
|
||||
walkFormat(child);
|
||||
child = child.nextSibling;
|
||||
}
|
||||
}
|
||||
|
||||
let parser = Components.classes['@mozilla.org/xmlextras/domparser;1']
|
||||
.createInstance(Components.interfaces.nsIDOMParser);
|
||||
let doc = parser.parseFromString('', 'text/html');
|
||||
|
||||
// innerText transforms \n into <br>
|
||||
doc.body.innerText = text;
|
||||
walkFormat(doc.body);
|
||||
return doc.body.innerHTML;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Zotero.Item[]} annotations
|
||||
* @param {Boolean} skipEmbeddingItemData Do not add itemData to citation items
|
||||
|
@ -324,18 +392,23 @@ class EditorInstance {
|
|||
|
||||
// Text
|
||||
if (annotation.text) {
|
||||
highlightHTML = `<span class="highlight" data-annotation="${encodeURIComponent(JSON.stringify(storedAnnotation))}">“${annotation.text.trim()}”</span>`;
|
||||
let text = this._transformTextToHTML(annotation.text.trim());
|
||||
highlightHTML = `<span class="highlight" data-annotation="${encodeURIComponent(JSON.stringify(storedAnnotation))}">“${text}”</span>`;
|
||||
}
|
||||
|
||||
// Note
|
||||
if (annotation.comment) {
|
||||
commentHTML = ' ' + annotation.comment.trim();
|
||||
let comment = this._transformTextToHTML(annotation.comment.trim());
|
||||
// Move comment to the next line if it has multiple lines
|
||||
commentHTML = (((highlightHTML || imageHTML || citationHTML) && comment.includes('<br')) ? '<br/>' : ' ') + comment;
|
||||
}
|
||||
|
||||
if (citationHTML) {
|
||||
// Move citation to the next line if highlight has multiple lines or is after image
|
||||
citationHTML = ((highlightHTML && highlightHTML.includes('<br') || imageHTML) ? '<br>' : '') + citationHTML;
|
||||
}
|
||||
|
||||
let otherHTML = [highlightHTML, citationHTML, commentHTML].filter(x => x).join(' ');
|
||||
if (imageHTML && otherHTML) {
|
||||
imageHTML += '<br/>';
|
||||
}
|
||||
html += '<p>' + imageHTML + otherHTML + '</p>\n';
|
||||
}
|
||||
return { html, citationItems: storedCitationItems };
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit e8539c524e4deb0404aaf69a08e8e119f25c9d2a
|
||||
Subproject commit a348bbdebf2771222f628c8d14546e3b410c5a58
|
|
@ -1 +1 @@
|
|||
Subproject commit 65bb0ea542694d8a88a6c1aacb8488274ad96c03
|
||||
Subproject commit 326c2e0829522662fc35528dbde6454949142bb4
|
|
@ -1 +1 @@
|
|||
Subproject commit 41f952bccf4e038888791a120e41f0eeae1f2458
|
||||
Subproject commit 0b289deeb93dbc0f4d563897ac24e04e2942e097
|
Loading…
Reference in a new issue