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

initial commit

This commit is contained in:
Aurelien David 2018-10-25 22:03:08 +02:00
commit cdf84b50ee
9 changed files with 426 additions and 0 deletions

23
background.js Normal file
View File

@ -0,0 +1,23 @@
function detectFeed(event) {
// force application/rss+xml to text/xml so the browser displays it instead of downloading
for (var header of event.responseHeaders) {
if (header.name.toLowerCase() == "content-type") {
header.value = header.value.replace(/application\/(rss|atom)\+xml/,'text/xml');
break;
}
}
return {
responseHeaders: event.responseHeaders
};
}
browser.webRequest.onHeadersReceived.addListener(
detectFeed,
{ urls: ["<all_urls>"], types: ["main_frame"] },
["blocking", "responseHeaders"]
)

BIN
icons/file.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

BIN
icons/rss-48.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

29
manifest.json Normal file
View File

@ -0,0 +1,29 @@
{
"manifest_version": 2,
"name": "RSSPreview",
"version": "1.0",
"description": "Preview RSS feeds in browser",
"icons": {
"48": "icons/rss-48.png"
},
"background": {
"scripts": ["background.js"]
},
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["rsspreview.js"]
}
],
"web_accessible_resources": ["preview.html", "preview.js", "preview.css", "rss.xsl", "icons/file.png"],
"permissions": ["<all_urls>", "webRequest", "webRequestBlocking"]
}

116
preview.css Normal file
View File

@ -0,0 +1,116 @@
html {
font: 3mm tahoma,arial,helvetica,sans-serif;
background-color: rgb(240, 240, 240);
}
body {
margin: 0;
padding: 0 3em;
font: message-box;
}
h1 {
font-size: 160%;
border-bottom: 2px solid ThreeDLightShadow;
margin: 0 0 .2em 0;
}
h1 a {
color: inherit;
text-decoration: none;
}
h1 a:hover {
text-decoration: underline;
}
h2 {
color: GrayText;
font-size: 110%;
font-weight: normal;
margin: 0 0 .6em 0;
}
a[href] img {
border: none;
}
#feedBody {
border: 1px solid THreeDShadow;
padding: 3em;
padding-inline-start: 30px;
margin: 2em auto;
background-color: white;
}
#feedTitleLink {
float: right;
margin-inline-start: .6em;
margin-inline-end: 0;
margin-top: 0;
margin-bottom: 0;
}
#feedTitleContainer {
margin-inline-start: 0;
margin-inline-end: .6em;
margin-top: 0;
margin-bottom: 0;
}
#feedTitleImage {
margin-inline-start: .6em;
margin-inline-end: 0;
margin-top: 0;
margin-bottom: 0;
max-width: 300px;
max-height: 150px;
}
.feedEntryContent {
font-size: 110%;
}
.link {
color: #0000FF;
text-decoration: underline;
cursor: pointer;
}
.link:hover:active {
color: #FF0000;
}
.lastUpdated {
font-size: 85%;
font-weight: normal;
}
.type-icon {
vertical-align: bottom;
height: 16px;
width: 16px;
}
.enclosures {
border: 1px solid THreeDShadow;
padding: 1em;
margin: 1em auto;
background-color: rgb(240, 240, 240);
}
.enclosure {
vertical-align: middle;
margin-left: 2px;
}
.enclosureIcon {
vertical-align: bottom;
height: 16px;
width: 16px;
margin-right: 3px;
}

17
preview.html Normal file
View File

@ -0,0 +1,17 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="preview.css">
<link rel="shortcut icon" type="image/png" href="icons/rss-48.png">
<script src="preview.js" ></script>
</head>
<body>
<div id="feedBody"></div>
</body>
</html>

136
preview.js Normal file
View File

