diff --git a/src/dialog/vcopytextashtmldialog.cpp b/src/dialog/vcopytextashtmldialog.cpp
index d7a7287b..5ba12fec 100644
--- a/src/dialog/vcopytextashtmldialog.cpp
+++ b/src/dialog/vcopytextashtmldialog.cpp
@@ -65,6 +65,8 @@ void VCopyTextAsHtmlDialog::setConvertedHtml(const QUrl &p_baseUrl,
m_htmlViewer->setHtml(html, p_baseUrl);
setHtmlVisible(true);
+ VWebUtils::translateColors(html);
+
// Fix image source.
if (g_config->getFixImageSrcInWebWhenCopied()) {
VWebUtils::fixImageSrcInHtml(p_baseUrl, html);
diff --git a/src/resources/themes/v_moonlight/v_moonlight.palette b/src/resources/themes/v_moonlight/v_moonlight.palette
index bf517358..2b23fc15 100644
--- a/src/resources/themes/v_moonlight/v_moonlight.palette
+++ b/src/resources/themes/v_moonlight/v_moonlight.palette
@@ -7,6 +7,12 @@ mdhl_file=v_moonlight.mdhl
css_file=v_moonlight.css
codeblock_css_file=v_moonlight_codeblock.css
+; This mapping will be used to translate colors when the content of HTML is copied
+; without background. You could just specify the foreground colors mapping here.
+; It is useful for dark mode theme. '#aabbcc' or 'red' formats are supported.
+; col1:col1_new,col2:col2_new
+css_color_mapping=#abb2bf:#363636,#282c34:#f5f5f5,#61afef:#0099ff,#98c379:#8e24aa,#2c313a:#e0e0e0,#5c6370:#666666,#373e47:#999999,#6c6c6c:#444444,#c678dd:#0000ee,#e06c75:#880000,#56b6c2:#af00d7,#e6c07b:#008700,#d19a66:#bc6060,#61aeee:#bc6060
+
[phony]
; Abstract color attributes.
master_fg=@edit_fg
diff --git a/src/utils/vwebutils.cpp b/src/utils/vwebutils.cpp
index 6e86cfc6..98d14c44 100644
--- a/src/utils/vwebutils.cpp
+++ b/src/utils/vwebutils.cpp
@@ -4,6 +4,10 @@
#include
#include
+#include "vpalette.h"
+
+extern VPalette *g_palette;
+
VWebUtils::VWebUtils()
{
}
@@ -56,3 +60,67 @@ bool VWebUtils::fixImageSrcInHtml(const QUrl &p_baseUrl, QString &p_html)
return changed;
}
+
+bool VWebUtils::removeBackgroundColor(QString &p_html)
+{
+ QRegExp reg("(<[^>]+\\sstyle=[^>]*(\\s|\"))background(-color)?:[^;]+;([^>]*>)");
+ int size = p_html.size();
+ p_html.replace(reg, "\\1\\4");
+ return p_html.size() != size;
+}
+
+bool VWebUtils::translateColors(QString &p_html)
+{
+ bool changed = false;
+
+ const QHash &mapping = g_palette->getColorMapping();
+ if (mapping.isEmpty()) {
+ return changed;
+ }
+
+ QRegExp tagReg("(<[^>]+\\sstyle=[^>]*>)");
+ // Won't mixed up with background-color.
+ QRegExp colorReg("(\\s|\")color:([^;]+);");
+
+ int pos = 0;
+ while (pos < p_html.size()) {
+ int idx = p_html.indexOf(tagReg, pos);
+ if (idx == -1) {
+ break;
+ }
+
+ QString styleStr = tagReg.cap(1);
+ QString alteredStyleStr = styleStr;
+
+ int posb = 0;
+ while (posb < alteredStyleStr.size()) {
+ int idxb = alteredStyleStr.indexOf(colorReg, posb);
+ if (idxb == -1) {
+ break;
+ }
+
+ QString col = colorReg.cap(2).trimmed().toLower();
+ auto it = mapping.find(col);
+ if (it == mapping.end()) {
+ posb = idxb + colorReg.matchedLength();
+ continue;
+ }
+
+ // Replace the color.
+ QString newCol = it.value();
+ // Add one extra space between color and :.
+ QString newStr = QString("%1color : %2;").arg(colorReg.cap(1)).arg(newCol);
+ alteredStyleStr.replace(idxb, colorReg.matchedLength(), newStr);
+ posb = idxb + newStr.size();
+ changed = true;
+ }
+
+ pos = idx + tagReg.matchedLength();
+ if (changed) {
+ pos = pos + alteredStyleStr.size() - styleStr.size();
+ p_html.replace(idx, tagReg.matchedLength(), alteredStyleStr);
+ }
+ }
+
+ return changed;
+}
diff --git a/src/utils/vwebutils.h b/src/utils/vwebutils.h
index e0c82330..289e7680 100644
--- a/src/utils/vwebutils.h
+++ b/src/utils/vwebutils.h
@@ -11,6 +11,12 @@ public:
// Fix
in @p_html.
static bool fixImageSrcInHtml(const QUrl &p_baseUrl, QString &p_html);
+ // Remove background color style in @p_html.
+ static bool removeBackgroundColor(QString &p_html);
+
+ // Translate color styles in @p_html using mappings from VPalette.
+ static bool translateColors(QString &p_html);
+
private:
VWebUtils();
};
diff --git a/src/vpalette.cpp b/src/vpalette.cpp
index b8ea0180..45aed935 100644
--- a/src/vpalette.cpp
+++ b/src/vpalette.cpp
@@ -180,6 +180,19 @@ QMap VPalette::codeBlockCssStylesFromThemes(const QList m_colorMapping;
+
QString toString() const
{
- return QString("palette metadata qss=%1 mdhl=%2 css=%3 codeBlockCss=%4")
+ return QString("palette metadata qss=%1 mdhl=%2 css=%3 codeBlockCss=%4 colorMappingSize=%5")
.arg(m_qssFile)
.arg(m_mdhlFile)
.arg(m_cssFile)
- .arg(m_codeBlockCssFile);
+ .arg(m_codeBlockCssFile)
+ .arg(m_colorMapping.size());
}
};
@@ -39,6 +44,8 @@ public:
// Fill "@xxx" in @p_text with corresponding style.
void fillStyle(QString &p_text) const;
+ const QHash &getColorMapping() const;
+
// Read themes and return the mappings of editor styles.
static QMap editorStylesFromThemes(const QList &p_themeFiles);
@@ -77,4 +84,9 @@ private:
VPaletteMetaData m_data;
};
+inline const QHash &VPalette::getColorMapping() const
+{
+ return m_data.m_colorMapping;
+}
+
#endif // VPALETTE_H
diff --git a/src/vwebview.cpp b/src/vwebview.cpp
index eeadd98b..f047be56 100644
--- a/src/vwebview.cpp
+++ b/src/vwebview.cpp
@@ -229,14 +229,6 @@ void VWebView::hideUnusedActions(QMenu *p_menu)
}
}
-static bool removeBackgroundColor(QString &p_html)
-{
- QRegExp reg("(<[^>]+\\sstyle=[^>]*(\\s|\"))background(-color)?:[^;]+;([^>]*>)");
- int size = p_html.size();
- p_html.replace(reg, "\\1\\4");
- return p_html.size() != size;
-}
-
bool VWebView::removeStyles(QString &p_html)
{
bool changed = false;
@@ -336,8 +328,14 @@ void VWebView::alterHtmlMimeData(QClipboard *p_clipboard,
}
// Remove background color.
- if (p_removeBackground && removeBackgroundColor(html)) {
- altered = true;
+ if (p_removeBackground) {
+ if (VWebUtils::removeBackgroundColor(html)) {
+ altered = true;
+ }
+
+ if (VWebUtils::translateColors(html)) {
+ altered = true;
+ }
}
// Fix local relative images.