def testCoreToOdt_SaveFlat(mockGUI, fncDir, outDir, refDir): """Test the document save functions. """ theProject = NWProject(mockGUI) theDoc = ToOdt(theProject, isFlat=True) theDoc._isNovel = True assert theDoc.setLanguage(None) is False assert theDoc.setLanguage("nb_NO") is True theDoc.setColourHeaders(True) theDoc._theText = ("## Chapter One\n\n" "Text\n\n" "## Chapter Two\n\n" "Text\n\n") theDoc.tokenizeText() theDoc.initDocument() theDoc.doConvert() theDoc.closeDocument() flatFile = os.path.join(fncDir, "document.fodt") testFile = os.path.join(outDir, "coreToOdt_SaveFlat_document.fodt") compFile = os.path.join(refDir, "coreToOdt_SaveFlat_document.fodt") theDoc.saveFlatXML(flatFile) assert os.path.isfile(flatFile) copyfile(flatFile, testFile) assert cmpFiles(testFile, compFile, [4, 5])
def testCoreItem_Methods(mockGUI): """Test the simple methods of the NWItem class. """ theProject = NWProject(mockGUI) theItem = NWItem(theProject) # Describe Me # =========== assert theItem.describeMe() == "None" theItem.setType("ROOT") assert theItem.describeMe() == "Root Folder" theItem.setType("FOLDER") assert theItem.describeMe() == "Folder" theItem.setType("FILE") theItem.setLayout("DOCUMENT") assert theItem.describeMe() == "Novel Document" assert theItem.describeMe("H0") == "Novel Document" assert theItem.describeMe("H1") == "Novel Title Page" assert theItem.describeMe("H2") == "Novel Chapter" assert theItem.describeMe("H3") == "Novel Scene" assert theItem.describeMe("H4") == "Novel Document" theItem.setLayout("NOTE") assert theItem.describeMe() == "Project Note" # Status + Icon # ============= theItem.setType("FILE") theItem.setStatus("Note") theItem.setImport("Minor") theItem.setClass("NOVEL") stT, stI = theItem.getImportStatus() assert stT == "Note" assert isinstance(stI, QIcon) theItem.setClass("CHARACTER") stT, stI = theItem.getImportStatus() assert stT == "Minor" assert isinstance(stI, QIcon) # Representation # ============== theItem.setName("New Item") theItem.setHandle("1234567890abc") theItem.setParent("4567890abcdef") assert repr(theItem) == "<NWItem handle=1234567890abc, parent=4567890abcdef, name='New Item'>" # Truthiness # ========== assert bool(theItem) is True theItem.setHandle(None) assert bool(theItem) is False
def testCoreToHtml_Methods(mockGUI): """Test all the other methods of the ToHtml class. """ theProject = NWProject(mockGUI) theHtml = ToHtml(theProject) 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_SpecialCases(mockGUI): """Test some special cases that has caused errors in the past. """ theProject = NWProject(mockGUI) theHtml = ToHtml(theProject) theHtml._isNovel = True # Greater/Lesser than symbols # =========================== theHtml._theText = "Text with > and < with some **bold text** in it.\n" theHtml.tokenizeText() theHtml.doConvert() assert theHtml.theResult == ( "<p>Text with > and < with some <strong>bold text</strong> in it.</p>\n" ) theHtml._theText = "Text with some <**bold text**> in it.\n" theHtml.tokenizeText() theHtml.doConvert() assert theHtml.theResult == ( "<p>Text with some <<strong>bold text</strong>> in it.</p>\n") theHtml._theText = "Let's > be > _difficult **shall** > we_?\n" theHtml.tokenizeText() theHtml.doConvert() assert theHtml.theResult == ( "<p>Let's > be > <em>difficult <strong>shall</strong> > we</em>?</p>\n" ) theHtml._theText = "Test > text _<**bold**>_ and more.\n" theHtml.tokenizeText() theHtml.doConvert() assert theHtml.theResult == ( "<p>Test > text <em><<strong>bold</strong>></em> and more.</p>\n" ) # Test for bug #950 # ================= # See: https://github.com/vkbo/novelWriter/issues/950 theHtml.setComments(True) theHtml._theText = "% Test > text _<**bold**>_ and more.\n" theHtml.tokenizeText() theHtml.doConvert() assert theHtml.theResult == ( "<p class='comment'>" "<strong>Comment:</strong> Test > text _<**bold**>_ and more." "</p>\n") theHtml._theText = "## Heading <1>\n" theHtml.tokenizeText() theHtml.doConvert() assert theHtml.theResult == ( "<h1 style='page-break-before: always;'>Heading <1></h1>\n")
def testCoreToOdt_Init(mockGUI): """Test initialisation of the ODT document. """ theProject = NWProject(mockGUI) mockGUI.theIndex = NWIndex(theProject) # Flat Doc # ======== theDoc = ToOdt(theProject, isFlat=True) theDoc.initDocument() # Document XML assert theDoc._dFlat is not None assert theDoc._dCont is None assert theDoc._dMeta is None assert theDoc._dStyl is None # Content XML assert theDoc._xMeta is not None assert theDoc._xFont is not None assert theDoc._xFnt2 is None assert theDoc._xStyl is not None assert theDoc._xAuto is not None assert theDoc._xAut2 is None assert theDoc._xMast is not None assert theDoc._xBody is not None assert theDoc._xText is not None # ODT Doc # ======= theDoc = ToOdt(theProject, isFlat=False) theDoc.initDocument() # Document XML assert theDoc._dFlat is None assert theDoc._dCont is not None assert theDoc._dMeta is not None assert theDoc._dStyl is not None # Content XML assert theDoc._xMeta is not None assert theDoc._xFont is not None assert theDoc._xFnt2 is not None assert theDoc._xStyl is not None assert theDoc._xAuto is not None assert theDoc._xAut2 is not None assert theDoc._xMast is not None assert theDoc._xBody is not None assert theDoc._xText is not None
def testCoreItem_ClassDefaults(mockGUI): """Test the setter for the default values. """ theProject = NWProject(mockGUI) theItem = NWItem(theProject) # Root items should not have their class updated theItem.setParent(None) theItem.setClass(nwItemClass.NO_CLASS) assert theItem.itemClass == nwItemClass.NO_CLASS theItem.setClassDefaults(nwItemClass.NOVEL) assert theItem.itemClass == nwItemClass.NO_CLASS # Non-root items should have their class updated theItem.setParent("0123456789abc") theItem.setClass(nwItemClass.NO_CLASS) assert theItem.itemClass == nwItemClass.NO_CLASS theItem.setClassDefaults(nwItemClass.NOVEL) assert theItem.itemClass == nwItemClass.NOVEL # Non-layout items should have their layout set based on class theItem.setParent("0123456789abc") theItem.setClass(nwItemClass.NO_CLASS) theItem.setLayout(nwItemLayout.NO_LAYOUT) assert theItem.itemLayout == nwItemLayout.NO_LAYOUT theItem.setClassDefaults(nwItemClass.NOVEL) assert theItem.itemLayout == nwItemLayout.DOCUMENT theItem.setParent("0123456789abc") theItem.setClass(nwItemClass.NO_CLASS) theItem.setLayout(nwItemLayout.NO_LAYOUT) assert theItem.itemLayout == nwItemLayout.NO_LAYOUT theItem.setClassDefaults(nwItemClass.PLOT) assert theItem.itemLayout == nwItemLayout.NOTE # If documents are not allowed in that class, the layout should be changed theItem.setParent("0123456789abc") theItem.setClass(nwItemClass.NO_CLASS) theItem.setLayout(nwItemLayout.DOCUMENT) assert theItem.itemLayout == nwItemLayout.DOCUMENT theItem.setClassDefaults(nwItemClass.PLOT) assert theItem.itemLayout == nwItemLayout.NOTE # In all cases, status and importance should no longer be None assert theItem.itemStatus is not None assert theItem.itemImport is not None
def testCoreToken_MarginFormat(mockGUI): """Test the tokenization of margin formats in the Tokenizer class. """ theProject = NWProject(mockGUI) theToken = BareTokenizer(theProject) theToken.setKeepMarkdown(True) # Alignment and Indentation dblIndent = Tokenizer.A_IND_L | Tokenizer.A_IND_R rIndAlign = Tokenizer.A_RIGHT | Tokenizer.A_IND_R theToken._theText = ( "Some regular text\n\n" "Some left-aligned text <<\n\n" ">> Some right-aligned text\n\n" ">> Some centered text <<\n\n" "> Left-indented block\n\n" "Right-indented block <\n\n" "> Double-indented block <\n\n" ">> Right-indent, right-aligned <\n\n" ) theToken.tokenizeText() assert theToken._theTokens == [ (Tokenizer.T_TEXT, 1, "Some regular text", [], Tokenizer.A_NONE), (Tokenizer.T_EMPTY, 2, "", None, Tokenizer.A_NONE), (Tokenizer.T_TEXT, 3, "Some left-aligned text", [], Tokenizer.A_LEFT), (Tokenizer.T_EMPTY, 4, "", None, Tokenizer.A_NONE), (Tokenizer.T_TEXT, 5, "Some right-aligned text", [], Tokenizer.A_RIGHT), (Tokenizer.T_EMPTY, 6, "", None, Tokenizer.A_NONE), (Tokenizer.T_TEXT, 7, "Some centered text", [], Tokenizer.A_CENTRE), (Tokenizer.T_EMPTY, 8, "", None, Tokenizer.A_NONE), (Tokenizer.T_TEXT, 9, "Left-indented block", [], Tokenizer.A_IND_L), (Tokenizer.T_EMPTY, 10, "", None, Tokenizer.A_NONE), (Tokenizer.T_TEXT, 11, "Right-indented block", [], Tokenizer.A_IND_R), (Tokenizer.T_EMPTY, 12, "", None, Tokenizer.A_NONE), (Tokenizer.T_TEXT, 13, "Double-indented block", [], dblIndent), (Tokenizer.T_EMPTY, 14, "", None, Tokenizer.A_NONE), (Tokenizer.T_TEXT, 15, "Right-indent, right-aligned", [], rIndAlign), (Tokenizer.T_EMPTY, 16, "", None, Tokenizer.A_NONE), (Tokenizer.T_EMPTY, 16, "", None, Tokenizer.A_NONE), ] assert theToken.theMarkdown[-1] == ( "Some regular text\n\n" "Some left-aligned text\n\n" "Some right-aligned text\n\n" "Some centered text\n\n" "Left-indented block\n\n" "Right-indented block\n\n" "Double-indented block\n\n" "Right-indent, right-aligned\n\n\n" )
def testCoreToMarkdown_Format(mockGUI): """Test all the formatters for the ToMarkdown class. """ theProject = NWProject(mockGUI) mockGUI.theIndex = NWIndex(theProject) theMD = ToMarkdown(theProject) assert theMD._formatKeywords("", theMD.A_NONE) == "" assert theMD._formatKeywords("tag: Jane", theMD.A_NONE) == "**Tag:** Jane\n\n" assert theMD._formatKeywords("tag: Jane, John", theMD.A_NONE) == "**Tag:** Jane, John\n\n" assert theMD._formatKeywords("tag: Jane", theMD.A_Z_BTMMRG) == "**Tag:** Jane \n"
def testCoreDocument_Methods(mockGUI, nwMinimal): """Test other methods of the NWDoc class. """ theProject = NWProject(mockGUI) assert theProject.openProject(nwMinimal) assert theProject.projPath == nwMinimal sHandle = "8c659a11cd429" theDoc = NWDoc(theProject, sHandle) docPath = os.path.join(nwMinimal, "content", sHandle + ".nwd") assert theDoc.readDocument() == "### New Scene\n\n" # Check location assert theDoc.getFileLocation() == docPath # Check the item assert theDoc.getCurrentItem() is not None assert theDoc.getCurrentItem().itemHandle == sHandle # Check the meta theName, theParent, theClass, theLayout = theDoc.getMeta() assert theName == "New Scene" assert theParent == "a6d311a93600a" assert theClass == nwItemClass.NOVEL assert theLayout == nwItemLayout.DOCUMENT # Add meta data garbage assert theDoc.writeDocument("%%~ stuff\n### Test File\n\nText ...\n\n") assert readFile(docPath) == ("%%~name: New Scene\n" f"%%~path: a6d311a93600a/{sHandle}\n" "%%~kind: NOVEL/DOCUMENT\n" "%%~ stuff\n" "### Test File\n\n" "Text ...\n\n") assert theDoc.readDocument() == "### Test File\n\nText ...\n\n"
def testCoreToMarkdown_Complex(mockGUI, fncDir): """Test the save method of the ToMarkdown class. """ theProject = NWProject(mockGUI) theMD = ToMarkdown(theProject) theMD._isNovel = True # 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 = [ "# My Novel\n\n**By Jane Doh**\n\n", "## Chapter 1\n\nThe text of chapter one.\n\n", "### Scene 1\n\nThe text of scene one.\n\n", "#### A Section\n\nMore text in scene one.\n\n", "## Chapter 2\n\nThe text of chapter two.\n\n", "### Scene 2\n\nThe text of scene two.\n\n", "#### A Section\n\n\tMore text in scene two.\n\n", ] for i in range(len(docText)): theMD._theText = docText[i] theMD.doPreProcessing() theMD.tokenizeText() theMD.doConvert() assert theMD.theResult == resText[i] assert theMD.fullMD == resText assert theMD.getFullResultSize() == len("".join(resText)) theMD.replaceTabs(nSpaces=4, spaceChar=" ") resText[6] = "#### A Section\n\n More text in scene two.\n\n" # Check File # ========== saveFile = os.path.join(fncDir, "outFile.md") theMD.saveMarkdown(saveFile) assert readFile(saveFile) == "".join(resText)
def testCoreToOdt_Format(mockGUI): """Test the formatters for the ToOdt class. """ theProject = NWProject(mockGUI) theDoc = ToOdt(theProject, isFlat=True) assert theDoc._formatSynopsis("synopsis text") == ( "**Synopsis:** synopsis text", "_B b_ ") assert theDoc._formatComments("comment text") == ( "**Comment:** comment text", "_B b_ ") assert theDoc._formatKeywords("") == "" assert theDoc._formatKeywords("tag: Jane") == ("**Tag:** Jane", "_B b_ ") assert theDoc._formatKeywords("char: Bod, Jane") == ( "**Characters:** Bod, Jane", "_B b_ ")
def testCoreToMarkdown_ConvertDirect(mockGUI): """Test the converter directly using the ToMarkdown class. """ theProject = NWProject(mockGUI) mockGUI.theIndex = NWIndex(theProject) theMD = ToMarkdown(theProject) theMD._isNovel = True theMD._isNote = False # Special Titles # ============== # Title theMD._theTokens = [ (theMD.T_TITLE, 1, "A Title", None, theMD.A_PBB | theMD.A_CENTRE), (theMD.T_EMPTY, 1, "", None, theMD.A_NONE), ] theMD.doConvert() assert theMD.theResult == "# A Title\n\n" # Unnumbered theMD._theTokens = [ (theMD.T_UNNUM, 1, "Prologue", None, theMD.A_PBB), (theMD.T_EMPTY, 1, "", None, theMD.A_NONE), ] theMD.doConvert() assert theMD.theResult == "## Prologue\n\n" # Separators # ========== # Separator theMD._theTokens = [ (theMD.T_SEP, 1, "* * *", None, theMD.A_CENTRE), (theMD.T_EMPTY, 1, "", None, theMD.A_NONE), ] theMD.doConvert() assert theMD.theResult == "* * *\n\n" # Skip theMD._theTokens = [ (theMD.T_SKIP, 1, "", None, theMD.A_NONE), (theMD.T_EMPTY, 1, "", None, theMD.A_NONE), ] theMD.doConvert() assert theMD.theResult == "\n\n\n"
def testCoreToOdt_ConvertDirect(mockGUI): """Test the converter directly using the ToOdt class to reach some otherwise hard to reach conditions. """ theProject = NWProject(mockGUI) mockGUI.theIndex = NWIndex(theProject) theDoc = ToOdt(theProject, isFlat=True) theDoc._isNovel = True # Justified theDoc = ToOdt(theProject, isFlat=True) theDoc._theTokens = [ (theDoc.T_TEXT, 1, "This is a paragraph", [], theDoc.A_JUSTIFY), (theDoc.T_EMPTY, 1, "", None, theDoc.A_NONE), ] theDoc.initDocument() theDoc.doConvert() theDoc.closeDocument() assert ('<style:style style:name="P1" style:family="paragraph" ' 'style:parent-style-name="Text_20_body">' '<style:paragraph-properties fo:text-align="justify"/>' '</style:style>') in xmlToText(theDoc._xAuto) assert xmlToText(theDoc._xText) == ( '<office:text>' '<text:p text:style-name="P1">This is a paragraph</text:p>' '</office:text>') # Page Break After theDoc = ToOdt(theProject, isFlat=True) theDoc._theTokens = [ (theDoc.T_TEXT, 1, "This is a paragraph", [], theDoc.A_PBA), (theDoc.T_EMPTY, 1, "", None, theDoc.A_NONE), ] theDoc.initDocument() theDoc.doConvert() theDoc.closeDocument() assert ('<style:style style:name="P1" style:family="paragraph" ' 'style:parent-style-name="Text_20_body">' '<style:paragraph-properties fo:break-after="page"/>' '</style:style>') in xmlToText(theDoc._xAuto) assert xmlToText(theDoc._xText) == ( '<office:text>' '<text:p text:style-name="P1">This is a paragraph</text:p>' '</office:text>')
def testCoreToHtml_Format(mockGUI): """Test all the formatters for the ToHtml class. """ theProject = NWProject(mockGUI) mockGUI.theIndex = NWIndex(theProject) theHtml = ToHtml(theProject) # 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") == ( "<span class='tags'>Tag:</span> <a name='tag_Jane'>Jane</a>") assert theHtml._formatKeywords("char: Bod, Jane") == ( "<span class='tags'>Characters:</span> " "<a href='#tag_Bod'>Bod</a>, " "<a href='#tag_Jane'>Jane</a>") # 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") == ( "<span class='tags'>Tag:</span> <a name='tag_Jane'>Jane</a>") assert theHtml._formatKeywords("char: Bod, Jane") == ( "<span class='tags'>Characters:</span> " "<a href='#char=Bod'>Bod</a>, " "<a href='#char=Jane'>Jane</a>")
def testCoreOptions_SetGet(mockGUI): """Test setting and getting values from the OptionState class. """ theProject = NWProject(mockGUI) theOpts = OptionState(theProject) # Set invalid values assert not theOpts.setValue("MockGroup", "mockItem", None) assert not theOpts.setValue("GuiBuildNovel", "mockItem", None) # Set valid value assert theOpts.setValue("GuiBuildNovel", "winWidth", 100) # Set some values of different types assert theOpts.setValue("GuiBuildNovel", "winWidth", 100) assert theOpts.setValue("GuiBuildNovel", "winHeight", 12.34) assert theOpts.setValue("GuiBuildNovel", "addNovel", True) assert theOpts.setValue("GuiBuildNovel", "textFont", "Cantarell") # Generic get, doesn't check type assert theOpts.getValue("GuiBuildNovel", "winWidth", None) == 100 assert theOpts.getValue("GuiBuildNovel", "winHeight", None) == 12.34 assert theOpts.getValue("GuiBuildNovel", "addNovel", None) is True assert theOpts.getValue("GuiBuildNovel", "textFont", None) == "Cantarell" assert theOpts.getValue("GuiBuildNovel", "mockItem", None) is None # Get type-specific assert theOpts.getString("GuiBuildNovel", "winWidth", None) is None assert theOpts.getString("GuiBuildNovel", "mockItem", None) is None assert theOpts.getInt("GuiBuildNovel", "winWidth", None) == 100 assert theOpts.getInt("GuiBuildNovel", "textFont", None) is None assert theOpts.getInt("GuiBuildNovel", "mockItem", None) is None assert theOpts.getFloat("GuiBuildNovel", "winWidth", None) == 100.0 assert theOpts.getFloat("GuiBuildNovel", "textFont", None) is None assert theOpts.getFloat("GuiBuildNovel", "mockItem", None) is None assert theOpts.getBool("GuiBuildNovel", "addNovel", None) is True assert theOpts.getBool("GuiBuildNovel", "mockItem", None) is None
def testCoreItem_ConvertFromFmt12(mockGUI): """Test the setter for all the nwItemLayout values for the NWItem class using the class names that were present in file format 1.2. """ theProject = NWProject(mockGUI) theItem = NWItem(theProject) # Deprecated Layouts theItem.setLayout("TITLE") assert theItem.itemLayout == nwItemLayout.DOCUMENT theItem.setLayout("PAGE") assert theItem.itemLayout == nwItemLayout.DOCUMENT theItem.setLayout("BOOK") assert theItem.itemLayout == nwItemLayout.DOCUMENT theItem.setLayout("PARTITION") assert theItem.itemLayout == nwItemLayout.DOCUMENT theItem.setLayout("UNNUMBERED") assert theItem.itemLayout == nwItemLayout.DOCUMENT theItem.setLayout("CHAPTER") assert theItem.itemLayout == nwItemLayout.DOCUMENT theItem.setLayout("SCENE") assert theItem.itemLayout == nwItemLayout.DOCUMENT theItem.setLayout("MUMBOJUMBO") assert theItem.itemLayout == nwItemLayout.NO_LAYOUT
def testCoreItem_ClassSetter(mockGUI): """Test the setter for all the nwItemClass values for the NWItem class. """ theProject = NWProject(mockGUI) theItem = NWItem(theProject) # Class theItem.setClass(None) assert theItem.itemClass == nwItemClass.NO_CLASS theItem.setClass("NONSENSE") assert theItem.itemClass == nwItemClass.NO_CLASS theItem.setClass("NO_CLASS") assert theItem.itemClass == nwItemClass.NO_CLASS theItem.setClass("NOVEL") assert theItem.itemClass == nwItemClass.NOVEL theItem.setClass("PLOT") assert theItem.itemClass == nwItemClass.PLOT theItem.setClass("CHARACTER") assert theItem.itemClass == nwItemClass.CHARACTER theItem.setClass("WORLD") assert theItem.itemClass == nwItemClass.WORLD theItem.setClass("TIMELINE") assert theItem.itemClass == nwItemClass.TIMELINE theItem.setClass("OBJECT") assert theItem.itemClass == nwItemClass.OBJECT theItem.setClass("ENTITY") assert theItem.itemClass == nwItemClass.ENTITY theItem.setClass("CUSTOM") assert theItem.itemClass == nwItemClass.CUSTOM theItem.setClass("ARCHIVE") assert theItem.itemClass == nwItemClass.ARCHIVE theItem.setClass("TRASH") assert theItem.itemClass == nwItemClass.TRASH theItem.setClass(nwItemClass.NOVEL) assert theItem.itemClass == nwItemClass.NOVEL
def testCoreItem_LayoutSetter(mockGUI): """Test the setter for all the nwItemLayout values for the NWItem class. """ theProject = NWProject(mockGUI) theItem = NWItem(theProject) # Faulty Layouts theItem.setLayout(None) assert theItem.itemLayout == nwItemLayout.NO_LAYOUT theItem.setLayout("NONSENSE") assert theItem.itemLayout == nwItemLayout.NO_LAYOUT # Current Layouts theItem.setLayout("NO_LAYOUT") assert theItem.itemLayout == nwItemLayout.NO_LAYOUT theItem.setLayout("DOCUMENT") assert theItem.itemLayout == nwItemLayout.DOCUMENT theItem.setLayout("NOTE") assert theItem.itemLayout == nwItemLayout.NOTE # Alternative theItem.setLayout(nwItemLayout.NOTE) assert theItem.itemLayout == nwItemLayout.NOTE
def testCoreItem_TypeSetter(mockGUI): """Test the setter for all the nwItemType values for the NWItem class. """ theProject = NWProject(mockGUI) theItem = NWItem(theProject) # Type theItem.setType(None) assert theItem.itemType == nwItemType.NO_TYPE theItem.setType("NONSENSE") assert theItem.itemType == nwItemType.NO_TYPE theItem.setType("NO_TYPE") assert theItem.itemType == nwItemType.NO_TYPE theItem.setType("ROOT") assert theItem.itemType == nwItemType.ROOT theItem.setType("FOLDER") assert theItem.itemType == nwItemType.FOLDER theItem.setType("FILE") assert theItem.itemType == nwItemType.FILE # Alternative theItem.setType(nwItemType.ROOT) assert theItem.itemType == nwItemType.ROOT
def testCoreToken_TextFormat(mockGUI): """Test the tokenization of text formats in the Tokenizer class. """ theProject = NWProject(mockGUI) theToken = BareTokenizer(theProject) theToken.setKeepMarkdown(True) # Text theToken._theText = "Some plain text\non two lines\n\n\n" theToken.tokenizeText() assert theToken._theTokens == [ (Tokenizer.T_TEXT, 1, "Some plain text", [], Tokenizer.A_NONE), (Tokenizer.T_TEXT, 2, "on two lines", [], Tokenizer.A_NONE), (Tokenizer.T_EMPTY, 3, "", None, Tokenizer.A_NONE), (Tokenizer.T_EMPTY, 4, "", None, Tokenizer.A_NONE), (Tokenizer.T_EMPTY, 4, "", None, Tokenizer.A_NONE), ] assert theToken.theMarkdown[-1] == "Some plain text\non two lines\n\n\n\n" theToken.setBodyText(False) theToken.tokenizeText() assert theToken._theTokens == [ (Tokenizer.T_EMPTY, 3, "", None, Tokenizer.A_NONE), (Tokenizer.T_EMPTY, 4, "", None, Tokenizer.A_NONE), (Tokenizer.T_EMPTY, 4, "", None, Tokenizer.A_NONE), ] assert theToken.theMarkdown[-1] == "\n\n\n" theToken.setBodyText(True) # Text Emphasis theToken._theText = "Some **bolded text** on this lines\n" theToken.tokenizeText() assert theToken._theTokens == [ (Tokenizer.T_TEXT, 1, "Some **bolded text** on this lines", [ [5, 2, Tokenizer.FMT_B_B], [18, 2, Tokenizer.FMT_B_E], ], Tokenizer.A_NONE), (Tokenizer.T_EMPTY, 1, "", None, Tokenizer.A_NONE), ] assert theToken.theMarkdown[-1] == "Some **bolded text** on this lines\n\n" theToken._theText = "Some _italic text_ on this lines\n" theToken.tokenizeText() assert theToken._theTokens == [ (Tokenizer.T_TEXT, 1, "Some _italic text_ on this lines", [ [5, 1, Tokenizer.FMT_I_B], [17, 1, Tokenizer.FMT_I_E], ], Tokenizer.A_NONE), (Tokenizer.T_EMPTY, 1, "", None, Tokenizer.A_NONE), ] assert theToken.theMarkdown[-1] == "Some _italic text_ on this lines\n\n" theToken._theText = "Some **_bold italic text_** on this lines\n" theToken.tokenizeText() assert theToken._theTokens == [ (Tokenizer.T_TEXT, 1, "Some **_bold italic text_** on this lines", [ [5, 2, Tokenizer.FMT_B_B], [7, 1, Tokenizer.FMT_I_B], [24, 1, Tokenizer.FMT_I_E], [25, 2, Tokenizer.FMT_B_E], ], Tokenizer.A_NONE), (Tokenizer.T_EMPTY, 1, "", None, Tokenizer.A_NONE), ] assert theToken.theMarkdown[ -1] == "Some **_bold italic text_** on this lines\n\n" theToken._theText = "Some ~~strikethrough text~~ on this lines\n" theToken.tokenizeText() assert theToken._theTokens == [ (Tokenizer.T_TEXT, 1, "Some ~~strikethrough text~~ on this lines", [ [5, 2, Tokenizer.FMT_D_B], [25, 2, Tokenizer.FMT_D_E], ], Tokenizer.A_NONE), (Tokenizer.T_EMPTY, 1, "", None, Tokenizer.A_NONE), ] assert theToken.theMarkdown[ -1] == "Some ~~strikethrough text~~ on this lines\n\n" theToken._theText = "Some **nested bold and _italic_ and ~~strikethrough~~ text** here\n" theToken.tokenizeText() assert theToken._theTokens == [ (Tokenizer.T_TEXT, 1, "Some **nested bold and _italic_ and ~~strikethrough~~ text** here", [ [5, 2, Tokenizer.FMT_B_B], [23, 1, Tokenizer.FMT_I_B], [30, 1, Tokenizer.FMT_I_E], [36, 2, Tokenizer.FMT_D_B], [51, 2, Tokenizer.FMT_D_E], [58, 2, Tokenizer.FMT_B_E], ], Tokenizer.A_NONE), (Tokenizer.T_EMPTY, 1, "", None, Tokenizer.A_NONE), ] assert theToken.theMarkdown[-1] == ( "Some **nested bold and _italic_ and ~~strikethrough~~ text** here\n\n" )
def testCoreItem_Setters(mockGUI, mockRnd): """Test all the simple setters for the NWItem class. """ theProject = NWProject(mockGUI) theItem = NWItem(theProject) statusKeys = ["s000000", "s000001", "s000002", "s000003"] importKeys = ["i000004", "i000005", "i000006", "i000007"] # Name theItem.setName("A Name") assert theItem.itemName == "A Name" theItem.setName("\t A Name ") assert theItem.itemName == "A Name" theItem.setName("\t A\t\u2009\u202f\u2002\u2003\u2028\u2029Name ") assert theItem.itemName == "A Name" theItem.setName(123) assert theItem.itemName == "" # Handle theItem.setHandle(123) assert theItem.itemHandle is None theItem.setHandle("0123456789abcdef") assert theItem.itemHandle is None theItem.setHandle("0123456789abg") assert theItem.itemHandle is None theItem.setHandle("0123456789abc") assert theItem.itemHandle == "0123456789abc" # Parent theItem.setParent(None) assert theItem.itemParent is None theItem.setParent(123) assert theItem.itemParent is None theItem.setParent("0123456789abcdef") assert theItem.itemParent is None theItem.setParent("0123456789abg") assert theItem.itemParent is None theItem.setParent("0123456789abc") assert theItem.itemParent == "0123456789abc" # Root theItem.setRoot(None) assert theItem.itemRoot is None theItem.setRoot(123) assert theItem.itemRoot is None theItem.setRoot("0123456789abcdef") assert theItem.itemRoot is None theItem.setRoot("0123456789abg") assert theItem.itemRoot is None theItem.setRoot("0123456789abc") assert theItem.itemRoot == "0123456789abc" # Order theItem.setOrder(None) assert theItem.itemOrder == 0 theItem.setOrder("1") assert theItem.itemOrder == 1 theItem.setOrder(1) assert theItem.itemOrder == 1 # Importance theItem._class = nwItemClass.CHARACTER theItem.setImport("Word") assert theItem.itemImport == importKeys[0] # Default for key in importKeys: theItem.setImport(key) assert theItem.itemImport == key # Status theItem._class = nwItemClass.NOVEL theItem.setStatus("Word") assert theItem.itemStatus == statusKeys[0] # Default for key in statusKeys: theItem.setStatus(key) assert theItem.itemStatus == key # Status/Importance Wrapper theItem._class = nwItemClass.CHARACTER for key in importKeys: theItem.setImport(key) assert theItem.itemImport == key assert theItem.itemStatus == statusKeys[3] # Should not change theItem._class = nwItemClass.NOVEL for key in statusKeys: theItem.setStatus(key) assert theItem.itemImport == importKeys[3] # Should not change assert theItem.itemStatus == key # Expanded theItem.setExpanded(8) assert theItem.isExpanded is False theItem.setExpanded(None) assert theItem.isExpanded is False theItem.setExpanded("None") assert theItem.isExpanded is False theItem.setExpanded("What?") assert theItem.isExpanded is False theItem.setExpanded("True") assert theItem.isExpanded is True theItem.setExpanded(True) assert theItem.isExpanded is True # Exported theItem.setExported(8) assert theItem.isExported is False theItem.setExported(None) assert theItem.isExported is False theItem.setExported("None") assert theItem.isExported is False theItem.setExported("What?") assert theItem.isExported is False theItem.setExported("True") assert theItem.isExported is True theItem.setExported(True) assert theItem.isExported is True # CharCount theItem.setCharCount(None) assert theItem.charCount == 0 theItem.setCharCount("1") assert theItem.charCount == 1 theItem.setCharCount(1) assert theItem.charCount == 1 # WordCount theItem.setWordCount(None) assert theItem.wordCount == 0 theItem.setWordCount("1") assert theItem.wordCount == 1 theItem.setWordCount(1) assert theItem.wordCount == 1 # ParaCount theItem.setParaCount(None) assert theItem.paraCount == 0 theItem.setParaCount("1") assert theItem.paraCount == 1 theItem.setParaCount(1) assert theItem.paraCount == 1 # CursorPos theItem.setCursorPos(None) assert theItem.cursorPos == 0 theItem.setCursorPos("1") assert theItem.cursorPos == 1 theItem.setCursorPos(1) assert theItem.cursorPos == 1 # Initial Count theItem.setWordCount(234) theItem.saveInitialCount() assert theItem.initCount == 234
def testCoreItem_ClassSetter(mockGUI): """Test the setter for all the nwItemClass values for the NWItem class. """ theProject = NWProject(mockGUI) theItem = NWItem(theProject) # Class theItem.setClass(None) assert theItem.itemClass == nwItemClass.NO_CLASS theItem.setClass("NONSENSE") assert theItem.itemClass == nwItemClass.NO_CLASS theItem.setClass("NO_CLASS") assert theItem.itemClass == nwItemClass.NO_CLASS assert theItem.isNovelLike() is False assert theItem.documentAllowed() is False assert theItem.isInactive() is True theItem.setClass("NOVEL") assert theItem.itemClass == nwItemClass.NOVEL assert theItem.isNovelLike() is True assert theItem.documentAllowed() is True assert theItem.isInactive() is False theItem.setClass("PLOT") assert theItem.itemClass == nwItemClass.PLOT assert theItem.isNovelLike() is False assert theItem.documentAllowed() is False assert theItem.isInactive() is False theItem.setClass("CHARACTER") assert theItem.itemClass == nwItemClass.CHARACTER assert theItem.isNovelLike() is False assert theItem.documentAllowed() is False assert theItem.isInactive() is False theItem.setClass("WORLD") assert theItem.itemClass == nwItemClass.WORLD assert theItem.isNovelLike() is False assert theItem.documentAllowed() is False assert theItem.isInactive() is False theItem.setClass("TIMELINE") assert theItem.itemClass == nwItemClass.TIMELINE assert theItem.isNovelLike() is False assert theItem.documentAllowed() is False assert theItem.isInactive() is False theItem.setClass("OBJECT") assert theItem.itemClass == nwItemClass.OBJECT assert theItem.isNovelLike() is False assert theItem.documentAllowed() is False assert theItem.isInactive() is False theItem.setClass("ENTITY") assert theItem.itemClass == nwItemClass.ENTITY assert theItem.isNovelLike() is False assert theItem.documentAllowed() is False assert theItem.isInactive() is False theItem.setClass("CUSTOM") assert theItem.itemClass == nwItemClass.CUSTOM assert theItem.isNovelLike() is False assert theItem.documentAllowed() is False assert theItem.isInactive() is False theItem.setClass("ARCHIVE") assert theItem.itemClass == nwItemClass.ARCHIVE assert theItem.isNovelLike() is True assert theItem.documentAllowed() is True assert theItem.isInactive() is True theItem.setClass("TRASH") assert theItem.itemClass == nwItemClass.TRASH assert theItem.isNovelLike() is False assert theItem.documentAllowed() is True assert theItem.isInactive() is True # Alternative theItem.setClass(nwItemClass.NOVEL) assert theItem.itemClass == nwItemClass.NOVEL
def testCoreToken_MetaFormat(mockGUI): """Test the tokenization of meta formats in the Tokenizer class. """ theProject = NWProject(mockGUI) theToken = BareTokenizer(theProject) theToken.setKeepMarkdown(True) # Comment theToken._theText = "% A comment\n" theToken.tokenizeText() assert theToken._theTokens == [ (Tokenizer.T_COMMENT, 1, "A comment", None, Tokenizer.A_NONE), (Tokenizer.T_EMPTY, 1, "", None, Tokenizer.A_NONE), ] assert theToken.theMarkdown[-1] == "\n" theToken.setComments(True) theToken.tokenizeText() assert theToken.theMarkdown[-1] == "% A comment\n\n" # Symopsis theToken._theText = "%synopsis: The synopsis\n" theToken.tokenizeText() assert theToken._theTokens == [ (Tokenizer.T_SYNOPSIS, 1, "The synopsis", None, Tokenizer.A_NONE), (Tokenizer.T_EMPTY, 1, "", None, Tokenizer.A_NONE), ] theToken._theText = "% synopsis: The synopsis\n" theToken.tokenizeText() assert theToken._theTokens == [ (Tokenizer.T_SYNOPSIS, 1, "The synopsis", None, Tokenizer.A_NONE), (Tokenizer.T_EMPTY, 1, "", None, Tokenizer.A_NONE), ] assert theToken.theMarkdown[-1] == "\n" theToken.setSynopsis(True) theToken.tokenizeText() assert theToken.theMarkdown[-1] == "% synopsis: The synopsis\n\n" # Keyword theToken._theText = "@char: Bod\n" theToken.tokenizeText() assert theToken._theTokens == [ (Tokenizer.T_KEYWORD, 1, "char: Bod", None, Tokenizer.A_NONE), (Tokenizer.T_EMPTY, 1, "", None, Tokenizer.A_NONE), ] assert theToken.theMarkdown[-1] == "\n" theToken.setKeywords(True) theToken.tokenizeText() assert theToken.theMarkdown[-1] == "@char: Bod\n\n" theToken._theText = "@pov: Bod\n@plot: Main\n@location: Europe\n" theToken.tokenizeText() styTop = Tokenizer.A_NONE | Tokenizer.A_Z_BTMMRG styMid = Tokenizer.A_NONE | Tokenizer.A_Z_BTMMRG | Tokenizer.A_Z_TOPMRG styBtm = Tokenizer.A_NONE | Tokenizer.A_Z_TOPMRG assert theToken._theTokens == [ (Tokenizer.T_KEYWORD, 1, "pov: Bod", None, styTop), (Tokenizer.T_KEYWORD, 2, "plot: Main", None, styMid), (Tokenizer.T_KEYWORD, 3, "location: Europe", None, styBtm), (Tokenizer.T_EMPTY, 3, "", None, Tokenizer.A_NONE), ] assert theToken.theMarkdown[ -1] == "@pov: Bod\n@plot: Main\n@location: Europe\n\n"
def testCoreToHtml_ConvertDirect(mockGUI): """Test the converter directly using the ToHtml class. """ theProject = NWProject(mockGUI) mockGUI.theIndex = NWIndex(theProject) theHtml = ToHtml(theProject) theHtml._isNovel = True theHtml._isNote = False theHtml.setLinkHeaders(True) # Special Titles # ============== # Title theHtml._theTokens = [ (theHtml.T_TITLE, 1, "A Title", None, theHtml.A_PBB | 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: always;'>" "<a name='T000001'></a>A Title</h1>\n") # Unnumbered theHtml._theTokens = [ (theHtml.T_UNNUM, 1, "Prologue", None, theHtml.A_PBB), (theHtml.T_EMPTY, 1, "", None, theHtml.A_NONE), ] theHtml.doConvert() assert theHtml.theResult == ("<h1 style='page-break-before: always;'>" "<a name='T000001'></a>Prologue</h1>\n") # Separators # ========== # 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' style='text-align: center;'>* * *</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" # Alignment # ========= 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 # ========== # 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" ) # Indent # ====== # Indent Left theHtml._theTokens = [ (theHtml.T_TEXT, 1, "Some text ...", [], theHtml.A_IND_L), (theHtml.T_EMPTY, 2, "", None, theHtml.A_NONE), ] theHtml.doConvert() assert theHtml.theResult == ( "<p style='margin-left: 40px;'>Some text ...</p>\n") # Indent Right theHtml._theTokens = [ (theHtml.T_TEXT, 1, "Some text ...", [], theHtml.A_IND_R), (theHtml.T_EMPTY, 2, "", None, theHtml.A_NONE), ] theHtml.doConvert() assert theHtml.theResult == ( "<p style='margin-right: 40px;'>Some text ...</p>\n")
def testCoreToHtml_Complex(mockGUI, fncDir): """Test the save method of the ToHtml class. """ theProject = NWProject(mockGUI) theHtml = ToHtml(theProject) theHtml._isNovel = True # 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 class='title' style='text-align: center;'>My Novel</h1>\n" "<p><strong>By Jane Doh</strong></p>\n"), ("<h1 style='page-break-before: always;'>Chapter 1</h1>\n" "<p>The text of chapter one.</p>\n"), ("<h2>Scene 1</h2>\n" "<p>The text of scene one.</p>\n"), ("<h3>A Section</h3>\n" "<p>More text in scene one.</p>\n"), ("<h1 style='page-break-before: always;'>Chapter 2</h1>\n" "<p>The text of chapter two.</p>\n"), ("<h2>Scene 2</h2>\n" "<p>The text of scene two.</p>\n"), ("<h3>A Section</h3>\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] = "<h3>A Section</h3>\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 testCoreToHtml_ConvertFormat(mockGUI): """Test the tokenizer and converter chain using the ToHtml class. """ theProject = NWProject(mockGUI) mockGUI.theIndex = NWIndex(theProject) theHtml = ToHtml(theProject) # Novel Files Headers # =================== theHtml._isNovel = True theHtml._isNote = False theHtml._isFirst = True # Header 1 theHtml._theText = "# Partition\n" theHtml.tokenizeText() theHtml.doConvert() assert theHtml.theResult == ( "<h1 class='title' style='text-align: center;'>Partition</h1>\n") # Header 2 theHtml._theText = "## Chapter Title\n" theHtml.tokenizeText() theHtml.doConvert() assert theHtml.theResult == ( "<h1 style='page-break-before: always;'>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" # Title theHtml._theText = "#! Title\n" theHtml.tokenizeText() theHtml.doConvert() assert theHtml.theResult == ( "<h1 class='title' style='text-align: center;'>Title</h1>\n") # Unnumbered theHtml._theText = "##! Prologue\n" theHtml.tokenizeText() theHtml.doConvert() assert theHtml.theResult == "<h1 style='page-break-before: always;'>Prologue</h1>\n" # Note Files Headers # ================== theHtml._isNovel = False theHtml._isNote = True theHtml._isFirst = True 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" # Title theHtml._theText = "#! Heading One\n" theHtml.tokenizeText() theHtml.doConvert() assert theHtml.theResult == ( "<h1 style='text-align: center;'><a name='T000001'></a>Heading One</h1>\n" ) # Unnumbered theHtml._theText = "##! Heading Two\n" theHtml.tokenizeText() theHtml.doConvert() assert theHtml.theResult == "<h2><a name='T000001'></a>Heading Two</h2>\n" # Paragraphs # ========== # 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") # 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 testCoreItem_XMLPackUnpack(mockGUI, caplog, mockRnd): """Test packing and unpacking XML objects for the NWItem class. """ theProject = NWProject(mockGUI) nwXML = etree.Element("novelWriterXML") statusKeys = ["s000000", "s000001", "s000002", "s000003"] importKeys = ["i000004", "i000005", "i000006", "i000007"] # File # ==== theItem = NWItem(theProject) theItem.setHandle("0123456789abc") theItem.setParent("0123456789abc") theItem.setRoot("0123456789abc") theItem.setOrder(1) theItem.setName("A Name") theItem.setClass("NOVEL") theItem.setType("FILE") theItem.setImport(importKeys[3]) theItem.setLayout("NOTE") theItem.setExported(False) theItem.setParaCount(3) theItem.setWordCount(5) theItem.setCharCount(7) theItem.setCursorPos(11) # Pack xContent = etree.SubElement(nwXML, "content") theItem.packXML(xContent) assert etree.tostring(xContent, pretty_print=False, encoding="utf-8") == ( b'<content>' b'<item handle="0123456789abc" parent="0123456789abc" root="0123456789abc" order="1" ' b'type="FILE" class="NOVEL" layout="NOTE"><meta expanded="False" charCount="7" ' b'wordCount="5" paraCount="3" cursorPos="11"/><name status="None" import="%s" ' b'exported="False">A Name</name></item>' b'</content>') % bytes(importKeys[3], encoding="utf8") # Unpack theItem = NWItem(theProject) assert theItem.unpackXML(xContent[0]) assert theItem.itemHandle == "0123456789abc" assert theItem.itemParent == "0123456789abc" assert theItem.itemRoot == "0123456789abc" assert theItem.itemOrder == 1 assert theItem.isExported is False assert theItem.paraCount == 3 assert theItem.wordCount == 5 assert theItem.charCount == 7 assert theItem.cursorPos == 11 assert theItem.itemClass == nwItemClass.NOVEL assert theItem.itemType == nwItemType.FILE assert theItem.itemLayout == nwItemLayout.NOTE assert theItem.itemStatus == statusKeys[ 0] # Was None, should now be default assert theItem.itemImport == importKeys[3] # Folder # ====== theItem = NWItem(theProject) theItem.setHandle("0123456789abc") theItem.setParent("0123456789abc") theItem.setRoot("0123456789abc") theItem.setOrder(1) theItem.setName("A Name") theItem.setClass("NOVEL") theItem.setType("FOLDER") theItem.setStatus(statusKeys[1]) theItem.setLayout("NOTE") theItem.setExpanded(True) theItem.setExported(False) theItem.setParaCount(3) theItem.setWordCount(5) theItem.setCharCount(7) theItem.setCursorPos(11) # Pack xContent = etree.SubElement(nwXML, "content") theItem.packXML(xContent) assert etree.tostring(xContent, pretty_print=False, encoding="utf-8") == ( b'<content>' b'<item handle="0123456789abc" parent="0123456789abc" root="0123456789abc" order="1" ' b'type="FOLDER" class="NOVEL"><meta expanded="True"/><name status="%s" ' b'import="None">A Name</name></item>' b'</content>') % bytes(statusKeys[1], encoding="utf8") # Unpack theItem = NWItem(theProject) assert theItem.unpackXML(xContent[0]) assert theItem.itemHandle == "0123456789abc" assert theItem.itemParent == "0123456789abc" assert theItem.itemRoot == "0123456789abc" assert theItem.itemOrder == 1 assert theItem.isExpanded is True assert theItem.isExported is True assert theItem.paraCount == 0 assert theItem.wordCount == 0 assert theItem.charCount == 0 assert theItem.cursorPos == 0 assert theItem.itemClass == nwItemClass.NOVEL assert theItem.itemType == nwItemType.FOLDER assert theItem.itemLayout == nwItemLayout.NO_LAYOUT assert theItem.itemStatus == statusKeys[1] assert theItem.itemImport == importKeys[ 0] # Was None, should now be default # Errors # ====== # Not an Item mockXml = etree.SubElement(nwXML, "stuff") assert theItem.unpackXML(mockXml) is False # Item without Handle mockXml = etree.SubElement(nwXML, "item", attrib={"stuff": "nah"}) assert theItem.unpackXML(mockXml) is False # Item with Invalid SubElement is Accepted w/Error mockXml = etree.SubElement(nwXML, "item", attrib={"handle": "0123456789abc"}) xParam = etree.SubElement(mockXml, "invalid") xParam.text = "stuff" caplog.clear() assert theItem.unpackXML(mockXml) is True assert "Unknown tag 'invalid'" in caplog.text # Pack Valid Item mockXml = etree.SubElement(nwXML, "group") theItem._subPack(mockXml, "subGroup", {"one": "two"}, "value", False) assert etree.tostring(mockXml, pretty_print=False, encoding="utf-8") == ( b"<group><subGroup one=\"two\">value</subGroup></group>") # Pack Not Allowed None mockXml = etree.SubElement(nwXML, "group") assert theItem._subPack(mockXml, "subGroup", {}, None, False) is None assert theItem._subPack(mockXml, "subGroup", {}, "None", False) is None assert etree.tostring(mockXml, pretty_print=False, encoding="utf-8") == (b"<group/>")
def testCoreToken_SpecialFormat(mockGUI): """Test the tokenization of special formats in the Tokenizer class. """ theProject = NWProject(mockGUI) theToken = BareTokenizer(theProject) theToken._isNovel = True # New Page # ======== correctResp = [ (Tokenizer.T_HEAD1, 1, "Title One", None, Tokenizer.A_CENTRE), (Tokenizer.T_EMPTY, 2, "", None, Tokenizer.A_NONE), (Tokenizer.T_EMPTY, 4, "", None, Tokenizer.A_NONE), (Tokenizer.T_HEAD1, 5, "Title Two", None, Tokenizer.A_CENTRE | Tokenizer.A_PBB), (Tokenizer.T_EMPTY, 6, "", None, Tokenizer.A_NONE), (Tokenizer.T_EMPTY, 6, "", None, Tokenizer.A_NONE), ] # Command wo/Space theToken._isFirst = True theToken._theText = ("# Title One\n\n" "[NEWPAGE]\n\n" "# Title Two\n\n") theToken.tokenizeText() assert theToken._theTokens == correctResp # Command w/Space theToken._isFirst = True theToken._theText = ("# Title One\n\n" "[NEW PAGE]\n\n" "# Title Two\n\n") theToken.tokenizeText() assert theToken._theTokens == correctResp # Trailing Spaces theToken._isFirst = True theToken._theText = ("# Title One\n\n" "[NEW PAGE] \t\n\n" "# Title Two\n\n") theToken.tokenizeText() assert theToken._theTokens == correctResp # Single Empty Paragraph # ====================== theToken._theText = ("# Title One\n\n" "[VSPACE] \n\n" "Some text to go here ...\n\n") theToken.tokenizeText() assert theToken._theTokens == [ (Tokenizer.T_HEAD1, 1, "Title One", None, Tokenizer.A_PBB | Tokenizer.A_CENTRE), (Tokenizer.T_EMPTY, 2, "", None, Tokenizer.A_NONE), (Tokenizer.T_SKIP, 3, "", None, Tokenizer.A_NONE), (Tokenizer.T_EMPTY, 4, "", None, Tokenizer.A_NONE), (Tokenizer.T_TEXT, 5, "Some text to go here ...", [], Tokenizer.A_NONE), (Tokenizer.T_EMPTY, 6, "", None, Tokenizer.A_NONE), (Tokenizer.T_EMPTY, 6, "", None, Tokenizer.A_NONE), ] # Multiple Empty Paragraphs # ========================= # One Skip theToken._theText = ("# Title One\n\n" "[VSPACE:1] \n\n" "Some text to go here ...\n\n") theToken.tokenizeText() assert theToken._theTokens == [ (Tokenizer.T_HEAD1, 1, "Title One", None, Tokenizer.A_PBB | Tokenizer.A_CENTRE), (Tokenizer.T_EMPTY, 2, "", None, Tokenizer.A_NONE), (Tokenizer.T_SKIP, 3, "", None, Tokenizer.A_NONE), (Tokenizer.T_EMPTY, 4, "", None, Tokenizer.A_NONE), (Tokenizer.T_TEXT, 5, "Some text to go here ...", [], Tokenizer.A_NONE), (Tokenizer.T_EMPTY, 6, "", None, Tokenizer.A_NONE), (Tokenizer.T_EMPTY, 6, "", None, Tokenizer.A_NONE), ] # Three Skips theToken._theText = ("# Title One\n\n" "[VSPACE:3] \n\n" "Some text to go here ...\n\n") theToken.tokenizeText() assert theToken._theTokens == [ (Tokenizer.T_HEAD1, 1, "Title One", None, Tokenizer.A_PBB | Tokenizer.A_CENTRE), (Tokenizer.T_EMPTY, 2, "", None, Tokenizer.A_NONE), (Tokenizer.T_SKIP, 3, "", None, Tokenizer.A_NONE), (Tokenizer.T_SKIP, 3, "", None, Tokenizer.A_NONE), (Tokenizer.T_SKIP, 3, "", None, Tokenizer.A_NONE), (Tokenizer.T_EMPTY, 4, "", None, Tokenizer.A_NONE), (Tokenizer.T_TEXT, 5, "Some text to go here ...", [], Tokenizer.A_NONE), (Tokenizer.T_EMPTY, 6, "", None, Tokenizer.A_NONE), (Tokenizer.T_EMPTY, 6, "", None, Tokenizer.A_NONE), ] # Malformed Command, Case 1 theToken._theText = ("# Title One\n\n" "[VSPACE:3xa] \n\n" "Some text to go here ...\n\n") theToken.tokenizeText() assert theToken._theTokens == [ (Tokenizer.T_HEAD1, 1, "Title One", None, Tokenizer.A_PBB | Tokenizer.A_CENTRE), (Tokenizer.T_EMPTY, 2, "", None, Tokenizer.A_NONE), (Tokenizer.T_EMPTY, 4, "", None, Tokenizer.A_NONE), (Tokenizer.T_TEXT, 5, "Some text to go here ...", [], Tokenizer.A_NONE), (Tokenizer.T_EMPTY, 6, "", None, Tokenizer.A_NONE), (Tokenizer.T_EMPTY, 6, "", None, Tokenizer.A_NONE), ] # Malformed Command, Case 2 theToken._theText = ("# Title One\n\n" "[VSPACE:3.5]\n\n" "Some text to go here ...\n\n") theToken.tokenizeText() assert theToken._theTokens == [ (Tokenizer.T_HEAD1, 1, "Title One", None, Tokenizer.A_PBB | Tokenizer.A_CENTRE), (Tokenizer.T_EMPTY, 2, "", None, Tokenizer.A_NONE), (Tokenizer.T_EMPTY, 4, "", None, Tokenizer.A_NONE), (Tokenizer.T_TEXT, 5, "Some text to go here ...", [], Tokenizer.A_NONE), (Tokenizer.T_EMPTY, 6, "", None, Tokenizer.A_NONE), (Tokenizer.T_EMPTY, 6, "", None, Tokenizer.A_NONE), ] # Malformed Command, Case 3 theToken._theText = ("# Title One\n\n" "[VSPACE:-1]\n\n" "Some text to go here ...\n\n") theToken.tokenizeText() assert theToken._theTokens == [ (Tokenizer.T_HEAD1, 1, "Title One", None, Tokenizer.A_PBB | Tokenizer.A_CENTRE), (Tokenizer.T_EMPTY, 2, "", None, Tokenizer.A_NONE), (Tokenizer.T_EMPTY, 4, "", None, Tokenizer.A_NONE), (Tokenizer.T_TEXT, 5, "Some text to go here ...", [], Tokenizer.A_NONE), (Tokenizer.T_EMPTY, 6, "", None, Tokenizer.A_NONE), (Tokenizer.T_EMPTY, 6, "", None, Tokenizer.A_NONE), ] # Empty Paragraph and Page Break # ============================== # Single Skip theToken._theText = ("# Title One\n\n" "[NEW PAGE]\n\n" "[VSPACE]\n\n" "Some text to go here ...\n\n") theToken.tokenizeText() assert theToken._theTokens == [ (Tokenizer.T_HEAD1, 1, "Title One", None, Tokenizer.A_PBB | Tokenizer.A_CENTRE), (Tokenizer.T_EMPTY, 2, "", None, Tokenizer.A_NONE), (Tokenizer.T_EMPTY, 4, "", None, Tokenizer.A_NONE), (Tokenizer.T_SKIP, 5, "", None, Tokenizer.A_PBB), (Tokenizer.T_EMPTY, 6, "", None, Tokenizer.A_NONE), (Tokenizer.T_TEXT, 7, "Some text to go here ...", [], 0), (Tokenizer.T_EMPTY, 8, "", None, Tokenizer.A_NONE), (Tokenizer.T_EMPTY, 8, "", None, Tokenizer.A_NONE), ] # Multiple Skip theToken._theText = ("# Title One\n\n" "[NEW PAGE]\n\n" "[VSPACE:3]\n\n" "Some text to go here ...\n\n") theToken.tokenizeText() assert theToken._theTokens == [ (Tokenizer.T_HEAD1, 1, "Title One", None, Tokenizer.A_PBB | Tokenizer.A_CENTRE), (Tokenizer.T_EMPTY, 2, "", None, Tokenizer.A_NONE), (Tokenizer.T_EMPTY, 4, "", None, Tokenizer.A_NONE), (Tokenizer.T_SKIP, 5, "", None, Tokenizer.A_PBB), (Tokenizer.T_SKIP, 5, "", None, Tokenizer.A_NONE), (Tokenizer.T_SKIP, 5, "", None, Tokenizer.A_NONE), (Tokenizer.T_EMPTY, 6, "", None, Tokenizer.A_NONE), (Tokenizer.T_TEXT, 7, "Some text to go here ...", [], 0), (Tokenizer.T_EMPTY, 8, "", None, Tokenizer.A_NONE), (Tokenizer.T_EMPTY, 8, "", None, Tokenizer.A_NONE), ]
def testCoreItem_ConvertFromFmt13(mockGUI): """Test packing and unpacking XML objects for the NWItem class from format version 1.3 """ theProject = NWProject(mockGUI) # Make Version 1.3 XML nwXML = etree.Element("novelWriterXML") xContent = etree.SubElement(nwXML, "content") # Folder xPack = etree.SubElement(xContent, "item", attrib={ "handle": "a000000000001", "order": "1", "parent": "b000000000001", }) NWItem._subPack(xPack, "name", text="Folder") NWItem._subPack(xPack, "type", text="FOLDER") NWItem._subPack(xPack, "class", text="NOVEL") NWItem._subPack(xPack, "status", text="New") NWItem._subPack(xPack, "expanded", text="True") # Unpack Folder theItem = NWItem(theProject) theItem.unpackXML(xContent[0]) assert theItem.itemHandle == "a000000000001" assert theItem.itemParent == "b000000000001" assert theItem.itemOrder == 1 assert theItem.isExpanded is True assert theItem.isExported is True assert theItem.charCount == 0 assert theItem.wordCount == 0 assert theItem.paraCount == 0 assert theItem.cursorPos == 0 assert theItem.itemClass == nwItemClass.NOVEL assert theItem.itemType == nwItemType.FOLDER assert theItem.itemLayout == nwItemLayout.NO_LAYOUT # File xPack = etree.SubElement(xContent, "item", attrib={ "handle": "c000000000001", "order": "2", "parent": "a000000000001", }) NWItem._subPack(xPack, "name", text="Scene") NWItem._subPack(xPack, "type", text="FILE") NWItem._subPack(xPack, "class", text="NOVEL") NWItem._subPack(xPack, "status", text="New") NWItem._subPack(xPack, "exported", text="True") NWItem._subPack(xPack, "layout", text="DOCUMENT") NWItem._subPack(xPack, "charCount", text="600") NWItem._subPack(xPack, "wordCount", text="100") NWItem._subPack(xPack, "paraCount", text="6") NWItem._subPack(xPack, "cursorPos", text="50") # Unpack File theItem = NWItem(theProject) theItem.unpackXML(xContent[1]) assert theItem.itemHandle == "c000000000001" assert theItem.itemParent == "a000000000001" assert theItem.itemOrder == 2 assert theItem.isExpanded is False assert theItem.isExported is True assert theItem.charCount == 600 assert theItem.wordCount == 100 assert theItem.paraCount == 6 assert theItem.cursorPos == 50 assert theItem.itemClass == nwItemClass.NOVEL assert theItem.itemType == nwItemType.FILE assert theItem.itemLayout == nwItemLayout.DOCUMENT # Deprecated Type theItem.setType("TRASH") assert theItem.itemType == nwItemType.ROOT
def testCoreToken_ProcessHeaders(mockGUI): """Test the header and page parser of the Tokenizer class. """ theProject = NWProject(mockGUI) theProject.projLang = "en" theProject._loadProjectLocalisation() theToken = BareTokenizer(theProject) # Nothing theToken._theText = "Some text ...\n" assert theToken.doHeaders() is False theToken._isNone = True assert theToken.doHeaders() is False theToken._isNone = False assert theToken.doHeaders() is False theToken._isNote = True assert theToken.doHeaders() is False theToken._isNote = False ## # Story FIles ## theToken._isNone = False theToken._isNote = False theToken._isNovel = True # Titles # ====== # H1: Title, First Page assert theToken._isFirst is True theToken._theText = "# Part One\n" theToken.setTitleFormat(r"T: %title%") theToken.tokenizeText() theToken.doHeaders() assert theToken._theTokens == [ (Tokenizer.T_HEAD1, 1, "T: Part One", None, Tokenizer.A_CENTRE), (Tokenizer.T_EMPTY, 1, "", None, Tokenizer.A_NONE), ] # H1: Title, Not First Page assert theToken._isFirst is False theToken._theText = "# Part One\n" theToken.setTitleFormat(r"T: %title%") theToken.tokenizeText() theToken.doHeaders() assert theToken._theTokens == [ (Tokenizer.T_HEAD1, 1, "T: Part One", None, Tokenizer.A_PBB | Tokenizer.A_CENTRE), (Tokenizer.T_EMPTY, 1, "", None, Tokenizer.A_NONE), ] # Chapters # ======== # H2: Chapter theToken._theText = "## Chapter One\n" theToken.setChapterFormat(r"C: %title%") theToken.tokenizeText() theToken.doHeaders() assert theToken._theTokens == [ (Tokenizer.T_HEAD2, 1, "C: Chapter One", None, Tokenizer.A_PBB), (Tokenizer.T_EMPTY, 1, "", None, Tokenizer.A_NONE), ] # H2: Unnumbered Chapter theToken._theText = "##! Prologue\n" theToken.setUnNumberedFormat(r"U: %title%") theToken.tokenizeText() theToken.doHeaders() assert theToken._theTokens == [ (Tokenizer.T_UNNUM, 1, "U: Prologue", None, Tokenizer.A_PBB), (Tokenizer.T_EMPTY, 1, "", None, Tokenizer.A_NONE), ] # H2: Chapter Word Number theToken._theText = "## Chapter\n" theToken.setChapterFormat(r"Chapter %chw%") theToken._numChapter = 0 theToken.tokenizeText() theToken.doHeaders() assert theToken._theTokens == [ (Tokenizer.T_HEAD2, 1, "Chapter One", None, Tokenizer.A_PBB), (Tokenizer.T_EMPTY, 1, "", None, Tokenizer.A_NONE), ] # H2: Chapter Roman Number Upper Case theToken._theText = "## Chapter\n" theToken.setChapterFormat(r"Chapter %chI%") theToken.tokenizeText() theToken.doHeaders() assert theToken._theTokens == [ (Tokenizer.T_HEAD2, 1, "Chapter II", None, Tokenizer.A_PBB), (Tokenizer.T_EMPTY, 1, "", None, Tokenizer.A_NONE), ] # H2: Chapter Roman Number Lower Case theToken._theText = "## Chapter\n" theToken.setChapterFormat(r"Chapter %chi%") theToken.tokenizeText() theToken.doHeaders() assert theToken._theTokens == [ (Tokenizer.T_HEAD2, 1, "Chapter iii", None, Tokenizer.A_PBB), (Tokenizer.T_EMPTY, 1, "", None, Tokenizer.A_NONE), ] # Scenes # ====== # H3: Scene w/Title theToken._theText = "### Scene One\n" theToken.setSceneFormat(r"S: %title%", False) theToken.tokenizeText() theToken.doHeaders() assert theToken._theTokens == [ (Tokenizer.T_HEAD3, 1, "S: Scene One", None, Tokenizer.A_NONE), (Tokenizer.T_EMPTY, 1, "", None, Tokenizer.A_NONE), ] # H3: Scene Hidden wo/Format theToken._theText = "### Scene One\n" theToken.setSceneFormat(r"", True) theToken.tokenizeText() theToken.doHeaders() assert theToken._theTokens == [ (Tokenizer.T_EMPTY, 1, "", None, Tokenizer.A_NONE), (Tokenizer.T_EMPTY, 1, "", None, Tokenizer.A_NONE), ] # H3: Scene wo/Format, first theToken._theText = "### Scene One\n" theToken.setSceneFormat(r"", False) theToken._firstScene = True theToken.tokenizeText() theToken.doHeaders() assert theToken._theTokens == [ (Tokenizer.T_EMPTY, 1, "", None, Tokenizer.A_NONE), (Tokenizer.T_EMPTY, 1, "", None, Tokenizer.A_NONE), ] # H3: Scene wo/Format, not first theToken._theText = "### Scene One\n" theToken.setSceneFormat(r"", False) theToken._firstScene = False theToken.tokenizeText() theToken.doHeaders() assert theToken._theTokens == [ (Tokenizer.T_SKIP, 1, "", None, Tokenizer.A_NONE), (Tokenizer.T_EMPTY, 1, "", None, Tokenizer.A_NONE), ] # H3: Scene Separator, first theToken._theText = "### Scene One\n" theToken.setSceneFormat(r"* * *", False) theToken._firstScene = True theToken.tokenizeText() theToken.doHeaders() assert theToken._theTokens == [ (Tokenizer.T_EMPTY, 1, "", None, Tokenizer.A_NONE), (Tokenizer.T_EMPTY, 1, "", None, Tokenizer.A_NONE), ] # H3: Scene Separator, not first theToken._theText = "### Scene One\n" theToken.setSceneFormat(r"* * *", False) theToken._firstScene = False theToken.tokenizeText() theToken.doHeaders() assert theToken._theTokens == [ (Tokenizer.T_SEP, 1, "* * *", None, Tokenizer.A_CENTRE), (Tokenizer.T_EMPTY, 1, "", None, Tokenizer.A_NONE), ] # H3: Scene w/Absolute Number theToken._theText = "### A Scene\n" theToken.setSceneFormat(r"Scene %sca%", False) theToken._numAbsScene = 0 theToken._numChScene = 0 theToken.tokenizeText() theToken.doHeaders() assert theToken._theTokens == [ (Tokenizer.T_HEAD3, 1, "Scene 1", None, Tokenizer.A_NONE), (Tokenizer.T_EMPTY, 1, "", None, Tokenizer.A_NONE), ] # H3: Scene w/Chapter Number theToken._theText = "### A Scene\n" theToken.setSceneFormat(r"Scene %ch%.%sc%", False) theToken._numAbsScene = 0 theToken._numChScene = 1 theToken.tokenizeText() theToken.doHeaders() assert theToken._theTokens == [ (Tokenizer.T_HEAD3, 1, "Scene 3.2", None, Tokenizer.A_NONE), (Tokenizer.T_EMPTY, 1, "", None, Tokenizer.A_NONE), ] # Sections # ======== # H4: Section Hidden wo/Format theToken._theText = "#### A Section\n" theToken.setSectionFormat(r"", True) theToken.tokenizeText() theToken.doHeaders() assert theToken._theTokens == [ (Tokenizer.T_EMPTY, 1, "", None, Tokenizer.A_NONE), (Tokenizer.T_EMPTY, 1, "", None, Tokenizer.A_NONE), ] # H4: Section Visible wo/Format theToken._theText = "#### A Section\n" theToken.setSectionFormat(r"", False) theToken.tokenizeText() theToken.doHeaders() assert theToken._theTokens == [ (Tokenizer.T_SKIP, 1, "", None, Tokenizer.A_NONE), (Tokenizer.T_EMPTY, 1, "", None, Tokenizer.A_NONE), ] # H4: Section w/Format theToken._theText = "#### A Section\n" theToken.setSectionFormat(r"X: %title%", False) theToken.tokenizeText() theToken.doHeaders() assert theToken._theTokens == [ (Tokenizer.T_HEAD4, 1, "X: A Section", None, Tokenizer.A_NONE), (Tokenizer.T_EMPTY, 1, "", None, Tokenizer.A_NONE), ] # H4: Section Separator theToken._theText = "#### A Section\n" theToken.setSectionFormat(r"* * *", False) theToken.tokenizeText() theToken.doHeaders() assert theToken._theTokens == [ (Tokenizer.T_SEP, 1, "* * *", None, Tokenizer.A_CENTRE), (Tokenizer.T_EMPTY, 1, "", None, Tokenizer.A_NONE), ] # Check the first scene detector assert theToken._firstScene is False theToken._firstScene = True theToken._theText = "Some text ...\n" theToken.tokenizeText() theToken.doHeaders() assert theToken._firstScene is False