window.onload = async function(){ let locationHref = new URL(location.href); let node = locationHref.searchParams.get('node') let pubsub = locationHref.searchParams.get('pubsub') // Set button follow let follow = document.querySelector('#follow'); if (follow) { //let feedUrl = location.href.replace(/^https?:/, 'feed:'); let feedUrl = `feed://${location.host}/atom?pubsub=${pubsub}&node=${node}`; follow.href = feedUrl; follow.type = `application/atom+xml`; follow.addEventListener ('click', function() { window.open(feedUrl, "_self"); }); // Fix button subtome document.querySelector('#subtome').href='https://www.subtome.com/#/subscribe?feeds=' + feedUrl; } // Convert ISO8601 To UTC for (let element of document.querySelectorAll( '#articles > ul > li > div > h4.published,' + '#articles > ul > li > div > h4.updated, ' + '#feed > #header > h2#subtitle.date')) { let timeStamp = new Date(element.textContent); element.textContent = timeStamp.toUTCString(); } // Parse Markdown for (let element of document.querySelectorAll('#articles div[type="text"]')) { element.innerHTML = marked.parse(element.textContent); } // NOTE Report this issue to Movim. See node "deltachat" of pubsub "news.movim.eu". for (let element of document.querySelectorAll('#articles div[type="html"]')) { if (!element.children.length) { element.innerHTML = marked.parse(element.textContent); } } /* NOTE The reason for the following code to parse HTML inside an software which already parses HTML, is that some people who influence the so called Gecko HTML Engine product (mostly people from the advertisement industry with whom I shamefully used to work with) have intentions to eliminate standards and technologies such as Syndication (Atom/RDF/RSS), XSLT and many other technologies that actually empower people and their privacy. Recently, some changes were made to the XSLT parser of Gecko which result in noncompliance with the XSLT standard. The XSLT feature that was removed is "disable-output-escaping" which upon the value "yes" the XSLT engine should transform and treat a subject string into HTML, yet the Gecko HTML Engine ignores this XSLT direction. This change was probably made in order to: * Frustrate new XSLT developers; or * Influence new XSLT developers to think that XSLT has a limited set of features and believing of some sort of inability to parse HTML from a retrieved HTML string; and * Consequently cause developers to abstain from using the XSLT technology. Do not use HTML browsers or use Ladybird, Pale Moon or browsers that are powered by KHTML (WebKit) instead of anti-privacy software such as Chromium and Gecko. */ // Parse HTML //if (navigator.userAgent.includes(') Gecko/')) { // for (let element of document.querySelectorAll('#articles div[type="html"]')) { // element.innerHTML = element.textContent; // } //} for (let element of document.querySelectorAll('#articles div[type="html"]')) { if (!element.children.length) { element.innerHTML = element.textContent; } } // Build a journal list if (locationHref.pathname.startsWith('/atom') && pubsub && node && !node.includes('/')) { itemsList = await openJson(pubsub, node) if (itemsList && locationHref.searchParams.get('item')) { let elementDiv = document.createElement('div'); elementDiv.id = 'journal'; let elementH3 = document.createElement('h3'); elementH3.textContent = 'Journal'; elementDiv.appendChild(elementH3); let elementH4 = document.createElement('h4'); elementH4.textContent = node; elementDiv.appendChild(elementH4); let elementUl = document.createElement('ol'); elementDiv.appendChild(elementUl); for (let item of itemsList.reverse()) { let elementLi = document.createElement('li'); let elementA = document.createElement('a'); elementA.textContent = item.title; elementA.href = item.link; elementLi.appendChild(elementA); elementUl.appendChild(elementLi); console.log(elementLi.length) if (elementUl.children.length > 9) {break}; } let elementB = document.createElement('b'); elementB.textContent = 'Actions'; elementDiv.appendChild(elementB); let elementUl2 = document.createElement('ul'); elementDiv.appendChild(elementUl2); links = [ {'text' : 'Subscribe from an XMPP client.', 'href' : `xmpp:${pubsub}?pubsub;action=subscribe;node=${node}`, 'type' : 'x-scheme-handler/xmpp'}, {'text' : 'Subscribe with a News Reader.', 'href' : `feed://${location.host}/atom?pubsub=${pubsub}&node=${node}`, 'type' : 'application/atom+xml'}, {'text' : 'Browse the journal.', 'href' : `atom?pubsub=${pubsub}&node=${node}`, 'type' : 'application/atom+xml'}, {'text' : 'Browse the portal.', 'href' : `opml?pubsub=${pubsub}`, 'type' : 'text/x-opml'} ] for (let link of links) { let elementLi = document.createElement('li'); let elementA = document.createElement('a'); elementA.textContent = link.text; elementA.href = link.href; elementA.type = link.type; elementLi.appendChild(elementA); elementUl2.appendChild(elementLi); } elementDiv.appendChild(elementUl2); // document.querySelector('#feed').appendChild(elementDiv); // This would result in a combination of Title, Article, and Journal document.querySelector('#articles').appendChild(elementDiv); } } // Convert URI xmpp: to URI http: links. for (let xmppLink of document.querySelectorAll( '#articles h3 > a[href^="xmpp:"][id^="rivista-"],' + '#articles h5.related > a[class^="rivista-"],' + '#journal > ol > li > a[href^="xmpp:"]')) { xmppUri = new URL(xmppLink); let parameters = xmppUri.search.split(';'); try { try { let node = parameters.find(parameter => parameter.startsWith('node=')).split('=')[1]; let item = parameters.find(parameter => parameter.startsWith('item=')).split('=')[1]; let pubsub = xmppUri.pathname; xmppLink.href = `atom?pubsub=${pubsub}&node=${node}&item=${item}` } catch { let node = parameters.find(parameter => parameter.startsWith('node=')).split('=')[1]; let pubsub = xmppUri.pathname; xmppLink.href = `atom?pubsub=${pubsub}&node=${node}` } } catch (err) { console.warn(err) } } // Display a selection of suggested software. const selection = { 'akregator' : { 'name' : 'Akregator', 'image' : 'akregator.svg', 'url' : 'https://apps.kde.org/akregator/' }, 'leechcraft' : { 'name' : 'LeechCraft', 'image' : 'leechcraft.png', 'url' : 'https://leechcraft.org/' }, 'liferea' : { 'name' : 'Liferea', 'image' : 'liferea.svg', 'url' : 'https://lzone.de/liferea/' }, 'raven' : { 'name' : 'Raven Reader', 'image' : 'raven.svg', 'url' : 'https://ravenreader.app/' }, 'rssguard' : { 'name' : 'RSS Guard', 'image' : 'rssguard.png', 'url' : 'https://github.com/martinrotter/rssguard' }, 'rssowl' : { 'name' : 'RSSOwl', 'image' : 'rssowl.svg', 'url' : 'http://www.rssowl.org/' }, 'tickr' : { 'name' : 'TICKR', 'image' : 'tickr.png', 'url' : 'https://www.open-tickr.net/' } } let selectionLink = document.querySelector('#selection-link'); selectionLink.addEventListener ('click', function() { let elementDiv = document.createElement('div'); elementDiv.id = 'selection-page'; let elementH1 = document.createElement('h1'); elementH1.textContent = 'Select A News Reader'; elementDiv.appendChild(elementH1); let elementH2 = document.createElement('h2'); elementH2.textContent = 'Install A Feed Reader For Desktop And Mobile'; elementDiv.appendChild(elementH2); const brands = Object.keys(selection); let elementDivSel = document.createElement('div'); elementDivSel.id = 'selection'; for (let i = 0; i < brands.length; i++) { let brand = brands[i]; let elementSpan = document.createElement('span'); let elementA = document.createElement('a'); elementA.href = selection[brand].url; elementA.textContent = selection[brand].name; let elementImg = document.createElement('img'); elementImg.src = 'graphic/' + selection[brand].image; elementSpan.appendChild(elementImg); elementSpan.appendChild(elementA); elementDivSel.appendChild(elementSpan); elementDiv.appendChild(elementDivSel); } let elementP1 = document.createElement('p'); elementP1.textContent = '' + 'This is a selection of desktop, mobile and HTML (sometimes referred to ' + 'as "online") News Readers for you to choose from.'; elementDiv.appendChild(elementP1); let elementP2 = document.createElement('p'); elementP2.textContent = '' + 'This selection includes: Podcast Managers, Torrent ' + 'Clients, Chat Bots, HTML Browsers and Plugins which support ' + 'syndication feeds.'; elementDiv.appendChild(elementP2); let elementSpan = document.createElement('span'); elementSpan.id = 'return'; elementSpan.textContent = 'Continue Reading'; elementSpan.addEventListener ('click', function() { document.querySelector('#selection-page').remove(); }); elementDiv.appendChild(elementSpan); document.body.appendChild(elementDiv); }); } async function openJson(pubsubJid, nodeId) { return fetch(`/data/${pubsubJid}/${nodeId}.json`) .then(response => { if (!response.ok) { throw new Error('HTTP Error: ' + response.status); } return response.json(); }) .then(json => { return json; }) .catch(err => { console.warn(err); }) }