sjehuda Author

For some reason, this implementation doesn't works with file://


var
  xmlHTTPRequest, xmlFile,
  mimeType, isFeed;

const mimeArray = [
  'application/atom+xml',
  'application/stream+json',
  'application/rss+xml',
  'application/rdf+xml'
];
/*
httpGetAsync(
  document.documentURI,
  checkMediaType
);

xmlFile = httpGetAsync(document.documentURI, checkMediaType)

if (xmlFile) {
  renderFeed(
    xmlFile
  );
}

function httpGetAsync(uri, callback) {
  var xmlHTTPRequest = new XMLHttpRequest();
  xmlHTTPRequest.onreadystatechange = function() { 
    if (xmlHTTPRequest.readyState === 4) {
      xmlFile = xmlHTTPRequest.responseText;
      //console.log('xmlHTTPRequest.responseText')
      //console.log(xmlHTTPRequest.responseText)
      if (document.URL.startsWith('file:')) {
        mimeType = document.contentType;
      } else {
          mimeType =
            xmlHTTPRequest
            .getResponseHeader('Content-Type');
        }
      // FIXME
      // Not a good practice
      // Passing a file via a function
      // that returns true or false.
      // NOTE
      // Strangely enough, xmlFile
      // passes via the function even
      // without an explicit mention.
      callback(mimeType);
    };
  }
  xmlHTTPRequest.open("GET", uri, true); // true for asynchronous 
  xmlHTTPRequest.send(null);
}

fetch(document.documentURI)
  .then(checkStatus)
  .then(checkMediaType)

fetch(document.documentURI)
  .then((response) => {
     const contentType = response.headers.get('content-type');
     if (checkMediaType(contentType)) {
       return response.text();
     }
  })
  .then((data) => {
      renderFeed(data)
  })

fetch(document.documentURI)
  .then((response) => {
     const contentType = response.headers.get('content-type');
     if (!checkMediaType(contentType)) {
       throw new TypeError("Page does not seem to be a feed!");
     }
     return response.arrayBuffer();
  })
  .then((data) => {
    let decoder = new TextDecoder(document.characterSet);
    let text = decoder.decode(data);
    renderFeed(text)
  })
*/

let myPromise = new Promise(function(myResolve, myReject) {
  let request = new XMLHttpRequest();
  //request.onprogress = function(){pageLoader()};
  request.open('GET', document.documentURI);
  request.onload = function() {
    if (request.status == 200) {
      myResolve(request);
    } else {
      myReject("File not Found");
    }
  };
  request.send();
});

myPromise.then(
  function(request) {
      if (document.URL.startsWith('file:')) {
        mimeType = document.contentType;
      } else {
          mimeType =
            request
            .getResponseHeader('Content-Type');
        }
      if (checkMediaType(mimeType)) {
        request.onprogress = pageLoader(); // in case we have a larger xml file
        //setTimeout(function(){renderFeed(request.response)}, 1500); // timeout for testing
        renderFeed(request.response)
      }
  },
  function(error) {checkMediaType(error);}
);

function pageLoader() {
  // https://ao.foss.wtf/questions/6464592/how-to-align-entire-html-body-to-the-center
  const loadPage = '<html><head><link type="image/svg+xml" rel="shortcut icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>๐Ÿ“ฐ</text></svg>"><title>Newspaper</title><style>html,body{height:100%;}html{display:table;margin:auto;}body{display:table-cell;vertical-align:middle;}body{background-color:#f1f1f1;font-family:"Helvetica Neue", Helvetica,Arial,sans-serif;cursor:default;user-select:none;max-height:100%;max-width:100%;}div{font-size:2.3em;font-weight:bold;}#icon-tc{font-size:2em;position:relative;text-align:center;}#loader{animation:flickerAnimation 1s infinite;}.centerm{display:block;margin-left:auto;margin-right:auto;width:100%;}.center{padding:1em 0px 1em 0px;text-align:center;}@keyframes flickerAnimation{0%{opacity:1;}50%{opacity:0;}100%{opacity:1;}}.flip{display:inline-block;transform:scaleX(-1);-moz-transform:scaleX(-1);-o-transform:scaleX(-1);-webkit-transform:scaleX(-1);filter:FlipH;-ms-filter:FlipH;}</style></head><body><div id="icon-tc" class="centerm"><?xml version="1.0"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="128px" height="128px" id="RSSicon" viewBox="0 0 256 256"><defs><linearGradient x1="0.085" y1="0.085" x2="0.915" y2="0.915" id="RSSg"><stop  offset="0.0" stop-color="#E3702D"/><stop  offset="0.1071" stop-color="#EA7D31"/><stop  offset="0.3503" stop-color="#F69537"/><stop  offset="0.5" stop-color="#FB9E3A"/><stop  offset="0.7016" stop-color="#EA7C31"/><stop  offset="0.8866" stop-color="#DE642B"/><stop  offset="1.0" stop-color="#D95B29"/></linearGradient></defs><rect width="256" height="256" rx="55" ry="55" x="0"  y="0"  fill="#CC5D15"/><rect width="246" height="246" rx="50" ry="50" x="5"  y="5"  fill="#F49C52"/><rect width="236" height="236" rx="47" ry="47" x="10" y="10" fill="url(#RSSg)"/><circle cx="68" cy="189" r="24" fill="#FFF"/><path d="M160 213h-34a82 82 0 0 0 -82 -82v-34a116 116 0 0 1 116 116z" fill="#FFF"/><path d="M184 213A140 140 0 0 0 44 73 V 38a175 175 0 0 1 175 175z" fill="#FFF"/></svg></div><div id="message" class="center"></div><div id="loader" class="center">Loading</div></body></html>'
  const domParser = new DOMParser();
  const newDocument = domParser.parseFromString(loadPage, 'text/html');
  insertDocument = document.importNode(newDocument.documentElement, true);
  removeDocument = document.documentElement;
  document.replaceChild(insertDocument, removeDocument);
}

// Check if is of type syndication feed
function checkMediaType(mimeType) {
  //console.log(mimeType);
  
  // TODO Reorder if statements below
  if (!mimeType) {
    mimeType = 'text/plain';
  }

  for (let i = 0; i < mimeArray.length; i++) {
    if (mimeType.includes(mimeArray[i])
       ) {
      return true;
    }
    // Check if is application/xml or text/xml
    else
    if (mimeType.includes('/xml') || mimeType.includes('/html')) {
      // We do not use forEach, because we need to break out once at least on tag is found
      // List array by most commonly used formats and tags
      const tagArray = ['feed', 'atom:link', 'rss', 'rdf:RDF'];
      for (let i = 0; i < tagArray.length; i++) {
        var query = document.getElementsByTagName(tagArray[i]);
        if (query.length) {
          return true;
        }
      }
    }
    // Check if is plain text (XPath only is usable)
    else
    if (mimeType.match('text/plain')) {
      const tagArray = ['<feed', '<atom:link', '<rss', '<rdf:RDF'];
      for (let i = 0; i < tagArray.length; i++) {
        query = ['//*[contains(text(), "' + tagArray[i] + '")]'];
        query = queryByXPath(query);
        if (query.length) {
          return true;
        }
      }
    }
  }
}

