From aa4778d4cd39985237a1c3bc4f4b8897b04f9343 Mon Sep 17 00:00:00 2001 From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com> Date: Tue, 12 May 2020 18:41:08 +0200 Subject: [PATCH] Preserve markdown during build, and use lists instead of strings --- nw/core/tohtml.py | 25 ++++++++++++++---------- nw/core/tokenizer.py | 46 +++++++++++++++++++++++++++++++++++++------- nw/gui/build.py | 17 ++++++++++++++-- 3 files changed, 69 insertions(+), 19 deletions(-) diff --git a/nw/core/tohtml.py b/nw/core/tohtml.py index 20c32e58..7980d80b 100644 --- a/nw/core/tohtml.py +++ b/nw/core/tohtml.py @@ -105,8 +105,10 @@ class ToHtml(Tokenizer): } self.theResult = "" + thisPar = [] parStyle = "" + tmpResult = [] for tType, tText, tFormat, tStyle in self.theTokens: # Styles @@ -146,31 +148,31 @@ class ToHtml(Tokenizer): if tType == self.T_EMPTY: if len(thisPar) > 0: tTemp = "".join(thisPar) - self.theResult += "%s

\n" % (parStyle,tTemp.rstrip()) + tmpResult.append("%s

\n" % (parStyle, tTemp.rstrip())) thisPar = [] parStyle = "" elif tType == self.T_HEAD1: tHead = tText.replace(r"\\", "
") - self.theResult += "%s\n" % (hStyle, tHead) + tmpResult.append("%s\n" % (hStyle, tHead)) elif tType == self.T_HEAD2: tHead = tText.replace(r"\\", "
") - self.theResult += "%s\n" % (hStyle, tHead) + tmpResult.append("%s\n" % (hStyle, tHead)) elif tType == self.T_HEAD3: tHead = tText.replace(r"\\", "
") - self.theResult += "%s\n" % (hStyle, tHead) + tmpResult.append("%s\n" % (hStyle, tHead)) elif tType == self.T_HEAD4: tHead = tText.replace(r"\\", "
") - self.theResult += "%s\n" % (hStyle, tHead) + tmpResult.append("%s\n" % (hStyle, tHead)) elif tType == self.T_SEP: - self.theResult += "%s

\n" % (hStyle, tText) + tmpResult.append("%s

\n" % (hStyle, tText)) elif tType == self.T_SKIP: - self.theResult += " 

\n" % hStyle + tmpResult.append(" 

