eric6/UI/Previewers/PreviewerHTML.py

changeset 7301
6df711503ec0
parent 7264
bedbe458d792
child 7304
b072a364dd8d
diff -r 7622b6330e62 -r 6df711503ec0 eric6/UI/Previewers/PreviewerHTML.py
--- a/eric6/UI/Previewers/PreviewerHTML.py	Sun Oct 20 11:19:38 2019 +0200
+++ b/eric6/UI/Previewers/PreviewerHTML.py	Tue Oct 22 19:56:56 2019 +0200
@@ -211,6 +211,8 @@
                     self.ssiCheckBox.isChecked(), rootPath,
                     Preferences.getEditor("PreviewRestUseSphinx"),
                     Preferences.getEditor("PreviewMarkdownNLtoBR"),
+                    Preferences.getEditor(
+                        "PreviewMarkdownUsePyMdownExtensions"),
                     Preferences.getEditor("PreviewMarkdownHTMLFormat"),
                     Preferences.getEditor("PreviewRestDocutilsHTMLFormat"))
 
@@ -338,25 +340,34 @@
         self.__lock = threading.Lock()
     
     def process(self, filePath, language, text, ssiEnabled, rootPath,
-                useSphinx, convertNewLineToBreak, markdownHtmlFormat,
-                restDocutilsHtmlFormat):
+                useSphinx, convertNewLineToBreak, usePyMdownExtensions,
+                markdownHtmlFormat, restDocutilsHtmlFormat):
         """
         Public method to convert the given text to HTML.
         
-        @param filePath file path of the text (string)
-        @param language language of the text (string)
-        @param text text to be processed (string)
+        @param filePath file path of the text
+        @type str
+        @param language language of the text
+        @type str
+        @param text text to be processed
+        @type str
         @param ssiEnabled flag indicating to do some (limited) SSI processing
-            (boolean)
-        @param rootPath root path to be used for SSI processing (str)
+        @type bool
+        @param rootPath root path to be used for SSI processing
+        @type str
         @param useSphinx flag indicating to use Sphinx to generate the
-            ReST preview (boolean)
+            ReST preview
+        @type bool
         @param convertNewLineToBreak flag indicating to convert new lines
-            to HTML break (Markdown only) (boolean)
+            to HTML break (Markdown only)
+        @type bool
+        @param usePyMdownExtensions flag indicating to enable the PyMdown
+            extensions, if they are available
+        @type bool
         @param markdownHtmlFormat HTML format to be generated by markdown
-            (string)
+        @type str
         @param restDocutilsHtmlFormat HTML format to be generated by docutils
-            (string)
+        @type str
         """
         with self.__lock:
             self.__filePath = filePath
@@ -367,6 +378,7 @@
             self.__haveData = True
             self.__useSphinx = useSphinx
             self.__convertNewLineToBreak = convertNewLineToBreak
+            self.__usePyMdownExtensions = usePyMdownExtensions
             self.__markdownHtmlFormat = markdownHtmlFormat
             self.__restDocutilsHtmlFormat = restDocutilsHtmlFormat
             if not self.isRunning():
@@ -386,6 +398,7 @@
                 rootPath = self.__rootPath
                 useSphinx = self.__useSphinx
                 convertNewLineToBreak = self.__convertNewLineToBreak
+                usePyMdownExtensions = self.__usePyMdownExtensions
                 markdownHtmlFormat = self.__markdownHtmlFormat
                 restDocutilsHtmlFormat = self.__restDocutilsHtmlFormat
             
@@ -393,7 +406,8 @@
 
             html = self.__getHtml(language, text, ssiEnabled, filePath,
                                   rootPath, useSphinx, convertNewLineToBreak,
-                                  markdownHtmlFormat, restDocutilsHtmlFormat)
+                                  usePyMdownExtensions, markdownHtmlFormat,
+                                  restDocutilsHtmlFormat)
             
             with self.__lock:
                 if not self.__haveData:
