mirror of
https://gitee.com/vnotex/vnote.git
synced 2025-07-05 13:59:52 +08:00
MarkdownViewWindow: use web to highlight code block in editor
This commit is contained in:
parent
727fade948
commit
eff1a81125
@ -1 +1 @@
|
||||
Subproject commit 064a434202096f703cbed9162742bbc55911f974
|
||||
Subproject commit 43ed95437369d48ff0428661db9ebae711d725e9
|
@ -25,7 +25,7 @@
|
||||
using namespace vnotex;
|
||||
|
||||
#ifndef QT_NO_DEBUG
|
||||
// #define VX_DEBUG_WEB
|
||||
#define VX_DEBUG_WEB
|
||||
#endif
|
||||
|
||||
const QString ConfigMgr::c_orgName = "VNote";
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include "coreconfig.h"
|
||||
#include "editorconfig.h"
|
||||
#include "widgetconfig.h"
|
||||
#include "texteditorconfig.h"
|
||||
#include "markdowneditorconfig.h"
|
||||
|
||||
using namespace vnotex;
|
||||
@ -118,4 +119,5 @@ QString MainConfig::getVersion(const QJsonObject &p_jobj)
|
||||
void MainConfig::doVersionSpecificOverride()
|
||||
{
|
||||
// In a new version, we may want to change one value by force.
|
||||
m_editorConfig->getTextEditorConfig().m_highlightWhitespace = false;
|
||||
}
|
||||
|
@ -241,7 +241,7 @@ namespace vnotex
|
||||
InplacePreviewSources m_inplacePreviewSources = InplacePreviewSource::NoInplacePreview;
|
||||
|
||||
// View mode in edit mode.
|
||||
EditViewMode m_editViewMode = EditViewMode::EditPreview;
|
||||
EditViewMode m_editViewMode = EditViewMode::EditOnly;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -5,6 +5,8 @@
|
||||
|
||||
namespace vnotex
|
||||
{
|
||||
class MainConfig;
|
||||
|
||||
class TextEditorConfig : public IConfig
|
||||
{
|
||||
public:
|
||||
@ -73,6 +75,8 @@ namespace vnotex
|
||||
void setSpellCheckEnabled(bool p_enabled);
|
||||
|
||||
private:
|
||||
friend class MainConfig;
|
||||
|
||||
QString lineNumberTypeToString(LineNumberType p_type) const;
|
||||
LineNumberType stringToLineNumberType(const QString &p_str) const;
|
||||
|
||||
@ -99,7 +103,7 @@ namespace vnotex
|
||||
|
||||
int m_tabStopWidth = 4;
|
||||
|
||||
bool m_highlightWhitespace = true;
|
||||
bool m_highlightWhitespace = false;
|
||||
|
||||
int m_zoomDelta = 0;
|
||||
|
||||
|
@ -67,6 +67,7 @@ namespace vnotex
|
||||
|
||||
// Use for MarkdownEditor code block highlight.
|
||||
// If not specified, will use m_editorHighlightTheme.
|
||||
// Valid only when KSyntaxCodeBlockHighlighter is used.
|
||||
QString m_markdownEditorHighlightTheme;
|
||||
};
|
||||
|
||||
|
@ -141,7 +141,7 @@
|
||||
"wrap_mode": "word_anywhere",
|
||||
"expand_tab": true,
|
||||
"tab_stop_width": 4,
|
||||
"highlight_whitespace": true,
|
||||
"highlight_whitespace": false,
|
||||
"//comment" : "Positive to zoom in and negative to zoom out",
|
||||
"zoom_delta": 0,
|
||||
"spell_check": false
|
||||
@ -360,7 +360,7 @@
|
||||
"//comment" : "imagelink/codeblock/math",
|
||||
"inplace_preview_sources" : "imagelink;codeblock;math",
|
||||
"//comment" : "view mode of edit mode: editonly/editpreview",
|
||||
"edit_view_mode" : "editpreview"
|
||||
"edit_view_mode" : "editonly"
|
||||
},
|
||||
"image_host" : {
|
||||
"hosts" : [
|
||||
|
@ -35,6 +35,14 @@ new QWebChannel(qt.webChannelTransport,
|
||||
window.vnotex.htmlToMarkdown(p_id, p_timeStamp, p_html);
|
||||
});
|
||||
|
||||
adapter.highlightCodeBlockRequested.connect(function(p_idx, p_timeStamp, p_text) {
|
||||
window.vnotex.highlightCodeBlock(p_idx, p_timeStamp, p_text);
|
||||
});
|
||||
|
||||
adapter.parseStyleSheetRequested.connect(function(p_id, p_styleSheet) {
|
||||
window.vnotex.parseStyleSheet(p_id, p_styleSheet);
|
||||
});
|
||||
|
||||
adapter.crossCopyRequested.connect(function(p_id, p_timeStamp, p_target, p_baseUrl, p_html) {
|
||||
window.vnotex.crossCopy(p_id, p_timeStamp, p_target, p_baseUrl, p_html);
|
||||
});
|
||||
|
@ -270,6 +270,49 @@ class VNoteX extends EventEmitter {
|
||||
window.vxMarkdownAdapter.setMarkdownFromHtml(p_id, p_timeStamp, markdown);
|
||||
}
|
||||
|
||||
highlightCodeBlock(p_idx, p_timeStamp, p_text) {
|
||||
let match = /^```[^\S\n]*(\S+)?\s*\n([\s\S]+)\n```\s*$/.exec(p_text);
|
||||
if (!match || !match[1] || !match[2]) {
|
||||
window.vxMarkdownAdapter.setCodeBlockHighlightHtml(p_idx, p_timeStamp, '');
|
||||
return;
|
||||
}
|
||||
|
||||
let lang = match[1];
|
||||
let body = match[2];
|
||||
|
||||
if (Prism && Prism.languages[lang]) {
|
||||
let html = Prism.highlight(body, Prism.languages[lang], lang);
|
||||
window.vxMarkdownAdapter.setCodeBlockHighlightHtml(p_idx, p_timeStamp, html);
|
||||
} else {
|
||||
window.vxMarkdownAdapter.setCodeBlockHighlightHtml(p_idx, p_timeStamp, '');
|
||||
}
|
||||
}
|
||||
|
||||
parseStyleSheet(p_id, p_styleSheet) {
|
||||
let doc = document.implementation.createHTMLDocument('');
|
||||
let styleEle = document.createElement('style');
|
||||
styleEle.textContent = p_styleSheet;
|
||||
doc.body.appendChild(styleEle);
|
||||
|
||||
let styles = [];
|
||||
for (let i = 0; i < styleEle.sheet.cssRules.length; ++i) {
|
||||
let rule = styleEle.sheet.cssRules[i];
|
||||
if (rule.type != CSSRule.STYLE_RULE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
styles.push({
|
||||
selector: rule.selectorText,
|
||||
color: rule.style.color,
|
||||
backgroundColor: rule.style.backgroundColor,
|
||||
fontWeight: rule.style.fontWeight,
|
||||
fontStyle: rule.style.fontStyle
|
||||
});
|
||||
}
|
||||
|
||||
window.vxMarkdownAdapter.setStyleSheetStyles(p_id, styles);
|
||||
}
|
||||
|
||||
setCrossCopyTargets(p_targets) {
|
||||
window.vxMarkdownAdapter.setCrossCopyTargets(p_targets);
|
||||
}
|
||||
|
@ -8,24 +8,8 @@ using namespace vnotex;
|
||||
QAccessibleInterface *FakeAccessible::accessibleFactory(const QString &p_className, QObject *p_obj)
|
||||
{
|
||||
// Try to fix non-responsible issue caused by Youdao Dict.
|
||||
if (p_className == QLatin1String("vnotex::LineEdit")
|
||||
|| p_className == QLatin1String("vnotex::TitleBar")
|
||||
|| p_className == QLatin1String("vnotex::NotebookSelector")
|
||||
|| p_className == QLatin1String("vnotex::TagExplorer")
|
||||
|| p_className == QLatin1String("vnotex::SearchPanel")
|
||||
|| p_className == QLatin1String("vnotex::SnippetPanel")
|
||||
|| p_className == QLatin1String("vnotex::OutlineViewer")
|
||||
|| p_className == QLatin1String("vnotex::TitleToolBar")
|
||||
|| p_className == QLatin1String("vnotex::MainWindow")
|
||||
|| p_className == QLatin1String("vnotex::ViewArea")
|
||||
|| p_className == QLatin1String("vte::VTextEdit")
|
||||
|| p_className == QLatin1String("vte::IndicatorsBorder")
|
||||
|| p_className == QLatin1String("vte::MarkdownEditor")
|
||||
|| p_className == QLatin1String("vte::VMarkdownEditor")
|
||||
|| p_className == QLatin1String("vte::VTextEditor")
|
||||
|| p_className == QLatin1String("vte::ViStatusBar")
|
||||
|| p_className == QLatin1String("vte::StatusIndicator")
|
||||
|| p_className == QLatin1String("vte::ScrollBar")) {
|
||||
if (p_className.startsWith(QStringLiteral("vnotex::"))
|
||||
|| p_className.startsWith(QStringLiteral("vte::"))) {
|
||||
return new FakeAccessibleInterface(p_obj);
|
||||
}
|
||||
|
||||
|
29
src/utils/callbackpool.cpp
Normal file
29
src/utils/callbackpool.cpp
Normal file
@ -0,0 +1,29 @@
|
||||
#include "callbackpool.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
using namespace vnotex;
|
||||
|
||||
quint64 CallbackPool::add(const Callback &p_callback)
|
||||
{
|
||||
static quint64 nextId = 0;
|
||||
quint64 id = nextId++;
|
||||
m_pool.insert(id, p_callback);
|
||||
return id;
|
||||
}
|
||||
|
||||
void CallbackPool::call(quint64 p_id, void *p_data)
|
||||
{
|
||||
auto it = m_pool.find(p_id);
|
||||
if (it != m_pool.end()) {
|
||||
it.value()(p_data);
|
||||
m_pool.erase(it);
|
||||
} else {
|
||||
qWarning() << "failed to locate callback in pool with id" << p_id;
|
||||
}
|
||||
}
|
||||
|
||||
void CallbackPool::clear()
|
||||
{
|
||||
m_pool.clear();
|
||||
}
|
29
src/utils/callbackpool.h
Normal file
29
src/utils/callbackpool.h
Normal file
@ -0,0 +1,29 @@
|
||||
#ifndef CALLBACKPOOL_H
|
||||
#define CALLBACKPOOL_H
|
||||
|
||||
#include <functional>
|
||||
|
||||
#include <QMap>
|
||||
|
||||
namespace vnotex
|
||||
{
|
||||
// Manage callbacks with id.
|
||||
class CallbackPool
|
||||
{
|
||||
public:
|
||||
typedef std::function<void(void *)> Callback;
|
||||
|
||||
CallbackPool() = default;
|
||||
|
||||
quint64 add(const Callback &p_callback);
|
||||
|
||||
void call(quint64 p_id, void *p_data);
|
||||
|
||||
void clear();
|
||||
|
||||
private:
|
||||
QMap<quint64, Callback> m_pool;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // CALLBACKPOOL_H
|
@ -192,3 +192,15 @@ QJsonValue Utils::parseAndReadJson(const QJsonObject &p_obj, const QString &p_ex
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
QColor Utils::toColor(const QString &p_color)
|
||||
{
|
||||
// rgb(123, 123, 123).
|
||||
QRegularExpression rgbTripleRegExp(R"(^rgb\((\d+)\s*,\s*(\d+)\s*,\s*(\d+)\)$)", QRegularExpression::CaseInsensitiveOption);
|
||||
auto match = rgbTripleRegExp.match(p_color);
|
||||
if (match.hasMatch()) {
|
||||
return QColor(match.captured(1).toInt(), match.captured(2).toInt(), match.captured(3).toInt());
|
||||
}
|
||||
|
||||
return QColor(p_color);
|
||||
}
|
||||
|
@ -61,6 +61,8 @@ namespace vnotex
|
||||
// Parse @p_exp into tokens and read the target value from @p_obj.
|
||||
// Format: obj1.obj2.arr[2].obj3.
|
||||
static QJsonValue parseAndReadJson(const QJsonObject &p_obj, const QString &p_exp);
|
||||
|
||||
static QColor toColor(const QString &p_color);
|
||||
};
|
||||
} // ns vnotex
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
QT += widgets svg
|
||||
|
||||
SOURCES += \
|
||||
$$PWD/callbackpool.cpp \
|
||||
$$PWD/contentmediautils.cpp \
|
||||
$$PWD/docsutils.cpp \
|
||||
$$PWD/htmlutils.cpp \
|
||||
@ -17,6 +18,7 @@ SOURCES += \
|
||||
$$PWD/clipboardutils.cpp
|
||||
|
||||
HEADERS += \
|
||||
$$PWD/callbackpool.h \
|
||||
$$PWD/contentmediautils.h \
|
||||
$$PWD/docsutils.h \
|
||||
$$PWD/htmlutils.h \
|
||||
|
@ -1057,7 +1057,7 @@ void MarkdownEditor::parseToMarkdownAndPaste()
|
||||
void MarkdownEditor::handleHtmlToMarkdownData(quint64 p_id, TimeStamp p_timeStamp, const QString &p_text)
|
||||
{
|
||||
Q_UNUSED(p_id);
|
||||
qDebug() << "htmlToMarkdownData" << p_timeStamp;
|
||||
qDebug() << "htmlToMarkdownData" << p_timeStamp << p_text;
|
||||
if (m_timeStamp == p_timeStamp && !p_text.isEmpty()) {
|
||||
QString text(p_text);
|
||||
|
||||
|
@ -1,6 +1,5 @@
|
||||
#include "markdownvieweradapter.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QMap>
|
||||
|
||||
#include "../outlineprovider.h"
|
||||
@ -61,6 +60,35 @@ QJsonObject MarkdownViewerAdapter::FindOption::toJson() const
|
||||
return obj;
|
||||
}
|
||||
|
||||
MarkdownViewerAdapter::CssRuleStyle MarkdownViewerAdapter::CssRuleStyle::fromJson(const QJsonObject &p_obj)
|
||||
{
|
||||
CssRuleStyle style;
|
||||
style.m_selector = p_obj[QStringLiteral("selector")].toString();
|
||||
style.m_color = p_obj[QStringLiteral("color")].toString();
|
||||
style.m_backgroundColor = p_obj[QStringLiteral("backgroundColor")].toString();
|
||||
style.m_fontWeight = p_obj[QStringLiteral("fontWeight")].toString();
|
||||
style.m_fontStyle = p_obj[QStringLiteral("fontStyle")].toString();
|
||||
return style;
|
||||
}
|
||||
|
||||
QTextCharFormat MarkdownViewerAdapter::CssRuleStyle::toTextCharFormat() const
|
||||
{
|
||||
QTextCharFormat fmt;
|
||||
if (!m_color.isEmpty()) {
|
||||
fmt.setForeground(Utils::toColor(m_color));
|
||||
}
|
||||
if (!m_backgroundColor.isEmpty()) {
|
||||
fmt.setBackground(QColor(m_color));
|
||||
}
|
||||
if (m_fontWeight.contains(QStringLiteral("bold"))) {
|
||||
fmt.setFontWeight(QFont::Bold);
|
||||
}
|
||||
if (m_fontStyle.contains(QStringLiteral("italic"))) {
|
||||
fmt.setFontItalic(true);
|
||||
}
|
||||
return fmt;
|
||||
}
|
||||
|
||||
MarkdownViewerAdapter::MarkdownViewerAdapter(QObject *p_parent)
|
||||
: QObject(p_parent)
|
||||
{
|
||||
@ -269,6 +297,11 @@ void MarkdownViewerAdapter::setMarkdownFromHtml(quint64 p_id, quint64 p_timeStam
|
||||
emit htmlToMarkdownReady(p_id, p_timeStamp, p_text);
|
||||
}
|
||||
|
||||
void MarkdownViewerAdapter::setCodeBlockHighlightHtml(int p_idx, quint64 p_timeStamp, const QString &p_html)
|
||||
{
|
||||
emit highlightCodeBlockReady(p_idx, p_timeStamp, p_html);
|
||||
}
|
||||
|
||||
void MarkdownViewerAdapter::setCrossCopyTargets(const QJsonArray &p_targets)
|
||||
{
|
||||
m_crossCopyTargets.clear();
|
||||
@ -401,3 +434,44 @@ void MarkdownViewerAdapter::renderGraph(quint64 p_id,
|
||||
Q_ASSERT(false);
|
||||
}
|
||||
}
|
||||
|
||||
void MarkdownViewerAdapter::highlightCodeBlock(int p_idx, quint64 p_timeStamp, const QString &p_text)
|
||||
{
|
||||
if (m_viewerReady) {
|
||||
emit highlightCodeBlockRequested(p_idx, p_timeStamp, p_text);
|
||||
} else {
|
||||
m_pendingActions.append([this, p_idx, p_timeStamp, p_text]() {
|
||||
emit highlightCodeBlockRequested(p_idx, p_timeStamp, p_text);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void MarkdownViewerAdapter::setStyleSheetStyles(quint64 p_id, const QJsonArray &p_styles)
|
||||
{
|
||||
QVector<CssRuleStyle> ruleStyles;
|
||||
ruleStyles.reserve(p_styles.size());
|
||||
for (int i = 0; i < p_styles.size(); ++i) {
|
||||
ruleStyles.push_back(CssRuleStyle::fromJson(p_styles[i].toObject()));
|
||||
}
|
||||
|
||||
m_callbackPool.call(p_id, &ruleStyles);
|
||||
}
|
||||
|
||||
void MarkdownViewerAdapter::fetchStylesFromStyleSheet(const QString &p_styleSheet,
|
||||
const std::function<void(const QVector<CssRuleStyle> *)> &p_callback)
|
||||
{
|
||||
if (p_styleSheet.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const quint64 id = m_callbackPool.add([p_callback](void *data) {
|
||||
p_callback(reinterpret_cast<const QVector<CssRuleStyle> *>(data));
|
||||
});
|
||||
if (m_viewerReady) {
|
||||
emit parseStyleSheetRequested(id, p_styleSheet);
|
||||
} else {
|
||||
m_pendingActions.append([this, p_styleSheet, id]() {
|
||||
emit parseStyleSheetRequested(id, p_styleSheet);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -6,8 +6,10 @@
|
||||
#include <QJsonObject>
|
||||
#include <QScopedPointer>
|
||||
#include <QJsonArray>
|
||||
#include <QTextCharFormat>
|
||||
|
||||
#include <core/global.h>
|
||||
#include <utils/callbackpool.h>
|
||||
|
||||
namespace vnotex
|
||||
{
|
||||
@ -78,6 +80,23 @@ namespace vnotex
|
||||
bool m_regularExpression = false;
|
||||
};
|
||||
|
||||
struct CssRuleStyle
|
||||
{
|
||||
QTextCharFormat toTextCharFormat() const;
|
||||
|
||||
static CssRuleStyle fromJson(const QJsonObject &p_obj);
|
||||
|
||||
QString m_selector;
|
||||
|
||||
QString m_color;
|
||||
|
||||
QString m_backgroundColor;
|
||||
|
||||
QString m_fontWeight;
|
||||
|
||||
QString m_fontStyle;
|
||||
};
|
||||
|
||||
explicit MarkdownViewerAdapter(QObject *p_parent = nullptr);
|
||||
|
||||
virtual ~MarkdownViewerAdapter();
|
||||
@ -114,6 +133,12 @@ namespace vnotex
|
||||
// Should be called before WebViewer.setHtml().
|
||||
void reset();
|
||||
|
||||
void highlightCodeBlock(int p_idx, quint64 p_timeStamp, const QString &p_text);
|
||||
|
||||
// Parse style sheet and fetch the styles.
|
||||
void fetchStylesFromStyleSheet(const QString &p_styleSheet,
|
||||
const std::function<void(const QVector<CssRuleStyle> *)> &p_callback);
|
||||
|
||||
// Functions to be called from web side.
|
||||
public slots:
|
||||
void setReady(bool p_ready);
|
||||
@ -152,6 +177,8 @@ namespace vnotex
|
||||
// Set back the result of htmlToMarkdown() call.
|
||||
void setMarkdownFromHtml(quint64 p_id, quint64 p_timeStamp, const QString &p_text);
|
||||
|
||||
void setCodeBlockHighlightHtml(int p_idx, quint64 p_timeStamp, const QString &p_html);
|
||||
|
||||
void setCrossCopyTargets(const QJsonArray &p_targets);
|
||||
|
||||
void setCrossCopyResult(quint64 p_id, quint64 p_timeStamp, const QString &p_html);
|
||||
@ -167,6 +194,8 @@ namespace vnotex
|
||||
const QString &p_lang,
|
||||
const QString &p_text);
|
||||
|
||||
void setStyleSheetStyles(quint64 p_id, const QJsonArray &p_styles);
|
||||
|
||||
// Signals to be connected at web side.
|
||||
signals:
|
||||
// Current Markdown text is updated.
|
||||
@ -208,6 +237,10 @@ namespace vnotex
|
||||
const QString &p_format,
|
||||
const QString &p_data);
|
||||
|
||||
void highlightCodeBlockRequested(int p_idx, quint64 p_timeStamp, const QString &p_text);
|
||||
|
||||
void parseStyleSheetRequested(quint64 p_id, const QString &p_styleSheet);
|
||||
|
||||
// Signals to be connected at cpp side.
|
||||
signals:
|
||||
void graphPreviewDataReady(const PreviewData &p_data);
|
||||
@ -238,6 +271,8 @@ namespace vnotex
|
||||
const QString &p_content,
|
||||
const QString &p_bodyClassList);
|
||||
|
||||
void highlightCodeBlockReady(int p_idx, quint64 p_timeStamp, const QString &p_html);
|
||||
|
||||
private:
|
||||
void scrollToLine(int p_lineNumber);
|
||||
|
||||
@ -261,6 +296,8 @@ namespace vnotex
|
||||
|
||||
// Targets supported by cross copy. Set by web.
|
||||
QStringList m_crossCopyTargets;
|
||||
|
||||
CallbackPool m_callbackPool;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -383,7 +383,11 @@ void MainWindow::closeEvent(QCloseEvent *p_event)
|
||||
// Avoid geometry corruption caused by fullscreen or minimized window.
|
||||
const auto state = windowState();
|
||||
if (state & (Qt::WindowMinimized | Qt::WindowFullScreen)) {
|
||||
showNormal();
|
||||
if (m_windowOldState & Qt::WindowMaximized) {
|
||||
showMaximized();
|
||||
} else {
|
||||
showNormal();
|
||||
}
|
||||
}
|
||||
saveStateAndGeometry();
|
||||
}
|
||||
|
@ -17,12 +17,14 @@
|
||||
#include <core/fileopenparameters.h>
|
||||
#include <core/editorconfig.h>
|
||||
#include <core/htmltemplatehelper.h>
|
||||
#include <core/exception.h>
|
||||
#include <vtextedit/vtextedit.h>
|
||||
#include <vtextedit/pegmarkdownhighlighter.h>
|
||||
#include <vtextedit/markdowneditorconfig.h>
|
||||
#include <utils/pathutils.h>
|
||||
#include <utils/widgetutils.h>
|
||||
#include <utils/printutils.h>
|
||||
#include <utils/fileutils.h>
|
||||
#include <buffer/markdownbuffer.h>
|
||||
#include <core/vnotex.h>
|
||||
#include <core/thememgr.h>
|
||||
@ -359,6 +361,10 @@ void MarkdownViewWindow::setupTextEditor()
|
||||
adapter(), &MarkdownViewerAdapter::htmlToMarkdownRequested);
|
||||
connect(adapter(), &MarkdownViewerAdapter::htmlToMarkdownReady,
|
||||
m_editor, &MarkdownEditor::handleHtmlToMarkdownData);
|
||||
connect(m_editor, &vte::VMarkdownEditor::externalCodeBlockHighlightRequested,
|
||||
this, &MarkdownViewWindow::handleExternalCodeBlockHighlightRequest);
|
||||
connect(adapter(), &MarkdownViewerAdapter::highlightCodeBlockReady,
|
||||
m_editor, &vte::VMarkdownEditor::handleExternalCodeBlockHighlightData);
|
||||
|
||||
// Connect outline pipeline.
|
||||
connect(m_editor, &MarkdownEditor::headingsChanged,
|
||||
@ -1383,3 +1389,52 @@ void MarkdownViewWindow::print()
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void MarkdownViewWindow::handleExternalCodeBlockHighlightRequest(int p_idx, quint64 p_timeStamp, const QString &p_text)
|
||||
{
|
||||
static bool stylesInitialized = false;
|
||||
if (!stylesInitialized) {
|
||||
stylesInitialized = true;
|
||||
const auto file = VNoteX::getInst().getThemeMgr().getFile(Theme::File::HighlightStyleSheet);
|
||||
if (file.isEmpty()) {
|
||||
qWarning() << "no highlight style sheet specified for external code block highlight";
|
||||
} else {
|
||||
QString content;
|
||||
try {
|
||||
content = FileUtils::readTextFile(file);
|
||||
} catch (Exception &e) {
|
||||
qWarning() << "failed to read highlight style sheet for external code block highlight" << file << e.what();
|
||||
}
|
||||
adapter()->fetchStylesFromStyleSheet(content, [this](const QVector<MarkdownViewerAdapter::CssRuleStyle> *rules) {
|
||||
MarkdownEditor::ExternalCodeBlockHighlightStyles styles;
|
||||
|
||||
const QString prefix(".token.");
|
||||
for (const auto &rule : *rules) {
|
||||
bool isFirst = true;
|
||||
QTextCharFormat fmt;
|
||||
|
||||
// Just fetch `.token.attr` styles.
|
||||
auto selects = rule.m_selector.split(QLatin1Char(','));
|
||||
for (const auto &sel : selects) {
|
||||
const auto ts = sel.trimmed();
|
||||
if (!ts.startsWith(prefix)) {
|
||||
continue;
|
||||
}
|
||||
auto classList = ts.mid(prefix.size()).split(QLatin1Char('.'));
|
||||
for (const auto &cla : classList) {
|
||||
if (isFirst) {
|
||||
fmt = rule.toTextCharFormat();
|
||||
isFirst = false;
|
||||
}
|
||||
styles.insert(cla, fmt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MarkdownEditor::setExternalCodeBlockHighlihgtStyles(styles);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
adapter()->highlightCodeBlock(p_idx, p_timeStamp, p_text);
|
||||
}
|
||||
|
@ -177,6 +177,8 @@ namespace vnotex
|
||||
|
||||
void syncEditorPositionToPreview();
|
||||
|
||||
void handleExternalCodeBlockHighlightRequest(int p_idx, quint64 p_timeStamp, const QString &p_text);
|
||||
|
||||
template <class T>
|
||||
static QSharedPointer<Outline> headingsToOutline(const QVector<T> &p_headings);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user