From e690243fc3ce85bde960b2e68d895ee232c17319 Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Thu, 19 Jun 2025 20:21:19 +0200 Subject: [PATCH 01/12] Show notes and story structure comments in the viewer --- novelwriter/gui/docviewer.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/novelwriter/gui/docviewer.py b/novelwriter/gui/docviewer.py index 9657ee4e..4b43937b 100644 --- a/novelwriter/gui/docviewer.py +++ b/novelwriter/gui/docviewer.py @@ -228,6 +228,8 @@ class GuiDocViewer(QTextBrowser): qDoc.setTheme(self._docTheme) qDoc.initDocument() qDoc.setKeywords(True) + qDoc.setCommentType(nwComment.NOTE, CONFIG.viewComments) + qDoc.setCommentType(nwComment.STORY, CONFIG.viewComments) qDoc.setCommentType(nwComment.PLAIN, CONFIG.viewComments) qDoc.setCommentType(nwComment.SYNOPSIS, CONFIG.viewSynopsis) qDoc.setCommentType(nwComment.SHORT, CONFIG.viewSynopsis) From 3c474987b29ba94ae729c8e4e24e8d58a95feafd Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Mon, 23 Jun 2025 23:24:20 +0200 Subject: [PATCH 02/12] Check indent and justify after lines are combined in tokenizer, not before (#2426) --- novelwriter/formats/tokenizer.py | 34 ++++++----- tests/test_formats/test_fmt_tokenizer.py | 74 ++++++++++++++++++++++++ tests/test_formats/test_fmt_toodt.py | 2 +- 3 files changed, 93 insertions(+), 17 deletions(-) diff --git a/novelwriter/formats/tokenizer.py b/novelwriter/formats/tokenizer.py index e6d2d563..e0587002 100644 --- a/novelwriter/formats/tokenizer.py +++ b/novelwriter/formats/tokenizer.py @@ -880,31 +880,21 @@ class Tokenizer(ABC): if nBlock[0] != BlockTyp.TEXT: # Next block is not text, so we add the buffer to blocks nLines = len(pLines) - cStyle = pLines[0][4] - if firstIndent and not (self._noIndent or cStyle & BlockFmt.ALIGNED): - # If paragraph indentation is enabled, not temporarily - # turned off, and the block is not aligned, we add the - # text indentation flag - cStyle |= BlockFmt.IND_T + tFmt: T_Formats = [] + pTxt = "" + cStyle = BlockFmt.NONE if nLines == 1: - # The paragraph contains a single line, so we just save - # that directly to the blocks list. If justify is - # enabled, and there is no alignment, we apply it. - if doJustify and not cStyle & BlockFmt.ALIGNED: - cStyle |= BlockFmt.JUSTIFY - + # The paragraph contains a single line + tFmt = pLines[0][3] pTxt = pLines[0][2].translate(transMapB) - sBlocks.append(( - BlockTyp.TEXT, pLines[0][1], pTxt, pLines[0][3], cStyle - )) + cStyle = pLines[0][4] elif nLines > 1: # The paragraph contains multiple lines, so we need to # join them according to the line break policy, and # recompute all the formatting markers tTxt = "" - tFmt: T_Formats = [] for aBlock in pLines: tLen = len(tTxt) tTxt += f"{aBlock[2]}{lineSep}" @@ -912,6 +902,18 @@ class Tokenizer(ABC): cStyle |= aBlock[4] pTxt = tTxt[:-1].translate(transMapB) + + if nLines: + isAligned = cStyle & BlockFmt.ALIGNED + if firstIndent and not (self._noIndent or isAligned): + # If paragraph indentation is enabled, not temporarily + # turned off, and the block is not aligned, we add the + # text indentation flag + cStyle |= BlockFmt.IND_T + + if doJustify and not isAligned: + cStyle |= BlockFmt.JUSTIFY + sBlocks.append(( BlockTyp.TEXT, pLines[0][1], pTxt, tFmt, cStyle )) diff --git a/tests/test_formats/test_fmt_tokenizer.py b/tests/test_formats/test_fmt_tokenizer.py index 7795601c..58106cdd 100644 --- a/tests/test_formats/test_fmt_tokenizer.py +++ b/tests/test_formats/test_fmt_tokenizer.py @@ -1074,6 +1074,80 @@ def testFmtToken_Paragraphs(mockGUI): ] +@pytest.mark.core +def testFmtToken_BreakAlignIndent(mockGUI): + """Test the splitting of paragraphs with alignment.""" + project = NWProject() + tokens = BareTokenizer(project) + tokens._handle = TMH + + for text in [ + "This is text <<\nspanning multiple\nlines", + "This is text\nspanning multiple <<\nlines", + "This is text\nspanning multiple\nlines <<", + ]: + # Preserve Breaks + tokens.setKeepLineBreaks(True) + tokens._text = text + tokens.tokenizeText() + assert tokens._blocks == [ + (BlockTyp.TEXT, "", "This is text\nspanning multiple\nlines", [], BlockFmt.LEFT), + ] + + # Don't Preserve Breaks + tokens.setKeepLineBreaks(False) + tokens._text = text + tokens.tokenizeText() + assert tokens._blocks == [ + (BlockTyp.TEXT, "", "This is text spanning multiple lines", [], BlockFmt.LEFT), + ] + + # With Justify + # This should disable justify + tokens.setKeepLineBreaks(True) + tokens.setJustify(True) + tokens._text = text + tokens.tokenizeText() + assert tokens._blocks == [ + (BlockTyp.TEXT, "", "This is text\nspanning multiple\nlines", [], BlockFmt.LEFT), + ] + + # With Indent + # This should disable indent + tokens.setKeepLineBreaks(True) + tokens.setFirstLineIndent(True, 1.0, False) + tokens._text = text + tokens.tokenizeText() + assert tokens._blocks == [ + (BlockTyp.TEXT, "", "This is text\nspanning multiple\nlines", [], BlockFmt.LEFT), + ] + + +@pytest.mark.core +def testFmtToken_BreakJustify(mockGUI): + """Test the of processing of justify with breaks.""" + project = NWProject() + tokens = BareTokenizer(project) + tokens._handle = TMH + tokens.setJustify(True) + + # Applied to all lines when breaks are preserved + tokens._text = "This is text\nspanning multiple\nlines" + tokens.setKeepLineBreaks(True) + tokens.tokenizeText() + assert tokens._blocks == [ + (BlockTyp.TEXT, "", "This is text\nspanning multiple\nlines", [], BlockFmt.JUSTIFY), + ] + + # Turning off breaks should make no difference (see issue #2426) + tokens._text = "This is text\nspanning multiple\nlines" + tokens.setKeepLineBreaks(False) + tokens.tokenizeText() + assert tokens._blocks == [ + (BlockTyp.TEXT, "", "This is text spanning multiple lines", [], BlockFmt.JUSTIFY), + ] + + @pytest.mark.core def testFmtToken_TextFormat(mockGUI): """Test the tokenization of text formats in the Tokenizer class.""" diff --git a/tests/test_formats/test_fmt_toodt.py b/tests/test_formats/test_fmt_toodt.py index 70b72874..eded1eeb 100644 --- a/tests/test_formats/test_fmt_toodt.py +++ b/tests/test_formats/test_fmt_toodt.py @@ -733,7 +733,7 @@ def testFmtToOdt_ConvertParagraphs(mockGUI): '' 'Scene' 'Regular paragraph' - 'withbreak' + 'withbreak' 'Left Align' '' ) From 979a55d24a1e3261cb04cc92e06ee523baa24927 Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Tue, 24 Jun 2025 00:07:55 +0200 Subject: [PATCH 03/12] Add alignment precedence test to HTML tests --- tests/test_formats/test_fmt_tohtml.py | 51 +++++++++++++++++++++++++-- 1 file changed, 48 insertions(+), 3 deletions(-) diff --git a/tests/test_formats/test_fmt_tohtml.py b/tests/test_formats/test_fmt_tohtml.py index fb05ebfd..28b8e3e5 100644 --- a/tests/test_formats/test_fmt_tohtml.py +++ b/tests/test_formats/test_fmt_tohtml.py @@ -147,9 +147,6 @@ def testFmtToHtml_ConvertParagraphs(mockGUI): html._isNovel = True html._isFirst = True - # Paragraphs - # ========== - # Text html._text = "Some **nested bold and _italic_ and ~~strikethrough~~ text** here\n" html.tokenizeText() @@ -280,6 +277,54 @@ def testFmtToHtml_ConvertParagraphs(mockGUI): ) +@pytest.mark.core +def testFmtToHtml_Alignment(mockGUI): + """Test paragraph alignment in the ToHtml class.""" + project = NWProject() + html = ToHtml(project) + html.initDocument() + + # Left + html._text = "This is text <<\nspanning multiple\nlines" + html.tokenizeText() + html.doConvert() + assert html._pages[-1] == ( + "

This is text
spanning multiple
lines

\n" + ) + + # Right + html._text = ">> This is text\nspanning multiple\nlines" + html.tokenizeText() + html.doConvert() + assert html._pages[-1] == ( + "

This is text
spanning multiple
lines

\n" + ) + + # Centre + html._text = ">> This is text <<\nspanning multiple\nlines" + html.tokenizeText() + html.doConvert() + assert html._pages[-1] == ( + "

This is text
spanning multiple
lines

\n" + ) + + # Left before Right + html._text = ">> This is text\nspanning multiple <<\nlines" + html.tokenizeText() + html.doConvert() + assert html._pages[-1] == ( + "

This is text
spanning multiple
lines

\n" + ) + + # Right before Centre + html._text = ">> This is text <<\n>> spanning multiple\nlines" + html.tokenizeText() + html.doConvert() + assert html._pages[-1] == ( + "

This is text
spanning multiple
lines

\n" + ) + + @pytest.mark.core def testFmtToHtml_Dialog(mockGUI): """Test paragraph formats in the ToHtml class.""" From a210a665fbd10863e615363c05697281ebd785b8 Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Tue, 24 Jun 2025 00:08:08 +0200 Subject: [PATCH 04/12] Update documentation --- docs/source/usage/advanced_formatting.rst | 14 ++++++ docs/source/usage/alignment_and_indent.rst | 55 ++++++++++++++++++++-- 2 files changed, 65 insertions(+), 4 deletions(-) diff --git a/docs/source/usage/advanced_formatting.rst b/docs/source/usage/advanced_formatting.rst index 557db1a7..94bfec0f 100644 --- a/docs/source/usage/advanced_formatting.rst +++ b/docs/source/usage/advanced_formatting.rst @@ -56,6 +56,20 @@ activated by clicking the left-most icon button in the editor header. .. versionadded:: 2.2 +.. _docs_usage_formatting_shortcodes_break: + +Forced Line Break +----------------- + +Inserting ``[br]`` in the text will ensure a line break is always inserted in that place, even if +you turn off **Preserve Hard Line breaks** in your **Manuscript Build Settings**. + +You can add a manual line break after it too, for a better visual representation in the editor, but +keep in mind that this line break is removed before the text is processed, so the text on either +side will be considered as belonging to the same line. This can affect how alignment is treated. +See :ref:`docs_usage_align_indent_forced` for more details. + + .. _docs_usage_formatting_breaks: Vertical Space and Page Breaks diff --git a/docs/source/usage/alignment_and_indent.rst b/docs/source/usage/alignment_and_indent.rst index 2494ea32..dea1b171 100644 --- a/docs/source/usage/alignment_and_indent.rst +++ b/docs/source/usage/alignment_and_indent.rst @@ -53,18 +53,33 @@ the entire paragraph. For the following text, all lines will be centred: .. code-block:: md - >> I am the very model of a modern Major-General + >> I am the very model of a modern Major-General << I've information vegetable, animal, and mineral I know the kings of England, and I quote the fights historical - From Marathon to Waterloo, in order categorical << + From Marathon to Waterloo, in order categorical + +If you have multiple conflicting alignments on a paragraph, only one is applied. The order of +precedence is: + +#. Left alignment +#. Right alignment +#. Centred text +#. Justified text + +.. note:: + + It is strongly recommended that you keep the **Preserve Hard Line Breaks** setting enabled in + your **Manuscript Build Settings**. This setting assumes all single line breaks in your text are + intended. Turning this off makes adding line breaks much more complicated, but it is still + possible. See :ref:`docs_usage_align_indent_forced`. Alignment with First Line Indent ================================ If you have first line indent enabled in your manuscript build settings, you probably want to -disable it for text in verses. Adding any alignment tags will cause the first line indent to be -switched off for that paragraph. +disable it for text in verses. Adding any alignment tags on a paragraph will cause the first +line indent to be switched off for that paragraph. :bdg-info:`Example` @@ -76,3 +91,35 @@ The following text will always be aligned against the left margin: I've information vegetable, animal, and mineral I know the kings of England, and I quote the fights historical From Marathon to Waterloo, in order categorical + + +.. _docs_usage_align_indent_forced: + +Alignment with Forced Line Breaks +================================= + +If you turn off **Preserve Hard Line Breaks** in **Manuscript Build Settings**, you can still force +line breaks in paragraphs using the ``[br]`` shortcode. For clarity in the text, you can add a line +break after it as well. It doesn't result in two line breaks. + +Keep in mind that when the text is processed, these lines on either side of a ``[br]`` shortcode +are combined, and a trailing hard line break is *ignored*. This means that when such a paragraph is +processed, these line breaks count as the same line. This affects hiw alignment tags are handled. +For instance, this text becomes centred instead of left aligned. + +.. code-block:: md + + >> I am the very model of a modern Major-General[br] + I've information vegetable, animal, and mineral[br] + I know the kings of England, and I quote the fights historical[br] + From Marathon to Waterloo, in order categorical << + +Since this is understood as one line, this is the only way you can actually centre this paragraph. + +.. caution:: + + Due to this difference in how text with ``[br]`` tags are processed, it is generally better to + stick with the **Preserve Hard Line Breaks** setting enabled. It ensures a better correspondence + between what you see in the editor and what output you get. + +See also :ref:`docs_usage_formatting_shortcodes_break`. From c1dd2ebb92ab52f061aa7afd235d2d05c84e587a Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Tue, 24 Jun 2025 00:22:35 +0200 Subject: [PATCH 05/12] Fix typos and inconsistencies --- docs/source/usage/advanced_formatting.rst | 6 +++--- docs/source/usage/alignment_and_indent.rst | 18 +++++++++--------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/docs/source/usage/advanced_formatting.rst b/docs/source/usage/advanced_formatting.rst index 94bfec0f..556d6f1f 100644 --- a/docs/source/usage/advanced_formatting.rst +++ b/docs/source/usage/advanced_formatting.rst @@ -62,12 +62,12 @@ Forced Line Break ----------------- Inserting ``[br]`` in the text will ensure a line break is always inserted in that place, even if -you turn off **Preserve Hard Line breaks** in your **Manuscript Build Settings**. +you turn off **Preserve Hard Line Breaks** in your manuscript build settings. You can add a manual line break after it too, for a better visual representation in the editor, but keep in mind that this line break is removed before the text is processed, so the text on either -side will be considered as belonging to the same line. This can affect how alignment is treated. -See :ref:`docs_usage_align_indent_forced` for more details. +side of the ``[br]`` shortcode will be considered as belonging to the same line. This can affect +how alignment is treated. See :ref:`docs_usage_align_indent_forced` for more details. .. _docs_usage_formatting_breaks: diff --git a/docs/source/usage/alignment_and_indent.rst b/docs/source/usage/alignment_and_indent.rst index dea1b171..60949b9a 100644 --- a/docs/source/usage/alignment_and_indent.rst +++ b/docs/source/usage/alignment_and_indent.rst @@ -69,9 +69,9 @@ precedence is: .. note:: It is strongly recommended that you keep the **Preserve Hard Line Breaks** setting enabled in - your **Manuscript Build Settings**. This setting assumes all single line breaks in your text are - intended. Turning this off makes adding line breaks much more complicated, but it is still - possible. See :ref:`docs_usage_align_indent_forced`. + your manuscript build settings. This setting assumes all single line breaks in your text are + intended. Turning this off makes adding line breaks more complicated, but it is still possible. + See :ref:`docs_usage_align_indent_forced`. Alignment with First Line Indent @@ -98,13 +98,13 @@ The following text will always be aligned against the left margin: Alignment with Forced Line Breaks ================================= -If you turn off **Preserve Hard Line Breaks** in **Manuscript Build Settings**, you can still force -line breaks in paragraphs using the ``[br]`` shortcode. For clarity in the text, you can add a line -break after it as well. It doesn't result in two line breaks. +If you turn off **Preserve Hard Line Breaks** in your manuscript build settings, you can still +force line breaks in paragraphs using the ``[br]`` shortcode. For clarity in the text, you can add +a line break after it as well. It doesn't result in two line breaks. -Keep in mind that when the text is processed, these lines on either side of a ``[br]`` shortcode -are combined, and a trailing hard line break is *ignored*. This means that when such a paragraph is -processed, these line breaks count as the same line. This affects hiw alignment tags are handled. +Keep in mind that when the text is processed, the lines on either side of a ``[br]`` shortcode are +combined, and any trailing hard line break is *ignored*. This means that when such a paragraph is +processed, these line breaks count as the same line. This affects how alignment tags are handled. For instance, this text becomes centred instead of left aligned. .. code-block:: md From ad2288e2fce5292a042dbc04d851401f2c5adebb Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Tue, 24 Jun 2025 16:05:59 +0200 Subject: [PATCH 06/12] Add tag value for novel docs in Outline and Novel View (#2428) --- novelwriter/core/index.py | 14 ++++++++------ novelwriter/core/indexdata.py | 4 +++- novelwriter/gui/noveltree.py | 1 + 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/novelwriter/core/index.py b/novelwriter/core/index.py index d8e9c8e4..07933690 100644 --- a/novelwriter/core/index.py +++ b/novelwriter/core/index.py @@ -708,17 +708,19 @@ class Index: return 0, 0, 0 def getReferences(self, tHandle: str, sTitle: str | None = None) -> dict[str, list[str]]: - """Extract all references made in a file, and optionally title - section. + """Extract all tags and references made in a file, and + optionally title section. """ - tRefs = {x: [] for x in nwKeyWords.VALID_KEYS} + refs = {x: [] for x in nwKeyWords.VALID_KEYS} for rTitle, hItem in self._itemIndex.iterItemHeaders(tHandle): if sTitle is None or sTitle == rTitle: for aTag, refTypes in hItem.references.items(): for refType in refTypes: - if refType in tRefs: - tRefs[refType].append(self._tagsIndex.tagName(aTag)) - return tRefs + if refType in refs: + refs[refType].append(self._tagsIndex.tagName(aTag)) + if tag := hItem.tag: + refs[nwKeyWords.TAG_KEY] = [self._tagsIndex.tagName(tag)] + return refs def getReferenceForHeader(self, tHandle: str, nHead: int, keyClass: str) -> list[str]: """Get the display names for a tags class for insertion into a diff --git a/novelwriter/core/indexdata.py b/novelwriter/core/indexdata.py index 070558ce..4ddad943 100644 --- a/novelwriter/core/indexdata.py +++ b/novelwriter/core/indexdata.py @@ -342,12 +342,14 @@ class IndexHeading: ## def getReferences(self) -> dict[str, list[str]]: - """Extract all references for this heading.""" + """Extract all tags and references for this heading.""" refs = {x: [] for x in nwKeyWords.VALID_KEYS} for tag, types in self._refs.items(): for keyword in types: if keyword in refs and (name := self._cache.tags.tagName(tag)): refs[keyword].append(name) + if tag := self._tag: + refs[nwKeyWords.TAG_KEY] = [self._cache.tags.tagName(tag)] return refs def getReferencesByKeyword(self, keyword: str) -> list[str]: diff --git a/novelwriter/gui/noveltree.py b/novelwriter/gui/noveltree.py index 752c6d39..86913b61 100644 --- a/novelwriter/gui/noveltree.py +++ b/novelwriter/gui/noveltree.py @@ -593,6 +593,7 @@ class GuiNovelTree(NTreeView): lines = [] if head := SHARED.project.index.getItemHeading(tHandle, sTitle): tags = head.getReferences() + appendTags(tags, nwKeyWords.TAG_KEY, lines) appendTags(tags, nwKeyWords.POV_KEY, lines) appendTags(tags, nwKeyWords.FOCUS_KEY, lines) appendTags(tags, nwKeyWords.CHAR_KEY, lines) From 5ae385ec02e1a35864ddd43829a7d89a23097f28 Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Tue, 24 Jun 2025 16:15:35 +0200 Subject: [PATCH 07/12] Add tag to reference by keyword lookup --- novelwriter/core/indexdata.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/novelwriter/core/indexdata.py b/novelwriter/core/indexdata.py index 4ddad943..b74ce4c4 100644 --- a/novelwriter/core/indexdata.py +++ b/novelwriter/core/indexdata.py @@ -348,16 +348,20 @@ class IndexHeading: for keyword in types: if keyword in refs and (name := self._cache.tags.tagName(tag)): refs[keyword].append(name) - if tag := self._tag: - refs[nwKeyWords.TAG_KEY] = [self._cache.tags.tagName(tag)] + if name := self._cache.tags.tagName(self._tag): + refs[nwKeyWords.TAG_KEY] = [name] return refs def getReferencesByKeyword(self, keyword: str) -> list[str]: """Extract all references for this heading.""" refs = [] - for tag, types in self._refs.items(): - if keyword in types and (name := self._cache.tags.tagName(tag)): + if keyword == nwKeyWords.TAG_KEY: + if name := self._cache.tags.tagName(self._tag): refs.append(name) + else: + for tag, types in self._refs.items(): + if keyword in types and (name := self._cache.tags.tagName(tag)): + refs.append(name) return refs ## From aaf4ede04d78a39e40c413e2e3e7dccb440c018e Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Tue, 24 Jun 2025 16:15:49 +0200 Subject: [PATCH 08/12] Update test coverage --- tests/test_core/test_core_index.py | 5 ++++- tests/test_core/test_core_indexdata.py | 6 ++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/tests/test_core/test_core_index.py b/tests/test_core/test_core_index.py index dca4575a..e86b8dc0 100644 --- a/tests/test_core/test_core_index.py +++ b/tests/test_core/test_core_index.py @@ -695,6 +695,7 @@ def testCoreIndex_ExtractData(nwGUI, fncPath, mockRnd): )) assert index.scanText(nHandle, ( "# Hello World!\n" + "@tag: Scene\n" "@pov: Jane\n" "@char: Jane, John\n\n" "% this is a comment\n\n" @@ -749,11 +750,13 @@ def testCoreIndex_ExtractData(nwGUI, fncPath, mockRnd): # Look up an invalid handle refs = index.getReferences("Not a handle") + assert refs["@tag"] == [] assert refs["@pov"] == [] assert refs["@char"] == [] # The novel file should now refer to Jane as @pov and @char refs = index.getReferences(nHandle) + assert refs["@tag"] == ["Scene"] assert refs["@pov"] == ["Jane"] assert refs["@char"] == ["Jane", "John"] @@ -791,7 +794,7 @@ def testCoreIndex_ExtractData(nwGUI, fncPath, mockRnd): # getKeyWordTags # ============== - assert index.getKeyWordTags("@mention") == ["Jane", "John"] + assert index.getKeyWordTags("@mention") == ["Jane", "John", "Scene"] assert index.getKeyWordTags("@char") == ["Jane", "John"] assert index.getKeyWordTags("@plot") == [] assert index.getKeyWordTags("@tag") == [] diff --git a/tests/test_core/test_core_indexdata.py b/tests/test_core/test_core_indexdata.py index 5bf45c8a..d4797aee 100644 --- a/tests/test_core/test_core_indexdata.py +++ b/tests/test_core/test_core_indexdata.py @@ -267,6 +267,7 @@ def testCoreIndexData_IndexHeadingReferences(): head = IndexHeading(cache, "T0001") # Add some references + head.setTag("Scene") head.addReference("Jane", "@pov") head.addReference("Jane", "@char") head.addReference("John", "@char") @@ -290,6 +291,7 @@ def testCoreIndexData_IndexHeadingReferences(): } # Set names + cache.tags.add("Scene", "Scene", "0000000000000", "T00001", "NOVEL") cache.tags.add("Jane", "Jane", "0000000000000", "T00001", "CHARACTER") cache.tags.add("John", "John", "0000000000000", "T00001", "CHARACTER") cache.tags.add("Main", "Main", "0000000000000", "T00001", "PLOT") @@ -301,7 +303,7 @@ def testCoreIndexData_IndexHeadingReferences(): "@plot": ["Main"], "@object": ["Gun"], "@story": [], - "@tag": [], + "@tag": ["Scene"], "@focus": [], "@custom": [], "@time": [], @@ -316,7 +318,7 @@ def testCoreIndexData_IndexHeadingReferences(): assert head.getReferencesByKeyword("@plot") == ["Main"] assert head.getReferencesByKeyword("@object") == ["Gun"] assert head.getReferencesByKeyword("@story") == [] - assert head.getReferencesByKeyword("@tag") == [] + assert head.getReferencesByKeyword("@tag") == ["Scene"] assert head.getReferencesByKeyword("@focus") == [] assert head.getReferencesByKeyword("@custom") == [] assert head.getReferencesByKeyword("@time") == [] From b4db960e685aa0435987d3149146e66dd95e5c0f Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Tue, 24 Jun 2025 16:16:15 +0200 Subject: [PATCH 09/12] Add scene tag to sample main scene --- sample/content/636b6aa9b697b.nwd | 5 +++-- sample/nwProject.nwx | 6 +++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/sample/content/636b6aa9b697b.nwd b/sample/content/636b6aa9b697b.nwd index e3d4bfde..416efc4e 100644 --- a/sample/content/636b6aa9b697b.nwd +++ b/sample/content/636b6aa9b697b.nwd @@ -1,10 +1,11 @@ %%~name: Making a Scene %%~path: 6a2d6d5f4f401/636b6aa9b697b %%~kind: NOVEL/DOCUMENT -%%~hash: 1f3d98a6a27b4f9a7f2239fcd78f9e2263cd3b97 -%%~date: Unknown/2025-05-18 22:36:59 +%%~hash: b39201b02e3db63493d61d09e5fec5765a937255 +%%~date: Unknown/2025-06-24 09:09:56 ### Making a Scene +@tag: Scene @pov: Jane @char: John, Jane @location: Earth diff --git a/sample/nwProject.nwx b/sample/nwProject.nwx index ae0fee4d..c53ff1c9 100644 --- a/sample/nwProject.nwx +++ b/sample/nwProject.nwx @@ -1,6 +1,6 @@ - - + + Sample Project Jane Smith @@ -58,7 +58,7 @@ Chapter One - + Making a Scene From b16783143f1a2581a635aaa7562bac2bef975e6e Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Tue, 24 Jun 2025 16:37:50 +0200 Subject: [PATCH 10/12] Bump version to 2.7.2 and update changelog --- CHANGELOG.md | 40 ++++++++++++++++++++++++++++++++++++++++ novelwriter/__init__.py | 6 +++--- sample/nwProject.nwx | 4 ++-- 3 files changed, 45 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 455d9449..209aba53 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,45 @@ # novelWriter Changelog +## Version 2.7.2 [2025-06-24] + +### Release Notes + +This is a patch release that fixes several issues related to DocX and PDF manuscript documents, +improves how line breaks, alignment and indentation is processed, and fixes some issues with +displaying tags for novel documents on the user interface. + +### Detailed Changelog + +**Bugfixes** + +* Fixed an issue where escaped markup characters were not replaced properly in DocX and PDF + documents, and in previews. Issue #2410. PR #2411. +* Fixed an issue where titles with line breaks in them would have page breaks applied to both lines + for preview and PDF documents. Issue #2415. PR #2416. +* When comments are enabled in the viewer, story comments should also be visible. A separate filter + button will be added for this in 2.8. PR #2420. +* Fixed an issue where the justified text setting would not be properly applied to a paragraph in a + manuscript document if there was a line break in the paragraph, but single line breaks were set + to be ignored. Issue #2426. PR #2427. +* Fixed an issue where the "Tag" field of the Outline View details panel remained blank even if a + tag was set for the novel document. Issue #2428. PR #2429. + +**Improvements** + +* When a paragraph has line breaks in it, the alignment tag will now override first line + indentation even if the alignment tag is not on the first line. This is more consistent with the + alignment behaviour for multi-line paragraphs in general. Issue #2425. PR #2427. +* Tags will now be shown in the Novel View tooltip pop-out under the triangle button, together with + all the other meta data collected about a document or heading. PR #2429. + +**Documentation** + +* The documentation on how alignment and first line indentation works in conjunction with + in-paragraph line breaks, the setting to keep or ignore such line breaks, and the forced line + break shortcode, has been improved. Issue #2425. PR #2427. + +---- + ## Version 2.7.1 [2025-06-09] ### Release Notes diff --git a/novelwriter/__init__.py b/novelwriter/__init__.py index 594dc30c..7e9f604a 100644 --- a/novelwriter/__init__.py +++ b/novelwriter/__init__.py @@ -49,9 +49,9 @@ __license__ = "GPLv3" __author__ = "Veronica Berglyd Olsen" __maintainer__ = "Veronica Berglyd Olsen" __email__ = "code@vkbo.net" -__version__ = "2.7.1" -__hexversion__ = "0x020701f0" -__date__ = "2025-06-09" +__version__ = "2.7.2" +__hexversion__ = "0x020702f0" +__date__ = "2025-06-24" __status__ = "Stable" __domain__ = "novelwriter.io" diff --git a/sample/nwProject.nwx b/sample/nwProject.nwx index c53ff1c9..d25301aa 100644 --- a/sample/nwProject.nwx +++ b/sample/nwProject.nwx @@ -1,6 +1,6 @@ - - + + Sample Project Jane Smith From 4dd2d63d9bd6755581529d8e1045480286239240 Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Tue, 24 Jun 2025 16:40:25 +0200 Subject: [PATCH 11/12] Update changelog --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 209aba53..b7c7a039 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,8 +16,6 @@ displaying tags for novel documents on the user interface. documents, and in previews. Issue #2410. PR #2411. * Fixed an issue where titles with line breaks in them would have page breaks applied to both lines for preview and PDF documents. Issue #2415. PR #2416. -* When comments are enabled in the viewer, story comments should also be visible. A separate filter - button will be added for this in 2.8. PR #2420. * Fixed an issue where the justified text setting would not be properly applied to a paragraph in a manuscript document if there was a line break in the paragraph, but single line breaks were set to be ignored. Issue #2426. PR #2427. @@ -26,6 +24,8 @@ displaying tags for novel documents on the user interface. **Improvements** +* When comments are enabled in the viewer, story comments should also be visible. A separate filter + button will be added for this in 2.8. PR #2420. * When a paragraph has line breaks in it, the alignment tag will now override first line indentation even if the alignment tag is not on the first line. This is more consistent with the alignment behaviour for multi-line paragraphs in general. Issue #2425. PR #2427. From 5b24d8e61a73d28329f6898fa554d0dbe0dde930 Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Tue, 24 Jun 2025 17:16:39 +0200 Subject: [PATCH 12/12] Fix merge issue --- novelwriter/gui/docviewer.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/novelwriter/gui/docviewer.py b/novelwriter/gui/docviewer.py index ec002e9f..d5445536 100644 --- a/novelwriter/gui/docviewer.py +++ b/novelwriter/gui/docviewer.py @@ -228,8 +228,6 @@ class GuiDocViewer(QTextBrowser): qDoc.setTheme(self._docTheme) qDoc.initDocument() qDoc.setKeywords(True) - qDoc.setCommentType(nwComment.NOTE, CONFIG.viewComments) - qDoc.setCommentType(nwComment.STORY, CONFIG.viewComments) qDoc.setCommentType(nwComment.PLAIN, CONFIG.viewComments) qDoc.setCommentType(nwComment.SYNOPSIS, CONFIG.viewSynopsis) qDoc.setCommentType(nwComment.SHORT, CONFIG.viewSynopsis)