PegHighlighter: support math

This commit is contained in:
Le Tan 2018-07-13 20:32:22 +08:00
parent d06dcc36f5
commit f5bbc1ccd7
26 changed files with 284 additions and 1863 deletions

File diff suppressed because it is too large Load Diff

View File

@ -1,324 +0,0 @@
#ifndef HGMARKDOWNHIGHLIGHTER_H
#define HGMARKDOWNHIGHLIGHTER_H
#include <QSyntaxHighlighter>
#include <QAtomicInt>
#include <QMap>
#include <QSet>
#include <QString>
#include "vtextblockdata.h"
#include "markdownhighlighterdata.h"
class QTextDocument;
class HGMarkdownHighlighter : public QSyntaxHighlighter
{
Q_OBJECT
public:
HGMarkdownHighlighter(const QVector<HighlightingStyle> &styles,
const QHash<QString, QTextCharFormat> &codeBlockStyles,
int waitInterval,
QTextDocument *parent = 0);
~HGMarkdownHighlighter();
// Request to update highlihgt (re-parse and re-highlight)
void setCodeBlockHighlights(const QVector<HLUnitPos> &p_units);
const QVector<VElementRegion> &getHeaderRegions() const;
const QSet<int> &getPossiblePreviewBlocks() const;
void clearPossiblePreviewBlocks(const QVector<int> &p_blocksToClear);
void addPossiblePreviewBlock(int p_blockNumber);
// Parse and only update the highlight results for rehighlight().
void updateHighlightFast();
QHash<QString, QTextCharFormat> &getCodeBlockStyles();
QVector<HighlightingStyle> &getHighlightingStyles();
void setMathjaxEnabled(bool p_enabled);
signals:
void highlightCompleted();
// QVector is implicitly shared.
void codeBlocksUpdated(const QVector<VCodeBlock> &p_codeBlocks);
// Emitted when image regions have been fetched from a new parsing result.
void imageLinksUpdated(const QVector<VElementRegion> &p_imageRegions);
// Emitted when header regions have been fetched from a new parsing result.
void headersUpdated(const QVector<VElementRegion> &p_headerRegions);
// Emitted when Mathjax blocks updated.
void mathjaxBlocksUpdated(const QVector<VMathjaxBlock> &p_mathjaxBlocks);
protected:
void highlightBlock(const QString &text) Q_DECL_OVERRIDE;
public slots:
// Parse and rehighlight immediately.
void updateHighlight();
private slots:
void handleContentChange(int position, int charsRemoved, int charsAdded);
// @p_fast: if true, just parse and update styles.
void startParseAndHighlight(bool p_fast = false);
void completeHighlight();
private:
struct HeaderBlockInfo
{
HeaderBlockInfo(int p_level = -1, int p_length = 0)
: m_level(p_level), m_length(p_length)
{
}
// Header level based on 0.
int m_level;
// Block length;
int m_length;
};
TimeStamp m_timeStamp;
QRegExp codeBlockStartExp;
QRegExp codeBlockEndExp;
QRegExp m_mathjaxInlineExp;
QRegExp m_mathjaxBlockExp;
QTextCharFormat m_codeBlockFormat;
QTextCharFormat m_linkFormat;
QTextCharFormat m_imageFormat;
QTextCharFormat m_colorColumnFormat;
QTextCharFormat m_mathjaxFormat;
QTextDocument *document;
QVector<HighlightingStyle> highlightingStyles;
QHash<QString, QTextCharFormat> m_codeBlockStyles;
QVector<QVector<HLUnit> > m_blockHighlights;
// Used for cache, [0, 6].
QVector<QTextCharFormat> m_headerStyles;
// Use another member to store the codeblocks highlights, because the highlight
// sequence is blockHighlights, regular-expression-based highlihgts, and then
// codeBlockHighlights.
// Support fenced code block only.
QVector<QVector<HLUnitStyle> > m_codeBlockHighlights;
int m_numOfCodeBlockHighlightsToRecv;
// All image link regions.
QVector<VElementRegion> m_imageRegions;
// All header regions.
// May contains illegal elements.
// Sorted by start position.
QVector<VElementRegion> m_headerRegions;
// All verbatim blocks (by parser) number.
QSet<int> m_verbatimBlocks;
// All fenced code blocks.
QVector<VCodeBlock> m_codeBlocks;
// Indexed by block number.
QHash<int, HighlightBlockState> m_codeBlocksState;
// Indexed by block number.
QHash<int, HeaderBlockInfo> m_headerBlocks;
// Timer to signal highlightCompleted().
QTimer *m_completeTimer;
QAtomicInt parsing;
// Whether highlight results for blocks are ready.
bool m_blockHLResultReady;
QTimer *timer;
int waitInterval;
// Block number of those blocks which possible contains previewed image.
QSet<int> m_possiblePreviewBlocks;
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;
// Whether need to signal out changes when highlight completes.
bool m_signalOut;
char *content;
int capacity;
pmh_element **result;
static const int initCapacity;
void resizeBuffer(int newCap);
void highlightCodeBlock(int p_blockNumber, const QString &p_text);
void highlightMathJax(const QTextBlock &p_block, const QString &p_text);
void parse();
void parseInternal();
// Init highlight elements for all the blocks from parse results.
void initBlockHighlightFromResult(int nrBlocks);
// Init highlight elements for blocks from one parse result.
void initBlockHighlihgtOne(unsigned long pos,
unsigned long end,
int styleIndex);
// Return true if there are fenced code blocks and it will call rehighlight() later.
// Return false if there is none.
bool updateCodeBlocks();
void updateMathjaxBlocks();
// Fetch all the HTML comment regions from parsing result.
void initHtmlCommentRegionsFromResult();
// Fetch all the image link regions from parsing result.
void initImageRegionsFromResult();
// Fetch all the header regions from parsing result.
void initHeaderRegionsFromResult();
// Fetch all the verbatim blocks from parsing result.
void initVerbatimBlocksFromResult();
// Fetch all the fenced code blocks from parsing result.
void initFencedCodeBlocksFromResult();
// 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.
bool isBlockInsideCommentRegion(const QTextBlock &p_block) const;
// Whether @p_block is a Verbatim block.
bool isVerbatimBlock(const QTextBlock &p_block) const;
// Highlights have been changed. Try to signal highlightCompleted().
void highlightChanged();
// Set the user data of currentBlock().
void updateBlockUserData(int p_blockNum, const QString &p_text);
// Highlight color column in code block.
void highlightCodeBlockColorColumn(const QString &p_text);
bool isValidHeader(const QString &p_text);
VTextBlockData *currentBlockData() const;
VTextBlockData *previousBlockData() const;
// Highlight headers using regular expression first instead of waiting for
// another parse.
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
{
return m_headerRegions;
}
inline const QSet<int> &HGMarkdownHighlighter::getPossiblePreviewBlocks() const
{
return m_possiblePreviewBlocks;
}
inline void HGMarkdownHighlighter::clearPossiblePreviewBlocks(const QVector<int> &p_blocksToClear)
{
for (auto i : p_blocksToClear) {
m_possiblePreviewBlocks.remove(i);
}
}
inline void HGMarkdownHighlighter::addPossiblePreviewBlock(int p_blockNumber)
{
m_possiblePreviewBlocks.insert(p_blockNumber);
}
inline VTextBlockData *HGMarkdownHighlighter::currentBlockData() const
{
return static_cast<VTextBlockData *>(currentBlockUserData());
}
inline VTextBlockData *HGMarkdownHighlighter::previousBlockData() const
{
QTextBlock block = currentBlock().previous();
if (!block.isValid()) {
return NULL;
}
return static_cast<VTextBlockData *>(block.userData());
}
inline QHash<QString, QTextCharFormat> &HGMarkdownHighlighter::getCodeBlockStyles()
{
return m_codeBlockStyles;
}
inline QVector<HighlightingStyle> &HGMarkdownHighlighter::getHighlightingStyles()
{
return highlightingStyles;
}
inline bool HGMarkdownHighlighter::isVerbatimBlock(const QTextBlock &p_block) const
{
return m_verbatimBlocks.contains(p_block.blockNumber());
}
inline void HGMarkdownHighlighter::setMathjaxEnabled(bool p_enabled)
{
m_enableMathjax = p_enabled;
}
#endif

View File

@ -72,15 +72,6 @@ struct VMathjaxBlock
{
}
VMathjaxBlock(int p_blockNumber, const MathjaxInfo &p_info)
: m_blockNumber(p_blockNumber),
m_previewedAsBlock(p_info.m_previewedAsBlock),
m_index(p_info.m_index),
m_length(p_info.m_length),
m_text(p_info.m_text)
{
}
bool equalContent(const VMathjaxBlock &p_block) const
{
return m_text == p_block.m_text;
@ -94,13 +85,16 @@ struct VMathjaxBlock
m_length = p_block.m_length;
}
// Block number for in-place preview.
int m_blockNumber;
// Whether it should be previewed as block or not.
bool m_previewedAsBlock;
// Start index within the block.
// Start index wihtin block with number m_blockNumber, including the start mark.
int m_index;
// Length of this mathjax in block with number m_blockNumber, including the end mark.
int m_length;
QString m_text;
@ -171,12 +165,4 @@ struct VElementRegion
return QString("[%1,%2)").arg(m_startPos).arg(m_endPos);
}
};
struct PegHighlightResult
{
TimeStamp m_timeStamp;
QVector<QVector<HLUnit> > m_blockHighlights;
};
#endif // MARKDOWNHIGHLIGHTERDATA_H

