User:Werson/smartQuotes.js

// smartQuotes.js // by Werson // version 1.2, 2008-05-14 // works correctly in: // · Firefox 2.0 // works somewhat in: // · Safari 3.1 (doesn't skip PRE/TT/CODE sections) // // I, Werson, the copyright holder of this work, hereby release it into the public domain. This applies worldwide. // In case this is not legally possible, I grant any entity the right to use this work for any purpose, // without any conditions, unless such conditions are required by law.

// take a string and replace all straight marks with curly marks, //  applying some basic rules (it's almost always a closing mark, //   so figure out the few cases where it's an opening mark) function quoteReplace(data) {

// single quotation marks, //  problematic because apostrophes (same codepoint as closing quotes,  //   unfortunately) can come at the beginning of words, so we need to  //   list likely examples of that data = data.replace(/'([Nn])(\W)/g, '’$1$2');   // Guns 'n' Roses, or Guns 'n Roses, should use apostrophes data = data.replace(/'(\d)0s/g, '’$10s'); // '80s, '90s, etc. data = data.replace(/'([Tt]is)/g, '’$1'); // 'Tis the season, etc. data = data.replace(/'([Tt]was)/g, '’$1'); // 'Twas the season, etc.  data = data.replace(/^'s(\W)/g, '’s$1');   // John's (links are separate nodes,                                             //   so this would otherwise be seen as 'S...')

// the rest of these are homologous to double quotation marks data = data.replace(/\s'/g, ' ‘'); data = data.replace(/^'([\d\w])/g, '‘$1'); data = data.replace(/(\W)"([\d\w])/g, '$1“$2'); data = data.replace(/'/g, '’');

// double quotation marks data = data.replace(/\s"/g, ' “');             // a closing mark will never be preceded by a space  data = data.replace(/"([\d\w])/g, '“$1');      // a closing mark will never be at the beginning of a line //  (and won't be after a link if it's followed by a letter) data = data.replace(/(\W)"([\d\w])/g, '$1“$2');         // a closing mark won't be after a punctuation mark                                                   //  but before a letter  data = data.replace(/"/g, '”');            // anything else is probably a closer

return data; }

// go through document and get all text nodes, then replace quotation marks function smartQuotes { if (document.URL.indexOf('action=history') < 1 && document.URL.indexOf('action=edit') < 1) { // title is a special case, as replacing the node text doesn't do anything document.title = quoteReplace(document.title); // use an XPATH to find all text nodes, and run each one through quoteReplace //  but do not alter PRE, CODE, or TT elements, or any of their descendents //  (I don't know how to do this elegantly in XPath) var xPathResult = document.evaluate('.//*[name(.) != "PRE" and name(.) != "CODE" and name(.) != "TT"]/*[name(.) != "PRE" and name(.) != "CODE" and name(.) != "TT"]/*[name(.) != "PRE" and name(.) != "CODE" and name(.) != "TT"]/text[normalize-space(.) != ""]', document.documentElement, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); for (var i = 0, l = xPathResult.snapshotLength; i < l; i++) { var textNode = xPathResult.snapshotItem(i); textNode.data = quoteReplace(textNode.data); }   // crappy way to do this var html = document.body.innerHTML; document.body.innerHTML = html.replace('”<a ', '“<a '); } }

// initiate smartQuotes script $(smartQuotes);