HTML Preview and Exporter: added support for dark color schemes.

Sat, 11 Apr 2020 19:08:37 +0200

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Sat, 11 Apr 2020 19:08:37 +0200
changeset 7524
282680dae446
parent 7523
6e26ec343c78
child 7525
6d1f954947bc

HTML Preview and Exporter: added support for dark color schemes.

eric6/QScintilla/Exporters/ExporterHTML.py file | annotate | diff | comparison | revisions
eric6/UI/Previewers/MarkdownExtensions.py file | annotate | diff | comparison | revisions
eric6/UI/Previewers/PreviewerHTML.py file | annotate | diff | comparison | revisions
eric6/UI/Previewers/PreviewerHTMLStyles.py file | annotate | diff | comparison | revisions
--- a/eric6/QScintilla/Exporters/ExporterHTML.py	Sat Apr 11 14:50:48 2020 +0200
+++ b/eric6/QScintilla/Exporters/ExporterHTML.py	Sat Apr 11 19:08:37 2020 +0200
@@ -17,7 +17,7 @@
 
 from PyQt5.QtCore import Qt
 from PyQt5.QtGui import QCursor, QFontInfo
-from PyQt5.QtWidgets import QApplication
+from PyQt5.QtWidgets import QApplication, QInputDialog
 from PyQt5.Qsci import QsciScintilla
 
 from E5Gui import E5MessageBox
@@ -408,7 +408,25 @@
                 self.editor.getLanguage().lower() == "markdown"
             ):
                 # export markdown to HTML
-                html = self.__generateFromMarkdown()
+                colorSchemes = [
+                    self.tr("Light Background Color"),
+                    self.tr("Dark Background Color"),
+                ]
+                QApplication.restoreOverrideCursor()
+                colorScheme, ok = QInputDialog.getItem(
+                    None,
+                    self.tr("Markdown Export"),
+                    self.tr("Select color scheme:"),
+                    colorSchemes,
+                    0, False)
+                if ok:
+                    colorSchemeIndex = colorSchemes.index(colorScheme)
+                else:
+                    # light background as default
+                    colorSchemeIndex = 0
+                QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
+                QApplication.processEvents()
+                html = self.__generateFromMarkdown(colorSchemeIndex == 1)
             elif (
                 extension in Preferences.getEditor(
                     "PreviewRestFileNameExtensions") or
@@ -503,10 +521,13 @@
         sys.stderr = origStderr
         return html
     
-    def __generateFromMarkdown(self):
+    def __generateFromMarkdown(self, useDarkScheme):
         """
         Private method to convert Markdown text into HTML.
         
+        @param useDarkScheme flag indicating to export using a dark color
+            scheme
+        @type bool
         @return processed HTML
         @rtype str
         """
@@ -534,7 +555,7 @@
         
         mermaidNeeded = False
         if Preferences.getEditor("PreviewMarkdownMermaid"):
-            if MarkdownExtensions.MermaidRegex.search(text):
+            if MarkdownExtensions.MermaidRegexFullText.search(text):
                 extensions.append(MarkdownExtensions.MermaidExtension())
                 mermaidNeeded = True
         
@@ -592,12 +613,37 @@
                 " src='https://unpkg.com/mermaid@8/dist/mermaid.min.js'>\n"
                 "</script>\n"
             )
+            if useDarkScheme:
+                mermaid_initialize = (
+                    "<script>mermaid.initialize({"
+                    "theme: 'dark', "
+                    "startOnLoad:true"
+                    "});</script>"
+                )
+            else:
+                mermaid_initialize = (
+                    "<script>mermaid.initialize({"
+                    "theme: 'default', "
+                    "startOnLoad:true"
+                    "});</script>"
+                )
         else:
             mermaid = ""
+            mermaid_initialize = ""
         
         htmlFormat = Preferences.getEditor("PreviewMarkdownHTMLFormat").lower()
         body = markdown.markdown(text, extensions=extensions,
                                  output_format=htmlFormat)
+        if useDarkScheme:
+            style = (
+                PreviewerHTMLStyles.css_markdown_dark +
+                PreviewerHTMLStyles.css_pygments_dark
+            )
+        else:
+            style = (
+                PreviewerHTMLStyles.css_markdown_light +
+                PreviewerHTMLStyles.css_pygments_light
+            )
         
         if htmlFormat == "xhtml1":
             head = (
@@ -632,12 +678,8 @@
             '''</style>\n'''
             '''</head>\n'''
             '''<body>\n'''
-        ).format(
-            mathjax, mermaid,
-            PreviewerHTMLStyles.css_markdown +
-            PreviewerHTMLStyles.css_pygments
-        )
+        ).format(mathjax, mermaid, style)
         
         foot = '''\n</body>\n</html>\n'''
         
