novelWriter 2.7.5__py3-none-any.whl → 2.8b1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- novelwriter/__init__.py +8 -7
 - novelwriter/assets/icons/font_awesome.icons +22 -4
 - novelwriter/assets/icons/material_filled_normal.icons +20 -2
 - novelwriter/assets/icons/material_filled_thin.icons +20 -2
 - novelwriter/assets/icons/material_rounded_normal.icons +20 -2
 - novelwriter/assets/icons/material_rounded_thin.icons +20 -2
 - novelwriter/assets/icons/material_sharp_normal.icons +20 -2
 - novelwriter/assets/icons/material_sharp_thin.icons +20 -2
 - novelwriter/assets/icons/remix_filled.icons +20 -2
 - novelwriter/assets/icons/remix_outline.icons +20 -2
 - novelwriter/assets/images/welcome.webp +0 -0
 - novelwriter/assets/manual.pdf +0 -0
 - novelwriter/assets/manual_fr.pdf +0 -0
 - novelwriter/assets/sample.zip +0 -0
 - novelwriter/assets/text/credits_en.htm +61 -11
 - novelwriter/assets/themes/aura.conf +97 -0
 - novelwriter/assets/themes/aura_bright.conf +95 -0
 - novelwriter/assets/themes/aura_soft.conf +97 -0
 - novelwriter/assets/themes/b2t_garden_dark.conf +97 -0
 - novelwriter/assets/themes/b2t_garden_light.conf +97 -0
 - novelwriter/assets/themes/b2t_suburb_dark.conf +97 -0
 - novelwriter/assets/themes/b2t_suburb_light.conf +97 -0
 - novelwriter/assets/themes/b4t_classic_o_dark.conf +97 -0
 - novelwriter/assets/themes/b4t_classic_o_light.conf +97 -0
 - novelwriter/assets/themes/b4t_modern_c_dark.conf +97 -0
 - novelwriter/assets/themes/b4t_modern_c_light.conf +97 -0
 - novelwriter/assets/themes/blue_streak_dark.conf +97 -0
 - novelwriter/assets/themes/blue_streak_light.conf +97 -0
 - novelwriter/assets/themes/castle_day.conf +95 -0
 - novelwriter/assets/themes/castle_night.conf +95 -0
 - novelwriter/assets/themes/catppuccin_latte.conf +97 -0
 - novelwriter/assets/themes/catppuccin_mocha.conf +97 -0
 - novelwriter/assets/themes/chalky_soil.conf +95 -0
 - novelwriter/assets/themes/chernozem.conf +95 -0
 - novelwriter/assets/themes/cyberpunk_night.conf +88 -40
 - novelwriter/assets/themes/default_dark.conf +89 -41
 - novelwriter/assets/themes/default_light.conf +89 -41
 - novelwriter/assets/themes/dracula.conf +91 -42
 - novelwriter/assets/themes/espresso.conf +97 -0
 - novelwriter/assets/themes/everforest_dark.conf +97 -0
 - novelwriter/assets/themes/everforest_light.conf +97 -0
 - novelwriter/assets/themes/floral_daydream.conf +95 -0
 - novelwriter/assets/themes/floral_midnight.conf +95 -0
 - novelwriter/assets/themes/full_moon.conf +95 -0
 - novelwriter/assets/themes/grey_dark.conf +97 -0
 - novelwriter/assets/themes/grey_light.conf +97 -0
 - novelwriter/assets/themes/horizon_dark.conf +97 -0
 - novelwriter/assets/themes/horizon_light.conf +97 -0
 - novelwriter/assets/themes/jewel_case_dark.conf +95 -0
 - novelwriter/assets/themes/jewel_case_light.conf +95 -0
 - novelwriter/assets/themes/lcars.conf +97 -0
 - novelwriter/assets/themes/light_owl.conf +117 -0
 - novelwriter/assets/themes/new_moon.conf +97 -0
 - novelwriter/assets/themes/night_owl.conf +117 -0
 - novelwriter/assets/themes/noctis.conf +129 -0
 - novelwriter/assets/themes/noctis_lux.conf +129 -0
 - novelwriter/assets/themes/nord.conf +97 -0
 - novelwriter/assets/themes/nordlicht.conf +95 -0
 - novelwriter/assets/themes/otium_dark.conf +95 -0
 - novelwriter/assets/themes/otium_light.conf +95 -0
 - novelwriter/assets/themes/paragon.conf +96 -0
 - novelwriter/assets/themes/primer_light.conf +97 -0
 - novelwriter/assets/themes/primer_night.conf +97 -0
 - novelwriter/assets/themes/rose_pine.conf +97 -0
 - novelwriter/assets/themes/rose_pine_dawn.conf +97 -0
 - novelwriter/assets/themes/ruby_day.conf +95 -0
 - novelwriter/assets/themes/ruby_night.conf +95 -0
 - novelwriter/assets/themes/selenium_dark.conf +95 -0
 - novelwriter/assets/themes/selenium_light.conf +95 -0
 - novelwriter/assets/themes/sepia_dark.conf +95 -0
 - novelwriter/assets/themes/sepia_light.conf +95 -0
 - novelwriter/assets/themes/snazzy.conf +102 -40
 - novelwriter/assets/themes/solarized_dark.conf +108 -40
 - novelwriter/assets/themes/solarized_light.conf +108 -40
 - novelwriter/assets/themes/sultana_light.conf +95 -0
 - novelwriter/assets/themes/sultana_night.conf +95 -0
 - novelwriter/assets/themes/tango_dark.conf +111 -0
 - novelwriter/assets/themes/tango_light.conf +111 -0
 - novelwriter/assets/themes/tomorrow.conf +117 -0
 - novelwriter/assets/themes/tomorrow_night.conf +117 -0
 - novelwriter/assets/themes/tomorrow_night_blue.conf +117 -0
 - novelwriter/assets/themes/tomorrow_night_bright.conf +117 -0
 - novelwriter/assets/themes/tomorrow_night_eighties.conf +117 -0
 - novelwriter/assets/themes/vivid_black_green.conf +97 -0
 - novelwriter/assets/themes/vivid_black_red.conf +97 -0
 - novelwriter/assets/themes/vivid_white_green.conf +97 -0
 - novelwriter/assets/themes/vivid_white_red.conf +97 -0
 - novelwriter/assets/themes/warpgate.conf +96 -0
 - novelwriter/assets/themes/waterlily_dark.conf +95 -0
 - novelwriter/assets/themes/waterlily_light.conf +95 -0
 - novelwriter/common.py +47 -17
 - novelwriter/config.py +57 -62
 - novelwriter/constants.py +32 -6
 - novelwriter/core/buildsettings.py +3 -23
 - novelwriter/core/coretools.py +21 -25
 - novelwriter/core/docbuild.py +4 -9
 - novelwriter/core/document.py +2 -6
 - novelwriter/core/index.py +33 -53
 - novelwriter/core/indexdata.py +17 -22
 - novelwriter/core/item.py +11 -35
 - novelwriter/core/itemmodel.py +5 -21
 - novelwriter/core/novelmodel.py +3 -7
 - novelwriter/core/options.py +3 -4
 - novelwriter/core/project.py +31 -21
 - novelwriter/core/projectdata.py +2 -21
 - novelwriter/core/projectxml.py +13 -21
 - novelwriter/core/sessions.py +2 -4
 - novelwriter/core/spellcheck.py +12 -13
 - novelwriter/core/status.py +27 -20
 - novelwriter/core/storage.py +5 -10
 - novelwriter/core/tree.py +6 -15
 - novelwriter/dialogs/about.py +9 -10
 - novelwriter/dialogs/docmerge.py +17 -14
 - novelwriter/dialogs/docsplit.py +18 -14
 - novelwriter/dialogs/editlabel.py +15 -9
 - novelwriter/dialogs/preferences.py +69 -68
 - novelwriter/dialogs/projectsettings.py +88 -67
 - novelwriter/dialogs/quotes.py +15 -10
 - novelwriter/dialogs/wordlist.py +18 -21
 - novelwriter/enum.py +75 -30
 - novelwriter/error.py +6 -11
 - novelwriter/extensions/configlayout.py +8 -34
 - novelwriter/extensions/eventfilters.py +3 -3
 - novelwriter/extensions/modified.py +87 -32
 - novelwriter/extensions/novelselector.py +13 -12
 - novelwriter/extensions/pagedsidebar.py +10 -18
 - novelwriter/extensions/progressbars.py +5 -11
 - novelwriter/extensions/statusled.py +3 -6
 - novelwriter/extensions/switch.py +8 -11
 - novelwriter/extensions/switchbox.py +2 -11
 - novelwriter/extensions/versioninfo.py +6 -7
 - novelwriter/formats/shared.py +10 -2
 - novelwriter/formats/todocx.py +15 -37
 - novelwriter/formats/tohtml.py +52 -61
 - novelwriter/formats/tokenizer.py +33 -64
 - novelwriter/formats/tomarkdown.py +4 -11
 - novelwriter/formats/toodt.py +12 -71
 - novelwriter/formats/toqdoc.py +11 -21
 - novelwriter/formats/toraw.py +2 -6
 - novelwriter/gui/doceditor.py +160 -225
 - novelwriter/gui/dochighlight.py +142 -101
 - novelwriter/gui/docviewer.py +53 -84
 - novelwriter/gui/docviewerpanel.py +18 -41
 - novelwriter/gui/editordocument.py +12 -17
 - novelwriter/gui/itemdetails.py +5 -14
 - novelwriter/gui/mainmenu.py +24 -32
 - novelwriter/gui/noveltree.py +13 -51
 - novelwriter/gui/outline.py +20 -61
 - novelwriter/gui/projtree.py +40 -96
 - novelwriter/gui/search.py +9 -24
 - novelwriter/gui/sidebar.py +54 -22
 - novelwriter/gui/statusbar.py +7 -22
 - novelwriter/gui/theme.py +482 -368
 - novelwriter/guimain.py +87 -101
 - novelwriter/shared.py +79 -48
 - novelwriter/splash.py +9 -5
 - novelwriter/text/comments.py +1 -1
 - novelwriter/text/counting.py +9 -5
 - novelwriter/text/patterns.py +20 -15
 - novelwriter/tools/dictionaries.py +18 -16
 - novelwriter/tools/lipsum.py +15 -17
 - novelwriter/tools/manusbuild.py +25 -45
 - novelwriter/tools/manuscript.py +94 -95
 - novelwriter/tools/manussettings.py +149 -104
 - novelwriter/tools/noveldetails.py +10 -24
 - novelwriter/tools/welcome.py +24 -72
 - novelwriter/tools/writingstats.py +17 -26
 - novelwriter/types.py +23 -13
 - {novelwriter-2.7.5.dist-info → novelwriter-2.8b1.dist-info}/METADATA +7 -7
 - novelwriter-2.8b1.dist-info/RECORD +212 -0
 - novelwriter/assets/images/welcome-dark.jpg +0 -0
 - novelwriter/assets/images/welcome-light.jpg +0 -0
 - novelwriter/assets/syntax/cyberpunk_night.conf +0 -28
 - novelwriter/assets/syntax/default_dark.conf +0 -42
 - novelwriter/assets/syntax/default_light.conf +0 -42
 - novelwriter/assets/syntax/dracula.conf +0 -44
 - novelwriter/assets/syntax/grey_dark.conf +0 -29
 - novelwriter/assets/syntax/grey_light.conf +0 -29
 - novelwriter/assets/syntax/light_owl.conf +0 -49
 - novelwriter/assets/syntax/night_owl.conf +0 -49
 - novelwriter/assets/syntax/snazzy.conf +0 -42
 - novelwriter/assets/syntax/solarized_dark.conf +0 -29
 - novelwriter/assets/syntax/solarized_light.conf +0 -29
 - novelwriter/assets/syntax/tango.conf +0 -39
 - novelwriter/assets/syntax/tomorrow.conf +0 -49
 - novelwriter/assets/syntax/tomorrow_night.conf +0 -49
 - novelwriter/assets/syntax/tomorrow_night_blue.conf +0 -49
 - novelwriter/assets/syntax/tomorrow_night_bright.conf +0 -49
 - novelwriter/assets/syntax/tomorrow_night_eighties.conf +0 -49
 - novelwriter/assets/themes/default.conf +0 -3
 - novelwriter-2.7.5.dist-info/RECORD +0 -163
 - {novelwriter-2.7.5.dist-info → novelwriter-2.8b1.dist-info}/WHEEL +0 -0
 - {novelwriter-2.7.5.dist-info → novelwriter-2.8b1.dist-info}/entry_points.txt +0 -0
 - {novelwriter-2.7.5.dist-info → novelwriter-2.8b1.dist-info}/licenses/LICENSE.md +0 -0
 - {novelwriter-2.7.5.dist-info → novelwriter-2.8b1.dist-info}/licenses/setup/LICENSE-Apache-2.0.txt +0 -0
 - {novelwriter-2.7.5.dist-info → novelwriter-2.8b1.dist-info}/top_level.txt +0 -0
 
    
        novelwriter/formats/tokenizer.py
    CHANGED
    
    | 
         @@ -21,7 +21,7 @@ General Public License for more details. 
     | 
