/* * qtmaildir - a Qt6 mail client for notmuch-indexed Maildirs * Copyright (C) 2026 Danilo M. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include "markdownrenderer.h" /// The extension configuration cmark-gfm renders the composer's body with. /// /// No QApplication is needed here: MarkdownRenderer is a pure function over /// strings, so QTEST_APPLESS_MAIN avoids pulling in a platform plugin for a /// test that has nothing to do with widgets. class TestMarkdownRenderer : public QObject { Q_OBJECT private slots: void commonMarkBasicsRender(); void autolinkTurnsABareUrlIntoALink(); void strikethroughRenders(); void tasklistRenders(); void tablesAreNotEnabled(); void rawHtmlIsSuppressed(); void unsafeLinksAreStripped(); void accentedTextSurvivesAsUtf8(); void emptyInputProducesEmptyOutput(); }; void TestMarkdownRenderer::commonMarkBasicsRender() { const QString html = MarkdownRenderer::toHtml( QStringLiteral("**bold** *italic* `code`")); QVERIFY2(html.contains(QStringLiteral("")), qPrintable(html)); QVERIFY2(html.contains(QStringLiteral("")), qPrintable(html)); QVERIFY2(html.contains(QStringLiteral("")), qPrintable(html)); } void TestMarkdownRenderer::autolinkTurnsABareUrlIntoALink() { // The whole reason cmark-gfm was chosen over plain cmark. Under // CommonMark a bare URL is text, and a bare URL in mail is expected to // be clickable. const QString html = MarkdownRenderer::toHtml( QStringLiteral("see https://example.org for details")); QVERIFY2(html.contains(QStringLiteral("gone")), qPrintable(html)); } void TestMarkdownRenderer::tasklistRenders() { // Known ceiling: many mail clients strip the checkbox, so those // recipients see the item with no marker. The plain part still carries // the literal "- [ ]", so nothing is lost, only the HTML rendering. const QString html = MarkdownRenderer::toHtml( QStringLiteral("- [ ] todo\n- [x] done")); QVERIFY2(html.contains(QStringLiteral("type=\"checkbox\"")), qPrintable(html)); // Not a bare "checked": that is a common English word ordinary prose // would satisfy on its own. The attribute is what proves [x] differs // from [ ]. QVERIFY2(html.contains(QStringLiteral("checked=\"\"")), qPrintable(html)); } void TestMarkdownRenderer::tablesAreNotEnabled() { // Deliberately off: tables render badly across mail clients regardless of // who generates them. The extension EXISTS in the library, so this // asserts a decision rather than a limitation, and would silently start // passing the wrong way if someone attached it "for completeness". const QString html = MarkdownRenderer::toHtml( QStringLiteral("| a | b |\n|---|---|\n| 1 | 2 |")); QVERIFY2(!html.contains(QStringLiteral("", // because the weaker assertion would still pass with CMARK_OPT_UNSAFE // set by mistake, as long as something ELSE in the string also matched // "not \n\nafter")); QVERIFY2(!html.contains(QStringLiteral("