1
0
mirror of https://github.com/aureliendavid/rsspreview.git synced 2025-08-23 03:38:44 +00:00

Merge pull request #10 from glhrmv/master

General code format changes (+ readme update)
This commit is contained in:
A. David 2018-12-19 09:47:45 +01:00 committed by GitHub
commit 1e65cb4c25
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 168 additions and 221 deletions

View File

@ -1,6 +1,9 @@
# rsspreview
Firefox has removed support for RSS in versions 64+. Firefox has removed support for RSS in versions 64+.
This includes the feed preview feature that was quite useful for some people. This includes the feed preview feature that was quite useful for some people.
This extension attempts to recreate it. This extension attempts to recreate it.
Download at: https://addons.mozilla.org/en-US/firefox/addon/rsspreview/

View File

@ -1,22 +1,21 @@
function detectFeed(event) { function detectFeed(event) {
// force application/rss+xml to text/xml so the browser displays it instead of downloading // force application/rss+xml to text/xml so the browser displays it instead of downloading
let isfeed = false;
var isfeed = false; for (let header of event.responseHeaders) {
if (header.name.toLowerCase() == 'content-type') {
for (var header of event.responseHeaders) { header.value = header.value.replace(
if (header.name.toLowerCase() == "content-type") { /application\/(rss|atom)\+xml/,
header.value = header.value.replace(/application\/(rss|atom)\+xml/,'text/xml'); 'text/xml'
);
isfeed = true; isfeed = true;
break; break;
} }
} }
if (isfeed) { if (isfeed) {
for (let i = 0; i < event.responseHeaders.length; i++) {
for (var i = 0; i < event.responseHeaders.length; i++) { if (event.responseHeaders[i].name.toLowerCase() == 'cache-control') {
if (event.responseHeaders[i].name.toLowerCase() == "cache-control") {
event.responseHeaders.splice(i, 1); event.responseHeaders.splice(i, 1);
break; break;
} }
@ -24,20 +23,19 @@ function detectFeed(event) {
// don't cache requests we modified // don't cache requests we modified
// otherwise on reload the content-type won't be modified again // otherwise on reload the content-type won't be modified again
event.responseHeaders.push({ name : "Cache-Control", value : "no-cache, no-store, must-revalidate" }); event.responseHeaders.push({
name: 'Cache-Control',
value: 'no-cache, no-store, must-revalidate',
});
} }
return { return { responseHeaders: event.responseHeaders };
responseHeaders: event.responseHeaders
};
} }
const browser = window.browser || window.chrome; const browser = window.browser || window.chrome;
browser.webRequest.onHeadersReceived.addListener( browser.webRequest.onHeadersReceived.addListener(
detectFeed, detectFeed,
{ urls: ["<all_urls>"], types: ["main_frame"] }, { urls: ['<all_urls>'], types: ['main_frame'] },
["blocking", "responseHeaders"] ['blocking', 'responseHeaders']
) );

View File

@ -1,5 +1,3 @@
html { html {
font: 3mm tahoma,arial,helvetica,sans-serif; font: 3mm tahoma,arial,helvetica,sans-serif;
background-color: rgb(240, 240, 240); background-color: rgb(240, 240, 240);
@ -53,8 +51,6 @@ a[href] img {
margin-bottom: 0; margin-bottom: 0;
} }
#feedTitleContainer { #feedTitleContainer {
margin-inline-start: 0; margin-inline-start: 0;
margin-inline-end: .6em; margin-inline-end: .6em;

View File

@ -5,297 +5,253 @@
* it will do nothing next time. * it will do nothing next time.
*/ */
if (window.hasRun) { if (window.hasRun) {
console.log("already run"); console.log('already run');
return; return;
} }
window.hasRun = true; window.hasRun = true;
var xml_parser = new XMLSerializer(); let xml_parser = new XMLSerializer();
var html_parser = new DOMParser(); let html_parser = new DOMParser();
function xhrdoc(url, type, cb) { function xhrdoc(url, type, cb) {
let xhr = new XMLHttpRequest();
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true); xhr.open('GET', url, true);
xhr.responseType = 'document'; xhr.responseType = 'document';
xhr.overrideMimeType('text/' + type); xhr.overrideMimeType('text/' + type);
xhr.onload = function () { xhr.onload = () => {
if (xhr.readyState === xhr.DONE) { if (xhr.readyState === xhr.DONE) {
if (xhr.status === 200) { if (xhr.status === 200) {
var resp = (type=="xml") ? xhr.responseXML : xhr.response; let resp = type == 'xml' ? xhr.responseXML : xhr.response;
cb(resp); cb(resp);
} }
} }
}; };
xhr.send(null); xhr.send(null);
} }
function applyxsl(xmlin, xsl, node, doc = document) { function applyxsl(xmlin, xsl, node, doc = document) {
var xsltProcessor = new XSLTProcessor(); let xsltProcessor = new XSLTProcessor();
xsltProcessor.importStylesheet(xsl); xsltProcessor.importStylesheet(xsl);
var fragment = xsltProcessor.transformToFragment(xmlin, doc); let fragment = xsltProcessor.transformToFragment(xmlin, doc);
node.appendChild(fragment); node.appendChild(fragment);
} }
function getlang() { function getlang() {
if (navigator.languages && navigator.languages[0]) if (navigator.languages && navigator.languages[0])
return navigator.languages[0]; return navigator.languages[0];
else if (navigator.language) else if (navigator.language) return navigator.language;
return navigator.language; else return null;
else
return null;
} }
function formatsubtitle() { function formatsubtitle() {
try { try {
var feed_desc = document.getElementById("feedSubtitleRaw"); let feed_desc = document.getElementById('feedSubtitleRaw');
var html_desc = html_parser.parseFromString('<h2 id="feedSubtitleText">'+feed_desc.innerText+'</h2>', "text/html"); let html_desc = html_parser.parseFromString(
var xml_desc = xml_parser.serializeToString(html_desc.body.firstChild); '<h2 id="feedSubtitleText">' + feed_desc.innerText + '</h2>',
'text/html'
);
let xml_desc = xml_parser.serializeToString(html_desc.body.firstChild);
feed_desc.insertAdjacentHTML('afterend', xml_desc); feed_desc.insertAdjacentHTML('afterend', xml_desc);
feed_desc.parentNode.removeChild(feed_desc); feed_desc.parentNode.removeChild(feed_desc);
} } catch (e) {
catch (e) {
console.error(e); console.error(e);
console.log(feed_desc.innerText); console.log(feed_desc.innerText);
} }
} }
function formatdescriptions(el = document) { function formatdescriptions(el = document) {
// unescapes descriptions to html then to xml // unescapes descriptions to html then to xml
let tohtml = el.getElementsByClassName('feedRawContent');
var tohtml = el.getElementsByClassName("feedRawContent"); for (let i = 0; i < tohtml.length; i++) {
for (var i = 0; i<tohtml.length; i++) {
// in case of xhtml the content is already parsed // in case of xhtml the content is already parsed
if (tohtml[i].getAttribute("desctype") != "xhtml") { if (tohtml[i].getAttribute('desctype') != 'xhtml') {
try { try {
var html_desc = html_parser.parseFromString('<div class="feedEntryContent">'+tohtml[i].innerText+'</div>', "text/html"); let html_desc = html_parser.parseFromString(
var xml_desc = xml_parser.serializeToString(html_desc.body.firstChild); '<div class="feedEntryContent">' + tohtml[i].innerText + '</div>',
'text/html'
);
let xml_desc = xml_parser.serializeToString(
html_desc.body.firstChild
);
tohtml[i].insertAdjacentHTML('afterend', xml_desc); tohtml[i].insertAdjacentHTML('afterend', xml_desc);
tohtml[i].setAttribute("todel", 1); tohtml[i].setAttribute('todel', 1);
} } catch (e) {
catch (e) {
console.error(e); console.error(e);
console.log(tohtml[i].innerHTML); console.log(tohtml[i].innerHTML);
} }
} }
} }
el.querySelectorAll('.feedRawContent').forEach(function(a){ el.querySelectorAll('.feedRawContent').forEach(a => {
if (a.getAttribute("todel") == "1") { if (a.getAttribute('todel') == '1') {
a.remove(); a.remove();
} else if (a.getAttribute('desctype') == 'xhtml') {
a.classList.add('feedEntryContent');
a.classList.remove('feedRawContent');
} }
else if (a.getAttribute("desctype") == "xhtml") { });
a.classList.add("feedEntryContent");
a.classList.remove("feedRawContent");
} }
})
}
function removeemptyenclosures(el = document) { function removeemptyenclosures(el = document) {
let encs = el.getElementsByClassName('enclosures');
var encs = el.getElementsByClassName("enclosures"); for (let i = 0; i < encs.length; i++)
for (var i = 0; i<encs.length; i++) { if (!encs[i].firstChild) encs[i].style.display = 'none';
if (!encs[i].firstChild)
encs[i].style.display = "none";
}
} }
function formatfilenames(el = document) { function formatfilenames(el = document) {
let encfn = el.getElementsByClassName('enclosureFilename');
for (let i = 0; i < encfn.length; i++) {
let url = new URL(encfn[i].innerText);
var encfn = el.getElementsByClassName("enclosureFilename");
for (var i = 0; i<encfn.length; i++) {
var url = new URL(encfn[i].innerText);
if (url) { if (url) {
var fn = url.pathname.split("/").pop(); let fn = url.pathname.split('/').pop();
if (fn != "") {
encfn[i].innerText = fn;
}
}
if (fn != '') encfn[i].innerText = fn;
}
} }
} }
function formatfilesizes(el = document) { function formatfilesizes(el = document) {
function humanfilesize(size) { function humanfilesize(size) {
var i = 0; let i = 0;
if (size && size != "" && size > 0)
if (size && size != '' && size > 0)
i = Math.floor(Math.log(size) / Math.log(1024)); i = Math.floor(Math.log(size) / Math.log(1024));
return ( size / Math.pow(1024, i) ).toFixed(2) * 1 + ' ' + ['B', 'kB', 'MB', 'GB', 'TB'][i];
};
var encsz = el.getElementsByClassName("enclosureSize"); return (
for (var i = 0; i<encsz.length; i++) { (size / Math.pow(1024, i)).toFixed(2) * 1 +
var hsize = humanfilesize(encsz[i].innerText); ' ' +
if (hsize) { ['B', 'kB', 'MB', 'GB', 'TB'][i]
encsz[i].innerText = hsize; );
} }
} let encsz = el.getElementsByClassName('enclosureSize');
} for (let i = 0; i < encsz.length; i++) {
let hsize = humanfilesize(encsz[i].innerText);
if (hsize) encsz[i].innerText = hsize;
}
}
function formattitles(el = document) { function formattitles(el = document) {
let et = el.getElementsByClassName('entrytitle');
var et = el.getElementsByClassName("entrytitle"); for (let i = 0; i < et.length; i++) {
for (var i = 0; i<et.length; i++) {
//basically removes html content if there is some //basically removes html content if there is some
//only do it if there's a tag to avoid doing it when text titles cointain a '&' //only do it if there's a tag to avoid doing it when text titles cointain a '&'
//(which can be caught but still displays an error in console, which is annoying) //(which can be caught but still displays an error in console, which is annoying)
if (et[i].innerText.indexOf('<') >= 0) { if (et[i].innerText.indexOf('<') >= 0) {
let tmp = document.createElement('span');
var tmp = document.createElement("span");
try { try {
tmp.innerHTML = et[i].innerText; tmp.innerHTML = et[i].innerText;
et[i].innerText = tmp.textContent; et[i].innerText = tmp.textContent;
} } catch (e) {
catch (e) {
console.error(e); console.error(e);
console.log(et[i].innerText); console.log(et[i].innerText);
} }
} }
} }
} }
function formatdates(el = document) { function formatdates(el = document) {
let lang = getlang();
if (!lang) return;
var lang = getlang(); let opts = {
if (!lang) weekday: 'long',
return; year: 'numeric',
month: 'long',
day: 'numeric',
};
var opts = { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' }; let ed = el.getElementsByClassName('lastUpdated');
for (let i = 0; i < ed.length; i++) {
let d = new Date(ed[i].innerText);
if (isNaN(d)) continue;
var ed = el.getElementsByClassName("lastUpdated"); let dstr =
for (var i = 0; i<ed.length; i++) { d.toLocaleDateString(lang, opts) + ' ' + d.toLocaleTimeString(lang);
var d = new Date(ed[i].innerText);
if (isNaN(d))
continue;
var dstr = d.toLocaleDateString(lang, opts) + ' ' + d.toLocaleTimeString(lang);
ed[i].innerText = dstr; ed[i].innerText = dstr;
} }
} }
function extensionimages(el = document) { function extensionimages(el = document) {
let extimgs = el.getElementsByClassName('extImg');
var extimgs = el.getElementsByClassName("extImg"); for (let i = 0; i < extimgs.length; i++)
for (var i = 0; i<extimgs.length; i++) { extimgs[i].src = chrome.extension.getURL(
extimgs[i].src = chrome.extension.getURL(extimgs[i].attributes['data-src'].nodeValue); extimgs[i].attributes['data-src'].nodeValue
} );
} }
function makepreviewhtml() { function makepreviewhtml() {
let doc = document.implementation.createHTMLDocument('');
var doc = document.implementation.createHTMLDocument(""); let feedBody = doc.createElement('div');
feedBody.id = 'feedBody';
var feedBody = doc.createElement("div");
feedBody.id = "feedBody";
doc.body.appendChild(feedBody); doc.body.appendChild(feedBody);
var css = doc.createElement('link'); let css = doc.createElement('link');
css.setAttribute('rel', 'stylesheet'); css.setAttribute('rel', 'stylesheet');
css.setAttribute('href', chrome.extension.getURL("preview.css")); css.setAttribute('href', chrome.extension.getURL('preview.css'));
doc.head.appendChild(css); doc.head.appendChild(css);
return doc; return doc;
} }
function detect() { function detect() {
let rootNode = document.getRootNode().documentElement;
var rootNode = document.getRootNode().documentElement;
// for chrome // for chrome
var d = document.getElementById("webkit-xml-viewer-source-xml"); let d = document.getElementById('webkit-xml-viewer-source-xml');
if (d && d.firstChild) if (d && d.firstChild) rootNode = d.firstChild;
rootNode = d.firstChild;
const rootName = rootNode.nodeName.toLowerCase(); const rootName = rootNode.nodeName.toLowerCase();
let isRSS1 = false;
var isRSS1 = false; if (rootName == 'rdf' || rootName == 'rdf:rdf')
if (rootName == "rdf" || rootName == "rdf:rdf") { if (rootNode.attributes['xmlns'])
if (rootNode.attributes['xmlns']) { isRSS1 = rootNode.attributes['xmlns'].nodeValue.search('rss') > 0;
isRSS1 = (rootNode.attributes['xmlns'].nodeValue.search('rss') > 0)
}
}
if ( rootName == "rss" || rootName == "channel" // rss2
|| rootName == "feed" // atom
|| isRSS1 ) {
if (
rootName == 'rss' ||
rootName == 'channel' || // rss2
rootName == 'feed' || // atom
isRSS1
)
return rootNode; return rootNode;
}
return null; return null;
} }
function main(feedNode) { function main(feedNode) {
let feed_url = window.location.href;
let preview = makepreviewhtml();
var feed_url = window.location.href; xhrdoc(chrome.extension.getURL('rss.xsl'), 'xml', xsl_xml => {
applyxsl(feedNode, xsl_xml, preview.getElementById('feedBody'), preview);
var preview = makepreviewhtml();
xhrdoc(chrome.extension.getURL("rss.xsl"), "xml", function(xsl_xml) {
applyxsl(feedNode, xsl_xml, preview.getElementById("feedBody"), preview);
// replace the content with the preview document // replace the content with the preview document
document.replaceChild(document.importNode(preview.documentElement, true), document.documentElement); document.replaceChild(
document.importNode(preview.documentElement, true),
document.documentElement
);
var t0 = performance.now(); let t0 = performance.now();
formatsubtitle(); formatsubtitle();
@ -307,20 +263,14 @@
formatdates(); formatdates();
extensionimages(); extensionimages();
var t1 = performance.now(); let t1 = performance.now();
//console.log("exec in: " + (t1 - t0) + "ms"); //console.log("exec in: " + (t1 - t0) + "ms");
document.title = document.getElementById("feedTitleText").innerText; document.title = document.getElementById('feedTitleText').innerText;
}); });
} }
var feedRoot = detect(); let feedRoot = detect();
if (feedRoot)
main(feedRoot);
if (feedRoot) main(feedRoot);
})(); })();