mirror of
https://gitee.com/vnotex/vnote.git
synced 2025-07-05 13:59:52 +08:00
PegHighlighter: support math
This commit is contained in:
parent
d06dcc36f5
commit
f5bbc1ccd7
File diff suppressed because it is too large
Load Diff
@ -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
|
|
@ -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
|
bool equalContent(const VMathjaxBlock &p_block) const
|
||||||
{
|
{
|
||||||
return m_text == p_block.m_text;
|
return m_text == p_block.m_text;
|
||||||
@ -94,13 +85,16 @@ struct VMathjaxBlock
|
|||||||
m_length = p_block.m_length;
|
m_length = p_block.m_length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Block number for in-place preview.
|
||||||
int m_blockNumber;
|
int m_blockNumber;
|
||||||
|
|
||||||
|
// Whether it should be previewed as block or not.
|
||||||
bool m_previewedAsBlock;
|
bool m_previewedAsBlock;
|
||||||
|
|
||||||
// Start index within the block.
|
// Start index wihtin block with number m_blockNumber, including the start mark.
|
||||||
int m_index;
|
int m_index;
|
||||||
|
|
||||||
|
// Length of this mathjax in block with number m_blockNumber, including the end mark.
|
||||||
int m_length;
|
int m_length;
|
||||||
|
|
||||||
QString m_text;
|
QString m_text;
|
||||||
@ -171,12 +165,4 @@ struct VElementRegion
|
|||||||
return QString("[%1,%2)").arg(m_startPos).arg(m_endPos);
|
return QString("[%1,%2)").arg(m_startPos).arg(m_endPos);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PegHighlightResult
|
|
||||||
{
|
|
||||||
TimeStamp m_timeStamp;
|
|
||||||
|
|
||||||
QVector<QVector<HLUnit> > m_blockHighlights;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // MARKDOWNHIGHLIGHTERDATA_H
|
#endif // MARKDOWNHIGHLIGHTERDATA_H
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include <QTextDocument>
|
#include <QTextDocument>
|
||||||
#include <QTextBlock>
|
#include <QTextBlock>
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
#include "pegmarkdownhighlighter.h"
|
#include "pegmarkdownhighlighter.h"
|
||||||
#include "utils/vutils.h"
|
#include "utils/vutils.h"
|
||||||
@ -31,6 +32,8 @@ PegHighlighterResult::PegHighlighterResult(const PegMarkdownHighlighter *p_peg,
|
|||||||
m_headerRegions = p_result->m_headerRegions;
|
m_headerRegions = p_result->m_headerRegions;
|
||||||
|
|
||||||
parseFencedCodeBlocks(p_peg, p_result);
|
parseFencedCodeBlocks(p_peg, p_result);
|
||||||
|
|
||||||
|
parseMathjaxBlocks(p_peg, p_result);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool compHLUnit(const HLUnit &p_a, const HLUnit &p_b)
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -44,6 +44,9 @@ public:
|
|||||||
|
|
||||||
int m_numOfCodeBlockHighlightsToRecv;
|
int m_numOfCodeBlockHighlightsToRecv;
|
||||||
|
|
||||||
|
// All MathJax blocks.
|
||||||
|
QVector<VMathjaxBlock> m_mathjaxBlocks;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Parse highlight elements for all the blocks from parse results.
|
// Parse highlight elements for all the blocks from parse results.
|
||||||
void parseBlocksHighlights(const PegMarkdownHighlighter *p_peg,
|
void parseBlocksHighlights(const PegMarkdownHighlighter *p_peg,
|
||||||
@ -59,6 +62,10 @@ private:
|
|||||||
void parseFencedCodeBlocks(const PegMarkdownHighlighter *p_peg,
|
void parseFencedCodeBlocks(const PegMarkdownHighlighter *p_peg,
|
||||||
const QSharedPointer<PegParseResult> &p_result);
|
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,
|
void parseBlocksElementRegionOne(QHash<int, QVector<VElementRegion>> &p_regs,
|
||||||
const QTextDocument *p_doc,
|
const QTextDocument *p_doc,
|
||||||
unsigned long p_pos,
|
unsigned long p_pos,
|
||||||
|
@ -15,7 +15,7 @@ PegMarkdownHighlighter::PegMarkdownHighlighter(QTextDocument *p_doc)
|
|||||||
m_doc(p_doc),
|
m_doc(p_doc),
|
||||||
m_timeStamp(0),
|
m_timeStamp(0),
|
||||||
m_parser(NULL),
|
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_styles = p_styles;
|
||||||
m_codeBlockStyles = p_codeBlockStyles;
|
m_codeBlockStyles = p_codeBlockStyles;
|
||||||
|
|
||||||
|
if (p_mathjaxEnabled) {
|
||||||
|
m_parserExts |= pmh_EXT_MATH;
|
||||||
|
}
|
||||||
|
|
||||||
m_codeBlockFormat.setForeground(QBrush(Qt::darkYellow));
|
m_codeBlockFormat.setForeground(QBrush(Qt::darkYellow));
|
||||||
for (int index = 0; index < m_styles.size(); ++index) {
|
for (int index = 0; index < m_styles.size(); ++index) {
|
||||||
switch (m_styles[index].type) {
|
switch (m_styles[index].type) {
|
||||||
@ -272,7 +276,6 @@ void PegMarkdownHighlighter::updateBlockUserData(int p_blockNum, const QString &
|
|||||||
setCurrentBlockUserData(blockData);
|
setCurrentBlockUserData(blockData);
|
||||||
} else {
|
} else {
|
||||||
blockData->setCodeBlockIndentation(-1);
|
blockData->setCodeBlockIndentation(-1);
|
||||||
blockData->clearMathjax();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (blockData->getPreviews().isEmpty()) {
|
if (blockData->getPreviews().isEmpty()) {
|
||||||
@ -402,6 +405,10 @@ void PegMarkdownHighlighter::completeHighlight(QSharedPointer<PegHighlighterResu
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isMathJaxEnabled()) {
|
||||||
|
emit mathjaxBlocksUpdated(p_result->m_mathjaxBlocks);
|
||||||
|
}
|
||||||
|
|
||||||
emit imageLinksUpdated(p_result->m_imageRegions);
|
emit imageLinksUpdated(p_result->m_imageRegions);
|
||||||
emit headersUpdated(p_result->m_headerRegions);
|
emit headersUpdated(p_result->m_headerRegions);
|
||||||
|
|
||||||
|
@ -96,6 +96,8 @@ private:
|
|||||||
|
|
||||||
void completeHighlight(QSharedPointer<PegHighlighterResult> p_result);
|
void completeHighlight(QSharedPointer<PegHighlighterResult> p_result);
|
||||||
|
|
||||||
|
bool isMathJaxEnabled() const;
|
||||||
|
|
||||||
QTextDocument *m_doc;
|
QTextDocument *m_doc;
|
||||||
|
|
||||||
TimeStamp m_timeStamp;
|
TimeStamp m_timeStamp;
|
||||||
@ -176,4 +178,9 @@ inline VTextBlockData *PegMarkdownHighlighter::previousBlockData() const
|
|||||||
|
|
||||||
return static_cast<VTextBlockData *>(block.userData());
|
return static_cast<VTextBlockData *>(block.userData());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool PegMarkdownHighlighter::isMathJaxEnabled() const
|
||||||
|
{
|
||||||
|
return m_parserExts & pmh_EXT_MATH;
|
||||||
|
}
|
||||||
#endif // PEGMARKDOWNHIGHLIGHTER_H
|
#endif // PEGMARKDOWNHIGHLIGHTER_H
|
||||||
|
@ -15,6 +15,10 @@ void PegParseResult::parse(QAtomicInt &p_stop)
|
|||||||
parseHeaderRegions(p_stop);
|
parseHeaderRegions(p_stop);
|
||||||
|
|
||||||
parseFencedCodeBlockRegions(p_stop);
|
parseFencedCodeBlockRegions(p_stop);
|
||||||
|
|
||||||
|
parseInlineEquationRegions(p_stop);
|
||||||
|
|
||||||
|
parseDisplayFormulaRegions(p_stop);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PegParseResult::parseImageRegions(QAtomicInt &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)
|
PegParserWorker::PegParserWorker(QObject *p_parent)
|
||||||
: QThread(p_parent),
|
: QThread(p_parent),
|
||||||
@ -152,13 +208,7 @@ QSharedPointer<PegParseResult> PegParserWorker::parseMarkdown(const QSharedPoint
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
pmh_element **pmhResult = NULL;
|
result->m_pmhElements = PegParser::parseMarkdownToElements(p_config);
|
||||||
|
|
||||||
char *data = p_config->m_data.data();
|
|
||||||
|
|
||||||
pmh_markdown_to_elements(data, p_config->m_extensions, &pmhResult);
|
|
||||||
|
|
||||||
result->m_pmhElements = pmhResult;
|
|
||||||
|
|
||||||
if (p_stop.load() == 1) {
|
if (p_stop.load() == 1) {
|
||||||
return result;
|
return result;
|
||||||
@ -274,3 +324,39 @@ void PegParser::scheduleWork(PegParserWorker *p_worker,
|
|||||||
p_worker->prepareParse(p_config);
|
p_worker->prepareParse(p_config);
|
||||||
p_worker->start();
|
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;
|
||||||
|
}
|
||||||
|
@ -13,6 +13,13 @@
|
|||||||
|
|
||||||
struct PegParseConfig
|
struct PegParseConfig
|
||||||
{
|
{
|
||||||
|
PegParseConfig()
|
||||||
|
: m_timeStamp(0),
|
||||||
|
m_numOfBlocks(0),
|
||||||
|
m_extensions(pmh_EXT_NONE)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
TimeStamp m_timeStamp;
|
TimeStamp m_timeStamp;
|
||||||
|
|
||||||
QByteArray m_data;
|
QByteArray m_data;
|
||||||
@ -86,12 +93,23 @@ struct PegParseResult
|
|||||||
// Ordered by start position in ascending order.
|
// Ordered by start position in ascending order.
|
||||||
QMap<int, VElementRegion> m_codeBlockRegions;
|
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:
|
private:
|
||||||
void parseImageRegions(QAtomicInt &p_stop);
|
void parseImageRegions(QAtomicInt &p_stop);
|
||||||
|
|
||||||
void parseHeaderRegions(QAtomicInt &p_stop);
|
void parseHeaderRegions(QAtomicInt &p_stop);
|
||||||
|
|
||||||
void parseFencedCodeBlockRegions(QAtomicInt &p_stop);
|
void parseFencedCodeBlockRegions(QAtomicInt &p_stop);
|
||||||
|
|
||||||
|
void parseInlineEquationRegions(QAtomicInt &p_stop);
|
||||||
|
|
||||||
|
void parseDisplayFormulaRegions(QAtomicInt &p_stop);
|
||||||
};
|
};
|
||||||
|
|
||||||
class PegParserWorker : public QThread
|
class PegParserWorker : public QThread
|
||||||
@ -162,6 +180,11 @@ public:
|
|||||||
|
|
||||||
void parseAsync(const QSharedPointer<PegParseConfig> &p_config);
|
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:
|
signals:
|
||||||
void parseResultReady(const QSharedPointer<PegParseResult> &p_result);
|
void parseResultReady(const QSharedPointer<PegParseResult> &p_result);
|
||||||
|
|
||||||
|
@ -108,7 +108,9 @@ mdit = mdit.use(window.markdownitFootnote);
|
|||||||
|
|
||||||
mdit = mdit.use(window["markdown-it-imsize.js"]);
|
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 mdHasTocSection = function(markdown) {
|
||||||
var n = markdown.search(/(\n|^)\[toc\]/i);
|
var n = markdown.search(/(\n|^)\[toc\]/i);
|
||||||
|
@ -39,8 +39,6 @@ color-column-foreground: eeeeee
|
|||||||
preview-image-line-foreground: 6f5799
|
preview-image-line-foreground: 6f5799
|
||||||
# [VNote] Style for preview image (useful for SVG in dark theme)
|
# [VNote] Style for preview image (useful for SVG in dark theme)
|
||||||
preview-image-background: 949494
|
preview-image-background: 949494
|
||||||
# [VNote] Style for MathJax
|
|
||||||
mathjax-foreground: 93d3cc
|
|
||||||
|
|
||||||
editor-selection
|
editor-selection
|
||||||
foreground: dadada
|
foreground: dadada
|
||||||
@ -184,3 +182,11 @@ font-style: strikeout
|
|||||||
|
|
||||||
FRONTMATTER
|
FRONTMATTER
|
||||||
foreground: af8787
|
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
|
||||||
|
@ -39,8 +39,6 @@ color-column-foreground: eeeeee
|
|||||||
preview-image-line-foreground: 6f5799
|
preview-image-line-foreground: 6f5799
|
||||||
# [VNote] Style for preview image (useful for SVG in dark theme)
|
# [VNote] Style for preview image (useful for SVG in dark theme)
|
||||||
preview-image-background: b0bec5
|
preview-image-background: b0bec5
|
||||||
# [VNote] Style for MathJax
|
|
||||||
mathjax-foreground: 4db6ac
|
|
||||||
|
|
||||||
editor-selection
|
editor-selection
|
||||||
foreground: bcbcbc
|
foreground: bcbcbc
|
||||||
@ -183,3 +181,11 @@ font-style: strikeout
|
|||||||
|
|
||||||
FRONTMATTER
|
FRONTMATTER
|
||||||
foreground: 6e7686
|
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
|
||||||
|
@ -36,8 +36,6 @@ color-column-background: dd0000
|
|||||||
color-column-foreground: ffff00
|
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
|
|
||||||
mathjax-foreground: 00897b
|
|
||||||
|
|
||||||
editor-selection
|
editor-selection
|
||||||
foreground: ffffff
|
foreground: ffffff
|
||||||
@ -179,3 +177,11 @@ font-style: strikeout
|
|||||||
|
|
||||||
FRONTMATTER
|
FRONTMATTER
|
||||||
foreground: 6c6c6c
|
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
|
||||||
|
@ -37,8 +37,6 @@ color-column-background: dd0000
|
|||||||
color-column-foreground: ffff00
|
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
|
|
||||||
mathjax-foreground: 00897b
|
|
||||||
|
|
||||||
editor-selection
|
editor-selection
|
||||||
foreground: f5f5f5
|
foreground: f5f5f5
|
||||||
@ -180,3 +178,11 @@ font-style: strikeout
|
|||||||
|
|
||||||
FRONTMATTER
|
FRONTMATTER
|
||||||
foreground: 6c6c6c
|
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
|
||||||
|
@ -29,7 +29,6 @@ SOURCES += main.cpp\
|
|||||||
vdocument.cpp \
|
vdocument.cpp \
|
||||||
utils/vutils.cpp \
|
utils/vutils.cpp \
|
||||||
vpreviewpage.cpp \
|
vpreviewpage.cpp \
|
||||||
hgmarkdownhighlighter.cpp \
|
|
||||||
vstyleparser.cpp \
|
vstyleparser.cpp \
|
||||||
dialog/vnewnotebookdialog.cpp \
|
dialog/vnewnotebookdialog.cpp \
|
||||||
vmarkdownconverter.cpp \
|
vmarkdownconverter.cpp \
|
||||||
@ -158,7 +157,6 @@ HEADERS += vmainwindow.h \
|
|||||||
vdocument.h \
|
vdocument.h \
|
||||||
utils/vutils.h \
|
utils/vutils.h \
|
||||||
vpreviewpage.h \
|
vpreviewpage.h \
|
||||||
hgmarkdownhighlighter.h \
|
|
||||||
vstyleparser.h \
|
vstyleparser.h \
|
||||||
dialog/vnewnotebookdialog.h \
|
dialog/vnewnotebookdialog.h \
|
||||||
vmarkdownconverter.h \
|
vmarkdownconverter.h \
|
||||||
|
@ -32,8 +32,8 @@
|
|||||||
#include "vorphanfile.h"
|
#include "vorphanfile.h"
|
||||||
#include "vnote.h"
|
#include "vnote.h"
|
||||||
#include "vnotebook.h"
|
#include "vnotebook.h"
|
||||||
#include "hgmarkdownhighlighter.h"
|
|
||||||
#include "vpreviewpage.h"
|
#include "vpreviewpage.h"
|
||||||
|
#include "pegparser.h"
|
||||||
|
|
||||||
extern VConfigManager *g_config;
|
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_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_previewImageBlockRegExp = QString("[\\n|^][ |\\t]*\\xfffc[ |\\t]*(?=\\n)");
|
||||||
|
|
||||||
const QString VUtils::c_headerRegExp = QString("^(#{1,6})\\s+(((\\d+\\.)+(?=\\s))?\\s*(\\S.*)?)$");
|
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_markdownitAnchorExtraFile + "\"></script>\n" +
|
||||||
"<script src=\"qrc" + VNote::c_markdownitTaskListExtraFile + "\"></script>\n" +
|
"<script src=\"qrc" + VNote::c_markdownitTaskListExtraFile + "\"></script>\n" +
|
||||||
"<script src=\"qrc" + VNote::c_markdownitImsizeExtraFile + "\"></script>\n" +
|
"<script src=\"qrc" + VNote::c_markdownitImsizeExtraFile + "\"></script>\n" +
|
||||||
"<script src=\"qrc" + VNote::c_markdownitFootnoteExtraFile + "\"></script>\n" +
|
"<script src=\"qrc" + VNote::c_markdownitFootnoteExtraFile + "\"></script>\n";
|
||||||
"<script src=\"qrc" + VNote::c_markdownitTexMathExtraFile + "\"></script>\n";
|
|
||||||
|
if (g_config->getEnableMathjax()) {
|
||||||
|
extraFile += "<script src=\"qrc" + VNote::c_markdownitTexMathExtraFile + "\"></script>\n";
|
||||||
|
}
|
||||||
|
|
||||||
const MarkdownitOption &opt = g_config->getMarkdownitOption();
|
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)
|
QVector<VElementRegion> VUtils::fetchImageRegionsUsingParser(const QString &p_content)
|
||||||
{
|
{
|
||||||
Q_ASSERT(!p_content.isEmpty());
|
Q_ASSERT(!p_content.isEmpty());
|
||||||
QVector<VElementRegion> regs;
|
|
||||||
|
|
||||||
QByteArray ba = p_content.toUtf8();
|
const QSharedPointer<PegParseConfig> parserConfig(new PegParseConfig());
|
||||||
const char *data = (const char *)ba.data();
|
parserConfig->m_data = p_content.toUtf8();
|
||||||
int len = ba.size();
|
|
||||||
|
|
||||||
pmh_element **result = NULL;
|
return PegParser::parseImageRegions(parserConfig);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString VUtils::displayDateTime(const QDateTime &p_dateTime,
|
QString VUtils::displayDateTime(const QDateTime &p_dateTime,
|
||||||
|
@ -374,14 +374,6 @@ public:
|
|||||||
static const QString c_fencedCodeBlockStartRegExp;
|
static const QString c_fencedCodeBlockStartRegExp;
|
||||||
static const QString c_fencedCodeBlockEndRegExp;
|
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.
|
// Regular expression for preview image block.
|
||||||
static const QString c_previewImageBlockRegExp;
|
static const QString c_previewImageBlockRegExp;
|
||||||
|
|
||||||
@ -403,7 +395,7 @@ private:
|
|||||||
|
|
||||||
static void initAvailableLanguage();
|
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);
|
static QVector<VElementRegion> fetchImageRegionsUsingParser(const QString &p_content);
|
||||||
|
|
||||||
// Delete file/directory specified by @p_path by moving it to the recycle bin
|
// Delete file/directory specified by @p_path by moving it to the recycle bin
|
||||||
|
@ -620,7 +620,6 @@ void VConfigManager::updateMarkdownEditStyle()
|
|||||||
m_editorColorColumnFg = defaultColor;
|
m_editorColorColumnFg = defaultColor;
|
||||||
m_editorPreviewImageLineFg = defaultColor;
|
m_editorPreviewImageLineFg = defaultColor;
|
||||||
m_editorPreviewImageBg.clear();
|
m_editorPreviewImageBg.clear();
|
||||||
m_editorMathjaxFg = defaultColor;
|
|
||||||
|
|
||||||
auto editorIt = styles.find("editor");
|
auto editorIt = styles.find("editor");
|
||||||
if (editorIt != styles.end()) {
|
if (editorIt != styles.end()) {
|
||||||
@ -698,11 +697,6 @@ void VConfigManager::updateMarkdownEditStyle()
|
|||||||
if (it != editorIt->end()) {
|
if (it != editorIt->end()) {
|
||||||
m_editorPreviewImageBg = "#" + *it;
|
m_editorPreviewImageBg = "#" + *it;
|
||||||
}
|
}
|
||||||
|
|
||||||
it = editorIt->find("mathjax-foreground");
|
|
||||||
if (it != editorIt->end()) {
|
|
||||||
m_editorMathjaxFg = "#" + *it;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -333,8 +333,6 @@ public:
|
|||||||
|
|
||||||
const QString &getEditorPreviewImageBg() const;
|
const QString &getEditorPreviewImageBg() const;
|
||||||
|
|
||||||
const QString &getEditorMathjaxFg() const;
|
|
||||||
|
|
||||||
bool getEnableCodeBlockLineNumber() const;
|
bool getEnableCodeBlockLineNumber() const;
|
||||||
void setEnableCodeBlockLineNumber(bool p_enabled);
|
void setEnableCodeBlockLineNumber(bool p_enabled);
|
||||||
|
|
||||||
@ -789,7 +787,7 @@ private:
|
|||||||
// [DocType] -> { Suffixes }.
|
// [DocType] -> { Suffixes }.
|
||||||
QHash<int, QList<QString>> m_docSuffixes;
|
QHash<int, QList<QString>> m_docSuffixes;
|
||||||
|
|
||||||
// Interval for HGMarkdownHighlighter highlight timer (milliseconds).
|
// Interval for PegMarkdownHighlighter highlight timer (milliseconds).
|
||||||
int m_markdownHighlightInterval;
|
int m_markdownHighlightInterval;
|
||||||
|
|
||||||
// Line distance height in pixel.
|
// Line distance height in pixel.
|
||||||
@ -825,9 +823,6 @@ private:
|
|||||||
// The forced background color of the preview image. Can be empty.
|
// The forced background color of the preview image. Can be empty.
|
||||||
QString m_editorPreviewImageBg;
|
QString m_editorPreviewImageBg;
|
||||||
|
|
||||||
// The foreground color of the MathJax.
|
|
||||||
QString m_editorMathjaxFg;
|
|
||||||
|
|
||||||
// Icon size of tool bar in pixels.
|
// Icon size of tool bar in pixels.
|
||||||
int m_toolBarIconSize;
|
int m_toolBarIconSize;
|
||||||
|
|
||||||
@ -1927,11 +1922,6 @@ inline const QString &VConfigManager::getEditorPreviewImageBg() const
|
|||||||
return m_editorPreviewImageBg;
|
return m_editorPreviewImageBg;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const QString &VConfigManager::getEditorMathjaxFg() const
|
|
||||||
{
|
|
||||||
return m_editorMathjaxFg;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool VConfigManager::getEnableCodeBlockLineNumber() const
|
inline bool VConfigManager::getEnableCodeBlockLineNumber() const
|
||||||
{
|
{
|
||||||
return m_enableCodeBlockLineNumber;
|
return m_enableCodeBlockLineNumber;
|
||||||
|
@ -119,23 +119,7 @@ enum HighlightBlockState
|
|||||||
// A fenced code block.
|
// A fenced code block.
|
||||||
CodeBlockStart,
|
CodeBlockStart,
|
||||||
CodeBlock,
|
CodeBlock,
|
||||||
CodeBlockEnd,
|
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
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Pages to open on start up.
|
// Pages to open on start up.
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QTextDocument>
|
#include <QTextDocument>
|
||||||
|
|
||||||
#include "hgmarkdownhighlighter.h"
|
#include "pegmarkdownhighlighter.h"
|
||||||
#include "vpreviewmanager.h"
|
#include "vpreviewmanager.h"
|
||||||
#include "vconstants.h"
|
#include "vconstants.h"
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
|
||||||
#include "hgmarkdownhighlighter.h"
|
#include "pegmarkdownhighlighter.h"
|
||||||
#include "vpreviewmanager.h"
|
#include "vpreviewmanager.h"
|
||||||
#include "vconstants.h"
|
#include "vconstants.h"
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#include <QtWidgets>
|
#include <QtWidgets>
|
||||||
#include "vmdedit.h"
|
#include "vmdedit.h"
|
||||||
#include "hgmarkdownhighlighter.h"
|
#include "pegmarkdownhighlighter.h"
|
||||||
#include "vmdeditoperations.h"
|
#include "vmdeditoperations.h"
|
||||||
#include "vnote.h"
|
#include "vnote.h"
|
||||||
#include "vconfigmanager.h"
|
#include "vconfigmanager.h"
|
||||||
@ -30,6 +30,7 @@ VMdEdit::VMdEdit(VFile *p_file, VDocument *p_vdoc, MarkdownConverterType p_type,
|
|||||||
|
|
||||||
setAcceptRichText(false);
|
setAcceptRichText(false);
|
||||||
|
|
||||||
|
/*
|
||||||
m_mdHighlighter = new HGMarkdownHighlighter(g_config->getMdHighlightingStyles(),
|
m_mdHighlighter = new HGMarkdownHighlighter(g_config->getMdHighlightingStyles(),
|
||||||
g_config->getCodeBlockStyles(),
|
g_config->getCodeBlockStyles(),
|
||||||
g_config->getMarkdownHighlightInterval(),
|
g_config->getMarkdownHighlightInterval(),
|
||||||
@ -37,13 +38,13 @@ VMdEdit::VMdEdit(VFile *p_file, VDocument *p_vdoc, MarkdownConverterType p_type,
|
|||||||
|
|
||||||
connect(m_mdHighlighter, &HGMarkdownHighlighter::headersUpdated,
|
connect(m_mdHighlighter, &HGMarkdownHighlighter::headersUpdated,
|
||||||
this, &VMdEdit::updateHeaders);
|
this, &VMdEdit::updateHeaders);
|
||||||
|
|
||||||
// After highlight, the cursor may trun into non-visible. We should make it visible
|
// After highlight, the cursor may trun into non-visible. We should make it visible
|
||||||
// in this case.
|
// in this case.
|
||||||
connect(m_mdHighlighter, &HGMarkdownHighlighter::highlightCompleted,
|
connect(m_mdHighlighter, &HGMarkdownHighlighter::highlightCompleted,
|
||||||
this, [this]() {
|
this, [this]() {
|
||||||
makeBlockVisible(textCursor().block());
|
makeBlockVisible(textCursor().block());
|
||||||
});
|
});
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
m_imagePreviewer = new VImagePreviewer(this, m_mdHighlighter);
|
m_imagePreviewer = new VImagePreviewer(this, m_mdHighlighter);
|
||||||
|
@ -12,8 +12,8 @@
|
|||||||
#include "vconfigmanager.h"
|
#include "vconfigmanager.h"
|
||||||
#include "utils/vutils.h"
|
#include "utils/vutils.h"
|
||||||
|
|
||||||
class HGMarkdownHighlighter;
|
|
||||||
class VDocument;
|
class VDocument;
|
||||||
|
class PegMarkdownHighlighter;
|
||||||
|
|
||||||
class VMdEdit : public VEdit
|
class VMdEdit : public VEdit
|
||||||
{
|
{
|
||||||
@ -108,7 +108,7 @@ private:
|
|||||||
// Index in m_headers of current header which contains the cursor.
|
// Index in m_headers of current header which contains the cursor.
|
||||||
int indexOfCurrentHeader() const;
|
int indexOfCurrentHeader() const;
|
||||||
|
|
||||||
HGMarkdownHighlighter *m_mdHighlighter;
|
PegMarkdownHighlighter *m_mdHighlighter;
|
||||||
// VImagePreviewer *m_imagePreviewer;
|
// VImagePreviewer *m_imagePreviewer;
|
||||||
|
|
||||||
// Image links inserted while editing.
|
// Image links inserted while editing.
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
#include <QVector>
|
#include <QVector>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QHash>
|
#include <QHash>
|
||||||
#include "hgmarkdownhighlighter.h"
|
#include "pegmarkdownhighlighter.h"
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include <pmh_definitions.h>
|
#include <pmh_definitions.h>
|
||||||
|
@ -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.
|
// User data for each block.
|
||||||
class VTextBlockData : public QTextBlockUserData
|
class VTextBlockData : public QTextBlockUserData
|
||||||
{
|
{
|
||||||
@ -217,16 +163,6 @@ public:
|
|||||||
|
|
||||||
void setCodeBlockIndentation(int p_indent);
|
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:
|
private:
|
||||||
// Check the order of elements.
|
// Check the order of elements.
|
||||||
bool checkOrder() const;
|
bool checkOrder() const;
|
||||||
@ -236,12 +172,6 @@ private:
|
|||||||
|
|
||||||
// Indentation of the this code block if this block is a fenced code block.
|
// Indentation of the this code block if this block is a fenced code block.
|
||||||
int m_codeBlockIndentation;
|
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
|
inline const QVector<VPreviewInfo *> &VTextBlockData::getPreviews() const
|
||||||
@ -258,31 +188,4 @@ inline void VTextBlockData::setCodeBlockIndentation(int p_indent)
|
|||||||
{
|
{
|
||||||
m_codeBlockIndentation = 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
|
#endif // VTEXTBLOCKDATA_H
|
||||||
|
Loading…
x
Reference in New Issue
Block a user