mirror of
https://invent.kde.org/graphics/okular
synced 2024-10-02 14:14:10 +00:00
0bc8c76c3c
Previously the `<del>` tag that Discount emits would be removed by Qt
since it's not in the subset of HTML that it understands. It does know
about `<s>` though, so replace `<del>` with `<s>` to render strikethroughs
correctly.
Note that I couldn't get Okular to build locally (PEBCAK issue) so I split out this file to debug it. I've tested against http://daringfireball.net/projects/downloads/MarkdownTest_1.0.zip and ff866f73d4/tests/data
and the only difference is that trailing whitespace is now trimmed from the end of a line:
```diff
8c8
< <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Dashes:</p>
---
> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Dashes: </p>
```
A quick search suggests this isn't a problem though https://stackoverflow.com/a/27026403:
> Within block tags (i.e. `<p>`, `<h1>`, `<div>`, ...) spaces as well as line breaks at the beginning or end of the tags should always be ignored (i.e. `<p>test</p>` should look the same as `<p> test </p>`).
I also tried https://doc.qt.io/qt-5/qtextdocument.html#setMarkdown which solves the strikethrough problem, though there are many visible differences with that approach. Most notably, everything is squashed together and code blocks lose their formatting.
227 lines
7.8 KiB
C++
227 lines
7.8 KiB
C++
/*
|
|
SPDX-FileCopyrightText: 2020 Markus Brenneis <support.gulp21+kde@gmail.com>
|
|
|
|
SPDX-License-Identifier: GPL-2.0-or-later
|
|
*/
|
|
|
|
#include <QTest>
|
|
|
|
#include "../settings_core.h"
|
|
#include "core/document.h"
|
|
#include "generators/markdown/converter.h"
|
|
#include <QMimeDatabase>
|
|
#include <QMimeType>
|
|
#include <QTextDocument>
|
|
#include <memory>
|
|
|
|
class MarkdownTest : public QObject
|
|
{
|
|
Q_OBJECT
|
|
|
|
private Q_SLOTS:
|
|
void initTestCase();
|
|
|
|
void testFancyPantsEnabled();
|
|
void testFancyPantsDisabled();
|
|
void testImageSizes();
|
|
void testSpecialCharsInImageFileName();
|
|
void testStrikeThrough();
|
|
void testHtmlTagFixup();
|
|
|
|
private:
|
|
void findImages(QTextFrame *parent, QVector<QTextImageFormat> &images);
|
|
void findImages(const QTextBlock &parent, QVector<QTextImageFormat> &images);
|
|
};
|
|
|
|
void MarkdownTest::initTestCase()
|
|
{
|
|
Okular::SettingsCore::instance(QStringLiteral("markdowntest"));
|
|
}
|
|
|
|
void MarkdownTest::testFancyPantsEnabled()
|
|
{
|
|
Markdown::Converter converter;
|
|
converter.setFancyPantsEnabled(true);
|
|
std::unique_ptr<QTextDocument> document(converter.convert(QStringLiteral(KDESRCDIR "data/imageSizes.md")));
|
|
|
|
QTextFrame::iterator secondFrame = ++(document->rootFrame()->begin());
|
|
QVERIFY(secondFrame.currentBlock().text().startsWith(QStringLiteral("©")));
|
|
}
|
|
|
|
void MarkdownTest::testFancyPantsDisabled()
|
|
{
|
|
Markdown::Converter converter;
|
|
converter.setFancyPantsEnabled(false);
|
|
std::unique_ptr<QTextDocument> document(converter.convert(QStringLiteral(KDESRCDIR "data/imageSizes.md")));
|
|
|
|
QTextFrame::iterator secondFrame = ++(document->rootFrame()->begin());
|
|
QVERIFY(secondFrame.currentBlock().text().startsWith(QStringLiteral("(c)")));
|
|
}
|
|
|
|
void MarkdownTest::testImageSizes()
|
|
{
|
|
Markdown::Converter converter;
|
|
std::unique_ptr<QTextDocument> document(converter.convert(QStringLiteral(KDESRCDIR "data/imageSizes.md")));
|
|
|
|
QTextFrame *parent = document->rootFrame();
|
|
|
|
QVector<QTextImageFormat> images;
|
|
findImages(parent, images);
|
|
|
|
QCOMPARE(images.size(), 17);
|
|
|
|
qreal expectedSizes[][2] = {// width, height
|
|
// small image
|
|
{412, 349},
|
|
{100, 84.70873786407767},
|
|
{118.0515759312321, 100},
|
|
{100, 100},
|
|
{890, 753.9077669902913},
|
|
{890, 890},
|
|
// wide image
|
|
{890, 178},
|
|
{100, 20},
|
|
{500, 100},
|
|
{100, 100},
|
|
{890, 178},
|
|
{890, 890},
|
|
// tall image
|
|
{300, 1500},
|
|
{100, 500},
|
|
{20, 100},
|
|
{100, 100},
|
|
{890, 890}};
|
|
|
|
for (int i = 0; i < images.size(); i++) {
|
|
QCOMPARE(images[i].width(), expectedSizes[i][0]);
|
|
QCOMPARE(images[i].height(), expectedSizes[i][1]);
|
|
}
|
|
}
|
|
|
|
void MarkdownTest::findImages(QTextFrame *parent, QVector<QTextImageFormat> &images)
|
|
{
|
|
for (QTextFrame::iterator it = parent->begin(); !it.atEnd(); ++it) {
|
|
QTextFrame *textFrame = it.currentFrame();
|
|
const QTextBlock textBlock = it.currentBlock();
|
|
|
|
if (textFrame) {
|
|
findImages(textFrame, images);
|
|
} else if (textBlock.isValid()) {
|
|
findImages(textBlock, images);
|
|
}
|
|
}
|
|
}
|
|
|
|
void MarkdownTest::findImages(const QTextBlock &parent, QVector<QTextImageFormat> &images)
|
|
{
|
|
for (QTextBlock::iterator it = parent.begin(); !it.atEnd(); ++it) {
|
|
const QTextFragment textFragment = it.fragment();
|
|
if (textFragment.isValid()) {
|
|
const QTextCharFormat textCharFormat = textFragment.charFormat();
|
|
if (textCharFormat.isImageFormat()) {
|
|
images.append(textCharFormat.toImageFormat());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void MarkdownTest::testSpecialCharsInImageFileName()
|
|
{
|
|
Markdown::Converter converter;
|
|
std::unique_ptr<QTextDocument> document(converter.convert(QStringLiteral(KDESRCDIR "data/imageUrlsWithSpecialChars.md")));
|
|
|
|
QTextFrame *parent = document->rootFrame();
|
|
|
|
QVector<QTextImageFormat> images;
|
|
findImages(parent, images);
|
|
|
|
QCOMPARE(images.size(), 1);
|
|
QVERIFY(images[0].name().endsWith(QStringLiteral("kartöffelchen.jpg")));
|
|
QVERIFY(!images[0].name().contains(QStringLiteral("kart%C3%B6ffelchen.jpg")));
|
|
}
|
|
|
|
void MarkdownTest::testStrikeThrough()
|
|
{
|
|
Markdown::Converter converter;
|
|
converter.setFancyPantsEnabled(true);
|
|
std::unique_ptr<QTextDocument> document(converter.convert(QStringLiteral(KDESRCDIR "data/strikethrough.md")));
|
|
|
|
const QTextFrame *rootFrame = document->rootFrame();
|
|
auto frameIter = rootFrame->begin();
|
|
|
|
// Header line.
|
|
QCOMPARE_NE(frameIter, rootFrame->end());
|
|
QCOMPARE(frameIter.currentBlock().text(), QStringLiteral("Test for strikethrough tag workaround"));
|
|
|
|
// Ordinary line.
|
|
{
|
|
++frameIter;
|
|
QCOMPARE_NE(frameIter, rootFrame->end());
|
|
auto block = frameIter.currentBlock();
|
|
QCOMPARE(block.text(), QStringLiteral("Line without strikethrough"));
|
|
// Single format for the entire line.
|
|
auto formats = block.textFormats();
|
|
QCOMPARE(formats.size(), 1);
|
|
QVERIFY(!formats[0].format.fontStrikeOut());
|
|
}
|
|
|
|
// Part of the line has a strikethrough.
|
|
{
|
|
++frameIter;
|
|
QCOMPARE_NE(frameIter, rootFrame->end());
|
|
auto block = frameIter.currentBlock();
|
|
QCOMPARE(block.text(), QStringLiteral("Line with strikethrough"));
|
|
// The "with" should be the only thing striked out.
|
|
auto formats = block.textFormats();
|
|
QCOMPARE(formats.size(), 3);
|
|
QCOMPARE(block.text().sliced(formats[0].start, formats[0].length), QStringLiteral("Line "));
|
|
QVERIFY(!formats[0].format.fontStrikeOut());
|
|
QCOMPARE(block.text().sliced(formats[1].start, formats[1].length), QStringLiteral("with"));
|
|
QVERIFY(formats[1].format.fontStrikeOut());
|
|
QCOMPARE(block.text().sliced(formats[2].start, formats[2].length), QStringLiteral(" strikethrough"));
|
|
QVERIFY(!formats[2].format.fontStrikeOut());
|
|
}
|
|
|
|
// Code block shouldn't have leading spaces, or be modified by our fixup.
|
|
{
|
|
++frameIter;
|
|
QCOMPARE_NE(frameIter, rootFrame->end());
|
|
auto block = frameIter.currentBlock();
|
|
QCOMPARE(block.text(), QStringLiteral("~~Strikethrough~~ should be <del>ignored</del> in a <s>code block</s>"));
|
|
}
|
|
}
|
|
|
|
void MarkdownTest::testHtmlTagFixup()
|
|
{
|
|
const QString wrapperTag = QStringLiteral("ignored_by_qt");
|
|
const QString wrapperTagBegin = QStringLiteral("<ignored_by_qt>");
|
|
const QString wrapperTagEnd = QStringLiteral("</ignored_by_qt>");
|
|
|
|
// These should passthrough unchanged.
|
|
const QString testCases[] = {
|
|
QStringLiteral("basic test"),
|
|
QStringLiteral("<p>test with tag</p>"),
|
|
QStringLiteral("line with <em>combined <strong>tags</strong></em>"),
|
|
};
|
|
for (const QString &inputHtml : testCases) {
|
|
const QString outputHtml = Markdown::detail::fixupHtmlTags(QString(inputHtml));
|
|
QCOMPARE(outputHtml, wrapperTagBegin + inputHtml + wrapperTagEnd);
|
|
}
|
|
|
|
// <del> should become <s>.
|
|
{
|
|
const QString outputHtml = Markdown::detail::fixupHtmlTags(QStringLiteral("<del>test</del>"));
|
|
QCOMPARE(outputHtml, wrapperTagBegin + QStringLiteral("<s>test</s>") + wrapperTagEnd);
|
|
}
|
|
|
|
// Check that the wrapper is ignored by Qt.
|
|
{
|
|
QTextDocument dom;
|
|
dom.setHtml(wrapperTagBegin + QStringLiteral("basic test") + wrapperTagEnd);
|
|
QVERIFY(!dom.toHtml().contains(wrapperTag));
|
|
}
|
|
}
|
|
|
|
QTEST_MAIN(MarkdownTest)
|
|
#include "markdowntest.moc"
|