mirror of
https://github.com/martinrotter/rssguard.git
synced 2025-02-02 18:36:49 +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/builtin_js/observer.js</file>
|
||||||
<file>scripts/web_ui/rssguard.html</file>
|
<file>scripts/web_ui/rssguard.html</file>
|
||||||
|
<file>scripts/gemini/style.css</file>
|
||||||
|
|
||||||
<file>sounds/boing.wav</file>
|
<file>sounds/boing.wav</file>
|
||||||
<file>sounds/rooster.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>
|
#include <QTimer>
|
||||||
|
|
||||||
Downloader::Downloader(QObject* parent)
|
Downloader::Downloader(QObject* parent)
|
||||||
: QObject(parent), m_geminiClient(new GeminiClient(this)), m_activeReply(nullptr),
|
: QObject(parent), m_geminiClient(new GeminiClient(this)), m_geminiParser(GeminiParser(false)),
|
||||||
m_downloadManager(new SilentNetworkAccessManager(this)), m_timer(new QTimer(this)), m_inputData(QByteArray()),
|
m_activeReply(nullptr), m_downloadManager(new SilentNetworkAccessManager(this)), m_timer(new QTimer(this)),
|
||||||
m_inputMultipartData(nullptr), m_targetProtected(false), m_targetUsername(QString()), m_targetPassword(QString()),
|
m_inputData(QByteArray()), m_inputMultipartData(nullptr), m_targetProtected(false), m_targetUsername(QString()),
|
||||||
m_lastOutputData({}), m_lastOutputError(QNetworkReply::NetworkError::NoError), m_lastHttpStatusCode(0),
|
m_targetPassword(QString()), m_lastOutputData({}), m_lastOutputError(QNetworkReply::NetworkError::NoError),
|
||||||
m_lastHeaders({}) {
|
m_lastHttpStatusCode(0), m_lastHeaders({}) {
|
||||||
m_timer->setInterval(DOWNLOAD_TIMEOUT);
|
m_timer->setInterval(DOWNLOAD_TIMEOUT);
|
||||||
m_timer->setSingleShot(true);
|
m_timer->setSingleShot(true);
|
||||||
|
|
||||||
@ -50,7 +50,7 @@ void Downloader::geminiFinished(const QByteArray& data, const QString& mime) {
|
|||||||
m_lastOutputMultipartData = {};
|
m_lastOutputMultipartData = {};
|
||||||
|
|
||||||
if (mime.startsWith(QSL(GEMINI_MIME_TYPE))) {
|
if (mime.startsWith(QSL(GEMINI_MIME_TYPE))) {
|
||||||
m_lastOutputData = GeminiParser().geminiToHtml(data).toUtf8();
|
m_lastOutputData = m_geminiParser.geminiToHtml(data).toUtf8();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
m_lastOutputData = data;
|
m_lastOutputData = data;
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
#include "definitions/definitions.h"
|
#include "definitions/definitions.h"
|
||||||
#include "network-web/gemini/geminiclient.h"
|
#include "network-web/gemini/geminiclient.h"
|
||||||
|
#include "network-web/gemini/geminiparser.h"
|
||||||
#include "network-web/httpresponse.h"
|
#include "network-web/httpresponse.h"
|
||||||
|
|
||||||
#include <QHttpMultiPart>
|
#include <QHttpMultiPart>
|
||||||
@ -105,6 +106,7 @@ class Downloader : public QObject {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
GeminiClient* m_geminiClient;
|
GeminiClient* m_geminiClient;
|
||||||
|
GeminiParser m_geminiParser;
|
||||||
QNetworkReply* m_activeReply;
|
QNetworkReply* m_activeReply;
|
||||||
QScopedPointer<SilentNetworkAccessManager> m_downloadManager;
|
QScopedPointer<SilentNetworkAccessManager> m_downloadManager;
|
||||||
QTimer* m_timer;
|
QTimer* m_timer;
|
||||||
|
@ -12,12 +12,14 @@ QString GeminiParser::geminiToHtml(const QByteArray& gemini_data) {
|
|||||||
QStringList lines = gemini_hypertext.split(QL1C('\n'));
|
QStringList lines = gemini_hypertext.split(QL1C('\n'));
|
||||||
mode = State::Normal;
|
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_heading(R"(^(#{1,6})\s+(.+)$)");
|
||||||
static QRegularExpression exp_list(R"(^\*\s(.+)$)");
|
static QRegularExpression exp_list(R"(^\*\s(.+)$)");
|
||||||
static QRegularExpression exp_quote(R"((?:^>$|^>\s?(.+)$))");
|
static QRegularExpression exp_quote(R"((?:^>$|^>\s?(.+)$))");
|
||||||
static QRegularExpression exp_pre(R"(^```.*$)");
|
static QRegularExpression exp_pre(R"(^```.*$)");
|
||||||
|
|
||||||
|
static QString rich_style = QString::fromUtf8(IOFactory::readFile(QSL(":/scripts/gemini/style.css")));
|
||||||
|
|
||||||
QRegularExpressionMatch mtch;
|
QRegularExpressionMatch mtch;
|
||||||
QString title;
|
QString title;
|
||||||
|
|
||||||
@ -69,13 +71,17 @@ QString GeminiParser::geminiToHtml(const QByteArray& gemini_data) {
|
|||||||
|
|
||||||
html += endBlock(State::Normal);
|
html += endBlock(State::Normal);
|
||||||
|
|
||||||
// IOFactory::writeFile("aa", html.toUtf8());
|
return QSL("<!DOCTYPE html>"
|
||||||
|
"<html>"
|
||||||
return QSL("<html>"
|
"<head>"
|
||||||
"<head><title>%1</title></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>"
|
"<body>%2</body>"
|
||||||
"</html>")
|
"</html>")
|
||||||
.arg(title, html);
|
.arg(title, html, m_richHtml ? rich_style : QString());
|
||||||
}
|
}
|
||||||
|
|
||||||
QString GeminiParser::beginBlock(State new_mode) {
|
QString GeminiParser::beginBlock(State new_mode) {
|
||||||
@ -87,11 +93,12 @@ QString GeminiParser::beginBlock(State new_mode) {
|
|||||||
return "<ul>\n";
|
return "<ul>\n";
|
||||||
|
|
||||||
case State::Quote:
|
case State::Quote:
|
||||||
return "<div align=\"center\" style=\""
|
return QSL("<%1 style=\""
|
||||||
"background-color: #E1E5EE;"
|
"background-color: #E1E5EE;"
|
||||||
"font-style: italic;"
|
"font-style: italic;"
|
||||||
"margin-left: 20px;"
|
"margin-left: 20px;"
|
||||||
"margin-right: 20px;\">\n";
|
"margin-right: 20px;\">\n")
|
||||||
|
.arg(m_richHtml ? QSL("blockquote") : QSL("div"));
|
||||||
|
|
||||||
case State::Pre:
|
case State::Pre:
|
||||||
return "<pre style=\"background-color: #E1E5EE;\">\n";
|
return "<pre style=\"background-color: #E1E5EE;\">\n";
|
||||||
@ -111,7 +118,7 @@ QString GeminiParser::endBlock(State new_mode) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case State::Quote:
|
case State::Quote:
|
||||||
to_return = "</div>\n";
|
to_return = QSL("</%1>\n").arg(m_richHtml ? QSL("blockquote") : QSL("div"));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case State::Pre:
|
case State::Pre:
|
||||||
@ -125,6 +132,8 @@ QString GeminiParser::endBlock(State new_mode) {
|
|||||||
return to_return;
|
return to_return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GeminiParser::GeminiParser(bool rich_html) : m_richHtml(rich_html) {}
|
||||||
|
|
||||||
QString GeminiParser::parseLink(const QRegularExpressionMatch& mtch) const {
|
QString GeminiParser::parseLink(const QRegularExpressionMatch& mtch) const {
|
||||||
QString link = mtch.captured(1);
|
QString link = mtch.captured(1);
|
||||||
QString name = mtch.captured(2);
|
QString name = mtch.captured(2);
|
||||||
@ -146,8 +155,10 @@ QString GeminiParser::parseHeading(const QRegularExpressionMatch& mtch, QString*
|
|||||||
|
|
||||||
QString GeminiParser::parseQuote(const QRegularExpressionMatch& mtch) const {
|
QString GeminiParser::parseQuote(const QRegularExpressionMatch& mtch) const {
|
||||||
QString text = mtch.captured(1);
|
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 {
|
QString GeminiParser::parseList(const QRegularExpressionMatch& mtch) const {
|
||||||
|
@ -8,6 +8,8 @@
|
|||||||
|
|
||||||
class GeminiParser {
|
class GeminiParser {
|
||||||
public:
|
public:
|
||||||
|
explicit GeminiParser(bool rich_html);
|
||||||
|
|
||||||
QString geminiToHtml(const QByteArray& gemini_data);
|
QString geminiToHtml(const QByteArray& gemini_data);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -37,6 +39,7 @@ class GeminiParser {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
State mode;
|
State mode;
|
||||||
|
bool m_richHtml;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // GEMINIPARSER_H
|
#endif // GEMINIPARSER_H
|
||||||
|
@ -8,7 +8,8 @@
|
|||||||
|
|
||||||
#include <QBuffer>
|
#include <QBuffer>
|
||||||
|
|
||||||
GeminiSchemeHandler::GeminiSchemeHandler(QObject* parent) : QWebEngineUrlSchemeHandler(parent) {}
|
GeminiSchemeHandler::GeminiSchemeHandler(QObject* parent)
|
||||||
|
: QWebEngineUrlSchemeHandler(parent), m_geminiParser(GeminiParser(true)) {}
|
||||||
|
|
||||||
void GeminiSchemeHandler::requestStarted(QWebEngineUrlRequestJob* request) {
|
void GeminiSchemeHandler::requestStarted(QWebEngineUrlRequestJob* request) {
|
||||||
GeminiClient* gemini_client = new GeminiClient(this);
|
GeminiClient* gemini_client = new GeminiClient(this);
|
||||||
@ -45,9 +46,13 @@ void GeminiSchemeHandler::onCompleted(const QByteArray& data, const QString& mim
|
|||||||
buf->open(QBuffer::ReadWrite);
|
buf->open(QBuffer::ReadWrite);
|
||||||
|
|
||||||
if (mime.startsWith(QSL(GEMINI_MIME_TYPE))) {
|
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");
|
target_mime = QSL("text/html");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#define GEMINISCHEMEHANDLER_H
|
#define GEMINISCHEMEHANDLER_H
|
||||||
|
|
||||||
#include "network-web/gemini/geminiclient.h"
|
#include "network-web/gemini/geminiclient.h"
|
||||||
|
#include "network-web/gemini/geminiparser.h"
|
||||||
|
|
||||||
#include <QWebEngineUrlRequestJob>
|
#include <QWebEngineUrlRequestJob>
|
||||||
#include <QWebEngineUrlSchemeHandler>
|
#include <QWebEngineUrlSchemeHandler>
|
||||||
@ -23,6 +24,7 @@ class GeminiSchemeHandler : public QWebEngineUrlSchemeHandler {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
QHash<QWebEngineUrlRequestJob*, GeminiClient*> m_jobs;
|
QHash<QWebEngineUrlRequestJob*, GeminiClient*> m_jobs;
|
||||||
|
GeminiParser m_geminiParser;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // GEMINISCHEMEHANDLER_H
|
#endif // GEMINISCHEMEHANDLER_H
|
||||||
|
Loading…
x
Reference in New Issue
Block a user