Le Tan 7 лет назад
Родитель
Сommit
4a4e4ed377

+ 3 - 0
src/resources/themes/v_moonlight/v_moonlight.css

@@ -5,6 +5,7 @@ body {
     line-height: 1;
     padding: 15px;
     background: #282C34;
+    font-size: 16px;
 }
 
 h1, h2, h3, h4, h5, h6 {
@@ -96,6 +97,8 @@ pre code {
     color: #98C379;
     background-color: #2C313A;
     line-height: 1.5;
+    font-family: Consolas, Monaco, Monospace, Courier;
+    white-space: pre;
 }
 
 code.mathjax-code {

+ 3 - 0
src/resources/themes/v_pure/v_pure.css

@@ -5,6 +5,7 @@ body {
     line-height: 1;
     padding: 15px;
     background: #F5F5F5;
+    font-size: 16px;
 }
 
 h1, h2, h3, h4, h5, h6 {
@@ -96,6 +97,8 @@ pre code {
     color: #222222;
     background-color: #E0E0E0;
     line-height: 1.5;
+    font-family: Consolas, Monaco, Monospace, Courier;
+    white-space: pre;
 }
 
 /* Should reference the style of P. */

+ 3 - 0
src/resources/themes/v_white/v_white.css

@@ -4,6 +4,7 @@ body {
     color: #222222;
     line-height: 1;
     padding: 15px;
+    font-size: 16px;
 }
 
 h1, h2, h3, h4, h5, h6 {
@@ -95,6 +96,8 @@ pre code {
     color: #222222;
     background-color: #E0E0E0;
     line-height: 1.5;
+    font-family: Consolas, Monaco, Monospace, Courier;
+    white-space: pre;
 }
 
 code.mathjax-code {

+ 6 - 3
src/resources/vnote.ini

@@ -220,20 +220,23 @@ styles_to_inline_when_copied=all$border:color:display:font-family:font-size:font
 ; Define targets the copied content will be pasted into
 ; target_name$action1:action2:action3,targeet_name2$action2:action3
 ; Available actions:
-; s - add surrounding tags <html><body>
+; s - add surrounding tags <html><body> </body></html>
+; e - add surrounding tags <html><body><!--StartFragment--> <!--EndFragment--></body></html>
 ; b(tag1|tag2) - remove background color of all tags except tag1 and tag2
 ; c(tag1|tag2) - translate colors using palette defined mapping except tag1 and tag2
 ; i - fix local relative <img src>
 ; m(tag1|tag2) - remove margin/margin-left/margin-right/padding/padding-left/padding-right of all tags except tag1 and tag2
 ; r - raw html with all styles removed
 ; a - transform <mark> to <span>
-; x(tag1|tag2) - remove styles specified in [styles_to_inline_when_copied] of all tags except tag1 and tag2
+; x(tag1|tag2) - remove styles specified in [styles_to_remove_when_copied] of all tags except tag1 and tag2
 ; p - replace the background color of <pre> with that of its child <code>
 ; n - replace the \n in <pre> with <br>
 ; g - replace local relative/absolute <img> tag with a warning label
 ; d - add <span> to <code> which is not inside <pre>
 ; f - replace &quot; with ' in font-family style
-copy_targets="Without Background"$s:b(mark):c:i:x,OneNote$s:b(mark):c:i:m:a:x,"Microsoft Word"$s:p:b(mark|pre):c(pre):i:m:a:x,"WeChat Public Account"$s:p:b(mark|pre):c(pre):g:m:x:n:f,"Web Editor"$s:p:b(mark|pre):c(pre):m:x:n,"Raw HTML"$r:x
+; h - replace <hi> tag with <span>
+; j - fix XHTML tag like <img> and <br>
+copy_targets="Without Background"$s:b(mark):c:i:x,Evernote$e:p:b(mark|pre):c(pre):g:m:a:x:n:j,OneNote$e:b(mark):c:i:m:a:x,"Microsoft Word"$s:p:b(mark|pre):c(pre):i:m:a:x,"WeChat Public Account"$s:p:b(mark|pre):c(pre):g:m:x:n:f,"Web Editor"$s:p:b(mark|pre):c(pre):m:x:n,"Raw HTML"$r:x
 
 [shortcuts]
 ; Define shortcuts here, with each item in the form "operation=keysequence".

+ 124 - 13
src/utils/vwebutils.cpp

@@ -1,6 +1,5 @@
 #include "vwebutils.h"
 
-#include <QRegExp>
 #include <QFileInfo>
 #include <QObject>
 #include <QDebug>
@@ -26,6 +25,8 @@ void VWebUtils::init()
 
     m_styleTagReg = QRegExp("<([^>\\s]+)([^>]*\\s)style=\"([^\">]+)\"([^>]*)>");
 
+    m_imgTagReg = QRegExp("<img src=\"([^\"]+)\"[^>]*>");
+
     initCopyTargets(g_config->getCopyTargets());
 }
 
@@ -115,11 +116,10 @@ bool VWebUtils::fixImageSrc(const QUrl &p_baseUrl, QString &p_html)
         pos = idx + reg.matchedLength();
         if (!fixedStr.isEmpty() && urlStr != fixedStr) {
             qDebug() << "fix img url" << urlStr << fixedStr;
-            // Insert one more space to avoid fix the url twice.
             pos = pos + fixedStr.size() + 1 - urlStr.size();
             p_html.replace(idx,
                            reg.matchedLength(),
-                           QString("<img  src=\"%1\"").arg(fixedStr));
+                           QString("<img src=\"%1\"").arg(fixedStr));
             changed = true;
         }
     }
@@ -151,6 +151,11 @@ bool VWebUtils::alterHtmlAsTarget(const QUrl &p_baseUrl, QString &p_html, const
         }
     }
 
+    if (altered) {
+        qDebug() << "==html==";
+        qDebug() << p_html;
+    }
+
     return altered;
 }
 
