mirror of
https://gitee.com/vnotex/vnote.git
synced 2025-07-05 13:59:52 +08:00
fix MathJax highlight with inline code, HTML comment, link, bold, and italic elements
This commit is contained in:
parent
80e65faca2
commit
67e40cbe87
@ -185,8 +185,13 @@ void HGMarkdownHighlighter::highlightBlock(const QString &text)
|
|||||||
if (isVerbatimBlock(curBlock)) {
|
if (isVerbatimBlock(curBlock)) {
|
||||||
setCurrentBlockState(HighlightBlockState::Verbatim);
|
setCurrentBlockState(HighlightBlockState::Verbatim);
|
||||||
goto exit;
|
goto exit;
|
||||||
} else if (m_enableMathjax) {
|
}
|
||||||
highlightMathJax(text);
|
|
||||||
|
highlightHeaderFast(blockNum, text);
|
||||||
|
|
||||||
|
if (m_enableMathjax
|
||||||
|
&& currentBlockState() == HighlightBlockState::Normal) {
|
||||||
|
highlightMathJax(curBlock, text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -195,8 +200,6 @@ void HGMarkdownHighlighter::highlightBlock(const QString &text)
|
|||||||
// fix this.
|
// fix this.
|
||||||
// highlightLinkWithSpacesInURL(text);
|
// highlightLinkWithSpacesInURL(text);
|
||||||
|
|
||||||
highlightHeaderFast(blockNum, text);
|
|
||||||
|
|
||||||
if (currentBlockState() != HighlightBlockState::CodeBlock) {
|
if (currentBlockState() != HighlightBlockState::CodeBlock) {
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
@ -304,7 +307,6 @@ void HGMarkdownHighlighter::initBlockHighlightFromResult(int nrBlocks)
|
|||||||
|
|
||||||
void HGMarkdownHighlighter::initHtmlCommentRegionsFromResult()
|
void HGMarkdownHighlighter::initHtmlCommentRegionsFromResult()
|
||||||
{
|
{
|
||||||
// From Qt5.7, the capacity is preserved.
|
|
||||||
m_commentRegions.clear();
|
m_commentRegions.clear();
|
||||||
|
|
||||||
if (!result) {
|
if (!result) {
|
||||||
@ -318,12 +320,9 @@ void HGMarkdownHighlighter::initHtmlCommentRegionsFromResult()
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_commentRegions.push_back(VElementRegion(elem->pos, elem->end));
|
initBlockElementRegionOne(m_commentRegions, elem->pos, elem->end);
|
||||||
|
|
||||||
elem = elem->next;
|
elem = elem->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
qDebug() << "highlighter: parse" << m_commentRegions.size() << "HTML comment regions";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void HGMarkdownHighlighter::initImageRegionsFromResult()
|
void HGMarkdownHighlighter::initImageRegionsFromResult()
|
||||||
@ -523,7 +522,7 @@ static bool intersect(const QList<QPair<int, int>> &p_indices, int &p_start, int
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void HGMarkdownHighlighter::highlightMathJax(const QString &p_text)
|
void HGMarkdownHighlighter::highlightMathJax(const QTextBlock &p_block, const QString &p_text)
|
||||||
{
|
{
|
||||||
const int blockMarkLength = 2;
|
const int blockMarkLength = 2;
|
||||||
const int inlineMarkLength = 1;
|
const int inlineMarkLength = 1;
|
||||||
@ -531,6 +530,8 @@ void HGMarkdownHighlighter::highlightMathJax(const QString &p_text)
|
|||||||
VTextBlockData *blockData = currentBlockData();
|
VTextBlockData *blockData = currentBlockData();
|
||||||
Q_ASSERT(blockData);
|
Q_ASSERT(blockData);
|
||||||
|
|
||||||
|
int blockNumber = p_block.blockNumber();
|
||||||
|
|
||||||
int startIdx = 0;
|
int startIdx = 0;
|
||||||
// Next position to search.
|
// Next position to search.
|
||||||
int pos = 0;
|
int pos = 0;
|
||||||
@ -542,71 +543,84 @@ void HGMarkdownHighlighter::highlightMathJax(const QString &p_text)
|
|||||||
// Mathjax block formula.
|
// Mathjax block formula.
|
||||||
if (state != HighlightBlockState::MathjaxBlock) {
|
if (state != HighlightBlockState::MathjaxBlock) {
|
||||||
fromPreBlock = false;
|
fromPreBlock = false;
|
||||||
startIdx = m_mathjaxBlockExp.indexIn(p_text);
|
startIdx = findMathjaxMarker(blockNumber, p_text, pos, m_mathjaxBlockExp, blockMarkLength);
|
||||||
pos = startIdx + m_mathjaxBlockExp.matchedLength();
|
pos = startIdx + blockMarkLength;
|
||||||
startIdx = pos - blockMarkLength;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
while (startIdx >= 0) {
|
while (startIdx >= 0) {
|
||||||
int endIdx = m_mathjaxBlockExp.indexIn(p_text, pos);
|
int endIdx = findMathjaxMarker(blockNumber, p_text, pos, m_mathjaxBlockExp, blockMarkLength);
|
||||||
int mathLength = 0;
|
int mathLength = 0;
|
||||||
MathjaxInfo info;
|
MathjaxInfo info;
|
||||||
|
bool valid = false;
|
||||||
if (endIdx == -1) {
|
if (endIdx == -1) {
|
||||||
setCurrentBlockState(HighlightBlockState::MathjaxBlock);
|
|
||||||
mathLength = p_text.length() - startIdx;
|
mathLength = p_text.length() - startIdx;
|
||||||
pos = startIdx + mathLength;
|
pos = p_text.length();
|
||||||
|
|
||||||
info.m_previewedAsBlock = false;
|
if (isValidMathjaxRegion(blockNumber, startIdx, pos)) {
|
||||||
info.m_index = startIdx,
|
valid = true;
|
||||||
info.m_length = mathLength;
|
setCurrentBlockState(HighlightBlockState::MathjaxBlock);
|
||||||
if (fromPreBlock) {
|
info.m_previewedAsBlock = false;
|
||||||
VTextBlockData *preBlockData = previousBlockData();
|
info.m_index = startIdx,
|
||||||
Q_ASSERT(preBlockData);
|
info.m_length = mathLength;
|
||||||
const MathjaxInfo &preInfo = preBlockData->getPendingMathjax();
|
if (fromPreBlock) {
|
||||||
info.m_text = preInfo.text() + "\n" + p_text.mid(startIdx, mathLength);
|
VTextBlockData *preBlockData = previousBlockData();
|
||||||
} else {
|
Q_ASSERT(preBlockData);
|
||||||
info.m_text = p_text.mid(startIdx, mathLength);
|
const MathjaxInfo &preInfo = preBlockData->getPendingMathjax();
|
||||||
|
info.m_text = preInfo.text() + "\n" + p_text.mid(startIdx, mathLength);
|
||||||
|
} else {
|
||||||
|
info.m_text = p_text.mid(startIdx, mathLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
blockData->setPendingMathjax(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
blockData->setPendingMathjax(info);
|
|
||||||
} else {
|
} else {
|
||||||
// Found end marker of a formula.
|
// Found end marker of a formula.
|
||||||
mathLength = endIdx - startIdx + m_mathjaxBlockExp.matchedLength();
|
pos = endIdx + blockMarkLength;
|
||||||
pos = startIdx + mathLength;
|
mathLength = pos - startIdx;
|
||||||
|
|
||||||
info.m_previewedAsBlock = false;
|
if (isValidMathjaxRegion(blockNumber, startIdx, pos)) {
|
||||||
info.m_index = startIdx;
|
valid = true;
|
||||||
info.m_length = mathLength;
|
info.m_previewedAsBlock = false;
|
||||||
if (fromPreBlock) {
|
info.m_index = startIdx;
|
||||||
// A cross-block formula.
|
info.m_length = mathLength;
|
||||||
if (pos >= p_text.length()) {
|
if (fromPreBlock) {
|
||||||
info.m_previewedAsBlock = true;
|
// A cross-block formula.
|
||||||
|
if (pos >= p_text.length()) {
|
||||||
|
info.m_previewedAsBlock = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
VTextBlockData *preBlockData = previousBlockData();
|
||||||
|
Q_ASSERT(preBlockData);
|
||||||
|
const MathjaxInfo &preInfo = preBlockData->getPendingMathjax();
|
||||||
|
info.m_text = preInfo.text() + "\n" + p_text.mid(startIdx, mathLength);
|
||||||
|
} else {
|
||||||
|
// A formula within one block.
|
||||||
|
if (pos >= p_text.length() && startIdx == 0) {
|
||||||
|
info.m_previewedAsBlock = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
info.m_text = p_text.mid(startIdx, mathLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
VTextBlockData *preBlockData = previousBlockData();
|
blockData->addMathjax(info);
|
||||||
Q_ASSERT(preBlockData);
|
|
||||||
const MathjaxInfo &preInfo = preBlockData->getPendingMathjax();
|
|
||||||
info.m_text = preInfo.text() + "\n" + p_text.mid(startIdx, mathLength);
|
|
||||||
} else {
|
|
||||||
// A formula within one block.
|
|
||||||
if (pos >= p_text.length() && startIdx == 0) {
|
|
||||||
info.m_previewedAsBlock = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
info.m_text = p_text.mid(startIdx, mathLength);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
blockData->addMathjax(info);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fromPreBlock = false;
|
fromPreBlock = false;
|
||||||
|
|
||||||
blockIdices.append(QPair<int, int>(startIdx, pos));
|
if (valid) {
|
||||||
|
blockIdices.append(QPair<int, int>(startIdx, pos));
|
||||||
|
setFormat(startIdx, mathLength, m_mathjaxFormat);
|
||||||
|
startIdx = findMathjaxMarker(blockNumber, p_text, pos, m_mathjaxBlockExp, blockMarkLength);
|
||||||
|
pos = startIdx + blockMarkLength;
|
||||||
|
} else {
|
||||||
|
// Make the second mark as the first one and try again.
|
||||||
|
if (endIdx == -1) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
setFormat(startIdx, mathLength, m_mathjaxFormat);
|
startIdx = pos - blockMarkLength;
|
||||||
startIdx = m_mathjaxBlockExp.indexIn(p_text, pos);
|
}
|
||||||
pos = startIdx + m_mathjaxBlockExp.matchedLength();
|
|
||||||
startIdx = pos - blockMarkLength;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mathjax inline formula.
|
// Mathjax inline formula.
|
||||||
@ -615,24 +629,25 @@ void HGMarkdownHighlighter::highlightMathJax(const QString &p_text)
|
|||||||
fromPreBlock = true;
|
fromPreBlock = true;
|
||||||
if (state != HighlightBlockState::MathjaxInline) {
|
if (state != HighlightBlockState::MathjaxInline) {
|
||||||
fromPreBlock = false;
|
fromPreBlock = false;
|
||||||
startIdx = m_mathjaxInlineExp.indexIn(p_text);
|
startIdx = findMathjaxMarker(blockNumber, p_text, pos, m_mathjaxInlineExp, inlineMarkLength);
|
||||||
pos = startIdx + m_mathjaxInlineExp.matchedLength();
|
pos = startIdx + inlineMarkLength;
|
||||||
startIdx = pos - inlineMarkLength;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
while (startIdx >= 0) {
|
while (startIdx >= 0) {
|
||||||
int endIdx = m_mathjaxInlineExp.indexIn(p_text, pos);
|
int endIdx = findMathjaxMarker(blockNumber, p_text, pos, m_mathjaxInlineExp, inlineMarkLength);
|
||||||
int mathLength = 0;
|
int mathLength = 0;
|
||||||
|
bool valid = false;
|
||||||
if (endIdx == -1) {
|
if (endIdx == -1) {
|
||||||
setCurrentBlockState(HighlightBlockState::MathjaxBlock);
|
|
||||||
mathLength = p_text.length() - startIdx;
|
mathLength = p_text.length() - startIdx;
|
||||||
|
pos = p_text.length();
|
||||||
} else {
|
} else {
|
||||||
mathLength = endIdx - startIdx + m_mathjaxInlineExp.matchedLength();
|
pos = endIdx + inlineMarkLength;
|
||||||
|
mathLength = pos - startIdx;
|
||||||
}
|
}
|
||||||
|
|
||||||
pos = startIdx + mathLength;
|
valid = isValidMathjaxRegion(blockNumber, startIdx, pos);
|
||||||
// Check if it intersect with blocks.
|
// Check if it intersect with blocks.
|
||||||
if (!intersect(blockIdices, startIdx, pos)) {
|
if (valid && !intersect(blockIdices, startIdx, pos)) {
|
||||||
// A valid inline mathjax.
|
// A valid inline mathjax.
|
||||||
MathjaxInfo info;
|
MathjaxInfo info;
|
||||||
if (endIdx == -1) {
|
if (endIdx == -1) {
|
||||||
@ -769,6 +784,12 @@ void HGMarkdownHighlighter::parse(bool p_fast)
|
|||||||
initHeaderRegionsFromResult();
|
initHeaderRegionsFromResult();
|
||||||
|
|
||||||
initVerbatimBlocksFromResult();
|
initVerbatimBlocksFromResult();
|
||||||
|
|
||||||
|
initInlineCodeRegionsFromResult();
|
||||||
|
|
||||||
|
initBoldItalicRegionsFromResult();
|
||||||
|
|
||||||
|
initLinkRegionsFromResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result) {
|
if (result) {
|
||||||
@ -989,11 +1010,12 @@ bool HGMarkdownHighlighter::isBlockInsideCommentRegion(const QTextBlock &p_block
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int start = p_block.position();
|
auto it = m_commentRegions.find(p_block.blockNumber());
|
||||||
int end = start + p_block.length();
|
if (it != m_commentRegions.end()) {
|
||||||
|
const QVector<VElementRegion> ®s = it.value();
|
||||||
for (auto const & reg : m_commentRegions) {
|
if (regs.size() == 1
|
||||||
if (reg.contains(start) && reg.contains(end)) {
|
&& regs[0].m_startPos == 0
|
||||||
|
&& regs[0].m_endPos == p_block.length()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1051,18 +1073,20 @@ bool HGMarkdownHighlighter::isValidHeader(const QString &p_text)
|
|||||||
|
|
||||||
void HGMarkdownHighlighter::highlightHeaderFast(int p_blockNumber, const QString &p_text)
|
void HGMarkdownHighlighter::highlightHeaderFast(int p_blockNumber, const QString &p_text)
|
||||||
{
|
{
|
||||||
if (currentBlockState() != HighlightBlockState::Normal) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto it = m_headerBlocks.find(p_blockNumber);
|
auto it = m_headerBlocks.find(p_blockNumber);
|
||||||
if (it != m_headerBlocks.end()) {
|
if (it != m_headerBlocks.end()) {
|
||||||
const HeaderBlockInfo &info = it.value();
|
const HeaderBlockInfo &info = it.value();
|
||||||
if (!isValidHeader(p_text)) {
|
if (!isValidHeader(p_text)) {
|
||||||
// Set an empty format to clear formats. It seems to work.
|
// Set an empty format to clear formats. It seems to work.
|
||||||
setFormat(0, p_text.size(), QTextCharFormat());
|
setFormat(0, p_text.size(), QTextCharFormat());
|
||||||
} else if (info.m_length < p_text.size()) {
|
} else {
|
||||||
setFormat(info.m_length, p_text.size() - info.m_length, m_headerStyles[info.m_level]);
|
if (info.m_length < p_text.size()) {
|
||||||
|
setFormat(info.m_length,
|
||||||
|
p_text.size() - info.m_length,
|
||||||
|
m_headerStyles[info.m_level]);
|
||||||
|
}
|
||||||
|
|
||||||
|
setCurrentBlockState(HighlightBlockState::Header);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1092,3 +1116,228 @@ void HGMarkdownHighlighter::updateMathjaxBlocks()
|
|||||||
|
|
||||||
emit mathjaxBlocksUpdated(blocks);
|
emit mathjaxBlocksUpdated(blocks);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HGMarkdownHighlighter::initInlineCodeRegionsFromResult()
|
||||||
|
{
|
||||||
|
m_inlineCodeRegions.clear();
|
||||||
|
|
||||||
|
if (!result) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
pmh_element *elem = result[pmh_CODE];
|
||||||
|
while (elem != NULL) {
|
||||||
|
if (elem->end <= elem->pos) {
|
||||||
|
elem = elem->next;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
initBlockElementRegionOne(m_inlineCodeRegions, elem->pos, elem->end);
|
||||||
|
elem = elem->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void HGMarkdownHighlighter::initBoldItalicRegionsFromResult()
|
||||||
|
{
|
||||||
|
m_boldItalicRegions.clear();
|
||||||
|
|
||||||
|
if (!result) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
pmh_element_type types[2] = {pmh_EMPH, pmh_STRONG};
|
||||||
|
|
||||||
|
for (int i = 0; i < 2; ++i) {
|
||||||
|
pmh_element *elem = result[types[i]];
|
||||||
|
while (elem != NULL) {
|
||||||
|
if (elem->end <= elem->pos) {
|
||||||
|
elem = elem->next;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
initBlockElementRegionOne(m_boldItalicRegions, elem->pos, elem->end);
|
||||||
|
elem = elem->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void HGMarkdownHighlighter::initLinkRegionsFromResult()
|
||||||
|
{
|
||||||
|
m_linkRegions.clear();
|
||||||
|
|
||||||
|
if (!result) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
pmh_element_type types[2] = {pmh_LINK, pmh_IMAGE};
|
||||||
|
|
||||||
|
for (int i = 0; i < 2; ++i) {
|
||||||
|
pmh_element *elem = result[types[i]];
|
||||||
|
while (elem != NULL) {
|
||||||
|
if (elem->end <= elem->pos) {
|
||||||
|
elem = elem->next;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
initBlockElementRegionOne(m_linkRegions, elem->pos, elem->end);
|
||||||
|
elem = elem->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void HGMarkdownHighlighter::initBlockElementRegionOne(QHash<int, QVector<VElementRegion>> &p_regs,
|
||||||
|
unsigned long p_pos,
|
||||||
|
unsigned long p_end)
|
||||||
|
{
|
||||||
|
// When the the highlight element is at the end of document, @p_end will equals
|
||||||
|
// to the characterCount.
|
||||||
|
unsigned int nrChar = (unsigned int)document->characterCount();
|
||||||
|
if (p_end >= nrChar && nrChar > 0) {
|
||||||
|
p_end = nrChar - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int startBlockNum = document->findBlock(p_pos).blockNumber();
|
||||||
|
int endBlockNum = document->findBlock(p_end).blockNumber();
|
||||||
|
|
||||||
|
for (int i = startBlockNum; i <= endBlockNum; ++i)
|
||||||
|
{
|
||||||
|
QTextBlock block = document->findBlockByNumber(i);
|
||||||
|
int blockStartPos = block.position();
|
||||||
|
|
||||||
|
QVector<VElementRegion> ®s = p_regs[i];
|
||||||
|
int start, end;
|
||||||
|
if (i == startBlockNum) {
|
||||||
|
start = p_pos - blockStartPos;
|
||||||
|
end = (startBlockNum == endBlockNum) ? (p_end - blockStartPos)
|
||||||
|
: block.length();
|
||||||
|
} else if (i == endBlockNum) {
|
||||||
|
start = 0;
|
||||||
|
end = p_end - blockStartPos;
|
||||||
|
} else {
|
||||||
|
start = 0;
|
||||||
|
end = block.length();
|
||||||
|
}
|
||||||
|
|
||||||
|
regs.append(VElementRegion(start, end));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool indexInsideRegion(const QVector<VElementRegion> &p_regions, int p_idx)
|
||||||
|
{
|
||||||
|
for (auto const & reg : p_regions) {
|
||||||
|
if (reg.contains(p_idx)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int HGMarkdownHighlighter::findMathjaxMarker(int p_blockNumber,
|
||||||
|
const QString &p_text,
|
||||||
|
int p_pos,
|
||||||
|
QRegExp &p_reg,
|
||||||
|
int p_markerLength)
|
||||||
|
{
|
||||||
|
if (p_pos >= p_text.size()) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int idx = -1;
|
||||||
|
auto inlineCodeIt = m_inlineCodeRegions.find(p_blockNumber);
|
||||||
|
auto commentIt = m_commentRegions.find(p_blockNumber);
|
||||||
|
auto boldItalicIt = m_boldItalicRegions.find(p_blockNumber);
|
||||||
|
auto linkIt = m_linkRegions.find(p_blockNumber);
|
||||||
|
|
||||||
|
while (p_pos < p_text.size()) {
|
||||||
|
idx = p_reg.indexIn(p_text, p_pos);
|
||||||
|
if (idx == -1) {
|
||||||
|
return idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
p_pos = idx + p_reg.matchedLength();
|
||||||
|
idx = p_pos - p_markerLength;
|
||||||
|
|
||||||
|
// Check if this idx is legal.
|
||||||
|
// Check inline code.
|
||||||
|
if (inlineCodeIt != m_inlineCodeRegions.end()) {
|
||||||
|
if (indexInsideRegion(inlineCodeIt.value(), idx)) {
|
||||||
|
idx = -1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (commentIt != m_commentRegions.end()) {
|
||||||
|
if (indexInsideRegion(commentIt.value(), idx)) {
|
||||||
|
idx = -1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (boldItalicIt != m_boldItalicRegions.end()) {
|
||||||
|
if (indexInsideRegion(boldItalicIt.value(), idx)) {
|
||||||
|
idx = -1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (linkIt != m_linkRegions.end()) {
|
||||||
|
if (indexInsideRegion(linkIt.value(), idx)) {
|
||||||
|
idx = -1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool intersectRegion(const QVector<VElementRegion> &p_regions,
|
||||||
|
int p_start,
|
||||||
|
int p_end)
|
||||||
|
{
|
||||||
|
for (auto const & reg : p_regions) {
|
||||||
|
if (reg.intersect(p_start, p_end)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HGMarkdownHighlighter::isValidMathjaxRegion(int p_blockNumber,
|
||||||
|
int p_start,
|
||||||
|
int p_end)
|
||||||
|
{
|
||||||
|
auto inlineCodeIt = m_inlineCodeRegions.find(p_blockNumber);
|
||||||
|
if (inlineCodeIt != m_inlineCodeRegions.end()) {
|
||||||
|
if (intersectRegion(inlineCodeIt.value(), p_start, p_end)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto commentIt = m_commentRegions.find(p_blockNumber);
|
||||||
|
if (commentIt != m_commentRegions.end()) {
|
||||||
|
if (intersectRegion(commentIt.value(), p_start, p_end)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto boldItalicIt = m_boldItalicRegions.find(p_blockNumber);
|
||||||
|
if (boldItalicIt != m_boldItalicRegions.end()) {
|
||||||
|
if (intersectRegion(boldItalicIt.value(), p_start, p_end)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto linkIt = m_linkRegions.find(p_blockNumber);
|
||||||
|
if (linkIt != m_linkRegions.end()) {
|
||||||
|
if (intersectRegion(linkIt.value(), p_start, p_end)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
@ -148,7 +148,12 @@ struct VElementRegion
|
|||||||
// Whether this region contains @p_pos.
|
// Whether this region contains @p_pos.
|
||||||
bool contains(int p_pos) const
|
bool contains(int p_pos) const
|
||||||
{
|
{
|
||||||
return m_startPos <= p_pos && m_endPos >= p_pos;
|
return m_startPos <= p_pos && m_endPos > p_pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool intersect(int p_start, int p_end) const
|
||||||
|
{
|
||||||
|
return !(p_end <= m_startPos || p_start >= m_endPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator==(const VElementRegion &p_other) const
|
bool operator==(const VElementRegion &p_other) const
|
||||||
@ -168,6 +173,11 @@ struct VElementRegion
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString toString() const
|
||||||
|
{
|
||||||
|
return QString("[%1,%2)").arg(m_startPos).arg(m_endPos);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class HGMarkdownHighlighter : public QSyntaxHighlighter
|
class HGMarkdownHighlighter : public QSyntaxHighlighter
|
||||||
@ -277,9 +287,6 @@ private:
|
|||||||
|
|
||||||
int m_numOfCodeBlockHighlightsToRecv;
|
int m_numOfCodeBlockHighlightsToRecv;
|
||||||
|
|
||||||
// All HTML comment regions.
|
|
||||||
QVector<VElementRegion> m_commentRegions;
|
|
||||||
|
|
||||||
// All image link regions.
|
// All image link regions.
|
||||||
QVector<VElementRegion> m_imageRegions;
|
QVector<VElementRegion> m_imageRegions;
|
||||||
|
|
||||||
@ -311,6 +318,18 @@ private:
|
|||||||
|
|
||||||
bool m_enableMathjax;
|
bool m_enableMathjax;
|
||||||
|
|
||||||
|
// Inline code regions for each block.
|
||||||
|
// VElementRegion's position is relative position within a block.
|
||||||
|
QHash<int, QVector<VElementRegion>> m_inlineCodeRegions;
|
||||||
|
|
||||||
|
QHash<int, QVector<VElementRegion>> m_boldItalicRegions;
|
||||||
|
|
||||||
|
// Including links and images.
|
||||||
|
QHash<int, QVector<VElementRegion>> m_linkRegions;
|
||||||
|
|
||||||
|
// Comment regions for each block.
|
||||||
|
QHash<int, QVector<VElementRegion>> m_commentRegions;
|
||||||
|
|
||||||
char *content;
|
char *content;
|
||||||
int capacity;
|
int capacity;
|
||||||
pmh_element **result;
|
pmh_element **result;
|
||||||
@ -321,7 +340,7 @@ private:
|
|||||||
|
|
||||||
void highlightCodeBlock(const QTextBlock &p_block, const QString &p_text);
|
void highlightCodeBlock(const QTextBlock &p_block, const QString &p_text);
|
||||||
|
|
||||||
void highlightMathJax(const QString &p_text);
|
void highlightMathJax(const QTextBlock &p_block, const QString &p_text);
|
||||||
|
|
||||||
// Highlight links using regular expression.
|
// Highlight links using regular expression.
|
||||||
// PEG Markdown Highlight treat URLs with spaces illegal. This function is
|
// PEG Markdown Highlight treat URLs with spaces illegal. This function is
|
||||||
@ -358,6 +377,19 @@ private:
|
|||||||
// Fetch all the verbatim blocks from parsing result.
|
// Fetch all the verbatim blocks from parsing result.
|
||||||
void initVerbatimBlocksFromResult();
|
void initVerbatimBlocksFromResult();
|
||||||
|
|
||||||
|
// Fetch all the inlnie code regions from parsing result.
|
||||||
|
void initInlineCodeRegionsFromResult();
|
||||||
|
|
||||||
|
// Fetch all bold/italic regions from parsing result.
|
||||||
|
void initBoldItalicRegionsFromResult();
|
||||||
|
|
||||||
|
// Fetch all bold/italic regions from parsing result.
|
||||||
|
void initLinkRegionsFromResult();
|
||||||
|
|
||||||
|
void initBlockElementRegionOne(QHash<int, QVector<VElementRegion>> &p_regs,
|
||||||
|
unsigned long p_pos,
|
||||||
|
unsigned long p_end);
|
||||||
|
|
||||||
// Whether @p_block is totally inside a HTML comment.
|
// Whether @p_block is totally inside a HTML comment.
|
||||||
bool isBlockInsideCommentRegion(const QTextBlock &p_block) const;
|
bool isBlockInsideCommentRegion(const QTextBlock &p_block) const;
|
||||||
|
|
||||||
@ -385,6 +417,14 @@ private:
|
|||||||
// Highlight headers using regular expression first instead of waiting for
|
// Highlight headers using regular expression first instead of waiting for
|
||||||
// another parse.
|
// another parse.
|
||||||
void highlightHeaderFast(int p_blockNumber, const QString &p_text);
|
void highlightHeaderFast(int p_blockNumber, const QString &p_text);
|
||||||
|
|
||||||
|
int findMathjaxMarker(int p_blockNumber,
|
||||||
|
const QString &p_text,
|
||||||
|
int p_pos,
|
||||||
|
QRegExp &p_reg,
|
||||||
|
int p_markerLength);
|
||||||
|
|
||||||
|
bool isValidMathjaxRegion(int p_blockNumber, int p_start, int p_end);
|
||||||
};
|
};
|
||||||
|
|
||||||
inline const QVector<VElementRegion> &HGMarkdownHighlighter::getHeaderRegions() const
|
inline const QVector<VElementRegion> &HGMarkdownHighlighter::getHeaderRegions() const
|
||||||
|
@ -38,7 +38,7 @@ color-column-foreground: eeeeee
|
|||||||
# [VNote] Style for preview image line
|
# [VNote] Style for preview image line
|
||||||
preview-image-line-foreground: 6f5799
|
preview-image-line-foreground: 6f5799
|
||||||
# [VNote] Style for MathJax
|
# [VNote] Style for MathJax
|
||||||
mathjax-foreground: ce93d8
|
mathjax-foreground: 4db6ac
|
||||||
|
|
||||||
editor-selection
|
editor-selection
|
||||||
foreground: dadada
|
foreground: dadada
|
||||||
|
@ -37,7 +37,7 @@ color-column-foreground: ffff00
|
|||||||
# [VNote] Style for preview image line
|
# [VNote] Style for preview image line
|
||||||
preview-image-line-foreground: 9575cd
|
preview-image-line-foreground: 9575cd
|
||||||
# [VNote] Style for MathJax
|
# [VNote] Style for MathJax
|
||||||
mathjax-foreground: 8e24aa
|
mathjax-foreground: 00897b
|
||||||
|
|
||||||
editor-selection
|
editor-selection
|
||||||
foreground: eeeeee
|
foreground: eeeeee
|
||||||
|
@ -38,7 +38,7 @@ color-column-foreground: ffff00
|
|||||||
# [VNote] Style for preview image line
|
# [VNote] Style for preview image line
|
||||||
preview-image-line-foreground: 9575cd
|
preview-image-line-foreground: 9575cd
|
||||||
# [VNote] Style for MathJax
|
# [VNote] Style for MathJax
|
||||||
mathjax-foreground: 8e24aa
|
mathjax-foreground: 00897b
|
||||||
|
|
||||||
editor-selection
|
editor-selection
|
||||||
foreground: eeeeee
|
foreground: eeeeee
|
||||||
|
@ -125,7 +125,10 @@ enum HighlightBlockState
|
|||||||
|
|
||||||
// Mathjax. It means the pending state of the block.
|
// Mathjax. It means the pending state of the block.
|
||||||
MathjaxBlock,
|
MathjaxBlock,
|
||||||
MathjaxInline
|
MathjaxInline,
|
||||||
|
|
||||||
|
// Header.
|
||||||
|
Header
|
||||||
};
|
};
|
||||||
|
|
||||||
// Pages to open on start up.
|
// Pages to open on start up.
|
||||||
|
@ -43,12 +43,6 @@ void VMathJaxPreviewHelper::doInit()
|
|||||||
m_webView->hide();
|
m_webView->hide();
|
||||||
m_webView->setFocusPolicy(Qt::NoFocus);
|
m_webView->setFocusPolicy(Qt::NoFocus);
|
||||||
|
|
||||||
if (focusWid) {
|
|
||||||
focusWid->setFocus();
|
|
||||||
} else {
|
|
||||||
m_parentWidget->setFocus();
|
|
||||||
}
|
|
||||||
|
|
||||||
m_webDoc = new VMathJaxWebDocument(m_webView);
|
m_webDoc = new VMathJaxWebDocument(m_webView);
|
||||||
connect(m_webDoc, &VMathJaxWebDocument::mathjaxPreviewResultReady,
|
connect(m_webDoc, &VMathJaxWebDocument::mathjaxPreviewResultReady,
|
||||||
this, [this](int p_identifier,
|
this, [this](int p_identifier,
|
||||||
@ -75,6 +69,12 @@ void VMathJaxPreviewHelper::doInit()
|
|||||||
m_webView->page()->setWebChannel(channel);
|
m_webView->page()->setWebChannel(channel);
|
||||||
|
|
||||||
m_webView->setHtml(VUtils::generateMathJaxPreviewTemplate(), QUrl("qrc:/resources"));
|
m_webView->setHtml(VUtils::generateMathJaxPreviewTemplate(), QUrl("qrc:/resources"));
|
||||||
|
|
||||||
|
if (focusWid) {
|
||||||
|
focusWid->setFocus();
|
||||||
|
} else {
|
||||||
|
m_parentWidget->setFocus();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VMathJaxPreviewHelper::previewMathJax(int p_identifier,
|
void VMathJaxPreviewHelper::previewMathJax(int p_identifier,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user