-        return head + body + foot
+        return head + body + mermaid_initialize + foot
--- a/eric6/UI/Previewers/MarkdownExtensions.py	Sat Apr 11 14:50:48 2020 +0200
+++ b/eric6/UI/Previewers/MarkdownExtensions.py	Sat Apr 11 19:08:37 2020 +0200
@@ -86,9 +86,6 @@
 
         if is_mermaid:
             new_lines.append('')
-            new_lines.append(
-                '<script>mermaid.initialize({startOnLoad:true});</script>'
-            )
 
         return new_lines
 
--- a/eric6/UI/Previewers/PreviewerHTML.py	Sat Apr 11 14:50:48 2020 +0200
+++ b/eric6/UI/Previewers/PreviewerHTML.py	Sat Apr 11 19:08:37 2020 +0200
@@ -743,12 +743,37 @@
                 " src='https://unpkg.com/mermaid@8/dist/mermaid.min.js'>\n"
                 "</script>\n"
             )
+            if e5App().usesDarkPalette():
+                mermaid_initialize = (
+                    "<script>mermaid.initialize({"
+                    "theme: 'dark', "
+                    "startOnLoad:true"
+                    "});</script>"
+                )
+            else:
+                mermaid_initialize = (
+                    "<script>mermaid.initialize({"
+                    "theme: 'default', "
+                    "startOnLoad:true"
+                    "});</script>"
+                )
         else:
             mermaid = ""
+            mermaid_initialize = ""
         
         htmlFormat = Preferences.getEditor("PreviewMarkdownHTMLFormat").lower()
         body = markdown.markdown(text, extensions=extensions,
                                  output_format=htmlFormat.lower())
+        if e5App().usesDarkPalette():
+            style = (
+                PreviewerHTMLStyles.css_markdown_dark +
+                PreviewerHTMLStyles.css_pygments_dark
+            )
+        else:
+            style = (
+                PreviewerHTMLStyles.css_markdown_light +
+                PreviewerHTMLStyles.css_pygments_light
+            )
         
         if htmlFormat == "xhtml1":
             head = (
@@ -777,12 +802,8 @@
             '''</style>\n'''
             '''</head>\n'''
             '''<body>\n'''
-        ).format(
-            mathjax, mermaid,
-            PreviewerHTMLStyles.css_markdown +
-            PreviewerHTMLStyles.css_pygments
-        )
+        ).format(mathjax, mermaid, style)
         
         foot = '''\n</body>\n</html>\n'''
         
-        return head + body + foot
+        return head + body + mermaid_initialize + foot
--- a/eric6/UI/Previewers/PreviewerHTMLStyles.py	Sat Apr 11 14:50:48 2020 +0200
+++ b/eric6/UI/Previewers/PreviewerHTMLStyles.py	Sat Apr 11 19:08:37 2020 +0200
@@ -7,33 +7,18 @@
 Module implementing CSS styles for the Markdown preview.
 """
 
-
-css_markdown = """
-@media (prefers-color-scheme: light) {
-    :root {
-        --font-color: #000;
-        --background-color: #fff;
-        --alt-backgroundcolor: #f8f8f8;
-        --frame-color: #333;
-    }
-}
+###########################################################################
+## Styles for light window schemes below
+###########################################################################
 
-@media (prefers-color-scheme: dark) {
-    :root {
-        --font-color: #fff;
-        --background-color: #000;
-        --alt-backgroundcolor: #707070;
-        --frame-color: #ccc;
-    }
-}
-
+css_markdown_light = """
 html {
-    background-color: var(--background-color, #fff);
+    background-color: #ffffff;
 }
 
 body {
-    background-color: var(--background-color, #fff);
-    color: var(--font-color, #000);
+    background-color: #ffffff;
+    color: #000000;
     font-family: sans-serif;
     font-size:12px;
     line-height:1.7;
@@ -85,7 +70,7 @@
 h1 .octicon-link, h2 .octicon-link, h3 .octicon-link, h4 .octicon-link,
 h5 .octicon-link, h6 .octicon-link {
     display:none;
-    color: var(--font-color, #000);
+    color: #000000;
 }
 
 h1:hover a.anchor, h2:hover a.anchor, h3:hover a.anchor, h4:hover a.anchor,
@@ -211,11 +196,11 @@
 
 table tr {
     border-top:1px solid #ccc;
-    background-color: var(--background-color, #fff);
+    background-color: #ffffff;
 }
 
 table tr:nth-child(2n) {
-    background-color:var(--alt-background-color, #f8f8f8);
+    background-color:#f8f8f8;
 }
 
 img {
@@ -246,7 +231,7 @@
 
 span.frame span span {
     clear:both;
-    color:var(--frame-color, #333);
+    color:#333333;
     display:block;
     padding:5px 0 0
 }
@@ -315,7 +300,7 @@
 code, tt {
     margin:0;
     border:1px solid #ddd;
-    background-color:var(--alt-background-color, #f8f8f8);
+    background-color:#f8f8f8;
     border-radius:3px;
     max-width:100%;
     display:inline-block;
@@ -342,7 +327,7 @@
 }
 
 .highlight pre, pre {
-    background-color:var(--alt-background-color, #f8f8f8);
+    background-color:#f8f8f8;
     border:1px solid #ddd;
     font-size:12px;
     line-height:16px;
@@ -386,7 +371,7 @@
 """
 
 
