def testCoreToHtml_Methods(dummyGUI): """Test all the other methods of the ToHtml class. """ theProject = NWProject(dummyGUI) theHtml = ToHtml(theProject, dummyGUI) theHtml.setKeepMarkdown(True) # Auto-Replace, keep Unicode docText = "Text with <brackets> & short–dash, long—dash …\n" theHtml.theText = docText theHtml.setReplaceUnicode(False) theHtml.doPreProcessing() theHtml.tokenizeText() theHtml.doConvert() assert theHtml.theResult == ( "<p>Text with <brackets> & short–dash, long—dash …</p>\n") # Auto-Replace, replace Unicode docText = "Text with <brackets> & short–dash, long—dash …\n" theHtml.theText = docText theHtml.setReplaceUnicode(True) theHtml.doPreProcessing() theHtml.tokenizeText() theHtml.doConvert() assert theHtml.theResult == ( "<p>Text with <brackets> & short–dash, long—dash …</p>\n" ) # With Preview theHtml.setPreview(True, True) theHtml.theText = docText theHtml.doPreProcessing() theHtml.tokenizeText() theHtml.doConvert() assert theHtml.theMarkdown[-1] == ( "Text with <brackets> & short–dash, long—dash …\n\n" ) theHtml.doPostProcessing() assert theHtml.theMarkdown[-1] == ( "Text with <brackets> & short–dash, long—dash …\n\n" ) # Result Size assert theHtml.getFullResultSize() == 147 # CSS # === assert len(theHtml.getStyleSheet()) > 1 assert "p {text-align: left;" in " ".join(theHtml.getStyleSheet()) assert "p {text-align: justify;" not in " ".join(theHtml.getStyleSheet()) theHtml.setJustify(True) assert "p {text-align: left;" not in " ".join(theHtml.getStyleSheet()) assert "p {text-align: justify;" in " ".join(theHtml.getStyleSheet()) theHtml.setStyles(False) assert theHtml.getStyleSheet() == []
def testCoreToHtml_Methods(dummyGUI): """Test all the other methods of the ToHtml class. """ theProject = NWProject(dummyGUI) theHtml = ToHtml(theProject, dummyGUI) # Auto-Replace docText = "Text with <brackets> & short–dash, long—dash …\n" theHtml.theText = docText theHtml.doAutoReplace() theHtml.tokenizeText() theHtml.doConvert() assert theHtml.theResult == ( "<p>Text with <brackets> & short–dash, long—dash …</p>\n" ) # Revert on MD assert theHtml.theMarkdown == ( "Text with <brackets> & short–dash, long—dash …\n\n" ) theHtml.doPostProcessing() assert theHtml.theMarkdown == docText + "\n" # With Preview, No Revert theHtml.setPreview(True, True) theHtml.theText = docText theHtml.doAutoReplace() theHtml.tokenizeText() theHtml.doConvert() assert theHtml.theMarkdown == ( "Text with <brackets> & short–dash, long—dash …\n\n" ) theHtml.doPostProcessing() assert theHtml.theMarkdown == ( "Text with <brackets> & short–dash, long—dash …\n\n" ) # CSS # === assert len(theHtml.getStyleSheet()) > 1 assert "p {text-align: left;}" in theHtml.getStyleSheet() assert "p {text-align: justify;}" not in theHtml.getStyleSheet() theHtml.setJustify(True) assert "p {text-align: left;}" not in theHtml.getStyleSheet() assert "p {text-align: justify;}" in theHtml.getStyleSheet() theHtml.setStyles(False) assert theHtml.getStyleSheet() == []
def testCoreToHtml_Format(dummyGUI): """Test all the formatters for the ToHtml class. """ theProject = NWProject(dummyGUI) dummyGUI.theIndex = NWIndex(theProject, dummyGUI) theHtml = ToHtml(theProject, dummyGUI) # Export Mode # =========== assert theHtml._formatSynopsis("synopsis text") == ( "<p class='synopsis'><strong>Synopsis:</strong> synopsis text</p>\n") assert theHtml._formatComments("comment text") == ( "<p class='comment'><strong>Comment:</strong> comment text</p>\n") assert theHtml._formatKeywords("") == "" assert theHtml._formatKeywords("tag: Jane") == ( "<div><span class='tags'>Tag:</span> <a name='tag_Jane'>Jane</a></div>\n" ) assert theHtml._formatKeywords("char: Bod, Jane") == ( "<div>" "<span class='tags'>Characters:</span> " "<a href='#tag_Bod'>Bod</a>, " "<a href='#tag_Jane'>Jane</a>" "</div>\n") # Preview Mode # ============ theHtml.setPreview(True, True) assert theHtml._formatSynopsis("synopsis text") == ( "<p class='comment'><span class='synopsis'>Synopsis:</span> synopsis text</p>\n" ) assert theHtml._formatComments("comment text") == ( "<p class='comment'>comment text</p>\n") assert theHtml._formatKeywords("") == "" assert theHtml._formatKeywords("tag: Jane") == ( "<div><span class='tags'>Tag:</span> <a name='tag_Jane'>Jane</a></div>\n" ) assert theHtml._formatKeywords("char: Bod, Jane") == ( "<div>" "<span class='tags'>Characters:</span> " "<a href='#char=Bod'>Bod</a>, " "<a href='#char=Jane'>Jane</a>" "</div>\n")
def _buildPreview(self): """Build a preview of the project in the document viewer. """ # Get Settings justifyText = self.justifyText.isChecked() noStyling = self.noStyling.isChecked() textFont = self.textFont.text() textSize = self.textSize.value() replaceTabs = self.replaceTabs.isChecked() self.htmlText = [] self.htmlStyle = [] self.htmlSize = 0 # Build Preview # ============= makeHtml = ToHtml(self.theProject, self.theParent) self._doBuild(makeHtml, isPreview=True) if replaceTabs: makeHtml.replaceTabs() self.htmlText = makeHtml.fullHTML self.htmlStyle = makeHtml.getStyleSheet() self.htmlSize = makeHtml.getFullResultSize() self.buildTime = int(time()) # Load Preview # ============ self.docView.setTextFont(textFont, textSize) self.docView.setJustify(justifyText) if noStyling: self.docView.clearStyleSheet() else: self.docView.setStyleSheet(self.htmlStyle) if self.htmlSize < nwConst.MAX_BUILDSIZE: self.docView.setContent(self.htmlText, self.buildTime) else: self.docView.setText( "Failed to generate preview. The result is too big.") self._saveCache() return
def _buildPreview(self): """Build a preview of the project in the document viewer. """ # Get Settings fmtTitle = self.fmtTitle.text().strip() fmtChapter = self.fmtChapter.text().strip() fmtUnnumbered = self.fmtUnnumbered.text().strip() fmtScene = self.fmtScene.text().strip() fmtSection = self.fmtSection.text().strip() justifyText = self.justifyText.isChecked() noStyling = self.noStyling.isChecked() textFont = self.textFont.text() textSize = self.textSize.value() incSynopsis = self.includeSynopsis.isChecked() incComments = self.includeComments.isChecked() incKeywords = self.includeKeywords.isChecked() novelFiles = self.novelFiles.isChecked() noteFiles = self.noteFiles.isChecked() ignoreFlag = self.ignoreFlag.isChecked() includeBody = self.includeBody.isChecked() replaceTabs = self.replaceTabs.isChecked() makeHtml = ToHtml(self.theProject, self.theParent) makeHtml.setTitleFormat(fmtTitle) makeHtml.setChapterFormat(fmtChapter) makeHtml.setUnNumberedFormat(fmtUnnumbered) makeHtml.setSceneFormat(fmtScene, fmtScene == "") makeHtml.setSectionFormat(fmtSection, fmtSection == "") makeHtml.setBodyText(includeBody) makeHtml.setSynopsis(incSynopsis) makeHtml.setComments(incComments) makeHtml.setKeywords(incKeywords) makeHtml.setJustify(justifyText) makeHtml.setStyles(not noStyling) # Make sure the tree order is correct self.theParent.treeView.flushTreeOrder() self.buildProgress.setMaximum(len(self.theProject.projTree)) self.buildProgress.setValue(0) tStart = int(time()) self.htmlText = [] self.htmlStyle = [] self.nwdText = [] htmlSize = 0 for nItt, tItem in enumerate(self.theProject.projTree): noteRoot = noteFiles noteRoot &= tItem.itemType == nwItemType.ROOT noteRoot &= tItem.itemClass != nwItemClass.NOVEL noteRoot &= tItem.itemClass != nwItemClass.ARCHIVE try: if noteRoot: # Add headers for root folders of notes makeHtml.addRootHeading(tItem.itemHandle) makeHtml.doConvert() self.htmlText.append(makeHtml.getResult()) self.nwdText.append(makeHtml.getFilteredMarkdown()) htmlSize += makeHtml.getResultSize() elif self._checkInclude(tItem, noteFiles, novelFiles, ignoreFlag): makeHtml.setText(tItem.itemHandle) makeHtml.doAutoReplace() makeHtml.tokenizeText() makeHtml.doHeaders() makeHtml.doConvert() makeHtml.doPostProcessing() self.htmlText.append(makeHtml.getResult()) self.nwdText.append(makeHtml.getFilteredMarkdown()) htmlSize += makeHtml.getResultSize() except Exception as e: logger.error("Failed to generate html of document '%s'" % tItem.itemHandle) logger.error(str(e)) self.docView.setText( ("Failed to generate preview. " "Document with title '%s' could not be parsed.") % tItem.itemName) return False # Update progress bar, also for skipped items self.buildProgress.setValue(nItt + 1) if makeHtml.errData: self.theParent.makeAlert( ("There were problems when building the project:" "<br>- %s") % "<br>- ".join(makeHtml.errData), nwAlert.ERROR) if replaceTabs: htmlText = [] eightSpace = " " * 8 for aLine in self.htmlText: htmlText.append(aLine.replace("\t", eightSpace)) self.htmlText = htmlText nwdText = [] for aLine in self.nwdText: nwdText.append(aLine.replace("\t", " ")) self.nwdText = nwdText tEnd = int(time()) logger.debug("Built project in %.3f ms" % (1000 * (tEnd - tStart))) self.htmlStyle = makeHtml.getStyleSheet() self.buildTime = tEnd # Load the preview document with the html data self.docView.setTextFont(textFont, textSize) self.docView.setJustify(justifyText) if noStyling: self.docView.clearStyleSheet() else: self.docView.setStyleSheet(self.htmlStyle) if htmlSize < nwConst.maxBuildSize: self.docView.setContent(self.htmlText, self.buildTime) self._enableQtSave(True) else: self.docView.setText( "Failed to generate preview. The result is too big.") self._enableQtSave(False) self._saveCache() return
def testCoreToHtml_Convert(dummyGUI): """Test the converter of the ToHtml class. """ theProject = NWProject(dummyGUI) dummyGUI.theIndex = NWIndex(theProject, dummyGUI) theHtml = ToHtml(theProject, dummyGUI) # Export Mode # =========== theHtml.isNovel = True # Header 1 theHtml.theText = "# Title\n" theHtml.tokenizeText() theHtml.doConvert() assert theHtml.theResult == "<h1 class='title'>Title</h1>\n" # Header 2 theHtml.theText = "## Chapter Title\n" theHtml.tokenizeText() theHtml.doConvert() assert theHtml.theResult == "<h1>Chapter Title</h1>\n" # Header 3 theHtml.theText = "### Scene Title\n" theHtml.tokenizeText() theHtml.doConvert() assert theHtml.theResult == "<h2>Scene Title</h2>\n" # Header 4 theHtml.theText = "#### Section Title\n" theHtml.tokenizeText() theHtml.doConvert() assert theHtml.theResult == "<h3>Section Title</h3>\n" theHtml.isNovel = False theHtml.setLinkHeaders(True) # Header 1 theHtml.theText = "# Heading One\n" theHtml.tokenizeText() theHtml.doConvert() assert theHtml.theResult == "<h1><a name='T000001'></a>Heading One</h1>\n" # Header 2 theHtml.theText = "## Heading Two\n" theHtml.tokenizeText() theHtml.doConvert() assert theHtml.theResult == "<h2><a name='T000001'></a>Heading Two</h2>\n" # Header 3 theHtml.theText = "### Heading Three\n" theHtml.tokenizeText() theHtml.doConvert() assert theHtml.theResult == "<h3><a name='T000001'></a>Heading Three</h3>\n" # Header 4 theHtml.theText = "#### Heading Four\n" theHtml.tokenizeText() theHtml.doConvert() assert theHtml.theResult == "<h4><a name='T000001'></a>Heading Four</h4>\n" # Text theHtml.theText = "Some **nested bold and _italic_ and ~~strikethrough~~ text** here\n" theHtml.tokenizeText() theHtml.doConvert() assert theHtml.theResult == ( "<p>Some <strong>nested bold and <em>italic</em> and " "<del>strikethrough</del> text</strong> here</p>\n") # Text w/Hard Break theHtml.theText = "Line one \nLine two \nLine three\n" theHtml.tokenizeText() theHtml.doConvert() assert theHtml.theResult == ( "<p class='break'>Line one<br/>Line two<br/>Line three</p>\n") # Synopsis theHtml.theText = "%synopsis: The synopsis ...\n" theHtml.tokenizeText() theHtml.doConvert() assert theHtml.theResult == "" theHtml.setSynopsis(True) theHtml.theText = "%synopsis: The synopsis ...\n" theHtml.tokenizeText() theHtml.doConvert() assert theHtml.theResult == ( "<p class='synopsis'><strong>Synopsis:</strong> The synopsis ...</p>\n" ) # Comment theHtml.theText = "% A comment ...\n" theHtml.tokenizeText() theHtml.doConvert() assert theHtml.theResult == "" theHtml.setComments(True) theHtml.theText = "% A comment ...\n" theHtml.tokenizeText() theHtml.doConvert() assert theHtml.theResult == ( "<p class='comment'><strong>Comment:</strong> A comment ...</p>\n") # Keywords theHtml.theText = "@char: Bod, Jane\n" theHtml.tokenizeText() theHtml.doConvert() assert theHtml.theResult == "" theHtml.setKeywords(True) theHtml.theText = "@char: Bod, Jane\n" theHtml.tokenizeText() theHtml.doConvert() assert theHtml.theResult == ( "<p><span class='tags'>Characters:</span> " "<a href='#tag_Bod'>Bod</a>, <a href='#tag_Jane'>Jane</a></p>\n") # Multiple Keywords theHtml.setKeywords(True) theHtml.theText = "## Chapter\n\n@pov: Bod\n@plot: Main\n@location: Europe\n\n" theHtml.tokenizeText() theHtml.doConvert() assert theHtml.theResult == ( "<h2>" "<a name='T000001'></a>Chapter</h2>\n" "<p style='margin-bottom: 0;'>" "<span class='tags'>Point of View:</span> <a href='#tag_Bod'>Bod</a>" "</p>\n" "<p style='margin-bottom: 0; margin-top: 0;'>" "<span class='tags'>Plot:</span> <a href='#tag_Main'>Main</a>" "</p>\n" "<p style='margin-top: 0;'>" "<span class='tags'>Locations:</span> <a href='#tag_Europe'>Europe</a>" "</p>\n") # Direct Tests # ============ theHtml.isNovel = True # Title theHtml.theTokens = [ (theHtml.T_TITLE, 1, "A Title", None, theHtml.A_PBB_AUT | theHtml.A_CENTRE), (theHtml.T_EMPTY, 1, "", None, theHtml.A_NONE), ] theHtml.doConvert() assert theHtml.theResult == ( "<h1 class='title' style='text-align: center; page-break-before: auto;'>" "<a name='T000001'></a>A Title</h1>\n") # Separator theHtml.theTokens = [ (theHtml.T_SEP, 1, "* * *", None, theHtml.A_CENTRE), (theHtml.T_EMPTY, 1, "", None, theHtml.A_NONE), ] theHtml.doConvert() assert theHtml.theResult == "<p class='sep'>* * *</p>\n" # Skip theHtml.theTokens = [ (theHtml.T_SKIP, 1, "", None, theHtml.A_NONE), (theHtml.T_EMPTY, 1, "", None, theHtml.A_NONE), ] theHtml.doConvert() assert theHtml.theResult == "<p class='skip'> </p>\n" # Styles # ====== theHtml.setLinkHeaders(False) # Align Left theHtml.setStyles(False) theHtml.theTokens = [ (theHtml.T_HEAD1, 1, "A Title", None, theHtml.A_LEFT), ] theHtml.doConvert() assert theHtml.theResult == ("<h1 class='title'>A Title</h1>\n") theHtml.setStyles(True) # Align Left theHtml.theTokens = [ (theHtml.T_HEAD1, 1, "A Title", None, theHtml.A_LEFT), ] theHtml.doConvert() assert theHtml.theResult == ( "<h1 class='title' style='text-align: left;'>A Title</h1>\n") # Align Right theHtml.theTokens = [ (theHtml.T_HEAD1, 1, "A Title", None, theHtml.A_RIGHT), ] theHtml.doConvert() assert theHtml.theResult == ( "<h1 class='title' style='text-align: right;'>A Title</h1>\n") # Align Centre theHtml.theTokens = [ (theHtml.T_HEAD1, 1, "A Title", None, theHtml.A_CENTRE), ] theHtml.doConvert() assert theHtml.theResult == ( "<h1 class='title' style='text-align: center;'>A Title</h1>\n") # Align Justify theHtml.theTokens = [ (theHtml.T_HEAD1, 1, "A Title", None, theHtml.A_JUSTIFY), ] theHtml.doConvert() assert theHtml.theResult == ( "<h1 class='title' style='text-align: justify;'>A Title</h1>\n") # Page Break Always theHtml.theTokens = [ (theHtml.T_HEAD1, 1, "A Title", None, theHtml.A_PBB | theHtml.A_PBA), ] theHtml.doConvert() assert theHtml.theResult == ( "<h1 class='title' " "style='page-break-before: always; page-break-after: always;'>A Title</h1>\n" ) # Page Break Auto theHtml.theTokens = [ (theHtml.T_HEAD1, 1, "A Title", None, theHtml.A_PBB_AUT | theHtml.A_PBA_AUT), ] theHtml.doConvert() assert theHtml.theResult == ( "<h1 class='title' " "style='page-break-before: auto; page-break-after: auto;'>A Title</h1>\n" ) # Preview Mode # ============ theHtml.setPreview(True, True) # Text (HTML4) theHtml.theText = "Some **nested bold and _italic_ and ~~strikethrough~~ text** here\n" theHtml.tokenizeText() theHtml.doConvert() assert theHtml.theResult == ( "<p>Some <b>nested bold and <i>italic</i> and " "<span style='text-decoration: line-through;'>strikethrough</span> " "text</b> here</p>\n")
def testCoreToHtml_Complex(dummyGUI, fncDir): """Test the ave method of the ToHtml class. """ theProject = NWProject(dummyGUI) theHtml = ToHtml(theProject, dummyGUI) # Build Project # ============= docText = [ "# My Novel\n**By Jane Doh**\n", "## Chapter 1\n\nThe text of chapter one.\n", "### Scene 1\n\nThe text of scene one.\n", "#### A Section\n\nMore text in scene one.\n", "## Chapter 2\n\nThe text of chapter two.\n", "### Scene 2\n\nThe text of scene two.\n", "#### A Section\n\n\tMore text in scene two.\n", ] resText = [ "<h1>My Novel</h1>\n<p><strong>By Jane Doh</strong></p>\n", "<h2>Chapter 1</h2>\n<p>The text of chapter one.</p>\n", "<h3>Scene 1</h3>\n<p>The text of scene one.</p>\n", "<h4>A Section</h4>\n<p>More text in scene one.</p>\n", "<h2>Chapter 2</h2>\n<p>The text of chapter two.</p>\n", "<h3>Scene 2</h3>\n<p>The text of scene two.</p>\n", "<h4>A Section</h4>\n<p>\tMore text in scene two.</p>\n", ] for i in range(len(docText)): theHtml.theText = docText[i] theHtml.doPreProcessing() theHtml.tokenizeText() theHtml.doConvert() assert theHtml.theResult == resText[i] assert theHtml.fullHTML == resText theHtml.replaceTabs(nSpaces=2, spaceChar=" ") resText[ 6] = "<h4>A Section</h4>\n<p> More text in scene two.</p>\n" # Check File # ========== theStyle = theHtml.getStyleSheet() theStyle.append("article {width: 800px; margin: 40px auto;}") htmlDoc = ("<!DOCTYPE html>\n" "<html>\n" "<head>\n" "<meta charset='utf-8'>\n" "<title></title>\n" "</head>\n" "<style>\n" "{htmlStyle:s}\n" "</style>\n" "<body>\n" "<article>\n" "{bodyText:s}\n" "</article>\n" "</body>\n" "</html>\n").format(htmlStyle="\n".join(theStyle), bodyText="".join(resText).rstrip()) saveFile = os.path.join(fncDir, "outFile.htm") theHtml.saveHTML5(saveFile) assert readFile(saveFile) == htmlDoc
def loadText(self, tHandle, updateHistory=True): """Load text into the viewer from an item handle. """ tItem = self.theProject.projTree[tHandle] if tItem is None: logger.warning("Item not found") return False if tItem.itemType != nwItemType.FILE: return False logger.debug("Generating preview for item %s" % tHandle) qApp.setOverrideCursor(QCursor(Qt.WaitCursor)) sPos = self.verticalScrollBar().value() aDoc = ToHtml(self.theProject, self.theParent) aDoc.setPreview(True, self.mainConf.viewComments, self.mainConf.viewSynopsis) aDoc.setLinkHeaders(True) # Be extra careful here to prevent crashes when first opening a # project as a crash here leaves no way of recovering. # See issue #298 try: aDoc.setText(tHandle) aDoc.doAutoReplace() aDoc.tokenizeText() aDoc.doConvert() aDoc.doPostProcessing() except Exception as e: logger.error( "Failed to generate preview for document with handle '%s'" % tHandle) logger.error(str(e)) self.setText("An error occurred while generating the preview.") return False # Refresh the tab stops if self.mainConf.verQtValue >= 51000: self.setTabStopDistance(self.mainConf.getTabWidth()) else: self.setTabStopWidth(self.mainConf.getTabWidth()) # Must be before setHtml if updateHistory: self.docHistory.append(tHandle) self.setHtml(aDoc.theResult.replace("\t", "!!tab!!")) self.setDocumentTitle(tHandle) # Loop through the text and put back in the tabs. Tabs are removed by # the setHtml function, so the ToHtml class puts in a placeholder. while self.find("!!tab!!"): theCursor = self.textCursor() theCursor.insertText("\t") if self.theHandle == tHandle: self.verticalScrollBar().setValue(sPos) self.theHandle = tHandle self.theProject.setLastViewed(tHandle) self.docHeader.setTitleFromHandle(self.theHandle) self.updateDocMargins() # Make sure the main GUI knows we changed the content self.theParent.viewMeta.refreshReferences(tHandle) # Since we change the content while it may still be rendering, we mark # the document dirty again to make sure it's re-rendered properly. self.redrawText() qApp.restoreOverrideCursor() return True
def _saveDocument(self, theFmt): """Save the document to various formats. """ replaceTabs = self.replaceTabs.isChecked() fileExt = "" textFmt = "" # Settings # ======== if theFmt == self.FMT_ODT: fileExt = "odt" textFmt = self.tr("Open Document") elif theFmt == self.FMT_FODT: fileExt = "fodt" textFmt = self.tr("Flat Open Document") elif theFmt == self.FMT_HTM: fileExt = "htm" textFmt = self.tr("Plain HTML") elif theFmt == self.FMT_NWD: fileExt = "nwd" textFmt = self.tr("novelWriter Markdown") elif theFmt == self.FMT_MD: fileExt = "md" textFmt = self.tr("Standard Markdown") elif theFmt == self.FMT_GH: fileExt = "md" textFmt = self.tr("GitHub Markdown") elif theFmt == self.FMT_JSON_H: fileExt = "json" textFmt = self.tr("JSON + novelWriter HTML") elif theFmt == self.FMT_JSON_M: fileExt = "json" textFmt = self.tr("JSON + novelWriter Markdown") elif theFmt == self.FMT_PDF: fileExt = "pdf" textFmt = self.tr("PDF") else: return False # Generate File Name # ================== if fileExt: cleanName = makeFileNameSafe(self.theProject.projName) fileName = "%s.%s" % (cleanName, fileExt) saveDir = self.mainConf.lastPath savePath = os.path.join(saveDir, fileName) if not os.path.isdir(saveDir): saveDir = self.mainConf.homePath savePath, _ = QFileDialog.getSaveFileName( self, self.tr("Save Document As"), savePath) if not savePath: return False self.mainConf.setLastPath(savePath) else: return False # Build and Write # =============== errMsg = "" wSuccess = False if theFmt == self.FMT_ODT: makeOdt = ToOdt(self.theProject, self.theParent, isFlat=False) self._doBuild(makeOdt) try: makeOdt.saveOpenDocText(savePath) wSuccess = True except Exception as e: errMsg = str(e) elif theFmt == self.FMT_FODT: makeOdt = ToOdt(self.theProject, self.theParent, isFlat=True) self._doBuild(makeOdt) try: makeOdt.saveFlatXML(savePath) wSuccess = True except Exception as e: errMsg = str(e) elif theFmt == self.FMT_HTM: makeHtml = ToHtml(self.theProject, self.theParent) self._doBuild(makeHtml) if replaceTabs: makeHtml.replaceTabs() try: makeHtml.saveHTML5(savePath) wSuccess = True except Exception as e: errMsg = str(e) elif theFmt == self.FMT_NWD: makeNwd = ToMarkdown(self.theProject, self.theParent) makeNwd.setKeepMarkdown(True) self._doBuild(makeNwd, doConvert=False) if replaceTabs: makeNwd.replaceTabs(spaceChar=" ") try: makeNwd.saveRawMarkdown(savePath) wSuccess = True except Exception as e: errMsg = str(e) elif theFmt in (self.FMT_MD, self.FMT_GH): makeMd = ToMarkdown(self.theProject, self.theParent) if theFmt == self.FMT_GH: makeMd.setGitHubMarkdown() else: makeMd.setStandardMarkdown() self._doBuild(makeMd) if replaceTabs: makeMd.replaceTabs(nSpaces=4, spaceChar=" ") try: makeMd.saveMarkdown(savePath) wSuccess = True except Exception as e: errMsg = str(e) elif theFmt == self.FMT_JSON_H or theFmt == self.FMT_JSON_M: jsonData = { "meta": { "workingTitle": self.theProject.projName, "novelTitle": self.theProject.bookTitle, "authors": self.theProject.bookAuthors, "buildTime": self.buildTime, } } if theFmt == self.FMT_JSON_H: makeHtml = ToHtml(self.theProject, self.theParent) self._doBuild(makeHtml) if replaceTabs: makeHtml.replaceTabs() theBody = [] for htmlPage in makeHtml.fullHTML: theBody.append(htmlPage.rstrip("\n").split("\n")) jsonData["text"] = { "css": self.htmlStyle, "html": theBody, } elif theFmt == self.FMT_JSON_M: makeMd = ToHtml(self.theProject, self.theParent) makeMd.setKeepMarkdown(True) self._doBuild(makeMd, doConvert=False) if replaceTabs: makeMd.replaceTabs(spaceChar=" ") theBody = [] for nwdPage in makeMd.theMarkdown: theBody.append(nwdPage.split("\n")) jsonData["text"] = { "nwd": theBody, } try: with open(savePath, mode="w", encoding="utf8") as outFile: outFile.write(json.dumps(jsonData, indent=2)) wSuccess = True except Exception as e: errMsg = str(e) elif theFmt == self.FMT_PDF: try: thePrinter = QPrinter() thePrinter.setOutputFormat(QPrinter.PdfFormat) thePrinter.setOrientation(QPrinter.Portrait) thePrinter.setDuplex(QPrinter.DuplexLongSide) thePrinter.setFontEmbeddingEnabled(True) thePrinter.setColorMode(QPrinter.Color) thePrinter.setOutputFileName(savePath) self.docView.qDocument.print(thePrinter) wSuccess = True except Exception as e: errMsg - str(e) else: errMsg = self.tr("Unknown format") # Report to user if wSuccess: self.theParent.makeAlert( "%s<br>%s" % (self.tr("{0} file successfully written to:").format(textFmt), savePath), nwAlert.INFO) else: self.theParent.makeAlert( self.tr("Failed to write {0} file. {1}").format( textFmt, errMsg), nwAlert.ERROR) return wSuccess