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_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();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
||||
|
@ -113,9 +113,13 @@ As VNote suggests:
|
||||
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
|
||||
|
||||
; 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
|
||||
|
@ -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)
|
||||
|
@ -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)");
|
||||
|
||||
|
@ -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]);
|
||||
|
Loading…
x
Reference in New Issue
Block a user