refactor: html format (#3062)

* refactor: html format

Fix a few small bugs too

* fix

* fix

* trigger build

* striptags instead of encode title
This commit is contained in:
Dag 2022-10-16 12:03:57 +02:00 committed by GitHub
parent 78fa03238c
commit e21394d2d3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 141 additions and 121 deletions

View File

@ -24,7 +24,7 @@ class TelegramBridge extends BridgeAbstract
'http://telegram.me/rssbridge' => ['username' => 'rssbridge'],
];
const CACHE_TIMEOUT = 900; // 15 mins
const CACHE_TIMEOUT = 60 * 15; // 15 mins
private $feedName = '';
private $enclosures = [];

View File

@ -7,137 +7,56 @@ class HtmlFormat extends FormatAbstract
public function stringify()
{
$extraInfos = $this->getExtraInfos();
$title = e($extraInfos['name']);
$uri = e($extraInfos['uri']);
$donationUri = e($extraInfos['donationUri']);
$donationsAllowed = Configuration::getConfig('admin', 'donations');
// Dynamically build buttons for all formats (except HTML)
$formatFactory = new FormatFactory();
$buttons = '';
$links = '';
$buttons = [];
$linkTags = [];
foreach ($formatFactory->getFormatNames() as $format) {
// Dynamically build buttons for all formats (except HTML)
if ($format === 'Html') {
continue;
}
$queryString = $_SERVER['QUERY_STRING'];
$query = str_ireplace('format=Html', 'format=' . $format, htmlentities($queryString));
$buttons .= sprintf('<a href="./?%s"><button class="rss-feed">%s</button></a>', $query, $format) . "\n";
$mime = $formatFactory->create($format)->getMimeType();
$links .= sprintf('<link href="./?%s" title="%s" rel="alternate" type="%s">', $query, $format, $mime) . "\n";
$formatUrl = '?' . str_ireplace('format=Html', 'format=' . $format, htmlentities($_SERVER['QUERY_STRING']));
$buttons[] = [
'href' => $formatUrl,
'value' => $format,
];
$linkTags[] = [
'href' => $formatUrl,
'title' => $format,
'type' => $formatFactory->create($format)->getMimeType(),
];
}
if ($donationUri !== '' && $donationsAllowed) {
$str = sprintf(
'<a href="%s" target="_blank"><button class="highlight">Donate to maintainer</button></a>',
$donationUri
);
$buttons .= $str;
$str1 = sprintf(
'<link href="%s target="_blank"" title="Donate to Maintainer" rel="alternate">',
$donationUri
);
$links .= $str1;
if (Configuration::getConfig('admin', 'donations') && $extraInfos['donationUri'] !== '') {
$buttons[] = [
'href' => e($extraInfos['donationUri']),
'value' => 'Donate to maintainer',
];
}
$entries = '';
$items = [];
foreach ($this->getItems() as $item) {
if ($item->getAuthor()) {
$entryAuthor = sprintf('<br /><p class="author">by: %s</p>', $item->getAuthor());
} else {
$entryAuthor = '';
}
$entryTitle = sanitize_html(strip_tags($item->getTitle()));
$entryUri = $item->getURI() ?: $uri;
$entryDate = '';
if ($item->getTimestamp()) {
$entryDate = sprintf(
'<time datetime="%s">%s</time>',
date('Y-m-d H:i:s', $item->getTimestamp()),
date('Y-m-d H:i:s', $item->getTimestamp())
);
}
$entryContent = '';
if ($item->getContent()) {
$str2 = sprintf('<div class="content">%s</div>', sanitize_html($item->getContent()));
$entryContent = $str2;
}
$entryEnclosures = '';
if (!empty($item->getEnclosures())) {
$entryEnclosures = '<div class="attachments"><p>Attachments:</p>';
foreach ($item->getEnclosures() as $enclosure) {
$template = '<li class="enclosure"><a href="%s" rel="noopener noreferrer nofollow">%s</a></li>';
$url = sanitize_html($enclosure);
$anchorText = substr($url, strrpos($url, '/') + 1);
$entryEnclosures .= sprintf($template, $url, $anchorText);
}
$entryEnclosures .= '</div>';
}
$entryCategories = '';
if (!empty($item->getCategories())) {
$entryCategories = '<div class="categories"><p>Categories:</p>';
foreach ($item->getCategories() as $category) {
$entryCategories .= '<li class="category">'
. sanitize_html($category)
. '</li>';
}
$entryCategories .= '</div>';
}
$entries .= <<<EOD
<section class="feeditem">
<h2><a class="itemtitle" href="{$entryUri}">{$entryTitle}</a></h2>
{$entryDate}
{$entryAuthor}
{$entryContent}
{$entryEnclosures}
{$entryCategories}
</section>
EOD;
$items[] = [
'url' => $item->getURI() ?: $extraInfos['uri'],
'title' => $item->getTitle() ?? '(no title)',
'timestamp' => $item->getTimestamp(),
'author' => $item->getAuthor(),
'content' => $item->getContent() ?? '',
'enclosures' => $item->getEnclosures(),
'categories' => $item->getCategories(),
];
}
$charset = $this->getCharset();
$toReturn = <<<EOD
<!DOCTYPE html>
<html>
<head>
<meta charset="{$charset}">
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>{$title}</title>
<link href="static/HtmlFormat.css" rel="stylesheet">
<link rel="icon" type="image/png" href="static/favicon.png">
{$links}
<meta name="robots" content="noindex, follow">
</head>
<body>
<h1 class="pagetitle"><a href="{$uri}" target="_blank">{$title}</a></h1>
<div class="buttons">
<a href="./#bridge-{$_GET['bridge']}"><button class="backbutton"> back to rss-bridge</button></a>
{$buttons}
</div>
{$entries}
</body>
</html>
EOD;
$html = render_template(__DIR__ . '/../templates/html-format.html.php', [
'charset' => $this->getCharset(),
'title' => $extraInfos['name'],
'linkTags' => $linkTags,
'uri' => $extraInfos['uri'],
'buttons' => $buttons,
'items' => $items,
]);
// Remove invalid characters
ini_set('mbstring.substitute_character', 'none');
$toReturn = mb_convert_encoding($toReturn, $this->getCharset(), 'UTF-8');
return $toReturn;
return mb_convert_encoding($html, $this->getCharset(), 'UTF-8');
}
}

