mirror of
https://gitee.com/vnotex/vnote.git
synced 2025-07-05 13:59:52 +08:00
PegParser: support ~~~ as fenced code block
This commit is contained in:
parent
026f3a6535
commit
28eb48cc2e
File diff suppressed because it is too large
Load Diff
@ -25,8 +25,8 @@ PegHighlighterResult::PegHighlighterResult()
|
|||||||
m_codeBlockTimeStamp(0),
|
m_codeBlockTimeStamp(0),
|
||||||
m_numOfCodeBlockHighlightsToRecv(0)
|
m_numOfCodeBlockHighlightsToRecv(0)
|
||||||
{
|
{
|
||||||
m_codeBlockStartExp = QRegExp(VUtils::c_fencedCodeBlockStartRegExp);
|
m_codeBlockStartExp = QRegularExpression(VUtils::c_fencedCodeBlockStartRegExp);
|
||||||
m_codeBlockEndExp = QRegExp(VUtils::c_fencedCodeBlockEndRegExp);
|
m_codeBlockEndExp = QRegularExpression(VUtils::c_fencedCodeBlockEndRegExp);
|
||||||
}
|
}
|
||||||
|
|
||||||
PegHighlighterResult::PegHighlighterResult(const PegMarkdownHighlighter *p_peg,
|
PegHighlighterResult::PegHighlighterResult(const PegMarkdownHighlighter *p_peg,
|
||||||
@ -37,8 +37,8 @@ PegHighlighterResult::PegHighlighterResult(const PegMarkdownHighlighter *p_peg,
|
|||||||
m_codeBlockTimeStamp(0),
|
m_codeBlockTimeStamp(0),
|
||||||
m_numOfCodeBlockHighlightsToRecv(0)
|
m_numOfCodeBlockHighlightsToRecv(0)
|
||||||
{
|
{
|
||||||
m_codeBlockStartExp = QRegExp(VUtils::c_fencedCodeBlockStartRegExp);
|
m_codeBlockStartExp = QRegularExpression(VUtils::c_fencedCodeBlockStartRegExp);
|
||||||
m_codeBlockEndExp = QRegExp(VUtils::c_fencedCodeBlockEndRegExp);
|
m_codeBlockEndExp = QRegularExpression(VUtils::c_fencedCodeBlockEndRegExp);
|
||||||
|
|
||||||
parseBlocksHighlights(m_blocksHighlights, p_peg, p_result);
|
parseBlocksHighlights(m_blocksHighlights, p_peg, p_result);
|
||||||
|
|
||||||
@ -215,6 +215,7 @@ void PegHighlighterResult::parseFencedCodeBlocks(const PegMarkdownHighlighter *p
|
|||||||
const QTextDocument *doc = p_peg->getDocument();
|
const QTextDocument *doc = p_peg->getDocument();
|
||||||
VCodeBlock item;
|
VCodeBlock item;
|
||||||
bool inBlock = false;
|
bool inBlock = false;
|
||||||
|
QString marker;
|
||||||
for (auto it = regs.begin(); it != regs.end(); ++it) {
|
for (auto it = regs.begin(); it != regs.end(); ++it) {
|
||||||
QTextBlock block = doc->findBlock(it.value().m_startPos);
|
QTextBlock block = doc->findBlock(it.value().m_startPos);
|
||||||
int lastBlock = doc->findBlock(it.value().m_endPos - 1).blockNumber();
|
int lastBlock = doc->findBlock(it.value().m_endPos - 1).blockNumber();
|
||||||
@ -232,10 +233,12 @@ void PegHighlighterResult::parseFencedCodeBlocks(const PegMarkdownHighlighter *p
|
|||||||
QString text = block.text();
|
QString text = block.text();
|
||||||
if (inBlock) {
|
if (inBlock) {
|
||||||
item.m_text = item.m_text + "\n" + text;
|
item.m_text = item.m_text + "\n" + text;
|
||||||
int idx = m_codeBlockEndExp.indexIn(text);
|
auto match = m_codeBlockEndExp.match(text);
|
||||||
if (idx >= 0) {
|
if (match.hasMatch() && marker == match.captured(2)) {
|
||||||
// End block.
|
// End block.
|
||||||
inBlock = false;
|
inBlock = false;
|
||||||
|
marker.clear();
|
||||||
|
|
||||||
state = HighlightBlockState::CodeBlockEnd;
|
state = HighlightBlockState::CodeBlockEnd;
|
||||||
item.m_endBlock = blockNumber;
|
item.m_endBlock = blockNumber;
|
||||||
m_codeBlocks.append(item);
|
m_codeBlocks.append(item);
|
||||||
@ -244,17 +247,17 @@ void PegHighlighterResult::parseFencedCodeBlocks(const PegMarkdownHighlighter *p
|
|||||||
state = HighlightBlockState::CodeBlock;
|
state = HighlightBlockState::CodeBlock;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
int idx = m_codeBlockStartExp.indexIn(text);
|
auto match = m_codeBlockStartExp.match(text);
|
||||||
if (idx >= 0) {
|
if (match.hasMatch()) {
|
||||||
// Start block.
|
// Start block.
|
||||||
inBlock = true;
|
inBlock = true;
|
||||||
|
marker = match.captured(2);
|
||||||
|
|
||||||
state = HighlightBlockState::CodeBlockStart;
|
state = HighlightBlockState::CodeBlockStart;
|
||||||
item.m_startBlock = blockNumber;
|
item.m_startBlock = blockNumber;
|
||||||
item.m_startPos = block.position();
|
item.m_startPos = block.position();
|
||||||
item.m_text = text;
|
item.m_text = text;
|
||||||
if (m_codeBlockStartExp.captureCount() == 2) {
|
item.m_lang = match.captured(3).trimmed();
|
||||||
item.m_lang = m_codeBlockStartExp.capturedTexts()[2];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#define PEGHIGHLIGHTERRESULT_H
|
#define PEGHIGHLIGHTERRESULT_H
|
||||||
|
|
||||||
#include <QSet>
|
#include <QSet>
|
||||||
|
#include <QRegularExpression>
|
||||||
|
|
||||||
#include "vconstants.h"
|
#include "vconstants.h"
|
||||||
#include "pegparser.h"
|
#include "pegparser.h"
|
||||||
@ -114,8 +115,8 @@ private:
|
|||||||
unsigned long p_end);
|
unsigned long p_end);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
QRegExp m_codeBlockStartExp;
|
QRegularExpression m_codeBlockStartExp;
|
||||||
QRegExp m_codeBlockEndExp;
|
QRegularExpression m_codeBlockEndExp;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline bool PegHighlighterResult::matched(TimeStamp p_timeStamp) const
|
inline bool PegHighlighterResult::matched(TimeStamp p_timeStamp) const
|
||||||
|
@ -607,10 +607,10 @@ void PegMarkdownHighlighter::updateAllBlocksUserState(const QSharedPointer<PegHi
|
|||||||
case HighlightBlockState::CodeBlockStart:
|
case HighlightBlockState::CodeBlockStart:
|
||||||
{
|
{
|
||||||
int startLeadingSpaces = 0;
|
int startLeadingSpaces = 0;
|
||||||
QRegExp reg(VUtils::c_fencedCodeBlockStartRegExp);
|
QRegularExpression reg(VUtils::c_fencedCodeBlockStartRegExp);
|
||||||
int idx = reg.indexIn(block.text());
|
auto match = reg.match(block.text());
|
||||||
if (idx >= 0) {
|
if (match.hasMatch()) {
|
||||||
startLeadingSpaces = reg.capturedTexts()[1].size();
|
startLeadingSpaces = match.captured(1).size();
|
||||||
}
|
}
|
||||||
|
|
||||||
blockData->setCodeBlockIndentation(startLeadingSpaces);
|
blockData->setCodeBlockIndentation(startLeadingSpaces);
|
||||||
|
@ -112,9 +112,13 @@ As VNote suggests:
|
|||||||
This is a fenced code block.
|
This is a fenced code block.
|
||||||
```
|
```
|
||||||
|
|
||||||
|
~~~
|
||||||
|
This is another fenced code block.
|
||||||
|
~~~
|
||||||
|
|
||||||
**Notes**:
|
**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
|
### Diagrams
|
||||||
|
|
||||||
|
@ -113,9 +113,13 @@ As VNote suggests:
|
|||||||
This is a fenced code block.
|
This is a fenced code block.
|
||||||
```
|
```
|
||||||
|
|
||||||
|
~~~
|
||||||
|
This is another fenced code block.
|
||||||
|
~~~
|
||||||
|
|
||||||
**注意**:
|
**注意**:
|
||||||
|
|
||||||
- `lang`用于指定代码块的代码语言,可选;
|
- `lang`用于指定代码块的代码语言,可选;如果不指定,VNote不会尝试高亮代码;
|
||||||
|
|
||||||
### 图表
|
### 图表
|
||||||
|
|
||||||
|
@ -258,7 +258,7 @@ smart_live_preview=3
|
|||||||
insert_new_note_in_front=false
|
insert_new_note_in_front=false
|
||||||
|
|
||||||
; Whether highlight matches in page when activating a search result item
|
; 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
|
; Incremental search in page
|
||||||
find_incremental_search=true
|
find_incremental_search=true
|
||||||
|
@ -1130,9 +1130,16 @@ bool VEditUtils::isWordSeparator(QChar p_char)
|
|||||||
QString VEditUtils::removeCodeBlockFence(const QString &p_text)
|
QString VEditUtils::removeCodeBlockFence(const QString &p_text)
|
||||||
{
|
{
|
||||||
QString text = VCodeBlockHighlightHelper::unindentCodeBlock(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;
|
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)
|
bool VEditUtils::isSpaceOrWordSeparator(QChar p_char)
|
||||||
|
@ -61,9 +61,9 @@ const QString VUtils::c_linkRegExp = QString("\\[([^\\]]*)\\]"
|
|||||||
|
|
||||||
const QString VUtils::c_fileNameRegExp = QString("(?:[^\\\\/:\\*\\?\"<>\\|\\s]| )*");
|
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)");
|
const QString VUtils::c_previewImageBlockRegExp = QString("[\\n|^][ |\\t]*\\xfffc[ |\\t]*(?=\\n)");
|
||||||
|
|
||||||
|
@ -33,8 +33,8 @@ QString VCodeBlockHighlightHelper::unindentCodeBlock(const QString &p_text)
|
|||||||
}
|
}
|
||||||
|
|
||||||
QStringList lines = p_text.split('\n');
|
QStringList lines = p_text.split('\n');
|
||||||
V_ASSERT(lines[0].trimmed().startsWith("```"));
|
Q_ASSERT(lines[0].trimmed().startsWith("```") || lines[0].trimmed().startsWith("~~~"));
|
||||||
V_ASSERT(lines.size() > 1);
|
Q_ASSERT(lines.size() > 1);
|
||||||
|
|
||||||
QRegExp regExp("(^\\s*)");
|
QRegExp regExp("(^\\s*)");
|
||||||
regExp.indexIn(lines[0]);
|
regExp.indexIn(lines[0]);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user