From 41db61ecb9f17b92511806f223aee5d0e5c52ec5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adomas=20Ven=C4=8Dkauskas?= Date: Wed, 17 May 2017 17:12:05 +0300 Subject: [PATCH] Move citation unserialization Using new es6 class syntax because getters/setters don't retain `this` context with Zotero.extendClass and we're building with at least FX45 on every platform now where the syntax is supported --- chrome/content/zotero/xpcom/integration.js | 395 ++++++++++----------- 1 file changed, 194 insertions(+), 201 deletions(-) diff --git a/chrome/content/zotero/xpcom/integration.js b/chrome/content/zotero/xpcom/integration.js index ab028ab2d..4f0691670 100644 --- a/chrome/content/zotero/xpcom/integration.js +++ b/chrome/content/zotero/xpcom/integration.js @@ -878,7 +878,7 @@ Zotero.Integration.Interface.prototype.setDocPrefs = Zotero.Promise.coroutine(fu let field = Zotero.Integration.Field.loadExisting(fields[i]); if (convertItems && field.type === INTEGRATION_TYPE_ITEM) { - var citation = this._session.unserializeCitation(field.code); + var citation = field.unserialize(); if (!citation.properties.dontUpdate) { fieldsToConvert.push(field); fieldNoteTypes.push(this._session.data.prefs.noteType); @@ -1121,7 +1121,7 @@ Zotero.Integration.Fields.prototype._processFields = Zotero.Promise.coroutine(fu if (field.type === INTEGRATION_TYPE_ITEM) { var noteIndex = field.getNoteIndex(); try { - yield this._session.addCitation(i, noteIndex, field.code); + yield this._session.addCitation(i, noteIndex, field.unserialize()); } catch(e) { var removeCode = false; @@ -1347,7 +1347,7 @@ Zotero.Integration.Fields.prototype.addEditCitation = Zotero.Promise.coroutine(f } try { - citation = session.unserializeCitation(field.code); + citation = field.unserialize(); } catch(e) {} if (citation) { @@ -1869,17 +1869,9 @@ Zotero.Integration._oldCitationLocatorMap = { /** * Adds a citation to the arrays representing the document */ -Zotero.Integration.Session.prototype.addCitation = Zotero.Promise.coroutine(function* (index, noteIndex, arg) { +Zotero.Integration.Session.prototype.addCitation = Zotero.Promise.coroutine(function* (index, noteIndex, citation) { var index = parseInt(index, 10); - if(typeof(arg) == "string") { // text field - if(arg == "!" || arg == "X") return; - - var citation = this.unserializeCitation(arg, index); - } else { // a citation already - var citation = arg; - } - // get items yield this.lookupItems(citation, index); @@ -2037,127 +2029,6 @@ Zotero.Integration.Session.prototype.lookupItems = Zotero.Promise.coroutine(func } }); -/** - * Unserializes a JSON citation into a citation object (sans items) - */ -Zotero.Integration.Session.prototype.unserializeCitation = function(code, index) { - var firstBracket = code.indexOf("{"); - if (firstBracket !== -1) { // JSON field - code = code.substr(firstBracket); - - // fix for corrupted fields - var lastBracket = code.lastIndexOf("}"); - if(lastBracket+1 != code.length) { - if(index) this.updateIndices[index] = true; - code = code.substr(0, lastBracket+1); - } - - // get JSON - try { - var citation = JSON.parse(code); - } catch(e) { - // fix for corrupted fields (corrupted by Word, somehow) - try { - var citation = JSON.parse(code.substr(0, code.length-1)); - } catch(e) { - // another fix for corrupted fields (corrupted by 2.1b1) - try { - var citation = JSON.parse(code.replace(/{{((?:\s*,?"unsorted":(?:true|false)|\s*,?"custom":"(?:(?:\\")?[^"]*\s*)*")*)}}/, "{$1}")); - } catch(e) { - throw new Zotero.Integration.CorruptFieldException(code, e); - } - } - } - - // fix for uppercase citation codes - if(citation.CITATIONITEMS) { - if(index) this.updateIndices[index] = true; - citation.citationItems = []; - for (var i=0; i this._text = this._text ? this._text : this.getText(), - set: (v) => {this._text = v; this.dirty = true} -}); - -Zotero.defineProperty(Zotero.Integration.Field.prototype, 'code', { - get: () => this._code = this._code ? this._code : this.getCode(), - set: (v) => {this._code = v; this.dirty = true;} -}); - -Zotero.Integration.Field.prototype = { - writeToDoc: function(doc) { - this.dirty = false; - - let text = this._text; - let isRich = false; - // If RTF wrap with RTF tags - if (text.indexOf("\\") !== -1) { - text = "{\\rtf "+text+"}"; - isRich = true; - } - this._field.setText(text, isRich); - - // Boo. Inconsistent. - if (this.type == INTEGRATION_TYPE_ITEM) { - this._field.setCode(`ITEM CSL_CITATION ${JSON.stringify(this._data)}`); - } else if (this.type == INTEGRATION_TYPE_BIBLIOGRAPHY) { - this._field.setCode(`BIBL ${JSON.stringify(this._data)} CSL_BIBLIOGRAPHY`); - } - - // Retrigger retrieval from doc. - this._text = null; - this._code = null; - }, +Zotero.Integration.CitationField = class extends Zotero.Integration.Field { + constructor(field) { + super(field); + this.type = INTEGRATION_TYPE_ITEM; + } - getCode: function() { - let code = this._field.getCode(); - let start = code.indexOf('{'); - if (start == -1) { - return '{}'; + /** + * Don't be fooled, this should be as simple as JSON.parse(). + * The schema for the code is defined @ https://raw.githubusercontent.com/citation-style-language/schema/master/csl-citation.json + * + * However, over the years and different versions of Zotero there's been changes to the schema, + * incorrect serialization, etc. Therefore this function is cruft-full and we can't get rid of it. + * + * @returns {{citationItems: Object[], properties: Object}} + */ + unserialize() { + function unserialize(code) { + try { + return JSON.parse(code); + } catch(e) { + // fix for corrupted fields (corrupted by 2.1b1) + try { + return JSON.parse(code.replace(/{{((?:\s*,?"unsorted":(?:true|false)|\s*,?"custom":"(?:(?:\\")?[^"]*\s*)*")*)}}/, "{$1}")); + } catch(e) { + throw new Zotero.Integration.CorruptFieldException(code, e); + } + } } - return code.substr(start, start + code.indexOf('}')); + + function upgradeCruft(citation, code) { + // fix for uppercase citation codes + if(citation.CITATIONITEMS) { + citation.citationItems = []; + for (var i=0; i