190 |
189 |
191 if bool(editor.text()): |
190 if bool(editor.text()): |
192 self.__processingThread.process( |
191 self.__processingThread.process( |
193 fn, language, editor.text(), |
192 fn, language, editor.text(), |
194 self.ssiCheckBox.isChecked(), rootPath, |
193 self.ssiCheckBox.isChecked(), rootPath, |
195 Preferences.getEditor("PreviewRestUseSphinx")) |
194 Preferences.getEditor("PreviewRestUseSphinx"), |
|
195 Preferences.getEditor("PreviewMarkdownNLtoBR"), |
|
196 Preferences.getEditor("PreviewMarkdownHTMLFormat"), |
|
197 Preferences.getEditor("PreviewRestDocutilsHTMLFormat")) |
196 |
198 |
197 def __setHtml(self, filePath, html): |
199 def __setHtml(self, filePath, html): |
198 """ |
200 """ |
199 Private method to set the HTML to the view and restore the scroll bars |
201 Private method to set the HTML to the view and restore the scroll bars |
200 positions. |
202 positions. |
355 super(PreviewProcessingThread, self).__init__() |
357 super(PreviewProcessingThread, self).__init__() |
356 |
358 |
357 self.__lock = threading.Lock() |
359 self.__lock = threading.Lock() |
358 |
360 |
359 def process(self, filePath, language, text, ssiEnabled, rootPath, |
361 def process(self, filePath, language, text, ssiEnabled, rootPath, |
360 useSphinx): |
362 useSphinx, convertNewLineToBreak, markdownHtmlFormat, |
|
363 restDocutilsHtmlFormat): |
361 """ |
364 """ |
362 Public method to convert the given text to HTML. |
365 Public method to convert the given text to HTML. |
363 |
366 |
364 @param filePath file path of the text (string) |
367 @param filePath file path of the text (string) |
365 @param language language of the text (string) |
368 @param language language of the text (string) |
367 @param ssiEnabled flag indicating to do some (limited) SSI processing |
370 @param ssiEnabled flag indicating to do some (limited) SSI processing |
368 (boolean) |
371 (boolean) |
369 @param rootPath root path to be used for SSI processing (str) |
372 @param rootPath root path to be used for SSI processing (str) |
370 @param useSphinx flag indicating to use Sphinx to generate the |
373 @param useSphinx flag indicating to use Sphinx to generate the |
371 ReST preview (boolean) |
374 ReST preview (boolean) |
|
375 @param convertNewLineToBreak flag indicating to convert new lines |
|
376 to HTML break (Markdown only) (boolean) |
|
377 @param markdownHtmlFormat HTML format to be generated by markdown |
|
378 (string) |
|
379 @param restDocutilsHtmlFormat HTML format to be generated by docutils |
|
380 (string) |
372 """ |
381 """ |
373 with self.__lock: |
382 with self.__lock: |
374 self.__filePath = filePath |
383 self.__filePath = filePath |
375 self.__language = language |
384 self.__language = language |
376 self.__text = text |
385 self.__text = text |
377 self.__ssiEnabled = ssiEnabled |
386 self.__ssiEnabled = ssiEnabled |
378 self.__rootPath = rootPath |
387 self.__rootPath = rootPath |
379 self.__haveData = True |
388 self.__haveData = True |
380 self.__useSphinx = useSphinx |
389 self.__useSphinx = useSphinx |
|
390 self.__convertNewLineToBreak = convertNewLineToBreak |
|
391 self.__markdownHtmlFormat = markdownHtmlFormat |
|
392 self.__restDocutilsHtmlFormat = restDocutilsHtmlFormat |
381 if not self.isRunning(): |
393 if not self.isRunning(): |
382 self.start(QThread.LowPriority) |
394 self.start(QThread.LowPriority) |
383 |
395 |
384 def run(self): |
396 def run(self): |
385 """ |
397 """ |
392 language = self.__language |
404 language = self.__language |
393 text = self.__text |
405 text = self.__text |
394 ssiEnabled = self.__ssiEnabled |
406 ssiEnabled = self.__ssiEnabled |
395 rootPath = self.__rootPath |
407 rootPath = self.__rootPath |
396 useSphinx = self.__useSphinx |
408 useSphinx = self.__useSphinx |
|
409 convertNewLineToBreak = self.__convertNewLineToBreak |
|
410 markdownHtmlFormat = self.__markdownHtmlFormat |
|
411 restDocutilsHtmlFormat = self.__restDocutilsHtmlFormat |
|
412 |
397 self.__haveData = False |
413 self.__haveData = False |
398 |
414 |
399 html = self.__getHtml(language, text, ssiEnabled, filePath, |
415 html = self.__getHtml(language, text, ssiEnabled, filePath, |
400 rootPath, useSphinx) |
416 rootPath, useSphinx, convertNewLineToBreak, |
|
417 markdownHtmlFormat, restDocutilsHtmlFormat) |
401 |
418 |
402 with self.__lock: |
419 with self.__lock: |
403 if not self.__haveData: |
420 if not self.__haveData: |
404 self.htmlReady.emit(filePath, html) |
421 self.htmlReady.emit(filePath, html) |
405 break |
422 break |
406 # else - next iteration |
423 # else - next iteration |
407 |
424 |
408 def __getHtml(self, language, text, ssiEnabled, filePath, rootPath, |
425 def __getHtml(self, language, text, ssiEnabled, filePath, rootPath, |
409 useSphinx): |
426 useSphinx, convertNewLineToBreak, markdownHtmlFormat, |
|
427 restDocutilsHtmlFormat): |
410 """ |
428 """ |
411 Private method to process the given text depending upon the given |
429 Private method to process the given text depending upon the given |
412 language. |
430 language. |
413 |
431 |
414 @param language language of the text (string) |
432 @param language language of the text (string) |
417 (boolean) |
435 (boolean) |
418 @param filePath file path of the text (string) |
436 @param filePath file path of the text (string) |
419 @param rootPath root path to be used for SSI processing (str) |
437 @param rootPath root path to be used for SSI processing (str) |
420 @param useSphinx flag indicating to use Sphinx to generate the |
438 @param useSphinx flag indicating to use Sphinx to generate the |
421 ReST preview (boolean) |
439 ReST preview (boolean) |
|
440 @param convertNewLineToBreak flag indicating to convert new lines |
|
441 to HTML break (Markdown only) (boolean) |
|
442 @param markdownHtmlFormat HTML format to be generated by markdown |
|
443 (string) |
|
444 @param restDocutilsHtmlFormat HTML format to be generated by docutils |
|
445 (string) |
422 @return processed HTML text (string) |
446 @return processed HTML text (string) |
423 """ |
447 """ |
424 if language == "HTML": |
448 if language == "HTML": |
425 if ssiEnabled: |
449 if ssiEnabled: |
426 return self.__processSSI(text, filePath, rootPath) |
450 return self.__processSSI(text, filePath, rootPath) |
427 else: |
451 else: |
428 return text |
452 return text |
429 elif language == "Markdown": |
453 elif language == "Markdown": |
430 return self.__convertMarkdown(text) |
454 return self.__convertMarkdown(text, convertNewLineToBreak, |
|
455 markdownHtmlFormat) |
431 elif language == "ReST": |
456 elif language == "ReST": |
432 return self.__convertReST(text, useSphinx) |
457 return self.__convertReST(text, useSphinx, restDocutilsHtmlFormat) |
433 else: |
458 else: |
434 return self.tr( |
459 return self.tr( |
435 "<p>No preview available for this type of file.</p>") |
460 "<p>No preview available for this type of file.</p>") |
436 |
461 |
437 def __processSSI(self, txt, filename, root): |
462 def __processSSI(self, txt, filename, root): |
479 incTxt = "" |
504 incTxt = "" |
480 txt = txt[:incMatch.start(0)] + incTxt + txt[incMatch.end(0):] |
505 txt = txt[:incMatch.start(0)] + incTxt + txt[incMatch.end(0):] |
481 |
506 |
482 return txt |
507 return txt |
483 |
508 |
484 def __convertReST(self, text, useSphinx): |
509 def __convertReST(self, text, useSphinx, restDocutilsHtmlFormat): |
485 """ |
510 """ |
486 Private method to convert ReST text into HTML. |
511 Private method to convert ReST text into HTML. |
487 |
512 |
488 @param text text to be processed (string) |
513 @param text text to be processed (string) |
489 @param useSphinx flag indicating to use Sphinx to generate the |
514 @param useSphinx flag indicating to use Sphinx to generate the |
490 ReST preview (boolean) |
515 ReST preview (boolean) |
|
516 @param restDocutilsHtmlFormat HTML format to be generated by docutils |
|
517 (string) |
491 @return processed HTML (string) |
518 @return processed HTML (string) |
492 """ |
519 """ |
493 if useSphinx: |
520 if useSphinx: |
494 return self.__convertReSTSphinx(text) |
521 return self.__convertReSTSphinx(text) |
495 else: |
522 else: |
496 return self.__convertReSTDocutils(text) |
523 return self.__convertReSTDocutils(text, restDocutilsHtmlFormat) |
497 |
524 |
498 def __convertReSTSphinx(self, text): |
525 def __convertReSTSphinx(self, text): |
499 """ |
526 """ |
500 Private method to convert ReST text into HTML using 'sphinx'. |
527 Private method to convert ReST text into HTML using 'sphinx'. |
501 |
528 |
541 finally: |
568 finally: |
542 shutil.rmtree(tempDir) |
569 shutil.rmtree(tempDir) |
543 |
570 |
544 return html |
571 return html |
545 |
572 |
546 def __convertReSTDocutils(self, text): |
573 def __convertReSTDocutils(self, text, htmlFormat): |
547 """ |
574 """ |
548 Private method to convert ReST text into HTML using 'docutils'. |
575 Private method to convert ReST text into HTML using 'docutils'. |
549 |
576 |
550 @param text text to be processed (string) |
577 @param text text to be processed (string) |
|
578 @param htmlFormat HTML format to be generated (string) |
551 @return processed HTML (string) |
579 @return processed HTML (string) |
552 """ |
580 """ |
553 if 'sphinx' in sys.modules: |
581 if 'sphinx' in sys.modules: |
554 # Make sure any Sphinx polution of docutils has been removed. |
582 # Make sure any Sphinx polution of docutils has been removed. |
555 unloadKeys = [k for k in sys.modules.keys() |
583 unloadKeys = [k for k in sys.modules.keys() |
568 """this page.</a></p>""") |
596 """this page.</a></p>""") |
569 |
597 |
570 # redirect sys.stderr because we are not interested in it here |
598 # redirect sys.stderr because we are not interested in it here |
571 origStderr = sys.stderr |
599 origStderr = sys.stderr |
572 sys.stderr = io.StringIO() |
600 sys.stderr = io.StringIO() |
573 html = docutils.core.publish_string(text, writer_name='html')\ |
601 html = docutils.core.publish_string( |
574 .decode("utf-8") |
602 text, writer_name=htmlFormat.lower()).decode("utf-8") |
575 sys.stderr = origStderr |
603 sys.stderr = origStderr |
576 return html |
604 return html |
577 |
605 |
578 def __convertMarkdown(self, text): |
606 def __convertMarkdown(self, text, convertNewLineToBreak, htmlFormat): |
579 """ |
607 """ |
580 Private method to convert Markdown text into HTML. |
608 Private method to convert Markdown text into HTML. |
581 |
609 |
582 @param text text to be processed (string) |
610 @param text text to be processed (string) |
|
611 @param convertNewLineToBreak flag indicating to convert new lines |
|
612 to HTML break (Markdown only) (boolean) |
|
613 @param htmlFormat HTML format to be generated by markdown (string) |
583 @return processed HTML (string) |
614 @return processed HTML (string) |
584 """ |
615 """ |
585 try: |
616 try: |
586 import markdown # __IGNORE_EXCEPTION__ |
617 import markdown # __IGNORE_EXCEPTION__ |
587 except ImportError: |
618 except ImportError: |
595 try: |
626 try: |
596 import mdx_mathjax # __IGNORE_EXCEPTION__ __IGNORE_WARNING__ |
627 import mdx_mathjax # __IGNORE_EXCEPTION__ __IGNORE_WARNING__ |
597 except ImportError: |
628 except ImportError: |
598 #mathjax doesn't require import statement if installed as extension |
629 #mathjax doesn't require import statement if installed as extension |
599 pass |
630 pass |
600 |
631 |
601 extensions = ['fenced_code', 'nl2br', 'extra'] |
632 if convertNewLineToBreak: |
|
633 extensions = ['fenced_code', 'nl2br', 'extra'] |
|
634 else: |
|
635 extensions = ['fenced_code', 'extra'] |
602 |
636 |
603 # version 2.0 supports only extension names, not instances |
637 # version 2.0 supports only extension names, not instances |
604 if markdown.version_info[0] > 2 or \ |
638 if markdown.version_info[0] > 2 or \ |
605 (markdown.version_info[0] == 2 and |
639 (markdown.version_info[0] == 2 and |
606 markdown.version_info[1] > 0): |
640 markdown.version_info[1] > 0): |
623 md.inlinePatterns.add('del', del_tag, '>not_strong') |
657 md.inlinePatterns.add('del', del_tag, '>not_strong') |
624 |
658 |
625 extensions.append(_StrikeThroughExtension()) |
659 extensions.append(_StrikeThroughExtension()) |
626 |
660 |
627 try: |
661 try: |
628 return markdown.markdown(text, extensions + ['mathjax']) |
662 return markdown.markdown(text, extensions=extensions + ['mathjax'], |
|
663 output_format=htmlFormat.lower()) |
629 except (ImportError, ValueError): |
664 except (ImportError, ValueError): |
630 # markdown raises ValueError or ImportError, depends on version |
665 # markdown raises ValueError or ImportError, depends on version |
631 # It is not clear, how to distinguish missing mathjax from other |
666 # It is not clear, how to distinguish missing mathjax from other |
632 # errors. So keep going without mathjax. |
667 # errors. So keep going without mathjax. |
633 return markdown.markdown(text, extensions) |
668 return markdown.markdown(text, extensions=extensions, |
|
669 output_format=htmlFormat.lower()) |