@@ -402,27 +416,37 @@
                 # else - next iteration
     
     def __getHtml(self, language, text, ssiEnabled, filePath, rootPath,
-                  useSphinx, convertNewLineToBreak, markdownHtmlFormat,
-                  restDocutilsHtmlFormat):
+                  useSphinx, convertNewLineToBreak, usePyMdownExtensions,
+                  markdownHtmlFormat, restDocutilsHtmlFormat):
         """
         Private method to process the given text depending upon the given
         language.
         
-        @param language language of the text (string)
-        @param text to be processed (string)
+        @param language language of the text
+        @type str
+        @param text to be processed
+        @type str
         @param ssiEnabled flag indicating to do some (limited) SSI processing
-            (boolean)
-        @param filePath file path of the text (string)
-        @param rootPath root path to be used for SSI processing (str)
+        @type bool
+        @param filePath file path of the text
+        @type str
+        @param rootPath root path to be used for SSI processing
+        @type str
         @param useSphinx flag indicating to use Sphinx to generate the
-            ReST preview (boolean)
+            ReST preview
+        @type bool
         @param convertNewLineToBreak flag indicating to convert new lines
-            to HTML break (Markdown only) (boolean)
+            to HTML break (Markdown only)
+        @type bool
+        @param usePyMdownExtensions flag indicating to enable the PyMdown
+            extensions, if they are available
+        @type bool
         @param markdownHtmlFormat HTML format to be generated by markdown
-            (string)
+        @type str
         @param restDocutilsHtmlFormat HTML format to be generated by docutils
-            (string)
-        @return processed HTML text (string)
+        @type str
+        @return processed HTML text
+        @rtype str
         """
         if language == "HTML":
             if ssiEnabled:
@@ -431,8 +455,9 @@
                 html = text
             return self.__processRootPath(html, rootPath)
         elif language == "Markdown":
-            return self.__convertMarkdown(text, convertNewLineToBreak,
-                                          markdownHtmlFormat)
+            return self.__convertMarkdown(
+                text, convertNewLineToBreak, usePyMdownExtensions,
+                markdownHtmlFormat)
         elif language == "ReST":
             return self.__convertReST(text, useSphinx, restDocutilsHtmlFormat)
         else:
@@ -625,15 +650,23 @@
         sys.stderr = origStderr
         return html
     
-    def __convertMarkdown(self, text, convertNewLineToBreak, htmlFormat):
+    def __convertMarkdown(self, text, convertNewLineToBreak,
+                          usePyMdownExtensions, htmlFormat):
         """
         Private method to convert Markdown text into HTML.
         
-        @param text text to be processed (string)
+        @param text text to be processed
+        @type str
         @param convertNewLineToBreak flag indicating to convert new lines
-            to HTML break (Markdown only) (boolean)
-        @param htmlFormat HTML format to be generated by markdown (string)
-        @return processed HTML (string)
+            to HTML break (Markdown only)
+        @type bool
+        @param usePyMdownExtensions flag indicating to enable the PyMdown
+            extensions, if they are available
+        @type bool
+        @param htmlFormat HTML format to be generated by markdown
+        @type str
+        @return processed HTML
+        @rtype str
         """
         try:
             import markdown     # __IGNORE_EXCEPTION__
@@ -652,42 +685,110 @@
             # as extension
             pass
         
-        if convertNewLineToBreak:
-            extensions = ['fenced_code', 'nl2br', 'extra']
-        else:
-            extensions = ['fenced_code', 'extra']
-        
-        # version 2.0 supports only extension names, not instances
-        if (
-            markdown.version_info[0] > 2 or
-            (markdown.version_info[0] == 2 and
-             markdown.version_info[1] > 0)
-        ):
-            class _StrikeThroughExtension(markdown.Extension):
-                """
-                Class is placed here, because it depends on imported markdown,
-                and markdown import is lazy.
+        extensions = []
+        if usePyMdownExtensions:
+            try:
+                import pymdownx     # __IGNORE_EXCEPTION__ __IGNORE_WARNING__
+                # PyPI package is 'pymdown-extensions'
                 
-                (see https://pythonhosted.org/Markdown/extensions/api.html
-                this page for details)
-                """
-                DEL_RE = r'(~~)(.*?)~~'
+                extensions = [
+                    'pymdownx.extra', 'pymdownx.caret', 'pymdownx.emoji',
+                    'pymdownx.mark', 'pymdownx.tilde', 'pymdownx.keys',
+                    'pymdownx.tasklist', 'pymdownx.smartsymbols',
+                ]
+                if convertNewLineToBreak:
+                    extensions.append('nl2br')
+            except ImportError:
+                pass
+        if not extensions:
+            if convertNewLineToBreak:
+                extensions = ['extra', 'toc', 'nl2br']
+            else:
+                extensions = ['extra', 'toc']
+            
+            # version 2.0 supports only extension names, not instances
+            if (
+                markdown.version_info[0] > 2 or
+                (markdown.version_info[0] == 2 and
+                 markdown.version_info[1] > 0)
+            ):
+                class _TildeExtension(markdown.Extension):
+                    """
+                    Class is placed here, because it depends on imported
+                    markdown, and markdown import is lazy.
+                    
+                    (see https://pythonhosted.org/Markdown/extensions/api.html
+                    this page for details)
+                    """
+                    DEL_RE = r'(~~)(.+?)~~'
+                    SUB_RE = r'(~)(.+?)~'
 