@@ -181,6 +186,14 @@ bool VWebUtils::alterHtmlByTargetAction(const QUrl &p_baseUrl, QString &p_html,
 
         break;
 
+    case 'e':
+        if (!p_html.startsWith("<html>")) {
+            p_html = "<html><body><!--StartFragment-->" + p_html + "<!--EndFragment--></body></html>";
+            altered = true;
+        }
+
+        break;
+
     case 'b':
         altered = removeBackgroundColor(p_html, p_action.m_args);
         break;
@@ -229,6 +242,14 @@ bool VWebUtils::alterHtmlByTargetAction(const QUrl &p_baseUrl, QString &p_html,
         altered = replaceQuoteInFontFamily(p_html);
         break;
 
+    case 'h':
+        altered = replaceHeadingWithSpan(p_html);
+        break;
+
+    case 'j':
+        altered = fixXHtmlTags(p_html);
+        break;
+
     default:
         break;
     }
@@ -626,6 +647,7 @@ bool VWebUtils::replaceNewLineWithBR(QString &p_html)
 
     bool altered = false;
     int pos = 0;
+    const QString brTag("<br/>");
 
     while (pos < p_html.size()) {
         int tagIdx = p_html.indexOf(m_tagReg, pos);
@@ -648,10 +670,9 @@ bool VWebUtils::replaceNewLineWithBR(QString &p_html)
                 break;
             }
 
-            QString br("<br>");
-            p_html.replace(idx, 1, br);
-            pos = idx + br.size() - 1;
-            preEnd = preEnd + br.size() - 1;
+            p_html.replace(idx, 1, brTag);
+            pos = idx + brTag.size() - 1;
+            preEnd = preEnd + brTag.size() - 1;
 
             altered = true;
         }
