From 180ab463674db7110f5a5a48fe0381521a1d079e Mon Sep 17 00:00:00 2001 From: Le Tan Date: Sun, 22 Jan 2017 19:39:43 +0800 Subject: [PATCH] bugfix: highlight links and images with spaces in URL It is said that URL should not contain spaces. Anyway, we use regular expression syntax highlighting to complement PEG Markdown Highlight. Signed-off-by: Le Tan --- src/hgmarkdownhighlighter.cpp | 54 ++++++++++++++++++++++++++--------- src/hgmarkdownhighlighter.h | 16 ++++------- src/vmdedit.cpp | 2 +- 3 files changed, 46 insertions(+), 26 deletions(-) diff --git a/src/hgmarkdownhighlighter.cpp b/src/hgmarkdownhighlighter.cpp index a9443b1a..04f290fd 100644 --- a/src/hgmarkdownhighlighter.cpp +++ b/src/hgmarkdownhighlighter.cpp @@ -1,12 +1,3 @@ -/* PEG Markdown Highlight - * Copyright 2011-2016 Ali Rantakari -- http://hasseg.org - * Licensed under the GPL2+ and MIT licenses (see LICENSE for more info). - * - * highlighter.cpp - * - * Qt 4.7 example for highlighting a rich text widget. - */ - #include #include #include "hgmarkdownhighlighter.h" @@ -36,9 +27,13 @@ HGMarkdownHighlighter::HGMarkdownHighlighter(const QVector &s codeBlockEndExp = QRegExp("^(\\s)*```$"); codeBlockFormat.setForeground(QBrush(Qt::darkYellow)); for (int index = 0; index < styles.size(); ++index) { - if (styles[index].type == pmh_VERBATIM) { + const pmh_element_type &eleType = styles[index].type; + if (eleType == pmh_VERBATIM) { codeBlockFormat = styles[index].format; - break; + } else if (eleType == pmh_LINK) { + m_linkFormat = styles[index].format; + } else if (eleType == pmh_IMAGE) { + m_imageFormat = styles[index].format; } } @@ -77,8 +72,16 @@ void HGMarkdownHighlighter::highlightBlock(const QString &text) setFormat(unit.start, unit.length, highlightingStyles[unit.styleIndex].format); } } - setCurrentBlockState(HighlightBlockState::BlockNormal); + + // We use PEG Markdown Highlight as the main highlighter. + // We can use other highlighting methods to complement it. + + // PEG Markdown Highlight does not handle the ``` code block correctly. + setCurrentBlockState(HighlightBlockState::Normal); highlightCodeBlock(text); + + // PEG Markdown Highlight does not handle links with spaces in the URL. + highlightLinkWithSpacesInURL(text); } void HGMarkdownHighlighter::setStyles(const QVector &styles) @@ -177,7 +180,7 @@ void HGMarkdownHighlighter::highlightCodeBlock(const QString &text) { int nextIndex = 0; int startIndex = 0; - if (previousBlockState() != HighlightBlockState::BlockCodeBlock) { + if (previousBlockState() != HighlightBlockState::CodeBlock) { startIndex = codeBlockStartExp.indexIn(text); if (startIndex >= 0) { nextIndex = startIndex + codeBlockStartExp.matchedLength(); @@ -190,7 +193,7 @@ void HGMarkdownHighlighter::highlightCodeBlock(const QString &text) int endIndex = codeBlockEndExp.indexIn(text, nextIndex); int codeBlockLength; if (endIndex == -1) { - setCurrentBlockState(HighlightBlockState::BlockCodeBlock); + setCurrentBlockState(HighlightBlockState::CodeBlock); codeBlockLength = text.length() - startIndex; } else { codeBlockLength = endIndex - startIndex + codeBlockEndExp.matchedLength(); @@ -205,6 +208,29 @@ void HGMarkdownHighlighter::highlightCodeBlock(const QString &text) } } +void HGMarkdownHighlighter::highlightLinkWithSpacesInURL(const QString &p_text) +{ + if (currentBlockState() == HighlightBlockState::CodeBlock) { + return; + } + // TODO: should select links with spaces in URL. + QRegExp regExp("[\\!]?\\[[^\\]]*\\]\\(([^\\n\\)]+)\\)"); + int index = regExp.indexIn(p_text); + while (index >= 0) { + Q_ASSERT(regExp.captureCount() == 1); + int length = regExp.matchedLength(); + const QString &capturedText = regExp.capturedTexts()[1]; + if (capturedText.contains(' ')) { + if (p_text[index] == '!' && m_imageFormat.isValid()) { + setFormat(index, length, m_imageFormat); + } else if (m_linkFormat.isValid()) { + setFormat(index, length, m_linkFormat); + } + } + index = regExp.indexIn(p_text, index + length); + } +} + void HGMarkdownHighlighter::parse() { if (!parsing.testAndSetRelaxed(0, 1)) { diff --git a/src/hgmarkdownhighlighter.h b/src/hgmarkdownhighlighter.h index be4cb74d..0fabc88c 100644 --- a/src/hgmarkdownhighlighter.h +++ b/src/hgmarkdownhighlighter.h @@ -1,12 +1,3 @@ -/* PEG Markdown Highlight - * Copyright 2011-2016 Ali Rantakari -- http://hasseg.org - * Licensed under the GPL2+ and MIT licenses (see LICENSE for more info). - * - * highlighter.h - * - * Qt 4.7 example for highlighting a rich text widget. - */ - #ifndef HGMARKDOWNHIGHLIGHTER_H #define HGMARKDOWNHIGHLIGHTER_H @@ -31,8 +22,8 @@ struct HighlightingStyle enum HighlightBlockState { - BlockNormal = 0, - BlockCodeBlock = 1, + Normal = 0, + CodeBlock = 1, }; // One continuous region for a certain markdown highlight style @@ -74,6 +65,8 @@ private: QRegExp codeBlockStartExp; QRegExp codeBlockEndExp; QTextCharFormat codeBlockFormat; + QTextCharFormat m_linkFormat; + QTextCharFormat m_imageFormat; QTextDocument *document; QVector highlightingStyles; @@ -92,6 +85,7 @@ private: void resizeBuffer(int newCap); void highlightCodeBlock(const QString &text); + void highlightLinkWithSpacesInURL(const QString &p_text); void parse(); void parseInternal(); void initBlockHighlightFromResult(int nrBlocks); diff --git a/src/vmdedit.cpp b/src/vmdedit.cpp index 9292816a..5850f193 100644 --- a/src/vmdedit.cpp +++ b/src/vmdedit.cpp @@ -204,7 +204,7 @@ void VMdEdit::generateEditOutline() QRegExp headerReg("(#{1,6})\\s*(\\S.*)"); // Need to trim the spaces for (QTextBlock block = doc->begin(); block != doc->end(); block = block.next()) { Q_ASSERT(block.lineCount() == 1); - if ((block.userState() == HighlightBlockState::BlockNormal) && + if ((block.userState() == HighlightBlockState::Normal) && headerReg.exactMatch(block.text())) { VHeader header(headerReg.cap(1).length(), headerReg.cap(2).trimmed(), "", block.firstLineNumber());