// Begin processing
function renderFeed(xmlFile) {

  var
    domParser,
    xmlDocument, xsltProcessor,
    newDocument, head, style, isRTL,
    stylesheet_ltr, stylesheet_rtl,
    insertDocument, removeDocument;
    

  // FIXME
  // Make this function to work
  // function domParser(xmlDoc, xmlType) {
  //   domParser = new DOMParser();
  //   domParser.parseFromString(xmlDoc, xmlType);
  // }

  xmlFile =
    xmlFile
    .trim();

  domParser = new DOMParser();

  xmlDocument =
    domParser
    .parseFromString(
      xmlFile,
      'text/xml'
    );

  // NOTE
  // Consider migration to SaxonJS XSLT 3.0 Processor
  xsltProcessor = new XSLTProcessor();

  xslFile = '<?xml version="1.0" encoding="UTF-8"?><xsl:stylesheet xmlns="http://purl.org/rss/1.0/" xmlns:admin="http://webns.net/mvcb/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:atom10="http://www.w3.org/2005/Atom" xmlns:c="http://s.opencalais.com/1/pred/" xmlns:cc="http://web.resource.org/cc/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dct="http://purl.org/dc/terms/" xmlns:dbo="http://dbpedia.org/ontology/" xmlns:dbp="http://dbpedia.org/property/" xmlns:enc="http://purl.oclc.org/net/rss_2.0/enc#" xmlns:fh="http://purl.org/syndication/history/1.0" xmlns:foaf="http://xmlns.com/foaf/0.1/" xmlns:foo="http://purl.org/rss/1.0/" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:georss="http://www.georss.org/georss" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:media="http://search.yahoo.com/mrss/" xmlns:owl="http://www.w3.org/2002/07/owl#" xmlns:prov="http://www.w3.org/ns/prov#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#" xmlns:sioc="http://rdfs.org/sioc/ns#" xmlns:sioct="http://rdfs.org/sioc/types#" xmlns:skos="http://www.w3.org/2004/02/skos/core#" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:syn="http://purl.org/rss/1.0/modules/syndication/" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"><xsl:output method="html" indent="yes" omit-xml-decleration="no"/><xsl:output media-type="application/atom+xml"/><xsl:template match="/atom:feed"><xsl:variable name="rtl" select="@xml:lang[ contains(self::node(),&quot;ar&quot;) or contains(self::node(),&quot;fa&quot;) or contains(self::node(),&quot;he&quot;) or contains(self::node(),&quot;ji&quot;) or contains(self::node(),&quot;ku&quot;) or contains(self::node(),&quot;ur&quot;) or contains(self::node(),&quot;yi&quot;)]"/><html><head><xsl:call-template name="metadata"><xsl:with-param name="name" select="&quot;description&quot;"/><xsl:with-param name="content" select="atom:subtitle"/></xsl:call-template><xsl:call-template name="metadata"><xsl:with-param name="name" select="&quot;generator&quot;"/><xsl:with-param name="content" select="&quot;syndication4humans https://sjehuda.github.io/&quot;"/></xsl:call-template><xsl:call-template name="metadata"><xsl:with-param name="name" select="&quot;mimetype&quot;"/><xsl:with-param name="content" select="&quot;application/atom+xml&quot;"/></xsl:call-template><title><xsl:choose><xsl:when test="atom:title and not(atom:title=&quot;&quot;)"><xsl:value-of select="atom:title"/></xsl:when><xsl:otherwise>Streamburner News Reader</xsl:otherwise></xsl:choose></title><xsl:if test="$rtl"><meta name="semitic" content="true"/></xsl:if></head><body><div id="feed"><header><div id="title"><xsl:choose><xsl:when test="atom:title and not(atom:title=&quot;&quot;)"><xsl:attribute name="title"><xsl:value-of select="atom:title"/></xsl:attribute><xsl:value-of select="atom:title"/></xsl:when><xsl:otherwise><div class="empty"/></xsl:otherwise></xsl:choose></div><div id="subtitle"><xsl:attribute name="title"><xsl:value-of select="atom:subtitle"/></xsl:attribute><xsl:value-of select="atom:subtitle"/></div></header><section id="links"><a title="Click to get the latest updates and news" onclick="location.href = &quot;feed:&quot; + location.href"></a><a title="Subscribe via SubToMe"><xsl:attribute name="href">https://www.subtome.com/#/subscribe?feeds=<xsl:value-of select="atom:link[@rel=&quot;self&quot;]/@href"/></xsl:attribute><xsl:attribute name="onclick">(function(btn){var z=document.createElement(&quot;script&quot;);document.subtomeBtn=btn;z.src=&quot;https://www.subtome.com/load.js&quot;;document.body.appendChild(z);})(this);return false;</xsl:attribute></a><a title="Learn about syndication feed" onclick="document.getElementById(&quot;aboutfeed&quot;).classList.toggle(&quot;show&quot;);" class="popup"><span class="popuptext" id="aboutfeed"/></a><a href="https://wikiless.org/wiki/Template:Aggregators" title="Get a feed reader for desktop and mobile"/><a href="https://wikiless.org/wiki/RSS" title="Learn the benefits of using feeds for personal and corporates"/></section><xsl:choose><xsl:when test="atom:entry"><div id="toc"><xsl:for-each select="atom:entry[not(position() &gt;20)]"><xsl:if test="atom:title"><xsl:element name="a"><xsl:attribute name="href"><xsl:text>#newspaper-oujs-</xsl:text><xsl:value-of select="position()"/></xsl:attribute><xsl:value-of select="atom:title"/></xsl:element></xsl:if></xsl:for-each></div></xsl:when></xsl:choose><section id="articles"><xsl:choose><xsl:when test="atom:entry"><xsl:for-each select="atom:entry[not(position() &gt;20)]"><div class="entry"><xsl:if test="atom:title"><div class="title"><xsl:element name="a"><xsl:attribute name="href"><xsl:choose><xsl:when test="atom:link[contains(@rel,&quot;alternate&quot;)]"><xsl:value-of select="atom:link[contains(@rel,&quot;alternate&quot;)]/@href"/></xsl:when><xsl:otherwise><xsl:value-of select="atom:link/@href"/></xsl:otherwise></xsl:choose></xsl:attribute><xsl:attribute name="title"><xsl:value-of select="atom:title"/></xsl:attribute><xsl:attribute name="id"><xsl:text>newspaper-oujs-</xsl:text><xsl:value-of select="position()"/></xsl:attribute><xsl:value-of select="atom:title"/></xsl:element></div></xsl:if><xsl:choose><xsl:when test="geo:lat and geo:long"><xsl:variable name="lat" select="geo:lat"/><xsl:variable name="lng" select="geo:long"/><span class="geolocation"><a href="geo:{$lat},{$lng}">๐Ÿ“</a></span></xsl:when><xsl:when test="geo:Point"><xsl:variable name="lat" select="geo:Point/geo:lat"/><xsl:variable name="lng" select="geo:Point/geo:long"/><span class="geolocation"><a href="geo:{$lat},{$lng}">๐Ÿ“</a></span></xsl:when><xsl:when test="georss:point"><xsl:variable name="lat" select="substring-before(georss:point, &quot; &quot;)"/><xsl:variable name="lng" select="substring-after(georss:point, &quot; &quot;)"/><xsl:variable name="name" select="georss:featurename"/><span class="geolocation"><a href="geo:{$lat},{$lng}" title="{$name}">๐Ÿ“</a></span></xsl:when></xsl:choose><xsl:choose><xsl:when test="atom:updated"><div class="updated"><xsl:value-of select="atom:updated"/></div></xsl:when><xsl:when test="atom:published"><div class="published"><xsl:value-of select="atom:published"/></div></xsl:when><xsl:otherwise><div class="warning atom1 published"/></xsl:otherwise></xsl:choose><xsl:if test="atom:content or atom:summary"><div class="content"><xsl:choose><xsl:when test="atom:summary[contains(@type,&quot;text&quot;)]"><xsl:attribute name="type"><xsl:value-of select="atom:summary/@type"/></xsl:attribute><xsl:value-of select="atom:summary"/></xsl:when><xsl:when test="atom:summary[contains(@type,&quot;base64&quot;)]"></xsl:when><xsl:when test="atom:content[contains(@type,&quot;text&quot;)]"><xsl:attribute name="type"><xsl:value-of select="atom:content/@type"/></xsl:attribute><xsl:value-of select="atom:content"/></xsl:when><xsl:when test="atom:content[contains(@type,&quot;base64&quot;)]"></xsl:when><xsl:otherwise><xsl:choose><xsl:when test="atom:summary and not(atom:summary=&quot;&quot;)"><xsl:value-of select="atom:summary" disable-output-escaping="yes"/></xsl:when><xsl:otherwise><xsl:value-of select="atom:content" disable-output-escaping="yes"/></xsl:otherwise></xsl:choose></xsl:otherwise></xsl:choose></div></xsl:if><xsl:if test="atom:link[contains(@rel,&quot;enclosure&quot;)]"><div class="enclosure" title="Right-click and Save link asโ€ฆ"><xsl:for-each select="atom:link[contains(@rel,&quot;enclosure&quot;)]"><xsl:element name="span"><xsl:attribute name="icon"><xsl:value-of select="substring-before(@type,&quot;/&quot;)"/></xsl:attribute></xsl:element><xsl:element name="a"><xsl:attribute name="href"><xsl:value-of select="@href"/></xsl:attribute><xsl:attribute name="download"/><xsl:call-template name="extract-filename"><xsl:with-param name="url" select="@href"/></xsl:call-template></xsl:element><xsl:element name="span"><xsl:attribute name="class"><xsl:value-of select="substring-before(@type,&quot;/&quot;)"/></xsl:attribute></xsl:element><xsl:if test="@length &gt; 0"><xsl:call-template name="transform-filesize"><xsl:with-param name="length" select="@length"/></xsl:call-template></xsl:if><xsl:element name="br"/></xsl:for-each><xsl:for-each select="media:content"><xsl:element name="span"><xsl:attribute name="icon"><xsl:value-of select="@medium"/></xsl:attribute></xsl:element><xsl:element name="a"><xsl:attribute name="href"><xsl:value-of select="@url"/></xsl:attribute><xsl:attribute name="download"/><xsl:call-template name="extract-filename"><xsl:with-param name="url" select="@url"/></xsl:call-template></xsl:element><xsl:element name="span"><xsl:attribute name="class"><xsl:value-of select="@medium"/></xsl:attribute></xsl:element><xsl:if test="@fileSize &gt; 0"><xsl:call-template name="transform-filesize"><xsl:with-param name="length" select="@fileSize"/></xsl:call-template></xsl:if><xsl:element name="br"/></xsl:for-each></div></xsl:if></div><xsl:if test="not(atom:id)"><div class="warning atom1 id"/></xsl:if></xsl:for-each></xsl:when><xsl:otherwise><div class="notice no-entry"/></xsl:otherwise></xsl:choose></section></div></body></html></xsl:template><xsl:output media-type="application/rdf+xml"/><xsl:template match="/rdf:RDF"><xsl:variable name="rtl" select="channel/language[ contains(text(),&quot;ar&quot;) or contains(text(),&quot;fa&quot;) or contains(text(),&quot;he&quot;) or contains(text(),&quot;ji&quot;) or contains(text(),&quot;ku&quot;) or contains(text(),&quot;ur&quot;) or contains(text(),&quot;yi&quot;)]"/><html><head><xsl:call-template name="metadata"><xsl:with-param name="name" select="&quot;description&quot;"/><xsl:with-param name="content" select="foo:channel/foo:description"/></xsl:call-template><xsl:call-template name="metadata"><xsl:with-param name="name" select="&quot;generator&quot;"/><xsl:with-param name="content" select="&quot;syndication4humans https://sjehuda.github.io/&quot;"/></xsl:call-template><xsl:call-template name="metadata"><xsl:with-param name="name" select="&quot;mimetype&quot;"/><xsl:with-param name="content" select="&quot;application/rdf+xml&quot;"/></xsl:call-template><title><xsl:choose><xsl:when test="foo:channel/foo:title and not(foo:channel/foo:title=&quot;&quot;)"><xsl:value-of select="foo:channel/foo:title"/></xsl:when><xsl:otherwise>Streamburner News Reader</xsl:otherwise></xsl:choose></title><xsl:if test="$rtl"><meta name="semitic" content="true"/></xsl:if></head><body><div id="feed"><header><div id="title"><xsl:choose><xsl:when test="foo:channel/foo:title and not(foo:channel/foo:title=&quot;&quot;)"><xsl:attribute name="title"><xsl:value-of select="foo:channel/foo:title"/></xsl:attribute><xsl:value-of select="foo:channel/foo:title"/></xsl:when><xsl:otherwise><div class="empty"/></xsl:otherwise></xsl:choose></div><xsl:choose><xsl:when test="foo:channel/itunes:subtitle"><div id="subtitle"><xsl:attribute name="title"><xsl:value-of select="foo:channel/itunes:subtitle"/></xsl:attribute><xsl:value-of select="foo:channel/itunes:subtitle"/></div></xsl:when><xsl:when test="foo:channel/foo:description"><div id="subtitle"><xsl:attribute name="title"><xsl:value-of select="foo:channel/foo:description"/></xsl:attribute><xsl:value-of select="foo:channel/foo:description"/></div></xsl:when></xsl:choose></header><section id="links"><a title="Click to get the latest updates and news" onclick="location.href = &quot;feed:&quot; + location.href"></a><a title="Subscribe via SubToMe"><xsl:attribute name="href">https://www.subtome.com/#/subscribe?feeds=<xsl:value-of select="atom:link[@rel=&quot;self&quot;]/@href"/></xsl:attribute><xsl:attribute name="onclick">(function(btn){var z=document.createElement(&quot;script&quot;);document.subtomeBtn=btn;z.src=&quot;https://www.subtome.com/load.js&quot;;document.body.appendChild(z);})(this);return false;</xsl:attribute></a><a title="Learn about syndication feed" onclick="document.getElementById(&quot;aboutfeed&quot;).classList.toggle(&quot;show&quot;);" class="popup"><span class="popuptext" id="aboutfeed"/></a><a href="https://wikiless.org/wiki/Template:Aggregators" title="Get a feed reader for desktop and mobile"/><a href="https://wikiless.org/wiki/RSS" title="Learn the benefits of using feeds for personal and corporates"/></section><xsl:choose><xsl:when test="foo:item"><div id="toc"><xsl:for-each select="foo:item[not(position() &gt;20)]"><xsl:choose><xsl:when test="itunes:subtitle"><xsl:element name="a"><xsl:attribute name="href"><xsl:text>#newspaper-oujs-</xsl:text><xsl:value-of select="position()"/></xsl:attribute><xsl:value-of select="itunes:subtitle"/></xsl:element></xsl:when><xsl:when test="foo:title"><xsl:element name="a"><xsl:attribute name="href"><xsl:text>#newspaper-oujs-</xsl:text><xsl:value-of select="position()"/></xsl:attribute><xsl:value-of select="foo:title"/></xsl:element></xsl:when></xsl:choose></xsl:for-each></div></xsl:when></xsl:choose><section id="articles"><xsl:choose><xsl:when test="foo:item"><xsl:for-each select="foo:item[not(position() &gt;20)]"><div class="entry"><xsl:choose><xsl:when test="itunes:subtitle"><div class="title"><xsl:element name="a"><xsl:attribute name="href"><xsl:value-of select="foo:link"/></xsl:attribute><xsl:attribute name="title"><xsl:value-of select="itunes:subtitle"/></xsl:attribute><xsl:attribute name="id"><xsl:text>newspaper-oujs-</xsl:text><xsl:value-of select="position()"/></xsl:attribute><xsl:value-of select="itunes:subtitle"/></xsl:element></div></xsl:when><xsl:when test="foo:title"><div class="title"><xsl:element name="a"><xsl:attribute name="href"><xsl:value-of select="foo:link"/></xsl:attribute><xsl:attribute name="title"><xsl:value-of select="foo:title"/></xsl:attribute><xsl:attribute name="id"><xsl:text>newspaper-oujs-</xsl:text><xsl:value-of select="position()"/></xsl:attribute><xsl:value-of select="foo:title"/></xsl:element></div></xsl:when><xsl:otherwise><div class="warning rss title"/></xsl:otherwise></xsl:choose><xsl:choose><xsl:when test="geo:lat and geo:long"><xsl:variable name="lat" select="geo:lat"/><xsl:variable name="lng" select="geo:long"/><span class="geolocation"><a href="geo:{$lat},{$lng}">๐Ÿ“</a></span></xsl:when><xsl:when test="geo:Point"><xsl:variable name="lat" select="geo:Point/geo:lat"/><xsl:variable name="lng" select="geo:Point/geo:long"/><span class="geolocation"><a href="geo:{$lat},{$lng}">๐Ÿ“</a></span></xsl:when><xsl:when test="georss:point"><xsl:variable name="lat" select="substring-before(georss:point, &quot; &quot;)"/><xsl:variable name="lng" select="substring-after(georss:point, &quot; &quot;)"/><xsl:variable name="name" select="georss:featurename"/><span class="geolocation"><a href="geo:{$lat},{$lng}" title="{$name}">๐Ÿ“</a></span></xsl:when></xsl:choose><xsl:if test="dc:date"><div class="published"><xsl:value-of select="dc:date"/></div></xsl:if><xsl:choose><xsl:when test="content:encoded"><div class="content"><xsl:value-of select="content:encoded" disable-output-escaping="yes"/></div></xsl:when><xsl:when test="foo:description"><div class="content"><xsl:value-of select="foo:description" disable-output-escaping="yes"/></div></xsl:when><xsl:when test="itunes:summary"><div class="content"><xsl:value-of select="itunes:summary" disable-output-escaping="yes"/></div></xsl:when><xsl:otherwise><div class="warning rss description"/></xsl:otherwise></xsl:choose><xsl:if test="enc:enclosure"><div class="enclosure" title="Right-click and Save link asโ€ฆ"><xsl:for-each select="enc:enclosure"><xsl:element name="span"><xsl:attribute name="icon"><xsl:value-of select="substring-before(@enc:type,&quot;/&quot;)"/></xsl:attribute></xsl:element><xsl:element name="a"><xsl:attribute name="href"><xsl:value-of select="@rdf:resource"/></xsl:attribute><xsl:attribute name="download"/><xsl:call-template name="extract-filename"><xsl:with-param name="url" select="@rdf:resource"/></xsl:call-template></xsl:element><xsl:element name="span"><xsl:attribute name="class"><xsl:value-of select="substring-before(@enc:type,&quot;/&quot;)"/></xsl:attribute></xsl:element><xsl:if test="@enc:length &gt; 0"><xsl:call-template name="transform-filesize"><xsl:with-param name="length" select="@enc:length"/></xsl:call-template></xsl:if><xsl:element name="br"/></xsl:for-each></div></xsl:if></div></xsl:for-each></xsl:when><xsl:otherwise><div class="notice no-entry"/></xsl:otherwise></xsl:choose></section></div></body></html></xsl:template><xsl:output media-type="application/rss+xml"/><xsl:template match="/rss"><xsl:variable name="rtl" select="channel/language[ contains(text(),&quot;ar&quot;) or contains(text(),&quot;fa&quot;) or contains(text(),&quot;he&quot;) or contains(text(),&quot;ji&quot;) or contains(text(),&quot;ku&quot;) or contains(text(),&quot;ur&quot;) or contains(text(),&quot;yi&quot;)]"/><html><head><xsl:call-template name="metadata"><xsl:with-param name="name" select="&quot;description&quot;"/><xsl:with-param name="content" select="channel/description"/></xsl:call-template><xsl:call-template name="metadata"><xsl:with-param name="name" select="&quot;generator&quot;"/><xsl:with-param name="content" select="&quot;syndication4humans https://sjehuda.github.io/&quot;"/></xsl:call-template><xsl:call-template name="metadata"><xsl:with-param name="name" select="&quot;mimetype&quot;"/><xsl:with-param name="content" select="&quot;application/rss+xml&quot;"/></xsl:call-template><title><xsl:choose><xsl:when test="channel/title and not(channel/title=&quot;&quot;)"><xsl:value-of select="channel/title"/></xsl:when><xsl:otherwise>Streamburner News Reader</xsl:otherwise></xsl:choose></title><xsl:if test="$rtl"><meta name="semitic" content="true"/></xsl:if></head><body><div id="feed"><header><div id="title"><xsl:choose><xsl:when test="channel/title and not(channel/title=&quot;&quot;)"><xsl:attribute name="title"><xsl:value-of select="channel/title"/></xsl:attribute><xsl:value-of select="channel/title"/></xsl:when><xsl:otherwise><div class="empty"/></xsl:otherwise></xsl:choose></div><xsl:choose><xsl:when test="channel/itunes:subtitle"><div id="subtitle"><xsl:attribute name="title"><xsl:value-of select="channel/itunes:subtitle"/></xsl:attribute><xsl:value-of select="channel/itunes:subtitle"/></div></xsl:when><xsl:when test="channel/description"><div id="subtitle"><xsl:attribute name="title"><xsl:value-of select="channel/description"/></xsl:attribute><xsl:value-of select="channel/description"/></div></xsl:when></xsl:choose></header><section id="links"><a title="Click to get the latest updates and news" onclick="location.href = &quot;feed:&quot; + location.href"></a><a title="Subscribe via SubToMe"><xsl:attribute name="href">https://www.subtome.com/#/subscribe?feeds=<xsl:value-of select="atom:link[@rel=&quot;self&quot;]/@href"/></xsl:attribute><xsl:attribute name="onclick">(function(btn){var z=document.createElement(&quot;script&quot;);document.subtomeBtn=btn;z.src=&quot;https://www.subtome.com/load.js&quot;;document.body.appendChild(z);})(this);return false;</xsl:attribute></a><a title="Learn about syndication feed" onclick="document.getElementById(&quot;aboutfeed&quot;).classList.toggle(&quot;show&quot;);" class="popup"><span class="popuptext" id="aboutfeed"/></a><a href="https://wikiless.org/wiki/Template:Aggregators" title="Get a feed reader for desktop and mobile"/><a href="https://wikiless.org/wiki/RSS" title="Learn the benefits of using feeds for personal and corporates"/></section><xsl:choose><xsl:when test="channel/item"><div id="toc"><xsl:for-each select="channel/item[not(position() &gt;20)]"><xsl:choose><xsl:when test="itunes:subtitle"><xsl:element name="a"><xsl:attribute name="href"><xsl:text>#newspaper-oujs-</xsl:text><xsl:value-of select="position()"/></xsl:attribute><xsl:value-of select="itunes:subtitle"/></xsl:element></xsl:when><xsl:when test="title"><xsl:element name="a"><xsl:attribute name="href"><xsl:text>#newspaper-oujs-</xsl:text><xsl:value-of select="position()"/></xsl:attribute><xsl:value-of select="title"/></xsl:element></xsl:when></xsl:choose></xsl:for-each></div></xsl:when></xsl:choose><section id="articles"><xsl:choose><xsl:when test="channel/item"><xsl:for-each select="channel/item[not(position() &gt;20)]"><div class="entry"><xsl:choose><xsl:when test="itunes:subtitle"><div class="title"><xsl:element name="a"><xsl:attribute name="href"><xsl:value-of select="link"/></xsl:attribute><xsl:attribute name="title"><xsl:value-of select="itunes:subtitle"/></xsl:attribute><xsl:attribute name="id"><xsl:text>newspaper-oujs-</xsl:text><xsl:value-of select="position()"/></xsl:attribute><xsl:value-of select="itunes:subtitle"/></xsl:element></div></xsl:when><xsl:when test="title"><div class="title"><xsl:element name="a"><xsl:attribute name="href"><xsl:value-of select="link"/></xsl:attribute><xsl:attribute name="title"><xsl:value-of select="title"/></xsl:attribute><xsl:attribute name="id"><xsl:text>newspaper-oujs-</xsl:text><xsl:value-of select="position()"/></xsl:attribute><xsl:value-of select="title"/></xsl:element></div></xsl:when><xsl:otherwise><div class="warning rss2 title"/></xsl:otherwise></xsl:choose><xsl:choose><xsl:when test="geo:lat and geo:long"><xsl:variable name="lat" select="geo:lat"/><xsl:variable name="lng" select="geo:long"/><span class="geolocation"><a href="geo:{$lat},{$lng}">๐Ÿ“</a></span></xsl:when><xsl:when test="geo:Point"><xsl:variable name="lat" select="geo:Point/geo:lat"/><xsl:variable name="lng" select="geo:Point/geo:long"/><span class="geolocation"><a href="geo:{$lat},{$lng}">๐Ÿ“</a></span></xsl:when><xsl:when test="georss:point"><xsl:variable name="lat" select="substring-before(georss:point, &quot; &quot;)"/><xsl:variable name="lng" select="substring-after(georss:point, &quot; &quot;)"/><xsl:variable name="name" select="georss:featurename"/><span class="geolocation"><a href="geo:{$lat},{$lng}" title="{$name}">๐Ÿ“</a></span></xsl:when></xsl:choose><xsl:if test="pubDate"><div class="published"><xsl:value-of select="pubDate"/></div></xsl:if><xsl:choose><xsl:when test="content:encoded"><div class="content"><xsl:value-of select="content:encoded" disable-output-escaping="yes"/></div></xsl:when><xsl:when test="description"><div class="content"><xsl:value-of select="description" disable-output-escaping="yes"/></div></xsl:when><xsl:when test="itunes:summary"><div class="content"><xsl:value-of select="itunes:summary" disable-output-escaping="yes"/></div></xsl:when><xsl:otherwise><div class="warning rss2 description"/></xsl:otherwise></xsl:choose><xsl:if test="enclosure or media:content"><div class="enclosure" title="Right-click and Save link asโ€ฆ"><xsl:for-each select="enclosure"><xsl:element name="span"><xsl:attribute name="icon"><xsl:value-of select="substring-before(@type,&quot;/&quot;)"/></xsl:attribute></xsl:element><xsl:element name="a"><xsl:attribute name="href"><xsl:value-of select="@url"/></xsl:attribute><xsl:attribute name="download"/><xsl:call-template name="extract-filename"><xsl:with-param name="url" select="@url"/></xsl:call-template></xsl:element><xsl:element name="span"><xsl:attribute name="class"><xsl:value-of select="substring-before(@type,&quot;/&quot;)"/></xsl:attribute></xsl:element><xsl:if test="@length &gt; 0"><xsl:call-template name="transform-filesize"><xsl:with-param name="length" select="@length"/></xsl:call-template></xsl:if><xsl:element name="br"/></xsl:for-each><xsl:for-each select="media:content"><xsl:element name="span"><xsl:attribute name="icon"><xsl:value-of select="@medium"/></xsl:attribute></xsl:element><xsl:element name="a"><xsl:attribute name="href"><xsl:value-of select="@url"/></xsl:attribute><xsl:attribute name="download"/><xsl:call-template name="extract-filename"><xsl:with-param name="url" select="@url"/></xsl:call-template></xsl:element><xsl:element name="span"><xsl:attribute name="class"><xsl:value-of select="@medium"/></xsl:attribute></xsl:element><xsl:if test="@fileSize &gt; 0"><xsl:call-template name="transform-filesize"><xsl:with-param name="length" select="@fileSize"/></xsl:call-template></xsl:if><xsl:element name="br"/></xsl:for-each></div></xsl:if></div></xsl:for-each></xsl:when><xsl:otherwise><div class="notice no-entry"/></xsl:otherwise></xsl:choose></section></div></body></html></xsl:template><xsl:template name="metadata"><xsl:param name="name"/><xsl:param name="content"/><xsl:if test="$content and not($content=&quot;&quot;)"><xsl:element name="meta"><xsl:attribute name="name"><xsl:value-of select="$name"/></xsl:attribute><xsl:attribute name="content"><xsl:value-of select="$content"/></xsl:attribute></xsl:element></xsl:if></xsl:template><xsl:template name="extract-filename"><xsl:param name="url"/><xsl:choose><xsl:when test="substring($url, string-length($url) - string-length(&quot;/&quot;) + 1) = &quot;/&quot;"><xsl:value-of select="substring-after(substring($url, 1, string-length($url) - 1),&quot;://&quot;)"/></xsl:when><xsl:otherwise><xsl:choose><xsl:when test="contains($url,&quot;/&quot;) and contains(substring-after($url,&quot;/&quot;),&quot;.&quot;)"><xsl:call-template name="extract-filename"><xsl:with-param name="url" select="substring-after($url,&quot;/&quot;)"/></xsl:call-template></xsl:when><xsl:otherwise><xsl:value-of select="$url"/></xsl:otherwise></xsl:choose></xsl:otherwise></xsl:choose></xsl:template><xsl:template name="transform-filesize"><xsl:param name="length"/><xsl:choose><xsl:when test="$length &lt; 2"><xsl:value-of select="$length"/>Byte</xsl:when><xsl:when test="floor($length div 1024) &lt; 1"><xsl:value-of select="$length"/>Bytes</xsl:when><xsl:when test="floor($length div (1024 * 1024)) &lt; 1"><xsl:value-of select="floor($length div 1024)"/>.<xsl:value-of select="substring($length mod 1024,0,2)"/>KiB</xsl:when><xsl:when test="floor($length div (1024 * 1024 * 1024)) &lt; 1"><xsl:value-of select="floor($length div (1024 * 1024))"/>.<xsl:value-of select="substring($length mod (1024 * 1024),0,2)"/>MiB</xsl:when><xsl:otherwise><xsl:value-of select="floor($length div (1024 * 1024 * 1024))"/>.<xsl:value-of select="substring($length mod (1024 * 1024 * 1024),0,2)"/>GiB</xsl:otherwise></xsl:choose></xsl:template></xsl:stylesheet>';

  xsltStylesheet =
    domParser
    .parseFromString(
      xslFile, 'application/xml' // application/xslt+xml or text/xsl are Not Valid
    );

  xsltProcessor
  .importStylesheet(
    xsltStylesheet
  );

  newDocument =
    xsltProcessor
    .transformToDocument(
      xmlDocument
    );

  // FIXME
  // Blocked due to server policy
  // https://archlinux.org/feeds/packages/
  // https://www.openstreetmap.org/traces/rss
  // NOTE
  // We can use inline style (i.e. style="")
  // but that would make the code lesser manageable
  stylesheet_ltr = "html,body{padding:0;margin:0}body{background:WhiteSmoke;color:#333;hyphens:auto}header{margin:0 -1em 1em -1em;margin-bottom:1em;padding:1em 1em 0 1em}#feed{min-width:400px;overflow:auto;position:relative}*{max-width:97%;object-fit:contain;height:auto}#logo{display:inline-block;float:left;overflow:hidden;position:relative;height:60px;width:60px;margin-right:9;padding-top:12}#logo>a>img{margin:auto;max-width:100%;position:absolute;width:5em;bottom:0;right:0;left:0;top:0}#title{font-variant:small-caps;text-align:center}#title{font-weight:bold;margin-bottom:0;overflow:hidden;-webkit-line-clamp:2;white-space:nowrap;margin:0;font-size:2.2em}#title .empty:before{font-variant:small-caps;content:'Streamburner News Dashboard';text-align:center}#subtitle{overflow:hidden;-webkit-line-clamp:2;white-space:wrap;font-weight:bold;font-size:1.5em;text-align:center;font-variant:small-caps}.container{display:flex}#links{border-top:.1em solid;margin:auto;width:50%;text-align:center;direction:ltr}#links>a{padding:10px;text-decoration:none;font-size:70%}#links>a:nth-child(1):after{content:'Follow';cursor:pointer;border-color:grey;border-left-style:solid;border-radius:1px;padding:6px;background:#eee !important}#links>a:nth-child(2):after{content:'SubToMe';cursor:pointer}#links>a:nth-child(3):after{content:'Whatโ€™s This?';cursor:help}#links>a:nth-child(4):after{content:'Get a News Reader'}#links>a:nth-child(5):after{content:'More Info...'}#toc{margin-left:3%;padding:5px}#toc:before{content:'Latest Updates';font-size:76%;font-weight:bold}#toc>a{text-decoration:none;font-size:66%;display:block;padding:5px 0;margin-left:1%}#toc>a:hover{text-decoration:underline}#toc>a:visited{text-decoration:line-through}.popup{position:relative;display:inline-block;cursor:pointer}.popup .popuptext{visibility:hidden;width:160px;color:#fff;border-radius:6px;padding:18px;position:absolute;z-index:1;background-color:#555;position:absolute;right:4%;position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);width:50%;text-align:left}.popup .popuptext:after{content:'๐Ÿ“ฐ Web Syndication News Feed \\A\\A ' ' Syndication Feed is a mean for content and media publishers ' 'to reach a wider audience easily. ' ' It allows you to receive information directly without the ' 'going from site to site. \\A\\A ' ' Essentially, a feed is a function that allows โ€œFeed Readersโ€ ' 'to access multiple websites automatically looking for new ' 'content and then posting the information about new content ' 'and updates to another website, mobile app or desktop software ' 'at the office. \\A\\A ' ' Feeds provide a way for users to keep up with the latest ' 'news, events and package and delivery status information ' 'posted on different websites such as social networks, torrent ' 'indexers or podcasts in one spot.';white-space:pre-wrap;line-height:1.8;font-size:150%}.popup .show{visibility:visible;-webkit-animation:fadeIn 1s;animation:fadeIn 1s}@-webkit-keyframes fadeIn{from{opacity:0}to{opacity:1}}@keyframes fadeIn{from{opacity:0}to{opacity:1}}#articles{justify-content:space-between;max-width:90%;margin:0 auto;padding:10px 0}#articles>*{margin:.5em;white-space:normal;vertical-align:top;margin-bottom:50px}.entry{border-bottom:inset;margin-left:auto;margin-right:auto;overflow:auto;line-height:1.6;font-size:85%;overflow-x:hidden}.entry:hover{background:#f8f9fa}.entry *{max-width:98%}.entry>a{white-space:normal}.title{cursor:pointer;display:inline-block;font-size:110%;font-weight:bold;text-decoration:underline;overflow:visible;text-overflow:ellipsis;white-space:nowrap;font-variant:small-caps}a{color:#333;display:inline-block}.geolocation>a{text-decoration:none;padding-left:6px}.author{font-size:75%;margin:0 auto 0 auto}.author:before{content:'By '}.author:after{content:' / '}.published,.updated{font-size:75%;margin:0 auto 0 auto}.content{margin:15px auto 15px 1%;inline-size:95%;text-indent:3px}.content[type='text']{font-family:monospace}code{overflow:auto;display:block;max-height:300px;border-radius:4px}.enclosure{background:#eee;border:1px solid GrayText;border-radius:4px;clear:both;color:#525c66;cursor:help;direction:ltr;font-size:.8em;margin:5px auto 15px 1%;padding:15px;vertical-align:middle;border:1px solid #aaa;border-radius:.5em;max-width:100%;moz-border-radius:.5em;padding:1em}.enclosure>span:after{content:' (Document file) '}.enclosure>span.executable:after{content:' (Executable file) '}.enclosure>span.image:after{content:' (Image file) '}.enclosure>span.audio:after{content:' (Audio file) '}.enclosure>span.video:after{content:' (Video file) '}.enclosure>span[icon]:after{content:'๐Ÿ“„๏ธ';margin:3px}.enclosure>span[icon='executable']:after{content:'๐Ÿ“ฆ๏ธ';margin:3px}.enclosure>span[icon='image']:after{content:'๐Ÿ–ผ๏ธ';margin:3px}.enclosure>span[icon='audio']:after{content:'๐ŸŽผ๏ธ';margin:3px}.enclosure>span[icon='video']:after{content:'๐Ÿ“ฝ๏ธ';margin:3px}.notice{text-align:center;display:block;font-size:130%;font-weight:lighter;font-variant-caps:small-caps;font-style:oblique;color:FireBrick}.warning{display:block;font-size:60%;font-weight:bold;color:DarkRed}.no-entry:after{content:'This news feed is empty'}.atom1.author:after{content:'Atom 1.0 Warning: Element </author> is missing'}.atom1.id:after{content:'Atom 1.0 Warning: Element </id> is missing'}.atom1.link:after{content:'Atom 1.0 Warning: Element </link> is missing'}.atom1.published:after{content:'Atom 1.0 Warning: Element </published> is missing'}.atom1.title:after{content:'Atom 1.0 Warning: Element </title> is missing'}.rss2.description:after{content:'RSS 2.0 Warning: Element </description> is missing'}.rss2.link:after{content:'RSS 2.0 Warning: Element </link> is missing'}.rss2.title:after{content:'RSS 2.0 Warning: Element </title> is missing'}abbr,acronym{border-bottom:1px dotted #c30}dt{font-weight:bold}";
  stylesheet_rtl = "html,body{text-align:right}#feed{direction:rtl}#logo{float:right;margin-left:9}.geolocation>a{padding-right:6px}.image{float:right;margin-left:40px;margin-right:auto}"
  style = newDocument.createElement('style');
  newDocument.head.append(style);
  style.type = 'text/css';

  // NOTE
  // Because we use JS, maybe it is better to set direction by
  // the letters of the initial set of words.
  var isRTL =
    newDocument
    .querySelector(
      'meta[name="semitic"]'
    );

  if (isRTL) {
    style.innerHTML =
      stylesheet_ltr +
      stylesheet_rtl;
  } else {
    style.innerHTML =
      stylesheet_ltr;
  }

  for (const image of newDocument.querySelectorAll('img')) {
    //source = image.src;
    //image.removeAttribute('src');
    //image.setAttribute('src-data', source);
    image.setAttribute('src-data', image.src);
    image.removeAttribute('src');
  }

  //var newDoc = document.adoptNode(newDoc.documentElement, true);
  insertDocument =
    document
    .importNode(
      newDocument
      .documentElement,
      true
    );

  removeDocument =
    document
    .documentElement;

  document
  .replaceChild(
    insertDocument,
    removeDocument
  );

  /*
  document.body.addEventListener ("mouseover", function(e) {
    if (e.target && e.target.nodeName == "IMG" && !e.target.src) {
      console.log('DELEGATED')
      source = e.target.getAttribute('src-data');
      e.target.removeAttribute('src-data');
      e.target.src = source;
    }
  });
  */

  for (const image of newDocument.querySelectorAll('img')) {
    image.onmouseover = () => {
      console.log('onmouseover')
      source = image.getAttribute('src-data');
      image.removeAttribute('src-data');
      image.src = source;
    }
  }

  /*
  for (const image of document.querySelectorAll('img')) {
    image.addEventListener('focus',event => {
    //image.addEventListener('mouseover',event => {
      if (image.getAttribute('src-data')) {
        //toggleAttribute(image)
        source = image.getAttribute('src-data');
        image.removeAttribute('src-data');
        image.src = source;
      }
    }, {passive: true});
    image.onmouseover = () => {
      if (image.getAttribute('src-data')) {
        //toggleAttribute(image)
        source = image.getAttribute('src-data');
        image.removeAttribute('src-data');
        image.src = source;
      }
    };
  }
  */

}

