From 2c527201b8bf56e20ef6642c1b781333602e1559 Mon Sep 17 00:00:00 2001 From: Le Tan Date: Thu, 12 Apr 2018 19:31:35 +0800 Subject: [PATCH] do not highlight verbatim code blocks --- src/hgmarkdownhighlighter.cpp | 49 +++++++++++++++++++++++++++++++---- src/hgmarkdownhighlighter.h | 16 +++++++++++- src/vconstants.h | 5 +++- 3 files changed, 63 insertions(+), 7 deletions(-) diff --git a/src/hgmarkdownhighlighter.cpp b/src/hgmarkdownhighlighter.cpp index b5cf93a8..96bce5e9 100644 --- a/src/hgmarkdownhighlighter.cpp +++ b/src/hgmarkdownhighlighter.cpp @@ -121,7 +121,8 @@ void HGMarkdownHighlighter::updateBlockUserData(int p_blockNum, const QString &p void HGMarkdownHighlighter::highlightBlock(const QString &text) { - int blockNum = currentBlock().blockNumber(); + QTextBlock curBlock = currentBlock(); + int blockNum = curBlock.blockNumber(); if (m_blockHLResultReady && m_blockHighlights.size() > blockNum) { // units are sorted by start position and length. const QVector &units = m_blockHighlights[blockNum]; @@ -161,14 +162,20 @@ void HGMarkdownHighlighter::highlightBlock(const QString &text) updateBlockUserData(blockNum, text); // If it is a block inside HTML comment, just skip it. - if (isBlockInsideCommentRegion(currentBlock())) { + if (isBlockInsideCommentRegion(curBlock)) { setCurrentBlockState(HighlightBlockState::Comment); goto exit; } // PEG Markdown Highlight does not handle the ``` code block correctly. setCurrentBlockState(HighlightBlockState::Normal); - highlightCodeBlock(text); + highlightCodeBlock(curBlock, text); + + if (currentBlockState() == HighlightBlockState::Normal + && isVerbatimBlock(curBlock)) { + setCurrentBlockState(HighlightBlockState::Verbatim); + goto exit; + } // PEG Markdown Highlight does not handle links with spaces in the URL. // Links in the URL should be encoded to %20. We just let it be here and won't @@ -328,6 +335,31 @@ void HGMarkdownHighlighter::initImageRegionsFromResult() emit imageLinksUpdated(m_imageRegions); } +void HGMarkdownHighlighter::initVerbatimBlocksFromResult() +{ + m_verbatimBlocks.clear(); + if (!result) { + return; + } + + pmh_element *elem = result[pmh_VERBATIM]; + while (elem != NULL) { + if (elem->end <= elem->pos) { + elem = elem->next; + continue; + } + + // [firstBlock, lastBlock]. + int firstBlock = document->findBlock(elem->pos).blockNumber(); + int lastBlock = document->findBlock(elem->end - 1).blockNumber(); + for (int i = firstBlock; i <= lastBlock; ++i) { + m_verbatimBlocks.insert(i); + } + + elem = elem->next; + } +} + void HGMarkdownHighlighter::initHeaderRegionsFromResult() { // From Qt5.7, the capacity is preserved. @@ -404,7 +436,7 @@ void HGMarkdownHighlighter::initBlockHighlihgtOne(unsigned long pos, } } -void HGMarkdownHighlighter::highlightCodeBlock(const QString &text) +void HGMarkdownHighlighter::highlightCodeBlock(const QTextBlock &p_block, const QString &text) { VTextBlockData *blockData = currentBlockData(); Q_ASSERT(blockData); @@ -418,7 +450,7 @@ void HGMarkdownHighlighter::highlightCodeBlock(const QString &text) && preState != HighlightBlockState::CodeBlockStart) { // Need to find a new code block start. index = codeBlockStartExp.indexIn(text); - if (index >= 0) { + if (index >= 0 && !isVerbatimBlock(p_block)) { // Start a new code block. length = text.length(); state = HighlightBlockState::CodeBlockStart; @@ -533,6 +565,8 @@ void HGMarkdownHighlighter::parse(bool p_fast) initImageRegionsFromResult(); initHeaderRegionsFromResult(); + + initVerbatimBlocksFromResult(); } if (result) { @@ -630,6 +664,11 @@ bool HGMarkdownHighlighter::updateCodeBlocks() // Only handle complete codeblocks. QTextBlock block = document->firstBlock(); while (block.isValid()) { + if (!inBlock && isVerbatimBlock(block)) { + block = block.next(); + continue; + } + QString text = block.text(); if (inBlock) { item.m_text = item.m_text + "\n" + text; diff --git a/src/hgmarkdownhighlighter.h b/src/hgmarkdownhighlighter.h index 3f79ee70..3badf08e 100644 --- a/src/hgmarkdownhighlighter.h +++ b/src/hgmarkdownhighlighter.h @@ -232,6 +232,10 @@ private: // Sorted by start position. QVector m_headerRegions; + // All verbatim blocks (by parser) number. + // It may be a code block inside fenced code block. + QSet m_verbatimBlocks; + // Indexed by block number. QHash m_headerBlocks; @@ -256,7 +260,7 @@ private: static const int initCapacity; void resizeBuffer(int newCap); - void highlightCodeBlock(const QString &text); + void highlightCodeBlock(const QTextBlock &p_block, const QString &text); // Highlight links using regular expression. // PEG Markdown Highlight treat URLs with spaces illegal. This function is @@ -288,9 +292,15 @@ private: // Fetch all the header regions from parsing result. void initHeaderRegionsFromResult(); + // Fetch all the verbatim blocks from parsing result. + void initVerbatimBlocksFromResult(); + // Whether @p_block is totally inside a HTML comment. bool isBlockInsideCommentRegion(const QTextBlock &p_block) const; + // Whether @p_block is a Verbatim block. + bool isVerbatimBlock(const QTextBlock &p_block) const; + // Highlights have been changed. Try to signal highlightCompleted(). void highlightChanged(); @@ -361,4 +371,8 @@ inline QVector &HGMarkdownHighlighter::getHighlightingStyles( return highlightingStyles; } +inline bool HGMarkdownHighlighter::isVerbatimBlock(const QTextBlock &p_block) const +{ + return m_verbatimBlocks.contains(p_block.blockNumber()); +} #endif diff --git a/src/vconstants.h b/src/vconstants.h index c9c36baa..ef36f4e4 100644 --- a/src/vconstants.h +++ b/src/vconstants.h @@ -118,7 +118,10 @@ enum HighlightBlockState CodeBlockEnd, // This block is inside a HTML comment region. - Comment + Comment, + + // Verbatim code block. + Verbatim }; // Pages to open on start up.