|
| 
       21 
21 
     | 
    
         | 
| 
       22 
22 
     | 
    
         
             
            You should have received a copy of the GNU General Public License
         
     | 
| 
       23 
23 
     | 
    
         
             
            along with this program. If not, see <https://www.gnu.org/licenses/>.
         
     | 
| 
       24 
     | 
    
         
            -
            """
         
     | 
| 
      
 24 
     | 
    
         
            +
            """  # noqa
         
     | 
| 
       25 
25 
     | 
    
         
             
            from __future__ import annotations
         
     | 
| 
       26 
26 
     | 
    
         | 
| 
       27 
27 
     | 
    
         
             
            import logging
         
     | 
| 
         @@ -55,6 +55,7 @@ logger = logging.getLogger(__name__) 
     | 
|
| 
       55 
55 
     | 
    
         | 
| 
       56 
56 
     | 
    
         | 
| 
       57 
57 
     | 
    
         
             
            class ComStyle(NamedTuple):
         
     | 
| 
      
 58 
     | 
    
         
            +
                """Comment style info."""
         
     | 
| 
       58 
59 
     | 
    
         | 
| 
       59 
60 
     | 
    
         
             
                label: str = ""
         
     | 
| 
       60 
61 
     | 
    
         
             
                labelClass: str = ""
         
     | 
| 
         @@ -71,16 +72,28 @@ COMMENT_STYLE = { 
     | 
|
| 
       71 
72 
     | 
    
         
             
                nwComment.COMMENT:  ComStyle(),
         
     | 
| 
       72 
73 
     | 
    
         
             
                nwComment.STORY:    ComStyle("Story Structure", "modifier", "note"),
         
     | 
| 
       73 
74 
     | 
    
         
             
            }
         
     | 
| 
       74 
     | 
    
         
            -
             
     | 