@@ -666,28 +687,28 @@ bool VWebUtils::replaceLocalImgWithWarningLabel(QString &p_html)
 {
     bool altered = false;
 
-    QRegExp reg("<img src=\"([^\"]+)\"[^>]*>");
-
     QString label = QString("<span style=\"font-weight: bold; color: #FFFFFF; background-color: #EE0000;\">%1</span>")
                            .arg(QObject::tr("Insert_Image_HERE"));
 
     int pos = 0;
     while (pos < p_html.size()) {
-        int idx = p_html.indexOf(reg, pos);
+        int idx = p_html.indexOf(m_imgTagReg, pos);
         if (idx == -1) {
             break;
         }
 
-        QString urlStr = reg.cap(1);
+        QString urlStr = m_imgTagReg.cap(1);
         QUrl imgUrl(urlStr);
 
         if (imgUrl.scheme() == "https" || imgUrl.scheme() == "http") {
-            pos = idx + reg.matchedLength();
+            pos = idx + m_imgTagReg.matchedLength();
             continue;
         }
 
-        p_html.replace(idx, reg.matchedLength(), label);
+        p_html.replace(idx, m_imgTagReg.matchedLength(), label);
         pos = idx + label.size();
+
+        altered = true;
     }
 
     return altered;
@@ -785,3 +806,93 @@ bool VWebUtils::replaceQuoteInFontFamily(QString &p_html)
 
     return altered;
 }
+
+static bool isHeadingTag(const QString &p_tagName)
+{
+    QString tag = p_tagName.toLower();
+    if (!tag.startsWith('h') || tag.size() != 2) {
+        return false;
+    }
+
+    return tag == "h1"
+           || tag == "h2"
+           || tag == "h3"
+           || tag == "h4"
+           || tag == "h5"
+           || tag == "h6";
+}
+
+bool VWebUtils::replaceHeadingWithSpan(QString &p_html)
+{
+    bool altered = false;
+    int pos = 0;
+    QString spanTag("span");
+
+    while (pos < p_html.size()) {
+        int tagIdx = p_html.indexOf(m_tagReg, pos);
+        if (tagIdx == -1) {
+            break;
+        }
+
+        QString tagName = m_tagReg.cap(1);
+        if (!isHeadingTag(tagName)) {
+            pos = tagIdx + m_tagReg.matchedLength();
+            continue;
+        }
+
+        p_html.replace(tagIdx + 1, 2, spanTag);
+
+        pos = tagIdx + m_tagReg.matchedLength() + spanTag.size() - 2;
+
+        pos = skipToTagEnd(p_html, pos, tagName);
+
+        Q_ASSERT(pos != -1);
+
+        Q_ASSERT(p_html.mid(pos - 3, 2) == tagName);
+
+        p_html.replace(pos - 3, 2, spanTag);
+
+        pos = pos + spanTag.size() - 2;
+
+        altered = true;
+    }
+
+    return altered;
+}
+
+bool VWebUtils::fixXHtmlTags(QString &p_html)
+{
+    bool altered = false;
+
+    // <img>.
+    int pos = 0;
+    const QString legalTag("/>");
+    while (pos < p_html.size()) {
+        int idx = p_html.indexOf(m_imgTagReg, pos);
+        if (idx == -1) {
+            break;
+        }
+
+        pos = idx + m_imgTagReg.matchedLength();
+
+        Q_ASSERT(p_html[pos - 1] == '>');
+
+        if (p_html.mid(pos - 2, 2) == legalTag) {
+            continue;
+        }
+
+        p_html.replace(pos - 1, 1, legalTag);
+        pos = pos + legalTag.size() - 1;
+
+        altered = true;
+    }
+
+    // <br>.
+    int size = p_html.size();
+    p_html.replace("<br>", "<br/>");
+    if (!altered && size != p_html.size()) {
+        altered = true;
+    }
+
+    return altered;
+}

+ 11 - 0
src/utils/vwebutils.h

@@ -103,6 +103,12 @@ private:
     // Replace &quot; in font-family with '.
     bool replaceQuoteInFontFamily(QString &p_html);
 
+    // Replace headings with span.
+    bool replaceHeadingWithSpan(QString &p_html);
+
+    // Fix tags as XHTML like <img> and <br>.
+    bool fixXHtmlTags(QString &p_html);
+
     QVector<CopyTarget> m_copyTargets;
 
     // Custom styles to remove when copied.
@@ -124,5 +130,10 @@ private:
     // 3. Text inside 'style=""';
     // 4. Text after 'style=""' and before '>';
     QRegExp m_styleTagReg;
+
+    // <Img> tag.
+    // Captured texts:
+    // 1. Src string without ";
+    QRegExp m_imgTagReg;
 };
 #endif // VWEBUTILS_H