PegParser: support ~~~ as fenced code block

This commit is contained in:
Le Tan 2018-11-22 20:31:47 +08:00
parent 026f3a6535
commit 28eb48cc2e
10 changed files with 727 additions and 626 deletions

File diff suppressed because it is too large Load Diff

View File

@ -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();
}
}

View File

@ -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

View File

@ -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);

View File

@ -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

View File

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

View File

@ -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

View File

@ -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)

View File

@ -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)");

View File

@ -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]);