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
|
||||
HGMarkdownHighlighter::HGMarkdownHighlighter(const QVector<HighlightingStyle> &styles,
|
||||
const QMap<QString, QTextCharFormat> &codeBlockStyles,
|
||||
const QHash<QString, QTextCharFormat> &codeBlockStyles,
|
||||
int waitInterval,
|
||||
QTextDocument *parent)
|
||||
: QSyntaxHighlighter(parent), highlightingStyles(styles),
|
||||
@ -47,10 +47,19 @@ HGMarkdownHighlighter::HGMarkdownHighlighter(const QVector<HighlightingStyle> &s
|
||||
|
||||
resizeBuffer(initCapacity);
|
||||
document = parent;
|
||||
|
||||
timer = new QTimer(this);
|
||||
timer->setSingleShot(true);
|
||||
timer->setInterval(this->waitInterval);
|
||||
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,
|
||||
this, &HGMarkdownHighlighter::handleContentChange);
|
||||
}
|
||||
@ -83,6 +92,12 @@ void HGMarkdownHighlighter::highlightBlock(const QString &text)
|
||||
// We use PEG Markdown Highlight as the main highlighter.
|
||||
// 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.
|
||||
setCurrentBlockState(HighlightBlockState::Normal);
|
||||
highlightCodeBlock(text);
|
||||
@ -123,6 +138,9 @@ void HGMarkdownHighlighter::highlightBlock(const QString &text)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
exit:
|
||||
highlightChanged();
|
||||
}
|
||||
|
||||
void HGMarkdownHighlighter::initBlockHighlightFromResult(int nrBlocks)
|
||||
@ -142,6 +160,8 @@ void HGMarkdownHighlighter::initBlockHighlightFromResult(int nrBlocks)
|
||||
pmh_element *elem_cursor = result[style.type];
|
||||
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) {
|
||||
elem_cursor = elem_cursor->next;
|
||||
continue;
|
||||
@ -150,9 +170,29 @@ void HGMarkdownHighlighter::initBlockHighlightFromResult(int nrBlocks)
|
||||
elem_cursor = elem_cursor->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pmh_free_elements(result);
|
||||
result = NULL;
|
||||
void HGMarkdownHighlighter::initHtmlCommentRegionsFromResult()
|
||||
{
|
||||
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)
|
||||
@ -249,7 +289,16 @@ void HGMarkdownHighlighter::parse()
|
||||
qWarning() << "HighlightingStyles is not set";
|
||||
return;
|
||||
}
|
||||
|
||||
initBlockHighlightFromResult(nrBlocks);
|
||||
|
||||
initHtmlCommentRegionsFromResult();
|
||||
|
||||
if (result) {
|
||||
pmh_free_elements(result);
|
||||
result = NULL;
|
||||
}
|
||||
|
||||
parsing.store(0);
|
||||
}
|
||||
|
||||
@ -294,7 +343,8 @@ void HGMarkdownHighlighter::timerTimeout()
|
||||
if (!updateCodeBlocks()) {
|
||||
rehighlight();
|
||||
}
|
||||
emit highlightCompleted();
|
||||
|
||||
highlightChanged();
|
||||
}
|
||||
|
||||
void HGMarkdownHighlighter::updateHighlight()
|
||||
@ -331,8 +381,12 @@ bool HGMarkdownHighlighter::updateCodeBlocks()
|
||||
// End block.
|
||||
inBlock = false;
|
||||
item.m_endBlock = block.blockNumber();
|
||||
|
||||
// See if it is a code block inside HTML comment.
|
||||
if (!isBlockInsideCommentRegion(block)) {
|
||||
codeBlocks.append(item);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
int idx = codeBlockStartExp.indexIn(text);
|
||||
if (idx >= 0) {
|
||||
@ -427,3 +481,27 @@ exit:
|
||||
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 <QList>
|
||||
#include <QString>
|
||||
#include <QMap>
|
||||
#include <QHash>
|
||||
|
||||
extern "C" {
|
||||
#include <pmh_parser.h>
|
||||
@ -26,7 +26,12 @@ struct HighlightingStyle
|
||||
enum HighlightBlockState
|
||||
{
|
||||
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
|
||||
@ -76,13 +81,33 @@ struct HLUnitPos
|
||||
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
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
HGMarkdownHighlighter(const QVector<HighlightingStyle> &styles,
|
||||
const QMap<QString, QTextCharFormat> &codeBlockStyles,
|
||||
const QHash<QString, QTextCharFormat> &codeBlockStyles,
|
||||
int waitInterval,
|
||||
QTextDocument *parent = 0);
|
||||
~HGMarkdownHighlighter();
|
||||
@ -112,7 +137,7 @@ private:
|
||||
|
||||
QTextDocument *document;
|
||||
QVector<HighlightingStyle> highlightingStyles;
|
||||
QMap<QString, QTextCharFormat> m_codeBlockStyles;
|
||||
QHash<QString, QTextCharFormat> m_codeBlockStyles;
|
||||
QVector<QVector<HLUnit> > blockHighlights;
|
||||
|
||||
// Use another member to store the codeblocks highlights, because the highlight
|
||||
@ -123,6 +148,12 @@ private:
|
||||
|
||||
int m_numOfCodeBlockHighlightsToRecv;
|
||||
|
||||
// All HTML comment regions.
|
||||
QVector<VCommentRegion> m_commentRegions;
|
||||
|
||||
// Timer to signal highlightCompleted().
|
||||
QTimer *m_completeTimer;
|
||||
|
||||
QAtomicInt parsing;
|
||||
QTimer *timer;
|
||||
int waitInterval;
|
||||
@ -145,6 +176,15 @@ private:
|
||||
// Return true if there are fenced code blocks and it will call rehighlight() later.
|
||||
// Return false if there is none.
|
||||
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
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include <QPalette>
|
||||
#include <QVector>
|
||||
#include <QSettings>
|
||||
#include <QHash>
|
||||
#include "vnotebook.h"
|
||||
#include "hgmarkdownhighlighter.h"
|
||||
#include "vmarkdownconverter.h"
|
||||
@ -63,7 +64,7 @@ public:
|
||||
|
||||
inline QVector<HighlightingStyle> getMdHighlightingStyles() const;
|
||||
|
||||
inline QMap<QString, QTextCharFormat> getCodeBlockStyles() const;
|
||||
inline QHash<QString, QTextCharFormat> getCodeBlockStyles() const;
|
||||
|
||||
inline QString getWelcomePagePath() const;
|
||||
|
||||
@ -231,7 +232,7 @@ private:
|
||||
QFont mdEditFont;
|
||||
QPalette mdEditPalette;
|
||||
QVector<HighlightingStyle> mdHighlightingStyles;
|
||||
QMap<QString, QTextCharFormat> m_codeBlockStyles;
|
||||
QHash<QString, QTextCharFormat> m_codeBlockStyles;
|
||||
QString welcomePagePath;
|
||||
QString m_templateCss;
|
||||
QString m_editorStyle;
|
||||
@ -360,7 +361,7 @@ inline QVector<HighlightingStyle> VConfigManager::getMdHighlightingStyles() cons
|
||||
return mdHighlightingStyles;
|
||||
}
|
||||
|
||||
inline QMap<QString, QTextCharFormat> VConfigManager::getCodeBlockStyles() const
|
||||
inline QHash<QString, QTextCharFormat> VConfigManager::getCodeBlockStyles() const
|
||||
{
|
||||
return m_codeBlockStyles;
|
||||
}
|
||||
|
@ -490,6 +490,10 @@ void VMdTab::updateTocFromHeaders(const QVector<VHeader> &p_headers)
|
||||
m_toc.m_file = m_file;
|
||||
m_toc.valid = true;
|
||||
|
||||
// Clear current header.
|
||||
m_curHeader = VAnchor(m_file, "", -1, -1);
|
||||
emit curHeaderChanged(m_curHeader);
|
||||
|
||||
emit outlineChanged(m_toc);
|
||||
}
|
||||
|
||||
|
@ -130,9 +130,9 @@ QVector<HighlightingStyle> VStyleParser::fetchMarkdownStyles(const QFont &baseFo
|
||||
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];
|
||||
|
||||
|
@ -4,7 +4,7 @@
|
||||
#include <QPalette>
|
||||
#include <QVector>
|
||||
#include <QString>
|
||||
#include <QMap>
|
||||
#include <QHash>
|
||||
#include "hgmarkdownhighlighter.h"
|
||||
|
||||
extern "C" {
|
||||
@ -26,7 +26,7 @@ public:
|
||||
// @styles: [rule] -> ([attr] -> value).
|
||||
void fetchMarkdownEditorStyles(QPalette &palette, QFont &font,
|
||||
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:
|
||||
QColor QColorFromPmhAttr(pmh_attr_argb_color *attr) const;
|
||||
|
Loading…
x
Reference in New Issue
Block a user