├── .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 |
2 | set_time_limit(240);
3 | ini_set("default_socket_timeout", 120);
4 |
5 | if(isset($_GET["url"])) {
6 | function eschtml($str) {
7 | return str_replace(array(">", "<", "\""), 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 "\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 = "= $text ?>";
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 |
175 | }
176 | }
177 | else {
178 | ?>
179 |
180 |
181 |
182 |
183 | RSS 2 HTML
184 |
185 |
186 |
187 |
188 |
189 |
190 |
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 |
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 |
341 | }
342 | ?>
343 |
--------------------------------------------------------------------------------