\n" % hStyle) elif tType == self.T_TEXT: tTemp = tText @@ -183,13 +185,16 @@ class ToHtml(Tokenizer): thisPar.append(tTemp.rstrip()+" ") elif tType == self.T_SYNOPSIS and self.doSynopsis: - self.theResult += self._formatSynopsis(tText) + tmpResult.append(self._formatSynopsis(tText)) elif tType == self.T_COMMENT and self.doComments: - self.theResult += self._formatComments(tText) + tmpResult.append(self._formatComments(tText)) elif tType == self.T_KEYWORD and self.doKeywords: - self.theResult += self._formatKeywords(tText) + tmpResult.append(self._formatKeywords(tText)) + + self.theResult = "".join(tmpResult) + tmpResult = [] return diff --git a/nw/core/tokenizer.py b/nw/core/tokenizer.py index 20d89623..025a9cfb 100644 --- a/nw/core/tokenizer.py +++ b/nw/core/tokenizer.py @@ -84,6 +84,7 @@ class Tokenizer(): self.theItem = None # The NWItem associated with the handle self.theTokens = None # The list of the processed tokens self.theResult = None # The result text after conversion + self.theMarkdown = None # The result text in novelWriter markdown # User Settings self.doBodyText = True # Include body text @@ -125,13 +126,14 @@ class Tokenizer(): """Clear the data arrays and variables, but not settings, so the class can be reused for multiple documents. """ - self.theText = None - self.theHandle = None - self.theItem = None - self.theTokens = None - self.theResult = None - self.numChapter = 0 - self.firstScene = False + self.theText = None + self.theHandle = None + self.theItem = None + self.theTokens = None + self.theResult = None + self.theMarkdown = None + self.numChapter = 0 + self.firstScene = False self.isNone = False self.isTitle = False @@ -230,6 +232,11 @@ class Tokenizer(): """ return self.theResult + def getFilteredMarkdown(self): + """Return the novelWriter markdown after the filters have been applied. + """ + return self.theMarkdown + def doAutoReplace(self): """Run through the user's auto-replace dictionary. """ @@ -280,6 +287,8 @@ class Tokenizer(): defAlign = self.A_LEFT self.theTokens = [] + self.theMarkdown = "" + tmpMarkdown = [] for aLine in self.theText.splitlines(): # Tag lines starting with specific characters @@ -287,36 +296,54 @@ class Tokenizer(): self.theTokens.append(( self.T_EMPTY, "", None, None )) + tmpMarkdown.append("\n") + elif aLine[0] == "%": cLine = aLine[1:].strip() if cLine.lower().startswith("synopsis:"): self.theTokens.append(( self.T_SYNOPSIS, cLine[9:].strip(), None, defAlign )) + if self.doSynopsis: + tmpMarkdown.append("%s\n" % aLine) else: self.theTokens.append(( self.T_COMMENT, aLine[1:].strip(), None, defAlign )) + if self.doComments: + tmpMarkdown.append("%s\n" % aLine) + elif aLine[0] == "@": self.theTokens.append(( self.T_KEYWORD, aLine[1:].strip(), None, self.A_LEFT )) + if self.doKeywords: + tmpMarkdown.append("%s\n" % aLine) + elif aLine[:2] == "# ": self.theTokens.append(( self.T_HEAD1, aLine[2:].strip(), None, self.A_LEFT | self.A_PBB )) + tmpMarkdown.append("%s\n" % aLine) + elif aLine[:3] == "## ": self.theTokens.append(( self.T_HEAD2, aLine[3:].strip(), None, self.A_LEFT | self.A_PBA_AV )) + tmpMarkdown.append("%s\n" % aLine) + elif aLine[:4] == "### ": self.theTokens.append(( self.T_HEAD3, aLine[4:].strip(), None, self.A_LEFT | self.A_PBA_AV )) + tmpMarkdown.append("%s\n" % aLine) + elif aLine[:5] == "#### ": self.theTokens.append(( self.T_HEAD4, aLine[5:].strip(), None, self.A_LEFT | self.A_PBA_AV )) + tmpMarkdown.append("%s\n" % aLine) + else: if not self.doBodyText: # Skip all body text @@ -340,11 +367,16 @@ class Tokenizer(): self.theTokens.append(( self.T_TEXT, aLine, fmtPos, defAlign )) + tmpMarkdown.append("%s\n" % aLine) # Always add an empty line at the end self.theTokens.append(( self.T_EMPTY, "", None, None )) + tmpMarkdown.append("\n") + + self.theMarkdown = "".join(tmpMarkdown) + tmpMarkdown = [] return diff --git a/nw/gui/build.py b/nw/gui/build.py index d007ae70..d95be6de 100644 --- a/nw/gui/build.py +++ b/nw/gui/build.py @@ -29,6 +29,7 @@ import logging import nw from os import path +from time import time from PyQt5.QtCore import Qt, QByteArray from PyQt5.QtPrintSupport import QPrinter, QPrintPreviewDialog @@ -69,6 +70,7 @@ class GuiBuildNovel(QDialog): self.optState = self.theProject.optState self.htmlText = "" + self.nwdText = "" self.setWindowTitle("Build Novel Project") self.setMinimumWidth(800) @@ -311,9 +313,13 @@ class GuiBuildNovel(QDialog): makeHtml.setKeywords(incKeywords) makeHtml.setJustify(justifyText) - self.htmlText = "" self.buildProgress.setMaximum(len(self.theProject.projTree)) self.buildProgress.setValue(0) + + tStart = time() + + tmpHtml = [] + tmpNwd = [] for nItt, tItem in enumerate(self.theProject.projTree): if self._checkInclude(tItem, noteFiles, novelFiles, ignoreFlag): makeHtml.setText(tItem.itemHandle) @@ -322,9 +328,16 @@ class GuiBuildNovel(QDialog): makeHtml.doHeaders() makeHtml.doConvert() makeHtml.doPostProcessing() - self.htmlText += makeHtml.getResult() + tmpHtml.append(makeHtml.getResult()) + tmpNwd.append(makeHtml.getFilteredMarkdown()) self.buildProgress.setValue(nItt+1) + self.htmlText = "".join(tmpHtml) + self.nwdText = "".join(tmpNwd) + + tEnd = time() + logger.debug("Built project in %.3f ms" % (1000*(tEnd-tStart))) + self.docView.setHtml(self.htmlText) return