浏览代码

PegParser: support ~~~ as fenced code block

Le Tan 7 年之前
父节点
当前提交
28eb48cc2e

文件差异内容过多而无法显示
+ 503 - 421
peg-highlight/pmh_parser.c


+ 14 - 11
src/peghighlighterresult.cpp

@@ -25,8 +25,8 @@ PegHighlighterResult::PegHighlighterResult()
       m_codeBlockTimeStamp(0),
       m_numOfCodeBlockHighlightsToRecv(0)
 {
-    m_codeBlockStartExp = QRegExp(VUtils::c_fencedCodeBlockStartRegExp);
-    m_codeBlockEndExp = QRegExp(VUtils::c_fencedCodeBlockEndRegExp);
+    m_codeBlockStartExp = QRegularExpression(VUtils::c_fencedCodeBlockStartRegExp);
+    m_codeBlockEndExp = QRegularExpression(VUtils::c_fencedCodeBlockEndRegExp);
 }
 
 PegHighlighterResult::PegHighlighterResult(const PegMarkdownHighlighter *p_peg,
@@ -37,8 +37,8 @@ PegHighlighterResult::PegHighlighterResult(const PegMarkdownHighlighter *p_peg,
       m_codeBlockTimeStamp(0),
       m_numOfCodeBlockHighlightsToRecv(0)
 {
-    m_codeBlockStartExp = QRegExp(VUtils::c_fencedCodeBlockStartRegExp);
-    m_codeBlockEndExp = QRegExp(VUtils::c_fencedCodeBlockEndRegExp);
+    m_codeBlockStartExp = QRegularExpression(VUtils::c_fencedCodeBlockStartRegExp);
+    m_codeBlockEndExp = QRegularExpression(VUtils::c_fencedCodeBlockEndRegExp);
 
     parseBlocksHighlights(m_blocksHighlights, p_peg, p_result);
 
@@ -215,6 +215,7 @@ void PegHighlighterResult::parseFencedCodeBlocks(const PegMarkdownHighlighter *p
     const QTextDocument *doc = p_peg->getDocument();
     VCodeBlock item;
     bool inBlock = false;
+    QString marker;
     for (auto it = regs.begin(); it != regs.end(); ++it) {
         QTextBlock block = doc->findBlock(it.value().m_startPos);
         int lastBlock = doc->findBlock(it.value().m_endPos - 1).blockNumber();
@@ -232,10 +233,12 @@ void PegHighlighterResult::parseFencedCodeBlocks(const PegMarkdownHighlighter *p
             QString text = block.text();
             if (inBlock) {
                 item.m_text = item.m_text + "\n" + text;
-                int idx = m_codeBlockEndExp.indexIn(text);
-                if (idx >= 0) {
+                auto match = m_codeBlockEndExp.match(text);
+                if (match.hasMatch() && marker == match.captured(2)) {
                     // End block.
                     inBlock = false;
+                    marker.clear();
+
                     state = HighlightBlockState::CodeBlockEnd;
                     item.m_endBlock = blockNumber;
                     m_codeBlocks.append(item);
@@ -244,17 +247,17 @@ void PegHighlighterResult::parseFencedCodeBlocks(const PegMarkdownHighlighter *p
                     state = HighlightBlockState::CodeBlock;
                 }
             } else {
-                int idx = m_codeBlockStartExp.indexIn(text);
-                if (idx >= 0) {
+                auto match = m_codeBlockStartExp.match(text);
+                if (match.hasMatch()) {
                     // Start block.
                     inBlock = true;
+                    marker = match.captured(2);
+
                     state = HighlightBlockState::CodeBlockStart;
                     item.m_startBlock = blockNumber;
                     item.m_startPos = block.position();
                     item.m_text = text;
-                    if (m_codeBlockStartExp.captureCount() == 2) {
-                        item.m_lang = m_codeBlockStartExp.capturedTexts()[2];
-                    }
+                    item.m_lang = match.captured(3).trimmed();
                 }
             }
 

+ 3 - 2
src/peghighlighterresult.h

@@ -2,6 +2,7 @@
 #define PEGHIGHLIGHTERRESULT_H
 
 #include <QSet>
+#include <QRegularExpression>
 
 #include "vconstants.h"
 #include "pegparser.h"
@@ -114,8 +115,8 @@ private:
                                      unsigned long p_end);
 #endif
 
-    QRegExp m_codeBlockStartExp;
-    QRegExp m_codeBlockEndExp;
+    QRegularExpression m_codeBlockStartExp;
+    QRegularExpression m_codeBlockEndExp;
 };
 
 inline bool PegHighlighterResult::matched(TimeStamp p_timeStamp) const

+ 4 - 4
src/pegmarkdownhighlighter.cpp

@@ -607,10 +607,10 @@ void PegMarkdownHighlighter::updateAllBlocksUserState(const QSharedPointer<PegHi
             case HighlightBlockState::CodeBlockStart:
             {
                 int startLeadingSpaces = 0;
-                QRegExp reg(VUtils::c_fencedCodeBlockStartRegExp);
-                int idx = reg.indexIn(block.text());
-                if (idx >= 0) {
-                    startLeadingSpaces = reg.capturedTexts()[1].size();
+                QRegularExpression reg(VUtils::c_fencedCodeBlockStartRegExp);
+                auto match = reg.match(block.text());
+                if (match.hasMatch()) {
+                    startLeadingSpaces = match.captured(1).size();
                 }
 
                 blockData->setCodeBlockIndentation(startLeadingSpaces);

+ 5 - 1
src/resources/docs/markdown_guide_en.md

@@ -112,9 +112,13 @@ As VNote suggests:
     This is a fenced code block.
     ```
 
+    ~~~
+    This is another fenced code block.
+    ~~~
+
 **Notes**:
 
-- `lang` is optional to specify the language of the code;
+- `lang` is optional to specify the language of the code; if not specified, VNote won't highlight the code;
 
 ### Diagrams
 

+ 5 - 1
src/resources/docs/markdown_guide_zh.md

@@ -113,9 +113,13 @@ As VNote suggests:
     This is a fenced code block.
     ```
 
+    ~~~
+    This is another fenced code block.
+    ~~~
+
 **注意**:
 
-- `lang`用于指定代码块的代码语言,可选;
+- `lang`用于指定代码块的代码语言,可选;如果不指定,VNote不会尝试高亮代码;
 
 ### 图表
 

+ 1 - 1
src/resources/vnote.ini

@@ -258,7 +258,7 @@ smart_live_preview=3
 insert_new_note_in_front=false
 
 ; Whether highlight matches in page when activating a search result item
-highlight_matches_in_page=true
+highlight_matches_in_page=false
 
 ; Incremental search in page
 find_incremental_search=true

+ 9 - 2
src/utils/veditutils.cpp

@@ -1130,9 +1130,16 @@ bool VEditUtils::isWordSeparator(QChar p_char)
 QString VEditUtils::removeCodeBlockFence(const QString &p_text)
 {
     QString text = VCodeBlockHighlightHelper::unindentCodeBlock(p_text);
-    Q_ASSERT(text.startsWith("```") && text.endsWith("```"));
+    Q_ASSERT(text.startsWith("```") || text.startsWith("~~~"));
     int idx = text.indexOf('\n') + 1;
-    return text.mid(idx, text.size() - idx - 3);
+    int lidx = text.size() - 1;
+    // Trim spaces at the end.
+    while (lidx >= 0 && text[lidx].isSpace()) {
+        --lidx;
+    }
+
+    Q_ASSERT(text[lidx] == '`' || text[lidx] == '~');
+    return text.mid(idx, lidx + 1 - idx - 3);
 }
 
 bool VEditUtils::isSpaceOrWordSeparator(QChar p_char)

+ 2 - 2
src/utils/vutils.cpp

@@ -61,9 +61,9 @@ const QString VUtils::c_linkRegExp = QString("\\[([^\\]]*)\\]"
 
 const QString VUtils::c_fileNameRegExp = QString("(?:[^\\\\/:\\*\\?\"<>\\|\\s]| )*");
 
-const QString VUtils::c_fencedCodeBlockStartRegExp = QString("^(\\s*)```([^`\\s]*)\\s*[^`]*$");
+const QString VUtils::c_fencedCodeBlockStartRegExp = QString("^(\\s*)([`~])\\2{2}((?:(?!\\2)[^\\r\\n])*)$");
 
-const QString VUtils::c_fencedCodeBlockEndRegExp = QString("^(\\s*)```$");
+const QString VUtils::c_fencedCodeBlockEndRegExp = QString("^(\\s*)([`~])\\2{2}\\s*$");
 
 const QString VUtils::c_previewImageBlockRegExp = QString("[\\n|^][ |\\t]*\\xfffc[ |\\t]*(?=\\n)");
 

+ 2 - 2
src/vcodeblockhighlighthelper.cpp

@@ -33,8 +33,8 @@ QString VCodeBlockHighlightHelper::unindentCodeBlock(const QString &p_text)
     }
 
     QStringList lines = p_text.split('\n');
-    V_ASSERT(lines[0].trimmed().startsWith("```"));
-    V_ASSERT(lines.size() > 1);
+    Q_ASSERT(lines[0].trimmed().startsWith("```") || lines[0].trimmed().startsWith("~~~"));
+    Q_ASSERT(lines.size() > 1);
 
     QRegExp regExp("(^\\s*)");
     regExp.indexIn(lines[0]);

部分文件因为文件数量过多而无法显示