View File

@ -2,6 +2,7 @@
#include <QTextDocument>
#include <QTextBlock>
#include <QDebug>
#include "pegmarkdownhighlighter.h"
#include "utils/vutils.h"
@ -31,6 +32,8 @@ PegHighlighterResult::PegHighlighterResult(const PegMarkdownHighlighter *p_peg,
m_headerRegions = p_result->m_headerRegions;
parseFencedCodeBlocks(p_peg, p_result);
parseMathjaxBlocks(p_peg, p_result);
}
static bool compHLUnit(const HLUnit &p_a, const HLUnit &p_b)
@ -221,3 +224,86 @@ void PegHighlighterResult::parseFencedCodeBlocks(const PegMarkdownHighlighter *p
}
}
}
void PegHighlighterResult::parseMathjaxBlocks(const PegMarkdownHighlighter *p_peg,
const QSharedPointer<PegParseResult> &p_result)
{
const QTextDocument *doc = p_peg->getDocument();
// Inline equations.
const QVector<VElementRegion> inlineRegs = p_result->m_inlineEquationRegions;
for (auto it = inlineRegs.begin(); it != inlineRegs.end(); ++it) {
const VElementRegion &r = *it;
QTextBlock block = doc->findBlock(r.m_startPos);
// Inline equation MUST in one block.
Q_ASSERT(block.blockNumber() == doc->findBlock(r.m_endPos - 1).blockNumber());
if (!block.isValid()) {
continue;
}
if (r.m_endPos - block.position() > block.length()) {
continue;
}
VMathjaxBlock item;
item.m_blockNumber = block.blockNumber();
item.m_previewedAsBlock = false;
item.m_index = r.m_startPos - block.position();
item.m_length = r.m_endPos - r.m_startPos;
item.m_text = block.text().mid(item.m_index, item.m_length);
m_mathjaxBlocks.append(item);
}
// Display formulas.
// One block may be split into several regions due to list indentation.
const QVector<VElementRegion> formulaRegs = p_result->m_displayFormulaRegions;
VMathjaxBlock item;
bool inBlock = false;
QString marker("$$");
for (auto it = formulaRegs.begin(); it != formulaRegs.end(); ++it) {
const VElementRegion &r = *it;
QTextBlock block = doc->findBlock(r.m_startPos);
int lastBlock = doc->findBlock(r.m_endPos - 1).blockNumber();
while (block.isValid()) {
int blockNum = block.blockNumber();
if (blockNum > lastBlock) {
break;
}
int pib = r.m_startPos - block.position();
int length = r.m_endPos - r.m_startPos;
QString text = block.text().mid(pib, length);
if (inBlock) {
item.m_text = item.m_text + "\n" + text;
if (text.endsWith(marker)) {
// End of block.
inBlock = false;
item.m_blockNumber = blockNum;
item.m_index = pib;
item.m_length = length;
m_mathjaxBlocks.append(item);
}
} else {
Q_ASSERT(text.startsWith(marker));
if (text.size() > 2 && text.endsWith(marker)) {
// Within one block.
item.m_blockNumber = blockNum;
item.m_previewedAsBlock = true;
item.m_index = pib;
item.m_length = length;
item.m_text = text;
m_mathjaxBlocks.append(item);
} else {
inBlock = true;
item.m_previewedAsBlock = true;
item.m_text = text;
}
}
block = block.next();
}
}
}

