diff --git a/.gitignore b/.gitignore index 1b03d0dd..6645bcf1 100644 --- a/.gitignore +++ b/.gitignore @@ -18,6 +18,8 @@ i18n/*.qph # Documentation /docs/build/ /nw/assets/help/html/ +/nw/assets/help/manual.pdf +/UserManual.pdf *.qch *.qhc diff --git a/docs/source/conf.py b/docs/source/conf.py index b253da66..99e955bc 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -4,20 +4,15 @@ # This file does only contain a selection of the most common options. For a # full list see the documentation: # http://www.sphinx-doc.org/en/master/config - -# -- Path setup -------------------------------------------------------------- - -# If extensions (or modules to document with autodoc) are in another directory, -# add these directories to sys.path here. If the directory is relative to the -# documentation root, use os.path.abspath to make it absolute, like shown here. # -# import sys -# sys.path.insert(0, os.path.abspath(".")) + +# -- Imports ----------------------------------------------------------------- + import os import time -import sphinx_rtd_theme # noqa: F401 +import sphinx_rtd_theme # noqa: F401 -# -- Project information ----------------------------------------------------- +# -- Project Information ----------------------------------------------------- project = "novelWriter" copyright = "2018–2021, Veronica Berglyd Olsen" @@ -28,7 +23,7 @@ version = "1.5" # The full version, including alpha/beta/rc tags release = "1.5-alpha0" -# -- General configuration --------------------------------------------------- +# -- General Configuration --------------------------------------------------- os.environ["TZ"] = "Europe/Oslo" time.tzset() @@ -45,7 +40,7 @@ language = None exclude_patterns = [] pygments_style = None -# -- Options for HTML output ------------------------------------------------- +# -- Options for HTML Output ------------------------------------------------- html_theme = "sphinx_rtd_theme" html_logo = "images/novelwriter.png" @@ -64,48 +59,32 @@ html_css_files = [ "css/custom.css", ] -# Custom sidebar templates, must be a dictionary that maps document names -# to template names. -# The default sidebars (for documents that don"t match any pattern) are -# defined by theme itself. Builtin themes are using these templates by -# default: ``["localtoc.html", "relations.html", "sourcelink.html", -# "searchbox.html"]``. -# html_sidebars = {} - -# -- Options for HTMLHelp output --------------------------------------------- +# -- Options for HTMLHelp Output --------------------------------------------- # Output file base name for HTML help builder. htmlhelp_basename = "novelWriterDoc" -# -- Options for LaTeX output ------------------------------------------------ +# -- Options for LaTeX Output ------------------------------------------------ latex_elements = { - # The paper size ("letterpaper" or "a4paper"). - # - # "papersize": "letterpaper", - - # The font size ("10pt", "11pt" or "12pt"). - # - # "pointsize": "10pt", - - # Additional stuff for the LaTeX preamble. - # - # "preamble": "", - - # Latex figure (float) alignment - # - # "figure_align": "htbp", + "papersize": "a4paper", + "pointsize": "11pt", + "preamble": ( + "\\usepackage[utf8]{inputenc}\n" + "\\DeclareUnicodeCharacter{2212}{\\textendash}\n" + ), + "figure_align": "htbp", } # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). latex_documents = [( - master_doc, "novelWriter.tex", "novelWriter Documentation", + master_doc, "manual.tex", "novelWriter Documentation", author, "manual" )] -# -- Options for manual page output ------------------------------------------ +# -- Options for Man Page Output --------------------------------------------- # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). @@ -113,7 +92,7 @@ man_pages = [( master_doc, "novelwriter", "novelWriter Documentation", [author], 1 )] -# -- Options for Texinfo output ---------------------------------------------- +# -- Options for Texinfo Output ---------------------------------------------- # Grouping the document tree into Texinfo files. List of tuples # (source start file, target name, title, author, @@ -123,7 +102,7 @@ texinfo_documents = [( "novelWriter", "Markdown-like editor for novels.", "Miscellaneous" )] -# -- Options for Epub output ------------------------------------------------- +# -- Options for EPub Output ------------------------------------------------- # Bibliographic Dublin Core info. epub_title = project diff --git a/docs/source/index.rst b/docs/source/index.rst index 6c0eb7f2..1a0401f0 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -2,29 +2,31 @@ novelWriter |release| ##################### -.. image:: https://github.com/vkbo/novelWriter/workflows/python%203.8/badge.svg?branch=main - :target: https://github.com/vkbo/novelWriter/actions - :alt: Python Tests +.. only:: html -.. image:: https://codecov.io/gh/vkbo/novelWriter/branch/main/graph/badge.svg - :target: https://codecov.io/gh/vkbo/novelWriter - :alt: Code Coverage + .. image:: https://github.com/vkbo/novelWriter/workflows/python%203.8/badge.svg?branch=main + :target: https://github.com/vkbo/novelWriter/actions + :alt: Python Tests -.. image:: https://readthedocs.org/projects/novelwriter/badge/?version=latest - :target: https://novelwriter.readthedocs.io/en/latest/?badge=latest - :alt: Documentation + .. image:: https://codecov.io/gh/vkbo/novelWriter/branch/main/graph/badge.svg + :target: https://codecov.io/gh/vkbo/novelWriter + :alt: Code Coverage -.. image:: https://img.shields.io/github/v/release/vkbo/novelwriter - :target: https://github.com/vkbo/novelWriter/releases - :alt: GitHub Release + .. image:: https://readthedocs.org/projects/novelwriter/badge/?version=latest + :target: https://novelwriter.readthedocs.io/en/latest/?badge=latest + :alt: Documentation -.. image:: https://img.shields.io/pypi/v/novelwriter - :target: https://pypi.org/project/novelWriter/ - :alt: PyPI + .. image:: https://img.shields.io/github/v/release/vkbo/novelwriter + :target: https://github.com/vkbo/novelWriter/releases + :alt: GitHub Release -.. image:: https://img.shields.io/pypi/pyversions/novelwriter - :target: https://pypi.org/project/novelWriter/ - :alt: Python Version + .. image:: https://img.shields.io/pypi/v/novelwriter + :target: https://pypi.org/project/novelWriter/ + :alt: PyPI + + .. image:: https://img.shields.io/pypi/pyversions/novelwriter + :target: https://pypi.org/project/novelWriter/ + :alt: Python Version **Last Updated:** |today| @@ -101,6 +103,7 @@ for your operating system for further details. :caption: Under the Hood tech_storage + tech_tests Indices and Tables diff --git a/docs/source/int_started.rst b/docs/source/int_started.rst index 51384019..51a3f67e 100644 --- a/docs/source/int_started.rst +++ b/docs/source/int_started.rst @@ -157,13 +157,15 @@ The documentation can then be built from the ``docs`` folder in the source code If successful, the documentation should be available in the ``docs/build/html`` folder and you can open the ``index.html`` file in your browser. -You can also build the documentation by using the setup script: +You can also build the PDF documentation locally using the setup script: .. code-block:: console - python setup.py docs + python setup.py pdfdocs -This does the same as the ``make help`` command, but in addition it copies the documentation into -novelWriter's assets folder. This will make it possible to open the documentation from inside of -novelWriter by pressing :kbd:`F1` even without an internet connection, as it will instead open the -local copy. +This will build the documentation as a PDF using LaTeX. The file will then be copied into the +assets folder and made available in the :guilabel:`Help` menu in novelWriter. The Sphinx build +system has a few extra dependencies when building the PDF. Please check the `Sphinx Docs`_ if you +have any issues. + +.. _Sphinx Docs: https://www.sphinx-doc.org/ diff --git a/docs/source/tech_storage.rst b/docs/source/tech_storage.rst index a279706d..c06aff2e 100644 --- a/docs/source/tech_storage.rst +++ b/docs/source/tech_storage.rst @@ -35,9 +35,9 @@ your own backup solution. extensions `.json` as JSON files are used to cache the index and various run-time settings and are generally large files that change often. You'd also want to exclude the ``cache`` folder. -The project XML file is indent-formatted, suitable for diff tools and version control since most of -the file will stay static, although a timesetamp is set in the meta section on line 2, and various -meta data entries incremented, on each save. +The project XML file is indent-formatted, and is suitable for diff tools and version control since +most of the file will stay static, although a timesetamp is set in the meta section on line 2, and +various meta data entries incremented, on each save. Project Documents @@ -45,7 +45,7 @@ Project Documents All the project documents are saved in a folder in the main project folder named ``content``. Each document has a file handle taken from the first 13 characters of a SHA256 hash of the system time -plus an incremented number when the document was first created. The documents are saved with a +when the document was first created, plus an incremented number. The documents are saved with a filename assembled from this hash and the file extension ``.nwd``. If you wish to find the file system location of a document in the project, you can either look it @@ -60,7 +60,7 @@ what the user names the document within the project, or changes it to. Each document file contains a plain text version of the text from the editor. The file can in principle be edited in any text editor, and is suitable for diffing and version control if so -desired. Just make sure the file remains in utf-8 encoding, otherwise unicode chatracters may +desired. Just make sure the file remains in utf-8 encoding, otherwise unicode characters may become mangled when the file is opened in novelWriter again. Editing these files is generally not recommended outside of special circumstances, whatever they @@ -115,7 +115,7 @@ project, and the word counts within each header section. The integrity of the index is checked when the file is loaded. It is possible to corrupt the index if the file is manually edited and manipulated, so the check is important to avoid sudden crashes -of novelWriter. if the file contains errors, novelWriter will automatically build it anew. If the +of novelWriter. If the file contains errors, novelWriter will automatically build it anew. If the check somehow fails and novelWriter keeps crashing, you can delete the file manually and rebuild the index. If this too fails, you have likely encountered a bug. diff --git a/docs/source/tech_tests.rst b/docs/source/tech_tests.rst new file mode 100644 index 00000000..5fe24149 --- /dev/null +++ b/docs/source/tech_tests.rst @@ -0,0 +1,85 @@ +.. _a_pytest: + +************* +Running Tests +************* + +The novelWriter source code is well covered by tests. The test framework used for the development +is ``pytest`` with the use of an extension for Qt. + + +Dependencies +============ + +The dependencies for running the tests can be installed with: + +.. code-block:: console + + pip install -r requirements-dev.txt + +This will install a couple of extra packages for coverage and test management. The minimum +requirement is just ``pytest`` and ``pytest-qt``. + + +Simple Test Run +=============== + +To run the tests, you simply need to execute the following from the root of the source folder: + +.. code-block:: console + + pytest + +Since several of the tests involve opening up the novelWriter GUI, you may want to disable the GUI +for the duration of the test run. Moving your mouse while the tests are running may otherwise +interfere with the execution of some tests. + +You can disable the renderring of the GUI by setting the flag ``export QT_QPA_PLATFORM=offscreen``, +or alternatively run the tests with the ``xvfb`` package, like so: + +.. code-block:: console + + xvfb-run pytest + + +Advanced Options +================ + +Adding the flag ``-v`` to the ``pytest`` command will increase verbosity of the test execution. + +You can also add coverage report generation. For instance to HTML: + +.. code-block:: console + + xvfb-run pytest -v --cov=nw --cov-report=html + +Other useful report formats are ``xml``, and ``term`` for terminal output. + +You can also run tests per subpackage of novelWriter with the ``-m`` command. The available +subpackage groups are ``base``, ``core``, and ``gui``. Consider for instance: + +.. code-block:: console + + xvfb-run pytest -v --cov=nw --cov-report=html -m core + +This will only run the tests of the "core" package, that is, all the classes that deal with the +project data of a novelWriter project. The "gui" tests, likewise, will run the tests for the GUI +components, and the "base" tests cover the bits in-between. + +You can also filter the tests with the ``-k`` switch. The following will do the same as +``-m core``: + +.. code-block:: console + + xvfb-run pytest -v --cov=nw --cov-report=html -k testCore + +All tests are named in such a way that you can filter them by adding more bits of the test names. +They all start with the word "test". Then comes the group: "Core", "Base", "Dlg", "Tool", or "Gui". +Finally comes the name of the class or module, which generally corresponds to a single source code +file. For instance, running the following will run all tests for the document editor: + +.. code-block:: console + + xvfb-run pytest -v --cov=nw --cov-report=html -k testGuiEditor + +To run a single test, simply add the full test name to the ``-k`` switch. diff --git a/docs/source/usage_shortcuts.rst b/docs/source/usage_shortcuts.rst index 6c92c350..7a06e26a 100644 --- a/docs/source/usage_shortcuts.rst +++ b/docs/source/usage_shortcuts.rst @@ -80,7 +80,7 @@ The main shorcuts are as follows: ":kbd:`Ctrl`:kbd:`Shift`:kbd:`W`", "Close the current project." ":kbd:`Ctrl`:kbd:`Shift`:kbd:`Z`", "Undo move of project tree item." ":kbd:`Ctrl`:kbd:`Shift`:kbd:`Del`", "If in the project tree, move a document to trash, or delete a folder." - ":kbd:`F1`", "Open the documentation. This will either open the Qt Assistant, if available, or send you to the documentation website." + ":kbd:`F1`", "Open the online user manual." ":kbd:`F2`", "If in the project tree, edit a document or folder settings. (Same as :kbd:`Ctrl`:kbd:`E`)" ":kbd:`F3`", "Find next occurrence of search word in current document. (Same as :kbd:`Ctrl`:kbd:`G`)" ":kbd:`F5`", "Open the :guilabel:`Build Novel Project` dialog." @@ -90,7 +90,7 @@ The main shorcuts are as follows: ":kbd:`F9`", "Re-build the project index." ":kbd:`F10`", "Re-build the project outline." ":kbd:`F11`", "Activate full screen mode." - ":kbd:`Shift`:kbd:`F1`", "Open the online documentation in the system default browser." + ":kbd:`Shift`:kbd:`F1`", "Open the local user manual (PDF) if it is available." ":kbd:`Shift`:kbd:`F3`", "Find previous occurrence of search word in current document. (Same as :kbd:`Ctrl`:kbd:`Shift`:kbd:`G`.)" ":kbd:`Shift`:kbd:`F6`", "Open the :guilabel:`Project Details` dialog." ":kbd:`Return`", "If in the project tree, open a document for editing." diff --git a/nw/config.py b/nw/config.py index 031449fe..5d49ecd0 100644 --- a/nw/config.py +++ b/nw/config.py @@ -71,6 +71,7 @@ class Config: self.themeRoot = None # The full path to the nw/assets/themes folder self.dictPath = None # The full path to the nw/assets/dict folder self.iconPath = None # The full path to the nw/assets/icons folder + self.pdfDocs = None # The location of the PDF manual, if it exists # Runtime Settings and Variables self.confChanged = False # True whenever the config has chenged, false after save @@ -356,6 +357,16 @@ class Config: if self.spellLanguage is None: self.spellLanguage = "en" + # Look for a PDF version of the manual + lookIn = [ + os.path.join(self.assetPath, "help", "manual.pdf"), + os.path.join(self.appRoot, "UserManual.pdf"), + ] + for pdfDocs in lookIn: + if os.path.isfile(pdfDocs): + self.pdfDocs = pdfDocs + break + logger.debug("Config initialisation complete") return True diff --git a/nw/core/toodt.py b/nw/core/toodt.py index 69dac848..152d2889 100644 --- a/nw/core/toodt.py +++ b/nw/core/toodt.py @@ -107,7 +107,7 @@ class ToOdt(Tokenizer): self.headerText = "" # Internal - self._fontFamily = "'Liberation Sans'" + self._fontFamily = "'Liberation Serif'" self._fontPitch = "variable" self._fSizeTitle = "30pt" self._fSizeHead1 = "24pt" @@ -239,6 +239,9 @@ class ToOdt(Tokenizer): self._blockIndent = self._emToCm(self.blockIndent) self._textAlign = "justify" if self.doJustify else "left" + # Clear Errors + self._errData = [] + # Document Header # =============== @@ -546,8 +549,8 @@ class ToOdt(Tokenizer): rFmt += "_B%s b_ " % (" "*len(tText)) if len(theBits) > 1: if theBits[0] == nwKeyWords.TAG_KEY: - rTxt += "%s" % theBits[1] - rFmt += "%s" % (" "*len(theBits[1])) + rTxt += theBits[1] + rFmt += " "*len(theBits[1]) else: tTags = ", ".join(theBits[1:]) rTxt += tTags @@ -585,12 +588,15 @@ class ToOdt(Tokenizer): tTemp = "" xFmt = 0x00 pFmt = 0x00 + pErr = 0 parProc = XMLParagraph(xElem) for i, c in enumerate(theText): - if theFmt[i] == "_": + if theFmt[i] == " ": + tTemp += c + elif theFmt[i] == "_": continue elif theFmt[i] == "B": xFmt |= X_BLD @@ -604,9 +610,8 @@ class ToOdt(Tokenizer): xFmt |= X_DEL elif theFmt[i] == "s": xFmt &= M_DEL - - if theFmt[i] == " ": - tTemp += c + else: + pErr += 1 if xFmt != pFmt: if pFmt == 0x00: @@ -624,6 +629,9 @@ class ToOdt(Tokenizer): else: parProc.appendSpan(tTemp, self._textStyle(pFmt)) + if pErr > 0: + self._errData.append("Unknown format tag encountered") + nErr, errMsg = parProc.checkError() if nErr > 0: # pragma: no cover # This one should only capture bugs @@ -652,23 +660,23 @@ class ToOdt(Tokenizer): return newName - def _textStyle(self, styleCode): + def _textStyle(self, tFmt): """Return a text style for a given style code. """ - if styleCode in self._autoText: - return self._autoText[styleCode][0] + if tFmt in self._autoText: + return self._autoText[tFmt][0] newName = "T%d" % (len(self._autoText) + 1) newStyle = ODTTextStyle() - if styleCode & X_BLD: + if tFmt & X_BLD: newStyle.setFontWeight("bold") - if styleCode & X_ITA: + if tFmt & X_ITA: newStyle.setFontStyle("italic") - if styleCode & X_DEL: + if tFmt & X_DEL: newStyle.setStrikeStyle("solid") newStyle.setStrikeType("single") - self._autoText[styleCode] = (newName, newStyle) + self._autoText[tFmt] = (newName, newStyle) return newName diff --git a/nw/gui/mainmenu.py b/nw/gui/mainmenu.py index c80ffa46..0c3dc5e5 100644 --- a/nw/gui/mainmenu.py +++ b/nw/gui/mainmenu.py @@ -23,11 +23,9 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . """ -import os import nw import logging -from http.client import HTTPSConnection from urllib.parse import urljoin from urllib.request import pathname2url @@ -137,31 +135,13 @@ class GuiMainMenu(QMenuBar): QDesktopServices.openUrl(QUrl(theUrl)) return True - def _openDocumentation(self): - """Open the documentation, and select whether it should be the - stable or latest version. If no internet connection, open - local. + def _openUserManualFile(self): + """Open the documentation in PDF format. """ - if nw.__hexversion__[-2] == "f": - docsPath = "/en/stable/" - else: - docsPath = "/en/latest/" - - try: - conn = HTTPSConnection(nw.__docurl__.replace("https://", "")) - conn.request("HEAD", docsPath) - resp = conn.getresponse() - hasAccess = resp.code == 200 - except Exception: - hasAccess = False - - docsFile = os.path.join(self.mainConf.assetPath, "help", "html", "index.html") - if hasAccess or not os.path.isfile(docsFile): - self._openWebsite(nw.__docurl__ + docsPath) - else: - self._openWebsite(urljoin("file:", pathname2url(docsFile))) - - return + if self.mainConf.pdfDocs is None: + return False + QDesktopServices.openUrl(QUrl(urljoin("file:", pathname2url(self.mainConf.pdfDocs)))) + return True ## # Menu Builders @@ -1106,13 +1086,21 @@ class GuiMainMenu(QMenuBar): # Help > Separator self.helpMenu.addSeparator() - # Help > Documentation - self.aHelpDocs = QAction(self.tr("Documentation"), self) + # Help > User Manual (Online) + self.aHelpDocs = QAction(self.tr("User Manual (Online)"), self) self.aHelpDocs.setStatusTip(self.tr("Open documentation in browser")) - self.aHelpDocs.triggered.connect(self._openDocumentation) self.aHelpDocs.setShortcut("F1") + self.aHelpDocs.triggered.connect(lambda: self._openWebsite(nw.__docurl__)) self.helpMenu.addAction(self.aHelpDocs) + # Help > User Manual (PDF) + if self.mainConf.pdfDocs is not None: + self.aPdfDocs = QAction(self.tr("User Manual (PDF)"), self) + self.aPdfDocs.setStatusTip(self.tr("Open PDF documentation")) + self.aPdfDocs.setShortcut("Shift+F1") + self.aPdfDocs.triggered.connect(self._openUserManualFile) + self.helpMenu.addAction(self.aPdfDocs) + # Help > Separator self.helpMenu.addSeparator() diff --git a/nw/guimain.py b/nw/guimain.py index add555f4..61422a2d 100644 --- a/nw/guimain.py +++ b/nw/guimain.py @@ -1373,6 +1373,8 @@ class GuiMain(QMainWindow): # Help self.addAction(self.mainMenu.aHelpDocs) + if self.mainConf.pdfDocs is not None: + self.addAction(self.mainMenu.aPdfDocs) return True diff --git a/setup.py b/setup.py index 590c0f4a..a2345f61 100755 --- a/setup.py +++ b/setup.py @@ -222,35 +222,51 @@ def buildQtDocs(): ## -# Html Documentation Builder (docs) +# Html or PDF Documentation Builder (docs, docs_pdf) ## -def buildHtmlDocs(): - """This function will build the Sphinx HTML documentation. The files - are then copied into the nw/assets/help/html directory and can be - included in builds. +def buildLocalDocs(bldFmt="HTML"): + """This function will build the Sphinx HTML or PDF documentation. + For HTML, the files are then copied into the nw/assets/help/html + directory and can be included in builds. """ - buildDir = os.path.join("docs", "build", "html") - helpDir = os.path.join("nw", "assets", "help", "html") - print("") print("Building Documentation") print("======================") + print("Format: %s" % bldFmt) print("") + if bldFmt == "HTML": + buildDir = os.path.join("docs", "build", "html") + elif bldFmt == "PDF": + buildDir = os.path.join("docs", "build", "latex") + else: + print("Docs Build Error:") + return + buildFail = False try: subprocess.call(["make", "-C", "docs", "clean"]) - subprocess.call(["make", "-C", "docs", "html"]) + if bldFmt == "HTML": + subprocess.call(["make", "-C", "docs", "html"]) + elif bldFmt == "PDF": + subprocess.call(["make", "-C", "docs", "latexpdf"]) except Exception as e: print("Docs Build Error:") print(str(e)) buildFail = True try: - if os.path.isdir(helpDir): - shutil.rmtree(helpDir) - shutil.copytree(buildDir, helpDir) + if bldFmt == "HTML": + helpDir = os.path.join("nw", "assets", "help", "html") + if os.path.isdir(helpDir): + shutil.rmtree(helpDir) + shutil.copytree(buildDir, helpDir) + elif bldFmt == "PDF": + os.rename( + os.path.join(buildDir, "manual.pdf"), + os.path.join("nw", "assets", "help", "manual.pdf") + ) except Exception as e: print("Docs Build Error:") print(str(e)) @@ -262,7 +278,11 @@ def buildHtmlDocs(): print("") print("Dependencies:") print(" * pip install sphinx") - print(" * pip install sphinx-rtd-theme") + if bldFmt == "HTML": + print(" * pip install sphinx-rtd-theme") + elif bldFmt == "PDF": + print(" * Package latexmk") + print(" * LaTeX build system") sys.exit(1) else: print("Documentation build: OK") @@ -401,7 +421,7 @@ def makeMinimalPackage(targetOS): # Build docs try: - buildHtmlDocs() + buildLocalDocs(bldFmt="PDF") except Exception as e: print("Failed with error:") print(str(e)) @@ -440,7 +460,19 @@ def makeMinimalPackage(targetOS): if os.path.isfile(outFile): os.unlink(outFile) - rootFiles = ["LICENSE.md", "README.md", "CHANGELOG.md", "requirements.txt", "setup.py"] + # Add the manual also to the root + pdfDocs = os.path.join("nw", "assets", "help", "manual.pdf") + if os.path.isfile(pdfDocs): + os.rename(pdfDocs, "UserManual.pdf") + + rootFiles = [ + "CHANGELOG.md", + "LICENSE.md", + "README.md", + "requirements.txt", + "setup.py", + "UserManual.pdf", + ] with ZipFile(outFile, "w", compression=ZIP_DEFLATED, compresslevel=9) as zipObj: @@ -1195,7 +1227,8 @@ if __name__ == "__main__": "", "Additional Builds:", "", - " docs Build the help documentation as HTML." + " htmldocs Build the help documentation as HTML.", + " pdfdocs Build the help documentation as PDF (requires LaTeX).", " qthelp Build the help documentation for use with the Qt Assistant.", " qtlupdate Update the translation files for internationalisation.", " qtlrelease Build the language files for internationalisation.", @@ -1262,9 +1295,13 @@ if __name__ == "__main__": # Additional Builds # ================= - if "docs" in sys.argv: - sys.argv.remove("docs") - buildHtmlDocs() + if "htmldocs" in sys.argv: + sys.argv.remove("htmldocs") + buildLocalDocs(bldFmt="HTML") + + if "pdfdocs" in sys.argv: + sys.argv.remove("pdfdocs") + buildLocalDocs(bldFmt="PDF") if "qthelp" in sys.argv: sys.argv.remove("qthelp") diff --git a/tests/test_core/test_core_toodt.py b/tests/test_core/test_core_toodt.py index fd6f1c0b..f9c551e3 100644 --- a/tests/test_core/test_core_toodt.py +++ b/tests/test_core/test_core_toodt.py @@ -199,10 +199,10 @@ def testCoreToOdt_TextFormatting(mockGUI): # Incorrectly Formatted Text theDoc.initDocument() - theTxt = "A **few** _words" - theFmt = " _b b_ I " + theTxt = "A **few** _wordsXXX" + theFmt = " _b b_ I XXX" theDoc._addTextPar("Standard", oStyle, theTxt, theFmt=theFmt) - assert theDoc.getErrors() == [] + assert theDoc.getErrors() == ["Unknown format tag encountered"] assert xmlToText(theDoc._xText) == ( "" ""