mirror of
https://gitee.com/vnotex/vnote.git
synced 2025-07-06 06:19:52 +08:00
bugfix: fix nested fenced code block issue
The opening ``` and closing ``` should have the same indentation.
This commit is contained in:
parent
85c09c296d
commit
4730d67393
@ -4,6 +4,7 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include "hgmarkdownhighlighter.h"
|
#include "hgmarkdownhighlighter.h"
|
||||||
#include "vconfigmanager.h"
|
#include "vconfigmanager.h"
|
||||||
|
#include "utils/vutils.h"
|
||||||
|
|
||||||
extern VConfigManager vconfig;
|
extern VConfigManager vconfig;
|
||||||
|
|
||||||
@ -31,8 +32,9 @@ HGMarkdownHighlighter::HGMarkdownHighlighter(const QVector<HighlightingStyle> &s
|
|||||||
m_codeBlockStyles(codeBlockStyles), m_numOfCodeBlockHighlightsToRecv(0),
|
m_codeBlockStyles(codeBlockStyles), m_numOfCodeBlockHighlightsToRecv(0),
|
||||||
parsing(0), waitInterval(waitInterval), content(NULL), capacity(0), result(NULL)
|
parsing(0), waitInterval(waitInterval), content(NULL), capacity(0), result(NULL)
|
||||||
{
|
{
|
||||||
codeBlockStartExp = QRegExp("^\\s*```(\\S*)");
|
codeBlockStartExp = QRegExp(VUtils::c_fencedCodeBlockStartRegExp);
|
||||||
codeBlockEndExp = QRegExp("^\\s*```$");
|
codeBlockEndExp = QRegExp(VUtils::c_fencedCodeBlockEndRegExp);
|
||||||
|
|
||||||
codeBlockFormat.setForeground(QBrush(Qt::darkYellow));
|
codeBlockFormat.setForeground(QBrush(Qt::darkYellow));
|
||||||
for (int index = 0; index < styles.size(); ++index) {
|
for (int index = 0; index < styles.size(); ++index) {
|
||||||
const pmh_element_type &eleType = styles[index].type;
|
const pmh_element_type &eleType = styles[index].type;
|
||||||
@ -223,34 +225,48 @@ void HGMarkdownHighlighter::initBlockHighlihgtOne(unsigned long pos, unsigned lo
|
|||||||
|
|
||||||
void HGMarkdownHighlighter::highlightCodeBlock(const QString &text)
|
void HGMarkdownHighlighter::highlightCodeBlock(const QString &text)
|
||||||
{
|
{
|
||||||
int nextIndex = 0;
|
static int startLeadingSpaces = -1;
|
||||||
int startIndex = 0;
|
int length = 0;
|
||||||
if (previousBlockState() != HighlightBlockState::CodeBlock) {
|
int index = -1;
|
||||||
startIndex = codeBlockStartExp.indexIn(text);
|
int preState = previousBlockState();
|
||||||
if (startIndex >= 0) {
|
int state = HighlightBlockState::Normal;
|
||||||
nextIndex = startIndex + codeBlockStartExp.matchedLength();
|
|
||||||
|
if (preState != HighlightBlockState::CodeBlock
|
||||||
|
&& preState != HighlightBlockState::CodeBlockStart) {
|
||||||
|
// Need to find a new code block start.
|
||||||
|
index = codeBlockStartExp.indexIn(text);
|
||||||
|
if (index >= 0) {
|
||||||
|
// Start a new code block.
|
||||||
|
length = text.length();
|
||||||
|
state = HighlightBlockState::CodeBlockStart;
|
||||||
|
|
||||||
|
// The leading spaces of code block start and end must be identical.
|
||||||
|
startLeadingSpaces = codeBlockStartExp.capturedTexts()[1].size();
|
||||||
} else {
|
} else {
|
||||||
nextIndex = -1;
|
// A normal block.
|
||||||
|
startLeadingSpaces = -1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Need to find a code block end.
|
||||||
|
index = codeBlockEndExp.indexIn(text);
|
||||||
|
|
||||||
|
// The closing ``` should have the same indentation as the open ```.
|
||||||
|
if (index >= 0
|
||||||
|
&& startLeadingSpaces == codeBlockEndExp.capturedTexts()[1].size()) {
|
||||||
|
// End of code block.
|
||||||
|
length = text.length();
|
||||||
|
state = HighlightBlockState::CodeBlockEnd;
|
||||||
|
} else {
|
||||||
|
// Within code block.
|
||||||
|
index = 0;
|
||||||
|
length = text.length();
|
||||||
|
state = HighlightBlockState::CodeBlock;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while (nextIndex >= 0) {
|
setCurrentBlockState(state);
|
||||||
int endIndex = codeBlockEndExp.indexIn(text, nextIndex);
|
setFormat(index, length, codeBlockFormat);
|
||||||
int codeBlockLength;
|
|
||||||
if (endIndex == -1) {
|
|
||||||
setCurrentBlockState(HighlightBlockState::CodeBlock);
|
|
||||||
codeBlockLength = text.length() - startIndex;
|
|
||||||
} else {
|
|
||||||
codeBlockLength = endIndex - startIndex + codeBlockEndExp.matchedLength();
|
|
||||||
}
|
|
||||||
setFormat(startIndex, codeBlockLength, codeBlockFormat);
|
|
||||||
startIndex = codeBlockStartExp.indexIn(text, startIndex + codeBlockLength);
|
|
||||||
if (startIndex >= 0) {
|
|
||||||
nextIndex = startIndex + codeBlockStartExp.matchedLength();
|
|
||||||
} else {
|
|
||||||
nextIndex = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void HGMarkdownHighlighter::highlightLinkWithSpacesInURL(const QString &p_text)
|
void HGMarkdownHighlighter::highlightLinkWithSpacesInURL(const QString &p_text)
|
||||||
@ -369,6 +385,7 @@ bool HGMarkdownHighlighter::updateCodeBlocks()
|
|||||||
|
|
||||||
VCodeBlock item;
|
VCodeBlock item;
|
||||||
bool inBlock = false;
|
bool inBlock = false;
|
||||||
|
int startLeadingSpaces = -1;
|
||||||
|
|
||||||
// Only handle complete codeblocks.
|
// Only handle complete codeblocks.
|
||||||
QTextBlock block = document->firstBlock();
|
QTextBlock block = document->firstBlock();
|
||||||
@ -377,13 +394,14 @@ bool HGMarkdownHighlighter::updateCodeBlocks()
|
|||||||
if (inBlock) {
|
if (inBlock) {
|
||||||
item.m_text = item.m_text + "\n" + text;
|
item.m_text = item.m_text + "\n" + text;
|
||||||
int idx = codeBlockEndExp.indexIn(text);
|
int idx = codeBlockEndExp.indexIn(text);
|
||||||
if (idx >= 0) {
|
if (idx >= 0 && codeBlockEndExp.capturedTexts()[1].size() == startLeadingSpaces) {
|
||||||
// End block.
|
// End block.
|
||||||
inBlock = false;
|
inBlock = false;
|
||||||
item.m_endBlock = block.blockNumber();
|
item.m_endBlock = block.blockNumber();
|
||||||
|
|
||||||
// See if it is a code block inside HTML comment.
|
// See if it is a code block inside HTML comment.
|
||||||
if (!isBlockInsideCommentRegion(block)) {
|
if (!isBlockInsideCommentRegion(block)) {
|
||||||
|
qDebug() << "add one code block in lang" << item.m_lang;
|
||||||
codeBlocks.append(item);
|
codeBlocks.append(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -395,11 +413,14 @@ bool HGMarkdownHighlighter::updateCodeBlocks()
|
|||||||
item.m_startBlock = block.blockNumber();
|
item.m_startBlock = block.blockNumber();
|
||||||
item.m_startPos = block.position();
|
item.m_startPos = block.position();
|
||||||
item.m_text = text;
|
item.m_text = text;
|
||||||
if (codeBlockStartExp.captureCount() == 1) {
|
if (codeBlockStartExp.captureCount() == 2) {
|
||||||
item.m_lang = codeBlockStartExp.capturedTexts()[1];
|
item.m_lang = codeBlockStartExp.capturedTexts()[2];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
startLeadingSpaces = codeBlockStartExp.capturedTexts()[1].size();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
block = block.next();
|
block = block.next();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,7 +28,9 @@ enum HighlightBlockState
|
|||||||
Normal = 0,
|
Normal = 0,
|
||||||
|
|
||||||
// A fenced code block.
|
// A fenced code block.
|
||||||
|
CodeBlockStart,
|
||||||
CodeBlock,
|
CodeBlock,
|
||||||
|
CodeBlockEnd,
|
||||||
|
|
||||||
// This block is inside a HTML comment region.
|
// This block is inside a HTML comment region.
|
||||||
Comment
|
Comment
|
||||||
|
@ -29,6 +29,10 @@ const QString VUtils::c_imageLinkRegExp = QString("\\!\\[([^\\]]*)\\]\\(([^\\)\"
|
|||||||
|
|
||||||
const QString VUtils::c_fileNameRegExp = QString("[^\\\\/:\\*\\?\"<>\\|]*");
|
const QString VUtils::c_fileNameRegExp = QString("[^\\\\/:\\*\\?\"<>\\|]*");
|
||||||
|
|
||||||
|
const QString VUtils::c_fencedCodeBlockStartRegExp = QString("^(\\s*)```([^`\\s]*)\\s*[^`]*$");
|
||||||
|
|
||||||
|
const QString VUtils::c_fencedCodeBlockEndRegExp = QString("^(\\s*)```$");
|
||||||
|
|
||||||
VUtils::VUtils()
|
VUtils::VUtils()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -109,6 +109,10 @@ public:
|
|||||||
// Forbidden char: \/:*?"<>|
|
// Forbidden char: \/:*?"<>|
|
||||||
static const QString c_fileNameRegExp;
|
static const QString c_fileNameRegExp;
|
||||||
|
|
||||||
|
// Regular expression for fenced code block.
|
||||||
|
static const QString c_fencedCodeBlockStartRegExp;
|
||||||
|
static const QString c_fencedCodeBlockEndRegExp;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// <value, name>
|
// <value, name>
|
||||||
static const QVector<QPair<QString, QString>> c_availableLanguages;
|
static const QVector<QPair<QString, QString>> c_availableLanguages;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user