View File

@ -44,6 +44,9 @@ public:
int m_numOfCodeBlockHighlightsToRecv;
// All MathJax blocks.
QVector<VMathjaxBlock> m_mathjaxBlocks;
private:
// Parse highlight elements for all the blocks from parse results.
void parseBlocksHighlights(const PegMarkdownHighlighter *p_peg,
@ -59,6 +62,10 @@ private:
void parseFencedCodeBlocks(const PegMarkdownHighlighter *p_peg,
const QSharedPointer<PegParseResult> &p_result);
// Parse fenced code blocks from parse results.
void parseMathjaxBlocks(const PegMarkdownHighlighter *p_peg,
const QSharedPointer<PegParseResult> &p_result);
void parseBlocksElementRegionOne(QHash<int, QVector<VElementRegion>> &p_regs,
const QTextDocument *p_doc,
unsigned long p_pos,

View File

@ -15,7 +15,7 @@ PegMarkdownHighlighter::PegMarkdownHighlighter(QTextDocument *p_doc)
m_doc(p_doc),
m_timeStamp(0),
m_parser(NULL),
m_parserExts(pmh_EXT_STRIKE | pmh_EXT_FRONTMATTER)
m_parserExts(pmh_EXT_NOTES | pmh_EXT_STRIKE | pmh_EXT_FRONTMATTER)
{
}
@ -27,6 +27,10 @@ void PegMarkdownHighlighter::init(const QVector<HighlightingStyle> &p_styles,
m_styles = p_styles;
m_codeBlockStyles = p_codeBlockStyles;
if (p_mathjaxEnabled) {
m_parserExts |= pmh_EXT_MATH;
}
m_codeBlockFormat.setForeground(QBrush(Qt::darkYellow));
for (int index = 0; index < m_styles.size(); ++index) {
switch (m_styles[index].type) {
@ -272,7 +276,6 @@ void PegMarkdownHighlighter::updateBlockUserData(int p_blockNum, const QString &
setCurrentBlockUserData(blockData);
} else {
blockData->setCodeBlockIndentation(-1);
blockData->clearMathjax();
}
if (blockData->getPreviews().isEmpty()) {
@ -402,6 +405,10 @@ void PegMarkdownHighlighter::completeHighlight(QSharedPointer<PegHighlighterResu
return;
}
if (isMathJaxEnabled()) {
emit mathjaxBlocksUpdated(p_result->m_mathjaxBlocks);
}
emit imageLinksUpdated(p_result->m_imageRegions);
emit headersUpdated(p_result->m_headerRegions);

View File

@ -96,6 +96,8 @@ private:
void completeHighlight(QSharedPointer<PegHighlighterResult> p_result);
bool isMathJaxEnabled() const;
QTextDocument *m_doc;
TimeStamp m_timeStamp;
@ -176,4 +178,9 @@ inline VTextBlockData *PegMarkdownHighlighter::previousBlockData() const
return static_cast<VTextBlockData *>(block.userData());
}
inline bool PegMarkdownHighlighter::isMathJaxEnabled() const
{
return m_parserExts & pmh_EXT_MATH;
}
#endif // PEGMARKDOWNHIGHLIGHTER_H

View File

@ -15,6 +15,10 @@ void PegParseResult::parse(QAtomicInt &p_stop)
parseHeaderRegions(p_stop);
parseFencedCodeBlockRegions(p_stop);
parseInlineEquationRegions(p_stop);
parseDisplayFormulaRegions(p_stop);
}
void PegParseResult::parseImageRegions(QAtomicInt &p_stop)
@ -100,6 +104,58 @@ void PegParseResult::parseFencedCodeBlockRegions(QAtomicInt &p_stop)
}
}
void PegParseResult::parseInlineEquationRegions(QAtomicInt &p_stop)
{
m_inlineEquationRegions.clear();
if (isEmpty()) {
return;
}
pmh_element *elem = m_pmhElements[pmh_INLINEEQUATION];
while (elem != NULL) {
if (elem->end <= elem->pos) {
elem = elem->next;
continue;
}
if (p_stop.load() == 1) {
return;
}
m_inlineEquationRegions.push_back(VElementRegion(elem->pos, elem->end));
elem = elem->next;
}
}
void PegParseResult::parseDisplayFormulaRegions(QAtomicInt &p_stop)
{
m_displayFormulaRegions.clear();
if (isEmpty()) {
return;
}
pmh_element *elem = m_pmhElements[pmh_DISPLAYFORMULA];
while (elem != NULL) {
if (elem->end <= elem->pos) {
elem = elem->next;
continue;
}
if (p_stop.load() == 1) {
return;
}
m_displayFormulaRegions.push_back(VElementRegion(elem->pos, elem->end));
elem = elem->next;
}
if (p_stop.load() == 1) {
return;
}
std::sort(m_displayFormulaRegions.begin(), m_displayFormulaRegions.end());
}
PegParserWorker::PegParserWorker(QObject *p_parent)
: QThread(p_parent),
@ -152,13 +208,7 @@ QSharedPointer<PegParseResult> PegParserWorker::parseMarkdown(const QSharedPoint
return result;
}
pmh_element **pmhResult = NULL;
char *data = p_config->m_data.data();
pmh_markdown_to_elements(data, p_config->m_extensions, &pmhResult);
result->m_pmhElements = pmhResult;
result->m_pmhElements = PegParser::parseMarkdownToElements(p_config);
if (p_stop.load() == 1) {
return result;
@ -274,3 +324,39 @@ void PegParser::scheduleWork(PegParserWorker *p_worker,
p_worker->prepareParse(p_config);
p_worker->start();
}
QVector<VElementRegion> PegParser::parseImageRegions(const QSharedPointer<PegParseConfig> &p_config)
{
QVector<VElementRegion> regs;
pmh_element **res = PegParser::parseMarkdownToElements(p_config);
if (!res) {
return regs;
}
pmh_element *elem = res[pmh_IMAGE];
while (elem != NULL) {
if (elem->end <= elem->pos) {
elem = elem->next;
continue;
}
regs.push_back(VElementRegion(elem->pos, elem->end));
elem = elem->next;
}
pmh_free_elements(res);
return regs;
}
pmh_element **PegParser::parseMarkdownToElements(const QSharedPointer<PegParseConfig> &p_config)
{
if (p_config->m_data.isEmpty()) {
return NULL;
}
pmh_element **pmhResult = NULL;
char *data = p_config->m_data.data();
pmh_markdown_to_elements(data, p_config->m_extensions, &pmhResult);
return pmhResult;
}

View File

@ -13,6 +13,13 @@
struct PegParseConfig
{
PegParseConfig()
: m_timeStamp(0),
m_numOfBlocks(0),
m_extensions(pmh_EXT_NONE)
{
}
TimeStamp m_timeStamp;
QByteArray m_data;
@ -86,12 +93,23 @@ struct PegParseResult
// Ordered by start position in ascending order.
QMap<int, VElementRegion> m_codeBlockRegions;
// All $ $ inline equation regions.
QVector<VElementRegion> m_inlineEquationRegions;
// All $$ $$ display formula regions.
// Sorted by start position.
QVector<VElementRegion> m_displayFormulaRegions;
private:
void parseImageRegions(QAtomicInt &p_stop);
void parseHeaderRegions(QAtomicInt &p_stop);
void parseFencedCodeBlockRegions(QAtomicInt &p_stop);
void parseInlineEquationRegions(QAtomicInt &p_stop);
void parseDisplayFormulaRegions(QAtomicInt &p_stop);
};
class PegParserWorker : public QThread
@ -162,6 +180,11 @@ public:
void parseAsync(const QSharedPointer<PegParseConfig> &p_config);
static QVector<VElementRegion> parseImageRegions(const QSharedPointer<PegParseConfig> &p_config);
// MUST pmh_free_elements() the result.
static pmh_element **parseMarkdownToElements(const QSharedPointer<PegParseConfig> &p_config);
signals:
void parseResultReady(const QSharedPointer<PegParseResult> &p_result);

View File

@ -108,7 +108,9 @@ mdit = mdit.use(window.markdownitFootnote);
mdit = mdit.use(window["markdown-it-imsize.js"]);
mdit = mdit.use(texmath, { delimiters: 'dollars' });
if (typeof texmath != 'undefined') {
mdit = mdit.use(texmath, { delimiters: 'dollars' });
}
var mdHasTocSection = function(markdown) {
var n = markdown.search(/(\n|^)\[toc\]/i);

View File

@ -39,8 +39,6 @@ color-column-foreground: eeeeee
preview-image-line-foreground: 6f5799
# [VNote] Style for preview image (useful for SVG in dark theme)
preview-image-background: 949494
# [VNote] Style for MathJax
mathjax-foreground: 93d3cc
editor-selection
foreground: dadada
@ -184,3 +182,11 @@ font-style: strikeout
FRONTMATTER
foreground: af8787
INLINEEQUATION
foreground: 93d3cc
font-family: Consolas, Monaco, Andale Mono, Monospace, Courier New
DISPLAYFORMULA
foreground: 93d3cc
font-family: Consolas, Monaco, Andale Mono, Monospace, Courier New

View File

@ -39,8 +39,6 @@ color-column-foreground: eeeeee
preview-image-line-foreground: 6f5799
# [VNote] Style for preview image (useful for SVG in dark theme)
preview-image-background: b0bec5
# [VNote] Style for MathJax
mathjax-foreground: 4db6ac
editor-selection
foreground: bcbcbc
@ -183,3 +181,11 @@ font-style: strikeout
FRONTMATTER
foreground: 6e7686
INLINEEQUATION
foreground: 4db6ac
font-family: Consolas, Monaco, Andale Mono, Monospace, Courier New
DISPLAYFORMULA
foreground: 4db6ac
font-family: Consolas, Monaco, Andale Mono, Monospace, Courier New

View File

@ -36,8 +36,6 @@ color-column-background: dd0000
color-column-foreground: ffff00
# [VNote] Style for preview image line
preview-image-line-foreground: 9575cd
# [VNote] Style for MathJax
mathjax-foreground: 00897b
editor-selection
foreground: ffffff
@ -179,3 +177,11 @@ font-style: strikeout
FRONTMATTER
foreground: 6c6c6c
INLINEEQUATION
foreground: 00897b
font-family: Consolas, Monaco, Andale Mono, Monospace, Courier New
DISPLAYFORMULA
foreground: 00897b
font-family: Consolas, Monaco, Andale Mono, Monospace, Courier New

View File

@ -37,8 +37,6 @@ color-column-background: dd0000
color-column-foreground: ffff00
# [VNote] Style for preview image line
preview-image-line-foreground: 9575cd
# [VNote] Style for MathJax
mathjax-foreground: 00897b
editor-selection
foreground: f5f5f5
@ -180,3 +178,11 @@ font-style: strikeout
FRONTMATTER
foreground: 6c6c6c
INLINEEQUATION
foreground: 00897b
font-family: Consolas, Monaco, Andale Mono, Monospace, Courier New
DISPLAYFORMULA
foreground: 00897b
font-family: Consolas, Monaco, Andale Mono, Monospace, Courier New

View File

@ -29,7 +29,6 @@ SOURCES += main.cpp\
vdocument.cpp \
utils/vutils.cpp \
vpreviewpage.cpp \
hgmarkdownhighlighter.cpp \
vstyleparser.cpp \
dialog/vnewnotebookdialog.cpp \
vmarkdownconverter.cpp \
@ -158,7 +157,6 @@ HEADERS += vmainwindow.h \
vdocument.h \
utils/vutils.h \
vpreviewpage.h \
hgmarkdownhighlighter.h \
vstyleparser.h \
dialog/vnewnotebookdialog.h \
vmarkdownconverter.h \

View File

@ -32,8 +32,8 @@
#include "vorphanfile.h"
#include "vnote.h"
#include "vnotebook.h"
#include "hgmarkdownhighlighter.h"
#include "vpreviewpage.h"
#include "pegparser.h"
extern VConfigManager *g_config;
@ -52,10 +52,6 @@ const QString VUtils::c_fencedCodeBlockStartRegExp = QString("^(\\s*)```([^`\\s]
const QString VUtils::c_fencedCodeBlockEndRegExp = QString("^(\\s*)```$");
const QString VUtils::c_mathjaxInlineRegExp = QString("(?:^|[^\\$\\\\]|(?:^|[^\\\\])(?:\\\\\\\\)+)\\$(?!\\$)");
const QString VUtils::c_mathjaxBlockRegExp = QString("(?:^|[^\\$\\\\]|(?:^|[^\\\\])(?:\\\\\\\\)+)\\$\\$(?!\\$)");
const QString VUtils::c_previewImageBlockRegExp = QString("[\\n|^][ |\\t]*\\xfffc[ |\\t]*(?=\\n)");
const QString VUtils::c_headerRegExp = QString("^(#{1,6})\\s+(((\\d+\\.)+(?=\\s))?\\s*(\\S.*)?)$");
@ -661,8 +657,11 @@ QString VUtils::generateHtmlTemplate(const QString &p_template,
"<script src=\"qrc" + VNote::c_markdownitAnchorExtraFile + "\"></script>\n" +
"<script src=\"qrc" + VNote::c_markdownitTaskListExtraFile + "\"></script>\n" +
"<script src=\"qrc" + VNote::c_markdownitImsizeExtraFile + "\"></script>\n" +
"<script src=\"qrc" + VNote::c_markdownitFootnoteExtraFile + "\"></script>\n" +
"<script src=\"qrc" + VNote::c_markdownitTexMathExtraFile + "\"></script>\n";
"<script src=\"qrc" + VNote::c_markdownitFootnoteExtraFile + "\"></script>\n";
if (g_config->getEnableMathjax()) {
extraFile += "<script src=\"qrc" + VNote::c_markdownitTexMathExtraFile + "\"></script>\n";
}
const MarkdownitOption &opt = g_config->getMarkdownitOption();
@ -1201,38 +1200,11 @@ bool VUtils::deleteFile(const QString &p_recycleBinFolderPath,
QVector<VElementRegion> VUtils::fetchImageRegionsUsingParser(const QString &p_content)
{
Q_ASSERT(!p_content.isEmpty());
QVector<VElementRegion> regs;
QByteArray ba = p_content.toUtf8();
const char *data = (const char *)ba.data();
int len = ba.size();
const QSharedPointer<PegParseConfig> parserConfig(new PegParseConfig());
parserConfig->m_data = p_content.toUtf8();
pmh_element **result = NULL;
char *content = new char[len + 1];
memcpy(content, data, len);
content[len] = '\0';
pmh_markdown_to_elements(content, pmh_EXT_NONE, &result);
if (!result) {
return regs;
}
pmh_element *elem = result[pmh_IMAGE];
while (elem != NULL) {
if (elem->end <= elem->pos) {
elem = elem->next;
continue;
}
regs.push_back(VElementRegion(elem->pos, elem->end));
elem = elem->next;
}
pmh_free_elements(result);
return regs;
return PegParser::parseImageRegions(parserConfig);
}
QString VUtils::displayDateTime(const QDateTime &p_dateTime,

View File

@ -374,14 +374,6 @@ public:
static const QString c_fencedCodeBlockStartRegExp;
static const QString c_fencedCodeBlockEndRegExp;
// Regular expression for inline mathjax formula.
// $..$
static const QString c_mathjaxInlineRegExp;
// Regular expression for block mathjax formula.
// $$..$$
static const QString c_mathjaxBlockRegExp;
// Regular expression for preview image block.
static const QString c_previewImageBlockRegExp;
@ -403,7 +395,7 @@ private:
static void initAvailableLanguage();
// Use HGMarkdownParser to parse @p_content to get all image link regions.
// Use PegParser to parse @p_content to get all image link regions.
static QVector<VElementRegion> fetchImageRegionsUsingParser(const QString &p_content);
// Delete file/directory specified by @p_path by moving it to the recycle bin

View File

@ -620,7 +620,6 @@ void VConfigManager::updateMarkdownEditStyle()
m_editorColorColumnFg = defaultColor;
m_editorPreviewImageLineFg = defaultColor;
m_editorPreviewImageBg.clear();
m_editorMathjaxFg = defaultColor;
auto editorIt = styles.find("editor");
if (editorIt != styles.end()) {
@ -698,11 +697,6 @@ void VConfigManager::updateMarkdownEditStyle()
if (it != editorIt->end()) {
m_editorPreviewImageBg = "#" + *it;
}
it = editorIt->find("mathjax-foreground");
if (it != editorIt->end()) {
m_editorMathjaxFg = "#" + *it;
}
}
}

View File

@ -333,8 +333,6 @@ public:
const QString &getEditorPreviewImageBg() const;
const QString &getEditorMathjaxFg() const;
bool getEnableCodeBlockLineNumber() const;
void setEnableCodeBlockLineNumber(bool p_enabled);
@ -789,7 +787,7 @@ private:
// [DocType] -> { Suffixes }.
QHash<int, QList<QString>> m_docSuffixes;
// Interval for HGMarkdownHighlighter highlight timer (milliseconds).
// Interval for PegMarkdownHighlighter highlight timer (milliseconds).
int m_markdownHighlightInterval;
// Line distance height in pixel.
@ -825,9 +823,6 @@ private:
// The forced background color of the preview image. Can be empty.
QString m_editorPreviewImageBg;
// The foreground color of the MathJax.
QString m_editorMathjaxFg;
// Icon size of tool bar in pixels.
int m_toolBarIconSize;
@ -1927,11 +1922,6 @@ inline const QString &VConfigManager::getEditorPreviewImageBg() const
return m_editorPreviewImageBg;
}
inline const QString &VConfigManager::getEditorMathjaxFg() const
{
return m_editorMathjaxFg;
}
inline bool VConfigManager::getEnableCodeBlockLineNumber() const
{
return m_enableCodeBlockLineNumber;

View File

@ -119,23 +119,7 @@ enum HighlightBlockState
// A fenced code block.
CodeBlockStart,
CodeBlock,
CodeBlockEnd,
// This block is inside a HTML comment region.
// Obsolete.
Comment,
// Verbatim code block.
// Obsolete.
Verbatim,
// Mathjax. It means the pending state of the block.
MathjaxBlock,
MathjaxInline,
// Header.
// Obsolete.
Header
CodeBlockEnd
};
// Pages to open on start up.

View File

@ -4,7 +4,7 @@
#include <QObject>
#include <QTextDocument>
#include "hgmarkdownhighlighter.h"
#include "pegmarkdownhighlighter.h"
#include "vpreviewmanager.h"
#include "vconstants.h"

View File

@ -3,7 +3,7 @@
#include <QObject>
#include "hgmarkdownhighlighter.h"
#include "pegmarkdownhighlighter.h"
#include "vpreviewmanager.h"
#include "vconstants.h"

View File

@ -1,6 +1,6 @@
#include <QtWidgets>
#include "vmdedit.h"
#include "hgmarkdownhighlighter.h"
#include "pegmarkdownhighlighter.h"
#include "vmdeditoperations.h"
#include "vnote.h"
#include "vconfigmanager.h"
@ -30,6 +30,7 @@ VMdEdit::VMdEdit(VFile *p_file, VDocument *p_vdoc, MarkdownConverterType p_type,
setAcceptRichText(false);
/*
m_mdHighlighter = new HGMarkdownHighlighter(g_config->getMdHighlightingStyles(),
g_config->getCodeBlockStyles(),
g_config->getMarkdownHighlightInterval(),
@ -37,13 +38,13 @@ VMdEdit::VMdEdit(VFile *p_file, VDocument *p_vdoc, MarkdownConverterType p_type,
connect(m_mdHighlighter, &HGMarkdownHighlighter::headersUpdated,
this, &VMdEdit::updateHeaders);
// After highlight, the cursor may trun into non-visible. We should make it visible
// in this case.
connect(m_mdHighlighter, &HGMarkdownHighlighter::highlightCompleted,
this, [this]() {
makeBlockVisible(textCursor().block());
});
*/
/*
m_imagePreviewer = new VImagePreviewer(this, m_mdHighlighter);

View File

@ -12,8 +12,8 @@
#include "vconfigmanager.h"
#include "utils/vutils.h"
class HGMarkdownHighlighter;
class VDocument;
class PegMarkdownHighlighter;
class VMdEdit : public VEdit
{
@ -108,7 +108,7 @@ private:
// Index in m_headers of current header which contains the cursor.
int indexOfCurrentHeader() const;
HGMarkdownHighlighter *m_mdHighlighter;
PegMarkdownHighlighter *m_mdHighlighter;
// VImagePreviewer *m_imagePreviewer;
// Image links inserted while editing.

View File

@ -5,7 +5,7 @@
#include <QVector>
#include <QString>
#include <QHash>
#include "hgmarkdownhighlighter.h"
#include "pegmarkdownhighlighter.h"
extern "C" {
#include <pmh_definitions.h>

View File

@ -139,60 +139,6 @@ struct VPreviewInfo
};
struct MathjaxInfo
{
public:
MathjaxInfo()
: m_previewedAsBlock(false),
m_index(-1),
m_length(0)
{
}
bool isValid() const
{
return m_index >= 0 && m_length > 0;
}
bool previewedAsBlock() const
{
return m_previewedAsBlock;
}
void clear()
{
m_previewedAsBlock = false;
m_index = -1;
m_length = 0;
}
const QString &text() const
{
return m_text;
}
QString toString() const
{
return QString("MathjaxInfo %1 (%2,%3) %4").arg(m_previewedAsBlock)
.arg(m_index)
.arg(m_length)
.arg(m_text);
}
// Whether it should be previewed as block or not.
bool m_previewedAsBlock;
// Start index wihtin block, including the start mark.
int m_index;
// Length of this mathjax, including the end mark.
int m_length;
QString m_text;
};
// User data for each block.
class VTextBlockData : public QTextBlockUserData
{
@ -217,16 +163,6 @@ public:
void setCodeBlockIndentation(int p_indent);
void clearMathjax();
const MathjaxInfo &getPendingMathjax() const;
void setPendingMathjax(const MathjaxInfo &p_info);
const QVector<MathjaxInfo> &getMathjax() const;
void addMathjax(const MathjaxInfo &p_info);
private:
// Check the order of elements.
bool checkOrder() const;
@ -236,12 +172,6 @@ private:
// Indentation of the this code block if this block is a fenced code block.
int m_codeBlockIndentation;
// Pending Mathjax info, such as this block is the start of a Mathjax formula.
MathjaxInfo m_pendingMathjax;
// Mathjax info ends in this block.
QVector<MathjaxInfo> m_mathjax;
};
inline const QVector<VPreviewInfo *> &VTextBlockData::getPreviews() const
@ -258,31 +188,4 @@ inline void VTextBlockData::setCodeBlockIndentation(int p_indent)
{
m_codeBlockIndentation = p_indent;
}
inline void VTextBlockData::clearMathjax()
{
m_pendingMathjax.clear();
m_mathjax.clear();
}
inline const MathjaxInfo &VTextBlockData::getPendingMathjax() const
{
return m_pendingMathjax;
}
inline void VTextBlockData::setPendingMathjax(const MathjaxInfo &p_info)
{
m_pendingMathjax = p_info;
}
inline const QVector<MathjaxInfo> &VTextBlockData::getMathjax() const
{
return m_mathjax;
}
inline void VTextBlockData::addMathjax(const MathjaxInfo &p_info)
{
m_mathjax.append(p_info);
}
#endif // VTEXTBLOCKDATA_H