Improve paragraph skips in Markdown output

This commit is contained in:
Veronica Berglyd Olsen
2024-03-14 22:01:44 +01:00
parent b8af6d3990
commit 8ef5eea825
4 changed files with 110 additions and 11 deletions
+1
View File
@@ -405,6 +405,7 @@ class nwUnicode:
U_THNBSP = "\u202f" # Thin non-breaking space U_THNBSP = "\u202f" # Thin non-breaking space
U_ENSP = "\u2002" # Short (en) space U_ENSP = "\u2002" # Short (en) space
U_EMSP = "\u2003" # Long (em) space U_EMSP = "\u2003" # Long (em) space
U_MMSP = "\u205f" # Medium mathematical space
U_LSEP = "\u2028" # Line separator U_LSEP = "\u2028" # Line separator
U_PSEP = "\u2029" # Paragraph separator U_PSEP = "\u2029" # Paragraph separator
+5 -3
View File
@@ -27,7 +27,7 @@ import logging
from pathlib import Path from pathlib import Path
from novelwriter.constants import nwHeadFmt, nwLabels from novelwriter.constants import nwHeadFmt, nwLabels, nwUnicode
from novelwriter.core.project import NWProject from novelwriter.core.project import NWProject
from novelwriter.core.tokenizer import Tokenizer from novelwriter.core.tokenizer import Tokenizer
@@ -108,6 +108,7 @@ class ToMarkdown(Tokenizer):
self.FMT_SUB_B: "", self.FMT_SUB_B: "",
self.FMT_SUB_E: "", self.FMT_SUB_E: "",
} }
cSkip = ""
else: else:
# Extended Markdown # Extended Markdown
mdTags = { mdTags = {
@@ -126,6 +127,7 @@ class ToMarkdown(Tokenizer):
self.FMT_SUB_B: "~", self.FMT_SUB_B: "~",
self.FMT_SUB_E: "~", self.FMT_SUB_E: "~",
} }
cSkip = nwUnicode.U_MMSP
self._result = "" self._result = ""
@@ -136,7 +138,7 @@ class ToMarkdown(Tokenizer):
for tType, _, tText, tFormat, tStyle in self._tokens: for tType, _, tText, tFormat, tStyle in self._tokens:
if tType == self.T_EMPTY: if tType == self.T_EMPTY:
if len(para) > 0: if para:
tTemp = (lineSep.join(para)).rstrip(" ") tTemp = (lineSep.join(para)).rstrip(" ")
lines.append(f"{tTemp}\n\n") lines.append(f"{tTemp}\n\n")
para = [] para = []
@@ -165,7 +167,7 @@ class ToMarkdown(Tokenizer):
lines.append(f"{tText}\n\n") lines.append(f"{tText}\n\n")
elif tType == self.T_SKIP: elif tType == self.T_SKIP:
lines.append("\n\n\n") lines.append(f"{cSkip}\n\n")
elif tType == self.T_TEXT: elif tType == self.T_TEXT:
tTemp = tText tTemp = tText
+103 -7
View File
@@ -1734,10 +1734,8 @@ def testCoreToken_CountStats(mockGUI, ipsumText):
@pytest.mark.core @pytest.mark.core
def testCoreToken_HeaderCounterAndVisibility(mockGUI): def testCoreToken_SceneSeparators(mockGUI):
"""Test the header counter and visibility of the Tokenizer class. """Test the section and scene separators of the Tokenizer class."""
This is a special test to cover issue #1704.
"""
project = NWProject() project = NWProject()
project.data.setLanguage("en") project.data.setLanguage("en")
project._loadProjectLocalisation() project._loadProjectLocalisation()
@@ -1855,8 +1853,50 @@ def testCoreToken_HeaderCounterAndVisibility(mockGUI):
"Text\n\n" "Text\n\n"
) )
# Show/Hide Headings # Separators with Scenes Only
# ================== # ===========================
# Requires a fresh builder class
md = ToMarkdown(project)
md.setExtendedMarkdown()
md._isNone = False
md._isNote = False
md._isNovel = True
md._text = (
"### Scene One\n\n"
"Text\n\n"
"### Scene Two\n\n"
"Text\n\n"
"### Scene Three\n\n"
"Text\n\n"
"###! Scene Four\n\n"
"Text\n\n"
)
md.setSceneFormat("", False)
md.setHardSceneFormat("* * *", False)
md.tokenizeText()
md.doConvert()
assert md.result == (
"Text\n\n"
"\u205f\n\n"
"Text\n\n"
"\u205f\n\n"
"Text\n\n"
"* * *\n\n"
"Text\n\n"
)
# END Test testCoreToken_SceneSeparators
@pytest.mark.core
def testCoreToken_HeaderVisibility(mockGUI):
"""Test the heading visibility settings of the Tokenizer class."""
project = NWProject()
project.data.setLanguage("en")
project._loadProjectLocalisation()
md = ToMarkdown(project)
md._text = ( md._text = (
"#! Novel\n\n" "#! Novel\n\n"
@@ -1876,6 +1916,13 @@ def testCoreToken_HeaderCounterAndVisibility(mockGUI):
"Text\n\n" "Text\n\n"
) )
# Novel Files
# ===========
md._isNone = False
md._isNote = False
md._isNovel = True
# Show All # Show All
md.setTitleFormat(nwHeadFmt.TITLE, False) md.setTitleFormat(nwHeadFmt.TITLE, False)
md.setChapterFormat(nwHeadFmt.TITLE, False) md.setChapterFormat(nwHeadFmt.TITLE, False)
@@ -1923,6 +1970,55 @@ def testCoreToken_HeaderCounterAndVisibility(mockGUI):
"Text\n\n" "Text\n\n"
) )
# Note Files
# ==========
md._isNone = False
md._isNote = True
md._isNovel = False
# Hide All
md.setTitleFormat(nwHeadFmt.TITLE, True)
md.setChapterFormat(nwHeadFmt.TITLE, True)
md.setUnNumberedFormat(nwHeadFmt.TITLE, True)
md.setSceneFormat(nwHeadFmt.TITLE, True)
md.setHardSceneFormat(nwHeadFmt.TITLE, True)
md.setSectionFormat(nwHeadFmt.TITLE, True)
md.tokenizeText()
md.doConvert()
assert md.result == (
"# Novel\n\n"
"# Title One\n\n"
"## Prologue\n\n"
"Text\n\n"
"## Chapter One\n\n"
"### Scene One\n\n"
"Text\n\n"
"### Scene Two\n\n"
"#### Section Two\n\n"
"Text\n\n"
"## Chapter Two\n\n"
"### Scene Three\n\n"
"Text\n\n"
"### Scene Four\n\n"
"Text\n\n"
)
# END Test testCoreToken_HeaderVisibility
@pytest.mark.core
def testCoreToken_CounterHandling(mockGUI):
"""Test the heading counter of the Tokenizer class."""
project = NWProject()
project.data.setLanguage("en")
project._loadProjectLocalisation()
md = ToMarkdown(project)
md._isNone = False
md._isNote = False
md._isNovel = True
# Counter Handling, Novel Titles # Counter Handling, Novel Titles
# ============================== # ==============================
# This also checks that only numbered chapters bump the counter # This also checks that only numbered chapters bump the counter
@@ -1998,7 +2094,7 @@ def testCoreToken_HeaderCounterAndVisibility(mockGUI):
"Text\n\n" "Text\n\n"
) )
# END Test testCoreToken_HeaderCounterAndVisibility # END Test testCoreToken_CounterHandling
@pytest.mark.core @pytest.mark.core
+1 -1
View File
@@ -230,7 +230,7 @@ def testCoreToMarkdown_ConvertDirect(mockGUI):
(toMD.T_EMPTY, 1, "", None, toMD.A_NONE), (toMD.T_EMPTY, 1, "", None, toMD.A_NONE),
] ]
toMD.doConvert() toMD.doConvert()
assert toMD.result == "\n\n\n" assert toMD.result == "\n\n"
# END Test testCoreToMarkdown_ConvertDirect # END Test testCoreToMarkdown_ConvertDirect