function toggleAttribute(image) {
    source = image.getAttribute('src-data');
    image.removeAttribute('src-data');
    image.src = source;
}

function queryByXPath(queries) {
  var result;
  let i = 0;
  do {
    result = document.evaluate(
      queries[i], document,
      null, XPathResult.STRING_TYPE);
    i = i + 1;
    result = result.stringValue;
  } while (!result && i < queries.length);
  return result;
}

I've written a userscript that redirects to proxy addresses, and another userscript that changes URL; both use the same dataset.

The code seems to be done for both programs, and no technical updates are expected to occur.

However, the only frequent update that these userscripts are subjected to is database update.

How should @require be utilized to achieve dataset update or should we have a @data metablock to handle this task?


You tell us. :)

It's a difficult question. I'm not sure.

As with Tampermonkey for Android you might run the risk of it's base core, Chromium, being out of date. i.e. possible browser security vulnerabilities.

Is this so for Mull too?


Synchronize url list with a remote database using:

  • @require; or
  • @resource; or
  • DHT with BitTorrent, ed2K, IPFS etc.

๏ฟผ



Program FREELink

You have to remove/comment the following code to test this issue:

for (const link of document.querySelectorAll('a[href^="http"]')) {
  //mod = init(link);
  mod = init(link.href, link.outerText);
  if (mod) {
    link.href = mod
  }
}