| 
      
 75 
     | 
    
         
            +
            COMMENT_TYPE = {
         
     | 
| 
      
 76 
     | 
    
         
            +
                nwComment.PLAIN:    BlockTyp.COMMENT,
         
     | 
| 
      
 77 
     | 
    
         
            +
                nwComment.IGNORE:   BlockTyp.COMMENT,
         
     | 
| 
      
 78 
     | 
    
         
            +
                nwComment.SYNOPSIS: BlockTyp.SUMMARY,
         
     | 
| 
      
 79 
     | 
    
         
            +
                nwComment.SHORT:    BlockTyp.SUMMARY,
         
     | 
| 
      
 80 
     | 
    
         
            +
                nwComment.NOTE:     BlockTyp.NOTE,
         
     | 
| 
      
 81 
     | 
    
         
            +
                nwComment.FOOTNOTE: BlockTyp.COMMENT,
         
     | 
| 
      
 82 
     | 
    
         
            +
                nwComment.COMMENT:  BlockTyp.COMMENT,
         
     | 
| 
      
 83 
     | 
    
         
            +
                nwComment.STORY:    BlockTyp.NOTE,
         
     | 
| 
      
 84 
     | 
    
         
            +
            }
         
     | 
| 
      
 85 
     | 
    
         
            +
            HEADING_BLOCKS = [
         
     | 
| 
       75 
86 
     | 
    
         
             
                BlockTyp.TITLE, BlockTyp.PART, BlockTyp.HEAD1,
         
     | 
| 
       76 
87 
     | 
    
         
             
                BlockTyp.HEAD2, BlockTyp.HEAD3, BlockTyp.HEAD4,
         
     | 
| 
       77 
88 
     | 
    
         
             
            ]
         
     | 
| 
       78 
     | 
    
         
            -
             
     | 
| 
      
 89 
     | 
    
         
            +
            COMMENT_BLOCKS = (BlockTyp.COMMENT, BlockTyp.SUMMARY, BlockTyp.NOTE)
         
     | 
| 
      
 90 
     | 
    
         
            +
            META_BLOCKS = (BlockTyp.COMMENT, BlockTyp.SUMMARY, BlockTyp.NOTE, BlockTyp.KEYWORD)
         
     | 
| 
      
 91 
     | 
    
         
            +
            SKIP_INDENT = [*HEADING_BLOCKS, BlockTyp.SEP, BlockTyp.SKIP]
         
     | 
| 
       79 
92 
     | 
    
         
             
            B_EMPTY: T_Block = (BlockTyp.EMPTY, "", "", [], BlockFmt.NONE)
         
     | 
| 
       80 
93 
     | 
    
         | 
| 
       81 
94 
     | 
    
         | 
| 
       82 
95 
     | 
    
         
             
            class Tokenizer(ABC):
         
     | 
| 
       83 
     | 
    
         
            -
                """Core: Text Tokenizer Abstract Base Class
         
     | 
| 
      
 96 
     | 
    
         
            +
                """Core: Text Tokenizer Abstract Base Class.
         
     | 
| 
       84 
97 
     | 
    
         | 
| 
       85 
98 
     | 
    
         
             
                This is the base class for all document build classes. It parses the
         
     | 
| 
       86 
99 
     | 
    
         
             
                novelWriter markup format and generates a registry of tokens and
         
     | 
| 
         @@ -189,6 +202,7 @@ class Tokenizer(ABC): 
     | 
|
| 
       189 
202 
     | 
    
         
             
                        (REGEX_PATTERNS.markdownItalic, [0, TextFmt.I_B, 0, TextFmt.I_E]),
         
     | 
| 
       190 
203 
     | 
    
         
             
                        (REGEX_PATTERNS.markdownBold,   [0, TextFmt.B_B, 0, TextFmt.B_E]),
         
     | 
| 
       191 
204 
     | 
    
         
             
                        (REGEX_PATTERNS.markdownStrike, [0, TextFmt.D_B, 0, TextFmt.D_E]),
         
     | 
| 
      
 205 
     | 
    
         
            +
                        (REGEX_PATTERNS.markdownMark,   [0, TextFmt.M_B, 0, TextFmt.M_E]),
         
     | 
| 
       192 
206 
     | 
    
         
             
                    ]
         
     | 
| 
       193 
207 
     | 
    
         | 
| 
       194 