-                def extendMarkdown(self, md, md_globals):
-                    # Create the del pattern
-                    del_tag = markdown.inlinepatterns.SimpleTagPattern(
-                        self.DEL_RE, 'del')
-                    # Insert del pattern into markdown parser
-                    md.inlinePatterns.add('del', del_tag, '>not_strong')
-            
-            extensions.append(_StrikeThroughExtension())
+                    def extendMarkdown(self, md, md_globals):
+                        # Create the sub pattern and insert it into markdown
+                        # parser
+                        sub_tag = markdown.inlinepatterns.SimpleTagPattern(
+                            self.SUB_RE, 'sub')
+                        md.inlinePatterns.add('sub', sub_tag, '>not_strong')
+                        
+                        # Create the del pattern and insert it into markdown
+                        # parser
+                        del_tag = markdown.inlinepatterns.SimpleTagPattern(
+                            self.DEL_RE, 'del')
+                        md.inlinePatterns.add('del', del_tag, '>not_strong')
+                
+                class _CaretExtension(markdown.Extension):
+                    """
+                    Class is placed here, because it depends on imported
+                    markdown, and markdown import is lazy.
+                    
+                    (see https://pythonhosted.org/Markdown/extensions/api.html
+                    this page for details)
+                    """
+                    INS_RE = r'(\^\^)(.*?)\^\^'
+                    SUP_RE = r'(\^)(.*?)\^'
+                    
+                    def extendMarkdown(self, md, md_globals):
+                        # Create the sup pattern and insert it into markdown
+                        # parser
+                        sup_tag = markdown.inlinepatterns.SimpleTagPattern(
+                            self.SUP_RE, 'sup')
+                        md.inlinePatterns.add('sup', sup_tag, '>not_strong')
+                        
+                        # Create the ins pattern and insert it into markdown
+                        # parser
+                        ins_tag = markdown.inlinepatterns.SimpleTagPattern(
+                            self.INS_RE, 'ins')
+                        md.inlinePatterns.add('ins', ins_tag, '>not_strong')
+                
+                class _MarkExtension(markdown.Extension):
+                    """
+                    Class is placed here, because it depends on imported
+                    markdown, and markdown import is lazy.
+                    
+                    (see https://pythonhosted.org/Markdown/extensions/api.html
+                    this page for details)
+                    """
+                    MARK_RE = r'(==)(.*?)=='
+                    
+                    def extendMarkdown(self, md, md_globals):
+                        # Create the mark pattern and insert it into markdown
+                        # parser
+                        mark_tag = markdown.inlinepatterns.SimpleTagPattern(
+                            self.MARK_RE, 'mark')
+                        md.inlinePatterns.add('mark', mark_tag, '>not_strong')
+                
+                extensions.extend([
+                    _TildeExtension(), _CaretExtension(), _MarkExtension()
+                ])
 
         try:
-            return markdown.markdown(text, extensions=extensions + ['mathjax'],
-                                     output_format=htmlFormat.lower())
+            return markdown.markdown(
+                text, extensions=extensions + ['mdx_mathjax'],
+                output_format=htmlFormat.lower())
         except (ImportError, ValueError):
             # markdown raises ValueError or ImportError, depends on version
             # It is not clear, how to distinguish missing mathjax from other
             # errors. So keep going without mathjax.
-            return markdown.markdown(text, extensions=extensions,
-                                     output_format=htmlFormat.lower())
+            return markdown.markdown(
+                text, extensions=extensions,
+                output_format=htmlFormat.lower())

eric ide

mercurial