mirror of
https://github.com/martinrotter/rssguard.git
synced 2025-02-02 10:27:15 +01:00
better format for gemini articles in WebEngine version
This commit is contained in:
parent
3dde4064fb
commit
a352b7551e
@ -11,6 +11,7 @@
|
||||
|
||||
<file>scripts/builtin_js/observer.js</file>
|
||||
<file>scripts/web_ui/rssguard.html</file>
|
||||
<file>scripts/gemini/style.css</file>
|
||||
|
||||
<file>sounds/boing.wav</file>
|
||||
<file>sounds/rooster.wav</file>
|
||||
|
60
resources/scripts/gemini/style.css
Normal file
60
resources/scripts/gemini/style.css
Normal file
@ -0,0 +1,60 @@
|
||||
p {
|
||||
min-height: 0.1em;
|
||||
margin: 6px 0px;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6, ul, ol, pre {
|
||||
margin: 9px 0px;
|
||||
}
|
||||
|
||||
pre {
|
||||
font-family: "Consolas", "Andale Mono WT", "Andale Mono", "Lucida Console", "Lucida Sans Typewriter", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Liberation Mono", "Nimbus Mono L", Monaco, "Courier New", Courier, monospace;
|
||||
white-space: pre-wrap;
|
||||
overflow-x: auto;
|
||||
padding: 8px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
a:link {
|
||||
text-decoration-line: none;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration-line: underline;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
font-size: 1.2em;
|
||||
width: 80%;
|
||||
margin: 14px auto;
|
||||
font-family: "Open Sans";
|
||||
font-style: italic;
|
||||
color: #555555;
|
||||
padding: 1em 16px 1em 30px;
|
||||
border-left: 4px solid #75bff7;
|
||||
line-height: 1.1;
|
||||
position: relative;
|
||||
background: #EDEDED;
|
||||
}
|
||||
|
||||
blockquote::before {
|
||||
font-family: Arial;
|
||||
content: "\201C";
|
||||
color: #7598f7;
|
||||
font-size: 3em;
|
||||
position: absolute;
|
||||
left: 10px;
|
||||
top: 0px;
|
||||
}
|
||||
|
||||
blockquote::after {
|
||||
content: '';
|
||||
}
|
||||
|
||||
blockquote span {
|
||||
display: block;
|
||||
color: #333333;
|
||||
font-style: normal;
|
||||
font-weight: bold;
|
||||
margin-top: 1em;
|
||||
}
|
@ -15,11 +15,11 @@
|
||||
#include <QTimer>
|
||||
|
||||
Downloader::Downloader(QObject* parent)
|
||||
: QObject(parent), m_geminiClient(new GeminiClient(this)), m_activeReply(nullptr),
|
||||
m_downloadManager(new SilentNetworkAccessManager(this)), m_timer(new QTimer(this)), m_inputData(QByteArray()),
|
||||
m_inputMultipartData(nullptr), m_targetProtected(false), m_targetUsername(QString()), m_targetPassword(QString()),
|
||||
m_lastOutputData({}), m_lastOutputError(QNetworkReply::NetworkError::NoError), m_lastHttpStatusCode(0),
|
||||
m_lastHeaders({}) {
|
||||
: QObject(parent), m_geminiClient(new GeminiClient(this)), m_geminiParser(GeminiParser(false)),
|
||||
m_activeReply(nullptr), m_downloadManager(new SilentNetworkAccessManager(this)), m_timer(new QTimer(this)),
|
||||
m_inputData(QByteArray()), m_inputMultipartData(nullptr), m_targetProtected(false), m_targetUsername(QString()),
|
||||
m_targetPassword(QString()), m_lastOutputData({}), m_lastOutputError(QNetworkReply::NetworkError::NoError),
|
||||
m_lastHttpStatusCode(0), m_lastHeaders({}) {
|
||||
m_timer->setInterval(DOWNLOAD_TIMEOUT);
|
||||
m_timer->setSingleShot(true);
|
||||
|
||||
@ -50,7 +50,7 @@ void Downloader::geminiFinished(const QByteArray& data, const QString& mime) {
|
||||
m_lastOutputMultipartData = {};
|
||||
|
||||
if (mime.startsWith(QSL(GEMINI_MIME_TYPE))) {
|
||||
m_lastOutputData = GeminiParser().geminiToHtml(data).toUtf8();
|
||||
m_lastOutputData = m_geminiParser.geminiToHtml(data).toUtf8();
|
||||
}
|
||||
else {
|
||||
m_lastOutputData = data;
|
||||
|
@ -5,6 +5,7 @@
|
||||
|
||||
#include "definitions/definitions.h"
|
||||
#include "network-web/gemini/geminiclient.h"
|
||||
#include "network-web/gemini/geminiparser.h"
|
||||
#include "network-web/httpresponse.h"
|
||||
|
||||
#include <QHttpMultiPart>
|
||||
@ -105,6 +106,7 @@ class Downloader : public QObject {
|
||||
|
||||
private:
|
||||
GeminiClient* m_geminiClient;
|
||||
GeminiParser m_geminiParser;
|
||||
QNetworkReply* m_activeReply;
|
||||
QScopedPointer<SilentNetworkAccessManager> m_downloadManager;
|
||||
QTimer* m_timer;
|
||||
|
@ -12,12 +12,14 @@ QString GeminiParser::geminiToHtml(const QByteArray& gemini_data) {
|
||||
QStringList lines = gemini_hypertext.split(QL1C('\n'));
|
||||
mode = State::Normal;
|
||||
|
||||
static QRegularExpression exp_link(R"(^=>\s+([^\s]+)(?:\s+(\w.+))?$)");
|
||||
static QRegularExpression exp_link(R"(^=>\s+([^\s]+)(?:\s+(\S.+))?$)");
|
||||
static QRegularExpression exp_heading(R"(^(#{1,6})\s+(.+)$)");
|
||||
static QRegularExpression exp_list(R"(^\*\s(.+)$)");
|
||||
static QRegularExpression exp_quote(R"((?:^>$|^>\s?(.+)$))");
|
||||
static QRegularExpression exp_pre(R"(^```.*$)");
|
||||
|
||||
static QString rich_style = QString::fromUtf8(IOFactory::readFile(QSL(":/scripts/gemini/style.css")));
|
||||
|
||||
QRegularExpressionMatch mtch;
|
||||
QString title;
|
||||
|
||||
@ -69,13 +71,17 @@ QString GeminiParser::geminiToHtml(const QByteArray& gemini_data) {
|
||||
|
||||
html += endBlock(State::Normal);
|
||||
|
||||
// IOFactory::writeFile("aa", html.toUtf8());
|
||||
|
||||
return QSL("<html>"
|
||||
"<head><title>%1</title></head>"
|
||||
return QSL("<!DOCTYPE html>"
|
||||
"<html>"
|
||||
"<head>"
|
||||
"<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">"
|
||||
"<meta charset=utf-8>"
|
||||
"<title>%1</title>"
|
||||
"<style>%3</style>"
|
||||
"</head>"
|
||||
"<body>%2</body>"
|
||||
"</html>")
|
||||
.arg(title, html);
|
||||
.arg(title, html, m_richHtml ? rich_style : QString());
|
||||
}
|
||||
|
||||
QString GeminiParser::beginBlock(State new_mode) {
|
||||
@ -87,11 +93,12 @@ QString GeminiParser::beginBlock(State new_mode) {
|
||||
return "<ul>\n";
|
||||
|
||||
case State::Quote:
|
||||
return "<div align=\"center\" style=\""
|
||||
"background-color: #E1E5EE;"
|
||||
"font-style: italic;"
|
||||
"margin-left: 20px;"
|
||||
"margin-right: 20px;\">\n";
|
||||
return QSL("<%1 style=\""
|
||||
"background-color: #E1E5EE;"
|
||||
"font-style: italic;"
|
||||
"margin-left: 20px;"
|
||||
"margin-right: 20px;\">\n")
|
||||
.arg(m_richHtml ? QSL("blockquote") : QSL("div"));
|
||||
|
||||
case State::Pre:
|
||||
return "<pre style=\"background-color: #E1E5EE;\">\n";
|
||||
@ -111,7 +118,7 @@ QString GeminiParser::endBlock(State new_mode) {
|
||||
break;
|
||||
|
||||
case State::Quote:
|
||||
to_return = "</div>\n";
|
||||
to_return = QSL("</%1>\n").arg(m_richHtml ? QSL("blockquote") : QSL("div"));
|
||||
break;
|
||||
|
||||
case State::Pre:
|
||||
@ -125,6 +132,8 @@ QString GeminiParser::endBlock(State new_mode) {
|
||||
return to_return;
|
||||
}
|
||||
|
||||
GeminiParser::GeminiParser(bool rich_html) : m_richHtml(rich_html) {}
|
||||
|
||||
QString GeminiParser::parseLink(const QRegularExpressionMatch& mtch) const {
|
||||
QString link = mtch.captured(1);
|
||||
QString name = mtch.captured(2);
|
||||
@ -146,8 +155,10 @@ QString GeminiParser::parseHeading(const QRegularExpressionMatch& mtch, QString*
|
||||
|
||||
QString GeminiParser::parseQuote(const QRegularExpressionMatch& mtch) const {
|
||||
QString text = mtch.captured(1);
|
||||
QString element = m_richHtml ? QSL("p") : QSL("div");
|
||||
|
||||
return QSL("<div>%1</div>\n").arg(text.isEmpty() ? QString() : QSL("“%1”").arg(text));
|
||||
return QSL("<%2>%1</%2>\n")
|
||||
.arg(text.simplified().isEmpty() ? QString() : (m_richHtml ? text : QSL("“%1”").arg(text)), element);
|
||||
}
|
||||
|
||||
QString GeminiParser::parseList(const QRegularExpressionMatch& mtch) const {
|
||||
|
@ -8,6 +8,8 @@
|
||||
|
||||
class GeminiParser {
|
||||
public:
|
||||
explicit GeminiParser(bool rich_html);
|
||||
|
||||
QString geminiToHtml(const QByteArray& gemini_data);
|
||||
|
||||
private:
|
||||
@ -37,6 +39,7 @@ class GeminiParser {
|
||||
|
||||
private:
|
||||
State mode;
|
||||
bool m_richHtml;
|
||||
};
|
||||
|
||||
#endif // GEMINIPARSER_H
|
||||
|
@ -8,7 +8,8 @@
|
||||
|
||||
#include <QBuffer>
|
||||
|
||||
GeminiSchemeHandler::GeminiSchemeHandler(QObject* parent) : QWebEngineUrlSchemeHandler(parent) {}
|
||||
GeminiSchemeHandler::GeminiSchemeHandler(QObject* parent)
|
||||
: QWebEngineUrlSchemeHandler(parent), m_geminiParser(GeminiParser(true)) {}
|
||||
|
||||
void GeminiSchemeHandler::requestStarted(QWebEngineUrlRequestJob* request) {
|
||||
GeminiClient* gemini_client = new GeminiClient(this);
|
||||
@ -45,9 +46,13 @@ void GeminiSchemeHandler::onCompleted(const QByteArray& data, const QString& mim
|
||||
buf->open(QBuffer::ReadWrite);
|
||||
|
||||
if (mime.startsWith(QSL(GEMINI_MIME_TYPE))) {
|
||||
// IOFactory::writeFile("a", data);
|
||||
QString htmlized_gemini = m_geminiParser.geminiToHtml(data);
|
||||
buf->write(htmlized_gemini.toUtf8());
|
||||
|
||||
#if !defined(NDEBUG)
|
||||
IOFactory::writeFile("aa.html", htmlized_gemini.toUtf8());
|
||||
#endif
|
||||
|
||||
buf->write(GeminiParser().geminiToHtml(data).toUtf8());
|
||||
target_mime = QSL("text/html");
|
||||
}
|
||||
else {
|
||||
|
@ -4,6 +4,7 @@
|
||||
#define GEMINISCHEMEHANDLER_H
|
||||
|
||||
#include "network-web/gemini/geminiclient.h"
|
||||
#include "network-web/gemini/geminiparser.h"
|
||||
|
||||
#include <QWebEngineUrlRequestJob>
|
||||
#include <QWebEngineUrlSchemeHandler>
|
||||
@ -23,6 +24,7 @@ class GeminiSchemeHandler : public QWebEngineUrlSchemeHandler {
|
||||
|
||||
private:
|
||||
QHash<QWebEngineUrlRequestJob*, GeminiClient*> m_jobs;
|
||||
GeminiParser m_geminiParser;
|
||||
};
|
||||
|
||||
#endif // GEMINISCHEMEHANDLER_H
|
||||
|
Loading…
x
Reference in New Issue
Block a user