208 
     | 
    
         
             
                    self._shortCodeFmt = {
         
     | 
| 
         @@ -211,8 +225,6 @@ class Tokenizer(ABC): 
     | 
|
| 
       211 
225 
     | 
    
         
             
                    self._dialogParser = DialogParser()
         
     | 
| 
       212 
226 
     | 
    
         
             
                    self._dialogParser.initParser()
         
     | 
| 
       213 
227 
     | 
    
         | 
| 
       214 
     | 
    
         
            -
                    return
         
     | 
| 
       215 
     | 
    
         
            -
             
     | 
| 
       216 
228 
     | 
    
         
             
                ##
         
     | 
| 
       217 
229 
     | 
    
         
             
                #  Properties
         
     | 
| 
       218 
230 
     | 
    
         
             
                ##
         
     | 
| 
         @@ -240,94 +252,78 @@ class Tokenizer(ABC): 
     | 
|
| 
       240 
252 
     | 
    
         
             
                    """Set language for the document."""
         
     | 
| 
       241 
253 
     | 
    
         
             
                    if language:
         
     | 
| 
       242 
254 
     | 
    
         
             
                        self._dLocale = QLocale(language)
         
     | 
| 
       243 
     | 
    
         
            -
                    return
         
     | 
| 
       244 
255 
     | 
    
         | 
| 
       245 
256 
     | 
    
         
             
                def setTheme(self, theme: TextDocumentTheme) -> None:
         
     | 
| 
       246 
257 
     | 
    
         
             
                    """Set the document colour theme."""
         
     | 
| 
       247 
258 
     | 
    
         
             
                    self._theme = theme
         
     | 
| 
       248 
     | 
    
         
            -
                    return
         
     | 
| 
       249 
259 
     | 
    
         | 
| 
       250 
260 
     | 
    
         
             
                def setPartitionFormat(self, hFormat: str, hide: bool = False) -> None:
         
     | 
| 
       251 
261 
     | 
    
         
             
                    """Set the partition format pattern."""
         
     | 
| 
       252 
262 
     | 
    
         
             
                    self._fmtPart = hFormat.strip()
         
     | 
| 
       253 
263 
     | 
    
         
             
                    self._hidePart = hide
         
     | 
| 
       254 
     | 
    
         
            -
                    return
         
     | 
| 
       255 
264 
     | 
    
         | 
| 
       256 
265 
     | 
    
         
             
                def setChapterFormat(self, hFormat: str, hide: bool = False) -> None:
         
     | 
| 
       257 
266 
     | 
    
         
             
                    """Set the chapter format pattern."""
         
     | 
| 
       258 
267 
     | 
    
         
             
                    self._fmtChapter = hFormat.strip()
         
     | 
| 
       259 
268 
     | 
    
         
             
                    self._hideChapter = hide
         
     | 
| 
       260 
     | 
    
         
            -
                    return
         
     | 
| 
       261 
269 
     | 
    
         | 
| 
       262 
270 
     | 
    
         
             
                def setUnNumberedFormat(self, hFormat: str, hide: bool = False) -> None:
         
     | 
| 
       263 
271 
     | 
    
         
             
                    """Set the unnumbered format pattern."""
         
     | 
| 
       264 
272 
     | 
    
         
             
                    self._fmtUnNum = hFormat.strip()
         
     | 
| 
       265 
273 
     | 
    
         
             
                    self._hideUnNum = hide
         
     | 
| 
       266 
     | 
    
         
            -
                    return
         
     | 
| 
       267 
274 
     | 
    
         | 
| 
       268 
275 
     | 
    
         
             
                def setSceneFormat(self, hFormat: str, hide: bool = False) -> None:
         
     | 
| 
       269 
276 
     | 
    
         
             
                    """Set the scene format pattern and hidden status."""
         
     | 
| 
       270 
277 
     | 
    
         
             
                    self._fmtScene = hFormat.strip()
         
     | 
| 
       271 
278 
     | 
    
         
             
                    self._hideScene = hide
         
     | 
| 
       272 
     | 
    
         
            -
                    return
         
     | 
| 
       273 
279 
     | 
    
         | 
| 
       274 
280 
     | 
    
         
             
                def setHardSceneFormat(self, hFormat: str, hide: bool = False) -> None:
         
     | 
| 
       275 
281 
     | 
    
         
             
                    """Set the hard scene format pattern and hidden status."""
         
     | 
| 
       276 
282 
     | 
    
         
             
                    self._fmtHScene = hFormat.strip()
         
     | 
| 
       277 
283 
     | 
    
         
             
                    self._hideHScene = hide
         
     | 
| 
       278 
     | 
    
         
            -
                    return
         
     | 
| 
       279 
284 
     | 
    
         | 
| 
       280 
285 
     | 
    
         
             
                def setSectionFormat(self, hFormat: str, hide: bool = False) -> None:
         
     | 
| 
       281 
286 
     | 
    
         
             
                    """Set the section format pattern and hidden status."""
         
     | 
| 
       282 
287 
     | 
    
         
             
                    self._fmtSection = hFormat.strip()
         
     | 
| 
       283 
288 
     | 
    
         
             
                    self._hideSection = hide
         
     | 
| 
       284 
     | 
    
         
            -
                    return
         
     | 
| 
       285 
289 
     | 
    
         | 
| 
       286 
290 
     | 
    
         
             
                def setTitleStyle(self, center: bool, pageBreak: bool) -> None:
         
     | 
| 
       287 
291 
     | 
    
         
             
                    """Set the title heading style."""
         
     | 
| 
       288 
292 
     | 
    
         
             
                    self._titleStyle = BlockFmt.CENTRE if center else BlockFmt.NONE
         
     | 
| 
       289 
293 
     | 
    
         
             
                    self._titleStyle |= BlockFmt.PBB if pageBreak else BlockFmt.NONE
         
     | 
| 
       290 
     | 
    
         
            -
                    return
         
     | 
| 
       291 
294 
     | 
    
         | 
| 
       292 
295 
     | 
    
         
             
                def setPartitionStyle(self, center: bool, pageBreak: bool) -> None:
         
     | 
| 
       293 
296 
     | 
    
         
             
                    """Set the partition heading style."""
         
     | 
| 
       294 
297 
     | 
    
         
             
                    self._partStyle = BlockFmt.CENTRE if center else BlockFmt.NONE
         
     | 
| 
       295 
298 
     | 
    
         
             
                    self._partStyle |= BlockFmt.PBB if pageBreak else BlockFmt.NONE
         
     | 
| 
       296 
     | 
    
         
            -
                    return
         
     | 
| 
       297 
299 
     | 
    
         | 
| 
       298 
300 
     | 
    
         
             
                def setChapterStyle(self, center: bool, pageBreak: bool) -> None:
         
     | 
| 
       299 
301 
     | 
    
         
             
                    """Set the chapter heading style."""
         
     | 
| 
       300 
302 
     | 
    
         
             
                    self._chapterStyle = BlockFmt.CENTRE if center else BlockFmt.NONE
         
     | 
| 
       301 
303 
     | 
    
         
             
                    self._chapterStyle |= BlockFmt.PBB if pageBreak else BlockFmt.NONE
         
     | 
| 
       302 
     | 
    
         
            -
                    return
         
     | 
| 
       303 
304 
     | 
    
         | 
| 
       304 
305 
     | 
    
         
             
                def setSceneStyle(self, center: bool, pageBreak: bool) -> None:
         
     | 
| 
       305 
306 
     | 
    
         
             
                    """Set the scene heading style."""
         
     | 
| 
       306 
307 
     | 
    
         
             
                    self._sceneStyle = BlockFmt.CENTRE if center else BlockFmt.NONE
         
     | 
| 
       307 
308 
     | 
    
         
             
                    self._sceneStyle |= BlockFmt.PBB if pageBreak else BlockFmt.NONE
         
     | 
| 
       308 
     | 
    
         
            -
                    return
         
     | 
| 
       309 
309 
     | 
    
         | 
| 
       310 
310 
     | 
    
         
             
                def setTextFont(self, font: QFont) -> None:
         
     | 
| 
       311 
311 
     | 
    
         
             
                    """Set the build font."""
         
     | 
| 
       312 
312 
     | 
    
         
             
                    self._textFont = fontMatcher(font)
         
     | 
| 
       313 
     | 
    
         
            -
                    return
         
     | 
| 
       314 
313 
     | 
    
         | 
| 
       315 
314 
     | 
    
         
             
                def setLineHeight(self, height: float) -> None:
         
     | 
| 
       316 
315 
     | 
    
         
             
                    """Set the line height between 0.5 and 5.0."""
         
     | 
| 
       317 
316 
     | 
    
         
             
                    self._lineHeight = min(max(float(height), 0.5), 5.0)
         
     | 
| 
       318 
     | 
    
         
            -
                    return
         
     | 
| 
       319 
317 
     | 
    
         | 
| 
       320 
318 
     | 
    
         
             
                def setHeadingStyles(self, color: bool, scale: bool, bold: bool) -> None:
         
     | 
| 
       321 
319 
     | 
    
         
             
                    """Set text style for headings."""
         
     | 
| 
       322 
320 
     | 
    
         
             
                    self._colorHeads = color
         
     | 
| 
       323 
321 
     | 
    
         
             
                    self._scaleHeads = scale
         
     | 
| 
       324 
322 
     | 
    
         
             
                    self._boldHeads = bold
         
     | 
| 
       325 
     | 
    
         
            -
                    return
         
     | 
| 
       326 
323 
     | 
    
         | 
| 
       327 
324 
     | 
    
         
             
                def setBlockIndent(self, indent: float) -> None:
         
     | 
| 
       328 
325 
     | 
    
         
             
                    """Set the block indent between 0.0 and 10.0."""
         
     | 
| 
       329 
326 
     | 
    
         
             
                    self._blockIndent = min(max(float(indent), 0.0), 10.0)
         
     | 
| 
       330 
     | 
    
         
            -
                    return
         
     | 
| 
       331 
327 
     | 
    
         | 
| 
       332 
328 
     | 
    
         
             
                def setFirstLineIndent(self, state: bool, indent: float, first: bool) -> None:
         
     | 
| 
       333 
329 
     | 
    
         
             
                    """Set first line indent and whether to also indent first
         
     | 
| 
         @@ -336,67 +332,54 @@ class Tokenizer(ABC): 
     | 
|
| 
       336 
332 
     | 
    
         
             
                    self._firstIndent = state
         
     | 
| 
       337 
333 
     | 
    
         
             
                    self._firstWidth = indent
         
     | 
| 
       338 
334 
     | 
    
         
             
                    self._indentFirst = first
         
     | 
| 
       339 
     | 
    
         
            -
                    return
         
     | 
| 
       340 
335 
     | 
    
         | 
| 
       341 
336 
     | 
    
         
             
                def setJustify(self, state: bool) -> None:
         
     | 
| 
       342 
337 
     | 
    
         
             
                    """Enable or disable text justification."""
         
     | 
| 
       343 
338 
     | 
    
         
             
                    self._doJustify = state
         
     | 
| 
       344 
     | 
    
         
            -
                    return
         
     | 
| 
       345 
339 
     | 
    
         | 
| 
       346 
340 
     | 
    
         
             
                def setDialogHighlight(self, state: bool) -> None:
         
     | 
| 
       347 
341 
     | 
    
         
             
                    """Enable or disable dialogue highlighting."""
         
     | 
| 
       348 
342 
     | 
    
         
             
                    self._hlightDialog = state
         
     | 
| 
       349 
     | 
    
         
            -
                    return
         
     | 
| 
       350 
343 
     | 
    
         | 
| 
       351 
344 
     | 
    
         
             
                def setTitleMargins(self, upper: float, lower: float) -> None:
         
     | 
| 
       352 
345 
     | 
    
         
             
                    """Set the upper and lower title margin."""
         
     | 
| 
       353 
346 
     | 
    
         
             
                    self._marginTitle = (float(upper), float(lower))
         
     | 
| 
       354 
     | 
    
         
            -
                    return
         
     | 
| 
       355 
347 
     | 
    
         | 
| 
       356 
348 
     | 
    
         
             
                def setHead1Margins(self, upper: float, lower: float) -> None:
         
     | 
| 
       357 
349 
     | 
    
         
             
                    """Set the upper and lower heading 1 margin."""
         
     | 
| 
       358 
350 
     | 
    
         
             
                    self._marginHead1 = (float(upper), float(lower))
         
     | 
| 
       359 
     | 
    
         
            -
                    return
         
     | 
| 
       360 
351 
     | 
    
         | 
| 
       361 
352 
     | 
    
         
             
                def setHead2Margins(self, upper: float, lower: float) -> None:
         
     | 
| 
       362 
353 
     | 
    
         
             
                    """Set the upper and lower heading 2 margin."""
         
     | 
| 
       363 
354 
     | 
    
         
             
                    self._marginHead2 = (float(upper), float(lower))
         
     | 
| 
       364 
     | 
    
         
            -
                    return
         
     | 
| 
       365 
355 
     | 
    
         | 
| 
       366 
356 
     | 
    
         
             
                def setHead3Margins(self, upper: float, lower: float) -> None:
         
     | 
| 
       367 
357 
     | 
    
         
             
                    """Set the upper and lower heading 3 margin."""
         
     | 
| 
       368 
358 
     | 
    
         
             
                    self._marginHead3 = (float(upper), float(lower))
         
     | 
| 
       369 
     | 
    
         
            -
                    return
         
     | 
| 
       370 
359 
     | 
    
         | 
| 
       371 
360 
     | 
    
         
             
                def setHead4Margins(self, upper: float, lower: float) -> None:
         
     | 
| 
       372 
361 
     | 
    
         
             
                    """Set the upper and lower heading 4 margin."""
         
     | 
| 
       373 
362 
     | 
    
         
             
                    self._marginHead4 = (float(upper), float(lower))
         
     | 
| 
       374 
     | 
    
         
            -
                    return
         
     | 
| 
       375 
363 
     | 
    
         | 
| 
       376 
364 
     | 
    
         
             
                def setTextMargins(self, upper: float, lower: float) -> None:
         
     | 
| 
       377 
365 
     | 
    
         
             
                    """Set the upper and lower text margin."""
         
     | 
| 
       378 
366 
     | 
    
         
             
                    self._marginText = (float(upper), float(lower))
         
     | 
| 
       379 
     | 
    
         
            -
                    return
         
     | 
| 
       380 
367 
     | 
    
         | 
| 
       381 
368 
     | 
    
         
             
                def setMetaMargins(self, upper: float, lower: float) -> None:
         
     | 
| 
       382 
369 
     | 
    
         
             
                    """Set the upper and lower meta text margin."""
         
     | 
| 
       383 
370 
     | 
    
         
             
                    self._marginMeta = (float(upper), float(lower))
         
     | 
| 
       384 
     | 
    
         
            -
                    return
         
     | 
| 
       385 
371 
     | 
    
         | 
| 
       386 
372 
     | 
    
         
             
                def setSeparatorMargins(self, upper: float, lower: float) -> None:
         
     | 
| 
       387 
373 
     | 
    
         
             
                    """Set the upper and lower meta text margin."""
         
     | 
| 
       388 
374 
     | 
    
         
             
                    self._marginSep = (float(upper), float(lower))
         
     | 
| 
       389 
     | 
    
         
            -
                    return
         
     | 
| 
       390 
375 
     | 
    
         | 
| 
       391 
376 
     | 
    
         
             
                def setLinkHeadings(self, state: bool) -> None:
         
     | 
| 
       392 
377 
     | 
    
         
             
                    """Enable or disable adding an anchor before headings."""
         
     | 
| 
       393 
378 
     | 
    
         
             
                    self._linkHeadings = state
         
     | 
| 
       394 
     | 
    
         
            -
                    return
         
     | 
| 
       395 
379 
     | 
    
         | 
| 
       396 
380 
     | 
    
         
             
                def setBodyText(self, state: bool) -> None:
         
     | 
| 
       397 
381 
     | 
    
         
             
                    """Include body text in build."""
         
     | 
| 
       398 
382 
     | 
    
         
             
                    self._doBodyText = state
         
     | 
| 
       399 
     | 
    
         
            -
                    return
         
     | 
| 
       400 
383 
     | 
    
         | 
| 
       401 
384 
     | 
    
         
             
                def setCommentType(self, comment: nwComment, state: bool) -> None:
         
     | 
| 
       402 
385 
     | 
    
         
             
                    """Toggle the inclusion og certain comment types."""
         
     | 
| 
         @@ -404,22 +387,18 @@ class Tokenizer(ABC): 
     | 
|
| 
       404 
387 
     | 
    
         
             
                        self._doComments.add(comment)
         
     | 
| 
       405 
388 
     | 
    
         
             
                    else:
         
     | 
| 
       406 
389 
     | 
    
         
             
                        self._doComments.discard(comment)
         
     | 
| 
       407 
     | 
    
         
            -
                    return
         
     | 
| 
       408 
390 
     | 
    
         | 
| 
       409 
391 
     | 
    
         
             
                def setKeywords(self, state: bool) -> None:
         
     | 
| 
       410 
392 
     | 
    
         
             
                    """Include keywords in build."""
         
     | 
| 
       411 
393 
     | 
    
         
             
                    self._doKeywords = state
         
     | 
| 
       412 
     | 
    
         
            -
                    return
         
     | 
| 
       413 
394 
     | 
    
         | 
| 
       414 
395 
     | 
    
         
             
                def setIgnoredKeywords(self, keywords: str) -> None:
         
     | 
| 
       415 
396 
     | 
    
         
             
                    """Comma separated string of keywords to ignore."""
         
     | 
| 
       416 
397 
     | 
    
         
             
                    self._skipKeywords = set(x.lower().strip() for x in keywords.split(","))
         
     | 
| 
       417 
     | 
    
         
            -
                    return
         
     | 
| 
       418 
398 
     | 
    
         | 
| 
       419 
399 
     | 
    
         
             
                def setKeepLineBreaks(self, state: bool) -> None:
         
     | 
| 
       420 
400 
     | 
    
         
             
                    """Keep line breaks in paragraphs."""
         
     | 
| 
       421 
401 
     | 
    
         
             
                    self._keepBreaks = state
         
     | 
| 
       422 
     | 
    
         
            -
                    return
         
     | 
| 
       423 
402 
     | 
    
         | 
| 
       424 
403 
     | 
    
         
             
                ##
         
     | 
| 
       425 
404 
     | 
    
         
             
                #  Class Methods
         
     | 
| 
         @@ -447,12 +426,10 @@ class Tokenizer(ABC): 
     | 
|
| 
       447 
426 
     | 
    
         
             
                    self._classes["tag"] = self._theme.tag
         
     | 
| 
       448 
427 
     | 
    
         
             
                    self._classes["keyword"] = self._theme.keyword
         
     | 
| 
       449 
428 
     | 
    
         
             
                    self._classes["optional"] = self._theme.optional
         
     | 
| 
       450 
     | 
    
         
            -
                    return
         
     | 
| 
       451 
429 
     | 
    
         | 
| 
       452 
430 
     | 
    
         
             
                def setBreakNext(self) -> None:
         
     | 
| 
       453 
431 
     | 
    
         
             
                    """Set a page break for next block."""
         
     | 
| 
       454 
432 
     | 
    
         
             
                    self._breakNext = True
         
     | 
| 
       455 
     | 
    
         
            -
                    return
         
     | 
| 
       456 
433 
     | 
    
         | 
| 
       457 
434 
     | 
    
         
             
                def addRootHeading(self, tHandle: str) -> None:
         
     | 
| 
       458 
435 
     | 
    
         
             
                    """Add a heading at the start of a new root folder."""
         
     | 
| 
         @@ -478,8 +455,6 @@ class Tokenizer(ABC): 
     | 
|
| 
       478 
455 
     | 
    
         
             
                        if self._keepRaw:
         
     | 
| 
       479 
456 
     | 
    
         
             
                            self._raw.append(f"#! {title}\n\n")
         
     | 
| 
       480 
457 
     | 
    
         | 
| 
       481 
     | 
    
         
            -
                    return
         
     | 
| 
       482 
     | 
    
         
            -
             
     | 
| 
       483 
458 
     | 
    
         
             
                def setText(self, tHandle: str, text: str | None = None) -> None:
         
     | 
| 
       484 
459 
     | 
    
         
             
                    """Set the text for the tokenizer from a handle. If text is not
         
     | 
| 
       485 
460 
     | 
    
         
             
                    set, it's is loaded from the file.
         
     | 
| 
         @@ -490,7 +465,6 @@ class Tokenizer(ABC): 
     | 
|
| 
       490 
465 
     | 
    
         
             
                        self._text = text or self._project.storage.getDocumentText(tHandle)
         
     | 
| 
       491 
466 
     | 
    
         
             
                        self._handle = tHandle
         
     | 
| 
       492 
467 
     | 
    
         
             
                        self._isNovel = nwItem.itemLayout == nwItemLayout.DOCUMENT
         
     | 
| 
       493 
     | 
    
         
            -
                    return
         
     | 
| 
       494 
468 
     | 
    
         | 
| 
       495 
469 
     | 
    
         
             
                def doPreProcessing(self) -> None:
         
     | 
| 
       496 
470 
     | 
    
         
             
                    """Run pre-processing jobs before the text is tokenized."""
         
     | 
| 
         @@ -499,7 +473,6 @@ class Tokenizer(ABC): 
     | 
|
| 
       499 
473 
     | 
    
         
             
                        replace = {f"<{k}>": v for k, v in entry.items()}
         
     | 
| 
       500 
474 
     | 
    
         
             
                        rxRep = re.compile("|".join([re.escape(k) for k in replace]), flags=re.DOTALL)
         
     | 
| 
       501 
475 
     | 
    
         
             
                        self._text = rxRep.sub(lambda x: replace[x.group(0)], self._text)
         
     | 
| 
       502 
     | 
    
         
            -
                    return
         
     | 
| 
       503 
476 
     | 
    
         | 
| 
       504 
477 
     | 
    
         
             
                def tokenizeText(self) -> None:
         
     | 
| 
       505 
478 
     | 
    
         
             
                    """Scan the text for either lines starting with specific
         
     | 
| 
         @@ -577,13 +550,13 @@ class Tokenizer(ABC): 
     | 
|
| 
       577 
550 
     | 
    
         
             
                                self._breakNext = True
         
     | 
| 
       578 
551 
     | 
    
         
             
                                continue
         
     | 
| 
       579 
552 
     | 
    
         | 
| 
       580 
     | 
    
         
            -
                             
     | 
| 
      
 553 
     | 
    
         
            +
                            if sLine == "[vspace]":
         
     | 
| 
       581 
554 
     | 
    
         
             
                                tBlocks.append(
         
     | 
| 
       582 
555 
     | 
    
         
             
                                    (BlockTyp.SKIP, "", "", [], tStyle)
         
     | 
| 
       583 
556 
     | 
    
         
             
                                )
         
     | 
| 
       584 
557 
     | 
    
         
             
                                continue
         
     | 
| 
       585 
558 
     | 
    
         | 
| 
       586 
     | 
    
         
            -
                             
     | 
| 
      
 559 
     | 
    
         
            +
                            if sLine.startswith("[vspace:") and sLine.endswith("]"):
         
     | 
| 
       587 
560 
     | 
    
         
             
                                nSkip = checkInt(sLine[8:-1], 0)
         
     | 
| 
       588 
561 
     | 
    
         
             
                                if nSkip >= 1:
         
     | 
| 
       589 
562 
     | 
    
         
             
                                    tBlocks.append(
         
     | 
| 
         @@ -618,7 +591,7 @@ class Tokenizer(ABC): 
     | 
|
| 
       618 
591 
     | 
    
         
             
                                bStyle = COMMENT_STYLE[cStyle]
         
     | 
| 
       619 
592 
     | 
    
         
             
                                tLine, tFmt = self._formatComment(bStyle, cKey, cText)
         
     | 
| 
       620 
593 
     | 
    
         
             
                                tBlocks.append((
         
     | 
| 
       621 
     | 
    
         
            -
                                     
     | 
| 
      
 594 
     | 
    
         
            +
                                    COMMENT_TYPE[cStyle], "", tLine, tFmt, tStyle
         
     | 
| 
       622 
595 
     | 
    
         
             
                                ))
         
     | 
| 
       623 
596 
     | 
    
         | 
| 
       624 
597 
     | 
    
         
             
                            elif cStyle == nwComment.FOOTNOTE:
         
     | 
| 
         @@ -862,12 +835,12 @@ class Tokenizer(ABC): 
     | 
|
| 
       862 
835 
     | 
    
         
             
                            # We don't need to keep the empty lines after this pass
         
     | 
| 
       863 
836 
     | 
    
         
             
                            pass
         
     | 
| 
       864 
837 
     | 
    
         | 
| 
       865 
     | 
    
         
            -
                        elif cBlock[0]  
     | 
| 
       866 
     | 
    
         
            -
                            # Adjust margins for lines in  
     | 
| 
      
 838 
     | 
    
         
            +
                        elif cBlock[0] in (BlockTyp.KEYWORD, BlockTyp.NOTE):
         
     | 
| 
      
 839 
     | 
    
         
            +
                            # Adjust margins for lines in repeated meta blocks
         
     | 
| 
       867 
840 
     | 
    
         
             
                            aStyle = cBlock[4]
         
     | 
| 
       868 
     | 
    
         
            -
                            if pBlock[0] ==  
     | 
| 
      
 841 
     | 
    
         
            +
                            if pBlock[0] == cBlock[0]:
         
     | 
| 
       869 
842 
     | 
    
         
             
                                aStyle |= BlockFmt.Z_TOP
         
     | 
| 
       870 
     | 
    
         
            -
                            if nBlock[0] ==  
     | 
| 
      
 843 
     | 
    
         
            +
                            if nBlock[0] == cBlock[0]:
         
     | 
| 
       871 
844 
     | 
    
         
             
                                aStyle |= BlockFmt.Z_BTM
         
     | 
| 
       872 
845 
     | 
    
         
             
                            sBlocks.append((
         
     | 
| 
       873 
846 
     | 
    
         
             
                                cBlock[0], cBlock[1], cBlock[2], cBlock[3], aStyle
         
     | 
| 
         @@ -949,8 +922,6 @@ class Tokenizer(ABC): 
     | 
|
| 
       949 
922 
     | 
    
         
             
                        text = tText.replace(nwHeadFmt.BR, " ").replace("&", "&")
         
     | 
| 
       950 
923 
     | 
    
         
             
                        self._outline[tKey] = f"{prefix}|{text}"
         
     | 
| 
       951 
924 
     | 
    
         | 
| 
       952 
     | 
    
         
            -
                    return
         
     | 
| 
       953 
     | 
    
         
            -
             
     | 
| 
       954 
925 
     | 
    
         
             
                def countStats(self) -> None:
         
     | 
| 
       955 
926 
     | 
    
         
             
                    """Count stats on the tokenized text."""
         
     | 
| 
       956 
927 
     | 
    
         
             
                    titleCount = self._counts.get(nwStats.TITLES, 0)
         
     | 
| 
         @@ -991,7 +962,7 @@ class Tokenizer(ABC): 
     | 
|
| 
       991 
962 
     | 
    
         
             
                            allWordChars += nPWChars
         
     | 
| 
       992 
963 
     | 
    
         
             
                            textWordChars += nPWChars
         
     | 
| 
       993 
964 
     | 
    
         | 
| 
       994 
     | 
    
         
            -
                        elif tType in  
     | 
| 
      
 965 
     | 
    
         
            +
                        elif tType in HEADING_BLOCKS:
         
     | 
| 
       995 
966 
     | 
    
         
             
                            titleCount += 1
         
     | 
| 
       996 
967 
     | 
    
         
             
                            allWords += nWords
         
     | 
| 
       997 
968 
     | 
    
         
             
                            titleWords += nWords
         
     | 
| 
         @@ -1005,7 +976,7 @@ class Tokenizer(ABC): 
     | 
|
| 
       1005 
976 
     | 
    
         
             
                            allChars += nChars
         
     | 
| 
       1006 
977 
     | 
    
         
             
                            allWordChars += nWChars
         
     | 
| 
       1007 
978 
     | 
    
         | 
| 
       1008 
     | 
    
         
            -
                        elif tType in  
     | 
| 
      
 979 
     | 
    
         
            +
                        elif tType in META_BLOCKS:
         
     | 
| 
       1009 
980 
     | 
    
         
             
                            words = tText.split()
         
     | 
| 
       1010 
981 
     | 
    
         
             
                            allWords += len(words)
         
     | 
| 
       1011 
982 
     | 
    
         
             
                            allChars += len(tText)
         
     | 
| 
         @@ -1026,8 +997,6 @@ class Tokenizer(ABC): 
     | 
|
| 
       1026 
997 
     | 
    
         
             
                    self._counts[nwStats.WCHARS_TEXT] = textWordChars
         
     | 
| 
       1027 
998 
     | 
    
         
             
                    self._counts[nwStats.WCHARS_TITLE] = titleWordChars
         
     | 
| 
       1028 
999 
     | 
    
         | 
| 
       1029 
     | 
    
         
            -
                    return
         
     | 
| 
       1030 
     | 
    
         
            -
             
     | 
| 
       1031 
1000 
     | 
    
         
             
                ##
         
     | 
| 
       1032 
1001 
     | 
    
         
             
                #  Internal Functions
         
     | 
| 
       1033 
1002 
     | 
    
         
             
                ##
         
     | 
| 
         @@ -1169,6 +1138,12 @@ class Tokenizer(ABC): 
     | 
|
| 
       1169 
1138 
     | 
    
         | 
| 
       1170 
1139 
     | 
    
         | 
| 
       1171 
1140 
     | 
    
         
             
            class HeadingFormatter:
         
     | 
| 
      
 1141 
     | 
    
         
            +
                """Core: Format Text Headings.
         
     | 
| 
      
 1142 
     | 
    
         
            +
             
     | 
| 
      
 1143 
     | 
    
         
            +
                This class holds the various chapter and scene counters and can
         
     | 
| 
      
 1144 
     | 
    
         
            +
                apply the Build Settings header format settings based on internal
         
     | 
| 
      
 1145 
     | 
    
         
            +
                counter state.
         
     | 
| 
      
 1146 
     | 
    
         
            +
                """
         
     | 
| 
       1172 
1147 
     | 
    
         | 
| 
       1173 
1148 
     | 
    
         
             
                def __init__(
         
     | 
| 
       1174 
1149 
     | 
    
         
             
                    self,
         
     | 
| 
         @@ -1182,35 +1157,29 @@ class HeadingFormatter: 
     | 
|
| 
       1182 
1157 
     | 
    
         
             
                    self._chapter = chapter
         
     | 
| 
       1183 
1158 
     | 
    
         
             
                    self._scene = scene
         
     | 
| 
       1184 
1159 
     | 
    
         
             
                    self._absolute = absolute
         
     | 
| 
       1185 
     | 
    
         
            -
                    return
         
     | 
| 
       1186 
1160 
     | 
    
         | 
| 
       1187 
1161 
     | 
    
         
             
                def setHandle(self, tHandle: str | None) -> None:
         
     | 
| 
       1188 
1162 
     | 
    
         
             
                    """Set the handle currently being processed."""
         
     | 
| 
       1189 
1163 
     | 
    
         
             
                    self._handle = tHandle
         
     | 
| 
       1190 
     | 
    
         
            -
                    return
         
     | 
| 
       1191 
1164 
     | 
    
         | 
| 
       1192 
1165 
     | 
    
         
             
                def incChapter(self) -> None:
         
     | 
| 
       1193 
1166 
     | 
    
         
             
                    """Increment the chapter counter."""
         
     | 
| 
       1194 
1167 
     | 
    
         
             
                    self._chapter += 1
         
     | 
| 
       1195 
     | 
    
         
            -
                    return
         
     | 
| 
       1196 
1168 
     | 
    
         | 
| 
       1197 
1169 
     | 
    
         
             
                def incScene(self) -> None:
         
     | 
| 
       1198 
1170 
     | 
    
         
             
                    """Increment the scene counters."""
         
     | 
| 
       1199 
1171 
     | 
    
         
             
                    self._scene += 1
         
     | 
| 
       1200 
1172 
     | 
    
         
             
                    self._absolute += 1
         
     | 
| 
       1201 
     | 
    
         
            -
                    return
         
     | 
| 
       1202 
1173 
     | 
    
         | 
| 
       1203 
1174 
     | 
    
         
             
                def resetAll(self) -> None:
         
     | 
| 
       1204 
1175 
     | 
    
         
             
                    """Reset all counters."""
         
     | 
| 
       1205 
1176 
     | 
    
         
             
                    self._chapter = 0
         
     | 
| 
       1206 
1177 
     | 
    
         
             
                    self._scene = 0
         
     | 
| 
       1207 
1178 
     | 
    
         
             
                    self._absolute = 0
         
     | 
| 
       1208 
     | 
    
         
            -
                    return
         
     | 
| 
       1209 
1179 
     | 
    
         | 
| 
       1210 
1180 
     | 
    
         
             
                def resetScene(self) -> None:
         
     | 
| 
       1211 
1181 
     | 
    
         
             
                    """Reset the chapter scene counter."""
         
     | 
| 
       1212 
1182 
     | 
    
         
             
                    self._scene = 0
         
     | 
| 
       1213 
     | 
    
         
            -
                    return
         
     | 
| 
       1214 
1183 
     | 
    
         | 
| 
       1215 
1184 
     | 
    
         
             
                def apply(self, hFormat: str, text: str, nHead: int) -> str:
         
     | 
| 
       1216 
1185 
     | 
    
         
             
                    """Apply formatting to a specific heading."""
         
     | 
| 
         @@ -20,7 +20,7 @@ General Public License for more details. 
     | 
|
| 
       20 
20 
     | 
    
         | 
| 
       21 
21 
     | 
    
         
             
            You should have received a copy of the GNU General Public License
         
     | 
| 
       22 
22 
     | 
    
         
             
            along with this program. If not, see <https://www.gnu.org/licenses/>.
         
     | 
| 
       23 
     | 
    
         
            -
            """
         
     | 
| 
      
 23 
     | 
    
         
            +
            """  # noqa
         
     | 
| 
       24 
24 
     | 
    
         
             
            from __future__ import annotations
         
     | 
| 
       25 
25 
     | 
    
         | 
| 
       26 
26 
     | 
    
         
             
            import logging
         
     | 
| 
         @@ -29,7 +29,7 @@ from typing import TYPE_CHECKING 
     | 
|
| 
       29 
29 
     | 
    
         | 
| 
       30 
30 
     | 
    
         
             
            from novelwriter.constants import nwUnicode
         
     | 
| 
       31 
31 
     | 
    
         
             
            from novelwriter.formats.shared import BlockFmt, BlockTyp, T_Formats, TextFmt
         
     | 
| 
       32 
     | 
    
         
            -
            from novelwriter.formats.tokenizer import Tokenizer
         
     | 
| 
      
 32 
     | 
    
         
            +
            from novelwriter.formats.tokenizer import COMMENT_BLOCKS, Tokenizer
         
     | 
| 
       33 
33 
     | 
    
         | 
| 
       34 
34 
     | 
    
         
             
            if TYPE_CHECKING:
         
     | 
| 
       35 
35 
     | 
    
         
             
                from pathlib import Path
         
     | 
| 
         @@ -79,7 +79,7 @@ EXT_MD = { 
     | 
|
| 
       79 
79 
     | 
    
         | 
| 
       80 
80 
     | 
    
         | 
| 
       81 
81 
     | 
    
         
             
            class ToMarkdown(Tokenizer):
         
     | 
| 
       82 
     | 
    
         
            -
                """Core: Markdown Document Writer
         
     | 
| 
      
 82 
     | 
    
         
            +
                """Core: Markdown Document Writer.
         
     | 
| 
       83 
83 
     | 
    
         | 
| 
       84 
84 
     | 
    
         
             
                Extend the Tokenizer class to writer Markdown output. It supports
         
     | 
| 
       85 
85 
     | 
    
         
             
                both Standard Markdown and Extended Markdown. The class also
         
     | 
| 
         @@ -91,7 +91,6 @@ class ToMarkdown(Tokenizer): 
     | 
|
| 
       91 
91 
     | 
    
         
             
                    self._extended = extended
         
     | 
| 
       92 
92 
     | 
    
         
             
                    self._usedNotes: dict[str, int] = {}
         
     | 
| 
       93 
93 
     | 
    
         
             
                    self._usedFields: list[tuple[int, str]] = []
         
     | 
| 
       94 
     | 
    
         
            -
                    return
         
     | 
| 
       95 
94 
     | 
    
         | 
| 
       96 
95 
     | 
    
         
             
                ##
         
     | 
| 
       97 
96 
     | 
    
         
             
                #  Class Methods
         
     | 
| 
         @@ -144,7 +143,7 @@ class ToMarkdown(Tokenizer): 
     | 
|
| 
       144 
143 
     | 
    
         
             
                        elif tType == BlockTyp.SKIP:
         
     | 
| 
       145 
144 
     | 
    
         
             
                            lines.append(f"{cSkip}\n\n")
         
     | 
| 
       146 
145 
     | 
    
         | 
| 
       147 
     | 
    
         
            -
                        elif tType  
     | 
| 
      
 146 
     | 
    
         
            +
                        elif tType in COMMENT_BLOCKS:
         
     | 
| 
       148 
147 
     | 
    
         
             
                            lines.append(f"{self._formatText(tText, tFormat, mTags)}\n\n")
         
     | 
| 
       149 
148 
     | 
    
         | 
| 
       150 
149 
     | 
    
         
             
                        elif tType == BlockTyp.KEYWORD:
         
     | 
| 
         @@ -153,8 +152,6 @@ class ToMarkdown(Tokenizer): 
     | 
|
| 
       153 
152 
     | 
    
         | 
| 
       154 
153 
     | 
    
         
             
                    self._pages.append("".join(lines))
         
     | 
| 
       155 
154 
     | 
    
         | 
| 
       156 
     | 
    
         
            -
                    return
         
     | 
| 
       157 
     | 
    
         
            -
             
     | 
| 
       158 
155 
     | 
    
         
             
                def closeDocument(self) -> None:
         
     | 
| 
       159 
156 
     | 
    
         
             
                    """Run close document tasks."""
         
     | 
| 
       160 
157 
     | 
    
         
             
                    # Replace fields if there are stats available
         
     | 
| 
         @@ -181,20 +178,16 @@ class ToMarkdown(Tokenizer): 
     | 
|
| 
       181 
178 
     | 
    
         
             
                        lines.append("\n")
         
     | 
| 
       182 
179 
     | 
    
         
             
                        self._pages.append("".join(lines))
         
     | 
| 
       183 
180 
     | 
    
         | 
| 
       184 
     | 
    
         
            -
                    return
         
     | 
| 
       185 
     | 
    
         
            -
             
     | 
| 
       186 
181 
     | 
    
         
             
                def saveDocument(self, path: Path) -> None:
         
     | 
| 
       187 
182 
     | 
    
         
             
                    """Save the data to a plain text file."""
         
     | 
| 
       188 
183 
     | 
    
         
             
                    with open(path, mode="w", encoding="utf-8") as outFile:
         
     | 
| 
       189 
184 
     | 
    
         
             
                        outFile.write("".join(self._pages))
         
     | 
| 
       190 
185 
     | 
    
         
             
                    logger.info("Wrote file: %s", path)
         
     | 
| 
       191 
     | 
    
         
            -
                    return
         
     | 
| 
       192 
186 
     | 
    
         | 
| 
       193 
187 
     | 
    
         
             
                def replaceTabs(self, nSpaces: int = 8, spaceChar: str = " ") -> None:
         
     | 
| 
       194 
188 
     | 
    
         
             
                    """Replace tabs with spaces."""
         
     | 
| 
       195 
189 
     | 
    
         
             
                    spaces = spaceChar*nSpaces
         
     | 
| 
       196 
190 
     | 
    
         
             
                    self._pages = [p.replace("\t", spaces) for p in self._pages]
         
     | 
| 
       197 
     | 
    
         
            -
                    return
         
     | 
| 
       198 
191 
     | 
    
         | 
| 
       199 
192 
     | 
    
         
             
                ##
         
     | 
| 
       200 
193 
     | 
    
         
             
                #  Internal Functions
         
     |