-css_pygments = """
+css_pygments_light = """
 pre .hll { background-color: #ffffcc }
 
 /* Comment */
@@ -570,3 +555,556 @@
 pre .il { color: #009999 }
 
 """
+
+###########################################################################
+## Styles for dark window schemes below
+###########################################################################
+
+css_markdown_dark = """
+html {
+    background-color: #262626;
+}
+
+body {
+    background-color: #262626);
+    color: #ffffff;
+    font-family: sans-serif;
+    font-size:12px;
+    line-height:1.7;
+    word-wrap:break-word
+}
+
+body>*:first-child {
+    margin-top:0 !important
+}
+
+body>*:last-child {
+    margin-bottom:0 !important
+}
+
+a {
+    color:#8ebfff
+}
+
+a.absent {
+    color:#dd0000
+}
+
+a.anchor {
+    display:block;
+    padding-right:6px;
+    padding-left:30px;
+    margin-left:-30px;
+    cursor:pointer;
+    position:absolute;
+    top:0;
+    left:0;
+    bottom:0
+}
+
+a.anchor:focus {
+    outline:none
+}
+
+tt, code, pre {
+    font-family: Consolas, "Liberation Mono", Courier, monospace;
+    font-size: 12px;
+}
+
+h1, h2, h3, h4, h5, h6 {
+    margin:1em 0 6px;
+    padding:0;
+    font-weight:bold;
+    line-height:1.7;
+    cursor:text;
+    position:relative
+}
+
+h1 .octicon-link, h2 .octicon-link, h3 .octicon-link, h4 .octicon-link,
+h5 .octicon-link, h6 .octicon-link {
+    display:none;
+    color: #ffffff;
+}
+
+h1:hover a.anchor, h2:hover a.anchor, h3:hover a.anchor, h4:hover a.anchor,
+h5:hover a.anchor, h6:hover a.anchor {
+    text-decoration:none;
+    line-height:1;
+    padding-left:8px;
+    margin-left:-30px;
+    top:15%
+}
+
+h1:hover a.anchor .octicon-link, h2:hover a.anchor .octicon-link,
+h3:hover a.anchor .octicon-link, h4:hover a.anchor .octicon-link,
+h5:hover a.anchor .octicon-link, h6:hover a.anchor .octicon-link {
+    display:inline-block
+}
+
+h1 tt, h1 code, h2 tt, h2 code, h3 tt, h3 code, h4 tt, h4 code,
+h5 tt, h5 code, h6 tt, h6 code {
+    font-size:inherit
+}
+
+h1 {
+    font-size:2em;
+    border-bottom:1px solid #ddd
+}
+
+h2 {
+    font-size:1.6em;
+    border-bottom:1px solid #eee
+}
+
+h3 {
+    font-size:1.4em
+}
+
+h4 {
+    font-size:1.2em
+}
+
+h5 {
+    font-size:1em
+}
+
+h6 {
+    color:#aaaaaa;
+    font-size:1em
+}
+
+p, blockquote, ul, ol, dl, table, pre {
+    margin:8px 0
+}
+
+hr {
+    background: rgba(120, 120, 120, 1);
+    border: 0 none;
+    color: #ccc;
+    height: 2px;
+    padding: 0;
+    margin: 8px 0;
+}
+
+ul, ol {
+    padding-left:15px
+}
+
+ul.no-list, ul.task-list, ol.no-list, ol.task-list {
+    list-style-type:none;
+}
+
+ul ul, ul ol, ol ol, ol ul {
+    margin-top:0;
+    margin-bottom:0
+}
+
+
+dl {
+    padding:0
+}
+
+dl dt {
+    font-size:14px;
+    font-weight:bold;
+    font-style:italic;
+    padding:0;
+    margin-top:8px
+}
+
+dl dd {
+    margin-bottom:15px;
+    padding:0 8px
+}
+
+blockquote {
+    border-left:4px solid #DDD;
+    padding:0 8px;
+    color:#aaaaaa
+}
+
+blockquote>:first-child {
+    margin-top:0px
+}
+
+blockquote>:last-child {
+    margin-bottom:0px
+}
+
+table {
+    border-collapse: collapse;
+    border-spacing: 0;
+    overflow:auto;
+    display:block
+}
+
+table th {
+    font-weight:bold
+}
+
+table th, table td {
+    border:1px solid #ddd;
+    padding:3px 3px
+}
+
+table tr {
+    border-top:1px solid #cccccc;
+    background-color: #262626;
+}
+
+table tr:nth-child(2n) {
+    background-color:#404040;
+}
+
+img {
+    max-width:100%;
+    -moz-box-sizing:border-box;
+    box-sizing:border-box
+}
+
+span.frame {
+    display:block;
+    overflow:hidden
+}
+
+span.frame>span {
+    border:1px solid #464646;
+    display:block;
+    float:left;
+    overflow:hidden;
+    margin:6px 0 0;
+    padding:7px;
+    width:auto
+}
+
+span.frame span img {
+    display:block;
+    float:left
+}
+
+span.frame span span {
+    clear:both;
+    color:#565656;
+    display:block;
+    padding:5px 0 0
+}
+
+span.align-center {
+    display:block;
+    overflow:hidden;
+    clear:both
+}
+
+span.align-center>span {
+    display:block;
+    overflow:hidden;
+    margin:6px auto 0;
+    text-align:center
+}
+
+span.align-center span img {
+    margin:0 auto;
+    text-align:center
+}
+
+span.align-right {
+    display:block;
+    overflow:hidden;
+    clear:both
+}
+
+span.align-right>span {
+    display:block;
+    overflow:hidden;
+    margin:6px 0 0;
+    text-align:right
+}
+
+span.align-right span img {
+    margin:0;
+    text-align:right
+}
+
+span.float-left {
+    display:block;
+    margin-right:6px;
+    overflow:hidden;
+    float:left
+}
+
+span.float-left span {
+    margin:6px 0 0
+}
+
+span.float-right {
+    display:block;
+    margin-left:6px;
+    overflow:hidden;
+    float:right
+}
+
+span.float-right>span {
+    display:block;
+    overflow:hidden;
+    margin:6px auto 0;
+    text-align:right
+}
+
+code, tt {
+    margin:0;
+    border:1px solid #ddd;
+    background-color:#404040;
+    border-radius:3px;
+    max-width:100%;
+    display:inline-block;
+    overflow:auto;
+    vertical-align:middle;
+    line-height:1.1;
+    padding:0
+}
+
+code:before, code:after, tt:before, tt:after {
+    content:"\00a0"
+}
+
+code {
+    white-space:nowrap
+}
+
+pre>code {
+    margin:0;
+    padding:0;
+    white-space:pre;
+    border:none;
+    background:transparent
+}
+
+.highlight pre, pre {
+    background-color:#404040;
+    border:1px solid #ddd;
+    font-size:12px;
+    line-height:16px;
+    overflow:auto;
+    padding:6px 6px;
+    border-radius:3px
+}
+
+pre {
+    word-wrap:normal
+}
+
+pre code, pre tt {
+    margin:0;
+    padding:0;
+    background-color:transparent;
+    border:none;
+    word-wrap:normal;
+    max-width:initial;
+    display:inline;
+    overflow:initial;
+    line-height:inherit
+}
+
+pre code:before, pre code:after, pre tt:before, pre tt:after {
+    content:normal
+}
+
+kbd {
+    border:1px solid gray;
+    font-size:1.2em;
+    box-shadow:1px 0 1px 0 #eee, 0 1px 0 1px #ccc, 0 2px 0 2px #444;
+    -webkit-border-radius:2px;
+    -moz-border-radius:2px;
+    border-radius:2px;
+    margin:2px 3px;
+    padding:1px 5px;
+    color: #000;
+    background-color: #fff
+}
+"""
+
+
+css_pygments_dark = """
+pre .hll { background-color: #464646 }
+
+/* Comment */
+pre .c { color: #74cc66; font-style: italic }
+
+/* Error */
+pre .err { color: #a61717; background-color: #e3d2d2 }
+
+/* Keyword */
+pre .k { font-weight: bold }
+
+/* Operator */
+pre .o { font-weight: bold }
+
+/* Comment.Multiline */
+pre .cm { color: #74cc66; font-style: italic }
+
+/* Comment.Preproc */
+pre .cp { color: #74cc66; font-weight: bold; font-style: italic }
+
+/* Comment.Single */
+pre .c1 { color: #74cc66; font-style: italic }
+
+/* Comment.Special */
+pre .cs { color: #74cc66; font-weight: bold; font-style: italic }
+
+/* Generic.Deleted */
+pre .gd { color: #ffffff; background-color: #843d3d }
+
+/* Generic.Emph */
+pre .ge { font-style: italic }
+
+/* Generic.Error */
+pre .gr { color: #ff0000 }
+
+/* Generic.Heading */
+pre .gh { color: #dadada }
+
+/* Generic.Inserted */
+pre .gi { color: #ffffff; background-color: #4e8750 }
+
+/* Generic.Output */
+pre .go { color: #bbbbbb }
+
+/* Generic.Prompt */
+pre .gp { color: #999999 }
+
+/* Generic.Strong */
+pre .gs { font-weight: bold }
+
+/* Generic.Subheading */
+pre .gu { color: #dd60dd }
+
+/* Generic.Traceback */
+pre .gt { color: #ff0000 }
+
+/* Keyword.Constant */
+pre .kc { font-weight: bold }
+
+/* Keyword.Declaration */
+pre .kd { font-weight: bold }
+
+/* Keyword.Namespace */
+pre .kn { font-weight: bold }
+
+/* Keyword.Pseudo */
+pre .kp { font-weight: bold }
+
+/* Keyword.Reserved */
+pre .kr { font-weight: bold }
+
+/* Keyword.Type */
+pre .kt { color: #b3efad; font-weight: bold }
+
+/* Literal.Number */
+pre .m { color: #00c8c8 }
+
+/* Literal.String */
+pre .s { color: #f46b6b }
+
+/* Name.Attribute */
+pre .na { color: #b6d13b }
+
+/* Name.Builtin */
+pre .nb { color: #b3efad }
+
+/* Name.Class */
+pre .nc { color: #00aaff; font-weight: bold }
+
+/* Name.Constant */
+pre .no { color: #dd3131 }
+
+/* Name.Decorator */
+pre .nd { color: #e19bff; font-weight: bold }
+
+/* Name.Entity */
+pre .ni { color: #dedede }
+
+/* Name.Exception */
+pre .ne { color: #e75555; font-weight: bold }
+
+/* Name.Function */
+pre .nf { color: #00aaff; font-weight: bold }
+
+/* Name.Label */
+pre .nl { color: #e1e100; font-weight: bold }
+
+/* Name.Namespace */
+pre .nn { color: #00aaff }
+
+/* Name.Tag */
+pre .nt { color: #b3efad }
+
+/* Name.Variable */
+pre .nv { color: #00aaff }
+
+/* Operator.Word */
+pre .ow { font-weight: bold }
+
+/* Text.Whitespace */
+pre .w { color: #bbbbbb }
+
+/* Literal.Number.Float */
+pre .mf { color: #00aaff }
+
+/* Literal.Number.Hex */
+pre .mh { color: #00aaff }
+
+/* Literal.Number.Integer */
+pre .mi { color: #00aaff }
+
+/* Literal.Number.Oct */
+pre .mo { color: #00aaff }
+
+/* Literal.String.Backtick */
+pre .sb { color: #f46b6b }
+
+/* Literal.String.Char */
+pre .sc { color: #f46b6b }
+
+/* Literal.String.Doc */
+pre .sd { color: #f46b6b }
+
+/* Literal.String.Double */
+pre .s2 { color: #f46b6b }
+
+/* Literal.String.Escape */
+pre .se { color: #f46b6b }
+
+/* Literal.String.Heredoc */
+pre .sh { color: #f46b6b }
+
+/* Literal.String.Interpol */
+pre .si { color: #f46b6b }
+
+/* Literal.String.Other */
+pre .sx { color: #f46b6b }
+
+/* Literal.String.Regex */
+pre .sr { color: #bb6688 }
+
+/* Literal.String.Single */
+pre .s1 { color: #f46b6b }
+
+/* Literal.String.Symbol */
+pre .ss { color: #00aaff }
+
+/* Name.Builtin.Pseudo */
+pre .bp { color: #b3efad }
+
+/* Name.Variable.Class */
+pre .vc { color: #00aaff }
+
+/* Name.Variable.Global */
+pre .vg { color: #00aaff }
+
+/* Name.Variable.Instance */
+pre .vi { color: #00aaff }
+
+/* Literal.Number.Integer.Long */
+pre .il { color: #00c8c8 }
+
+"""

eric ide

mercurial