@ -0,0 +1,136 @@
document.addEventListener('DOMContentLoaded', function () {
main();
});
function getxml(url) {
var xhttp = new XMLHttpRequest();
xhttp.open("GET", url, false);
xhttp.send(null);
return xhttp.responseXML;
}
function xhrxml(url, cb) {
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.responseType = 'document';
xhr.overrideMimeType('text/xml');
xhr.onload = function () {
if (xhr.readyState === xhr.DONE) {
if (xhr.status === 200) {
cb(xhr.responseXML);
}
}
};
xhr.send(null);
}
function applyxsl(xmlin, xsl, node) {
var xsltProcessor = new XSLTProcessor();
xsltProcessor.importStylesheet(xsl);
var fragment = xsltProcessor.transformToFragment(xmlin, document);
node.appendChild(fragment);
}
function formatdescriptions() {
// unescapes descriptions to html
var tohtml = document.getElementsByClassName("feedEntryContent");
for (var i = 0; i<tohtml.length; i++) {
tohtml[i].innerHTML = tohtml[i].innerText;
}
var feed_desc = document.getElementById("feedSubtitleText");
feed_desc.innerHTML = feed_desc.innerText;
}
function removeemptyenclosures() {
var encs = document.getElementsByClassName("enclosures");
for (var i = 0; i<encs.length; i++) {
if (!encs[i].firstChild)
encs[i].style.display = "none";
}
}
function formatfilenames() {
var encfn = document.getElementsByClassName("enclosureFilename");
for (var i = 0; i<encfn.length; i++) {
var url = new URL(encfn[i].innerText);
if (url) {
var fn = url.pathname.split("/").pop();
if (fn != "") {
encfn[i].innerText = fn;
}
}
}
}
function formatfilesizes() {
function humanfilesize(size) {
console.log(size);
var i = 0;
if (size && size != "" && size > 0)
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 = document.getElementsByClassName("enclosureSize");
for (var i = 0; i<encsz.length; i++) {
var hsize = humanfilesize(encsz[i].innerText);
if (hsize) {
encsz[i].innerText = hsize;
}
}
}
function main() {
var query_string = location.search.substring(1).split("&");
var feed_url = decodeURIComponent(query_string[0]);
xhrxml(feed_url, function(feed_xml) {
xhrxml(chrome.extension.getURL("rss.xsl"), function(xsl_xml) {
applyxsl(feed_xml, xsl_xml, document.getElementById("feedBody"));
removeemptyenclosures();
formatdescriptions();
formatfilenames();
formatfilesizes();
document.title = "RSSPreview: " + document.getElementById("feedTitleText").innerText;
});
});
}

77
rss.xsl Normal file
View File

@ -0,0 +1,77 @@
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:atom="http://www.w3.org/2005/Atom" exclude-result-prefixes="atom" >
<xsl:output method="html" indent="yes" encoding="utf-8" />
<xsl:template match="channel | atom:feed">
<div id="feedTitle">
<a id="feedTitleLink">
<img id="feedTitleImage" src="{image/url | atom:logo}" />
</a>
<div id="feedTitleContainer">
<h1 id="feedTitleText" >
<a href="{link | atom:link[@rel='alternate']/@href}" target="_blank">
<xsl:value-of select="title | atom:title" />
</a>
</h1>
<h2 id="feedSubtitleText" ><xsl:value-of select="description | atom:subtitle" /></h2>
<!--div class="lastUpdated">Last updated: <xsl:value-of select="lastBuildDate | atom:updated" /></div-->
</div>
</div>
<div id="feedContent">
<xsl:for-each select="item | atom:entry">
<div class="entry">
<h3>
<xsl:choose>
<xsl:when test="link | atom:link[@rel='alternate']/@href">
<a href="{link | atom:link[@rel='alternate']/@href}" target="_blank">
<span><xsl:value-of select="title | atom:title" /></span>
</a>
</xsl:when>
<xsl:otherwise>
<span><xsl:value-of select="title | atom:title" /></span>
</xsl:otherwise>
</xsl:choose>
<div class="lastUpdated"><xsl:value-of select="pubDate | atom:updated" /></div>
</h3>
<div class="feedEntryContent">
<xsl:value-of select="description | atom:summary" disable-output-escaping="yes" />
</div>
<div class="enclosures">
<xsl:for-each select="enclosure | atom:link[@rel='enclosure']">
<div class="enclosure">
<img src="icons/file.png" class="enclosureIcon" />
<a href="{@url | @href}" target="_blank" class="enclosureFilename"><xsl:value-of select="@url | @href" /></a>
(<xsl:value-of select="@type" />, <span class="enclosureSize"><xsl:value-of select="@length" /></span>)
</div>
</xsl:for-each>
</div>
</div>
<div style="clear: both;"></div>
</xsl:for-each>
</div>
</xsl:template>
<xsl:template match="/">
<xsl:apply-templates select="//channel | //atom:feed" />
</xsl:template>
</xsl:stylesheet>

28
rsspreview.js Normal file
View File

@ -0,0 +1,28 @@
(function() {
/**
* Check and set a global guard variable.
* If this content script is injected into the same page again,
* it will do nothing next time.
*/
if (window.hasRun) {
console.log("already run");
return;
}
window.hasRun = true;
const rootName = document.getRootNode().documentElement.nodeName;
if (rootName == "rss" || rootName == "channel" || rootName == "feed") {
var feed_url = window.location.href;
var url = "preview.html?" + encodeURIComponent(feed_url);
url = chrome.extension.getURL(url);
// redirect to preview page with feed url as query string
window.location.replace(url);
}
})();