📄 feedprocessor.js
字号:
if (bagHasKey(guid, "isPermaLink")) isPermaLink = new Boolean(guid.getProperty("isPermaLink")); if (guid && isPermaLink) this.link = strToURI(guid.getProperty("guid")); } if (this.updated) this.updated = dateParse(this.updated); if (this.published) this.published = dateParse(this.published); this._resetBagMembersToRawText([this.searchLists.content, this.searchLists.summary, this.searchLists.title]); }, QueryInterface: function(iid) { if (iid.equals(Ci.nsIFeedEntry) || iid.equals(Ci.nsIFeedContainer) || iid.equals(Ci.nsISupports)) return this; throw Cr.NS_ERROR_NOINTERFACE; }}Entry.prototype._atomLinksToURI = Feed.prototype._atomLinksToURI;Entry.prototype._resetBagMembersToRawText = Feed.prototype._resetBagMembersToRawText;// TextConstruct represents and element that could contain (X)HTMLfunction TextConstruct() { this.lang = null; this.base = null; this.type = "text"; this.text = null;}TextConstruct.prototype = { plainText: function TC_plainText() { if (this.type != "text") { return gUnescapeHTML.unescape(stripTags(this.text)); } return this.text; }, createDocumentFragment: function TC_createDocumentFragment(element) { if (this.type == "text") { var doc = element.ownerDocument; var docFragment = doc.createDocumentFragment(); var node = doc.createTextNode(this.text); docFragment.appendChild(node); return docFragment; } var isXML; if (this.type == "xhtml") isXML = true else if (this.type == "html") isXML = false; else return null; return gUnescapeHTML.parseFragment(this.text, isXML, this.base, element); }, QueryInterface: function(iid) { if (iid.equals(Ci.nsIFeedTextConstruct) || iid.equals(Ci.nsISupports)) return this; throw Cr.NS_ERROR_NOINTERFACE; }}// Generator represents the software that produced the feedfunction Generator() { this.lang = null; this.agent = null; this.version = null; this.uri = null; // nsIFeedElementBase this._attributes = null; this.baseURI = null;}Generator.prototype = { get attributes() { return this._attributes; }, set attributes(value) { this._attributes = value; this.version = this._attributes.getValueFromName("","version"); var uriAttribute = this._attributes.getValueFromName("","uri") || this._attributes.getValueFromName("","url"); this.uri = strToURI(uriAttribute, this.baseURI); // RSS1 uriAttribute = this._attributes.getValueFromName(RDF_NS,"resource"); if (uriAttribute) { this.agent = uriAttribute; this.uri = strToURI(uriAttribute, this.baseURI); } }, QueryInterface: function(iid) { if (iid.equals(Ci.nsIFeedGenerator) || iid.equals(Ci.nsIFeedElementBase) || iid.equals(Ci.nsISupports)) return this; throw Cr.NS_ERROR_NOINTERFACE; }}function Person() { this.name = null; this.uri = null; this.email = null; // nsIFeedElementBase this.attributes = null; this.baseURI = null;}Person.prototype = { QueryInterface: function(iid) { if (iid.equals(Ci.nsIFeedPerson) || iid.equals(Ci.nsIFeedElementBase) || iid.equals(Ci.nsISupports)) return this; throw Cr.NS_ERROR_NOINTERFACE; }}/** * Map a list of fields into properties on a container. * * @param container An nsIFeedContainer * @param fields A list of fields to search for. List members can * be a list, in which case the second member is * transformation function (like parseInt). */function fieldsToObj(container, fields) { var props,prop,field,searchList; for (var key in fields) { searchList = fields[key]; for (var i=0; i < searchList.length; ++i) { props = searchList[i]; prop = null; field = isArray(props) ? props[0] : props; try { prop = container.fields.getProperty(field); } catch(e) { } if (prop) { prop = isArray(props) ? props[1](prop) : prop; container[key] = prop; } } }}/** * Lower cases an element's localName property * @param element A DOM element. * * @returns The lower case localName property of the specified element */function LC(element) { return element.localName.toLowerCase();}// TODO move these post-processor functions// create a generator elementfunction atomGenerator(s, generator) { generator.QueryInterface(Ci.nsIFeedGenerator); generator.agent = trimString(s); return generator;} // post-process an RSS category, map it to the Atom fields.function rssCatTerm(s, cat) { // add slash handling? cat.setPropertyAsAString("term", trimString(s)); return cat;} // post-process a GUID function rssGuid(s, guid) { guid.setPropertyAsAString("guid", trimString(s)); return guid;}// post-process an RSS author element//// It can contain a field like this:// // <author>lawyer@boyer.net (Lawyer Boyer)</author>//// or, delightfully, a field like this://// <dc:creator>Simon St.Laurent (mailto:simonstl@simonstl.com)</dc:creator>//// We want to split this up and assign it to corresponding Atom// fields.//function rssAuthor(s,author) { author.QueryInterface(Ci.nsIFeedPerson); // check for RSS2 string format var chars = trimString(s); var matches = chars.match(/(.*)\((.*)\)/); var emailCheck = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/; if (matches) { var match1 = trimString(matches[1]); var match2 = trimString(matches[2]); if (match2.indexOf("mailto:") == 0) match2 = match2.substring(7); if (emailCheck.test(match1)) { author.email = match1; author.name = match2; } else if (emailCheck.test(match2)) { author.email = match2; author.name = match1; } else { // put it back together author.name = match1 + " (" + match2 + ")"; } } else { author.name = chars; if (chars.indexOf('@')) author.email = chars; } return author;}//// skipHours and skipDays map to arrays, so we need to change the// string to an nsISupports in order to stick it in there.//function rssArrayElement(s) { var str = Cc["@mozilla.org/supports-string;1"]. createInstance(Ci.nsISupportsString); str.data = s; str.QueryInterface(Ci.nsISupportsString); return str;}/***** Some feed utils from TBird *****//** * Tests a RFC822 date against a regex. * @param aDateStr A string to test as an RFC822 date. * * @returns A boolean indicating whether the string is a valid RFC822 date. */function isValidRFC822Date(aDateStr) { var regex = new RegExp(RFC822_RE); return regex.test(aDateStr);}/** * Removes leading and trailing whitespace from a string. * @param s The string to trim. * * @returns A new string with whitespace stripped. */function trimString(s) { return(s.replace(/^\s+/, "").replace(/\s+$/, ""));}// Regular expression matching RFC822 dates const RFC822_RE = "^(((Mon)|(Tue)|(Wed)|(Thu)|(Fri)|(Sat)|(Sun)), *)?\\d\\d?"+ " +((Jan)|(Feb)|(Mar)|(Apr)|(May)|(Jun)|(Jul)|(Aug)|(Sep)|(Oct)|(Nov)|(Dec))"+ " +\\d\\d(\\d\\d)? +\\d\\d:\\d\\d(:\\d\\d)? +(([+-]?\\d\\d\\d\\d)|(UT)|(GMT)"+ "|(EST)|(EDT)|(CST)|(CDT)|(MST)|(MDT)|(PST)|(PDT)|\\w)$";/** * XXX -- need to decide what this should return. * XXX -- Is there a Date class usable from C++? * * Tries tries parsing various date formats. * @param dateString * A string that is supposedly an RFC822 or RFC3339 date. * @returns A Date.toString XXX--fixme */function dateParse(dateString) { var date = trimString(dateString); if (date.search(/^\d\d\d\d/) != -1) //Could be a ISO8601/W3C date return W3CToIETFDate(dateString); if (isValidRFC822Date(date)) return date; if (!isNaN(parseInt(date, 10))) { //It's an integer, so maybe it's a timestamp var d = new Date(parseInt(date, 10) * 1000); var now = new Date(); var yeardiff = now.getFullYear() - d.getFullYear(); if ((yeardiff >= 0) && (yeardiff < 3)) { // it's quite likely the correct date. 3 years is an arbitrary cutoff, // but this is an invalid date format, and there's no way to verify // its correctness. return d.toString(); } } // Can't help. return null;} const XHTML_NS = "http://www.w3.org/1999/xhtml";// The XHTMLHandler handles inline XHTML found in things like atom:summaryfunction XHTMLHandler(processor, isAtom) { this._buf = ""; this._processor = processor; this._depth = 0; this._isAtom = isAtom;}// The fidelity can be improved here, to allow handling of stuff like// SVG and MathML. XXXXHTMLHandler.prototype = { startDocument: function XH_startDocument() { }, endDocument: function XH_endDocument() { }, startElement: function XH_startElement(uri, localName, qName, attributes) { ++this._depth; // RFC4287 requires XHTML to be wrapped in a div that is *not* part of // the content. This prevents people from screwing up namespaces, but // we need to skip it here. if (this._isAtom && this._depth == 1 && localName == "div") return; // If it's an XHTML element, record it. Otherwise, it's ignored. if (uri == XHTML_NS) { this._buf += "<" + localName; for (var i=0; i < attributes.length; ++i) { // XHTML attributes aren't in a namespace if (attributes.getURI(i) == "") { this._buf += (" " + attributes.getLocalName(i) + "='" + xmlEscape(attributes.getValue(i)) + "'"); } } this._buf += ">"; } }, endElement: function XH_endElement(uri, localName, qName) { --this._depth; // We need to skip outer divs in Atom. See comment in startElement. if (this._isAtom && this._depth == 0 && localName == "div") return; // When we peek too far, go back to the main processor if (this._depth < 0) { this._processor.returnFromXHTMLHandler(trimString(this._buf), uri, localName, qName); return; } // If it's an XHTML element, record it. Otherwise, it's ignored. if (uri == XHTML_NS) { this._buf += "</" + localName + ">"; } }, characters: function XH_characters(data) { this._buf += xmlEscape(data); }, startPrefixMapping: function XH_startPrefixMapping() { }, endPrefixMapping: function XH_endPrefixMapping() { }, processingInstruction: function XH_processingInstruction() { }, }/** * The ExtensionHandler deals with elements we haven't explicitly * added to our transition table in the FeedProcessor. */function ExtensionHandler(processor) { this._buf = ""; this._depth = 0; this._hasChildElements = false; // The FeedProcessor this._processor = processor; // Fields of the outermost extension element. this._localName = null; this._uri = null; this._qName = null; this._attrs = null;}ExtensionHandler.prototype = { startDocument: function EH_startDocument() { }, endDocument: function EH_endDocument() { }, startElement: function EH_startElement(uri, localName, qName, attrs) { ++this._depth; var prefix = gNamespaces[uri] ? gNamespaces[uri] + ":" : ""; var key = prefix + localName; if (this._depth == 1) { this._uri = uri; this._localName = localName; this._qName = qName; this._attrs = attrs; } // if we descend into another element, we won't send text this._hasChildElements = (this._depth > 1); }, endElement: function EH_endElement(uri, localName, qName) { --this._depth; if (this._depth == 0) { var text = this._hasChildElements ? null : trimString(this._buf); this._processor.returnFromExtHandler(this._uri, this._localName, text, this._attrs); } }, characters: function EH_characters(data) { if (!this._hasChildElements) this._buf += data; }, startPrefixMapping: function EH_startPrefixMapping() { }, endPrefixMapping: function EH_endPrefixMapping() { }, processingInstruction: function EH_processingInstruction() { }, };
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -