├── .gitignore ├── Procfile ├── .user.ini ├── composer.json ├── favicon.ico ├── images └── top1.png ├── composer.lock ├── LICENSE ├── scripts └── parse.js ├── style.css └── index.php /.gitignore: -------------------------------------------------------------------------------- 1 | vendor/ -------------------------------------------------------------------------------- /Procfile: -------------------------------------------------------------------------------- 1 | web: vendor/bin/heroku-php-nginx -------------------------------------------------------------------------------- /.user.ini: -------------------------------------------------------------------------------- 1 | short_open_tag = On; 2 | log_errors = Off; -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "require": { 3 | "php": "~7.0" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bloopletech/rss2html/HEAD/favicon.ico -------------------------------------------------------------------------------- /images/top1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bloopletech/rss2html/HEAD/images/top1.png -------------------------------------------------------------------------------- /composer.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_readme": [ 3 | "This file locks the dependencies of your project to a known state", 4 | "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", 5 | "This file is @generated automatically" 6 | ], 7 | "content-hash": "53b7fe9174a2e47a39af26686e3abdf4", 8 | "packages": [], 9 | "packages-dev": [], 10 | "aliases": [], 11 | "minimum-stability": "stable", 12 | "stability-flags": [], 13 | "prefer-stable": false, 14 | "prefer-lowest": false, 15 | "platform": { 16 | "php": "~7.0" 17 | }, 18 | "platform-dev": [] 19 | } 20 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2007-2017 Brenton Fletcher (http://blog.bloople.net i@bloople.net) 2 | 3 | Permission is hereby granted, free of charge, to any person 4 | obtaining a copy of this software and associated documentation 5 | files (the "Software"), to deal in the Software without 6 | restriction, including without limitation the rights to use, 7 | copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the 9 | Software is furnished to do so, subject to the following 10 | conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /scripts/parse.js: -------------------------------------------------------------------------------- 1 | $ = document.getElementById.bind(document); 2 | 3 | function showAdvanced() { 4 | document.body.classList.toggle("show-advanced"); 5 | $("showopt").value = document.body.classList.contains("show-advanced") ? "Less options" : "More options"; 6 | } 7 | 8 | function doParse() { 9 | var detail = ""; 10 | if($("detailhide").checked) detail = "&detail=-1"; 11 | if($("detailshow").checked) detail = "&detail=" + $("detailnum").value; 12 | 13 | var limit = $("limit").checked ? ("&limit=" + $("limitnum").value) : ""; 14 | 15 | var advanced = document.body.classList.contains("show-advanced"); 16 | var showtitle = (advanced && $("showtitle").checked ? "" : "&showtitle=false"); 17 | var showicon = (advanced && $("showicon").checked ? "&showicon=true" : ""); 18 | var showempty = (advanced && $("showempty").checked ? "&showempty=true" : ""); 19 | var striphtml = (advanced && $("striphtml").checked ? "&striphtml=true" : ""); 20 | var forceutf8 = (advanced && $("forceutf8").checked ? "&forceutf8=true" : ""); 21 | var fixbugs = (advanced && $("fixbugs").checked ? "&fixbugs=true" : ""); 22 | 23 | var path = "/?url=" + encodeURIComponent($("url").value) + detail + limit + showtitle + showicon + showempty + striphtml + forceutf8 + fixbugs; 24 | var url = "//rss.bloople.net" + path; 25 | var code = ""; 26 | 27 | var type = $("form").elements["codegen"].value; 28 | if(type == "php") code = ""; 29 | else if(type == "js") code = ""; 30 | else if(type == "html") code = ""; 31 | 32 | $("codeout").value = code; 33 | $("live-example").src = path; 34 | 35 | document.body.classList.add("submitted"); 36 | 37 | return false; 38 | } 39 | 40 | window.onload = function() { 41 | $("form").onsubmit = doParse; 42 | 43 | $("limitnum").onclick = function() { 44 | $("limit").checked = true; 45 | }; 46 | 47 | $("detailnum").onclick = function() { 48 | $("detailshow").checked = true; 49 | }; 50 | 51 | $("url").focus(); 52 | }; -------------------------------------------------------------------------------- /style.css: -------------------------------------------------------------------------------- 1 | * { 2 | box-sizing: border-box; 3 | } 4 | 5 | body { 6 | font-family: "Open Sans", Tahoma, Helvetica, Arial, sans-serif; 7 | font-size: 16px; 8 | line-height: 1.4; 9 | background-color: #ffffff; 10 | color: #000000; 11 | margin: 0px; 12 | padding: 0px; 13 | } 14 | 15 | h1 { 16 | margin: 0; 17 | padding: 0; 18 | font-size: 40px; 19 | color: #ffffff; 20 | } 21 | 22 | h3 { 23 | margin: 0 0 10px 0; 24 | padding: 0; 25 | font-size: 20px; 26 | font-weight: bold; 27 | } 28 | 29 | 30 | hr { border: none; height: 1px; background-color: #808080; margin: 5px 0; } 31 | hr.p-after { margin-bottom: 1.1em; } 32 | 33 | header { 34 | text-align: center; 35 | padding-top: 19px; 36 | height: 90px; 37 | background: url(images/top1.png) repeat-x; 38 | } 39 | 40 | .mast { 41 | font-size: 18px; 42 | } 43 | 44 | #mainbody { 45 | margin: 20px; 46 | } 47 | 48 | 49 | 50 | p { 51 | margin: 0 0 20px 0; 52 | padding: 0; 53 | } 54 | 55 | form { 56 | padding: 0px; 57 | margin: 0px; 58 | } 59 | 60 | label { 61 | display: block; 62 | } 63 | 64 | input, textarea { 65 | font-size: 100%; 66 | } 67 | 68 | #url { 69 | width: 100%; 70 | } 71 | 72 | input[type="text"], textarea, iframe { 73 | border: 1px solid #aaa; 74 | padding: 3px; 75 | } 76 | 77 | textarea { 78 | width: 100%; 79 | height: 100px; 80 | } 81 | 82 | iframe { 83 | width: 100%; 84 | height: 400px; 85 | } 86 | 87 | table { 88 | border-collapse: collapse; 89 | width: 800px; 90 | margin-bottom: 20px; 91 | } 92 | 93 | @media screen and (max-width: 839px) { 94 | table { 95 | width: 100%; 96 | } 97 | } 98 | 99 | table, tr, td { 100 | border: none; 101 | } 102 | 103 | td { 104 | padding: 0.5em 0.3em; 105 | vertical-align: top; 106 | border-bottom: 1px dotted #808080; 107 | } 108 | 109 | table td.l { 110 | width: 12em; 111 | text-align: right; 112 | } 113 | 114 | input.text { width: 30em; } 115 | input.num { width: 3em; } 116 | 117 | .results td { 118 | display: none; 119 | } 120 | 121 | .advanced td { 122 | display: none; 123 | } 124 | 125 | body.show-advanced .advanced td { 126 | display: table-cell; 127 | } 128 | 129 | body.submitted .results td { 130 | display: table-cell; 131 | } 132 | 133 | .actions { 134 | text-align: right; 135 | } 136 | 137 | input[type="button"], input[type="submit"] { 138 | display: inline-block; 139 | margin: 0; 140 | padding: 6px 12px; 141 | border-radius: 4px; 142 | text-align: center; 143 | vertical-align: middle; 144 | cursor: pointer; 145 | user-select: none; 146 | touch-action: manipulation; 147 | } 148 | 149 | input[type="button"] { 150 | color: #ffffff; 151 | background-color: #31b0d5; 152 | border: 1px solid #269abc; 153 | } 154 | 155 | input[type="submit"] { 156 | color: #ffffff; 157 | background-color: #5cb85c; 158 | border: 1px solid #4cae4c; 159 | } 160 | 161 | #showopt { 162 | margin-right: 10px; 163 | } 164 | 165 | .footer { background-color: #ffffaa; padding: 3px; } 166 | -------------------------------------------------------------------------------- /index.php: -------------------------------------------------------------------------------- 1 | ", "<", "\""), array(">", "<", """), $str); 8 | } 9 | 10 | function remtags($str) { 11 | $str = html_entity_decode($str, ENT_COMPAT, "UTF-8"); 12 | return strip_tags($str); 13 | } 14 | 15 | $url = $_GET["url"]; 16 | $detail = (isset($_GET["detail"]) ? intval($_GET["detail"]) : 2147483647); 17 | $limit = (isset($_GET["limit"]) ? $_GET["limit"] : 2147483647); 18 | $striphtml = (isset($_GET["striphtml"]) ? ($_GET["striphtml"] == "true") : false); 19 | $showtitle = (isset($_GET["showtitle"]) ? ($_GET["showtitle"] == "true") : true); 20 | $showtitledesc = (isset($_GET["showtitledesc"]) ? ($_GET["showtitledesc"] == "true") : false); 21 | $titleprefix = (isset($_GET["titleprefix"]) ? $_GET["titleprefix"] : ""); 22 | $titlereplacement = (isset($_GET["titlereplacement"]) ? $_GET["titlereplacement"] : ""); 23 | $titledescprefix = (isset($_GET["titledescprefix"]) ? $_GET["titledescprefix"] : ""); 24 | $itemtitleprefix = (isset($_GET["itemtitleprefix"]) ? $_GET["itemtitleprefix"] : ""); 25 | $itemdescprefix = (isset($_GET["itemdescprefix"]) ? $_GET["itemdescprefix"] : ""); 26 | $showicon = (isset($_GET["showicon"]) ? ($_GET["showicon"] == "true") : false); 27 | $showempty = (isset($_GET["showempty"]) ? ($_GET["showempty"] == "true") : false); 28 | $type = (isset($_GET["type"]) ? $_GET["type"] : "php"); 29 | $fixbugs = (isset($_GET["fixbugs"]) ? ($_GET["fixbugs"] == "true") : false); 30 | $forceutf8 = (isset($_GET["forceutf8"]) ? ($_GET["forceutf8"] == "true") : false); 31 | 32 | if($type == "html") { 33 | header("Content-Type: text/html; charset=utf-8"); 34 | echo "\n\n\n\n\n"; 35 | } 36 | else if($type == "js") { 37 | header("Content-Type: text/javascript; charset=utf-8"); 38 | ob_start(); 39 | } 40 | 41 | $headers = "Connection: close\r\n". 42 | "User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36\r\n". 43 | "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n". 44 | "Accept-Language: en-us,en;q=0.5\r\n". 45 | "Referer: /\r\n"; 46 | 47 | $http_context = array( 48 | 'protocol_version' => 1.1, 49 | 'method' => 'GET', 50 | 'header' => $headers 51 | ); 52 | $feedtext = file_get_contents($url, false, stream_context_create(array('http' => $http_context))); 53 | $feedtext = trim($feedtext); 54 | 55 | if($fixbugs) { 56 | $feedtext = str_replace("& ", " & ", $feedtext); 57 | 58 | $feedtext = str_replace("&x80;", "€", $feedtext); 59 | $feedtext = str_replace("&x81;", "‘", $feedtext); 60 | $feedtext = str_replace("&x85;", "…", $feedtext); 61 | $feedtext = str_replace("&x86;", "†", $feedtext); 62 | $feedtext = str_replace("&x87;", "‡", $feedtext); 63 | $feedtext = str_replace("&x88;", "ˆ", $feedtext); 64 | $feedtext = str_replace("&x89;", "‰", $feedtext); 65 | $feedtext = str_replace("&x8A;", "Š", $feedtext); 66 | $feedtext = str_replace("&x8B;", "‹", $feedtext); 67 | $feedtext = str_replace("&x8C;", "Œ", $feedtext); 68 | $feedtext = str_replace("&x8E", "", $feedtext); 69 | $feedtext = str_replace("&x91;", "‘", $feedtext); 70 | $feedtext = str_replace("&x92;", "’", $feedtext); 71 | $feedtext = str_replace("&x93;", "“", $feedtext); 72 | $feedtext = str_replace("&x94;", "”", $feedtext); 73 | $feedtext = str_replace("&x95;", "•", $feedtext); 74 | $feedtext = str_replace("&x96;", "-", $feedtext); 75 | $feedtext = str_replace("&x97;", "—", $feedtext); 76 | $feedtext = str_replace("&x98;", "˜", $feedtext); 77 | $feedtext = str_replace("&x99;", "™", $feedtext); 78 | $feedtext = str_replace("&x9A;", "š", $feedtext); 79 | $feedtext = str_replace("&x9B;", "›", $feedtext); 80 | $feedtext = str_replace("&x9C;", "&eolig;", $feedtext); 81 | $feedtext = str_replace("&x9E;", "", $feedtext); 82 | $feedtext = str_replace("&x9F;", "Ÿ", $feedtext); 83 | } 84 | 85 | if($forceutf8) { 86 | $feedtext = preg_replace("/<\?xml(.*?)encoding=['\"].*?['\"](.*?)\?>/m", "", $feedtext); 87 | } 88 | 89 | $doc = new DOMDocument(); 90 | $doc->loadXML($feedtext); 91 | 92 | function search($tag, $context, $single = true) { 93 | $nodes = $context->getElementsByTagName($tag); 94 | 95 | if($nodes->length > 0) return $single ? $nodes->item(0) : $nodes; 96 | return NULL; 97 | } 98 | 99 | if($showtitle == true) { 100 | $channel = search("channel", $doc); 101 | 102 | $title = search("title", $channel); 103 | $title = eschtml((isset($title) ? $titleprefix.$title->textContent : "(No feed title)")); 104 | if($titlereplacement) $title = $titlereplacement; 105 | if($striphtml) $title = remtags($title); 106 | 107 | $link = search("link", $channel); 108 | $link = ($link ? (isset($eschtml) ? eschtml($link->textContent) : $link->textContent) : ""); 109 | if($link != "") $title = "$title"; 110 | if($striphtml) $link = remtags($link); 111 | 112 | $desc = search("description", $channel); 113 | $desc = eschtml(isset($desc) ? $desc->textContent : ""); 114 | if($striphtml) $desc = remtags($desc); 115 | 116 | $image = search("url", $channel); 117 | $image = (isset($image) ? $image->textContent : ""); 118 | 119 | if($showicon && $image != "") $title = "$title"; 120 | 121 | if($showempty || (!$showempty && $title != "")) echo "

$title

\n"; 122 | if($showtitledesc && ($showempty || (!$showempty && $desc != ""))) echo "

$titledescprefix$desc

\n"; 123 | } 124 | 125 | $items = search("item", $doc, false); 126 | 127 | foreach($items as $i => $item) { 128 | if($i == $limit) break; 129 | 130 | $title = search("title", $item); 131 | $title = (isset($title) ? eschtml($title->textContent) : "(No title)"); 132 | 133 | $link = search("link", $item); 134 | $link = (isset($link) ? eschtml($link->textContent) : ""); 135 | if($link != "") $title = "$title"; 136 | 137 | $desc = search("description", $item); 138 | $desc = (isset($desc) ? $desc->textContent : ""); 139 | if($striphtml) $desc = remtags($desc); 140 | 141 | if($showempty || (!$showempty && $title != "")) echo "

$itemtitleprefix$title

\n"; 142 | if(($detail > 0) && ($showempty || (!$showempty && $desc != ""))) { 143 | $words = explode(" ", $desc); 144 | if(count($words) > $detail) { 145 | $words = array_slice($words, 0, $detail); 146 | $desc = implode(" ", $words)."..."; 147 | } 148 | echo "

$itemdescprefix$desc

\n"; 149 | } 150 | } 151 | 152 | echo "
Powered by rss2html
\n
\n"; 153 | 154 | if($type == "html") { 155 | echo "\n"; 156 | } 157 | else if($type == "js") { 158 | $text = ob_get_contents(); 159 | ob_end_clean(); 160 | 161 | $text = str_replace("\n", "", str_replace("\"", "\\\"", $text)); 162 | 163 | ?> 164 | var container = document.createElement("div"); 165 | container.innerHTML = ""; 166 | var nodes = [].slice.call(container.childNodes); 167 | 168 | var script = document.scripts[document.scripts.length - 1]; 169 | var parent = script.parentNode; 170 | 171 | while(nodes.length > 0) parent.insertBefore(nodes.shift(), script); 172 | 173 | parent.removeChild(script); 174 | 179 | 180 | 181 | 182 | 183 | RSS 2 HTML 184 | 185 | 186 | 187 | 188 | 189 | 190 |
191 |

RSS 2 HTML

192 |
193 | 194 |
195 |

Welcome to RSS 2 HTML!

196 |

This page offers an easy way to embed RSS feeds in HTML webpages. One line of code in your webpage, and easily-styled HTML will be generated, with no advertisements or other restrictions.

197 |

Use the form below to generate the code to include in your webpage:

198 | 199 |
200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 213 | 214 | 215 | 216 | 222 | 223 | 224 | 225 | 239 | 240 | 241 | 242 | 248 | 249 | 250 | 251 | 257 | 258 | 259 | 260 | 266 | 267 | 268 | 269 | 275 | 276 | 277 | 278 | 284 | 285 | 286 | 287 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 311 | 312 | 313 | 317 | 318 |
URL of RSS feed:
208 | 212 |
217 | 221 |
Length of feed item descriptions: 226 | 230 | 234 | 238 |
243 | 247 |
252 | 256 |
261 | 265 |
270 | 274 |
279 | 283 |
How should the feed be embedded in your webpage: 288 | 292 | 296 | 300 |
Embed this code in your webpage:
Live example: 309 | 310 |
314 | 315 | 316 |
319 |
320 | 321 |

Styling the output

322 |

323 | The HTML generated by this code contains CSS hooks so you can style the output in your stylesheet.
324 | The title of the feed is displayed in a <h3> tag, with the class feed-title.
325 | The feed description is displayed in a <p> tag with class feed-desc.
326 | The feed icon is displayed in an <img> tag with class feed-title-image.
327 | Each feed item title is displayed in a <h4> tag with class feed-item-title.
328 | Each feed item description is displayed in a <p> tag with class feed-item-desc. 329 |

330 |

331 | Note that this code does not generate HTML for empty feed titles, descriptions, etc.
332 | If you want empty HTML to be generated, click "more options" and tick the "Output HTML for empty..." checkbox. 333 |

334 | 335 |
336 | 337 |
338 | 339 | 340 | 343 | --------------------------------------------------------------------------------