The following event delegator doesn't work in some cases (see below).

// /questions/29896128/add-event-listener-on-every-link
// mouseover isn't available when only keyboard is in use
// try also infocus, focus or similar
//document.body.addEventListener("click", function(e) {
document.body.addEventListener("mouseover", function(e) { // mouseover works with keyboard too
  if (e.target && e.target.nodeName == "A") {
    mod = init(e.target.href, e.target.outerText);
    if (mod) {
      e.target.href = mod;
    }
  }
});

Hyperlinks nested inside and wrap other elements (or a single element?) are not affected.

<a href="https://www.youtube.com/watch?v=4NpS1uqTjlQ" rel="noreferrer">
<img alt="Bq-paella-installation-tutorial.jpg" src="/images/thumb/c/ce/Bq-paella-installation-tutorial.jpg/256px-Bq-paella-installation-tutorial.jpg" decoding="async" width="256" height="144" srcset="/images/thumb/c/ce/Bq-paella-installation-tutorial.jpg/384px-Bq-paella-installation-tutorial.jpg 1.5x, /images/thumb/c/ce/Bq-paella-installation-tutorial.jpg/512px-Bq-paella-installation-tutorial.jpg 2x">
</a>

From https://wiki.postmarketos.org/wiki/BQ_Aquaris_X5_(bq-paella)#Installation

