mirror of
https://gitee.com/vnotex/vnote.git
synced 2025-07-05 13:59:52 +08:00
handle HTML comment correctly
This commit is contained in:
parent
97051badf0
commit
5b150a3634
@ -24,7 +24,7 @@ void HGMarkdownHighlighter::resizeBuffer(int newCap)
|
|||||||
|
|
||||||
// Will be freeed by parent automatically
|
// Will be freeed by parent automatically
|
||||||
HGMarkdownHighlighter::HGMarkdownHighlighter(const QVector<HighlightingStyle> &styles,
|
HGMarkdownHighlighter::HGMarkdownHighlighter(const QVector<HighlightingStyle> &styles,
|
||||||
const QMap<QString, QTextCharFormat> &codeBlockStyles,
|
const QHash<QString, QTextCharFormat> &codeBlockStyles,
|
||||||
int waitInterval,
|
int waitInterval,
|
||||||
QTextDocument *parent)
|
QTextDocument *parent)
|
||||||
: QSyntaxHighlighter(parent), highlightingStyles(styles),
|
: QSyntaxHighlighter(parent), highlightingStyles(styles),
|
||||||
@ -47,10 +47,19 @@ HGMarkdownHighlighter::HGMarkdownHighlighter(const QVector<HighlightingStyle> &s
|
|||||||
|
|
||||||
resizeBuffer(initCapacity);
|
resizeBuffer(initCapacity);
|
||||||
document = parent;
|
document = parent;
|
||||||
|
|
||||||
timer = new QTimer(this);
|
timer = new QTimer(this);
|
||||||
timer->setSingleShot(true);
|
timer->setSingleShot(true);
|
||||||
timer->setInterval(this->waitInterval);
|
timer->setInterval(this->waitInterval);
|
||||||
connect(timer, &QTimer::timeout, this, &HGMarkdownHighlighter::timerTimeout);
|
connect(timer, &QTimer::timeout, this, &HGMarkdownHighlighter::timerTimeout);
|
||||||
|
|
||||||
|
static const int completeWaitTime = 500;
|
||||||
|
m_completeTimer = new QTimer(this);
|
||||||
|
m_completeTimer->setSingleShot(true);
|
||||||
|
m_completeTimer->setInterval(completeWaitTime);
|
||||||
|
connect(m_completeTimer, &QTimer::timeout,
|
||||||
|
this, &HGMarkdownHighlighter::highlightCompleted);
|
||||||
|
|
||||||
connect(document, &QTextDocument::contentsChange,
|
connect(document, &QTextDocument::contentsChange,
|
||||||
this, &HGMarkdownHighlighter::handleContentChange);
|
this, &HGMarkdownHighlighter::handleContentChange);
|
||||||
}
|
}
|
||||||
@ -83,6 +92,12 @@ void HGMarkdownHighlighter::highlightBlock(const QString &text)
|
|||||||
// We use PEG Markdown Highlight as the main highlighter.
|
// We use PEG Markdown Highlight as the main highlighter.
|
||||||
// We can use other highlighting methods to complement it.
|
// We can use other highlighting methods to complement it.
|
||||||
|
|
||||||
|
// If it is a block inside HTML comment, just skip it.
|
||||||
|
if (isBlockInsideCommentRegion(currentBlock())) {
|
||||||
|
setCurrentBlockState(HighlightBlockState::Comment);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
// PEG Markdown Highlight does not handle the ``` code block correctly.
|
// PEG Markdown Highlight does not handle the ``` code block correctly.
|
||||||
setCurrentBlockState(HighlightBlockState::Normal);
|
setCurrentBlockState(HighlightBlockState::Normal);
|
||||||
highlightCodeBlock(text);
|
highlightCodeBlock(text);
|
||||||
@ -123,6 +138,9 @@ void HGMarkdownHighlighter::highlightBlock(const QString &text)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exit:
|
||||||
|
highlightChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
void HGMarkdownHighlighter::initBlockHighlightFromResult(int nrBlocks)
|
void HGMarkdownHighlighter::initBlockHighlightFromResult(int nrBlocks)
|
||||||
@ -142,6 +160,8 @@ void HGMarkdownHighlighter::initBlockHighlightFromResult(int nrBlocks)
|
|||||||
pmh_element *elem_cursor = result[style.type];
|
pmh_element *elem_cursor = result[style.type];
|
||||||
while (elem_cursor != NULL)
|
while (elem_cursor != NULL)
|
||||||
{
|
{
|
||||||
|
// elem_cursor->pos and elem_cursor->end is the start
|
||||||
|
// and end position of the element in document.
|
||||||
if (elem_cursor->end <= elem_cursor->pos) {
|
if (elem_cursor->end <= elem_cursor->pos) {
|
||||||
elem_cursor = elem_cursor->next;
|
elem_cursor = elem_cursor->next;
|
||||||
continue;
|
continue;
|
||||||
@ -150,9 +170,29 @@ void HGMarkdownHighlighter::initBlockHighlightFromResult(int nrBlocks)
|
|||||||
elem_cursor = elem_cursor->next;
|
elem_cursor = elem_cursor->next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pmh_free_elements(result);
|
void HGMarkdownHighlighter::initHtmlCommentRegionsFromResult()
|
||||||
result = NULL;
|
{
|
||||||
|
m_commentRegions.clear();
|
||||||
|
|
||||||
|
if (!result) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
pmh_element *elem = result[pmh_COMMENT];
|
||||||
|
while (elem != NULL) {
|
||||||
|
if (elem->end <= elem->pos) {
|
||||||
|
elem = elem->next;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_commentRegions.push_back(VCommentRegion(elem->pos, elem->end));
|
||||||
|
|
||||||
|
elem = elem->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
qDebug() << "highlighter:" << m_commentRegions.size() << "HTML comment regions";
|
||||||
}
|
}
|
||||||
|
|
||||||
void HGMarkdownHighlighter::initBlockHighlihgtOne(unsigned long pos, unsigned long end, int styleIndex)
|
void HGMarkdownHighlighter::initBlockHighlihgtOne(unsigned long pos, unsigned long end, int styleIndex)
|
||||||
@ -249,7 +289,16 @@ void HGMarkdownHighlighter::parse()
|
|||||||
qWarning() << "HighlightingStyles is not set";
|
qWarning() << "HighlightingStyles is not set";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
initBlockHighlightFromResult(nrBlocks);
|
initBlockHighlightFromResult(nrBlocks);
|
||||||
|
|
||||||
|
initHtmlCommentRegionsFromResult();
|
||||||
|
|
||||||
|
if (result) {
|
||||||
|
pmh_free_elements(result);
|
||||||
|
result = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
parsing.store(0);
|
parsing.store(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -294,7 +343,8 @@ void HGMarkdownHighlighter::timerTimeout()
|
|||||||
if (!updateCodeBlocks()) {
|
if (!updateCodeBlocks()) {
|
||||||
rehighlight();
|
rehighlight();
|
||||||
}
|
}
|
||||||
emit highlightCompleted();
|
|
||||||
|
highlightChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
void HGMarkdownHighlighter::updateHighlight()
|
void HGMarkdownHighlighter::updateHighlight()
|
||||||
@ -331,7 +381,11 @@ bool HGMarkdownHighlighter::updateCodeBlocks()
|
|||||||
// End block.
|
// End block.
|
||||||
inBlock = false;
|
inBlock = false;
|
||||||
item.m_endBlock = block.blockNumber();
|
item.m_endBlock = block.blockNumber();
|
||||||
codeBlocks.append(item);
|
|
||||||
|
// See if it is a code block inside HTML comment.
|
||||||
|
if (!isBlockInsideCommentRegion(block)) {
|
||||||
|
codeBlocks.append(item);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
int idx = codeBlockStartExp.indexIn(text);
|
int idx = codeBlockStartExp.indexIn(text);
|
||||||
@ -427,3 +481,27 @@ exit:
|
|||||||
rehighlight();
|
rehighlight();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool HGMarkdownHighlighter::isBlockInsideCommentRegion(const QTextBlock &p_block) const
|
||||||
|
{
|
||||||
|
if (!p_block.isValid()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int start = p_block.position();
|
||||||
|
int end = start + p_block.length();
|
||||||
|
|
||||||
|
for (auto const & reg : m_commentRegions) {
|
||||||
|
if (reg.contains(start) && reg.contains(end)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HGMarkdownHighlighter::highlightChanged()
|
||||||
|
{
|
||||||
|
m_completeTimer->stop();
|
||||||
|
m_completeTimer->start();
|
||||||
|
}
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
#include <QSet>
|
#include <QSet>
|
||||||
#include <QList>
|
#include <QList>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QMap>
|
#include <QHash>
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include <pmh_parser.h>
|
#include <pmh_parser.h>
|
||||||
@ -26,7 +26,12 @@ struct HighlightingStyle
|
|||||||
enum HighlightBlockState
|
enum HighlightBlockState
|
||||||
{
|
{
|
||||||
Normal = 0,
|
Normal = 0,
|
||||||
CodeBlock = 1,
|
|
||||||
|
// A fenced code block.
|
||||||
|
CodeBlock,
|
||||||
|
|
||||||
|
// This block is inside a HTML comment region.
|
||||||
|
Comment
|
||||||
};
|
};
|
||||||
|
|
||||||
// One continuous region for a certain markdown highlight style
|
// One continuous region for a certain markdown highlight style
|
||||||
@ -76,13 +81,33 @@ struct HLUnitPos
|
|||||||
QString m_style;
|
QString m_style;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// HTML comment.
|
||||||
|
struct VCommentRegion
|
||||||
|
{
|
||||||
|
VCommentRegion() : m_startPos(0), m_endPos(0) {}
|
||||||
|
|
||||||
|
VCommentRegion(int p_start, int p_end) : m_startPos(p_start), m_endPos(p_end) {}
|
||||||
|
|
||||||
|
// The start position of the region in document.
|
||||||
|
int m_startPos;
|
||||||
|
|
||||||
|
// The end position of the region in document.
|
||||||
|
int m_endPos;
|
||||||
|
|
||||||
|
// Whether this region contains @p_pos.
|
||||||
|
bool contains(int p_pos) const
|
||||||
|
{
|
||||||
|
return m_startPos <= p_pos && m_endPos >= p_pos;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class HGMarkdownHighlighter : public QSyntaxHighlighter
|
class HGMarkdownHighlighter : public QSyntaxHighlighter
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
HGMarkdownHighlighter(const QVector<HighlightingStyle> &styles,
|
HGMarkdownHighlighter(const QVector<HighlightingStyle> &styles,
|
||||||
const QMap<QString, QTextCharFormat> &codeBlockStyles,
|
const QHash<QString, QTextCharFormat> &codeBlockStyles,
|
||||||
int waitInterval,
|
int waitInterval,
|
||||||
QTextDocument *parent = 0);
|
QTextDocument *parent = 0);
|
||||||
~HGMarkdownHighlighter();
|
~HGMarkdownHighlighter();
|
||||||
@ -112,7 +137,7 @@ private:
|
|||||||
|
|
||||||
QTextDocument *document;
|
QTextDocument *document;
|
||||||
QVector<HighlightingStyle> highlightingStyles;
|
QVector<HighlightingStyle> highlightingStyles;
|
||||||
QMap<QString, QTextCharFormat> m_codeBlockStyles;
|
QHash<QString, QTextCharFormat> m_codeBlockStyles;
|
||||||
QVector<QVector<HLUnit> > blockHighlights;
|
QVector<QVector<HLUnit> > blockHighlights;
|
||||||
|
|
||||||
// Use another member to store the codeblocks highlights, because the highlight
|
// Use another member to store the codeblocks highlights, because the highlight
|
||||||
@ -123,6 +148,12 @@ private:
|
|||||||
|
|
||||||
int m_numOfCodeBlockHighlightsToRecv;
|
int m_numOfCodeBlockHighlightsToRecv;
|
||||||
|
|
||||||
|
// All HTML comment regions.
|
||||||
|
QVector<VCommentRegion> m_commentRegions;
|
||||||
|
|
||||||
|
// Timer to signal highlightCompleted().
|
||||||
|
QTimer *m_completeTimer;
|
||||||
|
|
||||||
QAtomicInt parsing;
|
QAtomicInt parsing;
|
||||||
QTimer *timer;
|
QTimer *timer;
|
||||||
int waitInterval;
|
int waitInterval;
|
||||||
@ -145,6 +176,15 @@ private:
|
|||||||
// Return true if there are fenced code blocks and it will call rehighlight() later.
|
// Return true if there are fenced code blocks and it will call rehighlight() later.
|
||||||
// Return false if there is none.
|
// Return false if there is none.
|
||||||
bool updateCodeBlocks();
|
bool updateCodeBlocks();
|
||||||
|
|
||||||
|
// Fetch all the HTML comment regions from parsing result.
|
||||||
|
void initHtmlCommentRegionsFromResult();
|
||||||
|
|
||||||
|
// Whether @p_block is totally inside a HTML comment.
|
||||||
|
bool isBlockInsideCommentRegion(const QTextBlock &p_block) const;
|
||||||
|
|
||||||
|
// Highlights have been changed. Try to signal highlightCompleted().
|
||||||
|
void highlightChanged();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#include <QPalette>
|
#include <QPalette>
|
||||||
#include <QVector>
|
#include <QVector>
|
||||||
#include <QSettings>
|
#include <QSettings>
|
||||||
|
#include <QHash>
|
||||||
#include "vnotebook.h"
|
#include "vnotebook.h"
|
||||||
#include "hgmarkdownhighlighter.h"
|
#include "hgmarkdownhighlighter.h"
|
||||||
#include "vmarkdownconverter.h"
|
#include "vmarkdownconverter.h"
|
||||||
@ -63,7 +64,7 @@ public:
|
|||||||
|
|
||||||
inline QVector<HighlightingStyle> getMdHighlightingStyles() const;
|
inline QVector<HighlightingStyle> getMdHighlightingStyles() const;
|
||||||
|
|
||||||
inline QMap<QString, QTextCharFormat> getCodeBlockStyles() const;
|
inline QHash<QString, QTextCharFormat> getCodeBlockStyles() const;
|
||||||
|
|
||||||
inline QString getWelcomePagePath() const;
|
inline QString getWelcomePagePath() const;
|
||||||
|
|
||||||
@ -231,7 +232,7 @@ private:
|
|||||||
QFont mdEditFont;
|
QFont mdEditFont;
|
||||||
QPalette mdEditPalette;
|
QPalette mdEditPalette;
|
||||||
QVector<HighlightingStyle> mdHighlightingStyles;
|
QVector<HighlightingStyle> mdHighlightingStyles;
|
||||||
QMap<QString, QTextCharFormat> m_codeBlockStyles;
|
QHash<QString, QTextCharFormat> m_codeBlockStyles;
|
||||||
QString welcomePagePath;
|
QString welcomePagePath;
|
||||||
QString m_templateCss;
|
QString m_templateCss;
|
||||||
QString m_editorStyle;
|
QString m_editorStyle;
|
||||||
@ -360,7 +361,7 @@ inline QVector<HighlightingStyle> VConfigManager::getMdHighlightingStyles() cons
|
|||||||
return mdHighlightingStyles;
|
return mdHighlightingStyles;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline QMap<QString, QTextCharFormat> VConfigManager::getCodeBlockStyles() const
|
inline QHash<QString, QTextCharFormat> VConfigManager::getCodeBlockStyles() const
|
||||||
{
|
{
|
||||||
return m_codeBlockStyles;
|
return m_codeBlockStyles;
|
||||||
}
|
}
|
||||||
|
@ -490,6 +490,10 @@ void VMdTab::updateTocFromHeaders(const QVector<VHeader> &p_headers)
|
|||||||
m_toc.m_file = m_file;
|
m_toc.m_file = m_file;
|
||||||
m_toc.valid = true;
|
m_toc.valid = true;
|
||||||
|
|
||||||
|
// Clear current header.
|
||||||
|
m_curHeader = VAnchor(m_file, "", -1, -1);
|
||||||
|
emit curHeaderChanged(m_curHeader);
|
||||||
|
|
||||||
emit outlineChanged(m_toc);
|
emit outlineChanged(m_toc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,9 +130,9 @@ QVector<HighlightingStyle> VStyleParser::fetchMarkdownStyles(const QFont &baseFo
|
|||||||
return styles;
|
return styles;
|
||||||
}
|
}
|
||||||
|
|
||||||
QMap<QString, QTextCharFormat> VStyleParser::fetchCodeBlockStyles(const QFont & p_baseFont) const
|
QHash<QString, QTextCharFormat> VStyleParser::fetchCodeBlockStyles(const QFont & p_baseFont) const
|
||||||
{
|
{
|
||||||
QMap<QString, QTextCharFormat> styles;
|
QHash<QString, QTextCharFormat> styles;
|
||||||
|
|
||||||
pmh_style_attribute *attrs = markdownStyles->element_styles[pmh_VERBATIM];
|
pmh_style_attribute *attrs = markdownStyles->element_styles[pmh_VERBATIM];
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
#include <QPalette>
|
#include <QPalette>
|
||||||
#include <QVector>
|
#include <QVector>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QMap>
|
#include <QHash>
|
||||||
#include "hgmarkdownhighlighter.h"
|
#include "hgmarkdownhighlighter.h"
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@ -26,7 +26,7 @@ public:
|
|||||||
// @styles: [rule] -> ([attr] -> value).
|
// @styles: [rule] -> ([attr] -> value).
|
||||||
void fetchMarkdownEditorStyles(QPalette &palette, QFont &font,
|
void fetchMarkdownEditorStyles(QPalette &palette, QFont &font,
|
||||||
QMap<QString, QMap<QString, QString>> &styles) const;
|
QMap<QString, QMap<QString, QString>> &styles) const;
|
||||||
QMap<QString, QTextCharFormat> fetchCodeBlockStyles(const QFont &p_baseFont) const;
|
QHash<QString, QTextCharFormat> fetchCodeBlockStyles(const QFont &p_baseFont) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QColor QColorFromPmhAttr(pmh_attr_argb_color *attr) const;
|
QColor QColorFromPmhAttr(pmh_attr_argb_color *attr) const;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user