42 #include <QLoggingCategory>
43 #if QT_CONFIG(regularexpression)
44 #include <QRegularExpression>
46 #include <QTextCursor>
47 #include <QTextDocument>
48 #include <QTextDocumentFragment>
51 #if QT_CONFIG(system_textmarkdownreader)
54 #include "../../3rdparty/md4c/md4c.h"
65 static
const int BlockQuoteIndent = 40;
117 static void CbDebugLog(
const char *
msg,
void *userdata)
136 return defaultAlignment;
142 , m_features(features)
155 unsigned(m_features),
181 m_blockType = blockType;
185 qCDebug(lcMD, m_listItem ?
"P of LI at level %d" :
"P continuation inside LI at level %d",
int(m_listStack.
count()));
188 m_needsInsertBlock =
true;
192 qCDebug(lcMD,
"QUOTE level %d", m_blockQuoteDepth);
200 m_needsInsertBlock =
true;
201 if (m_blockQuoteDepth)
202 qCDebug(lcMD,
"CODE lang '%s' info '%s' fenced with '%c' inside QUOTE %d", qPrintable(m_blockCodeLanguage), qPrintable(
info), m_blockCodeFence, m_blockQuoteDepth);
204 qCDebug(lcMD,
"CODE lang '%s' info '%s' fenced with '%c'", qPrintable(m_blockCodeLanguage), qPrintable(
info), m_blockCodeFence);
210 int sizeAdjustment = 4 - int(detail->
level);
214 m_needsInsertBlock =
false;
224 m_needsInsertBlock =
true;
227 m_markerType = detail->
is_task ?
233 if (m_needsInsertList)
236 m_needsInsertList =
true;
240 switch (detail->
mark) {
251 qCDebug(lcMD,
"UL %c level %d", detail->
mark,
int(m_listStack.
count()) + 1);
254 if (m_needsInsertList)
257 m_needsInsertList =
true;
272 qWarning(
"malformed table in Markdown input");
279 qCDebug(lcMD) <<
"TD; align" << detail->
align << MdAlignment(detail->
align) <<
"col" << m_tableCol;
282 ++m_tableColumnCount;
284 if (m_currentTable->
columns() < m_tableColumnCount)
286 auto cell = m_currentTable->
cellAt(m_tableRowCount - 1, m_tableCol);
287 if (!cell.isValid()) {
288 qWarning(
"malformed table in Markdown input");
291 auto fmt = cell.format();
297 m_nonEmptyTableCells.
clear();
298 if (m_currentTable->
rows() < m_tableRowCount)
304 m_tableColumnCount = 0;
332 qCWarning(lcMD,
"list ended unexpectedly");
334 qCDebug(lcMD,
"list at level %d ended",
int(m_listStack.
count()));
344 for (
int col = m_tableCol; col >= 0; --col) {
345 if (m_nonEmptyTableCells.
contains(col)) {
346 if (mergeEnd >= 0 && mergeBegin >= 0) {
347 qCDebug(lcMD) <<
"merging cells" << mergeBegin <<
"to" << mergeEnd <<
"inclusive, on row" << m_currentTable->
rows() - 1;
348 m_currentTable->
mergeCells(m_currentTable->
rows() - 1, mergeBegin - 1, 1, mergeEnd - mergeBegin + 2);
361 qCDebug(lcMD,
"QUOTE level %d ended", m_blockQuoteDepth);
363 m_needsInsertBlock =
true;
366 qCDebug(lcMD) <<
"table ended with" << m_currentTable->
columns() <<
"cols and" << m_currentTable->
rows() <<
"rows";
367 m_currentTable =
nullptr;
371 qCDebug(lcMD,
"LI at level %d ended",
int(m_listStack.
count()));
376 m_blockCodeLanguage.
clear();
377 m_blockCodeFence = 0;
378 if (m_blockQuoteDepth)
379 qCDebug(lcMD,
"CODE ended inside QUOTE %d", m_blockQuoteDepth);
382 m_needsInsertBlock =
true;
396 if (!m_spanFormatStack.
isEmpty())
397 charFmt = m_spanFormatStack.
top();
435 m_spanFormatStack.
push(charFmt);
447 if (!m_spanFormatStack.
isEmpty()) {
448 m_spanFormatStack.
pop();
449 if (!m_spanFormatStack.
isEmpty())
450 charFmt = m_spanFormatStack.
top();
463 if (m_needsInsertBlock)
465 #if QT_CONFIG(regularexpression)
473 #if QT_CONFIG(regularexpression)
474 if (m_htmlTagDepth) {
475 m_htmlAccumulator +=
s;
492 #if QT_CONFIG(texthtmlparser)
495 m_htmlAccumulator +=
s;
503 #if QT_CONFIG(regularexpression) && QT_CONFIG(texthtmlparser)
506 while ((startIdx =
s.indexOf(openingBracket, startIdx)) >= 0) {
511 while ((startIdx =
s.indexOf(closingBracket, startIdx)) >= 0) {
516 m_htmlAccumulator +=
s;
517 if (!m_htmlTagDepth) {
518 qCDebug(lcMD) <<
"HTML" << m_htmlAccumulator;
520 if (m_spanFormatStack.
isEmpty())
531 switch (m_blockType) {
533 m_nonEmptyTableCells.
append(m_tableCol);
539 m_needsInsertBlock =
true;
553 <<
"alt" <<
s <<
"relative to" << m_doc->
baseUrl();
576 qCDebug(lcMD) << textType <<
"in block" << m_blockType <<
s << qPrintable(debugInfo)
594 void QTextMarkdownImporter::insertBlock()
597 if (!m_spanFormatStack.
isEmpty())
598 charFormat = m_spanFormatStack.
top();
600 if (!m_listStack.
isEmpty() && !m_needsInsertList && m_listItem) {
603 blockFormat =
list->item(
list->count() - 1).blockFormat();
605 qWarning() <<
"attempted to insert into a list that no longer exists";
607 if (m_blockQuoteDepth) {
609 blockFormat.
setLeftMargin(BlockQuoteIndent * m_blockQuoteDepth);
614 if (m_blockCodeFence) {
618 charFormat.
setFont(m_monoFont);
632 }
else if (m_listItem) {
638 if (m_needsInsertList) {
640 }
else if (!m_listStack.
isEmpty() && m_listItem && m_listStack.
top()) {
643 m_needsInsertList =
false;
644 m_needsInsertBlock =
false;
small capitals from c petite p scientific f u
const QColor & color() const
The QByteArray class provides an array of bytes.
qsizetype size() const noexcept
const char * constData() const noexcept
The QChar class provides a 16-bit Unicode character.
static constexpr QChar fromLatin1(char c) noexcept
QString name(NameFormat format=HexRgb) const
The QFontDatabase class provides information about the fonts available in the underlying window syste...
QStringList families() const
The QLatin1String class provides a thin wrapper around an US-ASCII/Latin-1 encoded string literal.
bool isEmpty() const noexcept
qsizetype count() const noexcept
void append(parameter_type t)
const QBrush & link() const
The QRegularExpression class provides pattern matching using regular expressions.
The QString class provides a Unicode character string.
static QString fromUtf8(QByteArrayView utf8)
static QString number(int, int base=10)
QByteArray toUtf8() const &
The QTextBlockFormat class provides formatting information for blocks of text in a QTextDocument....
qreal bottomMargin() const
void setLeftMargin(qreal margin)
void setAlignment(Qt::Alignment alignment)
void setMarker(MarkerType marker)
void setBottomMargin(qreal margin)
void setNonBreakableLines(bool b)
void setRightMargin(qreal margin)
void setIndent(int indent)
void setHeadingLevel(int alevel)
qreal rightMargin() const
void setTopMargin(qreal margin)
The QTextCharFormat class provides formatting information for characters in a QTextDocument....
void setAnchor(bool anchor)
void setFontUnderline(bool underline)
void setToolTip(const QString &tip)
void setFontFixedPitch(bool fixedPitch)
void setFontStrikeOut(bool strikeOut)
void setAnchorHref(const QString &value)
void setFontItalic(bool italic)
void setFontWeight(int weight)
void setFont(const QFont &font, FontPropertiesInheritanceBehavior behavior=FontPropertiesAll)
The QTextCursor class offers an API to access and modify QTextDocuments.
QTextBlockFormat blockFormat() const
bool movePosition(MoveOperation op, MoveMode=MoveAnchor, int n=1)
void insertHtml(const QString &html)
void setBlockFormat(const QTextBlockFormat &format)
void setCharFormat(const QTextCharFormat &format)
void insertText(const QString &text)
QTextList * currentList() const
void insertImage(const QTextImageFormat &format, QTextFrameFormat::Position alignment)
QTextList * insertList(const QTextListFormat &format)
QTextTable * insertTable(int rows, int cols, const QTextTableFormat &format)
QTextList * createList(const QTextListFormat &format)
The QTextDocument class holds formatted text.
QFont defaultFont
the default font used to display the document's text
QUrl baseUrl
the base URL used to resolve relative resource URLs within the document.
QString stringProperty(int propertyId) const
void setForeground(const QBrush &brush)
@ BlockTrailingHorizontalRulerWidth
int intProperty(int propertyId) const
void setProperty(int propertyId, const QVariant &value)
bool hasProperty(int propertyId) const
void clearProperty(int propertyId)
QBrush foreground() const
The QTextImageFormat class provides formatting information for images in a QTextDocument....
void setName(const QString &name)
The QTextListFormat class provides formatting information for lists in a QTextDocument....
void setStyle(Style style)
void setIndent(int indent)
void setNumberSuffix(const QString &numberSuffix)
The QTextList class provides a decorated list of items in a QTextDocument. \inmodule QtGui.
void add(const QTextBlock &block)
QTextListFormat format() const
int cbLeaveBlock(int blockType, void *detail)
int cbText(int textType, const char *text, unsigned size)
QTextMarkdownImporter(Features features)
int cbEnterBlock(int blockType, void *detail)
void import(QTextDocument *doc, const QString &markdown)
int cbEnterSpan(int spanType, void *detail)
int cbLeaveSpan(int spanType, void *detail)
The QTextTableCell class represents the properties of a cell in a QTextTable. \inmodule QtGui.
QTextCursor firstCursorPosition() const
void appendRows(int count)
void appendColumns(int count)
QTextTableCell cellAt(int row, int col) const
void mergeCells(int row, int col, int numRows, int numCols)
union Alignment_ Alignment
auto it unsigned count const
backing_store_ptr info
[4]
int md_parse(const MD_CHAR *text, MD_SIZE size, const MD_PARSER *parser, void *userdata)
#define MD_FLAG_TASKLISTS
#define MD_FLAG_NOHTMLBLOCKS
#define MD_FLAG_NOINDENTEDCODEBLOCKS
#define MD_FLAG_PERMISSIVEURLAUTOLINKS
#define MD_FLAG_PERMISSIVEWWWAUTOLINKS
#define MD_FLAG_UNDERLINE
#define MD_FLAG_PERMISSIVEEMAILAUTOLINKS
#define MD_DIALECT_GITHUB
#define MD_FLAG_PERMISSIVEATXHEADERS
#define MD_FLAG_PERMISSIVEAUTOLINKS
#define MD_DIALECT_COMMONMARK
#define MD_FLAG_NOHTMLSPANS
#define MD_FLAG_COLLAPSEWHITESPACE
#define MD_FLAG_STRIKETHROUGH
#define Q_LOGGING_CATEGORY(name,...)
#define qCWarning(category,...)
#define qCDebug(category,...)
GLboolean GLboolean GLboolean GLboolean a
[7]
GLenum GLuint GLintptr GLsizeiptr size
[1]
#define QStringLiteral(str)
QUrl url("http://www.example.com/List of holidays.xml")
[0]
The QLatin1Char class provides an 8-bit ASCII/Latin-1 character.
bool contains(const AT &t) const noexcept