<div id="downloads" class="clearfix" align="center">
 <a href="https://gh.odyssey346.dev/Tomas-M/xlunch/archive/v4.7.4.zip" id="download-zip" class="button" rel="noreferrer"><span>Download xlunch v4.7.4.zip &nbsp;&nbsp;</span></a>
 <a href="https://gothub.lunar.icu/Tomas-M/xlunch/archive/v4.7.4.tar.gz" id="download-tar-gz" class="button" rel="noreferrer"><span>Download xlunch v4.7.4.tar.gz &nbsp;&nbsp;</span></a>
 <a href="https://github.com/Tomas-M/xlunch" id="view-on-github" class="button" rel="noreferrer"><span>View on GitHub &nbsp;&nbsp;</span></a>
 </div>

From http://xlunch.org/

Please help.







Also posted at: Falkon, Greasemonkey, Tampermonkey and Violentmonkey.

I think it would be useful to add @nocors metadata block (similarly to @noframes) which would be productive in the sense of coding and consequently make userscript managers to behave in a uniform fashion.

no-www is using GM.xmlHttpRequest which doesn't seem to be supported with all userscript managers.

Example userscript

if (!location.host.startsWith('www.')) return; // exit (else, continue)

var newURL = location.href.replace('://www.','://');

GM.xmlHttpRequest({
  method: 'GET',
  url: newURL,
  synchronous: true,
  onprogress: console.log('Checking for no-www...'),
  onload: function(response) {
    if (response.finalUrl == newURL) {
      location.href = newURL;
    } else {
      console.log('Please contact webmaster to remove www. https://no-www.org/');
    }
  },
  onerror: function(response) {
    console.log('Error requesting for no-www')
  }
})

If @nocors was introduced, this script could have been shorter.

fetch(newURL)
  .then((response) => {
     if (request.reseponseURL == newURL) {
       window.open(newURL,'_self');
     }
  })

synchronize url list with a remote database, using @require or @resource.



itemization

  • extract search parameter
  • decode parameter => url
  • process url




Below is my recent attempt, so far.
I'd appreciate your help with it.

Code:

while (toot < 5) {
  inst = instList[Math.floor(Math.random()*instList.length)];
  inst = inst.split(',')[1];
  toot = toot + 1
  console.log('toot')
  console.log(toot)
  console.log('inst')
  console.log(inst)
  GM.xmlHttpRequest({
    method: 'GET',
    mode: 'no-cors',
    url: inst,
    synchronous: true,
    onload: function(response) {
      status = response.status;
      console.log([
        response.status,
        response.statusText,
        response.readyState,
        response.responseHeaders,
        response.responseText,
        response.finalUrl,
        responseXML
      ].join("\n"));
    }
  })
  console.log('status')
  console.log(status)
}

Output:

1                                        FREEdirector:572:11
inst                                     FREEdirector:573:11
https://lieu.cblgh.org                   FREEdirector:574:11
status                                   FREEdirector:593:11
undefined                                FREEdirector:594:11
toot                                     FREEdirector:571:11
2                                        FREEdirector:572:11
inst                                     FREEdirector:573:11
https://searx.be                         FREEdirector:574:11
status                                   FREEdirector:593:11
undefined                                FREEdirector:594:11
toot                                     FREEdirector:571:11
3                                        FREEdirector:572:11
inst                                     FREEdirector:573:11
https://searx.rasp.fr                    FREEdirector:574:11
status                                   FREEdirector:593:11
undefined                                FREEdirector:594:11
toot                                     FREEdirector:571:11
4                                        FREEdirector:572:11
inst                                     FREEdirector:573:11
https://85.199.74.98:8443                FREEdirector:574:11
status                                   FREEdirector:593:11
undefined                                FREEdirector:594:11
toot                                     FREEdirector:571:11
5                                        FREEdirector:572:11
inst                                     FREEdirector:573:11
https://farside.link/searx               FREEdirector:574:11
status                                   FREEdirector:593:11
undefined                                FREEdirector:594:11

Redirecting to https://search.yacy.net/yacysearch.html?query=userscripts

Hello,

I want to check http status code of URL using GM.xmlHttpRequest.

Code: source

  // url (instance) is selected from instList
  inst = instList[Math.floor(Math.random()*instList.length)];
  name = inst.split(',')[0];
  inst = inst.split(',')[1];

This is what I want to do:

while (status =! 200) {
  inst = instList[Math.floor(Math.random()*instList.length)];
  inst = inst.split(',')[1];
  // CHECK HTTP STATUS OF GIVEN URL ("inst")
  status = response.status
}

Userscript https://openuserjs.org/scripts/sjehuda/FREEdirector



Code; courtesy of 7nik

Just use fetch, it is more simple. This should work:

async function httpGetAsync(uri, callback) {
  let resp = await fetch(uri, { method: "HEAD" });
  if (!resp.ok) resp = await fetch(uri);
  const mimeType = resp.headers.get("Content-Type");
  callback(mimeType);
}

Hello,

I'm looking into replacing callback and XMLHttpRequest by

  • Fetch
  • Promise and XMLHttpRequest

Fetch doesn't support file:// hence I've decided not to use it, because callback and XMLHttpRequest do allow file://. See Newspaper/issues/Observation_Fetch_API.

This is the code for Promise and it seems to skip the statement (document.URL.startsWith('file:')) that should allow applying this userscript to local files too.

let myPromise = new Promise(function(myResolve, myReject) {
  let request = new XMLHttpRequest();
  request.open('GET', document.documentURI);
  request.onload = function() {
    if (request.status == 200) {
      myResolve(request);
    } else {
      myReject("File not Found");
    }
  };
  request.send();
});

myPromise.then(
  function(request) {
      if (document.URL.startsWith('file:')) {
        mimeType = document.contentType;
      } else {
          mimeType =
            request
            .getResponseHeader('Content-Type');
        }
      if (checkMediaType(mimeType)) {
        renderFeed(request.response)
      }
  },
  function(error) {checkMediaType(error);}
);

Please help.
Thank you.


Below is a draft utilizing fetch.

fetch(document.documentURI)
  .then((response) => {
     const contentType = response.headers.get('content-type');
     if (checkMediaType(contentType)) {
       return response.text();
     }
  })
  .then((data) => {
      renderFeed(data)
  })

I've examined the following code, and I haven't found the ease and sensibility of coding with fetch significantly advantageous because of the following reasons:

  • Fetch doesn't support file URL.
  • The code is short enough for callback to be understandable.
var
  xmlHTTPRequest, xmlFile,
  mimeType, isFeed;

const mimeArray = [
  'application/atom+xml',
  'application/stream+json',
  'application/rss+xml',
  'application/rdf+xml'
];

fetch(document.documentURI)
  .then((response) => {
     const contentType = response.headers.get('content-type');
     if (!checkMediaType(contentType)) {
       throw new TypeError("Page does not seem to be a feed!");
     }
     return response.arrayBuffer();
  })
  .then((data) => {
    let decoder = new TextDecoder(document.characterSet);
    let text = decoder.decode(data);
    renderFeed(text)
  })

function checkStatus(response) {
  if (response.status >= 200 && response.status < 300) {
    return Promise.resolve(response.responseText)
  } else {
    return Promise.reject(new Error(response.statusText))
  }
}

// Check if is of type syndication feed
function checkMediaType(mimeType) {

  if (!mimeType) {
    mimeType = 'text/plain';
  }

  for (let i = 0; i < mimeArray.length; i++) {
    if (mimeType.includes(mimeArray[i])
       ) {
      return true;
    }
    // Check if is application/xml or text/xml
    else
    if (mimeType.includes('/xml') || mimeType.includes('/html')) {
      const tagArray = ['feed', 'atom:link', 'rss', 'rdf:RDF'];
      for (let i = 0; i < tagArray.length; i++) {
        var query = document.getElementsByTagName(tagArray[i]);
        if (query.length) {
          return true;
        }
      }
    }
    // Check if is plain text (XPath only is usable)
    else
    if (mimeType.match('text/plain')) {
      const tagArray = ['<feed', '<atom:link', '<rss', '<rdf:RDF'];
      for (let i = 0; i < tagArray.length; i++) {
        query = ['//*[contains(text(), "' + tagArray[i] + '")]'];
        query = queryByXPath(query);
        if (query.length) {
          return true;
        }
      }
    }
  }
}

