From 216fc8687e5e1e9dc8cd305bcc6eac02af91fa5a Mon Sep 17 00:00:00 2001 From: Simon Kornblith Date: Thu, 17 Jan 2008 04:28:04 +0000 Subject: [PATCH] closes #879, Underline continues after two books without page numbers in OOo/MLA closes #847, Quote issues references #885, JSON parsing error: "Missing ) in parenthetical" (might fix, but I don't know how to reproduce it) --- chrome/content/zotero/xpcom/cite.js | 250 +++++++++++---------- chrome/content/zotero/xpcom/integration.js | 4 +- 2 files changed, 138 insertions(+), 116 deletions(-) diff --git a/chrome/content/zotero/xpcom/cite.js b/chrome/content/zotero/xpcom/cite.js index d3898c803..78edeed4b 100644 --- a/chrome/content/zotero/xpcom/cite.js +++ b/chrome/content/zotero/xpcom/cite.js @@ -516,7 +516,7 @@ Zotero.CSL.prototype.formatCitation = function(citation, format) { } var returnString = string.clone(); - returnString.append(string.get(), context.layout, false, true); + returnString.concat(string, context.layout); var returnString = returnString.get(); // loop through to remove _csl property @@ -2636,6 +2636,7 @@ Zotero.CSL.FormattedString = function(context, format, delimiter, subsequent) { this.delimiter = delimiter; this.string = ""; this.closePunctuation = false; + this.closeFormatting = ""; this.useBritishStyleQuotes = false; // insert tab iff second-field-align is on @@ -2668,25 +2669,32 @@ Zotero.CSL.FormattedString.prototype.concat = function(formattedString, element) throw "CSL: cannot concatenate formatted strings: formats do not match"; } - if(formattedString.string) { - // first, append the actual string - var haveAppended = this.append(formattedString.string, element, false, true); - - // if there's close punctuation to append, that also counts - if(formattedString.closePunctuation) { - haveAppended = true; - if(this.closePunctuation) { - // if there's existing close punctuation and punctuation to - // append, we need to append that - this.string += this.closePunctuation; - } - // add the new close punctuation - this.closePunctuation = formattedString.closePunctuation; + var haveAppended = false; + var suffix = false; + if(formattedString.string !== "") { + // first, append the actual string without its suffix + if(element && element.@suffix.length()) { + // don't edit original element + element = element.copy(); + // let us decide to add the suffix + suffix = element.@suffix.toString(); + element.@suffix = []; } - - return haveAppended; + haveAppended = this.append(formattedString.string, element, false, true); } - return false; + + // if there's close punctuation to append, that also counts + if(formattedString.closePunctuation || formattedString.closeFormatting) { + haveAppended = true; + // add the new close punctuation + this.closeFormatting = formattedString.closeFormatting; + this.closePunctuation = formattedString.closePunctuation; + } + + // append suffix, if we didn't before + if(haveAppended && suffix !== false) this.append(suffix, null, true); + + return haveAppended; } Zotero.CSL.FormattedString._rtfEscapeFunction = function(aChar) { @@ -2697,10 +2705,10 @@ Zotero.CSL.FormattedString._rtfEscapeFunction = function(aChar) { * appends a string (with format parameters) to the current one */ Zotero.CSL.FormattedString.prototype.append = function(string, element, dontDelimit, dontEscape) { - if(!string) return false; if(typeof(string) != "string") { string = string.toString(); } + if(string.toString() === "") return false; // append delimiter if necessary if(this.delimiter && this.string && !dontDelimit) { @@ -2719,48 +2727,39 @@ Zotero.CSL.FormattedString.prototype.append = function(string, element, dontDeli } } + if(prefix) { + this.append(prefix, null, true); + } + + var addBefore = ""; + var addAfter = ""; + // append line before if display="block" - var closeDiv = false; if(element && (element["@display"] == "block" || this.appendLine)) { if(this.format == "HTML") { if(this.option.(@name == "hanging-indent").@value == "true") { - this.string += '
' + addBefore += '
' } else { - this.string += '
'; + addBefore += '
'; } - var closeDiv; + addAfter = '
'; } else { if(this.format == "RTF") { - this.string += "\r\n\\line "; + addBefore += "\r\n\\line "; } else if(this.format == "Integration") { - this.string += "\x0B"; + addBefore += "\x0B"; } else { - this.string += (Zotero.isWin ? "\r\n" : "\n"); + addBefore += (Zotero.isWin ? "\r\n" : "\n"); } this.appendLine = element["@display"] == "block"; } } - if(prefix) { - this.append(prefix, null, true); - } - if(this.suppressLeadingWhitespace) { string = string.replace(/^\s+/, ""); this.suppressLeadingWhitespace = false; } - if(string.length && string[0] == "." && - Zotero.CSL.FormattedString._punctuation.indexOf(this.string[this.string.length-1]) != -1) { - // if string already ends in punctuation, preserve the existing stuff - // and don't add a period - string = string.substr(1); - } else if(this.string[this.string.length-1] == "(" && string[0] == " ") { - string = string.substr(1); - } else if(this.string[this.string.length-1] == " " && string[0] == ")") { - this.string = this.string.substr(0, this.string.length-1); - } - // close quotes, etc. using punctuation if(this.closePunctuation) { if(Zotero.CSL.FormattedString._punctuation.indexOf(string[0]) != -1) { @@ -2771,59 +2770,56 @@ Zotero.CSL.FormattedString.prototype.append = function(string, element, dontDeli this.closePunctuation = false; } + // clean up + if(string.length && string[0] == "." && + Zotero.CSL.FormattedString._punctuation.indexOf(this.string[this.string.length-1]) != -1) { + // if string already ends in punctuation, preserve the existing stuff + // and don't add a period + string = string.substr(1); + } else if(this.string[this.string.length-1] == "(" && string[0] == " ") { + string = string.substr(1); + } else if(this.string[this.string.length-1] == " " && string[0] == ")") { + this.string = this.string.substr(0, this.string.length-1); + } + + // close previous formatting + this.string += this.closeFormatting; + this.closeFormatting = ""; + // handling of "text-transform" attribute (now obsolete) if(element && element["@text-transform"].length() && !element["@text-case"].length()) { var mapping = {"lowercase":"lowercase", "uppercase":"uppercase", "capitalize":"capitalize-first"}; element["@text-case"] = mapping[element["@text-transform"].toString()]; } + // handle text case - if(element && element["@text-case"].length()) { - if(element["@text-case"] == "lowercase") { - // all lowercase - string = string.toLowerCase(); - } else if(element["@text-case"] == "uppercase") { - // all uppercase - string = string.toUpperCase(); - } else if(element["@text-case"] == "capitalize-first") { - // capitalize first - string = string[0].toUpperCase()+string.substr(1).toLowerCase(); - } else if(element["@text-case"] == "capitalize-all") { - // capitalize first - var strings = string.split(" "); - for(var i=0; i 1) { - strings[i] = strings[i][0].toUpperCase()+strings[i].substr(1).toLowerCase(); - } else if(strings[i].length == 1) { - strings[i] = strings[i].toUpperCase(); - } - } - string = strings.join(" "); - } else if(element["@text-case"] == "title") { - string = Zotero.Text.titleCase(string); - } - } - - if(!dontEscape) { - if(this.format == "HTML") { - string = string.replace("&", "&", "g") - .replace("<", "<", "g") - .replace(">", ">", "g") - .replace(/(\r\n|\r|\n)/g, "
") - .replace(/[\x00-\x1F]/g, ""); - } else if(this.format == "RTF") { - string = string.replace("\\", "\\\\", "g") - .replace(/[\x7F-\uFFFF]/g, Zotero.CSL.FormattedString._rtfEscapeFunction) - .replace("\t", "\\tab ", "g") - .replace(/(\r\n|\r|\n)/g, "\\line "); - } else if(this.format == "Integration") { - string = string.replace(/\\/g, "\\\\") - .replace(/(\r\n|\r|\n)/g, "\\line "); - } else { - string = string.replace(/(\r\n|\r|\n)/g, (Zotero.isWin ? "\r\n" : "\n")); - } - } - if(element) { + if(element["@text-case"].length()) { + if(element["@text-case"] == "lowercase") { + // all lowercase + string = string.toLowerCase(); + } else if(element["@text-case"] == "uppercase") { + // all uppercase + string = string.toUpperCase(); + } else if(element["@text-case"] == "capitalize-first") { + // capitalize first + string = string[0].toUpperCase()+string.substr(1).toLowerCase(); + } else if(element["@text-case"] == "capitalize-all") { + // capitalize first + var strings = string.split(" "); + for(var i=0; i 1) { + strings[i] = strings[i][0].toUpperCase()+strings[i].substr(1).toLowerCase(); + } else if(strings[i].length == 1) { + strings[i] = strings[i].toUpperCase(); + } + } + string = strings.join(" "); + } else if(element["@text-case"] == "title") { + string = Zotero.Text.titleCase(string); + } + } + // style attributes if(this.format == "HTML") { var style = ""; @@ -2839,30 +2835,26 @@ Zotero.CSL.FormattedString.prototype.append = function(string, element, dontDeli } if(style) { - string = ''+string+''; + addBefore += ''; + addAfter = ''+addAfter; } } else { if(this.format == "RTF" || this.format == "Integration") { - if(element["@font-style"] == "oblique" || element["@font-style"] == "italic") { - string = "\\i "+string+"\\i0 "; + var rtfAttributes = { + "font-style":{"oblique":"i", "italic":"i"}, + "font-variant":{"small-caps":"scaps"}, + "font-weight":{"bold":"b"}, + "text-decoration":{"underline":"ul"}, + "vertical-align":{"sup":"super", "sub":"sub"} } - if(element["@font-variant"] == "small-caps") { - string = "\\scaps "+string+"\\scaps0 "; - } - - if(element["@font-weight"] == "bold") { - string = "\\b "+string+"\\b0 "; - } - - if(element["@text-decoration"] == "underline") { - string = "\\ul "+string+"\\ul0 "; - } - - if(element["@vertical-align"] == "sup") { - string = "\\super "+string+"\\super0 "; - } else if(element["@vertical-align"] == "sub") { - string = "\\sub "+string+"\\sub0 "; + for(var j in rtfAttributes) { + for(var k in rtfAttributes[j]) { + if(element["@"+j] == k) { + addBefore += "\\"+rtfAttributes[j][k]+" "; + addAfter = "\\"+rtfAttributes[j][k]+"0 "+addAfter; + } + } } } } @@ -2879,7 +2871,36 @@ Zotero.CSL.FormattedString.prototype.append = function(string, element, dontDeli } } - this.string += string; + if(!dontEscape) { + if(this.format == "HTML") { + string = string.replace("&", "&", "g") + .replace("<", "<", "g") + .replace(">", ">", "g") + .replace(/(\r\n|\r|\n)/g, "
") + .replace(/[\x00-\x1F]/g, ""); + } else if(this.format == "RTF" || this.format == "Integration") { + string = string.replace("\\", "\\\\", "g") + .replace(/(\r\n|\r|\n)/g, "\\line "); + if(string.substr(string.length-6) == "\\line ") { + string = string.substr(0, string.length-6); + addAfter = "\\line "+addAfter; + } + + if(this.format == "RTF") { + string = string.replace(/[\x7F-\uFFFF]/g, Zotero.CSL.FormattedString._rtfEscapeFunction) + .replace("\t", "\\tab ", "g"); + + if(string.substr(string.length-5) == "\\tab ") { + string = string.substr(0, string.length-5); + addAfter = "\\tab "+addAfter; + } + } + } else { + string = string.replace(/(\r\n|\r|\n)/g, (Zotero.isWin ? "\r\n" : "\n")); + } + } + + this.string += addBefore+string; var suffix; if(element && element.@suffix.length()) { @@ -2887,9 +2908,6 @@ Zotero.CSL.FormattedString.prototype.append = function(string, element, dontDeli } // close div for display=block in HTML - if(closeDiv) { - this.string += "
"; - } // save for second-field-align if(!dontDelimit && this.insertTabAfterField) { @@ -2897,19 +2915,21 @@ Zotero.CSL.FormattedString.prototype.append = function(string, element, dontDeli this.string = this.string.replace(/\s+$/, ""); if(this.format == "HTML") { - this.string += ''; + addAfter += ''; } else if(this.format == "RTF") { - this.string += "\\tab "; + addAfter += "\\tab "; } else if(this.format == "Integration") { - this.string += "\t"; + addAfter += "\t"; } else { - this.string += " "; + addAfter += " "; } this.insertTabAfterField = false; this.suppressLeadingWhitespace = true; } + this.closeFormatting = addAfter; + return true; } @@ -2917,7 +2937,7 @@ Zotero.CSL.FormattedString.prototype.append = function(string, element, dontDeli * gets the formatted string */ Zotero.CSL.FormattedString.prototype.get = function() { - return this.string+(this.closePunctuation ? this.closePunctuation : ""); + return this.string+(this.closeFormatting ? this.closeFormatting : "")+(this.closePunctuation ? this.closePunctuation : ""); } /* diff --git a/chrome/content/zotero/xpcom/integration.js b/chrome/content/zotero/xpcom/integration.js index dc85e93df..908869705 100644 --- a/chrome/content/zotero/xpcom/integration.js +++ b/chrome/content/zotero/xpcom/integration.js @@ -1003,7 +1003,9 @@ Zotero.Integration.Session.prototype.getCitations = function(regenerateAll) { if(citation.properties.custom) { output.push(citation.properties.custom); } else { - output.push(this.style.formatCitation(citation, "Integration")); + var citation = this.style.formatCitation(citation, "Integration"); + if(citation == "") citation = " "; + output.push(citation); } } }