View File

@ -42,7 +42,7 @@ interface FormatInterface
* Return items
*
* @throws \LogicException if the items are not set
* @return array The items
* @return FeedItem[] The items
*/
public function getItems();

View File

@ -18,15 +18,26 @@ function render(string $template, array $context = []): string
return render_template('base.html.php', $context);
}
/**
* Render template as absolute path or relative to templates folder.
* Do not pass user input in $template
*/
function render_template(string $template, array $context = []): string
{
if (isset($context['template'])) {
throw new \Exception("Don't use `template` as a context key");
}
$templateFilepath = __DIR__ . '/../templates/' . $template;
extract($context);
ob_start();
try {
require __DIR__ . '/../templates/' . $template;
if (is_file($template)) {
require $template;
} elseif (is_file($templateFilepath)) {
require $templateFilepath;
} else {
throw new \Exception(sprintf('Unable to find template `%s`', $template));
}
} catch (\Throwable $e) {
ob_end_clean();
throw $e;

View File

@ -0,0 +1,90 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="<?= $charset ?>">
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title><?= e($title) ?></title>
<link href="static/HtmlFormat.css" rel="stylesheet">
<link rel="icon" type="image/png" href="static/favicon.png">
<?php foreach ($linkTags as $link): ?>
<link
href="<?= $link['href'] ?>"
title="<?= $link['title'] ?>"
rel="alternate"
type="<?= $link['type'] ?>"
>
<?php endforeach; ?>
<meta name="robots" content="noindex, follow">
</head>
<body>
<h1 class="pagetitle">
<a href="<?= e($uri) ?>" target="_blank">
<?= e($title) ?>
</a>
</h1>
<div class="buttons">
<a href="./#bridge-<?= $_GET['bridge'] ?>">
<button class="backbutton"> back to rss-bridge</button>
</a>
<?php foreach ($buttons as $button): ?>
<a href="<?= $button['href'] ?>">
<button class="rss-feed"><?= $button['value'] ?></button>
</a>
<?php endforeach; ?>
</div>
<?php foreach ($items as $item): ?>
<section class="feeditem">
<h2>
<a
class="itemtitle"
href="<?= e($item['url']) ?>"
><?= strip_tags($item['title']) ?></a>
</h2>
<?php if ($item['timestamp']): ?>
<time datetime="<?= date('Y-m-d H:i:s', $item['timestamp']) ?>">
<?= date('Y-m-d H:i:s', $item['timestamp']) ?>
</time>
<?php endif; ?>
<?php if ($item['author']): ?>
<br/>
<p class="author">by: <?= e($item['author']) ?></p>
<?php endif; ?>
<div class="content">
<?= sanitize_html($item['content']) ?>
</div>
<?php if ($item['enclosures']): ?>
<div class="attachments">
<p>Attachments:</p>
<?php foreach ($item['enclosures'] as $enclosure): ?>
<li class="enclosure">
<a href="<?= e($enclosure) ?>" rel="noopener noreferrer nofollow">
<?= e(substr($enclosure, strrpos($enclosure, '/') + 1)) ?>
</a>
</li>
<?php endforeach; ?>
</div>
<?php endif; ?>
<?php if ($item['categories']): ?>
<div class="categories">
<p>Categories:</p>
<?php foreach ($item['categories'] as $category): ?>
<li class="category"><?= e($category) ?></li>
<?php endforeach; ?>
</div>
<?php endif; ?>
</section>
<?php endforeach; ?>
</body>
</html>