summaryrefslogtreecommitdiffstats
path: root/src/gui/text/qtextmarkdownimporter.cpp
Commit message (Collapse)AuthorAgeFilesLines
* Fix static assert in Markdown parserAndreas Buhr2020-11-081-1/+1
| | | | | | | | | A static assert was misstated. The equality operator has precedence over the bitwise or operator, the static assert was thus not checking what it was intended to check. Fixed by this patch. Change-Id: If21faa617dca1d1786fc6bfaf0b87423e0d35e4e Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* Support the markdown underline extensionShawn Rutledge2020-11-071-1/+5
| | | | | | | | | | | | | | | | MarkdownDialectGitHub now includes this feature, so *emph* is italicized and _emph_ is underlined. This is a better fit for QTextDocument capabilities; until now, _underlined_ markdown could be read, but would be rendered with italics, because in CommonMark, *emphasis* and _emphasis_ are the same. But QTextMarkdownWriter already writes underlining and italics distinctly in this way. [ChangeLog][QtGui][Text] By default (with MarkdownDialectGitHub), markdown _underline_ and *italic* text styles are now distinct. Fixes: QTBUG-84429 Change-Id: Ifc6defa4852abe831949baa4ce28bae5f1a82265 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* Add ; to Q_UNUSEDLars Schmertmann2020-07-071-3/+3
| | | | | | | | This is required to remove the ; from the macro with Qt 6. Task-number: QTBUG-82978 Change-Id: I3f0b6717956ca8fa486bed9817b89dfa19f5e0e1 Reviewed-by: Friedemann Kleint <Friedemann.Kleint@qt.io>
* Use qsizetype in QListLars Knoll2020-07-061-5/+5
| | | | | | | | | | | | | | | | | | | | The change creates a slight source incompatibility. The main things to take care of are * code using printf statements on list.size(). Using qsizetype in printf statements will always require a cast to work on both 32 and 64 bit. * A few places where overloads now get ambiguous. One example is QRandomGenerator::bounded() that has overloads for int, uint and double, but not int64. * Streaming list.size() to a QDataStream will change the format depending on the architecture. [ChangeLog][QtCore][QList] QList now uses qsizetype to index into elements. Change-Id: Iaff562a4d072b97f458417b670f95971bd47cbc6 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
* Port Q_STATIC_ASSERT(_X) to static_assertGiuseppe D'Angelo2020-06-191-15/+15
| | | | | | | | | | | | | | | | | There is no reason for keep using our macro now that we have C++17. The macro itself is left in for the moment being, as well as its detection logic, because it's needed for C code (not everything supports C11 yet). A few more cleanups will arrive in the next few patches. Note that this is a mere search/replace; some places were using double braces to work around the presence of commas in a macro, no attempt has been done to fix those. tst_qglobal had just some minor changes to keep testing the macro. Change-Id: I1c1c397d9f3e63db3338842bf350c9069ea57639 Reviewed-by: Lars Knoll <lars.knoll@qt.io>
* QTextMarkdownImporter: allow nesting text span formattingShawn Rutledge2020-05-271-0/+2
| | | | | | | | | | | | | | | The bold+italic combination indicated by ***triple stars*** requires this; but it enables combinations of italics, bold, strikeout, anchor text (and associated link formatting), image alternate text, and inline code formatting (monospace). A code span overrides the formatting from surrounding spans (which might be a bug to fix in another patch, if we compare to how md2html formats code nested in bold-italics for example), but the format stack restores state when any char format span ends. Task-number: QTBUG-81306 Pick-to: 5.15 Change-Id: I289556fa53de400eb50a4d159b9b344eafc517da Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* QtGui: fix deprecated QChar conversionsMarc Mutz2020-05-111-1/+1
| | | | | | | | | Conversions from non-char-types to QChar are going to be deprecated. Use QChar::fromUcs2(), fromUcs4(), QLatin1Char(), or convert the constructor argument to char16_t. Change-Id: Ib45ebd5560aa3a2bc460037ab09773607485c6e2 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* QTextMarkdownImporter: fix use after free; add fuzz-generated testsShawn Rutledge2020-02-281-2/+5
| | | | | | | | | | | | | | It was possible to end up with a dangling pointer in m_listStack. This is now avoided by using QPointer and doing nullptr checks before accessing any QTextList pointer stored there. We have 2 specimens of garbage that caused crashes before; now they don't. But only fuzz20450 triggered the dangling pointer in the list stack. The crash caused by fuzz20580 was fixed by updating md4c from upstream: 4b0fc030777cd541604f5ebaaad47a2b76d61ff9 Change-Id: I8e1eca23b281256a03aea0f55e9ae20f1bdd2a38 Reviewed-by: Robert Loehning <robert.loehning@qt.io>
* Markdown importer: properly set hyperlinksGiuseppe D'Angelo2020-02-031-1/+3
| | | | | | | | The "title" in markdown is the tooltip, not the name attribute of a link. Also, tell the char format that it's an anchor. Change-Id: I2978848ec6705fe16376d6fe17f31007cce4b801 Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
* Markdown importer: use Unicode decodingGiuseppe D'Angelo2020-02-031-2/+2
| | | | | | | | | | | | | | | Given we feed UTF-8 data into the importer, it must be able to cope with Unicode. Build md4c with UTF-8 support, advertise it at usage site, and change a couple of broken decodings. Driveby: the textedit example used the wrong codec to decode a Markdown file. While the Markdown spec doesn't deal with encodings, using the default one for HTML is certainly wrong. Port the loading of both markdown and plaintext to UTF-8, as that what _saving_ via QTextDocumentWriter would use by default. Change-Id: I51c6214cfe45ebfc5a67a7366f7866a5328366ec Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
* Remove empty block at beginning of imported markdownRainer Keller2020-01-131-2/+12
| | | | | | | | | | | | An empty QTextDocument already contains a block; so when the formatting is fully determined, if the document is still empty, then instead of inserting a new block, we can set formatting on the cursor, which affects the pre-existing block, before inserting text. This avoids leaving a blank line (the default block) above the inserted content. Fixes: QTBUG-81060 Change-Id: I14e45e300a602493aa59680417d74d4c2b25862d Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
* Use default QTD font size for mono font when importing markdownEike Ziller2019-11-131-0/+4
| | | | | | | | | | QFontDatabase::systemFont(FixedFont) determines the font for inline code and code blocks in a markdown document. Now we change the size of that font to the same size as QTextDocument::defaultFont() so that the user has the ability to customize the font size in each document instead of only system-wide. Change-Id: Ief7367336f7613e88695dbb08bcb7e9f50db8961 Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
* Avoid crashing when the end of an empty markdown list is detectedShawn Rutledge2019-11-051-6/+18
| | | | | | | | | | | | | | | | | | | | | | The markdown parser generates empty lists in some cases when a character that can be used as a bullet is found on a line by itself. cbEnterBlock() and cbLeaveBlock() are called symmetrically in such cases. QStack::pop() on an empty stack triggers an assert, so push and pop need to be done symmetrically too. But it's difficult to actually create the list as soon as the MD_BLOCK_UL or MD_BLOCK_OL callback occurs, without breaking the case fixed in 7224d0e427d71e559b928c44634839b4791c1416 (and probably other cases). That's because QTextCursor::insertList() creates a list item at the same time as it creates the list itself, and also inherits block formatting from the previous block. We now insert empty lists with empty items whenever the need for that is detected though, and there's a failsafe to prevent popping in case something still goes wrong with that logic. We aren't strict about reproducing the original markdown when regenerating it via toMarkdown(), but it's getting closer. Fixes: QTBUG-78870 Change-Id: Ided194ce7aec2710c60dbac42761ee4169ed9b78 Reviewed-by: Edward Welbourne <edward.welbourne@qt.io> Reviewed-by: Robert Loehning <robert.loehning@qt.io>
* Enforce QTextDocument::MarkdownFeature compatibility at compile timeShawn Rutledge2019-10-241-0/+21
| | | | | | | | | | | | | | | | | | | | | | | | | | | | We use md4c for parsing markdown. It provides flags to control the feature set that will be supported when parsing particular documents. QTextMarkdownImporter::Feature is a fine-grained set of flags that exactly match the md4c feature flags that we support in Qt so far. QTextMarkdownImporter is a private exported class (new in 5.14). We don't expect the corresponding flags in md4c to change in incompatible ways in the future: the md4c authors have as much respect for avoiding compatibility issues as we do, and likely will only add features, not remove them. We now enforce QTextMarkdownImporter::Features compatibility with QTextDocument::MarkdownFeatures by setting them directly. We check QTextMarkdownImporter::Features compatibility with md4c's #define'd feature flags using static asserts, so that any hypothetical incompatibility would be detected at compile time. The enum conversion from QTextDocument::MarkdownFeatures to QTextMarkdownImporter::Features is moved to a new QTextMarkdownImporter constructor; thus the conversions from QTextDocument::MarkdownFeatures to QTextMarkdownImporter::Features, and then to unsigned (in QTextMarkdownImporter::import()) are adjacent in the same private class implementation. If incompatibility ever occurred, we would need to replace one or both of those with another suitable conversion function. Change-Id: I0bf8a21eb7559df1d38406b948ef657f9060c67b Reviewed-by: Vitaly Fanaskov <vitaly.fanaskov@qt.io>
* Make QTextBlockFormat::MarkerType an enum classShawn Rutledge2019-10-101-3/+3
| | | | | | | This came up during API review. Change-Id: I9198e1eb96db0c21e46a226a032919bb62d3ca66 Reviewed-by: Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
* qtlite: Fix build with -no-feature-texthtmlparserMikhail Svetkin2019-06-111-1/+1
| | | | | | Change-Id: I3ffd4612884f57c2d0ff8e9c9c10d0805dd72f6f Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
* QTextMarkdownWriter: write fenced code blocks with language declarationShawn Rutledge2019-06-041-2/+6
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | MD4C now makes it possible to detect indented and fenced code blocks: https://github.com/mity/md4c/issues/81 Fenced code blocks have the advantages of being easier to write by hand, and having an "info string" following the opening fence, which is commonly used to declare the language. Also, the HTML parser now recognizes tags of the form <pre class="language-foo"> which is one convention for declaring the programming language (as opposed to human language, for which the lang attribute would be used): https://stackoverflow.com/questions/5134242/semantics-standards-and-using-the-lang-attribute-for-source-code-in-markup So it's possible to read HTML and write markdown without losing this information. It's also possible to read markdown with any type of code block: fenced with ``` or ~~~, or indented, and rewrite it the same way. Change-Id: I33c2bf7d7b66c8f3ba5bdd41ab32572f09349c47 Reviewed-by: Gatis Paeglis <gatis.paeglis@qt.io>
* Markdown and HTML: support image alt text and titleShawn Rutledge2019-06-011-10/+14
| | | | | | | | | | | | | | | | | | | | | It's a required CommonMark feature: https://spec.commonmark.org/0.29/#images and alt text is also required in HTML: https://www.w3.org/wiki/Html/Elements/img#Requirements_for_providing_text_to_act_as_an_alternative_for_images Now we are able to read these attributes from either html or markdown and rewrite either an html or markdown document that preserves them. This patch does not add viewing or editing support in QTextEdit etc. Change-Id: I51307389f8f9fc00809808390e583a83111a7b33 Reviewed-by: Gatis Paeglis <gatis.paeglis@qt.io>
* QTextMarkdownImporter: don't keep heading level on following list itemShawn Rutledge2019-05-241-44/+52
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | When reading a document like # heading - list item and then re-writing it, it turned into # heading - # list item because QTextCursor::insertList() simply calls QTextCursor::insertBlock(), thus inheriting block format from the previous block, without an opportunity to explicitly define the block format. So be more consistent: use QTextMarkdownImporter::insertBlock() for blocks inside list items too. Now it fully defines blockFormat first, then inserts the block, and then adds it to the current list only when the "paragraph" is actually the list item's text (but not when it's a continuation paragraph). Also, be prepared for applying and removing block markers to arbitrary blocks, just in case (they might be useful for block quotes, for example). Change-Id: I391820af9b65e75abce12abab45d2477c49c86ac Reviewed-by: Gatis Paeglis <gatis.paeglis@qt.io>
* Fix gui build without feature.regularexpressionTasuku Suzuki2019-05-221-1/+11
| | | | | | | | | | | Change-Id: Id27fc81af8d2b0355b186540f41d75a9c8d7c7f3 Reviewed-by: David Faure <david.faure@kdab.com>
* Markdown: blockquotes, code blocks, and generalized nestingShawn Rutledge2019-05-081-20/+83
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Can now detect nested quotes and code blocks inside quotes, and can rewrite the markdown too. QTextHtmlParser sets hard-coded left and right margins, so we need to do the same to be able to read HTML and write markdown, or vice-versa, and to ensure that all views (QTextEdit, QTextBrowser, QML Text etc.) will render it with margins. But now we add a semantic memory too: BlockQuoteLevel is similar to HeadingLevel, which was added in 310daae53926628f80c08e4415b94b90ad525c8f to preserve H1..H6 heading levels, because detecting it via font size didn't make sense in QTextMarkdownWriter. Likewise detecting quote level by its margins didn't make sense; markdown supports nesting quotes; and indenting nested quotes via 40 pixels may be a bit too much, so we should consider it subject to change (and perhaps be able to change it via CSS later on). Since we're adding BlockQuoteLevel and depending on it in QTextMarkdownWriter, it's necessary to set it in QTextHtmlParser to enable HTML->markdown conversion. (But so far, nested blockquotes in HTML are not supported.) Quotes (and nested quotes) can contain indented code blocks, but it seems the reverse is not true (according to https://spec.commonmark.org/0.29/#example-201 ) Quotes can contain fenced code blocks. Quotes can contain lists. Nested lists can be interrupted with nested code blocks and nested quotes. So far the writer assumes all code blocks are the indented type. It will be necessary to add another attribute to remember whether the code block is indented or fenced (assuming that's necessary). Fenced code blocks would work better for writing inside block quotes and list items because the fence is less ambiguous than the indent. Postponing cursor->insertBlock() as long as possible helps with nesting. cursor->insertBlock() needs to be done "just in time" before inserting text that will go in the block. The block and char formats aren't necessarily known until that time. When a nested block (such as a nested quote) ends, the context reverts to the previous block format, which then needs to be re-determined and set before we insert text into the outer block; but if no text will be inserted, no new block is necessary. But we can't use QTextBlockFormat itself as storage, because for some reason bullets become very "sticky" and it becomes impossible to have plain continuation paragraphs inside list items: they all get bullets. Somehow QTextBlockFormat remembers, if we copy it. But we can create a new one each time and it's OK. Change-Id: Icd0529eb90d2b6a3cb57f0104bf78a7be81ede52 Reviewed-by: Gatis Paeglis <gatis.paeglis@qt.io>
* Markdown: deal with horizontal rules (thematic breaks)Shawn Rutledge2019-05-081-1/+2
| | | | | Change-Id: I14d4bcfe1a6c3bd87d1328f0abb81b2138545e4e Reviewed-by: Gatis Paeglis <gatis.paeglis@qt.io>
* Markdown: fix several issues with lists and continuationsShawn Rutledge2019-05-081-9/+50
| | | | | | | | | | | | | | | | | | | | Importer fixes: - the first list item after a heading doesn't keep the heading font - the first text fragment after a bullet is the bullet text, not a separate paragraph - detect continuation lines and append to the list item text - detect continuation paragraphs and indent them properly - indent nested list items properly - add a test for QTextMarkdownImporter Writer fixes: - after bullet items, continuation lines and paragraphs are indented - indentation of continuations isn't affected by checkboxes - add extra newlines between list items in "loose" lists - avoid writing triple newlines - enhance the test for QTextMarkdownWriter Change-Id: Ib1dda514832f6dc0cdad177aa9a423a7038ac8c6 Reviewed-by: Gatis Paeglis <gatis.paeglis@qt.io>
* Remove 3rdparty include from QTextMarkdownImporter header fileShawn Rutledge2019-05-081-24/+25
| | | | | | | | It's a private header; but to be able to use it in a test, it has to be as clean as a public header. Change-Id: I868372406e62acc24051a6523fee89bb911a61f9 Reviewed-by: Gatis Paeglis <gatis.paeglis@qt.io>
* QTextMarkdownImporter: Fix deprecation warningFriedemann Kleint2019-05-021-1/+1
| | | | | | | | | | | Use QTextCharFormat::setAnchorNames(), fixing: text/qtextmarkdownimporter.cpp:322:36: warning: 'void QTextCharFormat::setAnchorName(const QString&)' is deprecated: Use setAnchorNames() instead [-Wdeprecated-declarations] Amends 65314b6ce88cdbb28a22be0cab9856ec9bc9604b. Task-number: QTBUG-72349 Change-Id: I7f909d1fcc5c4045c738b5a5c491b2ac1de6eac5 Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
* QTextMarkdownImporter: insert list items into the correct listShawn Rutledge2019-04-271-2/+3
| | | | | | | | | | | | | | | There was a bug when handling situations like 1. first 1) subfirst 2. second It was always inserting items into the list where the cursor already was, but it needs to insert the "second" list item into the list which is currently the top of m_listStack. Change-Id: Id0899032efafb2e2b9e7c45a6fb9f2c5221fc4df Reviewed-by: Gatis Paeglis <gatis.paeglis@qt.io>
* Fix -Wc++11-narrowing error in qtextmarkdownimporterMårten Nordheim2019-04-241-1/+1
| | | | | | | | error: non-constant-expression cannot be narrowed from type 'qt::QFlags::Int' (aka 'int') to 'unsigned int' in initializer list [-Wc++11-narrowing] Change-Id: Ic634a98d29a108741d41955da1fbf2c986e4a943 Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
* Add QTextMarkdownImporterShawn Rutledge2019-04-171-0/+435
This provides the ability to read from a Markdown string or file into a QTextDocument, such that the formatting will be recognized and can be rendered. - Add QTextDocument::setMarkdown(QString) - Add QTextEdit::setMarkdown(QString) - Add TextFormat::MarkdownText - QWidgetTextControl::setContent() calls QTextDocument::setMarkdown() if that's the format Fixes: QTBUG-72349 Change-Id: Ief2ad71bf840666c64145d58e9ca71d05fad5659 Reviewed-by: Lisandro Damián Nicanor Pérez Meyer <perezmeyer@gmail.com> Reviewed-by: Gatis Paeglis <gatis.paeglis@qt.io>