// Begin processing
function renderFeed(xmlFile) {

  var
    domParser,
    xmlDocument, xsltProcessor,
    newDocument, head, style, isRTL,
    stylesheet_ltr, stylesheet_rtl,
    insertDocument, removeDocument;

  xmlFile =
    xmlFile
    .trim();

  domParser = new DOMParser();

  xmlDocument =
    domParser
    .parseFromString(
      xmlFile,
      'text/xml'
    );

  xsltProcessor = new XSLTProcessor();

  xslFile = '<?xml version="1.0" encoding="UTF-8"?><xsl:stylesheet xmlns="http://purl.org/rss/1.0/" xmlns:admin="http://webns.net/mvcb/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:atom10="http://www.w3.org/2005/Atom" xmlns:c="http://s.opencalais.com/1/pred/" xmlns:cc="http://web.resource.org/cc/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dct="http://purl.org/dc/terms/" xmlns:dbo="http://dbpedia.org/ontology/" xmlns:dbp="http://dbpedia.org/property/" xmlns:enc="http://purl.oclc.org/net/rss_2.0/enc#" xmlns:fh="http://purl.org/syndication/history/1.0" xmlns:foaf="http://xmlns.com/foaf/0.1/" xmlns:foo="http://purl.org/rss/1.0/" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:georss="http://www.georss.org/georss" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:media="http://search.yahoo.com/mrss/" xmlns:owl="http://www.w3.org/2002/07/owl#" xmlns:prov="http://www.w3.org/ns/prov#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#" xmlns:sioc="http://rdfs.org/sioc/ns#" xmlns:sioct="http://rdfs.org/sioc/types#" xmlns:skos="http://www.w3.org/2004/02/skos/core#" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:syn="http://purl.org/rss/1.0/modules/syndication/" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"><xsl:output method="html" indent="yes" omit-xml-decleration="no"/><xsl:output media-type="application/atom+xml"/><xsl:template match="/atom:feed"><xsl:variable name="rtl" select="@xml:lang[ contains(self::node(),&quot;ar&quot;) or contains(self::node(),&quot;fa&quot;) or contains(self::node(),&quot;he&quot;) or contains(self::node(),&quot;ji&quot;) or contains(self::node(),&quot;ku&quot;) or contains(self::node(),&quot;ur&quot;) or contains(self::node(),&quot;yi&quot;)]"/><html><head><xsl:call-template name="metadata"><xsl:with-param name="name" select="&quot;description&quot;"/><xsl:with-param name="content" select="atom:subtitle"/></xsl:call-template><xsl:call-template name="metadata"><xsl:with-param name="name" select="&quot;generator&quot;"/><xsl:with-param name="content" select="&quot;syndication4humans https://sjehuda.github.io/&quot;"/></xsl:call-template><xsl:call-template name="metadata"><xsl:with-param name="name" select="&quot;mimetype&quot;"/><xsl:with-param name="content" select="&quot;application/atom+xml&quot;"/></xsl:call-template><title><xsl:choose><xsl:when test="atom:title and not(atom:title=&quot;&quot;)"><xsl:value-of select="atom:title"/></xsl:when><xsl:otherwise>Streamburner News Reader</xsl:otherwise></xsl:choose></title><xsl:if test="$rtl"><meta name="semitic" content="true"/></xsl:if></head><body><div id="feed"><header><div id="title"><xsl:choose><xsl:when test="atom:title and not(atom:title=&quot;&quot;)"><xsl:attribute name="title"><xsl:value-of select="atom:title"/></xsl:attribute><xsl:value-of select="atom:title"/></xsl:when><xsl:otherwise><div class="empty"/></xsl:otherwise></xsl:choose></div><div id="subtitle"><xsl:attribute name="title"><xsl:value-of select="atom:subtitle"/></xsl:attribute><xsl:value-of select="atom:subtitle"/></div></header><section id="links"><a title="Click to get the latest updates and news" onclick="location.href = &quot;feed:&quot; + location.href"></a><a title="Subscribe via SubToMe"><xsl:attribute name="href">https://www.subtome.com/#/subscribe?feeds=<xsl:value-of select="atom:link[@rel=&quot;self&quot;]/@href"/></xsl:attribute><xsl:attribute name="onclick">(function(btn){var z=document.createElement(&quot;script&quot;);document.subtomeBtn=btn;z.src=&quot;https://www.subtome.com/load.js&quot;;document.body.appendChild(z);})(this);return false;</xsl:attribute></a><a title="Learn about syndication feed" onclick="document.getElementById(&quot;aboutfeed&quot;).classList.toggle(&quot;show&quot;);" class="popup"><span class="popuptext" id="aboutfeed"/></a><a href="https://wikiless.org/wiki/Template:Aggregators" title="Get a feed reader for desktop and mobile"/><a href="https://wikiless.org/wiki/RSS" title="Learn the benefits of using feeds for personal and corporates"/></section><xsl:choose><xsl:when test="atom:entry"><div id="toc"><xsl:for-each select="atom:entry[not(position() &gt;20)]"><xsl:if test="atom:title"><xsl:element name="a"><xsl:attribute name="href"><xsl:text>#newspaper-oujs-</xsl:text><xsl:value-of select="position()"/></xsl:attribute><xsl:value-of select="atom:title"/></xsl:element></xsl:if></xsl:for-each></div></xsl:when></xsl:choose><section id="articles"><xsl:choose><xsl:when test="atom:entry"><xsl:for-each select="atom:entry[not(position() &gt;20)]"><div class="entry"><xsl:if test="atom:title"><div class="title"><xsl:element name="a"><xsl:attribute name="href"><xsl:choose><xsl:when test="atom:link[contains(@rel,&quot;alternate&quot;)]"><xsl:value-of select="atom:link[contains(@rel,&quot;alternate&quot;)]/@href"/></xsl:when><xsl:otherwise><xsl:value-of select="atom:link/@href"/></xsl:otherwise></xsl:choose></xsl:attribute><xsl:attribute name="title"><xsl:value-of select="atom:title"/></xsl:attribute><xsl:attribute name="id"><xsl:text>newspaper-oujs-</xsl:text><xsl:value-of select="position()"/></xsl:attribute><xsl:value-of select="atom:title"/></xsl:element></div></xsl:if><xsl:choose><xsl:when test="geo:lat and geo:long"><xsl:variable name="lat" select="geo:lat"/><xsl:variable name="lng" select="geo:long"/><span class="geolocation"><a href="geo:{$lat},{$lng}">๐Ÿ“</a></span></xsl:when><xsl:when test="geo:Point"><xsl:variable name="lat" select="geo:Point/geo:lat"/><xsl:variable name="lng" select="geo:Point/geo:long"/><span class="geolocation"><a href="geo:{$lat},{$lng}">๐Ÿ“</a></span></xsl:when><xsl:when test="georss:point"><xsl:variable name="lat" select="substring-before(georss:point, &quot; &quot;)"/><xsl:variable name="lng" select="substring-after(georss:point, &quot; &quot;)"/><xsl:variable name="name" select="georss:featurename"/><span class="geolocation"><a href="geo:{$lat},{$lng}" title="{$name}">๐Ÿ“</a></span></xsl:when></xsl:choose><xsl:choose><xsl:when test="atom:updated"><div class="updated"><xsl:value-of select="atom:updated"/></div></xsl:when><xsl:when test="atom:published"><div class="published"><xsl:value-of select="atom:published"/></div></xsl:when><xsl:otherwise><div class="warning atom1 published"/></xsl:otherwise></xsl:choose><xsl:if test="atom:content or atom:summary"><div class="content"><xsl:choose><xsl:when test="atom:summary[contains(@type,&quot;text&quot;)]"><xsl:attribute name="type"><xsl:value-of select="atom:summary/@type"/></xsl:attribute><xsl:value-of select="atom:summary"/></xsl:when><xsl:when test="atom:summary[contains(@type,&quot;base64&quot;)]"></xsl:when><xsl:when test="atom:content[contains(@type,&quot;text&quot;)]"><xsl:attribute name="type"><xsl:value-of select="atom:content/@type"/></xsl:attribute><xsl:value-of select="atom:content"/></xsl:when><xsl:when test="atom:content[contains(@type,&quot;base64&quot;)]"></xsl:when><xsl:otherwise><xsl:choose><xsl:when test="atom:summary and not(atom:summary=&quot;&quot;)"><xsl:value-of select="atom:summary" disable-output-escaping="yes"/></xsl:when><xsl:otherwise><xsl:value-of select="atom:content" disable-output-escaping="yes"/></xsl:otherwise></xsl:choose></xsl:otherwise></xsl:choose></div></xsl:if><xsl:if test="atom:link[contains(@rel,&quot;enclosure&quot;)]"><div class="enclosure" title="Right-click and Save link asโ€ฆ"><xsl:for-each select="atom:link[contains(@rel,&quot;enclosure&quot;)]"><xsl:element name="span"><xsl:attribute name="icon"><xsl:value-of select="substring-before(@type,&quot;/&quot;)"/></xsl:attribute></xsl:element><xsl:element name="a"><xsl:attribute name="href"><xsl:value-of select="@href"/></xsl:attribute><xsl:attribute name="download"/><xsl:call-template name="extract-filename"><xsl:with-param name="url" select="@href"/></xsl:call-template></xsl:element><xsl:element name="span"><xsl:attribute name="class"><xsl:value-of select="substring-before(@type,&quot;/&quot;)"/></xsl:attribute></xsl:element><xsl:if test="@length &gt; 0"><xsl:call-template name="transform-filesize"><xsl:with-param name="length" select="@length"/></xsl:call-template></xsl:if><xsl:element name="br"/></xsl:for-each><xsl:for-each select="media:content"><xsl:element name="span"><xsl:attribute name="icon"><xsl:value-of select="@medium"/></xsl:attribute></xsl:element><xsl:element name="a"><xsl:attribute name="href"><xsl:value-of select="@url"/></xsl:attribute><xsl:attribute name="download"/><xsl:call-template name="extract-filename"><xsl:with-param name="url" select="@url"/></xsl:call-template></xsl:element><xsl:element name="span"><xsl:attribute name="class"><xsl:value-of select="@medium"/></xsl:attribute></xsl:element><xsl:if test="@fileSize &gt; 0"><xsl:call-template name="transform-filesize"><xsl:with-param name="length" select="@fileSize"/></xsl:call-template></xsl:if><xsl:element name="br"/></xsl:for-each></div></xsl:if></div><xsl:if test="not(atom:id)"><div class="warning atom1 id"/></xsl:if></xsl:for-each></xsl:when><xsl:otherwise><div class="notice no-entry"/></xsl:otherwise></xsl:choose></section></div></body></html></xsl:template><xsl:output media-type="application/rdf+xml"/><xsl:template match="/rdf:RDF"><xsl:variable name="rtl" select="channel/language[ contains(text(),&quot;ar&quot;) or contains(text(),&quot;fa&quot;) or contains(text(),&quot;he&quot;) or contains(text(),&quot;ji&quot;) or contains(text(),&quot;ku&quot;) or contains(text(),&quot;ur&quot;) or contains(text(),&quot;yi&quot;)]"/><html><head><xsl:call-template name="metadata"><xsl:with-param name="name" select="&quot;description&quot;"/><xsl:with-param name="content" select="foo:channel/foo:description"/></xsl:call-template><xsl:call-template name="metadata"><xsl:with-param name="name" select="&quot;generator&quot;"/><xsl:with-param name="content" select="&quot;syndication4humans https://sjehuda.github.io/&quot;"/></xsl:call-template><xsl:call-template name="metadata"><xsl:with-param name="name" select="&quot;mimetype&quot;"/><xsl:with-param name="content" select="&quot;application/rdf+xml&quot;"/></xsl:call-template><title><xsl:choose><xsl:when test="foo:channel/foo:title and not(foo:channel/foo:title=&quot;&quot;)"><xsl:value-of select="foo:channel/foo:title"/></xsl:when><xsl:otherwise>Streamburner News Reader</xsl:otherwise></xsl:choose></title><xsl:if test="$rtl"><meta name="semitic" content="true"/></xsl:if></head><body><div id="feed"><header><div id="title"><xsl:choose><xsl:when test="foo:channel/foo:title and not(foo:channel/foo:title=&quot;&quot;)"><xsl:attribute name="title"><xsl:value-of select="foo:channel/foo:title"/></xsl:attribute><xsl:value-of select="foo:channel/foo:title"/></xsl:when><xsl:otherwise><div class="empty"/></xsl:otherwise></xsl:choose></div><xsl:choose><xsl:when test="foo:channel/itunes:subtitle"><div id="subtitle"><xsl:attribute name="title"><xsl:value-of select="foo:channel/itunes:subtitle"/></xsl:attribute><xsl:value-of select="foo:channel/itunes:subtitle"/></div></xsl:when><xsl:when test="foo:channel/foo:description"><div id="subtitle"><xsl:attribute name="title"><xsl:value-of select="foo:channel/foo:description"/></xsl:attribute><xsl:value-of select="foo:channel/foo:description"/></div></xsl:when></xsl:choose></header><section id="links"><a title="Click to get the latest updates and news" onclick="location.href = &quot;feed:&quot; + location.href"></a><a title="Subscribe via SubToMe"><xsl:attribute name="href">https://www.subtome.com/#/subscribe?feeds=<xsl:value-of select="atom:link[@rel=&quot;self&quot;]/@href"/></xsl:attribute><xsl:attribute name="onclick">(function(btn){var z=document.createElement(&quot;script&quot;);document.subtomeBtn=btn;z.src=&quot;https://www.subtome.com/load.js&quot;;document.body.appendChild(z);})(this);return false;</xsl:attribute></a><a title="Learn about syndication feed" onclick="document.getElementById(&quot;aboutfeed&quot;).classList.toggle(&quot;show&quot;);" class="popup"><span class="popuptext" id="aboutfeed"/></a><a href="https://wikiless.org/wiki/Template:Aggregators" title="Get a feed reader for desktop and mobile"/><a href="https://wikiless.org/wiki/RSS" title="Learn the benefits of using feeds for personal and corporates"/></section><xsl:choose><xsl:when test="foo:item"><div id="toc"><xsl:for-each select="foo:item[not(position() &gt;20)]"><xsl:choose><xsl:when test="itunes:subtitle"><xsl:element name="a"><xsl:attribute name="href"><xsl:text>#newspaper-oujs-</xsl:text><xsl:value-of select="position()"/></xsl:attribute><xsl:value-of select="itunes:subtitle"/></xsl:element></xsl:when><xsl:when test="foo:title"><xsl:element name="a"><xsl:attribute name="href"><xsl:text>#newspaper-oujs-</xsl:text><xsl:value-of select="position()"/></xsl:attribute><xsl:value-of select="foo:title"/></xsl:element></xsl:when></xsl:choose></xsl:for-each></div></xsl:when></xsl:choose><section id="articles"><xsl:choose><xsl:when test="foo:item"><xsl:for-each select="foo:item[not(position() &gt;20)]"><div class="entry"><xsl:choose><xsl:when test="itunes:subtitle"><div class="title"><xsl:element name="a"><xsl:attribute name="href"><xsl:value-of select="foo:link"/></xsl:attribute><xsl:attribute name="title"><xsl:value-of select="itunes:subtitle"/></xsl:attribute><xsl:attribute name="id"><xsl:text>newspaper-oujs-</xsl:text><xsl:value-of select="position()"/></xsl:attribute><xsl:value-of select="itunes:subtitle"/></xsl:element></div></xsl:when><xsl:when test="foo:title"><div class="title"><xsl:element name="a"><xsl:attribute name="href"><xsl:value-of select="foo:link"/></xsl:attribute><xsl:attribute name="title"><xsl:value-of select="foo:title"/></xsl:attribute><xsl:attribute name="id"><xsl:text>newspaper-oujs-</xsl:text><xsl:value-of select="position()"/></xsl:attribute><xsl:value-of select="foo:title"/></xsl:element></div></xsl:when><xsl:otherwise><div class="warning rss title"/></xsl:otherwise></xsl:choose><xsl:choose><xsl:when test="geo:lat and geo:long"><xsl:variable name="lat" select="geo:lat"/><xsl:variable name="lng" select="geo:long"/><span class="geolocation"><a href="geo:{$lat},{$lng}">๐Ÿ“</a></span></xsl:when><xsl:when test="geo:Point"><xsl:variable name="lat" select="geo:Point/geo:lat"/><xsl:variable name="lng" select="geo:Point/geo:long"/><span class="geolocation"><a href="geo:{$lat},{$lng}">๐Ÿ“</a></span></xsl:when><xsl:when test="georss:point"><xsl:variable name="lat" select="substring-before(georss:point, &quot; &quot;)"/><xsl:variable name="lng" select="substring-after(georss:point, &quot; &quot;)"/><xsl:variable name="name" select="georss:featurename"/><span class="geolocation"><a href="geo:{$lat},{$lng}" title="{$name}">๐Ÿ“</a></span></xsl:when></xsl:choose><xsl:if test="dc:date"><div class="published"><xsl:value-of select="dc:date"/></div></xsl:if><xsl:choose><xsl:when test="content:encoded"><div class="content"><xsl:value-of select="content:encoded" disable-output-escaping="yes"/></div></xsl:when><xsl:when test="foo:description"><div class="content"><xsl:value-of select="foo:description" disable-output-escaping="yes"/></div></xsl:when><xsl:when test="itunes:summary"><div class="content"><xsl:value-of select="itunes:summary" disable-output-escaping="yes"/></div></xsl:when><xsl:otherwise><div class="warning rss description"/></xsl:otherwise></xsl:choose><xsl:if test="enc:enclosure"><div class="enclosure" title="Right-click and Save link asโ€ฆ"><xsl:for-each select="enc:enclosure"><xsl:element name="span"><xsl:attribute name="icon"><xsl:value-of select="substring-before(@enc:type,&quot;/&quot;)"/></xsl:attribute></xsl:element><xsl:element name="a"><xsl:attribute name="href"><xsl:value-of select="@rdf:resource"/></xsl:attribute><xsl:attribute name="download"/><xsl:call-template name="extract-filename"><xsl:with-param name="url" select="@rdf:resource"/></xsl:call-template></xsl:element><xsl:element name="span"><xsl:attribute name="class"><xsl:value-of select="substring-before(@enc:type,&quot;/&quot;)"/></xsl:attribute></xsl:element><xsl:if test="@enc:length &gt; 0"><xsl:call-template name="transform-filesize"><xsl:with-param name="length" select="@enc:length"/></xsl:call-template></xsl:if><xsl:element name="br"/></xsl:for-each></div></xsl:if></div></xsl:for-each></xsl:when><xsl:otherwise><div class="notice no-entry"/></xsl:otherwise></xsl:choose></section></div></body></html></xsl:template><xsl:output media-type="application/rss+xml"/><xsl:template match="/rss"><xsl:variable name="rtl" select="channel/language[ contains(text(),&quot;ar&quot;) or contains(text(),&quot;fa&quot;) or contains(text(),&quot;he&quot;) or contains(text(),&quot;ji&quot;) or contains(text(),&quot;ku&quot;) or contains(text(),&quot;ur&quot;) or contains(text(),&quot;yi&quot;)]"/><html><head><xsl:call-template name="metadata"><xsl:with-param name="name" select="&quot;description&quot;"/><xsl:with-param name="content" select="channel/description"/></xsl:call-template><xsl:call-template name="metadata"><xsl:with-param name="name" select="&quot;generator&quot;"/><xsl:with-param name="content" select="&quot;syndication4humans https://sjehuda.github.io/&quot;"/></xsl:call-template><xsl:call-template name="metadata"><xsl:with-param name="name" select="&quot;mimetype&quot;"/><xsl:with-param name="content" select="&quot;application/rss+xml&quot;"/></xsl:call-template><title><xsl:choose><xsl:when test="channel/title and not(channel/title=&quot;&quot;)"><xsl:value-of select="channel/title"/></xsl:when><xsl:otherwise>Streamburner News Reader</xsl:otherwise></xsl:choose></title><xsl:if test="$rtl"><meta name="semitic" content="true"/></xsl:if></head><body><div id="feed"><header><div id="title"><xsl:choose><xsl:when test="channel/title and not(channel/title=&quot;&quot;)"><xsl:attribute name="title"><xsl:value-of select="channel/title"/></xsl:attribute><xsl:value-of select="channel/title"/></xsl:when><xsl:otherwise><div class="empty"/></xsl:otherwise></xsl:choose></div><xsl:choose><xsl:when test="channel/itunes:subtitle"><div id="subtitle"><xsl:attribute name="title"><xsl:value-of select="channel/itunes:subtitle"/></xsl:attribute><xsl:value-of select="channel/itunes:subtitle"/></div></xsl:when><xsl:when test="channel/description"><div id="subtitle"><xsl:attribute name="title"><xsl:value-of select="channel/description"/></xsl:attribute><xsl:value-of select="channel/description"/></div></xsl:when></xsl:choose></header><section id="links"><a title="Click to get the latest updates and news" onclick="location.href = &quot;feed:&quot; + location.href"></a><a title="Subscribe via SubToMe"><xsl:attribute name="href">https://www.subtome.com/#/subscribe?feeds=<xsl:value-of select="atom:link[@rel=&quot;self&quot;]/@href"/></xsl:attribute><xsl:attribute name="onclick">(function(btn){var z=document.createElement(&quot;script&quot;);document.subtomeBtn=btn;z.src=&quot;https://www.subtome.com/load.js&quot;;document.body.appendChild(z);})(this);return false;</xsl:attribute></a><a title="Learn about syndication feed" onclick="document.getElementById(&quot;aboutfeed&quot;).classList.toggle(&quot;show&quot;);" class="popup"><span class="popuptext" id="aboutfeed"/></a><a href="https://wikiless.org/wiki/Template:Aggregators" title="Get a feed reader for desktop and mobile"/><a href="https://wikiless.org/wiki/RSS" title="Learn the benefits of using feeds for personal and corporates"/></section><xsl:choose><xsl:when test="channel/item"><div id="toc"><xsl:for-each select="channel/item[not(position() &gt;20)]"><xsl:choose><xsl:when test="itunes:subtitle"><xsl:element name="a"><xsl:attribute name="href"><xsl:text>#newspaper-oujs-</xsl:text><xsl:value-of select="position()"/></xsl:attribute><xsl:value-of select="itunes:subtitle"/></xsl:element></xsl:when><xsl:when test="title"><xsl:element name="a"><xsl:attribute name="href"><xsl:text>#newspaper-oujs-</xsl:text><xsl:value-of select="position()"/></xsl:attribute><xsl:value-of select="title"/></xsl:element></xsl:when></xsl:choose></xsl:for-each></div></xsl:when></xsl:choose><section id="articles"><xsl:choose><xsl:when test="channel/item"><xsl:for-each select="channel/item[not(position() &gt;20)]"><div class="entry"><xsl:choose><xsl:when test="itunes:subtitle"><div class="title"><xsl:element name="a"><xsl:attribute name="href"><xsl:value-of select="link"/></xsl:attribute><xsl:attribute name="title"><xsl:value-of select="itunes:subtitle"/></xsl:attribute><xsl:attribute name="id"><xsl:text>newspaper-oujs-</xsl:text><xsl:value-of select="position()"/></xsl:attribute><xsl:value-of select="itunes:subtitle"/></xsl:element></div></xsl:when><xsl:when test="title"><div class="title"><xsl:element name="a"><xsl:attribute name="href"><xsl:value-of select="link"/></xsl:attribute><xsl:attribute name="title"><xsl:value-of select="title"/></xsl:attribute><xsl:attribute name="id"><xsl:text>newspaper-oujs-</xsl:text><xsl:value-of select="position()"/></xsl:attribute><xsl:value-of select="title"/></xsl:element></div></xsl:when><xsl:otherwise><div class="warning rss2 title"/></xsl:otherwise></xsl:choose><xsl:choose><xsl:when test="geo:lat and geo:long"><xsl:variable name="lat" select="geo:lat"/><xsl:variable name="lng" select="geo:long"/><span class="geolocation"><a href="geo:{$lat},{$lng}">๐Ÿ“</a></span></xsl:when><xsl:when test="geo:Point"><xsl:variable name="lat" select="geo:Point/geo:lat"/><xsl:variable name="lng" select="geo:Point/geo:long"/><span class="geolocation"><a href="geo:{$lat},{$lng}">๐Ÿ“</a></span></xsl:when><xsl:when test="georss:point"><xsl:variable name="lat" select="substring-before(georss:point, &quot; &quot;)"/><xsl:variable name="lng" select="substring-after(georss:point, &quot; &quot;)"/><xsl:variable name="name" select="georss:featurename"/><span class="geolocation"><a href="geo:{$lat},{$lng}" title="{$name}">๐Ÿ“</a></span></xsl:when></xsl:choose><xsl:if test="pubDate"><div class="published"><xsl:value-of select="pubDate"/></div></xsl:if><xsl:choose><xsl:when test="content:encoded"><div class="content"><xsl:value-of select="content:encoded" disable-output-escaping="yes"/></div></xsl:when><xsl:when test="description"><div class="content"><xsl:value-of select="description" disable-output-escaping="yes"/></div></xsl:when><xsl:when test="itunes:summary"><div class="content"><xsl:value-of select="itunes:summary" disable-output-escaping="yes"/></div></xsl:when><xsl:otherwise><div class="warning rss2 description"/></xsl:otherwise></xsl:choose><xsl:if test="enclosure or media:content"><div class="enclosure" title="Right-click and Save link asโ€ฆ"><xsl:for-each select="enclosure"><xsl:element name="span"><xsl:attribute name="icon"><xsl:value-of select="substring-before(@type,&quot;/&quot;)"/></xsl:attribute></xsl:element><xsl:element name="a"><xsl:attribute name="href"><xsl:value-of select="@url"/></xsl:attribute><xsl:attribute name="download"/><xsl:call-template name="extract-filename"><xsl:with-param name="url" select="@url"/></xsl:call-template></xsl:element><xsl:element name="span"><xsl:attribute name="class"><xsl:value-of select="substring-before(@type,&quot;/&quot;)"/></xsl:attribute></xsl:element><xsl:if test="@length &gt; 0"><xsl:call-template name="transform-filesize"><xsl:with-param name="length" select="@length"/></xsl:call-template></xsl:if><xsl:element name="br"/></xsl:for-each><xsl:for-each select="media:content"><xsl:element name="span"><xsl:attribute name="icon"><xsl:value-of select="@medium"/></xsl:attribute></xsl:element><xsl:element name="a"><xsl:attribute name="href"><xsl:value-of select="@url"/></xsl:attribute><xsl:attribute name="download"/><xsl:call-template name="extract-filename"><xsl:with-param name="url" select="@url"/></xsl:call-template></xsl:element><xsl:element name="span"><xsl:attribute name="class"><xsl:value-of select="@medium"/></xsl:attribute></xsl:element><xsl:if test="@fileSize &gt; 0"><xsl:call-template name="transform-filesize"><xsl:with-param name="length" select="@fileSize"/></xsl:call-template></xsl:if><xsl:element name="br"/></xsl:for-each></div></xsl:if></div></xsl:for-each></xsl:when><xsl:otherwise><div class="notice no-entry"/></xsl:otherwise></xsl:choose></section></div></body></html></xsl:template><xsl:template name="metadata"><xsl:param name="name"/><xsl:param name="content"/><xsl:if test="$content and not($content=&quot;&quot;)"><xsl:element name="meta"><xsl:attribute name="name"><xsl:value-of select="$name"/></xsl:attribute><xsl:attribute name="content"><xsl:value-of select="$content"/></xsl:attribute></xsl:element></xsl:if></xsl:template><xsl:template name="extract-filename"><xsl:param name="url"/><xsl:choose><xsl:when test="substring($url, string-length($url) - string-length(&quot;/&quot;) + 1) = &quot;/&quot;"><xsl:value-of select="substring-after(substring($url, 1, string-length($url) - 1),&quot;://&quot;)"/></xsl:when><xsl:otherwise><xsl:choose><xsl:when test="contains($url,&quot;/&quot;) and contains(substring-after($url,&quot;/&quot;),&quot;.&quot;)"><xsl:call-template name="extract-filename"><xsl:with-param name="url" select="substring-after($url,&quot;/&quot;)"/></xsl:call-template></xsl:when><xsl:otherwise><xsl:value-of select="$url"/></xsl:otherwise></xsl:choose></xsl:otherwise></xsl:choose></xsl:template><xsl:template name="transform-filesize"><xsl:param name="length"/><xsl:choose><xsl:when test="$length &lt; 2"><xsl:value-of select="$length"/>Byte</xsl:when><xsl:when test="floor($length div 1024) &lt; 1"><xsl:value-of select="$length"/>Bytes</xsl:when><xsl:when test="floor($length div (1024 * 1024)) &lt; 1"><xsl:value-of select="floor($length div 1024)"/>.<xsl:value-of select="substring($length mod 1024,0,2)"/>KiB</xsl:when><xsl:when test="floor($length div (1024 * 1024 * 1024)) &lt; 1"><xsl:value-of select="floor($length div (1024 * 1024))"/>.<xsl:value-of select="substring($length mod (1024 * 1024),0,2)"/>MiB</xsl:when><xsl:otherwise><xsl:value-of select="floor($length div (1024 * 1024 * 1024))"/>.<xsl:value-of select="substring($length mod (1024 * 1024 * 1024),0,2)"/>GiB</xsl:otherwise></xsl:choose></xsl:template></xsl:stylesheet>';

  xsltStylesheet =
    domParser
    .parseFromString(
      xslFile, 'application/xml' // application/xslt+xml or text/xsl are Not Valid
    );

  xsltProcessor
  .importStylesheet(
    xsltStylesheet
  );

  newDocument =
    xsltProcessor
    .transformToDocument(
      xmlDocument
    );

  // FIXME
  // Blocked due to server policy
  // https://archlinux.org/feeds/packages/
  // https://www.openstreetmap.org/traces/rss
  // https://gultsch.social/@daniel.rss
  // NOTE
  // We can use inline style (i.e. style="")
  // but that would make the code lesser manageable
  stylesheet_ltr = "html,body{padding:0;margin:0}body{background:WhiteSmoke;color:#333;hyphens:auto}header{margin:0 -1em 1em -1em;margin-bottom:1em;padding:1em 1em 0 1em}#feed{min-width:400px;overflow:auto;position:relative}*{max-width:100%;object-fit:contain;height:auto}#logo{display:inline-block;float:left;overflow:hidden;position:relative;height:60px;width:60px;margin-right:9;padding-top:12}#logo>a>img{margin:auto;max-width:100%;position:absolute;width:5em;bottom:0;right:0;left:0;top:0}#title{font-variant:small-caps;text-align:center}#title{font-weight:bold;margin-bottom:0;overflow:hidden;-webkit-line-clamp:2;white-space:nowrap;margin:0;font-size:2.2em}#title .empty:before{font-variant:small-caps;content:'Streamburner News Dashboard';text-align:center}#subtitle{overflow:hidden;-webkit-line-clamp:2;white-space:wrap;font-weight:bold;font-size:1.5em;text-align:center;font-variant:small-caps}.container{display:flex}#links{border-top:.1em solid;margin:auto;width:50%;text-align:center;direction:ltr}#links>a{padding:10px;text-decoration:none;font-size:70%}#links>a:nth-child(1):after{content:'Follow';cursor:pointer;border-color:grey;border-left-style:solid;border-radius:1px;padding:6px;background:#eee !important}#links>a:nth-child(2):after{content:'SubToMe';cursor:pointer}#links>a:nth-child(3):after{content:'Whatโ€™s This?';cursor:help}#links>a:nth-child(4):after{content:'Get a News Reader'}#links>a:nth-child(5):after{content:'More Info...'}#toc{margin-left:3%;padding:5px}#toc:before{content:'Latest Updates';font-size:76%;font-weight:bold}#toc>a{text-decoration:none;font-size:66%;display:block;padding:5px 0;margin-left:1%}#toc>a:hover{text-decoration:underline}#toc>a:visited{text-decoration:line-through}.popup{position:relative;display:inline-block;cursor:pointer}.popup .popuptext{visibility:hidden;width:160px;color:#fff;border-radius:6px;padding:18px;position:absolute;z-index:1;background-color:#555;position:absolute;right:4%;position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);width:50%;text-align:left}.popup .popuptext:after{content:'๐Ÿ“ฐ Web Syndication News Feed \\A\\A ' ' Syndication Feed is a mean for content and media publishers ' 'to reach a wider audience easily. ' ' It allows you to receive information directly without the ' 'going from site to site. \\A\\A ' ' Essentially, a feed is a function that allows โ€œFeed Readersโ€ ' 'to access multiple websites automatically looking for new ' 'content and then posting the information about new content ' 'and updates to another website, mobile app or desktop software ' 'at the office. \\A\\A ' ' Feeds provide a way for users to keep up with the latest ' 'news, events and package and delivery status information ' 'posted on different websites such as social networks, torrent ' 'indexers or podcasts in one spot.';white-space:pre-wrap;line-height:1.8;font-size:150%}.popup .show{visibility:visible;-webkit-animation:fadeIn 1s;animation:fadeIn 1s}@-webkit-keyframes fadeIn{from{opacity:0}to{opacity:1}}@keyframes fadeIn{from{opacity:0}to{opacity:1}}#articles{justify-content:space-between;max-width:90%;margin:0 auto;padding:10px 0}#articles>*{margin:.5em;white-space:normal;vertical-align:top;margin-bottom:50px}.entry{border-bottom:inset;margin-left:auto;margin-right:auto;overflow:auto;line-height:1.6;font-size:85%;overflow-x:hidden}.entry:hover{background:#f8f9fa}.entry *{max-width:98%}.entry>a{white-space:normal}.title{cursor:pointer;display:inline-block;font-size:110%;font-weight:bold;text-decoration:underline;overflow:visible;text-overflow:ellipsis;white-space:nowrap;font-variant:small-caps}a{color:#333;display:inline-block}.geolocation>a{text-decoration:none;padding-left:6px}.author{font-size:75%;margin:0 auto 0 auto}.author:before{content:'By '}.author:after{content:' / '}.published,.updated{font-size:75%;margin:0 auto 0 auto}.content{margin:15px auto 15px 1%;inline-size:95%;text-indent:3px}.content[type='text']{font-family:monospace}code{overflow:auto;display:block;max-height:300px;border-radius:4px}.enclosure{background:#eee;border:1px solid GrayText;border-radius:4px;clear:both;color:#525c66;cursor:help;direction:ltr;font-size:.8em;margin:5px auto 15px 1%;padding:15px;vertical-align:middle;border:1px solid #aaa;border-radius:.5em;max-width:100%;moz-border-radius:.5em;padding:1em}.enclosure>span:after{content:' (Document file) '}.enclosure>span.executable:after{content:' (Executable file) '}.enclosure>span.image:after{content:' (Image file) '}.enclosure>span.audio:after{content:' (Audio file) '}.enclosure>span.video:after{content:' (Video file) '}.enclosure>span[icon]:after{content:'๐Ÿ“„๏ธ';margin:3px}.enclosure>span[icon='executable']:after{content:'๐Ÿ“ฆ๏ธ';margin:3px}.enclosure>span[icon='image']:after{content:'๐Ÿ–ผ๏ธ';margin:3px}.enclosure>span[icon='audio']:after{content:'๐ŸŽผ๏ธ';margin:3px}.enclosure>span[icon='video']:after{content:'๐Ÿ“ฝ๏ธ';margin:3px}.notice{text-align:center;display:block;font-size:130%;font-weight:lighter;font-variant-caps:small-caps;font-style:oblique;color:FireBrick}.warning{display:block;font-size:60%;font-weight:bold;color:DarkRed}.no-entry:after{content:'This news feed is empty'}.atom1.author:after{content:'Atom 1.0 Warning: Element </author> is missing'}.atom1.id:after{content:'Atom 1.0 Warning: Element </id> is missing'}.atom1.link:after{content:'Atom 1.0 Warning: Element </link> is missing'}.atom1.published:after{content:'Atom 1.0 Warning: Element </published> is missing'}.atom1.title:after{content:'Atom 1.0 Warning: Element </title> is missing'}.rss2.description:after{content:'RSS 2.0 Warning: Element </description> is missing'}.rss2.link:after{content:'RSS 2.0 Warning: Element </link> is missing'}.rss2.title:after{content:'RSS 2.0 Warning: Element </title> is missing'}abbr,acronym{border-bottom:1px dotted #c30}dt{font-weight:bold}";
  stylesheet_rtl = "html,body{text-align:right}#feed{direction:rtl}#logo{float:right;margin-left:9}.geolocation>a{padding-right:6px}.image{float:right;margin-left:40px;margin-right:auto}"
  style = newDocument.createElement('style');
  newDocument.head.append(style);
  style.type = 'text/css';

  // NOTE
  // Because we use JS, maybe it is better to set direction by
  // the letters of the initial set of words.
  var isRTL =
    newDocument
    .querySelector(
      'meta[name="semitic"]'
    );

  if (isRTL) {
    style.innerHTML =
      stylesheet_ltr +
      stylesheet_rtl;
  } else {
    style.innerHTML =
      stylesheet_ltr;
  }

  //var newDoc = document.adoptNode(newDoc.documentElement, true);
  insertDocument =
    document
    .importNode(
      newDocument
      .documentElement,
      true
    );

  removeDocument =
    document
    .documentElement;

  document
  .replaceChild(
    insertDocument,
    removeDocument
  );

}

function queryByXPath(queries) {
  var result;
  let i = 0;
  do {
    result = document.evaluate(
      queries[i], document,
      null, XPathResult.STRING_TYPE);
    i = i + 1;
    result = result.stringValue;
  } while (!result && i < queries.length);
  return result;
}

Conclusion: Examine Promise with XMLHttpRequest.