Restrict dialogue line symbols

This commit is contained in:
Veronica Berglyd Olsen
2025-05-04 22:17:13 +02:00
parent 6f38867972
commit 607001f2dd
5 changed files with 32 additions and 7 deletions
+10 -1
View File
@@ -40,7 +40,7 @@ from PyQt6.QtCore import QCoreApplication, QMimeData, QUrl
from PyQt6.QtGui import QAction, QDesktopServices, QFont, QFontDatabase, QFontInfo
from PyQt6.QtWidgets import QMenu, QMenuBar, QWidget
from novelwriter.constants import nwConst, nwLabels, nwUnicode, trConst
from novelwriter.constants import nwConst, nwLabels, nwQuotes, nwUnicode, trConst
from novelwriter.enum import nwItemClass, nwItemLayout, nwItemType
from novelwriter.error import logException
@@ -298,6 +298,15 @@ def uniqueCompact(text: str) -> str:
return "".join(sorted(set(compact(text))))
def processDialogSymbols(symbols: str) -> str:
"""Process dialogue line symbols."""
result = ""
for c in uniqueCompact(symbols):
if c in nwQuotes.ALLOWED:
result += c
return result
def elide(text: str, length: int) -> str:
"""Elide a piece of text to a maximum length."""
if len(text) > (cut := max(4, length)):
+3 -2
View File
@@ -42,7 +42,7 @@ from PyQt6.QtWidgets import QApplication
from novelwriter.common import (
NWConfigParser, checkInt, checkPath, describeFont, fontMatcher,
formatTimeStamp
formatTimeStamp, processDialogSymbols
)
from novelwriter.constants import nwFiles, nwHtmlUnicode, nwQuotes, nwUnicode
from novelwriter.error import formatException, logException
@@ -680,7 +680,7 @@ class Config:
self.showFullPath = conf.rdBool(sec, "showfullpath", self.showFullPath)
self.dialogStyle = conf.rdInt(sec, "dialogstyle", self.dialogStyle)
self.allowOpenDial = conf.rdBool(sec, "allowopendial", self.allowOpenDial)
self.dialogLine = conf.rdStr(sec, "dialogline", self.dialogLine)
dialogLine = conf.rdStr(sec, "dialogline", self.dialogLine)
narratorBreak = conf.rdStr(sec, "narratorbreak", self.narratorBreak)
narratorDialog = conf.rdStr(sec, "narratordialog", self.narratorDialog)
self.altDialogOpen = conf.rdStr(sec, "altdialogopen", self.altDialogOpen)
@@ -721,6 +721,7 @@ class Config:
logger.info("Using straight double quotes, so disabling auto-replace")
self.doReplaceDQuote = False
self.dialogLine = processDialogSymbols(dialogLine)
self.narratorBreak = narratorBreak if narratorBreak in nwQuotes.DASHES else ""
self.narratorDialog = narratorDialog if narratorDialog in nwQuotes.DASHES else ""
+6
View File
@@ -512,6 +512,12 @@ class nwQuotes:
"\u2015": QT_TRANSLATE_NOOP("Constant", "Horizontal bar"),
}
ALLOWED: Final[list[str]] = [
"\u0027", "\u0022", "\u2018", "\u2019", "\u201a", "\u201b", "\u201c", "\u201d", "\u201e",
"\u201f", "\u2e42", "\u2039", "\u203a", "\u00ab", "\u00bb", "\u300c", "\u300d", "\u300e",
"\u300f", "\u2013", "\u2014", "\u2015",
]
class nwUnicode:
"""Supported unicode character constants and their HTML equivalents."""
+2 -2
View File
@@ -34,7 +34,7 @@ from PyQt6.QtWidgets import (
)
from novelwriter import CONFIG, SHARED
from novelwriter.common import compact, describeFont, uniqueCompact
from novelwriter.common import compact, describeFont, processDialogSymbols, uniqueCompact
from novelwriter.config import DEF_GUI, DEF_ICONS, DEF_SYNTAX, DEF_TREECOL
from novelwriter.constants import nwLabels, nwQuotes, nwUnicode, trConst
from novelwriter.dialogs.quotes import GuiQuoteSelect
@@ -1033,7 +1033,7 @@ class GuiPreferences(NDialog):
# Text Highlighting
dialogueStyle = self.dialogStyle.currentData()
allowOpenDial = self.allowOpenDial.isChecked()
dialogueLine = uniqueCompact(self.dialogLine.text())
dialogueLine = processDialogSymbols(self.dialogLine.text())
narratorBreak = self.narratorBreak.currentData()
narratorDialog = self.narratorDialog.currentData()
altDialogOpen = compact(self.altDialogOpen.text())
+11 -2
View File
@@ -37,8 +37,9 @@ from novelwriter.common import (
formatFileFilter, formatInt, formatTime, formatTimeStamp, formatVersion,
fuzzyTime, getFileSize, hexToInt, isHandle, isItemClass, isItemLayout,
isItemType, isListInstance, isTitleTag, jsonEncode, makeFileNameSafe,
minmax, numberToRoman, openExternalPath, readTextFile, simplified,
transferCase, uniqueCompact, xmlElement, xmlIndent, xmlSubElem, yesNo
minmax, numberToRoman, openExternalPath, processDialogSymbols,
readTextFile, simplified, transferCase, uniqueCompact, xmlElement,
xmlIndent, xmlSubElem, yesNo
)
from tests.mocked import causeOSError
@@ -377,6 +378,14 @@ def testBaseCommon_uniqueCompact():
assert uniqueCompact("3 2 1") == "123"
@pytest.mark.base
def testBaseCommon_processDialogSymbols():
"""Test the processDialogSymbols function."""
assert processDialogSymbols("abc") == ""
assert processDialogSymbols("\u00ab\u00ab\u00bb\u00bb") == "\u00ab\u00bb"
assert processDialogSymbols("-\u2013\u2014\u2015") == "\u2013\u2014\u2015"
@pytest.mark.base
def testBaseCommon_elide():
"""Test the elide function."""